[Pkg-xen-changes] [xen] 01/34: Import xen_4.5.0~rc3.orig.tar.xz
Ian James Campbell
ijc at moszumanska.debian.org
Tue Dec 9 12:49:50 UTC 2014
This is an automated email from the git hooks/post-receive script.
ijc pushed a commit to branch feature/experimental-rc3
in repository xen.
commit 9ca7a919493667f7b431cf66eca19d4deccc3a61
Author: Ian Campbell <ijc at debian.org>
Date: Mon Dec 8 16:06:35 2014 +0000
Import xen_4.5.0~rc3.orig.tar.xz
---
.gitignore | 127 +-
.hgignore | 15 -
Config.mk | 95 +-
INSTALL | 341 ++
MAINTAINERS | 68 +-
Makefile | 182 +-
README | 96 +-
autogen.sh | 8 +-
buildconfigs/Rules.mk | 42 -
buildconfigs/enable-xen-config | 127 -
buildconfigs/interface.exclude | 7 -
buildconfigs/ketchup | 742 ----
buildconfigs/mk.linux-2.6 | 10 -
buildconfigs/mk.linux-2.6-common | 154 -
buildconfigs/mk.linux-2.6-git | 2 -
buildconfigs/mk.linux-2.6-mm | 2 -
buildconfigs/mk.linux-2.6-native | 5 -
buildconfigs/mk.linux-2.6-pvops | 17 -
buildconfigs/mk.linux-2.6-rc | 2 -
buildconfigs/mk.linux-2.6-tip | 2 -
buildconfigs/mk.linux-2.6-tip-latest | 17 -
buildconfigs/mk.linux-2.6-xen | 6 -
buildconfigs/mk.linux-2.6-xen0 | 2 -
buildconfigs/mk.linux-2.6-xenU | 2 -
buildconfigs/select-linux-arch | 30 -
buildconfigs/select-linux-image | 33 -
buildconfigs/select-repository | 69 -
buildconfigs/src.git-clone | 32 -
buildconfigs/src.hg-clone | 32 -
buildconfigs/src.tarball | 19 -
config/Docs.mk.in | 8 +-
config/FreeBSD.mk | 5 +
config/Linux.mk | 7 +-
config/MiniOS.mk | 1 +
config/NetBSD.mk | 5 -
config/NetBSDRump.mk | 9 +
config/Paths.mk.in | 63 +
config/StdGNU.mk | 27 +-
config/Stubdom.mk.in | 8 +-
config/SunOS.mk | 22 +-
config/Tools.mk.in | 29 +-
config/arm32.mk | 2 +
config/arm64.mk | 4 +
config/x86_32.mk | 6 +
config/x86_64.mk | 6 +
configure | 199 +-
configure.ac | 16 +-
docs/Makefile | 69 +-
docs/README.remus | 20 +
docs/configure | 76 +-
docs/configure.ac | 2 +
docs/man/xend-config.sxp.pod.5 | 158 -
docs/man/xl.cfg.pod.5 | 351 +-
docs/man/xl.conf.pod.5 | 6 +
docs/man/xl.pod.1 | 181 +-
docs/man/xm.pod.1 | 1004 -----
docs/man/xmdomain.cfg.pod.5 | 358 --
docs/misc/amd-ucode-container.txt | 90 +
docs/misc/arm/device-tree/booting.txt | 64 +-
docs/misc/arm/early-printk.txt | 3 +
docs/misc/channel.txt | 106 +
docs/misc/console.txt | 69 +-
docs/misc/distro_mapping.txt | 6 +-
docs/misc/efi.markdown | 38 +-
docs/misc/kexec_and_kdump.txt | 9 +-
docs/misc/printk-formats.txt | 10 +
docs/misc/pvh-readme.txt | 2 +
docs/misc/pvh.markdown | 377 ++
docs/misc/tmem-internals.html | 7 -
docs/misc/vbd-interface.txt | 6 +
docs/misc/vtpm-platforms.txt | 141 +
docs/misc/vtpm.txt | 249 +-
docs/misc/vtpmmgr.txt | 165 +
docs/misc/x86-xenpv-bootloader.markdown | 49 +
docs/misc/xen-command-line.markdown | 455 +-
docs/misc/xend.tex | 419 --
docs/misc/xenstore-paths.markdown | 28 +-
docs/misc/xenstore-ring.txt | 116 +
docs/misc/xl-disk-configuration.txt | 55 +
docs/misc/xl-numa-placement.markdown | 162 +-
docs/misc/xsm-flask.txt | 33 -
extras/mini-os/Config.mk | 2 +-
extras/mini-os/Makefile | 23 +-
extras/mini-os/README | 4 +-
extras/mini-os/arch/arm/arm32.S | 233 +
extras/mini-os/arch/arm/events.c | 31 +
extras/mini-os/arch/arm/hypercalls32.S | 64 +
extras/mini-os/arch/arm/minios-arm32.lds | 83 +
extras/mini-os/arch/arm/mm.c | 139 +
extras/mini-os/arch/arm/sched.c | 47 +
extras/mini-os/arch/arm/setup.c | 119 +
extras/mini-os/arch/x86/events.c | 35 +
extras/mini-os/arch/x86/mm.c | 13 +
extras/mini-os/arch/x86/sched.c | 3 +
extras/mini-os/arch/x86/setup.c | 44 +-
extras/mini-os/arch/x86/time.c | 2 +-
extras/mini-os/arch/x86/x86_32.S | 2 +-
extras/mini-os/arch/x86/x86_64.S | 2 +-
extras/mini-os/blkfront.c | 18 +-
extras/mini-os/console/console.c | 2 +-
extras/mini-os/events.c | 66 +-
extras/mini-os/gntmap.c | 35 +-
extras/mini-os/gnttab.c | 11 +-
extras/mini-os/hypervisor.c | 12 +-
extras/mini-os/include/arm/arch_endian.h | 7 +
extras/mini-os/include/arm/arch_limits.h | 9 +
extras/mini-os/include/arm/arch_mm.h | 38 +
extras/mini-os/include/arm/arch_sched.h | 19 +
extras/mini-os/include/arm/arch_spinlock.h | 36 +
extras/mini-os/include/arm/arm32/arch_wordsize.h | 1 +
extras/mini-os/include/arm/gic.h | 1 +
extras/mini-os/include/arm/hypercall-arm.h | 98 +
extras/mini-os/include/arm/os.h | 216 +
extras/mini-os/include/arm/traps.h | 20 +
extras/mini-os/include/compiler.h | 10 +
extras/mini-os/include/events.h | 7 +
extras/mini-os/include/gnttab.h | 1 +
extras/mini-os/include/hypervisor.h | 2 +
extras/mini-os/include/kernel.h | 6 +-
extras/mini-os/include/lib.h | 11 +-
extras/mini-os/include/mm.h | 5 +-
extras/mini-os/include/types.h | 24 +-
extras/mini-os/include/x86/arch_spinlock.h | 2 +-
extras/mini-os/include/x86/os.h | 16 +-
.../mini-os/include/x86/x86_32/hypercall-x86_32.h | 5 +
.../mini-os/include/x86/x86_64/hypercall-x86_64.h | 4 +
extras/mini-os/kernel.c | 49 +-
extras/mini-os/lib/math.c | 13 -
extras/mini-os/lock.c | 1 +
extras/mini-os/main.c | 3 +-
extras/mini-os/mm.c | 4 +-
extras/mini-os/sched.c | 37 +-
extras/mini-os/test.c | 16 +-
extras/mini-os/tpm_tis.c | 15 +-
extras/mini-os/tpmback.c | 12 +-
extras/mini-os/tpmfront.c | 1 +
extras/mini-os/xenbus/xenbus.c | 2 +-
install.sh | 3 -
m4/README.source | 36 +
m4/paths.m4 | 113 +
m4/pkg.m4 | 88 +-
m4/systemd.m4 | 127 +
m4/xenstored.m4 | 56 +
misc/coverity/model.c | 141 +
scripts/get_maintainer.pl | 2 +-
stubdom/Makefile | 35 +-
stubdom/README | 9 -
stubdom/c/minios.cfg | 1 -
stubdom/caml/minios.cfg | 1 -
stubdom/configure | 18 +-
stubdom/grub.patches/11graphics-keyboard.diff | 13 +
stubdom/grub/Makefile | 2 +-
stubdom/grub/kexec.c | 58 +-
stubdom/grub/mini-os.c | 10 +-
stubdom/grub/mini-os.h | 2 +
stubdom/lwip.dhcp_create_request-hwaddr_len.patch | 13 +
stubdom/newlib.patch | 22 -
stubdom/vtpm-cmake-Wextra.patch | 21 +
stubdom/vtpm-deepquote.patch | 187 +
stubdom/vtpm-parent-sign-ek.patch | 196 +
stubdom/vtpm/README | 75 -
stubdom/vtpm/vtpm.c | 40 +-
stubdom/vtpm/vtpm_cmd.c | 45 +
stubdom/vtpmmgr/Makefile | 9 +-
stubdom/vtpmmgr/README | 75 -
stubdom/vtpmmgr/calc.pl | 97 +
stubdom/vtpmmgr/disk_crypto.c | 231 +
stubdom/vtpmmgr/disk_crypto.h | 17 +
stubdom/vtpmmgr/disk_format.h | 193 +
stubdom/vtpmmgr/disk_io.c | 125 +
stubdom/vtpmmgr/disk_io.h | 25 +
stubdom/vtpmmgr/disk_read.c | 606 +++
stubdom/vtpmmgr/disk_tpm.c | 259 ++
stubdom/vtpmmgr/disk_tpm.h | 25 +
stubdom/vtpmmgr/disk_write.c | 410 ++
stubdom/vtpmmgr/endian_int.h | 72 +
stubdom/vtpmmgr/init.c | 110 +-
stubdom/vtpmmgr/log.h | 8 +-
stubdom/vtpmmgr/manage-vtpmmgr.pl | 160 +
stubdom/vtpmmgr/marshal.h | 910 ++--
stubdom/vtpmmgr/mgmt_authority.c | 323 ++
stubdom/vtpmmgr/mgmt_authority.h | 11 +
stubdom/vtpmmgr/tcg.h | 49 +
stubdom/vtpmmgr/tpm.c | 1352 +++---
stubdom/vtpmmgr/tpm.h | 112 +-
stubdom/vtpmmgr/tpmrsa.c | 25 +
stubdom/vtpmmgr/tpmrsa.h | 3 +
stubdom/vtpmmgr/vtpm_cmd_handler.c | 895 +++-
stubdom/vtpmmgr/vtpm_disk.c | 237 ++
stubdom/vtpmmgr/vtpm_disk.h | 233 +
stubdom/vtpmmgr/vtpm_manager.h | 391 +-
stubdom/vtpmmgr/vtpm_storage.c | 794 ----
stubdom/vtpmmgr/vtpm_storage.h | 68 -
stubdom/vtpmmgr/vtpmmgr.h | 18 +-
tools/Makefile | 101 +-
tools/Rules.mk | 37 +-
tools/blktap/drivers/Makefile | 2 +-
tools/blktap2/control/Makefile | 4 +-
tools/blktap2/drivers/Makefile | 16 +-
tools/blktap2/vhd/Makefile | 4 +-
tools/blktap2/vhd/lib/Makefile | 1 -
tools/config.h.in | 15 +
tools/configure | 1259 ++++--
tools/configure.ac | 177 +-
tools/console/Makefile | 4 +-
tools/console/client/main.c | 18 +-
tools/console/daemon/io.c | 40 +-
tools/debugger/gdbsx/xg/xg_main.c | 4 +-
tools/debugger/kdd/Makefile | 2 +-
tools/examples/Makefile | 33 +-
tools/examples/README | 6 +-
tools/examples/xend-config.sxp | 304 --
tools/examples/xend-pci-permissive.sxp | 27 -
tools/examples/xend-pci-quirks.sxp | 96 -
tools/examples/xm-config.xml | 45 -
tools/examples/xmexample.hvm | 373 --
tools/examples/xmexample.hvm-stubdom | 317 --
tools/examples/xmexample.nbd | 26 -
tools/examples/xmexample.pv-grub | 172 -
tools/examples/xmexample1 | 197 -
tools/examples/xmexample2 | 232 -
tools/examples/xmexample3 | 218 -
tools/firmware/Makefile | 28 +-
tools/firmware/hvmloader/Makefile | 1 +
tools/firmware/hvmloader/acpi/build.c | 15 +-
tools/firmware/hvmloader/acpi/dsdt.asl | 60 +-
tools/firmware/hvmloader/cacheattr.c | 25 +-
tools/firmware/hvmloader/config.h | 3 +-
tools/firmware/hvmloader/hvm_param.c | 36 +
tools/firmware/hvmloader/hvmloader.c | 14 +-
tools/firmware/hvmloader/pci.c | 87 +-
tools/firmware/hvmloader/util.h | 11 +-
tools/firmware/hvmloader/xenbus.c | 62 +-
tools/firmware/seabios-config | 97 -
tools/flask/policy/Makefile | 2 +-
tools/flask/policy/policy/modules/xen/xen.if | 3 +-
tools/flask/policy/policy/modules/xen/xen.te | 6 +-
tools/flask/utils/Makefile | 2 +-
tools/flask/utils/loadpolicy.c | 2 +-
tools/hotplug/FreeBSD/Makefile | 42 +
tools/hotplug/FreeBSD/rc.d/xencommons.in | 120 +
tools/hotplug/FreeBSD/vif-bridge | 41 +
tools/hotplug/Linux/Makefile | 24 +-
tools/hotplug/Linux/block-drbd-probe | 87 +
tools/hotplug/Linux/init.d/sysconfig.xencommons | 33 -
tools/hotplug/Linux/init.d/sysconfig.xencommons.in | 42 +
tools/hotplug/Linux/init.d/xen-watchdog | 90 -
tools/hotplug/Linux/init.d/xen-watchdog.in | 90 +
tools/hotplug/Linux/init.d/xencommons | 167 -
tools/hotplug/Linux/init.d/xencommons.in | 148 +
tools/hotplug/Linux/init.d/xend | 82 -
tools/hotplug/Linux/init.d/xendomains | 585 ---
tools/hotplug/Linux/init.d/xendomains.in | 50 +
tools/hotplug/Linux/network-bridge | 339 --
tools/hotplug/Linux/network-nat | 124 -
tools/hotplug/Linux/network-route | 28 -
tools/hotplug/Linux/remus-netbuf-setup | 230 +
tools/hotplug/Linux/systemd/Makefile | 47 +
tools/hotplug/Linux/systemd/proc-xen.mount.in | 10 +
.../Linux/systemd/show_service_dependencies.sh | 31 +
.../Linux/systemd/var-lib-xenstored.mount.in | 14 +
.../hotplug/Linux/systemd/xen-init-dom0.service.in | 14 +
.../systemd/xen-qemu-dom0-disk-backend.service.in | 21 +
.../hotplug/Linux/systemd/xen-watchdog.service.in | 13 +
tools/hotplug/Linux/systemd/xenconsoled.service.in | 19 +
tools/hotplug/Linux/systemd/xendomains.service.in | 16 +
tools/hotplug/Linux/systemd/xenstored.service.in | 24 +
tools/hotplug/Linux/systemd/xenstored.socket.in | 13 +
tools/hotplug/Linux/systemd/xenstored_ro.socket.in | 13 +
tools/hotplug/Linux/vif-bridge | 8 +-
tools/hotplug/Linux/vif-common.sh | 4 +-
tools/hotplug/Linux/vif-nat | 4 -
tools/hotplug/Linux/vif-openvswitch | 4 -
tools/hotplug/Linux/vif-route | 4 -
tools/hotplug/Linux/vif-setup | 9 -
tools/hotplug/Linux/vif-setup.in | 9 +
tools/hotplug/Linux/xen-backend.rules | 15 -
tools/hotplug/Linux/xen-backend.rules.in | 15 +
tools/hotplug/Linux/xen-hotplug-common.sh | 120 -
tools/hotplug/Linux/xen-hotplug-common.sh.in | 120 +
tools/hotplug/Linux/xend.rules | 4 -
tools/hotplug/Linux/xendomains.in | 575 +++
tools/hotplug/Makefile | 1 +
tools/hotplug/NetBSD/Makefile | 11 +-
tools/hotplug/NetBSD/block | 2 +-
tools/hotplug/NetBSD/rc.d/xencommons | 125 -
tools/hotplug/NetBSD/rc.d/xencommons.in | 124 +
tools/hotplug/NetBSD/rc.d/xend | 71 -
tools/hotplug/NetBSD/rc.d/xendomains | 2 +-
tools/hotplug/NetBSD/vif-bridge | 2 +-
tools/hotplug/NetBSD/vif-ip | 2 +-
tools/hotplug/common/Makefile | 4 +-
tools/include/xen-sys/FreeBSD/evtchn.h | 87 +
tools/include/xen-sys/FreeBSD/privcmd.h | 64 +
tools/include/xen-sys/NetBSDRump/privcmd.h | 31 +
tools/libfsimage/common/Makefile | 2 +-
tools/libvchan/init.c | 8 +-
tools/libvchan/io.c | 6 +-
tools/libxc/Makefile | 56 +-
tools/libxc/include/xc_dom.h | 403 ++
tools/libxc/include/xenctrl.h | 2717 ++++++++++++
tools/libxc/include/xenctrlosdep.h | 173 +
tools/libxc/include/xenguest.h | 325 ++
tools/libxc/include/xentoollog.h | 137 +
tools/libxc/xc_bitops.h | 8 +
tools/libxc/xc_compression.c | 1 -
tools/libxc/xc_core.c | 2 +-
tools/libxc/xc_core_x86.c | 4 -
tools/libxc/xc_cpufeature.h | 5 +
tools/libxc/xc_cpuid_x86.c | 83 +-
tools/libxc/xc_dom.h | 389 --
tools/libxc/xc_dom_arm.c | 233 +-
tools/libxc/xc_dom_bzimageloader.c | 20 +
tools/libxc/xc_dom_core.c | 61 +-
tools/libxc/xc_dom_decompress_lz4.c | 6 +-
tools/libxc/xc_dom_decompress_unsafe_lzo1x.c | 1 +
tools/libxc/xc_dom_decompress_unsafe_xz.c | 11 -
tools/libxc/xc_dom_x86.c | 4 +-
tools/libxc/xc_domain.c | 505 ++-
tools/libxc/xc_domain_restore.c | 248 +-
tools/libxc/xc_domain_save.c | 144 +-
tools/libxc/xc_flask.c | 2 -
tools/libxc/xc_foreign_memory.c | 2 +-
tools/libxc/xc_freebsd.c | 72 +
tools/libxc/xc_freebsd_osdep.c | 405 ++
tools/libxc/xc_gnttab.c | 3 +-
tools/libxc/xc_hvm_build_x86.c | 89 +-
tools/libxc/xc_linux_osdep.c | 22 +-
tools/libxc/xc_mem_access.c | 74 +-
tools/libxc/xc_mem_event.c | 120 +
tools/libxc/xc_mem_paging.c | 2 +-
tools/libxc/xc_minios.c | 5 +-
tools/libxc/xc_misc.c | 62 +-
tools/libxc/xc_msr_x86.h | 36 +
tools/libxc/xc_nomigrate.c | 6 +-
tools/libxc/xc_offline_page.c | 4 +-
tools/libxc/xc_pm.c | 51 +-
tools/libxc/xc_private.c | 41 +-
tools/libxc/xc_private.h | 140 +-
tools/libxc/xc_psr.c | 215 +
tools/libxc/xc_resource.c | 150 +
tools/libxc/xc_resume.c | 19 +-
tools/libxc/xc_rt.c | 65 +
tools/libxc/xc_suspend.c | 173 +-
tools/libxc/xc_tbuf.c | 4 +-
tools/libxc/xc_tmem.c | 10 -
tools/libxc/xenctrl.h | 2430 -----------
tools/libxc/xenctrl_osdep_ENOSYS.c | 36 +-
tools/libxc/xenctrlosdep.h | 172 -
tools/libxc/xenguest.h | 308 --
tools/libxc/xentoollog.h | 135 -
tools/libxc/xg_private.c | 1 -
tools/libxc/xg_private.h | 24 +-
tools/libxc/xg_save_restore.h | 24 +-
tools/libxc/xtl_logger_stdio.c | 20 +-
tools/libxen/COPYING | 510 ---
tools/libxen/Makefile | 74 -
tools/libxen/Makefile.dist | 115 -
tools/libxen/README | 55 -
tools/libxen/include/xen/api/xen_all.h | 40 -
tools/libxen/include/xen/api/xen_common.h | 211 -
tools/libxen/include/xen/api/xen_console.h | 247 --
tools/libxen/include/xen/api/xen_console_decl.h | 30 -
.../libxen/include/xen/api/xen_console_protocol.h | 82 -
tools/libxen/include/xen/api/xen_cpu_pool.h | 424 --
tools/libxen/include/xen/api/xen_cpu_pool_decl.h | 30 -
tools/libxen/include/xen/api/xen_crashdump.h | 199 -
tools/libxen/include/xen/api/xen_crashdump_decl.h | 30 -
tools/libxen/include/xen/api/xen_event.h | 102 -
tools/libxen/include/xen/api/xen_event_decl.h | 25 -
tools/libxen/include/xen/api/xen_event_operation.h | 82 -
tools/libxen/include/xen/api/xen_host.h | 505 ---
tools/libxen/include/xen/api/xen_host_cpu.h | 263 --
tools/libxen/include/xen/api/xen_host_cpu_decl.h | 30 -
tools/libxen/include/xen/api/xen_host_decl.h | 30 -
tools/libxen/include/xen/api/xen_host_metrics.h | 199 -
.../libxen/include/xen/api/xen_host_metrics_decl.h | 30 -
tools/libxen/include/xen/api/xen_int_float_map.h | 53 -
tools/libxen/include/xen/api/xen_int_int_map.h | 53 -
.../include/xen/api/xen_int_string_set_map.h | 53 -
tools/libxen/include/xen/api/xen_network.h | 276 --
tools/libxen/include/xen/api/xen_network_decl.h | 30 -
.../include/xen/api/xen_on_crash_behaviour.h | 97 -
tools/libxen/include/xen/api/xen_on_normal_exit.h | 77 -
tools/libxen/include/xen/api/xen_pbd.h | 223 -
tools/libxen/include/xen/api/xen_pbd_decl.h | 30 -
tools/libxen/include/xen/api/xen_pif.h | 277 --
tools/libxen/include/xen/api/xen_pif_decl.h | 30 -
tools/libxen/include/xen/api/xen_pif_metrics.h | 198 -
.../libxen/include/xen/api/xen_pif_metrics_decl.h | 30 -
tools/libxen/include/xen/api/xen_sr.h | 277 --
tools/libxen/include/xen/api/xen_sr_decl.h | 30 -
tools/libxen/include/xen/api/xen_string_set.h | 47 -
.../libxen/include/xen/api/xen_string_string_map.h | 53 -
tools/libxen/include/xen/api/xen_user.h | 204 -
tools/libxen/include/xen/api/xen_user_decl.h | 30 -
tools/libxen/include/xen/api/xen_vbd.h | 390 --
tools/libxen/include/xen/api/xen_vbd_decl.h | 30 -
tools/libxen/include/xen/api/xen_vbd_metrics.h | 198 -
.../libxen/include/xen/api/xen_vbd_metrics_decl.h | 30 -
tools/libxen/include/xen/api/xen_vbd_mode.h | 77 -
tools/libxen/include/xen/api/xen_vbd_type.h | 77 -
tools/libxen/include/xen/api/xen_vdi.h | 360 --
tools/libxen/include/xen/api/xen_vdi_decl.h | 30 -
tools/libxen/include/xen/api/xen_vdi_type.h | 92 -
tools/libxen/include/xen/api/xen_vif.h | 379 --
tools/libxen/include/xen/api/xen_vif_decl.h | 30 -
tools/libxen/include/xen/api/xen_vif_metrics.h | 198 -
.../libxen/include/xen/api/xen_vif_metrics_decl.h | 30 -
tools/libxen/include/xen/api/xen_vm.h | 931 ----
tools/libxen/include/xen/api/xen_vm_decl.h | 30 -
.../libxen/include/xen/api/xen_vm_guest_metrics.h | 234 --
.../include/xen/api/xen_vm_guest_metrics_decl.h | 30 -
tools/libxen/include/xen/api/xen_vm_metrics.h | 251 --
tools/libxen/include/xen/api/xen_vm_metrics_decl.h | 30 -
tools/libxen/include/xen/api/xen_vm_power_state.h | 97 -
tools/libxen/include/xen/api/xen_xspolicy.h | 293 --
tools/libxen/include/xen/api/xen_xspolicy_decl.h | 31 -
.../libxen/include/xen_console_protocol_internal.h | 37 -
.../libxen/include/xen_event_operation_internal.h | 37 -
tools/libxen/include/xen_internal.h | 188 -
.../include/xen_on_crash_behaviour_internal.h | 38 -
tools/libxen/include/xen_on_normal_exit_internal.h | 37 -
tools/libxen/include/xen_vbd_mode_internal.h | 37 -
tools/libxen/include/xen_vbd_type_internal.h | 37 -
tools/libxen/include/xen_vdi_type_internal.h | 37 -
tools/libxen/include/xen_vm_power_state_internal.h | 37 -
tools/libxen/src/xen_common.c | 1784 --------
tools/libxen/src/xen_console.c | 298 --
tools/libxen/src/xen_console_protocol.c | 82 -
tools/libxen/src/xen_cpu_pool.c | 671 ---
tools/libxen/src/xen_crashdump.c | 191 -
tools/libxen/src/xen_event.c | 123 -
tools/libxen/src/xen_event_operation.c | 75 -
tools/libxen/src/xen_host.c | 915 ----
tools/libxen/src/xen_host_cpu.c | 353 --
tools/libxen/src/xen_host_metrics.c | 190 -
tools/libxen/src/xen_int_float_map.c | 39 -
tools/libxen/src/xen_int_int_map.c | 39 -
tools/libxen/src/xen_int_string_set_map.c | 54 -
tools/libxen/src/xen_network.c | 371 --
tools/libxen/src/xen_on_crash_behaviour.c | 85 -
tools/libxen/src/xen_on_normal_exit.c | 81 -
tools/libxen/src/xen_pbd.c | 249 --
tools/libxen/src/xen_pif.c | 380 --
tools/libxen/src/xen_pif_metrics.c | 190 -
tools/libxen/src/xen_sr.c | 379 --
tools/libxen/src/xen_string_set.c | 48 -
tools/libxen/src/xen_string_set.h | 47 -
tools/libxen/src/xen_string_string_map.c | 52 -
tools/libxen/src/xen_user.c | 210 -
tools/libxen/src/xen_vbd.c | 626 ---
tools/libxen/src/xen_vbd_metrics.c | 190 -
tools/libxen/src/xen_vbd_mode.c | 81 -
tools/libxen/src/xen_vbd_type.c | 81 -
tools/libxen/src/xen_vdi.c | 575 ---
tools/libxen/src/xen_vdi_type.c | 84 -
tools/libxen/src/xen_vif.c | 616 ---
tools/libxen/src/xen_vif_metrics.c | 190 -
tools/libxen/src/xen_vm.c | 1837 --------
tools/libxen/src/xen_vm_guest_metrics.c | 279 --
tools/libxen/src/xen_vm_metrics.c | 318 --
tools/libxen/src/xen_vm_power_state.c | 85 -
tools/libxen/src/xen_xspolicy.c | 363 --
tools/libxen/test/test_bindings.c | 1453 -------
tools/libxen/test/test_event_handling.c | 210 -
tools/libxl/CODING_STYLE | 192 +-
tools/libxl/Makefile | 80 +-
tools/libxl/check-xl-disk-parse | 87 +-
tools/libxl/gentest.py | 66 +-
tools/libxl/gentypes.py | 303 +-
tools/libxl/idl.py | 47 +-
tools/libxl/idl.txt | 30 +-
tools/libxl/libxl.c | 1344 +++++-
tools/libxl/libxl.h | 325 +-
tools/libxl/libxl_aoutils.c | 170 +
tools/libxl/libxl_arm.c | 214 +-
tools/libxl/libxl_bootloader.c | 20 +-
tools/libxl/libxl_cpuid.c | 142 +-
tools/libxl/libxl_create.c | 281 +-
tools/libxl/libxl_device.c | 127 +-
tools/libxl/libxl_dm.c | 191 +-
tools/libxl/libxl_dom.c | 965 ++++-
tools/libxl/libxl_event.c | 174 +-
tools/libxl/libxl_exec.c | 55 +-
tools/libxl/libxl_freebsd.c | 133 +
tools/libxl/libxl_genid.c | 117 +
tools/libxl/libxl_internal.c | 195 +-
tools/libxl/libxl_internal.h | 757 +++-
tools/libxl/libxl_json.c | 467 ++-
tools/libxl/libxl_json.h | 3 +-
tools/libxl/libxl_netbuffer.c | 517 +++
tools/libxl/libxl_nocpuid.c | 18 +
tools/libxl/libxl_nonetbuffer.c | 54 +
tools/libxl/libxl_numa.c | 5 +
tools/libxl/libxl_osdeps.h | 7 +
tools/libxl/libxl_paths.c | 7 +-
tools/libxl/libxl_pci.c | 293 +-
tools/libxl/libxl_psr.c | 217 +
tools/libxl/libxl_qmp.c | 11 +-
tools/libxl/libxl_remus_device.c | 327 ++
tools/libxl/libxl_remus_disk_drbd.c | 258 ++
tools/libxl/libxl_save_callout.c | 16 +-
tools/libxl/libxl_save_helper.c | 109 +-
tools/libxl/libxl_save_msgs_gen.pl | 13 +-
tools/libxl/libxl_types.idl | 148 +-
tools/libxl/libxl_types_internal.idl | 9 +-
tools/libxl/libxl_utils.c | 100 +-
tools/libxl/libxl_utils.h | 32 +
tools/libxl/libxl_uuid.c | 64 +-
tools/libxl/libxl_uuid.h | 29 +-
tools/libxl/libxlu_cfg_y.c | 538 +--
tools/libxl/libxlu_cfg_y.h | 14 +-
tools/libxl/libxlu_disk_l.c | 707 ++--
tools/libxl/libxlu_disk_l.h | 2 +-
tools/libxl/libxlu_disk_l.l | 3 +
tools/libxl/libxlu_pci.c | 2 +
tools/libxl/xen-init-dom0.c | 120 +
tools/libxl/xl.c | 41 +-
tools/libxl/xl.h | 23 +-
tools/libxl/xl_cmdimpl.c | 1526 +++++--
tools/libxl/xl_cmdtable.c | 54 +-
tools/libxl/xl_sxp.c | 13 +-
tools/memshr/Makefile | 1 -
tools/misc/Makefile | 15 +-
tools/misc/mkdeb | 31 +-
tools/misc/mkrpm | 76 +
tools/misc/mktarball | 38 +
tools/misc/nsplitd/Makefile | 25 -
tools/misc/nsplitd/nsplitd.c | 686 ---
tools/misc/sxp-pretty | 37 -
tools/misc/xen-hptool.c | 24 +-
tools/misc/xen-mfndump.c | 72 +-
tools/misc/xen-python-path | 24 -
tools/misc/xenpm.c | 95 +-
tools/ocaml/Makefile | 7 +-
tools/ocaml/libs/eventchn/xeneventchn.mli | 2 +-
tools/ocaml/libs/xb/Makefile | 1 +
tools/ocaml/libs/xb/xb.ml | 21 +
tools/ocaml/libs/xb/xb.mli | 4 +-
tools/ocaml/libs/xb/xs_ring.ml | 28 +
tools/ocaml/libs/xb/xs_ring_stubs.c | 118 +-
tools/ocaml/libs/xc/Makefile | 1 +
tools/ocaml/libs/xc/xenctrl_stubs.c | 8 +-
tools/ocaml/libs/xentoollog/Makefile | 3 +-
tools/ocaml/libs/xentoollog/genlevels.py | 2 +-
tools/ocaml/libs/xl/Makefile | 1 +
tools/ocaml/libs/xl/genwrap.py | 1 +
tools/ocaml/libs/xl/xenlight_stubs.c | 25 +
tools/ocaml/test/Makefile | 1 +
tools/ocaml/xenstored/Makefile | 24 +-
tools/ocaml/xenstored/connection.ml | 20 +-
tools/ocaml/xenstored/connections.ml | 61 +-
tools/ocaml/xenstored/domain.ml | 12 +-
tools/ocaml/xenstored/logging.ml | 11 +-
tools/ocaml/xenstored/oxenstored.conf | 3 +
tools/ocaml/xenstored/parse_arg.ml | 8 +-
tools/ocaml/xenstored/process.ml | 14 +-
tools/ocaml/xenstored/quota.ml | 5 +
tools/ocaml/xenstored/select.ml | 77 +
tools/ocaml/xenstored/select.mli | 27 +
tools/ocaml/xenstored/select_stubs.c | 80 +
tools/ocaml/xenstored/store.ml | 19 +-
tools/ocaml/xenstored/systemd.ml | 17 +
tools/ocaml/xenstored/systemd.mli | 24 +
tools/ocaml/xenstored/systemd_stubs.c | 152 +
tools/ocaml/xenstored/transaction.ml | 4 +-
tools/ocaml/xenstored/utils.ml | 21 +-
tools/ocaml/xenstored/xenstored.ml | 86 +-
tools/pygrub/Makefile | 13 +-
tools/pygrub/src/GrubConf.py | 10 +-
tools/pygrub/src/pygrub | 102 +-
tools/python/Makefile | 35 +-
tools/python/README.XendConfig | 160 -
tools/python/README.sxpcfg | 114 -
tools/python/logging/logging-0.4.9.2/PKG-INFO | 25 -
tools/python/logging/logging-0.4.9.2/README.txt | 311 --
tools/python/logging/logging-0.4.9.2/default.css | 32 -
.../python/logging/logging-0.4.9.2/liblogging.tex | 1281 ------
.../logging/logging-0.4.9.2/logging/__init__.py | 1225 ------
.../logging/logging-0.4.9.2/logging/config.py | 301 --
.../logging/logging-0.4.9.2/logging/handlers.py | 787 ----
.../logging/logging-0.4.9.2/python_logging.html | 1183 ------
tools/python/logging/logging-0.4.9.2/setup.py | 29 -
tools/python/logging/logging-0.4.9.2/test/app.py | 5 -
.../logging/logging-0.4.9.2/test/critical.ini | 60 -
.../python/logging/logging-0.4.9.2/test/debug.ini | 60 -
.../python/logging/logging-0.4.9.2/test/error.ini | 60 -
.../python/logging/logging-0.4.9.2/test/events.xml | 31 -
.../logging/logging-0.4.9.2/test/log_test.py | 158 -
.../logging/logging-0.4.9.2/test/log_test0.py | 118 -
.../logging/logging-0.4.9.2/test/log_test1.py | 85 -
.../logging/logging-0.4.9.2/test/log_test10.py | 87 -
.../logging/logging-0.4.9.2/test/log_test11.py | 72 -
.../logging/logging-0.4.9.2/test/log_test12.py | 47 -
.../logging/logging-0.4.9.2/test/log_test13.py | 106 -
.../logging/logging-0.4.9.2/test/log_test14.py | 108 -
.../logging/logging-0.4.9.2/test/log_test15.py | 70 -
.../logging/logging-0.4.9.2/test/log_test16.py | 73 -
.../logging/logging-0.4.9.2/test/log_test17.py | 111 -
.../logging/logging-0.4.9.2/test/log_test18.py | 102 -
.../logging/logging-0.4.9.2/test/log_test19.py | 57 -
.../logging/logging-0.4.9.2/test/log_test2.py | 119 -
.../logging/logging-0.4.9.2/test/log_test20.py | 84 -
.../logging/logging-0.4.9.2/test/log_test21.py | 141 -
.../logging/logging-0.4.9.2/test/log_test22.py | 50 -
.../logging/logging-0.4.9.2/test/log_test3.ini | 95 -
.../logging/logging-0.4.9.2/test/log_test3.py | 70 -
.../logging/logging-0.4.9.2/test/log_test4.py | 168 -
.../logging/logging-0.4.9.2/test/log_test5.py | 44 -
.../logging/logging-0.4.9.2/test/log_test6.py | 47 -
.../logging/logging-0.4.9.2/test/log_test7.py | 48 -
.../logging/logging-0.4.9.2/test/log_test8.py | 69 -
.../logging/logging-0.4.9.2/test/log_test9.py | 71 -
.../logging/logging-0.4.9.2/test/logconf.ini | 180 -
.../python/logging/logging-0.4.9.2/test/logconf.py | 1738 --------
.../logging/logging-0.4.9.2/test/logging.dtd | 19 -
.../logging/logging-0.4.9.2/test/logging.xml | 5 -
.../logging/logging-0.4.9.2/test/logrecv.ini | 36 -
.../python/logging/logging-0.4.9.2/test/logrecv.py | 443 --
tools/python/logging/logging-0.4.9.2/test/myapp.py | 13 -
.../logging/logging-0.4.9.2/test/mymodule.py | 8 -
.../python/logging/logging-0.4.9.2/test/stderr.exp | 566 ---
.../python/logging/logging-0.4.9.2/test/stdout.exp | 24 -
tools/python/logging/logging-0.4.9.2/test/warn.ini | 60 -
tools/python/logging/setup.py | 11 -
tools/python/ptsname/ptsname.c | 44 -
tools/python/scripts/README | 49 -
tools/python/scripts/README.lifecycle | 136 -
tools/python/scripts/test_hvm_create.py | 178 -
tools/python/scripts/test_vm_create.py | 211 -
tools/python/scripts/xapi.domcfg.py | 37 -
tools/python/scripts/xapi.py | 854 ----
tools/python/scripts/xapi.vbdcfg.py | 12 -
tools/python/scripts/xapi.vdicfg.py | 6 -
tools/python/scripts/xapi.vifcfg.py | 10 -
tools/python/scripts/xapi.vtpmcfg.py | 3 -
tools/python/setup.py | 101 +-
tools/python/xen/lowlevel/checkpoint/checkpoint.c | 371 --
tools/python/xen/lowlevel/checkpoint/checkpoint.h | 61 -
.../python/xen/lowlevel/checkpoint/libcheckpoint.c | 847 ----
tools/python/xen/lowlevel/flask/flask.c | 292 --
tools/python/xen/lowlevel/netlink/libnetlink.c | 585 ---
tools/python/xen/lowlevel/netlink/libnetlink.h | 58 -
tools/python/xen/lowlevel/netlink/netlink.c | 215 -
tools/python/xen/lowlevel/process/process.c | 164 -
tools/python/xen/lowlevel/scf/scf.c | 156 -
tools/python/xen/lowlevel/xc/xc.c | 63 +-
tools/python/xen/remus/__init__.py | 0
tools/python/xen/remus/blkdev.py | 31 -
tools/python/xen/remus/device.py | 397 --
tools/python/xen/remus/image.py | 227 -
tools/python/xen/remus/netlink.py | 318 --
tools/python/xen/remus/profile.py | 56 -
tools/python/xen/remus/qdisc.py | 189 -
tools/python/xen/remus/save.py | 186 -
tools/python/xen/remus/tapdisk.py | 4 -
tools/python/xen/remus/util.py | 82 -
tools/python/xen/remus/vbd.py | 9 -
tools/python/xen/remus/vdi.py | 121 -
tools/python/xen/remus/vif.py | 18 -
tools/python/xen/remus/vm.py | 168 -
tools/python/xen/util/Brctl.py | 186 -
tools/python/xen/util/SSHTransport.py | 102 -
tools/python/xen/util/__init__.py | 1 -
tools/python/xen/util/acmpolicy.py | 1622 -------
tools/python/xen/util/asserts.py | 27 -
tools/python/xen/util/auxbin.py | 47 -
tools/python/xen/util/blkif.py | 107 -
tools/python/xen/util/bootloader.py | 626 ---
tools/python/xen/util/bugtool.py | 234 --
tools/python/xen/util/diagnose.py | 185 -
tools/python/xen/util/dictio.py | 50 -
tools/python/xen/util/fileuri.py | 156 -
tools/python/xen/util/ip.py | 121 -
tools/python/xen/util/mac.py | 11 -
tools/python/xen/util/mkdir.py | 44 -
tools/python/xen/util/oshelp.py | 33 -
tools/python/xen/util/pci.py | 1416 -------
tools/python/xen/util/rwlock.py | 137 -
tools/python/xen/util/sxputils.py | 64 -
tools/python/xen/util/utils.py | 78 -
tools/python/xen/util/vscsi_util.py | 304 --
tools/python/xen/util/vusb_util.py | 338 --
tools/python/xen/util/xmlrpcclient.py | 129 -
tools/python/xen/util/xmlrpclib2.py | 220 -
tools/python/xen/util/xpopen.py | 182 -
tools/python/xen/util/xsconstants.py | 115 -
tools/python/xen/util/xsm/__init__.py | 2 -
tools/python/xen/util/xsm/acm/__init__.py | 1 -
tools/python/xen/util/xsm/acm/acm.py | 1627 -------
tools/python/xen/util/xsm/dummy/__init__.py | 1 -
tools/python/xen/util/xsm/dummy/dummy.py | 136 -
tools/python/xen/util/xsm/flask/__init__.py | 1 -
tools/python/xen/util/xsm/flask/flask.py | 65 -
tools/python/xen/util/xsm/xsm.py | 20 -
tools/python/xen/util/xsm/xsm_core.py | 7 -
tools/python/xen/util/xspolicy.py | 66 -
tools/python/xen/web/SrvBase.py | 98 -
tools/python/xen/web/SrvDir.py | 126 -
tools/python/xen/web/__init__.py | 17 -
tools/python/xen/web/connection.py | 333 --
tools/python/xen/web/http.py | 518 ---
tools/python/xen/web/httpserver.py | 367 --
tools/python/xen/web/protocol.py | 40 -
tools/python/xen/web/resource.py | 108 -
tools/python/xen/web/static.py | 61 -
tools/python/xen/web/tcp.py | 212 -
tools/python/xen/web/unix.py | 69 -
tools/python/xen/xend/Args.py | 166 -
tools/python/xen/xend/MemoryPool.py | 118 -
tools/python/xen/xend/PrettyPrint.py | 323 --
tools/python/xen/xend/Vifctl.py | 35 -
tools/python/xen/xend/XendAPI.py | 2812 -------------
tools/python/xen/xend/XendAPIConstants.py | 82 -
tools/python/xen/xend/XendAPIStore.py | 83 -
tools/python/xen/xend/XendAPIVersion.py | 22 -
tools/python/xen/xend/XendAuthSessions.py | 131 -
tools/python/xen/xend/XendBase.py | 126 -
tools/python/xen/xend/XendBootloader.py | 230 -
tools/python/xen/xend/XendCPUPool.py | 910 ----
tools/python/xen/xend/XendCheckpoint.py | 425 --
tools/python/xen/xend/XendClient.py | 40 -
tools/python/xen/xend/XendConfig.py | 2265 ----------
tools/python/xen/xend/XendConstants.py | 164 -
tools/python/xen/xend/XendDPCI.py | 165 -
tools/python/xen/xend/XendDSCSI.py | 299 --
tools/python/xen/xend/XendDevices.py | 85 -
tools/python/xen/xend/XendDmesg.py | 41 -
tools/python/xen/xend/XendDomain.py | 1958 ---------
tools/python/xen/xend/XendDomainInfo.py | 4429 --------------------
tools/python/xen/xend/XendError.py | 252 --
tools/python/xen/xend/XendLocalStorageRepo.py | 93 -
tools/python/xen/xend/XendLogging.py | 149 -
tools/python/xen/xend/XendMonitor.py | 340 --
tools/python/xen/xend/XendNetwork.py | 238 --
tools/python/xen/xend/XendNode.py | 1183 ------
tools/python/xen/xend/XendOptions.py | 567 ---
tools/python/xen/xend/XendPBD.py | 99 -
tools/python/xen/xend/XendPIF.py | 390 --
tools/python/xen/xend/XendPIFMetrics.py | 59 -
tools/python/xen/xend/XendPPCI.py | 160 -
tools/python/xen/xend/XendPSCSI.py | 211 -
tools/python/xen/xend/XendProtocol.py | 225 -
tools/python/xen/xend/XendQCoWStorageRepo.py | 340 --
tools/python/xen/xend/XendSXPDev.py | 13 -
tools/python/xen/xend/XendStateStore.py | 234 --
tools/python/xen/xend/XendStorageRepository.py | 118 -
tools/python/xen/xend/XendTask.py | 224 -
tools/python/xen/xend/XendTaskManager.py | 110 -
tools/python/xen/xend/XendVDI.py | 214 -
tools/python/xen/xend/XendVMMetrics.py | 146 -
tools/python/xen/xend/XendVnet.py | 181 -
tools/python/xen/xend/XendXSPolicy.py | 305 --
tools/python/xen/xend/XendXSPolicyAdmin.py | 386 --
tools/python/xen/xend/__init__.py | 1 -
tools/python/xen/xend/arch.py | 32 -
tools/python/xen/xend/balloon.py | 244 --
tools/python/xen/xend/encode.py | 180 -
tools/python/xen/xend/image.py | 1103 -----
tools/python/xen/xend/osdep.py | 268 --
tools/python/xen/xend/server/BlktapController.py | 313 --
tools/python/xen/xend/server/ConsoleController.py | 38 -
tools/python/xen/xend/server/DevConstants.py | 49 -
tools/python/xen/xend/server/DevController.py | 677 ---
tools/python/xen/xend/server/SSLXMLRPCServer.py | 103 -
tools/python/xen/xend/server/SrvDaemon.py | 420 --
tools/python/xen/xend/server/SrvDmesg.py | 52 -
tools/python/xen/xend/server/SrvDomain.py | 329 --
tools/python/xen/xend/server/SrvDomainDir.py | 222 -
tools/python/xen/xend/server/SrvNode.py | 64 -
tools/python/xen/xend/server/SrvRoot.py | 43 -
tools/python/xen/xend/server/SrvServer.py | 261 --
tools/python/xen/xend/server/SrvVnetDir.py | 128 -
tools/python/xen/xend/server/SrvXendLog.py | 37 -
tools/python/xen/xend/server/XMLRPCServer.py | 273 --
tools/python/xen/xend/server/__init__.py | 1 -
tools/python/xen/xend/server/blkif.py | 221 -
tools/python/xen/xend/server/iopif.py | 102 -
tools/python/xen/xend/server/irqif.py | 95 -
tools/python/xen/xend/server/netif.py | 218 -
tools/python/xen/xend/server/netif2.py | 163 -
tools/python/xen/xend/server/params.py | 46 -
tools/python/xen/xend/server/pciif.py | 596 ---
tools/python/xen/xend/server/pciquirk.py | 149 -
tools/python/xen/xend/server/relocate.py | 173 -
tools/python/xen/xend/server/tests/__init__.py | 1 -
.../xen/xend/server/tests/test_controllers.py | 81 -
tools/python/xen/xend/server/udevevent.py | 92 -
tools/python/xen/xend/server/vfbif.py | 91 -
tools/python/xen/xend/server/vscsiif.py | 246 --
tools/python/xen/xend/server/vusbif.py | 126 -
tools/python/xen/xend/sxp.py | 765 ----
tools/python/xen/xend/tests/__init__.py | 1 -
tools/python/xen/xend/tests/test_XendConfig.py | 42 -
tools/python/xen/xend/tests/test_sxp.py | 39 -
tools/python/xen/xend/tests/test_uuid.py | 30 -
tools/python/xen/xend/tests/xend-config.sxp | 131 -
tools/python/xen/xend/uuid.py | 69 -
tools/python/xen/xend/xend | 110 -
tools/python/xen/xend/xenstore/__init__.py | 16 -
tools/python/xen/xend/xenstore/tests/__init__.py | 2 -
tools/python/xen/xend/xenstore/tests/stress_xs.py | 121 -
tools/python/xen/xend/xenstore/xstransact.py | 368 --
tools/python/xen/xend/xenstore/xsutil.py | 32 -
tools/python/xen/xend/xenstore/xswatch.py | 80 -
tools/python/xen/xm/XenAPI.py | 206 -
tools/python/xen/xm/__init__.py | 0
tools/python/xen/xm/addlabel.py | 274 --
tools/python/xen/xm/console.py | 88 -
tools/python/xen/xm/cpupool-create.py | 51 -
tools/python/xen/xm/cpupool-new.py | 50 -
tools/python/xen/xm/cpupool.py | 236 --
tools/python/xen/xm/create.dtd | 154 -
tools/python/xen/xm/create.py | 1529 -------
tools/python/xen/xm/dry-run.py | 161 -
tools/python/xen/xm/dumppolicy.py | 69 -
tools/python/xen/xm/getenforce.py | 66 -
tools/python/xen/xm/getlabel.py | 157 -
tools/python/xen/xm/getpolicy.py | 135 -
tools/python/xen/xm/help.py | 100 -
tools/python/xen/xm/labels.py | 89 -
tools/python/xen/xm/main.py | 4030 ------------------
tools/python/xen/xm/migrate.py | 87 -
tools/python/xen/xm/new.py | 79 -
tools/python/xen/xm/opts.py | 627 ---
tools/python/xen/xm/resetpolicy.py | 106 -
tools/python/xen/xm/resources.py | 65 -
tools/python/xen/xm/rmlabel.py | 216 -
tools/python/xen/xm/setenforce.py | 74 -
tools/python/xen/xm/setpolicy.py | 181 -
tools/python/xen/xm/shutdown.py | 164 -
tools/python/xen/xm/tests/__init__.py | 2 -
tools/python/xen/xm/tests/test_create.py | 206 -
tools/python/xen/xm/xenapi_create.py | 1129 -----
tools/python/xen/xm/xm | 20 -
tools/remus/Makefile | 15 -
tools/remus/README | 4 -
tools/remus/remus | 230 -
tools/tests/mce-test/tools/Makefile | 8 +-
tools/tests/mce-test/tools/xen-mceinj.c | 277 +-
tools/tests/utests/run_all_tests.py | 10 +-
tools/tests/utests/ut_util/ut_fileuri.py | 209 -
tools/tests/utests/ut_xend/ut_XendConfig.py | 117 -
tools/tests/utests/ut_xend/ut_image.py | 147 -
tools/tests/vhpet/.gitignore | 4 +
tools/tests/vhpet/Makefile | 36 +
tools/tests/vhpet/emul.h | 416 ++
tools/tests/vhpet/main.c | 776 ++++
tools/tests/x86_emulator/test_x86_emulator.c | 8 +-
tools/tests/x86_emulator/x86_emulate.c | 2 +
tools/tests/xen-access/xen-access.c | 136 +-
tools/xcutils/Makefile | 17 +-
tools/xcutils/xc_restore.c | 72 -
tools/xcutils/xc_save.c | 227 -
tools/xenmon/xenbaked.c | 2 +-
tools/xenpaging/Makefile | 10 +-
tools/xenpaging/xenpaging.c | 2 +-
tools/xenstat/libxenstat/Makefile | 7 +-
tools/xenstat/libxenstat/src/xenstat.c | 2 +-
tools/xenstat/libxenstat/src/xenstat_freebsd.c | 47 +
tools/xenstat/libxenstat/src/xenstat_linux.c | 42 +-
tools/xenstat/xentop/Makefile | 5 +-
tools/xenstat/xentop/xentop.1 | 4 +
tools/xenstat/xentop/xentop.c | 74 +-
tools/xenstore/Makefile | 49 +-
tools/xenstore/{ => include}/compat/xs.h | 0
tools/xenstore/{ => include}/compat/xs_lib.h | 0
tools/xenstore/{ => include}/xenstore.h | 0
tools/xenstore/{ => include}/xenstore_lib.h | 0
tools/xenstore/init-xenstore-domain.c | 14 +-
tools/xenstore/xenstore_client.c | 21 +-
tools/xenstore/xenstored_core.c | 109 +-
tools/xenstore/xenstored_core.h | 3 +
tools/xenstore/xenstored_domain.c | 3 +-
tools/xenstore/xenstored_linux.c | 73 -
tools/xenstore/xenstored_minios.c | 2 +-
tools/xenstore/xenstored_netbsd.c | 73 -
tools/xenstore/xenstored_osdep.h | 20 +
tools/xenstore/xenstored_posix.c | 54 +
tools/xenstore/xs.c | 5 +-
tools/xenstore/xs_lib.c | 7 +-
tools/xenstore/xs_tdb_dump.c | 1 +
tools/xentrace/Makefile | 4 +-
tools/xentrace/formats | 18 +
tools/xentrace/xenctx.c | 594 ++-
tools/xentrace/xentrace.8 | 4 +-
tools/xm-test/COPYING | 340 --
tools/xm-test/ChangeLog | 11 -
tools/xm-test/Makefile.am | 18 -
tools/xm-test/README | 310 --
tools/xm-test/TODO | 3 -
tools/xm-test/Writing_Tests_HOWTO | 136 -
tools/xm-test/autogen | 9 -
tools/xm-test/configure.ac | 155 -
tools/xm-test/grouptest/cpupool | 1 -
tools/xm-test/grouptest/create | 1 -
tools/xm-test/grouptest/default | 30 -
tools/xm-test/grouptest/medium | 24 -
tools/xm-test/grouptest/quick | 4 -
tools/xm-test/grouptest/xapi | 1 -
tools/xm-test/lib/XmTestLib/Console.py | 302 --
tools/xm-test/lib/XmTestLib/DomainTracking.py | 61 -
tools/xm-test/lib/XmTestLib/NetConfig.py | 268 --
tools/xm-test/lib/XmTestLib/Test.py | 203 -
tools/xm-test/lib/XmTestLib/XenAPIDomain.py | 183 -
tools/xm-test/lib/XmTestLib/XenDevice.py | 275 --
tools/xm-test/lib/XmTestLib/XenDomain.py | 385 --
tools/xm-test/lib/XmTestLib/XenMemory.py | 68 -
tools/xm-test/lib/XmTestLib/Xm.py | 245 --
tools/xm-test/lib/XmTestLib/__init__.py | 27 -
tools/xm-test/lib/XmTestLib/arch.py | 126 -
tools/xm-test/lib/XmTestLib/block_utils.py | 53 -
tools/xm-test/lib/XmTestLib/config.py.in | 7 -
tools/xm-test/lib/XmTestLib/network_utils.py | 60 -
tools/xm-test/lib/XmTestLib/xapi.py | 54 -
tools/xm-test/lib/XmTestReport/OSReport.py | 248 --
tools/xm-test/lib/XmTestReport/ProgReport.py | 119 -
tools/xm-test/lib/XmTestReport/Report.py | 156 -
tools/xm-test/lib/XmTestReport/ResultReport.py | 157 -
tools/xm-test/lib/XmTestReport/arch.py | 46 -
tools/xm-test/lib/XmTestReport/utils.py | 31 -
tools/xm-test/lib/XmTestReport/xmtest.py.in | 15 -
tools/xm-test/mergereport | 25 -
tools/xm-test/mkreport | 71 -
tools/xm-test/ramdisk/Makefile.am | 126 -
.../ramdisk/README-XenSource-initrd-0.7-img | 42 -
.../ramdisk/README-XenSource-initrd-0.8-img | 42 -
.../ramdisk/README-XenSource-initrd-1.0-img | 46 -
.../ramdisk/README-XenSource-initrd-1.1-img | 45 -
tools/xm-test/ramdisk/bin/create_disk_image | 384 --
tools/xm-test/ramdisk/configs/buildroot-i386 | 346 --
tools/xm-test/ramdisk/configs/busybox | 465 --
tools/xm-test/ramdisk/configs/uClibc | 172 -
tools/xm-test/ramdisk/make-release.sh | 44 -
.../patches/buildroot/add_xvd_devices.patch | 13 -
.../xm-test/ramdisk/patches/buildroot/hping.patch | 67 -
tools/xm-test/ramdisk/skel/.profile | 3 -
tools/xm-test/ramdisk/skel/etc/init.d/rcS | 19 -
tools/xm-test/ramdisk/skel/etc/inittab | 5 -
tools/xm-test/ramdisk/skel/root/.profile | 3 -
tools/xm-test/runtest.sh | 337 --
tools/xm-test/tests/Makefile.am | 43 -
tools/xm-test/tests/Makefile.am.template | 21 -
tools/xm-test/tests/_sanity/01_domu_proc.py | 32 -
tools/xm-test/tests/_sanity/Makefile.am | 21 -
.../block-create/01_block_attach_device_pos.py | 49 -
.../02_block_attach_file_device_pos.py | 49 -
.../04_block_attach_device_repeatedly_pos.py | 46 -
...ock_attach_and_dettach_device_repeatedly_pos.py | 49 -
.../block-create/06_block_attach_baddomain_neg.py | 18 -
.../block-create/07_block_attach_baddevice_neg.py | 53 -
.../08_block_attach_bad_filedevice_neg.py | 52 -
...ock_attach_and_dettach_device_check_data_pos.py | 66 -
.../10_block_attach_dettach_multiple_devices.py | 100 -
.../block-create/11_block_attach_shared_dom0.py | 38 -
.../block-create/12_block_attach_shared_domU.py | 30 -
tools/xm-test/tests/block-create/Makefile.am | 29 -
.../block-destroy/01_block-destroy_btblock_pos.py | 44 -
.../block-destroy/02_block-destroy_rtblock_pos.py | 41 -
.../block-destroy/03_block-destroy_nonexist_neg.py | 17 -
.../04_block-destroy_nonattached_neg.py | 33 -
.../block-destroy/05_block-destroy_byname_pos.py | 43 -
.../06_block-destroy_check_list_pos.py | 42 -
tools/xm-test/tests/block-destroy/Makefile.am | 26 -
.../block-integrity/01_block_device_read_verify.py | 62 -
.../02_block_device_write_verify.py | 63 -
tools/xm-test/tests/block-integrity/Makefile.am | 22 -
.../xm-test/tests/block-list/01_block-list_pos.py | 42 -
.../tests/block-list/02_block-list_attachbd_pos.py | 46 -
.../block-list/03_block-list_anotherbd_pos.py | 54 -
.../tests/block-list/04_block-list_nodb_pos.py | 28 -
.../tests/block-list/05_block-list_nonexist_neg.py | 18 -
.../block-list/06_block-list_checkremove_pos.py | 61 -
tools/xm-test/tests/block-list/Makefile.am | 26 -
.../xm-test/tests/console/01_console_badopt_neg.py | 21 -
.../xm-test/tests/console/02_console_baddom_neg.py | 27 -
tools/xm-test/tests/console/Makefile.am | 22 -
.../xm-test/tests/cpupool/01_cpupool_basic_pos.py | 72 -
.../xm-test/tests/cpupool/02_cpupool_manage_pos.py | 152 -
tools/xm-test/tests/cpupool/03_cpupool_domain.py | 126 -
tools/xm-test/tests/cpupool/04_cpupool_migrate.py | 84 -
tools/xm-test/tests/cpupool/Makefile.am | 22 -
tools/xm-test/tests/cpupool/pool1.cfg | 1 -
tools/xm-test/tests/cpupool/pools.py | 78 -
tools/xm-test/tests/create/01_create_basic_pos.py | 49 -
tools/xm-test/tests/create/02_create_noparm_neg.py | 17 -
.../xm-test/tests/create/03_create_badparm_neg.py | 19 -
.../tests/create/04_create_conflictname_neg.py | 41 -
tools/xm-test/tests/create/06_create_mem_neg.py | 53 -
tools/xm-test/tests/create/07_create_mem64_pos.py | 49 -
tools/xm-test/tests/create/08_create_mem128_pos.py | 49 -
tools/xm-test/tests/create/09_create_mem256_pos.py | 49 -
.../xm-test/tests/create/10_create_fastdestroy.py | 43 -
.../tests/create/11_create_concurrent_pos.py | 78 -
.../create/12_create_concurrent_stress_pos.py | 59 -
.../xm-test/tests/create/13_create_multinic_pos.py | 27 -
.../tests/create/14_create_blockroot_pos.py | 44 -
.../xm-test/tests/create/15_create_smallmem_pos.py | 27 -
.../xm-test/tests/create/16_create_smallmem_neg.py | 30 -
tools/xm-test/tests/create/Makefile.am | 33 -
.../xm-test/tests/destroy/01_destroy_basic_pos.py | 40 -
.../xm-test/tests/destroy/02_destroy_noparm_neg.py | 16 -
.../tests/destroy/03_destroy_nonexist_neg.py | 16 -
.../tests/destroy/04_destroy_badparm_neg.py | 16 -
tools/xm-test/tests/destroy/05_destroy_byid_pos.py | 33 -
tools/xm-test/tests/destroy/06_destroy_dom0_neg.py | 14 -
.../xm-test/tests/destroy/07_destroy_stale_pos.py | 133 -
tools/xm-test/tests/destroy/Makefile.am | 27 -
tools/xm-test/tests/dmesg/01_dmesg_basic_pos.py | 15 -
tools/xm-test/tests/dmesg/02_dmesg_basic_neg.py | 17 -
tools/xm-test/tests/dmesg/Makefile.am | 21 -
tools/xm-test/tests/domid/01_domid_basic_pos.py | 16 -
tools/xm-test/tests/domid/02_domid_basic_neg.py | 15 -
tools/xm-test/tests/domid/Makefile.am | 21 -
.../xm-test/tests/domname/01_domname_basic_pos.py | 17 -
.../xm-test/tests/domname/02_domname_basic_neg.py | 15 -
tools/xm-test/tests/domname/Makefile.am | 21 -
.../01_enforce_dom0_cpus_basic_pos.py | 126 -
tools/xm-test/tests/enforce_dom0_cpus/Makefile.am | 21 -
tools/xm-test/tests/help/01_help_basic_pos.py | 14 -
tools/xm-test/tests/help/02_help_basic_neg.py | 14 -
tools/xm-test/tests/help/03_help_badparm_neg.py | 14 -
tools/xm-test/tests/help/04_help_long_pos.py | 16 -
tools/xm-test/tests/help/05_help_nonroot_pos.py | 17 -
tools/xm-test/tests/help/06_help_allcmds.py | 44 -
tools/xm-test/tests/help/Makefile.am | 26 -
tools/xm-test/tests/info/01_info_basic_pos.py | 11 -
.../xm-test/tests/info/02_info_compiledata_pos.py | 42 -
tools/xm-test/tests/info/Makefile.am | 22 -
tools/xm-test/tests/list/01_list_basic_pos.py | 14 -
tools/xm-test/tests/list/02_list_badparm_neg.py | 16 -
tools/xm-test/tests/list/03_list_nonexist_neg.py | 17 -
tools/xm-test/tests/list/04_list_goodparm_pos.py | 28 -
tools/xm-test/tests/list/05_list_long_pos.py | 22 -
tools/xm-test/tests/list/06_list_nonroot.py | 15 -
tools/xm-test/tests/list/Makefile.am | 27 -
.../xm-test/tests/memmax/01_memmax_badparm_neg.py | 29 -
tools/xm-test/tests/memmax/Makefile.am | 21 -
tools/xm-test/tests/memset/01_memset_basic_pos.py | 82 -
.../xm-test/tests/memset/02_memset_badparm_neg.py | 56 -
tools/xm-test/tests/memset/03_memset_random_pos.py | 64 -
.../xm-test/tests/memset/04_memset_smallmem_pos.py | 55 -
tools/xm-test/tests/memset/Makefile.am | 24 -
.../tests/migrate/01_migrate_localhost_pos.py | 86 -
tools/xm-test/tests/migrate/Makefile.am | 20 -
.../tests/network-attach/01_network_attach_pos.py | 43 -
.../network-attach/02_network_attach_detach_pos.py | 49 -
.../03_network_attach_detach_multiple_pos.py | 51 -
.../04_network_attach_baddomain_neg.py | 15 -
tools/xm-test/tests/network-attach/Makefile.am | 24 -
.../tests/network/02_network_local_ping_pos.py | 71 -
.../tests/network/03_network_local_tcp_pos.py | 75 -
.../tests/network/04_network_local_udp_pos.py | 76 -
.../tests/network/05_network_dom0_ping_pos.py | 54 -
.../tests/network/06_network_dom0_tcp_pos.py | 57 -
.../tests/network/07_network_dom0_udp_pos.py | 56 -
.../tests/network/11_network_domU_ping_pos.py | 62 -
.../tests/network/12_network_domU_tcp_pos.py | 64 -
.../tests/network/13_network_domU_udp_pos.py | 76 -
tools/xm-test/tests/network/Makefile.am | 34 -
tools/xm-test/tests/pause/01_pause_basic_pos.py | 63 -
tools/xm-test/tests/pause/02_pause_badopt_neg.py | 32 -
tools/xm-test/tests/pause/03_pause_badname_neg.py | 18 -
tools/xm-test/tests/pause/04_pause_badid_neg.py | 18 -
tools/xm-test/tests/pause/Makefile.am | 22 -
tools/xm-test/tests/reboot/01_reboot_basic_pos.py | 52 -
tools/xm-test/tests/reboot/02_reboot_badopt_neg.py | 32 -
.../xm-test/tests/reboot/03_reboot_badname_neg.py | 18 -
tools/xm-test/tests/reboot/Makefile.am | 23 -
.../xm-test/tests/restore/01_restore_basic_pos.py | 82 -
.../tests/restore/02_restore_badparm_neg.py | 28 -
.../tests/restore/03_restore_badfilename_neg.py | 28 -
.../tests/restore/04_restore_withdevices_pos.py | 130 -
tools/xm-test/tests/restore/Makefile.am | 24 -
tools/xm-test/tests/save/01_save_basic_pos.py | 37 -
tools/xm-test/tests/save/02_save_badparm_neg.py | 28 -
tools/xm-test/tests/save/03_save_bogusfile_neg.py | 39 -
tools/xm-test/tests/save/Makefile.am | 24 -
.../sched-credit/01_sched_credit_weight_cap_pos.py | 72 -
tools/xm-test/tests/sched-credit/Makefile.am | 20 -
.../xm-test/tests/sedf/01_sedf_period_slice_pos.py | 62 -
.../xm-test/tests/sedf/02_sedf_period_lower_neg.py | 44 -
.../xm-test/tests/sedf/03_sedf_slice_lower_neg.py | 40 -
.../xm-test/tests/sedf/04_sedf_slice_upper_neg.py | 48 -
tools/xm-test/tests/sedf/05_sedf_extratime_pos.py | 63 -
.../tests/sedf/06_sedf_extratime_disable_neg.py | 71 -
tools/xm-test/tests/sedf/Makefile.am | 25 -
.../tests/shutdown/01_shutdown_basic_pos.py | 54 -
.../tests/shutdown/02_shutdown_badparm_neg.py | 39 -
.../tests/shutdown/03_shutdown_nonexist_neg.py | 22 -
tools/xm-test/tests/shutdown/Makefile.am | 21 -
tools/xm-test/tests/sysrq/01_sysrq_basic_neg.py | 20 -
tools/xm-test/tests/sysrq/02_sysrq_sync_pos.py | 52 -
.../xm-test/tests/sysrq/03_sysrq_withreboot_pos.py | 40 -
tools/xm-test/tests/sysrq/Makefile.am | 23 -
.../xm-test/tests/unpause/01_unpause_basic_pos.py | 76 -
tools/xm-test/tests/unpause/Makefile.am | 20 -
.../vcpu-disable/01_vcpu-disable_basic_pos.py | 82 -
tools/xm-test/tests/vcpu-disable/Makefile.am | 21 -
.../tests/vcpu-pin/01_vcpu-pin_basic_pos.py | 50 -
tools/xm-test/tests/vcpu-pin/Makefile.am | 21 -
tools/xm-test/tests/xapi/01_xapi-vm_basic.py | 61 -
tools/xm-test/tests/xapi/02_xapi-vbd_basic.py | 122 -
tools/xm-test/tests/xapi/03_xapi-network_pos.py | 123 -
.../tests/xapi/04_xapi-data_uri_handling.py | 65 -
tools/xm-test/tests/xapi/20_xapi-cpu_pool_basic.py | 157 -
tools/xm-test/tests/xapi/Makefile.am | 23 -
xen/Makefile | 35 +-
xen/Rules.mk | 12 +-
xen/arch/arm/Makefile | 14 +-
xen/arch/arm/README.LinuxPrimitives | 163 +
xen/arch/arm/Rules.mk | 34 +-
xen/arch/arm/arm32/Makefile | 2 +-
xen/arch/arm/arm32/asm-offsets.c | 11 +-
xen/arch/arm/arm32/debug-exynos4210.inc | 32 -
xen/arch/arm/arm32/head.S | 196 +-
xen/arch/arm/arm32/lib/Makefile | 3 +-
xen/arch/arm/arm32/lib/assembler.h | 8 +-
xen/arch/arm/arm32/lib/bitops.h | 22 +-
xen/arch/arm/arm32/lib/changebit.S | 4 +-
xen/arch/arm/arm32/lib/clearbit.S | 4 +-
xen/arch/arm/arm32/lib/copy_template.S | 36 +-
xen/arch/arm/arm32/lib/memchr.S | 28 +
xen/arch/arm/arm32/lib/memmove.S | 36 +-
xen/arch/arm/arm32/lib/memset.S | 100 +-
xen/arch/arm/arm32/lib/setbit.S | 4 +-
xen/arch/arm/arm32/lib/strchr.S | 29 +
xen/arch/arm/arm32/lib/strrchr.S | 28 +
xen/arch/arm/arm32/lib/testchangebit.S | 4 +-
xen/arch/arm/arm32/lib/testclearbit.S | 4 +-
xen/arch/arm/arm32/lib/testsetbit.S | 4 +-
xen/arch/arm/arm32/proc-caxx.c | 35 +
xen/arch/arm/arm32/proc-v7.S | 19 +-
xen/arch/arm/arm32/traps.c | 23 +
xen/arch/arm/arm64/Makefile | 1 +
xen/arch/arm/arm64/asm-offsets.c | 11 +-
xen/arch/arm/arm64/cache.S | 52 +
xen/arch/arm/arm64/domain.c | 4 +-
xen/arch/arm/arm64/domctl.c | 7 +-
xen/arch/arm/arm64/head.S | 350 +-
xen/arch/arm/arm64/lib/Makefile | 3 +
xen/arch/arm/arm64/lib/assembler.h | 12 +
xen/arch/arm/arm64/lib/bitops.S | 3 +-
xen/arch/arm/arm64/lib/clear_page.S | 36 +
xen/arch/arm/arm64/lib/memchr.S | 44 +
xen/arch/arm/arm64/lib/memcmp.S | 258 ++
xen/arch/arm/arm64/lib/memcpy.S | 201 +
xen/arch/arm/arm64/lib/memmove.S | 197 +
xen/arch/arm/arm64/lib/memset.S | 216 +
xen/arch/arm/arm64/lib/strchr.S | 41 +
xen/arch/arm/arm64/lib/strcmp.S | 235 ++
xen/arch/arm/arm64/lib/strlen.S | 128 +
xen/arch/arm/arm64/lib/strncmp.S | 311 ++
xen/arch/arm/arm64/lib/strnlen.S | 172 +
xen/arch/arm/arm64/lib/strrchr.S | 42 +
xen/arch/arm/arm64/smpboot.c | 5 +-
xen/arch/arm/arm64/vfp.c | 6 +-
xen/arch/arm/bootfdt.c | 370 ++
xen/arch/arm/decode.c | 2 +-
xen/arch/arm/device.c | 15 +
xen/arch/arm/domain.c | 107 +-
xen/arch/arm/domain_build.c | 520 ++-
xen/arch/arm/domctl.c | 35 +
xen/arch/arm/early_printk.c | 36 +-
xen/arch/arm/efi/Makefile | 3 +
xen/arch/arm/efi/efi-boot.h | 576 +++
xen/arch/arm/efi/runtime.h | 1 +
xen/arch/arm/gic-v2.c | 787 ++++
xen/arch/arm/gic-v3.c | 1299 ++++++
xen/arch/arm/gic.c | 1017 ++---
xen/arch/arm/guestcopy.c | 2 +-
xen/arch/arm/io.c | 59 +-
xen/arch/arm/io.h | 57 -
xen/arch/arm/irq.c | 388 +-
xen/arch/arm/kernel.c | 281 +-
xen/arch/arm/kernel.h | 46 +-
xen/arch/arm/mm.c | 256 +-
xen/arch/arm/p2m.c | 1072 +++--
xen/arch/arm/platform.c | 2 +-
xen/arch/arm/platforms/Makefile | 2 +
xen/arch/arm/platforms/brcm.c | 294 ++
xen/arch/arm/platforms/exynos5.c | 232 +-
xen/arch/arm/platforms/omap5.c | 47 +-
xen/arch/arm/platforms/seattle.c | 60 +
xen/arch/arm/platforms/sunxi.c | 32 +
xen/arch/arm/platforms/vexpress.c | 8 +-
xen/arch/arm/platforms/xgene-storm.c | 124 +-
xen/arch/arm/processor.c | 49 +
xen/arch/arm/psci.c | 108 +-
xen/arch/arm/setup.c | 327 +-
xen/arch/arm/shutdown.c | 27 +-
xen/arch/arm/smc.S | 21 +
xen/arch/arm/smp.c | 13 +-
xen/arch/arm/smpboot.c | 18 +-
xen/arch/arm/time.c | 102 +-
xen/arch/arm/traps.c | 349 +-
xen/arch/arm/vgic-v2.c | 589 +++
xen/arch/arm/vgic-v3.c | 1086 +++++
xen/arch/arm/vgic.c | 735 +---
xen/arch/arm/vpsci.c | 136 +-
xen/arch/arm/vtimer.c | 33 +-
xen/arch/arm/vtimer.h | 2 +-
xen/arch/arm/vuart.c | 30 +-
xen/arch/arm/xen.lds.S | 17 +
xen/arch/x86/Makefile | 2 +
xen/arch/x86/Rules.mk | 1 +
xen/arch/x86/acpi/boot.c | 12 +-
xen/arch/x86/acpi/cpu_idle.c | 120 +-
xen/arch/x86/acpi/cpufreq/cpufreq.c | 4 +-
xen/arch/x86/acpi/cpuidle_menu.c | 21 +-
xen/arch/x86/acpi/suspend.c | 6 +-
xen/arch/x86/alternative.c | 213 +
xen/arch/x86/apic.c | 63 +-
xen/arch/x86/boot/Makefile | 8 +-
xen/arch/x86/boot/build32.mk | 5 +-
xen/arch/x86/boot/cmdline.S | 4 +
xen/arch/x86/boot/head.S | 37 +-
xen/arch/x86/boot/reloc.c | 15 +-
xen/arch/x86/boot/trampoline.S | 5 +-
xen/arch/x86/boot/wakeup.S | 5 +-
xen/arch/x86/boot/x86_64.S | 53 +-
xen/arch/x86/bzimage.c | 4 +-
xen/arch/x86/cpu/amd.c | 199 +-
xen/arch/x86/cpu/common.c | 197 +-
xen/arch/x86/cpu/cpu.h | 1 -
xen/arch/x86/cpu/intel.c | 159 +-
xen/arch/x86/cpu/intel_cacheinfo.c | 49 +-
xen/arch/x86/cpu/mcheck/Makefile | 2 -
xen/arch/x86/cpu/mcheck/amd_f10.c | 147 -
xen/arch/x86/cpu/mcheck/amd_k8.c | 117 -
xen/arch/x86/cpu/mcheck/mcaction.c | 2 +-
xen/arch/x86/cpu/mcheck/mcaction.h | 2 +-
xen/arch/x86/cpu/mcheck/mce-apei.c | 19 +-
xen/arch/x86/cpu/mcheck/mce.c | 30 +-
xen/arch/x86/cpu/mcheck/mce.h | 7 +-
xen/arch/x86/cpu/mcheck/mce_amd.c | 160 +-
xen/arch/x86/cpu/mcheck/mce_amd.h | 3 -
xen/arch/x86/cpu/mcheck/mce_intel.c | 18 +-
xen/arch/x86/cpu/mcheck/mctelem.c | 21 +-
xen/arch/x86/cpu/mcheck/mctelem.h | 2 +-
xen/arch/x86/cpu/mcheck/vmce.c | 20 +-
xen/arch/x86/cpu/mcheck/vmce.h | 5 +-
xen/arch/x86/cpu/mcheck/x86_mca.h | 2 +-
xen/arch/x86/cpu/mtrr/generic.c | 181 +-
xen/arch/x86/cpu/mtrr/main.c | 2 +-
xen/arch/x86/cpu/mtrr/mtrr.h | 18 -
xen/arch/x86/cpu/mwait-idle.c | 276 +-
xen/arch/x86/crash.c | 8 +-
xen/arch/x86/dmi_scan.c | 8 +-
xen/arch/x86/domain.c | 148 +-
xen/arch/x86/domain_build.c | 752 +++-
xen/arch/x86/domain_page.c | 6 +-
xen/arch/x86/domctl.c | 310 +-
xen/arch/x86/e820.c | 8 +-
xen/arch/x86/efi/boot.c | 1723 --------
xen/arch/x86/efi/efi-boot.h | 639 +++
xen/arch/x86/efi/efi.h | 39 -
xen/arch/x86/efi/runtime.c | 547 ---
xen/arch/x86/efi/runtime.h | 5 +
xen/arch/x86/efi/stub.c | 6 +
xen/arch/x86/flushtlb.c | 31 +-
xen/arch/x86/genapic/x2apic.c | 5 +
xen/arch/x86/hpet.c | 2 +-
xen/arch/x86/hvm/emulate.c | 337 +-
xen/arch/x86/hvm/hpet.c | 188 +-
xen/arch/x86/hvm/hvm.c | 2573 +++++++++---
xen/arch/x86/hvm/i8254.c | 20 +-
xen/arch/x86/hvm/intercept.c | 34 +-
xen/arch/x86/hvm/io.c | 154 +-
xen/arch/x86/hvm/irq.c | 29 +-
xen/arch/x86/hvm/mtrr.c | 350 +-
xen/arch/x86/hvm/rtc.c | 18 +
xen/arch/x86/hvm/save.c | 6 +
xen/arch/x86/hvm/svm/svm.c | 315 +-
xen/arch/x86/hvm/svm/vpmu.c | 7 +-
xen/arch/x86/hvm/viridian.c | 142 +-
xen/arch/x86/hvm/vlapic.c | 373 +-
xen/arch/x86/hvm/vmsi.c | 47 +-
xen/arch/x86/hvm/vmx/realmode.c | 23 +-
xen/arch/x86/hvm/vmx/vmcs.c | 55 +-
xen/arch/x86/hvm/vmx/vmx.c | 293 +-
xen/arch/x86/hvm/vmx/vpmu_core2.c | 79 +-
xen/arch/x86/hvm/vmx/vvmx.c | 17 +-
xen/arch/x86/hvm/vpic.c | 20 +
xen/arch/x86/hvm/vpmu.c | 36 +-
xen/arch/x86/hvm/vpt.c | 20 +-
xen/arch/x86/i8259.c | 73 +-
xen/arch/x86/io_apic.c | 25 +-
xen/arch/x86/irq.c | 31 +-
xen/arch/x86/microcode_amd.c | 230 +-
xen/arch/x86/mm.c | 296 +-
xen/arch/x86/mm/Makefile | 2 -
xen/arch/x86/mm/guest_walk.c | 53 +-
xen/arch/x86/mm/hap/hap.c | 50 +-
xen/arch/x86/mm/hap/nested_ept.c | 6 +-
xen/arch/x86/mm/hap/nested_hap.c | 21 +-
xen/arch/x86/mm/mem_access.c | 70 -
xen/arch/x86/mm/mem_event.c | 698 ---
xen/arch/x86/mm/mem_paging.c | 2 +-
xen/arch/x86/mm/mem_sharing.c | 30 +-
xen/arch/x86/mm/p2m-ept.c | 642 ++-
xen/arch/x86/mm/p2m-pod.c | 49 +-
xen/arch/x86/mm/p2m-pt.c | 553 ++-
xen/arch/x86/mm/p2m.c | 806 +++-
xen/arch/x86/mm/paging.c | 286 +-
xen/arch/x86/mm/shadow/common.c | 30 +-
xen/arch/x86/mm/shadow/multi.c | 69 +-
xen/arch/x86/mm/shadow/private.h | 6 +-
xen/arch/x86/msi.c | 55 +-
xen/arch/x86/nmi.c | 72 +-
xen/arch/x86/numa.c | 505 +--
xen/arch/x86/oprofile/backtrace.c | 8 +-
xen/arch/x86/oprofile/nmi_int.c | 4 +-
xen/arch/x86/oprofile/op_model_athlon.c | 15 +-
xen/arch/x86/oprofile/op_model_p4.c | 2 +-
xen/arch/x86/oprofile/op_model_ppro.c | 12 +-
xen/arch/x86/oprofile/op_x86_model.h | 2 +-
xen/arch/x86/physdev.c | 20 +-
xen/arch/x86/platform_hypercall.c | 159 +
xen/arch/x86/psr.c | 200 +
xen/arch/x86/setup.c | 121 +-
xen/arch/x86/shutdown.c | 49 +-
xen/arch/x86/smp.c | 12 +-
xen/arch/x86/smpboot.c | 60 +-
xen/arch/x86/srat.c | 16 +-
xen/arch/x86/sysctl.c | 67 +
xen/arch/x86/tboot.c | 15 +-
xen/arch/x86/time.c | 259 +-
xen/arch/x86/trace.c | 28 +-
xen/arch/x86/traps.c | 434 +-
xen/arch/x86/usercopy.c | 6 +
xen/arch/x86/x86_64/asm-offsets.c | 14 +-
xen/arch/x86/x86_64/compat/entry.S | 5 +-
xen/arch/x86/x86_64/compat/mm.c | 21 +-
xen/arch/x86/x86_64/compat/traps.c | 2 +-
xen/arch/x86/x86_64/entry.S | 129 +-
xen/arch/x86/x86_64/mm.c | 98 +-
xen/arch/x86/x86_64/mmconf-fam10h.c | 1 +
xen/arch/x86/x86_64/mmconfig-shared.c | 1 +
xen/arch/x86/x86_64/mmconfig.h | 4 -
xen/arch/x86/x86_64/platform_hypercall.c | 4 +
xen/arch/x86/x86_64/traps.c | 42 +-
xen/arch/x86/x86_emulate/x86_emulate.c | 247 +-
xen/arch/x86/x86_emulate/x86_emulate.h | 27 +-
xen/arch/x86/xen.lds.S | 15 +
xen/arch/x86/xstate.c | 91 +-
xen/common/Makefile | 4 +
xen/common/bitmap.c | 8 +-
xen/common/compat/domain.c | 2 +-
xen/common/compat/grant_table.c | 27 +-
xen/common/compat/memory.c | 9 +-
xen/common/cpupool.c | 49 +-
xen/common/device_tree.c | 582 +--
xen/common/domain.c | 247 +-
xen/common/domctl.c | 354 +-
xen/common/efi/boot.c | 1322 ++++++
xen/{arch/x86 => common}/efi/compat.c | 0
xen/common/efi/efi.h | 41 +
xen/common/efi/runtime.c | 600 +++
xen/common/event_channel.c | 19 +-
xen/common/event_fifo.c | 82 +-
xen/common/grant_table.c | 260 +-
xen/common/hvm/save.c | 19 +-
xen/common/kernel.c | 9 +-
xen/common/kexec.c | 2 +-
xen/common/keyhandler.c | 44 +-
xen/common/lib.c | 5 +
xen/common/libelf/libelf-private.h | 5 +
xen/common/libfdt/Makefile.libfdt | 4 +-
xen/common/libfdt/fdt.c | 30 +-
xen/common/libfdt/fdt_empty_tree.c | 84 +
xen/common/libfdt/fdt_ro.c | 7 +-
xen/common/libfdt/fdt_rw.c | 31 +-
xen/common/libfdt/fdt_sw.c | 4 +-
xen/common/libfdt/fdt_wip.c | 2 +-
xen/common/libfdt/version.lds | 6 +
xen/common/lz4/defs.h | 14 -
xen/common/lzo.c | 762 ++--
xen/common/mem_access.c | 159 +
xen/common/mem_event.c | 742 ++++
xen/common/memory.c | 215 +-
xen/common/page_alloc.c | 279 +-
xen/common/pdx.c | 117 +
xen/common/rangeset.c | 107 +-
xen/common/sched_credit.c | 161 +-
xen/common/sched_credit2.c | 534 ++-
xen/common/sched_rt.c | 1112 +++++
xen/common/sched_sedf.c | 14 +-
xen/common/schedule.c | 87 +-
xen/common/shutdown.c | 4 +-
xen/common/softirq.c | 56 +-
xen/common/symbols.c | 2 +-
xen/common/tmem.c | 608 +--
xen/common/trace.c | 10 +-
xen/common/unlzma.c | 2 +-
xen/common/vsprintf.c | 155 +-
xen/common/wait.c | 10 +-
xen/common/xenoprof.c | 10 +-
xen/crypto/rijndael.c | 3 +
xen/drivers/acpi/apei/erst.c | 47 +-
xen/drivers/char/console.c | 86 +-
xen/drivers/char/dt-uart.c | 9 +-
xen/drivers/char/ehci-dbgp.c | 8 +-
xen/drivers/char/exynos4210-uart.c | 41 +-
xen/drivers/char/ns16550.c | 487 ++-
xen/drivers/char/omap-uart.c | 43 +-
xen/drivers/char/pl011.c | 44 +-
xen/drivers/char/serial.c | 9 -
xen/drivers/passthrough/Makefile | 6 +-
xen/drivers/passthrough/amd/iommu_cmd.c | 3 +-
xen/drivers/passthrough/amd/iommu_detect.c | 2 +-
xen/drivers/passthrough/amd/iommu_guest.c | 11 +-
xen/drivers/passthrough/amd/iommu_init.c | 26 +-
xen/drivers/passthrough/amd/iommu_map.c | 56 +-
xen/drivers/passthrough/amd/pci_amd_iommu.c | 74 +-
xen/drivers/passthrough/arm/Makefile | 2 +
xen/drivers/passthrough/arm/iommu.c | 70 +
xen/drivers/passthrough/arm/smmu.c | 1784 ++++++++
xen/drivers/passthrough/device_tree.c | 108 +
xen/drivers/passthrough/io.c | 568 ++-
xen/drivers/passthrough/iommu.c | 523 +--
xen/drivers/passthrough/pci.c | 439 +-
xen/drivers/passthrough/vtd/extern.h | 9 +-
xen/drivers/passthrough/vtd/intremap.c | 4 +-
xen/drivers/passthrough/vtd/iommu.c | 322 +-
xen/drivers/passthrough/vtd/iommu.h | 2 -
xen/drivers/passthrough/vtd/qinval.c | 245 +-
xen/drivers/passthrough/vtd/quirks.c | 46 +-
xen/drivers/passthrough/vtd/x86/vtd.c | 14 +-
xen/drivers/passthrough/x86/Makefile | 1 +
xen/drivers/passthrough/x86/ats.c | 2 +-
xen/drivers/passthrough/x86/iommu.c | 145 +
xen/drivers/video/arm_hdlcd.c | 31 +-
xen/include/Makefile | 25 +-
xen/include/acpi/apei.h | 6 +-
xen/include/asm-arm/arm32/atomic.h | 196 +-
xen/include/asm-arm/arm32/bug.h | 13 +
xen/include/asm-arm/arm32/cmpxchg.h | 155 +
xen/include/asm-arm/arm32/flushtlb.h | 16 +-
xen/include/asm-arm/arm32/macros.h | 8 +
xen/include/asm-arm/arm32/page.h | 60 +-
xen/include/asm-arm/arm32/processor.h | 6 +-
xen/include/asm-arm/arm32/system.h | 131 +-
xen/include/asm-arm/arm64/atomic.h | 48 +-
xen/include/asm-arm/arm64/bug.h | 10 +
xen/include/asm-arm/arm64/cmpxchg.h | 178 +
xen/include/asm-arm/arm64/efibind.h | 216 +
xen/include/asm-arm/arm64/page.h | 45 +-
xen/include/asm-arm/arm64/processor.h | 10 +-
xen/include/asm-arm/arm64/spinlock.h | 6 +-
xen/include/asm-arm/arm64/system.h | 171 +-
xen/include/asm-arm/atomic.h | 23 +-
xen/include/asm-arm/bug.h | 77 +-
xen/include/asm-arm/config.h | 26 +-
xen/include/asm-arm/cpufeature.h | 8 +-
xen/include/asm-arm/debugger.h | 2 +-
xen/include/asm-arm/device.h | 14 +-
xen/include/asm-arm/domain.h | 96 +-
xen/include/asm-arm/early_printk.h | 27 +-
xen/include/asm-arm/efibind.h | 2 +
xen/include/asm-arm/event.h | 1 +
xen/include/asm-arm/flushtlb.h | 3 +
xen/include/asm-arm/gic.h | 317 +-
xen/include/asm-arm/gic_v3_defs.h | 161 +
xen/include/asm-arm/grant_table.h | 5 +-
xen/include/asm-arm/hvm/iommu.h | 10 +
xen/include/asm-arm/iommu.h | 36 +
xen/include/asm-arm/irq.h | 18 +-
xen/include/asm-arm/macros.h | 16 +
xen/include/asm-arm/mm.h | 50 +-
xen/include/asm-arm/mmio.h | 71 +
xen/include/asm-arm/numa.h | 1 +
xen/include/asm-arm/p2m.h | 56 +-
xen/include/asm-arm/page.h | 201 +-
xen/include/asm-arm/platform.h | 5 +
xen/include/asm-arm/platforms/exynos5.h | 7 +-
xen/include/asm-arm/processor-ca15.h | 42 -
xen/include/asm-arm/processor-ca7.h | 20 -
xen/include/asm-arm/processor.h | 153 +-
xen/include/asm-arm/procinfo.h | 17 +-
xen/include/asm-arm/psci.h | 87 +-
xen/include/asm-arm/setup.h | 55 +-
xen/include/asm-arm/smp.h | 2 +-
xen/include/asm-arm/softirq.h | 2 +
xen/include/asm-arm/string.h | 36 +-
xen/include/asm-arm/sysregs.h | 56 +
xen/include/asm-arm/system.h | 26 +-
xen/include/asm-arm/time.h | 10 +-
xen/include/asm-arm/types.h | 5 +
xen/include/asm-arm/vgic.h | 209 +
xen/include/asm-x86/acpi.h | 1 -
xen/include/asm-x86/alternative.h | 78 +
xen/include/asm-x86/apic.h | 2 +-
xen/include/asm-x86/apicdef.h | 17 +-
xen/include/asm-x86/asm_defns.h | 259 +-
xen/include/asm-x86/atomic.h | 43 +-
xen/include/asm-x86/bitops.h | 62 +-
xen/include/asm-x86/config.h | 11 +-
xen/include/asm-x86/cpufeature.h | 61 +-
xen/include/asm-x86/current.h | 27 +-
xen/include/asm-x86/debugreg.h | 14 +
xen/include/asm-x86/desc.h | 13 +-
xen/include/asm-x86/domain.h | 70 +-
xen/include/asm-x86/e820.h | 10 +-
xen/include/asm-x86/edd.h | 76 +-
xen/include/asm-x86/fixmap.h | 1 -
xen/include/asm-x86/flushtlb.h | 18 +
xen/include/asm-x86/genapic.h | 11 +-
xen/include/asm-x86/grant_table.h | 3 +
xen/include/asm-x86/hap.h | 2 +-
xen/include/asm-x86/hvm/cacheattr.h | 12 +-
xen/include/asm-x86/hvm/domain.h | 69 +-
xen/include/asm-x86/hvm/emulate.h | 13 +-
xen/include/asm-x86/hvm/hvm.h | 119 +-
xen/include/asm-x86/hvm/io.h | 6 +-
xen/include/asm-x86/hvm/iommu.h | 22 +
xen/include/asm-x86/hvm/support.h | 19 +-
xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 2 +-
xen/include/asm-x86/hvm/svm/svm.h | 6 +
xen/include/asm-x86/hvm/svm/vmcb.h | 27 +-
xen/include/asm-x86/hvm/trace.h | 7 +
xen/include/asm-x86/hvm/vcpu.h | 17 +-
xen/include/asm-x86/hvm/viridian.h | 27 +
xen/include/asm-x86/hvm/vlapic.h | 27 +-
xen/include/asm-x86/hvm/vmx/vmcs.h | 14 +
xen/include/asm-x86/hvm/vmx/vmx.h | 17 +-
xen/include/asm-x86/hvm/vpmu.h | 7 +-
xen/include/asm-x86/hvm/vpt.h | 4 +-
xen/include/asm-x86/i387.h | 4 +-
xen/include/asm-x86/io_apic.h | 20 +-
xen/include/asm-x86/iommu.h | 43 +
xen/include/asm-x86/irq.h | 2 +
xen/include/asm-x86/ldt.h | 2 +-
xen/include/asm-x86/mem_access.h | 35 -
xen/include/asm-x86/mem_event.h | 82 -
xen/include/asm-x86/mm.h | 14 +-
xen/include/asm-x86/msi.h | 10 +-
xen/include/asm-x86/msr-index.h | 64 +-
xen/include/asm-x86/msr.h | 6 +-
xen/include/asm-x86/mtrr.h | 27 +-
xen/include/asm-x86/nmi.h | 9 +-
xen/include/asm-x86/nops.h | 66 +
xen/include/asm-x86/p2m.h | 139 +-
xen/include/asm-x86/page.h | 5 -
xen/include/asm-x86/paging.h | 24 +-
xen/include/asm-x86/perfc_defn.h | 1 +
xen/include/asm-x86/processor.h | 92 +-
xen/include/asm-x86/psr.h | 61 +
xen/include/asm-x86/setup.h | 1 -
xen/include/asm-x86/shadow.h | 4 -
xen/include/asm-x86/softirq.h | 5 +-
xen/include/asm-x86/system.h | 2 +
xen/include/asm-x86/tboot.h | 4 -
xen/include/asm-x86/time.h | 13 +-
xen/include/asm-x86/traps.h | 2 -
xen/include/asm-x86/types.h | 1 +
xen/include/asm-x86/uaccess.h | 8 +-
xen/include/asm-x86/x86_64/asm_defns.h | 231 -
xen/include/asm-x86/x86_64/page.h | 36 +-
xen/include/asm-x86/x86_64/system.h | 4 +-
xen/include/asm-x86/xstate.h | 20 +-
xen/include/public/arch-arm.h | 50 +-
xen/include/public/arch-x86/cpuid.h | 29 +-
xen/include/public/arch-x86/hvm/save.h | 23 +-
xen/include/public/domctl.h | 172 +-
xen/include/public/event_channel.h | 4 +
xen/include/public/features.h | 5 +
xen/include/public/grant_table.h | 20 +
xen/include/public/hvm/hvm_op.h | 195 +-
xen/include/public/hvm/ioreq.h | 9 +-
xen/include/public/hvm/params.h | 48 +-
xen/include/public/io/blkif.h | 32 +
xen/include/public/io/netif.h | 53 +
xen/include/public/io/vscsiif.h | 185 +-
xen/include/public/io/xs_wire.h | 13 +-
xen/include/public/mem_event.h | 70 +-
xen/include/public/memory.h | 113 +-
xen/include/public/platform.h | 46 +-
xen/include/public/sched.h | 7 +-
xen/include/public/sysctl.h | 40 +-
xen/include/public/trace.h | 25 +-
xen/include/xen/bitmap.h | 30 +-
xen/include/xen/compat.h | 7 +-
xen/include/xen/compiler.h | 8 +-
xen/include/xen/config.h | 15 +-
xen/include/xen/device_tree.h | 137 +-
xen/include/xen/domain.h | 18 +-
xen/include/xen/early_printk.h | 21 +
xen/include/xen/efi.h | 1 +
xen/include/xen/event.h | 3 +
xen/include/xen/grant_table.h | 4 +-
xen/include/xen/hvm/iommu.h | 33 +-
xen/include/xen/hvm/irq.h | 10 +-
xen/include/xen/init.h | 8 +
xen/include/xen/iommu.h | 103 +-
xen/include/xen/irq.h | 41 +-
xen/include/xen/kernel.h | 3 +-
xen/include/xen/lib.h | 11 +-
xen/include/xen/libfdt/fdt.h | 93 +-
xen/include/xen/libfdt/libfdt.h | 315 +-
xen/include/xen/libfdt/libfdt_env.h | 4 +
xen/include/xen/list.h | 18 +-
xen/include/xen/lzo.h | 11 +-
xen/include/xen/mem_access.h | 65 +
xen/include/xen/mem_event.h | 143 +
xen/include/xen/mm.h | 27 +
xen/include/xen/p2m-common.h | 47 +
xen/include/xen/pci.h | 4 +-
xen/include/xen/pdx.h | 50 +
xen/include/xen/prefetch.h | 1 -
xen/include/xen/rangeset.h | 20 +
xen/include/xen/sched-if.h | 3 +-
xen/include/xen/sched.h | 82 +-
xen/include/xen/serial.h | 5 -
xen/include/xen/shutdown.h | 9 +-
xen/include/xen/sizes.h | 48 +
xen/include/xen/softirq.h | 3 +
xen/include/xen/stdarg.h | 1 +
xen/include/xen/time.h | 2 +
xen/include/xlat.lst | 16 +
xen/include/xsm/dummy.h | 92 +-
xen/include/xsm/xsm.h | 125 +-
xen/xsm/dummy.c | 23 +-
xen/xsm/flask/avc.c | 16 +-
xen/xsm/flask/flask_op.c | 122 +-
xen/xsm/flask/hooks.c | 358 +-
xen/xsm/flask/include/conditional.h | 4 +-
xen/xsm/flask/include/objsec.h | 6 -
xen/xsm/flask/policy/access_vectors | 30 +-
xen/xsm/flask/policy/security_classes | 1 +
xen/xsm/flask/ss/avtab.c | 5 +-
xen/xsm/flask/ss/conditional.c | 14 +-
xen/xsm/flask/ss/ebitmap.c | 11 +-
xen/xsm/flask/ss/hashtab.c | 14 +-
xen/xsm/flask/ss/policydb.c | 49 +-
xen/xsm/flask/ss/services.c | 57 +-
xen/xsm/xsm_core.c | 66 +-
xen/xsm/xsm_policy.c | 62 +-
1639 files changed, 75487 insertions(+), 141133 deletions(-)
diff --git a/.gitignore b/.gitignore
index db3b083..b24e905 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,6 +16,7 @@
*.spit
*.gcno
*.gcda
+*.py[ocd]
TAGS
GTAGS
GRTAGS
@@ -36,75 +37,21 @@ config.log
config.status
config.cache
config/Toplevel.mk
+config/Paths.mk
build-*
dist/*
-docs/autom4te.cache/
-docs/config.log
-docs/config.status
-docs/*.aux
-docs/*.dvi
-docs/*.log
-docs/*.pdf
-docs/*.ps
-docs/*.toc
-docs/api/*
-docs/figs/xenserver.eps
-docs/html/*
-docs/interface/WARNINGS
-docs/interface/images.pl
-docs/interface/images.tex
-docs/interface/img1.png
-docs/interface/index.html
-docs/interface/interface.css
-docs/interface/interface.html
-docs/interface/labels.pl
+docs/html/
docs/man1/
docs/man5/
-docs/pdf/*
-docs/ps/*
-docs/user/WARNINGS
-docs/user/images.pl
-docs/user/images.tex
-docs/user/img1.png
-docs/user/img2.png
-docs/user/img3.png
-docs/user/index.html
-docs/user/internals.pl
-docs/user/labels.pl
-docs/user/user.css
-docs/user/user.html
-docs/xen-api/vm_lifecycle.eps
-docs/xen-api/xenapi-datamodel-graph.eps
-docs/xen-api/xenapi.out
-docs/xen-api/xenapi.dvi
-docs/xen-api/xenapi.pdf
-docs/xen-api/xenapi.ps
-docs/xen-api/xenapi.toc
+docs/pdf/
+docs/txt/
extras/mini-os/include/mini-os
extras/mini-os/include/x86/mini-os
extras/mini-os/include/xen
extras/mini-os/include/list.h
extras/mini-os/mini-os*
install/*
-linux-[^/]*-paravirt/*
-linux-2.6[^/]*/*
-linux-[^/]*-rc/*
-linux-[^/]*-tip/*
-linux-[^/]*-git/*
-linux-[^/]*.patch
-mkddbxen
-netbsd-[^/]*-tools/*
-netbsd-[^/]*-xen0/*
-netbsd-[^/]*-xenU/*
-netbsd-[^/]*.patch
-patches/*/.makedep
-patches/ebtables-brnf-5_vs_2.4.25.diff
-patches/ebtables.diff
-patches/tmp/*
-pristine-*
-ref-*
-tmp-*
stubdom/autom4te.cache/
stubdom/binutils-*
stubdom/config.log
@@ -159,7 +106,6 @@ tools/blktap/drivers/img2qcow
tools/blktap/drivers/qcow-create
tools/blktap/drivers/qcow2raw
tools/blktap/drivers/tapdisk
-tools/check/.*
tools/console/xenconsole
tools/console/xenconsoled
tools/debugger/gdb/gdb-6.2.1-linux-i386-xen/*
@@ -193,14 +139,17 @@ tools/flask/utils/flask-loadpolicy
tools/flask/utils/flask-setenforce
tools/flask/utils/flask-set-bool
tools/flask/utils/flask-label-pci
-tools/fs-back/fs-backend
tools/hotplug/common/hotplugpath.sh
+tools/hotplug/FreeBSD/rc.d/xencommons
+tools/hotplug/Linux/init.d/xen-watchdog
+tools/hotplug/Linux/init.d/xendomains
+tools/hotplug/Linux/vif-setup
+tools/hotplug/Linux/xen-backend.rules
+tools/hotplug/Linux/xen-hotplug-common.sh
+tools/hotplug/Linux/xendomains
tools/include/xen/*
tools/include/xen-foreign/*.(c|h|size)
tools/include/xen-foreign/checker
-tools/libxen/libxenapi-
-tools/libxen/test/test_bindings
-tools/libxen/test/test_event_handling
tools/libxl/libxlu_cfg_y.output
tools/libxl/xl
tools/libxl/testenum
@@ -224,9 +173,6 @@ tools/misc/lowmemd
tools/misc/xencov
tools/pygrub/build/*
tools/python/build/*
-tools/python/xen/util/path.py
-tools/remus/imqebt/imqebt
-tools/remus/kmod/*(.cmd|.mod|.ko|.mod.c|.symvers|.xen)
tools/security/secpol_tool
tools/security/xen/*
tools/security/xensec_tool
@@ -240,24 +186,14 @@ tools/tests/regression/build/*
tools/tests/regression/downloads/*
tools/tests/mem-sharing/memshrtool
tools/tests/mce-test/tools/xen-mceinj
-tools/vtpm/tpm_emulator-*.tar.gz
-tools/vtpm/tpm_emulator/*
-tools/vtpm/vtpm/*
-tools/vtpm_manager/manager/vtpm_managerd
tools/xcutils/lsevtchn
-tools/xcutils/xc_restore
-tools/xcutils/xc_save
tools/xcutils/readnotes
-tools/xenfb/sdlfb
-tools/xenfb/vncfb
tools/xenmon/xentrace_setmask
tools/xenmon/xenbaked
tools/xenpaging/xenpaging
tools/xenpmd/xenpmd
tools/xenstat/xentop/xentop
-tools/xenstore/testsuite/tmp/*
tools/xenstore/init-xenstore-domain
-tools/xenstore/xen
tools/xenstore/xenstore
tools/xenstore/xenstore-chmod
tools/xenstore/xenstore-exists
@@ -269,29 +205,11 @@ tools/xenstore/xenstore-control
tools/xenstore/xenstore-ls
tools/xenstore/xenstored
tools/xenstore/xenstored_test
-tools/xenstore/xs_crashme
-tools/xenstore/xs_random
-tools/xenstore/xs_stress
tools/xenstore/xs_tdb_dump
-tools/xenstore/xs_test
-tools/xenstore/xs_watch_stress
tools/xentrace/xentrace_setsize
tools/xentrace/tbctl
tools/xentrace/xenctx
tools/xentrace/xentrace
-tools/xm-test/ramdisk/buildroot
-tools/xm-test/aclocal.m4
-tools/xm-test/autom4te
-tools/xm-test/install-sh
-tools/xm-test/mkinstalldirs
-tools/xm-test/missing
-tools/xm-test/config(ure|.log|.status|.guess|.sub)
-tools/xm-test/Makefile(.in)*
-tools/xm-test/*/Makefile(.in)*
-tools/xm-test/lib/XmTestLib/config.py
-tools/xm-test/lib/XmTestReport/xmtest.py
-tools/xm-test/tests/*.test
-tools/ocaml-xenstored*
xen/.banner
xen/System.map
xen/arch/arm/asm-offsets.s
@@ -306,13 +224,14 @@ xen/arch/x86/efi.lds
xen/arch/x86/efi/check.efi
xen/arch/x86/efi/disabled
xen/arch/x86/efi/mkreloc
-xen/ddb/*
+xen/arch/*/efi/boot.c
+xen/arch/*/efi/compat.c
+xen/arch/*/efi/efi.h
+xen/arch/*/efi/runtime.c
xen/include/headers.chk
xen/include/asm
xen/include/asm-*/asm-offsets.h
xen/include/compat/*
-xen/include/hypervisor-ifs/arch
-xen/include/linux
xen/include/public/public
xen/include/xen/*.new
xen/include/xen/acm_policy.h
@@ -324,7 +243,7 @@ xen/xsm/flask/include/class_to_string.h
xen/xsm/flask/include/flask.h
xen/xsm/flask/include/initial_sid_to_string.h
tools/flask/policy/policy.conf
-tools/flask/policy/xenpolicy.24
+tools/flask/policy/xenpolicy-*
xen/xen
xen/xen-syms
xen/xen.*
@@ -343,6 +262,9 @@ tools/qemu-xen-traditional-dir
tools/firmware/seabios-dir-remote
tools/firmware/seabios-dir
+tools/firmware/ovmf-dir-remote
+tools/firmware/ovmf-dir
+
tools/firmware/rombios/_rombios_.c
tools/firmware/rombios/rombios.s
tools/firmware/rombios/rombios.sym
@@ -356,12 +278,14 @@ tools/include/xen-foreign/arm64.h
.git
tools/misc/xen-hptool
tools/misc/xen-mfndump
+tools/libxc/_*.[ch]
tools/libxl/_*.[ch]
tools/libxl/testidl
tools/libxl/testidl.c
tools/libxl/*.pyc
tools/libxl/libxl-save-helper
tools/libxl/test_timedereg
+tools/libxl/xen-init-dom0
tools/blktap2/control/tap-ctl
tools/firmware/etherboot/eb-roms.h
tools/firmware/etherboot/gpxe-git-snapshot.tar.gz
@@ -390,6 +314,8 @@ tools/ocaml/xenstored/oxenstored
tools/ocaml/test/xtl
tools/ocaml/test/send_debug_keys
tools/ocaml/test/list_domains
+tools/ocaml/test/dmesg
+tools/ocaml/test/raise_exception
tools/debugger/kdd/kdd
tools/firmware/etherboot/ipxe.tar.gz
tools/firmware/etherboot/ipxe/
@@ -400,3 +326,8 @@ tools/xenstore/xenstore-watch
docs/txt/misc/*.txt
docs/txt/man/*.txt
docs/figs/*.png
+
+tools/hotplug/Linux/systemd/*.conf
+tools/hotplug/Linux/systemd/*.mount
+tools/hotplug/Linux/systemd/*.socket
+tools/hotplug/Linux/systemd/*.service
diff --git a/.hgignore b/.hgignore
index 9c9421e..da27f80 100644
--- a/.hgignore
+++ b/.hgignore
@@ -186,9 +186,6 @@
^tools/include/xen/.*$
^tools/include/xen-foreign/.*\.(c|h|size)$
^tools/include/xen-foreign/checker$
-^tools/libxen/libxenapi-
-^tools/libxen/test/test_bindings$
-^tools/libxen/test/test_event_handling$
^tools/libxl/_.*\.h$
^tools/libxl/_.*\.c$
^tools/libxl/libxlu_cfg_y\.output$
@@ -278,18 +275,6 @@
^tools/xentrace/tbctl$
^tools/xentrace/xenctx$
^tools/xentrace/xentrace$
-^tools/xm-test/ramdisk/buildroot
-^tools/xm-test/aclocal.m4$
-^tools/xm-test/autom4te
-^tools/xm-test/install-sh$
-^tools/xm-test/mkinstalldirs$
-^tools/xm-test/missing$
-^tools/xm-test/config(ure|.log|.status|.guess|.sub)$
-^tools/xm-test/Makefile(.in)*$
-^tools/xm-test/.*/Makefile(.in)*$
-^tools/xm-test/lib/XmTestLib/config.py$
-^tools/xm-test/lib/XmTestReport/xmtest.py$
-^tools/xm-test/tests/.*\.test$
^tools/firmware/ovmf-remote
^tools/firmware/ovmf$
^tools/qemu-xen-traditional-dir-remote
diff --git a/Config.mk b/Config.mk
index c44853f..a53cfb5 100644
--- a/Config.mk
+++ b/Config.mk
@@ -12,11 +12,12 @@ space := $(empty) $(empty)
# fallback for older make
realpath = $(wildcard $(foreach file,$(1),$(shell cd -P $(dir $(file)) && echo "$$PWD/$(notdir $(file))")))
+or = $(if $(strip $(1)),$(1),$(if $(strip $(2)),$(2),$(if $(strip $(3)),$(3),$(if $(strip $(4)),$(4)))))
-include $(XEN_ROOT)/.config
# A debug build of Xen and tools?
-debug ?= n
+debug ?= y
debug_symbols ?= $(debug)
# Test coverage support
@@ -57,11 +58,6 @@ endif
include $(XEN_ROOT)/config/$(XEN_OS).mk
include $(XEN_ROOT)/config/$(XEN_TARGET_ARCH).mk
-SHAREDIR ?= $(PREFIX)/share
-DOCDIR ?= $(SHAREDIR)/doc/xen
-MANDIR ?= $(SHAREDIR)/man
-BASH_COMPLETION_DIR ?= $(CONFIG_DIR)/bash_completion.d
-
# arguments: variable, common path part, path to test, if yes, if no
define setvar_dir
ifndef $(1)
@@ -73,11 +69,6 @@ define setvar_dir
endif
endef
-# See distro_mapping.txt for other options
-$(eval $(call setvar_dir,CONFIG_LEAF_DIR,,/etc/sysconfig,sysconfig,default))
-$(eval $(call setvar_dir,SUBSYS_DIR,/var/run,/subsys,/subsys,))
-$(eval $(call setvar_dir,INITD_DIR,/etc,/rc.d/init.d,/rc.d/init.d,/init.d))
-
ifneq ($(EXTRA_PREFIX),)
EXTRA_INCLUDES += $(EXTRA_PREFIX)/include
EXTRA_LIB += $(EXTRA_PREFIX)/lib
@@ -101,7 +92,7 @@ PYTHON_PREFIX_ARG ?= --prefix="$(PREFIX)"
#
# Usage: cflags-y += $(call cc-option,$(CC),-march=winchip-c6,-march=i586)
cc-option = $(shell if test -z "`echo 'void*p=1;' | \
- $(1) $(2) -S -o /dev/null -xc - 2>&1 | grep -- $(2) -`"; \
+ $(1) $(2) -S -o /dev/null -x c - 2>&1 | grep -- $(2) -`"; \
then echo "$(2)"; else echo "$(3)"; fi ;)
# cc-option-add: Add an option to compilation flags, but only if supported.
@@ -166,16 +157,25 @@ define move-if-changed
if ! cmp -s $(1) $(2); then mv -f $(1) $(2); else rm -f $(1); fi
endef
+BUILD_MAKE_VARS := SBINDIR BINDIR LIBEXEC LIBEXEC_BIN LIBDIR SHAREDIR \
+ XENFIRMWAREDIR XEN_CONFIG_DIR XEN_SCRIPT_DIR XEN_LOCK_DIR \
+ XEN_RUN_DIR XEN_PAGING_DIR
+
buildmakevars2file = $(eval $(call buildmakevars2file-closure,$(1)))
define buildmakevars2file-closure
- .PHONY: genpath
- genpath:
- rm -f $(1).tmp; \
- $(foreach var, \
- SBINDIR BINDIR LIBEXEC LIBDIR SHAREDIR PRIVATE_BINDIR \
- XENFIRMWAREDIR XEN_CONFIG_DIR XEN_SCRIPT_DIR XEN_LOCK_DIR \
- XEN_RUN_DIR XEN_PAGING_DIR, \
- echo "$(var)=\"$($(var))\"" >>$(1).tmp;) \
+ $(1): .phony
+ rm -f $(1).tmp; \
+ $(foreach var, $(BUILD_MAKE_VARS), \
+ echo "$(var)=\"$($(var))\"" >>$(1).tmp;) \
+ $(call move-if-changed,$(1).tmp,$(1))
+endef
+
+buildmakevars2header = $(eval $(call buildmakevars2header-closure,$(1)))
+define buildmakevars2header-closure
+ $(1): .phony
+ rm -f $(1).tmp; \
+ $(foreach var, $(BUILD_MAKE_VARS), \
+ echo "#define $(var) \"$($(var))\"" >>$(1).tmp;) \
$(call move-if-changed,$(1).tmp,$(1))
endef
@@ -203,6 +203,9 @@ LDFLAGS += $(foreach i, $(EXTRA_LIB), -L$(i))
CFLAGS += $(foreach i, $(EXTRA_INCLUDES), -I$(i))
LDFLAGS += $(foreach i, $(PREPEND_LIB), -L$(i))
CFLAGS += $(foreach i, $(PREPEND_INCLUDES), -I$(i))
+ifeq ($(XEN_TOOLS_RPATH),y)
+LDFLAGS += -Wl,-rpath,$(LIBDIR)
+endif
APPEND_LDFLAGS += $(foreach i, $(APPEND_LIB), -L$(i))
APPEND_CFLAGS += $(foreach i, $(APPEND_INCLUDES), -I$(i))
@@ -218,37 +221,59 @@ XEN_EXTFILES_URL ?= http://xenbits.xen.org/xen-extfiles
# the internet. The original download URL is preserved as a comment
# near the place in the Xen Makefiles where the file is used.
-ifeq ($(GIT_HTTP),y)
-QEMU_REMOTE ?= http://xenbits.xen.org/git-http/qemu-xen-4.4-testing.git
-else
-QEMU_REMOTE ?= git://xenbits.xen.org/qemu-xen-4.4-testing.git
+# Where to look for inlined subtrees (for example, from a tarball)
+QEMU_UPSTREAM_INTREE ?= $(XEN_ROOT)/tools/qemu-xen
+QEMU_TRADITIONAL_INTREE ?= $(XEN_ROOT)/tools/qemu-xen-traditional
+
+
+# Handle legacy options
+ifneq (,$(SEABIOS_UPSTREAM_TAG))
+SEABIOS_UPSTREAM_REVISION ?= $(SEABIOS_UPSTREAM_TAG)
+endif
+ifneq (,$(QEMU_REMOTE))
+QEMU_TRADITIONAL_URL ?= $(QEMU_REMOTE)
+endif
+ifneq (,$(CONFIG_QEMU))
+QEMU_TRADITIONAL_LOC ?= $(CONFIG_QEMU)
+endif
+ifneq (,$(QEMU_TAG))
+QEMU_TRADITIONAL_REVISION ?= $(QEMU_TAG)
endif
ifeq ($(GIT_HTTP),y)
OVMF_UPSTREAM_URL ?= http://xenbits.xen.org/git-http/ovmf.git
-QEMU_UPSTREAM_URL ?= http://xenbits.xen.org/git-http/qemu-upstream-4.4-testing.git
+QEMU_UPSTREAM_URL ?= http://xenbits.xen.org/git-http/qemu-upstream-unstable.git
+QEMU_TRADITIONAL_URL ?= http://xenbits.xen.org/git-http/qemu-xen-unstable.git
SEABIOS_UPSTREAM_URL ?= http://xenbits.xen.org/git-http/seabios.git
else
OVMF_UPSTREAM_URL ?= git://xenbits.xen.org/ovmf.git
-QEMU_UPSTREAM_URL ?= git://xenbits.xen.org/qemu-upstream-4.4-testing.git
+QEMU_UPSTREAM_URL ?= git://xenbits.xen.org/qemu-upstream-unstable.git
+QEMU_TRADITIONAL_URL ?= git://xenbits.xen.org/qemu-xen-unstable.git
SEABIOS_UPSTREAM_URL ?= git://xenbits.xen.org/seabios.git
endif
OVMF_UPSTREAM_REVISION ?= 447d264115c476142f884af0be287622cd244423
-QEMU_UPSTREAM_REVISION ?= qemu-xen-4.4.1
-SEABIOS_UPSTREAM_TAG ?= rel-1.7.3.1
-# Fri Aug 2 14:12:09 2013 -0400
-# Fix bug in CBFS file walking with compressed files.
+QEMU_UPSTREAM_REVISION ?= qemu-xen-4.5.0-rc3
+SEABIOS_UPSTREAM_REVISION ?= rel-1.7.5
+# Thu May 22 16:59:16 2014 -0400
+# python3 fixes for vgabios and csm builds.
ETHERBOOT_NICS ?= rtl8139 8086100e
+
+QEMU_TRADITIONAL_REVISION ?= xen-4.5.0-rc1
+# Mon Oct 6 16:24:46 2014 +0100
+# qemu-xen-trad: Switch to $(LIBEXEC_BIN) from $(LIBEXEC)
+
# Specify which qemu-dm to use. This may be `ioemu' to use the old
# Mercurial in-tree version, or a local directory, or a git URL.
-# CONFIG_QEMU ?= `pwd`/$(XEN_ROOT)/../qemu-xen.git
-CONFIG_QEMU ?= $(QEMU_REMOTE)
+# QEMU_UPSTREAM_LOC ?= `pwd`/$(XEN_ROOT)/../qemu-xen.git
+
+# Defaults for subtree locations
+QEMU_TRADITIONAL_LOC ?= $(call or,$(wildcard $(QEMU_TRADITIONAL_INTREE)),\
+ $(QEMU_TRADITIONAL_URL))
-QEMU_TAG ?= xen-4.4.1
-# Tue Apr 8 16:50:06 2014 +0000
-# qemu-xen-trad: free all the pirqs for msi/msix when driver unloads
+QEMU_UPSTREAM_LOC ?= $(call or,$(wildcard $(QEMU_UPSTREAM_INTREE)),\
+ $(QEMU_UPSTREAM_URL))
# Short answer -- do not enable this unless you know what you are
# doing and are prepared for some pain.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..0bc67ea
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,341 @@
+
+Compiling Xen from source
+
+* Overview
+* Options recognized by configure
+* Variables recognized by make
+* Systemd support
+* History of options
+* Examples
+
+Overview
+========
+
+The xen source contains four subsystems: xen, tools, stubdom and docs.
+All but xen have to be prepared for build with a configure script in the
+toplevel directory. configure recognizes certain arguments and
+environment variables which are used to adjust various aspects of the
+following compile process. Once configure is done, make(1) has to be
+called. Also make(1) recognizes certain arguments. The following sections
+will give an overview.
+
+Options recognized by configure
+===============================
+
+The configure script in the toplevel directory will recognize these
+options. It will pass them to the configure scripts in the tools,
+stubdom, and docs directory.
+
+Individual subsystems can be selected by one of the following options.
+Please note that stubdom requires tools.
+ --disable-xen
+ --disable-tools
+ --enable-stubdom
+ --disable-docs
+
+The well known GNU configure options to specify the target directories.
+Some components of these paths will be compiled into the binaries.
+Note: prefix defaults to /usr/local, sysconfdir defaults to /etc,
+localstatedir defaults to /var.
+ --prefix=DIR
+ --libdir=DIR
+ --libexecdir=BASEDIR
+ --bindir=DIR
+ --sbindir=DIR
+ --sysconfdir=DIR
+ --sharedstatedir=DIR
+ --localstatedir=DIR
+ --includedir=DIR
+ --datarootdir=DIR
+ --datadir=DIR
+ --mandir=DIR
+ --docdir=DIR
+
+To automatically run the toolstack in dom0 during system startup some
+sysv runlevel scripts are installed. This option allows to set the path
+for a given system. Possible values are /etc/init.d, /etc/rc.d/init.d or
+/etc/rc.d. If not specified configure tries to guess the path.
+ --with-initddir=DIR
+
+The runlevel scripts load certain configuration files. They are
+typically located in a subdirectory of /etc. Possible values are this
+subdirectory are "sysconfig" or "default". If not specified configure
+tries to guess the subdir.
+ --with-sysconfig-leaf-dir=SUBDIR
+
+If the tools are configured with a non-standard --prefix the runtime
+linker will either not find the required libraries or it will load them
+from a wrong location. Compiling the tools with rpath will force the
+linker to look in the correct location.
+ --enable-rpath
+
+During build in a git checkout the buildsystem needs to download
+additional tools such as qemu. This is done with either the native git
+protocol, or via http if this option is enabled.
+ --enable-githttp
+
+Disable xenstat and xentop monitoring tools.
+ --disable-monitors
+
+Disable build of certain ocaml libraries and tools. To actually build
+them ocaml development packages must be installed. If they are missing
+configure will automatically disable this option.
+ --disable-ocamltools
+
+Disable XSM policy compilation.
+ --disable-xsmpolicy
+
+Attempt to build of an OVMF firmware binary. This requires special
+versions of development tools. Use at your own risk.
+ --enable-ovmf
+
+Use the given OVMF binary instead of compiling a private copy.
+ --with-system-ovmf=PATH
+
+Build a private copy of SeaBIOS.
+ --disable-seabios
+
+Use the given SeaBIOS binary instead of compiling a private copy.
+ --with-system-seabios=PATH
+
+Build the old qemu used by xm/xend. This is required if existing domUs
+should be migrated to this host, or if existing domU snapshots should be
+started with this version of the tools. Only if all domUs used the new
+upstream qemu during initial start it is safe to disable this option.
+The old qemu requires rombios, which can be disable along with
+qemu-traditional.
+ --enable-qemu-traditional
+ --enable-rombios
+
+The libxl toolstack uses the upstream qemu per default. A private copy
+will be built. If desired this private copy can be configured with
+additional options passed to its configure script.
+ --with-extra-qemuu-configure-args="arg1 arg2"
+
+Use the given qemu binary instead of compiling a private copy.
+ --with-system-qemu=PATH
+
+A dom0 requires a set of backend drivers. The configure script already
+supplies a list of known drivers which are automatically loaded in dom0.
+This internal list can be changed with this option.
+ --with-linux-backend-modules="kmod1 kmod2"
+
+Two variants of a xenstored exist: the original xenstored written in C
+(xenstored) or the newer and robust one written in Ocaml (oxenstored).
+The oxenstored daemon is the default but can only be used if the
+required ocaml packages are installed. In case they are missing the
+original xenstored will be used. Valid names are xenstored and
+oxenstored.
+ --with-xenstored=name
+
+Instead of starting the tools in dom0 with sysv runlevel scripts they
+can also be started by systemd. If this option is enabled xenstored will
+receive the communication socked directly from systemd. So starting it
+manually will not work anymore. The paths to systemd internals can also
+be changed in case the default paths do not fit anymore.
+NOTE: if systemd development packages are installed the systemd support
+will be the enabled per default. Using --disable-systemd will override
+this detection and the sysv runlevel scripts have to be used.
+ --enable-systemd
+ --with-systemd=DIR
+ --with-systemd-modules-load=DIR
+
+The old backend drivers are disabled because qdisk is now the default.
+This option can be used to build them anyway.
+ --enable-blktap1
+ --enable-blktap2
+
+Build various stubom components, some are only example code. Its usually
+enough to specify just --enable-stubdom and leave these options alone.
+ --enable-ioemu-stubdom
+ --enable-c-stubdom
+ --enable-caml-stubdom
+ --disable-pv-grub
+ --disable-xenstore-stubdom
+ --enable-vtpm-stubdom
+ --enable-vtpmmgr-stubdom
+ --disable-extfiles
+
+Per default some parts of the tools code will print additional runtime
+debug. This option can be used to disable such code paths.
+ --disable-debug
+
+The configure script recognizes also many environment variables. Calling
+the individual configure scripts in the subdirectories with the "--help"
+option will list these environment variables.
+
+Variables recognized by make
+==========================
+
+The following variables are recognized by the build system. They have to
+be passed as make options, like 'make variable=value'. Having these
+variables in the environment, like 'env variable=value make', will not
+work for most of them.
+
+In addition to pass variables as make options it is also supported to
+create a ".config" file in the toplevel directory. The file will be
+sourced by make(1).
+
+The well known variable to specify an offset during make install,
+useful for packaging.
+DESTDIR=
+
+Per default some parts of the tools code will print additional runtime
+debug. This option can be used to disable such code paths.
+debug=y
+debug_symbols=y
+
+If --prefix= was used during configure the and ocaml was enabled the
+resulting libraries will not be installed in the specified path. Instead
+the path provided by ocamlfind(1) will be used. This variable can be
+used to override this path. Using the environment variable
+OCAMLFIND_DESTDIR= and OCAMLFIND_METADIR= will have the same effect.
+OCAMLDESTDIR=
+
+The xen subsystem will install the hypervisor into fixed locations.
+BOOT_DIR defaults to /boot, EFI_DIR to /usr/lib64/efi.
+BOOT_DIR=
+EFI_DIR=
+
+The make target 'rpmball' will build a xen.rpm. This variable can be
+used to append a custom string to the name.
+PKG_SUFFIX=
+
+The hypervisor will report a certain version string. This variable can
+be used to append a custom string to the version.
+XEN_VENDORVERSION=
+
+During boot xen will report a certain user at host string, which can be
+changed with these variables.
+XEN_WHOAMI=
+XEN_DOMAIN=
+
+The following variables can be used to tweak some aspects of the
+hypervisor build.
+verbose=y
+perfc=y
+perfc_arrays=y
+lock_profile=y
+crash_debug=y
+frame_pointer=y
+lto=y
+
+During tools build external repos will be cloned into the source tree.
+This variable can be used to point to a different git binary to be used.
+GIT=
+
+During tools build external repos will be cloned into the source tree.
+During stubdom build external packages will be downloaded into the
+source tree. These variables can be used to point to a different
+locations.
+XEN_EXTFILES_URL=
+OVMF_UPSTREAM_URL=
+QEMU_UPSTREAM_URL=
+QEMU_TRADITIONAL_URL=
+SEABIOS_UPSTREAM_URL=
+
+Using additional CFLAGS to build tools which will run in dom0 is
+required when building distro packages. These variables can be used to
+pass RPM_OPT_FLAGS.
+EXTRA_CFLAGS_XEN_TOOLS=
+EXTRA_CFLAGS_QEMU_TRADITIONAL=
+EXTRA_CFLAGS_QEMU_XEN=
+
+This variable can be used to use DIR/include and DIR/lib during build.
+This is the same as PREPEND_LIB and PREPEND_INCLUDES. APPEND_LIB and
+APPEND_INCLUDES= will be appended to the CFLAGS/LDFLAGS variable.
+EXTRA_PREFIX=DIR
+PREPEND_LIB=DIR
+PREPEND_INCLUDES=DIR
+APPEND_LIB=DIR
+APPEND_INCLUDES=DIR
+
+While the tools build will set the path to the python binary with the
+configure script, the hypervisor build has to use this variable to use a
+different python binary.
+PYTHON=
+
+Building the python tools may fail unless certain options are passed to
+setup.py. Config.mk contains additional info how to use this variable.
+PYTHON_PREFIX_ARG=
+
+The hypervisor may be build with XSM support, which can be changed with
+the following variables.
+XSM_ENABLE=y
+FLASK_ENABLE=y
+
+Do a build for coverage.
+coverage=y
+
+Use clang instead of GCC.
+clang=y
+
+
+Systemd support
+===============
+
+If the systemd development packages are available then the support for
+systemd will be enabled per default. It is required to manually enable
+the installed systemd service files. Systemd has dependency tracking,
+which means all dependencies will be started automatically:
+
+systemctl enable xen-qemu-dom0-disk-backend.service
+systemctl enable xen-init-dom0.service
+systemctl enable xenconsoled.service
+
+Other optional services are:
+systemctl enable xen-domains.service
+systemctl enable xen-watchdog.service
+
+
+History of options
+==================
+
+Prior to xen-4.5 configure recognized essentially only the --prefix= and
+--libdir= option to specify target directories. Starting with xen-4.5
+all paths can be adjusted once with configure.
+
+
+Examples
+========
+
+* To build a private copy of tools and xen:
+configure --prefix=/odd/path --sysconfdir=/odd/path/etc --enable-rpath
+make
+sudo make install BOOT_DIR=/ood/path/boot EFI_DIR=/odd/path/efi
+
+
+* Use configure and make to build a distro rpm package (it is required
+ to unset variables set by the rpm configure macro):
+%build
+export WGET=$(type -P false)
+export GIT=$(type -P false)
+export EXTRA_CFLAGS_XEN_TOOLS="$RPM_OPT_FLAGS"
+export EXTRA_CFLAGS_QEMU_TRADITIONAL="$RPM_OPT_FLAGS"
+export EXTRA_CFLAGS_QEMU_XEN="$RPM_OPT_FLAGS"
+%configure \
+ --with-initddir=%{_initddir}
+unset CFLAGS CXXFLAGS FFLAGS LDFLAGS
+make
+%install
+make install \
+ SYSCONFIG_DIR=/var/adm/fillup-templates \
+ DESTDIR=$RPM_BUILD_ROOT
+
+
+* To build xen and tools using a cross compiler:
+./configure --build=x86_64-unknown-linux-gnu --host=aarch64-linux-gnu
+make XEN_TARGET_ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
+make XEN_TARGET_ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \
+ DESTDIR=/some/path install
+
+
+TODO
+====
+
+ - DESTDIR should be empty, not "/"
+ - add make uninstall targets
+ - replace private path variables as needed (SBINDIR/sbindir)
+ - ...
+
+# vim: tw=72 et
diff --git a/MAINTAINERS b/MAINTAINERS
index 902c077..ee2fe90 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -49,14 +49,9 @@ for inclusion in xen-unstable.
Please see http://wiki.xen.org/wiki/Xen_Maintenance_Releases for more
information.
-Remember to copy the stable branch maintainer. The maintainer for this
-branch is:
-
- Jan Beulich <jbeulich at suse.com>
-
-Tools backport requests should also be copied to:
-
- Ian Jackson <Ian.Jackson at eu.citrix.com>
+Remember to copy the appropriate stable branch maintainer who will be
+listed in this section of the MAINTAINERS file in the appropriate
+branch.
Unstable Subsystem Maintainers
==============================
@@ -111,12 +106,14 @@ F: xen/include/acpi/
AMD IOMMU
M: Suravee Suthikulpanit <suravee.suthikulpanit at amd.com>
+M: Aravind Gopalakrishnan <Aravind.Gopalakrishnan at amd.com>
S: Maintained
F: xen/drivers/passthrough/amd/
AMD SVM
M: Boris Ostrovsky <boris.ostrovsky at oracle.com>
M: Suravee Suthikulpanit <suravee.suthikulpanit at amd.com>
+M: Aravind Gopalakrishnan <Aravind.Gopalakrishnan at amd.com>
S: Supported
F: xen/arch/x86/hvm/svm/
@@ -135,9 +132,14 @@ S: Supported
L: xen-devel at lists.xen.org
F: xen/arch/arm/
F: xen/include/asm-arm/
+F: xen/drivers/char/dt-uart.c
+F: xen/drivers/char/exynos4210-uart.c
+F: xen/drivers/char/omap-uart.c
+F: xen/drivers/char/pl011.c
+F: xen/drivers/passthrough/arm/
CPU POOLS
-M: Juergen Gross <juergen.gross at ts.fujitsu.com>
+M: Juergen Gross <jgross at suse.com>
S: Supported
F: xen/common/cpupool.c
@@ -155,6 +157,7 @@ EFI
M: Jan Beulich <jbeulich at suse.com>
S: Supported
F: xen/arch/x86/efi/
+F: xen/common/efi/
F: xen/include/efi/
F: xen/include/asm-x86/efi*.h
F: xen/include/asm-x86/x86_*/efi*.h
@@ -185,24 +188,26 @@ F: xen/arch/x86/tboot.c
F: xen/include/asm-x86/tboot.h
INTEL(R) VT FOR DIRECTED I/O (VT-D)
-M: Xiantao Zhang <xiantao.zhang at intel.com>
+M: Yang Zhang <yang.z.zhang at intel.com>
+M: Kevin Tian <kevin.tian at intel.com>
S: Supported
F: xen/drivers/passthrough/vtd/
INTEL(R) VT FOR X86 (VT-X)
M: Jun Nakajima <jun.nakajima at intel.com>
M: Eddie Dong <eddie.dong at intel.com>
+M: Kevin Tian <kevin.tian at intel.com>
S: Supported
F: xen/arch/x86/hvm/vmx/
F: xen/arch/x86/mm/hap/p2m-ept.c
F: xen/include/asm-x86/hvm/vmx/
IOMMU VENDOR INDEPENDENT CODE
-M: Xiantao Zhang <xiantao.zhang at intel.com>
M: Jan Beulich <jbeulich at suse.com>
S: Supported
F: xen/drivers/passthrough/
X: xen/drivers/passthrough/amd/
+X: xen/drivers/passthrough/arm/
X: xen/drivers/passthrough/vtd/
F: xen/include/xen/iommu.h
@@ -216,7 +221,7 @@ F: xen/arch/x86/x86_64/kexec_reloc.S
MACHINE CHECK (MCA) & RAS
M: Christoph Egger <chegger at amazon.de>
-M: Liu Jinsong <jinsong.liu at intel.com>
+M: Liu Jinsong <jinsong.liu at alibaba-inc.com>
S: Supported
F: xen/arch/x86/cpu/mcheck/
@@ -224,6 +229,7 @@ MINI-OS
M: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
M: Samuel Thibault <samuel.thibault at ens-lyon.org>
S: Supported
+F: config/MiniOS.mk
F: extras/mini-os/
OCAML TOOLS
@@ -233,7 +239,7 @@ F: tools/ocaml/
POWER MANAGEMENT
M: Jan Beulich <jbeulich at suse.com>
-M: Liu Jinsong <jinsong.liu at intel.com>
+M: Liu Jinsong <jinsong.liu at alibaba-inc.com>
S: Supported
F: xen/arch/x86/acpi/
X: xen/arch/x86/acpi/boot.c
@@ -253,12 +259,18 @@ T: git git://xenbits.xen.org/qemu-upstream-*.git
REMUS
M: Shriram Rajagopalan <rshriram at cs.ubc.ca>
+M: Yang Hongyang <yanghy at cn.fujitsu.com>
S: Maintained
-F: tools/remus/
-F: tools/python/xen/remus/
-F: tools/python/xen/lowlevel/checkpoint/
+F: docs/README.remus
+F: tools/libxc/xc_domain_save.c
+F: tools/libxc/xc_domain_restore.c
F: tools/blktap2/drivers/block-remus.c
F: tools/blktap2/drivers/hashtable*
+F: tools/libxl/libxl_remus_*
+F: tools/libxl/libxl_netbuffer.c
+F: tools/libxl/libxl_nonetbuffer.c
+F: tools/hotplug/Linux/remus-netbuf-setup
+F: tools/hotplug/Linux/block-drbd-probe
SCHEDULING
M: George Dunlap <george.dunlap at eu.citrix.com>
@@ -274,13 +286,26 @@ STUB DOMAINS
M: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
M: Samuel Thibault <samuel.thibault at ens-lyon.org>
S: Supported
+F: config/Stubdom.mk.in
+F: m4/stubdom.m4
F: stubdom/
TOOLSTACK
M: Ian Jackson <ian.jackson at eu.citrix.com>
M: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
M: Ian Campbell <ian.campbell at citrix.com>
+M: Wei Liu <wei.liu2 at citrix.com>
S: Supported
+F: autogen.sh
+F: config/*.in
+F: install.sh
+F: m4/
+F: configure
+F: docs/Makefile
+F: stubdom/Makefile
+F: *.ac
+F: */configure
+F: */*.ac
F: tools/
TRANSCENDENT MEMORY (TMEM)
@@ -320,6 +345,7 @@ S: Supported
L: xen-devel at lists.xen.org
F: xen/arch/x86/
F: xen/include/asm-x86/
+F: tools/firmware/hvmloader/
X86 MEMORY MANAGEMENT
M: Tim Deegan <tim at xen.org>
@@ -334,6 +360,12 @@ F: xen/arch/x86/mm/mem_sharing.c
F: xen/arch/x86/mm/mem_paging.c
F: tools/memshr
+MEMORY EVENT AND ACCESS
+M: Tim Deegan <tim at xen.org>
+S: Supported
+F: xen/common/mem_event.c
+F: xen/common/mem_access.c
+
XENTRACE
M: George Dunlap <george.dunlap at eu.citrix.com>
S: Supported
@@ -349,7 +381,11 @@ F: xen/xsm/
F: docs/misc/xsm-flask.txt
THE REST
+M: Ian Campbell <ian.campbell at citrix.com>
+M: Ian Jackson <ian.jackson at eu.citrix.com>
+M: Jan Beulich <jbeulich at suse.com>
M: Keir Fraser <keir at xen.org>
+M: Tim Deegan <tim at xen.org>
L: xen-devel at lists.xen.org
S: Supported
F: *
diff --git a/Makefile b/Makefile
index 4e48457..6e9a4c7 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@
all: dist
-include config/Toplevel.mk
-SUBSYSTEMS?=xen kernels tools stubdom docs
+SUBSYSTEMS?=xen tools stubdom docs
TARGS_DIST=$(patsubst %, dist-%, $(SUBSYSTEMS))
TARGS_INSTALL=$(patsubst %, install-%, $(SUBSYSTEMS))
@@ -15,15 +15,15 @@ export XEN_ROOT=$(CURDIR)
include Config.mk
SUBARCH := $(subst x86_32,i386,$(XEN_TARGET_ARCH))
-export XEN_TARGET_ARCH SUBARCH XEN_SYSTYPE
-include buildconfigs/Rules.mk
+export XEN_TARGET_ARCH SUBARCH
+export DESTDIR
# build and install everything into the standard system directories
.PHONY: install
install: $(TARGS_INSTALL)
.PHONY: build
-build: kernels
+build:
$(MAKE) -C xen build
$(MAKE) -C tools build
$(MAKE) -C stubdom build
@@ -54,53 +54,22 @@ dist-%: install-%
@: # do nothing
# Legacy dist targets
-.PHONY: xen tools stubdom kernels docs
+.PHONY: xen tools stubdom docs
xen: dist-xen
tools: dist-tools
-kernels: dist-kernels
stubdom: dist-stubdom
docs: dist-docs
-.PHONY: prep-kernels
-prep-kernels:
- for i in $(XKERNELS) ; do $(MAKE) $$i-prep || exit 1; done
-
.PHONY: install-xen
install-xen:
$(MAKE) -C xen install
-ifeq ($(CONFIG_QEMU_TRAD),y)
-QEMU_TRAD_DIR_TGT := tools/qemu-xen-traditional-dir
-
-tools/qemu-xen-traditional-dir:
- $(MAKE) -C tools qemu-xen-traditional-dir-find
-
-.PHONY: tools/qemu-xen-traditional-dir-force-update
-tools/qemu-xen-traditional-dir-force-update:
- $(MAKE) -C tools qemu-xen-traditional-dir-force-update
-endif
-
-ifeq ($(CONFIG_QEMU_XEN),y)
-QEMU_XEN_DIR_TGT := tools/qemu-xen-dir
-
-tools/qemu-xen-dir:
- $(MAKE) -C tools qemu-xen-dir-find
-
-.PHONY: tools/qemu-xen-dir-force-update
-tools/qemu-xen-dir-force-update:
- $(MAKE) -C tools qemu-xen-dir-force-update
-endif
-
.PHONY: install-tools
-install-tools: $(QEMU_TRAD_DIR_TARGET) $(QEMU_XEN_DIR_TARGET)
+install-tools:
$(MAKE) -C tools install
-.PHONY: install-kernels
-install-kernels:
- for i in $(XKERNELS) ; do $(MAKE) $$i-install || exit 1; done
-
.PHONY: install-stubdom
-install-stubdom: $(QEMU_TRAD_DIR_TARGET) install-tools
+install-stubdom: install-tools
$(MAKE) -C stubdom install
ifeq (x86_64,$(XEN_TARGET_ARCH))
XEN_TARGET_ARCH=x86_32 $(MAKE) -C stubdom install-grub
@@ -118,31 +87,12 @@ tools/firmware/ovmf-dir-force-update:
install-docs:
$(MAKE) -C docs install
-.PHONY: dev-docs
-dev-docs:
- $(MAKE) -C docs dev-docs
-
-# Build all the various kernels and modules
-.PHONY: kbuild
-kbuild: kernels
-
-# Delete the kernel build trees entirely
-.PHONY: kdelete
-kdelete:
- for i in $(XKERNELS) ; do $(MAKE) $$i-delete ; done
-
-# Clean the kernel build trees
-.PHONY: kclean
-kclean:
- for i in $(XKERNELS) ; do $(MAKE) $$i-clean ; done
-
-# build xen, the tools, and a domain 0 plus unprivileged linux-xen images,
-# and place them in the install directory. 'make install' should then
-# copy them to the normal system directories
+# build xen and the tools and place them in the install
+# directory. 'make install' should then copy them to the normal system
+# directories
.PHONY: world
world:
$(MAKE) clean
- $(MAKE) kdelete
$(MAKE) dist
# Package a build in a debball file, that is inside a .deb format
@@ -150,9 +100,40 @@ world:
# to be a full featured policy compliant .deb package.
.PHONY: debball
debball: dist
- fakeroot sh ./tools/misc/mkdeb $(XEN_ROOT) $$($(MAKE) -C xen xenversion | grep -v :)
+ fakeroot sh ./tools/misc/mkdeb $(XEN_ROOT) $$($(MAKE) -C xen xenversion --no-print-directory)
+
+# Package a build in an rpmball file, that is inside a .rpm format
+# container to allow for easy and clean removal. This is not intended
+# to be a full featured policy compliant .rpm package.
+.PHONY: rpmball
+rpmball: dist
+ bash ./tools/misc/mkrpm $(XEN_ROOT) $$($(MAKE) -C xen xenversion --no-print-directory)
+
+.PHONY: subtree-force-update
+subtree-force-update:
+ $(MAKE) -C tools subtree-force-update
+
+.PHONY: subtree-force-update-all
+subtree-force-update-all:
+ $(MAKE) -C tools subtree-force-update-all
+
+# Make a source tarball, including qemu sub-trees.
+#
+# src-tarball will use "git describe" for the version number. This
+# will have the most recent tag, number of commits since that tag, and
+# git commit id of the head. This is suitable for a "snapshot"
+# tarball of an unreleased tree.
+#
+# src-tarball-release will use "make xenversion" as the version
+# number. This is suitable for release tarballs.
+.PHONY: src-tarball-release
+src-tarball-release: subtree-force-update-all
+ bash ./tools/misc/mktarball $(XEN_ROOT) $$($(MAKE) -C xen xenversion --no-print-directory)
+
+.PHONY: src-tarball
+src-tarball: subtree-force-update-all
+ bash ./tools/misc/mktarball $(XEN_ROOT) $$(git describe)
-# clean doesn't do a kclean
.PHONY: clean
clean::
$(MAKE) -C xen clean
@@ -163,7 +144,7 @@ ifeq (x86_64,$(XEN_TARGET_ARCH))
endif
$(MAKE) -C docs clean
-# clean, but blow away kernel build tree plus tarballs
+# clean, but blow away tarballs
.PHONY: distclean
distclean:
rm -f config/Toplevel.mk
@@ -174,60 +155,48 @@ ifeq (x86_64,$(XEN_TARGET_ARCH))
XEN_TARGET_ARCH=x86_32 $(MAKE) -C stubdom distclean
endif
$(MAKE) -C docs distclean
- rm -rf dist patches/tmp
- for i in $(ALLKERNELS) ; do $(MAKE) $$i-delete ; done
- rm -rf patches/*/.makedep
+ rm -rf dist
rm -rf config.log config.status config.cache autom4te.cache
# Linux name for GNU distclean
.PHONY: mrproper
mrproper: distclean
-# Prepare for source tarball
-.PHONY: src-tarball
-src-tarball: distclean
- $(MAKE) -C xen .banner
- rm -rf xen/tools/figlet .[a-z]*
- $(MAKE) -C xen distclean
-
.PHONY: help
help:
@echo 'Installation targets:'
- @echo ' install - build and install everything'
- @echo ' install-xen - build and install the Xen hypervisor'
- @echo ' install-tools - build and install the control tools'
- @echo ' install-kernels - build and install guest kernels'
- @echo ' install-stubdom - build and install the stubdomain images'
- @echo ' install-docs - build and install user documentation'
+ @echo ' install - build and install everything'
+ @echo ' install-xen - build and install the Xen hypervisor'
+ @echo ' install-tools - build and install the control tools'
+ @echo ' install-stubdom - build and install the stubdomain images'
+ @echo ' install-docs - build and install user documentation'
@echo ''
@echo 'Building targets:'
- @echo ' dist - build and install everything into local dist directory'
- @echo ' world - clean everything, delete guest kernel build'
- @echo ' trees then make dist'
- @echo ' xen - build and install Xen hypervisor'
- @echo ' tools - build and install tools'
- @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'
- @echo ' dev-docs - build developer-only documentation'
+ @echo ' dist - build and install everything into local dist directory'
+ @echo ' world - clean everything then make dist'
+ @echo ' xen - build and install Xen hypervisor'
+ @echo ' tools - build and install tools'
+ @echo ' stubdom - build and install the stubdomain images'
+ @echo ' docs - build and install user documentation'
@echo ''
@echo 'Cleaning targets:'
- @echo ' clean - clean the Xen, tools and docs (but not guest kernel trees)'
- @echo ' distclean - clean plus delete kernel build trees and'
- @echo ' local downloaded files'
- @echo ' kdelete - delete guest kernel build trees'
- @echo ' kclean - clean guest kernel build trees'
+ @echo ' clean - clean the Xen, tools and docs (but not guest kernel trees)'
+ @echo ' distclean - clean plus delete kernel build trees and'
+ @echo ' local downloaded files'
+ @echo ' subtree-force-update - Call *-force-update on all git subtrees (qemu, seabios, ovmf)'
@echo ''
@echo 'Miscellaneous targets:'
- @echo ' prep-kernels - prepares kernel directories, does not build'
- @echo ' uninstall - attempt to remove installed Xen tools'
- @echo ' (use with extreme care!)'
+ @echo ' uninstall - attempt to remove installed Xen tools'
+ @echo ' (use with extreme care!)'
@echo
@echo 'Trusted Boot (tboot) targets:'
- @echo ' build-tboot - download and build the tboot module'
- @echo ' install-tboot - download, build, and install the tboot module'
- @echo ' clean-tboot - clean the tboot module if it exists'
+ @echo ' build-tboot - download and build the tboot module'
+ @echo ' install-tboot - download, build, and install the tboot module'
+ @echo ' clean-tboot - clean the tboot module if it exists'
+ @echo
+ @echo 'Package targets:'
+ @echo ' src-tarball-release - make a source tarball with xen and qemu tagged with a release'
+ @echo ' src-tarball - make a source tarball with xen and qemu tagged with git describe'
@echo
@echo 'Environment:'
@echo ' [ this documentation is sadly not complete ]'
@@ -236,23 +205,10 @@ help:
.PHONY: uninstall
uninstall: D=$(DESTDIR)
uninstall:
- [ -d $(D)$(XEN_CONFIG_DIR) ] && mv -f $(D)$(XEN_CONFIG_DIR) $(D)$(XEN_CONFIG_DIR).old-`date +%s` || true
$(MAKE) -C xen uninstall
- rm -rf $(D)$(CONFIG_DIR)/init.d/xendomains $(D)$(CONFIG_DIR)/init.d/xend
- rm -rf $(D)$(CONFIG_DIR)/init.d/xencommons $(D)$(CONFIG_DIR)/init.d/xen-watchdog
- rm -f $(D)$(CONFIG_DIR)/udev/rules.d/xen-backend.rules
- rm -f $(D)$(CONFIG_DIR)/udev/rules.d/xend.rules
- rm -f $(D)$(SYSCONFIG_DIR)/xendomains
- rm -f $(D)$(SYSCONFIG_DIR)/xencommons
- rm -rf $(D)/var/run/xen* $(D)/var/lib/xen*
make -C tools uninstall
rm -rf $(D)/boot/tboot*
-# Legacy targets for compatibility
-.PHONY: linux26
-linux26:
- $(MAKE) 'KERNELS=linux-2.6*' kernels
-
.PHONY: xenversion
xenversion:
@$(MAKE) --no-print-directory -C xen xenversion
diff --git a/README b/README
index bc2146b..412607a 100644
--- a/README
+++ b/README
@@ -1,9 +1,9 @@
#################################
-__ __ _ _ _ _
-\ \/ /___ _ __ | || | | || |
- \ // _ \ '_ \ | || |_| || |_
- / \ __/ | | | |__ _|__ _|
-/_/\_\___|_| |_| |_|(_) |_|
+__ __ _ _ ____ _ _ _
+\ \/ /___ _ __ | || | | ___| _ _ _ __ ___| |_ __ _| |__ | | ___
+ \ // _ \ '_ \ | || |_ |___ \ _____| | | | '_ \/ __| __/ _` | '_ \| |/ _ \
+ / \ __/ | | | |__ _| ___) |_____| |_| | | | \__ \ || (_| | |_) | | __/
+/_/\_\___|_| |_| |_|(_)____/ \__,_|_| |_|___/\__\__,_|_.__/|_|\___|
#################################
@@ -19,16 +19,14 @@ is freely-distributable Open Source software, released under the GNU
GPL. Since its initial public release, Xen has grown a large
development community, spearheaded by xen.org (http://www.xen.org).
-The 4.4 release offers a number of improvements, including solid
-support for libvirt running on libxl, a new scalable event channel
-interface, improved flexibility for driver domains, an experimental
-"PVH" virtualization mode, improved kexec support, and improved
-support for SPICE clients. Additionally, the ARM platform has had a
-number of improvements. The most important of these is that the
-hypervisor ABIs for both arm32 and arm64 have been declared stable.
-Additionally, many new ARM platforms have been added, and changes have
-been made that will make adding new platforms easier. And as always,
-there are a number of performance, stability, and security
+The 4.3 release offers a number of improvements, including NUMA
+scheduling affinity, openvswitch integration, and defaulting to
+qemu-xen rather than qemu-traditional for non-stubdom guests.
+(qemu-xen is kept very close to the upstream project.) We also have a
+number of updates to vTPM, and improvements to XSM and Flask to allow
+greater disaggregation. Additionally, 4.3 contains a basic version of
+Xen for the new ARM server architecture, both 32- and 64-bit. And as
+always, there are a number of performance, stability, and security
improvements under-the hood.
This file contains some quick-start instructions to install Xen on
@@ -59,7 +57,6 @@ provided by your OS distributor:
* pkg-config
* bridge-utils package (/sbin/brctl)
* iproute package (/sbin/ip)
- * udev
* GNU bison and GNU flex
* GNU gettext
* 16-bit x86 assembler, loader and compiler (dev86 rpm or bin86 & bcc debs)
@@ -74,6 +71,11 @@ disabled at compile time:
* cmake (if building vtpm stub domains)
* markdown
* figlet (for generating the traditional Xen start of day banner)
+ * systemd daemon development files
+ * Development install of libnl3 (e.g., libnl-3-200,
+ libnl-3-dev, etc). Required if network buffering is desired
+ when using Remus with libxl. See docs/README.remus for detailed
+ information.
Second, you need to acquire a suitable kernel for use in domain 0. If
possible you should use a kernel provided by your OS distributor. If
@@ -88,8 +90,8 @@ performed with root privileges.]
1. Download and untar the source tarball file. This will be a
file named xen-unstable-src.tgz, or xen-$version-src.tgz.
- You can also pull the current version from the mercurial
- repository at http://xenbits.xen.org/
+ You can also pull the current version from the git or mercurial
+ repositories at http://xenbits.xen.org/
# tar xzf xen-unstable-src.tgz
@@ -107,8 +109,7 @@ performed with root privileges.]
# make world
# make install
- If you want, you can run ./configure --help to see the list of
- options available options when building and installing Xen.
+ See the documentation in the INSTALL file for more info.
This will create and install onto the local machine. It will build
the xen binary (xen.gz), the tools and the documentation.
@@ -131,35 +132,46 @@ performed with root privileges.]
versions of those scripts, so that you can copy the dist directory
to another machine and install from that distribution.
-Python Runtime Libraries
-========================
+xenstore: xenstored and oxenstored
+====================================
-Xend (the Xen daemon) has the following runtime dependencies:
+Xen uses a configuration database called xenstore [0] to maintain configuration
+and status information shared between domains. A daemon is implemented as part
+of xenstore to act as an interface for access to the database for dom0 and
+guests. Two xenstored daemons are supported, one written in C which we refer
+to as the xenstored (sometimes referred to as cxenstored), and another written
+in Ocaml called oxenstored. Details for xenstore and the different
+implementations can be found on the wiki's xenstore reference guide [1] and
+the xenstored [2] page. You can choose which xenstore you want to enable as
+default on a system through configure:
- * Python 2.3 or later.
- In some distros, the XML-aspects to the standard library
- (xml.dom.minidom etc) are broken out into a separate python-xml package.
- This is also required.
- In more recent versions of Debian and Ubuntu the XML-aspects are included
- in the base python package however (python-xml has been removed
- from Debian in squeeze and from Ubuntu in intrepid).
+ ./configure --with-xenstored=xenstored
+ ./configure --with-xenstored=oxenstored
- URL: http://www.python.org/
- Debian: python
+By default oxenstored will be used if the ocaml development tools are found.
+If you enable oxenstored the xenstored will still be built and installed,
+the xenstored used can be changed through the configuration file:
+
+/etc/sysconfig/xencommons
+or
+/etc/default/xencommons
- * For optional SSL support, pyOpenSSL:
- URL: http://pyopenssl.sourceforge.net/
- Debian: python-pyopenssl
+You can change the preferred xenstored you want to use in the configuration
+but since we cannot stop the daemon a reboot will be required to make the
+change take effect.
- * For optional PAM support, PyPAM:
- URL: http://www.pangalactic.org/PyPAM/
- Debian: python-pam
+[0] http://wiki.xen.org/wiki/XenStore
+[1] http://wiki.xen.org/wiki/XenStoreReference
+[2] http://wiki.xen.org/wiki/Xenstored
- * For optional XenAPI support in XM, lxml:
- URL: http://lxml.de/
- Debian: python-lxml
- YUM: python-lxml
+Python Runtime Libraries
+========================
+
+Various tools, such as pygrub, have the following runtime dependencies:
+ * Python 2.3 or later.
+ URL: http://www.python.org/
+ Debian: python
Intel(R) Trusted Execution Technology Support
=============================================
diff --git a/autogen.sh b/autogen.sh
index b5c9688..2be8360 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,12 +1,12 @@
#!/bin/sh -e
-autoconf
+autoconf -f
( cd tools
- autoconf
+ autoconf -f
autoheader
)
( cd stubdom
- autoconf
+ autoconf -f
)
( cd docs
- autoconf
+ autoconf -f
)
diff --git a/buildconfigs/Rules.mk b/buildconfigs/Rules.mk
deleted file mode 100644
index ee61cf6..0000000
--- a/buildconfigs/Rules.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-
-include Config.mk
-
-export DESTDIR
-
-ALLKERNELS = $(patsubst buildconfigs/mk.%,%,$(wildcard buildconfigs/mk.*))
-
-%-install:
- $(MAKE) -f buildconfigs/mk.$* build
-
-%-dist: DESTDIR=$(DISTDIR)/install
-%-dist: %-install
- @: # do nothing
-
-# Legacy dist target
-%-build: %-dist
- @: # do nothing
-
-%-prep: DESTDIR=$(DISTDIR)/install
-%-prep:
- $(MAKE) -f buildconfigs/mk.$* prep
-
-%-config: DESTDIR=$(DISTDIR)/install
-%-config:
- $(MAKE) -f buildconfigs/mk.$* config
-
-%-delete:
- $(MAKE) -f buildconfigs/mk.$* delete
-
-%-clean:
- $(MAKE) -f buildconfigs/mk.$* clean
-
-%.patch:
- $(MAKE) -f buildconfigs/mk.$* $@
-
-%-mrproper:
- $(MAKE) -f buildconfigs/mk.$*-xen mrproper
- rm -rf pristine-$(*)* ref-$(*)*
- rm -rf $*-xen.patch
-
-# never delete any intermediate files.
-.SECONDARY:
diff --git a/buildconfigs/enable-xen-config b/buildconfigs/enable-xen-config
deleted file mode 100644
index 7ee4d37..0000000
--- a/buildconfigs/enable-xen-config
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/bin/sh
-
-set -e
-
-if [ $# -ne 1 ] ; then
- echo "Usage $(basename $0) <config-file>" 1>&2
- exit 1
-fi
-
-CONFIG=$1
-
-setopt()
-{
- OPTION=$1
- VALUE=$2
-
- # First remove any existing instances of this option
- sed -e "s/^# ${OPTION} is not set$//g ; s/^${OPTION}=.*$//g" -i "${CONFIG}"
-
- # Then append the new value
- case ${VALUE} in
- n) echo "# ${OPTION} is not set" >> "${CONFIG}" ;;
- y|m|*) echo "${OPTION}=${VALUE}" >> "${CONFIG}" ;;
- esac
-}
-
-setopt CONFIG_PARAVIRT y
-setopt CONFIG_PARAVIRT_DEBUG y
-setopt CONFIG_PARAVIRT_GUEST y
-setopt CONFIG_PARAVIRT_SPINLOCKS y
-
-setopt CONFIG_XEN y
-setopt CONFIG_XEN_BLKDEV_FRONTEND y
-setopt CONFIG_XEN_NETDEV_FRONTEND y
-setopt CONFIG_XEN_KBDDEV_FRONTEND y
-setopt CONFIG_XEN_FBDEV_FRONTEND y
-setopt CONFIG_XEN_PCIDEV_FRONTEND y
-setopt CONFIG_XEN_BALLOON y
-setopt CONFIG_XEN_SCRUB_PAGES y
-setopt CONFIG_XEN_DEV_EVTCHN y
-setopt CONFIG_XEN_BACKEND y
-setopt CONFIG_XEN_BLKDEV_BACKEND y
-setopt CONFIG_XEN_BLKDEV_TAP y
-setopt CONFIG_XEN_NETDEV_BACKEND y
-setopt CONFIG_XEN_PCIDEV_BACKEND y
-setopt CONFIG_XEN_PCIDEV_BACKEND_VPCI y
-setopt CONFIG_XEN_PCIDEV_BACKEND_PASS n
-setopt CONFIG_XEN_PCIDEV_BACKEND_SLOT n
-setopt CONFIG_XEN_PCIDEV_BE_DEBUG n
-setopt CONFIG_XENFS y
-setopt CONFIG_XEN_COMPAT_XENFS y
-setopt CONFIG_XEN_PCI_PASSTHROUGH y
-setopt CONFIG_HVC_XEN y
-setopt CONFIG_XEN_MAX_DOMAIN_MEMORY 32
-setopt CONFIG_XEN_DEBUG_FS y
-setopt CONFIG_XEN_DOM0 y
-setopt CONFIG_XEN_SYS_HYPERVISOR y
-setopt CONFIG_XEN_GNTDEV y
-setopt CONFIG_XEN_PLATFORM_PCI y
-
-setopt CONFIG_VMI y
-setopt CONFIG_TUN y
-
-setopt CONFIG_KVM y
-setopt CONFIG_KVM_INTEL y
-setopt CONFIG_KVM_AMD y
-setopt CONFIG_KVM_CLOCK y
-setopt CONFIG_KVM_GUEST n
-setopt CONFIG_KVM_TRACE n
-
-setopt CONFIG_LGUEST n
-
-setopt CONFIG_LOCALVERSION_AUTO n
-
-setopt CONFIG_BRIDGE y
-
-setopt CONFIG_DEBUG_STACK_USAGE n
-
-setopt CONFIG_MEMORY_HOTPLUG y
-setopt CONFIG_MEMORY_HOTREMOVE y
-
-setopt CONFIG_MIGRATION n
-
-setopt CONFIG_ACPI_HOTPLUG_MEMORY n
-
-# Should all be set one way or another in defconfig but aren't
-setopt CONFIG_NUMA n
-setopt CONFIG_X86_VSMP n
-setopt CONFIG_X86_UV n
-setopt CONFIG_CALGARY_IOMMU n
-setopt CONFIG_AMD_IOMMU n
-setopt CONFIG_MAXSMP n
-setopt CONFIG_SPARSEMEM_VMEMMAP n
-setopt CONFIG_I7300_IDLE n
-setopt CONFIG_DMAR n
-setopt CONFIG_INTR_REMAP n
-setopt CONFIG_GFS2_FS n
-setopt CONFIG_IOMMU_DEBUG n
-setopt CONFIG_X86_MCE_INTEL n
-setopt CONFIG_X86_MCE_AMD n
-setopt CONFIG_CRYPTO_AES_NI_INTEL n
-setopt CONFIG_CISS_SCSI_TAPE n
-
-setopt CONFIG_FUSION y
-setopt CONFIG_FUSION_SPI m
-setopt CONFIG_FUSION_SAS m
-setopt CONFIG_FUSION_FC m
-setopt CONFIG_FUSION_MAX_SGE 128
-setopt CONFIG_FUSION_CTL n
-setopt CONFIG_FUSION_LOGGING n
-
-setopt CONFIG_BLK_CPQ_CISS_DA m
-
-case ${XEN_TARGET_ARCH} in
- x86_32) setopt CONFIG_64BIT n ;;
- x86_64)
- setopt CONFIG_64BIT y
- setopt CONFIG_IA32_EMULATION y
- setopt CONFIG_IA32_AOUT n
- setopt CONFIG_CRYPTO_AES_X86_64 n
- setopt CONFIG_CRYPTO_SALSA20_X86_64 n
- setopt CONFIG_CRYPTO_TWOFISH_X86_64 n
- ;;
- *) ;;
-esac
-
-exit 0
diff --git a/buildconfigs/interface.exclude b/buildconfigs/interface.exclude
deleted file mode 100644
index 1df89a5..0000000
--- a/buildconfigs/interface.exclude
+++ /dev/null
@@ -1,7 +0,0 @@
-*.size
-*.pyc
-checker
-checker.c
-ia64.h
-x86_32.h
-x86_64.h
diff --git a/buildconfigs/ketchup b/buildconfigs/ketchup
deleted file mode 100644
index 8725f7d..0000000
--- a/buildconfigs/ketchup
+++ /dev/null
@@ -1,742 +0,0 @@
-#!/usr/bin/python
-#
-# ketchup 0.9.8
-# http://selenic.com/ketchup/wiki
-#
-# Copyright 2004 Matt Mackall <mpm at selenic.com>
-#
-# This software may be used and distributed according to the terms
-# of the GNU General Public License, incorporated herein by reference.
-#
-# Usage:
-#
-# in an existing kernel directory, run:
-#
-# ketchup <version>
-#
-# where version is a complete kernel version, or a branch name to grab
-# the latest version
-#
-# You can override some variables by creating a ~/.ketchuprc file.
-# The ~/.ketchuprc is just a Python script, eg. it might look like this:
-#
-# kernel_url = 'http://kernel.localdomain/pub/linux/kernel'
-# archive = os.environ["HOME"] + '/tmp/ketchup-archive'
-# gpg = '/weird/path/to/gpg'
-#
-
-import re, sys, urllib, os, getopt, glob, shutil
-
-def error(*args):
- sys.stderr.write("ketchup: ")
- for a in args:
- sys.stderr.write(str(a))
- sys.stderr.write("\n")
-
-def qprint(*args):
- if not options["quiet"]:
- sys.stdout.write(" ".join(map(str, args)))
- sys.stdout.write("\n")
-
-def lprint(*args):
- sys.stdout.write(" ".join(map(str, args)))
- sys.stdout.write("\n")
-
-
-def fancyopts(args, options, state, syntax=''):
- long = []
- short = ''
- map = {}
- dt = {}
-
- def help(state, opt, arg, options = options, syntax = syntax):
- lprint("Usage: ", syntax)
-
- for s, l, d, c in options:
- opt = ' '
- if s: opt = opt + '-' + s + ' '
- if l: opt = opt + '--' + l + ' '
- if d: opt = opt + '(' + str(d) + ')'
- lprint(opt)
- if c: lprint(' %s' % c)
- sys.exit(0)
-
- options = [('h', 'help', help, 'Show usage info')] + options
-
- for s, l, d, c in options:
- map['-'+s] = map['--'+l]=l
- state[l] = d
- dt[l] = type(d)
- if not d is None and not type(d) is type(help): s, l = s + ':', l + '='
- if s: short = short + s
- if l: long.append(l)
-
- if os.environ.has_key("KETCHUP_OPTS"):
- args = os.environ["KETCHUP_OPTS"].split() + args
-
- try:
- opts, args = getopt.getopt(args, short, long)
- except getopt.GetoptError:
- help(state, None, args)
- sys.exit(-1)
-
- for opt, arg in opts:
- if dt[map[opt]] is type(help): state[map[opt]](state,map[opt],arg)
- elif dt[map[opt]] is type(1): state[map[opt]] = int(arg)
- elif dt[map[opt]] is type(''): state[map[opt]] = arg
- elif dt[map[opt]] is type([]): state[map[opt]].append(arg)
- elif dt[map[opt]] is type(None): state[map[opt]] = 1
-
- return args
-
-# Default values
-kernel_url = 'http://www.kernel.org/pub/linux/kernel'
-archive = os.environ["HOME"] + "/.ketchup"
-rename_prefix = 'linux-'
-rename_with_localversion = False
-wget = "/usr/bin/wget"
-gpg = "/usr/bin/gpg"
-precommand = postcommand = None
-default_tree = None
-local_trees = {}
-
-# Functions to parse version strings
-
-def tree(ver):
- return float(re.match(r'(\d+\.\d+)', ver).group(1))
-
-def rev(ver):
- p = pre(ver)
- r = int(re.match(r'\d+\.\d+\.(\d+)', ver).group(1))
- if p: r = r - 1
- return r
-
-def pre(ver):
- try: return re.match(r'\d+\.\d+\.\d+(\.\d+)?-((rc|pre)\d+)', ver).group(2)
- except: return None
-
-def post(ver):
- try: return re.match(r'\d+\.\d+\.\d+\.(\d+)', ver).group(1)
- except: return None
-
-def pretype(ver):
- try: return re.match(r'\d+\.\d+\.\d+(\.\d+)?-((rc|pre)\d+)', ver).group(3)
- except: return None
-
-def prenum(ver):
- try: return int(re.match(r'\d+\.\d+\.\d+-((rc|pre)(\d+))', ver).group(3))
- except: return None
-
-def prebase(ver):
- return re.match(r'(\d+\.\d+\.\d+((-(rc|pre)|\.)\d+)?)', ver).group(1)
-
-def revbase(ver):
- return "%s.%s" % (tree(ver), rev(ver))
-
-def base(ver):
- v = revbase(ver)
- if post(ver): v += "." + post(ver)
- return v
-
-def forkname(ver):
- try: return re.match(r'\d+.\d+.\d+(\.\d+)?(-(rc|pre)\d+)?(-(\w+?)\d+)?',
- ver).group(5)
- except: return None
-
-def forknum(ver):
- try: return int(
- re.match(r'\d+.\d+.\d+(\.\d+)?(-(rc|pre)\d+)?(-(\w+?)(\d+))?',
- ver).group(6))
- except: return None
-
-def fork(ver):
- try: return re.match(r'\d+.\d+.\d+(\.\d+)?(-(rc|pre)\d+)?(-(\w+))?', ver).group(4)
- except: return None
-
-def get_ver(makefile):
- """ Read the version information from the specified makefile """
- part = {}
- parts = "VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION".split(' ')
- m = open(makefile)
- for l in m.readlines():
- for p in parts:
- try: part[p] = re.match(r'%s\s*=\s*(\S+)' % p, l).group(1)
- except: pass
-
- version = "%s.%s.%s" % tuple([part[p] for p in parts[:3]])
- version += part.get("EXTRAVERSION","")
- return version
-
-def get_localversion():
- v = ''
-
- for name in glob.glob('localversion*'):
- try: v += open(name).readline().strip()
- except: pass
-
- try:
- c = open('.config').read()
- v += re.search(r'^CONFIG_LOCALVERSION="(.+)"', c, re.M).group(1)
- except: pass
-
- return v
-
-def compare_ver(a, b):
- """
- Compare kernel versions a and b
-
- Note that -pre and -rc versions sort before the version they modify,
- -pre sorts before -rc, -bk, -git, and -mm, etc. sort alphabetically.
- """
- if a == b: return 0
-
- c = cmp(float(tree(a)), float(tree(b)))
- if c: return c
- c = cmp(rev(a), rev(b))
- if c: return c
- c = cmp(int(post(a) or 0), int(post(b) or 0))
- if c: return c
- c = cmp(pretype(a), pretype(b)) # pre sorts before rc
- if c: return c
- c = cmp(prenum(a), prenum(b))
- if c: return c
- c = cmp(forkname(a), forkname(b))
- if c: return c
- return cmp(forknum(a), forknum(b))
-
-def last(url, pat="(.*/)"):
- for l in urllib.urlopen(url).readlines():
- m = re.search('(?i)<a href="%s">' % pat, l)
- if m: n = m.group(1)
- return n
-
-def latest_mm(url, pat):
- url = kernel_url + '/people/akpm/patches/2.6/'
- url += last(url)
- part = last(url)
- return part[:-1]
-
-def latest_ck(url, pat):
- url = "http://ck.kolivas.org/patches/2.6/pre-releases/"
- url += last(url)
- part = last(url)
- pre = part[:-1]
-
- url = "http://ck.kolivas.org/patches/2.6/"
- url += last(url,"(2.6.*/)")
- part = last(url)
- rel = part[:-1]
-
- l = [pre, rel]
- l.sort(compare_ver)
- return l[-1]
-
-def latest_dir(url, pat):
- """Find the latest link matching pat at url after sorting"""
- p = []
- for l in urllib.urlopen(url).readlines():
- m = re.search('"%s"' % pat, l)
- if m: p.append(m.group(1))
-
- if not p: return None
-
- p.sort(compare_ver)
- return p[-1]
-
-# mbligh is lazy and has a bunch of empty directories
-def latest_mjb(url, pat):
- url = kernel_url + '/people/mbligh/'
-
- # find the last Linus release and search backwards
- l = [find_ver('2.6'), find_ver("2.6-pre")]
- l.sort(compare_ver)
- linus = l[-1]
-
- p = []
- for l in urllib.urlopen(url).readlines():
- m = re.search('"(2\.6\..*/)"', l)
- if m:
- v = m.group(1)
- if compare_ver(v, linus) <= 0:
- p.append(v)
-
- p.sort(compare_ver)
- p.reverse()
-
- for ver in p:
- mjb = latest_dir(url + ver, pat)
- if mjb: return mjb
-
- return None
-
-def latest_26_tip(url, pat):
- l = [find_ver('2.6'), find_ver('2.6-git'), find_ver('2.6-pre')]
- l.sort(compare_ver)
- return l[-1]
-
-def find_info(ver):
- b = "%.1f" % tree(ver)
- f = forkname(ver)
- p = pre(ver)
-
- s = b
- if f:
- s = "%s-%s" % (b, f)
- elif p:
- s = "%s-pre" % b
-
- return version_info[s]
-
-def version_urls(ver):
- """ Return the URL for the patch associated with the specified version """
- i = find_info(ver)[1]
- if type(i) != type([]):
- i = [i]
-
- v = {
- 'full': ver,
- 'tree': tree(ver),
- 'base': base(ver),
- 'prebase': prebase(ver)
- }
-
- l = []
- for e in i:
- l.append(e % v)
-
- return l
-
-def patch_path(ver):
- return os.path.join(archive, os.path.basename(version_urls(ver)[0]))
-
-def download(url, f):
- qprint("Downloading %s" % os.path.basename(url))
- if options["dry-run"]:
- return 1
-
- if not options["wget"]:
- p = urllib.urlopen(url).read()
- if p.find("<title>404") != -1:
- return None
- open(f, 'w').write(p)
- else:
- e = os.system("%s -c -O %s %s" %
- (options["wget"], f + ".partial", url))
- if e:
- return None
- os.rename(f + ".partial", f)
-
- return 1
-
-def verify(url, f, sign):
- if options["no-gpg"] or options["dry-run"] or not options["gpg-path"]:
- return 1
-
- sf = f + sign
- if not download(url + sign, sf):
- error("signature download failed")
- error("removing files...")
- os.unlink(f)
- return 0
-
- qprint("Verifying signature...")
- r = os.system("%s --verify %s %s" % (options["gpg-path"], sf, f))
- if r:
- error("gpg returned %d" % r)
- error("removing files...")
- os.unlink(f)
- os.unlink(sf)
- return 0
-
- return 1
-
-def trydownload(urls, f, sign):
- for url in urls:
- if download(url, f):
- if not sign or verify(url, f, sign):
- return f
- if url[-4:] == ".bz2":
- f2 = f[:-4] + ".gz"
- url2 = url[:-4] + ".gz"
- if download(url2, f2):
- if not sign or verify(url2, f2, sign):
- return f2
- return None
-
-def get_patch(ver):
- """Return the path to patch for given ver, downloading if necessary"""
- f = patch_path(ver)
- if os.path.exists(f):
- return f
- if f[-4:] == ".bz2":
- f2 = f[:-4] + ".gz"
- if os.path.exists(f2):
- return f2
-
- urls = version_urls(ver)
- sign = find_info(ver)[3]
- if sign == 1: sign = ".sign"
- f = trydownload(urls, f, sign)
- if not f:
- error("patch download failed")
- sys.exit(-1)
-
- return f
-
-def apply_patch(ver, reverse = 0):
- """Find the patch to upgrade from the predecessor of ver to ver and
- apply or reverse it."""
- p = get_patch(ver)
- r = ""
- if reverse:
- r = " -R"
-
- qprint("Applying %s%s" % (os.path.basename(p), r))
- if options["dry-run"]:
- return ver
-
- def cmd(patch, reverse, dry):
- base = "patch -l -p1%s" % reverse
- if dry:
- base += " --dry-run"
-
- if p[-4:] == ".bz2":
- pipe = "bzcat %s | %s" % (patch, base)
- elif p[-3:] == ".gz":
- pipe = "zcat %s | %s" % (patch, base)
- else:
- pipe = "%s < %s" % (base, patch)
-
- err = os.system(pipe + " > .patchdiag")
- if err:
- sys.stderr.write(open(".patchdiag").read())
- os.unlink(".patchdiag")
- return err
-
- err = cmd(p, r, 1)
- if err:
- error("patch %s failed: %d" % (p, err))
- sys.exit(-1)
-
- err = cmd(p, r, 0)
- if err:
- error("patch %s failed while it was supposed to apply: %d" % (p, err))
- sys.exit(-1)
-
-def untar(tarfile):
- old = os.getcwd()
- os.mkdir("ketchup-tmp")
- os.chdir("ketchup-tmp")
-
- err = os.system("bzcat %s | tar -xf -" % tarfile)
- if err:
- error("Unpacking failed: ", err)
- sys.exit(-1)
-
- err = os.system("mv linux*/* linux*/.[^.]* ..; rmdir linux*")
- if err:
- error("Unpacking failed: ", err)
- sys.exit(-1)
-
- os.chdir(old)
- shutil.rmtree("ketchup-tmp")
-
-def install_nearest(ver):
- t = tree(ver)
- tarballs = glob.glob(archive + "/linux-%s.*.tar.bz2" % t)
- list = []
-
- for f in tarballs:
- m = re.match(r'.*/linux-(.*).tar.bz2$', f)
- v = m.group(1)
- d = abs(rev(v) - rev(ver))
- list.append((d, f, v))
- list.sort()
-
- if not list or (options["full-tarball"] and list[0][0]):
- f = "linux-%s.tar.bz2" % ver
- url = "%s/v%s/%s" % (kernel_url, t, f)
- f = archive + "/" + f
-
- sign = find_info(ver)[3]
- if sign == 1: sign = ".sign"
-
- f = trydownload([url], f, sign)
- if not f:
- error("Tarball download failed")
- sys.exit(-1)
-
- else:
- f = list[0][1]
- ver = list[0][2]
-
- qprint("Unpacking %s" % os.path.basename(f))
- if options["dry-run"]: return ver
- untar(f)
-
- return ver
-
-def find_ver(ver):
- if ver in version_info.keys():
- v = version_info[ver]
- d = v[1]
- if type(d) is type([]):
- d = d[0]
- for n in range(5):
- return v[0](os.path.dirname(d), v[2])
- error('retrying version lookup for %s' % ver)
- else:
- return ver
-
-def transform(a, b):
- if a == b:
- qprint("Nothing to do!")
- return
- if not a:
- a = install_nearest(base(b))
- t = tree(a)
- if t != tree(b):
- error("Can't patch %s to %s" % (tree(a), tree(b)))
- sys.exit(-1)
- if fork(a):
- apply_patch(a, 1)
- a = prebase(a)
- if prebase(a) != prebase(b):
- if pre(a):
- apply_patch(a, 1)
- a = base(a)
-
- if post(a) and post(a) != post(b):
- apply_patch(prebase(a), 1)
-
- ra, rb = rev(a), rev(b)
- if ra > rb:
- for r in range(ra, rb, -1):
- apply_patch("%s.%s" % (t, r), -1)
- if ra < rb:
- for r in range(ra + 1, rb + 1):
- apply_patch("%s.%s" % (t, r))
- a = revbase(b)
-
- if post(b) and post(a) != post(b):
- apply_patch(prebase(b), 0)
- a = base(b)
-
- if pre(b):
- apply_patch(prebase(b))
- a = prebase(b)
-
- if fork(b):
- a = apply_patch(b)
-
-def rename_dir(v):
- """Rename the current directory to linux-v, where v is the function arg"""
- if rename_with_localversion:
- v += get_localversion()
- cwd = os.getcwd()
- basedir = os.path.dirname(cwd)
- newdir = os.path.join(basedir, rename_prefix + v)
- if newdir == cwd:
- return
- if os.access(newdir, os.F_OK):
- error("Cannot rename directory, destination exists: %s", newdir);
- return
- os.rename(cwd, newdir)
- qprint('Current directory renamed to %s' % newdir)
-
-
-# latest lookup function, canonical urls, pattern for lookup function,
-# signature flag, description
-version_info = {
- '2.4': (latest_dir,
- kernel_url + "/v2.4" + "/patch-%(base)s.bz2",
- r'patch-(.*?).bz2',
- 1, "old stable kernel series"),
- '2.4-pre': (latest_dir,
- kernel_url + "/v2.4" + "/testing/patch-%(prebase)s.bz2",
- r'patch-(.*?).bz2',
- 1, "old stable kernel series prereleases"),
- '2.6': (latest_dir,
- kernel_url + "/v2.6" + "/patch-%(prebase)s.bz2",
- r'patch-(.*?).bz2',
- 1, "current stable kernel series"),
- '2.6-rc': (latest_dir,
- kernel_url + "/v2.6" + "/testing/patch-%(prebase)s.bz2",
- r'patch-(.*?).bz2',
- 1, "current stable kernel series prereleases"),
- '2.6-pre': (latest_dir,
- kernel_url + "/v2.6" + "/testing/patch-%(prebase)s.bz2",
- r'patch-(.*?).bz2',
- 1, "current stable kernel series prereleases"),
- '2.6-git': (latest_dir,
- [kernel_url + "/v2.6" + "/snapshots/patch-%(full)s.bz2",
- kernel_url + "/v2.6" + "/snapshots/old/patch-%(full)s.bz2"],
- r'patch-(.*?).bz2',
- 1, "current stable kernel series snapshots"),
- '2.6-bk': (latest_dir,
- [kernel_url + "/v2.6" + "/snapshots/patch-%(full)s.bz2",
- kernel_url + "/v2.6" + "/snapshots/old/patch-%(full)s.bz2"],
- r'patch-(.*?).bz2',
- 1, "old stable kernel series snapshots"),
- '2.6-tip': (latest_26_tip, "", "", 1,
- "current stable kernel series tip"),
- '2.6-mm': (latest_mm,
- kernel_url + "/people/akpm/patches/" +
- "%(tree)s/%(prebase)s/%(full)s/%(full)s.bz2", "",
- 1, "Andrew Morton's -mm development tree"),
- '2.6-tiny': (latest_dir,
- "http://www.selenic.com/tiny/%(full)s.patch.bz2",
- r'(2.6.*?).patch.bz2',
- 1, "Matt Mackall's -tiny tree for small systems"),
- '2.6-mjb': (latest_mjb,
- kernel_url + "/people/mbligh/%(prebase)s/patch-%(full)s.bz2",
- r'patch-(2.6.*?).bz2',
- 1, "Martin Bligh's random collection 'o crap"),
- '2.6-rt': (latest_dir,
- ["http://people.redhat.com/mingo/" +
- "realtime-preempt/patch-%(full)s",
- "http://people.redhat.com/mingo/" +
- "realtime-preempt/older/patch-%(full)s"],
- r'patch-(2.6.*?)',
- 0, "Ingo Molnar's realtime-preempt kernel"),
- '2.6-ck': (latest_ck,
- ["http://ck.kolivas.org/patches/2.6/" +
- "%(prebase)s/%(full)s/patch-%(full)s.bz2",
- "http://ck.kolivas.org/patches/2.6/pre-releases/" +
- "%(prebase)s/%(full)s/patch-%(full)s.bz2"],
- "", ".sig",
- "Con Kolivas' patches for system responsiveness (desktop)"),
- '2.6-cks': (latest_dir,
- "http://ck.kolivas.org/patches/cks/patch-%(full)s.bz2",
- r'patch-(2.6.*?).bz2', ".sig",
- "Con Kolivas' patches for system responsiveness (server)")
- }
-
-# Override defaults with ~/.ketchuprc which is just a Python script
-rcpath = os.path.expanduser('~/.ketchuprc')
-if os.path.isfile(rcpath):
- try:
- execfile(rcpath)
- except Exception, e:
- sys.exit('Failed parsing %s\nError was: %s' % (rcpath, e))
-
-# Add local trees
-for k,v in local_trees.items():
- version_info[k] = v
-
-# Environment variables override defaults and ketchuprc
-kernel_url = os.environ.get("KETCHUP_URL", kernel_url)
-archive = os.environ.get("KETCHUP_ARCH", archive)
-
-# And finally command line overrides everything
-if not os.path.exists(wget): wget = ""
-if not os.path.exists(gpg): gpg = ""
-
-options = {}
-opts = [
- ('a', 'archive', archive, 'cache directory'),
- ('d', 'directory', '.', 'directory to update'),
- ('f', 'full-tarball', None, 'if unpacking a tarball, download the latest'),
- ('g', 'gpg-path', gpg, 'path for GnuPG'),
- ('G', 'no-gpg', None, 'disable GPG signature verification'),
- ('k', 'kernel-url', kernel_url, 'base url for kernel.org mirror'),
- ('l', 'list-trees', None, 'list supported trees'),
- ('m', 'show-makefile', None, 'output version in makefile <arg>'),
- ('n', 'dry-run', None, 'don\'t download or apply patches'),
- ('p', 'show-previous', None, 'output version previous to <arg>'),
- ('q', 'quiet', None, 'reduce output'),
- ('r', 'rename-directory', None, 'rename updated directory to %s<v>'
- % rename_prefix),
- ('s', 'show-latest', None, 'output the latest version of <arg>'),
- ('u', 'show-url', None, 'output URL for <arg>'),
- ('w', 'wget', wget, 'command to use for wget'),
- ]
-
-args = fancyopts(sys.argv[1:], opts, options,
- 'ketchup [options] [ver]')
-
-archive = options["archive"]
-kernel_url = options["kernel-url"]
-if options["no-gpg"]: options["gpg-path"] = ''
-
-# Process args
-
-if not os.path.exists(options["directory"]):
- qprint("Creating target directory", options["directory"])
- os.mkdir(options["directory"])
-os.chdir(options["directory"])
-
-if os.path.isfile(".ketchuprc"):
- try:
- execfile(".ketchuprc")
- except Exception, e:
- sys.exit('Failed parsing .ketchuprc\nError was: %s' % (e))
-
-if options["list-trees"]:
- l = version_info.keys()
- l.sort()
- for tree in l:
- if version_info[tree][3] == 0:
- lprint(tree, "(unsigned)")
- else:
- lprint(tree, "(signed)")
- lprint(" " + version_info[tree][4])
- sys.exit(0)
-
-if options["show-makefile"] and len(args) < 2:
- if not args:
- lprint(get_ver("Makefile"))
- else:
- lprint(get_ver(args[0]))
- sys.exit(0)
-
-if len(args) == 0 and default_tree:
- qprint("Using default tree \"%s\"" % (default_tree))
- args.append(default_tree)
-
-if len(args) != 1:
- error("No version given on command line and no default in configuration")
- sys.exit(-1)
-
-if options["show-latest"]:
- lprint(find_ver(args[0]))
- sys.exit(0)
-
-if options["show-url"]:
- lprint(version_urls(find_ver(args[0]))[0])
- sys.exit(0)
-
-if options["show-previous"]:
- v = find_ver(args[0])
- p = prebase(v)
- if p == v: p = base(v)
- if p == v:
- if rev(v) > 0: p = "%.1f.%s" % (tree(v), rev(v) -1)
- else: p = "unknown"
- lprint(p)
- sys.exit(0)
-
-if not os.path.exists(options["archive"]):
- qprint("Creating cache directory", options["archive"])
- os.mkdir(options["archive"])
-
-if precommand and os.system(precommand):
- sys.exit('Precommand "%s" failed!' % precommand)
-
-try:
- a = get_ver('Makefile')
-except:
- a = None
-
-if not a and os.listdir("."):
- error("Can't find kernel version for non-empty directory")
- sys.exit(-1)
-
-b = find_ver(args[0])
-qprint("%s -> %s" % (a, b))
-transform(a, b)
-if options["rename-directory"] and not options["dry-run"]:
- rename_dir(b)
-
-if postcommand and os.system(postcommand):
- sys.exit('Postcommand "%s" failed!' % postcommand)
diff --git a/buildconfigs/mk.linux-2.6 b/buildconfigs/mk.linux-2.6
deleted file mode 100644
index 6b8d989..0000000
--- a/buildconfigs/mk.linux-2.6
+++ /dev/null
@@ -1,10 +0,0 @@
-XEN_LINUX_SOURCE ?= tarball
-LINUX_VER ?= 2.6
-
-IMAGE_TARGET ?= vmlinux bzImage
-
-XEN_LINUX_CONFIG_UPDATE := buildconfigs/enable-xen-config
-
-EXTRAVERSION ?=
-
-include buildconfigs/mk.linux-2.6-common
diff --git a/buildconfigs/mk.linux-2.6-common b/buildconfigs/mk.linux-2.6-common
deleted file mode 100644
index e8e97fb..0000000
--- a/buildconfigs/mk.linux-2.6-common
+++ /dev/null
@@ -1,154 +0,0 @@
-LINUX_SERIES = 2.6
-
-# Linux search path, will be searched for tarballs and mercurial
-# repositories.
-LINUX_SRC_PATH ?= .:..
-
-# The source directory is not automatically updated to avoid blowing
-# away developer's changes. If you want to automatically pull a new
-# version of the Linux tree then add `XEN_LINUX_UPDATE=y' to your make
-# command line.
-ifeq ($(XEN_LINUX_UPDATE),y)
-__XEN_LINUX_UPDATE = $(LINUX_SRCDIR)/.force-update
-else
-__XEN_LINUX_UPDATE =
-endif
-
-ifeq ($(XEN_LINUX_NONINTERACTIVE_CONFIG),y)
-__NONINT_CONFIG = yes $$'\n' |
-else
-__NONINT_CONFIG =
-endif
-
-LINUX_DIR = build-linux-$(LINUX_VER)$(EXTRAVERSION)_$(XEN_TARGET_ARCH)
-
-IMAGE_TARGET ?= vmlinuz
-
-LINUX_VER3 := $(LINUX_SERIES).$(word 3, $(subst ., ,$(LINUX_VER)))
-
-.PHONY: _build
-_build: build
-
--include buildconfigs/src.$(XEN_LINUX_SOURCE)
-
-LINUX_ARCH = $$(sh buildconfigs/select-linux-arch $(LINUX_SRCDIR))
-IMAGE_PATH = $$(sh buildconfigs/select-linux-image $(LINUX_DIR) $(LINUX_ARCH) $(IMAGE_TARGET))
-
-INSTALL_BOOT_PATH := $(DESTDIR)/boot
-
-# Default to allowing interface mismatch
-ifndef XEN_LINUX_ALLOW_INTERFACE_MISMATCH
-XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
-endif
-
-KERNELRELEASE = $(shell $(MAKE) -s --no-print-directory -C $(LINUX_DIR) kernelrelease)
-
-# The real action starts here!
-.PHONY: build
-build: $(LINUX_DIR)/include/linux/autoconf.h
-ifneq ($(XEN_LINUX_ALLOW_INTERFACE_MISMATCH),y)
- @if ! diff -urN -X buildconfigs/interface.exclude \
- $(LINUX_SRCDIR)/include/xen/interface xen/include/public ; then \
- echo "" 1>&2 ; \
- echo " *** $(LINUX_SRCDIR)/include/xen/interface is out of date " 1>&2 ; \
- echo " *** relative to $(XEN_ROOT)/xen/include/public." 1>&2 ; \
- echo "" 1>&2 ; \
- exit 1 ; \
- fi
-endif
- if grep "^CONFIG_MODULES=" $(LINUX_DIR)/.config ; then \
- $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) modules || exit 1 ; \
- $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_MOD_PATH=$(DESTDIR) modules_install ; \
- fi
- $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR) $(IMAGE_TARGET)
- mkdir -p $(INSTALL_BOOT_PATH)
- @cp -v $(IMAGE_PATH) $(INSTALL_BOOT_PATH)/vmlinuz-$(KERNELRELEASE)
- @cp -v $(LINUX_DIR)/.config $(INSTALL_BOOT_PATH)/config-$(KERNELRELEASE)
- @cp -v $(LINUX_DIR)/System.map $(INSTALL_BOOT_PATH)/System.map-$(KERNELRELEASE)
-
-$(LINUX_DIR)/include/linux/autoconf.h: CONFIG_FILE=$(CURDIR)/$(LINUX_DIR)/.config
-$(LINUX_DIR)/include/linux/autoconf.h: $(LINUX_SRCDIR)/.valid-src
- rm -rf $(LINUX_DIR)
- mkdir -p $(LINUX_DIR)
- # Re-use config from install dir if one exists. Next try to use
- # buildconfigs/create_config.sh is one is provided by the source
- # tree. Finally attempt to use make defconfig.
- set -e ; \
- CONFIG_VERSION=$$(sed -ne 's/$$(XENGUEST)//; s/^EXTRAVERSION = //p' $(LINUX_SRCDIR)/Makefile); \
- if [ ! -z "$(XEN_LINUX_CONFIG)" -a -r "$(XEN_LINUX_CONFIG)" ]; then \
- cp $(XEN_LINUX_CONFIG) $(CONFIG_FILE); \
- elif [ -r $(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION$(EXTRAVERSION) ] ; then \
- cp $(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION$(EXTRAVERSION) $(CONFIG_FILE) ; \
- elif [ -e $(LINUX_SRCDIR)/buildconfigs/create_config.sh ] ; then \
- cd $(LINUX_SRCDIR) && sh buildconfigs/create_config.sh \
- $(CONFIG_FILE) $(EXTRAVERSION) $(XEN_TARGET_ARCH) $(XEN_SYSTYPE) ; \
- echo "Configured $(LINUX_DIR) using create_config.sh" ; \
- elif $(MAKE) -C $(LINUX_SRCDIR) ARCH=$(LINUX_ARCH) defconfig O=$$(/bin/pwd)/$(LINUX_DIR) ; then \
- echo "Configured $(LINUX_DIR) using defconfig" ; \
- else \
- echo "No configuration method found for this kernel" ; \
- fi
-ifneq ($(XEN_LINUX_CONFIG_UPDATE),)
- echo "Updating $(CONFIG_FILE) using $(XEN_LINUX_CONFIG_UPDATE)"
- sh $(XEN_LINUX_CONFIG_UPDATE) $(CONFIG_FILE)
-endif
-ifeq ($(XEN_TARGET_ARCH),x86_32)
- sed -e 's!^CONFIG_HIGHMEM4G=y$$!\# CONFIG_HIGHMEM4G is not set!;s!^\# CONFIG_HIGHMEM64G is not set$$!CONFIG_HIGHMEM64G=y!' $(CONFIG_FILE) > $(CONFIG_FILE)- && mv $(CONFIG_FILE)- $(CONFIG_FILE)
-endif
-ifneq ($(EXTRAVERSION),)
- echo "$(EXTRAVERSION)" >$(LINUX_DIR)/localversion-xen
-endif
- $(__NONINT_CONFIG) $(MAKE) -C $(LINUX_SRCDIR) ARCH=$(LINUX_ARCH) oldconfig O=$$(/bin/pwd)/$(LINUX_DIR)
- @set -e ; if [ ! -f $(LINUX_DIR)/Makefile ] ; then \
- echo "==================================="; \
- echo "oldconfig did not create a Makefile"; \
- echo "Generating $(LINUX_DIR)/Makefile "; \
- echo "==================================="; \
- ( echo "# Automatically generated: don't edit"; \
- echo ""; \
- echo "VERSION = 2"; \
- echo "PATCHLEVEL = 6"; \
- echo ""; \
- echo "KERNELSRC := $(CURDIR)/$(LINUX_SRCDIR)"; \
- echo "KERNELOUTPUT := $(CURDIR)/$(LINUX_DIR)"; \
- echo ""; \
- echo "MAKEFLAGS += --no-print-directory"; \
- echo ""; \
- echo ".PHONY: all \$$(MAKECMDGOALS)"; \
- echo ""; \
- echo "all:"; \
- echo " \$$(MAKE) -C \$$(KERNELSRC) O=\$$(KERNELOUTPUT)"; \
- echo ""; \
- echo "Makefile:;"; \
- echo ""; \
- echo "\$$(filter-out all Makefile,\$$(MAKECMDGOALS)) %/:"; \
- echo " \$$(MAKE) -C \$$(KERNELSRC) O=\$$(KERNELOUTPUT) \$$@"; \
- ) > $(LINUX_DIR)/Makefile ; \
- fi
- $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) prepare
-
-.PHONY: prep
-prep: $(LINUX_DIR)/include/linux/autoconf.h
-
-.PHONY: config
-config: CONFIGMODE = menuconfig
-config: $(LINUX_DIR)/include/linux/autoconf.h
- $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) $(CONFIGMODE)
-
-.PHONY: clean
-clean::
- [ ! -d $(LINUX_DIR) ] || \
- $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) clean
-
-.PHONY: delete
-delete:
- rm -rf tmp-linux-$(LINUX_VER) $(LINUX_DIR) $(LINUX_SRCDIR)
-
-.PHONY: mrproper
-mrproper:
- rm -rf $(LINUX_SRCDIR)
- rm -f linux-$(LINUX_VER).tar.bz2
-
-.PHONY: $(LINUX_SRCDIR)/.force-update
-$(LINUX_SRCDIR)/.force-update:
- @ :
diff --git a/buildconfigs/mk.linux-2.6-git b/buildconfigs/mk.linux-2.6-git
deleted file mode 100644
index 1a142dd..0000000
--- a/buildconfigs/mk.linux-2.6-git
+++ /dev/null
@@ -1,2 +0,0 @@
-LINUX_VER ?= 2.6-git
-include buildconfigs/mk.linux-2.6
diff --git a/buildconfigs/mk.linux-2.6-mm b/buildconfigs/mk.linux-2.6-mm
deleted file mode 100644
index f02e864..0000000
--- a/buildconfigs/mk.linux-2.6-mm
+++ /dev/null
@@ -1,2 +0,0 @@
-LINUX_VER ?= 2.6-mm
-include buildconfigs/mk.linux-2.6
diff --git a/buildconfigs/mk.linux-2.6-native b/buildconfigs/mk.linux-2.6-native
deleted file mode 100644
index c7c0949..0000000
--- a/buildconfigs/mk.linux-2.6-native
+++ /dev/null
@@ -1,5 +0,0 @@
-EXTRAVERSION = -native
-IMAGE_TARGET = bzImage
-INSTALL_BOOT_PATH = $(DESTDIR)/boot
-
-include buildconfigs/mk.linux-2.6-common
diff --git a/buildconfigs/mk.linux-2.6-pvops b/buildconfigs/mk.linux-2.6-pvops
deleted file mode 100644
index 59cae79..0000000
--- a/buildconfigs/mk.linux-2.6-pvops
+++ /dev/null
@@ -1,17 +0,0 @@
-XEN_LINUX_SOURCE ?= git-clone
-LINUX_VER ?= 2.6-pvops
-
-IMAGE_TARGET ?= bzImage
-
-XEN_LINUX_CONFIG_UPDATE := buildconfigs/enable-xen-config
-
-ifeq ($(GIT_HTTP),y)
-XEN_LINUX_GIT_URL ?= http://www.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git
-else
-XEN_LINUX_GIT_URL ?= git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git
-endif
-XEN_LINUX_GIT_REMOTEBRANCH ?= xen/stable-2.6.32.x
-
-EXTRAVERSION ?=
-
-include buildconfigs/mk.linux-2.6-common
diff --git a/buildconfigs/mk.linux-2.6-rc b/buildconfigs/mk.linux-2.6-rc
deleted file mode 100644
index 34f4513..0000000
--- a/buildconfigs/mk.linux-2.6-rc
+++ /dev/null
@@ -1,2 +0,0 @@
-LINUX_VER ?= 2.6-rc
-include buildconfigs/mk.linux-2.6
diff --git a/buildconfigs/mk.linux-2.6-tip b/buildconfigs/mk.linux-2.6-tip
deleted file mode 100644
index 0588ad2..0000000
--- a/buildconfigs/mk.linux-2.6-tip
+++ /dev/null
@@ -1,2 +0,0 @@
-LINUX_VER ?= 2.6-tip
-include buildconfigs/mk.linux-2.6
diff --git a/buildconfigs/mk.linux-2.6-tip-latest b/buildconfigs/mk.linux-2.6-tip-latest
deleted file mode 100644
index 2a0b9af..0000000
--- a/buildconfigs/mk.linux-2.6-tip-latest
+++ /dev/null
@@ -1,17 +0,0 @@
-XEN_LINUX_SOURCE ?= git-clone
-LINUX_VER ?= 2.6-x86-latest
-
-IMAGE_TARGET ?= bzImage vmlinux
-
-XEN_LINUX_CONFIG_UPDATE := buildconfigs/enable-xen-config
-
-ifeq ($(GIT_HTTP),y)
-XEN_LINUX_GIT_URL ?= http://www.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-tip.git
-else
-XEN_LINUX_GIT_URL ?= git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-tip.git
-endif
-XEN_LINUX_GIT_REMOTEBRANCH ?= auto-latest
-
-EXTRAVERSION ?=
-
-include buildconfigs/mk.linux-2.6-common
diff --git a/buildconfigs/mk.linux-2.6-xen b/buildconfigs/mk.linux-2.6-xen
deleted file mode 100644
index 8594b55..0000000
--- a/buildconfigs/mk.linux-2.6-xen
+++ /dev/null
@@ -1,6 +0,0 @@
-EXTRAVERSION ?= -xen
-LINUX_VER ?= 2.6.18
-
-XEN_LINUX_SOURCE ?= hg-clone
-
-include buildconfigs/mk.linux-2.6-common
diff --git a/buildconfigs/mk.linux-2.6-xen0 b/buildconfigs/mk.linux-2.6-xen0
deleted file mode 100644
index 96a5712..0000000
--- a/buildconfigs/mk.linux-2.6-xen0
+++ /dev/null
@@ -1,2 +0,0 @@
-EXTRAVERSION = -xen0
-include buildconfigs/mk.linux-2.6-xen
diff --git a/buildconfigs/mk.linux-2.6-xenU b/buildconfigs/mk.linux-2.6-xenU
deleted file mode 100644
index 02f3e07..0000000
--- a/buildconfigs/mk.linux-2.6-xenU
+++ /dev/null
@@ -1,2 +0,0 @@
-EXTRAVERSION = -xenU
-include buildconfigs/mk.linux-2.6-xen
diff --git a/buildconfigs/select-linux-arch b/buildconfigs/select-linux-arch
deleted file mode 100755
index a5d0856..0000000
--- a/buildconfigs/select-linux-arch
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh
-
-ME=$(basename $0)
-
-if [ $# -lt 1 ] || [ $# -gt 2 ] ; then
- echo "usage: $ME <linux-build-directory>" 1>&2
- exit 1;
-fi
-
-LINUX_DIR=$1
-
-case ${XEN_TARGET_ARCH} in
- x86_32|x86_64)
- if [ -d ${LINUX_DIR}/arch/x86 ] ; then
- ARCH=x86
- elif [ "${XEN_TARGET_ARCH}" = "x86_32" ] ; then
- ARCH=i386
- else
- ARCH=x86_64
- fi
- ;;
- *)
- ARCH=${XEN_TARGET_ARCH}
- ;;
-esac
-
-echo "$ME: ${ARCH}" 1>&2
-echo ${ARCH}
-
-exit 0
diff --git a/buildconfigs/select-linux-image b/buildconfigs/select-linux-image
deleted file mode 100755
index 07899f8..0000000
--- a/buildconfigs/select-linux-image
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-
-ME=$(basename $0)
-
-if [ $# -lt 3 ] ; then
- echo "usage: $ME <linux-build-directory> <linux-arch> <linux-targets...>" 1>&2
- exit 1;
-fi
-
-LINUX_DIR=$1
-LINUX_ARCH=$2
-LINUX_TARGET=$3 # We don't care about second and subsequent targets
-
-case ${XEN_TARGET_ARCH} in
- ia64)
- IMAGE=${LINUX_DIR}/arch/ia64/hp/sim/boot/vmlinux.gz
- ;;
- *)
- if [ -f ${LINUX_DIR}/arch/${LINUX_ARCH}/boot/${LINUX_TARGET} ] ; then
- IMAGE=${LINUX_DIR}/arch/${LINUX_ARCH}/boot/${LINUX_TARGET}
- elif [ -f ${LINUX_DIR}/${LINUX_TARGET} ] ; then
- IMAGE=${LINUX_DIR}/${LINUX_TARGET}
- else
- echo "$ME: cannot determine Linux image to use for ${LINUX_ARCH} in ${LINUX_DIR}" 1>&2
- exit 1
- fi
- ;;
-esac
-
-echo "$ME: ${IMAGE}" 1>&2
-echo ${IMAGE}
-
-exit 0
diff --git a/buildconfigs/select-repository b/buildconfigs/select-repository
deleted file mode 100755
index 48ae00f..0000000
--- a/buildconfigs/select-repository
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/bin/sh
-
-ME=$(basename $0)
-
-if [ $# -lt 1 ] || [ $# -gt 2 ] ; then
- echo "usage: $ME <repository-name> [search-path]" 1>&2
- exit 1;
-fi
-
-REPO=$1
-LINUX_SRC_PATH=$2
-
-if [ X"${LINUX_SRC_PATH}" != X ] ; then
- echo "$ME: Searching \`${LINUX_SRC_PATH}' for $REPO" 1>&2
- IFS_saved="$IFS"
- IFS=:
- for i in $LINUX_SRC_PATH ; do
- # Ignore current directory since we will almost certainly find
- # the target directory there which breaks updating (there's no
- # point updating from yourself!).
- if [ X"." = X"${i}" ] ; then
- echo "$ME: Ignoring \`.'" 1>&2
- continue
- fi
-
- if [ -d "$i/$REPO/.hg" ] ; then
- echo "$ME: Found $i/$REPO" 1>&2
- echo "$i/$REPO"
- exit 0
- fi
- done
- IFS="$IFS_saved"
-fi
-
-if [ -d ${XEN_ROOT}/.hgxxx ] ; then
- XEN=$(hg -R ${XEN_ROOT} path default)
- if [ $? -ne 0 ] || [ X"$XEN" = "X" ] ; then
- echo "$ME: Unable to determine Xen repository parent." 1>&2
- exit 1;
- fi
-
- BASE=$(dirname ${XEN})
- if [ $? -ne 0 ] || [ X"$BASE" = "X" ] ; then
- echo "$ME: Unable to determine Xen repository base." 1>&2
- exit 1;
- fi
- if [ -d "$XEN" ] && [ ! -d "$BASE/$REPO" ] ; then
- echo "$ME: No such dir: $BASE/$REPO" 1>&2
- exit 1
- fi
-
- echo "$ME: Found ${BASE}/${REPO}" 1>&2
-
- # If ${BASE}/${REPO} is a local directory then prepend file:// so that
- # the test in src.hg-clone will fail and we will clone instead of
- # linking this repository. We only want to link repositories which
- # were found via LINUX_SRC_PATH.
- if [ -d "${BASE}/${REPO}" ] ; then
- echo "file://${BASE}/${REPO}"
- else
- echo ${BASE}/${REPO}
- fi
-else
- echo "Unable to determine path to Linux source tree." 1>&2
- echo "Falling back to linux-2.6.18-xen Mercurial repository." 1>&2
- echo http://xenbits.xen.org/linux-2.6.18-xen.hg
-fi
-
-exit 0
diff --git a/buildconfigs/src.git-clone b/buildconfigs/src.git-clone
deleted file mode 100644
index 35865e1..0000000
--- a/buildconfigs/src.git-clone
+++ /dev/null
@@ -1,32 +0,0 @@
-# Mercurial
-GIT ?= git
-
-LINUX_SRCDIR ?= linux-$(LINUX_VER).git
-
-# The URL of the remote GIT repository
-ifeq ($(XEN_LINUX_GIT_URL),)
-.ERROR: XEN_LINUX_GIT_URL not specified
-endif
-
-# The branch in the remote repository
-ifeq ($(XEN_LINUX_GIT_REMOTEBRANCH),)
-.ERROR: XEN_LINUX_GIT_REMOTEBRANCH not specified
-endif
-
-XEN_GIT_ORIGIN ?= xen
-
-XEN_LINUX_GIT_LOCALBRANCH ?= $(XEN_LINUX_GIT_REMOTEBRANCH)
-
-# Set XEN_LINUX_GITREV to update to a particlar revision.
-XEN_LINUX_GITREV ?= $(XEN_GIT_ORIGIN)/$(XEN_LINUX_GIT_REMOTEBRANCH)
-
-$(LINUX_SRCDIR)/.valid-src: $(__XEN_LINUX_UPDATE)
- set -ex; \
- if ! [ -d $(LINUX_SRCDIR) ]; then \
- rm -rf $(LINUX_SRCDIR) $(LINUX_SRCDIR).tmp; \
- mkdir $(LINUX_SRCDIR).tmp; rmdir $(LINUX_SRCDIR).tmp; \
- $(GIT) clone -o $(XEN_GIT_ORIGIN) -n $(XEN_LINUX_GIT_URL) $(LINUX_SRCDIR).tmp; \
- (cd $(LINUX_SRCDIR).tmp; git checkout -b $(XEN_LINUX_GIT_LOCALBRANCH) $(XEN_LINUX_GITREV) ); \
- mv $(LINUX_SRCDIR).tmp $(LINUX_SRCDIR); \
- fi
- touch $@
diff --git a/buildconfigs/src.hg-clone b/buildconfigs/src.hg-clone
deleted file mode 100644
index 0586bc8..0000000
--- a/buildconfigs/src.hg-clone
+++ /dev/null
@@ -1,32 +0,0 @@
-# Mercurial
-HG ?= hg
-
-LINUX_SRCDIR ?= linux-$(LINUX_VER)-xen.hg
-
-# Repository to clone.
-XEN_LINUX_HGREPO ?= $$(sh buildconfigs/select-repository $(LINUX_SRCDIR) $(LINUX_SRC_PATH))
-
-# Set XEN_LINUX_HGREV to update to a particlar revision.
-XEN_LINUX_HGREV ?= tip
-
-$(LINUX_SRCDIR)/.valid-src: $(__XEN_LINUX_UPDATE)
- set -e ; \
- if [ ! -e $(LINUX_SRCDIR)/.hg ] ; then \
- __repo=$(XEN_LINUX_HGREPO) ; \
- if [ -d $${__repo} ] ; then \
- echo "Linking $${__repo} to $(LINUX_SRCDIR)." ; \
- ln -s $${__repo} $(LINUX_SRCDIR) ; \
- else \
- echo "Cloning $${__repo} to $(LINUX_SRCDIR)." ; \
- $(HG) clone $${__repo#file://} $(LINUX_SRCDIR) ; \
- fi ; \
- else \
- __parent=$$($(HG) -R $(LINUX_SRCDIR) path default) ; \
- echo "Pulling changes from $${__parent} into $(LINUX_SRCDIR)." ; \
- $(HG) -R $(LINUX_SRCDIR) pull $${__parent} ; \
- fi
- set -e ; if [ -n "$(XEN_LINUX_HGREV)" ] ; then \
- echo "Updating $(LINUX_SRCDIR) to revision $(XEN_LINUX_HGREV)." ; \
- ( cd $(LINUX_SRCDIR) && $(HG) update $(XEN_LINUX_HGREV) ); \
- fi
- touch $@
diff --git a/buildconfigs/src.tarball b/buildconfigs/src.tarball
deleted file mode 100644
index 2101e1a..0000000
--- a/buildconfigs/src.tarball
+++ /dev/null
@@ -1,19 +0,0 @@
-XEN_LINUX_MIRROR ?= http://www.kernel.org/pub/linux/kernel/v2.6/
-XEN_LINUX_TARBALL ?= linux-$(LINUX_VER)-xen.tar.bz2
-
-LINUX_SRCDIR ?= linux-$(LINUX_VER)
-
-KETCHUP ?= python buildconfigs/ketchup
-
-vpath linux-%.tar.bz2 $(LINUX_SRC_PATH)
-
-# download a pristine Linux kernel tarball if there isn't one in LINUX_SRC_PATH
-linux-%.tar.bz2:
- @echo "Cannot find $@ in path $(LINUX_SRC_PATH)"
- false wget $(XEN_LINUX_MIRROR)/$@ -O./$@
-
-# XXX create a pristine tree for diff -Nurp convenience
-
-%/.valid-src: $(__XEN_LINUX_UPDATE)
- $(KETCHUP) -d $(@D) $(LINUX_VER)
- touch $@ # update timestamp to avoid rebuild
diff --git a/config/Docs.mk.in b/config/Docs.mk.in
index a2a72fd..33bd529 100644
--- a/config/Docs.mk.in
+++ b/config/Docs.mk.in
@@ -1,9 +1,4 @@
-# Prefix and install folder
-prefix := @prefix@
-PREFIX := $(prefix)
-exec_prefix := @exec_prefix@
-libdir := @libdir@
-LIBDIR := $(libdir)
+-include $(XEN_ROOT)/config/Paths.mk
# Tools
FIG2DEV := @FIG2DEV@
@@ -11,4 +6,5 @@ POD2MAN := @POD2MAN@
POD2HTML := @POD2HTML@
POD2TEXT := @POD2TEXT@
MARKDOWN := @MARKDOWN@
+PANDOC := @PANDOC@
PERL := @PERL@
diff --git a/config/FreeBSD.mk b/config/FreeBSD.mk
index b421a1c..5a13d60 100644
--- a/config/FreeBSD.mk
+++ b/config/FreeBSD.mk
@@ -1 +1,6 @@
include $(XEN_ROOT)/config/StdGNU.mk
+
+DLOPEN_LIBS =
+
+# No wget on FreeBSD base system
+WGET = ftp
diff --git a/config/Linux.mk b/config/Linux.mk
index 10d84af..2a84b6b 100644
--- a/config/Linux.mk
+++ b/config/Linux.mk
@@ -1,8 +1,3 @@
include $(XEN_ROOT)/config/StdGNU.mk
-# You may use wildcards, e.g. KERNELS=*2.6*
-KERNELS ?=
-
-XKERNELS := $(foreach kernel, $(KERNELS), \
- $(patsubst buildconfigs/mk.%,%, \
- $(wildcard buildconfigs/mk.$(kernel))) )
+SYSCONFIG_DIR = $(CONFIG_DIR)/$(CONFIG_LEAF_DIR)
diff --git a/config/MiniOS.mk b/config/MiniOS.mk
index fc02b70..32260ad 100644
--- a/config/MiniOS.mk
+++ b/config/MiniOS.mk
@@ -7,3 +7,4 @@ LDFLAGS += $(DEF_LDFLAGS) $(ARCH_LDFLAGS)
# Override settings for this OS
PTHREAD_LIBS =
+nosharedlibs=y
diff --git a/config/NetBSD.mk b/config/NetBSD.mk
index 141de7c..21318d6 100644
--- a/config/NetBSD.mk
+++ b/config/NetBSD.mk
@@ -1,11 +1,6 @@
include $(XEN_ROOT)/config/StdGNU.mk
# Override settings for this OS
-LIBEXEC = $(PREFIX)/libexec
-PRIVATE_BINDIR = $(BINDIR)
-
DLOPEN_LIBS =
-XEN_LOCK_DIR = /var/lib
-
WGET = ftp
diff --git a/config/NetBSDRump.mk b/config/NetBSDRump.mk
new file mode 100644
index 0000000..2a87218
--- /dev/null
+++ b/config/NetBSDRump.mk
@@ -0,0 +1,9 @@
+include $(XEN_ROOT)/config/StdGNU.mk
+
+DLOPEN_LIBS =
+PTHREAD_LIBS =
+
+WGET = ftp
+
+XENSTORE_XENSTORED=n
+nosharedlibs=y
diff --git a/config/Paths.mk.in b/config/Paths.mk.in
new file mode 100644
index 0000000..fe10f76
--- /dev/null
+++ b/config/Paths.mk.in
@@ -0,0 +1,63 @@
+# Xen system configuration
+# ========================
+#
+# Xen uses a set of variables for system configuration and at build time,
+# because of this these variables are defined on one master input source file
+# and is generated after running ./configure. The master source is located
+# on the xen source tree at under config/Paths.mk.in and it is used to
+# generate shell or header files by the build system upon demand through the
+# use of the helper makefile helper buildmakevars2file().
+#
+# For more documentation you can refer to the wiki:
+#
+# http://wiki.xen.org/wiki/Category:Host_Configuration#System_wide_xen_configuration
+
+PACKAGE_TARNAME := @PACKAGE_TARNAME@
+prefix := @prefix@
+bindir := @bindir@
+sbindir := @sbindir@
+libdir := @libdir@
+libexecdir := @libexecdir@
+datarootdir := @datarootdir@
+mandir := @mandir@
+docdir := @docdir@
+dvidir := @dvidir@
+htmldir := @htmldir@
+pdfdir := @pdfdir@
+psdir := @psdir@
+includedir := @includedir@
+localstatedir := @localstatedir@
+sysconfdir := @sysconfdir@
+
+PREFIX := $(prefix)
+
+SBINDIR := $(sbindir)
+BINDIR := $(bindir)
+LIBEXEC := $(libexecdir)/$(PACKAGE_TARNAME)
+LIBEXEC_BIN := @LIBEXEC_BIN@
+LIBEXEC_LIB := $(LIBEXEC)/lib
+LIBEXEC_INC := $(LIBEXEC)/include
+
+INCLUDEDIR := $(includedir)
+SHAREDIR := @SHAREDIR@
+MANDIR := $(mandir)
+MAN1DIR := $(MANDIR)/man1
+MAN8DIR := $(MANDIR)/man8
+LIBDIR := $(libdir)
+DOCDIR := $(docdir)
+
+XEN_RUN_DIR := @XEN_RUN_DIR@
+XEN_LOG_DIR := @XEN_LOG_DIR@
+XEN_LIB_STORED := @XEN_LIB_STORED@
+
+CONFIG_DIR := @CONFIG_DIR@
+INITD_DIR := @INITD_DIR@
+CONFIG_LEAF_DIR := @CONFIG_LEAF_DIR@
+BASH_COMPLETION_DIR := $(CONFIG_DIR)/bash_completion.d
+XEN_LOCK_DIR := @XEN_LOCK_DIR@
+XEN_PAGING_DIR := @XEN_PAGING_DIR@
+
+XENFIRMWAREDIR := $(LIBEXEC)/boot
+
+XEN_CONFIG_DIR := @XEN_CONFIG_DIR@
+XEN_SCRIPT_DIR := @XEN_SCRIPT_DIR@
diff --git a/config/StdGNU.mk b/config/StdGNU.mk
index 25fc594..4efebe3 100644
--- a/config/StdGNU.mk
+++ b/config/StdGNU.mk
@@ -16,9 +16,6 @@ OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
SIZEUTIL = $(CROSS_COMPILE)size
-MSGFMT = msgfmt
-MSGMERGE = msgmerge
-
# Allow git to be wrappered in the environment
GIT ?= git
@@ -27,29 +24,7 @@ INSTALL_DIR = $(INSTALL) -d -m0755 -p
INSTALL_DATA = $(INSTALL) -m0644 -p
INSTALL_PROG = $(INSTALL) -m0755 -p
-PREFIX ?= /usr
-BINDIR = $(PREFIX)/bin
-INCLUDEDIR = $(PREFIX)/include
-LIBEXEC = $(PREFIX)/lib/xen/bin
-SHAREDIR = $(PREFIX)/share
-MANDIR = $(SHAREDIR)/man
-MAN1DIR = $(MANDIR)/man1
-MAN8DIR = $(MANDIR)/man8
-SBINDIR = $(PREFIX)/sbin
-XENFIRMWAREDIR = $(PREFIX)/lib/xen/boot
-
-PRIVATE_PREFIX = $(LIBDIR)/xen
-PRIVATE_BINDIR = $(PRIVATE_PREFIX)/bin
-
-CONFIG_DIR = /etc
-XEN_LOCK_DIR = /var/lock
-XEN_RUN_DIR = /var/run/xen
-XEN_PAGING_DIR = /var/lib/xen/xenpaging
-
-SYSCONFIG_DIR = $(CONFIG_DIR)/$(CONFIG_LEAF_DIR)
-
-XEN_CONFIG_DIR = $(CONFIG_DIR)/xen
-XEN_SCRIPT_DIR = $(XEN_CONFIG_DIR)/scripts
+BOOT_DIR ?= /boot
SOCKET_LIBS =
UTIL_LIBS = -lutil
diff --git a/config/Stubdom.mk.in b/config/Stubdom.mk.in
index 302842e..5990fc4 100644
--- a/config/Stubdom.mk.in
+++ b/config/Stubdom.mk.in
@@ -1,9 +1,4 @@
-# Prefix and install folder
-prefix := @prefix@
-PREFIX := $(prefix)
-exec_prefix := @exec_prefix@
-libdir := @libdir@
-LIBDIR := $(libdir)
+-include $(XEN_ROOT)/config/Paths.mk
# Path Programs
CMAKE := @CMAKE@
@@ -11,7 +6,6 @@ FETCHER := @FETCHER@
# A debug build of stubdom? //FIXME: Someone make this do something
debug := @debug@
-vtpm = @vtpm@
STUBDOM_TARGETS := @STUBDOM_TARGETS@
STUBDOM_BUILD := @STUBDOM_BUILD@
diff --git a/config/SunOS.mk b/config/SunOS.mk
index 2c528b7..3316280 100644
--- a/config/SunOS.mk
+++ b/config/SunOS.mk
@@ -10,8 +10,6 @@ OBJCOPY = $(CROSS_COMPILE)gobjcopy
OBJDUMP = $(CROSS_COMPILE)gobjdump
SIZEUTIL = $(CROSS_COMPILE)gsize
-MSGFMT = gmsgfmt
-
SHELL = bash
INSTALL = ginstall
@@ -19,25 +17,7 @@ INSTALL_DIR = $(INSTALL) -d -m0755 -p
INSTALL_DATA = $(INSTALL) -m0644 -p
INSTALL_PROG = $(INSTALL) -m0755 -p
-PREFIX ?= /usr
-BINDIR = $(PREFIX)/bin
-INCLUDEDIR = $(PREFIX)/include
-MANDIR = $(PREFIX)/share/man
-MAN1DIR = $(MANDIR)/man1
-MAN8DIR = $(MANDIR)/man8
-SBINDIR = $(PREFIX)/sbin
-XENFIRMWAREDIR = $(LIBDIR)/xen/boot
-
-PRIVATE_PREFIX = $(LIBDIR)/xen
-PRIVATE_BINDIR = $(PRIVATE_PREFIX)/bin
-
-ifeq ($(PREFIX),/usr)
-CONFIG_DIR = /etc
-else
-CONFIG_DIR = $(PREFIX)/etc
-endif
-XEN_CONFIG_DIR = $(CONFIG_DIR)/xen
-XEN_SCRIPT_DIR = $(PRIVATE_PREFIX)/scripts
+BOOT_DIR ?= /boot
SunOS_LIBDIR = /usr/sfw/lib
SunOS_LIBDIR_x86_64 = /usr/sfw/lib/amd64
diff --git a/config/Tools.mk.in b/config/Tools.mk.in
index d9d3239..89de5bd 100644
--- a/config/Tools.mk.in
+++ b/config/Tools.mk.in
@@ -1,9 +1,9 @@
-# Prefix and install folder
-prefix := @prefix@
-PREFIX := $(prefix)
-exec_prefix := @exec_prefix@
-libdir := @libdir@
-LIBDIR := $(libdir)
+-include $(XEN_ROOT)/config/Paths.mk
+
+CONFIG_RUMP := @CONFIG_RUMP@
+ifeq ($(CONFIG_RUMP),y)
+XEN_OS := NetBSDRump
+endif
# A debug build of tools?
debug := @debug@
@@ -38,6 +38,10 @@ PTHREAD_LIBS := @PTHREAD_LIBS@
PTYFUNCS_LIBS := @PTYFUNCS_LIBS@
+LIBNL3_LIBS := @LIBNL3_LIBS@
+LIBNL3_CFLAGS := @LIBNL3_CFLAGS@
+XEN_TOOLS_RPATH := @rpath@
+
# Download GIT repositories via HTTP or GIT's own protocol?
# GIT's protocol is faster and more robust, when it works at all (firewalls
# may block it). We make it the default, but if your GIT repository downloads
@@ -46,7 +50,6 @@ GIT_HTTP := @githttp@
# Optional components
XENSTAT_XENTOP := @monitors@
-LIBXENAPI_BINDINGS := @xenapi@
OCAML_TOOLS := @ocamltools@
FLASK_POLICY := @xsmpolicy@
CONFIG_OVMF := @ovmf@
@@ -54,8 +57,18 @@ CONFIG_ROMBIOS := @rombios@
CONFIG_SEABIOS := @seabios@
CONFIG_QEMU_TRAD := @qemu_traditional@
CONFIG_QEMU_XEN := @qemu_xen@
-CONFIG_XEND := @xend@
CONFIG_BLKTAP1 := @blktap1@
+CONFIG_BLKTAP2 := @blktap2@
+CONFIG_QEMUU_EXTRA_ARGS:= @EXTRA_QEMUU_CONFIGURE_ARGS@
+CONFIG_REMUS_NETBUF := @remus_netbuf@
+
+CONFIG_SYSTEMD := @systemd@
+SYSTEMD_CFLAGS := @SYSTEMD_CFLAGS@
+SYSTEMD_LIBS := @SYSTEMD_LIBS@
+XEN_SYSTEMD_DIR := @SYSTEMD_DIR@
+XEN_SYSTEMD_MODULES_LOAD := @SYSTEMD_MODULES_LOAD@
+
+LINUX_BACKEND_MODULES := @LINUX_BACKEND_MODULES@
#System options
ZLIB := @zlib@
diff --git a/config/arm32.mk b/config/arm32.mk
index aa79d22..4f83a63 100644
--- a/config/arm32.mk
+++ b/config/arm32.mk
@@ -18,3 +18,5 @@ HAS_NS16550 := y
LDFLAGS_DIRECT += -EL
CONFIG_LOAD_ADDRESS ?= 0x80000000
+
+IOEMU_CPU_ARCH ?= arm
diff --git a/config/arm64.mk b/config/arm64.mk
index 15b57a4..6eafda2 100644
--- a/config/arm64.mk
+++ b/config/arm64.mk
@@ -13,3 +13,7 @@ HAS_NS16550 := y
LDFLAGS_DIRECT += -EL
CONFIG_LOAD_ADDRESS ?= 0x80000000
+
+IOEMU_CPU_ARCH ?= aarch64
+
+EFI_DIR ?= /usr/lib64/efi
diff --git a/config/x86_32.mk b/config/x86_32.mk
index 7f76b25..c2d785e 100644
--- a/config/x86_32.mk
+++ b/config/x86_32.mk
@@ -6,9 +6,15 @@ CONFIG_HVM := y
CONFIG_MIGRATE := y
CONFIG_XCUTILS := y
+HAS_MEM_ACCESS := y
+HAS_MEM_PAGING := y
+HAS_MEM_SHARING := y
+
CFLAGS += -m32 -march=i686
# Use only if calling $(LD) directly.
LDFLAGS_DIRECT_OpenBSD = _obsd
LDFLAGS_DIRECT_FreeBSD = _fbsd
LDFLAGS_DIRECT += -melf_i386$(LDFLAGS_DIRECT_$(XEN_OS))
+
+IOEMU_CPU_ARCH ?= i386
diff --git a/config/x86_64.mk b/config/x86_64.mk
index 11104bd..bf104c2 100644
--- a/config/x86_64.mk
+++ b/config/x86_64.mk
@@ -7,6 +7,10 @@ CONFIG_HVM := y
CONFIG_MIGRATE := y
CONFIG_XCUTILS := y
+HAS_MEM_ACCESS := y
+HAS_MEM_PAGING := y
+HAS_MEM_SHARING := y
+
CONFIG_XEN_INSTALL_SUFFIX := .gz
CFLAGS += -m64
@@ -25,3 +29,5 @@ else
LDFLAGS_DIRECT += -melf_x86_64
endif
endif
+
+IOEMU_CPU_ARCH ?= x86_64
diff --git a/configure b/configure
index 95133be..98a73d4 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Xen Hypervisor 4.4.
+# Generated by GNU Autoconf 2.69 for Xen Hypervisor 4.5.
#
# Report bugs to <xen-devel at lists.xen.org>.
#
@@ -579,8 +579,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='Xen Hypervisor'
PACKAGE_TARNAME='xen'
-PACKAGE_VERSION='4.4'
-PACKAGE_STRING='Xen Hypervisor 4.4'
+PACKAGE_VERSION='4.5'
+PACKAGE_STRING='Xen Hypervisor 4.5'
PACKAGE_BUGREPORT='xen-devel at lists.xen.org'
PACKAGE_URL='http://www.xen.org/'
@@ -592,9 +592,20 @@ SUBSYSTEMS
docs
stubdom
tools
-kernels
xen
subdirs
+XEN_PAGING_DIR
+XEN_LOCK_DIR
+XEN_SCRIPT_DIR
+XEN_CONFIG_DIR
+INITD_DIR
+CONFIG_DIR
+SHAREDIR
+XEN_LIB_STORED
+XEN_LOG_DIR
+XEN_RUN_DIR
+LIBEXEC_BIN
+CONFIG_LEAF_DIR
host_os
host_vendor
host_cpu
@@ -644,8 +655,9 @@ SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
+with_initddir
+with_sysconfig_leaf_dir
enable_xen
-enable_kernels
enable_tools
enable_stubdom
enable_docs
@@ -654,7 +666,6 @@ enable_docs
host_alias
target_alias'
ac_subdirs_all='xen
-kernels
tools
stubdom
docs'
@@ -1197,7 +1208,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures Xen Hypervisor 4.4 to adapt to many kinds of systems.
+\`configure' configures Xen Hypervisor 4.5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1262,7 +1273,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of Xen Hypervisor 4.4:";;
+ short | recursive ) echo "Configuration of Xen Hypervisor 4.5:";;
esac
cat <<\_ACEOF
@@ -1271,11 +1282,21 @@ Optional Features:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--disable-xen Disable build and install of xen
- --disable-kernels Disable build and install of kernels
--disable-tools Disable build and install of tools
--enable-stubdom Enable build and install of stubdom
--disable-docs Disable build and install of docs
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-initddir=DIR Path to directory with sysv runlevel scripts.
+ [SYSCONFDIR/init.d]
+ --with-sysconfig-leaf-dir=SUBDIR
+ Name of subdirectory in /etc to store runtime
+ options for runlevel scripts and daemons such as
+ xenstored. This should be either "sysconfig" or
+ "default". [sysconfig]
+
Report bugs to <xen-devel at lists.xen.org>.
Xen Hypervisor home page: <http://www.xen.org/>.
_ACEOF
@@ -1340,7 +1361,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-Xen Hypervisor configure 4.4
+Xen Hypervisor configure 4.5
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1357,7 +1378,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by Xen Hypervisor $as_me 4.4, which was
+It was created by Xen Hypervisor $as_me 4.5, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -1706,7 +1727,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
-ac_config_files="$ac_config_files ./config/Toplevel.mk"
+ac_config_files="$ac_config_files config/Toplevel.mk config/Paths.mk"
ac_aux_dir=
@@ -1833,73 +1854,144 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
-case "$host_cpu" in
- i[3456]86|x86_64)
- arch_enable_stubdom=y
- ;;
- *)
- arch_enable_stubdom=n
- ;;
-esac
-
-# Check whether --enable-xen was given.
-if test "${enable_xen+set}" = set; then :
- enableval=$enable_xen;
+test "x$prefix" = "xNONE" && prefix=$ac_default_prefix
+test "x$exec_prefix" = "xNONE" && exec_prefix=${prefix}
-if test "x$enableval" = "xyes"; then :
+if test "$localstatedir" = '${prefix}/var' ; then
+ localstatedir=/var
+fi
+bindir=`eval echo $bindir`
+sbindir=`eval echo $sbindir`
+libdir=`eval echo $libdir`
-xen=y
-SUBSYSTEMS="$SUBSYSTEMS xen"
+if test "x$sysconfdir" = 'x${prefix}/etc' ; then
+ case "$host_os" in
+ *freebsd*)
+ sysconfdir=$prefix/etc
+ ;;
+ *solaris*)
+ if test "$prefix" = "/usr" ; then
+ sysconfdir=/etc
+ else
+ sysconfdir=$prefix/etc
+ fi
+ ;;
+ *)
+ sysconfdir=/etc
+ ;;
+ esac
+fi
+# Check whether --with-initddir was given.
+if test "${with_initddir+set}" = set; then :
+ withval=$with_initddir; initddir_path=$withval
else
+ case "$host_os" in
+ *linux*)
+ if test -d $sysconfdir/rc.d/init.d ; then
+ initddir_path=$sysconfdir/rc.d/init.d
+ else
+ initddir_path=$sysconfdir/init.d
+ fi
+ ;;
+ *)
+ initddir_path=$sysconfdir/rc.d
+ ;;
+ esac
+fi
-if test "x$enableval" = "xno"; then :
-xen=n
+# Check whether --with-sysconfig-leaf-dir was given.
+if test "${with_sysconfig_leaf_dir+set}" = set; then :
+ withval=$with_sysconfig_leaf_dir; config_leaf_dir=$withval
+else
+ config_leaf_dir=sysconfig
+ if test ! -d /etc/sysconfig ; then config_leaf_dir=default ; fi
+fi
+CONFIG_LEAF_DIR=$config_leaf_dir
-fi
+if test "$libexecdir" = '${exec_prefix}/libexec' ; then
+ case "$host_os" in
+ *netbsd*) ;;
+ *)
+ libexecdir='${exec_prefix}/lib'
+ ;;
+ esac
fi
+libexecdir=`eval echo $libexecdir`
+LIBEXEC_BIN=`eval echo $libexecdir/$PACKAGE_TARNAME/bin`
-else
+XEN_RUN_DIR=$localstatedir/run/xen
-xen=y
-SUBSYSTEMS="$SUBSYSTEMS xen"
+XEN_LOG_DIR=$localstatedir/log/xen
-fi
+XEN_LIB_STORED=$localstatedir/lib/xenstored
-if test -e "xen/configure"; then :
+SHAREDIR=$prefix/share
-if test "x$xen" = "xy" || test "x$xen" = "x" ; then
- subdirs="$subdirs xen"
-fi
+CONFIG_DIR=$sysconfdir
-fi
+
+INITD_DIR=$initddir_path
+XEN_CONFIG_DIR=$CONFIG_DIR/xen
-# Check whether --enable-kernels was given.
-if test "${enable_kernels+set}" = set; then :
- enableval=$enable_kernels;
+XEN_SCRIPT_DIR=$XEN_CONFIG_DIR/scripts
+
+
+case "$host_os" in
+*freebsd*) XEN_LOCK_DIR=$localstatedir/lib ;;
+*netbsd*) XEN_LOCK_DIR=$localstatedir/lib ;;
+*) XEN_LOCK_DIR=$localstatedir/lock ;;
+esac
+
+
+XEN_PAGING_DIR=$localstatedir/lib/xen/xenpaging
+
+
+
+case "$host_cpu" in
+ i[3456]86|x86_64)
+ arch_enable_stubdom=y
+ ;;
+ *)
+ arch_enable_stubdom=n
+ ;;
+esac
+
+case "$host_os" in
+ freebsd*)
+ arch_enable_stubdom=n
+ ;;
+esac
+
+
+
+
+# Check whether --enable-xen was given.
+if test "${enable_xen+set}" = set; then :
+ enableval=$enable_xen;
if test "x$enableval" = "xyes"; then :
-kernels=y
-SUBSYSTEMS="$SUBSYSTEMS kernels"
+xen=y
+SUBSYSTEMS="$SUBSYSTEMS xen"
else
@@ -1907,7 +1999,7 @@ else
if test "x$enableval" = "xno"; then :
-kernels=n
+xen=n
fi
@@ -1918,17 +2010,17 @@ fi
else
-kernels=y
-SUBSYSTEMS="$SUBSYSTEMS kernels"
+xen=y
+SUBSYSTEMS="$SUBSYSTEMS xen"
fi
-if test -e "kernels/configure"; then :
+if test -e "xen/configure"; then :
-if test "x$kernels" = "xy" || test "x$kernels" = "x" ; then
- subdirs="$subdirs kernels"
+if test "x$xen" = "xy" || test "x$xen" = "x" ; then
+ subdirs="$subdirs xen"
fi
@@ -2635,7 +2727,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by Xen Hypervisor $as_me 4.4, which was
+This file was extended by Xen Hypervisor $as_me 4.5, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -2689,7 +2781,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-Xen Hypervisor config.status 4.4
+Xen Hypervisor config.status 4.5
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -2799,7 +2891,8 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
for ac_config_target in $ac_config_targets
do
case $ac_config_target in
- "./config/Toplevel.mk") CONFIG_FILES="$CONFIG_FILES ./config/Toplevel.mk" ;;
+ "config/Toplevel.mk") CONFIG_FILES="$CONFIG_FILES config/Toplevel.mk" ;;
+ "config/Paths.mk") CONFIG_FILES="$CONFIG_FILES config/Paths.mk" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac
diff --git a/configure.ac b/configure.ac
index ce06dad..1843b52 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,12 +5,18 @@ AC_PREREQ([2.67])
AC_INIT([Xen Hypervisor], m4_esyscmd([./version.sh ./xen/Makefile]),
[xen-devel at lists.xen.org], [xen], [http://www.xen.org/])
AC_CONFIG_SRCDIR([./xen/common/kernel.c])
-AC_CONFIG_FILES([./config/Toplevel.mk])
+AC_CONFIG_FILES([
+ config/Toplevel.mk
+ config/Paths.mk
+])
AC_CANONICAL_HOST
m4_include([m4/features.m4])
m4_include([m4/subsystem.m4])
+m4_include([m4/paths.m4])
+
+AX_XEN_EXPAND_CONFIG()
dnl mini-os is only ported to certain platforms
case "$host_cpu" in
@@ -22,8 +28,14 @@ case "$host_cpu" in
;;
esac
+dnl Stubdomains need some work in order to compile on FreeBSD
+case "$host_os" in
+ freebsd*)
+ arch_enable_stubdom=n
+ ;;
+esac
+
AX_SUBSYSTEM_DEFAULT_ENABLE([xen])
-AX_SUBSYSTEM_DEFAULT_ENABLE([kernels])
AX_SUBSYSTEM_DEFAULT_ENABLE([tools])
AX_SUBSYSTEM_CONDITIONAL([stubdom], $arch_enable_stubdom)
AX_SUBSYSTEM_DEFAULT_ENABLE([docs])
diff --git a/docs/Makefile b/docs/Makefile
index 8d5d48e..2c0903b 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -6,26 +6,35 @@ VERSION := $(shell $(MAKE) -C $(XEN_ROOT)/xen --no-print-directory xenversion)
DOC_ARCHES := arm x86_32 x86_64
-DOC_MAN5SRC := $(wildcard man/*.pod.5)
-DOC_MAN1SRC := $(wildcard man/*.pod.1)
-DOC_MAN1 := $(patsubst man/%.pod.1,man1/%.1,$(DOC_MAN1SRC))
-DOC_MAN5 := $(patsubst man/%.pod.5,man5/%.5,$(DOC_MAN5SRC))
-DOC_MARKDOWN := $(wildcard misc/*.markdown)
-DOC_HTML := $(patsubst %.markdown,html/%.html,$(DOC_MARKDOWN)) \
- $(patsubst man/%.pod.1,html/man/%.1.html,$(DOC_MAN1SRC)) \
- $(patsubst man/%.pod.5,html/man/%.5.html,$(DOC_MAN5SRC)) \
- $(patsubst %.txt,html/%.txt,$(wildcard misc/*.txt)) \
- $(patsubst %,html/hypercall/%/index.html,$(DOC_ARCHES))
-DOC_TXT := $(patsubst %.txt,txt/%.txt,$(wildcard misc/*.txt)) \
- $(patsubst %.markdown,txt/%.txt,$(DOC_MARKDOWN)) \
- $(patsubst man/%.pod.1,txt/man/%.1.txt,$(DOC_MAN1SRC)) \
- $(patsubst man/%.pod.5,txt/man/%.5.txt,$(DOC_MAN5SRC))
+# Documentation sources to build
+MAN1SRC-y := $(wildcard man/xl*.pod.1)
+MAN1SRC-y += $(wildcard man/xenstore*.pod.1)
+
+MAN5SRC-y := $(wildcard man/xl*.pod.5)
+
+MARKDOWNSRC-y := $(wildcard misc/*.markdown)
+
+TXTSRC-y := $(wildcard misc/*.txt)
+
+
+DOC_MAN1 := $(patsubst man/%.pod.1,man1/%.1,$(MAN1SRC-y))
+DOC_MAN5 := $(patsubst man/%.pod.5,man5/%.5,$(MAN5SRC-y))
+DOC_HTML := $(patsubst %.markdown,html/%.html,$(MARKDOWNSRC-y)) \
+ $(patsubst man/%.pod.1,html/man/%.1.html,$(MAN1SRC-y)) \
+ $(patsubst man/%.pod.5,html/man/%.5.html,$(MAN5SRC-y)) \
+ $(patsubst %.txt,html/%.txt,$(TXTSRC-y)) \
+ $(patsubst %,html/hypercall/%/index.html,$(DOC_ARCHES))
+DOC_TXT := $(patsubst %.txt,txt/%.txt,$(TXTSRC-y)) \
+ $(patsubst %.markdown,txt/%.txt,$(MARKDOWNSRC-y)) \
+ $(patsubst man/%.pod.1,txt/man/%.1.txt,$(MAN1SRC-y)) \
+ $(patsubst man/%.pod.5,txt/man/%.5.txt,$(MAN5SRC-y))
+DOC_PDF := $(patsubst %.markdown,pdf/%.pdf,$(MARKDOWNSRC-y))
.PHONY: all
all: build
.PHONY: build
-build: html txt man-pages figs
+build: html txt pdf man-pages figs
.PHONY: html
html: $(DOC_HTML) html/index.html
@@ -54,6 +63,14 @@ else
@echo "pod2man not installed; skipping man-pages."
endif
+.PHONY: pdf
+pdf:
+ifdef PANDOC
+ $(MAKE) $(DOC_PDF)
+else
+ @echo "pandoc not installed; skipping pdfs."
+endif
+
man1/%.1: man/%.pod.1 Makefile
$(INSTALL_DIR) $(@D)
$(POD2MAN) --release=$(VERSION) --name=`echo $@ | sed 's/^man1.//'| \
@@ -69,7 +86,7 @@ clean:
$(MAKE) -C figs clean
rm -rf .word_count *.aux *.dvi *.bbl *.blg *.glo *.idx *~
rm -rf *.ilg *.log *.ind *.toc *.bak *.tmp core
- rm -rf html txt
+ rm -rf html txt pdf
rm -rf man5
rm -rf man1
@@ -78,16 +95,20 @@ distclean: clean
rm -rf $(XEN_ROOT)/config/Docs.mk config.log config.status config.cache \
autom4te.cache
-.PHONY: install
-install: all
- rm -rf $(DESTDIR)$(DOCDIR)
- $(INSTALL_DIR) $(DESTDIR)$(DOCDIR)
-
+.PHONY: install-man-pages
+install-man-pages: man-pages
$(INSTALL_DIR) $(DESTDIR)$(MANDIR)
cp -R man1 $(DESTDIR)$(MANDIR)
cp -R man5 $(DESTDIR)$(MANDIR)
+
+.PHONY: install-html
+install-html: html txt figs
+ $(INSTALL_DIR) $(DESTDIR)$(DOCDIR)
[ ! -d html ] || cp -R html $(DESTDIR)$(DOCDIR)
+.PHONY: install
+install: install-man-pages install-html
+
html/index.html: $(DOC_HTML) $(CURDIR)/gen-html-index INDEX
$(PERL) -w -- $(CURDIR)/gen-html-index -i INDEX html $(DOC_HTML)
@@ -103,7 +124,7 @@ endif
html/%.txt: %.txt
$(INSTALL_DIR) $(@D)
- cp $< $@
+ $(INSTALL_DATA) $< $@
html/man/%.1.html: man/%.pod.1 Makefile
$(INSTALL_DIR) $(@D)
@@ -166,6 +187,10 @@ else
@echo "pod2text not installed; skipping $<."
endif
+pdf/%.pdf: %.markdown
+ $(INSTALL_DIR) $(@D)
+ pandoc -N --toc --standalone $< --output $@
+
ifeq (,$(findstring clean,$(MAKECMDGOALS)))
$(XEN_ROOT)/config/Docs.mk:
$(error You have to run ./configure before building docs)
diff --git a/docs/README.remus b/docs/README.remus
new file mode 100644
index 0000000..20783c9
--- /dev/null
+++ b/docs/README.remus
@@ -0,0 +1,20 @@
+Remus provides fault tolerance for virtual machines by sending continuous
+checkpoints to a backup, which will activate if the target VM fails.
+
+See the website at http://wiki.xen.org/wiki/Remus for details.
+
+Using Remus with libxl on Xen 4.5 and higher:
+ To enable network buffering, you need libnl 3.2.8
+ or higher along with the development headers and command line utilities.
+ If your distro does not have the appropriate libnl3 version, you can find
+ the latest source tarball of libnl3 at http://www.carisma.slowglass.com/~tgr/libnl/
+
+Disk replication:
+ VMs protected by Remus need to use DRBD based disk backends. Specifically, you
+ need a compile and install a custom version of DRBD, that is available publicly
+ at https://github.com/rshriram/remus-drbd
+ This code is based on DRBD 8.3.11 and uses a new replication protocol (named
+ protocol D) for asynchronous disk checkpoint replication. A protected VM's DRBD
+ disks on the primary and backup hosts need to be configured to use protocol D
+ as the replication protocol. An example resource configuration file can be found
+ in the aforementioned github repository.
diff --git a/docs/configure b/docs/configure
index d67b532..c36e249 100755
--- a/docs/configure
+++ b/docs/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Xen Hypervisor Documentation 4.4.
+# Generated by GNU Autoconf 2.69 for Xen Hypervisor Documentation 4.5.
#
# Report bugs to <xen-devel at lists.xen.org>.
#
@@ -579,8 +579,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='Xen Hypervisor Documentation'
PACKAGE_TARNAME='xen'
-PACKAGE_VERSION='4.4'
-PACKAGE_STRING='Xen Hypervisor Documentation 4.4'
+PACKAGE_VERSION='4.5'
+PACKAGE_STRING='Xen Hypervisor Documentation 4.5'
PACKAGE_BUGREPORT='xen-devel at lists.xen.org'
PACKAGE_URL='http://www.xen.org/'
@@ -589,6 +589,7 @@ ac_subst_vars='LTLIBOBJS
LIBOBJS
PERL
MARKDOWN
+PANDOC
POD2TEXT
POD2HTML
POD2MAN
@@ -642,6 +643,7 @@ FIG2DEV
POD2MAN
POD2HTML
POD2TEXT
+PANDOC
MARKDOWN
PERL'
@@ -1184,7 +1186,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures Xen Hypervisor Documentation 4.4 to adapt to many kinds of systems.
+\`configure' configures Xen Hypervisor Documentation 4.5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1245,7 +1247,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of Xen Hypervisor Documentation 4.4:";;
+ short | recursive ) echo "Configuration of Xen Hypervisor Documentation 4.5:";;
esac
cat <<\_ACEOF
@@ -1254,6 +1256,7 @@ Some influential environment variables:
POD2MAN Path to pod2man tool
POD2HTML Path to pod2html tool
POD2TEXT Path to pod2text tool
+ PANDOC Path to pandoc tool
MARKDOWN Path to markdown tool
PERL Path to Perl parser
@@ -1324,7 +1327,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-Xen Hypervisor Documentation configure 4.4
+Xen Hypervisor Documentation configure 4.5
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1341,7 +1344,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by Xen Hypervisor Documentation $as_me 4.4, which was
+It was created by Xen Hypervisor Documentation $as_me 4.5, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -1732,6 +1735,12 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+
+
+
+
# Extract the first word of "fig2dev", so it can be a program name with args.
set dummy fig2dev; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
@@ -1928,6 +1937,55 @@ fi
+ # Extract the first word of "pandoc", so it can be a program name with args.
+set dummy pandoc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PANDOC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PANDOC in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PANDOC="$PANDOC" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PANDOC="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PANDOC=$ac_cv_path_PANDOC
+if test -n "$PANDOC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PANDOC" >&5
+$as_echo "$PANDOC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if ! test -x "$ac_cv_path_PANDOC"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pandoc is not available so some documentation won't be built" >&5
+$as_echo "$as_me: WARNING: pandoc is not available so some documentation won't be built" >&2;}
+
+fi
+
+
+
for ac_prog in markdown markdown_py
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
@@ -2570,7 +2628,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by Xen Hypervisor Documentation $as_me 4.4, which was
+This file was extended by Xen Hypervisor Documentation $as_me 4.5, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -2624,7 +2682,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-Xen Hypervisor Documentation config.status 4.4
+Xen Hypervisor Documentation config.status 4.5
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/docs/configure.ac b/docs/configure.ac
index f0ebf00..bc77f49 100644
--- a/docs/configure.ac
+++ b/docs/configure.ac
@@ -11,11 +11,13 @@ AC_CONFIG_AUX_DIR([../])
# M4 Macro includes
m4_include([../m4/docs_tool.m4])
m4_include([../m4/path_or_fail.m4])
+m4_include([../m4/features.m4])
AX_DOCS_TOOL_PROG([FIG2DEV], [fig2dev])
AX_DOCS_TOOL_PROG([POD2MAN], [pod2man])
AX_DOCS_TOOL_PROG([POD2HTML], [pod2html])
AX_DOCS_TOOL_PROG([POD2TEXT], [pod2text])
+AX_DOCS_TOOL_PROG([PANDOC], [pandoc])
AX_DOCS_TOOL_PROGS([MARKDOWN], [markdown], [markdown markdown_py])
AC_ARG_VAR([PERL], [Path to Perl parser])
diff --git a/docs/man/xend-config.sxp.pod.5 b/docs/man/xend-config.sxp.pod.5
deleted file mode 100644
index 9504c71..0000000
--- a/docs/man/xend-config.sxp.pod.5
+++ /dev/null
@@ -1,158 +0,0 @@
-=head1 NAME
-
-xend-config.sxp - Xen daemon configuration file
-
-=head1 SYNOPSIS
-
-/etc/xen/xend-config.sxp
-
-=head1 DESCRIPTION
-
-The xend(1) program requires xend-config.sxp to specify operating
-parameters which determine the behavior of the daemon at runtime.
-
-The parameters are specified in S-expression format. See the example
-configuration file in I</etc/xen/xend-config.sxp> for details.
-
-=head1 OPTIONS
-
-The following lists the daemon configuration parameters:
-
-=over 4
-
-=item I<logfile>
-
-The location of the file to record runtime log messages. Defaults to
-I</var/log/xen/xend.log>.
-
-=item I<loglevel>
-
-Filters out messages below the specified level. Possible values are
-DEBUG, INFO, WARNING, ERROR, CRITICAL. Defaults to I<DEBUG>.
-
-=item I<xend-http-server>
-
-A boolean value that tells xend whether or not to start the http
-stream socket management server. Defaults to I<no>.
-
-=item I<xend-unix-server>
-
-A boolean value that tells xend whether or not to start the unix
-domain socket management server. This is required for the CLI tools
-to operate. Defaults to I<yes>.
-
-=item I<xend-relocation-server>
-
-A boolean value that tells xend whether or not to start the relocation
-server. This is required for cross-machine migrations. Defaults to
-I<no>.
-
-=item I<xend-unix-path>
-
-The location of the unix domain socket the xend-unix-server will use
-to communicate with the management tools. Defaults to
-I</var/lib/xend/xend-socket>.
-
-=item I<xend-port>
-
-The port that will be used by the http management server. Defaults to
-I<8000>.
-
-=item I<xend-relocation-port>
-
-The port that will be used by the relocation server. Defaults to
-I<8002>.
-
-=item I<xend-address>
-
-The address to which the http management server will bind. Defaults
-to I<''> which means "all interfaces".
-
-=item I<xend-relocation-address>
-
-The address to which the relocation server will bind. Defaults to
-I<''> which means "all interfaces".
-
-=item I<console-limit>
-
-The kilobyte buffer limit that will be enforced by the console server.
-This limit is set per-domain, and is needed to prevent a single domain
-from overwhelming the console server with massive amounts of data.
-Defaults to I<1024>.
-
-=item I<network-script>
-
-The name of the script in I</etc/xen/scripts> that will be run to
-setup the networking environment. This can be any name, but in
-general is either I<network-bridge> or I<network-route>.
-
-=item I<vif-script>
-
-The name of the script in I</etc/xen/scripts> that will be run to
-setup a virtual interface when it is created or destroyed. This needs
-to (in general) work in unison with the I<network-script>.
-
-=item I<dom0-min-mem>
-
-This specifies the minimum number of megabytes that will be reserved
-for Domain0. If this value is positive, Domain0 will be automatically
-ballooned down to this limit to make space for new domains. If this
-is set to 0, Domain0 will not be automatically ballooned.
-
-=item I<dom0-cpus>
-
-This specifies the number of CPUs that Domain0 will be allowed to use.
-If the value is 0, all available CPUs will be used by Domain0.
-
-=item I<enable-dump>
-
-A boolean value that tells xend whether or not core dumps of guest
-domains should be saved when a crash occurs. Defaults to I<no>.
-
-=item I<external-migration-tool>
-
-The name of an application or script that can handle external device
-migration, such as for example virtual TPM migration. An example
-script is I</etc/xen/scripts/external-device-migrate>.
-
-=item I<device-create-timeout>
-
-Integer value that tells xend how long it should wait for a new device
-to be created. Defaults to I<100>.
-
-=item I<device-destroy-timeout>
-
-Integer value that tells xend how long it should wait for a device to
-be destroyed. Defaults to I<100>.
-
-=back
-
-=head1 EXAMPLES
-
-An example configuration with relocation enabled for the local network:
-
-=over 4
-
- (xend-relocation-server yes)
- (xend-relocation-address 192.0.2.192)
- (network-script network-bridge)
- (vif-script vif-bridge)
- (dom0-min-mem 0)
- (dom0-cpus 0)
-
-=back
-
-=head1 CAVEATS
-
-Note that relocation is currently unsecured and is very dangerous if
-left enabled. No authentication is performed, and very little sanity
-checking takes place. Enable at your own risk.
-
-=head1 SEE ALSO
-
-B<xend>(1)
-
-=head1 AUTHOR
-
-Dan Smith <danms at us.ibm.com>
-
diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
index e15a49f..622ea53 100644
--- a/docs/man/xl.cfg.pod.5
+++ b/docs/man/xl.cfg.pod.5
@@ -48,6 +48,14 @@ not nested.
The semantics of each C<KEY> defines which form of C<VALUE> is required.
+Pairs may be separated either by a newline or a semicolon. Both
+of the following are valid:
+
+ name="h0"
+ builder="hvm"
+
+ name="h0"; builder="hvm"
+
=head1 OPTIONS
=head2 Mandatory Configuration Items
@@ -135,27 +143,49 @@ Combining this with "all" is also possible, meaning "all,^nodes:1"
results in all the vcpus of the guest running on all the cpus on the
host, except for the cpus belonging to the host NUMA node 1.
-=item ["2", "3"] (or [2, 3])
+=item ["2", "3-8,^5"]
-To ask for specific vcpu mapping. That means (in this example), vcpu #0
-of the guest will run on cpu #2 of the host and vcpu #1 of the guest will
-run on cpu #3 of the host.
+To ask for specific vcpu mapping. That means (in this example), vcpu 0
+of the guest will run on cpu 2 of the host and vcpu 1 of the guest will
+run on cpus 3,4,6,7,8 of the host.
+
+More complex notation can be also used, exactly as described above. So
+"all,^5-8", or just "all", or "node:0,node:2,^9-11,18-20" are all legal,
+for each element of the list.
=back
If this option is not specified, no vcpu to cpu pinning is established,
-and the vcpus of the guest can run on all the cpus of the host.
-
-If we are on a NUMA machine (i.e., if the host has more than one NUMA
-node) and this option is not specified, libxl automatically tries to
-place the guest on the least possible number of nodes. That, however,
-will not affect vcpu pinning, so the guest will still be able to run on
-all the cpus, it will just prefer the ones from the node it has been
-placed on. A heuristic approach is used for choosing the best node (or
-set of nodes), with the goals of maximizing performance for the guest
-and, at the same time, achieving efficient utilization of host cpus
-and memory. See F<docs/misc/xl-numa-placement.markdown> for more
-details.
+and the vcpus of the guest can run on all the cpus of the host. If this
+option is specified, the intersection of the vcpu pinning mask, provided
+here, and the soft affinity mask, provided via B<cpus\_soft=> (if any),
+is utilized to compute the domain node-affinity, for driving memory
+allocations.
+
+=item B<cpus_soft="CPU-LIST">
+
+Exactly as B<cpus=>, but specifies soft affinity, rather than pinning
+(hard affinity). When using the credit scheduler, this means what cpus
+the vcpus of the domain prefer.
+
+A C<CPU-LIST> is specified exactly as above, for B<cpus=>.
+
+If this option is not specified, the vcpus of the guest will not have
+any preference regarding on what cpu to run. If this option is specified,
+the intersection of the soft affinity mask, provided here, and the vcpu
+pinning, provided via B<cpus=> (if any), is utilized to compute the
+domain node-affinity, for driving memory allocations.
+
+If this option is not specified (and B<cpus=> is not specified either),
+libxl automatically tries to place the guest on the least possible
+number of nodes. A heuristic approach is used for choosing the best
+node (or set of nodes), with the goal of maximizing performance for
+the guest and, at the same time, achieving efficient utilization of
+host cpus and memory. In that case, the soft affinity of all the vcpus
+of the domain will be set to the pcpus belonging to the NUMA nodes
+chosen during placement.
+
+For more details, see F<docs/misc/xl-numa-placement.markdown>.
=back
@@ -296,6 +326,44 @@ Action to take if the domain crashes. Default is C<destroy>.
=back
+=head3 Direct Kernel Boot
+
+Direct kernel boot allows booting directly from a kernel and initrd
+stored in the host physical machine OS, allowing command line arguments
+to be passed directly. PV guest direct kernel boot is supported. HVM
+guest direct kernel boot is supported with limitation (it's supported
+when using qemu-xen and default BIOS 'seabios'; not supported in case of
+stubdom-dm and old rombios.)
+
+=over 4
+
+=item B<kernel="PATHNAME">
+
+Load the specified file as the kernel image.
+
+=item B<ramdisk="PATHNAME">
+
+Load the specified file as the ramdisk.
+
+=item B<cmdline="STRING">
+
+Append B<cmdline="STRING"> to the kernel command line. (Note: it is
+guest specific what meaning this has). It can replace B<root="STRING">
+plus B<extra="STRING"> and is preferred. When B<cmdline="STRING"> is set,
+B<root="STRING"> and B<extra="STRING"> will be ignored.
+
+=item B<root="STRING">
+
+Append B<root="STRING"> to the kernel command line (Note: it is guest
+specific what meaning this has).
+
+=item B<extra="STRING">
+
+Append B<STRING> to the kernel command line. (Note: it is guest
+specific what meaning this has).
+
+=back
+
=head3 Other Options
=over 4
@@ -389,8 +457,8 @@ This options does not control the emulated graphics card presented to
an HVM guest. See L<Emulated VGA Graphics Device> below for how to
configure the emulated device. If L<Emulated VGA Graphics Device> options
are used in a PV guest configuration, xl will pick up B<vnc>, B<vnclisten>,
-B<vncpasswd>, B<vncdisplay> and B<vncunused> to construct paravirtual
-framebuffer device for the guest.
+B<vncpasswd>, B<vncdisplay>, B<vncunused>, B<sdl>, B<opengl> and
+B<keymap> to construct paravirtual framebuffer device for the guest.
Each B<VFB_SPEC_STRING> is a comma-separated list of C<KEY=VALUE>
settings, from the following list:
@@ -462,6 +530,59 @@ L<qemu(1)> manpage. The default is B<en-us>.
=back
+=item B<channel=[ "CHANNEL_SPEC_STRING", "CHANNEL_SPEC_STRING", ...]>
+
+Specifies the virtual channels to be provided to the guest. A
+channel is a low-bandwidth, bidirectional byte stream, which resembles
+a serial link. Typical uses for channels include transmitting VM
+configuration after boot and signalling to in-guest agents. Please see
+F<docs/misc/channels.txt> for more details.
+
+Each B<CHANNEL_SPEC_STRING> is a comma-separated list of C<KEY=VALUE>
+seettings. Leading and trailing whitespace is ignored in both KEY and
+VALUE. Neither KEY nor VALUE may contain ',', '=' or '"'. Defined values
+are:
+
+=over 4
+
+=item C<backend=DOMAIN>
+
+Specify the backend domain name or id. This parameter is optional. If
+this parameter is omitted then the toolstack domain will be assumed.
+
+=item C<name=NAME>
+
+Specify the string name for this device. This parameter is mandatory.
+This should be a well-known name for the specific application (e.g.
+guest agent) and should be used by the frontend to connect the
+application to the right channel device. There is no formal registry
+of channel names, so application authors are encouraged to make their
+names unique by including domain name and version number in the string
+(e.g. org.mydomain.guestagent.1).
+
+=item C<connection=CONNECTION>
+
+Specify how the backend will be implemented. This following options are
+available:
+
+=over 4
+
+=item B<connection=SOCKET>
+
+The backend will bind a Unix domain socket (at the path given by
+B<path=PATH>), call listen and accept connections. The backend will proxy
+data between the channel and the connected socket.
+
+=item B<connection=PTY>
+
+The backend will create a pty and proxy data between the channel and the
+master device. The command B<xl channel-list> can be used to discover the
+assigned slave device.
+
+=back
+
+=back
+
=item B<pci=[ "PCI_SPEC_STRING", "PCI_SPEC_STRING", ... ]>
Specifies the host PCI devices to passthrough to this guest. Each B<PCI_SPEC_STRING>
@@ -509,6 +630,15 @@ the PCI device regardless whether the guest uses INTx or MSI. Some
device drivers, such as NVIDIA's, detect an inconsistency and do not
function when this option is enabled. Therefore the default is false (0).
+=item B<seize=BOOLEAN>
+
+Tells xl to automatically attempt to re-assign a device to
+pciback if it is not already assigned.
+
+WARNING: If you set this option, xl will gladly re-assign a critical
+system device, such as a network or a disk controller being used by
+dom0 without confirmation. Please use with care.
+
=item B<power_mgmt=BOOLEAN>
(HVM only) Specifies that the VM should be able to program the
@@ -530,6 +660,11 @@ above.
Changes the default value of 'msitranslate' for all PCI devices passed
through to this VM. See L<msitranslate|/"msitranslate_boolean"> above.
+=item B<pci_seize=BOOLEAN>
+
+Changes the default value of 'seize' for all PCI devices passed
+through to this VM. See L<seize|/"seize_boolean"> above.
+
=item B<pci_power_mgmt=BOOLEAN>
(HVM only) Changes the default value of 'power_mgmt' for all PCI
@@ -588,17 +723,24 @@ is given in hexadecimal and may either a span e.g. C<2f8-2ff>
It is recommended to use this option only for trusted VMs under
administrator control.
-=item B<iomem=[ "IOMEM_START,NUM_PAGES", "IOMEM_START,NUM_PAGES", ... ]>
+=item B<iomem=[ "IOMEM_START,NUM_PAGES[@GFN]", "IOMEM_START,NUM_PAGES[@GFN]", ... ]>
+
+Allow auto-translated domains to access specific hardware I/O memory pages.
+
+B<IOMEM_START> is a physical page number. B<NUM_PAGES> is the number of pages
+beginning with B<START_PAGE> to allow access. B<GFN> specifies the guest frame
+number where the mapping will start in the domU's address space. If B<GFN> is
+not given, the mapping will be performed using B<IOMEM_START> as a start in the
+domU's address space, therefore performing an 1:1 mapping as default.
+All of these values must be given in hexadecimal.
-Allow guest to access specific hardware I/O memory pages. B<IOMEM_START>
-is a physical page number. B<NUM_PAGES> is the number
-of pages beginning with B<START_PAGE> to allow access. Both values
-must be given in hexadecimal.
+Note that the IOMMU won't be updated with the mappings specified with this
+option. This option therefore should not be used to passthrough any
+IOMMU-protected device.
It is recommended to use this option only for trusted VMs under
administrator control.
-
=item B<irqs=[ NUMBER, NUMBER, ... ]>
Allow a guest to access specific physical IRQs.
@@ -625,20 +767,12 @@ The following options apply only to Paravirtual guests.
=over 4
-=item B<kernel="PATHNAME">
-
-Load the specified file as the kernel image. Either B<kernel> or
-B<bootloader> must be specified for PV guests.
-
-=item B<ramdisk="PATHNAME">
-
-Load the specified file as the ramdisk.
-
=item B<bootloader="PROGRAM">
Run C<PROGRAM> to find the kernel image and ramdisk to use. Normally
C<PROGRAM> would be C<pygrub>, which is an emulation of
-grub/grub2/syslinux.
+grub/grub2/syslinux. Either B<kernel> or B<bootloader> must be specified
+for PV guests.
=item B<bootloader_args=[ "ARG", "ARG", ...]>
@@ -646,16 +780,6 @@ Append B<ARG>s to the arguments to the B<bootloader>
program. Alternatively if the argument is a simple string then it will
be split into words at whitespace (this second option is deprecated).
-=item B<root="STRING">
-
-Append B<root="STRING"> to the kernel command line (Note: it is guest
-specific what meaning this has).
-
-=item B<extra="STRING">
-
-Append B<STRING> to the kernel command line. Note: it is guest
-specific what meaning this has).
-
=item B<e820_host=BOOLEAN>
Selects whether to expose the host e820 (memory map) to the guest via
@@ -680,6 +804,7 @@ it is safe to allow this to be enabled but you may wish to disable it
anyway.
=item B<pvh=BOOLEAN>
+
Selects whether to run this PV guest in an HVM container. Default is 0.
=back
@@ -859,9 +984,13 @@ Possible values for a single feature bit:
'k' -> pass through the host bit value
's' -> as 'k' but preserve across save/restore and migration (not implemented)
+Note: when specifying B<cpuid> for hypervisor leaves (0x4000xxxx major group)
+only the lowest 8 bits of leaf's 0x4000xx00 EAX register are processed, the rest
+are ignored (these 8 bits signify maximum number of hypervisor leaves).
+
List of keys taking a value:
-apicidsize brandid clflush family localapicid maxleaf model nc proccount procpkg
-stepping
+apicidsize brandid clflush family localapicid maxleaf maxhvleaf model nc
+proccount procpkg stepping
List of keys taking a character:
3dnow 3dnowext 3dnowprefetch abm acpi aes altmovcr8 apic avx clfsh cmov
@@ -910,6 +1039,35 @@ number of vendor defined SMBIOS structures (type 128 - 255). Since SMBIOS
structures do not present their overall size, each entry in the file must be
preceded by a 32b integer indicating the size of the next structure.
+=item B<ms_vm_genid="OPTION">
+
+Provide a VM generation ID to the guest.
+
+The VM generation ID as a 128-bit random number that a guest may use
+to determine if the guest has been restored from an earlier snapshot
+or cloned.
+
+This is required for Microsoft Windows Server 2012 (and later) domain
+controllers.
+
+Valid options are:
+
+=over 4
+
+=item B<"generate">
+
+Generate a random VM generation ID every time the domain is created or
+restored.
+
+=item B<"none">
+
+Do not provide a VM generation ID.
+
+=back
+
+See also "Virtual Machine Generation ID" by Microsoft
+(http://www.microsoft.com/en-us/download/details.aspx?id=30707).
+
=back
=head3 Guest Virtual Time Controls
@@ -918,7 +1076,6 @@ preceded by a 32b integer indicating the size of the next structure.
=item B<tsc_mode="MODE">
-
Specifies how the TSC (Time Stamp Counter) should be provided to the
guest (X86 only). Specifying this option as a number is
deprecated. Options are:
@@ -964,7 +1121,6 @@ i.e. set to UTC.
Set the real time clock offset in seconds. False (0) by default.
-
=item B<vpt_align=BOOLEAN>
Specifies that periodic Virtual Platform Timers should be aligned to
@@ -1008,6 +1164,21 @@ wallclock (i.e., real) time.
=back
+=head3 Memory layout
+
+=over 4
+
+=item B<mmio_hole=MBYTES>
+
+Specifies the size the MMIO hole below 4GiB will be. Only valid for
+device_model_version = "qemu-xen".
+
+Cannot be smaller than 256. Cannot be larger than 3840.
+
+Known good large value is 3072.
+
+=back
+
=head3 Support for Paravirtualisation of HVM Guests
The following options allow Paravirtualised features (such as devices)
@@ -1031,18 +1202,68 @@ Windows L<http://wiki.xen.org/wiki/XenWindowsGplPv>.
Setting B<xen_platform_pci=0> with the default device_model "qemu-xen"
requires at least QEMU 1.6.
-=item B<viridian=BOOLEAN>
+=item B<viridian=[ "GROUP", "GROUP", ...]>
+
+The groups of Microsoft Hyper-V (AKA viridian) compatible enlightenments
+exposed to the guest. The following groups of enlightenments may be
+specified:
+
+=over 4
+
+=item B<base>
+
+This group incorporates the Hypercall MSRs, Virtual processor index MSR,
+and APIC access MSRs. These enlightenments can improve performance of
+Windows Vista and Windows Server 2008 onwards and setting this option
+for such guests is strongly recommended.
+This group is also a pre-requisite for all others. If it is disabled
+then it is an error to attempt to enable any other group.
+
+=item B<freq>
+
+This group incorporates the TSC and APIC frequency MSRs. These
+enlightenments can improve performance of Windows 7 and Windows
+Server 2008 R2 onwards.
+
+=item B<time_ref_count>
+
+This group incorporates Partition Time Reference Counter MSR. This
+enlightenment can improve performance of Windows 8 and Windows
+Server 2012 onwards.
+
+=item B<defaults>
-Turns on or off the exposure of MicroSoft Hyper-V (AKA viridian)
-compatible enlightenments to the guest. These can improve performance
-of Microsoft Windows guests from Windows Vista and Windows 2008
-onwards and setting this option for such guests is strongly
-recommended. This option should be harmless for other versions of
-Windows (although it will not give any benefit) and the majority of
-other non-Windows OSes. However it is known to be incompatible with
-some other Operating Systems and in some circumstance can prevent
-Xen's own paravirtualisation interfaces for HVM guests from being
-used.
+This is a special value that enables the default set of groups, which
+is currently the B<base>, B<freq> and B<time_ref_count> groups.
+
+=item B<all>
+
+This is a special value that enables all available groups.
+
+=back
+
+Groups can be disabled by prefixing the name with '!'. So, for example,
+to enable all groups except B<freq>, specify:
+
+=over 4
+
+B<viridian=[ "all", "!freq" ]>
+
+=back
+
+For details of the enlightenments see the latest version of Microsoft's
+Hypervisor Top-Level Functional Specification.
+
+The enlightenments should be harmless for other versions of Windows
+(although they will not give any benefit) and the majority of other
+non-Windows OSes.
+However it is known that they are incompatible with some other Operating
+Systems and in some circumstance can prevent Xen's own paravirtualisation
+interfaces for HVM guests from being used.
+
+The viridian option can be specified as a boolean. A value of true (1)
+is equivalent to the list [ "defaults" ], and a value of false (0) is
+equivalent to an empty list.
=back
@@ -1082,7 +1303,7 @@ This option is deprecated, use vga="stdvga" instead.
=item B<vga="STRING">
-Selects the emulated video card (stdvga|cirrus).
+Selects the emulated video card (none|stdvga|cirrus).
The default is cirrus.
=item B<vnc=BOOLEAN>
@@ -1090,10 +1311,6 @@ The default is cirrus.
Allow access to the display via the VNC protocol. This enables the
other VNC-related settings. The default is to enable this.
-=item B<vncviewer=BOOLEAN>
-
-Automatically spawn a vncviewer when creating/restoring a guest.
-
=item B<vnclisten="ADDRESS[:DISPLAYNUM]">
Specifies the IP address, and optionally VNC display number, to use.
@@ -1210,13 +1427,15 @@ an usb2 controller. The default is disabled (0).
=over 4
-=item B<serial=DEVICE>
+=item B<serial=[ "DEVICE", "DEVICE", ...]>
-Redirect the virtual serial port to B<DEVICE>. Please see the
+Redirect virtual serial ports to B<DEVICE>s. Please see the
B<-serial> option in the L<qemu(1)> manpage for details of the valid
B<DEVICE> options. Default is B<vc> when in graphical mode and
B<stdio> if B<nographics=1> is used.
+The form serial=DEVICE is also accepted for backwards compatibilty.
+
=item B<soundhw=DEVICE>
Select the virtual sound card to expose to the guest. The valid
diff --git a/docs/man/xl.conf.pod.5 b/docs/man/xl.conf.pod.5
index 7c43bde..8ae19bb 100644
--- a/docs/man/xl.conf.pod.5
+++ b/docs/man/xl.conf.pod.5
@@ -105,6 +105,12 @@ Configures the default gateway device to set for virtual network devices.
Default: C<None>
+=item B<remus.default.netbufscript="PATH">
+
+Configures the default script used by Remus to setup network buffering.
+
+Default: C</etc/xen/scripts/remus-netbuf-setup>
+
=item B<output_format="json|sxp">
Configures the default output format used by xl when printing "machine
diff --git a/docs/man/xl.pod.1 b/docs/man/xl.pod.1
index e7b9de2..6b89ba8 100644
--- a/docs/man/xl.pod.1
+++ b/docs/man/xl.pod.1
@@ -12,7 +12,6 @@ The B<xl> program is the new tool for managing Xen guest
domains. The program can be used to create, pause, and shutdown
domains. It can also be used to list current domains, enable or pin
VCPUs, and attach or detach virtual block devices.
-The old B<xm> tool is deprecated and should not be used.
The basic structure of every B<xl> command is almost always:
@@ -81,6 +80,12 @@ Force execution: xl will refuse to run some commands if it detects that xend is
also running, this option will force the execution of those commands, even
though it is unsafe.
+=item B<-t>
+
+Always use carriage-return-based overwriting for printing progress
+messages without scrolling the screen. Without -t, this is done only
+if stderr is a tty.
+
=back
=head1 DOMAIN SUBCOMMANDS
@@ -147,6 +152,12 @@ It is possible to pass I<key=value> pairs on the command line to provide
options as if they were written in the configuration file; these override
whatever is in the I<configfile>.
+NB: Many config options require characters such as quotes or brackets
+which are interpreted by the shell (and often discarded) before being
+passed to xl, resulting in xl being unable to parse the value
+correctly. A simple work-around is to put all extra options within a
+single set of quotes, separated by semicolons. (See below for an example.)
+
=back
B<EXAMPLES>
@@ -160,6 +171,13 @@ B<EXAMPLES>
This creates a domain with the file /etc/xen/DebianLenny, and returns as
soon as it is run.
+=item I<with extra parameters>
+
+ xl create hvm.cfg 'cpus="0-3"; pci=["01:05.1","01:05.2"]'
+
+This creates a domain with the file hvm.cfg, but additionally pins it to
+cpus 0-3, and passes through two PCI devices.
+
=back
=item B<config-update> B<domid> [I<configfile>] [I<OPTIONS>]
@@ -169,6 +187,11 @@ immediate effect but will be applied when the guest is next
restarted. This command is useful to ensure that runtime modifications
made to the guest will be preserved when the guest is restarted.
+Since Xen 4.5 xl has improved capabilities to handle dynamic domain
+configuration changes and will preserve any changes made a runtime
+when necessary. Therefore it should not normally be necessary to use
+this command any more.
+
I<configfile> has to be an absolute path to a file.
B<OPTIONS>
@@ -181,9 +204,11 @@ Use the given configuration file.
=item B<key=value>
-It is possible to pass I<key=value> pairs on the command line to provide
-options as if they were written in the configuration file; these override
-whatever is in the I<configfile>.
+It is possible to pass I<key=value> pairs on the command line to
+provide options as if they were written in the configuration file;
+these override whatever is in the I<configfile>. Please see the note
+under I<create> on handling special characters when passing
+I<key=value> pairs on the command line.
=back
@@ -212,13 +237,25 @@ Connect to console number I<NUM>. Console numbers start from 0.
=back
-=item B<destroy> I<domain-id>
+=item B<destroy> [I<OPTIONS>] I<domain-id>
Immediately terminate the domain I<domain-id>. This doesn't give the
domain OS any chance to react, and is the equivalent of ripping the
power cord out on a physical machine. In most cases you will want to
use the B<shutdown> command instead.
+B<OPTIONS>
+
+=over 4
+
+=item I<-f>
+
+Allow domain 0 to be destroyed. Because domain cannot destroy itself, this is
+only possible when using a disaggregated toolstack, and is most useful when
+using a hardware domain separated from domain 0.
+
+=back
+
=item B<domid> I<domain-name>
Converts a domain name to a domain id.
@@ -399,7 +436,7 @@ Enable Remus HA for domain. By default B<xl> relies on ssh as a transport
mechanism between the two hosts.
N.B: Remus support in xl is still in experimental (proof-of-concept) phase.
- There is no support for network or disk buffering at the moment.
+ Disk replication support is limited to DRBD disks.
B<OPTIONS>
@@ -409,11 +446,6 @@ B<OPTIONS>
Checkpoint domain memory every MS milliseconds (default 200ms).
-=item B<-b>
-
-Replicate memory checkpoints to /dev/null (blackhole).
-Generally useful for debugging.
-
=item B<-u>
Disable memory checkpoint compression.
@@ -428,6 +460,29 @@ If empty, run <host> instead of ssh <host> xl migrate-receive -r [-e].
On the new host, do not wait in the background (on <host>) for the death
of the domain. See the corresponding option of the I<create> subcommand.
+=item B<-N> I<netbufscript>
+
+Use <netbufscript> to setup network buffering instead of the
+default script (/etc/xen/scripts/remus-netbuf-setup).
+
+=item B<-F>
+
+Run Remus in unsafe mode. Use this option with caution as failover may
+not work as intended.
+
+=item B<-b>
+
+Replicate memory checkpoints to /dev/null (blackhole).
+Generally useful for debugging. Requires enabling unsafe mode.
+
+=item B<-n>
+
+Disable network output buffering. Requires enabling unsafe mode.
+
+=item B<-d>
+
+Disable disk replication. Requires enabling unsafe mode.
+
=back
=item B<pause> I<domain-id>
@@ -619,16 +674,32 @@ after B<vcpu-set>, go to B<SEE ALSO> section for information.
Lists VCPU information for a specific domain. If no domain is
specified, VCPU information for all domains will be provided.
-=item B<vcpu-pin> I<domain-id> I<vcpu> I<cpus>
+=item B<vcpu-pin> I<domain-id> I<vcpu> I<cpus hard> I<cpus soft>
+
+Set hard and soft affinity for a I<vcpu> of <domain-id>. Normally VCPUs
+can float between available CPUs whenever Xen deems a different run state
+is appropriate.
+
+Hard affinity can be used to restrict this, by ensuring certain VCPUs
+can only run on certain physical CPUs. Soft affinity specifies a I<preferred>
+set of CPUs. Soft affinity needs special support in the scheduler, which is
+only provided in credit1.
+
+The keyword B<all> can be used to apply the hard and soft affinity masks to
+all the VCPUs in the domain. The symbol '-' can be used to leave either
+hard or soft affinity alone.
+
+For example:
+
+ xl vcpu-pin 0 3 - 6-9
+
+will set soft affinity for vCPU 3 of domain 0 to pCPUs 6,7,8 and 9,
+leaving its hard affinity untouched. On the othe hand:
-Pins the VCPU to only run on the specific CPUs. The keyword
-B<all> can be used to apply the I<cpus> list to all VCPUs in the
-domain.
+ xl vcpu-pin 0 3 3,4 6-9
-Normally VCPUs can float between available CPUs whenever Xen deems a
-different run state is appropriate. Pinning can be used to restrict
-this, by ensuring certain VCPUs can only run on certain physical
-CPUs.
+will set both hard and soft affinity, the former to pCPUs 3 and 4, the
+latter to pCPUs 6,7,8, and 9.
=item B<vm-list>
@@ -987,6 +1058,41 @@ Restrict output to domains in the specified cpupool.
=back
+=item B<sched-rtds> [I<OPTIONS>]
+
+Set or get rtds (Real Time Deferrable Server) scheduler parameters.
+This rt scheduler applies Preemptive Global Earliest Deadline First
+real-time scheduling algorithm to schedule VCPUs in the system.
+Each VCPU has a dedicated period and budget.
+VCPUs in the same domain have the same period and budget.
+While scheduled, a VCPU burns its budget.
+A VCPU has its budget replenished at the beginning of each period;
+Unused budget is discarded at the end of each period.
+
+B<OPTIONS>
+
+=over 4
+
+=item B<-d DOMAIN>, B<--domain=DOMAIN>
+
+Specify domain for which scheduler parameters are to be modified or retrieved.
+Mandatory for modifying scheduler parameters.
+
+=item B<-p PERIOD>, B<--period=PERIOD>
+
+Period of time, in microseconds, over which to replenish the budget.
+
+=item B<-b BUDGET>, B<--budget=BUDGET>
+
+Amount of time, in microseconds, that the VCPU will be allowed
+to run every period.
+
+=item B<-c CPUPOOL>, B<--cpupool=CPUPOOL>
+
+Restrict output to domains in the specified cpupool.
+
+=back
+
=back
=head1 CPUPOOLS COMMANDS
@@ -1162,6 +1268,16 @@ List virtual network interfaces for a domain.
=back
+=head2 CHANNEL DEVICES
+
+=over 4
+
+=item B<channel-list> I<domain-id>
+
+List virtual channel interfaces for a domain.
+
+=back
+
=head2 VTPM DEVICES
=over 4
@@ -1336,6 +1452,33 @@ policy. Loading new security policy will reset runtime changes to device labels.
=back
+=head1 CACHE MONITORING TECHNOLOGY
+
+Intel Haswell and later server platforms offer monitoring capability in each
+logical processor to measure specific platform shared resource metric, for
+example, L3 cache occupancy. In Xen implementation, the monitoring granularity
+is domain level. To monitor a specific domain, just attach the domain id with
+the monitoring service. When the domain doesn't need to be monitored any more,
+detach the domain id from the monitoring service.
+
+=over 4
+
+=item B<psr-cmt-attach> [I<domain-id>]
+
+attach: Attach the platform shared resource monitoring service to a domain.
+
+=item B<psr-cmt-detach> [I<domain-id>]
+
+detach: Detach the platform shared resource monitoring service from a domain.
+
+=item B<psr-cmt-show> [I<psr-monitor-type>] [I<domain-id>]
+
+Show monitoring data for a certain domain or all domains. Current supported
+monitor types are:
+ - "cache-occupancy": showing the L3 cache occupancy.
+
+=back
+
=head1 TO BE DOCUMENTED
We need better documentation for:
diff --git a/docs/man/xm.pod.1 b/docs/man/xm.pod.1
deleted file mode 100644
index 973de95..0000000
--- a/docs/man/xm.pod.1
+++ /dev/null
@@ -1,1004 +0,0 @@
-=head1 NAME
-
-xm - Obsolete xen management user interface
-
-=head1 SYNOPSIS
-
-B<xm> I<subcommand> [I<args>]
-
-=head1 DESCRIPTION
-
-This program is now superseded by B<xl>, which should be largely
-backwards-compatible with B<xm>.
-
-The B<xm> program is the main interface for managing Xen guest domains
-when the obsolete Xend toolstack is in use. The program can be used to
-create, pause, and shutdown domains. It can also be used to list
-current domains, enable or pin VCPUs, and attach or detach virtual
-block devices.
-
-The basic structure of every B<xm> command is almost always:
-
-=over 2
-
-B<xm> I<subcommand> I<domain-id> [I<OPTIONS>]
-
-=back
-
-Where I<subcommand> is one of the subcommands listed below, I<domain-id>
-is the numeric domain id, or the domain name (which will be internally
-translated to domain id), and I<OPTIONS> are subcommand specific
-options. There are a few exceptions to this rule in the cases where
-the subcommand in question acts on all domains, the entire machine,
-or directly on the Xen hypervisor. Those exceptions will be clear for
-each of those subcommands.
-
-=head1 NOTES
-
-All B<xm> operations rely upon the Xen control daemon, aka B<xend>.
-For any B<xm> commands to run, xend must also be running. For this
-reason you should start xend as a service when your system first boots
-using Xen.
-
-Most B<xm> commands require root privileges to run due to the
-communications channels used to talk to the hypervisor. Running as
-non root will return an error.
-
-Most B<xm> commands act synchronously, except maybe create, shutdown,
-mem-set and vcpu-set. The fact that the B<xm> command returned doesn't
-necessarily mean that the action is complete and you must poll through
-xm list periodically to detect that the operation completed.
-
-=head1 DOMAIN SUBCOMMANDS
-
-The following subcommands manipulate domains directly. As stated
-previously, most commands take I<domain-id> as the first parameter.
-
-=over 4
-
-=item B<console> I<domain-id>
-
-Attach to domain I<domain-id>'s console. If you've set up your domains to
-have a traditional log in console this will look much like a normal
-text log in screen.
-
-This uses the back end xenconsole service which currently only
-works for para-virtual domains.
-
-The attached console will perform much like a standard serial console,
-so running curses based interfaces over the console B<is not
-advised>. Vi tends to get very odd when using it over this interface.
-
-Use the key combination Ctrl+] to detach the domain console.
-
-=item B<create> I<configfile> [I<OPTIONS>] [I<vars>]..
-
-The create subcommand requires a config file and can optionally take a
-series of I<vars> that add to or override variables defined
-in the config file. See L<xmdomain.cfg> for full details of that file
-format, and possible options used in either the configfile or for I<vars>.
-
-I<configfile> can either be an absolute path to a file, or a relative
-path to a file located in /etc/xen.
-
-Create will return B<as soon> as the domain is started. This B<does
-not> mean the guest OS in the domain has actually booted, or is
-available for input.
-
-B<OPTIONS>
-
-=over 4
-
-=item B<--help_config>
-
-Print the available configuration variables I<vars>. These variables may be
-used on the command line or in the configuration file I<configfile>.
-
-=item B<-q>, B<--quiet>
-
-No console output.
-
-=item B<--path>
-
-Search path for configuration scripts. The value of PATH is a
-colon-separated directory list.
-
-=item B<-f=FILE>, B<--defconfig=FILE>
-
-Use the given Python configuration script. The configuration
-script is loaded after arguments have been processed. Each
-command-line option sets a configuration variable named after
-its long option name, and these variables are placed in the
-environment of the script before it is loaded. Variables
-for options that may be repeated have list values. Other
-variables can be set using name=value on the command line.
-After the script is loaded, option values that were not set
-on the command line are replaced by the values set in the script.
-
-=item B<-F=FILE>, B<--config=FILE>
-
-Use the given SXP formatted configuration script.
-SXP is the underlying configuration format used by Xen.
-SXP configuration scripts can be hand-written or generated
-from Python configuration scripts, using the -n
-(dryrun) option to print the configuration. An SXP formatted
-configuration file may also be generated for a given I<domain-id> by
-redirecting the output from the the B<xm list --long I<domain-id>>
-to a file.
-
-=item B<-n>, B<--dryrun>
-
-Dry run - prints the resulting configuration in SXP
-but does not create the domain.
-
-=item B<-x>, B<--xmldryrun>
-
-XML dry run - prints the resulting configuration in
-XML but does not create the domain.
-
-=item B<-s>, B<--skipdtd>
-
-Skip DTD checking - skips checks on XML before
-creating. Experimental. Can decrease create time.
-
-=item B<-p>, B<--paused>
-
-Leave the domain paused after it is created.
-
-=item B<-c>, B<--console_autoconnect>
-
-Attach console to the domain as soon as it has started. This is
-useful for determining issues with crashing domains.
-
-=back
-
-B<EXAMPLES>
-
-=over 4
-
-=item I<with config file>
-
- xm create Fedora4
-
-This creates a domain with the file /etc/xen/Fedora4, and returns as
-soon as it is run.
-
-=item I<without config file>
-
- xm create /dev/null ramdisk=initrd.img \
- kernel=/boot/vmlinuz-2.6.12.6-xenU \
- name=ramdisk vif='' vcpus=1 \
- memory=64 root=/dev/ram0
-
-This creates the domain without using a config file (more specifically
-using /dev/null as an empty config file), kernel and ramdisk as
-specified, setting the name of the domain to "ramdisk", also disabling
-virtual networking. (This example comes from the xm-test test suite.)
-
-=back
-
-=item B<delete>
-
-Remove a domain from Xend domain management. The B<xm list> command
-shows the domain names.
-
-=item B<destroy> I<domain-id>
-
-Immediately terminate the domain I<domain-id>. This doesn't give the
-domain OS any chance to react, and is the equivalent of ripping the
-power cord out on a physical machine. In most cases you will want to
-use the B<shutdown> command instead.
-
-=item B<domid> I<domain-name>
-
-Converts a domain name to a domain id using xend's internal mapping.
-
-=item B<domname> I<domain-id>
-
-Converts a domain id to a domain name using xend's internal mapping.
-
-=item B<dump-core> [I<OPTIONS>] I<domain-id> [I<filename>]
-
-Dumps the virtual machine's memory for the specified domain to the
-I<filename> specified. The dump file will be written to a distribution
-specific directory for dump files. Such as: /var/lib/xen/dump or
-/var/xen/dump Defaults to dumping the core without pausing the domain
-if no I<OPTIONS> are specified.
-
-B<OPTIONS>
-
-=over 4
-
-=item B<-L>, B<--live>
-
-Dump core without pausing the domain.
-
-=item B<-C>, B<--crash>
-
-Crash domain after dumping core.
-
-=back
-
-=item B<help> [B<--long>]
-
-Displays the short help message (i.e. common commands).
-
-The B<--long> option prints out the complete set of B<xm> subcommands,
-grouped by function.
-
-=item B<list> [I<OPTIONS>] [I<domain-id> ...]
-
-Prints information about one or more domains. If no domains are
-specified it prints out information about all domains.
-
-
-B<OPTIONS>
-
-=over 4
-
-=item B<-l>, B<--long>
-
-The output for B<xm list> is not the table view shown below, but
-instead presents the data in SXP format.
-
-=item B<--label>
-
-Security labels are added to the output of xm list and the lines
-are sorted by the labels (ignoring case).
-See the ACCESS CONTROL SUBCOMMAND section of this man page for more
-information about labels.
-
-=item B<--state=<state>>
-
-Output information for VMs in the specified state.
-
-=back
-
-B<EXAMPLE>
-
-An example format for the list is as follows:
-
- Name ID Mem(MiB) VCPUs State Time(s)
- Domain-0 0 98 1 r----- 5068.6
- Fedora3 164 128 1 r----- 7.6
- Fedora4 165 128 1 ------ 0.6
- Mandrake2006 166 128 1 -b---- 3.6
- Mandrake10.2 167 128 1 ------ 2.5
- Suse9.2 168 100 1 ------ 1.8
-
-Name is the name of the domain. ID the numeric domain id. Mem is the
-desired amount of memory to allocate to the domain (although it may
-not be the currently allocated amount). VCPUs is the number of
-virtual CPUs allocated to the domain. State is the run state (see
-below). Time is the total run time of the domain as accounted for by
-Xen.
-
-B<STATES>
-
-The State field lists 6 states for a Xen domain, and which ones the
-current domain is in.
-
-=over 4
-
-=item B<r - running>
-
-The domain is currently running on a CPU.
-
-=item B<b - blocked>
-
-The domain is blocked, and not running or runnable. This can be caused
-because the domain is waiting on IO (a traditional wait state) or has
-gone to sleep because there was nothing else for it to do.
-
-=item B<p - paused>
-
-The domain has been paused, usually occurring through the administrator
-running B<xm pause>. When in a paused state the domain will still
-consume allocated resources like memory, but will not be eligible for
-scheduling by the Xen hypervisor.
-
-=item B<s - shutdown>
-
-FIXME: Why would you ever see this state?
-
-=item B<c - crashed>
-
-The domain has crashed, which is always a violent ending. Usually
-this state can only occur if the domain has been configured not to
-restart on crash. See L<xmdomain.cfg> for more info.
-
-=item B<d - dying>
-
-The domain is in process of dying, but hasn't completely shutdown or
-crashed.
-
-FIXME: Is this right?
-
-=back
-
-B<NOTES>
-
-=over 4
-
-The Time column is deceptive. Virtual IO (network and block devices)
-used by domains requires coordination by Domain0, which means that
-Domain0 is actually charged for much of the time that a DomainU is
-doing IO. Use of this time value to determine relative utilizations
-by domains is thus very suspect, as a high IO workload may show as
-less utilized than a high CPU workload. Consider yourself warned.
-
-=back
-
-=item B<mem-max> I<domain-id> I<mem>
-
-Specify the maximum amount of memory the domain is able to use. I<mem>
-is specified in megabytes.
-
-The mem-max value may not correspond to the actual memory used in the
-domain, as it may balloon down its memory to give more back to the OS.
-
-=item B<mem-set> I<domain-id> I<mem>
-
-Set the domain's used memory using the balloon driver.
-
-Because this operation requires cooperation from the domain operating
-system, there is no guarantee that it will succeed. This command will
-definitely not work unless the domain has the required paravirt
-driver.
-
-B<Warning:> There is no good way to know in advance how small of a
-mem-set will make a domain unstable and cause it to crash. Be very
-careful when using this command on running domains.
-
-=item B<migrate> I<domain-id> I<host> [I<OPTIONS>]
-
-Migrate a domain to another host machine. Xend must be running on
-other host machine, it must be running the same version of Xen, it
-must have the migration TCP port open and accepting connections from
-the source host, and there must be sufficient resources for the domain
-to run (memory, disk, etc).
-
-Migration is pretty complicated, and has many security implications.
-Please read the Xen User's Guide to ensure you understand the
-ramifications and limitations on migration before attempting it in
-production.
-
-B<OPTIONS>
-
-=over 4
-
-=item B<-l>, B<--live>
-
-Use live migration. This will migrate the domain between hosts
-without shutting down the domain. See the Xen User's Guide for more
-information.
-
-=item B<-r>, B<--resource> I<Mbs>
-
-Set maximum Mbs allowed for migrating the domain. This ensures that
-the network link is not saturated with migration traffic while
-attempting to do other useful work.
-
-=back
-
-=item B<new> I<configfile> [I<OPTIONS>] [I<vars>]...
-
-Adds a domain to Xend domain management.
-
-The new subcommand requires a config file and can optionally
-take a series of I<vars> that add to or override variables
-defined in the config file. See xmdomain.cfg for full details of that
-file format, and possible options used in either the configfile or for
-I<vars>.
-
-I<configfile> can either be an absolute path to a file, or a relative
-path to a file located in /etc/xen.
-
-The new subcommand will return without starting the domain. The
-domain needs to be started using the B<xm start> command.
-
-B<OPTIONS>
-
-=over 4
-
-=item B<--help_config>
-
-Print the available configuration variables I<vars>. These variables may be
-used on the command line or in the configuration file I<configfile>.
-
-=item B<-q>, B<--quiet>
-
-No console output.
-
-=item B<--path>
-
-Search path for configuration scripts. The value of PATH is a
-colon-separated directory list.
-
-=item B<-f=FILE>, B<--defconfig=FILE>
-
-
-Use the given Python configuration script. The configuration
-script is loaded after arguments have been processed. Each
-command-line option sets a configuration variable named after
-its long option name, and these variables are placed in the
-environment of the script before it is loaded. Variables
-for options that may be repeated have list values. Other
-variables can be set using name=value on the command line.
-After the script is loaded, option values that were not set
-on the command line are replaced by the values set in the script.
-
-=item B<-F=FILE>, B<--config=FILE>
-
-Use the given SXP formatted configuration script.
-SXP is the underlying configuration format used by Xen.
-SXP configuration scripts can be hand-written or generated
-from Python configuration scripts, using the -n
-(dryrun) option to print the configuration. An SXP formatted
-configuration file may also be generated for a given I<domain-id> by
-redirecting the output from the the B<xm list --long I<domain-id>>
-to a file.
-
-=item B<-n>, B<--dryrun>
-
-Dry run - prints the resulting configuration in SXP
-but does not create the domain.
-
-=item B<-x>, B<--xmldryrun>
-
-XML dry run - prints the resulting configuration in
-XML but does not create the domain.
-
-=item B<-s>, B<--skipdtd>
-
-Skip DTD checking - skips checks on XML before
-creating. Experimental. Can decrease create time.
-
-=item B<-p>, B<--paused>
-
-Leave the domain paused after it is created.
-
-=item B<-c>, B<--console_autoconnect>
-
-Attach console to the domain as soon as it has started. This is
-useful for determining issues with crashing domains.
-
-=back
-
-=item B<pause> I<domain-id>
-
-Pause a domain. When in a paused state the domain will still consume
-allocated resources such as memory, but will not be eligible for
-scheduling by the Xen hypervisor.
-
-=item B<reboot> [I<OPTIONS>] I<domain-id>
-
-Reboot a domain. This acts just as if the domain had the B<reboot>
-command run from the console. The command returns as soon as it has
-executed the reboot action, which may be significantly before the
-domain actually reboots.
-
-The behavior of what happens to a domain when it reboots is set by the
-B<on_reboot> parameter of the xmdomain.cfg file when the domain was
-created.
-
-B<OPTIONS>
-
-=over 4
-
-=item B<-a>, B<--all>
-
-Reboot all domains.
-
-=item B<-w>, B<--wait>
-
-Wait for reboot to complete before returning. This may take a while,
-as all services in the domain will have to be shut down cleanly.
-
-=back
-
-=item B<restore> I<state-file>
-
-Build a domain from an B<xm save> state file. See B<save> for more info.
-
-=item B<resume> I<domain-name> [I<OPTIONS>]
-
-Moves a domain out of the suspended state and back into memory.
-
-B<OPTIONS>
-
-=over 4
-
-=item B<-p>, <--paused>
-
-Moves a domain back into memory but leaves the domain in a paused state.
-The B<xm unpause> subcommand may then be used to bring it out of the
-paused state.
-
-=back
-
-=item B<save> I<domain-id> I<state-file>
-
-Saves a running domain to a state file so that it can be restored
-later. Once saved, the domain will no longer be running on the
-system, thus the memory allocated for the domain will be free for
-other domains to use. B<xm restore> restores from this state file.
-
-This is roughly equivalent to doing a hibernate on a running computer,
-with all the same limitations. Open network connections may be
-severed upon restore, as TCP timeouts may have expired.
-
-=item B<shutdown> [I<OPTIONS>] I<domain-id>
-
-Gracefully shuts down a domain. This coordinates with the domain OS
-to perform graceful shutdown, so there is no guarantee that it will
-succeed, and may take a variable length of time depending on what
-services must be shutdown in the domain. The command returns
-immediately after signally the domain unless that B<-w> flag is used.
-
-The behavior of what happens to a domain when it reboots is set by the
-B<on_shutdown> parameter of the xmdomain.cfg file when the domain was
-created.
-
-B<OPTIONS>
-
-=over 4
-
-=item B<-a>
-
-Shutdown B<all> domains. Often used when doing a complete shutdown of
-a Xen system.
-
-=item B<-w>
-
-Wait for the domain to complete shutdown before returning.
-
-=back
-
-=item B<start> I<domain-name> [I<OPTIONS>]
-
-Start a Xend managed domain that was added using the B<xm new> command.
-
-
-B<OPTIONS>
-
-=over 4
-
-=item B<-p>, B<--paused>
-
-Do not unpause domain after starting it.
-
-=item B<-c>, B<--console_autoconnect>
-
-Connect to the console after the domain is created.
-
-=back
-
-=item B<suspend> I<domain-name>
-
-Suspend a domain to a state file so that it can be later
-resumed using the B<xm resume> subcommand. Similar to the B<xm save>
-subcommand although the state file may not be specified.
-
-=item B<sysrq> I<domain-id> I<letter>
-
-Send a I<Magic System Request> signal to the domain. For more
-information on available magic sys req operations, see sysrq.txt in
-your Linux Kernel sources.
-
-=item B<unpause> I<domain-id>
-
-Moves a domain out of the paused state. This will allow a previously
-paused domain to now be eligible for scheduling by the Xen hypervisor.
-
-=item B<vcpu-set> I<domain-id> I<vcpu-count>
-
-Enables the I<vcpu-count> virtual CPUs for the domain in question.
-Like mem-set, this command can only allocate up to the maximum virtual
-CPU count configured at boot for the domain.
-
-If the I<vcpu-count> is smaller than the current number of active
-VCPUs, the highest number VCPUs will be hotplug removed. This may be
-important for pinning purposes.
-
-Attempting to set the VCPUs to a number larger than the initially
-configured VCPU count is an error. Trying to set VCPUs to < 1 will be
-quietly ignored.
-
-Because this operation requires cooperation from the domain operating
-system, there is no guarantee that it will succeed. This command will
-not work with a full virt domain.
-
-=item B<vcpu-list> [I<domain-id>]
-
-Lists VCPU information for a specific domain. If no domain is
-specified, VCPU information for all domains will be provided.
-
-=item B<vcpu-pin> I<domain-id> I<vcpu> I<cpus>
-
-Pins the the VCPU to only run on the specific CPUs. The keyword
-B<all> can be used to apply the I<cpus> list to all VCPUs in the
-domain.
-
-Normally VCPUs can float between available CPUs whenever Xen deems a
-different run state is appropriate. Pinning can be used to restrict
-this, by ensuring certain VCPUs can only run on certain physical
-CPUs.
-
-=back
-
-=head1 XEN HOST SUBCOMMANDS
-
-=over 4
-
-=item B<dmesg> [B<-c>]
-
-Reads the Xen message buffer, similar to dmesg on a Linux system. The
-buffer contains informational, warning, and error messages created
-during Xen's boot process. If you are having problems with Xen, this
-is one of the first places to look as part of problem determination.
-
-B<OPTIONS>
-
-=over 4
-
-=item B<-c>, B<--clear>
-
-Clears Xen's message buffer.
-
-=back
-
-=item B<info>
-
-Print information about the Xen host in I<name : value> format. When
-reporting a Xen bug, please provide this information as part of the
-bug report.
-
-Sample output looks as follows (lines wrapped manually to make the man
-page more readable):
-
- host : talon
- release : 2.6.12.6-xen0
- version : #1 Mon Nov 14 14:26:26 EST 2005
- machine : i686
- nr_cpus : 2
- nr_nodes : 1
- cores_per_socket : 1
- threads_per_core : 1
- cpu_mhz : 696
- hw_caps : 0383fbff:00000000:00000000:00000040
- total_memory : 767
- free_memory : 37
- xen_major : 3
- xen_minor : 0
- xen_extra : -devel
- xen_caps : xen-3.0-x86_32
- xen_scheduler : credit
- xen_pagesize : 4096
- platform_params : virt_start=0xfc000000
- xen_changeset : Mon Nov 14 18:13:38 2005 +0100
- 7793:090e44133d40
- cc_compiler : gcc version 3.4.3 (Mandrakelinux
- 10.2 3.4.3-7mdk)
- cc_compile_by : sdague
- cc_compile_domain : (none)
- cc_compile_date : Mon Nov 14 14:16:48 EST 2005
- xend_config_format : 3
-
-B<FIELDS>
-
-Not all fields will be explained here, but some of the less obvious
-ones deserve explanation:
-
-=over 4
-
-=item B<hw_caps>
-
-A vector showing what hardware capabilities are supported by your
-processor. This is equivalent to, though more cryptic, the flags
-field in /proc/cpuinfo on a normal Linux machine.
-
-=item B<free_memory>
-
-Available memory (in MB) not allocated to Xen, or any other domains.
-
-=item B<xen_caps>
-
-The Xen version and architecture. Architecture values can be one of:
-x86_32, x86_32p (i.e. PAE enabled), x86_64, ia64.
-
-=item B<xen_changeset>
-
-The Xen mercurial changeset id. Very useful for determining exactly
-what version of code your Xen system was built from.
-
-=back
-
-=item B<log>
-
-Print out the xend log. This log file can be found in
-/var/log/xend.log.
-
-=item B<top>
-
-Executes the B<xentop> command, which provides real time monitoring of
-domains. Xentop is a curses interface, and reasonably self
-explanatory.
-
-=item B<uptime>
-
-Prints the current uptime of the domains running.
-
-=back
-
-=head1 SCHEDULER SUBCOMMANDS
-
-Xen ships with a number of domain schedulers, which can be set at boot
-time with the B<sched=> parameter on the Xen command line. By
-default B<credit> is used for scheduling.
-
-FIXME: we really need a scheduler expert to write up this section.
-
-=over 4
-
-=item B<sched-credit> [ B<-d> I<domain-id> [ B<-w>[B<=>I<WEIGHT>] | B<-c>[B<=>I<CAP>] ] ]
-
-Set credit scheduler parameters. The credit scheduler is a
-proportional fair share CPU scheduler built from the ground up to be
-work conserving on SMP hosts.
-
-Each domain (including Domain0) is assigned a weight and a cap.
-
-B<PARAMETERS>
-
-=over 4
-
-=item I<WEIGHT>
-
-A domain with a weight of 512 will get twice as much CPU as a domain
-with a weight of 256 on a contended host. Legal weights range from 1
-to 65535 and the default is 256.
-
-=item I<CAP>
-
-The cap optionally fixes the maximum amount of CPU a domain will be
-able to consume, even if the host system has idle CPU cycles. The cap
-is expressed in percentage of one physical CPU: 100 is 1 physical CPU,
-50 is half a CPU, 400 is 4 CPUs, etc. The default, 0, means there is
-no upper cap.
-
-NB: Many systems have features that will scale down the computing
-power of a cpu that is not 100% utilized. This can be in the
-operating system, but can also sometimes be below the operating system
-in the BIOS. If you set a cap such that individual cores are running
-at less than 100%, this may have an impact on the performance of your
-workload over and above the impact of the cap. For example, if your
-processor runs at 2GHz, and you cap a vm at 50%, the power management
-system may also reduce the clock speed to 1GHz; the effect will be
-that your VM gets 25% of the available power (50% of 1GHz) rather than
-50% (50% of 2GHz). If you are not getting the performance you expect,
-look at performance and cpufreq options in your operating system and
-your BIOS.
-
-=back
-
-=item B<sched-sedf> I<period> I<slice> I<latency-hint> I<extratime> I<weight>
-
-Set Simple EDF (Earliest Deadline First) scheduler parameters. This
-scheduler provides weighted CPU sharing in an intuitive way and uses
-realtime-algorithms to ensure time guarantees. For more information
-see docs/misc/sedf_scheduler_mini-HOWTO.txt in the Xen distribution.
-
-B<PARAMETERS>
-
-=over 4
-
-=item I<period>
-
-The normal EDF scheduling usage in nanoseconds
-
-=item I<slice>
-
-The normal EDF scheduling usage in nanoseconds
-
-FIXME: these are lame, should explain more.
-
-=item I<latency-hint>
-
-Scaled period if domain is doing heavy I/O.
-
-=item I<extratime>
-
-Flag for allowing domain to run in extra time.
-
-=item I<weight>
-
-Another way of setting CPU slice.
-
-=back
-
-B<EXAMPLES>
-
-I<normal EDF (20ms/5ms):>
-
- xm sched-sedf <dom-id> 20000000 5000000 0 0 0
-
-I<best-effort domains (i.e. non-realtime):>
-
- xm sched-sedf <dom-id> 20000000 0 0 1 0
-
-I<normal EDF (20ms/5ms) + share of extra-time:>
-
- xm sched-sedf <dom-id> 20000000 5000000 0 1 0
-
-I<4 domains with weights 2:3:4:2>
-
- xm sched-sedf <d1> 0 0 0 0 2
- xm sched-sedf <d2> 0 0 0 0 3
- xm sched-sedf <d3> 0 0 0 0 4
- xm sched-sedf <d4> 0 0 0 0 2
-
-I<1 fully-specified (10ms/3ms) domain, 3 other domains share available
-rest in 2:7:3 ratio:>
-
- xm sched-sedf <d1> 10000000 3000000 0 0 0
- xm sched-sedf <d2> 0 0 0 0 2
- xm sched-sedf <d3> 0 0 0 0 7
- xm sched-sedf <d4> 0 0 0 0 3
-
-=back
-
-=head1 VIRTUAL DEVICE COMMANDS
-
-Most virtual devices can be added and removed while guests are
-running. The effect to the guest OS is much the same as any hotplug
-event.
-
-=head2 BLOCK DEVICES
-
-=over 4
-
-=item B<block-attach> I<domain-id> I<be-dev> I<fe-dev> I<mode> [I<bedomain-id>]
-
-Create a new virtual block device. This will trigger a hotplug event
-for the guest.
-
-B<OPTIONS>
-
-=over 4
-
-=item I<domain-id>
-
-The domain id of the guest domain that the device will be attached to.
-
-=item I<be-dev>
-
-The device in the backend domain (usually domain 0) to be exported.
-This can be specified as a physical partition (phy:sda7) or as a file
-mounted as loopback (file://path/to/loop.iso).
-
-=item I<fe-dev>
-
-How the device should be presented to the guest domain. It can be
-specified as either a symbolic name, such as /dev/hdc, for common
-devices, or by device id, such as 0x1400 (/dev/hdc device id in hex).
-
-=item I<mode>
-
-The access mode for the device from the guest domain. Supported modes
-are B<w> (read/write) or B<r> (read-only).
-
-=item I<bedomain-id>
-
-The back end domain hosting the device. This defaults to domain 0.
-
-=back
-
-B<EXAMPLES>
-
-=over 4
-
-=item I<Mount an ISO as a Disk>
-
-xm block-attach guestdomain file://path/to/dsl-2.0RC2.iso /dev/hdc r
-
-This will mount the dsl ISO as /dev/hdc in the guestdomain as a read
-only device. This will probably not be detected as a CD-ROM by the
-guest, but mounting /dev/hdc manually will work.
-
-=back
-
-=item B<block-detach> I<domain-id> I<devid> [B<--force>]
-
-Detach a domain's virtual block device. I<devid> may be the symbolic
-name or the numeric device id given to the device by domain 0. You
-will need to run B<xm block-list> to determine that number.
-
-Detaching the device requires the cooperation of the domain. If the
-domain fails to release the device (perhaps because the domain is hung
-or is still using the device), the detach will fail. The B<--force>
-parameter will forcefully detach the device, but may cause IO errors
-in the domain.
-
-=item B<block-list> [B<-l>|B<--long>] I<domain-id>
-
-List virtual block devices for a domain. The returned output is
-formatted as a list or as an S-Expression if the B<--long> option was given.
-
-=back
-
-=head2 NETWORK DEVICES
-
-=over 4
-
-=item B<network-attach> I<domain-id> [B<script=>I<scriptname>] [B<ip=>I<ipaddr>]
-[B<mac=>I<macaddr>] [B<bridge=>I<bridge-name>] [B<backend=>I<bedomain-id>]
-
-Creates a new network device in the domain specified by I<domain-id>. It
-takes the following optional options:
-
-=back
-
-B<OPTIONS>
-
-=over 4
-
-=item B<script=>I<scriptname>
-
-Use the specified script name to bring up the network. Defaults to
-the default setting in xend-config.sxp for B<vif-script>.
-
-=item B<ip=>I<ipaddr>
-
-Passes the specified IP Address to the adapter on creation.
-
-FIXME: this currently appears to be B<broken>. I'm not sure under what
-circumstances this should actually work.
-
-=item B<mac=>I<macaddr>
-
-The MAC address that the domain will see on its Ethernet device. If
-the device is not specified it will be randomly generated with the
-00:16:3e vendor id prefix.
-
-=item B<bridge=>I<bridge-name>
-
-The name of the bridge to attach the vif to, in case you have more
-than one. This defaults to xenbr0.
-
-=item B<backend=>I<bedomain-id>
-
-The backend domain id. By default this is domain 0.
-
-=back
-
-=over 4
-
-=item B<network-detach> I<domain-id> I<devid>
-
-Removes the network device from the domain specified by I<domain-id>.
-I<devid> is the virtual interface device number within the domain
-(i.e. the 3 in vif22.3).
-
-FIXME: this is currently B<broken>. Network devices aren't completely
-removed from domain 0.
-
-=item B<network-list> [B<-l>|B<--long>]> I<domain-id>
-
-List virtual network interfaces for a domain. The returned output is
-formatted as a list or as an S-Expression if the B<--long> option was given.
-
-=back
-
-=head1 SEE ALSO
-
-B<xmdomain.cfg>(5), B<xentop>(1)
-
-=head1 AUTHOR
-
- Sean Dague <sean at dague dot net>
- Daniel Stekloff <dsteklof at us dot ibm dot com>
- Reiner Sailer <sailer at us dot ibm dot com>
- Stefan Berger <stefanb at us dot ibm dot com>
-
-=head1 BUGS
diff --git a/docs/man/xmdomain.cfg.pod.5 b/docs/man/xmdomain.cfg.pod.5
deleted file mode 100644
index 2e73db4..0000000
--- a/docs/man/xmdomain.cfg.pod.5
+++ /dev/null
@@ -1,358 +0,0 @@
-=head1 NAME
-
-xmdomain.cfg - xm domain config file format
-
-=head1 SYNOPSIS
-
- /etc/xen/myxendomain
- /etc/xen/myxendomain2
- /etc/xen/auto/myxenautostarted
-
-=head1 DESCRIPTION
-
-The B<xm>(1) program uses python executable config files to define
-domains to create from scratch. Each of these config files needs to
-contain a number of required options, and may specify many more.
-
-Domain configuration files live in /etc/xen by default, if you store
-config files anywhere else the full path to the config file must be
-specified in the I<xm create> command.
-
-/etc/xen/auto is a special case. Domain config files in that
-directory will be started automatically at system boot if the
-xendomain init script is enabled. The contents of /etc/xen/auto
-should be symlinks to files in /etc/xen to allow I<xm create> to be
-used without full paths.
-
-Options are specified by I<name = value> statements in the
-xmdomain.cfg files.
-
-=head1 OPTIONS
-
-The following lists the most commonly used options for a domain config
-file.
-
-=over 4
-
-=item B<kernel>
-
-The kernel image for the domain. The format of the parameter is the
-fully qualified path to the kernel image file,
-i.e. I</boot/vmlinuz-2.6.12-xenU>.
-
-
-=item B<ramdisk>
-
-The initial ramdisk for the domain. The format of the parameter is
-the fully qualified path to the initrd, i.e. I</boot/initrd.gz>. On
-many Linux distros you will not need a ramdisk if using the default
-xen kernel.
-
-=item B<memory>
-
-The amount of RAM, in megabytes, to allocate to the domain when it
-starts. Allocating insufficient memory for a domain may produce
-extremely bizarre behavior. If there isn't enough free memory left on
-the machine to fulfil this request, the domain will fail to start.
-
-Xen does not support overcommit of memory, so the total memory of all
-guests (+ 64 MB needed for Xen) must be less than or equal to the
-physical RAM in the machine.
-
-=item B<name>
-
-A unique name for the domain. Attempting to create two domains with
-the same name will cause an error.
-
-=item B<root>
-
-Specifies the root device for the domain. This is required for Linux
-domains, and possibly other OSes.
-
-=item B<nics>
-
-The number of network interfaces allocated to the domain on boot. It
-defaults to 1.
-
-=item B<disk>
-
-An array of block device stanzas, in the form:
-
- disk = [ "stanza1", "stanza2", ... ]
-
-Each stanza has 3 terms, separated by commas,
-"backend-dev,frontend-dev,mode".
-
-=over 4
-
-=item I<backend-dev>
-
-The device in the backend domain that will be exported to the guest
-(frontend) domain. Supported formats include:
-
-I<phy:device> - export the physical device listed. The device can be
-in symbolic form, as in sda7, or as the hex major/minor number, as in
-0x301 (which is hda1).
-
-I<file://path/to/file> - export the file listed as a loopback device.
-This will take care of the loopback setup before exporting the device.
-
-=item I<frontend-dev>
-
-How the device should appear in the guest domain. The device can be
-in symbolic form, as in sda7, or as the hex major/minor number, as in
-0x301 (which is hda1).
-
-=item I<mode>
-
-The access mode for the device. There are currently 2 valid options,
-I<r> (read-only), I<w> (read/write).
-
-=back
-
-=item B<vif>
-
-An array of virtual interface stanzas in the form:
-
- vif = [ "stanza1", "stanza2", ... ]
-
-Each stanza specifies a set of I<name = value> options separated by
-commas, in the form: "name1=value1, name2=value2, ..."
-
-B<OPTIONS>
-
-=over 4
-
-=item I<bridge>
-
-The network bridge to be used for this device. This is especially
-needed if multiple bridges exist on the machine.
-
-=item I<mac>
-
-The MAC address for the virtual interface. If mac is not specified,
-one will be randomly chosen by xen with the 00:16:3e vendor id prefix.
-
-=back
-
-=item B<vfb>
-
-A virtual frame buffer stanza in the form:
-
- vfb = [ "stanza" ]
-
-The stanza specifies a set of I<name = value> options separated by
-commas, in the form: "name1=value1, name2=value2, ..."
-
-B<OPTIONS>
-
-=over 4
-
-=item I<type>
-
-There are currently two valid options: I<vnc> starts a VNC server that
-lets you connect an external VNC viewer, and I<sdl> starts an internal
-viewer.
-
-=item I<vncdisplay>
-
-The VNC display number to use, defaults to the domain ID. The
-VNC server listens on port 5900 + display number.
-
-=item I<vnclisten>
-
-The listening address for the VNC server, default 127.0.0.1.
-
-=item I<vncunused>
-
-If non-zero, the VNC server listens on the first unused port above
-5900.
-
-=item I<vncpasswd>
-
-Overrides the XenD configured default password.
-
-=item I<display>
-
-Display to use for the internal viewer, defaults to environment
-variable I<DISPLAY>.
-
-=item I<xauthority>
-
-Authority file to use for the internal viewer, defaults to environment
-variable I<XAUTHORITY>.
-
-=back
-
-=back
-
-=head1 ADDITIONAL OPTIONS
-
-The following options are also supported in the config file, though
-are far more rarely used.
-
-=over 4
-
-=item B<builder>
-
-Which builder should be used to construct the domain. This defaults
-to the I<linux> if not specified, which is the builder for
-paravirtualized Linux domains.
-
-=item B<cpu>
-
-Specifies which CPU the domain should be started on, where 0 specifies
-the first cpu, 1 the second, and so on. This defaults to -1, which
-means Xen is free to pick which CPU to start on.
-
-=item B<cpus>
-
-Specifies a list of CPUs on which the domains' VCPUs are allowed to
-execute upon. The syntax supports ranges (0-3), and negation, ^1.
-For instance:
-
- cpus = "0-3,5,^1"
-
-Will result in CPUs 0, 2, 3, 5 being available for use by the domain.
-
-=item B<extra>
-
-Extra information to append to the end of the kernel parameter line.
-The format is a string, the contents of which can be anything that the
-kernel supports. For instance:
-
- extra = "4"
-
-Will cause the domain to boot to runlevel 4.
-
-=item B<nfs_server>
-
-The IP address of the NFS server to use as the root device for the
-domain. In order to do this you'll need to specify I<root=/dev/nfs>,
-and specify I<nfs_root>.
-
-=item B<nfs_root>
-
-The directory on the NFS server to be used as the root filesystem.
-Specified as a fully qualified path, i.e. I</full/path/to/root/dir>.
-
-=item B<vcpus>
-
-The number of virtual cpus to allocate to the domain. In order to use
-this the xen kernel must be compiled with SMP support.
-
-This defaults to 1, meaning running the domain as a UP.
-
-=back
-
-=head1 DOMAIN SHUTDOWN OPTIONS
-
-There are 3 options which control domain shutdown (both planned and
-unplanned) under certain events. The 3 events currently captured are:
-
-=over 4
-
-=item B<on_shutdown>
-
-Triggered on either an I<xm shutdown> or graceful shutdown from inside
-the DomU.
-
-=item B<on_reboot>
-
-Triggered on either an I<xm reboot> or graceful reboot from inside the
-DomU.
-
-=item B<on_crash>
-
-Triggered when a DomU goes to the crashed state for any reason.
-
-=back
-
-All of them take one of 4 valid states listed below.
-
-=over 4
-
-=item B<destroy>
-
-The domain will be cleaned up completely. No attempt at respawning
-will occur. This is what a typical shutdown would look like.
-
-=item B<restart>
-
-The domain will be restarted with the same name as the old domain.
-This is what a typical reboot would look like.
-
-=item B<preserve>
-
-The domain will not be cleaned up at all. This is often useful for
-crash state domains which ensures that enough evidence is to debug the
-real issue.
-
-=item B<rename-restart>
-
-The old domain will not be cleaned up, but will be renamed so a new
-domain can be restarted in it's place. The old domain will be renamed with
-a suffix -1, -2, etc, and assigned a new random UUID; the new domain will
-keep the original name and UUID. The old domain will release the devices that
-it holds, so that the new one may take them.
-
-=back
-
-Additionally, the "on_crash" event can also take:
-
-=over 4
-
-=item B<coredump-destroy>
-
-Dump the crashed domain's core and then destroy it.
-
-=item B<coredump-restart>
-
-Dump the crashed domain's core and then restart it.
-
-=back
-
-=head1 EXAMPLES
-
-The following are quick examples of ways that domains might be
-configured. They should not be considered an exhaustive set.
-
-=over 4
-
-=item I<A Loopback File as Root>
-
- kernel = "/boot/vmlinuz-2.6-xenU"
- memory = 128
- name = "MyLinux"
- root = "/dev/hda1 ro"
- disk = [ "file:/var/xen/mylinux.img,hda1,w" ]
-
-This creates a domain called MyLinux with 128 MB of memory using a
-default xen kernel, and the file /var/xen/mylinux.img loopback mounted
-at hda1, which is the root filesystem.
-
-=item I<NFS Root>
-
-FIXME: write me
-
-=item I<LVM Root>
-
-FIXME: write me
-
-=item I<Two Networks>
-
-FIXME: write me
-
-=back
-
-=head1 SEE ALSO
-
-B<xm>(1)
-
-=head1 AUTHOR
-
- Sean Dague <sean at dague dot net>
-
-=head1 BUGS
-
-Not all options are currently documented
diff --git a/docs/misc/amd-ucode-container.txt b/docs/misc/amd-ucode-container.txt
new file mode 100644
index 0000000..1db6466
--- /dev/null
+++ b/docs/misc/amd-ucode-container.txt
@@ -0,0 +1,90 @@
+-------------------------------------------------
+AMD Microcode Container File format
+-------------------------------------------------
+Author:
+ Aravind [dot] Gopalakrishnan [at] amd [dot] com
+Initial version:
+ July 2014
+Updated:
+ October 2014
+-------------------------------------------------
+
+Intro to AMD Container Files:
+-----------------------------
+
+* AMD provides microcode patch support for processors belonging to AMD
+ processor families 10h, 11h, 12h, 14h, and 15h.
+* There is one single file (container file) containing all microcode patches
+ for AMD families 10h - 14h processors. [microcode_amd.bin]
+* For AMD processor families 15h and later, there is a separate container file
+ for each family. (e.g. microcode_amd_fam15h.bin)
+* Microcode patches are not incremental, therefore you only need to make
+ sure you have the latest container file for your AMD processor family.
+* One can find the latest AMD microcode containers from [1], [2]
+
+Mutual Exclusivity Rule of AMD containers:
+* The patches for families 10h - 14h are guaranteed to be only on
+ microcode_amd.bin
+* Similarly, patches for family 15h and later will only be on their respective
+ family specific container file. (e.g. microcode_amd_fam15h.bin)
+* This is because, the processes and scripts used to create container files
+ ensure that there is no mix-up
+
+Microcode patch header structure:
+---------------------------------
+struct __packed microcode_header_amd {
+ uint32_t data_code;
+ uint32_t patch_id;
+ uint8_t mc_patch_data_id[2];
+ uint8_t mc_patch_data_len;
+ uint8_t init_flag;
+ uint32_t mc_patch_data_checksum;
+ uint32_t nb_dev_id;
+ uint32_t sb_dev_id;
+ uint16_t processor_rev_id;
+ uint8_t nb_rev_id;
+ uint8_t sb_rev_id;
+ uint8_t bios_api_rev;
+ uint8_t reserved1[3];
+ uint32_t match_reg[8];
+}
+More details about microcode patch header are typically not exposed to public.
+
+Apply microcode updates using initrd:
+-------------------------------------
+Initrd images can be modified to contain AMD microcode containers in cpio
+format at the start of the image.
+
+Following example shows how to generate a combined initrd
+Note: initrd-<val> could be different on your machine. Substitute accordingly
+Example System base: Ubuntu 13.04 with 3.8.0-30-generic kernel
+
+1. mkdir initrd-for-xen-with_append
+2. cd initrd-for-xen-with_append
+3. mkdir -p kernel/x86/microcode
+4. cat /lib/firmware/amd-ucode/microcode_amd.bin \
+ /lib/firmware/amd-ucode/microcode_amd_fam15h.bin > \
+ kernel/x86/microcode/AuthenticAMD.bin
+5. find . | cpio -o -H newc > ucode.cpio
+6. cat ucode.cpio /boot/initrd.img-3.8.0-30-generic > /boot/initrd_for_xen_with_ucode
+7. On grub.cfg, provide the above initrd name as module.
+8. Use 'ucode=scan' option as Xen boot parameter.
+
+Misc Notes:
+-----------
+It is not recommended to concatenate two(or more) container files of
+the same kind. (e.g. two microcode_amd_fam15h.bin) since the hypervisor
+will apply a patch as and when it determines that it is a 'good fit'.
+Once the patch is applied, further parsing of the file is skipped.
+Therefore, if a subsequent container file has a newer/updated patch, that
+patch will be ignored.
+
+In cases where users are not sure about provenance of containers
+they should obtain a "good" set by downloading them from source links
+[1], [2] since it's not guaranteed that the latest patch will be applied.
+
+Reference(s):
+-------------
+[1] http://www.amd64.org/microcode.html
+[2] https://git.kernel.org/cgit/linux/kernel/git/firmware/linux-firmware.git/tree/amd-ucode
+[3] http://lxr.free-electrons.com/source/Documentation/x86/early-microcode.txt
diff --git a/docs/misc/arm/device-tree/booting.txt b/docs/misc/arm/device-tree/booting.txt
index 07fde27..ad98bf3 100644
--- a/docs/misc/arm/device-tree/booting.txt
+++ b/docs/misc/arm/device-tree/booting.txt
@@ -8,14 +8,37 @@ Each node contains the following properties:
- compatible
- Must be:
+ Must always include at least the generic compatiblity string:
- "xen,<type>", "xen,multiboot-module"
+ "multiboot,module"
- where <type> must be one of:
+ Optionally a more specific compatible string may be used in
+ addition to the above. One of:
- - "linux-zimage" -- the dom0 kernel
- - "linux-initrd" -- the dom0 ramdisk
+ - "multiboot,kernel" -- the dom0 kernel
+ - "multiboot,ramdisk" -- the dom0 ramdisk
+ - "xen,xsm-policy" -- XSM policy blob
+
+ It is normally recommended to include a more specific
+ compatible string (if one applies) in addition to the generic
+ string (which must always be present).
+
+ Xen will assume that the first module which lacks a more
+ specific compatible string is a "multiboot,kernel" and that
+ the second such is a "multiboot,ramdisk". Any subsequent
+ modules which lack a specific compatiblity string will not
+ receive any special treatment.
+
+ Xen 4.4 supported a different set of legacy compatible strings
+ which remain supported such that systems supporting both 4.4
+ and later can use a single DTB.
+
+ - "xen,multiboot-module" equivalent to "multiboot,module"
+ - "xen,linux-zimage" equivalent to "multiboot,kernel"
+ - "xen,linux-initrd" equivalent to "multiboot,ramdisk"
+
+ For compatibility with Xen 4.4 the more specific "xen,linux-*"
+ names are non-optional and must be included.
- reg
@@ -24,9 +47,36 @@ Each node contains the following properties:
- bootargs (optional)
- Command line associated with this module. This is deprecated and should
- be replaced by the bootargs variations described below.
+ Command line associated with this module. See below for the
+ priority of this field vs. other mechanisms of specifying the
+ bootargs for the kernel.
+
+Examples
+========
+
+A boot module of unspecified type:
+
+ module at 0xc0000000 {
+ compatible = "multiboot,module";
+ reg = <0xc0000000 0x1234>;
+ bootargs = "...";
+ };
+
+A boot module containing a ramdisk:
+
+ module at 0xd0000000 {
+ compatible = "multiboot,ramdisk", "multiboot,module";
+ reg = <0xd0000000 0x5678>;
+ };
+
+The previous examples are compatible with Xen 4.5+ only.
+
+To be compatible with Xen 4.4 as well use the legacy names:
+ module at 0xd0000000 {
+ compatible = "xen,linux-initrd", "xen,multiboot-module";
+ reg = <0xd0000000 0x5678>;
+ };
Command lines
=============
diff --git a/docs/misc/arm/early-printk.txt b/docs/misc/arm/early-printk.txt
index 1431751..71a0247 100644
--- a/docs/misc/arm/early-printk.txt
+++ b/docs/misc/arm/early-printk.txt
@@ -16,6 +16,9 @@ where mach is the name of the machine:
- omap5432: printk with UART3 on TI OMAP5432 processors
- sun6i: printk with 8250 on Allwinner A31 processors
- sun7i: printk with 8250 on Allwinner A20 processors
+ - brcm: printk with 8250 on Broadcom 7445D0 boards with A15 processors.
+ - hip04-d01: printk with 8250 on HiSilicon Hip-04 D01
+ - seattle: printk with pl011 for AMD Seattle processor
The base address and baud rate is hardcoded in xen/arch/arm/Rules.mk,
see there when adding support for new machines.
diff --git a/docs/misc/channel.txt b/docs/misc/channel.txt
new file mode 100644
index 0000000..9fc701a
--- /dev/null
+++ b/docs/misc/channel.txt
@@ -0,0 +1,106 @@
+Xen PV Channels
+===============
+
+A channel is a low-bandwidth private byte stream similar to a serial
+link. Typical uses of channels are
+
+ 1. to provide initial configuration information to a VM on boot
+ (example use: CloudStack's cloud-early-config service)
+ 2. to signal/query an in-guest agent
+ (example use: oVirt's guest agent)
+
+Channels are similar to virtio-serial devices and emulated serial links.
+Channels are intended to be used in the implementation of libvirt <channel>s
+when running on Xen.
+
+Note: if an application requires a high-bandwidth link then it should use
+vchan instead.
+
+How to use channels: an example
+-------------------------------
+
+Consider a cloud deployment where VMs are cloned from pre-made templates,
+and customised on first boot by an in-guest agent which sets the IP address,
+hostname, ssh keys etc. To install the system the cloud administrator would
+first:
+
+ 1. Install a guest as normal (no channel configuration necessary)
+ 2. Install the in-guest agent specific to the cloud software. This will
+ prepare the guest to communicate over the channel, and also prepare
+ the guest to be cloned safely (sometimes known as "sysprepping")
+ 3. Shutdown the guest
+ 4. Register the guest as a template with the cloud orchestration software
+ 5. Install the cloud orchestration agent in dom0
+
+At runtime, when a cloud tenant requests that a VM is created from the template,
+the sequence of events would be: (assuming a Linux domU)
+
+ 1. A VM is "cloned" from the template
+ 2. A unique Unix domain socket path in dom0 is allocated
+ (e.g. /my/cloud/software/talk/to/domain/<vm uuid>)
+ 3. Domain configuration is created for the VM, listing the channel
+ name expected by the in-guest agent. In xl syntax this would be:
+
+ channel = [ "connection=socket, name=org.my.cloud.software.agent.version1,
+ path = /my/cloud/software/talk/to/domain/<vm uuid>" ]
+
+ 4. The VM is started
+ 5. In dom0 the cloud orchestration agent connects to the Unix domain
+ socket, writes a handshake message and waits for a reply
+ 6. Assuming the guest kernel has CONFIG_HVC_XEN_FRONTEND set then the console
+ driver will generate a hotplug event
+ 7. A udev rule is activated by the hotplug event.
+
+ The udev rule would look something like:
+
+ SUBSYSTEM=="xen", DEVPATH=="/devices/console-[0-9]", RUN+="xen-console-setup"
+
+ where the "xen-console-setup" script would read the channel name and
+ make a symlink in /dev/xen-channel/org.my.cloud.software.agent.version1
+
+ 8. The in-guest agent uses inotify to see the creation of the /dev/xen-channel
+ symlink and opens the device.
+ 9. The in-guest agent completes the handshake with the dom0 agent
+ 10. The dom0 agent transmits the unique VM configuration: hostname, IP
+ address, ssh keys etc etc
+ 11. The in-guest agent receives the configuration and applies it.
+
+Using channels avoids having to use a temporary disk device or network
+connection.
+
+Design recommendations and pitfalls
+-----------------------------------
+
+It's necessary to install channel-specific software (an "agent") into the guest
+before you can use a channel. By default a channel will appear as a device
+which could be mistaken for a serial port or regular console. It is known
+that some software will proactively seek out serial ports and issue AT commands
+at them; make sure such software is disabled!
+
+Since channels are identified by names, application authors must ensure their
+channel names are unique to avoid clashes. We recommend that channel names
+include parts unique to the application such as a domain names. To assist
+prevent clashes we recommend authors add their names to our global channel
+registry at the end of this document.
+
+Limitations
+-----------
+
+Hotplug and unplug of channels is not currently implemented.
+
+Channel name registry
+---------------------
+
+It is important that channel names are globally unique. To help ensure
+that no-one's name clashes with yours, please add yours to this list.
+
+Key:
+N: Name
+C: Contact
+D: Short description of use, possibly including a URL to your software
+ or API
+
+N: org.xenproject.guest.clipboard.0.1
+C: David Scott <dave.scott at citrix.com>
+D: Share clipboard data via an in-guest agent. See:
+ http://wiki.xenproject.org/wiki/Clipboard_sharing_protocol
diff --git a/docs/misc/console.txt b/docs/misc/console.txt
index 8a53a95..ed7b795 100644
--- a/docs/misc/console.txt
+++ b/docs/misc/console.txt
@@ -9,10 +9,11 @@ relevant information in xenstore under /local/domain/$DOMID/console.
Now many years after the introduction of the pv console we have
multiple pv consoles support for pv and hvm guests; multiple pv
-console backends (qemu and xenconsoled) and emulated serial cards too.
+console backends (qemu and xenconsoled, see limitations below) and
+emulated serial cards too.
This document tries to describe how the whole system works and how the
-different components interact with each others.
+different components interact with each other.
The first PV console path in xenstore remains:
@@ -23,28 +24,63 @@ live in:
/local/domain/$DOMID/device/console/$DEVID.
-The output of a PV console, whether it should be a file, a pty, a
-socket, or something else, is specified by the toolstack in the xenstore
-node "output", under the relevant console section.
-For example:
+PV consoles have
+* (optional) string names;
+* 'connection' information describing to what they should be
+ connected; and
+* a 'type' indicating which daemon should process the data.
+
+We call a PV console with a name a "channel", in reference to the libvirt
+concept with the same name and purpose. The file "channels.txt" describes
+how to use channels and includes a registry of well-known channel names.
+
+If the PV console has a name (i.e. it is a "channel") then the name
+is written to the frontend directory:
+
+name = <name>
+
+If the PV console has no name (i.e. it is a regular console) then the "name"
+key is omitted.
+
+The toolstack writes 'connection' information in the xenstore backend in
+the keys
+* connection: either 'pty' or 'socket'
+* path: only present if connection = 'socket', the path of the socket to
+ glue the channel to
+
+An artifact of the current implementation, the toolstack will write an
+extra backend key
+* output: an identifier only meaningful for qemu/xenconsoled
-# xenstore-read /local/domain/26/device/console/1/output
-pty
+If the toolstack wants the console to be connected to a pty, it will write
+to the backend:
-The backend chosen for a particular console is specified by the
-toolstack in the "type" node on xenstore, under the relevant console
-section.
+connection = pty
+output = pty
+
+The backend will write the pty device name to the "tty" node in the
+console frontend.
+
+If the toolstack wants a listening Unix domain socket to be created at path
+<path>, a connection accepted and data proxied to the console, it will write:
+
+connection = socket
+path = <path>
+output = chardev:<some internal identifier>
+
+where chardev:<some internal identifier> matches a qemu character device
+configured on the qemu command-line.
+
+The backend implementation daemon chosen for a particular console is specified
+by the toolstack in the "type" node in the xenstore frontend.
For example:
# xenstore-read /local/domain/26/console/1/type
-xenconsoled
+ioemu
The supported values are only xenconsoled or ioemu; xenconsoled has
several limitations: it can only be used for the first PV console and it
-can only have a pty as output.
-
-If the output is a pty, backends write the device name to the "tty" node
-in xenstore under the relevant console path.
+can only connect to a pty.
Emulated serials are provided by qemu-dm only to hvm guests; the number
of emulated serials depends on how many "-serial" command line options
@@ -54,7 +90,6 @@ xenstore in the following path:
/local/domain/$DOMID/serial/$SERIAL_NUM/tty
-
xenconsole is the tool to connect to a PV console or an emulated serial
that has a pty as output. Xenconsole takes a domid as parameter plus an
optional console type (pv for PV consoles or serial for emulated
diff --git a/docs/misc/distro_mapping.txt b/docs/misc/distro_mapping.txt
index f56e281..2e46592 100644
--- a/docs/misc/distro_mapping.txt
+++ b/docs/misc/distro_mapping.txt
@@ -5,7 +5,6 @@ other distros one needs to set the variables for the elements below
| Red Hat | Debian | Suse |
-----------------+------------------+---------------+----------------+
CONFIG_LEAF_DIR | sysconfig | default | sysconfig |
-SUBSYS_DIR | /var/run/subsys | /var/run | /var/run |
INITD_DIR | /etc/rc.d/init.d | /etc/init.d | /etc/init.d |
-----------------+------------------+---------------+----------------+
@@ -14,8 +13,9 @@ build host, via the "setvar_dir" macro in Config.mk) and for some
scripts at run-time. If the Red Hat directory exists, it is used;
otherwise the Debian one is used.
-You can override this by setting the variables in the environment or
-your ".config" (which is included by .config).
+The INITD_DIR path can be changed with configure --with-initddir=DIR.
+The CONFIG_LEAF_DIR name can be changed with configure
+--with-sysconfig-leaf-dir=SUBDIR.
To add support for new distributions that don't use the above locations,
one must grep for the above elements and add appropriate checks.
diff --git a/docs/misc/efi.markdown b/docs/misc/efi.markdown
index 19b987a..f435ec7 100644
--- a/docs/misc/efi.markdown
+++ b/docs/misc/efi.markdown
@@ -1,8 +1,19 @@
-Building xen.efi requires gcc 4.5.x or above (4.6.x or newer recommended, as
-4.5.x was probably never really tested for this purpose) and binutils 2.22 or
-newer. Additionally, the binutils build must be configured to include support
-for the x86_64-pep emulation (i.e. `--enable-targets=x86_64-pep` or an option
-of equivalent effect should be passed to the configure script).
+For x86, building xen.efi requires gcc 4.5.x or above (4.6.x or newer
+recommended, as 4.5.x was probably never really tested for this purpose) and
+binutils 2.22 or newer. Additionally, the binutils build must be configured to
+include support for the x86_64-pep emulation (i.e.
+`--enable-targets=x86_64-pep` or an option of equivalent effect should be
+passed to the configure script).
+
+For arm64, the PE/COFF header is open-coded in assembly, so no toolchain
+support for PE/COFF is required. Also, the PE/COFF header co-exists with the
+normal Image format, so a single binary may be booted as an Image file or as an
+EFI application. When booted as an EFI application, Xen requires a
+configuration file as described below unless a bootloader, such as GRUB, has
+loaded the modules and describes them in the device tree provided to Xen. If a
+bootloader provides a device tree containing modules then any configuration
+files are ignored, and the bootloader is responsible for populating all
+relevant device tree nodes.
Once built, `make install-xen` will place the resulting binary directly into
the EFI boot partition, provided `EFI_VENDOR` is set in the environment (and
@@ -18,12 +29,18 @@ separators will be tried) to be present in the same directory as the binary.
(To illustrate the name handling, a binary named `xen-4.2-unstable.efi` would
try `xen-4.2-unstable.cfg`, `xen-4.2.cfg`, `xen-4.cfg`, and `xen.cfg` in
order.) One can override this with a command line option (`-cfg=<filename>`).
+This configuration file and EFI commandline are only used for booting directly
+from EFI firmware, or when using an EFI loader that does not support
+the multiboot2 protocol. When booting using GRUB or another multiboot aware
+loader the EFI commandline is ignored and all information is passed from
+the loader to Xen using the multiboot protocol.
The configuration file consists of one or more sections headed by a section
name enclosed in square brackets, with individual values specified in each
section. A section named `[global]` is treated specially to allow certain
settings to apply to all other sections (or to provide defaults for certain
-settings in case individual sections don't specify them). A typical file would
+settings in case individual sections don't specify them). This file (for now)
+needs to be of ASCII type and not e.g. UTF-8 or UTF-16. A typical file would
thus look like this (`#` serving as comment character):
**************************example begin******************************
@@ -73,7 +90,14 @@ Specifies an XSM module to load.
###`ucode=<filename>`
-Specifies a CPU microcode blob to load.
+Specifies a CPU microcode blob to load. (x86 only)
+
+###`dtb=<filename>`
+
+Specifies a device tree file to load. The platform firmware may provide a
+DTB in an EFI configuration table, so this field is optional in that
+case. A dtb specified in the configuration file will override a device tree
+provided in the EFI configuration table. (ARM only)
###`chain=<filename>`
diff --git a/docs/misc/kexec_and_kdump.txt b/docs/misc/kexec_and_kdump.txt
index 9ec3fcc..2f93771 100644
--- a/docs/misc/kexec_and_kdump.txt
+++ b/docs/misc/kexec_and_kdump.txt
@@ -137,10 +137,9 @@ command line parameter to the Xen hypervisor. It has two forms:
e.g. crashkernel=128M at 256M
Regardless of which of the two forms of the crashkernel command line you
- use, the crash kernel region should appear in /proc/iomem on x86 or
- /proc/iomem_machine on ia64. If it doesn't then either the crashkernel
- parameter is missing, or for some reason the region couldn't be placed -
- for instance because it is too large.
+ use, the crash kernel region should appear in /proc/iomem on x86. If it
+ doesn't then either the crashkernel parameter is missing, or for some
+ reason the region couldn't be placed - for instance because it is too large.
# cat /proc/iomem
...
@@ -179,8 +178,6 @@ On x86 systems the crash kernel may be either
- Relocatability is controlled by the CONFIG_RELOCATABLE kernel
compile configuration parameter. This option may not be available
depending on the kernel version
-On ia64
- Either a vmlinuz or vmlinux.gz image may be used
2. Execute
diff --git a/docs/misc/printk-formats.txt b/docs/misc/printk-formats.txt
index 4c4222b..dee0f3e 100644
--- a/docs/misc/printk-formats.txt
+++ b/docs/misc/printk-formats.txt
@@ -3,6 +3,11 @@ Xen custom %p format options. A subset, borrowed from Linux.
All parameters to a %p option should be compatible with void*. Regular
pointers are fine. Numbers should make use of the _p() macro.
+Raw buffer as hex string:
+
+ %*ph Up to 64 characters, printed as "00 01 02 ... ff". Buffer length
+ expected via the field_width paramter. i.e. printk("%*ph", 8, buffer);
+
Symbol/Function pointers:
%ps Symbol name with condition offset and size (iff offset != 0)
@@ -15,3 +20,8 @@ Symbol/Function pointers:
In the case that an appropriate symbol name can't be found, %p[sS] will
fall back to '%p' and print the address in hex.
+
+Domain and vCPU information:
+
+ %pv Domain and vCPU ID from a 'struct vcpu *' (printed as
+ "d<domid>v<vcpuid>")
diff --git a/docs/misc/pvh-readme.txt b/docs/misc/pvh-readme.txt
index 9fea137..c5b3de4 100644
--- a/docs/misc/pvh-readme.txt
+++ b/docs/misc/pvh-readme.txt
@@ -37,6 +37,8 @@ supported. Phase I patches are broken into three parts:
- tools changes for creating a PVH guest
- boot of 64bit dom0 in PVH mode.
+To boot 64bit dom0 in PVH mode, add dom0pvh to grub xen command line.
+
Following fixme's exist in the code:
- arch/x86/time.c: support more tsc modes.
diff --git a/docs/misc/pvh.markdown b/docs/misc/pvh.markdown
new file mode 100644
index 0000000..52d8e74
--- /dev/null
+++ b/docs/misc/pvh.markdown
@@ -0,0 +1,377 @@
+# PVH Specification #
+
+## Rationale ##
+
+PVH is a new kind of guest that has been introduced on Xen 4.4 as a DomU, and
+on Xen 4.5 as a Dom0. The aim of PVH is to make use of the hardware
+virtualization extensions present in modern x86 CPUs in order to
+improve performance.
+
+PVH is considered a mix between PV and HVM, and can be seen as a PV guest
+that runs inside of an HVM container, or as a PVHVM guest without any emulated
+devices. The design goal of PVH is to provide the best performance possible and
+to reduce the amount of modifications needed for a guest OS to run in this mode
+(compared to pure PV).
+
+This document tries to describe the interfaces used by PVH guests, focusing
+on how an OS should make use of them in order to support PVH.
+
+## Early boot ##
+
+PVH guests use the PV boot mechanism, that means that the kernel is loaded and
+directly launched by Xen (by jumping into the entry point). In order to do this
+Xen ELF Notes need to be added to the guest kernel, so that they contain the
+information needed by Xen. Here is an example of the ELF Notes added to the
+FreeBSD amd64 kernel in order to boot as PVH:
+
+ ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz, "FreeBSD")
+ ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz, __XSTRING(__FreeBSD_version))
+ ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz, "xen-3.0")
+ ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE, .quad, KERNBASE)
+ ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET, .quad, KERNBASE)
+ ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, .quad, xen_start)
+ ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .quad, hypercall_page)
+ ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW, .quad, HYPERVISOR_VIRT_START)
+ ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .asciz, "writable_descriptor_tables|auto_translated_physmap|supervisor_mode_kernel|hvm_callback_vector")
+ ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz, "yes")
+ ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, .long, PG_V, PG_V)
+ ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz, "generic")
+ ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long, 0)
+ ELFNOTE(Xen, XEN_ELFNOTE_BSD_SYMTAB, .asciz, "yes")
+
+On the Linux side, the above can be found in `arch/x86/xen/xen-head.S`.
+
+It is important to highlight the following notes:
+
+ * `XEN_ELFNOTE_ENTRY`: contains the virtual memory address of the kernel entry
+ point.
+ * `XEN_ELFNOTE_HYPERCALL_PAGE`: contains the virtual memory address of the
+ hypercal page inside of the guest kernel (this memory region will be filled
+ by Xen prior to booting).
+ * `XEN_ELFNOTE_FEATURES`: contains the list of features supported by the kernel.
+ In the example above the kernel is only able to boot as a PVH guest, but
+ those options can be mixed with the ones used by pure PV guests in order to
+ have a kernel that supports both PV and PVH (like Linux). The list of
+ options available can be found in the `features.h` public header. Note that
+ in the example above `hvm_callback_vector` is in `XEN_ELFNOTE_FEATURES`.
+ Older hypervisors will balk at this being part of it, so it can also be put
+ in `XEN_ELFNOTE_SUPPORTED_FEATURES` which older hypervisors will ignore.
+
+Xen will jump into the kernel entry point defined in `XEN_ELFNOTE_ENTRY` with
+paging enabled (either long mode or protected mode with paging turned on
+depending on the kernel bitness) and some basic page tables setup. An important
+distinction for a 64bit PVH is that it is launched at privilege level 0 as
+opposed to a 64bit PV guest which is launched at privilege level 3.
+
+Also, the `rsi` (`esi` on 32bits) register is going to contain the virtual
+memory address where Xen has placed the `start_info` structure. The `rsp` (`esp`
+on 32bits) will point to the top of an initial single page stack, that can be
+used by the guest kernel. The `start_info` structure contains all the info the
+guest needs in order to initialize. More information about the contents can be
+found in the `xen.h` public header.
+
+### Initial amd64 control registers values ###
+
+Initial values for the control registers are set up by Xen before booting the
+guest kernel. The guest kernel can expect to find the following features
+enabled by Xen.
+
+`CR0` has the following bits set by Xen:
+
+ * PE (bit 0): protected mode enable.
+ * ET (bit 4): 387 or newer processor.
+ * PG (bit 31): paging enabled.
+
+`CR4` has the following bits set by Xen:
+
+ * PAE (bit 5): PAE enabled.
+
+And finally in `EFER` the following features are enabled:
+
+ * LME (bit 8): Long mode enable.
+ * LMA (bit 10): Long mode active.
+
+At least the following flags in `EFER` are guaranteed to be disabled:
+
+ * SCE (bit 0): System call extensions disabled.
+ * NXE (bit 11): No-Execute disabled.
+
+There's no guarantee about the state of the other bits in the `EFER` register.
+
+All the segments selectors are set with a flat base at zero.
+
+The `cs` segment selector attributes are set to 0x0a09b, which describes an
+executable and readable code segment only accessible by the most privileged
+level. The segment is also set as a 64-bit code segment (`L` flag set, `D` flag
+unset).
+
+The remaining segment selectors (`ds`, `ss`, `es`, `fs` and `gs`) are all set
+to the same values. The attributes are set to 0x0c093, which implies a read and
+write data segment only accessible by the most privileged level.
+
+The `FS.base`, `GS.base` and `KERNEL_GS.base` MSRs are zeroed out.
+
+The `IDT` and `GDT` are also zeroed, so the guest must be specially careful to
+not trigger a fault until after they have been properly set. The way of setting
+the IDT and the GDT is using the native instructions as would be done on bare
+metal.
+
+The `RFLAGS` register is guaranteed to be clear when jumping into the kernel
+entry point, with the exception of the reserved bit 1 set.
+
+## Memory ##
+
+Since PVH guests rely on virtualization extensions provided by the CPU, they
+have access to a hardware virtualized MMU, which means page-table related
+operations should use the same instructions used on native.
+
+There are however some differences with native. The usage of native MTRR
+operations is forbidden, and `XENPF_*_memtype` hypercalls should be used
+instead. This can be avoided by simply not using MTRR and setting all the
+memory attributes using PAT, which doesn't require the usage of any hypercalls.
+
+Since PVH doesn't use a BIOS in order to boot, the physical memory map has
+to be retrieved using the `XENMEM_memory_map` hypercall, which will return
+an e820 map. This memory map might contain holes that describe MMIO regions,
+that will be already setup by Xen.
+
+*TODO*: we need to figure out what to do with MMIO regions, right now Xen
+sets all the holes in the native e820 to MMIO regions for Dom0 up to 4GB. We
+need to decide what to do with MMIO regions above 4GB on Dom0, and what to do
+for PVH DomUs with pci-passthrough.
+
+In the case of a guest started with memory != maxmem, the e820 memory map
+returned by Xen will contain the memory up to maxmem. The guest has to be very
+careful to only use the lower memory pages up to the value contained in
+`start_info->nr_pages` because any memory page above that value will not be
+populated.
+
+## Physical devices ##
+
+When running as Dom0 the guest OS has the ability to interact with the physical
+devices present in the system. A note should be made that PVH guests require
+a working IOMMU in order to interact with physical devices.
+
+The first step in order to manipulate the devices is to make Xen aware of
+them. Due to the fact that all the hardware description on x86 comes from
+ACPI, Dom0 is responsible for parsing the ACPI tables and notifying Xen about
+the devices it finds. This is done with the `PHYSDEVOP_pci_device_add`
+hypercall.
+
+*TODO*: explain the way to register the different kinds of PCI devices, like
+devices with virtual functions.
+
+## Interrupts ##
+
+All interrupts on PVH guests are routed over event channels, see
+[Event Channel Internals][event_channels] for more detailed information about
+event channels. In order to inject interrupts into the guest an IDT vector is
+used. This is the same mechanism used on PVHVM guests, and allows having
+per-cpu interrupts that can be used to deliver timers or IPIs.
+
+In order to register the callback IDT vector the `HVMOP_set_param` hypercall
+is used with the following values:
+
+ domid = DOMID_SELF
+ index = HVM_PARAM_CALLBACK_IRQ
+ value = (0x2 << 56) | vector_value
+
+The OS has to program the IDT for the `vector_value` using the baremetal
+mechanism.
+
+In order to know which event channel has fired, we need to look into the
+information provided in the `shared_info` structure. The `evtchn_pending`
+array is used as a bitmap in order to find out which event channel has
+fired. Event channels can also be masked by setting it's port value in the
+`shared_info->evtchn_mask` bitmap.
+
+### Interrupts from physical devices ###
+
+When running as Dom0 (or when using pci-passthrough) interrupts from physical
+devices are routed over event channels. There are 3 different kind of
+physical interrupts that can be routed over event channels by Xen: IO APIC,
+MSI and MSI-X interrupts.
+
+Since physical interrupts usually need EOI (End Of Interrupt), Xen allows the
+registration of a memory region that will contain whether a physical interrupt
+needs EOI from the guest or not. This is done with the
+`PHYSDEVOP_pirq_eoi_gmfn_v2` hypercall that takes a parameter containing the
+physical address of the memory page that will act as a bitmap. Then in order to
+find out if an IRQ needs EOI or not, the OS can perform a simple bit test on the
+memory page using the PIRQ value.
+
+### IO APIC interrupt routing ###
+
+IO APIC interrupts can be routed over event channels using `PHYSDEVOP`
+hypercalls. First the IRQ is registered using the `PHYSDEVOP_map_pirq`
+hypercall, as an example IRQ#9 is used here:
+
+ domid = DOMID_SELF
+ type = MAP_PIRQ_TYPE_GSI
+ index = 9
+ pirq = 9
+
+The IRQ#9 is now registered as PIRQ#9. The triggering and polarity can also
+be configured using the `PHYSDEVOP_setup_gsi` hypercall:
+
+ gsi = 9 # This is the IRQ value.
+ triggering = 0
+ polarity = 0
+
+In this example the IRQ would be configured to use edge triggering and high
+polarity.
+
+Finally the PIRQ can be bound to an event channel using the
+`EVTCHNOP_bind_pirq`, that will return the event channel port the PIRQ has been
+assigned. After this the event channel will be ready for delivery.
+
+*NOTE*: when running as Dom0, the guest has to parse the interrupt overrides
+found on the ACPI tables and notify Xen about them.
+
+### MSI ###
+
+In order to configure MSI interrupts for a device, Xen must be made aware of
+it's presence first by using the `PHYSDEVOP_pci_device_add` as described above.
+Then the `PHYSDEVOP_map_pirq` hypercall is used:
+
+ domid = DOMID_SELF
+ type = MAP_PIRQ_TYPE_MSI_SEG or MAP_PIRQ_TYPE_MULTI_MSI
+ index = -1
+ pirq = -1
+ bus = pci_device_bus
+ devfn = pci_device_function
+ entry_nr = number of MSI interrupts
+
+The type has to be set to `MAP_PIRQ_TYPE_MSI_SEG` if only one MSI interrupt
+source is being configured. On devices that support MSI interrupt groups
+`MAP_PIRQ_TYPE_MULTI_MSI` can be used to configure them by also placing the
+number of MSI interrupts in the `entry_nr` field.
+
+The values in the `bus` and `devfn` field should be the same as the ones used
+when registering the device with `PHYSDEVOP_pci_device_add`.
+
+### MSI-X ###
+
+*TODO*: how to register/use them.
+
+## Event timers and timecounters ##
+
+Since some hardware is not available on PVH (like the local APIC), Xen provides
+the OS with suitable replacements in order to get the same functionality. One
+of them is the timer interface. Using a set of hypercalls, a guest OS can set
+event timers that will deliver and event channel interrupt to the guest.
+
+In order to use the timer provided by Xen the guest OS first needs to register
+a VIRQ event channel to be used by the timer to deliver the interrupts. The
+event channel is registered using the `EVTCHNOP_bind_virq` hypercall, that
+only takes two parameters:
+
+ virq = VIRQ_TIMER
+ vcpu = vcpu_id
+
+The port that's going to be used by Xen in order to deliver the interrupt is
+returned in the `port` field. Once the interrupt is set, the timer can be
+programmed using the `VCPUOP_set_singleshot_timer` hypercall.
+
+ flags = VCPU_SSHOTTMR_future
+ timeout_abs_ns = absolute value when the timer should fire
+
+It is important to notice that the `VCPUOP_set_singleshot_timer` hypercall must
+be executed from the same vCPU where the timer should fire, or else Xen will
+refuse to set it. This is a single-shot timer, so it must be set by the OS
+every time it fires if a periodic timer is desired.
+
+Xen also shares a memory region with the guest OS that contains time related
+values that are updated periodically. This values can be used to implement a
+timecounter or to obtain the current time. This information is placed inside of
+`shared_info->vcpu_info[vcpu_id].time`. The uptime (time since the guest has
+been launched) can be calculated using the following expression and the values
+stored in the `vcpu_time_info` struct:
+
+ system_time + ((((tsc - tsc_timestamp) << tsc_shift) * tsc_to_system_mul) >> 32)
+
+The timeout that is passed to `VCPUOP_set_singleshot_timer` has to be
+calculated using the above value, plus the timeout the system wants to set.
+
+If the OS also wants to obtain the current wallclock time, the value calculated
+above has to be added to the values found in `shared_info->wc_sec` and
+`shared_info->wc_nsec`.
+
+## SMP discover and bring up ##
+
+The process of bringing up secondary CPUs is obviously different from native,
+since PVH doesn't have a local APIC. The first thing to do is to figure out
+how many vCPUs the guest has. This is done using the `VCPUOP_is_up` hypercall,
+using for example this simple loop:
+
+ for (i = 0; i < MAXCPU; i++) {
+ ret = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
+ if (ret >= 0)
+ /* vCPU#i is present */
+ }
+
+Note than when running as Dom0, the ACPI tables might report a different number
+of available CPUs. This is because the value on the ACPI tables is the
+number of physical CPUs the host has, and it might bear no resemblance with the
+number of vCPUs Dom0 actually has so it should be ignored.
+
+In order to bring up the secondary vCPUs they must be configured first. This is
+achieved using the `VCPUOP_initialise` hypercall. A valid context has to be
+passed to the vCPU in order to boot. The relevant fields for PVH guests are
+the following:
+
+ * `flags`: contains `VGCF_*` flags (see `arch-x86/xen.h` public header).
+ * `user_regs`: struct that contains the register values that will be set on
+ the vCPU before booting. All GPRs are available to be set, however, the
+ most relevant ones are `rip` and `rsp` in order to set the start address
+ and the stack. Please note, all selectors must be null.
+ * `ctrlreg[3]`: contains the address of the page tables that will be used by
+ the vCPU. Other control registers should be set to zero, or else the
+ hypercall will fail with -EINVAL.
+
+After the vCPU is initialized with the proper values, it can be started by
+using the `VCPUOP_up` hypercall. The values of the other control registers of
+the vCPU will be the same as the ones described in the `control registers`
+section.
+
+Examples about how to bring up secondary CPUs can be found on the FreeBSD
+code base in `sys/x86/xen/pv.c` and on Linux `arch/x86/xen/smp.c`.
+
+## Control operations (reboot/shutdown) ##
+
+Reboot and shutdown operations on PVH guests are performed using hypercalls.
+In order to issue a reboot, a guest must use the `SHUTDOWN_reboot` hypercall.
+In order to perform a power off from a guest DomU, the `SHUTDOWN_poweroff`
+hypercall should be used.
+
+The way to perform a full system power off from Dom0 is different than what's
+done in a DomU guest. In order to perform a power off from Dom0 the native
+ACPI path should be followed, but the guest should not write the `SLP_EN`
+bit to the Pm1Control register. Instead the `XENPF_enter_acpi_sleep` hypercall
+should be used, filling the following data in the `xen_platform_op` struct:
+
+ cmd = XENPF_enter_acpi_sleep
+ interface_version = XENPF_INTERFACE_VERSION
+ u.enter_acpi_sleep.pm1a_cnt_val = Pm1aControlValue
+ u.enter_acpi_sleep.pm1b_cnt_val = Pm1bControlValue
+
+This will allow Xen to do it's clean up and to power off the system. If the
+host is using hardware reduced ACPI, the following field should also be set:
+
+ u.enter_acpi_sleep.flags = XENPF_ACPI_SLEEP_EXTENDED (0x1)
+
+## CPUID ##
+
+The cpuid instruction that should be used is the normal `cpuid`, not the
+emulated `cpuid` that PV guests usually require.
+
+*TDOD*: describe which cpuid flags a guest should ignore and also which flags
+describe features can be used. It would also be good to describe the set of
+cpuid flags that will always be present when running as PVH.
+
+## Final notes ##
+
+All the other hardware functionality not described in this document should be
+assumed to be performed in the same way as native.
+
+[event_channels]: http://wiki.xen.org/wiki/Event_Channel_Internals
diff --git a/docs/misc/tmem-internals.html b/docs/misc/tmem-internals.html
index ccc34c3..2d8635d 100644
--- a/docs/misc/tmem-internals.html
+++ b/docs/misc/tmem-internals.html
@@ -728,13 +728,6 @@ However, the Xen heap is limited in size on
32-bit Xen so tmem did not work very well.
There are still 32-bit ifdefs in some places in the code, but things may
have bit-rotted so using tmem on a 32-bit Xen is not recommended.
-<P>
-<b><i>IA-64 implementation. </i></b>
-The vast majority of the tmem
-implementation is architecture-independent.
-For tmem to run on Xen/ia64, it is believed that only one or two
-routines needs to be written.(See the
-#ifdef __ia64__ at <i>cli_mfn_to_va()</i>.)
<h2>Known Issues</h2>
diff --git a/docs/misc/vbd-interface.txt b/docs/misc/vbd-interface.txt
index 3952e73..f873db0 100644
--- a/docs/misc/vbd-interface.txt
+++ b/docs/misc/vbd-interface.txt
@@ -125,3 +125,9 @@ because they directly map the bottom 8 bits of the xenstore integer
directly to the Linux guest's device number and throw away the rest;
they can crash due to minor number clashes. With these guests, the
workaround is not to supply problematic combinations of devices.
+
+
+Other frontend and backend options
+----------------------------------
+
+See xen/include/public/io/blkif.h for the full list of options.
diff --git a/docs/misc/vtpm-platforms.txt b/docs/misc/vtpm-platforms.txt
new file mode 100644
index 0000000..5a5f767
--- /dev/null
+++ b/docs/misc/vtpm-platforms.txt
@@ -0,0 +1,141 @@
+Author: Daniel De Graaf <dgdegra at tycho.nsa.gov>
+
+================================================================================
+Overview
+================================================================================
+
+This document describes example platforms which use virtual TPMs to provide
+security properties for guests running on the platforms. There are several
+tradeoffs between flexibility and trust which must be considered when
+implementing a platform containing vTPMs.
+
+================================================================================
+Example 1: Trusted Domain 0
+================================================================================
+
+This is the simplest example and provides maximal flexibility for testing the
+vTPM Manager and vTPMs. The vtpmmgr, vtpm, and guest domains are created using
+xl from the command line on domain 0.
+
+Provisioning on domain 0:
+# dd if=/dev/zero of=/images/vtpmmgr-stubdom.img bs=2M count=1
+# dd if=/dev/zero of=/images/vtpm-guest1.img bs=2M count=1
+# dd if=/dev/zero of=/images/vtpm-guest2.img bs=2M count=1
+
+The vtpmmgr configuration file (vtpmmgr.cfg):
+
+name="vtpmmgr"
+kernel="/usr/lib/xen/boot/vtpmmgr-stubdom.gz"
+extra="tpmlocality=2"
+memory=8
+disk=["file:/images/vtpmmgr-stubdom.img,hda,w"]
+iomem=["fed42,1"]
+
+The vtpm configuration files (vtpm-guest1.cfg, vtpm-guest2.cfg):
+
+name="vtpm-guest1"
+kernel="/usr/lib/xen/boot/vtpm-stubdom.gz"
+extra="loglevel=debug"
+memory=8
+disk=["file:/images/vtpm-guest1.img,hda,w"]
+vtpm=["backend=vtpmmgr,uuid=ac0a5b9e-cbe2-4c07-b43b-1d69e46fb839"]
+
+name="vtpm-guest2"
+kernel="/usr/lib/xen/boot/vtpm-stubdom.gz"
+extra="loglevel=debug"
+memory=8
+disk=["file:/images/vtpm-guest2.img,hda,w"]
+vtpm=["backend=vtpmmgr,uuid=6c3ff5f1-8d58-4fed-b00d-a5ea9a817f7f"]
+
+The guest configuration files (guest1.cfg, guest2.cfg):
+
+name="guest1"
+kernel="/usr/lib/xen/boot/pv-grub-x86_64.gz"
+memory=1024
+disk=["file:/images/guest1.img,xvda,w"]
+vif=['mac=00:01:02:03:04:05,bridge=br0']
+vtpm=["backend=vtpm-guest1"]
+
+name="guest2"
+kernel="/usr/lib/xen/boot/pv-grub-x86_64.gz"
+memory=1024
+disk=["file:/images/guest2.img,xvda,w"]
+vif=['mac=00:01:02:03:04:06,bridge=br0']
+vtpm=["backend=vtpm-guest2"]
+
+Starting domains:
+
+# xl create vtpmmgr.cfg
+# xl create vtpm-guest1.cfg
+# xl create guest1.cfg
+
+================================================================================
+Example 2: Domain Builder with Static vTPMs
+================================================================================
+
+This example uses the domain builder to construct a TPM Manager and vTPM which
+do not require trusting the hardware domain with the vTPM's secrets. However,
+it is not possible to construct additional vTPMs after the system is booted, and
+the guests with access to vTPMs may not be rebooted without rebooting the entire
+platform.
+
+The domain builder (dom0) constructs:
+ dom1 - xenstore system_u:system_r:xenstore_t
+ dom2 - hardware system_u:system_r:hwdom_t
+ dom3 - vtpmmgr system_u:system_r:vtpmmgr_t
+ dom4 - vtpm-hw system_u:system_r:vtpm_t
+ dom5 - vtpm-g1 guest1_u:vm_r:vtpm_t
+ dom6 - vtpm-g2 guest2_u:vm_r:vtpm_t
+ dom7 - guest1 guest1_u:vm_r:guest_t
+ dom8 - guest2 guest2_u:vm_r:guest_t
+
+It unpauses dom1 and dom2 after setting up Xenstore. The hardware domain is not
+permitted access to IO memory at 0xfed42; this IO memory is accessible to the
+vtpmmgr domain. The two guest domains may be instantiated using pv-grub or
+using the same kernel as the hardware domain to conserve space in the domain
+builder's initrd.
+
+Once the hardware domain boots, it runs:
+
+# xl block-attach vtpmmgr 'backendtype=phy,backend=hardware,vdev=hda,access=w,target=/dev/lvm/vtpmmgr'
+# xl block-attach vtpm-hw 'backendtype=phy,backend=hardware,vdev=hda,access=w,target=/dev/lvm/vtpm-hw'
+# xl block-attach vtpm-g1 'backendtype=phy,backend=hardware,vdev=hda,access=w,target=/dev/lvm/vtpm-g1'
+# xl block-attach vtpm-g2 'backendtype=phy,backend=hardware,vdev=hda,access=w,target=/dev/lvm/vtpm-g2'
+# xl block-attach guest1 'backendtype=phy,backend=hardware,vdev=xvda,access=w,target=/dev/lvm/guest1'
+# xl block-attach guest2 'backendtype=phy,backend=hardware,vdev=xvda,access=w,target=/dev/lvm/guest2'
+# xl vtpm-attach vtpm-hw uuid=062b6416-ed46-492a-9e65-a2f92dc07f7f backend=vtpmmgr
+# xl vtpm-attach vtpm-g1 uuid=e9aa9d0f-ece5-4b84-b129-93004ba61a5f backend=vtpmmgr
+# xl vtpm-attach vtpm-g2 uuid=3fb2caf0-d305-4516-96c7-420618d98efb backend=vtpmmgr
+# xl vtpm-attach hardware uuid=062b6416-ed46-492a-9e65-a2f92dc07f7f backend=vtpm-hw
+# xl vtpm-attach guest1 uuid=e9aa9d0f-ece5-4b84-b129-93004ba61a5f backend=vtpm-g1
+# xl vtpm-attach guest2 uuid=3fb2caf0-d305-4516-96c7-420618d98efb backend=vtpm-g2
+
+Once these commands are complete, the domains are unpaused and may boot. The XSM
+policy must be configured to not allow any of the domain types named above to be
+created by any domain except the domain builder; guests created by the hardware
+domain or one of the primary guests acting as a control domain must have a
+different type. The type vtpmmgr_t may only map grants from vtpm_t; vtpm_t may
+only map grants from a domain of type guest_t or hwdom_t with the same user
+field.
+
+This example may be extended to allow dynamic creation of domains by using a
+domain builder that accepts build requests. A single build request would create
+a pair of domains using an unused XSM user field: a vTPM and a pv-grub domain
+which requires the presence of a vTPM. To bind the configuration of the guest
+to the vTPM, the guest may use full-disk encryption which can be unlocked using
+an unseal operation; using the wrong vTPM will then yield a non-functioning
+guest.
+
+In order to use pv-grub to obtain measurements of the guest kernel in PCRs 4 and
+5, it must not be possible to attach to a guest's vTPM without booting a fresh
+guest image. This requires pairing every vTPM's launch with the launch of a
+guest, as described above, and using the --vtpm-label= argument to pv-grub so
+that it refuses to launch a guest if it could not write to the vTPM. To permit
+the hardware domain, which cannot use pv-grub, to use a vTPM in this situation,
+multiple vTPM groups must be used in the TPM Manager. Group 0 would be for the
+hardware domain only, and would only support vTPMs with label
+"system_u:system_r:vtpm_t". Group 1 would support vTPMs with label
+"*:vm_r:vtpm_t", and would be used for all guest vTPMs. The EK quote used in
+initial provisioning and any deep quotes produced later would include the label,
+which would allow a verifier to reliably determine if the value of the vTPM's
+PCR 4 contains the hash of the domain's kernel.
diff --git a/docs/misc/vtpm.txt b/docs/misc/vtpm.txt
index df1dfae..1887d40 100644
--- a/docs/misc/vtpm.txt
+++ b/docs/misc/vtpm.txt
@@ -22,8 +22,8 @@ major component of vTPM is implemented as a separate domain, providing secure
separation guaranteed by the hypervisor. The vTPM domains are implemented in
mini-os to reduce memory and processor overhead.
-This mini-os vTPM subsystem was built on top of the previous vTPM
-work done by IBM and Intel corporation.
+This mini-os vTPM subsystem was built on top of the previous vTPM work done by
+IBM and Intel corporation.
------------------------------
DESIGN OVERVIEW
@@ -106,24 +106,36 @@ INSTALLATION
Prerequisites:
--------------
-You must have an x86 machine with a TPM on the motherboard.
-The only software requirement to compiling vTPM is cmake.
-You must use libxl to manage domains with vTPMs. 'xm' is
-deprecated and does not support vTPM.
+You must have an x86 machine with a TPM on the motherboard. The only extra
+software requirement for compiling vTPM is cmake. You must use libxl to manage
+domains with vTPMs; 'xm' is deprecated and does not support vTPMs.
-Compiling the XEN tree:
+Compiling the Xen tree:
-----------------------
-Compile and install the XEN tree as usual. Be sure to build and install
-the stubdom tree.
+Compile and install the Xen tree as usual; be sure that the vTPM domains are
+enabled when you run configure.
Compiling the LINUX dom0 kernel:
--------------------------------
-The Linux dom0 kernel should not try accessing the TPM while the vTPM
-Manager domain is accessing it; the simplest way to accomplish this is
-to ensure the kernel is compiled without a driver for the TPM, or avoid
-loading the driver by blacklisting the module.
+Because the TPM manager uses direct access to the physical TPM, it may interfere
+with access to the TPM by dom0. The simplest solution for this is to prevent
+dom0 from accessing the physical TPM by compiling the kernel without a driver or
+blacklisting the module. If dom0 needs a TPM but does not need to use it during
+the boot process (i.e. it is not using IMA), a virtual TPM can be attached to
+dom0 after the system is booted.
+
+Access to the physical TPM may be required in order to manage the NVRAM or to
+perform other advanced operations where the vTPM is insufficient. In order to
+prevent interference, the TPM Manager and dom0 should use different values for
+the TPM's locality; since Linux always uses locality 0, using locality 2 for the
+TPM Manager is recommended. If both Linux and the TPM Manager attempt to access
+the TPM at the same time, the TPM device will return a busy status; some
+applications will consider this a fatal error instead of retrying the command at
+a later time. If a vTPM gets an error when loading its key, it will currently
+generate a fresh vTPM image (with a new EK, SRK, and blank NVRAM).
+
Compiling the LINUX domU kernel:
--------------------------------
@@ -142,130 +154,100 @@ VTPM MANAGER SETUP
Manager disk image setup:
-------------------------
-The vTPM Manager requires a disk image to store its
-encrypted data. The image does not require a filesystem
-and can live anywhere on the host disk. The image does not need
-to be large. 8 to 16 Mb should be sufficient.
-
-# dd if=/dev/zero of=/var/vtpmmgr-stubdom.img bs=16M count=1
+The vTPM Manager requires a disk image to store its encrypted data. The image
+does not require a filesystem and can live anywhere on the host disk. The image
+is not large; the Xen 4.5 vtpmmgr is limited to using the first 2MB of the image
+but can support more than 20,000 vTPMs.
Manager config file:
--------------------
-The vTPM Manager domain (vtpmmgr-stubdom) must be started like
-any other Xen virtual machine and requires a config file.
-The manager requires a disk image for storage and permission
-to access the hardware memory pages for the TPM. An
-example configuration looks like the following.
-
-kernel="/usr/lib/xen/boot/vtpmmgr-stubdom.gz"
-memory=16
-disk=["file:/var/vtpmmgr-stubdom.img,hda,w"]
-name="vtpmmgr"
-iomem=["fed40,5"]
-
-The iomem line tells xl to allow access to all of the TPM IO memory
-pages, which are 5 pages (one per locality) that start at 0xfed40000. By
-default, the TPM manager uses locality 0 (so only the page at 0xfed40 is
-needed); this can be changed on the domain's command line.
+The vTPM Manager domain (vtpmmgr-stubdom) must be started like any other Xen
+virtual machine and requires a config file. The manager requires a disk image
+for storage and permission to access the hardware memory pages for the TPM. The
+disk must be presented as "hda", and the TPM memory pages are passed using the
+iomem configuration parameter. The TPM TIS uses 5 pages of IO memory (one per
+locality) that start at physical address 0xfed40000. By default, the TPM manager
+uses locality 0 (so only the page at 0xfed40 is needed); this can be changed on
+the domain's command line. For full functionality in deep quotes, using
+locality 2 is required to manipulate PCR 20-22.
Starting and stopping the manager:
----------------------------------
-The vTPM manager should be started at boot, you may wish to
-create an init script to do this.
-
-# xl create -c vtpmmgr-stubdom.cfg
+The vTPM manager should be started at boot; you may wish to create an init
+script to do this. If a domain builder is used, the TPM Manager should be
+started by the domain builder to minimize the trusted computing base for the
+vTPM manager's secrets.
Once initialization is complete you should see the following:
INFO[VTPM]: Waiting for commands from vTPM's:
-To shutdown the manager you must destroy it. To avoid data corruption,
-only destroy the manager when you see the above "Waiting for commands"
-message. This ensures the disk is in a consistent state.
-
-# xl destroy vtpmmgr-stubdom
+The TPM Manager does not respond to shutdown requests; use the destroy command
+to shut it down.
------------------------------
VTPM AND LINUX PVM SETUP
------------------------------
-In the following examples we will assume we have Linux
-guest named "domu" with its associated configuration
-located at /home/user/domu. It's vtpm will be named
-domu-vtpm.
-
vTPM disk image setup:
----------------------
-The vTPM requires a disk image to store its persistent
-data. The image does not require a filesystem. The image
-does not need to be large. 8 Mb should be sufficient.
-
-# dd if=/dev/zero of=/home/user/domu/vtpm.img bs=8M count=1
+The vTPM requires a disk image to store its persistent data (RSA keys, NVRAM,
+etc). The image does not require a filesystem. The image does not need to be
+large; 2 Mb should be sufficient.
vTPM config file:
-----------------
-The vTPM domain requires a configuration file like
-any other domain. The vTPM requires a disk image for
-storage and a TPM frontend driver to communicate
-with the manager. An example configuration is given:
+The vTPM domain requires a configuration file like any other domain. The vTPM
+requires a disk image for storage and a TPM frontend driver to communicate with
+the manager. You are required to generate a uuid for this vtpm, which is
+specified on the "vtpm=" line that describes its connection to the vTPM Manager.
+The uuidgen application may be used to generate a uuid, or one from the output
+of the "manage-vtpmmgr.pl vtpm-add" command may be used to create a vTPM
+belonging to a specific group.
-kernel="/usr/lib/xen/boot/vtpm-stubdom.gz"
-memory=8
-disk=["file:/home/user/domu/vtpm.img,hda,w"]
-name="domu-vtpm"
-vtpm=["backend=vtpmmgr,uuid=ac0a5b9e-cbe2-4c07-b43b-1d69e46fb839"]
-
-The vtpm= line sets up the tpm frontend driver. The backend must set
-to vtpmmgr. You are required to generate a uuid for this vtpm.
-You can use the uuidgen unix program or some other method to create a
-uuid. The uuid uniquely identifies this vtpm to manager.
-
-If you wish to clear the vTPM data you can either recreate the
-disk image or change the uuid.
+If you wish to clear the vTPM data you can either recreate the disk image or
+change the uuid.
Linux Guest config file:
------------------------
-The Linux guest config file needs to be modified to include
-the Linux tpmfront driver. Add the following line:
+The Linux guest config file needs to be modified to include the Linux tpmfront
+driver. Add the following line:
vtpm=["backend=domu-vtpm"]
Currently only Linux guests are supported (PV or HVM with PV drivers).
-Launching and shut down:
-------------------------
-
-To launch a Linux guest with a vTPM we first have to start the vTPM domain.
+While attaching a vTPM after a guest is booted (using xl vtpm-attach) is
+supported, the attached vTPM will not have a record of the boot of the attached
+guest. Furthermore, if the vTPM has been freshly created, a malicious guest
+could then extend any values into PCRs, potentially forging its boot
+configuration. Attaching a vTPM to a running domain should only be used for
+trusted domains or when measurements have already been sent to the vTPM from
+another source.
-# xl create -c /home/user/domu/vtpm.cfg
+Using the vTPM in the guest:
+----------------------------
-After initialization is complete, you should see the following:
-Info: Waiting for frontend domain to connect..
-
-Next, launch the Linux guest
-
-# xl create -c /home/user/domu/domu.cfg
-
-If xen-tpmfront was compiled as a module, be sure to load it
-in the guest.
+If xen-tpmfront was compiled as a module, it must be loaded it in the guest.
# modprobe xen-tpmfront
-After the Linux domain boots and the xen-tpmfront driver is loaded,
-you should see the following on the vtpm console:
+After the Linux domain boots and the xen-tpmfront driver is loaded, you should
+see the following on the vtpm console:
Info: VTPM attached to Frontend X/Y
-If you have trousers and tpm_tools installed on the guest, you can test the
-vtpm.
+You can quickly test the vTPM by using the sysfs interface:
+
+# cat /sys/devices/vtpm-0/pubek
+# cat /sys/devices/vtpm-0/pcrs
-On guest:
-# tcsd (if tcsd is not running already)
-# tpm_version
+If you have trousers and tpm_tools installed on the guest, the tpm_version
+command should return the following:
The version command should return the following:
TPM 1.2 Version Info:
@@ -276,12 +258,12 @@ The version command should return the following:
TPM Version: 01010000
Manufacturer Info: 4554485a
-You should also see the command being sent to the vtpm console as well
-as the vtpm saving its state. You should see the vtpm key being
-encrypted and stored on the vtpmmgr console.
+You should also see the command being sent to the vtpm console as well as the
+vtpm saving its state. You should see the vtpm key being encrypted and stored on
+the vtpmmgr console.
-You may wish to write a script to start your vtpm and guest together and
-to destroy the vtpm when the guest shuts down.
+You may wish to write a script to start your vtpm and guest together and to
+destroy the vtpm when the guest shuts down.
------------------------------
INTEGRATION WITH PV-GRUB
@@ -305,10 +287,69 @@ way can attest to its early boot state.
MORE INFORMATION
------------------------------
-See stubdom/vtpmmgr/README for more details about how
-the manager domain works, how to use it, and its command line
-parameters.
+See vtpmmgr.txt for more details about how the manager domain works, how to use
+it, and its command line parameters.
-See stubdom/vtpm/README for more specifics about how vtpm-stubdom
-operates and the command line options it accepts.
+------------------------------
+VTPM DOMAIN OPERATION
+------------------------------
+
+The vtpm-stubdom is a mini-OS domain that emulates a TPM for the guest OS to
+use. It is a small wrapper around the Berlios TPM emulator version 0.7.4.
+Commands are passed from the linux guest via the mini-os TPM backend driver.
+vTPM data is encrypted and stored via a disk image provided to the virtual
+machine. The key used to encrypt the data along with a hash of the vTPM's data
+is sent to the vTPM manager for secure storage and later retrieval. The vTPM
+domain communicates with the manager using a mini-os tpm front/back device pair.
+
+------------------------------------
+VTPM DOMAIN COMMAND LINE ARGUMENTS
+------------------------------------
+
+Command line arguments are passed to the domain via the 'extra' parameter in the
+VM config file. Each parameter is separated by white space. For example:
+
+extra="foo=bar baz"
+
+List of Arguments:
+------------------
+
+loglevel=<LOG>: Controls the amount of logging printed to the console.
+ The possible values for <LOG> are:
+ error
+ info (default)
+ debug
+
+clear: Start the Berlios emulator in "clear" mode. (default)
+
+save: Start the Berlios emulator in "save" mode.
+
+deactivated: Start the Berlios emulator in "deactivated" mode.
+ See the Berlios TPM emulator documentation for details
+ about the startup mode. For all normal use, always use clear
+ which is the default. You should not need to specify any of these.
+
+maintcmds=<1|0>: Enable to disable the TPM maintenance commands.
+ These commands are used by tpm manufacturers and thus
+ open a security hole. They are disabled by default.
+
+hwinitpcr=<PCRSPEC>: Initialize the virtual Platform Configuration Registers
+ (PCRs) with PCR values from the hardware TPM. Each pcr specified by
+ <PCRSPEC> will be initialized with the value of that same PCR in TPM
+ once at startup. By default all PCRs are zero initialized.
+ Value values of <PCRSPEC> are:
+ all: copy all pcrs
+ none: copy no pcrs (default)
+ <N>: copy pcr n
+ <X-Y>: copy pcrs x to y (inclusive)
+
+ These can also be combined by comma separation, for example:
+ hwinitpcrs=5,12-16
+ will copy pcrs 5, 12, 13, 14, 15, and 16.
+
+------------------------------
+REFERENCES
+------------------------------
+Berlios TPM Emulator:
+http://tpm-emulator.berlios.de/
diff --git a/docs/misc/vtpmmgr.txt b/docs/misc/vtpmmgr.txt
new file mode 100644
index 0000000..026c52b
--- /dev/null
+++ b/docs/misc/vtpmmgr.txt
@@ -0,0 +1,165 @@
+Author: Daniel De Graaf <dgdegra at tycho.nsa.gov>
+
+This document describes the operation and command line interface of
+vtpmmgr-stubdom. See docs/misc/vtpm.txt for details on the vTPM subsystem as a
+whole.
+
+================================================================================
+Overview
+================================================================================
+
+The TPM Manager has three primary functions:
+
+1. Securely store the encryption keys for vTPMs
+2. Provide a single controlled path of access to the physical TPM
+3. Provide evidence (via TPM Quotes) of the current configuration
+
+When combined with a platform that provides a trusted method for creating
+domains, the TPM Manager provides assurance that the private keys in a vTPM are
+only available in specific trusted configurations.
+
+The manager accepts commands from the vtpm-stubdom domains via the mini-os TPM
+backend driver. The vTPM manager communicates directly with hardware TPM using
+the mini-os tpm_tis driver.
+
+================================================================================
+Boot Configurations and TPM Groups
+================================================================================
+
+The TPM Manager's data is secured by using the physical TPM's seal operation,
+which allows data to be bound to specific PCRs. These PCRs are populated in the
+physical TPM during the boot process, either by the firmware/BIOS or by a
+dynamic launch environment such as TBOOT. In order to provide assurance of the
+system's security, the PCRs used to seal the TPM manager's data must contain
+measurements for domains used to bootstrap the TPM Manager and vTPMs.
+
+Because these measurements are based on hashes, they will change any time that
+any component of the system is upgraded. Since it is not possible to construct a
+list of all possible future good measurements, the job of approving
+configurations is delegated to a third party, referred to here as the system
+approval agent (SAA). The SAA is identified by its public (RSA) signature key,
+which is used to sign lists of valid configurations. A single TPM manager can
+support multiple SAAs via the use of vTPM groups. Each group is associated with
+a single SAA; this allows the creation of a multi-tenant environment where
+tenants may not all choose to trust the same SAA.
+
+Each vTPM is bound to a vTPM group at the time of its creation. Each vTPM group
+has its own AIK in the physical TPM for quotes of the hardware TPM state; when
+used with a conforming Privacy CA, this allows each group on the system to form
+the basis of a distinct identity.
+
+================================================================================
+Initial Provisioning
+================================================================================
+
+When the TPM Manager first boots up, it will create a stub vTPM group along with
+entries for any vTPMs that communicate with it. This stub group must be
+provisioned with an SAA and a boot configuration in order to survive a reboot.
+
+When a vTPM is connected to the TPM Manager using a UUID that is not recognized,
+a slot will be created in group 0 for it. In the future, this auto-creation may
+be restricted to specific UUIDs (such as the all-zero UUID) to enforce the use
+of the TPM manager as the generator of the UUID. The first vTPM to be connected
+is given administrative privileges for the TPM Manager, and should be attached
+to dom0 or a control domain in order to send provisioning commands.
+
+Provisioning a vTPM group for the system requires the public key of the SAA and
+privacy CA data used to certify the AIK (see the TPM spec for details). Once the
+group is created, a signed list of boot measurements can be installed. The
+initial group controls the ability to boot the system as a whole, and cannot be
+deleted once provisioned.
+
+================================================================================
+Command Line Arguments
+================================================================================
+
+Command line arguments are passed to the domain via the 'extra' parameter in the
+VM config file. Each parameter is separated by white space. For example:
+
+extra="foo=bar baz"
+
+Valid arguments:
+
+owner_auth=<AUTHSPEC>
+srk_auth=<AUTHSPEC>
+ Set the owner and SRK authdata for the TPM. If not specified, the
+ default is 160 zero bits (the well-known auth value). Valid values of
+ <AUTHSPEC> are:
+ well-known Use the well known auth (default)
+ hash:<HASH> Use the given 40-character ASCII hex string
+ text:<STR> Use sha1 hash of <STR>.
+
+tpmdriver=<DRIVER>
+ Choose the driver used for communication with the hardware TPM. Values
+ other than tpm_tis should only be used for testing.
+
+ The possible values of <DRIVER> are:
+ tpm_tis Direct communication with a hardware TPM 1.2. The
+ domain must have access to TPM IO memory. (default)
+ tpmfront Use the Xen tpmfront interface to talk to another
+ domain which provides access to the TPM.
+
+The following options only apply to the tpm_tis driver:
+
+tpmiomem=<ADDR>: The base address of the hardware memory pages of the TPM.
+ The default is 0xfed40000, as defined by the TCG's PC Client spec.
+
+tpmirq=<IRQ>: The irq of the hardware TPM if using interrupts. A value of
+ "probe" can be set to probe for the irq. A value of 0 disables
+ interrupts and uses polling (default 0).
+
+tpmlocality=<LOC>: Attempt to use locality <LOC> of the hardware TPM.
+ For full functionality of the TPM Manager, this should be set to "2".
+
+================================================================================
+Platform Security Assumptions
+================================================================================
+
+While the TPM Manager has the ability to check the hash of the vTPM requesting a
+key, there is currently no trusted method to inform the TPM Manager of the hash
+of each new domain. Because of this, the TPM Manager trusts the UUID key in
+Xenstore to identify a vTPM in a trusted manner. The XSM policy may be used to
+strengthen this assumption if the creation of vTPM-labeled domains is more
+constrained (for example, only permitted to a domain builder service): the only
+grants mapped by the TPM Manager should belong to vTPM domains, so restricting
+the ability to map other domain's granted pages will prevent other domains from
+directly requesting keys from the TPM Manager. The TPM Manager uses the hash of
+the XSM label of the attached vTPM as the kernel hash, so vTPMs with distinct
+labels may be further partitioned using vTPM groups.
+
+A domain with direct access to the hardware TPM will be able to decrypt the TPM
+Manager's disk image if the haredware TPM's PCR values are in a permitted
+configuration. To protect the TPM Manager's data, the list of permitted
+configurations should be chosen to include PCRs that measure the hypervisor,
+domain 0, the TPM Manager, and other critical configuration such as the XSM
+policy. If the TPM Manager is configured to use locality 2 as recommended, it
+is safe to permit the hardware domain to access locality 0 (the default in
+Linux), although concurrent use of the TPM should be avoided as it can result in
+unexpected busy errors from the TPM driver. The ability to access locality 2 of
+the TPM should be enforced using IO memory labeling in the XSM policy; the
+physical address 0xFED42xxx is always locality 2 for TPMs using the TIS driver.
+
+================================================================================
+Appendix: unsecured migration process for vtpmmgr domain upgrade
+================================================================================
+
+There is no direct upgrade supported from previous versions of the vtpmmgr
+domain due to changes in the on-disk format and the method used to seal data.
+If a vTPM domain supports migration, this feature should be used to migrate the
+vTPM's data; however, the vTPM packaged with Xen does not yet support migration.
+
+If adding migration support to the vTPM is not desired, a simpler migration
+domain usable only for local migration can be constructed. The migration process
+would look like the following:
+
+1. Start the old vtpmmgr
+2. Start the vTPM migration domain
+3. Attach the vTPM migration domain's vtpm/0 device to the old vtpmmgr
+4. Migration domain executes vtpmmgr_LoadHashKey on vtpm/0
+5. Start the new vtpmmgr, possibly shutting down the old one first
+6. Attach the vTPM migration domain's vtpm/1 device to the new vtpmmgr
+7. Migration domain executes vtpmmgr_SaveHashKey on vtpm/1
+
+This requires the migration domain to be added to the list of valid vTPM kernel
+hashes. In the current version of the vtpmmgr domain, this is the hash of the
+XSM label, not the kernel.
diff --git a/docs/misc/x86-xenpv-bootloader.markdown b/docs/misc/x86-xenpv-bootloader.markdown
new file mode 100644
index 0000000..ec8854e
--- /dev/null
+++ b/docs/misc/x86-xenpv-bootloader.markdown
@@ -0,0 +1,49 @@
+# Xen x86 PV Bootloader Protocol
+
+## Introduction
+
+One method for booting an x86 Xen PV guest is to use a PV bootloader,
+that is, a bootloader which is itself a PV kernel but which behaves as
+a bootloader (examples include the pvgrub-legacy and grub2 targeting
+Xen).
+
+In many cases the user wishes to manage this PV bootloader from within
+the guest, and therefore wishes to chainload something from the guest
+filesystem, most likely via a stage 1 PV bootloader provided by dom0.
+
+The purpose of this document is to define the paths within the guest
+filesystem where a stage 1 bootloader should look for the in-guest PV
+bootloader to load and the protocol/format expected from the
+to-be-chainloaded bootloader.
+
+## Protocol
+
+The bootloader binary should be an ELF file of the appropriate type
+(32- or 64-bit). It should contain the standard Xen ELF notes allowing
+it to be loaded by the Xen toolstack domain builder (TBD: Reference).
+
+## Path
+
+The second stage bootloader should be installed into the guest
+filesystem as:
+
+ * `/boot/xen/pvboot-<ARCH>.elf`
+
+Where `<ARCH>` is the first element of the GNU triplet e.g. one of:
+
+ * i386 (nb only i386, not i686 etc), corresponding to the Xen
+ x86\_32(p) arch;
+ * x86\_64, corresponding to the Xen x86\_64 arch;
+
+It is allowable for `/boot` to be a separate filesystem from `/` and
+therefore stage 1 bootloaders should search
+`/boot/xen/pvboot-<ARCH>.elf` and `/xen/pvboot-<ARCH>.elf` (in that
+order). The `xen` directory should be on the same filesystem as /boot
+and therefore it is not necessary to search for /pvboot-<ARCH>.elf.
+
+It is not in general possible under Xen for a bootloader to boot a
+kernel of a different width from itself, and this extends to
+chainloading from a stage one. Therefore it is permissible to have
+both `/boot/xen/pvboot-i386.elf` and `/boot/xen/pvboot-x86\_64.elf`
+present in a guest to be used by the appropriate stage 1 (e.g. for
+systems with 32-bit userspace and an optional 64-bit kernel).
diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown
index 293d5ac..0866df2 100644
--- a/docs/misc/xen-command-line.markdown
+++ b/docs/misc/xen-command-line.markdown
@@ -46,8 +46,9 @@ undefined.
### Size (`<size>`)
-A size parameter may be any integer, with a size suffix
+A size parameter may be any integer, with a single size suffix
+* `T` or `t`: TiB (2^40)
* `G` or `g`: GiB (2^30)
* `M` or `m`: MiB (2^20)
* `K` or `k`: KiB (2^10)
@@ -110,20 +111,28 @@ Specify which ACPI MADT table to parse for APIC information, if more
than one is present.
### acpi\_pstate\_strict
-> `= <integer>`
+> `= <boolean>`
+
+> Default: `false`
+
+Enforce checking that P-state transitions by the ACPI cpufreq driver
+actually result in the nominated frequency to be established. A warning
+message will be logged if that isn't the case.
### acpi\_skip\_timer\_override
> `= <boolean>`
Instruct Xen to ignore timer-interrupt override.
-Because responsibility for ACPI processing is shared between Xen and
-the domain 0 kernel this option is automatically propagated to the
-domain 0 command line
-
### acpi\_sleep
> `= s3_bios | s3_mode`
+`s3_bios` instructs Xen to invoke video BIOS initialization during S3
+resume.
+
+`s3_mode` instructs Xen to set up the boot time (option `vga=`) video
+mode during S3 resume.
+
### allowsuperpage
> `= <boolean>`
@@ -150,6 +159,15 @@ to boot on systems with the following errata:
triggerable Denial of Service. Override only if you trust all of
your PV guests.
+### apicv
+> `= <boolean>`
+
+> Default: `true`
+
+Permit Xen to use APIC Virtualisation Extensions. This is an optimisation
+available as part of VT-x, and allows hardware to take care of the guests APIC
+handling, rather than requiring emulation in Xen.
+
### apic\_verbosity
> `= verbose | debug`
@@ -164,13 +182,25 @@ Permit Xen to use "Always Running APIC Timer" support on compatible hardware
in combination with cpuidle. This option is only expected to be useful for
developers wishing Xen to fall back to older timing methods on newer hardware.
-### ats
+### asid
> `= <boolean>`
> Default: `true`
-Permits Xen to set up and use PCI Address Translation Services, which
-is required for PCI Passthrough.
+Permit Xen to use Address Space Identifiers. This is an optimisation which
+tags the TLB entries with an ID per vcpu. This allows for guest TLB flushes
+to be performed without the overhead of a complete TLB flush.
+
+### ats
+> `= <boolean>`
+
+> Default: `false`
+
+Permits Xen to set up and use PCI Address Translation Services. This is a
+performance optimisation for PCI Passthrough.
+
+**WARNING: Xen cannot currently safely use ATS because of its synchronous wait
+loops for Queued Invalidation completions.**
### availmem
> `= <size>`
@@ -197,16 +227,29 @@ Scrub free RAM during boot. This is a safety feature to prevent
accidentally leaking sensitive VM data into other VMs if Xen crashes
and reboots.
-### cachesize
+### bootscrub\_chunk
> `= <size>`
-If set, override Xen's calculation of the level 2 cache line size.
+> Default: `128M`
+
+Maximum RAM block size chunks to be scrubbed whilst holding the page heap lock
+and not running softirqs. Reduce this if softirqs are not being run frequently
+enough. Setting this to a high value may cause boot failure, particularly if
+the NMI watchdog is also enabled.
### clocksource
> `= pit | hpet | acpi`
If set, override Xen's default choice for the platform timer.
+### cmos-rtc-probe
+> `= <boolean>`
+
+> Default: `false`
+
+Flag to indicate whether to probe for a CMOS Real Time Clock irrespective of
+ACPI indicating none to be there.
+
### com1,com2
> `= <baud>[/<clock_hz>][,[DPS][,[<io-base>|pci|amt][,[<irq>][,[<port-bdf>][,[<bridge-bdf>]]]]]]`
@@ -217,19 +260,14 @@ Both option `com1` and `com2` follow the same format.
* Optionally, a clock speed measured in hz can be specified.
* `DPS` represents the number of data bits, the parity, and the number
of stop bits.
-
- `D` is an integer between 5 and 8 for the number of data bits.
-
- `P` is a single character representing the type of parity:
-
- * `n` No
- * `o` Odd
- * `e` Even
- * `m` Mark
- * `s` Space
-
- `S` is an integer 1 or 2 for the number of stop bits.
-
+ * `D` is an integer between 5 and 8 for the number of data bits.
+ * `P` is a single character representing the type of parity:
+ * `n` No
+ * `o` Odd
+ * `e` Even
+ * `m` Mark
+ * `s` Space
+ * `S` is an integer 1 or 2 for the number of stop bits.
* `<io-base>` is an integer which specifies the IO base port for UART
registers.
* `<irq>` is the IRQ number to use, or `0` to use the UART in poll
@@ -275,11 +313,22 @@ cleared. This allows a single port to be shared by two subsystems
makes sense on its own.
### console\_timestamps
-> `= <boolean>`
+> `= none | date | datems | boot`
-> Default: `false`
+> Default: `none`
+
+Specify which timestamp format Xen should use for each console line.
+
+* `none`: No timestamps
+* `date`: Date and time information
+ * `[YYYY-MM-DD HH:MM:SS]`
+* `datems`: Date and time, with milliseconds
+ * `[YYYY-MM-DD HH:MM:SS.mmm]`
+* `boot`: Seconds and microseconds since boot
+ * `[SSSSSS.uuuuuu]`
-Flag to indicate whether include a timestamp with each console line.
+For compatibility with the older boolean parameter, specifying
+`console_timestamps` alone will enable the `date` option.
### console\_to\_ring
> `= <boolean>`
@@ -292,7 +341,7 @@ into the console ring buffer.
### conswitch
> `= <switch char>[x]`
-> Default `conswitch=a`
+> Default: `conswitch=a`
Specify which character should be used to switch serial input between
Xen and dom0. The required sequence is CTRL-<switch char> three
@@ -304,6 +353,11 @@ including omission, causes Xen to automatically switch to the dom0
console during dom0 boot. Use `conswitch=ax` to keep the default switch
character, but for xen to keep the console.
+### core\_parking
+> `= power | performance`
+
+> Default: `power`
+
### cpu\_type
> `= arch_perfmon`
@@ -311,40 +365,63 @@ If set, force use of the performance counters for oprofile, rather than detectin
available support.
### cpufreq
-> `= dom0-kernel | none | xen`
+> `= dom0-kernel | none | xen[,[powersave|performance|ondemand|userspace][,<maxfreq>][,[<minfreq>][,[verbose]]]]`
> Default: `xen`
Indicate where the responsibility for driving power states lies.
+* Default governor policy is ondemand.
+* `<maxfreq>` and `<minfreq>` are integers which represent max and min processor frequencies
+ respectively.
+* `verbose` option can be included as a string or also as `verbose=<integer>`
+
### cpuid\_mask\_cpu (AMD only)
> `= fam_0f_rev_c | fam_0f_rev_d | fam_0f_rev_e | fam_0f_rev_f | fam_0f_rev_g | fam_10_rev_b | fam_10_rev_c | fam_11_rev_b`
-If the other **cpuid\_mask\_{,ext\_}e{c,d}x** options are fully set
-(unspecified on the command line), specify a pre-canned cpuid mask to
-mask the current processor down to appear as the specified processor.
-It is important to ensure that all hosts in a pool appear the same to
-guests to allow successful live migration.
+If the other **cpuid\_mask\_{,ext\_,thermal\_,l7s0\_}e{a,b,c,d}x**
+options are fully set (unspecified on the command line), specify a
+pre-canned cpuid mask to mask the current processor down to appear as
+the specified processor. It is important to ensure that all hosts in a
+pool appear the same to guests to allow successful live migration.
-### cpuid\_mask\_ ecx,edx,ext\_ecx,ext\_edx,xsave_eax
+### cpuid\_mask\_{{,ext\_}ecx,edx}
> `= <integer>`
> Default: `~0` (all bits set)
-These five command line parameters are used to specify cpuid masks to
+These four command line parameters are used to specify cpuid masks to
help with cpuid levelling across a pool of hosts. Setting a bit in
the mask indicates that the feature should be enabled, while clearing
a bit in the mask indicates that the feature should be disabled. It
is important to ensure that all hosts in a pool appear the same to
guests to allow successful live migration.
+### cpuid\_mask\_xsave\_eax (Intel only)
+> `= <integer>`
+
+> Default: `~0` (all bits set)
+
+This command line parameter is also used to specify a cpuid mask to
+help with cpuid levelling across a pool of hosts. See the description
+of the other respective options above.
+
+### cpuid\_mask\_{l7s0\_{eax,ebx},thermal\_ecx} (AMD only)
+> `= <integer>`
+
+> Default: `~0` (all bits set)
+
+These three command line parameters are also used to specify cpuid
+masks to help with cpuid levelling across a pool of hosts. See the
+description of the other respective options above.
+
### cpuidle
> `= <boolean>`
### cpuinfo
> `= <boolean>`
-### crashinfo_maxaddr
+### crashinfo\_maxaddr
> `= <size>`
> Default: `4G`
@@ -416,13 +493,13 @@ defaults of 1 and unlimited respectively are used instead.
For example, with `dom0_max_vcpus=4-8`:
- Number of
- PCPUs | Dom0 VCPUs
- 2 | 4
- 4 | 4
- 6 | 6
- 8 | 8
- 10 | 8
+> Number of
+> PCPUs | Dom0 VCPUs
+> 2 | 4
+> 4 | 4
+> 6 | 6
+> 8 | 8
+> 10 | 8
### dom0\_mem
> `= List of ( min:<size> | max:<size> | <size> )`
@@ -465,6 +542,21 @@ Practices](http://wiki.xen.org/wiki/Xen_Best_Practices#Xen_dom0_dedicated_memory
Pin dom0 vcpus to their respective pcpus
+### dom0pvh
+> `= <boolean>`
+
+> Default: `false`
+
+Flag that makes a 64bit dom0 boot in PVH mode. No 32bit support at present.
+
+### dtuart (ARM)
+> `= path [,options]`
+
+> Default: `""`
+
+Specify the full path in the device tree for the UART. If the path doesn't
+start with `/`, it is assumed to be an alias. The options are device specific.
+
### e820-mtrr-clip
> `= <boolean>`
@@ -494,6 +586,13 @@ Either force retrieval of monitor EDID information via VESA DDC, or
disable it (edid=no). This option should not normally be required
except for debugging purposes.
+### efi-rs
+> `= <boolean>`
+
+> Default: `true`
+
+Force or disable use of EFI runtime services.
+
### extra\_guest\_irqs
> `= [<domU number>][,<dom0 number>]`
@@ -516,16 +615,47 @@ versa. For example to change dom0 without changing domU, use
Specify the font size when using the VESA console driver.
+### force-ept (Intel)
+> `= <boolean>`
+
+> Default: `false`
+
+Allow EPT to be enabled when VMX feature VM\_ENTRY\_LOAD\_GUEST\_PAT is not
+present.
+
+*Warning:*
+Due to CVE-2013-2212, VMX feature VM\_ENTRY\_LOAD\_GUEST\_PAT is by default
+required as a prerequisite for using EPT. If you are not using PCI Passthrough,
+or trust the guest administrator who would be using passthrough, then the
+requirement can be relaxed. This option is particularly useful for nested
+virtualization, to allow the L1 hypervisor to use EPT even if the L0 hypervisor
+does not provide VM\_ENTRY\_LOAD\_GUEST\_PAT.
+
### gdb
> `= <baud>[/<clock_hz>][,DPS[,<io-base>[,<irq>[,<port-bdf>[,<bridge-bdf>]]]] | pci | amt ] `
Specify the serial parameters for the GDB stub.
-### gnttab\_max\_nr\_frames
+### gnttab\_max\_frames
> `= <integer>`
Specify the maximum number of frames per grant table operation.
+### gnttab\_max\_maptrack\_frames
+> `= <integer>`
+
+Specify the maximum number of maptrack frames domain.
+The default value is 8 times gnttab_max_frames.
+
+### gnttab\_max\_nr\_frames
+> `= <integer>`
+
+*Deprecated*
+Use gnttab\_max\_frames and gnttab\_max\_maptrack\_frames instead.
+
+Specify the maximum number of frames per grant table operation and the
+maximum number of maptrack frames domain.
+
### guest\_loglvl
> `= <level>[/<rate-limited level>]` where level is `none | error | warning | info | debug | all`
@@ -561,15 +691,67 @@ Paging (HAP).
Flag to enable 2 MB host page table support for Hardware Assisted
Paging (HAP).
+### hardware\_dom
+> `= <domid>`
+
+> Default: `0`
+
+Enable late hardware domain creation using the specified domain ID. This is
+intended to be used when domain 0 is a stub domain which builds a disaggregated
+system including a hardware domain with the specified domain ID. This option is
+supported only when compiled with XSM\_ENABLE=y on x86.
+
+### hest\_disable
+> ` = <boolean>`
+
+> Default: `false`
+
+Control Xens use of the APEI Hardware Error Source Table, should one be found.
+
### hpetbroadcast
> `= <boolean>`
### hvm\_debug
> `= <integer>`
+The specified value is a bit mask with the individual bits having the
+following meaning:
+
+> Bit 0 - debug level 0 (unused at present)
+> Bit 1 - debug level 1 (Control Register logging)
+> Bit 2 - debug level 2 (VMX logging of MSR restores when context switching)
+> Bit 3 - debug level 3 (unused at present)
+> Bit 4 - I/O operation logging
+> Bit 5 - vMMU logging
+> Bit 6 - vLAPIC general logging
+> Bit 7 - vLAPIC timer logging
+> Bit 8 - vLAPIC interrupt logging
+> Bit 9 - vIOAPIC logging
+> Bit 10 - hypercall logging
+> Bit 11 - MSR operation logging
+
+Recognized in debug builds of the hypervisor only.
+
+### hvm\_fep
+> `= <boolean>`
+
+> Default: `false`
+
+Allow use of the Forced Emulation Prefix in HVM guests, to allow emulation of
+arbitrary instructions.
+
+This option is intended for development purposes, and is only available in
+debug builds of the hypervisor.
+
### hvm\_port80
> `= <boolean>`
+> Default: `true`
+
+Specify whether guests are to be given access to physical port 80
+(often used for debugging purposes), to override the DMI based
+detection of systems known to misbehave upon accesses to that port.
+
### highmem-start
> `= <size>`
@@ -580,10 +762,106 @@ debug hypervisor only).
> `= <integer>`
### ioapic\_ack
+> `= old | new`
+
+> Default: `new` unless directed-EOI is supported
+
### iommu
-### iommu\_inclusive\_mapping
+> `= List of [ <boolean> | force | required | intremap | qinval | snoop | sharept | dom0-passthrough | dom0-strict | amd-iommu-perdev-intremap | workaround_bios_bug | verbose | debug ]`
+
+> Sub-options:
+
+> `<boolean>`
+
+> Default: `on`
+
+>> Control the use of IOMMU(s) in the system.
+
+> All other sub-options are of boolean kind and can be prefixed with `no-` to
+> effect the inverse meaning.
+
+> `force` or `required`
+
+> Default: `false`
+
+>> Don't continue booting unless IOMMU support is found and can be initialized
+>> successfully.
+
+> `intremap`
+
+> Default: `true`
+
+>> Control the use of interrupt remapping (DMA remapping will always be enabled
+>> if IOMMU functionality is enabled).
+
+> `qinval` (VT-d)
+
+> Default: `true`
+
+>> Control the use of Queued Invalidation.
+
+> `snoop` (Intel)
+
+> Default: `true`
+
+>> Control the use of Snoop Control.
+
+> `sharept`
+
+> Default: `true`
+
+>> Control whether CPU and IOMMU page tables should be shared.
+
+> `dom0-passthrough`
+
+> Default: `false`
+
+>> Control whether to disable DMA remapping for Dom0.
+
+> `dom0-strict`
+
+> Default: `false`
+
+>> Control whether to set up DMA remapping only for the memory Dom0 actually
+>> got assigned. Implies `no-dom0-passthrough`.
+
+> `amd-iommu-perdev-intremap`
+
+> Default: `true`
+
+>> Control whether to set up interrupt remapping data structures per device
+>> rather that once for the entire system. Turning this off is making PCI
+>> device pass-through insecure and hence unsupported.
+
+> `workaround_bios_bug` (VT-d)
+
+> Default: `false`
+
+>> Causes DRHD entries without any PCI discoverable devices under them to be
+>> ignored (normally IOMMU setup fails if any of the devices listed by a DRHD
+>> entry aren't PCI discoverable).
+
+> `verbose`
+
+> Default: `false`
+
+>> Increase IOMMU code's verbosity.
+
+> `debug`
+
+> Default: `false`
+
+>> Enable IOMMU debugging code (implies `verbose`).
+
+### iommu\_inclusive\_mapping (VT-d)
> `= <boolean>`
+> Default: `false`
+
+Use this to work around firmware issues providing correct RMRR entries. Rather
+than only mapping RAM pages for IOMMU accesses for Dom0, with this option all
+pages not marked as unusable in the E820 table will get a mapping established.
+
### irq\_ratelimit
> `= <integer>`
@@ -603,10 +881,10 @@ Force the use of `[<seg>:]<bus>:<device>.<func>` as device ID of IO-APIC
ACPI table.
### lapic
+> `= <boolean>`
Force the use of use of the local APIC on a uniprocessor system, even
-if left disabled by the BIOS. This option will accept any value at
-all.
+if left disabled by the BIOS.
### lapic\_timer\_c2\_ok
> `= <boolean>`
@@ -636,12 +914,23 @@ which data structures should be deliberately allocated in low memory,
so the crash kernel may find find them. Should be used in combination
with **crashinfo_maxaddr**.
+### low\_mem\_virq\_limit
+> `= <size>`
+
+> Default: `64M`
+
+Specify the threshold below which Xen will inform dom0 that the quantity of
+free memory is getting low. Specifying `0` will disable this notification.
+
### max\_cstate
> `= <integer>`
### max\_gsi\_irqs
> `= <integer>`
+Specifies the number of interrupts to be use for pin (IO-APIC or legacy PIC)
+based interrupts. Any higher IRQs will be available for use via PCI MSI.
+
### maxcpus
> `= <integer>`
@@ -676,6 +965,13 @@ Specify if the MMConfig space should be enabled.
Force Xen to (not) use PCI-MSI, even if ACPI FADT says otherwise.
+### mtrr.show
+> `= <boolean>`
+
+> Default: `false`
+
+Print boot time MTRR state (x86 only).
+
### mwait-idle
> `= <boolean>`
@@ -703,9 +999,6 @@ Because responsibility for APIC setup is shared between Xen and the
domain 0 kernel this option is automatically propagated to the domain
0 command line.
-### nofxsr
-> `= <boolean>`
-
### noirqbalance
> `= <boolean>`
@@ -719,7 +1012,7 @@ IRQ routing issues.
> Default: `false`
Ignore the local APIC on a uniprocessor system, even if enabled by the
-BIOS. This option will accept value.
+BIOS.
### no-real-mode (x86)
> `= <boolean>`
@@ -735,11 +1028,6 @@ Do not automatically reboot after an error. This is useful for
catching debug output. Defaults to automatically reboot after 5
seconds.
-### noserialnumber
-> `= <boolean>`
-
-Disable CPU serial number reporting.
-
### nosmp
> `= <boolean>`
@@ -752,15 +1040,16 @@ Defaults to booting secondary processors.
### numa
> `= on | off | fake=<integer> | noacpi`
-Default: `on`
+> Default: `on`
### pci
> `= {no-}serr | {no-}perr`
+> Default: Signaling left as set by firmware.
+
Disable signaling of SERR (system errors) and/or PERR (parity errors)
on all PCI devices.
-Default: Signaling left as set by firmware.
### pci-phantom
> `=[<seg>:]<bus>:<device>,<stride>`
@@ -778,10 +1067,30 @@ This option can be specified more than once (up to 8 times at present).
### ple\_window
> `= <integer>`
+### psr (Intel)
+> `= List of ( cmt:<boolean> | rmid_max:<integer> )`
+
+> Default: `psr=cmt:0,rmid_max:255`
+
+Platform Shared Resource(PSR) Services. Intel Haswell and later server
+platforms offer information about the sharing of resources.
+
+To use the PSR monitoring service for a certain domain, a Resource
+Monitoring ID(RMID) is used to bind the domain to corresponding shared
+resource. RMID is a hardware-provided layer of abstraction between software
+and logical processors.
+
+The following resources are available:
+
+* Cache Monitoring Technology (Haswell and later). Information regarding the
+ L3 cache occupancy.
+ * `cmt` instructs Xen to enable/disable Cache Monitoring Technology.
+ * `rmid_max` indicates the max value for rmid.
+
### reboot
-> `= t[riple] | k[bd] | n[o] [, [w]arm | [c]old]`
+> `= t[riple] | k[bd] | a[cpi] | p[ci] | n[o] [, [w]arm | [c]old]`
-Default: `0`
+> Default: `0`
Specify the host reboot method.
@@ -789,12 +1098,16 @@ Specify the host reboot method.
`cold` instructs Xen to set the cold reboot flag.
+`no` instructs Xen to not automatically reboot after panics or crashes.
+
`triple` instructs Xen to reboot the host by causing a triple fault.
`kbd` instructs Xen to reboot the host via the keyboard controller.
`acpi` instructs Xen to reboot the host using RESET_REG in the ACPI FADT.
+`pci` instructs Xen to reboot the host using PCI reset register (port CF9).
+
### sched
> `= credit | credit2 | sedf | arinc653`
@@ -850,6 +1163,13 @@ Set the serial transmit buffer size.
Flag to enable Supervisor Mode Execution Protection
+### smap
+> `= <boolean>`
+
+> Default: `true`
+
+Flag to enable Supervisor Mode Access Prevention
+
### snb\_igd\_quirk
> `= <boolean>`
@@ -901,9 +1221,6 @@ pages) must also be specified via the tbuf\_size parameter.
### tmem\_dedup
> `= <boolean>`
-### tmem\_lock
-> `= <integer>`
-
### tmem\_shared\_auth
> `= <boolean>`
@@ -995,8 +1312,8 @@ flushes on VM entry and exit, increasing performance.
Switch on the virtualized performance monitoring unit for HVM guests.
-If the current cpu isn't supported a message like
-'VPMU: Initialization failed. ...'
+If the current cpu isn't supported a message like
+'VPMU: Initialization failed. ...'
is printed on the hypervisor serial log.
For some Intel Nehalem processors a quirk handling exist for an unknown
@@ -1010,12 +1327,14 @@ As the BTS virtualisation is not 100% safe and because of the nehalem quirk
don't use the vpmu flag on production systems with Intel cpus!
### watchdog
-> `= <boolean>`
+> `= force | <boolean>`
> Default: `false`
Run an NMI watchdog on each processor. If a processor is stuck for
-longer than the **watchdog\_timeout**, a panic occurs.
+longer than the **watchdog\_timeout**, a panic occurs. When `force` is
+specified, in addition to running an NMI watchdog on each processor,
+unknown NMIs will still be processed.
### watchdog\_timeout
> `= <integer>`
diff --git a/docs/misc/xend.tex b/docs/misc/xend.tex
deleted file mode 100644
index 1a6c687..0000000
--- a/docs/misc/xend.tex
+++ /dev/null
@@ -1,419 +0,0 @@
-% -*- mode: LaTeX -*-
-\def\seca{\chapter}
-\def\secb{\section}
-\def\secc{\subsection}
-\def\secd{\subsubsection}
-\def\refa{chapter}
-\def\refb{section}
-\def\refc{section}
-\def\refd{section}
-
-%\def\seca{\section}
-%\def\secb{\subsection}
-%\def\secc{\subsubsection}
-%\def\refa{section}
-%\def\refb{section}
-%\def\refc{section}
-
-\documentclass[11pt,twoside,final,openright]{report}
-\usepackage{a4,graphicx,setspace}
-\setstretch{1.15}
-
-\begin{document}
-
-% TITLE PAGE
-\pagestyle{empty}
-\begin{center}
-\vspace*{\fill}
-\includegraphics{figs/xenlogo.eps}
-\vfill
-\vfill
-\vfill
-\begin{tabular}{l}
-{\Huge \bf Xend} \\[4mm]
-{\huge Xen v2.0 for x86} \\[80mm]
-
-{\Large Xen is Copyright (c) 2004, The Xen Team} \\[3mm]
-{\Large University of Cambridge, UK} \\[20mm]
-{\large Last updated 30 August 2004}
-\end{tabular}
-\vfill
-\end{center}
-\cleardoublepage
-
-% TABLE OF CONTENTS
-\pagestyle{plain}
-\pagenumbering{roman}
-{ \parskip 0pt plus 1pt
- \tableofcontents }
-\cleardoublepage
-% PREPARE FOR MAIN TEXT
-\pagenumbering{arabic}
-\raggedbottom
-\widowpenalty=10000
-\clubpenalty=10000
-\parindent=0pt
-\renewcommand{\topfraction}{.8}
-\renewcommand{\bottomfraction}{.8}
-\renewcommand{\textfraction}{.2}
-\renewcommand{\floatpagefraction}{.8}
-
-\setstretch{1.15}
-
-\seca{Introduction}
-Xend is the control daemon used to manage a machine running the Xen hypervisor.
-Xend is responsible for creating and destroying domains and managing their
-resources, such as virtual block devices and virtual network interfaces.
-
-Xend exists because the Xen hypervisor itself only manages the memory image
-of a domain and its scheduling. Xen provides the event channels that connect
-a domain to its devices, but is intentionally not involved in setting them up.
-
-Xend runs as a daemon in the privileged domain 0 and uses a low-level api
-to communicate with Xen via the domain 0 kernel. Xend exports its control
-interface to its clients using HTTP. Most programming languages have
-HTTP client libraries, so this interface can be used from most popular
-languages, for example Python, Perl, C, Java.
-Xend itself is written in Python, as are most of the Xen tools.
-
-The xend interface is intended to be a complete interface for the creation
-and management of domains. It supports domain creation, shutdown, reboot,
-destruction, save, restore and migration.
-
-When xend creates a domain it creates the domain memory image and communicates
-with the device driver domain(s) to configure the devices for the domain.
-This sets up connections between the domain and backend device controllers
-in the driver domain. When a domain shuts down its memory image cannot be fully released
-unless its backend devices are released and disconnected. This is done by xend.
-In order to protect against loss of this information when xend is restarted,
-xend maintains a persistent database of domain configurations. This allows
-xend to be stopped and restarted without loss of configuration information.
-For example, in order to upgrade the xend software.
-
-\seca{Domain lifecycle}
-\secb{Domain creation}
-Xend is instructed to create a domain by posting a domain\_create message to it,
-containing the domain configuration to be instantiated. The domain configuration
-is in sxp format and is as far as possible {\em fully-bound}, that is, all
-parameters are fully-specified. The domain configuration is saved in the filesystem
-so that it can be reused later if necessary.
-
-The domain configuration specifies the domain name, memory size, kernel image
-and parameters, and all the domain devices. Xend uses the Xen api to create
-the domain memory image, and then {\em builds} the memory image for the domain
-using the kernel image. At this point the domain exists, but it cannot be run because
-it has no devices. Xend then communicates with the device driver domain to create
-the configured devices. Once the devices are created it sets up event channels
-for them between the driver domain and the new domain, and notifies the new domain
-that its devices are connected. At this point the domain can be started.
-
-Xend is also responsible for managing domain consoles. When a domain is created,
-xend sets up a console event channel to the domain, and creates a TCP listening port
-for the domain console. When a connection is accepted to the port, xend
-connects input and output for the port to the domain console channel.
-
-\secb{Domain destruction}
-When a domain terminates, because it has been shutdown or it has crashed, the
-domain resources must be released so that the domain memory image can be
-finally removed from xen. Xend monitors the domains, and is also signaled by
-xen (using a VIRQ) when a domain exits. Xend examines the domain states and
-determines which domains have exited. It then communicates with the driver domain
-to release the devices for exited domains. Xend also closes any open console
-connections and removes the TCP listeners for exited domains.
-Once all devices have been released it instructs xen to destroy the memory image.
-
-\secb{Domain restart}
-Domain restart is the xen equivalent of a machine reboot. When a domain
-exits because it has been shutdown in reboot mode, its exit code is reboot.
-When examining domains to find those that have exited and destroy them,
-xend detects those that have exited for reboot and does not completely destroy
-them. It disconnects all their devices, and detaches the console listener
-from its channel to the domain, but does not close it. Instead it schedules
-a call to rebuild the domain from its configuration. This proceeds almost
-identically to creating the domain, except that the console listener is
-reused and connected to the new domain. This allows existing console
-connections to remain connected across a domain restart. The restarted
-domain keeps the same name and domain id.
-
-The determination of when to restart a domain is in fact slightly more
-complex than described above. A domain is configured with a
-{\em restart mode}. If the restart mode is {\em onreboot}, the default,
-restart happens when the domain is shutdown normally and
-exits with code reboot. If the restart mode is {\em never} the domain is
-not restarted. If the restart mode is {\em always} the domain is always
-restarted, regardless of how it exited.
-
-In order to prevent continual domain crash causing restart loops, xend
-has a {\em minimum restart time}. Xend remembers when a domain was last
-restarted and will fail a restart that happens inside the minimum
-restart time.
-
-\seca{Devices}
-\secb{Virtual network interfaces}
-Each virtual network interface (vif) has 2 parts: the font-end device in its domain,
-and the back-end device in the driver domain. Usually the driver domain is domain 0,
-and there is a linux network device corresponding to the vif. The linux device for
-interface N on domain D is called vifD.N. When a packet is sent on the vif in the
-domain the packet is received from the linux device. The linux devices are connected
-to network interfaces using ethernet bridging.
-
-The default setup is a bridge xen-br0, with eth0 connected to it, and the routes
-for eth0 directed at xen-br0. This is controlled by the xend network setup script,
-default {\tt /etc/xen/network}, which is run when xend starts.
-
-When the vifs for a domain are created, a vif control script, default {\tt /etc/xen/vif-bridge},
-is run to connect the vif to its bridge. The default script connects the vif
-to xen-br0 and optionally sets up iptables rules to prevent IP address spoofing.
-The bridge a vif is connected to can be defined in its configuration, and this is useful
-for setting up virtual networks using several bridges.
-
-\secb{Virtual block devices}
-Virtual block devices in a domain are interfaces onto back-end device drivers
-that export physical devices to domains. In the default configuration the back-end
-driver is in domain 0 and can export any linux block device to a domain. This includes
-physical disk partitions, LVM volumes and loopback mounts of files. In fact anything
-that linux can represent as a block device can be exported to a domain as virtual
-block device.
-
-\seca{Xend invocation}
-Xend is started (by root) using the command
-\begin{verbatim}
-xend start
-\end{verbatim}
-Xend can be stopped using
-\begin{verbatim}
-xend stop
-\end{verbatim}
-Xend must be started before any domains (apart from domain 0) can be created.
-If you try to use the {\tt xm} tool when xend is not running you will get a
-'connection refused' message.
-
-\secb{Xend configuration}
-Xend reads its own configuration from {\tt /etc/xen/xend-config.sxp}, which is
-a sequence of s-expressions. The configuration parameters are:
-\begin{itemize}
-
-\item xend-port: Port xend should use for the HTTP interface (default 8000).
-
-\item xend-address: Address xend should listen on.
- Specifying 'localhost' prevents remote connections.
- Specifying the empty string '' allows all connections, and is the default.
-
-\item network-script: The script used to start/stop networking for xend (default network).
-
-\item vif-bridge: The default bridge that virtual interfaces should be connected to
- (default xen-br0).
-
-\item vif-script: The default script used to control virtual interfaces
- (default vif-bridge).
-
-\item vif-antispoof: Whether iptables should be set up to prevent IP spoofing for
- virtual interfaces (default yes).
-\end{itemize}
-
-Configuration scripts ({\it e.g.} for network-script) are looked for in {\tt /etc/xen}
-unless their name begins with '/'.
-
-Xend sends its log output to {\tt /var/log/xen/xend.log}. This is a rotating logfile,
-and logs are moved onto {\tt xend.log.1} {\it etc.} as they get large. Old logs may
-be deleted.
-
-\secb{Xend database}
-Xend needs to make some data persistent, and it uses files under {\tt /var/xen/xend-db}
-for this. The persistent data is stored in files in SXP format. Domain information
-is saved when domains are created. When xend starts it reads the file {\tt /var/xen/lastboot}
-(if it exists) to determine the last time the system was rebooted. It compares this time
-with the last reboot time in {\tt wtmp} to determine if the system has been rebooted
-since xend last ran. If the system has been rebooted xend removes all its saved data
-that is not persistent across reboots (for example domain data).
-
-\seca{Xend HTTP Interface}
- The xend interface uses HTTP 1.1 \cite{http} as its transport.
-Simple PUT and GET calls can encode parameters using the standard url-encoding
-for parameters: MIME type {\tt application/x-www-form-urlencoded}.
-When file upload is required, the {\tt multipart/form-data} encoding is used.
-See the HTML 4.1 specification for details \cite{html}.
-
-Xend functions as a webserver and supports two interfaces: one
-for web-browsers and one for programs.
-The web-browser interface returns replies in HTML and includes forms
-for interactive operations such as stopping domains and creating domains
-from an uploaded configuration. The programmatic interface usually returns replies
-in s-expression format. Both interfaces are accessed
-in exactly the same way over HTTP - the only difference is the data returned.
-
-The webserver distinguishes browsers from programs using the {\tt User-Agent}
-and {\tt Accept} headers in the HTTP request. If there is no {\tt User-Agent} or no
-{\tt Acccept} header, or {\tt Accept} includes the type {\tt application/sxp}, the
-webserver assumes the client is a program and returns SXP. Otherwise
-it assumes the client is a webserver and returns HTML.
-In some cases the return value is essentially a string, so {\tt Content-Type}
-{\tt text/plain} is returned.
-
-The HTTP api supported is listed below. All paths in it are relative to the
-server root, for example {\tt http://localhost:8000/xend}.
-As defined in the HTTP specification, we use GET for side-effect free
-operations that may safely be repeated, and POST for operations with
-side-effects. For each request we list the HTTP method (GET or POST),
-the url relative to the server root, the operation name and arguments (if any).
-The operation name is passed as request parameter 'op', and the arguments
-are passed by name. Operation name and parameters can be encoded using either
-encoding described above. We also list the corresponding api function from the
-Python client interface in {\tt xen.xend.XendClient}.
-
-\begin{itemize}
-\item {\tt GET /},\\
- {\tt xend()}:\\
- Get list of urls under xend root.
-
-\item {\tt GET /node},\\
- {\tt xend\_node()}:\\
- Get node information.
-
-\item {\tt POST /node shutdown()},\\
- {\tt xend\_node\_shutdown()}:\\
- Shutdown the node
-
-\item {\tt POST /node reboot()},\\
- {\tt xend\_node\_reboot()}:\\
- Reboot the node
-
-\item {\tt POST /node notify()}:\\
- Set node notification url
-
-\item {\tt GET /node/dmesg},\\
- {\tt xend\_node\_dmesg()}:\\
- Get xen boot message.
-
-\item {\tt GET /node/log},\\
- {\tt xend\_node\_log()}:\\
- Get xend log.
-
-\item {\tt GET /domain}\\
- {\tt xend\_domains()}:\\
- Get list of domains.
-
-\item {\tt POST /domain create(config)},\\
- {\tt xend\_domain\_create(config)}:\\
- Create a domain.
-
-\item {\tt POST /domain restore(file)},\\
- {\tt xend\_domain\_restore(filename)}:\\
- Restore a saved domain.
-
-\item {\tt GET /domain/<dom>},\\
- {\tt xend\_domain(dom)}:\\
- Get domain information.
-
-\item {\tt POST /domain/[dom] configure(config)},\\
- {\tt xend\_domain\_configure(dom, conf)}:\\
- Configure an existing domain (for internal use by restore and migrate).
-
-\item {\tt POST /domain/[dom] unpause()},\\
- {\tt xend\_domain\_unpause(dom)}:\\
- Start domain running
-
-\item {\tt POST /domain/[dom] pause()},\\
- {\tt xend\_domain\_pause(dom)}:\\
- Stop domain running.
-
-\item {\tt POST /domain/[dom] shutdown(reason)},\\
- {\tt xend\_domain\_shutdown(dom, reason)}:\\
- Shutdown domain, reason can be reboot, poweroff, halt.
-
-\item {\tt POST /domain/[dom] destroy(reason)},\\
- {\tt xend\_domain\_destroy(dom, reason)}:\\
- Destroy domain, reason can be reboot, halt.
-
-\item {\tt POST /domain/[dom] save(file)},\\
- {\tt xend\_domain\_save(dom, filename)}:\\
- Save a domain to a file.
-
-\item {\tt POST /domain/[dom] migrate(dst)},\\
- {\tt xend\_domain\_migrate(dom, dst)}:\\
- Migrate a domain.
-
-\item {\tt POST /domain/[dom] pincpu(cpu)},\\
- {\tt xend\_domain\_pincpu(self, id, cpu)}\\:
- Pin a domain to a cpu.
-
-\item {\tt POST /domain/[dom] maxmem\_set(memory)},\\
- {\tt xend\_domain\_maxmem\_set(dom, memory)}:\\
- Set domain maximum memory limit.
-
-\item {\tt POST /domain/[dom] device\_create(config)}\\
- {\tt xend\_domain\_device\_create(dom, config)}:\\
- Add a device to a domain.
-
-\item {\tt POST /domain/[dom] device\_destroy(type, index)},\\
- {\tt xend\_domain\_device\_destroy(dom, type, index)}:\\
- Delete a device from a domain
-
-\item {\tt GET /domain/[dom] vifs()},\\
- {\tt xend\_domain\_vifs(dom)}:\\
- Get virtual network interfaces.
-
-\item {\tt GET /domain/[dom] vif(vif)},\\
- {\tt xend\_domain\_vif(dom, vif)}:\\
- Get virtual network interface.
-
-\item {\tt GET /domain/[dom] vbds()},\\
- {\tt xend\_domain\_vbds(dom)}:\\
- Get virtual block devices.
-
-\item {\tt GET /domain/[dom] vbd(vbd)},\\
- {\tt xend\_domain\_vbd(dom, vbd)}:\\
- Get virtual block device.
-
-\item {\tt GET /console},\\
- {\tt xend\_consoles()}:\\
- Get list of consoles.
-
-\item {\tt GET /console/[id]}\\
- {\tt xend\_console(id)}:\\
- Get information about a console.
-
-\item {\tt GET /console/[id] disconnect()}\\
- {\tt xend\_console\_disconnect(self, id)}:\\
- Disconnect any console TCP connection.
-
-\item {\tt POST /event inject(event)}\\
- {\tt xend\_event\_inject(sxpr)}:\\
- Inject an event.
-
-\end{itemize}
-
-\secb{Xend debugging interface}
-Xend also listens on port 8001. Connecting to this port (for example via telnet)
-allows access to some debugging functions:
-\begin{itemize}
-\item help: list functions
-\item traceon: turn xend tracing on
-\item traceoff: turn xend tracing off
-\item quit: disconnect.
-\item info: list console listeners, block and network device controllers.
-\end{itemize}
-
-When tracing is on xend logs all functions calls and exceptions to
-{\tt /var/log/xen/xend.trace}.
-
-\begin{thebibliography}{99}
-
-\bibitem{html}
-HTML 4.01 Specification,\\
-http://www.w3.org/TR/html4/,\\
-W3C Recommendation, 24 December 1999.
-
-\bibitem{http}
-Hypertext Transfer Protocol -- HTTP/1.1,\\
-http://www.ietf.org/rfc/rfc2616.txt,\\
-RFC 2616, IETF 1999.
-
-\bibitem{ssh}
-http://www.openssh.org.
-
-\bibitem{stunnel}
-http://www.stunnel.org.
-
-\end{thebibliography}
-\end{document}
diff --git a/docs/misc/xenstore-paths.markdown b/docs/misc/xenstore-paths.markdown
index 70ab7f4..d94ea9d 100644
--- a/docs/misc/xenstore-paths.markdown
+++ b/docs/misc/xenstore-paths.markdown
@@ -166,11 +166,6 @@ use the xenstore-based protocol instead (see ~/control/shutdown,
below) even if the guest has advertised support for the event channel
protocol.
-#### ~/hvmloader/generation-id-address = ADDRESS [r,HVM,INTERNAL]
-
-The hexadecimal representation of the address of the domain's
-"generation id".
-
#### ~/hvmloader/allow-memory-relocate = ("1"|"0") [HVM,INTERNAL]
If the default low MMIO hole (below 4GiB) is not big enough for all
@@ -193,9 +188,22 @@ Various platform properties.
#### ~/platform/generation-id = INTEGER ":" INTEGER [HVM,INTERNAL]
-Two 64 bit values that represent the Windows Generation ID.
-Is used by the BIOS initializer to get this value.
-If not present or "0:0" (all zeroes) device will not be present to the machine.
+The lower and upper 64-bit words of the 128-bit VM Generation ID.
+
+This key is used by hvmloader to create the ACPI VM Generation ID
+device. It initialises a 16 octet region of guest memory with this
+value. The guest physical address of this region is saved in the
+HVM_PARAM_VM_GENERATION_ID_ADDR HVM parameter.
+
+If this key is not present, is empty, or is all-zeros ("0:0") then the
+ACPI device is not created.
+
+When restoring a guest, the toolstack may (in certain circumstances)
+need generate a new random generation ID and write it to guest memory
+at the guest physical address in HVM_PARAM_VM_GENERATION_ID_ADDR.
+
+See Microsoft's "Virtual Machine Generation ID" specification for the
+circumstances where the generation ID needs to be changed.
### Frontend device paths
@@ -385,6 +393,10 @@ The guest's virtual time offset from UTC in seconds.
The device model version for a domain.
+#### /libxl/$DOMID/remus/netbuf/$DEVID/ifb = STRING [n,INTERNAL]
+
+ifb device used by Remus to buffer network output from the associated vif.
+
[BLKIF]: http://xenbits.xen.org/docs/unstable/hypercall/include,public,io,blkif.h.html
[FBIF]: http://xenbits.xen.org/docs/unstable/hypercall/include,public,io,fbif.h.html
[HVMPARAMS]: http://xenbits.xen.org/docs/unstable/hypercall/include,public,hvm,params.h.html
diff --git a/docs/misc/xenstore-ring.txt b/docs/misc/xenstore-ring.txt
new file mode 100644
index 0000000..16b4d0f
--- /dev/null
+++ b/docs/misc/xenstore-ring.txt
@@ -0,0 +1,116 @@
+The xenstore ring is a datastructure stored within a single 4KiB page
+shared between the xenstore server and the guest. The ring contains
+two queues of bytes -- one in each direction -- and some signalling
+information. The [xenstore protocol](xenstore.txt) is layered on top of
+the byte streams.
+
+The xenstore ring datastructure
+===============================
+
+The following table describes the ring structure where
+ - offsets and lengths are in bytes;
+ - "Input" is used to describe the data sent to the server; and
+ - "Output" is used to describe the data sent to the domain.
+
+Offset Length Description
+-----------------------------------------------------------------
+0 1024 Input data
+1024 1024 Output data
+2048 4 Input consumer offset
+2052 4 Input producer offset
+2056 4 Output consumer offset
+2060 4 Output producer offset
+2064 4 Server feature bitmap
+2068 4 Connection state
+
+The Input data and Output data are circular buffers. Each buffer is
+associated with a pair of free-running offsets labelled "consumer" and
+"producer".
+
+A "producer" offset is the offset in the byte stream of the next byte
+to be written modulo 2^32. A "consumer" offset is the offset in the byte
+stream of the next byte to be read modulo 2^32. Implementations must
+take care to handle wraparound properly when performing arithmetic with
+these values.
+
+The byte at offset 'x' in the byte stream will be stored at offset
+'x modulo 1024' in the circular buffer.
+
+Implementations may only overwrite previously-written data if it has
+been marked as 'consumed' by the relevant consumer pointer.
+
+When the guest domain is created, there is no outstanding Input or Output
+data. However
+
+ - guests must not assume that producer or consumer pointers start
+ at zero; and
+ - guests must not assume that unused bytes in either the Input or
+ Output data buffers has any particular value.
+
+A xenstore ring is always associated with an event channel. Whenever the
+ring structure is updated the event channel must be signalled. The
+guest and server are free to inspect the contents of the ring at any
+time, not only in response to an event channel event. This implies that
+updates must be ordered carefully to ensure consistency.
+
+The xenstore server may decide to advertise some features via the
+"Server feature bitmap". The server can start advertising features
+at any time by setting bits but it will never stop advertising features
+i.e. bits will never be cleared. The guest is not permitted to write to
+the server feature bitmap. The server features are offered to the guest;
+it is up to the guest whether to use them or not. The guest should ignore
+any unknown feature bits.
+
+The following features are defined:
+
+Mask Description
+-----------------------------------------------------------------
+1 Ring reconnection (see the ring reconnection feature below)
+
+The "Connection state" field is used to request a ring close and reconnect.
+The "Connection state" field only contains valid data if the server has
+advertised the ring reconnection feature. If the feature has been advertised
+then the "Connection state" may take the following values:
+
+Value Description
+-----------------------------------------------------------------
+0 Ring is connected
+1 Ring close and reconnect is in progress (see the "ring
+ reconnection feature" described below)
+
+The ring reconnection feature
+=============================
+
+The ring reconnection feature allows the guest to ask the server to
+reset the ring to a valid initial state i.e. one in which the Input
+and Output queues contain no data and there are no outstanding requests,
+watches or transactions.
+
+The ring reconnection feature is only available if the 'Ring reconnection'
+feature bit has been set by the server in the "Server feature bitmap".
+If a server supports ring reconnection, it will guarantee to advertise
+the feature before producing or consuming any data from the Input or Output
+queues.
+
+Assuming the server has advertised the feature, the guest can initiate
+a reconnection by setting the the Connection state to 1 ("Ring close
+and reconnect is in progress") and signalling the event channel.
+The guest must now ignore all fields except the Connection state and
+wait for it to be set to 0 ("Ring is connected")
+
+The server will guarantee to
+
+ - drop any partially read or written higher-level
+ [xenstore protocol](xenstore.txt) packets it may have;
+ - empty the Input and Output queues in the xenstore ring;
+ - discard any in-flight requests
+ - discard any watches associated with the connection
+ - discard any transactions associated with the connection
+ - set the Connection state to 0 ("Ring is connected"); and
+ - signal the event channel.
+
+From the point of view of the guest, the connection has been reset on a
+packet boundary.
+
+Note that only the guest may set the Connection state to 1 and only the
+server may set it back to 0.
diff --git a/docs/misc/xl-disk-configuration.txt b/docs/misc/xl-disk-configuration.txt
index cf22397..6a2118d 100644
--- a/docs/misc/xl-disk-configuration.txt
+++ b/docs/misc/xl-disk-configuration.txt
@@ -178,6 +178,61 @@ information to be interpreted by the executable program <script>,
These scripts are normally called "block-<script>".
+direct-io-safe
+--------------
+
+Description: Disables non-O_DIRECT workaround
+Supported values: absent, present
+Mandatory: No
+Default value: absent (workaround may be enabled)
+
+There is a memory lifetime bug in some driver domain (dom0) kernels
+which can cause crashes when using O_DIRECT. The bug occurs due to a
+mismatch between the backend-visible lifetime of pages used for the
+Xen PV network protocol and that expected by the backend kernel's
+networking subsystem. This can cause crashes when using certain
+backends with certain underlying storage.
+
+See:
+ http://lists.xen.org/archives/html/xen-devel/2012-12/msg01154.html
+
+For this reason, (this version of) the Xen libxl toolstack disables
+O_DIRECT when using the qemu-based Xen PV backend ("qdisk").
+
+However, this workaround has performance and scaling implications, and
+it is only necessary if the underlying device is a network filesystem.
+If the underlying device is not, then it is good to disable it; that
+is what this option is for.
+
+This option simply requests that the workaround be disabled. (However,
+not all backends versions which use the workaround understand this
+option, so this is on a best effort basis.)
+
+It's important to note that if you are storing the VM disk on a
+network filesystem or a network block device (NFS or ISCSI) it might
+not be safe to use this option. Otherwise specifying it is safe and
+can give better performances.
+
+If in the future the bug is fixed properly this option will then be
+silently ignored.
+
+
+discard / no-discard
+---------------
+
+Description: Request that backend advertise discard support to frontend
+Supported values: discard
+ no-discard
+Mandatory: No
+Default value: discard
+
+An advisory setting for the backend driver, specifying whether to
+advertise discard support (TRIM, UNMAP) to the frontend. The real
+benefit of this option is to be able to force it off rather than on. It
+can be used to disable "hole punching" for file based backends which
+were intentionally created non-sparse to avoid fragmentation of the
+file.
+
============================================
DEPRECATED PARAMETERS, PREFIXES AND SYNTAXES
diff --git a/docs/misc/xl-numa-placement.markdown b/docs/misc/xl-numa-placement.markdown
index caa3fec..f863492 100644
--- a/docs/misc/xl-numa-placement.markdown
+++ b/docs/misc/xl-numa-placement.markdown
@@ -12,13 +12,6 @@ is quite more complex and slow. On these machines, a NUMA node is usually
defined as a set of processor cores (typically a physical CPU package) and
the memory directly attached to the set of cores.
-The Xen hypervisor deals with NUMA machines by assigning to each domain
-a "node affinity", i.e., a set of NUMA nodes of the host from which they
-get their memory allocated. Also, even if the node affinity of a domain
-is allowed to change on-line, it is very important to "place" the domain
-correctly when it is fist created, as the most of its memory is allocated
-at that time and can not (for now) be moved easily.
-
NUMA awareness becomes very important as soon as many domains start
running memory-intensive workloads on a shared host. In fact, the cost
of accessing non node-local memory locations is very high, and the
@@ -27,14 +20,37 @@ performance degradation is likely to be noticeable.
For more information, have a look at the [Xen NUMA Introduction][numa_intro]
page on the Wiki.
+## Xen and NUMA machines: the concept of _node-affinity_ ##
+
+The Xen hypervisor deals with NUMA machines throughout the concept of
+_node-affinity_. The node-affinity of a domain is the set of NUMA nodes
+of the host where the memory for the domain is being allocated (mostly,
+at domain creation time). This is, at least in principle, different and
+unrelated with the vCPU (hard and soft, see below) scheduling affinity,
+which instead is the set of pCPUs where the vCPU is allowed (or prefers)
+to run.
+
+Of course, despite the fact that they belong to and affect different
+subsystems, the domain node-affinity and the vCPUs affinity are not
+completely independent.
+In fact, if the domain node-affinity is not explicitly specified by the
+user, via the proper libxl calls or xl config item, it will be computed
+basing on the vCPUs' scheduling affinity.
+
+Notice that, even if the node affinity of a domain may change on-line,
+it is very important to "place" the domain correctly when it is fist
+created, as the most of its memory is allocated at that time and can
+not (for now) be moved easily.
+
### Placing via pinning and cpupools ###
-The simplest way of placing a domain on a NUMA node is statically pinning
-the domain's vCPUs to the pCPUs of the node. This goes under the name of
-CPU affinity and can be set through the "cpus=" option in the config file
-(more about this below). Another option is to pool together the pCPUs
-spanning the node and put the domain in such a cpupool with the "pool="
-config option (as documented in our [Wiki][cpupools_howto]).
+The simplest way of placing a domain on a NUMA node is setting the hard
+scheduling affinity of the domain's vCPUs to the pCPUs of the node. This
+also goes under the name of vCPU pinning, and can be done through the
+"cpus=" option in the config file (more about this below). Another option
+is to pool together the pCPUs spanning the node and put the domain in
+such a _cpupool_ with the "pool=" config option (as documented in our
+[Wiki][cpupools_howto]).
In both the above cases, the domain will not be able to execute outside
the specified set of pCPUs for any reasons, even if all those pCPUs are
@@ -45,24 +61,45 @@ may come at he cost of some load imbalances.
### NUMA aware scheduling ###
-If the credit scheduler is in use, the concept of node affinity defined
-above does not only apply to memory. In fact, starting from Xen 4.3, the
-scheduler always tries to run the domain's vCPUs on one of the nodes in
-its node affinity. Only if that turns out to be impossible, it will just
-pick any free pCPU.
-
-This is, therefore, something more flexible than CPU affinity, as a domain
-can still run everywhere, it just prefers some nodes rather than others.
-Locality of access is less guaranteed than in the pinning case, but that
-comes along with better chances to exploit all the host resources (e.g.,
-the pCPUs).
-
-In fact, if all the pCPUs in a domain's node affinity are busy, it is
-possible for the domain to run outside of there, but it is very likely that
-slower execution (due to remote memory accesses) is still better than no
-execution at all, as it would happen with pinning. For this reason, NUMA
-aware scheduling has the potential of bringing substantial performances
-benefits, although this will depend on the workload.
+If using the credit1 scheduler, and starting from Xen 4.3, the scheduler
+itself always tries to run the domain's vCPUs on one of the nodes in
+its node-affinity. Only if that turns out to be impossible, it will just
+pick any free pCPU. Locality of access is less guaranteed than in the
+pinning case, but that comes along with better chances to exploit all
+the host resources (e.g., the pCPUs).
+
+Starting from Xen 4.5, credit1 supports two forms of affinity: hard and
+soft, both on a per-vCPU basis. This means each vCPU can have its own
+soft affinity, stating where such vCPU prefers to execute on. This is
+less strict than what it (also starting from 4.5) is called hard affinity,
+as the vCPU can potentially run everywhere, it just prefers some pCPUs
+rather than others.
+In Xen 4.5, therefore, NUMA-aware scheduling is achieved by matching the
+soft affinity of the vCPUs of a domain with its node-affinity.
+
+In fact, as it was for 4.3, if all the pCPUs in a vCPU's soft affinity
+are busy, it is possible for the domain to run outside from there. The
+idea is that slower execution (due to remote memory accesses) is still
+better than no execution at all (as it would happen with pinning). For
+this reason, NUMA aware scheduling has the potential of bringing
+substantial performances benefits, although this will depend on the
+workload.
+
+Notice that, for each vCPU, the following three scenarios are possbile:
+
+ * a vCPU *is pinned* to some pCPUs and *does not have* any soft affinity
+ In this case, the vCPU is always scheduled on one of the pCPUs to which
+ it is pinned, without any specific peference among them.
+ * a vCPU *has* its own soft affinity and *is not* pinned to any particular
+ pCPU. In this case, the vCPU can run on every pCPU. Nevertheless, the
+ scheduler will try to have it running on one of the pCPUs in its soft
+ affinity;
+ * a vCPU *has* its own vCPU soft affinity and *is also* pinned to some
+ pCPUs. In this case, the vCPU is always scheduled on one of the pCPUs
+ onto which it is pinned, with, among them, a preference for the ones
+ that also forms its soft affinity. In case pinning and soft affinity
+ form two disjoint sets of pCPUs, pinning "wins", and the soft affinity
+ is just ignored.
## Guest placement in xl ##
@@ -71,33 +108,43 @@ both manual or automatic placement of them across the host's NUMA nodes.
Note that xm/xend does a very similar thing, the only differences being
the details of the heuristics adopted for automatic placement (see below),
-and the lack of support (in both xm/xend and the Xen versions where that\
+and the lack of support (in both xm/xend and the Xen versions where that
was the default toolstack) for NUMA aware scheduling.
### Placing the guest manually ###
Thanks to the "cpus=" option, it is possible to specify where a domain
should be created and scheduled on, directly in its config file. This
-affects NUMA placement and memory accesses as the hypervisor constructs
-the node affinity of a VM basing right on its CPU affinity when it is
-created.
+affects NUMA placement and memory accesses as, in this case, the
+hypervisor constructs the node-affinity of a VM basing right on its
+vCPU pinning when it is created.
This is very simple and effective, but requires the user/system
-administrator to explicitly specify affinities for each and every domain,
+administrator to explicitly specify the pinning for each and every domain,
or Xen won't be able to guarantee the locality for their memory accesses.
-Notice that this also pins the domain's vCPUs to the specified set of
-pCPUs, so it not only sets the domain's node affinity (its memory will
-come from the nodes to which the pCPUs belong), but at the same time
-forces the vCPUs of the domain to be scheduled on those same pCPUs.
+That, of course, also mean the vCPUs of the domain will only be able to
+execute on those same pCPUs.
+
+It is is also possible to have a "cpus\_soft=" option in the xl config file,
+to specify the soft affinity for all the vCPUs of the domain. This affects
+the NUMA placement in the following way:
+
+ * if only "cpus\_soft=" is present, the VM's node-affinity will be equal
+ to the nodes to which the pCPUs in the soft affinity mask belong;
+ * if both "cpus\_soft=" and "cpus=" are present, the VM's node-affinity
+ will be equal to the nodes to which the pCPUs present both in hard and
+ soft affinity belong.
### Placing the guest automatically ###
-If no "cpus=" option is specified in the config file, libxl tries
-to figure out on its own on which node(s) the domain could fit best.
+If neither "cpus=" nor "cpus\_soft=" are present in the config file, libxl
+tries to figure out on its own on which node(s) the domain could fit best.
If it finds one (some), the domain's node affinity get set to there,
and both memory allocations and NUMA aware scheduling (for the credit
-scheduler and starting from Xen 4.3) will comply with it.
+scheduler and starting from Xen 4.3) will comply with it. Starting from
+Xen 4.5, this also means that the mask resulting from this "fitting"
+procedure will become the soft affinity of all the vCPUs of the domain.
It is worthwhile noting that optimally fitting a set of VMs on the NUMA
nodes of an host is an incarnation of the Bin Packing Problem. In fact,
@@ -142,34 +189,43 @@ any placement from happening:
libxl_defbool_set(&domain_build_info->numa_placement, false);
-Also, if `numa_placement` is set to `true`, the domain must not
-have any CPU affinity (i.e., `domain_build_info->cpumap` must
-have all its bits set, as it is by default), or domain creation
-will fail returning `ERROR_INVAL`.
+Also, if `numa_placement` is set to `true`, the domain's vCPUs must
+not be pinned (i.e., `domain_build_info->cpumap` must have all its
+bits set, as it is by default), or domain creation will fail with
+`ERROR_INVAL`.
Starting from Xen 4.3, in case automatic placement happens (and is
-successful), it will affect the domain's node affinity and _not_ its
-CPU affinity. Namely, the domain's vCPUs will not be pinned to any
+successful), it will affect the domain's node-affinity and _not_ its
+vCPU pinning. Namely, the domain's vCPUs will not be pinned to any
pCPU on the host, but the memory from the domain will come from the
selected node(s) and the NUMA aware scheduling (if the credit scheduler
-is in use) will try to keep the domain there as much as possible.
+is in use) will try to keep the domain's vCPUs there as much as possible.
Besides than that, looking and/or tweaking the placement algorithm
search "Automatic NUMA placement" in libxl\_internal.h.
Note this may change in future versions of Xen/libxl.
+## Xen < 4.5 ##
+
+The concept of vCPU soft affinity has been introduced for the first time
+in Xen 4.5. In 4.3, it is the domain's node-affinity that drives the
+NUMA-aware scheduler. The main difference is soft affinity is per-vCPU,
+and so each vCPU can have its own mask of pCPUs, while node-affinity is
+per-domain, that is the equivalent of having all the vCPUs with the same
+soft affinity.
+
## Xen < 4.3 ##
As NUMA aware scheduling is a new feature of Xen 4.3, things are a little
bit different for earlier version of Xen. If no "cpus=" option is specified
and Xen 4.2 is in use, the automatic placement algorithm still runs, but
the results is used to _pin_ the vCPUs of the domain to the output node(s).
-This is consistent with what was happening with xm/xend, which were also
-affecting the domain's CPU affinity.
+This is consistent with what was happening with xm/xend.
On a version of Xen earlier than 4.2, there is not automatic placement at
-all in xl or libxl, and hence no node or CPU affinity being affected.
+all in xl or libxl, and hence no node-affinity, vCPU affinity or pinning
+being introduced/modified.
## Limitations ##
diff --git a/docs/misc/xsm-flask.txt b/docs/misc/xsm-flask.txt
index ddd5831..9559028 100644
--- a/docs/misc/xsm-flask.txt
+++ b/docs/misc/xsm-flask.txt
@@ -64,71 +64,38 @@ __HYPERVISOR_domctl (xen/include/public/domctl.h)
* XEN_DOMCTL_createdomain
* XEN_DOMCTL_destroydomain
- * XEN_DOMCTL_pausedomain
- * XEN_DOMCTL_unpausedomain
- * XEN_DOMCTL_getdomaininfo
* XEN_DOMCTL_getmemlist
- * XEN_DOMCTL_getpageframeinfo
- * XEN_DOMCTL_getpageframeinfo2
* XEN_DOMCTL_setvcpuaffinity
* XEN_DOMCTL_shadow_op
* XEN_DOMCTL_max_mem
* XEN_DOMCTL_setvcpucontext
* XEN_DOMCTL_getvcpucontext
- * XEN_DOMCTL_getvcpuinfo
* XEN_DOMCTL_max_vcpus
* XEN_DOMCTL_scheduler_op
- * XEN_DOMCTL_setdomainhandle
- * XEN_DOMCTL_setdebugging
- * XEN_DOMCTL_irq_permission
* XEN_DOMCTL_iomem_permission
- * XEN_DOMCTL_ioport_permission
- * XEN_DOMCTL_hypercall_init
- * XEN_DOMCTL_arch_setup
- * XEN_DOMCTL_settimeoffset
- * XEN_DOMCTL_getvcpuaffinity
- * XEN_DOMCTL_real_mode_area
- * XEN_DOMCTL_resumedomain
- * XEN_DOMCTL_sendtrigger
- * XEN_DOMCTL_subscribe
* XEN_DOMCTL_gethvmcontext
* XEN_DOMCTL_sethvmcontext
* XEN_DOMCTL_set_address_size
- * XEN_DOMCTL_get_address_size
* XEN_DOMCTL_assign_device
* XEN_DOMCTL_pin_mem_cacheattr
* XEN_DOMCTL_set_ext_vcpucontext
* XEN_DOMCTL_get_ext_vcpucontext
- * XEN_DOMCTL_set_opt_feature
* XEN_DOMCTL_test_assign_device
* XEN_DOMCTL_set_target
* XEN_DOMCTL_deassign_device
- * XEN_DOMCTL_set_cpuid
* XEN_DOMCTL_get_device_group
* XEN_DOMCTL_set_machine_address_size
- * XEN_DOMCTL_get_machine_address_size
- * XEN_DOMCTL_suppress_spurious_page_faults
* XEN_DOMCTL_debug_op
* XEN_DOMCTL_gethvmcontext_partial
* XEN_DOMCTL_mem_event_op
* XEN_DOMCTL_mem_sharing_op
- * XEN_DOMCTL_disable_migrate
- * XEN_DOMCTL_gettscinfo
- * XEN_DOMCTL_settscinfo
- * XEN_DOMCTL_getpageframeinfo3
* XEN_DOMCTL_setvcpuextstate
* XEN_DOMCTL_getvcpuextstate
* XEN_DOMCTL_set_access_required
- * XEN_DOMCTL_audit_p2m
* XEN_DOMCTL_set_virq_handler
* XEN_DOMCTL_set_broken_page_p2m
* XEN_DOMCTL_setnodeaffinity
- * XEN_DOMCTL_getnodeaffinity
- * XEN_DOMCTL_set_max_evtchn
* XEN_DOMCTL_gdbsx_guestmemio
- * XEN_DOMCTL_gdbsx_pausevcpu
- * XEN_DOMCTL_gdbsx_unpausevcpu
- * XEN_DOMCTL_gdbsx_domstatus
__HYPERVISOR_sysctl (xen/include/public/sysctl.h)
diff --git a/extras/mini-os/Config.mk b/extras/mini-os/Config.mk
index d61877b..4852443 100644
--- a/extras/mini-os/Config.mk
+++ b/extras/mini-os/Config.mk
@@ -46,7 +46,7 @@ DEF_CPPFLAGS += -D__MINIOS__
ifeq ($(libc),y)
DEF_CPPFLAGS += -DHAVE_LIBC
DEF_CPPFLAGS += -isystem $(MINI-OS_ROOT)/include/posix
-DEF_CPPFLAGS += -isystem $(XEN_ROOT)/tools/xenstore
+DEF_CPPFLAGS += -isystem $(XEN_ROOT)/tools/xenstore/include
endif
ifneq ($(LWIPDIR),)
diff --git a/extras/mini-os/Makefile b/extras/mini-os/Makefile
index 50d038b..6d6537e 100644
--- a/extras/mini-os/Makefile
+++ b/extras/mini-os/Makefile
@@ -50,6 +50,11 @@ flags-$(CONFIG_XENBUS) += -DCONFIG_XENBUS
DEF_CFLAGS += $(flags-y)
+# Symlinks and headers that must be created before building the C files
+GENERATED_HEADERS := include/list.h $(ARCH_LINKS) include/mini-os include/xen include/$(TARGET_ARCH_FAM)/mini-os
+
+EXTRA_DEPS += $(GENERATED_HEADERS)
+
# Include common mini-os makerules.
include minios.mk
@@ -124,11 +129,18 @@ include/list.h: $(XEN_ROOT)/tools/include/xen-external/bsd-sys-queue-h-seddery $
perl $^ --prefix=minios >$@.new
$(call move-if-changed,$@.new,$@)
+# Used by stubdom's Makefile
.PHONY: links
-links: include/list.h $(ARCH_LINKS)
- [ -e include/xen ] || ln -sf ../../../xen/include/public include/xen
- [ -e include/mini-os ] || ln -sf . include/mini-os
- [ -e include/$(TARGET_ARCH_FAM)/mini-os ] || ln -sf . include/$(TARGET_ARCH_FAM)/mini-os
+links: $(GENERATED_HEADERS)
+
+include/xen:
+ ln -sf ../../../xen/include/public $@
+
+include/mini-os:
+ ln -sf . $@
+
+include/$(TARGET_ARCH_FAM)/mini-os:
+ ln -sf . $@
.PHONY: arch_lib
arch_lib:
@@ -174,7 +186,7 @@ ifneq ($(APP_OBJS),)
APP_O=$(OBJ_DIR)/$(TARGET)_app.o
endif
-$(OBJ_DIR)/$(TARGET): links include/list.h $(OBJS) $(APP_O) arch_lib
+$(OBJ_DIR)/$(TARGET): $(OBJS) $(APP_O) arch_lib
$(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(APP_O) $(OBJS) $(LDARCHLIB) $(LDLIBS) -o $@.o
$(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start $@.o $@.o
$(LD) $(LDFLAGS) $(LDFLAGS_FINAL) $@.o $(EXTRA_OBJS) -o $@
@@ -212,4 +224,3 @@ tags:
.PHONY: TAGS
TAGS:
$(all_sources) | xargs etags
-
diff --git a/extras/mini-os/README b/extras/mini-os/README
index 710a303..7960314 100644
--- a/extras/mini-os/README
+++ b/extras/mini-os/README
@@ -25,8 +25,8 @@ This includes:
- to build it with much better libc support, see the stubdom/ directory
-- to start it do the following in domain0 (assuming xend is running)
- # xm create domain_config
+- to start it do the following in domain0
+ # xl create -c domain_config
This starts the kernel and prints out a bunch of stuff and then once every
second the system time.
diff --git a/extras/mini-os/arch/arm/arm32.S b/extras/mini-os/arch/arm/arm32.S
new file mode 100644
index 0000000..73223c8
--- /dev/null
+++ b/extras/mini-os/arch/arm/arm32.S
@@ -0,0 +1,233 @@
+@ Offset of the kernel within the RAM. This is a Linux/zImage convention which we
+@ rely on for now.
+#define ZIMAGE_KERNEL_OFFSET 0x8000
+
+.section .text
+
+.globl _start
+_start:
+ @ zImage header
+.rept 8
+ mov r0, r0
+.endr
+ b reset
+ .word 0x016f2818 @ Magic numbers to help the loader
+ .word 0 @ zImage start address (0 = relocatable)
+ .word _edata - _start @ zImage end address (excludes bss section)
+ @ end of zImage header
+
+@ Called at boot time. Sets up MMU, exception vectors and stack, and then calls C arch_init() function.
+@ => r2 -> DTB
+@ <= never returns
+@ Note: this boot code needs to be within the first (1MB - ZIMAGE_KERNEL_OFFSET) of _start.
+reset:
+ @ Problem: the C code wants to be at a known address (_start), but Xen might
+ @ load us anywhere. We initialise the MMU (mapping virtual to physical @ addresses)
+ @ so everything ends up where the code expects it to be.
+ @
+ @ We calculate the offet between where the linker thought _start would be and where
+ @ it actually is and initialise the page tables to have that offset for every page.
+ @
+ @ When we turn on the MMU, we're still executing at the old address. We don't want
+ @ the code to disappear from under us. So we have to do the mapping in stages:
+ @
+ @ 1. set up a mapping to our current page from both its current and desired addresses
+ @ 2. enable the MMU
+ @ 3. jump to the new address
+ @ 4. remap all the other pages with the calculated offset
+
+ adr r1, _start @ r1 = physical address of _start
+ ldr r3, =_start @ r3 = (desired) virtual address of _start
+ sub r9, r1, r3 @ r9 = (physical - virtual) offset
+
+ ldr r7, =_page_dir @ r7 = (desired) virtual addr of translation table
+ add r1, r7, r9 @ r1 = physical addr of translation table
+
+ @ Tell the system where our page table is located.
+ @ This is the 16 KB top-level translation table, in which
+ @ each word maps one 1MB virtual section to a physical section.
+ @ Note: We leave TTBCR as 0, meaning that only TTBR0 is used and
+ @ we use the short-descriptor format (32-bit physical addresses).
+ orr r0, r1, #0b0001011 @ Sharable, Inner/Outer Write-Back Write-Allocate Cacheable
+ mcr p15, 0, r0, c2, c0, 0 @ set TTBR0
+
+ @ Set access permission for domains.
+ @ Domains are deprecated, but we have to configure them anyway.
+ @ We mark every page as being domain 0 and set domain 0 to "client mode"
+ @ (client mode = use access flags in page table).
+ mov r0, #1 @ 1 = client
+ mcr p15, 0, r0, c3, c0, 0 @ DACR
+
+ @ Template (flags) for a 1 MB page-table entry.
+ @ TEX[2:0] C B = 001 1 1 (outer and inner write-back, write-allocate)
+ ldr r8, =(0x2 + /* Section entry */ \
+ 0xc + /* C B */ \
+ (3 << 10) + /* Read/write */ \
+ (1 << 12) + /* TEX */ \
+ (1 << 16) + /* Sharable */ \
+ (1<<19)) /* Non-secure */
+ @ r8 = template page table entry
+
+ @ Add an entry for the current physical section, at the old and new
+ @ addresses. It's OK if they're the same.
+ mov r0, pc, lsr#20
+ mov r0, r0, lsl#20 @ r0 = physical address of this code's section start
+ orr r3, r0, r8 @ r3 = table entry for this section
+ ldr r4, =_start @ r4 = desired virtual address of this section
+ str r3, [r1, r4, lsr#18] @ map desired virtual section to this code
+ str r3, [r1, r0, lsr#18] @ map current section to this code too
+
+ @ Invalidate TLB
+ dsb @ Caching is off, but must still prevent reordering
+ mcr p15, 0, r1, c8, c7, 0 @ TLBIALL
+
+ @ Enable MMU / SCTLR
+ mrc p15, 0, r1, c1, c0, 0 @ SCTLR
+ orr r1, r1, #3 << 11 @ enable icache, branch prediction
+ orr r1, r1, #4 + 1 @ enable dcache, MMU
+ mcr p15, 0, r1, c1, c0, 0 @ SCTLR
+ isb
+
+ ldr r1, =stage2 @ Virtual address of stage2
+ bx r1
+
+@ Called once the MMU is enabled. The boot code and the page table are mapped,
+@ but nothing else is yet.
+@
+@ => r2 -> dtb (physical)
+@ r7 = virtual address of page table
+@ r8 = section entry template (flags)
+@ r9 = desired physical - virtual offset
+@ pc -> somewhere in newly-mapped virtual code section
+stage2:
+ @ Invalidate TLB
+ mcr p15, 0, r1, c8, c7, 0 @ TLBIALL
+ isb
+
+ @ The new mapping has now taken effect:
+ @ r7 -> page_dir
+
+ @ Fill in the whole top-level translation table (at page_dir).
+ @ Populate the whole pagedir with 1MB section descriptors.
+
+ mov r1, r7 @ r1 -> first section entry
+ add r3, r1, #4*4*1024 @ limit (4 GB address space, 4 byte entries)
+ orr r0, r8, r9 @ r0 = entry mapping section zero to start of physical RAM
+1:
+ str r0, [r1],#4 @ write the section entry
+ add r0, r0, #1 << 20 @ next physical page (wraps)
+ cmp r1, r3
+ bne 1b
+
+ @ Invalidate TLB
+ dsb
+ mcr p15, 0, r1, c8, c7, 0 @ TLBIALL
+ isb
+
+ @ Set VBAR -> exception_vector_table
+ @ SCTLR.V = 0
+ adr r0, exception_vector_table
+ mcr p15, 0, r0, c12, c0, 0
+
+ @ Enable hardware floating point:
+ @ 1. Access to CP10 and CP11 must be enabled in the Coprocessor Access
+ @ Control Register (CP15.CACR):
+ mrc p15, 0, r1, c1, c0, 2 @ CACR
+ orr r1, r1, #(3 << 20) + (3 << 22) @ full access for CP10 & CP11
+ mcr p15, 0, r1, c1, c0, 2
+ @ 2. The EN bit in the FPEXC register must be set:
+ vmrs r0, FPEXC
+ orr r0, r0, #1<<30 @ EN (enable)
+ vmsr FPEXC, r0
+
+ @ Initialise 16 KB stack
+ ldr sp, =_boot_stack_end
+
+ sub r0, r2, r9 @ r0 -> device tree (virtual address)
+ mov r1, r9 @ r1 = physical_address_offset
+
+ b arch_init
+
+.pushsection .bss
+@ Note: calling arch_init zeroes out this region.
+.align 12
+.globl shared_info_page
+shared_info_page:
+ .fill (1024), 4, 0x0
+
+.align 3
+.globl irqstack
+.globl irqstack_end
+irqstack:
+ .fill (1024), 4, 0x0
+irqstack_end:
+
+.popsection
+
+@ exception base address
+.align 5
+.globl exception_vector_table
+@ Note: remember to call CLREX if returning from an exception:
+@ "The architecture enables the local monitor to treat any exclusive store as
+@ matching a previous LDREX address. For this reason, use of the CLREX
+@ instruction to clear an existing tag is required on context switches."
+@ -- ARM Cortex-A Series Programmer’s Guide (Version: 4.0)
+exception_vector_table:
+ b . @ reset
+ b . @ undefined instruction
+ b . @ supervisor call
+ b . @ prefetch call
+ b . @ prefetch abort
+ b . @ data abort
+ b irq_handler @ irq
+ .word 0xe7f000f0 @ abort on FIQ
+
+@ Call fault_undefined_instruction in "Undefined mode"
+bug:
+ .word 0xe7f000f0 @ und/udf - a "Permanently Undefined" instruction
+
+irq_handler:
+ ldr sp, =irqstack_end
+ push {r0 - r12, r14}
+
+ ldr r0, IRQ_handler
+ cmp r0, #0
+ beq bug
+ blx r0 @ call handler
+
+ @ Return from IRQ
+ pop {r0 - r12, r14}
+ clrex
+ subs pc, lr, #4
+
+.globl IRQ_handler
+IRQ_handler:
+ .long 0x0
+
+
+.globl __arch_switch_threads
+@ => r0 = &prev->sp
+@ r1 = &next->sp
+@ <= returns to next thread's saved return address
+__arch_switch_threads:
+ push {r4-r11} @ Store callee-saved registers to old thread's stack
+ stmia r0, {sp, lr} @ Store current sp and ip to prev's struct thread
+
+ ldmia r1, {sp, lr} @ Load new sp, ip from next's struct thread
+ pop {r4-r11} @ Load callee-saved registers from new thread's stack
+
+ bx lr
+
+@ This is called if you try to divide by zero. For now, we make a supervisor call,
+@ which will make us halt.
+.globl raise
+raise:
+ svc 0
+
+.globl arm_start_thread
+arm_start_thread:
+ pop {r0, r1}
+ @ r0 = user data
+ @ r1 -> thread's main function
+ ldr lr, =exit_thread
+ bx r1
diff --git a/extras/mini-os/arch/arm/events.c b/extras/mini-os/arch/arm/events.c
new file mode 100644
index 0000000..441010d
--- /dev/null
+++ b/extras/mini-os/arch/arm/events.c
@@ -0,0 +1,31 @@
+#include <mini-os/os.h>
+#include <mini-os/events.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/console.h>
+
+static void virq_debug(evtchn_port_t port, struct pt_regs *regs, void *params)
+{
+ printk("Received a virq_debug event\n");
+}
+
+evtchn_port_t debug_port = -1;
+void arch_init_events(void)
+{
+ debug_port = bind_virq(VIRQ_DEBUG, (evtchn_handler_t)virq_debug, 0);
+ if(debug_port == -1)
+ BUG();
+ unmask_evtchn(debug_port);
+}
+
+void arch_unbind_ports(void)
+{
+ if(debug_port != -1)
+ {
+ mask_evtchn(debug_port);
+ unbind_evtchn(debug_port);
+ }
+}
+
+void arch_fini_events(void)
+{
+}
diff --git a/extras/mini-os/arch/arm/hypercalls32.S b/extras/mini-os/arch/arm/hypercalls32.S
new file mode 100644
index 0000000..af8e175
--- /dev/null
+++ b/extras/mini-os/arch/arm/hypercalls32.S
@@ -0,0 +1,64 @@
+/******************************************************************************
+ * hypercall.S
+ *
+ * Xen hypercall wrappers
+ *
+ * Stefano Stabellini <stefano.stabellini at eu.citrix.com>, Citrix, 2012
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (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 <xen/xen.h>
+
+#define __HVC(imm16) .long ((0xE1400070 | (((imm16) & 0xFFF0) << 4) | ((imm16) & 0x000F)) & 0xFFFFFFFF)
+
+#define XEN_IMM 0xEA1
+
+#define HYPERCALL_SIMPLE(hypercall) \
+.globl HYPERVISOR_##hypercall; \
+.align 4,0x90; \
+HYPERVISOR_##hypercall: \
+ mov r12, #__HYPERVISOR_##hypercall; \
+ __HVC(XEN_IMM); \
+ mov pc, lr;
+
+#define _hypercall0 HYPERCALL_SIMPLE
+#define _hypercall1 HYPERCALL_SIMPLE
+#define _hypercall2 HYPERCALL_SIMPLE
+#define _hypercall3 HYPERCALL_SIMPLE
+#define _hypercall4 HYPERCALL_SIMPLE
+
+_hypercall2(sched_op);
+_hypercall2(memory_op);
+_hypercall2(event_channel_op);
+_hypercall2(xen_version);
+_hypercall3(console_io);
+_hypercall1(physdev_op);
+_hypercall3(grant_table_op);
+_hypercall3(vcpu_op);
+_hypercall1(sysctl);
+_hypercall1(domctl);
+_hypercall2(hvm_op);
+_hypercall1(xsm_op);
diff --git a/extras/mini-os/arch/arm/minios-arm32.lds b/extras/mini-os/arch/arm/minios-arm32.lds
new file mode 100755
index 0000000..9627162
--- /dev/null
+++ b/extras/mini-os/arch/arm/minios-arm32.lds
@@ -0,0 +1,83 @@
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ /* Note: we currently assume that Xen will load the kernel image
+ * at start-of-RAM + 0x8000. We use this initial 32 KB for the stack
+ * and translation tables.
+ */
+ _boot_stack = 0x400000; /* 16 KB boot stack */
+ _boot_stack_end = 0x404000;
+ _page_dir = 0x404000; /* 16 KB translation table */
+ . = 0x408000;
+ _text = .; /* Text and read-only data */
+ .text : {
+ *(.text)
+ *(.gnu.warning)
+ } = 0x9090
+
+ _etext = .; /* End of text section */
+
+ .rodata : { *(.rodata) *(.rodata.*) }
+ . = ALIGN(4096);
+ _erodata = .;
+
+ /* newlib initialization functions */
+ . = ALIGN(32 / 8);
+ PROVIDE (__preinit_array_start = .);
+ .preinit_array : { *(.preinit_array) }
+ PROVIDE (__preinit_array_end = .);
+ PROVIDE (__init_array_start = .);
+ .init_array : { *(.init_array) }
+ PROVIDE (__init_array_end = .);
+ PROVIDE (__fini_array_start = .);
+ .fini_array : { *(.fini_array) }
+ PROVIDE (__fini_array_end = .);
+
+ .ctors : {
+ __CTOR_LIST__ = .;
+ *(.ctors)
+ CONSTRUCTORS
+ LONG(0)
+ __CTOR_END__ = .;
+ }
+
+ .dtors : {
+ __DTOR_LIST__ = .;
+ *(.dtors)
+ LONG(0)
+ __DTOR_END__ = .;
+ }
+
+ .data : { /* Data */
+ *(.data)
+ }
+
+ /* Note: linker will insert any extra sections here, just before .bss */
+
+ .bss : {
+ _edata = .; /* End of data included in image */
+ /* Nothing after here is included in the zImage's size */
+
+ __bss_start = .;
+ *(.bss)
+ *(.app.bss)
+ }
+ _end = . ;
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.text.exit)
+ *(.data.exit)
+ *(.exitcall.exit)
+ }
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+}
diff --git a/extras/mini-os/arch/arm/mm.c b/extras/mini-os/arch/arm/mm.c
new file mode 100644
index 0000000..efecc51
--- /dev/null
+++ b/extras/mini-os/arch/arm/mm.c
@@ -0,0 +1,139 @@
+#include <mini-os/console.h>
+#include <xen/memory.h>
+#include <arch_mm.h>
+#include <mini-os/hypervisor.h>
+#include <libfdt.h>
+#include <lib.h>
+
+uint32_t physical_address_offset;
+
+unsigned long allocate_ondemand(unsigned long n, unsigned long alignment)
+{
+ // FIXME
+ BUG();
+}
+
+void arch_init_mm(unsigned long *start_pfn_p, unsigned long *max_pfn_p)
+{
+ int memory;
+ int prop_len = 0;
+ const uint64_t *regs;
+
+ printk(" _text: %p(VA)\n", &_text);
+ printk(" _etext: %p(VA)\n", &_etext);
+ printk(" _erodata: %p(VA)\n", &_erodata);
+ printk(" _edata: %p(VA)\n", &_edata);
+ printk(" stack start: %p(VA)\n", _boot_stack);
+ printk(" _end: %p(VA)\n", &_end);
+
+ if (fdt_num_mem_rsv(device_tree) != 0)
+ printk("WARNING: reserved memory not supported!\n");
+
+ memory = fdt_node_offset_by_prop_value(device_tree, -1, "device_type", "memory", sizeof("memory"));
+ if (memory < 0) {
+ printk("No memory found in FDT!\n");
+ BUG();
+ }
+
+ /* Xen will always provide us at least one bank of memory.
+ * Mini-OS will use the first bank for the time-being. */
+ regs = fdt_getprop(device_tree, memory, "reg", &prop_len);
+
+ /* The property must contain at least the start address
+ * and size, each of which is 8-bytes. */
+ if (regs == NULL || prop_len < 16) {
+ printk("Bad 'reg' property: %p %d\n", regs, prop_len);
+ BUG();
+ }
+
+ unsigned int end = (unsigned int) &_end;
+ paddr_t mem_base = fdt64_to_cpu(regs[0]);
+ uint64_t mem_size = fdt64_to_cpu(regs[1]);
+ printk("Found memory at 0x%llx (len 0x%llx)\n",
+ (unsigned long long) mem_base, (unsigned long long) mem_size);
+
+ BUG_ON(to_virt(mem_base) > (void *) &_text); /* Our image isn't in our RAM! */
+ *start_pfn_p = PFN_UP(to_phys(end));
+ uint64_t heap_len = mem_size - (PFN_PHYS(*start_pfn_p) - mem_base);
+ *max_pfn_p = *start_pfn_p + PFN_DOWN(heap_len);
+
+ printk("Using pages %lu to %lu as free space for heap.\n", *start_pfn_p, *max_pfn_p);
+
+ /* The device tree is probably in memory that we're about to hand over to the page
+ * allocator, so move it to the end and reserve that space.
+ */
+ uint32_t fdt_size = fdt_totalsize(device_tree);
+ void *new_device_tree = to_virt(((*max_pfn_p << PAGE_SHIFT) - fdt_size) & PAGE_MASK);
+ if (new_device_tree != device_tree) {
+ memmove(new_device_tree, device_tree, fdt_size);
+ }
+ device_tree = new_device_tree;
+ *max_pfn_p = to_phys(new_device_tree) >> PAGE_SHIFT;
+}
+
+void arch_init_p2m(unsigned long max_pfn)
+{
+}
+
+void arch_init_demand_mapping_area(unsigned long cur_pfn)
+{
+}
+
+/* Get Xen's suggested physical page assignments for the grant table. */
+static paddr_t get_gnttab_base(void)
+{
+ int hypervisor;
+ int len = 0;
+ const uint64_t *regs;
+ paddr_t gnttab_base;
+
+ hypervisor = fdt_node_offset_by_compatible(device_tree, -1, "xen,xen");
+ BUG_ON(hypervisor < 0);
+
+ regs = fdt_getprop(device_tree, hypervisor, "reg", &len);
+ /* The property contains the address and size, 8-bytes each. */
+ if (regs == NULL || len < 16) {
+ printk("Bad 'reg' property: %p %d\n", regs, len);
+ BUG();
+ }
+
+ gnttab_base = fdt64_to_cpu(regs[0]);
+
+ printk("FDT suggests grant table base %llx\n", (unsigned long long) gnttab_base);
+
+ return gnttab_base;
+}
+
+grant_entry_t *arch_init_gnttab(int nr_grant_frames)
+{
+ struct xen_add_to_physmap xatp;
+ struct gnttab_setup_table setup;
+ xen_pfn_t frames[nr_grant_frames];
+ paddr_t gnttab_table;
+ int i, rc;
+
+ gnttab_table = get_gnttab_base();
+
+ for (i = 0; i < nr_grant_frames; i++)
+ {
+ xatp.domid = DOMID_SELF;
+ xatp.size = 0; /* Seems to be unused */
+ xatp.space = XENMAPSPACE_grant_table;
+ xatp.idx = i;
+ xatp.gpfn = (gnttab_table >> PAGE_SHIFT) + i;
+ rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
+ BUG_ON(rc != 0);
+ }
+
+ setup.dom = DOMID_SELF;
+ setup.nr_frames = nr_grant_frames;
+ set_xen_guest_handle(setup.frame_list, frames);
+ HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+ if (setup.status != 0)
+ {
+ printk("GNTTABOP_setup_table failed; status = %d\n", setup.status);
+ BUG();
+ }
+
+ return to_virt(gnttab_table);
+}
diff --git a/extras/mini-os/arch/arm/sched.c b/extras/mini-os/arch/arm/sched.c
new file mode 100644
index 0000000..8091566
--- /dev/null
+++ b/extras/mini-os/arch/arm/sched.c
@@ -0,0 +1,47 @@
+#include <mini-os/sched.h>
+#include <mini-os/xmalloc.h>
+#include <mini-os/console.h>
+
+void arm_start_thread(void);
+
+/* The AAPCS requires the callee (e.g. __arch_switch_threads) to preserve r4-r11. */
+#define CALLEE_SAVED_REGISTERS 8
+
+/* Architecture specific setup of thread creation */
+struct thread* arch_create_thread(char *name, void (*function)(void *),
+ void *data)
+{
+ struct thread *thread;
+
+ thread = xmalloc(struct thread);
+ /* We can't use lazy allocation here since the trap handler runs on the stack */
+ thread->stack = (char *)alloc_pages(STACK_SIZE_PAGE_ORDER);
+ thread->name = name;
+ printk("Thread \"%s\": pointer: 0x%p, stack: 0x%p\n", name, thread,
+ thread->stack);
+
+ /* Save pointer to the thread on the stack, used by current macro */
+ *((unsigned long *)thread->stack) = (unsigned long)thread;
+
+ /* Push the details to pass to arm_start_thread onto the stack. */
+ int *sp = (int *) (thread->stack + STACK_SIZE);
+ *(--sp) = (int) function;
+ *(--sp) = (int) data;
+
+ /* We leave room for the 8 callee-saved registers which we will
+ * try to restore on thread switch, even though they're not needed
+ * for the initial switch. */
+ thread->sp = (unsigned long) sp - 4 * CALLEE_SAVED_REGISTERS;
+
+ thread->ip = (unsigned long) arm_start_thread;
+
+ return thread;
+}
+
+void run_idle_thread(void)
+{
+ __asm__ __volatile__ ("mov sp, %0; bx %1"::
+ "r"(idle_thread->sp + 4 * CALLEE_SAVED_REGISTERS),
+ "r"(idle_thread->ip));
+ /* Never arrive here! */
+}
diff --git a/extras/mini-os/arch/arm/setup.c b/extras/mini-os/arch/arm/setup.c
new file mode 100644
index 0000000..06afe46
--- /dev/null
+++ b/extras/mini-os/arch/arm/setup.c
@@ -0,0 +1,119 @@
+#include <mini-os/os.h>
+#include <mini-os/kernel.h>
+#include <mini-os/gic.h>
+#include <mini-os/console.h>
+#include <xen/xen.h>
+#include <xen/memory.h>
+#include <xen/hvm/params.h>
+#include <arch_mm.h>
+#include <libfdt.h>
+
+/*
+ * This structure contains start-of-day info, such as pagetable base pointer,
+ * address of the shared_info structure, and things like that.
+ * On x86, the hypervisor passes it to us. On ARM, we fill it in ourselves.
+ */
+union start_info_union start_info_union;
+
+/*
+ * Shared page for communicating with the hypervisor.
+ * Events flags go here, for example.
+ */
+shared_info_t *HYPERVISOR_shared_info;
+
+extern char shared_info_page[PAGE_SIZE];
+
+void *device_tree;
+
+static int hvm_get_parameter(int idx, uint64_t *value)
+{
+ struct xen_hvm_param xhv;
+ int ret;
+
+ xhv.domid = DOMID_SELF;
+ xhv.index = idx;
+ ret = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
+ if (ret < 0) {
+ BUG();
+ }
+ *value = xhv.value;
+ return ret;
+}
+
+static void get_console(void)
+{
+ uint64_t v = -1;
+
+ hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v);
+ start_info.console.domU.evtchn = v;
+
+ hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v);
+ start_info.console.domU.mfn = v;
+
+ printk("Console is on port %d\n", start_info.console.domU.evtchn);
+ printk("Console ring is at mfn %lx\n", (unsigned long) start_info.console.domU.mfn);
+}
+
+void get_xenbus(void)
+{
+ uint64_t value;
+
+ if (hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &value))
+ BUG();
+
+ start_info.store_evtchn = (int)value;
+
+ if(hvm_get_parameter(HVM_PARAM_STORE_PFN, &value))
+ BUG();
+ start_info.store_mfn = (unsigned long)value;
+}
+
+/*
+ * INITIAL C ENTRY POINT.
+ */
+void arch_init(void *dtb_pointer, uint32_t physical_offset)
+{
+ struct xen_add_to_physmap xatp;
+ int r;
+
+ memset(&__bss_start, 0, &_end - &__bss_start);
+
+ physical_address_offset = physical_offset;
+
+ xprintk("Virtual -> physical offset = %x\n", physical_address_offset);
+
+ xprintk("Checking DTB at %p...\n", dtb_pointer);
+
+ if ((r = fdt_check_header(dtb_pointer))) {
+ xprintk("Invalid DTB from Xen: %s\n", fdt_strerror(r));
+ BUG();
+ }
+ device_tree = dtb_pointer;
+
+ /* Map shared_info page */
+ xatp.domid = DOMID_SELF;
+ xatp.idx = 0;
+ xatp.space = XENMAPSPACE_shared_info;
+ xatp.gpfn = virt_to_pfn(shared_info_page);
+ if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0)
+ BUG();
+ HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
+
+ /* Fill in start_info */
+ get_console();
+ get_xenbus();
+
+ gic_init();
+
+ start_kernel();
+}
+
+void
+arch_fini(void)
+{
+}
+
+void
+arch_do_exit(void)
+{
+}
diff --git a/extras/mini-os/arch/x86/events.c b/extras/mini-os/arch/x86/events.c
new file mode 100644
index 0000000..5198cf3
--- /dev/null
+++ b/extras/mini-os/arch/x86/events.c
@@ -0,0 +1,35 @@
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+#include <mini-os/events.h>
+
+#if defined(__x86_64__)
+char irqstack[2 * STACK_SIZE];
+
+static struct pda
+{
+ int irqcount; /* offset 0 (used in x86_64.S) */
+ char *irqstackptr; /* 8 */
+} cpu0_pda;
+#endif
+
+void arch_init_events(void)
+{
+#if defined(__x86_64__)
+ asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
+ wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
+ cpu0_pda.irqcount = -1;
+ cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE)
+ & ~(STACK_SIZE - 1));
+#endif
+}
+
+void arch_unbind_ports(void)
+{
+}
+
+void arch_fini_events(void)
+{
+#if defined(__x86_64__)
+ wrmsrl(0xc0000101, NULL); /* 0xc0000101 is MSR_GS_BASE */
+#endif
+}
diff --git a/extras/mini-os/arch/x86/mm.c b/extras/mini-os/arch/x86/mm.c
index 35df15b..9c6d1b8 100644
--- a/extras/mini-os/arch/x86/mm.c
+++ b/extras/mini-os/arch/x86/mm.c
@@ -942,3 +942,16 @@ void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p)
*start_pfn_p = start_pfn;
*max_pfn_p = max_pfn;
}
+
+grant_entry_t *arch_init_gnttab(int nr_grant_frames)
+{
+ struct gnttab_setup_table setup;
+ unsigned long frames[nr_grant_frames];
+
+ setup.dom = DOMID_SELF;
+ setup.nr_frames = nr_grant_frames;
+ set_xen_guest_handle(setup.frame_list, frames);
+
+ HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+ return map_frames(frames, nr_grant_frames);
+}
diff --git a/extras/mini-os/arch/x86/sched.c b/extras/mini-os/arch/x86/sched.c
index 8a05b58..e4a3dc2 100644
--- a/extras/mini-os/arch/x86/sched.c
+++ b/extras/mini-os/arch/x86/sched.c
@@ -107,6 +107,9 @@ struct thread* arch_create_thread(char *name, void (*function)(void *),
thread->sp = (unsigned long)thread->stack + STACK_SIZE;
/* Save pointer to the thread on the stack, used by current macro */
*((unsigned long *)thread->stack) = (unsigned long)thread;
+
+ /* Must ensure that (%rsp + 8) is 16-byte aligned at the start of thread_starter. */
+ thread->sp -= sizeof(unsigned long);
stack_push(thread, (unsigned long) function);
stack_push(thread, (unsigned long) data);
diff --git a/extras/mini-os/arch/x86/setup.c b/extras/mini-os/arch/x86/setup.c
index 54046d3..5e87dd1 100644
--- a/extras/mini-os/arch/x86/setup.c
+++ b/extras/mini-os/arch/x86/setup.c
@@ -28,6 +28,8 @@
#include <mini-os/os.h>
#include <mini-os/lib.h> /* for printk, memcpy */
+#include <mini-os/kernel.h>
+#include <xen/xen.h>
/*
* Shared page for communicating with the hypervisor.
@@ -87,20 +89,45 @@ static inline void sse_init(void) {
#define sse_init()
#endif
+
+/*
+ * INITIAL C ENTRY POINT.
+ */
void
arch_init(start_info_t *si)
{
+ static char hello[] = "Bootstrapping...\n";
+
+ (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
+
+ trap_init();
+
/*Initialize floating point unit */
- fpu_init();
+ fpu_init();
- /* Initialize SSE */
- sse_init();
+ /* Initialize SSE */
+ sse_init();
/* Copy the start_info struct to a globally-accessible area. */
/* WARN: don't do printk before here, it uses information from
shared_info. Use xprintk instead. */
memcpy(&start_info, si, sizeof(*si));
+ /* print out some useful information */
+ printk("Xen Minimal OS!\n");
+ printk(" start_info: %p(VA)\n", si);
+ printk(" nr_pages: 0x%lx\n", si->nr_pages);
+ printk(" shared_inf: 0x%08lx(MA)\n", si->shared_info);
+ printk(" pt_base: %p(VA)\n", (void *)si->pt_base);
+ printk("nr_pt_frames: 0x%lx\n", si->nr_pt_frames);
+ printk(" mfn_list: %p(VA)\n", (void *)si->mfn_list);
+ printk(" mod_start: 0x%lx(VA)\n", si->mod_start);
+ printk(" mod_len: %lu\n", si->mod_len);
+ printk(" flags: 0x%x\n", (unsigned int)si->flags);
+ printk(" cmd_line: %s\n",
+ si->cmd_line ? (const char *)si->cmd_line : "NULL");
+ printk(" stack: %p-%p\n", stack, stack + sizeof(stack));
+
/* set up minimal memory infos */
phys_to_machine_mapping = (unsigned long *)start_info.mfn_list;
@@ -118,12 +145,15 @@ arch_init(start_info_t *si)
(unsigned long)failsafe_callback, 0);
#endif
-
+ start_kernel();
}
void
arch_fini(void)
{
+ /* Reset traps */
+ trap_fini();
+
#ifdef __i386__
HYPERVISOR_set_callbacks(0, 0, 0, 0);
#else
@@ -132,9 +162,7 @@ arch_fini(void)
}
void
-arch_print_info(void)
+arch_do_exit(void)
{
- printk(" stack: %p-%p\n", stack, stack + sizeof(stack));
+ stack_walk();
}
-
-
diff --git a/extras/mini-os/arch/x86/time.c b/extras/mini-os/arch/x86/time.c
index 89bc382..2c8d033 100644
--- a/extras/mini-os/arch/x86/time.c
+++ b/extras/mini-os/arch/x86/time.c
@@ -212,7 +212,7 @@ void block_domain(s_time_t until)
/*
- * Just a dummy
+ * Just a dummy
*/
static void timer_handler(evtchn_port_t ev, struct pt_regs *regs, void *ign)
{
diff --git a/extras/mini-os/arch/x86/x86_32.S b/extras/mini-os/arch/x86/x86_32.S
index fb3e30a..b9aa392 100644
--- a/extras/mini-os/arch/x86/x86_32.S
+++ b/extras/mini-os/arch/x86/x86_32.S
@@ -20,7 +20,7 @@ _start:
lss stack_start,%esp
andl $(~(__STACK_SIZE-1)), %esp
push %esi
- call start_kernel
+ call arch_init
stack_start:
.long stack+(2*__STACK_SIZE), __KERNEL_SS
diff --git a/extras/mini-os/arch/x86/x86_64.S b/extras/mini-os/arch/x86/x86_64.S
index f022eb3..df3469e 100644
--- a/extras/mini-os/arch/x86/x86_64.S
+++ b/extras/mini-os/arch/x86/x86_64.S
@@ -21,7 +21,7 @@ _start:
movq stack_start(%rip),%rsp
andq $(~(__STACK_SIZE-1)), %rsp
movq %rsi,%rdi
- call start_kernel
+ call arch_init
stack_start:
.quad stack+(2*__STACK_SIZE)
diff --git a/extras/mini-os/blkfront.c b/extras/mini-os/blkfront.c
index 62a32c5..59e576f 100644
--- a/extras/mini-os/blkfront.c
+++ b/extras/mini-os/blkfront.c
@@ -509,15 +509,19 @@ moretodo:
aiocbp = (void*) (uintptr_t) rsp->id;
status = rsp->status;
- if (status != BLKIF_RSP_OKAY)
- printk("block error %d for op %d\n", status, rsp->operation);
-
switch (rsp->operation) {
case BLKIF_OP_READ:
case BLKIF_OP_WRITE:
{
int j;
+ if (status != BLKIF_RSP_OKAY)
+ printk("%s error %d on %s at offset %llu, num bytes %llu\n",
+ rsp->operation == BLKIF_OP_READ?"read":"write",
+ status, aiocbp->aio_dev->nodename,
+ (unsigned long long) aiocbp->aio_offset,
+ (unsigned long long) aiocbp->aio_nbytes);
+
for (j = 0; j < aiocbp->n; j++)
gnttab_end_access(aiocbp->gref[j]);
@@ -525,11 +529,17 @@ moretodo:
}
case BLKIF_OP_WRITE_BARRIER:
+ if (status != BLKIF_RSP_OKAY)
+ printk("write barrier error %d\n", status);
+ break;
case BLKIF_OP_FLUSH_DISKCACHE:
+ if (status != BLKIF_RSP_OKAY)
+ printk("flush error %d\n", status);
break;
default:
- printk("unrecognized block operation %d response\n", rsp->operation);
+ printk("unrecognized block operation %d response (status %d)\n", rsp->operation, status);
+ break;
}
dev->ring.rsp_cons = ++cons;
diff --git a/extras/mini-os/console/console.c b/extras/mini-os/console/console.c
index 380f53c..5538bd4 100644
--- a/extras/mini-os/console/console.c
+++ b/extras/mini-os/console/console.c
@@ -124,7 +124,7 @@ void print(int direct, const char *fmt, va_list args)
static char buf[1024];
(void)vsnprintf(buf, sizeof(buf), fmt, args);
-
+
if(direct)
{
(void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
index 036b84b..2a23042 100644
--- a/extras/mini-os/events.c
+++ b/extras/mini-os/events.c
@@ -43,7 +43,6 @@ void unbind_all_ports(void)
int cpu = 0;
shared_info_t *s = HYPERVISOR_shared_info;
vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
- int rc;
for ( i = 0; i < NR_EVS; i++ )
{
@@ -53,14 +52,8 @@ void unbind_all_ports(void)
if ( test_and_clear_bit(i, bound_ports) )
{
- struct evtchn_close close;
printk("port %d still bound!\n", i);
- mask_evtchn(i);
- close.port = i;
- rc = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
- if ( rc )
- printk("WARN: close_port %s failed rc=%d. ignored\n", i, rc);
- clear_evtchn(i);
+ unbind_evtchn(i);
}
}
vcpu_info->evtchn_upcall_pending = 0;
@@ -109,24 +102,23 @@ evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler,
void unbind_evtchn(evtchn_port_t port )
{
- struct evtchn_close close;
+ struct evtchn_close close;
int rc;
- if ( ev_actions[port].handler == default_handler )
- printk("WARN: No handler for port %d when unbinding\n", port);
- mask_evtchn(port);
- clear_evtchn(port);
+ if ( ev_actions[port].handler == default_handler )
+ printk("WARN: No handler for port %d when unbinding\n", port);
+ mask_evtchn(port);
+ clear_evtchn(port);
- ev_actions[port].handler = default_handler;
- wmb();
- ev_actions[port].data = NULL;
- clear_bit(port, bound_ports);
+ ev_actions[port].handler = default_handler;
+ wmb();
+ ev_actions[port].data = NULL;
+ clear_bit(port, bound_ports);
- close.port = port;
- rc = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
+ close.port = port;
+ rc = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
if ( rc )
- printk("WARN: close_port %s failed rc=%d. ignored\n", port, rc);
-
+ printk("WARN: close_port %d failed rc=%d. ignored\n", port, rc);
}
evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
@@ -138,7 +130,8 @@ evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
op.virq = virq;
op.vcpu = smp_processor_id();
- if ( (rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op)) != 0 )
+ rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op);
+ if (rc != 0)
{
printk("Failed to bind virtual IRQ %d with rc=%d\n", virq, rc);
return -1;
@@ -166,44 +159,29 @@ evtchn_port_t bind_pirq(uint32_t pirq, int will_share,
return op.port;
}
-#if defined(__x86_64__)
-char irqstack[2 * STACK_SIZE];
-
-static struct pda
-{
- int irqcount; /* offset 0 (used in x86_64.S) */
- char *irqstackptr; /* 8 */
-} cpu0_pda;
-#endif
-
/*
* Initially all events are without a handler and disabled
*/
void init_events(void)
{
int i;
-#if defined(__x86_64__)
- asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
- wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
- cpu0_pda.irqcount = -1;
- cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE)
- & ~(STACK_SIZE - 1));
-#endif
+
/* initialize event handler */
for ( i = 0; i < NR_EVS; i++ )
{
ev_actions[i].handler = default_handler;
mask_evtchn(i);
}
+
+ arch_init_events();
}
void fini_events(void)
{
/* Dealloc all events */
+ arch_unbind_ports();
unbind_all_ports();
-#if defined(__x86_64__)
- wrmsrl(0xc0000101, NULL); /* 0xc0000101 is MSR_GS_BASE */
-#endif
+ arch_fini_events();
}
void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore)
@@ -267,7 +245,7 @@ int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size)
op.cmd = FLASK_GET_PEER_SID;
op.interface_version = XEN_FLASK_INTERFACE_VERSION;
op.u.peersid.evtchn = local_port;
- rc = _hypercall1(int, xsm_op, &op);
+ rc = HYPERVISOR_xsm_op(&op);
if (rc)
return rc;
sid = op.u.peersid.sid;
@@ -275,7 +253,7 @@ int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size)
op.u.sid_context.sid = sid;
op.u.sid_context.size = size;
set_xen_guest_handle(op.u.sid_context.context, ctx);
- rc = _hypercall1(int, xsm_op, &op);
+ rc = HYPERVISOR_xsm_op(&op);
return rc;
}
diff --git a/extras/mini-os/gntmap.c b/extras/mini-os/gntmap.c
index 22ed450..f6ab3ad 100644
--- a/extras/mini-os/gntmap.c
+++ b/extras/mini-os/gntmap.c
@@ -38,6 +38,15 @@
#include <inttypes.h>
#include <mini-os/gntmap.h>
+//#define GNTMAP_DEBUG
+#ifdef GNTMAP_DEBUG
+#define DEBUG(_f, _a...) \
+ printk("MINI_OS(gntmap.c:%d): %s" _f "\n", __LINE__, __func__, ## _a)
+#else
+#define DEBUG(_f, _a...) ((void)0)
+#endif
+
+
#define DEFAULT_MAX_GRANTS 128
struct gntmap_entry {
@@ -61,10 +70,8 @@ gntmap_find_free_entry(struct gntmap *map)
return &map->entries[i];
}
-#ifdef GNTMAP_DEBUG
- printk("gntmap_find_free_entry(map=%p): all %d entries full\n",
+ DEBUG("(map=%p): all %d entries full",
map, map->nentries);
-#endif
return NULL;
}
@@ -83,9 +90,7 @@ gntmap_find_entry(struct gntmap *map, unsigned long addr)
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
+ DEBUG("(map=%p, count=%d)", map, count);
if (map->nentries != 0)
return -EBUSY;
@@ -157,10 +162,8 @@ 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",
+ DEBUG("(map=%p, start_address=%lx, count=%d)",
map, start_address, count);
-#endif
for (i = 0; i < count; i++) {
ent = gntmap_find_entry(map, start_address + PAGE_SIZE * i);
@@ -189,14 +192,12 @@ gntmap_map_grant_refs(struct gntmap *map,
struct gntmap_entry *ent;
int i;
-#ifdef GNTMAP_DEBUG
- printk("gntmap_map_grant_refs(map=%p, count=%" PRIu32 ", "
+ DEBUG("(map=%p, count=%" PRIu32 ", "
"domids=%p [%" PRIu32 "...], domids_stride=%d, "
- "refs=%p [%" PRIu32 "...], writable=%d)\n",
+ "refs=%p [%" PRIu32 "...], writable=%d)",
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);
@@ -224,9 +225,7 @@ gntmap_map_grant_refs(struct gntmap *map,
void
gntmap_init(struct gntmap *map)
{
-#ifdef GNTMAP_DEBUG
- printk("gntmap_init(map=%p)\n", map);
-#endif
+ DEBUG("(map=%p)", map);
map->nentries = 0;
map->entries = NULL;
}
@@ -237,9 +236,7 @@ gntmap_fini(struct gntmap *map)
struct gntmap_entry *ent;
int i;
-#ifdef GNTMAP_DEBUG
- printk("gntmap_fini(map=%p)\n", map);
-#endif
+ DEBUG("(map=%p)", map);
for (i = 0; i < map->nentries; i++) {
ent = &map->entries[i];
diff --git a/extras/mini-os/gnttab.c b/extras/mini-os/gnttab.c
index 2f1b3d7..f395d12 100644
--- a/extras/mini-os/gnttab.c
+++ b/extras/mini-os/gnttab.c
@@ -164,7 +164,7 @@ gnttabop_error(int16_t status)
{
status = -status;
if (status < 0 || status >= ARRAY_SIZE(gnttabop_error_msgs))
- return "bad status";
+ return "bad status";
else
return gnttabop_error_msgs[status];
}
@@ -172,8 +172,6 @@ gnttabop_error(int16_t status)
void
init_gnttab(void)
{
- struct gnttab_setup_table setup;
- unsigned long frames[NR_GRANT_FRAMES];
int i;
#ifdef GNT_DEBUG
@@ -182,12 +180,7 @@ init_gnttab(void)
for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
put_free_entry(i);
- setup.dom = DOMID_SELF;
- setup.nr_frames = NR_GRANT_FRAMES;
- set_xen_guest_handle(setup.frame_list, frames);
-
- HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
- gnttab_table = map_frames(frames, NR_GRANT_FRAMES);
+ gnttab_table = arch_init_gnttab(NR_GRANT_FRAMES);
printk("gnttab_table mapped at %p.\n", gnttab_table);
}
diff --git a/extras/mini-os/hypervisor.c b/extras/mini-os/hypervisor.c
index b4688a0..1b61d9b 100644
--- a/extras/mini-os/hypervisor.c
+++ b/extras/mini-os/hypervisor.c
@@ -64,7 +64,7 @@ void do_hypervisor_callback(struct pt_regs *regs)
l2 &= ~(1UL << l2i);
port = (l1i * (sizeof(unsigned long) * 8)) + l2i;
- do_event(port, regs);
+ do_event(port, regs);
}
}
@@ -73,18 +73,26 @@ void do_hypervisor_callback(struct pt_regs *regs)
void force_evtchn_callback(void)
{
+#ifdef XEN_HAVE_PV_UPCALL_MASK
int save;
+#endif
vcpu_info_t *vcpu;
vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
+#ifdef XEN_HAVE_PV_UPCALL_MASK
save = vcpu->evtchn_upcall_mask;
+#endif
while (vcpu->evtchn_upcall_pending) {
+#ifdef XEN_HAVE_PV_UPCALL_MASK
vcpu->evtchn_upcall_mask = 1;
+#endif
barrier();
do_hypervisor_callback(NULL);
barrier();
+#ifdef XEN_HAVE_PV_UPCALL_MASK
vcpu->evtchn_upcall_mask = save;
barrier();
+#endif
};
}
@@ -110,7 +118,9 @@ inline void unmask_evtchn(uint32_t port)
&vcpu_info->evtchn_pending_sel) )
{
vcpu_info->evtchn_upcall_pending = 1;
+#ifdef XEN_HAVE_PV_UPCALL_MASK
if ( !vcpu_info->evtchn_upcall_mask )
+#endif
force_evtchn_callback();
}
}
diff --git a/extras/mini-os/include/arm/arch_endian.h b/extras/mini-os/include/arm/arch_endian.h
new file mode 100644
index 0000000..0771683
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_endian.h
@@ -0,0 +1,7 @@
+#ifndef ARCH_ENDIAN_H
+#error "Do not include arch_endian by itself, include endian.h"
+#else
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+#endif
diff --git a/extras/mini-os/include/arm/arch_limits.h b/extras/mini-os/include/arm/arch_limits.h
new file mode 100644
index 0000000..bae99e1
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_limits.h
@@ -0,0 +1,9 @@
+#ifndef __ARCH_LIMITS_H__
+#define __ARCH_LIMITS_H__
+
+#include <mm.h>
+
+#define __STACK_SIZE_PAGE_ORDER 2
+#define __STACK_SIZE (4 * PAGE_SIZE)
+
+#endif
diff --git a/extras/mini-os/include/arm/arch_mm.h b/extras/mini-os/include/arm/arch_mm.h
new file mode 100644
index 0000000..085d4e5
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_mm.h
@@ -0,0 +1,38 @@
+#ifndef _ARCH_MM_H_
+#define _ARCH_MM_H_
+
+typedef uint64_t paddr_t;
+
+extern char _text, _etext, _erodata, _edata, _end, __bss_start;
+extern int _boot_stack[];
+extern int _boot_stack_end[];
+extern uint32_t physical_address_offset; /* Add this to a virtual address to get the physical address (wraps at 4GB) */
+
+#define PAGE_SHIFT 12
+#define PAGE_SIZE (1 << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+#define L1_PAGETABLE_SHIFT 12
+
+#define to_phys(x) (((paddr_t)(x)+physical_address_offset) & 0xffffffff)
+#define to_virt(x) ((void *)(((x)-physical_address_offset) & 0xffffffff))
+
+#define PFN_UP(x) (unsigned long)(((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT)
+#define PFN_DOWN(x) (unsigned long)((x) >> L1_PAGETABLE_SHIFT)
+#define PFN_PHYS(x) ((uint64_t)(x) << L1_PAGETABLE_SHIFT)
+#define PHYS_PFN(x) (unsigned long)((x) >> L1_PAGETABLE_SHIFT)
+
+#define virt_to_pfn(_virt) (PFN_DOWN(to_phys(_virt)))
+#define virt_to_mfn(_virt) (PFN_DOWN(to_phys(_virt)))
+#define mfn_to_virt(_mfn) (to_virt(PFN_PHYS(_mfn)))
+#define pfn_to_virt(_pfn) (to_virt(PFN_PHYS(_pfn)))
+
+#define mfn_to_pfn(x) (x)
+#define pfn_to_mfn(x) (x)
+
+#define virtual_to_mfn(_virt) virt_to_mfn(_virt)
+
+// FIXME
+#define map_frames(f, n) (NULL)
+
+#endif
diff --git a/extras/mini-os/include/arm/arch_sched.h b/extras/mini-os/include/arm/arch_sched.h
new file mode 100644
index 0000000..de3ac02
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_sched.h
@@ -0,0 +1,19 @@
+#ifndef __ARCH_SCHED_H__
+#define __ARCH_SCHED_H__
+
+#include "arch_limits.h"
+
+static inline struct thread* get_current(void)
+{
+ struct thread **current;
+ unsigned long sp;
+ __asm__ __volatile__ ("mov %0, sp":"=r"(sp));
+ current = (void *)(unsigned long)(sp & ~(__STACK_SIZE-1));
+ return *current;
+}
+
+void __arch_switch_threads(unsigned long *prevctx, unsigned long *nextctx);
+
+#define arch_switch_threads(prev,next) __arch_switch_threads(&(prev)->sp, &(next)->sp)
+
+#endif /* __ARCH_SCHED_H__ */
diff --git a/extras/mini-os/include/arm/arch_spinlock.h b/extras/mini-os/include/arm/arch_spinlock.h
new file mode 100755
index 0000000..dccb9fc
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_spinlock.h
@@ -0,0 +1,36 @@
+#ifndef __ARCH_ASM_SPINLOCK_H
+#define __ARCH_ASM_SPINLOCK_H
+
+#include "os.h"
+
+#define ARCH_SPIN_LOCK_UNLOCKED { 1 }
+
+/*
+ * Simple spin lock operations. There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * We make no fairness assumptions. They have a cost.
+ */
+
+#define arch_spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) <= 0)
+#define arch_spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
+
+static inline void _raw_spin_unlock(spinlock_t *lock)
+{
+ xchg(&lock->slock, 1);
+}
+
+static inline int _raw_spin_trylock(spinlock_t *lock)
+{
+ return xchg(&lock->slock, 0) != 0 ? 1 : 0;
+}
+
+static inline void _raw_spin_lock(spinlock_t *lock)
+{
+ volatile int was_locked;
+ do {
+ was_locked = xchg(&lock->slock, 0) == 0 ? 1 : 0;
+ } while(was_locked);
+}
+
+#endif
diff --git a/extras/mini-os/include/arm/arm32/arch_wordsize.h b/extras/mini-os/include/arm/arm32/arch_wordsize.h
new file mode 100644
index 0000000..b47eee9
--- /dev/null
+++ b/extras/mini-os/include/arm/arm32/arch_wordsize.h
@@ -0,0 +1 @@
+#define __WORDSIZE 32
diff --git a/extras/mini-os/include/arm/gic.h b/extras/mini-os/include/arm/gic.h
new file mode 100644
index 0000000..cead2e5
--- /dev/null
+++ b/extras/mini-os/include/arm/gic.h
@@ -0,0 +1 @@
+void gic_init(void);
diff --git a/extras/mini-os/include/arm/hypercall-arm.h b/extras/mini-os/include/arm/hypercall-arm.h
new file mode 100644
index 0000000..26ac9f8
--- /dev/null
+++ b/extras/mini-os/include/arm/hypercall-arm.h
@@ -0,0 +1,98 @@
+/******************************************************************************
+ * hypercall-arm.h
+ *
+ * Copied from XenLinux.
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * 64-bit updates:
+ * Benjamin Liu <benjamin.liu at intel.com>
+ * Jun Nakajima <jun.nakajima at intel.com>
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (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.
+ */
+
+#ifndef __HYPERCALL_ARM_H__
+#define __HYPERCALL_ARM_H__
+
+#include <xen/xen.h>
+#include <xen/sched.h>
+#include <xen/xsm/flask_op.h>
+#include <mini-os/mm.h>
+
+int
+HYPERVISOR_sched_op(
+ int cmd, void *arg);
+
+static inline int
+HYPERVISOR_shutdown(
+ unsigned int reason)
+{
+ struct sched_shutdown shutdown = { .reason = reason };
+ HYPERVISOR_sched_op(SCHEDOP_shutdown, &shutdown);
+}
+
+int
+HYPERVISOR_memory_op(
+ unsigned int cmd, void *arg);
+
+int
+HYPERVISOR_event_channel_op(
+ int cmd, void *op);
+
+int
+HYPERVISOR_xen_version(
+ int cmd, void *arg);
+
+int
+HYPERVISOR_console_io(
+ int cmd, int count, char *str);
+
+int
+HYPERVISOR_physdev_op(
+ void *physdev_op);
+
+int
+HYPERVISOR_grant_table_op(
+ unsigned int cmd, void *uop, unsigned int count);
+
+int
+HYPERVISOR_vcpu_op(
+ int cmd, int vcpuid, void *extra_args);
+
+int
+HYPERVISOR_sysctl(
+ unsigned long op);
+
+int
+HYPERVISOR_domctl(
+ unsigned long op);
+
+int
+HYPERVISOR_hvm_op(
+ unsigned long op, void *arg);
+
+int
+HYPERVISOR_xsm_op(
+ struct xen_flask_op *);
+
+#endif /* __HYPERCALL_ARM_H__ */
diff --git a/extras/mini-os/include/arm/os.h b/extras/mini-os/include/arm/os.h
new file mode 100644
index 0000000..6a1cc37
--- /dev/null
+++ b/extras/mini-os/include/arm/os.h
@@ -0,0 +1,216 @@
+#ifndef _OS_H_
+#define _OS_H_
+
+#ifndef __ASSEMBLY__
+
+#include <mini-os/hypervisor.h>
+#include <mini-os/types.h>
+#include <mini-os/compiler.h>
+#include <mini-os/kernel.h>
+#include <xen/xen.h>
+
+void arch_fini(void);
+void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign);
+
+extern void *device_tree;
+
+#define BUG() while(1){asm volatile (".word 0xe7f000f0\n");} /* Undefined instruction; will call our fault handler. */
+
+#define smp_processor_id() 0
+
+#define barrier() __asm__ __volatile__("": : :"memory")
+
+extern shared_info_t *HYPERVISOR_shared_info;
+
+// disable interrupts
+static inline void local_irq_disable(void) {
+ __asm__ __volatile__("cpsid i":::"memory");
+}
+
+// enable interrupts
+static inline void local_irq_enable(void) {
+ __asm__ __volatile__("cpsie i":::"memory");
+}
+
+#define local_irq_save(x) { \
+ __asm__ __volatile__("mrs %0, cpsr;cpsid i":"=r"(x)::"memory"); \
+}
+
+#define local_irq_restore(x) { \
+ __asm__ __volatile__("msr cpsr_c, %0"::"r"(x):"memory"); \
+}
+
+#define local_save_flags(x) { \
+ __asm__ __volatile__("mrs %0, cpsr":"=r"(x)::"memory"); \
+}
+
+static inline int irqs_disabled(void) {
+ int x;
+ local_save_flags(x);
+ return x & 0x80;
+}
+
+/* We probably only need "dmb" here, but we'll start by being paranoid. */
+#define mb() __asm__("dsb":::"memory");
+#define rmb() __asm__("dsb":::"memory");
+#define wmb() __asm__("dsb":::"memory");
+
+/************************** arm *******************************/
+#ifdef __INSIDE_MINIOS__
+#if defined (__arm__)
+#define xchg(ptr,v) __atomic_exchange_n(ptr, v, __ATOMIC_SEQ_CST)
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ *
+ * This operation is atomic.
+ * If you need a memory barrier, use synch_test_and_clear_bit instead.
+ */
+static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+{
+ uint8_t *byte = ((uint8_t *)addr) + (nr >> 3);
+ uint8_t bit = 1 << (nr & 7);
+ uint8_t orig;
+
+ orig = __atomic_fetch_and(byte, ~bit, __ATOMIC_RELAXED);
+
+ return (orig & bit) != 0;
+}
+
+/**
+ * Atomically set a bit and return the old value.
+ * Similar to test_and_clear_bit.
+ */
+static __inline__ int test_and_set_bit(int nr, volatile void *base)
+{
+ uint8_t *byte = ((uint8_t *)base) + (nr >> 3);
+ uint8_t bit = 1 << (nr & 7);
+ uint8_t orig;
+
+ orig = __atomic_fetch_or(byte, bit, __ATOMIC_RELAXED);
+
+ return (orig & bit) != 0;
+}
+
+/**
+ * Test whether a bit is set. */
+static __inline__ int test_bit(int nr, const volatile unsigned long *addr)
+{
+ const uint8_t *ptr = (const uint8_t *) addr;
+ return ((1 << (nr & 7)) & (ptr[nr >> 3])) != 0;
+}
+
+/**
+ * Atomically set a bit in memory (like test_and_set_bit but discards result).
+ */
+static __inline__ void set_bit(int nr, volatile unsigned long *addr)
+{
+ test_and_set_bit(nr, addr);
+}
+
+/**
+ * Atomically clear a bit in memory (like test_and_clear_bit but discards result).
+ */
+static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
+{
+ test_and_clear_bit(nr, addr);
+}
+
+/**
+ * __ffs - find first (lowest) set bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static __inline__ unsigned long __ffs(unsigned long word)
+{
+ int clz;
+
+ /* xxxxx10000 = word
+ * xxxxx01111 = word - 1
+ * 0000011111 = word ^ (word - 1)
+ * 4 = 31 - clz(word ^ (word - 1))
+ */
+
+ __asm__ (
+ "sub r0, %[word], #1\n"
+ "eor r0, r0, %[word]\n"
+ "clz %[clz], r0\n":
+ /* Outputs: */
+ [clz] "=r"(clz):
+ /* Inputs: */
+ [word] "r"(word):
+ /* Clobbers: */
+ "r0");
+
+ return 31 - clz;
+}
+
+#else /* ifdef __arm__ */
+#error "Unsupported architecture"
+#endif
+#endif /* ifdef __INSIDE_MINIOS */
+
+/********************* common arm32 and arm64 ****************************/
+
+/* If *ptr == old, then store new there (and return new).
+ * Otherwise, return the old value.
+ * Atomic. */
+#define synch_cmpxchg(ptr, old, new) \
+({ __typeof__(*ptr) stored = old; \
+ __atomic_compare_exchange_n(ptr, &stored, new, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? new : old; \
+})
+
+/* As test_and_clear_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ int synch_test_and_clear_bit(int nr, volatile void *addr)
+{
+ uint8_t *byte = ((uint8_t *)addr) + (nr >> 3);
+ uint8_t bit = 1 << (nr & 7);
+ uint8_t orig;
+
+ orig = __atomic_fetch_and(byte, ~bit, __ATOMIC_SEQ_CST);
+
+ return (orig & bit) != 0;
+}
+
+/* As test_and_set_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ int synch_test_and_set_bit(int nr, volatile void *base)
+{
+ uint8_t *byte = ((uint8_t *)base) + (nr >> 3);
+ uint8_t bit = 1 << (nr & 7);
+ uint8_t orig;
+
+ orig = __atomic_fetch_or(byte, bit, __ATOMIC_SEQ_CST);
+
+ return (orig & bit) != 0;
+}
+
+/* As set_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ void synch_set_bit(int nr, volatile void *addr)
+{
+ synch_test_and_set_bit(nr, addr);
+}
+
+/* As clear_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ void synch_clear_bit(int nr, volatile void *addr)
+{
+ synch_test_and_clear_bit(nr, addr);
+}
+
+/* As test_bit, but with a following memory barrier. */
+static __inline__ int synch_test_bit(int nr, volatile void *addr)
+{
+ int result;
+ result = test_bit(nr, addr);
+ barrier();
+ return result;
+}
+
+#endif /* not assembly */
+
+#endif
diff --git a/extras/mini-os/include/arm/traps.h b/extras/mini-os/include/arm/traps.h
new file mode 100644
index 0000000..704df22
--- /dev/null
+++ b/extras/mini-os/include/arm/traps.h
@@ -0,0 +1,20 @@
+#ifndef _TRAPS_H_
+#define _TRAPS_H_
+
+struct pt_regs {
+ unsigned long r0;
+ unsigned long r1;
+ unsigned long r2;
+ unsigned long r3;
+ unsigned long r4;
+ unsigned long r5;
+ unsigned long r6;
+ unsigned long r7;
+ unsigned long r8;
+ unsigned long r9;
+ unsigned long r10;
+ unsigned long r11;
+ unsigned long r12;
+};
+
+#endif
diff --git a/extras/mini-os/include/compiler.h b/extras/mini-os/include/compiler.h
new file mode 100644
index 0000000..4188277
--- /dev/null
+++ b/extras/mini-os/include/compiler.h
@@ -0,0 +1,10 @@
+#ifndef __MINIOS_COMPILER_H_
+#define __MINIOS_COMPILER_H_
+
+#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
+#define __builtin_expect(x, expected_value) (x)
+#endif
+#define unlikely(x) __builtin_expect(!!(x),0)
+#define likely(x) __builtin_expect(!!(x),1)
+
+#endif /* __MINIOS_COMPILER_H_ */
diff --git a/extras/mini-os/include/events.h b/extras/mini-os/include/events.h
index 0e9d3a7..89b5997 100644
--- a/extras/mini-os/include/events.h
+++ b/extras/mini-os/include/events.h
@@ -25,6 +25,13 @@
typedef void (*evtchn_handler_t)(evtchn_port_t, struct pt_regs *, void *);
/* prototypes */
+void arch_init_events(void);
+
+/* Called by fini_events to close any ports opened by arch-specific code. */
+void arch_unbind_ports(void);
+
+void arch_fini_events(void);
+
int do_event(evtchn_port_t port, struct pt_regs *regs);
evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data);
evtchn_port_t bind_pirq(uint32_t pirq, int will_share, evtchn_handler_t handler, void *data);
diff --git a/extras/mini-os/include/gnttab.h b/extras/mini-os/include/gnttab.h
index acd6c39..c43ad42 100644
--- a/extras/mini-os/include/gnttab.h
+++ b/extras/mini-os/include/gnttab.h
@@ -12,5 +12,6 @@ unsigned long gnttab_end_transfer(grant_ref_t gref);
int gnttab_end_access(grant_ref_t ref);
const char *gnttabop_error(int16_t status);
void fini_gnttab(void);
+grant_entry_t *arch_init_gnttab(int nr_grant_frames);
#endif /* !__GNTTAB_H__ */
diff --git a/extras/mini-os/include/hypervisor.h b/extras/mini-os/include/hypervisor.h
index a62cb78..21b3566 100644
--- a/extras/mini-os/include/hypervisor.h
+++ b/extras/mini-os/include/hypervisor.h
@@ -18,6 +18,8 @@
#include <hypercall-x86_32.h>
#elif defined(__x86_64__)
#include <hypercall-x86_64.h>
+#elif defined(__arm__) || defined(__aarch64__)
+#include <hypercall-arm.h>
#else
#error "Unsupported architecture"
#endif
diff --git a/extras/mini-os/include/kernel.h b/extras/mini-os/include/kernel.h
index b36f172..13e3274 100644
--- a/extras/mini-os/include/kernel.h
+++ b/extras/mini-os/include/kernel.h
@@ -1,7 +1,9 @@
#ifndef _KERNEL_H_
#define _KERNEL_H_
-extern void do_exit(void) __attribute__((noreturn));
-extern void stop_kernel(void);
+void start_kernel(void);
+void do_exit(void) __attribute__((noreturn));
+void arch_do_exit(void);
+void stop_kernel(void);
#endif /* _KERNEL_H_ */
diff --git a/extras/mini-os/include/lib.h b/extras/mini-os/include/lib.h
index 935bede..62836c7 100644
--- a/extras/mini-os/include/lib.h
+++ b/extras/mini-os/include/lib.h
@@ -52,10 +52,19 @@
#include <stddef.h>
#include <xen/xen.h>
#include <xen/event_channel.h>
-#include <sys/queue.h>
#include "gntmap.h"
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+#define BUILD_BUG_ON(cond) ({ _Static_assert(!(cond), "!(" #cond ")"); })
+#define BUILD_BUG_ON_ZERO(cond) \
+ sizeof(struct { _Static_assert(!(cond), "!(" #cond ")"); })
+#else
+#define BUILD_BUG_ON_ZERO(cond) sizeof(struct { int:-!!(cond); })
+#define BUILD_BUG_ON(cond) ((void)BUILD_BUG_ON_ZERO(cond))
+#endif
+
#ifdef HAVE_LIBC
+#include <sys/queue.h>
#include <stdio.h>
#else
#include <lib-gpl.h>
diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h
index a94cd6d..f57d8ab 100644
--- a/extras/mini-os/include/mm.h
+++ b/extras/mini-os/include/mm.h
@@ -29,11 +29,12 @@
#include <xen/arch-x86_32.h>
#elif defined(__x86_64__)
#include <xen/arch-x86_64.h>
+#elif defined(__arm__) || defined(__aarch64__)
+#include <xen/arch-arm.h>
#else
#error "Unsupported architecture"
#endif
-
-#include <mini-os/lib.h>
+#include <xen/xen.h>
#include <mini-os/arch_limits.h>
#include <mini-os/arch_mm.h>
diff --git a/extras/mini-os/include/types.h b/extras/mini-os/include/types.h
index 6640ede..be9f1d3 100644
--- a/extras/mini-os/include/types.h
+++ b/extras/mini-os/include/types.h
@@ -27,34 +27,22 @@ typedef unsigned char u_char;
typedef unsigned int u_int;
typedef unsigned long u_long;
#endif
-#ifdef __i386__
+#if defined(__i386__) || defined(__arm__)
typedef long long quad_t;
typedef unsigned long long u_quad_t;
-
-typedef struct { unsigned long pte_low, pte_high; } pte_t;
-
#elif defined(__x86_64__)
typedef long quad_t;
typedef unsigned long u_quad_t;
-
-typedef struct { unsigned long pte; } pte_t;
#endif /* __i386__ || __x86_64__ */
-#ifdef __x86_64__
-#define __pte(x) ((pte_t) { (x) } )
-#else
-#define __pte(x) ({ unsigned long long _x = (x); \
- ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
-#endif
-
#ifdef HAVE_LIBC
#include <limits.h>
#include <stdint.h>
#else
-#ifdef __i386__
+#if defined(__i386__) || defined(__arm__)
typedef unsigned int uintptr_t;
typedef int intptr_t;
-#elif defined(__x86_64__)
+#elif defined(__x86_64__) || defined(__aarch64__)
typedef unsigned long uintptr_t;
typedef long intptr_t;
#endif /* __i386__ || __x86_64__ */
@@ -64,16 +52,16 @@ typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned int uint32_t;
typedef signed int int32_t;
-#ifdef __i386__
+#if defined(__i386__) || defined(__arm__)
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
-#elif defined(__x86_64__)
+#elif defined(__x86_64__) || defined(__aarch64__)
typedef signed long int64_t;
typedef unsigned long uint64_t;
#endif
typedef uint64_t uintmax_t;
typedef int64_t intmax_t;
-typedef uint64_t off_t;
+typedef int64_t off_t;
#endif
typedef intptr_t ptrdiff_t;
diff --git a/extras/mini-os/include/x86/arch_spinlock.h b/extras/mini-os/include/x86/arch_spinlock.h
index c08b6f1..59f7b63 100644
--- a/extras/mini-os/include/x86/arch_spinlock.h
+++ b/extras/mini-os/include/x86/arch_spinlock.h
@@ -61,7 +61,7 @@
static inline void _raw_spin_unlock(spinlock_t *lock)
{
- char oldval = 1;
+ char oldval = ARCH_SPIN_LOCK_UNLOCKED;
__asm__ __volatile__(
spin_unlock_string
);
diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h
index f193865..ee9050b 100644
--- a/extras/mini-os/include/x86/os.h
+++ b/extras/mini-os/include/x86/os.h
@@ -7,19 +7,15 @@
#ifndef _OS_H_
#define _OS_H_
-#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
-#define __builtin_expect(x, expected_value) (x)
-#endif
-#define unlikely(x) __builtin_expect((x),0)
-#define likely(x) __builtin_expect((x),1)
-
#define smp_processor_id() 0
#ifndef __ASSEMBLY__
+#include <mini-os/compiler.h>
#include <mini-os/types.h>
#include <mini-os/hypervisor.h>
#include <mini-os/kernel.h>
+#include <xen/xsm/flask_op.h>
#define USED __attribute__ ((used))
@@ -64,8 +60,6 @@ extern shared_info_t *HYPERVISOR_shared_info;
void trap_init(void);
void trap_fini(void);
-void arch_init(start_info_t *si);
-void arch_print_info(void);
void arch_fini(void);
@@ -565,6 +559,12 @@ static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
synch_const_test_bit((nr),(addr)) : \
synch_var_test_bit((nr),(addr)))
+static inline int
+HYPERVISOR_xsm_op(
+ struct xen_flask_op *op)
+{
+ return _hypercall1(int, xsm_op, op);
+}
#undef ADDR
diff --git a/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h b/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h
index dcfbe41..99a4ee3 100644
--- a/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h
+++ b/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h
@@ -35,6 +35,11 @@
#include <xen/nmi.h>
#include <mini-os/mm.h>
+typedef struct { unsigned long pte_low, pte_high; } pte_t;
+
+#define __pte(x) ({ unsigned long long _x = (x); \
+ ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
+
#define __STR(x) #x
#define STR(x) __STR(x)
diff --git a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
index 7083763..e00b3bd 100644
--- a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
+++ b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
@@ -38,6 +38,10 @@
#include <xen/sched.h>
#include <mini-os/mm.h>
+typedef struct { unsigned long pte; } pte_t;
+
+#define __pte(x) ((pte_t) { (x) } )
+
#define __STR(x) #x
#define STR(x) __STR(x)
diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
index ea409f4..437e5b4 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/kernel.c
@@ -28,6 +28,7 @@
*/
#include <mini-os/os.h>
+#include <mini-os/kernel.h>
#include <mini-os/hypervisor.h>
#include <mini-os/mm.h>
#include <mini-os/events.h>
@@ -68,7 +69,9 @@ void setup_xen_features(void)
/* This should be overridden by the application we are linked against. */
__attribute__((weak)) void app_shutdown(unsigned reason)
{
+ struct sched_shutdown sched_shutdown = { .reason = reason };
printk("Shutdown requested: %d\n", reason);
+ HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
}
static void shutdown_thread(void *p)
@@ -76,12 +79,14 @@ static void shutdown_thread(void *p)
const char *path = "control/shutdown";
const char *token = path;
xenbus_event_queue events = NULL;
- char *shutdown, *err;
+ char *shutdown = NULL, *err;
unsigned int shutdown_reason;
xenbus_watch_path_token(XBT_NIL, path, token, &events);
- while ((err = xenbus_read(XBT_NIL, path, &shutdown)) != NULL)
+ while ((err = xenbus_read(XBT_NIL, path, &shutdown)) != NULL || !strcmp(shutdown, ""))
{
free(err);
+ free(shutdown);
+ shutdown = NULL;
xenbus_wait_for_watch(&events);
}
err = xenbus_unwatch_path_token(XBT_NIL, path, token);
@@ -106,44 +111,17 @@ static void shutdown_thread(void *p)
/* This should be overridden by the application we are linked against. */
__attribute__((weak)) int app_main(start_info_t *si)
{
- printk("Dummy main: start_info=%p\n", si);
+ printk("kernel.c: dummy main: start_info=%p\n", si);
return 0;
}
-/*
- * INITIAL C ENTRY POINT.
- */
-void start_kernel(start_info_t *si)
+void start_kernel(void)
{
- static char hello[] = "Bootstrapping...\n";
-
- (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
-
- arch_init(si);
-
- trap_init();
-
- /* print out some useful information */
- printk("Xen Minimal OS!\n");
- printk(" start_info: %p(VA)\n", si);
- printk(" nr_pages: 0x%lx\n", si->nr_pages);
- printk(" shared_inf: 0x%08lx(MA)\n", si->shared_info);
- printk(" pt_base: %p(VA)\n", (void *)si->pt_base);
- printk("nr_pt_frames: 0x%lx\n", si->nr_pt_frames);
- printk(" mfn_list: %p(VA)\n", (void *)si->mfn_list);
- printk(" mod_start: 0x%lx(VA)\n", si->mod_start);
- printk(" mod_len: %lu\n", si->mod_len);
- printk(" flags: 0x%x\n", (unsigned int)si->flags);
- printk(" cmd_line: %s\n",
- si->cmd_line ? (const char *)si->cmd_line : "NULL");
-
/* Set up events. */
init_events();
-
- /* ENABLE EVENT DELIVERY. This is disabled at start of day. */
- __sti();
- arch_print_info();
+ /* ENABLE EVENT DELIVERY. This is disabled at start of day. */
+ local_irq_enable();
setup_xen_features();
@@ -197,9 +175,6 @@ void stop_kernel(void)
/* Reset events. */
fini_events();
- /* Reset traps */
- trap_fini();
-
/* Reset arch details */
arch_fini();
}
@@ -214,7 +189,7 @@ void stop_kernel(void)
void do_exit(void)
{
printk("Do_exit called!\n");
- stack_walk();
+ arch_do_exit();
for( ;; )
{
struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_crash };
diff --git a/extras/mini-os/lib/math.c b/extras/mini-os/lib/math.c
index c941b4c..561393e 100644
--- a/extras/mini-os/lib/math.c
+++ b/extras/mini-os/lib/math.c
@@ -424,16 +424,3 @@ __moddi3(quad_t a, quad_t b)
(void)__qdivrem(ua, ub, &ur);
return (neg ? -ur : ur);
}
-
-#ifndef HAVE_LIBC
-/* Should be random enough for our uses */
-int rand(void)
-{
- static unsigned int previous;
- struct timeval tv;
- gettimeofday(&tv, NULL);
- previous += tv.tv_sec + tv.tv_usec;
- previous *= RAND_MIX;
- return previous;
-}
-#endif
diff --git a/extras/mini-os/lock.c b/extras/mini-os/lock.c
index 71a4971..61194e5 100644
--- a/extras/mini-os/lock.c
+++ b/extras/mini-os/lock.c
@@ -9,6 +9,7 @@
#include <sys/lock.h>
#include <sched.h>
#include <wait.h>
+#include <mini-os/lib.h>
int ___lock_init(_LOCK_T *lock)
{
diff --git a/extras/mini-os/main.c b/extras/mini-os/main.c
index 73eb6fb..4ec40b5 100644
--- a/extras/mini-os/main.c
+++ b/extras/mini-os/main.c
@@ -15,6 +15,7 @@
#include <unistd.h>
#include <xenbus.h>
#include <events.h>
+#include <mini-os/lib.h>
extern int main(int argc, char *argv[], char *envp[]);
extern void __libc_init_array(void);
@@ -185,7 +186,7 @@ void _exit(int ret)
int app_main(start_info_t *si)
{
- printk("Dummy main: start_info=%p\n", si);
+ printk("main.c: dummy main: start_info=%p\n", si);
main_thread = create_thread("main", call_main, si);
return 0;
}
diff --git a/extras/mini-os/mm.c b/extras/mini-os/mm.c
index d2d5264..64b3292 100644
--- a/extras/mini-os/mm.c
+++ b/extras/mini-os/mm.c
@@ -409,8 +409,8 @@ void init_mm(void)
* now we can initialise the page allocator
*/
printk("MM: Initialise page allocator for %lx(%lx)-%lx(%lx)\n",
- (u_long)to_virt(PFN_PHYS(start_pfn)), PFN_PHYS(start_pfn),
- (u_long)to_virt(PFN_PHYS(max_pfn)), PFN_PHYS(max_pfn));
+ (u_long)to_virt(PFN_PHYS(start_pfn)), (u_long)PFN_PHYS(start_pfn),
+ (u_long)to_virt(PFN_PHYS(max_pfn)), (u_long)PFN_PHYS(max_pfn));
init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn));
printk("MM: done\n");
diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c
index 5ac5c1c..d0c607e 100644
--- a/extras/mini-os/sched.c
+++ b/extras/mini-os/sched.c
@@ -78,6 +78,11 @@ void schedule(void)
struct thread *prev, *next, *thread, *tmp;
unsigned long flags;
+ if (irqs_disabled()) {
+ printk("Must not call schedule() with IRQs disabled\n");
+ BUG();
+ }
+
prev = current;
local_irq_save(flags);
@@ -85,10 +90,6 @@ void schedule(void)
printk("Must not call schedule() from a callback\n");
BUG();
}
- if (flags) {
- printk("Must not call schedule() with IRQs disabled\n");
- BUG();
- }
do {
/* Examine all threads.
@@ -164,30 +165,32 @@ struct _reent *__getreent(void)
struct _reent *_reent;
if (!threads_started)
- _reent = _impure_ptr;
+ _reent = _impure_ptr;
else if (in_callback)
- _reent = &callback_reent;
+ _reent = &callback_reent;
else
- _reent = &get_current()->reent;
+ _reent = &get_current()->reent;
#ifndef NDEBUG
#if defined(__x86_64__) || defined(__x86__)
{
#ifdef __x86_64__
- register unsigned long sp asm ("rsp");
+ register unsigned long sp asm ("rsp");
#else
- register unsigned long sp asm ("esp");
+ register unsigned long sp asm ("esp");
#endif
- if ((sp & (STACK_SIZE-1)) < STACK_SIZE / 16) {
- static int overflowing;
- if (!overflowing) {
- overflowing = 1;
- printk("stack overflow\n");
- BUG();
- }
- }
+ if ((sp & (STACK_SIZE-1)) < STACK_SIZE / 16) {
+ static int overflowing;
+ if (!overflowing) {
+ overflowing = 1;
+ printk("stack overflow\n");
+ BUG();
+ }
+ }
}
#endif
+#else
+#error Not implemented yet
#endif
return _reent;
}
diff --git a/extras/mini-os/test.c b/extras/mini-os/test.c
index bbfc613..0d7aba4 100644
--- a/extras/mini-os/test.c
+++ b/extras/mini-os/test.c
@@ -56,8 +56,20 @@ void test_xenbus(void);
static void xenbus_tester(void *p)
{
- printk("Xenbus tests disabled, because of a Xend bug.\n");
- /* test_xenbus(); */
+ test_xenbus();
+}
+#endif
+
+#ifndef HAVE_LIBC
+/* Should be random enough for our uses */
+int rand(void)
+{
+ static unsigned int previous;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ previous += tv.tv_sec + tv.tv_usec;
+ previous *= RAND_MIX;
+ return previous;
}
#endif
diff --git a/extras/mini-os/tpm_tis.c b/extras/mini-os/tpm_tis.c
index e8ca69f..d78c465 100644
--- a/extras/mini-os/tpm_tis.c
+++ b/extras/mini-os/tpm_tis.c
@@ -26,12 +26,18 @@
#include <mini-os/events.h>
#include <mini-os/wait.h>
#include <mini-os/xmalloc.h>
+#include <mini-os/lib.h>
#include <errno.h>
#include <stdbool.h>
#ifndef min
#define min( a, b ) ( ((a) < (b)) ? (a) : (b) )
#endif
+#define ADJUST_TIMEOUTS_TO_STANDARD(initial,standard,timeout_no) \
+ if((initial) < (standard)){ \
+ (initial) = (standard); \
+ printk("Timeout %c was adjusted to standard value.\n",timeout_no); \
+ }
#define TPM_HEADER_SIZE 10
@@ -611,7 +617,7 @@ s_time_t tpm_calc_ordinal_duration(struct tpm_chip *chip,
static int locality_enabled(struct tpm_chip* tpm, int l) {
- return tpm->enabled_localities & (1 << l);
+ return l >= 0 && tpm->enabled_localities & (1 << l);
}
static int check_locality(struct tpm_chip* tpm, int l) {
@@ -996,15 +1002,22 @@ int tpm_get_timeouts(struct tpm_chip *chip)
}
if (timeout)
chip->timeout_a = MICROSECS(timeout * scale); /*Convert to msec */
+ ADJUST_TIMEOUTS_TO_STANDARD(chip->timeout_a,MILLISECS(TIS_SHORT_TIMEOUT),'a');
+
timeout = be32_to_cpu(timeout_cap->b);
if (timeout)
chip->timeout_b = MICROSECS(timeout * scale); /*Convert to msec */
+ ADJUST_TIMEOUTS_TO_STANDARD(chip->timeout_b,MILLISECS(TIS_LONG_TIMEOUT),'b');
+
timeout = be32_to_cpu(timeout_cap->c);
if (timeout)
chip->timeout_c = MICROSECS(timeout * scale); /*Convert to msec */
+ ADJUST_TIMEOUTS_TO_STANDARD(chip->timeout_c,MILLISECS(TIS_SHORT_TIMEOUT),'c');
+
timeout = be32_to_cpu(timeout_cap->d);
if (timeout)
chip->timeout_d = MICROSECS(timeout * scale); /*Convert to msec */
+ ADJUST_TIMEOUTS_TO_STANDARD(chip->timeout_d,MILLISECS(TIS_SHORT_TIMEOUT),'d');
duration:
tpm_cmd.header.in = tpm_getcap_header;
diff --git a/extras/mini-os/tpmback.c b/extras/mini-os/tpmback.c
index 0601eb3..00b66e8 100644
--- a/extras/mini-os/tpmback.c
+++ b/extras/mini-os/tpmback.c
@@ -140,12 +140,12 @@ int globalinit = 0;
* Duplicates are not allowed
* **********************************/
-inline void tpmif_req_ready(tpmif_t* tpmif) {
+static void tpmif_req_ready(tpmif_t* tpmif) {
tpmif->flags |= TPMIF_REQ_READY;
gtpmdev.flags |= TPMIF_REQ_READY;
}
-inline void tpmdev_check_req(void) {
+static void tpmdev_check_req(void) {
int i;
int flags;
local_irq_save(flags);
@@ -160,7 +160,7 @@ inline void tpmdev_check_req(void) {
local_irq_restore(flags);
}
-inline void tpmif_req_finished(tpmif_t* tpmif) {
+static void tpmif_req_finished(tpmif_t* tpmif) {
tpmif->flags &= ~TPMIF_REQ_READY;
tpmdev_check_req();
}
@@ -332,6 +332,7 @@ error_post_irq:
* returns 0 on success and non-zero on error */
int tpmif_change_state(tpmif_t* tpmif, enum xenbus_state state)
{
+ int tempst;
char path[512];
char *value;
char *err;
@@ -347,11 +348,12 @@ int tpmif_change_state(tpmif_t* tpmif, enum xenbus_state state)
free(err);
return -1;
}
- if(sscanf(value, "%d", &readst) != 1) {
+ if(sscanf(value, "%d", &tempst) != 1) {
TPMBACK_ERR("Non integer value (%s) in %s ??\n", value, path);
free(value);
return -1;
}
+ readst = (enum xenbus_state) tempst;
free(value);
/* It's possible that the backend state got updated by hotplug or something else behind our back */
@@ -380,7 +382,7 @@ int tpmif_change_state(tpmif_t* tpmif, enum xenbus_state state)
/**********************************
* TPMIF CREATION AND DELETION
* *******************************/
-inline tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
+static tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
{
tpmif_t* tpmif;
tpmif = malloc(sizeof(*tpmif));
diff --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
index ce5b3e1..6049244 100644
--- a/extras/mini-os/tpmfront.c
+++ b/extras/mini-os/tpmfront.c
@@ -31,6 +31,7 @@
#include <xen/io/xenbus.h>
#include <xen/io/tpmif.h>
#include <mini-os/tpmfront.h>
+#include <mini-os/lib.h>
#include <fcntl.h>
//#define TPMFRONT_PRINT_DEBUG
diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
index c5d9b02..934f23b 100644
--- a/extras/mini-os/xenbus/xenbus.c
+++ b/extras/mini-os/xenbus/xenbus.c
@@ -276,7 +276,7 @@ static void xenbus_evtchn_handler(evtchn_port_t port, struct pt_regs *regs,
}
static int nr_live_reqs;
-static spinlock_t req_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(req_lock);
static DECLARE_WAIT_QUEUE_HEAD(req_wq);
/* Release a xenbus identifier */
diff --git a/install.sh b/install.sh
index 272123a..3e11c4d 100644
--- a/install.sh
+++ b/install.sh
@@ -27,9 +27,6 @@ tmp="`mktemp -d`"
echo "Installing Xen from '$src' to '$dst'..."
(cd $src; tar -cf - * ) | tar -C "$tmp" -xf -
-echo " - modifying permissions"
-chmod -R a+rX "$tmp"
-
(cd $tmp; tar -cf - *) | tar --no-same-owner -C "$dst" -xf -
rm -rf "$tmp"
diff --git a/m4/README.source b/m4/README.source
new file mode 100644
index 0000000..21850a6
--- /dev/null
+++ b/m4/README.source
@@ -0,0 +1,36 @@
+About
+=====
+This documents the upstream sources for the different slew of different
+m4 sources we have picked up or developed.
+
+pkg.m4
+======
+The pkg-config m4 macro library comes from the upstream pkg-config
+git repository [0]. If you update the m4 library update this file
+with provenance and last commit ID information. For documentation
+on how to use this read the pkg-config(1) man page.
+
+Do not modify this file yourself, if you want to evolve it send
+patches upstream and then synch back here.
+
+Tree: git://anongit.freedesktop.org/pkg-config
+
+The last synch was from commit:
+
+commit 4f0084d9d3b8726a797a373c7ec5e406000995d0
+Author: Dan Nicholson <dbn.lists at gmail.com>
+Date: Mon Feb 3 15:59:18 2014 -0800
+
+ glib: Fix Makefiles to suppress warnings from automake
+
+ With the newly added glib.mk, some of the noinst_* variables need to use
+ += in the evaluation to avoid multiple definition warnings from
+ automake.
+
+systemd.m4
+==========
+
+systemd.m4 was contributed to by Luis R. Rodriguez <mcgrof at do-not-panic.com>,
+its current home project can be found at:
+
+https://github.com/mcgrof/funk-systemd
diff --git a/m4/paths.m4 b/m4/paths.m4
new file mode 100644
index 0000000..7ede5bd
--- /dev/null
+++ b/m4/paths.m4
@@ -0,0 +1,113 @@
+AC_DEFUN([AX_XEN_EXPAND_CONFIG], [
+dnl expand these early so we can use this for substitutions
+test "x$prefix" = "xNONE" && prefix=$ac_default_prefix
+test "x$exec_prefix" = "xNONE" && exec_prefix=${prefix}
+
+dnl Use /var instead of /usr/local/var because there can be only one
+dnl xenstored active at a time. All tools have to share this dir, even
+dnl if they come from a different --prefix=.
+if test "$localstatedir" = '${prefix}/var' ; then
+ localstatedir=/var
+fi
+
+dnl expand exec_prefix or it will endup in substituted variables
+bindir=`eval echo $bindir`
+sbindir=`eval echo $sbindir`
+libdir=`eval echo $libdir`
+
+dnl
+if test "x$sysconfdir" = 'x${prefix}/etc' ; then
+ case "$host_os" in
+ *freebsd*)
+ sysconfdir=$prefix/etc
+ ;;
+ *solaris*)
+ if test "$prefix" = "/usr" ; then
+ sysconfdir=/etc
+ else
+ sysconfdir=$prefix/etc
+ fi
+ ;;
+ *)
+ sysconfdir=/etc
+ ;;
+ esac
+fi
+
+AC_ARG_WITH([initddir],
+ AS_HELP_STRING([--with-initddir=DIR],
+ [Path to directory with sysv runlevel scripts. [SYSCONFDIR/init.d]]),
+ [initddir_path=$withval],
+ [case "$host_os" in
+ *linux*)
+ if test -d $sysconfdir/rc.d/init.d ; then
+ initddir_path=$sysconfdir/rc.d/init.d
+ else
+ initddir_path=$sysconfdir/init.d
+ fi
+ ;;
+ *)
+ initddir_path=$sysconfdir/rc.d
+ ;;
+ esac])
+
+AC_ARG_WITH([sysconfig-leaf-dir],
+ AS_HELP_STRING([--with-sysconfig-leaf-dir=SUBDIR],
+ [Name of subdirectory in /etc to store runtime options for runlevel
+ scripts and daemons such as xenstored.
+ This should be either "sysconfig" or "default". [sysconfig]]),
+ [config_leaf_dir=$withval],
+ [config_leaf_dir=sysconfig
+ if test ! -d /etc/sysconfig ; then config_leaf_dir=default ; fi])
+CONFIG_LEAF_DIR=$config_leaf_dir
+AC_SUBST(CONFIG_LEAF_DIR)
+
+if test "$libexecdir" = '${exec_prefix}/libexec' ; then
+ case "$host_os" in
+ *netbsd*) ;;
+ *)
+ libexecdir='${exec_prefix}/lib'
+ ;;
+ esac
+fi
+dnl expand exec_prefix or it will endup in substituted variables
+libexecdir=`eval echo $libexecdir`
+dnl autoconf doc suggest to use a "package name" subdir
+dnl This variable will be substituted in various .in files
+LIBEXEC_BIN=`eval echo $libexecdir/$PACKAGE_TARNAME/bin`
+AC_SUBST(LIBEXEC_BIN)
+
+XEN_RUN_DIR=$localstatedir/run/xen
+AC_SUBST(XEN_RUN_DIR)
+
+XEN_LOG_DIR=$localstatedir/log/xen
+AC_SUBST(XEN_LOG_DIR)
+
+XEN_LIB_STORED=$localstatedir/lib/xenstored
+AC_SUBST(XEN_LIB_STORED)
+
+SHAREDIR=$prefix/share
+AC_SUBST(SHAREDIR)
+
+CONFIG_DIR=$sysconfdir
+AC_SUBST(CONFIG_DIR)
+
+INITD_DIR=$initddir_path
+AC_SUBST(INITD_DIR)
+
+XEN_CONFIG_DIR=$CONFIG_DIR/xen
+AC_SUBST(XEN_CONFIG_DIR)
+
+XEN_SCRIPT_DIR=$XEN_CONFIG_DIR/scripts
+AC_SUBST(XEN_SCRIPT_DIR)
+
+case "$host_os" in
+*freebsd*) XEN_LOCK_DIR=$localstatedir/lib ;;
+*netbsd*) XEN_LOCK_DIR=$localstatedir/lib ;;
+*) XEN_LOCK_DIR=$localstatedir/lock ;;
+esac
+AC_SUBST(XEN_LOCK_DIR)
+
+XEN_PAGING_DIR=$localstatedir/lib/xen/xenpaging
+AC_SUBST(XEN_PAGING_DIR)
+])
diff --git a/m4/pkg.m4 b/m4/pkg.m4
index 9bb3e06..62995f0 100644
--- a/m4/pkg.m4
+++ b/m4/pkg.m4
@@ -26,7 +26,8 @@
# ----------------------------------
AC_DEFUN([PKG_PROG_PKG_CONFIG],
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
-m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
@@ -72,7 +73,8 @@ m4_define([_PKG_CONFIG],
pkg_cv_[]$1="$$1"
elif test -n "$PKG_CONFIG"; then
PKG_CHECK_EXISTS([$3],
- [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes ],
[pkg_failed=yes])
else
pkg_failed=untried
@@ -120,9 +122,9 @@ if test $pkg_failed = yes; then
AC_MSG_RESULT([no])
_PKG_SHORT_ERRORS_SUPPORTED
if test $_pkg_short_errors_supported = yes; then
- $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
else
- $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
@@ -135,7 +137,7 @@ $$1_PKG_ERRORS
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
-_PKG_TEXT])dnl
+_PKG_TEXT])[]dnl
])
elif test $pkg_failed = untried; then
AC_MSG_RESULT([no])
@@ -146,7 +148,7 @@ path to pkg-config.
_PKG_TEXT
-To get pkg-config, see <http://pkg-config.freedesktop.org/>.])dnl
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
])
else
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
@@ -155,3 +157,77 @@ else
$3
fi[]dnl
])# PKG_CHECK_MODULES
+
+
+# PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+# ---------------------------------------------------------------------
+# Checks for existence of MODULES and gathers its build flags with
+# static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
+# and VARIABLE-PREFIX_LIBS from --libs.
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES_STATIC might not happen, you should be sure to include
+# an explicit call to PKG_PROG_PKG_CONFIG in your configure.ac.
+AC_DEFUN([PKG_CHECK_MODULES_STATIC],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+_save_PKG_CONFIG=$PKG_CONFIG
+PKG_CONFIG="$PKG_CONFIG --static"
+PKG_CHECK_MODULES($@)
+PKG_CONFIG=$_save_PKG_CONFIG[]dnl
+])
+
+
+# PKG_INSTALLDIR(DIRECTORY)
+# -------------------------
+# Substitutes the variable pkgconfigdir as the location where a module
+# should install pkg-config .pc files. By default the directory is
+# $libdir/pkgconfig, but the default can be changed by passing
+# DIRECTORY. The user can override through the --with-pkgconfigdir
+# parameter.
+AC_DEFUN([PKG_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+ [pkg-config installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([pkgconfigdir],
+ [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
+ [with_pkgconfigdir=]pkg_default)
+AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+]) dnl PKG_INSTALLDIR
+
+
+# PKG_NOARCH_INSTALLDIR(DIRECTORY)
+# -------------------------
+# Substitutes the variable noarch_pkgconfigdir as the location where a
+# module should install arch-independent pkg-config .pc files. By
+# default the directory is $datadir/pkgconfig, but the default can be
+# changed by passing DIRECTORY. The user can override through the
+# --with-noarch-pkgconfigdir parameter.
+AC_DEFUN([PKG_NOARCH_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+ [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([noarch-pkgconfigdir],
+ [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
+ [with_noarch_pkgconfigdir=]pkg_default)
+AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+]) dnl PKG_NOARCH_INSTALLDIR
+
+
+# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# -------------------------------------------
+# Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])# PKG_CHECK_VAR
diff --git a/m4/systemd.m4 b/m4/systemd.m4
new file mode 100644
index 0000000..a832d59
--- /dev/null
+++ b/m4/systemd.m4
@@ -0,0 +1,127 @@
+# systemd.m4 - Macros to check for and enable systemd -*- Autoconf -*-
+#
+# Copyright (C) 2014 Luis R. Rodriguez <mcgrof at suse.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+dnl Some optional path options
+AC_DEFUN([AX_SYSTEMD_OPTIONS], [
+ AC_ARG_WITH(systemd,
+ AS_HELP_STRING([--with-systemd=DIR],
+ [set directory for systemd service files [PREFIX/lib/systemd/system]]),
+ [SYSTEMD_DIR="$withval"],[SYSTEMD_DIR=""])
+ AC_SUBST(SYSTEMD_DIR)
+
+ AC_ARG_WITH(systemd-modules-load,
+ AS_HELP_STRING([--with-systemd-modules-load=DIR],
+ [set directory for systemd modules load files [PREFIX/lib/modules-load.d/]]),
+ [SYSTEMD_MODULES_LOAD="$withval"], [SYSTEMD_MODULES_LOAD=""])
+ AC_SUBST(SYSTEMD_MODULES_LOAD)
+])
+
+AC_DEFUN([AX_ENABLE_SYSTEMD_OPTS], [
+ AX_ARG_DEFAULT_ENABLE([systemd], [Disable systemd support])
+ AX_SYSTEMD_OPTIONS()
+])
+
+AC_DEFUN([AX_ALLOW_SYSTEMD_OPTS], [
+ AX_ARG_DEFAULT_DISABLE([systemd], [Enable systemd support])
+ AX_SYSTEMD_OPTIONS()
+])
+
+AC_DEFUN([AX_CHECK_SYSTEMD_LIBS], [
+ AC_CHECK_HEADER([systemd/sd-daemon.h], [
+ AC_CHECK_LIB([systemd-daemon], [sd_listen_fds], [libsystemddaemon="y"])
+ ])
+ AS_IF([test "x$libsystemddaemon" = x], [
+ AC_MSG_ERROR([Unable to find a suitable libsystemd-daemon library])
+ ])
+
+ PKG_CHECK_MODULES([SYSTEMD], [libsystemd-daemon])
+ dnl pkg-config older than 0.24 does not set these for
+ dnl PKG_CHECK_MODULES() worth also noting is that as of version 208
+ dnl of systemd pkg-config --cflags currently yields no extra flags yet.
+ AC_SUBST([SYSTEMD_CFLAGS])
+ AC_SUBST([SYSTEMD_LIBS])
+
+ AS_IF([test "x$SYSTEMD_DIR" = x], [
+ dnl In order to use the line below we need to fix upstream systemd
+ dnl to properly ${prefix} for child variables in
+ dnl src/core/systemd.pc.in but this is a bit complex at the
+ dnl moment as they depend on another rootprefix, which can vary
+ dnl from prefix in practice. We provide our own definition as we
+ dnl *know* where systemd will dump this to, but this does limit
+ dnl us to stick to a non custom systemdsystemunitdir, to work
+ dnl around this we provide the additional configure option
+ dnl --with-systemd where you can specify the directory for the unit
+ dnl files. It would also be best to just extend the upstream
+ dnl pkg-config pkg.m4 with an AC_DEFUN() to do this neatly.
+ dnl SYSTEMD_DIR="`$PKG_CONFIG --define-variable=prefix=$PREFIX --variable=systemdsystemunitdir systemd`"
+ SYSTEMD_DIR="\$(prefix)/lib/systemd/system/"
+ ], [])
+
+ AS_IF([test "x$SYSTEMD_DIR" = x], [
+ AC_MSG_ERROR([SYSTEMD_DIR is unset])
+ ], [])
+
+ dnl There is no variable for this yet for some reason
+ AS_IF([test "x$SYSTEMD_MODULES_LOAD" = x], [
+ SYSTEMD_MODULES_LOAD="\$(prefix)/lib/modules-load.d/"
+ ], [])
+
+ AS_IF([test "x$SYSTEMD_MODULES_LOAD" = x], [
+ AC_MSG_ERROR([SYSTEMD_MODULES_LOAD is unset])
+ ], [])
+])
+
+AC_DEFUN([AX_CHECK_SYSTEMD], [
+ dnl Respect user override to disable
+ AS_IF([test "x$enable_systemd" != "xno"], [
+ AS_IF([test "x$systemd" = "xy" ], [
+ AC_DEFINE([HAVE_SYSTEMD], [1], [Systemd available and enabled])
+ systemd=y
+ AX_CHECK_SYSTEMD_LIBS()
+ ],[systemd=n])
+ ],[systemd=n])
+])
+
+AC_DEFUN([AX_CHECK_SYSTEMD_ENABLE_AVAILABLE], [
+ AC_CHECK_HEADER([systemd/sd-daemon.h], [
+ AC_CHECK_LIB([systemd-daemon], [sd_listen_fds], [systemd="y"])
+ ])
+])
+
+dnl Enables systemd by default and requires a --disable-systemd option flag
+dnl to configure if you want to disable.
+AC_DEFUN([AX_ENABLE_SYSTEMD], [
+ AX_ENABLE_SYSTEMD_OPTS()
+ AX_CHECK_SYSTEMD()
+])
+
+dnl Systemd will be disabled by default and requires you to run configure with
+dnl --enable-systemd to look for and enable systemd.
+AC_DEFUN([AX_ALLOW_SYSTEMD], [
+ AX_ALLOW_SYSTEMD_OPTS()
+ AX_CHECK_SYSTEMD()
+])
+
+dnl Systemd will be disabled by default but if your build system is detected
+dnl to have systemd build libraries it will be enabled. You can always force
+dnl disable with --disable-systemd
+AC_DEFUN([AX_AVAILABLE_SYSTEMD], [
+ AX_ALLOW_SYSTEMD_OPTS()
+ AX_CHECK_SYSTEMD_ENABLE_AVAILABLE()
+ AX_CHECK_SYSTEMD()
+])
diff --git a/m4/xenstored.m4 b/m4/xenstored.m4
new file mode 100644
index 0000000..fb77b4a
--- /dev/null
+++ b/m4/xenstored.m4
@@ -0,0 +1,56 @@
+AC_DEFUN([AX_XEN_OCAML_XENSTORE_CHECK], [
+ AS_IF([test "$ocamltools" = "n"], [
+ AC_MSG_ERROR([Missing ocaml dependencies for oxenstored, try installing ocaml ocaml-compiler-libs ocaml-runtime ocaml-findlib])
+ ])
+])
+
+AC_DEFUN([AX_XEN_OCAML_XENSTORE_DEFAULTS], [
+ xenstore="oxenstored"
+ xenstored=$sbindir/oxenstored
+ AS_IF([test "$ocamltools" = "n"], [
+ xenstore="xenstored"
+ xenstored=$sbindir/xenstored
+ ])
+])
+
+AC_DEFUN([AX_XENSTORE_OPTIONS], [
+AS_IF([test "x$XENSTORE" = "x"], [
+AC_ARG_WITH([xenstored],
+ AS_HELP_STRING([--with-xenstored@<:@=oxenstored|xenstored@:>@],
+ [This lets you choose which xenstore daemon you want, you have
+ two options: the original xenstored written in C (xenstored)
+ or the newer and robust one written in Ocaml (oxenstored).
+ The oxenstored daemon is the default but can only
+ be used if you have ocaml library / build dependencies solved,
+ if you have not specified a preference and do not have ocaml
+ dependencies resolved we'll enable the C xenstored for you. If
+ you ask for oxenstored we'll complain until you resolve those
+ dependencies]),
+ [
+ AS_IF([test "x$withval" = "xxenstored"], [
+ xenstore=$withval
+ xenstored=$sbindir/xenstored
+ ])
+ AS_IF([test "x$withval" = "xoxenstored"], [
+ xenstore=$withval
+ xenstored=$sbindir/oxenstored
+ AX_XEN_OCAML_XENSTORE_CHECK()
+ ])
+ AS_IF([test "x$withval" != "xoxenstored" && test "x$withval" != "xxenstored"], [
+ AC_MSG_ERROR([Unsupported xenstored specified, supported types: oxenstored xenstored])
+ ])
+ ],
+ [
+ AX_XEN_OCAML_XENSTORE_DEFAULTS()
+ ])
+])
+])
+
+AC_DEFUN([AX_XENSTORE_SET], [
+ XENSTORE=$xenstore
+
+ AS_IF([test "x$XENSTORED" = "x"], [
+ XENSTORED=$xenstored
+ ])
+ AC_SUBST(XENSTORED)
+])
diff --git a/misc/coverity/model.c b/misc/coverity/model.c
new file mode 100644
index 0000000..bd62566
--- /dev/null
+++ b/misc/coverity/model.c
@@ -0,0 +1,141 @@
+/* Coverity Scan model
+ *
+ * This is a modelling file for Coverity Scan. Modelling helps to avoid false
+ * positives.
+ *
+ * - A model file can't import any header files.
+ * - Therefore only some built-in primitives like int, char and void are
+ * available but not NULL etc.
+ * - Modelling doesn't need full structs and typedefs. Rudimentary structs
+ * and similar types are sufficient.
+ * - An uninitialised local pointer is not an error. It signifies that the
+ * variable could be either NULL or have some data.
+ *
+ * Coverity Scan doesn't pick up modifications automatically. The model file
+ * must be uploaded by an admin in the analysis.
+ *
+ * The Xen Coverity Scan modelling file used the cpython modelling file as a
+ * reference to get started (suggested by Coverty Scan themselves as a good
+ * example), but all content is Xen specific.
+ *
+ * Copyright (c) 2013-2014 Citrix Systems Ltd; All Right Reserved
+ *
+ * Based on:
+ * http://hg.python.org/cpython/file/tip/Misc/coverity_model.c
+ * Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+ * 2011, 2012, 2013 Python Software Foundation; All Rights Reserved
+ *
+ */
+
+/*
+ * Useful references:
+ * https://scan.coverity.com/models
+ */
+
+/* Definitions */
+#define NULL (void *)0
+#define PAGE_SIZE 4096UL
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+#define assert(cond) /* empty */
+
+struct page_info {};
+struct pthread_mutex_t {};
+
+struct libxl__ctx
+{
+ struct pthread_mutex_t lock;
+};
+typedef struct libxl__ctx libxl_ctx;
+
+/*
+ * Xen malloc. Behaves exactly like regular malloc(), except it also contains
+ * an alignment parameter.
+ *
+ * TODO: work out how to correctly model bad alignments as errors.
+ */
+void *_xmalloc(unsigned long size, unsigned long align)
+{
+ int has_memory;
+
+ __coverity_negative_sink__(size);
+ __coverity_negative_sink__(align);
+
+ if ( has_memory )
+ return __coverity_alloc__(size);
+ else
+ return NULL;
+}
+
+/*
+ * Xen free. Frees a pointer allocated by _xmalloc().
+ */
+void xfree(void *va)
+{
+ __coverity_free__(va);
+}
+
+
+/*
+ * map_domain_page() takes an existing domain page and possibly maps it into
+ * the Xen pagetables, to allow for direct access. Model this as a memory
+ * allocation of exactly 1 page.
+ *
+ * map_domain_page() never fails. (It will BUG() before returning NULL)
+ *
+ * TODO: work out how to correctly model the behaviour that this function will
+ * only ever return page aligned pointers.
+ */
+void *map_domain_page(unsigned long mfn)
+{
+ return __coverity_alloc__(PAGE_SIZE);
+}
+
+/*
+ * unmap_domain_page() will unmap a page. Model it as a free().
+ */
+void unmap_domain_page(const void *va)
+{
+ __coverity_free__(va);
+}
+
+/*
+ * Coverity appears not to understand that errx() unconditionally exits.
+ */
+void errx(int, const char*, ...)
+{
+ __coverity_panic__();
+}
+
+/*
+ * Coverity doesn't appear to be certain that the libxl ctx->lock is recursive.
+ */
+void libxl__ctx_lock(libxl_ctx *ctx)
+{
+ __coverity_recursive_lock_acquire__(&ctx->lock);
+}
+
+void libxl__ctx_unlock(libxl_ctx *ctx)
+{
+ __coverity_recursive_lock_release__(&ctx->lock);
+}
+
+/*
+ * Coverity doesn't understand __builtin_unreachable(), which causes it to
+ * incorrectly find issues based on continuing execution along the false
+ * branch of an ASSERT().
+ */
+void __builtin_unreachable(void)
+{
+ __coverity_panic__();
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index df920e2..cc445cd 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -35,7 +35,7 @@ my $email_git_min_percent = 5;
my $email_git_since = "1-year-ago";
my $email_hg_since = "-365";
my $interactive = 0;
-my $email_remove_duplicates = 1;
+my $email_remove_duplicates = 0;
my $email_use_mailmap = 1;
my $email_drop_the_rest_supporter_if_supporter_found = 1;
my $output_multiline = 1;
diff --git a/stubdom/Makefile b/stubdom/Makefile
index 19f2228..8fb885a 100644
--- a/stubdom/Makefile
+++ b/stubdom/Makefile
@@ -23,9 +23,6 @@ TARGET_CFLAGS=-mno-red-zone
NEWLIB_CFLAGS+=-D_I386MACH_ALLOW_HW_INTERRUPTS
STUBDOM_SUPPORTED=1
endif
-ifeq ($(GNU_TARGET_ARCH), ia64)
-TARGET_CFLAGS=-mconstant-gp
-endif
CROSS_ROOT=cross-root-$(GNU_TARGET_ARCH)
CROSS_PREFIX=$(CURDIR)/$(CROSS_ROOT)
@@ -51,18 +48,18 @@ TARGET_LDFLAGS += -nostdlib -L$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/lib
TARGETS=$(STUBDOM_TARGETS)
+STUBDOMPATH="stubdompath.sh"
+genpath-target = $(call buildmakevars2file,$(STUBDOMPATH))
+$(eval $(genpath-target))
+
.PHONY: all
all: build
ifeq ($(STUBDOM_SUPPORTED),1)
-build: genpath $(STUBDOM_BUILD)
+build: $(STUBDOMPATH) $(STUBDOM_BUILD)
else
-build: genpath
+build: $(STUBDOMPATH)
endif
-STUBDOMPATH="stubdompath.sh"
-genpath-target = $(call buildmakevars2file,$(STUBDOMPATH))
-$(eval $(genpath-target))
-
##############
# Cross-newlib
##############
@@ -148,6 +145,7 @@ lwip-$(XEN_TARGET_ARCH): lwip-$(LWIP_VERSION).tar.gz
tar xzf $<
mv lwip $@
patch -d $@ -p0 < lwip.patch-cvs
+ patch -d $@ -p0 < lwip.dhcp_create_request-hwaddr_len.patch
touch $@
#############
@@ -211,6 +209,9 @@ tpm_emulator-$(XEN_TARGET_ARCH): tpm_emulator-$(TPMEMU_VERSION).tar.gz
patch -d $@ -p1 < tpmemu-$(TPMEMU_VERSION).patch;
patch -d $@ -p1 < vtpm-bufsize.patch
patch -d $@ -p1 < vtpm-locality.patch
+ patch -d $@ -p1 < vtpm-parent-sign-ek.patch
+ patch -d $@ -p1 < vtpm-deepquote.patch
+ patch -d $@ -p1 < vtpm-cmake-Wextra.patch
mkdir $@/build
cd $@/build; CC=${CC} $(CMAKE) .. -DCMAKE_C_FLAGS:STRING="-std=c99 -DTPM_NO_EXTERN $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -Wno-declaration-after-statement"
touch $@
@@ -262,7 +263,7 @@ $(OCAML_STAMPFILE): ocaml-$(XEN_TARGET_ARCH)/.dirstamp
.PHONY: $(CROSS_ROOT)
$(CROSS_ROOT): cross-newlib cross-zlib cross-libpci
-QEMU_ROOT := $(shell if [ -d "$(CONFIG_QEMU)" ]; then echo "$(CONFIG_QEMU)"; else echo .; fi)
+QEMU_ROOT := $(shell if [ -d "$(QEMU_TRADITIONAL_LOC)" ]; then echo "$(QEMU_TRADITIONAL_LOC)"; else echo .; fi)
ifneq ($(filter ioemu,$(STUBDOM_TARGETS)),)
IOEMU_LINKFARM_TARGET := ioemu/linkfarm.stamp
@@ -306,12 +307,14 @@ mk-headers-$(XEN_TARGET_ARCH): $(IOEMU_LINKFARM_TARGET)
mkdir -p libxc-$(XEN_TARGET_ARCH)
[ -h libxc-$(XEN_TARGET_ARCH)/Makefile ] || ( cd libxc-$(XEN_TARGET_ARCH) && \
ln -sf $(XEN_ROOT)/tools/libxc/*.h . && \
+ ln -sf $(XEN_ROOT)/tools/libxc/include/*.h . && \
ln -sf $(XEN_ROOT)/tools/libxc/*.c . && \
ln -sf $(XEN_ROOT)/tools/libxc/Makefile . )
mkdir -p xenstore
[ -h xenstore/Makefile ] || ( cd xenstore && \
ln -sf $(XEN_ROOT)/tools/xenstore/*.c . && \
ln -sf $(XEN_ROOT)/tools/xenstore/*.h . && \
+ ln -sf $(XEN_ROOT)/tools/xenstore/include/*.h . && \
ln -sf $(XEN_ROOT)/tools/xenstore/Makefile . )
$(MAKE) DESTDIR= -C $(MINI_OS) links
touch mk-headers-$(XEN_TARGET_ARCH)
@@ -449,9 +452,9 @@ xenstore-stubdom: mini-os-$(XEN_TARGET_ARCH)-xenstore libxc xenstore
#########
ifeq ($(STUBDOM_SUPPORTED),1)
-install: genpath install-readme $(STUBDOM_INSTALL)
+install: $(STUBDOMPATH) install-readme $(STUBDOM_INSTALL)
else
-install: genpath
+install: $(STUBDOMPATH)
endif
install-readme:
@@ -459,9 +462,9 @@ install-readme:
$(INSTALL_DATA) README $(DESTDIR)$(DOCDIR)/README.stubdom
install-ioemu: ioemu-stubdom
- $(INSTALL_DIR) "$(DESTDIR)$(LIBEXEC)"
- $(INSTALL_PROG) stubdom-dm "$(DESTDIR)$(LIBEXEC)"
- $(INSTALL_DATA) stubdompath.sh "$(DESTDIR)$(LIBEXEC)"
+ $(INSTALL_DIR) "$(DESTDIR)$(LIBEXEC_BIN)"
+ $(INSTALL_PROG) stubdom-dm "$(DESTDIR)$(LIBEXEC_BIN)"
+ $(INSTALL_DATA) stubdompath.sh "$(DESTDIR)$(LIBEXEC_BIN)"
$(INSTALL_DIR) "$(DESTDIR)$(XENFIRMWAREDIR)"
$(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-ioemu/mini-os.gz "$(DESTDIR)$(XENFIRMWAREDIR)/ioemu-stubdom.gz"
@@ -469,6 +472,8 @@ install-grub: pv-grub
$(INSTALL_DIR) "$(DESTDIR)$(XENFIRMWAREDIR)"
$(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-grub/mini-os.gz "$(DESTDIR)$(XENFIRMWAREDIR)/pv-grub-$(XEN_TARGET_ARCH).gz"
+install-c: c-stubdom
+
install-caml: caml-stubdom
install-xenstore: xenstore-stubdom
diff --git a/stubdom/README b/stubdom/README
index 8d5da9a..de7b6c7 100644
--- a/stubdom/README
+++ b/stubdom/README
@@ -22,15 +22,6 @@ See xl.cfg(5) for more details of the xl domain configuration syntax
and http://wiki.xen.org/wiki/Device_Model_Stub_Domains for more
information on device model stub domains
-Using with XM/xend
-------------------
-
-There is a sample configuration set in xmexample.hvm-stubdom
-
-In your HVM config "hvmconfig" use stubdom-dm as dm script:
-
-device_model = 'stubdom-dm'
-
PV-GRUB
=======
diff --git a/stubdom/c/minios.cfg b/stubdom/c/minios.cfg
index e1faee5..e69de29 100644
--- a/stubdom/c/minios.cfg
+++ b/stubdom/c/minios.cfg
@@ -1 +0,0 @@
-CONFIG_TEST=y
diff --git a/stubdom/caml/minios.cfg b/stubdom/caml/minios.cfg
index e1faee5..e69de29 100644
--- a/stubdom/caml/minios.cfg
+++ b/stubdom/caml/minios.cfg
@@ -1 +0,0 @@
-CONFIG_TEST=y
diff --git a/stubdom/configure b/stubdom/configure
index 5b0ce0e..9981f5a 100755
--- a/stubdom/configure
+++ b/stubdom/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Xen Hypervisor Stub Domains 4.4.
+# Generated by GNU Autoconf 2.69 for Xen Hypervisor Stub Domains 4.5.
#
# Report bugs to <xen-devel at lists.xen.org>.
#
@@ -579,8 +579,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='Xen Hypervisor Stub Domains'
PACKAGE_TARNAME='xen'
-PACKAGE_VERSION='4.4'
-PACKAGE_STRING='Xen Hypervisor Stub Domains 4.4'
+PACKAGE_VERSION='4.5'
+PACKAGE_STRING='Xen Hypervisor Stub Domains 4.5'
PACKAGE_BUGREPORT='xen-devel at lists.xen.org'
PACKAGE_URL='http://www.xen.org/'
@@ -1250,7 +1250,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures Xen Hypervisor Stub Domains 4.4 to adapt to many kinds of systems.
+\`configure' configures Xen Hypervisor Stub Domains 4.5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1315,7 +1315,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of Xen Hypervisor Stub Domains 4.4:";;
+ short | recursive ) echo "Configuration of Xen Hypervisor Stub Domains 4.5:";;
esac
cat <<\_ACEOF
@@ -1425,7 +1425,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-Xen Hypervisor Stub Domains configure 4.4
+Xen Hypervisor Stub Domains configure 4.5
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1480,7 +1480,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by Xen Hypervisor Stub Domains $as_me 4.4, which was
+It was created by Xen Hypervisor Stub Domains $as_me 4.5, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -4178,7 +4178,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by Xen Hypervisor Stub Domains $as_me 4.4, which was
+This file was extended by Xen Hypervisor Stub Domains $as_me 4.5, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -4232,7 +4232,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-Xen Hypervisor Stub Domains config.status 4.4
+Xen Hypervisor Stub Domains config.status 4.5
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/stubdom/grub.patches/11graphics-keyboard.diff b/stubdom/grub.patches/11graphics-keyboard.diff
new file mode 100644
index 0000000..fe17b20
--- /dev/null
+++ b/stubdom/grub.patches/11graphics-keyboard.diff
@@ -0,0 +1,13 @@
+diff --git a/stage2/stage2.c b/stage2/stage2.c
+index 9d9fcc3..8353a3b 100644
+--- a/stage2/stage2.c
++++ b/stage2/stage2.c
+@@ -395,7 +395,7 @@ restart:
+ pressed.
+ This avoids polling (relevant in the grub-shell and later on
+ in grub if interrupt driven I/O is done). */
+- if (checkkey () >= 0 || grub_timeout < 0)
++ if (checkkey () > 0 || grub_timeout < 0)
+ {
+ /* Key was pressed, show which entry is selected before GETKEY,
+ since we're comming in here also on GRUB_TIMEOUT == -1 and
diff --git a/stubdom/grub/Makefile b/stubdom/grub/Makefile
index 6bd2c4c..934cc4c 100644
--- a/stubdom/grub/Makefile
+++ b/stubdom/grub/Makefile
@@ -5,7 +5,7 @@ vpath %.c ../grub-upstream
BOOT=$(OBJ_DIR)/boot-$(XEN_TARGET_ARCH).o
-DEF_CPPFLAGS += -I$(XEN_ROOT)/tools/libxc -I$(XEN_ROOT)/tools/include -I.
+DEF_CPPFLAGS += -I$(XEN_ROOT)/tools/libxc/include -I$(XEN_ROOT)/tools/include -I.
DEF_CPPFLAGS += -I../grub-upstream/stage1
DEF_CPPFLAGS += -I../grub-upstream/stage2
DEF_CPPFLAGS += -I../grub-upstream/netboot
diff --git a/stubdom/grub/kexec.c b/stubdom/grub/kexec.c
index cef357e..dc8db81 100644
--- a/stubdom/grub/kexec.c
+++ b/stubdom/grub/kexec.c
@@ -68,6 +68,14 @@ struct pcr_extend_cmd {
unsigned char hash[20];
} __attribute__((packed));
+struct pcr_extend_rsp {
+ uint16_t tag;
+ uint32_t size;
+ uint32_t status;
+
+ unsigned char hash[20];
+} __attribute__((packed));
+
/* Not imported from polarssl's header since the prototype unhelpfully defines
* the input as unsigned char, which causes pointer type mismatches */
void sha1(const void *input, size_t ilen, unsigned char output[20]);
@@ -135,20 +143,49 @@ int kexec_allocate(struct xc_dom_image *dom, xen_vaddr_t up_to)
return 0;
}
+/* Filled from mini-os command line or left as NULL */
+char *vtpm_label;
+
static void tpm_hash2pcr(struct xc_dom_image *dom, char *cmdline)
{
struct tpmfront_dev* tpm = init_tpmfront(NULL);
- uint8_t *resp;
+ struct pcr_extend_rsp *resp;
size_t resplen = 0;
struct pcr_extend_cmd cmd;
+ int rv;
- /* If all guests have access to a vTPM, it may be useful to replace this
- * with ASSERT(tpm) to prevent configuration errors from allowing a guest
- * to boot without a TPM (or with a TPM that has not been sent any
- * measurements, which could allow forging the measurements).
+ /*
+ * If vtpm_label was specified on the command line, require a vTPM to be
+ * attached and for the domain providing the vTPM to have the given
+ * label.
*/
- if (!tpm)
+ if (vtpm_label) {
+ char ctx[128];
+ if (!tpm) {
+ printf("No TPM found and vtpm_label specified, aborting!\n");
+ do_exit();
+ }
+ rv = evtchn_get_peercontext(tpm->evtchn, ctx, sizeof(ctx) - 1);
+ if (rv < 0) {
+ printf("Could not verify vtpm_label: %d\n", rv);
+ do_exit();
+ }
+ ctx[127] = 0;
+ rv = strcmp(ctx, vtpm_label);
+ if (rv && vtpm_label[0] == '*') {
+ int match_len = strlen(vtpm_label) - 1;
+ int offset = strlen(ctx) - match_len;
+ if (offset > 0)
+ rv = strcmp(ctx + offset, vtpm_label + 1);
+ }
+
+ if (rv) {
+ printf("Mismatched vtpm_label: '%s' != '%s'\n", ctx, vtpm_label);
+ do_exit();
+ }
+ } else if (!tpm) {
return;
+ }
cmd.tag = bswap_16(TPM_TAG_RQU_COMMAND);
cmd.size = bswap_32(sizeof(cmd));
@@ -156,15 +193,18 @@ static void tpm_hash2pcr(struct xc_dom_image *dom, char *cmdline)
cmd.pcr = bswap_32(4); // PCR #4 for kernel
sha1(dom->kernel_blob, dom->kernel_size, cmd.hash);
- tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen);
+ rv = tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), (void*)&resp, &resplen);
+ ASSERT(rv == 0 && resp->status == 0);
cmd.pcr = bswap_32(5); // PCR #5 for cmdline
sha1(cmdline, strlen(cmdline), cmd.hash);
- tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen);
+ rv = tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), (void*)&resp, &resplen);
+ ASSERT(rv == 0 && resp->status == 0);
cmd.pcr = bswap_32(5); // PCR #5 for initrd
sha1(dom->ramdisk_blob, dom->ramdisk_size, cmd.hash);
- tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen);
+ rv = tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), (void*)&resp, &resplen);
+ ASSERT(rv == 0 && resp->status == 0);
shutdown_tpmfront(tpm);
}
diff --git a/stubdom/grub/mini-os.c b/stubdom/grub/mini-os.c
index 64ab962..4fc052a 100644
--- a/stubdom/grub/mini-os.c
+++ b/stubdom/grub/mini-os.c
@@ -333,7 +333,7 @@ struct frame {
static void minios_transmit (struct nic *nic, const char *d, unsigned int t,
unsigned int s, const char *p)
{
- struct frame *frame = alloca(sizeof(frame) + s);
+ struct frame *frame = alloca(sizeof(*frame) + s);
memcpy(frame->dest, d, ETH_ALEN);
memcpy(frame->src, nic->node_addr, ETH_ALEN);
@@ -735,8 +735,14 @@ void __attribute__ ((noreturn)) grub_reboot (void)
* for grub's 32bit pointers to work */
char grub_scratch_mem[SCRATCH_MEMSIZE] __attribute__((aligned(PAGE_SIZE)));
-int main(int argc, char *argv[])
+int main(int argc, char **argv)
{
+ if (argc > 1 && memcmp(argv[1], "--vtpm-label=", 13) == 0) {
+ vtpm_label = argv[1] + 13;
+ argc--;
+ argv++;
+ }
+
if (argc > 1) {
strncpy(config_file, argv[1], sizeof(config_file) - 1);
config_file[sizeof(config_file) - 1] = 0;
diff --git a/stubdom/grub/mini-os.h b/stubdom/grub/mini-os.h
index 6c68441..9ec2bda 100644
--- a/stubdom/grub/mini-os.h
+++ b/stubdom/grub/mini-os.h
@@ -3,3 +3,5 @@ extern struct blkfront_dev **blk_dev;
extern struct netfront_dev *net_dev;
extern struct kbdfront_dev *kbd_dev;
extern struct fbfront_dev *fb_dev;
+
+extern char* vtpm_label;
diff --git a/stubdom/lwip.dhcp_create_request-hwaddr_len.patch b/stubdom/lwip.dhcp_create_request-hwaddr_len.patch
new file mode 100644
index 0000000..c43f282
--- /dev/null
+++ b/stubdom/lwip.dhcp_create_request-hwaddr_len.patch
@@ -0,0 +1,13 @@
+Index: src/core/dhcp.c
+===================================================================
+--- src/core/dhcp.c
++++ src/core/dhcp.c
+@@ -1356,7 +1358,7 @@ dhcp_create_request(struct netif *netif)
+ dhcp->msg_out->giaddr.addr = 0;
+ for (i = 0; i < DHCP_CHADDR_LEN; i++) {
+ /* copy netif hardware address, pad with zeroes */
+- dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0/* pad byte*/;
++ dhcp->msg_out->chaddr[i] = (i < (netif->hwaddr_len > NETIF_MAX_HWADDR_LEN ? NETIF_MAX_HWADDR_LEN : netif->hwaddr_len)) ? netif->hwaddr[i] : 0/* pad byte*/;
+ }
+ for (i = 0; i < DHCP_SNAME_LEN; i++) {
+ dhcp->msg_out->sname[i] = 0;
diff --git a/stubdom/newlib.patch b/stubdom/newlib.patch
index 733dc13..ee9b6f2 100644
--- a/stubdom/newlib.patch
+++ b/stubdom/newlib.patch
@@ -81,28 +81,6 @@ diff -u -p -r1.10 stdint.h
Define the basic ia64 jump buffer
-Index: newlib/libc/include/machine/setjmp.h
-===================================================================
-RCS file: /cvs/src/src/newlib/libc/include/machine/setjmp.h,v
-retrieving revision 1.34
-diff -u -p -r1.34 setjmp.h
---- newlib/libc/include/machine/setjmp.h 7 Nov 2007 21:42:24 -0000 1.34
-+++ newlib/libc/include/machine/setjmp.h 11 Jan 2008 18:10:43 -0000
-@@ -72,6 +72,11 @@ _BEGIN_STD_C
- #define _JBLEN 8
- #endif
-
-+#ifdef __ia64__
-+#define _JBTYPE long
-+#define _JBLEN 70
-+#endif
-+
- #ifdef __i960__
- #define _JBLEN 35
- #endif
-
-In mini-os we use a dynamic reentrency buffer.
-
Index: newlib/libc/include/sys/config.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/include/sys/config.h,v
diff --git a/stubdom/vtpm-cmake-Wextra.patch b/stubdom/vtpm-cmake-Wextra.patch
new file mode 100644
index 0000000..a603654
--- /dev/null
+++ b/stubdom/vtpm-cmake-Wextra.patch
@@ -0,0 +1,21 @@
+---
+ CMakeLists.txt | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+Index: tpm_emulator-x86_64/CMakeLists.txt
+===================================================================
+--- tpm_emulator-x86_64.orig/CMakeLists.txt
++++ tpm_emulator-x86_64/CMakeLists.txt
+@@ -40,10 +40,11 @@ set(TPM_STORAGE_NAME "/var/lib/tpm/tpm_e
+ set(TPM_DEVICE_NAME "/dev/tpm")
+ endif()
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+-add_definitions(-Wall -Werror -Wno-unused-parameter -Wpointer-arith -Wcast-align -Wwrite-strings)
++add_definitions(-Wall -Werror)
+ if("${CMAKE_SYSTEM}" MATCHES "Linux")
+ add_definitions(-Wextra)
+ endif()
++add_definitions(-Wno-unused-parameter -Wpointer-arith -Wcast-align -Wwrite-strings)
+ if(USE_OPENSSL)
+ add_definitions(-DUSE_OPENSSL)
+ endif()
diff --git a/stubdom/vtpm-deepquote.patch b/stubdom/vtpm-deepquote.patch
new file mode 100644
index 0000000..6344f38
--- /dev/null
+++ b/stubdom/vtpm-deepquote.patch
@@ -0,0 +1,187 @@
+diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c
+index 0fabf98..69511d1 100644
+--- a/tpm/tpm_cmd_handler.c
++++ b/tpm/tpm_cmd_handler.c
+@@ -3343,6 +3343,39 @@ static TPM_RESULT execute_TPM_ParentSignEK(TPM_REQUEST *req, TPM_RESPONSE *rsp)
+ return res;
+ }
+
++static TPM_RESULT execute_TPM_DeepQuote(TPM_REQUEST *req, TPM_RESPONSE *rsp)
++{
++ TPM_NONCE nonce;
++ TPM_RESULT res;
++ UINT32 sigSize;
++ BYTE *sig;
++ BYTE *ptr;
++ UINT32 len;
++ TPM_PCR_SELECTION myPCR;
++ TPM_PCR_SELECTION ptPCR;
++
++ tpm_compute_in_param_digest(req);
++
++ ptr = req->param;
++ len = req->paramSize;
++ if (tpm_unmarshal_TPM_NONCE(&ptr, &len, &nonce)
++ || tpm_unmarshal_TPM_PCR_SELECTION(&ptr, &len, &myPCR)
++ || tpm_unmarshal_TPM_PCR_SELECTION(&ptr, &len, &ptPCR)
++ || len != 0) return TPM_BAD_PARAMETER;
++
++ res = TPM_DeepQuote(&nonce, &myPCR, &ptPCR, &req->auth1, &sigSize, &sig);
++ if (res != TPM_SUCCESS) return res;
++ rsp->paramSize = len = sigSize;
++ rsp->param = ptr = tpm_malloc(len);
++ if (ptr == NULL || tpm_marshal_BLOB(&ptr, &len, sig, sigSize)) {
++ tpm_free(rsp->param);
++ res = TPM_FAIL;
++ }
++ tpm_free(sig);
++
++ return res;
++}
++
+ static void tpm_setup_rsp_auth(TPM_COMMAND_CODE ordinal, TPM_RESPONSE *rsp)
+ {
+ tpm_hmac_ctx_t hmac;
+@@ -4098,6 +4131,11 @@ void tpm_execute_command(TPM_REQUEST *req, TPM_RESPONSE *rsp)
+ res = execute_TPM_ParentSignEK(req, rsp);
+ break;
+
++ case TPM_ORD_DeepQuote:
++ debug("[TPM_ORD_DeepQuote]");
++ res = execute_TPM_DeepQuote(req, rsp);
++ break;
++
+ default:
+ #ifdef MTM_EMULATOR
+ res = mtm_execute_command(req, rsp);
+diff --git a/tpm/tpm_commands.h b/tpm/tpm_commands.h
+index 7fef934..328d1be 100644
+--- a/tpm/tpm_commands.h
++++ b/tpm/tpm_commands.h
+@@ -3071,6 +3071,25 @@ TPM_RESULT TPM_ParentSignEK(
+ BYTE **sig
+ );
+
++/**
++ * TPM_DeepQuote - gets a hardware TPM quote of a vTPM's PCRs
++ * @externalData: [in] AntiReplay nonce to prevent replay of messages
++ * @myPCR: [in] PCR selection for the virtual TPM
++ * @ptPCR: [in] PCR selection for the hardware TPM
++ * @auth1: [in, out] Authorization protocol parameters
++ * @sigSize: [out] The length of the returned digital signature
++ * @sig: [out] The resulting digital signature and PCR values
++ * Returns: TPM_SUCCESS on success, a TPM error code otherwise.
++ */
++TPM_RESULT TPM_DeepQuote(
++ TPM_NONCE *externalData,
++ TPM_PCR_SELECTION *myPCR,
++ TPM_PCR_SELECTION *ptPCR,
++ TPM_AUTH *auth1,
++ UINT32 *sigSize,
++ BYTE **sig
++);
++
+ /*
+ * Error handling
+ * [tpm_error.c]
+diff --git a/tpm/tpm_credentials.c b/tpm/tpm_credentials.c
+index 01f29e6..c0d62e7 100644
+--- a/tpm/tpm_credentials.c
++++ b/tpm/tpm_credentials.c
+@@ -211,3 +211,49 @@ TPM_RESULT TPM_ParentSignEK(TPM_NONCE *externalData, TPM_PCR_SELECTION *sel,
+ free_TPM_PUBKEY(pubKey);
+ return res;
+ }
++
++static const BYTE dquot_hdr[] = {
++ 0, 0, 0, 0, 'D', 'Q', 'U', 'T'
++};
++
++TPM_RESULT TPM_DeepQuote(TPM_NONCE *externalData, TPM_PCR_SELECTION *myPCR,
++ TPM_PCR_SELECTION *ptPCR, TPM_AUTH *auth1,
++ UINT32 *sigSize, BYTE **sig)
++{
++ TPM_RESULT res;
++ TPM_DIGEST hres;
++ TPM_PCR_INFO_SHORT pcrData;
++ tpm_sha1_ctx_t ctx;
++ BYTE *buf, *ptr;
++ UINT32 size, len;
++
++ info("TPM_DeepQuote()");
++
++ res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);
++ if (res != TPM_SUCCESS) return res;
++
++ res = tpm_compute_pcr_digest(myPCR, &pcrData.digestAtRelease, NULL);
++ if (res != TPM_SUCCESS) return res;
++
++ pcrData.pcrSelection.sizeOfSelect = myPCR->sizeOfSelect;
++ memcpy(pcrData.pcrSelection.pcrSelect, myPCR->pcrSelect, myPCR->sizeOfSelect);
++ pcrData.localityAtRelease = 1 << tpmData.stany.flags.localityModifier;
++
++ size = len = sizeof_TPM_PCR_INFO_SHORT(pcrData);
++ buf = ptr = tpm_malloc(size);
++ if (buf == NULL) return TPM_NOSPACE;
++ if (tpm_marshal_TPM_PCR_INFO_SHORT(&ptr, &len, &pcrData))
++ return TPM_FAIL;
++
++ tpm_sha1_init(&ctx);
++ tpm_sha1_update(&ctx, dquot_hdr, 8);
++ tpm_sha1_update(&ctx, externalData->nonce, 20);
++ tpm_sha1_update(&ctx, buf, size);
++ tpm_sha1_final(&ctx, hres.digest);
++
++ tpm_free(buf);
++
++ res = VTPM_GetParentQuote(&hres, ptPCR, sigSize, sig);
++
++ return res;
++}
+diff --git a/tpm/tpm_structures.h b/tpm/tpm_structures.h
+index b0f4625..dfb1894 100644
+--- a/tpm/tpm_structures.h
++++ b/tpm/tpm_structures.h
+@@ -660,6 +660,42 @@ typedef struct tdTPM_CMK_MA_APPROVAL {
+
+ /* VTPM-only commands: */
+ /*
++ * Deep Quote - Create quote of PCRs
++ * Input:
++ * TPM_TAG tag TPM_TAG_RQU_AUTH1_COMMAND
++ * UINT32 paramSize Total size of request
++ * TPM_COMMAND_CODE ordinal TPM_ORD_DeepQuote
++ * TPM_NONCE externData 20 bytes of external data
++ * TPM_PCR_SELECTION vtSel PCR selection for virtual TPM
++ * TPM_PCR_SELECTION ptSel PCR selection for physical TPM
++ * ---
++ * UINT32 authHandle Owner authorization session (OIAP)
++ * TPM_NONCE nonceOdd Nonce for authHandle
++ * BOOL continueAuth Continue flag for authHandle
++ * TPM_AUTHDATA privAuth Authorization digest for command
++ *
++ * Output:
++ * TPM_TAG tag TPM_TAG_RSP_AUTH1_COMMAND
++ * UINT32 paramSize Total size of response
++ * TPM_RESULT returnCode Return code of the operation
++ * BYTE[] sig Signature provided by physical TPM
++ * TPM_PCRVALUE[] pcrValue Values of hardware PCRs used in the quote
++ * ---
++ * TPM_NONCE nonceEven Nonce for authHandle
++ * BOOL continueAuth Continue flag for authHandle
++ * TPM_AUTHDATA resAuth Authorization digest for response
++ *
++ * The values of the virutal TPM's PCRs are not included in the response.
++ * The signature is a standard TPM_Quote response from the physical TPM; its
++ * externalData is the SHA1 hash of the following structure:
++ * TPM_STRUCT_VER version MUST be 0.0.0.0
++ * BYTE[4] fixed MUST be the string "DQUT"
++ * TPM_NONCE externData From input to the deep quote
++ * TPM_PCR_INFO_SHORT pcrData Virtual TPM's PCRs
++ */
++#define TPM_ORD_DeepQuote (TPM_VENDOR_COMMAND | TPM_ORD_Quote)
++
++/*
+ * ParentSignEK - Proof of fresh provisioning and EK value
+ *
+ * Input:
diff --git a/stubdom/vtpm-parent-sign-ek.patch b/stubdom/vtpm-parent-sign-ek.patch
new file mode 100644
index 0000000..14e66ee
--- /dev/null
+++ b/stubdom/vtpm-parent-sign-ek.patch
@@ -0,0 +1,196 @@
+diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c
+index 9e1cfb4..0fabf98 100644
+--- a/tpm/tpm_cmd_handler.c
++++ b/tpm/tpm_cmd_handler.c
+@@ -3312,6 +3312,37 @@ static TPM_RESULT execute_TPM_OwnerReadPubek(TPM_REQUEST *req, TPM_RESPONSE *rsp
+ return res;
+ }
+
++static TPM_RESULT execute_TPM_ParentSignEK(TPM_REQUEST *req, TPM_RESPONSE *rsp)
++{
++ TPM_NONCE nonce;
++ TPM_RESULT res;
++ UINT32 sigSize;
++ BYTE *sig;
++ BYTE *ptr;
++ UINT32 len;
++ TPM_PCR_SELECTION targetPCR;
++
++ tpm_compute_in_param_digest(req);
++
++ ptr = req->param;
++ len = req->paramSize;
++ if (tpm_unmarshal_TPM_NONCE(&ptr, &len, &nonce)
++ || tpm_unmarshal_TPM_PCR_SELECTION(&ptr, &len, &targetPCR)
++ || len != 0) return TPM_BAD_PARAMETER;
++
++ res = TPM_ParentSignEK(&nonce, &targetPCR, &req->auth1, &sigSize, &sig);
++ if (res != TPM_SUCCESS) return res;
++ rsp->paramSize = len = sigSize;
++ rsp->param = ptr = tpm_malloc(len);
++ if (ptr == NULL || tpm_marshal_BLOB(&ptr, &len, sig, sigSize)) {
++ tpm_free(rsp->param);
++ res = TPM_FAIL;
++ }
++ tpm_free(sig);
++
++ return res;
++}
++
+ static void tpm_setup_rsp_auth(TPM_COMMAND_CODE ordinal, TPM_RESPONSE *rsp)
+ {
+ tpm_hmac_ctx_t hmac;
+@@ -4062,6 +4093,11 @@ void tpm_execute_command(TPM_REQUEST *req, TPM_RESPONSE *rsp)
+ res = execute_TPM_OwnerReadPubek(req, rsp);
+ break;
+
++ case TPM_ORD_ParentSignEK:
++ debug("[TPM_ORD_ParentSignEK]");
++ res = execute_TPM_ParentSignEK(req, rsp);
++ break;
++
+ default:
+ #ifdef MTM_EMULATOR
+ res = mtm_execute_command(req, rsp);
+diff --git a/tpm/tpm_commands.h b/tpm/tpm_commands.h
+index a7666f6..7fef934 100644
+--- a/tpm/tpm_commands.h
++++ b/tpm/tpm_commands.h
+@@ -3054,6 +3054,23 @@ TPM_RESULT TPM_OwnerReadPubek(
+ TPM_PUBKEY *pubEndorsementKey
+ );
+
++/**
++ * TPM_ParentSignEK - gets a hardware TPM quote of a vTPM's EK
++ * @externalData: [in] AntiReplay nonce to prevent replay of messages
++ * @sel: [in] PCR selection for the hardware TPM's quote
++ * @auth1: [in, out] Authorization protocol parameters
++ * @sigSize: [out] The length of the returned digital signature
++ * @sig: [out] The resulting digital signature and PCR values
++ * Returns: TPM_SUCCESS on success, a TPM error code otherwise.
++ */
++TPM_RESULT TPM_ParentSignEK(
++ TPM_NONCE *externalData,
++ TPM_PCR_SELECTION *sel,
++ TPM_AUTH *auth1,
++ UINT32 *sigSize,
++ BYTE **sig
++);
++
+ /*
+ * Error handling
+ * [tpm_error.c]
+diff --git a/tpm/tpm_credentials.c b/tpm/tpm_credentials.c
+index 9cd64af..01f29e6 100644
+--- a/tpm/tpm_credentials.c
++++ b/tpm/tpm_credentials.c
+@@ -180,3 +180,34 @@ TPM_RESULT TPM_OwnerReadInternalPub(TPM_KEY_HANDLE keyHandle, TPM_AUTH *auth1,
+ return TPM_BAD_PARAMETER;
+ }
+ }
++
++int endorsementKeyFresh = 0;
++
++TPM_RESULT VTPM_GetParentQuote(TPM_DIGEST* data, TPM_PCR_SELECTION *sel, UINT32 *sigSize, BYTE **sig);
++
++TPM_RESULT TPM_ParentSignEK(TPM_NONCE *externalData, TPM_PCR_SELECTION *sel,
++ TPM_AUTH *auth1, UINT32 *sigSize, BYTE **sig)
++{
++ TPM_PUBKEY pubKey;
++ TPM_RESULT res;
++ TPM_DIGEST hres;
++
++ info("TPM_ParentSignEK()");
++
++ res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);
++ if (res != TPM_SUCCESS) return res;
++
++ if (!endorsementKeyFresh) return TPM_DISABLED_CMD;
++
++ res = tpm_get_pubek(&pubKey);
++ if (res != TPM_SUCCESS) return res;
++
++ if (tpm_compute_pubkey_checksum(externalData, &pubKey, &hres))
++ res = TPM_FAIL;
++
++ if (res == TPM_SUCCESS)
++ res = VTPM_GetParentQuote(&hres, sel, sigSize, sig);
++
++ free_TPM_PUBKEY(pubKey);
++ return res;
++}
+diff --git a/tpm/tpm_data.c b/tpm/tpm_data.c
+index 50c9697..6a0c499 100644
+--- a/tpm/tpm_data.c
++++ b/tpm/tpm_data.c
+@@ -76,6 +76,8 @@ static void init_timeouts(void)
+ tpmData.permanent.data.cmd_durations[2] = 1000;
+ }
+
++extern int endorsementKeyFresh;
++
+ void tpm_init_data(void)
+ {
+ /* endorsement key */
+@@ -157,6 +159,7 @@ void tpm_init_data(void)
+ if (tpmConf & TPM_CONF_GENERATE_EK) {
+ /* generate a new endorsement key */
+ tpm_rsa_generate_key(&tpmData.permanent.data.endorsementKey, 2048);
++ endorsementKeyFresh = 1;
+ } else {
+ /* setup endorsement key */
+ tpm_rsa_import_key(&tpmData.permanent.data.endorsementKey,
+diff --git a/tpm/tpm_structures.h b/tpm/tpm_structures.h
+index f746c05..b0f4625 100644
+--- a/tpm/tpm_structures.h
++++ b/tpm/tpm_structures.h
+@@ -658,6 +658,49 @@ typedef struct tdTPM_CMK_MA_APPROVAL {
+ #define TPM_ORD_TickStampBlob 242
+ #define TPM_ORD_MAX 256
+
++/* VTPM-only commands: */
++/*
++ * ParentSignEK - Proof of fresh provisioning and EK value
++ *
++ * Input:
++ * TPM_TAG tag TPM_TAG_RQU_AUTH1_COMMAND
++ * UINT32 paramSize Total size of request
++ * TPM_COMMAND_CODE ordinal TPM_ORD_ParentSignEK
++ * TPM_NONCE externData 20 bytes of external data
++ * TPM_PCR_SELECTION ptSel PCR selection for physical TPM
++ * ---
++ * UINT32 authHandle Owner authorization session (OIAP)
++ * TPM_NONCE nonceOdd Nonce for authHandle
++ * BOOL continueAuth Continue flag for authHandle
++ * TPM_AUTHDATA privAuth Authorization digest for command
++ *
++ * Output:
++ * TPM_TAG tag TPM_TAG_RSP_AUTH1_COMMAND
++ * UINT32 paramSize Total size of response
++ * TPM_RESULT returnCode Return code of the operation
++ * BYTE[] sig Signature provided by physical TPM
++ * TPM_PCRVALUE[] pcrValue Values of hardware PCRs used in the quote
++ * ---
++ * TPM_NONCE nonceEven Nonce for authHandle
++ * BOOL continueAuth Continue flag for authHandle
++ * TPM_AUTHDATA resAuth Authorization digest for response
++ *
++ * This command is only valid on the first boot of a vTPM; on any subsequent
++ * boot, the command returns TPM_DISABLED_CMD. It is intended to be used to
++ * provide evidence of proper platform configuration to the verifier/CA which is
++ * responsible for the creation of the vTPM's endorsement credential, which will
++ * be used on subsequent boots to certify AIKs via the usual Privacy CA protocol.
++ *
++ * The values of the virtual TPM's PCRs are not included in the response.
++ * The signature is a standard TPM_Quote response from the physical TPM; its
++ * externalData is the SHA1 hash of the following structure:
++ * TPM_PUBKEY pubEK The vTPM's public EK
++ * TPM_NONCE externData From input to the deep quote
++ *
++ * This structure was chosen to match the return of TPM_ReadPubek
++ */
++#define TPM_ORD_ParentSignEK (TPM_VENDOR_COMMAND | TPM_ORD_ReadPubek)
++
+ /*
+ * TCS Ordinals ([TPM_Part2], Section 17.1)
+ *
diff --git a/stubdom/vtpm/README b/stubdom/vtpm/README
deleted file mode 100644
index 11bdacb..0000000
--- a/stubdom/vtpm/README
+++ /dev/null
@@ -1,75 +0,0 @@
-Copyright (c) 2010-2012 United States Government, as represented by
-the Secretary of Defense. All rights reserved.
-November 12 2012
-Authors: Matthew Fioravante (JHUAPL),
-
-This document describes the operation and command line interface
-of vtpm-stubdom. See docs/misc/vtpm.txt for details on the
-vTPM subsystem as a whole.
-
-
-------------------------------
-OPERATION
-------------------------------
-
-The vtpm-stubdom is a mini-OS domain that emulates a TPM for the guest OS to
-use. It is a small wrapper around the Berlios TPM emulator
-version 0.7.4. Commands are passed from the linux guest via the
-mini-os TPM backend driver. vTPM data is encrypted and stored via a disk image
-provided to the virtual machine. The key used to encrypt the data along
-with a hash of the vTPM's data is sent to the vTPM manager for secure storage
-and later retrieval. The vTPM domain communicates with the manager using a
-mini-os tpm front/back device pair.
-
-------------------------------
-COMMAND LINE ARGUMENTS
-------------------------------
-
-Command line arguments are passed to the domain via the 'extra'
-parameter in the VM config file. Each parameter is separated
-by white space. For example:
-
-extra="foo=bar baz"
-
-List of Arguments:
-------------------
-
-loglevel=<LOG>: Controls the amount of logging printed to the console.
- The possible values for <LOG> are:
- error
- info (default)
- debug
-
-clear: Start the Berlios emulator in "clear" mode. (default)
-
-save: Start the Berlios emulator in "save" mode.
-
-deactivated: Start the Berlios emulator in "deactivated" mode.
- See the Berlios TPM emulator documentation for details
- about the startup mode. For all normal use, always use clear
- which is the default. You should not need to specify any of these.
-
-maintcmds=<1|0>: Enable to disable the TPM maintenance commands.
- These commands are used by tpm manufacturers and thus
- open a security hole. They are disabled by default.
-
-hwinitpcr=<PCRSPEC>: Initialize the virtual Platform Configuration Registers
- (PCRs) with PCR values from the hardware TPM. Each pcr specified by
- <PCRSPEC> will be initialized with the value of that same PCR in TPM
- once at startup. By default all PCRs are zero initialized.
- Value values of <PCRSPEC> are:
- all: copy all pcrs
- none: copy no pcrs (default)
- <N>: copy pcr n
- <X-Y>: copy pcrs x to y (inclusive)
-
- These can also be combined by comma separation, for example:
- hwinitpcrs=5,12-16
- will copy pcrs 5, 12, 13, 14, 15, and 16.
-
-------------------------------
-REFERENCES
-------------------------------
-
-Berlios TPM Emulator:
-http://tpm-emulator.berlios.de/
diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
index f67de18..61982c2 100644
--- a/stubdom/vtpm/vtpm.c
+++ b/stubdom/vtpm/vtpm.c
@@ -33,6 +33,7 @@
#include "vtpm_cmd.h"
#include "vtpm_pcrs.h"
#include "vtpmblk.h"
+#include "vtpm_manager.h"
#define TPM_LOG_INFO LOG_INFO
#define TPM_LOG_ERROR LOG_ERR
@@ -117,6 +118,40 @@ int init_random(void) {
return 0;
}
+int check_passthru(tpmcmd_t* tpmcmd) {
+ TPM_TAG tag;
+ UINT32 len = 10;
+ BYTE* ptr;
+ size_t size;
+
+ if(tpmcmd->req_len < 10) {
+ return false;
+ }
+
+ ptr = tpmcmd->req;
+ tpm_unmarshal_UINT16(&ptr, &len, &tag);
+
+ if (tag == VTPM_TAG_REQ2) {
+ info("VTPM passthru: %d bytes", (int)tpmcmd->req_len);
+ tpmfront_cmd(tpmfront_dev, tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &size);
+ tpmcmd->resp_len = size;
+ info("VTPM passthru return: %d bytes", (int)size);
+ return true;
+ }
+
+ if (tag == VTPM_TAG_REQ) {
+ info("VTPM pTPM-cmd: %d bytes", (int)tpmcmd->req_len);
+ ptr = tpmcmd->req;
+ tpm_marshal_UINT16(&ptr, &len, TPM_TAG_RQU_COMMAND);
+ tpmfront_cmd(tpmfront_dev, tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &size);
+ tpmcmd->resp_len = size;
+ info("VTPM pTPM-cmd return: %d bytes", (int)size);
+ return true;
+ }
+
+ return false;
+}
+
int check_ordinal(tpmcmd_t* tpmcmd) {
TPM_COMMAND_CODE ord;
UINT32 len = 4;
@@ -209,6 +244,9 @@ static void main_loop(void) {
error("Invalid locality (%d) for client in tpm_handle_command", tpmcmd->locality);
create_error_response(tpmcmd, TPM_FAIL);
}
+ /* Check for TPM Manager passthrough command */
+ else if(check_passthru(tpmcmd)) {
+ }
/* Check for disabled ordinals */
else if(!check_ordinal(tpmcmd)) {
create_error_response(tpmcmd, TPM_BAD_ORDINAL);
@@ -231,7 +269,7 @@ static void main_loop(void) {
}
abort_postpcrs:
- info("VTPM Shutting down\n");
+ info("VTPM Shutting down");
tpm_emulator_shutdown();
}
diff --git a/stubdom/vtpm/vtpm_cmd.c b/stubdom/vtpm/vtpm_cmd.c
index 7eae98b..6fda456 100644
--- a/stubdom/vtpm/vtpm_cmd.c
+++ b/stubdom/vtpm/vtpm_cmd.c
@@ -217,6 +217,51 @@ egress:
return status;
}
+extern struct tpmfront_dev* tpmfront_dev;
+TPM_RESULT VTPM_GetParentQuote(TPM_NONCE *data, TPM_PCR_SELECTION *sel, UINT32 *sigSize, BYTE **sig)
+{
+ TPM_RESULT status = TPM_SUCCESS;
+ uint8_t* bptr, *resp;
+ uint8_t* cmdbuf = NULL;
+ size_t resplen = 0;
+ UINT32 len;
+
+ TPM_TAG tag = VTPM_TAG_REQ;
+ UINT32 size;
+ TPM_COMMAND_CODE ord = VTPM_ORD_GET_QUOTE;
+
+ /*Create the command*/
+ len = size = VTPM_COMMAND_HEADER_SIZE + 25;
+ bptr = cmdbuf = malloc(size);
+ TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
+ TRYFAILGOTO(tpm_marshal_TPM_NONCE(&bptr, &len, data));
+ TRYFAILGOTO(tpm_marshal_TPM_PCR_SELECTION(&bptr, &len, sel));
+
+ /* Send the command to vtpm_manager */
+ info("Requesting Quote from backend");
+ TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp, &resplen), ERR_TPMFRONT);
+
+ /* Unpack response header */
+ bptr = resp;
+ len = resplen;
+ TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord), ERR_MALFORMED);
+
+ /* Check return code */
+ CHECKSTATUSGOTO(ord, "VTPM_GetParentQuote()");
+
+ /* Copy out the value */
+ *sigSize = len;
+ *sig = tpm_malloc(*sigSize);
+ TRYFAILGOTOMSG(tpm_unmarshal_BYTE_ARRAY(&bptr, &len, *sig, *sigSize), ERR_MALFORMED);
+
+ goto egress;
+abort_egress:
+ error("VTPM_GetParentQuote failed");
+egress:
+ free(cmdbuf);
+ return status;
+}
+
TPM_RESULT VTPM_PCRRead(struct tpmfront_dev* tpmfront_dev, UINT32 pcrIndex, BYTE* outDigest)
{
TPM_RESULT status = TPM_SUCCESS;
diff --git a/stubdom/vtpmmgr/Makefile b/stubdom/vtpmmgr/Makefile
index af13b39..c5e17c5 100644
--- a/stubdom/vtpmmgr/Makefile
+++ b/stubdom/vtpmmgr/Makefile
@@ -12,7 +12,9 @@
XEN_ROOT=../..
TARGET=vtpmmgr.a
-OBJS=vtpmmgr.o vtpm_cmd_handler.o vtpm_storage.o init.o tpmrsa.o tpm.o log.o
+OBJS=vtpmmgr.o vtpm_cmd_handler.o init.o tpmrsa.o tpm.o log.o
+OBJS += vtpm_disk.o disk_tpm.o disk_io.o disk_crypto.o disk_read.o disk_write.o
+OBJS += mgmt_authority.o
CFLAGS+=-Werror -Iutil -Icrypto -Itcs
CFLAGS+=-Wno-declaration-after-statement -Wno-unused-label
@@ -21,6 +23,11 @@ build: $(TARGET)
$(TARGET): $(OBJS)
ar -rcs $@ $^
+install:
+ $(INSTALL_DIR) "$(DESTDIR)$(LIBEXEC_BIN)"
+ $(INSTALL_PROG) calc.pl "$(DESTDIR)$(LIBEXEC_BIN)"
+ $(INSTALL_PROG) manage-vtpmmgr.pl "$(DESTDIR)$(LIBEXEC_BIN)"
+
clean:
rm -f $(TARGET) $(OBJS)
diff --git a/stubdom/vtpmmgr/README b/stubdom/vtpmmgr/README
deleted file mode 100644
index a70c1cc..0000000
--- a/stubdom/vtpmmgr/README
+++ /dev/null
@@ -1,75 +0,0 @@
-Copyright (c) 2010-2012 United States Government, as represented by
-the Secretary of Defense. All rights reserved.
-November 12 2012
-Authors: Matthew Fioravante (JHUAPL),
-
-This document describes the operation and command line interface
-of vtpmmgr-stubdom. See docs/misc/vtpm.txt for details on the
-vTPM subsystem as a whole.
-
-
-------------------------------
-OPERATION
-------------------------------
-
-The vtpmmgr-stubdom implements a vTPM manager who has two major functions:
-
- - Securely store encryption keys for each of the vTPMS
- - Regulate access to the hardware TPM for the entire system
-
-The manager accepts commands from the vtpm-stubdom domains via the mini-os
-TPM backend driver. The vTPM manager communicates directly with hardware TPM
-using the mini-os tpm_tis driver.
-
-
-When the manager starts for the first time it will check if the TPM
-has an owner. If the TPM is unowned, it will attempt to take ownership
-with the supplied owner_auth (see below) and then create a TPM
-storage key which will be used to secure vTPM key data. Currently the
-manager only binds vTPM keys to the disk. In the future support
-for sealing to PCRs should be added.
-
-------------------------------
-COMMAND LINE ARGUMENTS
-------------------------------
-
-Command line arguments are passed to the domain via the 'extra'
-parameter in the VM config file. Each parameter is separated
-by white space. For example:
-
-extra="foo=bar baz"
-
-List of Arguments:
-------------------
-
-owner_auth=<AUTHSPEC>: Set the owner auth of the TPM. The default
- is the well known owner auth of all ones.
-
-srk_auth=<AUTHSPEC>: Set the SRK auth for the TPM. The default is
- the well known srk auth of all zeroes.
- The possible values of <AUTHSPEC> are:
- well-known: Use the well known auth (default)
- random: Randomly generate an auth
- hash: <HASH>: Use the given 40 character ASCII hex string
- text: <STR>: Use sha1 hash of <STR>.
-
-tpmdriver=<DRIVER>: Which driver to use to talk to the hardware TPM.
- Don't change this unless you know what you're doing.
- The possible values of <DRIVER> are:
- tpm_tis: Use the tpm_tis driver to talk directly to the TPM.
- The domain must have access to TPM IO memory. (default)
- tpmfront: Use tpmfront to talk to the TPM. The domain must have
- a tpmfront device setup to talk to another domain
- which provides access to the TPM.
-
-The following options only apply to the tpm_tis driver:
-
-tpmiomem=<ADDR>: The base address of the hardware memory pages of the
- TPM (default 0xfed40000).
-
-tpmirq=<IRQ>: The irq of the hardware TPM if using interrupts. A value of
- "probe" can be set to probe for the irq. A value of 0
- disabled interrupts and uses polling (default 0).
-
-tpmlocality=<LOC>: Attempt to use locality <LOC> of the hardware TPM.
- (default 0)
diff --git a/stubdom/vtpmmgr/calc.pl b/stubdom/vtpmmgr/calc.pl
new file mode 100755
index 0000000..4183733
--- /dev/null
+++ b/stubdom/vtpmmgr/calc.pl
@@ -0,0 +1,97 @@
+#!/usr/bin/perl
+use strict;
+use Digest::SHA qw(sha1);
+use Math::BigInt only => 'GMP';
+
+my $s2 = Digest::SHA->new("SHA256");
+
+# The key below is an example; its private key is (obviously) not private. This
+# key must be protected at least as well as the vTPM's secrets, since it can
+# approve the release of these secrets to a new TCB. It may make sense to
+# modify this script to use a TPM or some other hardware key storage device to
+# hold the private key instead of holding the key in plaintext; such integration
+# is beyond the scope of this example script.
+#
+# The public exponent of this key must be 65537 (0x10001); this is the default
+# for TPM-generated RSA keys.
+#
+# The manage-tpmmgr.pl script expects the modulus of this RSA key to be
+# available; this may be done using:
+#
+# open KEY, '>rsa-modulus-file';
+# print KEY pack 'H*', $rsa_n;
+# close KEY;
+
+my $rsa_n = 'c1580b4ea118a6c2f0a56d5af59b080928a9de7267f824457a1e9d7216013b5a322ff67f72153cd4b58693284490aced3a85d81da909ffe544f934c80340020b5bf514e8850926c6ce3314c3283e33cb79cb6aecf041726782013d07f8171fde4ea8165c6a7050af534ffc1b11ae37ace2ed6436c626edb49bf5bd70ee71f74bf2c132a99e5a6427343dbe46829961755558386436ebea90959161295c78df0127d4e468f9a188b3c1e9b68e5b1e78a450ea437ac7930dab294ede8117f6849d53f11e0bbc8ccef44b7fc9ebd6d7c7532875b3225a9106961771001be618ab3f991ba18edc1b73d73b6b80b5df854f9 [...]
+my $rsa_d = '3229508daed80173f4114744e111beccf982d0d6a7c8c6484c3da3259535ee9b21083690ac1d7c71c742c9ed1994db7894c562e39716a4106c8ba738f936e310e563b96ff60c00c6757ae53918b8c2a158d100c5c63384a5fc21ac1ee42bc3b5de7c5788d4889d364f8c21e137fe162dc1964b78b682250bc5a6c4e686c6849cf8f0020f6ca383d784e5ffb85da56c2b89dc2e879509b1916c8b51f5907a0dbb7e2f9e5fabc500588ef7db6f78ba4605da86d907493648017ac46a1571ffe9b6a68babeeb277e3a96d346cddc996a94163f1e8393d88f710ff64369a62d3edfc62dbdeae57ee12a33adbb9b9d48d575 [...]
+
+sub rsa_sign {
+ my $m = '1'.('ff'x218).'003021300906052b0e03021a05000414';
+ $m .= unpack 'H*', sha1(shift);
+ $m = Math::BigInt->from_hex($m);
+ my $n = Math::BigInt->from_hex($rsa_n);
+ my $e = Math::BigInt->from_hex($rsa_d);
+ $m->bmodpow($e, $n);
+ $m = $m->as_hex();
+ $m =~ s/^0x//;
+ $m =~ s/^/0/ while length $m < 512;
+ pack 'H*', $m;
+}
+
+sub auth_update_file {
+ my($dst,$seq) = (shift, shift);
+ my(@plt, @pcrs, @kerns, $cfg);
+ open my $update, '>', $dst or die $!;
+ for (@_) {
+ if (/^([0-9a-fA-F]+)=([0-9a-fA-F]+)$/) {
+ push @pcrs, pack 'V', hex $1;
+ push @plt, pack 'H*', $2;
+ } elsif (/^[0-9a-fA-F]{40}$/) {
+ push @kerns, pack 'H*', $_;
+ } elsif (length $_ == 20) {
+ push @kerns, $_;
+ } else {
+ print "Bad argument: $_";
+ exit 1;
+ }
+ }
+ $cfg = pack 'Q>', $seq;
+ $cfg .= pack 'N/(a20)', @plt;
+ $cfg .= pack 'N/(a20)', @kerns;
+
+ printf "cfg_hash for %s: %s\n", $dst, Digest::SHA::sha1_hex($cfg);
+
+ print $update rsa_sign($cfg);
+ print $update $cfg;
+ print $update map { pack 'n/a3', $_ } @pcrs;
+ close $update;
+}
+
+my $out = shift;
+my $seq = $ENV{SEQ} || time;
+
+if (!$out) {
+ print <<EOF;
+Usage: $0 <output> {<pcrs>=<composite>}* {<kernel>}*
+ <output> is the file that will contain the signed configuration
+ <pcrs> is a 24-bit PCR mask in hexadecimal
+ <composite> is a PCR_COMPOSITE_HASH in hexadecimal
+ <kernel> is a 160-bit vTPM kernel hash in hexadecimal
+
+The sequence number may be specified using the SEQ environment variable,
+otherwise the current UNIX timestamp will be used. The sequence number of a
+vTPM group must increase on each update.
+
+When the vTPM Manager is compiled without support for a domain builder, the
+SHA-1 hash of the vTPM domain's XSM label is used in place of its kernel hash.
+
+Example:
+ A configuration with two valid command lines and one valid vTPM kernel
+ PCRs 0-7 and 17-19 are being validated (static RTM and TBOOT).
+ $0 auth-0 0e00ff=0593ecb564f532df6ef2f4d7272489da52c4c840 0e00ff=0593ecb564f532df6ef2f4d7272489da52c4c840 2bc65001d506ce6cd12cab90a4a2ad9040d641e1
+EOF
+ exit 0;
+}
+print "Sequence: $seq\n";
+
+auth_update_file $out, $seq, @ARGV;
diff --git a/stubdom/vtpmmgr/disk_crypto.c b/stubdom/vtpmmgr/disk_crypto.c
new file mode 100644
index 0000000..18718d0
--- /dev/null
+++ b/stubdom/vtpmmgr/disk_crypto.c
@@ -0,0 +1,231 @@
+#include <inttypes.h>
+#include <mini-os/byteorder.h>
+#include <polarssl/aes.h>
+#include <polarssl/sha2.h>
+#include <polarssl/ctr_drbg.h>
+
+#include "log.h"
+#include "vtpmmgr.h"
+#include "vtpm_disk.h"
+#include "disk_io.h"
+#include "disk_crypto.h"
+
+// XXX defining this stubs out all disk encryption for easier debugging
+#undef DISK_IS_PLAINTEXT
+
+void do_random(void *buf, size_t size)
+{
+ int rc = ctr_drbg_random(&vtpm_globals.ctr_drbg, buf, size);
+ if (rc) abort();
+}
+
+void aes_setup(aes_context *ctx, const struct key128 *key)
+{
+ aes_setkey_enc(ctx, (void*)key, 128);
+}
+
+static void aes_encrypt_ecb(void *target, const void *src, const aes_context *key_e)
+{
+ aes_crypt_ecb((void*)key_e, AES_ENCRYPT, src, target);
+}
+
+void aes_encrypt_one(void *target, const void *src, const struct key128 *key)
+{
+ aes_context ctx;
+ aes_setkey_enc(&ctx, (void*)key, 128);
+ aes_crypt_ecb(&ctx, AES_ENCRYPT, src, target);
+}
+
+void aes_decrypt_one(void *target, const void *src, const struct key128 *key)
+{
+ aes_context ctx;
+ aes_setkey_dec(&ctx, (void*)key, 128);
+ aes_crypt_ecb(&ctx, AES_DECRYPT, src, target);
+}
+
+static void aes_ctr_one(uint64_t out[2], uint64_t ctr[2], const aes_context *key_e)
+{
+#ifdef DISK_IS_PLAINTEXT
+ memset(out, 0, 16);
+#else
+ aes_encrypt_ecb(out, ctr, key_e);
+#endif
+ ctr[1]++;
+}
+
+void aes_encrypt_ctr(void *target, size_t target_size, const void *srcv, size_t pt_size, const aes_context *key_e)
+{
+ uint64_t ctr[2];
+ uint64_t tmp[2];
+ uint64_t *dst = target;
+ const uint64_t *src = srcv;
+
+ do_random(ctr, sizeof(ctr));
+ dst[0] = ctr[0];
+ dst[1] = ctr[1];
+ dst += 2;
+ target_size -= 16;
+
+ if (pt_size > target_size)
+ abort(); // invalid argument: target too small for plaintext
+
+ while (pt_size >= 16) {
+ aes_ctr_one(tmp, ctr, key_e);
+
+ dst[0] = tmp[0] ^ src[0];
+ dst[1] = tmp[1] ^ src[1];
+
+ dst += 2;
+ src += 2;
+ pt_size -= 16;
+ target_size -= 16;
+ }
+ if (pt_size) {
+ uint64_t stmp[2];
+ uint64_t dtmp[2];
+ memset(stmp, 0, 16);
+ memcpy(stmp, src, pt_size);
+
+ aes_ctr_one(tmp, ctr, key_e);
+
+ dtmp[0] = tmp[0] ^ stmp[0];
+ dtmp[1] = tmp[1] ^ stmp[1];
+ if (target_size < 16) {
+ memcpy(dst, dtmp, target_size);
+ return;
+ } else {
+ memcpy(dst, dtmp, 16);
+ target_size -= 16;
+ }
+ }
+ while (target_size >= 16) {
+ aes_ctr_one(dst, ctr, key_e);
+
+ dst += 2;
+ target_size -= 16;
+ }
+ if (target_size)
+ abort(); // invalid argument: overlarge target size is not a full block
+}
+
+void aes_decrypt_ctr(void *target, size_t pt_size, const void *srcv, size_t src_size, const aes_context *key_e)
+{
+ uint64_t ctr[2];
+ uint64_t tmp[2];
+ uint64_t *dst = target;
+ const uint64_t *src = srcv;
+
+ ctr[0] = src[0];
+ ctr[1] = src[1];
+ src += 2;
+ src_size -= 16;
+
+ if (pt_size > src_size)
+ abort(); // invalid argument: source too small for plaintext
+ // we discard src_size now
+
+ while (pt_size >= 16) {
+ aes_ctr_one(tmp, ctr, key_e);
+ dst[0] = tmp[0] ^ src[0];
+ dst[1] = tmp[1] ^ src[1];
+
+ dst += 2;
+ src += 2;
+ pt_size -= 16;
+ }
+ if (pt_size) {
+ uint64_t stmp[2];
+ uint64_t dtmp[2];
+ memset(stmp, 0, 16);
+ memcpy(stmp, src, pt_size);
+
+ aes_ctr_one(tmp, ctr, key_e);
+
+ dtmp[0] = tmp[0] ^ stmp[0];
+ dtmp[1] = tmp[1] ^ stmp[1];
+ memcpy(dst, dtmp, pt_size);
+ }
+}
+
+static void shl_128_mod_hex87(struct mac128 *dst, const struct mac128 *src)
+{
+ int i;
+ int carry = 0x87 * !!(src->bits[0] & 0x80);
+ for(i=0; i < 15; i++)
+ dst->bits[i] = (src->bits[i] << 1) | (src->bits[i+1] >> 7);
+ dst->bits[15] = (src->bits[15] << 1) ^ carry;
+}
+
+static void xor128(struct mac128 *dst, const struct mac128 *s1, const struct mac128 *s2)
+{
+ int i;
+ for(i=0; i < 16; i++)
+ dst->bits[i] = s1->bits[i] ^ s2->bits[i];
+}
+
+void aes_cmac(struct mac128 *target, const void *src, size_t size, const aes_context *key)
+{
+ const struct mac128 *M = src;
+ struct mac128 x, y, L, K1, K2;
+ int i;
+ size_t bsize = (size - 1) / 16;
+
+ memset(&x, 0, sizeof(x));
+ aes_encrypt_ecb(&L, &x, key);
+ shl_128_mod_hex87(&K1, &L);
+ shl_128_mod_hex87(&K2, &K1);
+
+ for(i=0; i < bsize; i++) {
+ xor128(&y, &x, &M[i]);
+ aes_encrypt_ecb(&x, &y, key);
+ }
+ if (size & 0xF) {
+ struct mac128 z;
+ memset(&z, 0, sizeof(z));
+ memcpy(&z, M + bsize, size & 0xF);
+ xor128(&y, &x, &K2);
+ xor128(&x, &y, &z);
+ } else {
+ xor128(&y, &x, &K1);
+ xor128(&x, &y, M + bsize);
+ }
+ aes_encrypt_ecb(target, &x, key);
+}
+
+static int verify_128(const void *a, const void* b)
+{
+ const volatile uint64_t *x = a;
+ const volatile uint64_t *y = b;
+ if ((x[0] ^ y[0]) | (x[1] ^ y[1]))
+ return 1;
+ return 0;
+}
+
+int aes_cmac_verify(const struct mac128 *target, const void *src, size_t size, const aes_context *key)
+{
+ struct mac128 mac;
+ aes_cmac(&mac, src, size, key);
+ return verify_128(&mac, target);
+}
+
+static int verify_256(const void *a, const void* b)
+{
+ const volatile uint64_t *x = a;
+ const volatile uint64_t *y = b;
+ if ((x[0] ^ y[0]) | (x[1] ^ y[1]) | (x[2] ^ y[2]) | (x[3] ^ y[3]))
+ return 1;
+ return 0;
+}
+
+void sha256(struct hash256 *target, const void *src, size_t size)
+{
+ void* dst = target;
+ sha2(src, size, dst, 0);
+}
+
+int sha256_verify(const struct hash256 *targ, const void *data, size_t size)
+{
+ struct hash256 hash;
+ sha256(&hash, data, size);
+ return verify_256(&hash, targ);
+}
diff --git a/stubdom/vtpmmgr/disk_crypto.h b/stubdom/vtpmmgr/disk_crypto.h
new file mode 100644
index 0000000..faae9ab
--- /dev/null
+++ b/stubdom/vtpmmgr/disk_crypto.h
@@ -0,0 +1,17 @@
+#ifndef __VTPMMGR_DISK_CRYPTO_H
+#define __VTPMMGR_DISK_CRYPTO_H
+
+void do_random(void *buf, size_t size);
+void aes_encrypt_one(void *target, const void *src, const struct key128 *key);
+void aes_decrypt_one(void *target, const void *src, const struct key128 *key);
+
+void aes_setup(aes_context *ctx, const struct key128 *key);
+void aes_encrypt_ctr(void *target, size_t target_size, const void *srcv, size_t src_size, const aes_context *key_e);
+void aes_decrypt_ctr(void *target, size_t target_size, const void *srcv, size_t src_size, const aes_context *key_e);
+void aes_cmac(struct mac128 *target, const void *src, size_t size, const aes_context *key);
+int aes_cmac_verify(const struct mac128 *target, const void *src, size_t size, const aes_context *key);
+
+void sha256(struct hash256 *target, const void *src, size_t size);
+int sha256_verify(const struct hash256 *targ, const void *data, size_t size);
+
+#endif
diff --git a/stubdom/vtpmmgr/disk_format.h b/stubdom/vtpmmgr/disk_format.h
new file mode 100644
index 0000000..bc20fbb
--- /dev/null
+++ b/stubdom/vtpmmgr/disk_format.h
@@ -0,0 +1,193 @@
+#ifndef __VTPMMGR_DISK_FORMAT_H
+#define __VTPMMGR_DISK_FORMAT_H
+
+static const uint8_t TPM_MGR_MAGIC[12] = {
+ 'T','P','M',0xfe,'M','G','R',0xdd,'D','O','M',0x00
+};
+
+/**
+ * Sector 0 on disk: stored in plaintext
+ */
+struct disk_header {
+ char magic[12];
+#define TPM_MGR_VERSION 0
+ be32_t version;
+};
+
+/**
+ * Raw contents of disk sectors that need both encryption and authentication
+ */
+struct disk_crypt_sector_plain {
+ struct mac128 mac;
+ union {
+ struct {
+ uint8_t iv[16];
+ char data[4096-32];
+ };
+ uint8_t iv_data[4096-16];
+ };
+};
+
+/**
+ * Contents of the sealed blob in the root seal list
+ */
+struct disk_root_sealed_data {
+#define DISK_ROOT_BOUND_MAGIC "Root"
+ char magic[4];
+ uuid_t tpm_manager_uuid;
+
+ be32_t nvram_slot;
+ struct tpm_authdata nvram_auth;
+ be32_t counter_index;
+ struct tpm_authdata counter_auth;
+
+ /* encrypted (AES-ECB) with key from NVRAM */
+ struct key128 tm_key;
+};
+
+/**
+ * Contents of the sealed blob in a group's seal list
+ */
+struct disk_group_sealed_data {
+#define DISK_GROUP_BOUND_MAGIC "TGrp"
+ char magic[4];
+ uuid_t tpm_manager_uuid;
+ struct tpm_authdata aik_authdata;
+
+ struct key128 group_key;
+ struct key128 rollback_mac_key;
+};
+
+/**
+ * Contents of the seal_list_N sectors on disk (plaintext, linked list)
+ *
+ * The hdr field is unused except in sector 0
+ */
+struct disk_seal_list {
+ struct disk_header hdr;
+ be32_t length;
+ sector_t next;
+#define SEALS_PER_ROOT_SEAL_LIST 13
+ struct disk_seal_entry entry[SEALS_PER_ROOT_SEAL_LIST];
+};
+
+/**
+ * TODO - overflow for struct disk_group_boot_config_list
+ */
+struct disk_group_seal_list {
+ sector_t next;
+#define SEALS_PER_GROUP_SEAL_LIST 13
+ struct disk_seal_entry entry[SEALS_PER_GROUP_SEAL_LIST];
+};
+
+/**
+ * Rollback detection MAC entry
+ */
+struct disk_rb_mac_entry {
+ be32_t id;
+ struct mac128 mac;
+};
+
+#define NR_ENTRIES_PER_ROOT 16
+/**
+ * The area of the root sector protected by rollback MACs
+ */
+struct disk_root_sector_mac1_area {
+ be64_t sequence;
+ be32_t tpm_counter_value;
+
+ be32_t nr_groups;
+ struct hash256 group_hash[NR_ENTRIES_PER_ROOT];
+};
+
+/**
+ * Decrypted contents of the root sector (sector 1 and 2) on disk
+ */
+struct disk_root_sector {
+ struct disk_root_sector_mac1_area v;
+
+ sector_t group_loc[NR_ENTRIES_PER_ROOT];
+
+ uint8_t pad[8];
+
+ /* Rollback detection MACs */
+ be32_t nr_rb_macs;
+ sector_t rb_next_loc;
+ /* used if rb_macs overflows */
+ struct hash256 rb_next_hash;
+
+#define NR_RB_MACS_PER_ROOT 128
+ struct disk_rb_mac_entry rb_macs[NR_RB_MACS_PER_ROOT];
+};
+
+/**
+ * Hash tree for list expansion. Used for the list of groups in the root and for
+ * the list of vTPMs in a group.
+ */
+struct disk_itree_sector {
+#define NR_ENTRIES_PER_ITREE 112
+ sector_t location[NR_ENTRIES_PER_ITREE];
+ /* SECTOR-HASH { */
+ struct hash256 hash[NR_ENTRIES_PER_ITREE];
+ /* SECTOR-HASH } */
+};
+
+#define NR_ENTRIES_PER_GROUP_BASE 16
+/**
+ * Data that must remain constant if a group is not open
+ */
+struct disk_group_sector_mac3_area {
+ struct group_id_data id_data; /* MAC2 */
+ struct group_details details;
+ struct disk_group_boot_config_list boot_configs;
+
+ be32_t nr_vtpms;
+ struct hash256 vtpm_hash[NR_ENTRIES_PER_GROUP_BASE];
+};
+
+/**
+ * Group metadata sector
+ *
+ * Encrypted with TM_KEY - takes 16 bytes for IV; integrity from parent.
+ */
+struct disk_group_sector {
+ /* SECTOR-HASH { */
+ struct disk_group_sector_mac3_area v;
+
+ /* MAC(MAC3, group_key) */
+ struct mac128 group_mac;
+ /* SECTOR-HASH } */
+
+ sector_t vtpm_location[NR_ENTRIES_PER_GROUP_BASE];
+ sector_t boot_configs_next;
+};
+
+/**
+ * Data on a vTPM which is available when its group is not open
+ */
+struct disk_vtpm_plain {
+ uuid_t uuid;
+ be32_t flags;
+};
+
+/**
+ * Data on a vTPM which is only available when its group is open
+ */
+struct disk_vtpm_secret {
+ uint8_t data[64];
+};
+
+/**
+ * Contents of a vTPM data disk sector
+ *
+ * Encrypted with TM_KEY - takes 16 bytes for IV
+ */
+struct disk_vtpm_sector {
+ /* SECTOR-HASH { */
+ struct disk_vtpm_plain header[VTPMS_PER_SECTOR];
+ struct mac128 iv;
+ struct disk_vtpm_secret data[VTPMS_PER_SECTOR];
+ /* SECTOR-HASH } */
+};
+
+#endif
diff --git a/stubdom/vtpmmgr/disk_io.c b/stubdom/vtpmmgr/disk_io.c
new file mode 100644
index 0000000..02b4fdd
--- /dev/null
+++ b/stubdom/vtpmmgr/disk_io.c
@@ -0,0 +1,125 @@
+#include <blkfront.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <mini-os/byteorder.h>
+
+#include "vtpm_manager.h"
+#include "log.h"
+#include "uuid.h"
+
+#include "vtpmmgr.h"
+#include "vtpm_disk.h"
+#include "disk_tpm.h"
+#include "disk_io.h"
+
+static uint8_t disk_staging_buf[4096] __attribute__((aligned(4096)));
+
+static struct blkfront_dev* blkdev;
+static int blkfront_fd = -1;
+
+int vtpm_storage_init(void) {
+ struct blkfront_info info;
+ blkdev = init_blkfront(NULL, &info);
+ if (blkdev == NULL)
+ return -1;
+ blkfront_fd = blkfront_open(blkdev);
+ if (blkfront_fd < 0)
+ return -1;
+ return 0;
+}
+
+void* disk_read_sector(sector_t sector)
+{
+ uint32_t pos = be32_native(sector);
+ int rc;
+ vtpmloginfo(VTPM_LOG_VTPM, "disk_read_sector %x\n", pos);
+ lseek(blkfront_fd, pos * 4096, SEEK_SET);
+ rc = read(blkfront_fd, disk_staging_buf, 4096);
+ if (rc != 4096)
+ abort();
+ return disk_staging_buf;
+}
+
+void* disk_write_buf(void) { return disk_staging_buf; }
+
+void disk_write_sector(sector_t sector, void* buf, size_t siz)
+{
+ int rc;
+ uint32_t pos = be32_native(sector);
+ lseek(blkfront_fd, pos * 4096, SEEK_SET);
+ if (siz < 4096) {
+ if (buf != disk_staging_buf)
+ memcpy(disk_staging_buf, buf, siz);
+ memset(disk_staging_buf + siz, 0, 4096 - siz);
+ buf = disk_staging_buf;
+ } else if (siz > 4096)
+ abort();
+
+ rc = write(blkfront_fd, buf, 4096);
+ if (rc != 4096)
+ abort();
+}
+
+void disk_write_barrier(void)
+{
+ blkfront_sync(blkdev);
+}
+
+enum inuse_value {
+ UNUSED,
+ SLOT_1,
+ SLOT_2,
+ SHARED
+};
+
+/* TODO make this dynamic to support using more than 2MB of disk */
+#define DISK_MAX_SECTOR 0x200
+
+/* The first 4 sectors are statically allocated:
+ * 0 - disk header (copy 1)
+ * 1 - disk header (copy 2)
+ * 2 - root sector (copy 1)
+ * 3 - root sector (copy 2)
+ */
+#define FIRST_DYNAMIC_SECTOR 4
+
+static uint8_t sector_inuse_map[DISK_MAX_SECTOR];
+
+static int active_slot(const struct mem_tpm_mgr *mgr)
+{
+ return 1 + mgr->active_root;
+}
+
+void disk_set_used(sector_t loc, const struct mem_tpm_mgr *mgr)
+{
+ uint32_t s = be32_native(loc);
+ if (s > DISK_MAX_SECTOR) {
+ printk("Attempted disk_set_used %x\n", s);
+ return;
+ }
+ sector_inuse_map[s] |= active_slot(mgr);
+}
+
+void disk_flush_slot(const struct mem_tpm_mgr *mgr)
+{
+ int i;
+ for(i = FIRST_DYNAMIC_SECTOR; i < DISK_MAX_SECTOR; i++)
+ sector_inuse_map[i] &= ~active_slot(mgr);
+}
+
+sector_t disk_find_free(const struct mem_tpm_mgr *mgr)
+{
+ int i;
+ for(i = FIRST_DYNAMIC_SECTOR; i < DISK_MAX_SECTOR; i++) {
+ if (sector_inuse_map[i])
+ continue;
+ sector_inuse_map[i] = active_slot(mgr);
+ return native_be32(i);
+ }
+ // TODO more graceful error handling (in callers)
+ abort();
+}
diff --git a/stubdom/vtpmmgr/disk_io.h b/stubdom/vtpmmgr/disk_io.h
new file mode 100644
index 0000000..c0d35a5
--- /dev/null
+++ b/stubdom/vtpmmgr/disk_io.h
@@ -0,0 +1,25 @@
+#ifndef __VTPMMGR_DISK_IO_H
+#define __VTPMMGR_DISK_IO_H
+
+void* disk_read_sector(sector_t sector);
+void disk_write_sector(sector_t sector, void* buf, size_t siz);
+void* disk_write_buf(void);
+void disk_write_barrier(void);
+
+sector_t disk_find_free(const struct mem_tpm_mgr *mgr);
+void disk_flush_slot(const struct mem_tpm_mgr *mgr);
+void disk_set_used(sector_t loc, const struct mem_tpm_mgr *mgr);
+
+void disk_write_all(struct mem_tpm_mgr *mgr);
+
+static inline sector_t seal_loc(struct mem_tpm_mgr *mgr)
+{
+ return native_be32(mgr->active_root);
+}
+
+static inline sector_t root_loc(struct mem_tpm_mgr *mgr)
+{
+ return native_be32(2 + mgr->active_root);
+}
+
+#endif
diff --git a/stubdom/vtpmmgr/disk_read.c b/stubdom/vtpmmgr/disk_read.c
new file mode 100644
index 0000000..33aacdd
--- /dev/null
+++ b/stubdom/vtpmmgr/disk_read.c
@@ -0,0 +1,606 @@
+#include <console.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <mini-os/byteorder.h>
+
+#include "vtpm_manager.h"
+#include "log.h"
+#include "uuid.h"
+
+#include "vtpmmgr.h"
+#include "vtpm_disk.h"
+#include "disk_tpm.h"
+#include "disk_io.h"
+#include "disk_crypto.h"
+#include "disk_format.h"
+
+static int disk_read_crypt_sector(void *data, size_t size, sector_t block, const struct mem_tpm_mgr *mgr)
+{
+ struct disk_crypt_sector_plain *sector = disk_read_sector(block);
+ if (!sector)
+ return 2;
+
+ if (aes_cmac_verify(§or->mac, sector->data, sizeof(sector->data), &mgr->tm_key_e))
+ return 2;
+
+ aes_decrypt_ctr(data, size, sector->iv_data, sizeof(sector->iv_data), &mgr->tm_key_e);
+ return 0;
+}
+
+static void group_free(struct mem_group *group)
+{
+ int i, j;
+ if (!group)
+ return;
+ if (group->data) {
+ for (i = 0; i < group->nr_pages; i++) {
+ for (j = 0; j < group->data[i].size; j++) {
+ free(group->data[i].vtpms[j]);
+ }
+ }
+ free(group->data);
+ }
+ free(group->seals);
+ free(group);
+}
+
+static void mgr_free(struct mem_tpm_mgr *mgr)
+{
+ int i;
+ if (!mgr)
+ return;
+ if (mgr->groups) {
+ for(i=0; i < mgr->nr_groups; i++)
+ group_free(mgr->groups[i].v);
+ free(mgr->groups);
+ }
+ free(mgr);
+}
+
+/* Open the group keys from one of the sealed strutures */
+static int find_group_key(struct mem_group *dst,
+ const struct disk_group_sector *group,
+ const struct mem_tpm_mgr *parent)
+{
+ int i, rc, rv = 1;
+ struct hash160 buf;
+ struct disk_group_sealed_data sealed;
+
+ dst->nr_seals = be32_native(group->v.boot_configs.nr_cfgs);
+ if (dst->nr_seals > NR_SEALS_PER_GROUP)
+ return 3; // TODO support spill to extra pages
+
+ dst->seals = calloc(dst->nr_seals, sizeof(dst->seals[0]));
+ if (!dst->seals) {
+ vtpmlogerror(VTPM_LOG_VTPM, "find_group_key alloc %x\n", dst->nr_seals);
+ return 2;
+ }
+
+ for(i=0; i < dst->nr_seals; i++) {
+ const struct disk_seal_entry *cfg = &group->v.boot_configs.entry[i];
+ dst->seals[i].pcr_selection = cfg->pcr_selection;
+ memcpy(&dst->seals[i].digest_release, &cfg->digest_release, 20);
+
+ TPM_pcr_digest(&buf, cfg->pcr_selection);
+ if (memcmp(&buf, &cfg->digest_release, 20))
+ continue;
+ rc = TPM_disk_unseal(&sealed, sizeof(sealed), cfg);
+ if (rc)
+ continue;
+ if (memcmp(&sealed.magic, DISK_GROUP_BOUND_MAGIC, 4))
+ continue;
+ if (memcmp(sealed.tpm_manager_uuid, parent->uuid, 16))
+ continue;
+
+ memcpy(&dst->rollback_mac_key, &sealed.rollback_mac_key, 16);
+ memcpy(&dst->group_key, &sealed.group_key, 16);
+ memcpy(&dst->aik_authdata, &sealed.aik_authdata, 20);
+ rv = 0;
+ }
+
+ // cache the list to allow writes without touching the TPM
+ memcpy(&dst->seal_bits, &group->v.boot_configs, sizeof(dst->seal_bits));
+ dst->flags |= MEM_GROUP_FLAG_SEAL_VALID;
+
+ return rv;
+}
+
+static int parse_root_key(struct mem_tpm_mgr *dst, struct disk_seal_entry *src)
+{
+ int rc;
+ struct disk_root_sealed_data sealed;
+
+ rc = TPM_disk_unseal(&sealed, sizeof(sealed), src);
+ if (rc)
+ return rc;
+
+ if (memcmp(&sealed.magic, DISK_ROOT_BOUND_MAGIC, 4))
+ return 1;
+
+ rc = TPM_disk_nvread(&dst->nv_key, 16, sealed.nvram_slot, sealed.nvram_auth);
+ if (rc)
+ return rc;
+
+ // TODO when an NV slot in the physical TPM is used to populate nv_key,
+ // that value should be used to mask the master key so that the value
+ // can be changed to revoke old disk state
+#if 0
+ aes_decrypt_one(&dst->tm_key, &sealed.tm_key, &dst->nv_key);
+#else
+ memcpy(&dst->tm_key, &sealed.tm_key, 16);
+#endif
+
+ memcpy(dst->uuid, sealed.tpm_manager_uuid, 16);
+ dst->nvram_slot = sealed.nvram_slot;
+ memcpy(&dst->nvram_auth, &sealed.nvram_auth, sizeof(struct tpm_authdata));
+ dst->counter_index = sealed.counter_index;
+ memcpy(&dst->counter_auth, &sealed.counter_auth, sizeof(struct tpm_authdata));
+
+ return 0;
+}
+
+static struct mem_tpm_mgr *find_root_key(int active_root)
+{
+ sector_t seal_list = native_be32(active_root);
+ struct disk_seal_list *seal = disk_read_sector(seal_list);
+ struct hash160 buf;
+ int i, rc, nr;
+ struct mem_tpm_mgr *dst;
+
+ if (memcmp(seal->hdr.magic, TPM_MGR_MAGIC, 12))
+ return NULL;
+
+ if (be32_native(seal->hdr.version) != TPM_MGR_VERSION)
+ return NULL;
+
+ dst = calloc(1, sizeof(*dst));
+ dst->active_root = active_root;
+
+ for (nr = 0; nr < 100; nr++) {
+ disk_set_used(seal_list, dst);
+ uint32_t nr_seals = be32_native(seal->length);
+ if (nr_seals > SEALS_PER_ROOT_SEAL_LIST)
+ break;
+ for (i = 0; i < nr_seals; i++) {
+ struct disk_seal_entry *src = &seal->entry[i];
+
+ TPM_pcr_digest(&buf, src->pcr_selection);
+ if (memcmp(&buf, &src->digest_release, 20))
+ continue;
+
+ rc = parse_root_key(dst, src);
+ if (rc)
+ continue;
+ return dst;
+ }
+ seal_list = seal->next;
+ if (seal_list.value == 0)
+ break;
+ seal = disk_read_sector(seal_list);
+ }
+ mgr_free(dst);
+ return NULL;
+}
+
+/* Load and verify one sector's worth of vTPMs. This loads all the vTPM entries
+ * and decrypts their state data into memory.
+ */
+static int load_verify_vtpm_page(struct mem_vtpm_page *dst, int base,
+ const struct mem_tpm_mgr *mgr, const aes_context *group_key)
+{
+ struct disk_vtpm_sector pt;
+ int i, rc;
+
+ disk_set_used(dst->disk_loc, mgr);
+
+ rc = disk_read_crypt_sector(&pt, sizeof(pt), dst->disk_loc, mgr);
+ if (rc) {
+ printk("Malformed sector %d\n", be32_native(dst->disk_loc));
+ return rc;
+ }
+
+ rc = sha256_verify(&dst->disk_hash, &pt, sizeof(pt));
+ if (rc) {
+ printk("Hash mismatch in sector %d\n", be32_native(dst->disk_loc));
+ return rc;
+ }
+
+ if (!group_key)
+ return 0;
+
+ aes_decrypt_ctr(pt.data, sizeof(pt.data), &pt.iv, sizeof(pt.data) + 16, group_key);
+
+ for (i = 0; i < dst->size; i++) {
+ struct mem_vtpm *vtpm = calloc(1, sizeof(*vtpm));
+ dst->vtpms[i] = vtpm;
+ memcpy(vtpm->uuid, pt.header[i].uuid, 16);
+ memcpy(vtpm->data, pt.data[i].data, 64);
+ vtpm->flags = be32_native(pt.header[i].flags);
+ vtpm->index_in_parent = i + base;
+ }
+ return 0;
+}
+
+static int load_verify_vtpm_pages(struct mem_group *group, int base, int size,
+ const struct hash256 *hash, const sector_t *loc,
+ const struct mem_tpm_mgr *mgr, const aes_context *group_key)
+{
+ int i, rc;
+ struct mem_vtpm_page *page = group->data + base;
+
+ /* base was in terms of sectors; convert to vtpms */
+ base *= VTPMS_PER_SECTOR;
+
+ for (i = 0; i < size; i++) {
+ page->disk_hash = hash[i];
+ page->disk_loc = loc[i];
+ if (group->nr_vtpms - base > VTPMS_PER_SECTOR)
+ page->size = VTPMS_PER_SECTOR;
+ else
+ page->size = group->nr_vtpms - base;
+ rc = load_verify_vtpm_page(page, base, mgr, group_key);
+ if (rc)
+ return rc;
+ base += VTPMS_PER_SECTOR;
+ }
+
+ return 0;
+}
+
+static int load_verify_vtpm_itree(struct mem_group_hdr *hdr, int base, int nr_entries,
+ const struct hash256 *hash, const sector_t *loc, int hsize,
+ const struct mem_tpm_mgr *mgr, const aes_context *group_key);
+
+static int load_verify_vtpm_itree(struct mem_group_hdr *hdr, int base, int nr_entries,
+ const struct hash256 *hash, const sector_t *loc, int hsize,
+ const struct mem_tpm_mgr *mgr, const aes_context *group_key)
+{
+ int i, rc, incr = 1, inuse_base = hdr->disk_nr_inuse, lsize;
+
+ // increase tree depth until all entries fit
+ while (nr_entries > incr * hsize)
+ incr *= NR_ENTRIES_PER_ITREE;
+
+ // save the list of used sectors (itree and vtpm) in the header
+ lsize = 1 + (nr_entries - 1) / incr;
+ hdr->disk_nr_inuse += lsize;
+ hdr->disk_inuse = realloc(hdr->disk_inuse, hdr->disk_nr_inuse * sizeof(sector_t));
+ memcpy(&hdr->disk_inuse[inuse_base], loc, lsize * sizeof(sector_t));
+
+ // if the entries already fit, process vtpm pages
+ if (nr_entries <= hsize)
+ return load_verify_vtpm_pages(hdr->v, base, nr_entries, hash, loc, mgr, group_key);
+
+ for (i = 0; i * incr < nr_entries; i++) {
+ struct disk_itree_sector pt;
+ int child_entries = incr;
+
+ // the last sector is not completely full
+ if (nr_entries - i * incr < incr)
+ child_entries = nr_entries - i * incr;
+
+ disk_set_used(loc[i], mgr);
+ hdr->disk_inuse[inuse_base++] = loc[i];
+
+ rc = disk_read_crypt_sector(&pt, sizeof(pt), loc[i], mgr);
+ if (rc) {
+ printk("Malformed sector %d\n", be32_native(loc[i]));
+ return rc;
+ }
+
+ rc = sha256_verify(&hash[i], pt.hash, sizeof(pt.hash));
+ if (rc) {
+ printk("Hash mismatch in sector %d\n", be32_native(loc[i]));
+ return rc;
+ }
+
+ rc = load_verify_vtpm_itree(hdr, base, child_entries, pt.hash, pt.location,
+ NR_ENTRIES_PER_ITREE, mgr, group_key);
+ if (rc)
+ return rc;
+
+ base += incr;
+ }
+
+ return 0;
+}
+
+/* Load and verify one group's data structure, including its vTPMs.
+ */
+static int load_verify_group(struct mem_group_hdr *dst, const struct mem_tpm_mgr *mgr)
+{
+ struct mem_group *group;
+ struct disk_group_sector disk;
+ int rc;
+ aes_context key_e;
+ aes_context *opened_key = NULL;
+
+ disk_set_used(dst->disk_loc, mgr);
+
+ rc = disk_read_crypt_sector(&disk, sizeof(disk), dst->disk_loc, mgr);
+ if (rc) {
+ printk("Malformed sector %d\n", be32_native(dst->disk_loc));
+ return rc;
+ }
+
+ rc = sha256_verify(&dst->disk_hash, &disk.v, sizeof(disk.v) + sizeof(disk.group_mac));
+ if (rc) {
+ printk("Hash mismatch in sector %d\n", be32_native(dst->disk_loc));
+ return rc;
+ }
+
+ dst->v = group = calloc(1, sizeof(*group));
+
+ rc = find_group_key(group, &disk, mgr);
+ if (rc == 0) {
+ opened_key = &key_e;
+ /* Verify the group with the group's own key */
+ aes_setup(opened_key, &group->group_key);
+ if (aes_cmac_verify(&disk.group_mac, &disk.v, sizeof(disk.v), opened_key)) {
+ printk("Group CMAC failed\n");
+ return 2;
+ }
+
+ memcpy(&group->id_data, &disk.v.id_data, sizeof(group->id_data));
+ memcpy(&group->details, &disk.v.details, sizeof(group->details));
+ } else if (rc == 1) {
+ // still need to walk the vtpm list
+ rc = 0;
+ } else {
+ printk("Group key unsealing failed\n");
+ return rc;
+ }
+
+ group->nr_vtpms = be32_native(disk.v.nr_vtpms);
+ group->nr_pages = (group->nr_vtpms + VTPMS_PER_SECTOR - 1) / VTPMS_PER_SECTOR;
+
+ group->data = calloc(group->nr_pages, sizeof(group->data[0]));
+
+ rc = load_verify_vtpm_itree(dst, 0, group->nr_pages, disk.v.vtpm_hash,
+ disk.vtpm_location, NR_ENTRIES_PER_GROUP_BASE, mgr, opened_key);
+
+ if (!opened_key) {
+ /* remove the struct */
+ free(group->data);
+ free(group->seals);
+ free(group);
+ dst->v = NULL;
+ }
+
+ return rc;
+}
+
+static int load_root_pre(struct disk_root_sector *root, struct mem_tpm_mgr *dst)
+{
+ int rc;
+
+ aes_setup(&dst->tm_key_e, &dst->tm_key);
+
+ rc = disk_read_crypt_sector(root, sizeof(*root), root_loc(dst), dst);
+
+ if (rc) {
+ vtpmloginfo(VTPM_LOG_VTPM, "root cmac verify failed in slot %d\n", dst->active_root);
+ return 2;
+ }
+
+ dst->root_seals_valid = 1 + dst->active_root;
+ dst->sequence = be64_native(root->v.sequence);
+
+ return 0;
+}
+
+static int load_verify_group_itree(struct mem_tpm_mgr *dst, int base, int nr_entries,
+ const struct hash256 *hash, const sector_t *loc, int hsize);
+
+static int load_verify_group_itree(struct mem_tpm_mgr *dst, int base, int nr_entries,
+ const struct hash256 *hash, const sector_t *loc, int hsize)
+{
+ int i, rc, incr = 1;
+
+ if (nr_entries <= hsize) {
+ for(i=0; i < nr_entries; i++) {
+ struct mem_group_hdr *group = dst->groups + base + i;
+ group->disk_loc = loc[i];
+ memcpy(&group->disk_hash, &hash[i], sizeof(group->disk_hash));
+ rc = load_verify_group(group, dst);
+ if (rc) {
+ printk("Error loading group %d\n", base + i);
+ return rc;
+ }
+ }
+ return 0;
+ }
+
+ // increase tree depth until all entries fit
+ while (nr_entries > incr * hsize)
+ incr *= NR_ENTRIES_PER_ITREE;
+
+ for (i = 0; i * incr < nr_entries; i++) {
+ struct disk_itree_sector pt;
+ int child_entries = incr;
+
+ // the last sector is not completely full
+ if (nr_entries - i * incr < incr)
+ child_entries = nr_entries - i * incr;
+
+ disk_set_used(loc[i], dst);
+
+ rc = disk_read_crypt_sector(&pt, sizeof(pt), loc[i], dst);
+ if (rc) {
+ printk("Malformed sector %d\n", be32_native(loc[i]));
+ return rc;
+ }
+
+ rc = sha256_verify(&hash[i], pt.hash, sizeof(pt.hash));
+ if (rc) {
+ printk("Hash mismatch in sector %d\n", be32_native(loc[i]));
+ return rc;
+ }
+
+ rc = load_verify_group_itree(dst, base, child_entries, pt.hash, pt.location, NR_ENTRIES_PER_ITREE);
+ if (rc)
+ return rc;
+
+ base += incr;
+ }
+
+ return 0;
+}
+
+static int load_root_post(struct mem_tpm_mgr *dst, const struct disk_root_sector *root)
+{
+ int rc, i, j;
+ uint32_t nr_disk_rbs = be32_native(root->nr_rb_macs);
+
+ rc = TPM_disk_check_counter(dst->counter_index, dst->counter_auth,
+ root->v.tpm_counter_value);
+ if (rc)
+ return 2;
+ dst->counter_value = root->v.tpm_counter_value;
+
+ dst->nr_groups = be32_native(root->v.nr_groups);
+ dst->groups = calloc(sizeof(dst->groups[0]), dst->nr_groups);
+
+ if (!dst->groups) {
+ vtpmlogerror(VTPM_LOG_VTPM, "load_root_post alloc %x\n", dst->nr_groups);
+ return 2;
+ }
+
+ rc = load_verify_group_itree(dst, 0, dst->nr_groups,
+ root->v.group_hash, root->group_loc, NR_ENTRIES_PER_ROOT);
+ if (rc)
+ return rc;
+
+ /* Sanity check: group0 must be open */
+ if (!dst->groups[0].v) {
+ printk("Error opening group 0\n");
+ return 2;
+ }
+
+ /* TODO support for spilling rollback list */
+ if (nr_disk_rbs > NR_RB_MACS_PER_ROOT)
+ return 3;
+
+ i = 0;
+ j = 0;
+ while (i < dst->nr_groups) {
+ aes_context key_e;
+ struct mem_group_hdr *group = &dst->groups[i];
+ struct mem_group *groupv = group->v;
+ const struct disk_rb_mac_entry *ent = &root->rb_macs[j];
+
+ if (!groupv) {
+ i++;
+ // this group is not open - no need to verify now
+ continue;
+ }
+
+ if (be32_native(ent->id) < i) {
+ // this entry is for a group that is not open
+ j++;
+ continue;
+ }
+
+ if (j >= nr_disk_rbs || be32_native(ent->id) != i) {
+ // TODO allow delegation
+ if (!(groupv->details.flags.value & FLAG_ROLLBACK_DETECTED)) {
+ groupv->details.flags.value |= FLAG_ROLLBACK_DETECTED;
+ group->disk_loc.value = 0;
+ }
+ i++;
+ continue;
+ }
+
+ aes_setup(&key_e, &groupv->rollback_mac_key);
+ if (aes_cmac_verify(&ent->mac, &root->v, sizeof(root->v), &key_e)) {
+ if (!(groupv->details.flags.value & FLAG_ROLLBACK_DETECTED)) {
+ groupv->details.flags.value |= FLAG_ROLLBACK_DETECTED;
+ group->disk_loc.value = 0;
+ }
+ }
+ i++; j++;
+ }
+
+ return 0;
+}
+
+int vtpm_load_disk(void)
+{
+ struct disk_root_sector root1, root2;
+ int rc = 0;
+ TPM_read_pcrs();
+
+ printk("TPM Manager - disk format %d\n", TPM_MGR_VERSION);
+ printk(" root seal: %lu; sector of %d: %lu\n",
+ sizeof(struct disk_root_sealed_data), SEALS_PER_ROOT_SEAL_LIST, sizeof(struct disk_seal_list));
+ printk(" root: %lu v=%lu\n", sizeof(root1), sizeof(root1.v));
+ printk(" itree: %lu; sector of %d: %lu\n",
+ 4 + 32, NR_ENTRIES_PER_ITREE, sizeof(struct disk_itree_sector));
+ printk(" group: %lu v=%lu id=%lu md=%lu\n",
+ sizeof(struct disk_group_sector), sizeof(struct disk_group_sector_mac3_area),
+ sizeof(struct group_id_data), sizeof(struct group_details));
+ printk(" group seal: %lu; %d in parent: %lu; sector of %d: %lu\n",
+ sizeof(struct disk_group_sealed_data), NR_SEALS_PER_GROUP, sizeof(struct disk_group_boot_config_list),
+ SEALS_PER_GROUP_SEAL_LIST, sizeof(struct disk_group_seal_list));
+ printk(" vtpm: %lu+%lu; sector of %d: %lu\n",
+ sizeof(struct disk_vtpm_plain), sizeof(struct disk_vtpm_secret),
+ VTPMS_PER_SECTOR, sizeof(struct disk_vtpm_sector));
+
+ struct mem_tpm_mgr *mgr1 = find_root_key(0);
+ struct mem_tpm_mgr *mgr2 = find_root_key(1);
+
+ rc = mgr1 ? load_root_pre(&root1, mgr1) : 0;
+ if (rc) {
+ mgr_free(mgr1);
+ mgr1 = NULL;
+ }
+
+ rc = mgr2 ? load_root_pre(&root2, mgr2) : 0;
+ if (rc) {
+ mgr_free(mgr2);
+ mgr2 = NULL;
+ }
+
+ printk("load_root_pre: %c/%c\n", mgr1 ? 'y' : 'n', mgr2 ? 'y' : 'n');
+
+ if (!mgr1 && !mgr2)
+ return 2;
+
+ if (mgr1 && mgr2 && mgr2->sequence > mgr1->sequence) {
+ rc = load_root_post(mgr2, &root2);
+ if (rc) {
+ mgr_free(mgr2);
+ mgr2 = NULL;
+ } else {
+ mgr_free(mgr1);
+ g_mgr = mgr2;
+ return 0;
+ }
+ }
+ if (mgr1) {
+ rc = load_root_post(mgr1, &root1);
+ if (rc) {
+ mgr_free(mgr1);
+ } else {
+ mgr_free(mgr2);
+ g_mgr = mgr1;
+ return 0;
+ }
+ }
+ if (mgr2) {
+ rc = load_root_post(mgr2, &root2);
+ if (rc) {
+ mgr_free(mgr2);
+ } else {
+ g_mgr = mgr2;
+ return 0;
+ }
+ }
+ printk("Could not read vTPM disk\n");
+
+ return 2;
+}
diff --git a/stubdom/vtpmmgr/disk_tpm.c b/stubdom/vtpmmgr/disk_tpm.c
new file mode 100644
index 0000000..d650fbc
--- /dev/null
+++ b/stubdom/vtpmmgr/disk_tpm.c
@@ -0,0 +1,259 @@
+/* TPM disk interface */
+#include <blkfront.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <mini-os/byteorder.h>
+#include <mini-os/lib.h>
+#include <polarssl/aes.h>
+#include <polarssl/sha1.h>
+
+#include "tpm.h"
+#include "tcg.h"
+
+#include "vtpmmgr.h"
+#include "vtpm_disk.h"
+#include "disk_tpm.h"
+
+// Print out input/output of seal/unseal operations (includes keys)
+#undef DEBUG_SEAL_OPS
+
+#ifdef DEBUG_SEAL_OPS
+#include "marshal.h"
+#endif
+
+struct pcr_list {
+ TPM_DIGEST pcrs[24];
+};
+
+static struct pcr_list hwtpm;
+
+void TPM_read_pcrs(void)
+{
+ int i;
+ for(i=0; i < 24; i++)
+ TPM_PCR_Read(i, &hwtpm.pcrs[i]);
+}
+
+struct pcr_composite_3 {
+ be16_t sel_size;
+ uint8_t sel[3];
+ be32_t val_size;
+ uint8_t val[0];
+} __attribute__((packed));
+
+void TPM_pcr_digest(struct hash160 *buf, le32_t selection)
+{
+ int i;
+ int count = 0;
+ uint32_t sel = le32_native(selection);
+ struct pcr_composite_3 *v;
+ for(i=0; i < 24; i++) {
+ if (sel & (1 << i))
+ count++;
+ }
+ v = alloca(sizeof(*v) + 20 * count);
+ v->sel_size = native_be16(3);
+ memcpy(v->sel, &selection, 3);
+ v->val_size = native_be32(20 * count);
+
+ count = 0;
+ for(i=0; i < 24; i++) {
+ if (sel & (1 << i)) {
+ memcpy(v->val + 20 * count, &hwtpm.pcrs[i], 20);
+ count++;
+ }
+ }
+
+ sha1((void*)v, sizeof(*v) + 20 * count, buf->bits);
+}
+
+
+int TPM_disk_seal(struct disk_seal_entry *dst, const void* src, size_t size)
+{
+ uint32_t rc;
+ uint32_t infoSize;
+ TPM_PCR_INFO_LONG info;
+ TPM_STORED_DATA12 out;
+ TPM_AUTH_SESSION osap = TPM_AUTH_SESSION_INIT;
+ TPM_AUTHDATA sharedsecret;
+ TPM_AUTHDATA auth;
+
+ printk("Calling TPM_disk_seal\n");
+
+ rc = TPM_OSAP(TPM_ET_KEYHANDLE, TPM_SRK_KEYHANDLE, (void*)&vtpm_globals.srk_auth,
+ &sharedsecret, &osap);
+
+ if (rc) abort();
+
+#ifdef DEBUG_SEAL_OPS
+ int i;
+ printk("to-seal:");
+ for(i=0; i < size; i++)
+ printk(" %02x", ((uint8_t*)src)[i]);
+ printk("\n");
+#endif
+
+ memset(auth, 0, 20);
+ info.tag = TPM_TAG_PCR_INFO_LONG;
+ info.localityAtCreation = 1 << vtpm_globals.hw_locality;
+ info.localityAtRelease = 1 << vtpm_globals.hw_locality;
+ info.creationPCRSelection.sizeOfSelect = 3;
+ info.creationPCRSelection.pcrSelect = (void*)&dst->pcr_selection;
+ info.releasePCRSelection.sizeOfSelect = 3;
+ info.releasePCRSelection.pcrSelect = (void*)&dst->pcr_selection;
+ memcpy(&info.digestAtCreation, &dst->digest_at_seal, 20);
+ memcpy(&info.digestAtRelease, &dst->digest_release, 20);
+
+ infoSize = 2 + 1 + 1 + 2 + 3 + 2 + 3 + 20 + 20;
+ //infoSize = sizeof_TPM_PCR_INFO_LONG(&info);
+
+ rc = TPM_Seal(TPM_SRK_KEYHANDLE, infoSize, &info, size, src, &out,
+ (void*)&sharedsecret, (void*)&auth, &osap);
+
+ TPM_TerminateHandle(osap.AuthHandle);
+
+#ifdef DEBUG_SEAL_OPS
+ printk("TPM_Seal rc=%d encDataSize=%d sealInfoSize=%d\n", rc, out.encDataSize, out.sealInfoLongSize);
+#endif
+ if (!rc)
+ memcpy(dst->sealed_data, out.encData, 256);
+
+#ifdef DEBUG_SEAL_OPS
+ uint8_t buf[512];
+ uint8_t *start = buf;
+ uint8_t *end = pack_TPM_STORED_DATA12(buf, &out);
+ printk("stored_data:");
+ while (start != end) {
+ printk(" %02x", *start);
+ start++;
+ }
+ printk("\n");
+#endif
+
+ free_TPM_STORED_DATA12(&out);
+ return rc;
+}
+
+int TPM_disk_unseal(void *dst, size_t size, const struct disk_seal_entry *src)
+{
+ uint32_t rc;
+ TPM_STORED_DATA12 in;
+ TPM_AUTH_SESSION oiap = TPM_AUTH_SESSION_INIT;
+ TPM_AUTHDATA auth;
+ uint32_t outSize = 0;
+ uint8_t *out = NULL;
+
+ printk("Calling TPM_disk_unseal\n");
+
+ rc = TPM_OIAP(&oiap);
+ if (rc) abort();
+
+ memset(auth, 0, 20);
+
+ in.tag = TPM_TAG_STORED_DATA12;
+ in.et = 0;
+ //in.sealInfoLongSize = sizeof_TPM_PCR_INFO_LONG(&in.sealInfoLong);
+ in.sealInfoLongSize = 2 + 1 + 1 + 2 + 3 + 2 + 3 + 20 + 20;
+ in.sealInfoLong.tag = TPM_TAG_PCR_INFO_LONG;
+ in.sealInfoLong.localityAtCreation = 1 << vtpm_globals.hw_locality;
+ in.sealInfoLong.localityAtRelease = 1 << vtpm_globals.hw_locality;
+ in.sealInfoLong.creationPCRSelection.sizeOfSelect = 3;
+ in.sealInfoLong.creationPCRSelection.pcrSelect = (void*)&src->pcr_selection;
+ in.sealInfoLong.releasePCRSelection.sizeOfSelect = 3;
+ in.sealInfoLong.releasePCRSelection.pcrSelect = (void*)&src->pcr_selection;
+ memcpy(&in.sealInfoLong.digestAtCreation, &src->digest_at_seal, 20);
+ memcpy(&in.sealInfoLong.digestAtRelease, &src->digest_release, 20);
+ in.encDataSize = 256;
+ in.encData = (void*)src->sealed_data;
+
+#ifdef DEBUG_SEAL_OPS
+ uint8_t buf[512];
+ uint8_t *start = buf;
+ uint8_t *end = pack_TPM_STORED_DATA12(buf, &in);
+ printk("stored_data:");
+ while (start != end) {
+ printk(" %02x", *start);
+ start++;
+ }
+ printk("\n");
+#endif
+
+ rc = TPM_Unseal(TPM_SRK_KEYHANDLE, &in, &outSize, &out,
+ (void*)&vtpm_globals.srk_auth, (void*)&auth, &vtpm_globals.oiap, &oiap);
+
+ TPM_TerminateHandle(oiap.AuthHandle);
+
+#ifdef DEBUG_SEAL_OPS
+ printk("TPM_Unseal rc=%d outSize=%d size=%d\n", rc, outSize, size);
+#endif
+ if (!rc) {
+ memcpy(dst, out, size);
+#ifdef DEBUG_SEAL_OPS
+ printk("unsealed:");
+ int i;
+ for(i=0; i < size; i++)
+ printk(" %02x", ((uint8_t*)dst)[i]);
+ printk("\n");
+#endif
+ }
+
+ free(out);
+
+ return rc;
+}
+
+int TPM_disk_nvalloc(be32_t *nvram_slot, struct tpm_authdata auth)
+{
+ // TODO-3
+ nvram_slot->value = 0;
+ return 0;
+}
+
+int TPM_disk_nvread(void *buf, size_t bufsiz, be32_t nvram_slot, struct tpm_authdata auth)
+{
+ // TODO-3
+ memset(buf, 0, bufsiz);
+ return 0;
+}
+
+int TPM_disk_nvwrite(void *buf, size_t bufsiz, be32_t nvram_slot, struct tpm_authdata auth)
+{
+ // TODO-3
+ return 0;
+}
+
+int TPM_disk_nvchange(be32_t nvram_slot, struct tpm_authdata old, struct tpm_authdata noo)
+{
+ // TODO-3
+ return 0;
+}
+
+int TPM_disk_alloc_counter(be32_t *slot, struct tpm_authdata auth, be32_t *value)
+{
+ // TODO-3
+ slot->value = 0;
+ value->value = 0;
+ return 0;
+}
+
+int TPM_disk_check_counter(be32_t slot, struct tpm_authdata auth, be32_t value)
+{
+ // TODO-3
+ return 0;
+}
+
+int TPM_disk_incr_counter(be32_t slot, struct tpm_authdata auth)
+{
+ // TODO-3
+ return 0;
+}
+
+int TPM_disk_change_counter(be32_t slot, struct tpm_authdata old, struct tpm_authdata noo)
+{
+ // TODO-3
+ return 0;
+}
diff --git a/stubdom/vtpmmgr/disk_tpm.h b/stubdom/vtpmmgr/disk_tpm.h
new file mode 100644
index 0000000..b235895
--- /dev/null
+++ b/stubdom/vtpmmgr/disk_tpm.h
@@ -0,0 +1,25 @@
+#ifndef __VTPMMGR_DISK_VTPM_H
+#define __VTPMMGR_DISK_VTPM_H
+#include "vtpm_disk.h"
+
+/* Read PCR values to determine which unseal to try */
+void TPM_read_pcrs(void);
+void TPM_pcr_digest(struct hash160 *buf, le32_t selection);
+
+/* Sealing for key storage */
+int TPM_disk_seal(struct disk_seal_entry *dst, const void* src, size_t size);
+int TPM_disk_unseal(void *dst, size_t size, const struct disk_seal_entry *src);
+
+/* NVRAM to allow revocation of TM-KEY */
+int TPM_disk_nvalloc(be32_t *nvram_slot, struct tpm_authdata auth);
+int TPM_disk_nvread(void *buf, size_t bufsiz, be32_t nvram_slot, struct tpm_authdata auth);
+int TPM_disk_nvwrite(void *buf, size_t bufsiz, be32_t nvram_slot, struct tpm_authdata auth);
+int TPM_disk_nvchange(be32_t nvram_slot, struct tpm_authdata old, struct tpm_authdata noo);
+
+/* Monotonic counters to detect rollback */
+int TPM_disk_alloc_counter(be32_t *slot, struct tpm_authdata auth, be32_t *value);
+int TPM_disk_check_counter(be32_t slot, struct tpm_authdata auth, be32_t value);
+int TPM_disk_incr_counter(be32_t slot, struct tpm_authdata auth);
+int TPM_disk_change_counter(be32_t slot, struct tpm_authdata old, struct tpm_authdata noo);
+
+#endif
diff --git a/stubdom/vtpmmgr/disk_write.c b/stubdom/vtpmmgr/disk_write.c
new file mode 100644
index 0000000..4c825c5
--- /dev/null
+++ b/stubdom/vtpmmgr/disk_write.c
@@ -0,0 +1,410 @@
+#include <console.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <mini-os/byteorder.h>
+
+#include "vtpm_manager.h"
+#include "log.h"
+#include "uuid.h"
+
+#include "vtpmmgr.h"
+#include "vtpm_disk.h"
+#include "disk_tpm.h"
+#include "disk_io.h"
+#include "disk_crypto.h"
+#include "disk_format.h"
+#include "mgmt_authority.h"
+
+static void disk_write_crypt_sector(sector_t *dst, const void *data, size_t size, const struct mem_tpm_mgr *mgr)
+{
+ struct disk_crypt_sector_plain *sector = disk_write_buf();
+ *dst = disk_find_free(mgr);
+ aes_encrypt_ctr(sector->iv_data, sizeof(sector->iv_data), data, size, &mgr->tm_key_e);
+ aes_cmac(§or->mac, sector->data, sizeof(sector->data), &mgr->tm_key_e);
+ disk_write_sector(*dst, sector, sizeof(*sector));
+}
+
+/*
+ * Mark unchanged sectors on disk as being used
+ */
+static void disk_populate_used_vtpm(const struct mem_vtpm_page *src, const struct mem_tpm_mgr *mgr)
+{
+ if (be32_native(src->disk_loc) != 0)
+ disk_set_used(src->disk_loc, mgr);
+}
+
+/*
+ * Write out a vTPM page to disk, doing nothing if the existing copy is valid
+ */
+static void disk_write_vtpm_page(struct mem_vtpm_page *dst, const aes_context *auth_key,
+ const struct mem_tpm_mgr *mgr)
+{
+ struct disk_vtpm_sector pt;
+ int i;
+ memset(&pt, 0, sizeof(pt));
+ if (be32_native(dst->disk_loc) != 0)
+ return;
+
+ for(i=0; i < dst->size; i++) {
+ memcpy(pt.header[i].uuid, dst->vtpms[i]->uuid, 16);
+ memcpy(pt.data[i].data, dst->vtpms[i]->data, 64);
+ pt.header[i].flags = native_be32(dst->vtpms[i]->flags & VTPM_FLAG_DISK_MASK);
+ }
+ aes_encrypt_ctr(&pt.iv, sizeof(pt.data) + 16, &pt.data, sizeof(pt.data), auth_key);
+
+ sha256(&dst->disk_hash, &pt, sizeof(pt));
+
+ disk_write_crypt_sector(&dst->disk_loc, &pt, sizeof(pt), mgr);
+}
+
+/*
+ * Generate TPM seal blobs for a group's keys; do nothing if existing copy is valid
+ */
+static void generate_group_seals(struct mem_group *src, const struct mem_tpm_mgr *parent)
+{
+ int i;
+ struct disk_group_sealed_data sblob;
+
+ // previous seals are still valid, skip talking to the TPM
+ if (src->flags & MEM_GROUP_FLAG_SEAL_VALID)
+ return;
+
+ memcpy(&sblob.magic, DISK_GROUP_BOUND_MAGIC, 4);
+ memcpy(sblob.tpm_manager_uuid, parent->uuid, 16);
+ memcpy(&sblob.aik_authdata, &src->aik_authdata, 20);
+ memcpy(&sblob.group_key, &src->group_key, 16);
+ memcpy(&sblob.rollback_mac_key, &src->rollback_mac_key, 16);
+
+ /* TODO support for more than NR_SEALS_PER_GROUP seals */
+ if (src->nr_seals > NR_SEALS_PER_GROUP)
+ abort();
+
+ for(i=0; i < src->nr_seals; i++) {
+ struct disk_seal_entry *dst = &src->seal_bits.entry[i];
+ dst->pcr_selection = src->seals[i].pcr_selection;
+ memcpy(&dst->digest_release, &src->seals[i].digest_release, 20);
+ TPM_pcr_digest(&dst->digest_at_seal, dst->pcr_selection);
+ TPM_disk_seal(dst, &sblob, sizeof(sblob));
+ }
+ src->seal_bits.nr_cfgs = native_be32(src->nr_seals);
+
+ src->flags |= MEM_GROUP_FLAG_SEAL_VALID;
+}
+
+/*
+ * Mark unchanged sectors on disk as being used
+ */
+static void disk_populate_used_group(const struct mem_group_hdr *src, const struct mem_tpm_mgr *mgr)
+{
+ int i;
+ struct mem_group *group = src->v;
+ if (be32_native(src->disk_loc) != 0) {
+ // entire group is unchanged - mark group, itree, and vtpm sectors
+ // TODO mark other children (seal)
+ disk_set_used(src->disk_loc, mgr);
+ for(i = 0; i < src->disk_nr_inuse; i++)
+ disk_set_used(src->disk_inuse[i], mgr);
+ return;
+ }
+
+ // unopened groups should never have been invalidated
+ if (!group)
+ abort();
+
+ for (i = 0; i < group->nr_pages; i++)
+ disk_populate_used_vtpm(&group->data[i], mgr);
+}
+
+static void disk_write_vtpm_itree(struct mem_group_hdr *hdr, int base, int nr_entries,
+ struct hash256 *hash, sector_t *loc, int hsize,
+ const aes_context *group_key, const struct mem_tpm_mgr *mgr);
+
+static void disk_write_vtpm_itree(struct mem_group_hdr *hdr, int base, int nr_entries,
+ struct hash256 *hash, sector_t *loc, int hsize,
+ const aes_context *group_key, const struct mem_tpm_mgr *mgr)
+{
+ int i, incr = 1, inuse_base, lsize;
+
+ while (nr_entries > incr * hsize)
+ incr *= NR_ENTRIES_PER_ITREE;
+
+ if (nr_entries <= hsize) {
+ struct mem_group *group = hdr->v;
+ for (i = 0; i < nr_entries; i++) {
+ struct mem_vtpm_page *page = group->data + base + i;
+ disk_write_vtpm_page(page, group_key, mgr);
+ loc[i] = page->disk_loc;
+ hash[i] = page->disk_hash;
+ }
+ } else {
+ for (i = 0; i * incr < nr_entries; i++) {
+ struct disk_itree_sector pt;
+ int child_entries = incr;
+
+ // the last sector is not completely full
+ if (nr_entries - i * incr < incr)
+ child_entries = nr_entries - i * incr;
+
+ disk_write_vtpm_itree(hdr, base, child_entries, pt.hash, pt.location,
+ NR_ENTRIES_PER_ITREE, group_key, mgr);
+
+ sha256(&hash[i], &pt.hash, sizeof(pt.hash));
+ disk_write_crypt_sector(&loc[i], &pt, sizeof(pt), mgr);
+
+ base += incr;
+ }
+ }
+
+ // save the list of used sectors (itree and vtpm) in the header
+ inuse_base = hdr->disk_nr_inuse;
+ lsize = 1 + (nr_entries - 1) / incr;
+ hdr->disk_nr_inuse += lsize;
+ hdr->disk_inuse = realloc(hdr->disk_inuse, hdr->disk_nr_inuse * sizeof(sector_t));
+ memcpy(&hdr->disk_inuse[inuse_base], loc, lsize * sizeof(sector_t));
+}
+
+/*
+ * Write out a vTPM group sector and its children
+ */
+static void disk_write_group_sector(struct mem_group_hdr *src,
+ const struct mem_tpm_mgr *mgr)
+{
+ struct disk_group_sector disk;
+ struct mem_group *group = src->v;
+ aes_context key_e;
+
+ /* Don't write if the data hasn't changed */
+ if (be32_native(src->disk_loc) != 0)
+ return;
+
+ // if the group was not opened, it should not have been changed
+ if (!group)
+ abort();
+
+ memset(&disk, 0, sizeof(disk));
+ memcpy(&disk.v.id_data, &group->id_data, sizeof(disk.v.id_data));
+ memcpy(&disk.v.details, &group->details, sizeof(disk.v.details));
+
+ aes_setup(&key_e, &group->group_key);
+
+ disk.v.nr_vtpms = native_be32(group->nr_vtpms);
+
+ // regenerated
+ src->disk_nr_inuse = 0;
+
+ disk_write_vtpm_itree(src, 0, group->nr_pages, disk.v.vtpm_hash, disk.vtpm_location,
+ NR_ENTRIES_PER_GROUP_BASE, &key_e, mgr);
+
+ generate_group_seals(group, mgr);
+ memcpy(&disk.v.boot_configs, &group->seal_bits, sizeof(group->seal_bits));
+
+ aes_cmac(&disk.group_mac, &disk.v, sizeof(disk.v), &key_e);
+ sha256(&src->disk_hash, &disk.v, sizeof(disk.v) + sizeof(disk.group_mac));
+ disk_write_crypt_sector(&src->disk_loc, &disk, sizeof(disk), mgr);
+}
+
+/*
+ * Write TPM seal blobs for the manager's keys, using the given group's list
+ * of valid configurations
+ */
+static void disk_write_seal_list(struct mem_tpm_mgr *mgr, struct mem_group *group)
+{
+ int i;
+ struct disk_seal_list *seal = disk_write_buf();
+ struct disk_root_sealed_data sblob;
+
+ if (mgr->root_seals_valid & (1 + mgr->active_root))
+ return;
+
+ memcpy(&sblob.magic, DISK_ROOT_BOUND_MAGIC, 4);
+ memcpy(sblob.tpm_manager_uuid, mgr->uuid, 16);
+ memcpy(&sblob.nvram_slot, &mgr->nvram_slot, 4);
+ memcpy(&sblob.nvram_auth, &mgr->nvram_auth, 20);
+ memcpy(&sblob.counter_index, &mgr->counter_index, 4);
+ memcpy(&sblob.counter_auth, &mgr->counter_auth, 20);
+
+ // TODO when an NV slot in the physical TPM is used to populate nv_key,
+ // that value should be used to mask the master key so that the value
+ // can be changed to revoke old disk state
+#if 0
+ aes_encrypt_one(&sblob.tm_key, &mgr->tm_key, &mgr->nv_key);
+#else
+ memcpy(&sblob.tm_key, &mgr->tm_key, 16);
+#endif
+
+ memset(seal, 0, sizeof(*seal));
+ seal->length = native_be32(group->nr_seals);
+
+ // TODO support for more entries
+ if (group->nr_seals > SEALS_PER_ROOT_SEAL_LIST)
+ abort();
+
+ for(i=0; i < group->nr_seals; i++) {
+ struct mem_seal *src = &group->seals[i];
+ struct disk_seal_entry *dst = &seal->entry[i];
+ dst->pcr_selection = src->pcr_selection;
+ memcpy(&dst->digest_release, &src->digest_release, 20);
+ TPM_pcr_digest(&dst->digest_at_seal, dst->pcr_selection);
+
+ TPM_disk_seal(dst, &sblob, sizeof(sblob));
+ }
+
+ memcpy(seal->hdr.magic, TPM_MGR_MAGIC, 12);
+ seal->hdr.version = native_be32(TPM_MGR_VERSION);
+
+ disk_write_sector(seal_loc(mgr), seal, sizeof(*seal));
+ mgr->root_seals_valid |= 1 + mgr->active_root;
+}
+
+/*
+ * Mark unchanged sectors on disk as being used
+ */
+static void disk_populate_used_mgr(const struct mem_tpm_mgr *mgr)
+{
+ int i;
+
+ // TODO walk the linked lists for seals, rb_macs here (when supported)
+
+ for(i=0; i < mgr->nr_groups; i++)
+ disk_populate_used_group(&mgr->groups[i], mgr);
+}
+
+static void disk_write_group_itree(struct mem_tpm_mgr *mgr, int base, int nr_entries,
+ struct hash256 *hash, sector_t *loc, int hsize);
+
+static void disk_write_group_itree(struct mem_tpm_mgr *mgr, int base, int nr_entries,
+ struct hash256 *hash, sector_t *loc, int hsize)
+{
+ int i, incr = 1;
+
+ if (nr_entries <= hsize) {
+ for(i=0; i < mgr->nr_groups; i++) {
+ struct mem_group_hdr *group = mgr->groups + base + i;
+ disk_write_group_sector(group, mgr);
+ loc[i] = group->disk_loc;
+ hash[i] = group->disk_hash;
+ }
+ return;
+ }
+
+ while (nr_entries > incr * hsize)
+ incr *= NR_ENTRIES_PER_ITREE;
+
+ for (i = 0; i * incr < nr_entries; i++) {
+ struct disk_itree_sector pt;
+ int child_entries = incr;
+
+ // the last sector is not completely full
+ if (nr_entries - i * incr < incr)
+ child_entries = nr_entries - i * incr;
+
+ disk_write_group_itree(mgr, base, child_entries, pt.hash, pt.location, NR_ENTRIES_PER_ITREE);
+
+ sha256(&hash[i], &pt.hash, sizeof(pt.hash));
+ disk_write_crypt_sector(&loc[i], &pt, sizeof(pt), mgr);
+
+ base += incr;
+ }
+}
+
+/*
+ * Write out the root TPM Manager sector and its children
+ */
+static void disk_write_root_sector(struct mem_tpm_mgr *mgr)
+{
+ int i, j;
+ struct disk_root_sector root;
+ memset(&root, 0, sizeof(root));
+ root.v.sequence = native_be64(mgr->sequence);
+ root.v.tpm_counter_value = mgr->counter_value;
+
+ root.v.nr_groups = native_be32(mgr->nr_groups);
+
+ disk_write_group_itree(mgr, 0, mgr->nr_groups, root.v.group_hash, root.group_loc, NR_ENTRIES_PER_ROOT);
+
+ i = 0;
+ j = 0;
+ while (i < mgr->nr_groups) {
+ aes_context key_e;
+ struct mem_group_hdr *group = &mgr->groups[i];
+ struct mem_group *groupv = group->v;
+
+ if (!groupv) {
+ i++;
+ continue;
+ }
+ if (groupv->details.flags.value & FLAG_ROLLBACK_DETECTED) {
+ i++;
+ continue;
+ }
+ if (j >= NR_RB_MACS_PER_ROOT)
+ break; // TODO support for nr_rb_macs > 128
+
+ aes_setup(&key_e, &groupv->rollback_mac_key);
+ root.rb_macs[j].id = native_be32(i);
+ aes_cmac(&root.rb_macs[j].mac, &root.v, sizeof(root.v), &key_e);
+ i++; j++;
+ }
+ root.nr_rb_macs = native_be32(j);
+
+ struct disk_crypt_sector_plain *root_sect = disk_write_buf();
+ aes_encrypt_ctr(root_sect->iv_data, sizeof(root_sect->iv_data), &root, sizeof(root), &mgr->tm_key_e);
+ aes_cmac(&root_sect->mac, &root_sect->data, sizeof(root_sect->data), &mgr->tm_key_e);
+ disk_write_sector(root_loc(mgr), root_sect, sizeof(*root_sect));
+}
+
+/*
+ * Write out changes to disk
+ */
+void disk_write_all(struct mem_tpm_mgr *mgr)
+{
+ disk_flush_slot(mgr);
+ disk_populate_used_mgr(mgr);
+ disk_write_root_sector(mgr);
+
+ disk_write_seal_list(mgr, mgr->groups[0].v);
+
+ disk_write_barrier();
+}
+
+/*
+ * Create a new (blank) TPM Manager disk image.
+ *
+ * Does not actually write anything to disk.
+ */
+int vtpm_new_disk(void)
+{
+ int rc;
+ struct mem_tpm_mgr *mgr = calloc(1, sizeof(*mgr));
+
+ do_random(mgr->uuid, 16);
+ do_random(&mgr->tm_key, 16);
+ do_random(&mgr->nvram_auth, 20);
+ do_random(&mgr->counter_auth, 20);
+ do_random(&mgr->nv_key, 16);
+
+ aes_setup(&mgr->tm_key_e, &mgr->tm_key);
+
+ // TODO postpone these allocs until first write?
+ rc = TPM_disk_nvalloc(&mgr->nvram_slot, mgr->nvram_auth);
+ if (rc)
+ return rc;
+
+ rc = TPM_disk_alloc_counter(&mgr->counter_index, mgr->counter_auth, &mgr->counter_value);
+ if (rc)
+ return rc;
+
+ mgr->nr_groups = 1;
+ mgr->groups = calloc(1, sizeof(mgr->groups[0]));
+ mgr->groups[0].v = vtpm_new_group(NULL);
+
+ TPM_disk_nvwrite(&mgr->nv_key, 16, mgr->nvram_slot, mgr->nvram_auth);
+
+ g_mgr = mgr;
+
+ return 0;
+}
diff --git a/stubdom/vtpmmgr/endian_int.h b/stubdom/vtpmmgr/endian_int.h
new file mode 100644
index 0000000..030f87b
--- /dev/null
+++ b/stubdom/vtpmmgr/endian_int.h
@@ -0,0 +1,72 @@
+#ifndef __VTPMMGR_ENDIAN_INT_H
+#define __VTPMMGR_ENDIAN_INT_H
+
+#include <mini-os/byteorder.h>
+
+/* These wrapper structs force the use of endian-to-CPU conversions */
+
+typedef struct be_int16 {
+ uint16_t value;
+} be16_t;
+
+typedef struct be_int32 {
+ uint32_t value;
+} be32_t;
+
+typedef struct le_int32 {
+ uint32_t value;
+} le32_t;
+
+typedef struct be_int64 {
+ uint64_t value;
+} be64_t;
+
+static inline uint16_t be16_native(be16_t v)
+{
+ return be16_to_cpu(v.value);
+}
+
+static inline uint32_t le32_native(le32_t v)
+{
+ return le32_to_cpu(v.value);
+}
+
+static inline uint32_t be32_native(be32_t v)
+{
+ return be32_to_cpu(v.value);
+}
+
+static inline uint64_t be64_native(be64_t v)
+{
+ return be64_to_cpu(v.value);
+}
+
+static inline be16_t native_be16(uint16_t v)
+{
+ be16_t rv;
+ rv.value = cpu_to_be16(v);
+ return rv;
+}
+
+static inline le32_t native_le32(uint32_t v)
+{
+ le32_t rv;
+ rv.value = cpu_to_le32(v);
+ return rv;
+}
+
+static inline be32_t native_be32(uint32_t v)
+{
+ be32_t rv;
+ rv.value = cpu_to_be32(v);
+ return rv;
+}
+
+static inline be64_t native_be64(uint64_t v)
+{
+ be64_t rv;
+ rv.value = cpu_to_be64(v);
+ return rv;
+}
+
+#endif
diff --git a/stubdom/vtpmmgr/init.c b/stubdom/vtpmmgr/init.c
index 33ac152..f3aa02f 100644
--- a/stubdom/vtpmmgr/init.c
+++ b/stubdom/vtpmmgr/init.c
@@ -48,7 +48,7 @@
#include "log.h"
#include "vtpmmgr.h"
-#include "vtpm_storage.h"
+#include "vtpm_disk.h"
#include "tpm.h"
#include "marshal.h"
@@ -64,17 +64,13 @@ struct Opts {
};
// --------------------------- Well Known Auths --------------------------
-const TPM_AUTHDATA WELLKNOWN_SRK_AUTH = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+const TPM_AUTHDATA WELLKNOWN_AUTH = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-const TPM_AUTHDATA WELLKNOWN_OWNER_AUTH = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
struct vtpm_globals vtpm_globals = {
.tpm_fd = -1,
- .storage_key = TPM_KEY_INIT,
- .storage_key_handle = 0,
- .oiap = { .AuthHandle = 0 }
+ .oiap = { .AuthHandle = 0 },
+ .hw_locality = 0
};
static int tpm_entropy_source(void* dummy, unsigned char* data, size_t len, size_t* olen) {
@@ -247,42 +243,11 @@ abort_egress:
return status;
}
-static void init_storage_key(TPM_KEY* key) {
- key->ver.major = 1;
- key->ver.minor = 1;
- key->ver.revMajor = 0;
- key->ver.revMinor = 0;
-
- key->keyUsage = TPM_KEY_BIND;
- key->keyFlags = 0;
- key->authDataUsage = TPM_AUTH_ALWAYS;
-
- TPM_KEY_PARMS* p = &key->algorithmParms;
- p->algorithmID = TPM_ALG_RSA;
- p->encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;
- p->sigScheme = TPM_SS_NONE;
- p->parmSize = 12;
-
- TPM_RSA_KEY_PARMS* r = &p->parms.rsa;
- r->keyLength = RSA_KEY_SIZE;
- r->numPrimes = 2;
- r->exponentSize = 0;
- r->exponent = NULL;
-
- key->PCRInfoSize = 0;
- key->encDataSize = 0;
- key->encData = NULL;
-}
-
-static int parse_auth_string(char* authstr, BYTE* target, const TPM_AUTHDATA wellknown, int allowrandom) {
+static int parse_auth_string(char* authstr, BYTE* target) {
int rc;
/* well known owner auth */
if(!strcmp(authstr, "well-known")) {
- memcpy(target, wellknown, sizeof(TPM_AUTHDATA));
- }
- /* Create a randomly generated owner auth */
- else if(allowrandom && !strcmp(authstr, "random")) {
- return 1;
+ return 0;
}
/* owner auth is a raw hash */
else if(!strncmp(authstr, "hash:", 5)) {
@@ -318,12 +283,12 @@ int parse_cmdline_opts(int argc, char** argv, struct Opts* opts)
int i;
//Set defaults
- memcpy(vtpm_globals.owner_auth, WELLKNOWN_OWNER_AUTH, sizeof(TPM_AUTHDATA));
- memcpy(vtpm_globals.srk_auth, WELLKNOWN_SRK_AUTH, sizeof(TPM_AUTHDATA));
+ memcpy(vtpm_globals.owner_auth, WELLKNOWN_AUTH, sizeof(TPM_AUTHDATA));
+ memcpy(vtpm_globals.srk_auth, WELLKNOWN_AUTH, sizeof(TPM_AUTHDATA));
for(i = 1; i < argc; ++i) {
if(!strncmp(argv[i], "owner_auth:", 10)) {
- if((rc = parse_auth_string(argv[i] + 10, vtpm_globals.owner_auth, WELLKNOWN_OWNER_AUTH, 1)) < 0) {
+ if((rc = parse_auth_string(argv[i] + 10, vtpm_globals.owner_auth)) < 0) {
goto err_invalid;
}
if(rc == 1) {
@@ -331,7 +296,7 @@ int parse_cmdline_opts(int argc, char** argv, struct Opts* opts)
}
}
else if(!strncmp(argv[i], "srk_auth:", 8)) {
- if((rc = parse_auth_string(argv[i] + 8, vtpm_globals.srk_auth, WELLKNOWN_SRK_AUTH, 0)) != 0) {
+ if((rc = parse_auth_string(argv[i] + 8, vtpm_globals.srk_auth)) != 0) {
goto err_invalid;
}
}
@@ -389,8 +354,6 @@ static TPM_RESULT vtpmmgr_create(void) {
TPMTRYRETURN(try_take_ownership());
// Generate storage key's auth
- memset(&vtpm_globals.storage_key_usage_auth, 0, sizeof(TPM_AUTHDATA));
-
TPMTRYRETURN( TPM_OSAP(
TPM_ET_KEYHANDLE,
TPM_SRK_KEYHANDLE,
@@ -398,30 +361,11 @@ static TPM_RESULT vtpmmgr_create(void) {
&sharedsecret,
&osap) );
- init_storage_key(&vtpm_globals.storage_key);
-
- //initialize the storage key
- TPMTRYRETURN( TPM_CreateWrapKey(
- TPM_SRK_KEYHANDLE,
- (const TPM_AUTHDATA*)&sharedsecret,
- (const TPM_AUTHDATA*)&vtpm_globals.storage_key_usage_auth,
- (const TPM_AUTHDATA*)&vtpm_globals.storage_key_usage_auth,
- &vtpm_globals.storage_key,
- &osap) );
-
- //Load Storage Key
- TPMTRYRETURN( TPM_LoadKey(
- TPM_SRK_KEYHANDLE,
- &vtpm_globals.storage_key,
- &vtpm_globals.storage_key_handle,
- (const TPM_AUTHDATA*) &vtpm_globals.srk_auth,
- &vtpm_globals.oiap));
-
//Make sure TPM has commited changes
TPMTRYRETURN( TPM_SaveState() );
//Create new disk image
- TPMTRYRETURN(vtpm_storage_new_header());
+ TPMTRYRETURN(vtpm_new_disk());
goto egress;
abort_egress:
@@ -436,10 +380,23 @@ egress:
return status;
}
-/* Set up the opaque field to contain a pointer to the UUID */
-static void set_opaque_to_uuid(domid_t domid, unsigned int handle)
+static void set_opaque(domid_t domid, unsigned int handle)
+{
+ struct tpm_opaque* opq;
+
+ opq = calloc(1, sizeof(*opq));
+ opq->uuid = (uuid_t*)tpmback_get_uuid(domid, handle);
+ opq->domid = domid;
+ opq->handle = handle;
+ tpmback_set_opaque(domid, handle, opq);
+}
+
+static void free_opaque(domid_t domid, unsigned int handle)
{
- tpmback_set_opaque(domid, handle, tpmback_get_uuid(domid, handle));
+ struct tpm_opaque* opq = tpmback_get_opaque(domid, handle);
+ if (opq && opq->vtpm)
+ opq->vtpm->flags &= ~VTPM_FLAG_OPEN;
+ free(opq);
}
TPM_RESULT vtpmmgr_init(int argc, char** argv) {
@@ -468,7 +425,7 @@ TPM_RESULT vtpmmgr_init(int argc, char** argv) {
}
//Setup tpmback device
- init_tpmback(set_opaque_to_uuid, NULL);
+ init_tpmback(set_opaque, free_opaque);
//Setup tpm access
switch(opts.tpmdriver) {
@@ -482,6 +439,7 @@ TPM_RESULT vtpmmgr_init(int argc, char** argv) {
}
vtpm_globals.tpm_fd = tpm_tis_open(tpm);
tpm_tis_request_locality(tpm, opts.tpmlocality);
+ vtpm_globals.hw_locality = opts.tpmlocality;
}
break;
case TPMDRV_TPMFRONT:
@@ -521,7 +479,8 @@ TPM_RESULT vtpmmgr_init(int argc, char** argv) {
TPMTRYRETURN( TPM_OIAP(&vtpm_globals.oiap) );
/* Load the Manager data, if it fails create a new manager */
- if (vtpm_storage_load_header() != TPM_SUCCESS) {
+ // TODO handle upgrade recovery of auth0
+ if (vtpm_load_disk()) {
/* If the OIAP session was closed by an error, create a new one */
if(vtpm_globals.oiap.AuthHandle == 0) {
TPMTRYRETURN( TPM_OIAP(&vtpm_globals.oiap) );
@@ -539,19 +498,12 @@ egress:
void vtpmmgr_shutdown(void)
{
- /* Cleanup resources */
- free_TPM_KEY(&vtpm_globals.storage_key);
-
/* Cleanup TPM resources */
- TPM_EvictKey(vtpm_globals.storage_key_handle);
TPM_TerminateHandle(vtpm_globals.oiap.AuthHandle);
/* Close tpmback */
shutdown_tpmback();
- /* Close the storage system and blkfront */
- vtpm_storage_shutdown();
-
/* Close tpmfront/tpm_tis */
close(vtpm_globals.tpm_fd);
diff --git a/stubdom/vtpmmgr/log.h b/stubdom/vtpmmgr/log.h
index 5c7abf5..455219f 100644
--- a/stubdom/vtpmmgr/log.h
+++ b/stubdom/vtpmmgr/log.h
@@ -64,18 +64,20 @@ extern char *module_names[];
#define SETBIT(num,idx) (num) |= BITMASK(idx)
#define CLEARBIT(num,idx) (num) &= ( ~ BITMASK(idx) )
+void printk(const char *fmt, ...);
+
#define vtpmloginfo(module, fmt, args...) \
if (GETBIT (LOGGING_MODULES, module) == 1) { \
- fprintf (stdout, "INFO[%s]: " fmt, module_names[module], ##args); \
+ printk("INFO[%s]: " fmt, module_names[module], ##args); \
}
#define vtpmloginfomore(module, fmt, args...) \
if (GETBIT (LOGGING_MODULES, module) == 1) { \
- fprintf (stdout, fmt,##args); \
+ printk(fmt,##args); \
}
#define vtpmlogerror(module, fmt, args...) \
- fprintf (stderr, "ERROR[%s]: " fmt, module_names[module], ##args);
+ printk("ERROR[%s]: " fmt, module_names[module], ##args);
//typedef UINT32 tpm_size_t;
diff --git a/stubdom/vtpmmgr/manage-vtpmmgr.pl b/stubdom/vtpmmgr/manage-vtpmmgr.pl
new file mode 100755
index 0000000..caf4f02
--- /dev/null
+++ b/stubdom/vtpmmgr/manage-vtpmmgr.pl
@@ -0,0 +1,160 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Digest::SHA;
+
+# The /dev/tpm0 device can only be opened by one application at a time, so if
+# the trousers daemon is running, this script will fail.
+system "killall tcsd 2>/dev/null";
+open my $tpm, '+>', '/dev/tpm0' or die "Could not open /dev/tpm0: $!";
+
+sub tpm_cmd_raw {
+ my $msg = join '', @_;
+ my $rsp;
+ print '<<', unpack('H*', $msg), "\n" if $ENV{V};
+ syswrite $tpm, $msg;
+ sysread $tpm, $rsp, 4096;
+ print '>>', unpack('H*', $rsp), "\n" if $ENV{V};
+ $rsp;
+}
+
+sub tpm_cmd_nohdr {
+ my($type, $msg) = @_;
+ my $head = pack 'nN', $type, 6 + length $msg;
+ my $rsp = tpm_cmd_raw $head, $msg;
+ my($rtype, $len, $stat, $reply) = unpack 'nNNa*', $rsp;
+ die "incomplete response" if $len != 10 + length $reply;
+ if ($stat) {
+ print "TPM error: $stat\n";
+ exit 1;
+ }
+ $reply;
+}
+
+sub cmd_list_group {
+ my $group = shift;
+ my($uuid, $pubk, $cfg_list) = unpack 'H32 a256 a*', tpm_cmd_nohdr 0x1C2,
+ pack 'NN', 0x02000107, $group;
+ $uuid = join "-", unpack 'a8a4a4a4a12', $uuid;
+ my $pk_hash = Digest::SHA::sha1_hex($pubk);
+ my $cfg_hash = Digest::SHA::sha1_hex($cfg_list);
+ my($seq, @cfgs) = unpack 'Q> N/(H40) a*', $cfg_list;
+ my @kerns = unpack "N/(H40)", pop @cfgs;
+ print "Group $group ($uuid):\n";
+ print " Public key hash: $pk_hash\n";
+ print " Boot config #$seq ($cfg_hash)\n";
+ print " Platforms:\n";
+ print " $_\n" for @cfgs;
+ print " Kernels:\n";
+ print " $_\n" for @kerns;
+ print " VTPMs:\n";
+
+ my($nr, @vtpms) = unpack 'N(H32)*', tpm_cmd_nohdr 0x1C2, pack 'NNN', 0x02000201, $group, 0;
+ if ($nr > @vtpms) {
+ print " TODO this list is cropped; needs multiple requests\n";
+ }
+ @vtpms = () if $nr == 0; # unpack returns an empty string in this case
+ @vtpms = map { join "-", unpack 'a8a4a4a4a12', $_ } @vtpms;
+ print " $_\n" for @vtpms;
+}
+
+sub cmd_list {
+ if (@_) {
+ cmd_list_group $_[0];
+ } else {
+ my $nr = unpack 'N', tpm_cmd_nohdr 0x1C2, pack 'N', 0x02000101;
+ cmd_list_group $_ for (0..($nr - 1));
+ }
+}
+
+sub cmd_group_add {
+ my $rsa_modfile = shift;
+ my $ca_digest = "\0"x20;
+ open MOD, $rsa_modfile or die $!;
+ my $group_pubkey = join '', <MOD>;
+ close MOD;
+
+ my($uuid, $pubkey, $pksig) = unpack 'H32 a256 a*', tpm_cmd_nohdr 0x1C2, pack 'N(a*)*',
+ 0x02000102, $ca_digest, $group_pubkey;
+ $uuid = join "-", unpack 'a8a4a4a4a12', $uuid;
+ print "$uuid\n";
+ mkdir "group-$uuid";
+ open F, ">group-$uuid/aik.pub";
+ print F $pubkey;
+ close F;
+ open F, ">group-$uuid/aik.priv-ca-data";
+ print F $pksig;
+ close F;
+
+ # TODO certify the AIK using the pTPM's EK (privacy CA)
+ # TODO escrow the recovery key for this group
+}
+
+sub cmd_group_del {
+ my $nr = shift;
+ tpm_cmd_nohdr 0x1C2, pack 'NN', 0x02000103, $nr;
+}
+
+sub cmd_group_update {
+ my $nr = shift;
+ open my $fh, '<', shift;
+ my $cmd = join '', <$fh>;
+ close $fh;
+
+ tpm_cmd_nohdr 0x1C2, pack 'NNa*', 0x02000106, $nr, $cmd;
+}
+
+sub cmd_vtpm_add {
+ my($group,$uuid) = @_;
+ if ($uuid) {
+ $uuid =~ s/-//g;
+ $uuid = pack('H32', $uuid)."\0";
+ } else {
+ $uuid = '';
+ }
+ $uuid = unpack 'H32', tpm_cmd_nohdr 0x1C2, pack 'NNa*', 0x02000204, $group, $uuid;
+ printf "%s\n", join "-", unpack 'a8a4a4a4a12', $uuid;
+}
+
+sub cmd_vtpm_del {
+ my($uuid) = @_;
+ $uuid =~ s/-//g;
+ tpm_cmd_nohdr 0x1C2, pack 'NH32', 0x02000205, $uuid;
+}
+
+sub cmd_help {
+ print <<EOH;
+Usage: $0 <command> <args>
+
+list [index]
+ Lists the group identified by index, or all groups if omitted
+
+group-add rsa-modulus-file
+ Adds a new group to the TPM. The public key and Privacy CA data are
+ output to group-UUID/aik.pub and group-UUID/aik.priv-ca-data, and the
+ UUID is output to stdout.
+
+group-update index signed-config-list-file
+ Updates the permitted boot configuration list for an group
+
+group-del index
+ Deletes a group
+
+vtpm-add index
+ Adds a vTPM. Output: UUID
+
+vtpm-del UUID
+ Deletes a vTPM.
+
+EOH
+}
+
+my $cmd = shift || 'help';
+$cmd =~ s/-/_/g;
+my $fn = $main::{"cmd_$cmd"};
+if ($fn) {
+ $fn->(@ARGV);
+} else {
+ print "Unknown command: $cmd\n";
+ exit 1;
+}
diff --git a/stubdom/vtpmmgr/marshal.h b/stubdom/vtpmmgr/marshal.h
index 77d32f0..bcc7c46 100644
--- a/stubdom/vtpmmgr/marshal.h
+++ b/stubdom/vtpmmgr/marshal.h
@@ -43,79 +43,81 @@
#include "tcg.h"
typedef enum UnpackPtr {
- UNPACK_ALIAS,
- UNPACK_ALLOC
+ UNPACK_ALIAS,
+ UNPACK_ALLOC
} UnpackPtr;
inline BYTE* pack_BYTE(BYTE* ptr, BYTE t) {
- ptr[0] = t;
- return ++ptr;
+ ptr[0] = t;
+ return ++ptr;
}
inline BYTE* unpack_BYTE(BYTE* ptr, BYTE* t) {
- t[0] = ptr[0];
- return ++ptr;
+ t[0] = ptr[0];
+ return ++ptr;
}
+inline int unpack3_BYTE(BYTE* ptr, UINT32* pos, UINT32 max, BYTE *t)
+{
+ if (*pos + 1 > max)
+ return TPM_SIZE;
+ unpack_BYTE(ptr + *pos, t);
+ *pos += 1;
+ return 0;
+}
+
+
#define pack_BOOL(p, t) pack_BYTE(p, t)
#define unpack_BOOL(p, t) unpack_BYTE(p, t)
+#define unpack3_BOOL(p, x, m, t) unpack3_BYTE(p, x, m, t)
+#define sizeof_BOOL(t) 1
-inline BYTE* pack_UINT16(BYTE* ptr, UINT16 t) {
- BYTE* b = (BYTE*)&t;
-#if __BYTE_ORDER == __LITTLE_ENDIAN
- ptr[0] = b[1];
- ptr[1] = b[0];
-#elif __BYTE_ORDER == __BIG_ENDIAN
- ptr[0] = b[0];
- ptr[1] = b[1];
-#endif
- return ptr + sizeof(UINT16);
+inline BYTE* pack_UINT16(void* ptr, UINT16 t) {
+ UINT16* p = ptr;
+ *p = cpu_to_be16(t);
+ return ptr + sizeof(UINT16);
}
-inline BYTE* unpack_UINT16(BYTE* ptr, UINT16* t) {
- BYTE* b = (BYTE*)t;
-#if __BYTE_ORDER == __LITTLE_ENDIAN
- b[0] = ptr[1];
- b[1] = ptr[0];
-#elif __BYTE_ORDER == __BIG_ENDIAN
- b[0] = ptr[0];
- b[1] = ptr[1];
-#endif
- return ptr + sizeof(UINT16);
-}
-
-inline BYTE* pack_UINT32(BYTE* ptr, UINT32 t) {
- BYTE* b = (BYTE*)&t;
-#if __BYTE_ORDER == __LITTLE_ENDIAN
- ptr[3] = b[0];
- ptr[2] = b[1];
- ptr[1] = b[2];
- ptr[0] = b[3];
-#elif __BYTE_ORDER == __BIG_ENDIAN
- ptr[0] = b[0];
- ptr[1] = b[1];
- ptr[2] = b[2];
- ptr[3] = b[3];
-#endif
- return ptr + sizeof(UINT32);
-}
-
-inline BYTE* unpack_UINT32(BYTE* ptr, UINT32* t) {
- BYTE* b = (BYTE*)t;
-#if __BYTE_ORDER == __LITTLE_ENDIAN
- b[0] = ptr[3];
- b[1] = ptr[2];
- b[2] = ptr[1];
- b[3] = ptr[0];
-#elif __BYTE_ORDER == __BIG_ENDIAN
- b[0] = ptr[0];
- b[1] = ptr[1];
- b[2] = ptr[2];
- b[3] = ptr[3];
-#endif
- return ptr + sizeof(UINT32);
+inline BYTE* unpack_UINT16(void* ptr, UINT16* t) {
+ UINT16* p = ptr;
+ *t = be16_to_cpu(*p);
+ return ptr + sizeof(UINT16);
+}
+
+inline int unpack3_UINT16(BYTE* ptr, UINT32* pos, UINT32 max, UINT16 *t)
+{
+ if (*pos + 2 > max)
+ return TPM_SIZE;
+ unpack_UINT16(ptr + *pos, t);
+ *pos += 2;
+ return 0;
+}
+
+inline BYTE* pack_UINT32(void* ptr, UINT32 t) {
+ UINT32* p = ptr;
+ *p = cpu_to_be32(t);
+ return ptr + sizeof(UINT32);
+}
+
+inline BYTE* unpack_UINT32(void* ptr, UINT32* t) {
+ UINT32* p = ptr;
+ *t = be32_to_cpu(*p);
+ return ptr + sizeof(UINT32);
+}
+
+inline int unpack3_UINT32(BYTE* ptr, UINT32* pos, UINT32 max, UINT32 *t)
+{
+ if (*pos + 4 > max)
+ return TPM_SIZE;
+ unpack_UINT32(ptr + *pos, t);
+ *pos += 4;
+ return 0;
}
+#define sizeof_BYTE(x) 1
+#define sizeof_UINT16(x) 2
+#define sizeof_UINT32(x) 4
+
#define pack_TPM_RESULT(p, t) pack_UINT32(p, t)
#define pack_TPM_PCRINDEX(p, t) pack_UINT32(p, t)
#define pack_TPM_DIRINDEX(p, t) pack_UINT32(p, t)
@@ -140,6 +142,7 @@ inline BYTE* unpack_UINT32(BYTE* ptr, UINT32* t) {
#define pack_TPM_MIGRATE_SCHEME(p, t) pack_UINT16(p, t)
#define pack_TPM_PHYSICAL_PRESENCE(p, t) pack_UINT16(p, t)
#define pack_TPM_KEY_FLAGS(p, t) pack_UINT32(p, t)
+#define pack_TPM_LOCALITY_SELECTION(p, t) pack_BYTE(p, t)
#define unpack_TPM_RESULT(p, t) unpack_UINT32(p, t)
#define unpack_TPM_PCRINDEX(p, t) unpack_UINT32(p, t)
@@ -165,56 +168,143 @@ inline BYTE* unpack_UINT32(BYTE* ptr, UINT32* t) {
#define unpack_TPM_MIGRATE_SCHEME(p, t) unpack_UINT16(p, t)
#define unpack_TPM_PHYSICAL_PRESENCE(p, t) unpack_UINT16(p, t)
#define unpack_TPM_KEY_FLAGS(p, t) unpack_UINT32(p, t)
+#define unpack_TPM_LOCALITY_SELECTION(p, t) unpack_BYTE(p, t)
+
+#define unpack3_TPM_RESULT(p, l, m, t) unpack3_UINT32(p, l, m, t)
+#define unpack3_TPM_PCRINDEX(p, l, m, t) unpack3_UINT32(p, l, m, t)
+#define unpack3_TPM_DIRINDEX(p, l, m, t) unpack3_UINT32(p, l, m, t)
+#define unpack3_TPM_HANDLE(p, l, m, t) unpack3_UINT32(p, l, m, t)
+#define unpack3_TPM_AUTHHANDLE(p, l, m, t) unpack3_TPM_HANDLE(p, l, m, t)
+#define unpack3_TCPA_HASHHANDLE(p, l, m, t) unpack3_TPM_HANDLE(p, l, m, t)
+#define unpack3_TCPA_HMACHANDLE(p, l, m, t) unpack3_TPM_HANDLE(p, l, m, t)
+#define unpack3_TCPA_ENCHANDLE(p, l, m, t) unpack3_TPM_HANDLE(p, l, m, t)
+#define unpack3_TPM_KEY_HANDLE(p, l, m, t) unpack3_TPM_HANDLE(p, l, m, t)
+#define unpack3_TCPA_ENTITYHANDLE(p, l, m, t) unpack3_TPM_HANDLE(p, l, m, t)
+#define unpack3_TPM_RESOURCE_TYPE(p, l, m, t) unpack3_UINT32(p, l, m, t)
+#define unpack3_TPM_COMMAND_CODE(p, l, m, t) unpack3_UINT32(p, l, m, t)
+#define unpack3_TPM_PROTOCOL_ID(p, l, m, t) unpack3_UINT16(p, l, m, t)
+#define unpack3_TPM_AUTH_DATA_USAGE(p, l, m, t) unpack3_BYTE(p, l, m, t)
+#define unpack3_TPM_ENTITY_TYPE(p, l, m, t) unpack3_UINT16(p, l, m, t)
+#define unpack3_TPM_ALGORITHM_ID(p, l, m, t) unpack3_UINT32(p, l, m, t)
+#define unpack3_TPM_KEY_USAGE(p, l, m, t) unpack3_UINT16(p, l, m, t)
+#define unpack3_TPM_STARTUP_TYPE(p, l, m, t) unpack3_UINT16(p, l, m, t)
+#define unpack3_TPM_CAPABILITY_AREA(p, l, m, t) unpack3_UINT32(p, l, m, t)
+#define unpack3_TPM_ENC_SCHEME(p, l, m, t) unpack3_UINT16(p, l, m, t)
+#define unpack3_TPM_SIG_SCHEME(p, l, m, t) unpack3_UINT16(p, l, m, t)
+#define unpack3_TPM_MIGRATE_SCHEME(p, l, m, t) unpack3_UINT16(p, l, m, t)
+#define unpack3_TPM_PHYSICAL_PRESENCE(p, l, m, t) unpack3_UINT16(p, l, m, t)
+#define unpack3_TPM_KEY_FLAGS(p, l, m, t) unpack3_UINT32(p, l, m, t)
+#define unpack3_TPM_LOCALITY_SELECTION(p, l, m, t) unpack3_BYTE(p, l, m, t)
+
+#define sizeof_TPM_RESULT(t) sizeof_UINT32(t)
+#define sizeof_TPM_PCRINDEX(t) sizeof_UINT32(t)
+#define sizeof_TPM_DIRINDEX(t) sizeof_UINT32(t)
+#define sizeof_TPM_HANDLE(t) sizeof_UINT32(t)
+#define sizeof_TPM_AUTHHANDLE(t) sizeof_TPM_HANDLE(t)
+#define sizeof_TCPA_HASHHANDLE(t) sizeof_TPM_HANDLE(t)
+#define sizeof_TCPA_HMACHANDLE(t) sizeof_TPM_HANDLE(t)
+#define sizeof_TCPA_ENCHANDLE(t) sizeof_TPM_HANDLE(t)
+#define sizeof_TPM_KEY_HANDLE(t) sizeof_TPM_HANDLE(t)
+#define sizeof_TCPA_ENTITYHANDLE(t) sizeof_TPM_HANDLE(t)
+#define sizeof_TPM_RESOURCE_TYPE(t) sizeof_UINT32(t)
+#define sizeof_TPM_COMMAND_CODE(t) sizeof_UINT32(t)
+#define sizeof_TPM_PROTOCOL_ID(t) sizeof_UINT16(t)
+#define sizeof_TPM_AUTH_DATA_USAGE(t) sizeof_BYTE(t)
+#define sizeof_TPM_ENTITY_TYPE(t) sizeof_UINT16(t)
+#define sizeof_TPM_ALGORITHM_ID(t) sizeof_UINT32(t)
+#define sizeof_TPM_KEY_USAGE(t) sizeof_UINT16(t)
+#define sizeof_TPM_STARTUP_TYPE(t) sizeof_UINT16(t)
+#define sizeof_TPM_CAPABILITY_AREA(t) sizeof_UINT32(t)
+#define sizeof_TPM_ENC_SCHEME(t) sizeof_UINT16(t)
+#define sizeof_TPM_SIG_SCHEME(t) sizeof_UINT16(t)
+#define sizeof_TPM_MIGRATE_SCHEME(t) sizeof_UINT16(t)
+#define sizeof_TPM_PHYSICAL_PRESENCE(t) sizeof_UINT16(t)
+#define sizeof_TPM_KEY_FLAGS(t) sizeof_UINT32(t)
+#define sizeof_TPM_LOCALITY_SELECTION(t) sizeof_BYTE(t)
+
+#define pack_TPM_AUTH_HANDLE(p, t) pack_UINT32(p, t)
+#define pack_TCS_CONTEXT_HANDLE(p, t) pack_UINT32(p, t)
+#define pack_TCS_KEY_HANDLE(p, t) pack_UINT32(p, t)
+
+#define unpack_TPM_AUTH_HANDLE(p, t) unpack_UINT32(p, t)
+#define unpack_TCS_CONTEXT_HANDLE(p, t) unpack_UINT32(p, t)
+#define unpack_TCS_KEY_HANDLE(p, t) unpack_UINT32(p, t)
+
+#define sizeof_TPM_AUTH_HANDLE(t) sizeof_UINT32(t)
+#define sizeof_TCS_CONTEXT_HANDLE(t) sizeof_UINT32(t)
+#define sizeof_TCS_KEY_HANDLE(t) sizeof_UINT32(t)
-#define pack_TPM_AUTH_HANDLE(p, t) pack_UINT32(p, t);
-#define pack_TCS_CONTEXT_HANDLE(p, t) pack_UINT32(p, t);
-#define pack_TCS_KEY_HANDLE(p, t) pack_UINT32(p, t);
-
-#define unpack_TPM_AUTH_HANDLE(p, t) unpack_UINT32(p, t);
-#define unpack_TCS_CONTEXT_HANDLE(p, t) unpack_UINT32(p, t);
-#define unpack_TCS_KEY_HANDLE(p, t) unpack_UINT32(p, t);
inline BYTE* pack_BUFFER(BYTE* ptr, const BYTE* buf, UINT32 size) {
- memcpy(ptr, buf, size);
- return ptr + size;
+ memcpy(ptr, buf, size);
+ return ptr + size;
}
inline BYTE* unpack_BUFFER(BYTE* ptr, BYTE* buf, UINT32 size) {
- memcpy(buf, ptr, size);
- return ptr + size;
+ memcpy(buf, ptr, size);
+ return ptr + size;
}
+inline int unpack3_BUFFER(BYTE* ptr, UINT32* pos, UINT32 max, BYTE* buf, UINT32 size) {
+ if (*pos + size > max)
+ return TPM_SIZE;
+ memcpy(buf, ptr + *pos, size);
+ *pos += size;
+ return 0;
+}
+
+#define sizeof_BUFFER(b, s) s
+
inline BYTE* unpack_ALIAS(BYTE* ptr, BYTE** buf, UINT32 size) {
- *buf = ptr;
- return ptr + size;
+ *buf = ptr;
+ return ptr + size;
}
inline BYTE* unpack_ALLOC(BYTE* ptr, BYTE** buf, UINT32 size) {
- if(size) {
- *buf = malloc(size);
- memcpy(*buf, ptr, size);
- } else {
- *buf = NULL;
- }
- return ptr + size;
+ if(size) {
+ *buf = malloc(size);
+ memcpy(*buf, ptr, size);
+ } else {
+ *buf = NULL;
+ }
+ return ptr + size;
}
inline BYTE* unpack_PTR(BYTE* ptr, BYTE** buf, UINT32 size, UnpackPtr alloc) {
- if(alloc == UNPACK_ALLOC) {
- return unpack_ALLOC(ptr, buf, size);
- } else {
- return unpack_ALIAS(ptr, buf, size);
- }
-}
+ if(alloc == UNPACK_ALLOC) {
+ return unpack_ALLOC(ptr, buf, size);
+ } else {
+ return unpack_ALIAS(ptr, buf, size);
+ }
+}
+
+inline int unpack3_PTR(BYTE* ptr, UINT32* pos, UINT32 max, BYTE** buf, UINT32 size, UnpackPtr alloc) {
+ if (size > max || *pos + size > max)
+ return TPM_SIZE;
+ if (alloc == UNPACK_ALLOC) {
+ unpack_ALLOC(ptr + *pos, buf, size);
+ } else {
+ unpack_ALIAS(ptr + *pos, buf, size);
+ }
+ *pos += size;
+ return 0;
+}
+#define unpack3_VPTR(ptr, pos, max, buf, size, alloc) unpack3_PTR(ptr, pos, max, (void*)(buf), size, alloc)
inline BYTE* pack_TPM_AUTHDATA(BYTE* ptr, const TPM_AUTHDATA* d) {
- return pack_BUFFER(ptr, *d, TPM_DIGEST_SIZE);
+ return pack_BUFFER(ptr, *d, TPM_DIGEST_SIZE);
}
inline BYTE* unpack_TPM_AUTHDATA(BYTE* ptr, TPM_AUTHDATA* d) {
- return unpack_BUFFER(ptr, *d, TPM_DIGEST_SIZE);
+ return unpack_BUFFER(ptr, *d, TPM_DIGEST_SIZE);
}
+inline int unpack3_TPM_AUTHDATA(BYTE* ptr, UINT32* pos, UINT32 len, TPM_AUTHDATA* d) {
+ return unpack3_BUFFER(ptr, pos, len, *d, TPM_DIGEST_SIZE);
+}
+
+#define sizeof_TPM_AUTHDATA(d) TPM_DIGEST_SIZE
+
#define pack_TPM_SECRET(p, t) pack_TPM_AUTHDATA(p, t)
#define pack_TPM_ENCAUTH(p, t) pack_TPM_AUTHDATA(p, t)
#define pack_TPM_PAYLOAD_TYPE(p, t) pack_BYTE(p, t)
@@ -226,303 +316,535 @@ inline BYTE* unpack_TPM_AUTHDATA(BYTE* ptr, TPM_AUTHDATA* d) {
#define unpack_TPM_PAYLOAD_TYPE(p, t) unpack_BYTE(p, t)
#define unpack_TPM_TAG(p, t) unpack_UINT16(p, t)
#define unpack_TPM_STRUCTURE_TAG(p, t) unpack_UINT16(p, t)
+#define unpack3_TPM_STRUCTURE_TAG(p, l, m, t) unpack3_UINT16(p, l, m, t)
+
+#define sizeof_TPM_SECRET(t) sizeof_TPM_AUTHDATA(t)
+#define sizeof_TPM_ENCAUTH(t) sizeof_TPM_AUTHDATA(t)
+#define sizeof_TPM_PAYLOAD_TYPE(t) sizeof_BYTE(t)
+#define sizeof_TPM_TAG(t) sizeof_UINT16(t)
+#define sizeof_TPM_STRUCTURE_TAG(t) sizeof_UINT16(t)
inline BYTE* pack_TPM_VERSION(BYTE* ptr, const TPM_VERSION* t) {
- ptr[0] = t->major;
- ptr[1] = t->minor;
- ptr[2] = t->revMajor;
- ptr[3] = t->revMinor;
- return ptr + 4;
+ ptr[0] = t->major;
+ ptr[1] = t->minor;
+ ptr[2] = t->revMajor;
+ ptr[3] = t->revMinor;
+ return ptr + 4;
}
inline BYTE* unpack_TPM_VERSION(BYTE* ptr, TPM_VERSION* t) {
- t->major = ptr[0];
- t->minor = ptr[1];
- t->revMajor = ptr[2];
- t->revMinor = ptr[3];
- return ptr + 4;
+ t->major = ptr[0];
+ t->minor = ptr[1];
+ t->revMajor = ptr[2];
+ t->revMinor = ptr[3];
+ return ptr + 4;
}
+inline int unpack3_TPM_VERSION(BYTE* ptr, UINT32 *pos, UINT32 max, TPM_VERSION* t) {
+ if (*pos + 4 > max)
+ return TPM_SIZE;
+ ptr += *pos;
+ t->major = ptr[0];
+ t->minor = ptr[1];
+ t->revMajor = ptr[2];
+ t->revMinor = ptr[3];
+ *pos += 4;
+ return 0;
+}
+
+#define sizeof_TPM_VERSION(x) 4
+
inline BYTE* pack_TPM_CAP_VERSION_INFO(BYTE* ptr, const TPM_CAP_VERSION_INFO* v) {
- ptr = pack_TPM_STRUCTURE_TAG(ptr, v->tag);
- ptr = pack_TPM_VERSION(ptr, &v->version);
- ptr = pack_UINT16(ptr, v->specLevel);
- ptr = pack_BYTE(ptr, v->errataRev);
- ptr = pack_BUFFER(ptr, v->tpmVendorID, sizeof(v->tpmVendorID));
- ptr = pack_UINT16(ptr, v->vendorSpecificSize);
- ptr = pack_BUFFER(ptr, v->vendorSpecific, v->vendorSpecificSize);
- return ptr;
+ ptr = pack_TPM_STRUCTURE_TAG(ptr, v->tag);
+ ptr = pack_TPM_VERSION(ptr, &v->version);
+ ptr = pack_UINT16(ptr, v->specLevel);
+ ptr = pack_BYTE(ptr, v->errataRev);
+ ptr = pack_BUFFER(ptr, v->tpmVendorID, sizeof(v->tpmVendorID));
+ ptr = pack_UINT16(ptr, v->vendorSpecificSize);
+ ptr = pack_BUFFER(ptr, v->vendorSpecific, v->vendorSpecificSize);
+ return ptr;
}
inline BYTE* unpack_TPM_CAP_VERSION_INFO(BYTE* ptr, TPM_CAP_VERSION_INFO* v, UnpackPtr alloc) {
- ptr = unpack_TPM_STRUCTURE_TAG(ptr, &v->tag);
- ptr = unpack_TPM_VERSION(ptr, &v->version);
- ptr = unpack_UINT16(ptr, &v->specLevel);
- ptr = unpack_BYTE(ptr, &v->errataRev);
- ptr = unpack_BUFFER(ptr, v->tpmVendorID, sizeof(v->tpmVendorID));
- ptr = unpack_UINT16(ptr, &v->vendorSpecificSize);
- ptr = unpack_PTR(ptr, &v->vendorSpecific, v->vendorSpecificSize, alloc);
- return ptr;
+ ptr = unpack_TPM_STRUCTURE_TAG(ptr, &v->tag);
+ ptr = unpack_TPM_VERSION(ptr, &v->version);
+ ptr = unpack_UINT16(ptr, &v->specLevel);
+ ptr = unpack_BYTE(ptr, &v->errataRev);
+ ptr = unpack_BUFFER(ptr, v->tpmVendorID, sizeof(v->tpmVendorID));
+ ptr = unpack_UINT16(ptr, &v->vendorSpecificSize);
+ ptr = unpack_PTR(ptr, &v->vendorSpecific, v->vendorSpecificSize, alloc);
+ return ptr;
}
inline BYTE* pack_TPM_DIGEST(BYTE* ptr, const TPM_DIGEST* d) {
- return pack_BUFFER(ptr, d->digest, TPM_DIGEST_SIZE);
+ return pack_BUFFER(ptr, d->digest, TPM_DIGEST_SIZE);
}
inline BYTE* unpack_TPM_DIGEST(BYTE* ptr, TPM_DIGEST* d) {
- return unpack_BUFFER(ptr, d->digest, TPM_DIGEST_SIZE);
+ return unpack_BUFFER(ptr, d->digest, TPM_DIGEST_SIZE);
}
-#define pack_TPM_PCRVALUE(ptr, d) pack_TPM_DIGEST(ptr, d);
-#define unpack_TPM_PCRVALUE(ptr, d) unpack_TPM_DIGEST(ptr, d);
+inline int unpack3_TPM_DIGEST(BYTE* ptr, UINT32* pos, UINT32 max, TPM_DIGEST* d) {
+ return unpack3_BUFFER(ptr, pos, max, d->digest, TPM_DIGEST_SIZE);
+}
+
+#define sizeof_TPM_DIGEST(d) TPM_DIGEST_SIZE
-#define pack_TPM_COMPOSITE_HASH(ptr, d) pack_TPM_DIGEST(ptr, d);
-#define unpack_TPM_COMPOSITE_HASH(ptr, d) unpack_TPM_DIGEST(ptr, d);
+#define pack_TPM_PCRVALUE(ptr, d) pack_TPM_DIGEST(ptr, d)
+#define unpack_TPM_PCRVALUE(ptr, d) unpack_TPM_DIGEST(ptr, d)
+#define unpack3_TPM_PCRVALUE(p...) unpack3_TPM_DIGEST(p)
-#define pack_TPM_DIRVALUE(ptr, d) pack_TPM_DIGEST(ptr, d);
-#define unpack_TPM_DIRVALUE(ptr, d) unpack_TPM_DIGEST(ptr, d);
+#define pack_TPM_COMPOSITE_HASH(ptr, d) pack_TPM_DIGEST(ptr, d)
+#define unpack_TPM_COMPOSITE_HASH(ptr, d) unpack_TPM_DIGEST(ptr, d)
+#define unpack3_TPM_COMPOSITE_HASH(ptr, p, m, d) unpack3_TPM_DIGEST(ptr, p, m, d)
+#define sizeof_TPM_COMPOSITE_HASH(d) TPM_DIGEST_SIZE
-#define pack_TPM_HMAC(ptr, d) pack_TPM_DIGEST(ptr, d);
-#define unpack_TPM_HMAC(ptr, d) unpack_TPM_DIGEST(ptr, d);
+#define pack_TPM_DIRVALUE(ptr, d) pack_TPM_DIGEST(ptr, d)
+#define unpack_TPM_DIRVALUE(ptr, d) unpack_TPM_DIGEST(ptr, d)
-#define pack_TPM_CHOSENID_HASH(ptr, d) pack_TPM_DIGEST(ptr, d);
-#define unpack_TPM_CHOSENID_HASH(ptr, d) unpack_TPM_DIGEST(ptr, d);
+#define pack_TPM_HMAC(ptr, d) pack_TPM_DIGEST(ptr, d)
+#define unpack_TPM_HMAC(ptr, d) unpack_TPM_DIGEST(ptr, d)
+
+#define pack_TPM_CHOSENID_HASH(ptr, d) pack_TPM_DIGEST(ptr, d)
+#define unpack_TPM_CHOSENID_HASH(ptr, d) unpack_TPM_DIGEST(ptr, d)
inline BYTE* pack_TPM_NONCE(BYTE* ptr, const TPM_NONCE* n) {
- return pack_BUFFER(ptr, n->nonce, TPM_DIGEST_SIZE);
+ return pack_BUFFER(ptr, n->nonce, TPM_DIGEST_SIZE);
}
inline BYTE* unpack_TPM_NONCE(BYTE* ptr, TPM_NONCE* n) {
- return unpack_BUFFER(ptr, n->nonce, TPM_DIGEST_SIZE);
+ return unpack_BUFFER(ptr, n->nonce, TPM_DIGEST_SIZE);
+}
+
+#define sizeof_TPM_NONCE(x) TPM_DIGEST_SIZE
+
+inline int unpack3_TPM_NONCE(BYTE* ptr, UINT32* pos, UINT32 max, TPM_NONCE* n) {
+ return unpack3_BUFFER(ptr, pos, max, n->nonce, TPM_DIGEST_SIZE);
}
inline BYTE* pack_TPM_SYMMETRIC_KEY_PARMS(BYTE* ptr, const TPM_SYMMETRIC_KEY_PARMS* k) {
- ptr = pack_UINT32(ptr, k->keyLength);
- ptr = pack_UINT32(ptr, k->blockSize);
- ptr = pack_UINT32(ptr, k->ivSize);
- return pack_BUFFER(ptr, k->IV, k->ivSize);
+ ptr = pack_UINT32(ptr, k->keyLength);
+ ptr = pack_UINT32(ptr, k->blockSize);
+ ptr = pack_UINT32(ptr, k->ivSize);
+ return pack_BUFFER(ptr, k->IV, k->ivSize);
+}
+
+inline BYTE* pack_TPM_SYMMETRIC_KEY(BYTE* ptr, const TPM_SYMMETRIC_KEY* k) {
+ ptr = pack_UINT32(ptr, k->algId);
+ ptr = pack_UINT16(ptr, k->encScheme);
+ ptr = pack_UINT16(ptr, k->size);
+ return pack_BUFFER(ptr, k->data, k->size);
+}
+
+inline int unpack3_TPM_SYMMETRIC_KEY_PARMS(BYTE* ptr, UINT32* pos, UINT32 max, TPM_SYMMETRIC_KEY_PARMS* k, UnpackPtr alloc) {
+ return unpack3_UINT32(ptr, pos, max, &k->keyLength) ||
+ unpack3_UINT32(ptr, pos, max, &k->blockSize) ||
+ unpack3_UINT32(ptr, pos, max, &k->ivSize) ||
+ unpack3_PTR(ptr, pos, max, &k->IV, k->ivSize, alloc);
}
-inline BYTE* unpack_TPM_SYMMETRIC_KEY_PARMS(BYTE* ptr, TPM_SYMMETRIC_KEY_PARMS* k, UnpackPtr alloc) {
- ptr = unpack_UINT32(ptr, &k->keyLength);
- ptr = unpack_UINT32(ptr, &k->blockSize);
- ptr = unpack_UINT32(ptr, &k->ivSize);
- return unpack_PTR(ptr, &k->IV, k->ivSize, alloc);
+inline int sizeof_TPM_SYMMETRIC_KEY_PARMS(const TPM_SYMMETRIC_KEY_PARMS* k) {
+ return 12 + k->ivSize;
+}
+
+inline int unpack3_TPM_SYMMETRIC_KEY(BYTE* ptr, UINT32* pos, UINT32 max, TPM_SYMMETRIC_KEY* k, UnpackPtr alloc) {
+ return unpack3_UINT32(ptr, pos, max, &k->algId) ||
+ unpack3_UINT16(ptr, pos, max, &k->encScheme) ||
+ unpack3_UINT16(ptr, pos, max, &k->size) ||
+ unpack3_PTR(ptr, pos, max, &k->data, k->size, alloc);
}
inline BYTE* pack_TPM_RSA_KEY_PARMS(BYTE* ptr, const TPM_RSA_KEY_PARMS* k) {
- ptr = pack_UINT32(ptr, k->keyLength);
- ptr = pack_UINT32(ptr, k->numPrimes);
- ptr = pack_UINT32(ptr, k->exponentSize);
- return pack_BUFFER(ptr, k->exponent, k->exponentSize);
+ ptr = pack_UINT32(ptr, k->keyLength);
+ ptr = pack_UINT32(ptr, k->numPrimes);
+ ptr = pack_UINT32(ptr, k->exponentSize);
+ return pack_BUFFER(ptr, k->exponent, k->exponentSize);
+}
+
+inline int unpack3_TPM_RSA_KEY_PARMS(BYTE* ptr, UINT32* pos, UINT32 max, TPM_RSA_KEY_PARMS* k, UnpackPtr alloc) {
+ return unpack3_UINT32(ptr, pos, max, &k->keyLength) ||
+ unpack3_UINT32(ptr, pos, max, &k->numPrimes) ||
+ unpack3_UINT32(ptr, pos, max, &k->exponentSize) ||
+ unpack3_PTR(ptr, pos, max, &k->exponent, k->exponentSize, alloc);
}
-inline BYTE* unpack_TPM_RSA_KEY_PARMS(BYTE* ptr, TPM_RSA_KEY_PARMS* k, UnpackPtr alloc) {
- ptr = unpack_UINT32(ptr, &k->keyLength);
- ptr = unpack_UINT32(ptr, &k->numPrimes);
- ptr = unpack_UINT32(ptr, &k->exponentSize);
- return unpack_PTR(ptr, &k->exponent, k->exponentSize, alloc);
+inline int sizeof_TPM_RSA_KEY_PARMS(const TPM_RSA_KEY_PARMS* k) {
+ return 12 + k->exponentSize;
}
+
inline BYTE* pack_TPM_KEY_PARMS(BYTE* ptr, const TPM_KEY_PARMS* k) {
- ptr = pack_TPM_ALGORITHM_ID(ptr, k->algorithmID);
- ptr = pack_TPM_ENC_SCHEME(ptr, k->encScheme);
- ptr = pack_TPM_SIG_SCHEME(ptr, k->sigScheme);
- ptr = pack_UINT32(ptr, k->parmSize);
-
- if(k->parmSize) {
- switch(k->algorithmID) {
- case TPM_ALG_RSA:
- return pack_TPM_RSA_KEY_PARMS(ptr, &k->parms.rsa);
- case TPM_ALG_AES128:
- case TPM_ALG_AES192:
- case TPM_ALG_AES256:
- return pack_TPM_SYMMETRIC_KEY_PARMS(ptr, &k->parms.sym);
- }
- }
- return ptr;
-}
-
-inline BYTE* unpack_TPM_KEY_PARMS(BYTE* ptr, TPM_KEY_PARMS* k, UnpackPtr alloc) {
- ptr = unpack_TPM_ALGORITHM_ID(ptr, &k->algorithmID);
- ptr = unpack_TPM_ENC_SCHEME(ptr, &k->encScheme);
- ptr = unpack_TPM_SIG_SCHEME(ptr, &k->sigScheme);
- ptr = unpack_UINT32(ptr, &k->parmSize);
-
- if(k->parmSize) {
- switch(k->algorithmID) {
- case TPM_ALG_RSA:
- return unpack_TPM_RSA_KEY_PARMS(ptr, &k->parms.rsa, alloc);
- case TPM_ALG_AES128:
- case TPM_ALG_AES192:
- case TPM_ALG_AES256:
- return unpack_TPM_SYMMETRIC_KEY_PARMS(ptr, &k->parms.sym, alloc);
- }
- }
- return ptr;
+ ptr = pack_TPM_ALGORITHM_ID(ptr, k->algorithmID);
+ ptr = pack_TPM_ENC_SCHEME(ptr, k->encScheme);
+ ptr = pack_TPM_SIG_SCHEME(ptr, k->sigScheme);
+ ptr = pack_UINT32(ptr, k->parmSize);
+
+ if(k->parmSize) {
+ switch(k->algorithmID) {
+ case TPM_ALG_RSA:
+ return pack_TPM_RSA_KEY_PARMS(ptr, &k->parms.rsa);
+ case TPM_ALG_AES128:
+ case TPM_ALG_AES192:
+ case TPM_ALG_AES256:
+ return pack_TPM_SYMMETRIC_KEY_PARMS(ptr, &k->parms.sym);
+ }
+ }
+ return ptr;
+}
+
+inline int unpack3_TPM_KEY_PARMS(BYTE* ptr, UINT32* pos, UINT32 len, TPM_KEY_PARMS* k, UnpackPtr alloc) {
+ int rc = unpack3_TPM_ALGORITHM_ID(ptr, pos, len, &k->algorithmID) ||
+ unpack3_TPM_ENC_SCHEME(ptr, pos, len, &k->encScheme) ||
+ unpack3_TPM_SIG_SCHEME(ptr, pos, len, &k->sigScheme) ||
+ unpack3_UINT32(ptr, pos, len, &k->parmSize);
+ if (rc || k->parmSize == 0)
+ return rc;
+ switch(k->algorithmID) {
+ case TPM_ALG_RSA:
+ return unpack3_TPM_RSA_KEY_PARMS(ptr, pos, len, &k->parms.rsa, alloc);
+ case TPM_ALG_AES128:
+ case TPM_ALG_AES192:
+ case TPM_ALG_AES256:
+ return unpack3_TPM_SYMMETRIC_KEY_PARMS(ptr, pos, len, &k->parms.sym, alloc);
+ }
+ return TPM_FAIL;
+}
+
+inline int sizeof_TPM_KEY_PARMS(const TPM_KEY_PARMS* k) {
+ int rc = 0;
+ rc += sizeof_TPM_ALGORITHM_ID(&k->algorithmID);
+ rc += sizeof_TPM_ENC_SCHEME(&k->encScheme);
+ rc += sizeof_TPM_SIG_SCHEME(&k->sigScheme);
+ rc += sizeof_UINT32(&k->parmSize);
+ if (!k->parmSize)
+ return rc;
+ switch(k->algorithmID) {
+ case TPM_ALG_RSA:
+ rc += sizeof_TPM_RSA_KEY_PARMS(&k->parms.rsa);
+ break;
+ case TPM_ALG_AES128:
+ case TPM_ALG_AES192:
+ case TPM_ALG_AES256:
+ rc += sizeof_TPM_SYMMETRIC_KEY_PARMS(&k->parms.sym);
+ break;
+ }
+ return rc;
}
inline BYTE* pack_TPM_STORE_PUBKEY(BYTE* ptr, const TPM_STORE_PUBKEY* k) {
- ptr = pack_UINT32(ptr, k->keyLength);
- ptr = pack_BUFFER(ptr, k->key, k->keyLength);
- return ptr;
+ ptr = pack_UINT32(ptr, k->keyLength);
+ ptr = pack_BUFFER(ptr, k->key, k->keyLength);
+ return ptr;
+}
+
+inline int unpack3_TPM_STORE_PUBKEY(BYTE* ptr, UINT32* pos, UINT32 max, TPM_STORE_PUBKEY* k, UnpackPtr alloc) {
+ return unpack3_UINT32(ptr, pos, max, &k->keyLength) ||
+ unpack3_PTR(ptr, pos, max, &k->key, k->keyLength, alloc);
}
-inline BYTE* unpack_TPM_STORE_PUBKEY(BYTE* ptr, TPM_STORE_PUBKEY* k, UnpackPtr alloc) {
- ptr = unpack_UINT32(ptr, &k->keyLength);
- ptr = unpack_PTR(ptr, &k->key, k->keyLength, alloc);
- return ptr;
+inline int sizeof_TPM_STORE_PUBKEY(const TPM_STORE_PUBKEY* k) {
+ return 4 + k->keyLength;
}
inline BYTE* pack_TPM_PUBKEY(BYTE* ptr, const TPM_PUBKEY* k) {
- ptr = pack_TPM_KEY_PARMS(ptr, &k->algorithmParms);
- return pack_TPM_STORE_PUBKEY(ptr, &k->pubKey);
+ ptr = pack_TPM_KEY_PARMS(ptr, &k->algorithmParms);
+ return pack_TPM_STORE_PUBKEY(ptr, &k->pubKey);
}
-inline BYTE* unpack_TPM_PUBKEY(BYTE* ptr, TPM_PUBKEY* k, UnpackPtr alloc) {
- ptr = unpack_TPM_KEY_PARMS(ptr, &k->algorithmParms, alloc);
- return unpack_TPM_STORE_PUBKEY(ptr, &k->pubKey, alloc);
+inline int unpack3_TPM_PUBKEY(BYTE* ptr, UINT32* pos, UINT32 len, TPM_PUBKEY* k, UnpackPtr alloc) {
+ return unpack3_TPM_KEY_PARMS(ptr, pos, len, &k->algorithmParms, alloc) ||
+ unpack3_TPM_STORE_PUBKEY(ptr, pos, len, &k->pubKey, alloc);
}
inline BYTE* pack_TPM_PCR_SELECTION(BYTE* ptr, const TPM_PCR_SELECTION* p) {
- ptr = pack_UINT16(ptr, p->sizeOfSelect);
- ptr = pack_BUFFER(ptr, p->pcrSelect, p->sizeOfSelect);
- return ptr;
+ ptr = pack_UINT16(ptr, p->sizeOfSelect);
+ ptr = pack_BUFFER(ptr, p->pcrSelect, p->sizeOfSelect);
+ return ptr;
}
inline BYTE* unpack_TPM_PCR_SELECTION(BYTE* ptr, TPM_PCR_SELECTION* p, UnpackPtr alloc) {
- ptr = unpack_UINT16(ptr, &p->sizeOfSelect);
- ptr = unpack_PTR(ptr, &p->pcrSelect, p->sizeOfSelect, alloc);
- return ptr;
+ ptr = unpack_UINT16(ptr, &p->sizeOfSelect);
+ ptr = unpack_PTR(ptr, &p->pcrSelect, p->sizeOfSelect, alloc);
+ return ptr;
}
-inline BYTE* pack_TPM_PCR_INFO(BYTE* ptr, const TPM_PCR_INFO* p) {
- ptr = pack_TPM_PCR_SELECTION(ptr, &p->pcrSelection);
- ptr = pack_TPM_COMPOSITE_HASH(ptr, &p->digestAtRelease);
- ptr = pack_TPM_COMPOSITE_HASH(ptr, &p->digestAtCreation);
- return ptr;
+inline int unpack3_TPM_PCR_SELECTION(BYTE* ptr, UINT32* pos, UINT32 max, TPM_PCR_SELECTION* p, UnpackPtr alloc) {
+ return unpack3_UINT16(ptr, pos, max, &p->sizeOfSelect) ||
+ unpack3_PTR(ptr, pos, max, &p->pcrSelect, p->sizeOfSelect, alloc);
}
-inline BYTE* unpack_TPM_PCR_INFO(BYTE* ptr, TPM_PCR_INFO* p, UnpackPtr alloc) {
- ptr = unpack_TPM_PCR_SELECTION(ptr, &p->pcrSelection, alloc);
- ptr = unpack_TPM_COMPOSITE_HASH(ptr, &p->digestAtRelease);
- ptr = unpack_TPM_COMPOSITE_HASH(ptr, &p->digestAtCreation);
- return ptr;
+inline int sizeof_TPM_PCR_SELECTION(const TPM_PCR_SELECTION* p) {
+ return 2 + p->sizeOfSelect;
+}
+
+inline BYTE* pack_TPM_PCR_INFO(BYTE* ptr, const TPM_PCR_INFO* p) {
+ ptr = pack_TPM_PCR_SELECTION(ptr, &p->pcrSelection);
+ ptr = pack_TPM_COMPOSITE_HASH(ptr, &p->digestAtRelease);
+ ptr = pack_TPM_COMPOSITE_HASH(ptr, &p->digestAtCreation);
+ return ptr;
+}
+
+inline int unpack3_TPM_PCR_INFO(BYTE* ptr, UINT32* pos, UINT32 max, TPM_PCR_INFO* p, UnpackPtr alloc) {
+ return unpack3_TPM_PCR_SELECTION(ptr, pos, max, &p->pcrSelection, alloc) ||
+ unpack3_TPM_COMPOSITE_HASH(ptr, pos, max, &p->digestAtRelease) ||
+ unpack3_TPM_COMPOSITE_HASH(ptr, pos, max, &p->digestAtCreation);
+}
+
+inline int sizeof_TPM_PCR_INFO(const TPM_PCR_INFO* p) {
+ int rc = 0;
+ rc += sizeof_TPM_PCR_SELECTION(&p->pcrSelection);
+ rc += sizeof_TPM_COMPOSITE_HASH(&p->digestAtRelease);
+ rc += sizeof_TPM_COMPOSITE_HASH(&p->digestAtCreation);
+ return rc;
+}
+
+inline BYTE* pack_TPM_PCR_INFO_LONG(BYTE* ptr, const TPM_PCR_INFO_LONG* p) {
+ ptr = pack_TPM_STRUCTURE_TAG(ptr, p->tag);
+ ptr = pack_TPM_LOCALITY_SELECTION(ptr, p->localityAtCreation);
+ ptr = pack_TPM_LOCALITY_SELECTION(ptr, p->localityAtRelease);
+ ptr = pack_TPM_PCR_SELECTION(ptr, &p->creationPCRSelection);
+ ptr = pack_TPM_PCR_SELECTION(ptr, &p->releasePCRSelection);
+ ptr = pack_TPM_COMPOSITE_HASH(ptr, &p->digestAtCreation);
+ ptr = pack_TPM_COMPOSITE_HASH(ptr, &p->digestAtRelease);
+ return ptr;
+}
+
+inline int sizeof_TPM_PCR_INFO_LONG(const TPM_PCR_INFO_LONG* p) {
+ int rc = 0;
+ rc += sizeof_TPM_STRUCTURE_TAG(p->tag);
+ rc += sizeof_TPM_LOCALITY_SELECTION(p->localityAtCreation);
+ rc += sizeof_TPM_LOCALITY_SELECTION(p->localityAtRelease);
+ rc += sizeof_TPM_PCR_SELECTION(&p->creationPCRSelection);
+ rc += sizeof_TPM_PCR_SELECTION(&p->releasePCRSelection);
+ rc += sizeof_TPM_COMPOSITE_HASH(&p->digestAtCreation);
+ rc += sizeof_TPM_COMPOSITE_HASH(&p->digestAtRelease);
+ return rc;
+}
+
+inline int unpack3_TPM_PCR_INFO_LONG(BYTE* ptr, UINT32* pos, UINT32 max, TPM_PCR_INFO_LONG* p, UnpackPtr alloc) {
+ return unpack3_TPM_STRUCTURE_TAG(ptr, pos, max, &p->tag) ||
+ unpack3_TPM_LOCALITY_SELECTION(ptr, pos, max,
+ &p->localityAtCreation) ||
+ unpack3_TPM_LOCALITY_SELECTION(ptr, pos, max,
+ &p->localityAtRelease) ||
+ unpack3_TPM_PCR_SELECTION(ptr, pos, max,
+ &p->creationPCRSelection, alloc) ||
+ unpack3_TPM_PCR_SELECTION(ptr, pos, max,
+ &p->releasePCRSelection, alloc) ||
+ unpack3_TPM_COMPOSITE_HASH(ptr, pos, max,
+ &p->digestAtCreation) ||
+ unpack3_TPM_COMPOSITE_HASH(ptr, pos, max, &p->digestAtRelease);
}
inline BYTE* pack_TPM_PCR_COMPOSITE(BYTE* ptr, const TPM_PCR_COMPOSITE* p) {
- ptr = pack_TPM_PCR_SELECTION(ptr, &p->select);
- ptr = pack_UINT32(ptr, p->valueSize);
- ptr = pack_BUFFER(ptr, (const BYTE*)p->pcrValue, p->valueSize);
- return ptr;
+ ptr = pack_TPM_PCR_SELECTION(ptr, &p->select);
+ ptr = pack_UINT32(ptr, p->valueSize);
+ ptr = pack_BUFFER(ptr, (const BYTE*)p->pcrValue, p->valueSize);
+ return ptr;
}
-inline BYTE* unpack_TPM_PCR_COMPOSITE(BYTE* ptr, TPM_PCR_COMPOSITE* p, UnpackPtr alloc) {
- ptr = unpack_TPM_PCR_SELECTION(ptr, &p->select, alloc);
- ptr = unpack_UINT32(ptr, &p->valueSize);
- ptr = unpack_PTR(ptr, (BYTE**)&p->pcrValue, p->valueSize, alloc);
- return ptr;
+inline int unpack3_TPM_PCR_COMPOSITE(BYTE* ptr, UINT32* pos, UINT32 max, TPM_PCR_COMPOSITE* p, UnpackPtr alloc) {
+ return unpack3_TPM_PCR_SELECTION(ptr, pos, max, &p->select, alloc) ||
+ unpack3_UINT32(ptr, pos, max, &p->valueSize) ||
+ unpack3_PTR(ptr, pos, max, (BYTE**)&p->pcrValue, p->valueSize, alloc);
}
inline BYTE* pack_TPM_KEY(BYTE* ptr, const TPM_KEY* k) {
- ptr = pack_TPM_VERSION(ptr, &k->ver);
- ptr = pack_TPM_KEY_USAGE(ptr, k->keyUsage);
- ptr = pack_TPM_KEY_FLAGS(ptr, k->keyFlags);
- ptr = pack_TPM_AUTH_DATA_USAGE(ptr, k->authDataUsage);
- ptr = pack_TPM_KEY_PARMS(ptr, &k->algorithmParms);
- ptr = pack_UINT32(ptr, k->PCRInfoSize);
- if(k->PCRInfoSize) {
- ptr = pack_TPM_PCR_INFO(ptr, &k->PCRInfo);
- }
- ptr = pack_TPM_STORE_PUBKEY(ptr, &k->pubKey);
- ptr = pack_UINT32(ptr, k->encDataSize);
- return pack_BUFFER(ptr, k->encData, k->encDataSize);
-}
-
-inline BYTE* unpack_TPM_KEY(BYTE* ptr, TPM_KEY* k, UnpackPtr alloc) {
- ptr = unpack_TPM_VERSION(ptr, &k->ver);
- ptr = unpack_TPM_KEY_USAGE(ptr, &k->keyUsage);
- ptr = unpack_TPM_KEY_FLAGS(ptr, &k->keyFlags);
- ptr = unpack_TPM_AUTH_DATA_USAGE(ptr, &k->authDataUsage);
- ptr = unpack_TPM_KEY_PARMS(ptr, &k->algorithmParms, alloc);
- ptr = unpack_UINT32(ptr, &k->PCRInfoSize);
- if(k->PCRInfoSize) {
- ptr = unpack_TPM_PCR_INFO(ptr, &k->PCRInfo, alloc);
- }
- ptr = unpack_TPM_STORE_PUBKEY(ptr, &k->pubKey, alloc);
- ptr = unpack_UINT32(ptr, &k->encDataSize);
- return unpack_PTR(ptr, &k->encData, k->encDataSize, alloc);
+ ptr = pack_TPM_VERSION(ptr, &k->ver);
+ ptr = pack_TPM_KEY_USAGE(ptr, k->keyUsage);
+ ptr = pack_TPM_KEY_FLAGS(ptr, k->keyFlags);
+ ptr = pack_TPM_AUTH_DATA_USAGE(ptr, k->authDataUsage);
+ ptr = pack_TPM_KEY_PARMS(ptr, &k->algorithmParms);
+ ptr = pack_UINT32(ptr, k->PCRInfoSize);
+ if(k->PCRInfoSize) {
+ ptr = pack_TPM_PCR_INFO(ptr, &k->PCRInfo);
+ }
+ ptr = pack_TPM_STORE_PUBKEY(ptr, &k->pubKey);
+ ptr = pack_UINT32(ptr, k->encDataSize);
+ return pack_BUFFER(ptr, k->encData, k->encDataSize);
+}
+
+inline int unpack3_TPM_KEY(BYTE* ptr, UINT32* pos, UINT32 max, TPM_KEY* k, UnpackPtr alloc) {
+ int rc = unpack3_TPM_VERSION(ptr, pos, max, &k->ver) ||
+ unpack3_TPM_KEY_USAGE(ptr, pos, max, &k->keyUsage) ||
+ unpack3_TPM_KEY_FLAGS(ptr, pos, max, &k->keyFlags) ||
+ unpack3_TPM_AUTH_DATA_USAGE(ptr, pos, max, &k->authDataUsage) ||
+ unpack3_TPM_KEY_PARMS(ptr, pos, max, &k->algorithmParms, alloc) ||
+ unpack3_UINT32(ptr, pos, max, &k->PCRInfoSize);
+ if (rc) return rc;
+ if(k->PCRInfoSize) {
+ rc = unpack3_TPM_PCR_INFO(ptr, pos, max, &k->PCRInfo, alloc);
+ }
+ if (rc) return rc;
+ return unpack3_TPM_STORE_PUBKEY(ptr, pos, max, &k->pubKey, alloc) ||
+ unpack3_UINT32(ptr, pos, max, &k->encDataSize) ||
+ unpack3_PTR(ptr, pos, max, &k->encData, k->encDataSize, alloc);
+}
+
+inline int sizeof_TPM_KEY(const TPM_KEY* k) {
+ int rc = 0;
+ rc += sizeof_TPM_VERSION(&k->ver);
+ rc += sizeof_TPM_KEY_USAGE(k->keyUsage);
+ rc += sizeof_TPM_KEY_FLAGS(k->keyFlags);
+ rc += sizeof_TPM_AUTH_DATA_USAGE(k->authDataUsage);
+ rc += sizeof_TPM_KEY_PARMS(&k->algorithmParms);
+ rc += sizeof_UINT32(k->PCRInfoSize);
+ if(k->PCRInfoSize) {
+ rc += sizeof_TPM_PCR_INFO(&k->PCRInfo);
+ }
+ rc += sizeof_TPM_STORE_PUBKEY(&k->pubKey);
+ rc += sizeof_UINT32(k->encDataSize);
+ rc += k->encDataSize;
+ return rc;
}
inline BYTE* pack_TPM_BOUND_DATA(BYTE* ptr, const TPM_BOUND_DATA* b, UINT32 payloadSize) {
- ptr = pack_TPM_VERSION(ptr, &b->ver);
- ptr = pack_TPM_PAYLOAD_TYPE(ptr, b->payload);
- return pack_BUFFER(ptr, b->payloadData, payloadSize);
+ ptr = pack_TPM_VERSION(ptr, &b->ver);
+ ptr = pack_TPM_PAYLOAD_TYPE(ptr, b->payload);
+ return pack_BUFFER(ptr, b->payloadData, payloadSize);
}
inline BYTE* unpack_TPM_BOUND_DATA(BYTE* ptr, TPM_BOUND_DATA* b, UINT32 payloadSize, UnpackPtr alloc) {
- ptr = unpack_TPM_VERSION(ptr, &b->ver);
- ptr = unpack_TPM_PAYLOAD_TYPE(ptr, &b->payload);
- return unpack_PTR(ptr, &b->payloadData, payloadSize, alloc);
+ ptr = unpack_TPM_VERSION(ptr, &b->ver);
+ ptr = unpack_TPM_PAYLOAD_TYPE(ptr, &b->payload);
+ return unpack_PTR(ptr, &b->payloadData, payloadSize, alloc);
}
inline BYTE* pack_TPM_STORED_DATA(BYTE* ptr, const TPM_STORED_DATA* d) {
- ptr = pack_TPM_VERSION(ptr, &d->ver);
- ptr = pack_UINT32(ptr, d->sealInfoSize);
- if(d->sealInfoSize) {
- ptr = pack_TPM_PCR_INFO(ptr, &d->sealInfo);
- }
- ptr = pack_UINT32(ptr, d->encDataSize);
- ptr = pack_BUFFER(ptr, d->encData, d->encDataSize);
- return ptr;
-}
-
-inline BYTE* unpack_TPM_STORED_DATA(BYTE* ptr, TPM_STORED_DATA* d, UnpackPtr alloc) {
- ptr = unpack_TPM_VERSION(ptr, &d->ver);
- ptr = unpack_UINT32(ptr, &d->sealInfoSize);
- if(d->sealInfoSize) {
- ptr = unpack_TPM_PCR_INFO(ptr, &d->sealInfo, alloc);
- }
- ptr = unpack_UINT32(ptr, &d->encDataSize);
- ptr = unpack_PTR(ptr, &d->encData, d->encDataSize, alloc);
- return ptr;
+ ptr = pack_TPM_VERSION(ptr, &d->ver);
+ ptr = pack_UINT32(ptr, d->sealInfoSize);
+ if(d->sealInfoSize) {
+ ptr = pack_TPM_PCR_INFO(ptr, &d->sealInfo);
+ }
+ ptr = pack_UINT32(ptr, d->encDataSize);
+ ptr = pack_BUFFER(ptr, d->encData, d->encDataSize);
+ return ptr;
+}
+
+inline int sizeof_TPM_STORED_DATA(const TPM_STORED_DATA* d) {
+ int rv = sizeof_TPM_VERSION(&d->ver) + sizeof_UINT32(d->sealInfoSize);
+ if (d->sealInfoSize) {
+ rv += sizeof_TPM_PCR_INFO(&d->sealInfo);
+ }
+ rv += sizeof_UINT32(d->encDataSize);
+ rv += sizeof_BUFFER(d->encData, d->encDataSize);
+ return rv;
+}
+
+inline int unpack3_TPM_STORED_DATA(BYTE* ptr, UINT32* pos, UINT32 len, TPM_STORED_DATA* d, UnpackPtr alloc) {
+ int rc = unpack3_TPM_VERSION(ptr, pos, len, &d->ver) ||
+ unpack3_UINT32(ptr, pos, len, &d->sealInfoSize);
+ if (rc)
+ return rc;
+ if (d->sealInfoSize)
+ rc = unpack3_TPM_PCR_INFO(ptr, pos, len, &d->sealInfo, alloc);
+ if (rc)
+ return rc;
+ rc = unpack3_UINT32(ptr, pos, len, &d->encDataSize) ||
+ unpack3_PTR(ptr, pos, len, &d->encData, d->encDataSize, alloc);
+ return rc;
+}
+
+inline BYTE* pack_TPM_STORED_DATA12(BYTE* ptr, const TPM_STORED_DATA12* d) {
+ ptr = pack_TPM_STRUCTURE_TAG(ptr, d->tag);
+ ptr = pack_TPM_ENTITY_TYPE(ptr, d->et);
+ ptr = pack_UINT32(ptr, d->sealInfoLongSize);
+ if(d->sealInfoLongSize) {
+ ptr = pack_TPM_PCR_INFO_LONG(ptr, &d->sealInfoLong);
+ }
+ ptr = pack_UINT32(ptr, d->encDataSize);
+ ptr = pack_BUFFER(ptr, d->encData, d->encDataSize);
+ return ptr;
+}
+
+inline int sizeof_TPM_STORED_DATA12(const TPM_STORED_DATA12* d) {
+ int rv = sizeof_TPM_STRUCTURE_TAG(&d->ver) +
+ sizeof_TPM_ENTITY_TYPE(&d->et) +
+ sizeof_UINT32(d->sealInfoLongSize);
+ if (d->sealInfoLongSize) {
+ rv += sizeof_TPM_PCR_INFO_LONG(&d->sealInfoLong);
+ }
+ rv += sizeof_UINT32(d->encDataSize);
+ rv += sizeof_BUFFER(d->encData, d->encDataSize);
+ return rv;
+}
+
+inline int unpack3_TPM_STORED_DATA12(BYTE* ptr, UINT32* pos, UINT32 len, TPM_STORED_DATA12* d, UnpackPtr alloc) {
+ int rc = unpack3_TPM_STRUCTURE_TAG(ptr, pos, len, &d->tag) ||
+ unpack3_TPM_ENTITY_TYPE(ptr, pos, len, &d->et) ||
+ unpack3_UINT32(ptr, pos, len, &d->sealInfoLongSize);
+ if (rc)
+ return rc;
+ if (d->sealInfoLongSize)
+ rc = unpack3_TPM_PCR_INFO_LONG(ptr, pos, len, &d->sealInfoLong,
+ alloc);
+ if (rc)
+ return rc;
+ rc = unpack3_UINT32(ptr, pos, len, &d->encDataSize) ||
+ unpack3_PTR(ptr, pos, len, &d->encData, d->encDataSize, alloc);
+ return rc;
}
inline BYTE* pack_TPM_AUTH_SESSION(BYTE* ptr, const TPM_AUTH_SESSION* auth) {
- ptr = pack_TPM_AUTH_HANDLE(ptr, auth->AuthHandle);
- ptr = pack_TPM_NONCE(ptr, &auth->NonceOdd);
- ptr = pack_BOOL(ptr, auth->fContinueAuthSession);
- ptr = pack_TPM_AUTHDATA(ptr, &auth->HMAC);
- return ptr;
+ ptr = pack_TPM_AUTH_HANDLE(ptr, auth->AuthHandle);
+ ptr = pack_TPM_NONCE(ptr, &auth->NonceOdd);
+ ptr = pack_BOOL(ptr, auth->fContinueAuthSession);
+ ptr = pack_TPM_AUTHDATA(ptr, &auth->HMAC);
+ return ptr;
}
inline BYTE* unpack_TPM_AUTH_SESSION(BYTE* ptr, TPM_AUTH_SESSION* auth) {
- ptr = unpack_TPM_NONCE(ptr, &auth->NonceEven);
- ptr = unpack_BOOL(ptr, &auth->fContinueAuthSession);
- ptr = unpack_TPM_AUTHDATA(ptr, &auth->HMAC);
- return ptr;
+ ptr = unpack_TPM_NONCE(ptr, &auth->NonceEven);
+ ptr = unpack_BOOL(ptr, &auth->fContinueAuthSession);
+ ptr = unpack_TPM_AUTHDATA(ptr, &auth->HMAC);
+ return ptr;
}
-inline BYTE* pack_TPM_RQU_HEADER(BYTE* ptr,
- TPM_TAG tag,
- UINT32 size,
- TPM_COMMAND_CODE ord) {
- ptr = pack_UINT16(ptr, tag);
- ptr = pack_UINT32(ptr, size);
- return pack_UINT32(ptr, ord);
+inline int unpack3_TPM_AUTH_SESSION(BYTE* ptr, UINT32* pos, UINT32 len, TPM_AUTH_SESSION* auth) {
+ return unpack3_TPM_NONCE(ptr, pos, len, &auth->NonceEven) ||
+ unpack3_BOOL(ptr, pos, len, &auth->fContinueAuthSession) ||
+ unpack3_TPM_AUTHDATA(ptr, pos, len, &auth->HMAC);
}
-inline BYTE* unpack_TPM_RQU_HEADER(BYTE* ptr,
- TPM_TAG* tag,
- UINT32* size,
- TPM_COMMAND_CODE* ord) {
- ptr = unpack_UINT16(ptr, tag);
- ptr = unpack_UINT32(ptr, size);
- ptr = unpack_UINT32(ptr, ord);
- return ptr;
+
+inline int sizeof_TPM_AUTH_SESSION(const TPM_AUTH_SESSION* auth) {
+ int rv = 0;
+ rv += sizeof_TPM_AUTH_HANDLE(auth->AuthHandle);
+ rv += sizeof_TPM_NONCE(&auth->NonceOdd);
+ rv += sizeof_BOOL(auth->fContinueAuthSession);
+ rv += sizeof_TPM_AUTHDATA(&auth->HMAC);
+ return rv;
}
-#define pack_TPM_RSP_HEADER(p, t, s, r) pack_TPM_RQU_HEADER(p, t, s, r);
-#define unpack_TPM_RSP_HEADER(p, t, s, r) unpack_TPM_RQU_HEADER(p, t, s, r);
+inline BYTE* pack_TPM_RQU_HEADER(BYTE* ptr,
+ TPM_TAG tag,
+ UINT32 size,
+ TPM_COMMAND_CODE ord) {
+ ptr = pack_UINT16(ptr, tag);
+ ptr = pack_UINT32(ptr, size);
+ return pack_UINT32(ptr, ord);
+}
+
+inline BYTE* unpack_TPM_RQU_HEADER(BYTE* ptr,
+ TPM_TAG* tag,
+ UINT32* size,
+ TPM_COMMAND_CODE* ord) {
+ ptr = unpack_UINT16(ptr, tag);
+ ptr = unpack_UINT32(ptr, size);
+ ptr = unpack_UINT32(ptr, ord);
+ return ptr;
+}
+
+inline int unpack3_TPM_RQU_HEADER(BYTE* ptr, UINT32* pos, UINT32 max,
+ TPM_TAG* tag, UINT32* size, TPM_COMMAND_CODE* ord) {
+ return
+ unpack3_UINT16(ptr, pos, max, tag) ||
+ unpack3_UINT32(ptr, pos, max, size) ||
+ unpack3_UINT32(ptr, pos, max, ord);
+}
+
+#define pack_TPM_RSP_HEADER(p, t, s, r) pack_TPM_RQU_HEADER(p, t, s, r)
+#define unpack_TPM_RSP_HEADER(p, t, s, r) unpack_TPM_RQU_HEADER(p, t, s, r)
+#define unpack3_TPM_RSP_HEADER(p, l, m, t, s, r) unpack3_TPM_RQU_HEADER(p, l, m, t, s, r)
#endif
diff --git a/stubdom/vtpmmgr/mgmt_authority.c b/stubdom/vtpmmgr/mgmt_authority.c
new file mode 100644
index 0000000..0526a12
--- /dev/null
+++ b/stubdom/vtpmmgr/mgmt_authority.c
@@ -0,0 +1,323 @@
+#include <console.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <mini-os/byteorder.h>
+#include <polarssl/sha1.h>
+
+#include "vtpm_manager.h"
+#include "log.h"
+#include "uuid.h"
+
+#include "tpm.h"
+#include "tcg.h"
+#include "marshal.h"
+#include "vtpmmgr.h"
+#include "vtpm_disk.h"
+#include "disk_tpm.h"
+#include "disk_io.h"
+#include "disk_crypto.h"
+#include "disk_format.h"
+#include "mgmt_authority.h"
+
+static int do_provision_aik(struct mem_group *group,
+ const struct tpm_authdata *privCADigest)
+{
+ TPM_KEY kinfo = {
+ .ver = TPM_STRUCT_VER_1_1,
+ .keyUsage = TPM_KEY_IDENTITY,
+ .keyFlags = 0,
+ .authDataUsage = TPM_AUTH_ALWAYS,
+ .algorithmParms = {
+ .algorithmID = TPM_ALG_RSA,
+ .encScheme = TPM_ES_NONE,
+ .sigScheme = TPM_SS_RSASSAPKCS1v15_SHA1,
+ .parmSize = 12,
+ .parms.rsa = {
+ .keyLength = RSA_KEY_SIZE,
+ .numPrimes = 2,
+ .exponentSize = 0,
+ .exponent = NULL,
+ },
+ },
+ .PCRInfoSize = 0,
+ .pubKey.keyLength = 0,
+ .encDataSize = 0,
+ };
+
+ TPM_AUTH_SESSION srkAuth = TPM_AUTH_SESSION_INIT;
+ TPM_AUTH_SESSION ownAuth = TPM_AUTH_SESSION_INIT;
+ TPM_SECRET osapMask;
+
+ TPM_KEY key = TPM_KEY_INIT;
+ UINT32 identityBindingSize;
+ BYTE* identityBinding = NULL;
+
+ TPM_RESULT rc;
+
+ rc = TPM_OSAP(TPM_ET_OWNER, 0, (void*)&vtpm_globals.owner_auth, &osapMask, &ownAuth);
+ if (rc)
+ return rc;
+
+ rc = TPM_OIAP(&srkAuth);
+ if (rc)
+ return rc;
+
+ rc = TPM_MakeIdentity((void*)&group->aik_authdata, (void*)privCADigest, &kinfo,
+ (void*)&vtpm_globals.srk_auth, (void*)&osapMask, &srkAuth, &ownAuth,
+ &key, &identityBindingSize, &identityBinding);
+
+ TPM_TerminateHandle(srkAuth.AuthHandle);
+ TPM_TerminateHandle(ownAuth.AuthHandle);
+
+ if (rc) {
+ printk("TPM_MakeIdentity failed: %d\n", rc);
+ return rc;
+ }
+
+ if (key.pubKey.keyLength != 256)
+ rc = TPM_FAIL;
+ if (key.encDataSize != 256)
+ rc = TPM_FAIL;
+ if (identityBindingSize != 256)
+ rc = TPM_FAIL;
+ if (rc) {
+ printk("TPM_MakeIdentity TPM_KEY mismatch: %d %d %d\n",
+ key.pubKey.keyLength, key.encDataSize, identityBindingSize);
+ } else {
+ memcpy(group->id_data.tpm_aik_public, key.pubKey.key, 256);
+ memcpy(group->id_data.tpm_aik_edata, key.encData, 256);
+ memcpy(group->details.recovery_data, identityBinding, 256);
+ }
+
+ free_TPM_KEY(&key);
+ free(identityBinding);
+
+ return rc;
+}
+
+static int do_load_aik(struct mem_group *group, TPM_HANDLE *handle)
+{
+ TPM_KEY key = {
+ .ver = TPM_STRUCT_VER_1_1,
+ .keyUsage = TPM_KEY_IDENTITY,
+ .keyFlags = 0,
+ .authDataUsage = TPM_AUTH_ALWAYS,
+ .algorithmParms = {
+ .algorithmID = TPM_ALG_RSA,
+ .encScheme = TPM_ES_NONE,
+ .sigScheme = TPM_SS_RSASSAPKCS1v15_SHA1,
+ .parmSize = 12,
+ .parms.rsa = {
+ .keyLength = RSA_KEY_SIZE,
+ .numPrimes = 2,
+ .exponentSize = 0,
+ .exponent = NULL,
+ },
+ },
+ .PCRInfoSize = 0,
+ .pubKey.keyLength = 256,
+ .pubKey.key = group->id_data.tpm_aik_public,
+ .encDataSize = 256,
+ .encData = group->id_data.tpm_aik_edata,
+ };
+
+ return TPM_LoadKey(TPM_SRK_KEYHANDLE, &key, handle, (void*)&vtpm_globals.srk_auth, &vtpm_globals.oiap);
+}
+
+/*
+ * Sets up resettable PCRs for a vTPM deep quote request
+ */
+static int do_pcr_setup(struct mem_group *group, const void* uuid, const uint8_t* kern_hash)
+{
+ uint32_t reset_sel = (1 << 20) | (1 << 21) | (1 << 22) | (1 << 23);
+ sha1_context ctx;
+ TPM_DIGEST extended;
+ TPM_PCR_SELECTION sel = {
+ .sizeOfSelect = 3,
+ .pcrSelect = (void*)&reset_sel,
+ };
+ int rc;
+ int i;
+
+ rc = TPM_Reset(&sel);
+ if (rc)
+ return rc;
+
+ sha1((void*)&group->id_data.saa_pubkey, sizeof(group->id_data.saa_pubkey), extended.digest);
+ rc = TPM_Extend(20, &extended, &extended);
+ if (rc)
+ return rc;
+
+ sha1_starts(&ctx);
+ sha1_update(&ctx, (void*)&group->details.cfg_seq, 8);
+ sha1_update(&ctx, (void*)&group->seal_bits.nr_cfgs, 4);
+ for(i=0; i < group->nr_seals; i++)
+ sha1_update(&ctx, (void*)&group->seals[i].digest_release, 20);
+ sha1_update(&ctx, (void*)&group->seal_bits.nr_kerns, 4);
+ sha1_update(&ctx, (void*)&group->seal_bits.kernels, 20 * be32_native(group->seal_bits.nr_kerns));
+ sha1_finish(&ctx, extended.digest);
+ rc = TPM_Extend(21, &extended, &extended);
+ if (rc)
+ return rc;
+
+ if (kern_hash) {
+ rc = TPM_Extend(22, (void*)kern_hash, &extended);
+ if (rc)
+ return rc;
+ }
+
+ memset(&extended, 0, 20);
+ memcpy(&extended, group->id_data.uuid, 16);
+ rc = TPM_Extend(23, &extended, &extended);
+ if (rc)
+ return rc;
+
+ if (uuid) {
+ memset(&extended, 0, 20);
+ memcpy(&extended, uuid, 16);
+ rc = TPM_Extend(23, &extended, &extended);
+ if (rc)
+ return rc;
+ }
+
+ return rc;
+}
+
+struct mem_group *vtpm_new_group(const struct tpm_authdata *privCADigest)
+{
+ static struct mem_group* group0_delayed = NULL;
+ struct mem_group *group;
+
+ if (group0_delayed) {
+ group = group0_delayed;
+ group0_delayed = NULL;
+ } else {
+ group = calloc(1, sizeof(*group));
+
+ group->flags = MEM_GROUP_FLAG_FIRSTBOOT;
+
+ do_random(&group->id_data.uuid, 16);
+ do_random(&group->group_key, 16);
+ do_random(&group->rollback_mac_key, 16);
+ do_random(&group->aik_authdata, 20);
+
+ group->id_data.uuid[6] = 0x40 | (group->id_data.uuid[6] & 0x0F);
+ group->id_data.uuid[8] = 0x80 | (group->id_data.uuid[8] & 0x3F);
+ }
+
+ if (privCADigest) {
+ int rc;
+ rc = do_provision_aik(group, privCADigest);
+ if (rc) {
+ free(group);
+ return NULL;
+ }
+ } else {
+ group0_delayed = group;
+ }
+
+ return group;
+}
+
+int group_do_activate(struct mem_group *group, void* blob, int blobSize,
+ void* resp, unsigned int *rlen)
+{
+ int rc;
+ TPM_HANDLE handle;
+ TPM_AUTH_SESSION aikAuth = TPM_AUTH_SESSION_INIT;
+ TPM_AUTH_SESSION ownAuth = TPM_AUTH_SESSION_INIT;
+ TPM_SYMMETRIC_KEY symKey;
+
+ /* ActivateIdentity with TPM_EK_BLOB_ACTIVATE can check PCRs */
+ rc = do_pcr_setup(group, NULL, NULL);
+ if (rc)
+ return rc;
+
+ rc = do_load_aik(group, &handle);
+ if (rc)
+ return rc;
+
+ rc = TPM_OIAP(&aikAuth);
+ if (rc) {
+ TPM_TerminateHandle(handle);
+ return rc;
+ }
+
+ rc = TPM_OIAP(&ownAuth);
+ if (rc) {
+ TPM_TerminateHandle(aikAuth.AuthHandle);
+ TPM_TerminateHandle(handle);
+ return rc;
+ }
+
+ rc = TPM_ActivateIdentity(handle, blob, blobSize, (void*)&group->aik_authdata,
+ (void*)&vtpm_globals.owner_auth, &aikAuth, &ownAuth, &symKey);
+
+ TPM_TerminateHandle(ownAuth.AuthHandle);
+ TPM_TerminateHandle(aikAuth.AuthHandle);
+ TPM_TerminateHandle(handle);
+
+ if (rc)
+ return rc;
+
+ pack_TPM_SYMMETRIC_KEY(resp + *rlen, &symKey);
+ *rlen += 8 + symKey.size;
+ free(symKey.data);
+
+ return rc;
+}
+
+int vtpm_do_quote(struct mem_group *group, const uuid_t uuid,
+ const uint8_t* kern_hash, const struct tpm_authdata *data, TPM_PCR_SELECTION *sel,
+ void* pcr_out, uint32_t *pcr_size, void* sig_out)
+{
+ TPM_HANDLE handle;
+ TPM_AUTH_SESSION oiap = TPM_AUTH_SESSION_INIT;
+ TPM_PCR_COMPOSITE pcrs;
+ BYTE* sig;
+ UINT32 size;
+ int rc;
+
+ rc = do_pcr_setup(group, uuid, kern_hash);
+ if (rc)
+ return rc;
+
+ rc = do_load_aik(group, &handle);
+ if (rc)
+ return rc;
+
+ rc = TPM_OIAP(&oiap);
+ if (rc) {
+ TPM_TerminateHandle(handle);
+ return rc;
+ }
+
+ rc = TPM_Quote(handle, (void*)data, sel, (void*)&group->aik_authdata, &oiap, &pcrs, &sig, &size);
+ printk("TPM_Quote: %d\n", rc);
+
+ TPM_TerminateHandle(oiap.AuthHandle);
+ TPM_FlushSpecific(handle, TPM_RT_KEY);
+
+ if (rc)
+ return rc;
+ if (size != 256) {
+ printk("Bad size\n");
+ return TPM_FAIL;
+ }
+
+ if (pcr_out) {
+ *pcr_size = pcrs.valueSize;
+ memcpy(pcr_out, pcrs.pcrValue, *pcr_size);
+ }
+
+ memcpy(sig_out, sig, size);
+
+ free_TPM_PCR_COMPOSITE(&pcrs);
+ free(sig);
+
+ return rc;
+}
diff --git a/stubdom/vtpmmgr/mgmt_authority.h b/stubdom/vtpmmgr/mgmt_authority.h
new file mode 100644
index 0000000..1e96c8a
--- /dev/null
+++ b/stubdom/vtpmmgr/mgmt_authority.h
@@ -0,0 +1,11 @@
+#ifndef __VTPMMGR_MGMT_AUTHORITY_H
+#define __VTPMMGR_MGMT_AUTHORITY_H
+
+struct mem_group *vtpm_new_group(const struct tpm_authdata *privCADigest);
+int group_do_activate(struct mem_group *group, void* blob, int blobSize,
+ void* resp, unsigned int *rlen);
+int vtpm_do_quote(struct mem_group *group, const uuid_t uuid,
+ const uint8_t* kern_hash, const struct tpm_authdata *data, TPM_PCR_SELECTION *sel,
+ void* pcr_out, uint32_t *pcr_size, void* sig_out);
+
+#endif
diff --git a/stubdom/vtpmmgr/tcg.h b/stubdom/vtpmmgr/tcg.h
index 7687eae..7321ec6 100644
--- a/stubdom/vtpmmgr/tcg.h
+++ b/stubdom/vtpmmgr/tcg.h
@@ -259,6 +259,8 @@
#define TPM_ST_DEACTIVATED 0x003
// TPM_TAG values
+#define TPM_TAG_PCR_INFO_LONG 0x0006
+#define TPM_TAG_STORED_DATA12 0x0016
#define TPM_TAG_RQU_COMMAND 0x00c1
#define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2
#define TPM_TAG_RQU_AUTH2_COMMAND 0x00c3
@@ -490,6 +492,13 @@ typedef struct TPM_SYMMETRIC_KEY_PARMS {
BYTE* IV;
} TPM_SYMMETRIC_KEY_PARMS;
+typedef struct TPM_SYMMETRIC_KEY {
+ UINT32 algId;
+ UINT16 encScheme;
+ UINT16 size;
+ BYTE* data;
+} TPM_SYMMETRIC_KEY;
+
inline void free_TPM_SYMMETRIC_KEY_PARMS(TPM_SYMMETRIC_KEY_PARMS* p) {
free(p->IV);
p->IV = NULL;
@@ -575,6 +584,26 @@ inline void free_TPM_PCR_SELECTION(TPM_PCR_SELECTION* p) {
p->pcrSelect = NULL;
}
+#define TPM_LOCALITY_SELECTION BYTE
+
+typedef struct TPM_PCR_INFO_LONG {
+ TPM_STRUCTURE_TAG tag;
+ TPM_LOCALITY_SELECTION localityAtCreation;
+ TPM_LOCALITY_SELECTION localityAtRelease;
+ TPM_PCR_SELECTION creationPCRSelection;
+ TPM_PCR_SELECTION releasePCRSelection;
+ TPM_COMPOSITE_HASH digestAtCreation;
+ TPM_COMPOSITE_HASH digestAtRelease;
+} TPM_PCR_INFO_LONG;
+
+#define TPM_PCR_INFO_LONG_INIT { 0, 0, 0, TPM_PCR_SELECTION_INIT, \
+ TPM_PCR_SELECTION_INIT }
+
+inline void free_TPM_PCR_INFO_LONG(TPM_PCR_INFO_LONG* p) {
+ free_TPM_PCR_SELECTION(&p->creationPCRSelection);
+ free_TPM_PCR_SELECTION(&p->releasePCRSelection);
+}
+
typedef struct TPM_PCR_INFO {
TPM_PCR_SELECTION pcrSelection;
TPM_COMPOSITE_HASH digestAtRelease;
@@ -660,6 +689,26 @@ inline void free_TPM_STORED_DATA(TPM_STORED_DATA* d) {
d->encData = NULL;
}
+typedef struct TPM_STORED_DATA12 {
+ TPM_STRUCTURE_TAG tag;
+ TPM_ENTITY_TYPE et;
+ UINT32 sealInfoLongSize;
+ TPM_PCR_INFO_LONG sealInfoLong;
+ UINT32 encDataSize;
+ BYTE* encData;
+} TPM_STORED_DATA12;
+
+#define TPM_STORED_DATA12_INIT { .sealInfoLongSize = 0, \
+ sealInfoLong = TPM_PCR_INFO_INIT, .encDataSize = 0, .encData = NULL }
+
+inline void free_TPM_STORED_DATA12(TPM_STORED_DATA12* d) {
+ if(d->sealInfoLongSize) {
+ free_TPM_PCR_INFO_LONG(&d->sealInfoLong);
+ }
+ free(d->encData);
+ d->encData = NULL;
+}
+
typedef struct TPM_AUTH_SESSION {
TPM_AUTHHANDLE AuthHandle;
TPM_NONCE NonceOdd; // system
diff --git a/stubdom/vtpmmgr/tpm.c b/stubdom/vtpmmgr/tpm.c
index 123a27c..779cddd 100644
--- a/stubdom/vtpmmgr/tpm.c
+++ b/stubdom/vtpmmgr/tpm.c
@@ -51,173 +51,247 @@
#define TCPA_MAX_BUFFER_LENGTH 0x2000
-#define TPM_BEGIN(TAG, ORD) \
- const TPM_TAG intag = TAG;\
-TPM_TAG tag = intag;\
-UINT32 paramSize;\
-const TPM_COMMAND_CODE ordinal = ORD;\
-TPM_RESULT status = TPM_SUCCESS;\
-BYTE in_buf[TCPA_MAX_BUFFER_LENGTH];\
-BYTE out_buf[TCPA_MAX_BUFFER_LENGTH];\
-UINT32 out_len = sizeof(out_buf);\
-BYTE* ptr = in_buf;\
-/*Print a log message */\
-vtpmloginfo(VTPM_LOG_TPM, "%s\n", __func__);\
-/* Pack the header*/\
-ptr = pack_TPM_TAG(ptr, tag);\
-ptr += sizeof(UINT32);\
-ptr = pack_TPM_COMMAND_CODE(ptr, ordinal)\
-
-#define TPM_AUTH_BEGIN() \
- sha1_context sha1_ctx;\
-BYTE* authbase = ptr - sizeof(TPM_COMMAND_CODE);\
-TPM_DIGEST paramDigest;\
-sha1_starts(&sha1_ctx)
-
-#define TPM_AUTH1_GEN(HMACkey, auth) do {\
- sha1_finish(&sha1_ctx, paramDigest.digest);\
- generateAuth(¶mDigest, HMACkey, auth);\
- ptr = pack_TPM_AUTH_SESSION(ptr, auth);\
-} while(0)
-
-#define TPM_AUTH2_GEN(HMACkey, auth) do {\
- generateAuth(¶mDigest, HMACkey, auth);\
- ptr = pack_TPM_AUTH_SESSION(ptr, auth);\
-} while(0)
-
-#define TPM_TRANSMIT() do {\
- /* Pack the command size */\
- paramSize = ptr - in_buf;\
- pack_UINT32(in_buf + sizeof(TPM_TAG), paramSize);\
- if((status = TPM_TransmitData(in_buf, paramSize, out_buf, &out_len)) != TPM_SUCCESS) {\
- goto abort_egress;\
- }\
-} while(0)
-
-#define TPM_AUTH_VERIFY_BEGIN() do {\
- UINT32 buf[2] = { cpu_to_be32(status), cpu_to_be32(ordinal) };\
- sha1_starts(&sha1_ctx);\
- sha1_update(&sha1_ctx, (unsigned char*)buf, sizeof(buf));\
- authbase = ptr;\
-} while(0)
-
-#define TPM_AUTH1_VERIFY(HMACkey, auth) do {\
- sha1_finish(&sha1_ctx, paramDigest.digest);\
- ptr = unpack_TPM_AUTH_SESSION(ptr, auth);\
- if((status = verifyAuth(¶mDigest, HMACkey, auth)) != TPM_SUCCESS) {\
- goto abort_egress;\
- }\
-} while(0)
-
-#define TPM_AUTH2_VERIFY(HMACkey, auth) do {\
- ptr = unpack_TPM_AUTH_SESSION(ptr, auth);\
- if((status = verifyAuth(¶mDigest, HMACkey, auth)) != TPM_SUCCESS) {\
- goto abort_egress;\
- }\
-} while(0)
-
-
-
-#define TPM_UNPACK_VERIFY() do { \
- ptr = out_buf;\
- ptr = unpack_TPM_RSP_HEADER(ptr, \
- &(tag), &(paramSize), &(status));\
- if((status) != TPM_SUCCESS || (tag) != (intag +3)) { \
- vtpmlogerror(VTPM_LOG_TPM, "Failed with return code %s\n", tpm_get_error_name(status));\
- goto abort_egress;\
- }\
-} while(0)
-
-#define TPM_AUTH_HASH() do {\
- sha1_update(&sha1_ctx, authbase, ptr - authbase);\
- authbase = ptr;\
-} while(0)
-
-#define TPM_AUTH_SKIP() do {\
- authbase = ptr;\
-} while(0)
+#define TPM_BEGIN_CMD(ord) \
+ const TPM_COMMAND_CODE ordinal = ord; \
+ TPM_RESULT status = TPM_SUCCESS; \
+ BYTE _io_buffer[TCPA_MAX_BUFFER_LENGTH]; \
+ UINT32 _io_bufsize_in; \
+ UINT32 _io_bufsize_out; \
+ vtpmloginfo(VTPM_LOG_TPM, "%s\n", __func__); \
+ do { \
+ BYTE *in_buf = _io_buffer; \
+ UINT32 in_pos = 6; \
+ PACK_IN(UINT32, ordinal);
+
+#define IN_PTR (in_buf + in_pos)
+
+#define PACK_IN(type, item...) do { \
+ UINT32 isize = sizeof_ ## type(item); \
+ if (isize + in_pos > TCPA_MAX_BUFFER_LENGTH) { \
+ status = TPM_SIZE; \
+ goto abort_egress; \
+ } \
+ pack_ ## type (IN_PTR, item); \
+ in_pos += isize; \
+} while (0)
+
+#define TPM_HASH_IN_BEGIN \
+ sha1_context sha1_ctx; \
+ sha1_starts(&sha1_ctx); \
+ sha1_update(&sha1_ctx, in_buf + 6, 4); \
+ TPM_HASH_IN_START
+
+#define TPM_HASH_IN_START \
+ do { \
+ UINT32 _hash_in_start = in_pos;
+
+#define TPM_HASH_IN_STOP \
+ sha1_update(&sha1_ctx, in_buf + _hash_in_start, in_pos - _hash_in_start); \
+ } while (0)
+
+#define TPM_TAG_COMMON(req_tag) \
+ _io_bufsize_in = in_pos; \
+ pack_TPM_TAG(in_buf, req_tag); \
+ pack_UINT32(in_buf + sizeof(TPM_TAG), in_pos); \
+ } while (0); \
+ _io_bufsize_out = TCPA_MAX_BUFFER_LENGTH; \
+ status = TPM_TransmitData(_io_buffer, _io_bufsize_in, _io_buffer, &_io_bufsize_out); \
+ if (status != TPM_SUCCESS) { \
+ goto abort_egress; \
+ } \
+ do { \
+ BYTE *out_buf = _io_buffer; \
+ UINT32 out_pos = 0; \
+ UINT32 out_len = _io_bufsize_out; \
+ do { \
+ TPM_TAG rsp_tag; \
+ UINT32 rsp_len; \
+ UINT32 rsp_status; \
+ UNPACK_OUT(TPM_RSP_HEADER, &rsp_tag, &rsp_len, &rsp_status); \
+ if (rsp_status != TPM_SUCCESS) { \
+ vtpmlogerror(VTPM_LOG_TPM, "Failed with return code %s\n", tpm_get_error_name(rsp_status)); \
+ status = rsp_status; \
+ goto abort_egress; \
+ } \
+ if (rsp_tag != req_tag + 3 || rsp_len != out_len) { \
+ status = TPM_FAIL; \
+ goto abort_egress; \
+ } \
+ } while(0)
+
+#define OUT_PTR (out_buf + out_pos)
+
+#define UNPACK_OUT(type, item...) do { \
+ if (unpack3_ ## type (out_buf, &out_pos, TCPA_MAX_BUFFER_LENGTH, item)) { \
+ status = TPM_SIZE; \
+ goto abort_egress; \
+ } \
+} while (0)
+
+#define TPM_XMIT_REQ() \
+ TPM_TAG_COMMON(TPM_TAG_RQU_COMMAND)
+
+#define TPM_XMIT_AUTH1(sec1, auth1) \
+ TPM_HASH_IN_STOP; \
+ do { \
+ TPM_DIGEST paramDigest; \
+ sha1_finish(&sha1_ctx, paramDigest.digest); \
+ generateAuth(¶mDigest, sec1, auth1); \
+ PACK_IN(TPM_AUTH_SESSION, auth1); \
+ } while (0); \
+ TPM_TAG_COMMON(TPM_TAG_RQU_AUTH1_COMMAND); \
+ TPM_HASH_OUT_BEGIN
+
+#define TPM_XMIT_AUTH2(sec1, auth1, sec2, auth2) \
+ TPM_HASH_IN_STOP; \
+ do { \
+ TPM_DIGEST paramDigest; \
+ sha1_finish(&sha1_ctx, paramDigest.digest); \
+ generateAuth(¶mDigest, sec1, auth1); \
+ PACK_IN(TPM_AUTH_SESSION, auth1); \
+ generateAuth(¶mDigest, sec2, auth2); \
+ PACK_IN(TPM_AUTH_SESSION, auth2); \
+ } while (0); \
+ TPM_TAG_COMMON(TPM_TAG_RQU_AUTH2_COMMAND); \
+ TPM_HASH_OUT_BEGIN
+
+#define TPM_HASH_OUT_BEGIN \
+ sha1_context sha1_ctx; \
+ sha1_starts(&sha1_ctx); \
+ do { \
+ UINT32 buf[2] = { cpu_to_be32(status), cpu_to_be32(ordinal) }; \
+ sha1_update(&sha1_ctx, (BYTE*)buf, sizeof(buf)); \
+ } while(0); \
+ TPM_HASH_OUT_START
+
+#define TPM_HASH_OUT_START \
+ do { \
+ UINT32 _hash_out_start = out_pos;
+
+#define TPM_HASH_OUT_STOP \
+ sha1_update(&sha1_ctx, out_buf + _hash_out_start, out_pos - _hash_out_start); \
+ } while (0)
+
+#define TPM_END_AUTH1(sec1, auth1) \
+ TPM_HASH_OUT_STOP; \
+ do { \
+ TPM_DIGEST paramDigest; \
+ sha1_finish(&sha1_ctx, paramDigest.digest); \
+ UNPACK_OUT(TPM_AUTH_SESSION, auth1); \
+ status = verifyAuth(¶mDigest, sec1, auth1); \
+ if (status != TPM_SUCCESS) \
+ goto abort_egress; \
+ } while(0); \
+ TPM_END_COMMON
+
+#define TPM_END_AUTH2(sec1, auth1, sec2, auth2) \
+ TPM_HASH_OUT_STOP; \
+ do { \
+ TPM_DIGEST paramDigest; \
+ sha1_finish(&sha1_ctx, paramDigest.digest); \
+ UNPACK_OUT(TPM_AUTH_SESSION, auth1); \
+ status = verifyAuth(¶mDigest, sec1, auth1); \
+ if (status != TPM_SUCCESS) \
+ goto abort_egress; \
+ UNPACK_OUT(TPM_AUTH_SESSION, auth2); \
+ status = verifyAuth(¶mDigest, sec2, auth2); \
+ if (status != TPM_SUCCESS) \
+ goto abort_egress; \
+ } while(0); \
+ TPM_END_COMMON
+
+#define TPM_END() TPM_END_COMMON
+
+#define TPM_END_COMMON \
+ if (out_pos != out_len) { \
+ vtpmloginfo(VTPM_LOG_TPM, "Response too long (%d != %d)", out_pos, out_len);\
+ status = TPM_SIZE; \
+ goto abort_egress; \
+ } \
+ } while (0); \
#define TPM_AUTH_ERR_CHECK(auth) do {\
- if(status != TPM_SUCCESS || auth->fContinueAuthSession == FALSE) {\
- vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x closed by TPM\n", auth->AuthHandle);\
- auth->AuthHandle = 0;\
- }\
+ if(status != TPM_SUCCESS || auth->fContinueAuthSession == FALSE) {\
+ vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x closed by TPM\n", auth->AuthHandle);\
+ auth->AuthHandle = 0;\
+ }\
} while(0)
static void xorEncrypt(const TPM_SECRET* sharedSecret,
- TPM_NONCE* nonce,
- const TPM_AUTHDATA* inAuth0,
- TPM_ENCAUTH outAuth0,
- const TPM_AUTHDATA* inAuth1,
- TPM_ENCAUTH outAuth1) {
- BYTE XORbuffer[sizeof(TPM_SECRET) + sizeof(TPM_NONCE)];
- BYTE XORkey[TPM_DIGEST_SIZE];
- BYTE* ptr = XORbuffer;
- ptr = pack_TPM_SECRET(ptr, sharedSecret);
- ptr = pack_TPM_NONCE(ptr, nonce);
-
- sha1(XORbuffer, ptr - XORbuffer, XORkey);
-
- if(inAuth0) {
- for(int i = 0; i < TPM_DIGEST_SIZE; ++i) {
- outAuth0[i] = XORkey[i] ^ (*inAuth0)[i];
- }
- }
- if(inAuth1) {
- for(int i = 0; i < TPM_DIGEST_SIZE; ++i) {
- outAuth1[i] = XORkey[i] ^ (*inAuth1)[i];
- }
- }
+ TPM_NONCE* nonce,
+ const TPM_AUTHDATA* inAuth0,
+ TPM_ENCAUTH outAuth0,
+ const TPM_AUTHDATA* inAuth1,
+ TPM_ENCAUTH outAuth1) {
+ BYTE XORbuffer[sizeof(TPM_SECRET) + sizeof(TPM_NONCE)];
+ BYTE XORkey[TPM_DIGEST_SIZE];
+ BYTE* ptr = XORbuffer;
+ ptr = pack_TPM_SECRET(ptr, sharedSecret);
+ ptr = pack_TPM_NONCE(ptr, nonce);
+
+ sha1(XORbuffer, ptr - XORbuffer, XORkey);
+
+ if(inAuth0) {
+ for(int i = 0; i < TPM_DIGEST_SIZE; ++i) {
+ outAuth0[i] = XORkey[i] ^ (*inAuth0)[i];
+ }
+ }
+ if(inAuth1) {
+ for(int i = 0; i < TPM_DIGEST_SIZE; ++i) {
+ outAuth1[i] = XORkey[i] ^ (*inAuth1)[i];
+ }
+ }
}
static void generateAuth(const TPM_DIGEST* paramDigest,
- const TPM_SECRET* HMACkey,
- TPM_AUTH_SESSION *auth)
+ const TPM_SECRET* HMACkey,
+ TPM_AUTH_SESSION *auth)
{
- //Generate new OddNonce
- vtpmmgr_rand((BYTE*)auth->NonceOdd.nonce, sizeof(TPM_NONCE));
+ //Generate new OddNonce
+ vtpmmgr_rand((BYTE*)auth->NonceOdd.nonce, sizeof(TPM_NONCE));
- // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
- BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
- BYTE* ptr = hmacText;
+ // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
+ BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
+ BYTE* ptr = hmacText;
- ptr = pack_TPM_DIGEST(ptr, paramDigest);
- ptr = pack_TPM_NONCE(ptr, &auth->NonceEven);
- ptr = pack_TPM_NONCE(ptr, &auth->NonceOdd);
- ptr = pack_BOOL(ptr, auth->fContinueAuthSession);
+ ptr = pack_TPM_DIGEST(ptr, paramDigest);
+ ptr = pack_TPM_NONCE(ptr, &auth->NonceEven);
+ ptr = pack_TPM_NONCE(ptr, &auth->NonceOdd);
+ ptr = pack_BOOL(ptr, auth->fContinueAuthSession);
- sha1_hmac((BYTE *) HMACkey, sizeof(TPM_DIGEST),
- (BYTE *) hmacText, sizeof(hmacText),
- auth->HMAC);
+ sha1_hmac((BYTE *) HMACkey, sizeof(TPM_DIGEST),
+ (BYTE *) hmacText, sizeof(hmacText),
+ auth->HMAC);
}
static TPM_RESULT verifyAuth(const TPM_DIGEST* paramDigest,
- /*[IN]*/ const TPM_SECRET *HMACkey,
- /*[IN,OUT]*/ TPM_AUTH_SESSION *auth)
+ /*[IN]*/ const TPM_SECRET *HMACkey,
+ /*[IN,OUT]*/ TPM_AUTH_SESSION *auth)
{
- // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
- TPM_AUTHDATA hm;
- BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
- BYTE* ptr = hmacText;
-
- ptr = pack_TPM_DIGEST(ptr, paramDigest);
- ptr = pack_TPM_NONCE(ptr, &auth->NonceEven);
- ptr = pack_TPM_NONCE(ptr, &auth->NonceOdd);
- ptr = pack_BOOL(ptr, auth->fContinueAuthSession);
-
- sha1_hmac( (BYTE *) HMACkey, sizeof(TPM_DIGEST),
- (BYTE *) hmacText, sizeof(hmacText),
- hm);
-
- // Compare correct HMAC with provided one.
- if (memcmp(hm, auth->HMAC, sizeof(TPM_DIGEST)) == 0) { // 0 indicates equality
- return TPM_SUCCESS;
- } else {
- vtpmlogerror(VTPM_LOG_TPM, "Auth Session verification failed!\n");
- return TPM_AUTHFAIL;
- }
+ // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
+ TPM_AUTHDATA hm;
+ BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
+ BYTE* ptr = hmacText;
+
+ ptr = pack_TPM_DIGEST(ptr, paramDigest);
+ ptr = pack_TPM_NONCE(ptr, &auth->NonceEven);
+ ptr = pack_TPM_NONCE(ptr, &auth->NonceOdd);
+ ptr = pack_BOOL(ptr, auth->fContinueAuthSession);
+
+ sha1_hmac( (BYTE *) HMACkey, sizeof(TPM_DIGEST),
+ (BYTE *) hmacText, sizeof(hmacText),
+ hm);
+
+ // Compare correct HMAC with provided one.
+ if (memcmp(hm, auth->HMAC, sizeof(TPM_DIGEST)) == 0) { // 0 indicates equality
+ return TPM_SUCCESS;
+ } else {
+ vtpmlogerror(VTPM_LOG_TPM, "Auth Session verification failed! %x %x\n",
+ *(UINT32*)auth->HMAC, *(UINT32*)hm);
+ return TPM_AUTHFAIL;
+ }
}
@@ -226,713 +300,605 @@ static TPM_RESULT verifyAuth(const TPM_DIGEST* paramDigest,
// Authorization Commands
// ------------------------------------------------------------------
-TPM_RESULT TPM_OIAP(TPM_AUTH_SESSION* auth) // out
+TPM_RESULT TPM_OIAP(TPM_AUTH_SESSION* auth) // out
{
- TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_OIAP);
+ TPM_BEGIN_CMD(TPM_ORD_OIAP);
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
+ TPM_XMIT_REQ();
- memset(&auth->HMAC, 0, sizeof(TPM_DIGEST));
- auth->fContinueAuthSession = TRUE;
+ memset(&auth->HMAC, 0, sizeof(TPM_DIGEST));
+ auth->fContinueAuthSession = TRUE;
- ptr = unpack_UINT32(ptr, &auth->AuthHandle);
- ptr = unpack_TPM_NONCE(ptr, &auth->NonceEven);
+ UNPACK_OUT(UINT32, &auth->AuthHandle);
+ UNPACK_OUT(TPM_NONCE, &auth->NonceEven);
+ TPM_END();
- vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x opened by TPM_OIAP.\n", auth->AuthHandle);
+ vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x opened by TPM_OIAP.\n", auth->AuthHandle);
abort_egress:
- return status;
+ return status;
}
TPM_RESULT TPM_OSAP(TPM_ENTITY_TYPE entityType, // in
- UINT32 entityValue, // in
- const TPM_AUTHDATA* usageAuth, //in
- TPM_SECRET *sharedSecret, //out
- TPM_AUTH_SESSION *auth)
+ UINT32 entityValue, // in
+ const TPM_AUTHDATA* usageAuth, //in
+ TPM_SECRET *sharedSecret, //out
+ TPM_AUTH_SESSION *auth)
{
- BYTE* nonceOddOSAP;
- TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_OSAP);
+ TPM_DIGEST nonceOddOSAP;
+ vtpmmgr_rand(nonceOddOSAP.digest, TPM_DIGEST_SIZE);
+ TPM_BEGIN_CMD(TPM_ORD_OSAP);
- ptr = pack_TPM_ENTITY_TYPE(ptr, entityType);
- ptr = pack_UINT32(ptr, entityValue);
+ PACK_IN(TPM_ENTITY_TYPE, entityType);
+ PACK_IN(UINT32, entityValue);
+ PACK_IN(TPM_DIGEST, &nonceOddOSAP);
- //nonce Odd OSAP
- nonceOddOSAP = ptr;
- vtpmmgr_rand(ptr, TPM_DIGEST_SIZE);
- ptr += TPM_DIGEST_SIZE;
+ TPM_XMIT_REQ();
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
+ UNPACK_OUT(UINT32, &auth->AuthHandle);
+ UNPACK_OUT(TPM_NONCE, &auth->NonceEven);
- ptr = unpack_UINT32(ptr, &auth->AuthHandle);
- ptr = unpack_TPM_NONCE(ptr, &auth->NonceEven);
+ //Calculate session secret
+ sha1_context ctx;
+ sha1_hmac_starts(&ctx, *usageAuth, TPM_DIGEST_SIZE);
+ sha1_hmac_update(&ctx, OUT_PTR, TPM_DIGEST_SIZE); // nonceEvenOSAP
+ sha1_hmac_update(&ctx, nonceOddOSAP.digest, TPM_DIGEST_SIZE);
+ sha1_hmac_finish(&ctx, *sharedSecret);
- //Calculate session secret
- sha1_context ctx;
- sha1_hmac_starts(&ctx, *usageAuth, TPM_DIGEST_SIZE);
- sha1_hmac_update(&ctx, ptr, TPM_DIGEST_SIZE); //ptr = nonceEvenOSAP
- sha1_hmac_update(&ctx, nonceOddOSAP, TPM_DIGEST_SIZE);
- sha1_hmac_finish(&ctx, *sharedSecret);
+ out_pos += TPM_DIGEST_SIZE;
+ TPM_END();
- memset(&auth->HMAC, 0, sizeof(TPM_DIGEST));
- auth->fContinueAuthSession = FALSE;
+ memset(&auth->HMAC, 0, sizeof(TPM_DIGEST));
+ auth->fContinueAuthSession = FALSE;
- vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x opened by TPM_OSAP.\n", auth->AuthHandle);
+ vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x opened by TPM_OSAP.\n", auth->AuthHandle);
abort_egress:
- return status;
+ return status;
}
TPM_RESULT TPM_TakeOwnership(
- const TPM_PUBKEY *pubEK, //in
- const TPM_AUTHDATA* ownerAuth, //in
- const TPM_AUTHDATA* srkAuth, //in
- const TPM_KEY* inSrk, //in
- TPM_KEY* outSrk, //out, optional
- TPM_AUTH_SESSION* auth) // in, out
+ const TPM_PUBKEY *pubEK, //in
+ const TPM_AUTHDATA* ownerAuth, //in
+ const TPM_AUTHDATA* srkAuth, //in
+ const TPM_KEY* inSrk, //in
+ TPM_KEY* outSrk, //out, optional
+ TPM_AUTH_SESSION* auth) // in, out
{
- int keyAlloced = 0;
- tpmrsa_context ek_rsa = TPMRSA_CTX_INIT;
-
- TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_TakeOwnership);
- TPM_AUTH_BEGIN();
-
- tpmrsa_set_pubkey(&ek_rsa,
- pubEK->pubKey.key, pubEK->pubKey.keyLength,
- pubEK->algorithmParms.parms.rsa.exponent,
- pubEK->algorithmParms.parms.rsa.exponentSize);
-
- /* Pack the protocol ID */
- ptr = pack_UINT16(ptr, TPM_PID_OWNER);
-
- /* Pack the encrypted owner auth */
- ptr = pack_UINT32(ptr, pubEK->algorithmParms.parms.rsa.keyLength / 8);
- tpmrsa_pub_encrypt_oaep(&ek_rsa,
- ctr_drbg_random, &vtpm_globals.ctr_drbg,
- sizeof(TPM_SECRET),
- (BYTE*) ownerAuth,
- ptr);
- ptr += pubEK->algorithmParms.parms.rsa.keyLength / 8;
-
- /* Pack the encrypted srk auth */
- ptr = pack_UINT32(ptr, pubEK->algorithmParms.parms.rsa.keyLength / 8);
- tpmrsa_pub_encrypt_oaep(&ek_rsa,
- ctr_drbg_random, &vtpm_globals.ctr_drbg,
- sizeof(TPM_SECRET),
- (BYTE*) srkAuth,
- ptr);
- ptr += pubEK->algorithmParms.parms.rsa.keyLength / 8;
-
- /* Pack the Srk key */
- ptr = pack_TPM_KEY(ptr, inSrk);
-
- /* Hash everything up to here */
- TPM_AUTH_HASH();
-
- /* Generate the authorization */
- TPM_AUTH1_GEN(ownerAuth, auth);
-
- /* Send the command to the tpm*/
- TPM_TRANSMIT();
- /* Unpack and validate the header */
- TPM_UNPACK_VERIFY();
- TPM_AUTH_VERIFY_BEGIN();
-
- if(outSrk != NULL) {
- /* If the user wants a copy of the srk we give it to them */
- keyAlloced = 1;
- ptr = unpack_TPM_KEY(ptr, outSrk, UNPACK_ALLOC);
- } else {
- /*otherwise just parse past it */
- TPM_KEY temp;
- ptr = unpack_TPM_KEY(ptr, &temp, UNPACK_ALIAS);
- }
-
- /* Hash the output key */
- TPM_AUTH_HASH();
-
- /* Verify authorizaton */
- TPM_AUTH1_VERIFY(ownerAuth, auth);
-
- goto egress;
+ int keyAlloced = 0;
+ tpmrsa_context ek_rsa = TPMRSA_CTX_INIT;
+
+ TPM_BEGIN_CMD(TPM_ORD_TakeOwnership);
+ TPM_HASH_IN_BEGIN;
+
+ tpmrsa_set_pubkey(&ek_rsa,
+ pubEK->pubKey.key, pubEK->pubKey.keyLength,
+ pubEK->algorithmParms.parms.rsa.exponent,
+ pubEK->algorithmParms.parms.rsa.exponentSize);
+
+ /* Pack the protocol ID */
+ PACK_IN(UINT16, TPM_PID_OWNER);
+
+ /* Pack the encrypted owner auth */
+ PACK_IN(UINT32, pubEK->algorithmParms.parms.rsa.keyLength / 8);
+ tpmrsa_pub_encrypt_oaep(&ek_rsa,
+ ctr_drbg_random, &vtpm_globals.ctr_drbg,
+ sizeof(TPM_SECRET),
+ (BYTE*) ownerAuth,
+ IN_PTR);
+ in_pos += pubEK->algorithmParms.parms.rsa.keyLength / 8;
+
+ /* Pack the encrypted srk auth */
+ PACK_IN(UINT32, pubEK->algorithmParms.parms.rsa.keyLength / 8);
+ tpmrsa_pub_encrypt_oaep(&ek_rsa,
+ ctr_drbg_random, &vtpm_globals.ctr_drbg,
+ sizeof(TPM_SECRET),
+ (BYTE*) srkAuth,
+ IN_PTR);
+ in_pos += pubEK->algorithmParms.parms.rsa.keyLength / 8;
+
+ PACK_IN(TPM_KEY, inSrk);
+
+ TPM_XMIT_AUTH1(ownerAuth, auth);
+
+ if (outSrk != NULL) {
+ /* If the user wants a copy of the srk we give it to them */
+ keyAlloced = 1;
+ UNPACK_OUT(TPM_KEY, outSrk, UNPACK_ALLOC);
+ } else {
+ /*otherwise just parse past it */
+ TPM_KEY temp;
+ UNPACK_OUT(TPM_KEY, &temp, UNPACK_ALIAS);
+ }
+
+ TPM_END_AUTH1(ownerAuth, auth);
+
+ goto egress;
abort_egress:
- if(keyAlloced) {
- free_TPM_KEY(outSrk);
- }
+ if(keyAlloced) {
+ free_TPM_KEY(outSrk);
+ }
egress:
- tpmrsa_free(&ek_rsa);
- TPM_AUTH_ERR_CHECK(auth);
- return status;
+ tpmrsa_free(&ek_rsa);
+ TPM_AUTH_ERR_CHECK(auth);
+ return status;
}
TPM_RESULT TPM_DisablePubekRead (
- const TPM_AUTHDATA* ownerAuth,
- TPM_AUTH_SESSION* auth)
+ const TPM_AUTHDATA* ownerAuth,
+ TPM_AUTH_SESSION* auth)
{
- TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_DisablePubekRead);
- TPM_AUTH_BEGIN();
-
- TPM_AUTH_HASH();
+ TPM_BEGIN_CMD(TPM_ORD_DisablePubekRead);
+ TPM_HASH_IN_BEGIN;
- TPM_AUTH1_GEN(ownerAuth, auth);
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
- TPM_AUTH_VERIFY_BEGIN();
+ TPM_XMIT_AUTH1(ownerAuth, auth);
- TPM_AUTH1_VERIFY(ownerAuth, auth);
+ TPM_END_AUTH1(ownerAuth, auth);
abort_egress:
- TPM_AUTH_ERR_CHECK(auth);
- return status;
+ TPM_AUTH_ERR_CHECK(auth);
+ return status;
}
TPM_RESULT TPM_TerminateHandle(TPM_AUTHHANDLE handle) // in
{
- if(handle == 0) {
- return TPM_SUCCESS;
- }
+ if(handle == 0) {
+ return TPM_SUCCESS;
+ }
- TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_Terminate_Handle);
+ TPM_BEGIN_CMD(TPM_ORD_Terminate_Handle);
- ptr = pack_TPM_AUTHHANDLE(ptr, handle);
+ PACK_IN(TPM_AUTHHANDLE, handle);
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
+ TPM_XMIT_REQ();
+ TPM_END();
- vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x closed by TPM_TerminateHandle\n", handle);
+ vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x closed by TPM_TerminateHandle\n", handle);
abort_egress:
- return status;
+ return status;
}
TPM_RESULT TPM_Extend( TPM_PCRINDEX pcrNum, // in
- TPM_DIGEST inDigest, // in
- TPM_PCRVALUE* outDigest) // out
+ TPM_DIGEST* inDigest, // in
+ TPM_PCRVALUE* outDigest) // out
{
- TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_Extend);
+ TPM_BEGIN_CMD(TPM_ORD_Extend);
+
+ PACK_IN(TPM_PCRINDEX, pcrNum);
+ PACK_IN(TPM_DIGEST, inDigest);
- ptr = pack_TPM_PCRINDEX(ptr, pcrNum);
- ptr = pack_TPM_DIGEST(ptr, &inDigest);
+ TPM_XMIT_REQ();
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
+ UNPACK_OUT(TPM_PCRVALUE, outDigest);
- ptr = unpack_TPM_PCRVALUE(ptr, outDigest);
+ TPM_END();
+
+abort_egress:
+ return status;
+}
+TPM_RESULT TPM_Reset(TPM_PCR_SELECTION *sel)
+{
+ TPM_BEGIN_CMD(TPM_ORD_PCR_Reset);
+ PACK_IN(TPM_PCR_SELECTION, sel);
+ TPM_XMIT_REQ();
+ TPM_END();
abort_egress:
- return status;
+ return status;
}
TPM_RESULT TPM_Seal(
- TPM_KEY_HANDLE keyHandle, // in
- UINT32 pcrInfoSize, // in
- TPM_PCR_INFO* pcrInfo, // in
- UINT32 inDataSize, // in
- const BYTE* inData, // in
- TPM_STORED_DATA* sealedData, //out
- const TPM_SECRET* osapSharedSecret, //in
- const TPM_AUTHDATA* sealedDataAuth, //in
- TPM_AUTH_SESSION* pubAuth // in, out
- )
+ TPM_KEY_HANDLE keyHandle, // in
+ UINT32 pcrInfoLongSize, // in
+ TPM_PCR_INFO_LONG* pcrInfoLong, // in
+ UINT32 inDataSize, // in
+ const BYTE* inData, // in
+ TPM_STORED_DATA12* sealedData, //out
+ const TPM_SECRET* osapSharedSecret, //in
+ const TPM_AUTHDATA* sealedDataAuth, //in
+ TPM_AUTH_SESSION* pubAuth // in, out
+ )
{
- int dataAlloced = 0;
- TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_Seal);
- TPM_AUTH_BEGIN();
+ memset(sealedData, 0, sizeof(*sealedData));
+ TPM_BEGIN_CMD(TPM_ORD_Seal);
+ PACK_IN(TPM_KEY_HANDLE, keyHandle);
+ TPM_HASH_IN_BEGIN;
+
+ xorEncrypt(osapSharedSecret, &pubAuth->NonceEven, sealedDataAuth, IN_PTR, NULL, NULL);
+ in_pos += sizeof(TPM_ENCAUTH);
- TPM_AUTH_HASH();
+ PACK_IN(UINT32, pcrInfoLongSize);
+ if (pcrInfoLongSize) {
+ PACK_IN(TPM_PCR_INFO_LONG, pcrInfoLong);
+ }
+ PACK_IN(UINT32, inDataSize);
+ PACK_IN(BUFFER, inData, inDataSize);
- ptr = pack_TPM_KEY_HANDLE(ptr, keyHandle);
+ TPM_XMIT_AUTH1(osapSharedSecret, pubAuth);
- TPM_AUTH_SKIP();
+ UNPACK_OUT(TPM_STORED_DATA12, sealedData, UNPACK_ALLOC);
- xorEncrypt(osapSharedSecret, &pubAuth->NonceEven,
- sealedDataAuth, ptr,
- NULL, NULL);
- ptr += sizeof(TPM_ENCAUTH);
+ TPM_END_AUTH1(osapSharedSecret, pubAuth);
- ptr = pack_UINT32(ptr, pcrInfoSize);
- ptr = pack_TPM_PCR_INFO(ptr, pcrInfo);
+ abort_egress:
+ if (status)
+ free_TPM_STORED_DATA12(sealedData);
+ TPM_AUTH_ERR_CHECK(pubAuth);
+ return status;
+}
- ptr = pack_UINT32(ptr, inDataSize);
- ptr = pack_BUFFER(ptr, inData, inDataSize);
+TPM_RESULT TPM_Unseal(
+ TPM_KEY_HANDLE parentHandle, // in
+ const TPM_STORED_DATA12* sealedData,
+ UINT32* outSize, // out
+ BYTE** out, //out
+ const TPM_AUTHDATA* key_usage_auth, //in
+ const TPM_AUTHDATA* data_usage_auth, //in
+ TPM_AUTH_SESSION* keyAuth, // in, out
+ TPM_AUTH_SESSION* dataAuth // in, out
+ )
+{
+ TPM_BEGIN_CMD(TPM_ORD_Unseal);
- TPM_AUTH_HASH();
+ PACK_IN(TPM_KEY_HANDLE, parentHandle);
- TPM_AUTH1_GEN(osapSharedSecret, pubAuth);
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
- TPM_AUTH_VERIFY_BEGIN();
+ TPM_HASH_IN_BEGIN;
+ PACK_IN(TPM_STORED_DATA12, sealedData);
- ptr = unpack_TPM_STORED_DATA(ptr, sealedData, UNPACK_ALLOC);
- dataAlloced = 1;
+ TPM_XMIT_AUTH2(key_usage_auth, keyAuth, data_usage_auth, dataAuth);
- TPM_AUTH_HASH();
+ UNPACK_OUT(UINT32, outSize);
+ UNPACK_OUT(PTR, out, *outSize, UNPACK_ALLOC);
- TPM_AUTH1_VERIFY(osapSharedSecret, pubAuth);
+ TPM_END_AUTH2(key_usage_auth, keyAuth, data_usage_auth, dataAuth);
- goto egress;
abort_egress:
- if(dataAlloced) {
- free_TPM_STORED_DATA(sealedData);
- }
-egress:
- TPM_AUTH_ERR_CHECK(pubAuth);
- return status;
+ TPM_AUTH_ERR_CHECK(keyAuth);
+ TPM_AUTH_ERR_CHECK(dataAuth);
+ return status;
}
-TPM_RESULT TPM_Unseal(
- TPM_KEY_HANDLE parentHandle, // in
- const TPM_STORED_DATA* sealedData,
- UINT32* outSize, // out
- BYTE** out, //out
- const TPM_AUTHDATA* key_usage_auth, //in
- const TPM_AUTHDATA* data_usage_auth, //in
- TPM_AUTH_SESSION* keyAuth, // in, out
- TPM_AUTH_SESSION* dataAuth // in, out
- )
+TPM_RESULT TPM_LoadKey(
+ TPM_KEY_HANDLE parentHandle, //
+ const TPM_KEY* key, //in
+ TPM_HANDLE* keyHandle, // out
+ const TPM_AUTHDATA* usage_auth,
+ TPM_AUTH_SESSION* auth)
{
- TPM_BEGIN(TPM_TAG_RQU_AUTH2_COMMAND, TPM_ORD_Unseal);
- TPM_AUTH_BEGIN();
+ TPM_BEGIN_CMD(TPM_ORD_LoadKey);
+ PACK_IN(TPM_KEY_HANDLE, parentHandle);
- TPM_AUTH_HASH();
+ TPM_HASH_IN_BEGIN;
- ptr = pack_TPM_KEY_HANDLE(ptr, parentHandle);
+ PACK_IN(TPM_KEY, key);
- TPM_AUTH_SKIP();
+ TPM_XMIT_AUTH1(usage_auth, auth);
- ptr = pack_TPM_STORED_DATA(ptr, sealedData);
+ UNPACK_OUT(UINT32, keyHandle);
- TPM_AUTH_HASH();
+ TPM_END_AUTH1(usage_auth, auth);
- TPM_AUTH1_GEN(key_usage_auth, keyAuth);
- TPM_AUTH2_GEN(data_usage_auth, dataAuth);
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
- TPM_AUTH_VERIFY_BEGIN();
+ vtpmloginfo(VTPM_LOG_TPM, "Key Handle: 0x%x opened by TPM_LoadKey\n", *keyHandle);
+abort_egress:
+ TPM_AUTH_ERR_CHECK(auth);
+ return status;
+}
- ptr = unpack_UINT32(ptr, outSize);
- ptr = unpack_ALLOC(ptr, out, *outSize);
+TPM_RESULT TPM_FlushSpecific(TPM_HANDLE handle,
+ TPM_RESOURCE_TYPE rt) {
+ if(handle == 0) {
+ return TPM_SUCCESS;
+ }
+ TPM_BEGIN_CMD(TPM_ORD_FlushSpecific);
- TPM_AUTH_HASH();
+ PACK_IN(TPM_HANDLE, handle);
+ PACK_IN(TPM_RESOURCE_TYPE, rt);
- TPM_AUTH1_VERIFY(key_usage_auth, keyAuth);
- TPM_AUTH2_VERIFY(data_usage_auth, dataAuth);
+ TPM_XMIT_REQ();
+ TPM_END();
abort_egress:
- TPM_AUTH_ERR_CHECK(keyAuth);
- TPM_AUTH_ERR_CHECK(dataAuth);
- return status;
+ return status;
}
-TPM_RESULT TPM_Bind(
- const TPM_KEY* key,
- const BYTE* in,
- UINT32 ilen,
- BYTE* out)
+TPM_RESULT TPM_GetRandom( UINT32* bytesRequested, // in, out
+ BYTE* randomBytes) // out
{
- TPM_RESULT status;
- tpmrsa_context rsa = TPMRSA_CTX_INIT;
- TPM_BOUND_DATA boundData;
- uint8_t plain[TCPA_MAX_BUFFER_LENGTH];
- BYTE* ptr = plain;
-
- vtpmloginfo(VTPM_LOG_TPM, "%s\n", __func__);
-
- tpmrsa_set_pubkey(&rsa,
- key->pubKey.key, key->pubKey.keyLength,
- key->algorithmParms.parms.rsa.exponent,
- key->algorithmParms.parms.rsa.exponentSize);
-
- // Fill boundData's accessory information
- boundData.ver = TPM_STRUCT_VER_1_1;
- boundData.payload = TPM_PT_BIND;
- boundData.payloadData = (BYTE*)in;
-
- //marshall the bound data object
- ptr = pack_TPM_BOUND_DATA(ptr, &boundData, ilen);
-
- // Encrypt the data
- TPMTRYRETURN(tpmrsa_pub_encrypt_oaep(&rsa,
- ctr_drbg_random, &vtpm_globals.ctr_drbg,
- ptr - plain,
- plain,
- out));
+ UINT32 req_len = *bytesRequested;
+ TPM_BEGIN_CMD(TPM_ORD_GetRandom);
+ PACK_IN(UINT32, req_len);
-abort_egress:
- tpmrsa_free(&rsa);
- return status;
+ TPM_XMIT_REQ();
+
+ UNPACK_OUT(UINT32, bytesRequested);
+ if (*bytesRequested > req_len)
+ return TPM_FAIL;
+ UNPACK_OUT(BUFFER, randomBytes, *bytesRequested);
+ TPM_END();
+abort_egress:
+ return status;
}
-TPM_RESULT TPM_UnBind(
- TPM_KEY_HANDLE keyHandle, // in
- UINT32 ilen, //in
- const BYTE* in, //
- UINT32* olen, //
- BYTE* out, //out
- const TPM_AUTHDATA* usage_auth,
- TPM_AUTH_SESSION* auth //in, out
- )
+
+TPM_RESULT TPM_ReadPubek(
+ TPM_PUBKEY* pubEK //out
+ )
{
- TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_UnBind);
- TPM_AUTH_BEGIN();
+ TPM_DIGEST antiReplay;
+ BYTE* kptr = NULL;
+ BYTE digest[TPM_DIGEST_SIZE];
+ sha1_context ctx;
- TPM_AUTH_HASH();
+ vtpmmgr_rand(antiReplay.digest, TPM_DIGEST_SIZE);
- ptr = pack_TPM_KEY_HANDLE(ptr, keyHandle);
+ TPM_BEGIN_CMD(TPM_ORD_ReadPubek);
- TPM_AUTH_SKIP();
+ PACK_IN(TPM_DIGEST, &antiReplay);
- ptr = pack_UINT32(ptr, ilen);
- ptr = pack_BUFFER(ptr, in, ilen);
+ TPM_XMIT_REQ();
- TPM_AUTH_HASH();
+ //unpack and allocate the key
+ kptr = OUT_PTR;
+ UNPACK_OUT(TPM_PUBKEY, pubEK, UNPACK_ALLOC);
- TPM_AUTH1_GEN(usage_auth, auth);
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
- TPM_AUTH_VERIFY_BEGIN();
+ //Verify the checksum
+ sha1_starts(&ctx);
+ sha1_update(&ctx, kptr, OUT_PTR - kptr);
+ sha1_update(&ctx, antiReplay.digest, TPM_DIGEST_SIZE);
+ sha1_finish(&ctx, digest);
- ptr = unpack_UINT32(ptr, olen);
- if(*olen > ilen) {
- vtpmlogerror(VTPM_LOG_TPM, "Output length < input length!\n");
- status = TPM_IOERROR;
- goto abort_egress;
- }
- ptr = unpack_BUFFER(ptr, out, *olen);
+ UNPACK_OUT(TPM_DIGEST, &antiReplay);
- TPM_AUTH_HASH();
+ TPM_END();
- TPM_AUTH1_VERIFY(usage_auth, auth);
+ //ptr points to the checksum computed by TPM
+ if(memcmp(digest, antiReplay.digest, TPM_DIGEST_SIZE)) {
+ vtpmlogerror(VTPM_LOG_TPM, "TPM_ReadPubek: Checksum returned by TPM was invalid!\n");
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+ goto egress;
abort_egress:
+ if(kptr != NULL) { //If we unpacked the pubEK, we have to free it
+ free_TPM_PUBKEY(pubEK);
+ }
egress:
- TPM_AUTH_ERR_CHECK(auth);
- return status;
+ return status;
}
-TPM_RESULT TPM_CreateWrapKey(
- TPM_KEY_HANDLE hWrappingKey, // in
- const TPM_AUTHDATA* osapSharedSecret,
- const TPM_AUTHDATA* dataUsageAuth, //in
- const TPM_AUTHDATA* dataMigrationAuth, //in
- TPM_KEY* key, //in, out
- TPM_AUTH_SESSION* pAuth) // in, out
+TPM_RESULT TPM_PCR_Read(UINT32 pcr, TPM_DIGEST *value)
{
- int keyAlloced = 0;
- TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_CreateWrapKey);
- TPM_AUTH_BEGIN();
-
- TPM_AUTH_HASH();
-
- ptr = pack_TPM_KEY_HANDLE(ptr, hWrappingKey);
-
- TPM_AUTH_SKIP();
-
- //Encrypted auths
- xorEncrypt(osapSharedSecret, &pAuth->NonceEven,
- dataUsageAuth, ptr,
- dataMigrationAuth, ptr + sizeof(TPM_ENCAUTH));
- ptr += sizeof(TPM_ENCAUTH) * 2;
-
- ptr = pack_TPM_KEY(ptr, key);
-
- TPM_AUTH_HASH();
-
- TPM_AUTH1_GEN(osapSharedSecret, pAuth);
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
- TPM_AUTH_VERIFY_BEGIN();
-
- keyAlloced = 1;
- ptr = unpack_TPM_KEY(ptr, key, UNPACK_ALLOC);
-
- TPM_AUTH_HASH();
-
- TPM_AUTH1_VERIFY(osapSharedSecret, pAuth);
-
- goto egress;
+ TPM_BEGIN_CMD(TPM_ORD_PcrRead);
+ PACK_IN(UINT32, pcr);
+ TPM_XMIT_REQ();
+ UNPACK_OUT(TPM_DIGEST, value);
+ TPM_END();
abort_egress:
- if(keyAlloced) {
- free_TPM_KEY(key);
- }
-egress:
- TPM_AUTH_ERR_CHECK(pAuth);
- return status;
+ return status;
}
-TPM_RESULT TPM_LoadKey(
- TPM_KEY_HANDLE parentHandle, //
- const TPM_KEY* key, //in
- TPM_HANDLE* keyHandle, // out
- const TPM_AUTHDATA* usage_auth,
- TPM_AUTH_SESSION* auth)
+TPM_RESULT TPM_SaveState(void)
{
- TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_LoadKey);
- TPM_AUTH_BEGIN();
-
- TPM_AUTH_HASH();
-
- ptr = pack_TPM_KEY_HANDLE(ptr, parentHandle);
-
- TPM_AUTH_SKIP();
-
- ptr = pack_TPM_KEY(ptr, key);
-
- TPM_AUTH_HASH();
-
- TPM_AUTH1_GEN(usage_auth, auth);
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
- TPM_AUTH_VERIFY_BEGIN();
-
- ptr = unpack_UINT32(ptr, keyHandle);
-
- TPM_AUTH_HASH();
-
- TPM_AUTH1_VERIFY(usage_auth, auth);
-
- vtpmloginfo(VTPM_LOG_TPM, "Key Handle: 0x%x opened by TPM_LoadKey\n", *keyHandle);
+ TPM_BEGIN_CMD(TPM_ORD_SaveState);
+ TPM_XMIT_REQ();
+ TPM_END();
abort_egress:
- TPM_AUTH_ERR_CHECK(auth);
- return status;
+ return status;
}
-TPM_RESULT TPM_EvictKey( TPM_KEY_HANDLE hKey) // in
+TPM_RESULT TPM_GetCapability(
+ TPM_CAPABILITY_AREA capArea,
+ UINT32 subCapSize,
+ const BYTE* subCap,
+ UINT32* respSize,
+ BYTE** resp)
{
- if(hKey == 0) {
- return TPM_SUCCESS;
- }
+ TPM_BEGIN_CMD(TPM_ORD_GetCapability);
- TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_EvictKey);
+ PACK_IN(TPM_CAPABILITY_AREA, capArea);
+ PACK_IN(UINT32, subCapSize);
+ PACK_IN(BUFFER, subCap, subCapSize);
- ptr = pack_TPM_KEY_HANDLE(ptr, hKey);
+ TPM_XMIT_REQ();
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
+ UNPACK_OUT(UINT32, respSize);
+ UNPACK_OUT(PTR, resp, *respSize, UNPACK_ALLOC);
- vtpmloginfo(VTPM_LOG_TPM, "Key handle: 0x%x closed by TPM_EvictKey\n", hKey);
+ TPM_END();
abort_egress:
- return status;
+ return status;
}
-TPM_RESULT TPM_FlushSpecific(TPM_HANDLE handle,
- TPM_RESOURCE_TYPE rt) {
- if(handle == 0) {
- return TPM_SUCCESS;
- }
-
- TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_FlushSpecific);
-
- ptr = pack_TPM_HANDLE(ptr, handle);
- ptr = pack_TPM_RESOURCE_TYPE(ptr, rt);
-
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
+TPM_RESULT TPM_CreateEndorsementKeyPair(
+ const TPM_KEY_PARMS* keyInfo,
+ TPM_PUBKEY* pubEK)
+{
+ BYTE* kptr = NULL;
+ sha1_context ctx;
+ TPM_DIGEST checksum;
+ TPM_DIGEST hash;
+ TPM_NONCE antiReplay;
+ TPM_BEGIN_CMD(TPM_ORD_CreateEndorsementKeyPair);
-abort_egress:
- return status;
-}
+ //Make anti replay nonce
+ vtpmmgr_rand(antiReplay.nonce, sizeof(antiReplay.nonce));
-TPM_RESULT TPM_GetRandom( UINT32* bytesRequested, // in, out
- BYTE* randomBytes) // out
-{
- TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_GetRandom);
+ PACK_IN(TPM_NONCE, &antiReplay);
+ PACK_IN(TPM_KEY_PARMS, keyInfo);
- // check input params
- if (bytesRequested == NULL || randomBytes == NULL){
- return TPM_BAD_PARAMETER;
- }
+ TPM_XMIT_REQ();
- ptr = pack_UINT32(ptr, *bytesRequested);
+ kptr = OUT_PTR;
+ UNPACK_OUT(TPM_PUBKEY, pubEK, UNPACK_ALLOC);
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
+ /* Hash the pub key blob */
+ sha1_starts(&ctx);
+ sha1_update(&ctx, kptr, OUT_PTR - kptr);
+ sha1_update(&ctx, antiReplay.nonce, sizeof(antiReplay.nonce));
+ sha1_finish(&ctx, hash.digest);
- ptr = unpack_UINT32(ptr, bytesRequested);
- ptr = unpack_BUFFER(ptr, randomBytes, *bytesRequested);
+ UNPACK_OUT(TPM_DIGEST, &checksum);
-abort_egress:
- return status;
-}
+ TPM_END();
+ if (memcmp(checksum.digest, hash.digest, TPM_DIGEST_SIZE)) {
+ vtpmloginfo(VTPM_LOG_VTPM, "TPM_CreateEndorsementKey: Checkum verification failed!\n");
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
-TPM_RESULT TPM_ReadPubek(
- TPM_PUBKEY* pubEK //out
- )
-{
- BYTE* antiReplay = NULL;
- BYTE* kptr = NULL;
- BYTE digest[TPM_DIGEST_SIZE];
- sha1_context ctx;
-
- TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_ReadPubek);
-
- //antiReplay nonce
- vtpmmgr_rand(ptr, TPM_DIGEST_SIZE);
- antiReplay = ptr;
- ptr += TPM_DIGEST_SIZE;
-
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
-
- //unpack and allocate the key
- kptr = ptr;
- ptr = unpack_TPM_PUBKEY(ptr, pubEK, UNPACK_ALLOC);
-
- //Verify the checksum
- sha1_starts(&ctx);
- sha1_update(&ctx, kptr, ptr - kptr);
- sha1_update(&ctx, antiReplay, TPM_DIGEST_SIZE);
- sha1_finish(&ctx, digest);
-
- //ptr points to the checksum computed by TPM
- if(memcmp(digest, ptr, TPM_DIGEST_SIZE)) {
- vtpmlogerror(VTPM_LOG_TPM, "TPM_ReadPubek: Checksum returned by TPM was invalid!\n");
- status = TPM_FAIL;
- goto abort_egress;
- }
-
- goto egress;
+ goto egress;
abort_egress:
- if(kptr != NULL) { //If we unpacked the pubEK, we have to free it
- free_TPM_PUBKEY(pubEK);
- }
+ if(kptr) {
+ free_TPM_PUBKEY(pubEK);
+ }
egress:
- return status;
+ return status;
}
-
-TPM_RESULT TPM_SaveState(void)
+TPM_RESULT TPM_MakeIdentity(
+ const TPM_AUTHDATA* identityAuth, // in
+ const TPM_AUTHDATA* privCADigest, // in
+ const TPM_KEY* kinfo, // in
+ const TPM_AUTHDATA* srk_auth, // in
+ const TPM_AUTHDATA* own_auth, // in
+ TPM_AUTH_SESSION* srkAuth, // in,out
+ TPM_AUTH_SESSION* ownAuth, // in,out
+ TPM_KEY* key, // out
+ UINT32* identityBindingSize, // out
+ BYTE** identityBinding) // out
{
- TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_SaveState);
+ TPM_BEGIN_CMD(TPM_ORD_MakeIdentity);
+ TPM_HASH_IN_BEGIN;
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
+ xorEncrypt(own_auth, &ownAuth->NonceEven, identityAuth, IN_PTR, NULL, NULL);
+ in_pos += sizeof(TPM_ENCAUTH);
-abort_egress:
- return status;
-}
-
-TPM_RESULT TPM_GetCapability(
- TPM_CAPABILITY_AREA capArea,
- UINT32 subCapSize,
- const BYTE* subCap,
- UINT32* respSize,
- BYTE** resp)
-{
- TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_GetCapability);
+ PACK_IN(TPM_AUTHDATA, privCADigest);
+ PACK_IN(TPM_KEY, kinfo);
- ptr = pack_TPM_CAPABILITY_AREA(ptr, capArea);
- ptr = pack_UINT32(ptr, subCapSize);
- ptr = pack_BUFFER(ptr, subCap, subCapSize);
+ TPM_XMIT_AUTH2(srk_auth, srkAuth, own_auth, ownAuth);
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
+ UNPACK_OUT(TPM_KEY, key, UNPACK_ALLOC);
+ UNPACK_OUT(UINT32, identityBindingSize);
+ UNPACK_OUT(PTR, identityBinding, *identityBindingSize, UNPACK_ALLOC);
- ptr = unpack_UINT32(ptr, respSize);
- ptr = unpack_ALLOC(ptr, resp, *respSize);
+ TPM_END_AUTH2(srk_auth, srkAuth, own_auth, ownAuth);
abort_egress:
- return status;
+ TPM_AUTH_ERR_CHECK(srkAuth);
+ TPM_AUTH_ERR_CHECK(ownAuth);
+ return status;
}
-TPM_RESULT TPM_CreateEndorsementKeyPair(
- const TPM_KEY_PARMS* keyInfo,
- TPM_PUBKEY* pubEK)
+TPM_RESULT TPM_ActivateIdentity(
+ TPM_KEY_HANDLE aikHandle, // in
+ BYTE* blob, // in
+ UINT32 blobSize, // in
+ const TPM_AUTHDATA* aik_auth, // in
+ const TPM_AUTHDATA* owner_auth, // in
+ TPM_AUTH_SESSION* aikAuth, // in,out
+ TPM_AUTH_SESSION* ownAuth, // in,out
+ TPM_SYMMETRIC_KEY* symKey) // out
{
- BYTE* kptr = NULL;
- sha1_context ctx;
- TPM_DIGEST checksum;
- TPM_DIGEST hash;
- TPM_NONCE antiReplay;
- TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_CreateEndorsementKeyPair);
+ TPM_BEGIN_CMD(TPM_ORD_ActivateIdentity);
+ PACK_IN(TPM_KEY_HANDLE, aikHandle);
+ TPM_HASH_IN_BEGIN;
+ PACK_IN(UINT32, blobSize);
+ PACK_IN(BUFFER, blob, blobSize);
+
+ TPM_XMIT_AUTH2(aik_auth, aikAuth, owner_auth, ownAuth);
- //Make anti replay nonce
- vtpmmgr_rand(antiReplay.nonce, sizeof(antiReplay.nonce));
+ UNPACK_OUT(TPM_SYMMETRIC_KEY, symKey, UNPACK_ALLOC);
- ptr = pack_TPM_NONCE(ptr, &antiReplay);
- ptr = pack_TPM_KEY_PARMS(ptr, keyInfo);
+ TPM_END_AUTH2(aik_auth, aikAuth, owner_auth, ownAuth);
- TPM_TRANSMIT();
- TPM_UNPACK_VERIFY();
-
- sha1_starts(&ctx);
+abort_egress:
+ TPM_AUTH_ERR_CHECK(aikAuth);
+ TPM_AUTH_ERR_CHECK(ownAuth);
+ return status;
+}
- kptr = ptr;
- ptr = unpack_TPM_PUBKEY(ptr, pubEK, UNPACK_ALLOC);
+TPM_RESULT TPM_Quote(
+ TPM_KEY_HANDLE keyh, // in
+ const TPM_NONCE* data, // in
+ const TPM_PCR_SELECTION *pcrSelect, // in
+ const TPM_AUTHDATA* auth, // in
+ TPM_AUTH_SESSION* oiap, // in,out
+ TPM_PCR_COMPOSITE *pcrs, // out
+ BYTE** sig, // out
+ UINT32* sigSize) // out
+{
+ TPM_BEGIN_CMD(TPM_ORD_Quote);
+ PACK_IN(TPM_KEY_HANDLE, keyh);
+ TPM_HASH_IN_BEGIN;
+ PACK_IN(TPM_NONCE, data);
+ PACK_IN(TPM_PCR_SELECTION, pcrSelect);
- /* Hash the pub key blob */
- sha1_update(&ctx, kptr, ptr - kptr);
- ptr = unpack_TPM_DIGEST(ptr, &checksum);
+ TPM_XMIT_AUTH1(auth, oiap);
- sha1_update(&ctx, antiReplay.nonce, sizeof(antiReplay.nonce));
+ UNPACK_OUT(TPM_PCR_COMPOSITE, pcrs, UNPACK_ALLOC);
+ UNPACK_OUT(UINT32, sigSize);
+ UNPACK_OUT(PTR, sig, *sigSize, UNPACK_ALLOC);
- sha1_finish(&ctx, hash.digest);
- if(memcmp(checksum.digest, hash.digest, TPM_DIGEST_SIZE)) {
- vtpmloginfo(VTPM_LOG_VTPM, "TPM_CreateEndorsementKey: Checkum verification failed!\n");
- status = TPM_FAIL;
- goto abort_egress;
- }
+ TPM_END_AUTH1(auth, oiap);
- goto egress;
abort_egress:
- if(kptr) {
- free_TPM_PUBKEY(pubEK);
- }
-egress:
- return status;
+ TPM_AUTH_ERR_CHECK(oiap);
+ return status;
}
TPM_RESULT TPM_TransmitData(
- BYTE* in,
- UINT32 insize,
- BYTE* out,
- UINT32* outsize) {
- TPM_RESULT status = TPM_SUCCESS;
-
- UINT32 i;
- vtpmloginfo(VTPM_LOG_TXDATA, "Sending buffer = 0x");
- for(i = 0 ; i < insize ; i++)
- vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", in[i]);
-
- vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
-
- ssize_t size = 0;
-
- // send the request
- size = write (vtpm_globals.tpm_fd, in, insize);
- if (size < 0) {
- vtpmlogerror(VTPM_LOG_TXDATA, "write() failed : %s\n", strerror(errno));
- ERRORDIE (TPM_IOERROR);
- }
- else if ((UINT32) size < insize) {
- vtpmlogerror(VTPM_LOG_TXDATA, "Wrote %d instead of %d bytes!\n", (int) size, insize);
- ERRORDIE (TPM_IOERROR);
- }
-
- // read the response
- size = read (vtpm_globals.tpm_fd, out, *outsize);
- if (size < 0) {
- vtpmlogerror(VTPM_LOG_TXDATA, "read() failed : %s\n", strerror(errno));
- ERRORDIE (TPM_IOERROR);
- }
-
- vtpmloginfo(VTPM_LOG_TXDATA, "Receiving buffer = 0x");
- for(i = 0 ; i < size ; i++)
- vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", out[i]);
-
- vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
-
- *outsize = size;
- goto egress;
+ BYTE* in,
+ UINT32 insize,
+ BYTE* out,
+ UINT32* outsize) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ UINT32 i;
+ vtpmloginfo(VTPM_LOG_TXDATA, "Sending buffer = 0x");
+ for(i = 0 ; i < insize ; i++)
+ vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", in[i]);
+
+ vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
+
+ ssize_t size = 0;
+
+ // send the request
+ size = write (vtpm_globals.tpm_fd, in, insize);
+ if (size < 0) {
+ vtpmlogerror(VTPM_LOG_TXDATA, "write() failed : %s\n", strerror(errno));
+ ERRORDIE (TPM_IOERROR);
+ }
+ else if ((UINT32) size < insize) {
+ vtpmlogerror(VTPM_LOG_TXDATA, "Wrote %d instead of %d bytes!\n", (int) size, insize);
+ ERRORDIE (TPM_IOERROR);
+ }
+
+ // read the response
+ size = read (vtpm_globals.tpm_fd, out, *outsize);
+ if (size < 0) {
+ vtpmlogerror(VTPM_LOG_TXDATA, "read() failed : %s\n", strerror(errno));
+ ERRORDIE (TPM_IOERROR);
+ }
+
+ vtpmloginfo(VTPM_LOG_TXDATA, "Receiving buffer = 0x");
+ for(i = 0 ; i < size ; i++)
+ vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", out[i]);
+
+ vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
+
+ *outsize = size;
+ goto egress;
abort_egress:
egress:
- return status;
+ return status;
}
diff --git a/stubdom/vtpmmgr/tpm.h b/stubdom/vtpmmgr/tpm.h
index 304e145..d613eb3 100644
--- a/stubdom/vtpmmgr/tpm.h
+++ b/stubdom/vtpmmgr/tpm.h
@@ -80,30 +80,19 @@ TPM_RESULT TPM_FlushSpecific ( TPM_HANDLE handle, // in
// TPM Mandatory
TPM_RESULT TPM_Extend ( TPM_PCRINDEX pcrNum, // in
- TPM_DIGEST inDigest, // in
+ TPM_DIGEST* inDigest, // in
TPM_PCRVALUE* outDigest // out
);
-TPM_RESULT TPM_PcrRead ( TPM_PCRINDEX pcrNum, // in
- TPM_PCRVALUE* outDigest // out
- );
-
-TPM_RESULT TPM_Quote ( TCS_KEY_HANDLE keyHandle, // in
- TPM_NONCE antiReplay, // in
- UINT32* PcrDataSize, // in, out
- BYTE** PcrData, // in, out
- TPM_AUTH_SESSION* privAuth, // in, out
- UINT32* sigSize, // out
- BYTE** sig // out
- );
+TPM_RESULT TPM_Reset(TPM_PCR_SELECTION *sel);
TPM_RESULT TPM_Seal(
TCS_KEY_HANDLE keyHandle, // in
- UINT32 pcrInfoSize, // in
- TPM_PCR_INFO* pcrInfo, // in
+ UINT32 pcrInfoLongSize, // in
+ TPM_PCR_INFO_LONG* pcrInfoLong, // in
UINT32 inDataSize, // in
const BYTE* inData, // in
- TPM_STORED_DATA* sealedData, //out
+ TPM_STORED_DATA12* sealedData, //out
const TPM_SECRET* osapSharedSecret, //in
const TPM_AUTHDATA* sealDataAuth, //in
TPM_AUTH_SESSION* pubAuth // in, out
@@ -111,7 +100,7 @@ TPM_RESULT TPM_Seal(
TPM_RESULT TPM_Unseal (
TPM_KEY_HANDLE parentHandle, // in
- const TPM_STORED_DATA* sealedData,
+ const TPM_STORED_DATA12* sealedData,
UINT32* outSize, // out
BYTE** out, //out
const TPM_AUTHDATA* key_usage_auth, //in
@@ -120,41 +109,6 @@ TPM_RESULT TPM_Unseal (
TPM_AUTH_SESSION* dataAuth // in, out
);
-TPM_RESULT TPM_DirWriteAuth ( TPM_DIRINDEX dirIndex, // in
- TPM_DIRVALUE newContents, // in
- TPM_AUTH_SESSION* ownerAuth // in, out
- );
-
-TPM_RESULT TPM_DirRead ( TPM_DIRINDEX dirIndex, // in
- TPM_DIRVALUE* dirValue // out
- );
-
-TPM_RESULT TPM_Bind(
- const TPM_KEY* key, //in
- const BYTE* in, //in
- UINT32 ilen, //in
- BYTE* out //out, must be at least cipher block size
- );
-
-TPM_RESULT TPM_UnBind (
- TCS_KEY_HANDLE keyHandle, // in
- UINT32 ilen, //in
- const BYTE* in, //
- UINT32* outDataSize, // out
- BYTE* outData, //out
- const TPM_AUTHDATA* usage_auth,
- TPM_AUTH_SESSION* auth //in, out
- );
-
-TPM_RESULT TPM_CreateWrapKey (
- TCS_KEY_HANDLE hWrappingKey, // in
- const TPM_AUTHDATA* osapSharedSecret,
- const TPM_AUTHDATA* dataUsageAuth, //in
- const TPM_AUTHDATA* dataMigrationAuth, //in
- TPM_KEY* key, //in
- TPM_AUTH_SESSION* pAuth // in, out
- );
-
TPM_RESULT TPM_LoadKey (
TPM_KEY_HANDLE parentHandle, //
const TPM_KEY* key, //in
@@ -163,35 +117,14 @@ TPM_RESULT TPM_LoadKey (
TPM_AUTH_SESSION* auth
);
-TPM_RESULT TPM_GetPubKey ( TCS_KEY_HANDLE hKey, // in
- TPM_AUTH_SESSION* pAuth, // in, out
- UINT32* pcPubKeySize, // out
- BYTE** prgbPubKey // out
- );
-
-TPM_RESULT TPM_EvictKey ( TCS_KEY_HANDLE hKey // in
- );
-
TPM_RESULT TPM_FlushSpecific(TPM_HANDLE handle, //in
TPM_RESOURCE_TYPE rt //in
);
-TPM_RESULT TPM_Sign ( TCS_KEY_HANDLE keyHandle, // in
- UINT32 areaToSignSize, // in
- BYTE* areaToSign, // in
- TPM_AUTH_SESSION* privAuth, // in, out
- UINT32* sigSize, // out
- BYTE** sig // out
- );
-
TPM_RESULT TPM_GetRandom ( UINT32* bytesRequested, // in, out
BYTE* randomBytes // out
);
-TPM_RESULT TPM_StirRandom ( UINT32 inDataSize, // in
- BYTE* inData // in
- );
-
TPM_RESULT TPM_ReadPubek (
TPM_PUBKEY* pubEK //out
);
@@ -203,12 +136,45 @@ TPM_RESULT TPM_GetCapability(
UINT32* respSize,
BYTE** resp);
+TPM_RESULT TPM_PCR_Read(UINT32 pcr, TPM_DIGEST *value);
TPM_RESULT TPM_SaveState(void);
TPM_RESULT TPM_CreateEndorsementKeyPair(
const TPM_KEY_PARMS* keyInfo,
TPM_PUBKEY* pubEK);
+TPM_RESULT TPM_MakeIdentity(
+ const TPM_AUTHDATA* identityAuth, // in
+ const TPM_AUTHDATA* privCADigest, // in
+ const TPM_KEY* kinfo, // in
+ const TPM_AUTHDATA* srk_auth, // in
+ const TPM_AUTHDATA* owner_auth, // in
+ TPM_AUTH_SESSION* srkAuth, // in,out
+ TPM_AUTH_SESSION* ownAuth, // in,out
+ TPM_KEY* key, // out
+ UINT32* identityBindingSize, // out
+ BYTE** identityBinding); // out
+
+TPM_RESULT TPM_ActivateIdentity(
+ TPM_KEY_HANDLE aikHandle, // in
+ BYTE* blob, // in
+ UINT32 blobSize, // in
+ const TPM_AUTHDATA* aik_auth, // in
+ const TPM_AUTHDATA* owner_auth, // in
+ TPM_AUTH_SESSION* aikAuth, // in,out
+ TPM_AUTH_SESSION* ownAuth, // in,out
+ TPM_SYMMETRIC_KEY* symKey); // out
+
+TPM_RESULT TPM_Quote(
+ TPM_KEY_HANDLE keyh, // in
+ const TPM_NONCE* data, // in
+ const TPM_PCR_SELECTION *pcrSelect, // in
+ const TPM_AUTHDATA* auth, // in
+ TPM_AUTH_SESSION* oiap, // in,out
+ TPM_PCR_COMPOSITE *pcrs, // out
+ BYTE** sig, // out
+ UINT32* sigSize); // out
+
TPM_RESULT TPM_TransmitData(
BYTE* in,
UINT32 insize,
diff --git a/stubdom/vtpmmgr/tpmrsa.c b/stubdom/vtpmmgr/tpmrsa.c
index 56094e7..2a2fa36 100644
--- a/stubdom/vtpmmgr/tpmrsa.c
+++ b/stubdom/vtpmmgr/tpmrsa.c
@@ -89,6 +89,31 @@ cleanup:
return TPM_SUCCESS;
}
+static const unsigned char rsa_der_header[] = {
+ 0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14,
+};
+
+TPM_RESULT tpmrsa_sigcheck(tpmrsa_context *ctx, const unsigned char *input, const unsigned char *sha1)
+{
+ unsigned char *tmp = alloca(ctx->len);
+ TPM_RESULT rv;
+ int i;
+ rv = tpmrsa_public(ctx, input, tmp);
+ if (rv)
+ return rv;
+ if (tmp[0] != 0 || tmp[1] != 1)
+ return TPM_INAPPROPRIATE_SIG;
+ for(i=2; i < 220; i++) {
+ if (tmp[i] != 0xFF)
+ return TPM_INAPPROPRIATE_SIG;
+ }
+ if (memcmp(tmp + 220, rsa_der_header, sizeof(rsa_der_header)))
+ return TPM_INAPPROPRIATE_SIG;
+ if (memcmp(tmp + 236, sha1, 20))
+ return TPM_DECRYPT_ERROR;
+ return TPM_SUCCESS;
+}
+
static void mgf_mask( unsigned char *dst, int dlen, unsigned char *src, int slen)
{
unsigned char mask[HASH_LEN];
diff --git a/stubdom/vtpmmgr/tpmrsa.h b/stubdom/vtpmmgr/tpmrsa.h
index 59579e7..31e5a8b 100644
--- a/stubdom/vtpmmgr/tpmrsa.h
+++ b/stubdom/vtpmmgr/tpmrsa.h
@@ -51,6 +51,9 @@ void tpmrsa_set_pubkey(tpmrsa_context* ctx,
const unsigned char* exponent,
int explen);
+/* Check an RSA signature */
+TPM_RESULT tpmrsa_sigcheck(tpmrsa_context *ctx, const unsigned char *input, const unsigned char *sha1);
+
/* Do rsa public crypto */
TPM_RESULT tpmrsa_pub_encrypt_oaep( tpmrsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
diff --git a/stubdom/vtpmmgr/vtpm_cmd_handler.c b/stubdom/vtpmmgr/vtpm_cmd_handler.c
index f82a2a9..13ead93 100644
--- a/stubdom/vtpmmgr/vtpm_cmd_handler.c
+++ b/stubdom/vtpmmgr/vtpm_cmd_handler.c
@@ -37,116 +37,843 @@
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
+#include <mini-os/console.h>
+#include <mini-os/lib.h>
+#include <polarssl/sha1.h>
+#include <polarssl/sha2.h>
#include "marshal.h"
#include "log.h"
-#include "vtpm_storage.h"
+#include "vtpm_disk.h"
#include "vtpmmgr.h"
#include "tpm.h"
+#include "tpmrsa.h"
#include "tcg.h"
+#include "mgmt_authority.h"
+#include "disk_crypto.h"
-static TPM_RESULT vtpmmgr_SaveHashKey(
- const uuid_t uuid,
- tpmcmd_t* tpmcmd)
+static void gen_random_uuid(uuid_t uuid)
{
- TPM_RESULT status = TPM_SUCCESS;
+ do_random(uuid, 16);
+ // make the 128-bit random number a valid UUID (122 bits remain)
+ uuid[6] = 0x40 | (uuid[6] & 0x0F);
+ uuid[8] = 0x80 | (uuid[8] & 0x3F);
+}
+
+/*
+ * Instead of using a kernel hash, which requires a trusted domain builder to
+ * report, use the XSM label as a substitute.
+ */
+static TPM_RESULT find_vtpm_khash(int domid, struct tpm_opaque *opq)
+{
+ char buf[128];
+ int i, rv;
+ buf[127] = 0;
+ rv = tpmback_get_peercontext(opq->domid, opq->handle, buf, sizeof(buf) - 1);
+ if (rv < 0)
+ return TPM_FAIL;
+
+ sha1((void*)buf, strlen(buf), opq->kern_hash);
+
+ /*
+ * As a hack to support the use of the XSM user field as an optional
+ * wildcard, check the hash against the group here. If it fails, replace
+ * the user field with a "*" and return the hash of that value.
+ */
+ for(i=0; i < be32_native(opq->group->seal_bits.nr_kerns); i++) {
+ if (!memcmp(opq->group->seal_bits.kernels[i].bits, opq->kern_hash, 20)) {
+ return TPM_SUCCESS;
+ }
+ }
+
+ char* upos = strchr(buf, ':');
+ if (upos == NULL || upos == buf)
+ return TPM_SUCCESS;
+
+ upos--;
+ upos[0] = '*';
+
+ sha1((void*)upos, strlen(upos), opq->kern_hash);
+ return TPM_SUCCESS;
+}
+
+static TPM_RESULT find_vtpm_verified(int domid, struct tpm_opaque *opq)
+{
+ TPM_RESULT rc;
+ int i;
+ if (opq->vtpm)
+ return TPM_SUCCESS;
+
+ rc = find_vtpm(&opq->group, &opq->vtpm, *opq->uuid);
+ if (rc)
+ return TPM_BAD_PARAMETER;
+
+ if (opq->vtpm->flags & VTPM_FLAG_OPEN) {
+ printk("Attempted to open vTPM twice!\n");
+ opq->vtpm = NULL;
+ opq->group = NULL;
+ return TPM_DISABLED;
+ }
+
+ rc = find_vtpm_khash(domid, opq);
+ if (rc)
+ return rc;
+
+ for(i=0; i < be32_native(opq->group->seal_bits.nr_kerns); i++) {
+ if (!memcmp(opq->group->seal_bits.kernels[i].bits, opq->kern_hash, 20)) {
+ opq->vtpm->flags |= VTPM_FLAG_OPEN;
+ return TPM_SUCCESS;
+ }
+ }
+ printk("Unauthorized vTPM kernel image used!\n");
+ return TPM_DISABLED;
+}
+
+static TPM_RESULT vtpmmgr_SaveHashKey(struct tpm_opaque *opq, tpmcmd_t* tpmcmd)
+{
+ TPM_RESULT status = TPM_SUCCESS;
+ int rc = 0;
+
+ size_t bufsize = tpmcmd->req_len - VTPM_COMMAND_HEADER_SIZE;
+ const void *buf = tpmcmd->req + VTPM_COMMAND_HEADER_SIZE;
- if(tpmcmd->req_len != VTPM_COMMAND_HEADER_SIZE + HASHKEYSZ) {
- vtpmlogerror(VTPM_LOG_VTPM, "VTPM_ORD_SAVEHASHKEY hashkey too short!\n");
- status = TPM_BAD_PARAMETER;
- goto abort_egress;
- }
+ if (bufsize < 52) {
+ vtpmlogerror(VTPM_LOG_VTPM, "VTPM_ORD_SAVEHASHKEY hashkey too short!\n");
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+ if (bufsize > 64) {
+ vtpmlogerror(VTPM_LOG_VTPM, "VTPM_ORD_SAVEHASHKEY hashkey too long!\n");
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
- /* Do the command */
- TPMTRYRETURN(vtpm_storage_save_hashkey(uuid, tpmcmd->req + VTPM_COMMAND_HEADER_SIZE));
+ vtpmloginfo(VTPM_LOG_VTPM, "vtpmmgr_SaveHashKey\n");
+ status = find_vtpm_verified(tpmcmd->domid, opq);
+
+ // auto-create vTPMs in group0 when saving a new UUID
+ // TODO restrict to certain UUIDs (such as all-zero)
+ // this is not done yet to simplify use of the TPM Manager
+ if (status == TPM_BAD_PARAMETER) {
+ opq->group = g_mgr->groups[0].v;
+ rc = create_vtpm(opq->group, &opq->vtpm, *opq->uuid);
+ if (rc) {
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+ if (opq->group->nr_vtpms == 1)
+ opq->vtpm->flags = VTPM_FLAG_ADMIN;
+ printk("SaveHashKey with unknown UUID="UUID_FMT" - creating in auth0 (f=%d)\n",
+ UUID_BYTES((*opq->uuid)), opq->vtpm->flags);
+ status = TPM_SUCCESS;
+ }
+ if (status)
+ goto abort_egress;
+
+ memcpy(opq->vtpm->data, buf, bufsize);
+ memset(opq->vtpm->data + bufsize, 0, 64 - bufsize);
+
+ vtpm_sync(opq->group, opq->vtpm);
abort_egress:
- pack_TPM_RSP_HEADER(tpmcmd->resp,
- VTPM_TAG_RSP, VTPM_COMMAND_HEADER_SIZE, status);
- tpmcmd->resp_len = VTPM_COMMAND_HEADER_SIZE;
+ pack_TPM_RSP_HEADER(tpmcmd->resp, VTPM_TAG_RSP, VTPM_COMMAND_HEADER_SIZE, status);
+ tpmcmd->resp_len = VTPM_COMMAND_HEADER_SIZE;
- return status;
+ return status;
}
-static TPM_RESULT vtpmmgr_LoadHashKey(
- const uuid_t uuid,
- tpmcmd_t* tpmcmd) {
- TPM_RESULT status = TPM_SUCCESS;
+static TPM_RESULT vtpmmgr_LoadHashKey(struct tpm_opaque *opq, tpmcmd_t* tpmcmd)
+{
+ TPM_RESULT status = TPM_SUCCESS;
+ int i;
+ uint8_t *buf = tpmcmd->resp + VTPM_COMMAND_HEADER_SIZE;
+
+ vtpmloginfo(VTPM_LOG_VTPM, "vtpmmgr_LoadHashKey\n");
+ tpmcmd->resp_len = VTPM_COMMAND_HEADER_SIZE;
- tpmcmd->resp_len = VTPM_COMMAND_HEADER_SIZE;
+ status = find_vtpm_verified(tpmcmd->domid, opq);
+ if (status)
+ goto abort_egress;
- TPMTRYRETURN(vtpm_storage_load_hashkey(uuid, tpmcmd->resp + VTPM_COMMAND_HEADER_SIZE));
+ memcpy(buf, opq->vtpm->data, 64);
- tpmcmd->resp_len += HASHKEYSZ;
+ for(i=52; i < 64; i++) {
+ if (buf[i]) {
+ tpmcmd->resp_len += 64;
+ goto abort_egress;
+ }
+ }
+ tpmcmd->resp_len += 52;
abort_egress:
- pack_TPM_RSP_HEADER(tpmcmd->resp,
- VTPM_TAG_RSP, tpmcmd->resp_len, status);
+ pack_TPM_RSP_HEADER(tpmcmd->resp, VTPM_TAG_RSP, tpmcmd->resp_len, status);
+
+ return status;
+}
+
+#define CMD_BEGIN \
+ TPM_RESULT status = TPM_SUCCESS; \
+ uint32_t in_pos = VTPM_COMMAND_HEADER_SIZE; \
+ tpmcmd->resp_len = VTPM_COMMAND_HEADER_SIZE; \
+ vtpmloginfo(VTPM_LOG_TPM, "%s\n", __func__);
+
+#define CMD_END \
+ abort_egress: \
+ if (status) \
+ tpmcmd->resp_len = VTPM_COMMAND_HEADER_SIZE; \
+ pack_TPM_RSP_HEADER(tpmcmd->resp, VTPM_TAG_RSP, tpmcmd->resp_len, status); \
+ return status
+
+#define UNPACK_IN(type, item...) do { \
+ status = unpack3_ ## type (tpmcmd->req, &in_pos, tpmcmd->req_len, item); \
+ if (status) { \
+ status = TPM_BAD_PARAMETER; \
+ goto abort_egress; \
+ } \
+} while (0)
+
+#define UNPACK_GROUP(group) do { \
+ uint32_t group_idx; \
+ UNPACK_IN(UINT32, &group_idx); \
+ if (group_idx >= g_mgr->nr_groups) { \
+ status = TPM_BADINDEX; \
+ goto abort_egress; \
+ } \
+ group = g_mgr->groups[group_idx].v; \
+ if (!group) { \
+ status = TPM_AUTHFAIL; \
+ goto abort_egress; \
+ } \
+} while (0)
+
+#define UNPACK_DONE() do { \
+ if (in_pos != tpmcmd->req_len) { \
+ status = TPM_BAD_PARAMETER; \
+ goto abort_egress; \
+ } \
+} while (0)
+
+#define PACK_OUT(type, item...) do { \
+ UINT32 isize = sizeof_ ## type(item); \
+ if (isize + tpmcmd->resp_len > TCPA_MAX_BUFFER_LENGTH) { \
+ status = TPM_SIZE; \
+ goto abort_egress; \
+ } \
+ pack_ ## type (tpmcmd->resp + tpmcmd->resp_len, item); \
+ tpmcmd->resp_len += isize; \
+} while (0)
+
+#define PACK_BUF ((void*)(tpmcmd->resp + tpmcmd->resp_len))
+
+static TPM_RESULT vtpmmgr_GetBootHash(struct tpm_opaque *opq, tpmcmd_t* tpmcmd)
+{
+ CMD_BEGIN;
+ UNPACK_DONE();
+
+ PACK_OUT(BUFFER, opq->kern_hash, 20);
+
+ CMD_END;
+}
+
+static TPM_RESULT vtpmmgr_GetQuote(struct tpm_opaque *opq, tpmcmd_t* tpmcmd)
+{
+ CMD_BEGIN;
+ int i;
+ void *ibuf;
+ uint32_t pcr_size;
+ TPM_PCR_SELECTION sel;
+
+ UNPACK_IN(VPTR, &ibuf, 20, UNPACK_ALIAS);
+ UNPACK_IN(TPM_PCR_SELECTION, &sel, UNPACK_ALIAS);
+ UNPACK_DONE();
+
+ if (!opq->vtpm) {
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+ printk("ibuf: ");
+ for (i=0; i < 20; i++)
+ printk("%02x", ((uint8_t*)ibuf)[i]);
+ printk("\n");
+
+ status = vtpm_do_quote(opq->group, *opq->uuid, opq->kern_hash, ibuf, &sel, PACK_BUF + 256, &pcr_size, PACK_BUF);
+ if (status)
+ goto abort_egress;
+ tpmcmd->resp_len += 256 + pcr_size;
+
+ CMD_END;
+}
+
+static TPM_RESULT vtpmmgr_GroupList(tpmcmd_t* tpmcmd)
+{
+ CMD_BEGIN;
+ UNPACK_DONE();
+ PACK_OUT(UINT32, g_mgr->nr_groups);
+ CMD_END;
+}
+
+static TPM_RESULT vtpmmgr_GroupNew(tpmcmd_t* tpmcmd)
+{
+ void *privCADigest;
+ BYTE *pubkey;
+ struct mem_group *group;
+ uint32_t group_idx;
+ CMD_BEGIN;
+
+ UNPACK_IN(VPTR, &privCADigest, 20, UNPACK_ALIAS);
+ UNPACK_IN(PTR, &pubkey, 256, UNPACK_ALIAS);
+ UNPACK_DONE();
+
+ group = vtpm_new_group(privCADigest);
+ if (!group) {
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+
+ memcpy(group->id_data.saa_pubkey, pubkey, 256);
+
+ PACK_OUT(BUFFER, group->id_data.uuid, 16);
+ PACK_OUT(BUFFER, group->id_data.tpm_aik_public, 256);
+ PACK_OUT(BUFFER, group->details.recovery_data, 256);
+
+ memset(group->details.recovery_data, 0, 256);
+
+ group->details.sequence = native_be64(g_mgr->sequence);
+
+ if (group != g_mgr->groups[0].v) {
+ group_idx = g_mgr->nr_groups;
+ g_mgr->nr_groups++;
+ g_mgr->groups = realloc(g_mgr->groups, g_mgr->nr_groups*sizeof(struct mem_group_hdr));
+ memset(&g_mgr->groups[group_idx], 0, sizeof(g_mgr->groups[0]));
+ g_mgr->groups[group_idx].v = group;
+ }
+
+ vtpm_sync_group(group, SEQ_UPDATE);
+ CMD_END;
+}
+
+static TPM_RESULT vtpmmgr_GroupDel(tpmcmd_t* tpmcmd)
+{
+ CMD_BEGIN;
+ struct mem_group *group;
+ uint32_t group_idx, nr_mov;
+
+ UNPACK_IN(UINT32, &group_idx);
+ UNPACK_DONE();
+
+ if (group_idx > g_mgr->nr_groups) {
+ status = TPM_BADINDEX;
+ goto abort_egress;
+ }
+ group = g_mgr->groups[group_idx].v;
+
+ if (group) {
+ int i, j;
+ for (i = 0; i < group->nr_pages; i++) {
+ for (j = 0; j < group->data[i].size; j++) {
+ if (group->data[i].vtpms[j]->flags & VTPM_FLAG_OPEN) {
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+ }
+ }
+
+ for (i = 0; i < group->nr_pages; i++) {
+ for (j = 0; j < group->data[i].size; j++) {
+ free(group->data[i].vtpms[j]);
+ }
+ }
+ free(group->data);
+ free(group->seals);
+ free(group);
+ }
+
+ g_mgr->nr_groups--;
+ nr_mov = g_mgr->nr_groups - group_idx;
+ memmove(&g_mgr->groups[group_idx], &g_mgr->groups[group_idx + 1], nr_mov * sizeof(g_mgr->groups[0]));
+
+ vtpm_sync_disk(g_mgr, CTR_UPDATE);
+
+ CMD_END;
+}
+
+static int pack_cfg_list(void* buf, struct mem_group *group)
+{
+ int i;
+ void *bstart = buf;
+ memcpy(buf, &group->details.cfg_seq, 8); buf += 8;
+ buf = pack_UINT32(buf, group->nr_seals);
+ for(i=0; i < group->nr_seals; i++) {
+ memcpy(buf, &group->seals[i].digest_release, 20);
+ buf += 20;
+ }
+ memcpy(buf, &group->seal_bits.nr_kerns, 4); buf += 4;
+ memcpy(buf, &group->seal_bits.kernels, 20 * be32_native(group->seal_bits.nr_kerns));
+ return buf - bstart + 20 * be32_native(group->seal_bits.nr_kerns);
+}
+
+static TPM_RESULT vtpmmgr_GroupShow(tpmcmd_t* tpmcmd)
+{
+ CMD_BEGIN;
+ struct mem_group *group;
+
+ UNPACK_GROUP(group);
+ UNPACK_DONE();
+
+ // TODO show is read-only access, need to hit disk if group is NULL
+
+ PACK_OUT(BUFFER, group->id_data.uuid, 16);
+ PACK_OUT(BUFFER, group->id_data.saa_pubkey, 256);
+ tpmcmd->resp_len += pack_cfg_list(PACK_BUF, group);
- return status;
+ CMD_END;
}
+static TPM_RESULT vtpmmgr_GroupActivate(tpmcmd_t* tpmcmd)
+{
+ CMD_BEGIN;
+ struct mem_group *group;
+ uint32_t blobSize;
+ void *blob;
+
+ UNPACK_GROUP(group);
+ UNPACK_IN(UINT32, &blobSize);
+ UNPACK_IN(VPTR, &blob, blobSize, UNPACK_ALIAS);
+ UNPACK_DONE();
+
+ status = group_do_activate(group, blob, blobSize, tpmcmd->resp, &tpmcmd->resp_len);
+
+ CMD_END;
+}
+
+/* 2048-bit MODP Group from RFC3526:
+ * 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
+ */
+static uint8_t P_bytes[256] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+ 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+ 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+ 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+};
+static t_uint Gp[] = { 2 };
+
+static void tm_dhkx_gen(void* dhkx1, void* dhkx2, void* out)
+{
+ mpi GX = { 0 }, GY = { 0 }, K = { 0 }, RP = { 0 };
+ mpi P = { 0 };
+
+ t_uint Xp[sizeof(P_bytes) / sizeof(t_uint)];
+ mpi X = {
+ .s = 1,
+ .n = ARRAY_SIZE(Xp),
+ .p = Xp
+ };
+ mpi G = {
+ .s = 1,
+ .n = 1,
+ .p = Gp,
+ };
+ mpi_read_binary(&P, P_bytes, sizeof(P_bytes));
+
+ do_random(Xp, sizeof(Xp));
+
+ mpi_exp_mod(&GX, &G, &X, &P, &RP);
+ mpi_write_binary(&GX, dhkx2, 256);
+ mpi_free(&GX);
+
+ mpi_read_binary(&GY, dhkx1, 256);
+ mpi_exp_mod(&K, &GY, &X, &P, &RP);
+ mpi_free(&P);
+ mpi_free(&RP);
+ mpi_free(&GY);
+
+ mpi_write_binary(&K, (void*)Xp, 256);
+ mpi_free(&K);
+ sha2((void*)Xp, 256, out, 0);
+}
+
+static void xor2_256b(void *xv, const void* yv)
+{
+ int i;
+ uint64_t *x = xv;
+ const uint64_t *y = yv;
+ for(i=0; i < 4; i++)
+ x[i] ^= y[i];
+}
+
+static TPM_RESULT vtpmmgr_GroupRegister(tpmcmd_t* tpmcmd)
+{
+ CMD_BEGIN;
+ struct mem_group *group = NULL;
+ tpmrsa_context saa_rsa = TPMRSA_CTX_INIT;
+ struct tpm_authdata digest;
+ sha1_context ctx;
+ TPM_PCR_SELECTION sel;
+ void *dhkx1, *dhkx2, *gk, *sig;
+
+ UNPACK_GROUP(group);
+ UNPACK_IN(VPTR, &dhkx1, 256, UNPACK_ALIAS);
+ UNPACK_IN(VPTR, &sig, 256, UNPACK_ALIAS);
+ UNPACK_IN(TPM_PCR_SELECTION, &sel, UNPACK_ALIAS);
+ UNPACK_DONE();
+
+ /* Only generating this quote during the same boot that this group was
+ * created in allows the quote to prove that the group key has never
+ * been available outside a configuration approved by its SAA.
+ */
+ if (!(group->flags & MEM_GROUP_FLAG_FIRSTBOOT)) {
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+
+ sha1(dhkx1, 256, digest.bits);
+ tpmrsa_set_pubkey(&saa_rsa, group->id_data.saa_pubkey, 256, 0, 0);
+ if (tpmrsa_sigcheck(&saa_rsa, sig, digest.bits))
+ status = TPM_FAIL;
+ tpmrsa_free(&saa_rsa);
+ if (status)
+ goto abort_egress;
+
+ dhkx2 = PACK_BUF;
+ tpmcmd->resp_len += 256;
+ gk = PACK_BUF;
+ tpmcmd->resp_len += 32;
+
+ tm_dhkx_gen(dhkx1, dhkx2, gk);
+ xor2_256b(gk, &group->group_key);
+
+ sha1_starts(&ctx);
+ sha1_update(&ctx, (void*)"REGR", 4);
+ sha1_update(&ctx, dhkx1, 256);
+ sha1_update(&ctx, dhkx2, 256 + 32);
+ sha1_finish(&ctx, digest.bits);
+
+ status = vtpm_do_quote(group, NULL, NULL, &digest, &sel, NULL, NULL, PACK_BUF);
+ tpmcmd->resp_len += 256;
+
+ CMD_END;
+}
+
+static TPM_RESULT vtpmmgr_GroupUpdate(tpmcmd_t* tpmcmd)
+{
+ CMD_BEGIN;
+ struct mem_group *group;
+ int i;
+ int hstart;
+ uint32_t nr_kerns, nr_seals;
+ uint64_t old_seq, new_seq;
+ struct mem_seal *seals = NULL;
+ tpmrsa_context saa_rsa = TPMRSA_CTX_INIT;
+ unsigned char digest[20];
+ TPM_RESULT rc;
+ void *sig, *seal_bits, *kern_bits;
+
+ UNPACK_GROUP(group);
+ UNPACK_IN(VPTR, &sig, 256, UNPACK_ALIAS);
+
+ // Hash starts here
+ hstart = in_pos;
+
+ new_seq = be64_native(*(be64_t*)(tpmcmd->req + in_pos));
+ old_seq = be64_native(group->details.cfg_seq);
+ in_pos += 8;
+ if (old_seq > new_seq) {
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+
+ UNPACK_IN(UINT32, &nr_seals);
+ UNPACK_IN(VPTR, &seal_bits, nr_seals * 20, UNPACK_ALIAS);
+
+ UNPACK_IN(UINT32, &nr_kerns);
+ UNPACK_IN(VPTR, &kern_bits, nr_kerns * 20, UNPACK_ALIAS);
+
+ // TODO handle saving larger lists on disk
+ if (nr_seals > NR_SEALS_PER_GROUP) {
+ status = TPM_SIZE;
+ goto abort_egress;
+ }
+
+ if (nr_kerns > NR_KERNS_PER_GROUP) {
+ status = TPM_SIZE;
+ goto abort_egress;
+ }
+
+ sha1(tpmcmd->req + hstart, in_pos - hstart, digest);
+
+ seals = calloc(nr_seals, sizeof(seals[0]));
+
+ for(i=0; i < nr_seals; i++) {
+ TPM_PCR_SELECTION sel;
+ UNPACK_IN(TPM_PCR_SELECTION, &sel, UNPACK_ALIAS);
+ memcpy(&seals[i].digest_release, seal_bits, 20);
+ seal_bits += 20;
+ if (sel.sizeOfSelect > 4) {
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+ seals[i].pcr_selection = native_le32(0);
+ memcpy(&seals[i].pcr_selection, sel.pcrSelect, sel.sizeOfSelect);
+ }
+
+ UNPACK_DONE();
+
+ tpmrsa_set_pubkey(&saa_rsa, group->id_data.saa_pubkey, 256, 0, 0);
+ rc = tpmrsa_sigcheck(&saa_rsa, sig, digest);
+ tpmrsa_free(&saa_rsa);
+ if (rc) {
+ printk("sigcheck failed: %d\n", rc);
+ status = rc;
+ goto abort_egress;
+ }
+
+ // Commit
+ free(group->seals);
+
+ memcpy(&group->seal_bits.kernels, kern_bits, 20 * nr_kerns);
+ group->details.cfg_seq = native_be64(new_seq);
+ group->nr_seals = nr_seals;
+ group->seals = seals;
+ group->seal_bits.nr_kerns = native_be32(nr_kerns);
+
+ seals = NULL;
+
+ group->flags &= ~MEM_GROUP_FLAG_SEAL_VALID;
+ if (group == g_mgr->groups[0].v)
+ g_mgr->root_seals_valid = 0;
+
+ // TODO use GROUP_KEY_UPDATE or MGR_KEY_UPDATE here?
+ // only required if this update was to address a potential key leak
+ vtpm_sync_group(group, SEQ_UPDATE);
+
+ abort_egress:
+ free(seals);
+
+ pack_TPM_RSP_HEADER(tpmcmd->resp, VTPM_TAG_RSP, tpmcmd->resp_len, status);
+ return status;
+}
+
+static TPM_RESULT vtpmmgr_VtpmList(tpmcmd_t* tpmcmd)
+{
+ CMD_BEGIN;
+ struct mem_group *group;
+ uint32_t vtpm_offset;
+ int i, j;
+
+ UNPACK_GROUP(group);
+ UNPACK_IN(UINT32, &vtpm_offset);
+
+ PACK_OUT(UINT32, group->nr_vtpms);
+ if (vtpm_offset > group->nr_vtpms)
+ goto egress;
+
+ for(i=0; i < group->nr_pages; i++) {
+ struct mem_vtpm_page *pg = &group->data[i];
+ for(j=0; j < pg->size; j++) {
+ if (vtpm_offset) {
+ // TODO a proper seek would be far faster
+ vtpm_offset--;
+ continue;
+ }
+ memcpy(PACK_BUF, pg->vtpms[j]->uuid, 16);
+ tpmcmd->resp_len += 16;
+ if (tpmcmd->resp_len + 16 > TCPA_MAX_BUFFER_LENGTH)
+ goto egress;
+ }
+ }
+
+ egress:
+ CMD_END;
+}
+
+static TPM_RESULT vtpmmgr_VtpmNew(tpmcmd_t* tpmcmd)
+{
+ CMD_BEGIN;
+ struct mem_group *group;
+ struct mem_vtpm *vtpm;
+ uuid_t newuuid;
+ int rc;
+
+ UNPACK_GROUP(group);
+
+ // XXX allow non-random UUIDs for testing
+ if (tpmcmd->req_len == 14 + 16)
+ UNPACK_IN(BUFFER, newuuid, 16);
+ else
+ gen_random_uuid(newuuid);
+ UNPACK_DONE();
+
+ rc = create_vtpm(group, &vtpm, newuuid);
+ if (rc) {
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+ memset(vtpm->data, 0, 64);
+ vtpm_sync(group, vtpm);
+
+ PACK_OUT(BUFFER, newuuid, 16);
+ CMD_END;
+}
+
+static TPM_RESULT vtpmmgr_VtpmDel(tpmcmd_t* tpmcmd)
+{
+ CMD_BEGIN;
+ uuid_t uuid;
+ struct mem_group *group;
+ struct mem_vtpm *vtpm;
+ int rc;
+
+ UNPACK_IN(BUFFER, uuid, 16);
+ UNPACK_DONE();
+ rc = find_vtpm(&group, &vtpm, uuid);
+ if (rc) {
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+
+ if (vtpm->flags & VTPM_FLAG_OPEN) {
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+
+ delete_vtpm(group, vtpm);
+
+ CMD_END;
+}
+
+static int vtpmmgr_permcheck(struct tpm_opaque *opq)
+{
+ if (!opq->vtpm)
+ return 1;
+ if (opq->vtpm->flags & VTPM_FLAG_ADMIN)
+ return 0;
+ return 1;
+}
TPM_RESULT vtpmmgr_handle_cmd(
- const uuid_t uuid,
- tpmcmd_t* tpmcmd)
-{
- TPM_RESULT status = TPM_SUCCESS;
- TPM_TAG tag;
- UINT32 size;
- TPM_COMMAND_CODE ord;
-
- unpack_TPM_RQU_HEADER(tpmcmd->req,
- &tag, &size, &ord);
-
- /* Handle the command now */
- switch(tag) {
- case VTPM_TAG_REQ:
- //This is a vTPM command
- switch(ord) {
- case VTPM_ORD_SAVEHASHKEY:
- return vtpmmgr_SaveHashKey(uuid, tpmcmd);
- case VTPM_ORD_LOADHASHKEY:
- return vtpmmgr_LoadHashKey(uuid, tpmcmd);
- default:
- vtpmlogerror(VTPM_LOG_VTPM, "Invalid vTPM Ordinal %" PRIu32 "\n", ord);
- status = TPM_BAD_ORDINAL;
- }
- break;
- case TPM_TAG_RQU_COMMAND:
- case TPM_TAG_RQU_AUTH1_COMMAND:
- case TPM_TAG_RQU_AUTH2_COMMAND:
- //This is a TPM passthrough command
- switch(ord) {
- case TPM_ORD_GetRandom:
- vtpmloginfo(VTPM_LOG_VTPM, "Passthrough: TPM_GetRandom\n");
- break;
- case TPM_ORD_PcrRead:
- vtpmloginfo(VTPM_LOG_VTPM, "Passthrough: TPM_PcrRead\n");
- break;
- default:
- vtpmlogerror(VTPM_LOG_VTPM, "TPM Disallowed Passthrough ord=%" PRIu32 "\n", ord);
- status = TPM_DISABLED_CMD;
- goto abort_egress;
- }
-
- size = TCPA_MAX_BUFFER_LENGTH;
- TPMTRYRETURN(TPM_TransmitData(tpmcmd->req, tpmcmd->req_len, tpmcmd->resp, &size));
- tpmcmd->resp_len = size;
-
- unpack_TPM_RESULT(tpmcmd->resp + sizeof(TPM_TAG) + sizeof(UINT32), &status);
- return status;
-
- break;
- default:
- vtpmlogerror(VTPM_LOG_VTPM, "Invalid tag=%" PRIu16 "\n", tag);
- status = TPM_BADTAG;
- }
+ struct tpm_opaque *opaque,
+ tpmcmd_t* tpmcmd)
+{
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_TAG tag;
+ UINT32 size;
+ TPM_COMMAND_CODE ord;
+
+ unpack_TPM_RQU_HEADER(tpmcmd->req,
+ &tag, &size, &ord);
+
+ /* Handle the command now */
+ switch(tag) {
+ case VTPM_TAG_REQ:
+ // This is a vTPM command
+ switch(ord) {
+ case VTPM_ORD_SAVEHASHKEY:
+ return vtpmmgr_SaveHashKey(opaque, tpmcmd);
+ case VTPM_ORD_LOADHASHKEY:
+ return vtpmmgr_LoadHashKey(opaque, tpmcmd);
+ case VTPM_ORD_GET_BOOT_HASH:
+ return vtpmmgr_GetBootHash(opaque, tpmcmd);
+ case VTPM_ORD_GET_QUOTE:
+ return vtpmmgr_GetQuote(opaque, tpmcmd);
+ default:
+ vtpmlogerror(VTPM_LOG_VTPM, "Invalid vTPM Ordinal %" PRIu32 "\n", ord);
+ status = TPM_BAD_ORDINAL;
+ }
+ break;
+ case VTPM_TAG_REQ2:
+ // This is a management command
+ if (vtpmmgr_permcheck(opaque)) {
+ status = TPM_AUTHFAIL;
+ vtpmlogerror(VTPM_LOG_VTPM, "Rejected attempt to use management command from client\n");
+ break;
+ }
+ switch (ord) {
+ case VTPM_ORD_GROUP_LIST:
+ return vtpmmgr_GroupList(tpmcmd);
+ case VTPM_ORD_GROUP_NEW:
+ return vtpmmgr_GroupNew(tpmcmd);
+ case VTPM_ORD_GROUP_DEL:
+ return vtpmmgr_GroupDel(tpmcmd);
+ case VTPM_ORD_GROUP_ACTIVATE:
+ return vtpmmgr_GroupActivate(tpmcmd);
+ case VTPM_ORD_GROUP_REGISTER:
+ return vtpmmgr_GroupRegister(tpmcmd);
+ case VTPM_ORD_GROUP_UPDATE:
+ return vtpmmgr_GroupUpdate(tpmcmd);
+ case VTPM_ORD_GROUP_SHOW:
+ return vtpmmgr_GroupShow(tpmcmd);
+ case VTPM_ORD_VTPM_LIST:
+ return vtpmmgr_VtpmList(tpmcmd);
+ case VTPM_ORD_VTPM_NEW:
+ return vtpmmgr_VtpmNew(tpmcmd);
+ case VTPM_ORD_VTPM_DEL:
+ return vtpmmgr_VtpmDel(tpmcmd);
+ default:
+ vtpmlogerror(VTPM_LOG_VTPM, "Invalid TM Ordinal %" PRIu32 "\n", ord);
+ status = TPM_BAD_ORDINAL;
+ }
+ break;
+ case TPM_TAG_RQU_COMMAND:
+ case TPM_TAG_RQU_AUTH1_COMMAND:
+ case TPM_TAG_RQU_AUTH2_COMMAND:
+ //This is a TPM passthrough command
+ switch(ord) {
+ case TPM_ORD_GetRandom:
+ vtpmloginfo(VTPM_LOG_VTPM, "Passthrough: TPM_GetRandom\n");
+ break;
+ case TPM_ORD_PcrRead:
+ vtpmloginfo(VTPM_LOG_VTPM, "Passthrough: TPM_PcrRead\n");
+ // Quotes also need to be restricted to hide PCR values
+ break;
+ case TPM_ORD_Extend:
+ // TODO allow to certain clients? A malicious client
+ // could scramble PCRs and make future quotes invalid.
+ if (vtpmmgr_permcheck(opaque)) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Disallowed TPM_Extend\n");
+ status = TPM_DISABLED_CMD;
+ goto abort_egress;
+ } else {
+ vtpmloginfo(VTPM_LOG_VTPM, "Passthrough: TPM_Extend\n");
+ }
+ break;
+ default:
+ vtpmlogerror(VTPM_LOG_VTPM, "TPM Disallowed Passthrough ord=%" PRIu32 "\n", ord);
+ status = TPM_DISABLED_CMD;
+ goto abort_egress;
+ }
+
+ size = TCPA_MAX_BUFFER_LENGTH;
+ TPMTRYRETURN(TPM_TransmitData(tpmcmd->req, tpmcmd->req_len, tpmcmd->resp, &size));
+ tpmcmd->resp_len = size;
+
+ return TPM_SUCCESS;
+ default:
+ vtpmlogerror(VTPM_LOG_VTPM, "Invalid tag=%" PRIu16 "\n", tag);
+ status = TPM_BADTAG;
+ }
abort_egress:
- tpmcmd->resp_len = VTPM_COMMAND_HEADER_SIZE;
- pack_TPM_RSP_HEADER(tpmcmd->resp,
- tag + 3, tpmcmd->resp_len, status);
+ tpmcmd->resp_len = VTPM_COMMAND_HEADER_SIZE;
+ pack_TPM_RSP_HEADER(tpmcmd->resp, tag + 3, tpmcmd->resp_len, status);
- return status;
+ return status;
}
diff --git a/stubdom/vtpmmgr/vtpm_disk.c b/stubdom/vtpmmgr/vtpm_disk.c
new file mode 100644
index 0000000..a01633a
--- /dev/null
+++ b/stubdom/vtpmmgr/vtpm_disk.c
@@ -0,0 +1,237 @@
+#include <console.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <mini-os/byteorder.h>
+
+#include "vtpm_manager.h"
+#include "log.h"
+#include "uuid.h"
+
+#include "vtpmmgr.h"
+#include "vtpm_disk.h"
+#include "disk_crypto.h"
+#include "disk_format.h"
+#include "disk_io.h"
+#include "disk_tpm.h"
+
+struct mem_tpm_mgr *g_mgr;
+
+int vtpm_sync_disk(struct mem_tpm_mgr *mgr, int depth)
+{
+ int old_active_root = mgr->active_root;
+ int new_active_root = !old_active_root;
+ int rc = 0;
+ struct tpm_authdata prev;
+ struct mem_group *group0 = mgr->groups[0].v;
+
+ // don't bother writing if we will never be able to read
+ if (!group0 || !group0->nr_seals)
+ return 0;
+
+ mgr->sequence++;
+ mgr->active_root = new_active_root;
+
+ switch (depth) {
+ case CTR_UPDATE:
+ {
+ uint32_t ctr = be32_native(mgr->counter_value);
+ mgr->counter_value = native_be32(ctr + 1);
+ break;
+ }
+ case MGR_KEY_UPDATE:
+ {
+ int i;
+ mgr->root_seals_valid = 0;
+ do_random(&mgr->tm_key, 16);
+ aes_setup(&mgr->tm_key_e, &mgr->tm_key);
+ do_random(&mgr->nv_key, 16);
+ for(i=0; i < mgr->nr_groups; i++) {
+ abort(); // TODO use raw re-encryption to handle unopened groups
+ }
+ break;
+ }
+ case CTR_AUTH_UPDATE:
+ mgr->root_seals_valid = 0;
+ memcpy(&prev, &mgr->counter_auth, 20);
+ do_random(&mgr->counter_auth, 20);
+ break;
+ case NV_AUTH_UPDATE:
+ mgr->root_seals_valid = 0;
+ memcpy(&prev, &mgr->nvram_auth, 20);
+ do_random(&mgr->nvram_auth, 20);
+ break;
+ }
+
+ disk_write_all(mgr);
+
+ switch (depth) {
+ case SEQ_UPDATE:
+ break;
+
+ case CTR_UPDATE:
+ rc = TPM_disk_incr_counter(mgr->counter_index, mgr->counter_auth);
+ if (rc) {
+ uint32_t ctr = be32_native(mgr->counter_value);
+ mgr->counter_value = native_be32(ctr - 1);
+ mgr->active_root = old_active_root;
+ return rc;
+ }
+ break;
+
+ case MGR_KEY_UPDATE:
+ rc = TPM_disk_nvwrite(&mgr->nv_key, 16, mgr->nvram_slot, mgr->nvram_auth);
+ if (rc)
+ abort();
+ break;
+
+ case CTR_AUTH_UPDATE:
+ rc = TPM_disk_change_counter(mgr->counter_index, prev, mgr->counter_auth);
+ if (rc)
+ abort();
+ break;
+
+ case NV_AUTH_UPDATE:
+ rc = TPM_disk_nvchange(mgr->nvram_slot, prev, mgr->nvram_auth);
+ if (rc)
+ abort();
+ break;
+ }
+
+ return rc;
+}
+
+static struct mem_group_hdr* find_mem_group_hdr(struct mem_tpm_mgr *mgr, struct mem_group *group)
+{
+ int i;
+ for (i = 0; i < mgr->nr_groups; i++) {
+ struct mem_group_hdr *hdr = mgr->groups + i;
+ if (hdr->v == group)
+ return hdr;
+ }
+ return NULL;
+}
+
+int vtpm_sync_group(struct mem_group *group, int depth)
+{
+ struct mem_group_hdr* hdr = find_mem_group_hdr(g_mgr, group);
+ uint64_t seq = be64_native(group->details.sequence);
+
+ if (!hdr)
+ abort();
+
+ hdr->disk_loc.value = 0;
+ group->details.sequence = native_be64(1 + seq);
+
+ if (depth == GROUP_KEY_UPDATE) {
+ int i;
+ do_random(&group->group_key, 16);
+ do_random(&group->rollback_mac_key, 16);
+ group->flags &= ~MEM_GROUP_FLAG_SEAL_VALID;
+ for (i = 0; i < group->nr_pages; i++)
+ group->data[i].disk_loc.value = 0;
+ depth = CTR_UPDATE;
+ }
+
+ return vtpm_sync_disk(g_mgr, depth);
+}
+
+static struct mem_vtpm_page* find_mem_vtpm_page(struct mem_group *group, struct mem_vtpm *vtpm)
+{
+ int pgidx = vtpm->index_in_parent / VTPMS_PER_SECTOR;
+ return group->data + pgidx;
+}
+
+int vtpm_sync(struct mem_group *group, struct mem_vtpm *vtpm)
+{
+ struct mem_vtpm_page *pg = find_mem_vtpm_page(group, vtpm);
+ if (!pg)
+ return 1;
+ pg->disk_loc.value = 0;
+ return vtpm_sync_group(group, SEQ_UPDATE);
+}
+
+/************************************************************************/
+
+int create_vtpm(struct mem_group *group, struct mem_vtpm **vtpmp, const uuid_t uuid)
+{
+ int pgidx = group->nr_vtpms / VTPMS_PER_SECTOR;
+ int vtidx = group->nr_vtpms % VTPMS_PER_SECTOR;
+ struct mem_vtpm *vtpm = calloc(1, sizeof(*vtpm));
+
+ struct mem_vtpm_page *page = group->data + pgidx;
+ if (pgidx >= group->nr_pages) {
+ if (pgidx != group->nr_pages)
+ abort(); // nr_vtpms inconsistent with nr_pages
+ group->nr_pages++;
+ group->data = realloc(group->data, group->nr_pages * sizeof(*page));
+ page = group->data + pgidx;
+ memset(page, 0, sizeof(*page));
+ }
+ if (page->size != vtidx)
+ abort(); // nr_vtpms inconsistent with page->size
+ page->size++;
+
+ page->vtpms[vtidx] = vtpm;
+ vtpm->index_in_parent = group->nr_vtpms;
+ vtpm->flags = 0;
+
+ group->nr_vtpms++;
+
+ memcpy(vtpm->uuid, uuid, 16);
+ *vtpmp = vtpm;
+ return 0;
+}
+
+int delete_vtpm(struct mem_group *group, struct mem_vtpm *vtpm)
+{
+ struct mem_vtpm_page *pg = find_mem_vtpm_page(group, vtpm);
+ struct mem_vtpm_page *last_pg = group->data + (group->nr_pages - 1);
+ struct mem_vtpm *last = last_pg->vtpms[last_pg->size - 1];
+ int vtidx = vtpm->index_in_parent % VTPMS_PER_SECTOR;
+
+ if (vtpm->flags & VTPM_FLAG_OPEN)
+ return 1;
+
+ last->index_in_parent = vtpm->index_in_parent;
+ pg->vtpms[vtidx] = last;
+ pg->disk_loc.value = 0;
+
+ last_pg->vtpms[last_pg->size - 1] = NULL;
+ last_pg->disk_loc.value = 0;
+ last_pg->size--;
+
+ if (last_pg->size == 0)
+ group->nr_pages--;
+ group->nr_vtpms--;
+ free(vtpm);
+ return 0;
+}
+
+int find_vtpm(struct mem_group **groupp, struct mem_vtpm **vtpmp, const uuid_t uuid)
+{
+ struct mem_group *group;
+ int i, j, k;
+
+ for (i = 0; i < g_mgr->nr_groups; i++) {
+ group = g_mgr->groups[i].v;
+ if (!group)
+ continue;
+ for (j = 0; j < group->nr_pages; j++) {
+ struct mem_vtpm_page *pg = &group->data[j];
+ for (k = 0; k < pg->size; k++) {
+ struct mem_vtpm *vt = pg->vtpms[k];
+ if (!memcmp(uuid, vt->uuid, 16)) {
+ *groupp = group;
+ *vtpmp = vt;
+ return 0;
+ }
+ }
+ }
+ }
+
+ return 1;
+}
diff --git a/stubdom/vtpmmgr/vtpm_disk.h b/stubdom/vtpmmgr/vtpm_disk.h
new file mode 100644
index 0000000..a567265
--- /dev/null
+++ b/stubdom/vtpmmgr/vtpm_disk.h
@@ -0,0 +1,233 @@
+#ifndef __VTPM_DISK_H
+#define __VTPM_DISK_H
+
+#include "uuid.h"
+#include <polarssl/aes.h>
+#include "endian_int.h"
+
+/* Type for disk sector indexes */
+typedef be32_t sector_t;
+
+/* A TPM authdata entry (160 random bits) */
+struct tpm_authdata {
+ uint8_t bits[20];
+};
+
+/* 160-bit hash (SHA-1) */
+struct hash160 {
+ uint8_t bits[20];
+};
+
+/* 256-bit hash (either SHA256 or SHA512-256) */
+struct hash256 {
+ uint8_t bits[32];
+};
+
+/* 128-bit MAC (AES-128 CMAC) */
+struct mac128 {
+ uint8_t bits[16];
+};
+
+struct key128 {
+ uint8_t bits[16];
+};
+
+/********************************************************************/
+
+/**
+ * Unique identifying information for a vTPM group. Once a group has been
+ * created, this data will be constant.
+ *
+ * This structure a component of struct disk_group_sector, stored directly.
+ */
+struct group_id_data {
+ uuid_t uuid;
+ uint8_t saa_pubkey[256];
+ uint8_t tpm_aik_public[256];
+ uint8_t tpm_aik_edata[256];
+ struct hash256 rollback_pubkey_hash;
+};
+
+/**
+ * Details of a vTPM group that change during normal operation.
+ *
+ * This structure a component of struct disk_group_sector, stored directly.
+ */
+struct group_details {
+ be64_t sequence;
+ be64_t cfg_seq;
+ be64_t flags;
+#define FLAG_ROLLBACK_DETECTED 1
+
+ /* Seal(recovery_seal, PCR16 = H(RECOVERY_KEY)) */
+ uint8_t recovery_data[256];
+};
+
+/**
+ * The required input to TPM_Unseal to obtain key data
+ *
+ * This structure a component of several disk structures, stored directly.
+ */
+struct disk_seal_entry {
+ le32_t pcr_selection;
+ struct hash160 digest_at_seal;
+ struct hash160 digest_release;
+ uint8_t sealed_data[256];
+};
+
+/**
+ * A vTPM group's configuration list and sealed key data
+ *
+ * This structure a component of struct disk_group_sector, stored directly.
+ */
+struct disk_group_boot_config_list {
+#define NR_SEALS_PER_GROUP 5
+ be32_t nr_cfgs;
+ struct disk_seal_entry entry[NR_SEALS_PER_GROUP];
+#define NR_KERNS_PER_GROUP 16
+ be32_t nr_kerns;
+ struct hash160 kernels[NR_KERNS_PER_GROUP];
+
+ /* TODO support overflow of either nr_cfgs or nr_kerns */
+ struct hash256 next;
+};
+
+/********************************************************************/
+
+#define VTPM_FLAG_ADMIN 1
+#define VTPM_FLAG_DISK_MASK (0xFFFF)
+#define VTPM_FLAG_OPEN (1UL<<31)
+
+/**
+ * A single vTPM's in-memory data. Do not free if the open flag is set.
+ */
+struct mem_vtpm {
+ uuid_t uuid;
+ uint8_t data[64];
+ uint32_t flags;
+ uint32_t index_in_parent;
+};
+
+/**
+ * Shortened form of struct disk_seal_entry
+ */
+struct mem_seal {
+ le32_t pcr_selection;
+ struct hash160 digest_release;
+};
+
+/**
+ * Maximum number of vTPMs in one sector on the disk.
+ *
+ * 20 + 64 = 84 bytes per vTPM; 32 bytes overhead from IVs
+ * 48*84 + 32 = 4064 bytes
+ */
+#define VTPMS_PER_SECTOR 48
+
+/**
+ * Decrypted and unpacked version of struct disk_vtpm_sector
+ */
+struct mem_vtpm_page {
+ struct hash256 disk_hash;
+ sector_t disk_loc;
+ int size;
+
+ struct mem_vtpm *vtpms[VTPMS_PER_SECTOR];
+};
+
+/**
+ * In-memory representation of an open vTPM group
+ */
+struct mem_group {
+ struct group_id_data id_data;
+ struct group_details details;
+
+ /* Obtained from sealed data */
+ struct tpm_authdata aik_authdata;
+ struct key128 group_key;
+ struct key128 rollback_mac_key;
+
+ int nr_vtpms;
+ int nr_pages;
+ struct mem_vtpm_page *data;
+
+ int flags;
+#define MEM_GROUP_FLAG_SEAL_VALID 1
+#define MEM_GROUP_FLAG_FIRSTBOOT 2
+ int nr_seals;
+ struct mem_seal *seals;
+
+ sector_t seal_next_loc;
+ struct disk_group_boot_config_list seal_bits;
+};
+
+/**
+ * In-memory representation of a vTPM group (open or not)
+ */
+struct mem_group_hdr {
+ sector_t disk_loc;
+ struct hash256 disk_hash;
+
+ int disk_nr_inuse;
+ sector_t *disk_inuse;
+
+ struct mem_group *v;
+};
+
+/**
+ * In-memory representation of the TPM Manager's permanent data
+ */
+struct mem_tpm_mgr {
+ struct key128 tm_key;
+ aes_context tm_key_e;
+ struct key128 nv_key;
+ uuid_t uuid;
+
+ be32_t nvram_slot;
+ struct tpm_authdata nvram_auth;
+ be32_t counter_index;
+ struct tpm_authdata counter_auth;
+ be32_t counter_value;
+
+ uint64_t sequence;
+
+ int active_root;
+
+ int nr_groups;
+ struct mem_group_hdr *groups;
+
+ int root_seals_valid;
+};
+
+int vtpm_storage_init(void);
+int vtpm_load_disk(void);
+int vtpm_new_disk(void);
+
+enum vtpm_sync_depth {
+ SEQ_UPDATE, /* Just the soft sequence number */
+ CTR_UPDATE, /* Sequence and TPM counter */
+ GROUP_KEY_UPDATE, /* Group key (and TPM counter) */
+ MGR_KEY_UPDATE, /* Manager key */
+ CTR_AUTH_UPDATE, /* TPM counter authdata */
+ NV_AUTH_UPDATE /* NVRAM authdata */
+};
+
+/*
+ * For a full manager key flush, use this ordering of writes:
+ * MGR_KEY_UPDATE
+ * CTR_AUTH_UPDATE
+ * NV_AUTH_UPDATE
+ * CTR_UPDATE or GROUP_KEY_UPDATE
+ */
+
+extern struct mem_tpm_mgr *g_mgr;
+
+int vtpm_sync_disk(struct mem_tpm_mgr *mgr, int depth);
+int vtpm_sync_group(struct mem_group *group, int depth);
+int vtpm_sync(struct mem_group *group, struct mem_vtpm *vtpm);
+
+int create_vtpm(struct mem_group *group, struct mem_vtpm **vtpmp, const uuid_t uuid);
+int delete_vtpm(struct mem_group *group, struct mem_vtpm *vtpm);
+int find_vtpm(struct mem_group **groupp, struct mem_vtpm **vtpmp, const uuid_t uuid);
+
+#endif
diff --git a/stubdom/vtpmmgr/vtpm_manager.h b/stubdom/vtpmmgr/vtpm_manager.h
index a2bbcca..156c2ce 100644
--- a/stubdom/vtpmmgr/vtpm_manager.h
+++ b/stubdom/vtpmmgr/vtpm_manager.h
@@ -38,7 +38,9 @@
#define VTPM_MANAGER_H
#define VTPM_TAG_REQ 0x01c1
+#define VTPM_TAG_REQ2 0x01c2
#define VTPM_TAG_RSP 0x01c4
+#define VTPM_TAG_RSP2 0x01c5
#define COMMAND_BUFFER_SIZE 4096
// Header size
@@ -46,12 +48,391 @@
//************************ Command Codes ****************************
#define VTPM_ORD_BASE 0x0000
-#define VTPM_PRIV_MASK 0x01000000 // Priviledged VTPM Command
-#define VTPM_PRIV_BASE (VTPM_ORD_BASE | VTPM_PRIV_MASK)
+#define TPM_VENDOR_COMMAND 0x02000000 // TPM Main, part 2, section 17.
+#define VTPM_PRIV_BASE (VTPM_ORD_BASE | TPM_VENDOR_COMMAND)
+
+/*
+ * Non-priviledged VTPM Commands:
+ *
+ * The PCRs available to read, extend, or quote may be limited to a given vTPM
+ * based on a local security policy (this is not yet implemented).
+ *
+ * vTPMs may request the following commands which will be forwarded directly to
+ * the physical TPM:
+ *
+ * TPM_ORD_GetRandom
+ * TPM_ORD_PcrRead
+ * TPM_ORD_Extend
+ *
+ * In addition, the following command are available to all vTPMs:
+ */
+
+/**
+ * Store a persistent key blob to TPM Manager storage
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_SAVEHASHKEY
+ * BYTE[] keyblob 52 or 64 bytes of key data
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ */
+#define VTPM_ORD_SAVEHASHKEY (VTPM_ORD_BASE + 1)
+/**
+ * Load the persistent key blob from TPM Manager storage
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_LOADHASHKEY
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ * BYTE[] keyblob 52 or 64 bytes of key data
+ */
+#define VTPM_ORD_LOADHASHKEY (VTPM_ORD_BASE + 2)
+/**
+ * Get a kernel hash of the control domain for this vTPM
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_GET_BOOT_HASH
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ * TPM_DIGEST digest hash for the initial extend of PCR0
+ */
+#define VTPM_ORD_GET_BOOT_HASH (VTPM_ORD_BASE + 3)
+/**
+ * Get a hardware TPM quote for this vTPM. The quote will use the AIK
+ * associated with the group this vTPM was created in. Values specific to the
+ * vTPM will be extended to certain resettable PCRs.
+ *
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_GET_QUOTE
+ * TPM_NONCE externData Data to be quoted
+ * PCR_SELECTION quoteSelect PCR selection for quote.
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ * BYTE[] signature 256 bytes of signature data
+ * TPM_PCRVALUE[] pcrValues Values of PCRs selected by the request
+ */
+#define VTPM_ORD_GET_QUOTE (VTPM_ORD_BASE + 4)
+
+/*
+ * Resettable PCR values in TPM Manager quotes (VTPM_ORD_GET_QUOTE):
+ *
+ * PCR#16:
+ * unused - debug PCR
+ *
+ * PCR#17-19: (cannot be reset by locality 2)
+ * DRTM measurements
+ *
+ * PCR#20: Remains constant over the life of the vTPM group
+ * SHA1(SAA pubkey)
+ *
+ * PCR#21: May change during the life; must be approved by SAA
+ * SHA1(TPM_MGR_CFG_LIST)
+ *
+ * PCR#22: May change during the life; must be in the cfg_list
+ * vTPM kernel build hash (truncated SHA256)
+ * Note: this is currently set to 20 zero bytes
+ *
+ * PCR#23: Remains constant over the life of the vTPM; system-specific
+ * group UUID || 00 00 00 00
+ * vTPM UUID || 00 00 00 00
+ *
+ *
+ * Group-only PCR values (VTPM_ORD_GROUP_*) are the same except:
+ *
+ * PCR#22: unused (value is zero)
+ * PCR#23:
+ * group UUID || 00 00 00 00
+ *
+ * The value of externalData for quotes using these PCRs is defined below; it is
+ * always a hash whose first 4 bytes identify the rest of the structure.
+ *
+ *
+ * The configuration list signed by a System Approval Agent (SAA) is:
+ *
+ * TPM_MGR_CFG_LIST:
+ * UINT64 sequence Monotonic sequence number
+ * UINT32 pltCfgSize Size of pltCfgs array
+ * TPM_COMPOSITE_HASH[] pltCfgs Valid platform configurations
+ * UINT32 kernSize Size of kernList array
+ * TPM_HASH[] kernList Valid vTPM kernels
+ */
+
+/************************************\
+ * TPM Manager Management Interface *
+\************************************/
+
+/**
+ * List groups
+ *
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ2
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_GROUP_LIST
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ * UINT32 count number of valid groups
+ */
+#define VTPM_ORD_GROUP_LIST (VTPM_PRIV_BASE + 0x101)
+/**
+ * Create a group
+ *
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ2
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_GROUP_NEW
+ * TPM_CHOSENID_HASH labelDigest Data for the privacy CA
+ * BYTE[256] SAASigKey RSA public signature key for the SAA
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ * BYTE[16] groupUUID UUID for the group
+ * BYTE[256] aikPubKey Public key of the AIK
+ * BYTE[256] aikBinding TPM_IDENTITY_CONTENTS signature
+ */
+#define VTPM_ORD_GROUP_NEW (VTPM_PRIV_BASE + 0x102)
+/**
+ * Delete a group
+ *
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ2
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_GROUP_DEL
+ * UINT32 groupID ID of the group to delete
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ */
+#define VTPM_ORD_GROUP_DEL (VTPM_PRIV_BASE + 0x103)
+/**
+ * Activate the group's AIK (message from privacy CA)
+ *
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ2
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_GROUP_ACTIVATE
+ * UINT32 groupID ID of the group to activate
+ * UINT32 blobSize
+ * BYTE[] blob Blob from the privay CA
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ * TPM_SYMMETRIC_KEY key Output from TPM_ActivateIdentity
+ */
+#define VTPM_ORD_GROUP_ACTIVATE (VTPM_PRIV_BASE + 0x104)
+/**
+ * Register this TPM manager slot with the SAA and provision its recovery data.
+ * The initial registration must be done with no reboots between the creation of
+ * the group and the execution of this command; it can only be done once.
+ *
+ * The ExternalData value is SHA1("REGR" || dhkx_1 || dhkx_2 || recoverBlob)
+ *
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ2
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_GROUP_REGISTER
+ * UINT32 groupID ID of the group to register
+ * BYTE[256] dhkx_1 One half of a diffie-hellman key exchange
+ * BYTE[256] SAAProof Signature (using SAASigKey) of derivData
+ * PCR_SELECTION quoteSelect PCR selection for quote.
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ * BYTE[256] dhkx_2 One half of a diffie-hellman key exchange
+ * BYTE[32] recoverBlob Encrypted blob (using key derived from DH)
+ * BYTE[256] regProof Quote using the group's AIK
+ */
+#define VTPM_ORD_GROUP_REGISTER (VTPM_PRIV_BASE + 0x105)
+/**
+ * Update the configuration list
+ *
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ2
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_GROUP_UPDATE
+ * UINT32 groupID ID of the group to update
+ * BYTE[256] cfgListSig Signature (using SAASigKey) of cfgList
+ * TPM_MGR_CFG_LIST cfgList Configurations the group is valid in
+ * PCR_SELECTION[] selForCfgs PCR selections used in the cfgList.pltCfgs
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ */
+#define VTPM_ORD_GROUP_UPDATE (VTPM_PRIV_BASE + 0x106)
+/**
+ * Get the current contents of the group structure.
+ *
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ2
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_GROUP_SHOW
+ * UINT32 groupID ID of the group to view
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ * BYTE[16] groupUUID UUID for the group
+ * BYTE[256] pubkey public key of the SAA
+ * TPM_MGR_CFG_LIST cfgList current list for this group
+ */
+#define VTPM_ORD_GROUP_SHOW (VTPM_PRIV_BASE + 0x107)
+/**
+ * Get a quote of the current status of the TMA structure. This can be used to
+ * prove that an update has been applied; it is similar to VTPM_ORD_GET_QUOTE,
+ * but does not include measurements specific to any vTPM.
+ *
+ * The ExternalData value for the quote is SHA1("SHOW" || nonce)
+ *
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ2
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_GROUP_QUOTE
+ * UINT32 groupID ID of the group to view
+ * TPM_NONCE nonce Anti-replay
+ * PCR_SELECTION quoteSelect PCR selection for quote.
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ * BYTE[] signature 256 bytes of signature data
+ * TPM_PCRVALUE[] pcrValues Values of PCRs selected by the request
+ */
+#define VTPM_ORD_GROUP_QUOTE (VTPM_PRIV_BASE + 0x108)
+/**
+ * Prepare to use recovery data to open a currently-closed group.
+ *
+ * The ExternalData value is SHA1("RCVR" || nonce || dhkx_1)
+ *
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ2
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_GROUP_RECOVER1
+ * UINT32 groupID ID of the group to recover
+ * TPM_KEY proxyAIK AIK to use for recovery quote
+ * TPM_NONCE nonce Anti-replay by challenger
+ * PCR_SELECTION quoteSelect PCR selection for quote
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ * BYTE[256] dhkx_1 One half of a diffie-hellman key exchange
+ * BYTE[256] signature quote using proxyAIK
+ */
+#define VTPM_ORD_GROUP_RECOVER1 (VTPM_PRIV_BASE + 0x109)
+/**
+ * Use recovery data to open a currently-closed group
+ *
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ2
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_GROUP_RECOVER2
+ * UINT32 groupID ID of the group to recover
+ * BYTE[256] dhkx_2 One half of a diffie-hellman key exchange
+ * BYTE[32] recoverBlob Encrypted blob (using key derived from DH)
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ */
+#define VTPM_ORD_GROUP_RECOVER2 (VTPM_PRIV_BASE + 0x10A)
+
+/**
+ * List the UUIDs of vTPMs in an group. Multiple calls may be required to list
+ * all the vTPMs in an group; if the returned list is shorter than totalCount
+ * would imply, additional requests using the offest will be required
+ * to build the full list.
+ *
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ2
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_VTPM_LIST
+ * UINT32 groupID ID of the group to list
+ * UINT32 offset Offset to start the list at
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ * UINT32 totalCount Count of all vTPMs under this group
+ * BYTE[] uuids List of UUIDs (16 bytes each)
+ */
+#define VTPM_ORD_VTPM_LIST (VTPM_PRIV_BASE + 0x201)
+#define VTPM_ORD_VTPM_SHOW (VTPM_PRIV_BASE + 0x202)
+#define VTPM_ORD_VTPM_EDIT (VTPM_PRIV_BASE + 0x203)
+/**
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ2
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_VTPM_NEW
+ * UINT32 groupID ID of the group to modify
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ * BYTE[16] vtpmUUID UUID for the vTPM
+ */
+#define VTPM_ORD_VTPM_NEW (VTPM_PRIV_BASE + 0x204)
+/**
+ * Input:
+ * TPM_TAG tag VTPM_TAG_REQ2
+ * UINT32 paramSize total size
+ * UINT32 ordinal VTPM_ORD_VTPM_DEL
+ ## UINT32 groupID ID of the group to modify
+ * BYTE[16] vtpmUUID UUID for the vTPM to delete
+ * Output:
+ * TPM_TAG tag VTPM_TAG_RSP
+ * UINT32 paramSize total size
+ * UINT32 status return code
+ */
+#define VTPM_ORD_VTPM_DEL (VTPM_PRIV_BASE + 0x205)
+
+/**
+ * Generate an unbound AIK for the pTPM
+ *
+ * This unbound AIK can be used in the GROUP_RECOVER1 operation.
+ */
+#define VTPM_ORD_MakeIdentity (VTPM_PRIV_BASE + 0x301)
+/**
+ * Activate an unbound AIK for the pTPM
+ */
+#define VTPM_ORD_ActivateIdentity (VTPM_PRIV_BASE + 0x302)
+/**
+ * Get the EK from the pTPM
+ *
+ * Used for any AIK activation
+ */
+#define VTPM_ORD_ReadPubek (VTPM_PRIV_BASE + 0x303)
+/**
+ * Define an NVRAM slot
+ */
+#define VTPM_NV_DefineSpace (VTPM_PRIV_BASE + 0x304)
+/**
+ * Write to NVRAM
+ */
+#define VTPM_NV_WriteValue (VTPM_PRIV_BASE + 0x305)
+/**
+ * Read from NVRAM
+ */
+#define VTPM_NV_ReadValue (VTPM_PRIV_BASE + 0x306)
-// Non-priviledged VTPM Commands (From DMI's)
-#define VTPM_ORD_SAVEHASHKEY (VTPM_ORD_BASE + 1) // DMI requests encryption key for persistent storage
-#define VTPM_ORD_LOADHASHKEY (VTPM_ORD_BASE + 2) // DMI requests symkey to be regenerated
//************************ Return Codes ****************************
#define VTPM_SUCCESS 0
diff --git a/stubdom/vtpmmgr/vtpm_storage.c b/stubdom/vtpmmgr/vtpm_storage.c
deleted file mode 100644
index de21b4a..0000000
--- a/stubdom/vtpmmgr/vtpm_storage.c
+++ /dev/null
@@ -1,794 +0,0 @@
-/*
- * Copyright (c) 2010-2012 United States Government, as represented by
- * the Secretary of Defense. All rights reserved.
- *
- * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
- * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
- * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
- * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
- * SOFTWARE.
- */
-
-/***************************************************************
- * DISK IMAGE LAYOUT
- * *************************************************************
- * All data is stored in BIG ENDIAN format
- * *************************************************************
- * Section 1: Header
- *
- * 10 bytes id ID String "VTPMMGRDOM"
- * uint32_t version Disk Image version number (current == 1)
- * uint32_t storage_key_len Length of the storage Key
- * TPM_KEY storage_key Marshalled TPM_KEY structure (See TPM spec v2)
- * RSA_BLOCK aes_crypto Encrypted aes key data (RSA_CIPHER_SIZE bytes), bound by the storage_key
- * BYTE[32] aes_key Aes key for encrypting the uuid table
- * uint32_t cipher_sz Encrypted size of the uuid table
- *
- * *************************************************************
- * Section 2: Uuid Table
- *
- * This table is encrypted by the aes_key in the header. The cipher text size is just
- * large enough to hold all of the entries plus required padding.
- *
- * Each entry is as follows
- * BYTE[16] uuid Uuid of a vtpm that is stored on this disk
- * uint32_t offset Disk offset where the vtpm data is stored
- *
- * *************************************************************
- * Section 3: Vtpm Table
- *
- * The rest of the disk stores vtpms. Each vtpm is an RSA_BLOCK encrypted
- * by the storage key. Each vtpm must exist on an RSA_BLOCK aligned boundary,
- * starting at the first RSA_BLOCK aligned offset after the uuid table.
- * As the uuid table grows, vtpms may be relocated.
- *
- * RSA_BLOCK vtpm_crypto Vtpm data encrypted by storage_key
- * BYTE[20] hash Sha1 hash of vtpm encrypted data
- * BYTE[16] vtpm_aes_key Encryption key for vtpm data
- *
- *************************************************************
- */
-#define DISKVERS 1
-#define IDSTR "VTPMMGRDOM"
-#define IDSTRLEN 10
-#define AES_BLOCK_SIZE 16
-#define AES_KEY_BITS 256
-#define AES_KEY_SIZE (AES_KEY_BITS/8)
-#define BUF_SIZE 4096
-
-#define UUID_TBL_ENT_SIZE (sizeof(uuid_t) + sizeof(uint32_t))
-
-#define HEADERSZ (10 + 4 + 4)
-
-#define TRY_READ(buf, size, msg) do {\
- int rc; \
- if((rc = read(blkfront_fd, buf, (size))) != (size)) { \
- vtpmlogerror(VTPM_LOG_VTPM, "read() failed! " msg " : rc=(%d/%d), error=(%s)\n", rc, (int)(size), strerror(errno)); \
- status = TPM_IOERROR;\
- goto abort_egress;\
- } \
-} while(0)
-
-#define TRY_WRITE(buf, size, msg) do {\
- int rc; \
- if((rc = write(blkfront_fd, buf, (size))) != (size)) { \
- vtpmlogerror(VTPM_LOG_VTPM, "write() failed! " msg " : rc=(%d/%d), error=(%s)\n", rc, (int)(size), strerror(errno)); \
- status = TPM_IOERROR;\
- goto abort_egress;\
- } \
-} while(0)
-
-#include <blkfront.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <mini-os/byteorder.h>
-#include <polarssl/aes.h>
-
-#include "vtpm_manager.h"
-#include "log.h"
-#include "marshal.h"
-#include "tpm.h"
-#include "uuid.h"
-
-#include "vtpmmgr.h"
-#include "vtpm_storage.h"
-
-#define MAX(a,b) ( ((a) > (b)) ? (a) : (b) )
-#define MIN(a,b) ( ((a) < (b)) ? (a) : (b) )
-
-/* blkfront device objets */
-static struct blkfront_dev* blkdev = NULL;
-static int blkfront_fd = -1;
-
-struct Vtpm {
- uuid_t uuid;
- int offset;
-};
-struct Storage {
- int aes_offset;
- int uuid_offset;
- int end_offset;
-
- int num_vtpms;
- int num_vtpms_alloced;
- struct Vtpm* vtpms;
-};
-
-/* Global storage data */
-static struct Storage g_store = {
- .vtpms = NULL,
-};
-
-static int get_offset(void) {
- return lseek(blkfront_fd, 0, SEEK_CUR);
-}
-
-static void reset_store(void) {
- g_store.aes_offset = 0;
- g_store.uuid_offset = 0;
- g_store.end_offset = 0;
-
- g_store.num_vtpms = 0;
- g_store.num_vtpms_alloced = 0;
- free(g_store.vtpms);
- g_store.vtpms = NULL;
-}
-
-static int vtpm_get_index(const uuid_t uuid) {
- int st = 0;
- int ed = g_store.num_vtpms-1;
- while(st <= ed) {
- int mid = ((unsigned int)st + (unsigned int)ed) >> 1; //avoid overflow
- int c = memcmp(uuid, &g_store.vtpms[mid].uuid, sizeof(uuid_t));
- if(c == 0) {
- return mid;
- } else if(c > 0) {
- st = mid + 1;
- } else {
- ed = mid - 1;
- }
- }
- return -(st + 1);
-}
-
-static void vtpm_add(const uuid_t uuid, int offset, int index) {
- /* Realloc more space if needed */
- if(g_store.num_vtpms >= g_store.num_vtpms_alloced) {
- g_store.num_vtpms_alloced += 16;
- g_store.vtpms = realloc(
- g_store.vtpms,
- sizeof(struct Vtpm) * g_store.num_vtpms_alloced);
- }
-
- /* Move everybody after the new guy */
- for(int i = g_store.num_vtpms; i > index; --i) {
- g_store.vtpms[i] = g_store.vtpms[i-1];
- }
-
- vtpmloginfo(VTPM_LOG_VTPM, "Registered vtpm " UUID_FMT "\n", UUID_BYTES(uuid));
-
- /* Finally add new one */
- memcpy(g_store.vtpms[index].uuid, uuid, sizeof(uuid_t));
- g_store.vtpms[index].offset = offset;
- ++g_store.num_vtpms;
-}
-
-#if 0
-static void vtpm_remove(int index) {
- for(i = index; i < g_store.num_vtpms; ++i) {
- g_store.vtpms[i] = g_store.vtpms[i+1];
- }
- --g_store.num_vtpms;
-}
-#endif
-
-static int pack_uuid_table(uint8_t* table, int size, int* nvtpms) {
- uint8_t* ptr = table;
- while(*nvtpms < g_store.num_vtpms && size >= 0)
- {
- /* Pack the uuid */
- memcpy(ptr, (uint8_t*)g_store.vtpms[*nvtpms].uuid, sizeof(uuid_t));
- ptr+= sizeof(uuid_t);
-
-
- /* Pack the offset */
- ptr = pack_UINT32(ptr, g_store.vtpms[*nvtpms].offset);
-
- ++*nvtpms;
- size -= UUID_TBL_ENT_SIZE;
- }
- return ptr - table;
-}
-
-/* Extract the uuids */
-static int extract_uuid_table(uint8_t* table, int size) {
- uint8_t* ptr = table;
- for(;size >= UUID_TBL_ENT_SIZE; size -= UUID_TBL_ENT_SIZE) {
- int index;
- uint32_t v32;
-
- /*uuid_t is just an array of bytes, so we can do a direct cast here */
- uint8_t* uuid = ptr;
- ptr += sizeof(uuid_t);
-
- /* Get the offset of the key */
- ptr = unpack_UINT32(ptr, &v32);
-
- /* Insert the new vtpm in sorted order */
- if((index = vtpm_get_index(uuid)) >= 0) {
- vtpmlogerror(VTPM_LOG_VTPM, "Vtpm (" UUID_FMT ") exists multiple times! ignoring...\n", UUID_BYTES(uuid));
- continue;
- }
- index = -index -1;
-
- vtpm_add(uuid, v32, index);
-
- }
- return ptr - table;
-}
-
-static void vtpm_decrypt_block(aes_context* aes,
- uint8_t* iv,
- uint8_t* cipher,
- uint8_t* plain,
- int cipher_sz,
- int* overlap)
-{
- int bytes_ext;
- /* Decrypt */
- aes_crypt_cbc(aes, AES_DECRYPT,
- cipher_sz,
- iv, cipher, plain + *overlap);
-
- /* Extract */
- bytes_ext = extract_uuid_table(plain, cipher_sz + *overlap);
-
- /* Copy left overs to the beginning */
- *overlap = cipher_sz + *overlap - bytes_ext;
- memcpy(plain, plain + bytes_ext, *overlap);
-}
-
-static int vtpm_encrypt_block(aes_context* aes,
- uint8_t* iv,
- uint8_t* plain,
- uint8_t* cipher,
- int block_sz,
- int* overlap,
- int* num_vtpms)
-{
- int bytes_to_crypt;
- int bytes_packed;
-
- /* Pack the uuid table */
- bytes_packed = *overlap + pack_uuid_table(plain + *overlap, block_sz - *overlap, num_vtpms);
- bytes_to_crypt = MIN(bytes_packed, block_sz);
-
- /* Add padding if we aren't on a multiple of the block size */
- if(bytes_to_crypt & (AES_BLOCK_SIZE-1)) {
- int oldsz = bytes_to_crypt;
- //add padding
- bytes_to_crypt += AES_BLOCK_SIZE - (bytes_to_crypt & (AES_BLOCK_SIZE-1));
- //fill padding with random bytes
- vtpmmgr_rand(plain + oldsz, bytes_to_crypt - oldsz);
- *overlap = 0;
- } else {
- *overlap = bytes_packed - bytes_to_crypt;
- }
-
- /* Encrypt this chunk */
- aes_crypt_cbc(aes, AES_ENCRYPT,
- bytes_to_crypt,
- iv, plain, cipher);
-
- /* Copy the left over partials to the beginning */
- memcpy(plain, plain + bytes_to_crypt, *overlap);
-
- return bytes_to_crypt;
-}
-
-static TPM_RESULT vtpm_storage_new_vtpm(const uuid_t uuid, int index) {
- TPM_RESULT status = TPM_SUCCESS;
- uint8_t plain[BUF_SIZE + AES_BLOCK_SIZE];
- uint8_t buf[BUF_SIZE];
- uint8_t* ptr;
- int cipher_sz;
- aes_context aes;
-
- /* Add new vtpm to the table */
- vtpm_add(uuid, g_store.end_offset, index);
- g_store.end_offset += RSA_CIPHER_SIZE;
-
- /* Compute the new end location of the encrypted uuid table */
- cipher_sz = AES_BLOCK_SIZE; //IV
- cipher_sz += g_store.num_vtpms * UUID_TBL_ENT_SIZE; //uuid table
- cipher_sz += (AES_BLOCK_SIZE - (cipher_sz & (AES_BLOCK_SIZE -1))) & (AES_BLOCK_SIZE-1); //aes padding
-
- /* Does this overlap any key data? If so they need to be relocated */
- int uuid_end = (g_store.uuid_offset + cipher_sz + RSA_CIPHER_SIZE) & ~(RSA_CIPHER_SIZE -1);
- for(int i = 0; i < g_store.num_vtpms; ++i) {
- if(g_store.vtpms[i].offset < uuid_end) {
-
- vtpmloginfo(VTPM_LOG_VTPM, "Relocating vtpm data\n");
-
- //Read the hashkey cipher text
- lseek(blkfront_fd, g_store.vtpms[i].offset, SEEK_SET);
- TRY_READ(buf, RSA_CIPHER_SIZE, "vtpm hashkey relocate");
-
- //Write the cipher text to new offset
- lseek(blkfront_fd, g_store.end_offset, SEEK_SET);
- TRY_WRITE(buf, RSA_CIPHER_SIZE, "vtpm hashkey relocate");
-
- //Save new offset
- g_store.vtpms[i].offset = g_store.end_offset;
- g_store.end_offset += RSA_CIPHER_SIZE;
- }
- }
-
- vtpmloginfo(VTPM_LOG_VTPM, "Generating a new symmetric key\n");
-
- /* Generate an aes key */
- TPMTRYRETURN(vtpmmgr_rand(plain, AES_KEY_SIZE));
- aes_setkey_enc(&aes, plain, AES_KEY_BITS);
- ptr = plain + AES_KEY_SIZE;
-
- /* Pack the crypted size */
- ptr = pack_UINT32(ptr, cipher_sz);
-
- vtpmloginfo(VTPM_LOG_VTPM, "Binding encrypted key\n");
-
- /* Seal the key and size */
- TPMTRYRETURN(TPM_Bind(&vtpm_globals.storage_key,
- plain,
- ptr - plain,
- buf));
-
- /* Write the sealed key to disk */
- lseek(blkfront_fd, g_store.aes_offset, SEEK_SET);
- TRY_WRITE(buf, RSA_CIPHER_SIZE, "vtpm aes key");
-
- /* ENCRYPT AND WRITE UUID TABLE */
-
- vtpmloginfo(VTPM_LOG_VTPM, "Encrypting the uuid table\n");
-
- int num_vtpms = 0;
- int overlap = 0;
- int bytes_crypted;
- uint8_t iv[AES_BLOCK_SIZE];
-
- /* Generate the iv for the first block */
- TPMTRYRETURN(vtpmmgr_rand(iv, AES_BLOCK_SIZE));
-
- /* Copy the iv to the cipher text buffer to be written to disk */
- memcpy(buf, iv, AES_BLOCK_SIZE);
- ptr = buf + AES_BLOCK_SIZE;
-
- /* Encrypt the first block of the uuid table */
- bytes_crypted = vtpm_encrypt_block(&aes,
- iv, //iv
- plain, //plaintext
- ptr, //cipher text
- BUF_SIZE - AES_BLOCK_SIZE,
- &overlap,
- &num_vtpms);
-
- /* Write the iv followed by the crypted table*/
- TRY_WRITE(buf, bytes_crypted + AES_BLOCK_SIZE, "vtpm uuid table");
-
- /* Decrement the number of bytes encrypted */
- cipher_sz -= bytes_crypted + AES_BLOCK_SIZE;
-
- /* If there are more vtpms, encrypt and write them block by block */
- while(cipher_sz > 0) {
- /* Encrypt the next block of the uuid table */
- bytes_crypted = vtpm_encrypt_block(&aes,
- iv,
- plain,
- buf,
- BUF_SIZE,
- &overlap,
- &num_vtpms);
-
- /* Write the cipher text to disk */
- TRY_WRITE(buf, bytes_crypted, "vtpm uuid table");
-
- cipher_sz -= bytes_crypted;
- }
-
- goto egress;
-abort_egress:
-egress:
- return status;
-}
-
-
-/**************************************
- * PUBLIC FUNCTIONS
- * ***********************************/
-
-int vtpm_storage_init(void) {
- struct blkfront_info info;
- if((blkdev = init_blkfront(NULL, &info)) == NULL) {
- return -1;
- }
- if((blkfront_fd = blkfront_open(blkdev)) < 0) {
- return -1;
- }
- return 0;
-}
-
-void vtpm_storage_shutdown(void) {
- reset_store();
- close(blkfront_fd);
-}
-
-TPM_RESULT vtpm_storage_load_hashkey(const uuid_t uuid, uint8_t hashkey[HASHKEYSZ])
-{
- TPM_RESULT status = TPM_SUCCESS;
- int index;
- uint8_t cipher[RSA_CIPHER_SIZE];
- uint8_t clear[RSA_CIPHER_SIZE];
- UINT32 clear_size;
-
- /* Find the index of this uuid */
- if((index = vtpm_get_index(uuid)) < 0) {
- index = -index-1;
- vtpmlogerror(VTPM_LOG_VTPM, "LoadKey failure: Unrecognized uuid! " UUID_FMT "\n", UUID_BYTES(uuid));
- status = TPM_BAD_PARAMETER;
- goto abort_egress;
- }
-
- /* Read the table entry */
- lseek(blkfront_fd, g_store.vtpms[index].offset, SEEK_SET);
- TRY_READ(cipher, RSA_CIPHER_SIZE, "vtpm hashkey data");
-
- /* Decrypt the table entry */
- TPMTRYRETURN(TPM_UnBind(
- vtpm_globals.storage_key_handle,
- RSA_CIPHER_SIZE,
- cipher,
- &clear_size,
- clear,
- (const TPM_AUTHDATA*)&vtpm_globals.storage_key_usage_auth,
- &vtpm_globals.oiap));
-
- if(clear_size < HASHKEYSZ) {
- vtpmloginfo(VTPM_LOG_VTPM, "Decrypted Hash key size (%" PRIu32 ") was too small!\n", clear_size);
- status = TPM_RESOURCES;
- goto abort_egress;
- }
-
- memcpy(hashkey, clear, HASHKEYSZ);
-
- vtpmloginfo(VTPM_LOG_VTPM, "Loaded hash and key for vtpm " UUID_FMT "\n", UUID_BYTES(uuid));
- goto egress;
-abort_egress:
- vtpmlogerror(VTPM_LOG_VTPM, "Failed to load key\n");
-egress:
- return status;
-}
-
-TPM_RESULT vtpm_storage_save_hashkey(const uuid_t uuid, uint8_t hashkey[HASHKEYSZ])
-{
- TPM_RESULT status = TPM_SUCCESS;
- int index;
- uint8_t buf[RSA_CIPHER_SIZE];
-
- /* Find the index of this uuid */
- if((index = vtpm_get_index(uuid)) < 0) {
- index = -index-1;
- /* Create a new vtpm */
- TPMTRYRETURN( vtpm_storage_new_vtpm(uuid, index) );
- }
-
- /* Encrypt the hash and key */
- TPMTRYRETURN( TPM_Bind(&vtpm_globals.storage_key,
- hashkey,
- HASHKEYSZ,
- buf));
-
- /* Write to disk */
- lseek(blkfront_fd, g_store.vtpms[index].offset, SEEK_SET);
- TRY_WRITE(buf, RSA_CIPHER_SIZE, "vtpm hashkey data");
-
- vtpmloginfo(VTPM_LOG_VTPM, "Saved hash and key for vtpm " UUID_FMT "\n", UUID_BYTES(uuid));
- goto egress;
-abort_egress:
- vtpmlogerror(VTPM_LOG_VTPM, "Failed to save key\n");
-egress:
- return status;
-}
-
-TPM_RESULT vtpm_storage_new_header()
-{
- TPM_RESULT status = TPM_SUCCESS;
- uint8_t buf[BUF_SIZE];
- uint8_t keybuf[AES_KEY_SIZE + sizeof(uint32_t)];
- uint8_t* ptr = buf;
- uint8_t* sptr;
-
- /* Clear everything first */
- reset_store();
-
- vtpmloginfo(VTPM_LOG_VTPM, "Creating new disk image header\n");
-
- /*Copy the ID string */
- memcpy(ptr, IDSTR, IDSTRLEN);
- ptr += IDSTRLEN;
-
- /*Copy the version */
- ptr = pack_UINT32(ptr, DISKVERS);
-
- /*Save the location of the key size */
- sptr = ptr;
- ptr += sizeof(UINT32);
-
- vtpmloginfo(VTPM_LOG_VTPM, "Saving root storage key..\n");
-
- /* Copy the storage key */
- ptr = pack_TPM_KEY(ptr, &vtpm_globals.storage_key);
-
- /* Now save the size */
- pack_UINT32(sptr, ptr - (sptr + 4));
-
- /* Create a fake aes key and set cipher text size to 0 */
- memset(keybuf, 0, sizeof(keybuf));
-
- vtpmloginfo(VTPM_LOG_VTPM, "Binding uuid table symmetric key..\n");
-
- /* Save the location of the aes key */
- g_store.aes_offset = ptr - buf;
-
- /* Store the fake aes key and vtpm count */
- TPMTRYRETURN(TPM_Bind(&vtpm_globals.storage_key,
- keybuf,
- sizeof(keybuf),
- ptr));
- ptr+= RSA_CIPHER_SIZE;
-
- /* Write the header to disk */
- lseek(blkfront_fd, 0, SEEK_SET);
- TRY_WRITE(buf, ptr-buf, "vtpm header");
-
- /* Save the location of the uuid table */
- g_store.uuid_offset = get_offset();
-
- /* Save the end offset */
- g_store.end_offset = (g_store.uuid_offset + RSA_CIPHER_SIZE) & ~(RSA_CIPHER_SIZE -1);
-
- vtpmloginfo(VTPM_LOG_VTPM, "Saved new manager disk header.\n");
-
- goto egress;
-abort_egress:
-egress:
- return status;
-}
-
-
-TPM_RESULT vtpm_storage_load_header(void)
-{
- TPM_RESULT status = TPM_SUCCESS;
- uint32_t v32;
- uint8_t buf[BUF_SIZE];
- uint8_t* ptr = buf;
- aes_context aes;
-
- /* Clear everything first */
- reset_store();
-
- /* Read the header from disk */
- lseek(blkfront_fd, 0, SEEK_SET);
- TRY_READ(buf, IDSTRLEN + sizeof(UINT32) + sizeof(UINT32), "vtpm header");
-
- vtpmloginfo(VTPM_LOG_VTPM, "Loading disk image header\n");
-
- /* Verify the ID string */
- if(memcmp(ptr, IDSTR, IDSTRLEN)) {
- vtpmlogerror(VTPM_LOG_VTPM, "Invalid ID string in disk image!\n");
- status = TPM_FAIL;
- goto abort_egress;
- }
- ptr+=IDSTRLEN;
-
- /* Unpack the version */
- ptr = unpack_UINT32(ptr, &v32);
-
- /* Verify the version */
- if(v32 != DISKVERS) {
- vtpmlogerror(VTPM_LOG_VTPM, "Unsupported disk image version number %" PRIu32 "\n", v32);
- status = TPM_FAIL;
- goto abort_egress;
- }
-
- /* Size of the storage key */
- ptr = unpack_UINT32(ptr, &v32);
-
- /* Sanity check */
- if(v32 > BUF_SIZE) {
- vtpmlogerror(VTPM_LOG_VTPM, "Size of storage key (%" PRIu32 ") is too large!\n", v32);
- status = TPM_IOERROR;
- goto abort_egress;
- }
-
- /* read the storage key */
- TRY_READ(buf, v32, "storage pub key");
-
- vtpmloginfo(VTPM_LOG_VTPM, "Unpacking storage key\n");
-
- /* unpack the storage key */
- ptr = unpack_TPM_KEY(buf, &vtpm_globals.storage_key, UNPACK_ALLOC);
-
- /* Load Storage Key into the TPM */
- TPMTRYRETURN( TPM_LoadKey(
- TPM_SRK_KEYHANDLE,
- &vtpm_globals.storage_key,
- &vtpm_globals.storage_key_handle,
- (const TPM_AUTHDATA*)&vtpm_globals.srk_auth,
- &vtpm_globals.oiap));
-
- /* Initialize the storage key auth */
- memset(vtpm_globals.storage_key_usage_auth, 0, sizeof(TPM_AUTHDATA));
-
- /* Store the offset of the aes key */
- g_store.aes_offset = get_offset();
-
- /* Read the rsa cipher text for the aes key */
- TRY_READ(buf, RSA_CIPHER_SIZE, "aes key");
- ptr = buf + RSA_CIPHER_SIZE;
-
- vtpmloginfo(VTPM_LOG_VTPM, "Unbinding uuid table symmetric key\n");
-
- /* Decrypt the aes key protecting the uuid table */
- UINT32 datalen;
- TPMTRYRETURN(TPM_UnBind(
- vtpm_globals.storage_key_handle,
- RSA_CIPHER_SIZE,
- buf,
- &datalen,
- ptr,
- (const TPM_AUTHDATA*)&vtpm_globals.storage_key_usage_auth,
- &vtpm_globals.oiap));
-
- /* Validate the length of the output buffer */
- if(datalen < AES_KEY_SIZE + sizeof(UINT32)) {
- vtpmlogerror(VTPM_LOG_VTPM, "Unbound AES key size (%d) was too small! expected (%zu)\n", datalen, AES_KEY_SIZE + sizeof(UINT32));
- status = TPM_IOERROR;
- goto abort_egress;
- }
-
- /* Extract the aes key */
- aes_setkey_dec(&aes, ptr, AES_KEY_BITS);
- ptr+= AES_KEY_SIZE;
-
- /* Extract the ciphertext size */
- ptr = unpack_UINT32(ptr, &v32);
- int cipher_size = v32;
-
- /* Sanity check */
- if(cipher_size & (AES_BLOCK_SIZE-1)) {
- vtpmlogerror(VTPM_LOG_VTPM, "Cipher text size (%" PRIu32 ") is not a multiple of the aes block size! (%d)\n", v32, AES_BLOCK_SIZE);
- status = TPM_IOERROR;
- goto abort_egress;
- }
-
- /* Save the location of the uuid table */
- g_store.uuid_offset = get_offset();
-
- /* Only decrypt the table if there are vtpms to decrypt */
- if(cipher_size > 0) {
- int rbytes;
- int overlap = 0;
- uint8_t plain[BUF_SIZE + AES_BLOCK_SIZE];
- uint8_t iv[AES_BLOCK_SIZE];
-
- vtpmloginfo(VTPM_LOG_VTPM, "Decrypting uuid table\n");
-
- /* Pre allocate the vtpm array */
- g_store.num_vtpms_alloced = cipher_size / UUID_TBL_ENT_SIZE;
- g_store.vtpms = malloc(sizeof(struct Vtpm) * g_store.num_vtpms_alloced);
-
- /* Read the iv and the first chunk of cipher text */
- rbytes = MIN(cipher_size, BUF_SIZE);
- TRY_READ(buf, rbytes, "vtpm uuid table\n");
- cipher_size -= rbytes;
-
- /* Copy the iv */
- memcpy(iv, buf, AES_BLOCK_SIZE);
- ptr = buf + AES_BLOCK_SIZE;
-
- /* Remove the iv from the number of bytes to decrypt */
- rbytes -= AES_BLOCK_SIZE;
-
- /* Decrypt and extract vtpms */
- vtpm_decrypt_block(&aes,
- iv, ptr, plain,
- rbytes, &overlap);
-
- /* Read the rest of the table if there is more */
- while(cipher_size > 0) {
- /* Read next chunk of cipher text */
- rbytes = MIN(cipher_size, BUF_SIZE);
- TRY_READ(buf, rbytes, "vtpm uuid table");
- cipher_size -= rbytes;
-
- /* Decrypt a block of text */
- vtpm_decrypt_block(&aes,
- iv, buf, plain,
- rbytes, &overlap);
-
- }
- vtpmloginfo(VTPM_LOG_VTPM, "Loaded %d vtpms!\n", g_store.num_vtpms);
- }
-
- /* The end of the key table, new vtpms go here */
- int uuid_end = (get_offset() + RSA_CIPHER_SIZE) & ~(RSA_CIPHER_SIZE -1);
- g_store.end_offset = uuid_end;
-
- /* Compute the end offset while validating vtpms*/
- for(int i = 0; i < g_store.num_vtpms; ++i) {
- /* offset must not collide with previous data */
- if(g_store.vtpms[i].offset < uuid_end) {
- vtpmlogerror(VTPM_LOG_VTPM, "vtpm: " UUID_FMT
- " offset (%d) is before end of uuid table (%d)!\n",
- UUID_BYTES(g_store.vtpms[i].uuid),
- g_store.vtpms[i].offset, uuid_end);
- status = TPM_IOERROR;
- goto abort_egress;
- }
- /* offset must be at a multiple of cipher size */
- if(g_store.vtpms[i].offset & (RSA_CIPHER_SIZE-1)) {
- vtpmlogerror(VTPM_LOG_VTPM, "vtpm: " UUID_FMT
- " offset(%d) is not at a multiple of the rsa cipher text size (%d)!\n",
- UUID_BYTES(g_store.vtpms[i].uuid),
- g_store.vtpms[i].offset, RSA_CIPHER_SIZE);
- status = TPM_IOERROR;
- goto abort_egress;
- }
- /* Save the last offset */
- if(g_store.vtpms[i].offset >= g_store.end_offset) {
- g_store.end_offset = g_store.vtpms[i].offset + RSA_CIPHER_SIZE;
- }
- }
-
- goto egress;
-abort_egress:
- //An error occured somewhere
- vtpmlogerror(VTPM_LOG_VTPM, "Failed to load manager data!\n");
-
- //Clear the data store
- reset_store();
-
- //Reset the storage key structure
- free_TPM_KEY(&vtpm_globals.storage_key);
- {
- TPM_KEY key = TPM_KEY_INIT;
- vtpm_globals.storage_key = key;
- }
-
- //Reset the storage key handle
- TPM_EvictKey(vtpm_globals.storage_key_handle);
- vtpm_globals.storage_key_handle = 0;
-egress:
- return status;
-}
-
-#if 0
-/* For testing disk IO */
-void add_fake_vtpms(int num) {
- for(int i = 0; i < num; ++i) {
- uint32_t ind = cpu_to_be32(i);
-
- uuid_t uuid;
- memset(uuid, 0, sizeof(uuid_t));
- memcpy(uuid, &ind, sizeof(ind));
- int index = vtpm_get_index(uuid);
- index = -index-1;
-
- vtpm_storage_new_vtpm(uuid, index);
- }
-}
-#endif
diff --git a/stubdom/vtpmmgr/vtpm_storage.h b/stubdom/vtpmmgr/vtpm_storage.h
deleted file mode 100644
index a5a5fd7..0000000
--- a/stubdom/vtpmmgr/vtpm_storage.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2010-2012 United States Government, as represented by
- * the Secretary of Defense. All rights reserved.
- *
- * based off of the original tools/vtpm_manager code base which is:
- * Copyright (c) 2005, Intel Corp.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef VTPM_STORAGE_H
-#define VTPM_STORAGE_h
-
-#include "uuid.h"
-
-#define VTPM_NVMKEY_SIZE 32
-#define HASHKEYSZ (sizeof(TPM_DIGEST) + VTPM_NVMKEY_SIZE)
-
-/* Initialize the storage system and its virtual disk */
-int vtpm_storage_init(void);
-
-/* Shutdown the storage system and its virtual disk */
-void vtpm_storage_shutdown(void);
-
-/* Loads Sha1 hash and 256 bit AES key from disk and stores them
- * packed together in outbuf. outbuf must be freed
- * by the caller using buffer_free()
- */
-TPM_RESULT vtpm_storage_load_hashkey(const uuid_t uuid, uint8_t hashkey[HASHKEYSZ]);
-
-/* inbuf must contain a sha1 hash followed by a 256 bit AES key.
- * Encrypts and stores the hash and key to disk */
-TPM_RESULT vtpm_storage_save_hashkey(const uuid_t uuid, uint8_t hashkey[HASHKEYSZ]);
-
-/* Load the vtpm manager data - call this on startup */
-TPM_RESULT vtpm_storage_load_header(void);
-
-/* Saves the vtpm manager data - call this on shutdown */
-TPM_RESULT vtpm_storage_new_header(void);
-
-
-#endif
diff --git a/stubdom/vtpmmgr/vtpmmgr.h b/stubdom/vtpmmgr/vtpmmgr.h
index 50a1992..2d9d153 100644
--- a/stubdom/vtpmmgr/vtpmmgr.h
+++ b/stubdom/vtpmmgr/vtpmmgr.h
@@ -50,16 +50,26 @@
struct vtpm_globals {
int tpm_fd;
- TPM_KEY storage_key;
- TPM_HANDLE storage_key_handle; // Key used by persistent store
TPM_AUTH_SESSION oiap; // OIAP session for storageKey
- TPM_AUTHDATA storage_key_usage_auth;
TPM_AUTHDATA owner_auth;
TPM_AUTHDATA srk_auth;
entropy_context entropy;
ctr_drbg_context ctr_drbg;
+
+ int hw_locality;
+};
+
+struct tpm_opaque {
+ uuid_t *uuid;
+ struct mem_group *group;
+ struct mem_vtpm *vtpm;
+
+ domid_t domid;
+ unsigned int handle;
+
+ uint8_t kern_hash[20];
};
// --------------------------- Global Values --------------------------
@@ -68,7 +78,7 @@ extern struct vtpm_globals vtpm_globals; // Key info and DMI states
TPM_RESULT vtpmmgr_init(int argc, char** argv);
void vtpmmgr_shutdown(void);
-TPM_RESULT vtpmmgr_handle_cmd(const uuid_t uuid, tpmcmd_t* tpmcmd);
+TPM_RESULT vtpmmgr_handle_cmd(struct tpm_opaque *opq, tpmcmd_t* tpmcmd);
inline TPM_RESULT vtpmmgr_rand(unsigned char* bytes, size_t num_bytes) {
return ctr_drbg_random(&vtpm_globals.ctr_drbg, bytes, num_bytes) == 0 ? 0 : TPM_FAIL;
diff --git a/tools/Makefile b/tools/Makefile
index 00c69ee..af9798a 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -16,14 +16,10 @@ SUBDIRS-y += console
SUBDIRS-y += xenmon
SUBDIRS-y += xenstat
SUBDIRS-$(CONFIG_Linux) += memshr
-ifeq ($(CONFIG_X86)$(CONFIG_Linux),yy)
SUBDIRS-$(CONFIG_BLKTAP1) += blktap
-endif
-SUBDIRS-$(CONFIG_Linux) += blktap2
-SUBDIRS-$(CONFIG_NetBSD) += blktap2
+SUBDIRS-$(CONFIG_BLKTAP2) += blktap2
SUBDIRS-$(CONFIG_NetBSD) += xenbackendd
SUBDIRS-y += libfsimage
-SUBDIRS-$(LIBXENAPI_BINDINGS) += libxen
SUBDIRS-$(CONFIG_Linux) += libvchan
# do not recurse in to a dir we are about to delete
@@ -34,7 +30,6 @@ endif
SUBDIRS-y += xenpmd
SUBDIRS-y += libxl
-SUBDIRS-y += remus
SUBDIRS-$(CONFIG_X86) += xenpaging
SUBDIRS-$(CONFIG_X86) += debugger/gdbsx
SUBDIRS-$(CONFIG_X86) += debugger/kdd
@@ -47,6 +42,10 @@ SUBDIRS-y += pygrub
SUBDIRS-$(OCAML_TOOLS) += ocaml
endif
+ifeq ($(CONFIG_RUMP),y)
+SUBDIRS-y := include libxc xenstore
+endif
+
# For the sake of linking, set the sys-root
ifneq ($(CROSS_COMPILE),)
CROSS_BIN_PATH ?= /usr/$(CROSS_COMPILE:-=)/bin
@@ -55,19 +54,27 @@ export CROSS_SYS_ROOT # exported for check/funcs.sh
export CROSS_BIN_PATH # exported for cross-install.sh
endif
-.PHONY: all
-all: subdirs-all
+.PHONY: build all
+build all: subdirs-all
.PHONY: install
install: subdirs-install
$(INSTALL_DIR) $(DESTDIR)/var/xen/dump
$(INSTALL_DIR) $(DESTDIR)/var/log/xen
$(INSTALL_DIR) $(DESTDIR)/var/lib/xen
- $(INSTALL_DIR) $(DESTDIR)/var/lock/subsys
.PHONY: uninstall
uninstall: D=$(DESTDIR)
uninstall:
+ [ -d $(D)$(XEN_CONFIG_DIR) ] && mv -f $(D)$(XEN_CONFIG_DIR) $(D)$(XEN_CONFIG_DIR).old-`date +%s` || true
+ rm -rf $(D)$(CONFIG_DIR)/init.d/xendomains $(D)$(CONFIG_DIR)/init.d/xend
+ rm -rf $(D)$(CONFIG_DIR)/init.d/xencommons $(D)$(CONFIG_DIR)/init.d/xen-watchdog
+ rm -f $(D)$(CONFIG_DIR)/udev/rules.d/xen-backend.rules
+ rm -f $(D)$(CONFIG_DIR)/udev/rules.d/xend.rules
+ rm -f $(D)$(SYSCONFIG_DIR)/xendomains
+ rm -f $(D)$(SBINDIR)/xendomains
+ rm -f $(D)$(SYSCONFIG_DIR)/xencommons
+ rm -rf $(D)/var/lib/xen*
rm -rf $(D)$(BINDIR)/cpuperf-perfcntr $(D)$(BINDIR)/cpuperf-xen
rm -rf $(D)$(BINDIR)/xc_shadow
rm -rf $(D)$(BINDIR)/pygrub
@@ -86,8 +93,7 @@ uninstall:
rm -rf $(D)$(LIBDIR)/libxenctrl* $(D)$(LIBDIR)/libxenguest*
rm -rf $(D)$(LIBDIR)/libxenstore* $(D)$(LIBDIR)/libxlutil*
rm -rf $(D)$(LIBDIR)/python/xen $(D)$(LIBDIR)/python/grub
- rm -rf $(D)$(LIBDIR)/xen/
- rm -rf $(D)$(LIBEXEC)/xen*
+ rm -rf $(D)$(LIBEXEC)
rm -rf $(D)$(SBINDIR)/setmask
rm -rf $(D)$(SBINDIR)/xen* $(D)$(SBINDIR)/netfix $(D)$(SBINDIR)/xm
rm -rf $(D)$(SHAREDIR)/doc/xen
@@ -107,47 +113,57 @@ distclean: subdirs-distclean
config.cache autom4te.cache
ifneq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
-IOEMU_CONFIGURE_CROSS ?= --cpu=$(XEN_TARGET_ARCH) \
- --cross-prefix=$(CROSS_COMPILE) \
+IOEMU_CONFIGURE_CROSS ?= --cross-prefix=$(CROSS_COMPILE) \
--interp-prefix=$(CROSS_SYS_ROOT)
endif
-QEMU_ROOT := $(shell if [ -d "$(CONFIG_QEMU)" ]; then echo "$(CONFIG_QEMU)"; else echo .; fi)
+ifeq ($(XEN_TOOLS_RPATH),y)
+QEMU_UPSTREAM_RPATH := -Wl,-rpath,$(LIBEXEC_LIB):$(LIBDIR)
+IOEMU_EXTRA_LDFLAGS := --extra-ldflags="-Wl,-rpath,$(LIBDIR)"
+else
+QEMU_UPSTREAM_RPATH := -Wl,-rpath,$(LIBEXEC_LIB)
+IOEMU_EXTRA_LDFLAGS :=
+endif
+
+QEMU_ROOT := $(shell if [ -d "$(QEMU_TRADITIONAL_LOC)" ]; then echo "$(QEMU_TRADITIONAL_LOC)"; else echo .; fi)
ifneq ($(QEMU_ROOT),.)
export QEMU_ROOT
endif
qemu-xen-traditional-dir-find:
set -ex; \
- if test -d $(CONFIG_QEMU); then \
+ if test -d $(QEMU_TRADITIONAL_LOC); then \
mkdir -p qemu-xen-traditional-dir; \
else \
export GIT=$(GIT); \
- $(XEN_ROOT)/scripts/git-checkout.sh $(CONFIG_QEMU) $(QEMU_TAG) qemu-xen-traditional-dir; \
+ $(XEN_ROOT)/scripts/git-checkout.sh $(QEMU_TRADITIONAL_LOC) $(QEMU_TRADITIONAL_REVISION) qemu-xen-traditional-dir; \
fi
qemu-xen-dir-find:
- if test -d $(QEMU_UPSTREAM_URL) ; then \
+ if test -d $(QEMU_UPSTREAM_LOC) ; then \
mkdir -p qemu-xen-dir; \
else \
export GIT=$(GIT); \
- $(XEN_ROOT)/scripts/git-checkout.sh $(QEMU_UPSTREAM_URL) $(QEMU_UPSTREAM_REVISION) qemu-xen-dir ; \
+ $(XEN_ROOT)/scripts/git-checkout.sh $(QEMU_UPSTREAM_LOC) $(QEMU_UPSTREAM_REVISION) qemu-xen-dir ; \
fi
.PHONY: qemu-xen-traditional-dir-force-update
-qemu-xen-traditional-dir-force-update:
+qemu-xen-traditional-dir-force-update: qemu-xen-traditional-dir-find
set -ex; \
- if [ "$(QEMU_TAG)" ]; then \
+ if [ "$(QEMU_TRADITIONAL_REVISION)" ]; then \
cd qemu-xen-traditional-dir-remote; \
$(GIT) fetch origin; \
- $(GIT) reset --hard $(QEMU_TAG); \
+ $(GIT) reset --hard $(QEMU_TRADITIONAL_REVISION); \
fi
subdir-all-qemu-xen-traditional-dir: qemu-xen-traditional-dir-find
set -e; \
$(buildmakevars2shellvars); \
cd qemu-xen-traditional-dir; \
- $(QEMU_ROOT)/xen-setup $(IOEMU_CONFIGURE_CROSS); \
+ $(QEMU_ROOT)/xen-setup \
+ $(IOEMU_EXTRA_LDFLAGS) \
+ --cpu=$(IOEMU_CPU_ARCH) \
+ $(IOEMU_CONFIGURE_CROSS); \
$(MAKE) all
subdir-install-qemu-xen-traditional-dir: qemu-xen-traditional-dir-find
@@ -156,6 +172,8 @@ subdir-install-qemu-xen-traditional-dir: qemu-xen-traditional-dir-find
cd qemu-xen-traditional-dir; \
$(QEMU_ROOT)/xen-setup \
--extra-cflags="$(EXTRA_CFLAGS_QEMU_TRADITIONAL)" \
+ $(IOEMU_EXTRA_LDFLAGS) \
+ --cpu=$(IOEMU_CPU_ARCH) \
$(IOEMU_CONFIGURE_CROSS); \
$(MAKE) install
@@ -165,7 +183,7 @@ subdir-clean-qemu-xen-traditional-dir:
fi
.PHONY: qemu-xen-dir-force-update
-qemu-xen-dir-force-update:
+qemu-xen-dir-force-update: qemu-xen-dir-find
set -ex; \
if [ "$(QEMU_UPSTREAM_REVISION)" ]; then \
cd qemu-xen-dir-remote; \
@@ -180,30 +198,35 @@ QEMU_XEN_ENABLE_DEBUG :=
endif
subdir-all-qemu-xen-dir: qemu-xen-dir-find
- if test -d $(QEMU_UPSTREAM_URL) ; then \
- source=$(QEMU_UPSTREAM_URL); \
+ if test -d $(QEMU_UPSTREAM_LOC) ; then \
+ source=$(QEMU_UPSTREAM_LOC); \
else \
source=.; \
fi; \
cd qemu-xen-dir; \
$$source/configure --enable-xen --target-list=i386-softmmu \
$(QEMU_XEN_ENABLE_DEBUG) \
- --prefix=$(PREFIX) \
+ --prefix=$(LIBEXEC) \
+ --libdir=$(LIBEXEC_LIB) \
+ --includedir=$(LIBEXEC_INC) \
--source-path=$$source \
--extra-cflags="-I$(XEN_ROOT)/tools/include \
- -I$(XEN_ROOT)/tools/libxc \
- -I$(XEN_ROOT)/tools/xenstore \
- -I$(XEN_ROOT)/tools/xenstore/compat \
+ -I$(XEN_ROOT)/tools/libxc/include \
+ -I$(XEN_ROOT)/tools/xenstore/include \
+ -I$(XEN_ROOT)/tools/xenstore/compat/include \
$(EXTRA_CFLAGS_QEMU_XEN)" \
--extra-ldflags="-L$(XEN_ROOT)/tools/libxc \
- -L$(XEN_ROOT)/tools/xenstore" \
- --bindir=$(LIBEXEC) \
+ -L$(XEN_ROOT)/tools/xenstore \
+ $(QEMU_UPSTREAM_RPATH)" \
+ --bindir=$(LIBEXEC_BIN) \
--datadir=$(SHAREDIR)/qemu-xen \
- --localstatedir=/var \
+ --localstatedir=$(localstatedir) \
--disable-kvm \
--disable-docs \
--disable-guest-agent \
--python=$(PYTHON) \
+ $(CONFIG_QEMUU_EXTRA_ARGS) \
+ --cpu=$(IOEMU_CPU_ARCH) \
$(IOEMU_CONFIGURE_CROSS); \
$(MAKE) all
@@ -237,3 +260,17 @@ subdir-all-debugger/kdd: .phony
subdir-distclean-firmware: .phony
$(MAKE) -C firmware distclean
+
+subtree-force-update:
+ifeq ($(CONFIG_QEMU_XEN),y)
+ $(MAKE) qemu-xen-dir-force-update
+endif
+ifeq ($(CONFIG_QEMU_TRAD),y)
+ $(MAKE) qemu-xen-traditional-dir-force-update
+endif
+ $(MAKE) -C firmware subtree-force-update
+
+subtree-force-update-all:
+ $(MAKE) qemu-xen-dir-force-update
+ $(MAKE) qemu-xen-traditional-dir-force-update
+ $(MAKE) -C firmware subtree-force-update-all
diff --git a/tools/Rules.mk b/tools/Rules.mk
index 13d8fc1..87a56dc 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -19,31 +19,42 @@ XEN_LIBVCHAN = $(XEN_ROOT)/tools/libvchan
CFLAGS_xeninclude = -I$(XEN_INCLUDE)
-CFLAGS_libxenctrl = -I$(XEN_LIBXC) $(CFLAGS_xeninclude)
-LDLIBS_libxenctrl = $(XEN_LIBXC)/libxenctrl.so
+XENSTORE_XENSTORED ?= y
+
+ifneq ($(nosharedlibs),y)
+INSTALL_SHLIB = $(INSTALL_PROG)
+SYMLINK_SHLIB = ln -sf
+libextension = .so
+else
+libextension = .a
+XENSTORE_STATIC_CLIENTS=y
+# If something tries to use these it is a mistake. Provide references
+# to nonexistent programs to produce a sane error message.
+INSTALL_SHLIB = : install-shlib-unsupported-fail
+SYMLINK_SHLIB = : symlink-shlib-unsupported-fail
+endif
+
+CFLAGS_libxenctrl = -I$(XEN_LIBXC)/include $(CFLAGS_xeninclude)
+LDLIBS_libxenctrl = $(XEN_LIBXC)/libxenctrl$(libextension)
SHLIB_libxenctrl = -Wl,-rpath-link=$(XEN_LIBXC)
-CFLAGS_libxenguest = -I$(XEN_LIBXC) $(CFLAGS_xeninclude)
-LDLIBS_libxenguest = $(XEN_LIBXC)/libxenguest.so
+CFLAGS_libxenguest = -I$(XEN_LIBXC)/include $(CFLAGS_xeninclude)
+LDLIBS_libxenguest = $(XEN_LIBXC)/libxenguest$(libextension)
SHLIB_libxenguest = -Wl,-rpath-link=L$(XEN_LIBXC)
-CFLAGS_libxenstore = -I$(XEN_XENSTORE) $(CFLAGS_xeninclude)
-LDLIBS_libxenstore = $(XEN_XENSTORE)/libxenstore.so
+CFLAGS_libxenstore = -I$(XEN_XENSTORE)/include $(CFLAGS_xeninclude)
+LDLIBS_libxenstore = $(XEN_XENSTORE)/libxenstore$(libextension)
SHLIB_libxenstore = -Wl,-rpath-link=$(XEN_XENSTORE)
CFLAGS_libxenstat = -I$(XEN_LIBXENSTAT)
-LDLIBS_libxenstat = $(SHLIB_libxenctrl) $(SHLIB_libxenstore) $(XEN_LIBXENSTAT)/libxenstat.so
+LDLIBS_libxenstat = $(SHLIB_libxenctrl) $(SHLIB_libxenstore) $(XEN_LIBXENSTAT)/libxenstat$(libextension)
SHLIB_libxenstat = -Wl,-rpath-link=$(XEN_LIBXENSTAT)
CFLAGS_libxenvchan = -I$(XEN_LIBVCHAN)
LDLIBS_libxenvchan = $(SHLIB_libxenctrl) $(SHLIB_libxenstore) -L$(XEN_LIBVCHAN) -lxenvchan
SHLIB_libxenvchan = -Wl,-rpath-link=$(XEN_LIBVCHAN)
-ifeq ($(CONFIG_Linux),y)
-LIBXL_BLKTAP ?= y
-else
-LIBXL_BLKTAP ?= n
-endif
+LIBXL_BLKTAP ?= $(CONFIG_BLKTAP2)
ifeq ($(LIBXL_BLKTAP),y)
CFLAGS_libblktapctl = -I$(XEN_BLKTAP2)/control -I$(XEN_BLKTAP2)/include $(CFLAGS_xeninclude)
@@ -56,7 +67,7 @@ SHLIB_libblktapctl =
endif
CFLAGS_libxenlight = -I$(XEN_XENLIGHT) $(CFLAGS_libxenctrl) $(CFLAGS_xeninclude)
-LDLIBS_libxenlight = $(XEN_XENLIGHT)/libxenlight.so $(SHLIB_libxenctrl) $(SHLIB_libxenstore) $(SHLIB_libblktapctl)
+LDLIBS_libxenlight = $(XEN_XENLIGHT)/libxenlight$(libextension) $(SHLIB_libxenctrl) $(SHLIB_libxenstore) $(SHLIB_libblktapctl)
SHLIB_libxenlight = -Wl,-rpath-link=$(XEN_XENLIGHT)
CFLAGS += -D__XEN_TOOLS__
diff --git a/tools/blktap/drivers/Makefile b/tools/blktap/drivers/Makefile
index 7461a95..cea8b3b 100644
--- a/tools/blktap/drivers/Makefile
+++ b/tools/blktap/drivers/Makefile
@@ -11,7 +11,7 @@ CFLAGS += $(CFLAGS_libxenctrl)
CFLAGS += $(CFLAGS_libxenstore)
CFLAGS += -D_GNU_SOURCE
-ifeq ($CONFIG_GCRYPT,y)
+ifeq ($(CONFIG_GCRYPT),y)
CFLAGS += -DUSE_GCRYPT
CRYPT_LIB := -lgcrypt
else
diff --git a/tools/blktap2/control/Makefile b/tools/blktap2/control/Makefile
index 86a433c..a88ff4c 100644
--- a/tools/blktap2/control/Makefile
+++ b/tools/blktap2/control/Makefile
@@ -52,13 +52,13 @@ $(LIBSONAME): $(LIB_SHARED)
ln -sf $< $@
tap-ctl: tap-ctl.o $(LIBNAME).so
- $(CC) $(LDFLAGS) -o $@ $^
+ $(CC) $(LDFLAGS) -o $@ $^ $(APPEND_LDFLAGS)
$(LIB_STATIC): $(CTL_OBJS)
$(AR) r $@ $^
$(LIB_SHARED): $(CTL_PICS)
- $(CC) $(LDFLAGS) -fPIC -Wl,$(SONAME_LDFLAG) -Wl,$(LIBSONAME) $(SHLIB_LDFLAGS) -rdynamic $^ -o $@
+ $(CC) $(LDFLAGS) -fPIC -Wl,$(SONAME_LDFLAG) -Wl,$(LIBSONAME) $(SHLIB_LDFLAGS) -rdynamic $^ -o $@ $(APPEND_LDFLAGS)
install: $(IBIN) $(LIB_STATIC) $(LIB_SHARED)
$(INSTALL_DIR) -p $(DESTDIR)$(SBINDIR)
diff --git a/tools/blktap2/drivers/Makefile b/tools/blktap2/drivers/Makefile
index 5c6ab6a..3476fc1 100644
--- a/tools/blktap2/drivers/Makefile
+++ b/tools/blktap2/drivers/Makefile
@@ -9,13 +9,15 @@ QCOW_UTIL = img2qcow qcow-create qcow2raw
LOCK_UTIL = lock-util
INST_DIR = $(SBINDIR)
-CFLAGS += -Werror -g
+CFLAGS += -Werror
CFLAGS += -Wno-unused
CFLAGS += -fno-strict-aliasing
CFLAGS += -I$(BLKTAP_ROOT)/include -I$(BLKTAP_ROOT)/drivers
CFLAGS += $(CFLAGS_libxenctrl)
CFLAGS += -D_GNU_SOURCE
CFLAGS += -DUSE_NFS_LOCKS
+# drivers/block-log.c incorrectly uses libxc internals
+CFLAGS += -I$(XEN_ROOT)/tools/libxc
ifeq ($(CONFIG_X86_64),y)
CFLAGS += -fPIC
@@ -79,25 +81,25 @@ all: $(IBIN) lock-util qcow-util
tapdisk2: $(TAP-OBJS-y) $(BLK-OBJS-y) $(MISC-OBJS-y) tapdisk2.o
- $(CC) -o $@ $^ $(LDFLAGS) -lrt -lz $(VHDLIBS) $(AIOLIBS) $(MEMSHRLIBS) -lm
+ $(CC) -o $@ $^ $(LDFLAGS) -lrt -lz $(VHDLIBS) $(AIOLIBS) $(MEMSHRLIBS) -lm $(APPEND_LDFLAGS)
tapdisk-client: tapdisk-client.o
- $(CC) -o $@ $^ $(LDFLAGS) -lrt
+ $(CC) -o $@ $^ $(LDFLAGS) -lrt $(APPEND_LDFLAGS)
tapdisk-stream tapdisk-diff: %: %.o $(TAP-OBJS-y) $(BLK-OBJS-y)
- $(CC) -o $@ $^ $(LDFLAGS) -lrt -lz $(VHDLIBS) $(AIOLIBS) $(MEMSHRLIBS) -lm
+ $(CC) -o $@ $^ $(LDFLAGS) -lrt -lz $(VHDLIBS) $(AIOLIBS) $(MEMSHRLIBS) -lm $(APPEND_LDFLAGS)
td-util: td.o tapdisk-utils.o tapdisk-log.o $(PORTABLE-OBJS-y)
- $(CC) -o $@ $^ $(LDFLAGS) $(VHDLIBS)
+ $(CC) -o $@ $^ $(LDFLAGS) $(VHDLIBS) $(APPEND_LDFLAGS)
lock-util: lock.c
- $(CC) $(CFLAGS) -DUTIL -o lock-util lock.c $(LDFLAGS)
+ $(CC) $(CFLAGS) -DUTIL -o lock-util lock.c $(LDFLAGS) $(APPEND_LDFLAGS)
.PHONY: qcow-util
qcow-util: img2qcow qcow2raw qcow-create
img2qcow qcow2raw qcow-create: %: %.o $(TAP-OBJS-y) $(BLK-OBJS-y)
- $(CC) -o $@ $^ $(LDFLAGS) -lrt -lz $(VHDLIBS) $(AIOLIBS) $(MEMSHRLIBS) -lm
+ $(CC) -o $@ $^ $(LDFLAGS) -lrt -lz $(VHDLIBS) $(AIOLIBS) $(MEMSHRLIBS) -lm $(APPEND_LDFLAGS)
install: all
$(INSTALL_DIR) -p $(DESTDIR)$(INST_DIR)
diff --git a/tools/blktap2/vhd/Makefile b/tools/blktap2/vhd/Makefile
index c5019de..fef0d36 100644
--- a/tools/blktap2/vhd/Makefile
+++ b/tools/blktap2/vhd/Makefile
@@ -31,10 +31,10 @@ LIBS_DEPENDS := lib/libvhd.so lib/vhd.a
$(LIBS_DEPENDS):subdirs-all
vhd-util: vhd-util.o $(LIBS_DEPENDS)
- $(CC) $(LDFLAGS) -o vhd-util vhd-util.o $(LIBS)
+ $(CC) $(LDFLAGS) -o vhd-util vhd-util.o $(LIBS) $(APPEND_LDFLAGS)
vhd-update: vhd-update.o $(LIBS_DEPENDS)
- $(CC) $(LDFLAGS) -o vhd-update vhd-update.o $(LIBS)
+ $(CC) $(LDFLAGS) -o vhd-update vhd-update.o $(LIBS) $(APPEND_LDFLAGS)
install: all
$(MAKE) subdirs-install
diff --git a/tools/blktap2/vhd/lib/Makefile b/tools/blktap2/vhd/lib/Makefile
index cdbb86c..99e3cdb 100644
--- a/tools/blktap2/vhd/lib/Makefile
+++ b/tools/blktap2/vhd/lib/Makefile
@@ -17,7 +17,6 @@ CFLAGS += -Wno-unused
CFLAGS += -I../../include
CFLAGS += -D_GNU_SOURCE
CFLAGS += -fPIC
-CFLAGS += -g
ifeq ($(CONFIG_Linux),y)
LIBS := -luuid
diff --git a/tools/config.h.in b/tools/config.h.in
index 015f2a1..2a0ae48 100644
--- a/tools/config.h.in
+++ b/tools/config.h.in
@@ -1,5 +1,8 @@
/* config.h.in. Generated from configure.ac by autoheader. */
+/* Blktap2 enabled */
+#undef HAVE_BLKTAP2
+
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
@@ -24,6 +27,9 @@
/* Qemu traditional enabled */
#undef HAVE_QEMU_TRADITIONAL
+/* ROMBIOS enabled */
+#undef HAVE_ROMBIOS
+
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
@@ -36,6 +42,9 @@
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
+/* Systemd available and enabled */
+#undef HAVE_SYSTEMD
+
/* Define to 1 if you have the <sys/eventfd.h> header file. */
#undef HAVE_SYS_EVENTFD_H
@@ -48,6 +57,12 @@
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
+/* Define to 1 if you have the <utmp.h> header file. */
+#undef HAVE_UTMP_H
+
+/* Define to 1 if you have the <valgrind/memcheck.h> header file. */
+#undef HAVE_VALGRIND_MEMCHECK_H
+
/* Define to 1 if you have the <yajl/yajl_version.h> header file. */
#undef HAVE_YAJL_YAJL_VERSION_H
diff --git a/tools/configure b/tools/configure
index b06fcf9..c65ad3a 100755
--- a/tools/configure
+++ b/tools/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Xen Hypervisor Tools 4.4.
+# Generated by GNU Autoconf 2.69 for Xen Hypervisor Tools 4.5.
#
# Report bugs to <xen-devel at lists.xen.org>.
#
@@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='Xen Hypervisor Tools'
PACKAGE_TARNAME='xen'
-PACKAGE_VERSION='4.4'
-PACKAGE_STRING='Xen Hypervisor Tools 4.4'
+PACKAGE_VERSION='4.5'
+PACKAGE_STRING='Xen Hypervisor Tools 4.5'
PACKAGE_BUGREPORT='xen-devel at lists.xen.org'
PACKAGE_URL='http://www.xen.org/'
@@ -624,6 +624,14 @@ ac_includes_default="\
ac_subst_vars='LTLIBOBJS
LIBOBJS
+SYSTEMD_LIBS
+SYSTEMD_CFLAGS
+SYSTEMD_MODULES_LOAD
+SYSTEMD_DIR
+systemd
+remus_netbuf
+LIBNL3_LIBS
+LIBNL3_CFLAGS
libiconv
PTYFUNCS_LIBS
PTHREAD_LIBS
@@ -648,6 +656,7 @@ CPP
pyconfig
PYTHONPATH
CHECKPOLICY
+XENSTORED
AWK
OCAMLFIND
OCAMLBUILD
@@ -683,21 +692,35 @@ APPEND_LIB
APPEND_INCLUDES
PREPEND_LIB
PREPEND_INCLUDES
+EXTRA_QEMUU_CONFIGURE_ARGS
ovmf_path
seabios_path
qemu_xen
+rombios
qemu_traditional
+blktap2
+LINUX_BACKEND_MODULES
blktap1
-xend
debug
seabios
-rombios
ovmf
xsmpolicy
ocamltools
-xenapi
monitors
githttp
+rpath
+XEN_PAGING_DIR
+XEN_LOCK_DIR
+XEN_SCRIPT_DIR
+XEN_CONFIG_DIR
+INITD_DIR
+CONFIG_DIR
+SHAREDIR
+XEN_LIB_STORED
+XEN_LOG_DIR
+XEN_RUN_DIR
+LIBEXEC_BIN
+CONFIG_LEAF_DIR
FILE_OFFSET_BITS
OBJEXT
EXEEXT
@@ -706,6 +729,7 @@ CPPFLAGS
LDFLAGS
CFLAGS
CC
+CONFIG_RUMP
host_os
host_vendor
host_cpu
@@ -756,21 +780,29 @@ ac_subst_files=''
ac_user_opts='
enable_option_checking
enable_largefile
+with_initddir
+with_sysconfig_leaf_dir
+enable_rpath
enable_githttp
enable_monitors
-enable_xenapi
enable_ocamltools
enable_xsmpolicy
enable_ovmf
-enable_rombios
enable_seabios
enable_debug
-enable_xend
enable_blktap1
+with_linux_backend_modules
+enable_blktap2
enable_qemu_traditional
+enable_rombios
with_system_qemu
with_system_seabios
with_system_ovmf
+with_extra_qemuu_configure_args
+with_xenstored
+enable_systemd
+with_systemd
+with_systemd_modules_load
'
ac_precious_vars='build_alias
host_alias
@@ -801,7 +833,11 @@ PKG_CONFIG
PKG_CONFIG_PATH
PKG_CONFIG_LIBDIR
glib_CFLAGS
-glib_LIBS'
+glib_LIBS
+LIBNL3_CFLAGS
+LIBNL3_LIBS
+SYSTEMD_CFLAGS
+SYSTEMD_LIBS'
# Initialize some variables set by options.
@@ -1342,7 +1378,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures Xen Hypervisor Tools 4.4 to adapt to many kinds of systems.
+\`configure' configures Xen Hypervisor Tools 4.5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1407,7 +1443,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of Xen Hypervisor Tools 4.4:";;
+ short | recursive ) echo "Configuration of Xen Hypervisor Tools 4.5:";;
esac
cat <<\_ACEOF
@@ -1416,26 +1452,40 @@ Optional Features:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--disable-largefile omit support for large files
+ --enable-rpath Build tools with -Wl,-rpath,LIBDIR (default is
+ DISABLED)
--enable-githttp Download GIT repositories via HTTP (default is
DISABLED)
--disable-monitors Disable xenstat and xentop monitoring tools (default
is ENABLED)
- --enable-xenapi Enable Xen API Bindings (default is DISABLED)
--disable-ocamltools Disable Ocaml tools (default is ENABLED)
--disable-xsmpolicy Disable XSM policy compilation (default is ENABLED)
--enable-ovmf Enable OVMF (default is DISABLED)
- --disable-rombios Disable ROM BIOS (default is ENABLED)
--disable-seabios Disable SeaBIOS (default is ENABLED)
--disable-debug Disable debug build of tools (default is ENABLED)
- --enable-xend Enable xend toolstack (default is DISABLED)
--enable-blktap1 Enable blktap1 tools (default is DISABLED)
+ --enable-blktap2 Enable blktap2, (DEFAULT is on for Linux, otherwise
+ off)
--enable-qemu-traditional
Enable qemu traditional device model, (DEFAULT is on
- for x86, otherwise off)
+ for Linux or NetBSD x86, otherwise off)
+ --enable-rombios Enable ROMBIOS, (DEFAULT is on if qemu-traditional
+ is enabled, otherwise off)
+ --enable-systemd Enable systemd support (default is DISABLED)
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-initddir=DIR Path to directory with sysv runlevel scripts.
+ [SYSCONFDIR/init.d]
+ --with-sysconfig-leaf-dir=SUBDIR
+ Name of subdirectory in /etc to store runtime
+ options for runlevel scripts and daemons such as
+ xenstored. This should be either "sysconfig" or
+ "default". [sysconfig]
+ --with-linux-backend-modules="mod1 mod2"
+ List of Linux backend module or modalias names to be
+ autoloaded on startup.
--with-system-qemu[=PATH]
Use system supplied qemu PATH or qemu (taken from
$PATH) as qemu-xen device model instead of building
@@ -1446,6 +1496,25 @@ Optional Packages:
--with-system-ovmf[=PATH]
Use system supplied OVMF PATH instead of building
and installing our own version
+ --with-extra-qemuu-configure-args[="--ARG1 ..."]
+ List of additional configure options for upstream
+ qemu
+ --with-xenstored[=oxenstored|xenstored]
+ This lets you choose which xenstore daemon you want,
+ you have two options: the original xenstored written
+ in C (xenstored) or the newer and robust one written
+ in Ocaml (oxenstored). The oxenstored daemon is the
+ default but can only be used if you have ocaml
+ library / build dependencies solved, if you have not
+ specified a preference and do not have ocaml
+ dependencies resolved we'll enable the C xenstored
+ for you. If you ask for oxenstored we'll complain
+ until you resolve those dependencies
+ --with-systemd=DIR set directory for systemd service files
+ [PREFIX/lib/systemd/system]
+ --with-systemd-modules-load=DIR
+ set directory for systemd modules load files
+ [PREFIX/lib/modules-load.d/]
Some influential environment variables:
CC C compiler command
@@ -1481,6 +1550,13 @@ Some influential environment variables:
path overriding pkg-config's built-in search path
glib_CFLAGS C compiler flags for glib, overriding pkg-config
glib_LIBS linker flags for glib, overriding pkg-config
+ LIBNL3_CFLAGS
+ C compiler flags for LIBNL3, overriding pkg-config
+ LIBNL3_LIBS linker flags for LIBNL3, overriding pkg-config
+ SYSTEMD_CFLAGS
+ C compiler flags for SYSTEMD, overriding pkg-config
+ SYSTEMD_LIBS
+ linker flags for SYSTEMD, overriding pkg-config
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
@@ -1549,7 +1625,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-Xen Hypervisor Tools configure 4.4
+Xen Hypervisor Tools configure 4.5
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1851,7 +1927,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by Xen Hypervisor Tools $as_me 4.4, which was
+It was created by Xen Hypervisor Tools $as_me 4.5, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2200,7 +2276,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
-ac_config_files="$ac_config_files ../config/Tools.mk"
+ac_config_files="$ac_config_files ../config/Tools.mk hotplug/FreeBSD/rc.d/xencommons hotplug/Linux/init.d/sysconfig.xencommons hotplug/Linux/init.d/xen-watchdog hotplug/Linux/init.d/xencommons hotplug/Linux/init.d/xendomains hotplug/Linux/systemd/proc-xen.mount hotplug/Linux/systemd/var-lib-xenstored.mount hotplug/Linux/systemd/xen-init-dom0.service hotplug/Linux/systemd/xen-qemu-dom0-disk-backend.service hotplug/Linux/systemd/xen-watchdog.service hotplug/Linux/systemd/xenconsoled.servic [...]
ac_config_headers="$ac_config_headers config.h"
@@ -2319,6 +2395,12 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+case $host_vendor in
+rumpxen) CONFIG_RUMP=y; rump=true ;;
+*) CONFIG_RUMP=n; rump=false ;;
+esac
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -3428,6 +3510,44 @@ esac
# PKG_CHECK_MODULES
+# PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+# ---------------------------------------------------------------------
+# Checks for existence of MODULES and gathers its build flags with
+# static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
+# and VARIABLE-PREFIX_LIBS from --libs.
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES_STATIC might not happen, you should be sure to include
+# an explicit call to PKG_PROG_PKG_CONFIG in your configure.ac.
+
+
+
+# PKG_INSTALLDIR(DIRECTORY)
+# -------------------------
+# Substitutes the variable pkgconfigdir as the location where a module
+# should install pkg-config .pc files. By default the directory is
+# $libdir/pkgconfig, but the default can be changed by passing
+# DIRECTORY. The user can override through the --with-pkgconfigdir
+# parameter.
+
+
+# PKG_NOARCH_INSTALLDIR(DIRECTORY)
+# -------------------------
+# Substitutes the variable noarch_pkgconfigdir as the location where a
+# module should install arch-independent pkg-config .pc files. By
+# default the directory is $datadir/pkgconfig, but the default can be
+# changed by passing DIRECTORY. The user can override through the
+# --with-noarch-pkgconfigdir parameter.
+
+
+# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# -------------------------------------------
+# Retrieves the value of the pkg-config variable for the given module.
+# PKG_CHECK_VAR
+
+
# We define, separately, PTHREAD_CFLAGS, _LDFLAGS and _LIBS
# even though currently we don't set them very separately.
@@ -3538,8 +3658,178 @@ esac
+
+# systemd.m4 - Macros to check for and enable systemd -*- Autoconf -*-
+#
+# Copyright (C) 2014 Luis R. Rodriguez <mcgrof at suse.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test "x$prefix" = "xNONE" && prefix=$ac_default_prefix
+test "x$exec_prefix" = "xNONE" && exec_prefix=${prefix}
+
+if test "$localstatedir" = '${prefix}/var' ; then
+ localstatedir=/var
+fi
+
+bindir=`eval echo $bindir`
+sbindir=`eval echo $sbindir`
+libdir=`eval echo $libdir`
+
+if test "x$sysconfdir" = 'x${prefix}/etc' ; then
+ case "$host_os" in
+ *freebsd*)
+ sysconfdir=$prefix/etc
+ ;;
+ *solaris*)
+ if test "$prefix" = "/usr" ; then
+ sysconfdir=/etc
+ else
+ sysconfdir=$prefix/etc
+ fi
+ ;;
+ *)
+ sysconfdir=/etc
+ ;;
+ esac
+fi
+
+
+# Check whether --with-initddir was given.
+if test "${with_initddir+set}" = set; then :
+ withval=$with_initddir; initddir_path=$withval
+else
+ case "$host_os" in
+ *linux*)
+ if test -d $sysconfdir/rc.d/init.d ; then
+ initddir_path=$sysconfdir/rc.d/init.d
+ else
+ initddir_path=$sysconfdir/init.d
+ fi
+ ;;
+ *)
+ initddir_path=$sysconfdir/rc.d
+ ;;
+ esac
+fi
+
+
+
+# Check whether --with-sysconfig-leaf-dir was given.
+if test "${with_sysconfig_leaf_dir+set}" = set; then :
+ withval=$with_sysconfig_leaf_dir; config_leaf_dir=$withval
+else
+ config_leaf_dir=sysconfig
+ if test ! -d /etc/sysconfig ; then config_leaf_dir=default ; fi
+fi
+
+CONFIG_LEAF_DIR=$config_leaf_dir
+
+
+if test "$libexecdir" = '${exec_prefix}/libexec' ; then
+ case "$host_os" in
+ *netbsd*) ;;
+ *)
+ libexecdir='${exec_prefix}/lib'
+ ;;
+ esac
+fi
+libexecdir=`eval echo $libexecdir`
+LIBEXEC_BIN=`eval echo $libexecdir/$PACKAGE_TARNAME/bin`
+
+
+XEN_RUN_DIR=$localstatedir/run/xen
+
+
+XEN_LOG_DIR=$localstatedir/log/xen
+
+
+XEN_LIB_STORED=$localstatedir/lib/xenstored
+
+
+SHAREDIR=$prefix/share
+
+
+CONFIG_DIR=$sysconfdir
+
+
+INITD_DIR=$initddir_path
+
+
+XEN_CONFIG_DIR=$CONFIG_DIR/xen
+
+
+XEN_SCRIPT_DIR=$XEN_CONFIG_DIR/scripts
+
+
+case "$host_os" in
+*freebsd*) XEN_LOCK_DIR=$localstatedir/lib ;;
+*netbsd*) XEN_LOCK_DIR=$localstatedir/lib ;;
+*) XEN_LOCK_DIR=$localstatedir/lock ;;
+esac
+
+
+XEN_PAGING_DIR=$localstatedir/lib/xen/xenpaging
+
+
+
# Enable/disable options
+# Check whether --enable-rpath was given.
+if test "${enable_rpath+set}" = set; then :
+ enableval=$enable_rpath;
+fi
+
+
+if test "x$enable_rpath" = "xno"; then :
+
+ ax_cv_rpath="n"
+
+elif test "x$enable_rpath" = "xyes"; then :
+
+ ax_cv_rpath="y"
+
+elif test -z $ax_cv_rpath; then :
+
+ ax_cv_rpath="n"
+
+fi
+rpath=$ax_cv_rpath
+
+
+
# Check whether --enable-githttp was given.
if test "${enable_githttp+set}" = set; then :
enableval=$enable_githttp;
@@ -3586,29 +3876,6 @@ monitors=$ax_cv_monitors
-# Check whether --enable-xenapi was given.
-if test "${enable_xenapi+set}" = set; then :
- enableval=$enable_xenapi;
-fi
-
-
-if test "x$enable_xenapi" = "xno"; then :
-
- ax_cv_xenapi="n"
-
-elif test "x$enable_xenapi" = "xyes"; then :
-
- ax_cv_xenapi="y"
-
-elif test -z $ax_cv_xenapi; then :
-
- ax_cv_xenapi="n"
-
-fi
-xenapi=$ax_cv_xenapi
-
-
-
# Check whether --enable-ocamltools was given.
if test "${enable_ocamltools+set}" = set; then :
enableval=$enable_ocamltools;
@@ -3678,29 +3945,6 @@ ovmf=$ax_cv_ovmf
-# Check whether --enable-rombios was given.
-if test "${enable_rombios+set}" = set; then :
- enableval=$enable_rombios;
-fi
-
-
-if test "x$enable_rombios" = "xno"; then :
-
- ax_cv_rombios="n"
-
-elif test "x$enable_rombios" = "xyes"; then :
-
- ax_cv_rombios="y"
-
-elif test -z $ax_cv_rombios; then :
-
- ax_cv_rombios="y"
-
-fi
-rombios=$ax_cv_rombios
-
-
-
# Check whether --enable-seabios was given.
if test "${enable_seabios+set}" = set; then :
enableval=$enable_seabios;
@@ -3747,49 +3991,88 @@ debug=$ax_cv_debug
-# Check whether --enable-xend was given.
-if test "${enable_xend+set}" = set; then :
- enableval=$enable_xend;
+# Check whether --enable-blktap1 was given.
+if test "${enable_blktap1+set}" = set; then :
+ enableval=$enable_blktap1;
fi
-if test "x$enable_xend" = "xno"; then :
+if test "x$enable_blktap1" = "xno"; then :
- ax_cv_xend="n"
+ ax_cv_blktap1="n"
-elif test "x$enable_xend" = "xyes"; then :
+elif test "x$enable_blktap1" = "xyes"; then :
- ax_cv_xend="y"
+ ax_cv_blktap1="y"
-elif test -z $ax_cv_xend; then :
+elif test -z $ax_cv_blktap1; then :
- ax_cv_xend="n"
+ ax_cv_blktap1="n"
fi
-xend=$ax_cv_xend
+blktap1=$ax_cv_blktap1
-# Check whether --enable-blktap1 was given.
-if test "${enable_blktap1+set}" = set; then :
- enableval=$enable_blktap1;
+
+# Check whether --with-linux-backend-modules was given.
+if test "${with_linux_backend_modules+set}" = set; then :
+ withval=$with_linux_backend_modules; LINUX_BACKEND_MODULES="$withval"
+else
+ case "$host_os" in
+*linux*)
+LINUX_BACKEND_MODULES="
+xen-evtchn
+xen-gntdev
+xen-gntalloc
+xen-blkback
+xen-netback
+xen-pciback
+evtchn
+gntdev
+netbk
+blkbk
+xen-scsibk
+usbbk
+pciback
+xen-acpi-processor
+blktap2
+blktap
+"
+;;
+*)
+LINUX_BACKEND_MODULES=
+;;
+esac
fi
+LINUX_BACKEND_MODULES="`eval echo $LINUX_BACKEND_MODULES`"
-if test "x$enable_blktap1" = "xno"; then :
- ax_cv_blktap1="n"
+# Check whether --enable-blktap2 was given.
+if test "${enable_blktap2+set}" = set; then :
+ enableval=$enable_blktap2;
+else
-elif test "x$enable_blktap1" = "xyes"; then :
+ case "$host_os" in
+ linux*)
+ enable_blktap2="yes";;
+ *) enable_blktap2="no";;
+ esac
- ax_cv_blktap1="y"
+fi
-elif test -z $ax_cv_blktap1; then :
+if test "x$enable_blktap2" = "xyes"; then :
- ax_cv_blktap1="n"
+
+$as_echo "#define HAVE_BLKTAP2 1" >>confdefs.h
+
+ blktap2=y
+else
+
+ blktap2=n
fi
-blktap1=$ax_cv_blktap1
@@ -3803,6 +4086,11 @@ else
enable_qemu_traditional="yes";;
*) enable_qemu_traditional="no";;
esac
+ case "$host_os" in
+ freebsd*)
+ enable_qemu_traditional="no";;
+ esac
+
fi
@@ -3819,6 +4107,36 @@ else
fi
+# Check whether --enable-rombios was given.
+if test "${enable_rombios+set}" = set; then :
+ enableval=$enable_rombios;
+else
+
+ if test "x$enable_qemu_traditional" = "xyes"; then :
+
+ enable_rombios="yes"
+
+else
+
+ enable_rombios="no"
+
+fi
+
+fi
+
+if test "x$enable_rombios" = "xyes"; then :
+
+
+$as_echo "#define HAVE_ROMBIOS 1" >>confdefs.h
+
+ rombios=y
+else
+
+ rombios=n
+
+fi
+
+
# Check whether --with-system-qemu was given.
if test "${with_system_qemu+set}" = set; then :
@@ -3834,6 +4152,8 @@ else
case "$host_cpu" in
i[3456]86|x86_64)
qemu_xen=y;;
+ arm*|aarch64)
+ qemu_xen=y;;
*) qemu_xen=n;;
esac
@@ -3877,6 +4197,19 @@ fi
+# Check whether --with-extra-qemuu-configure-args was given.
+if test "${with_extra_qemuu_configure_args+set}" = set; then :
+ withval=$with_extra_qemuu_configure_args;
+ case $withval in
+ no) EXTRA_QEMUU_CONFIGURE_ARGS= ;;
+ *) EXTRA_QEMUU_CONFIGURE_ARGS=$withval ;;
+ esac
+
+fi
+
+
+
+
@@ -4702,28 +5035,27 @@ if test x"${PERL}" = x"no"
then
as_fn_error $? "Unable to find perl, please install perl" "$LINENO" 5
fi
-if test "x$xapi" = "xy"; then :
- # Extract the first word of "curl-config", so it can be a program name with args.
-set dummy curl-config; ac_word=$2
+ # checking for ocamlc
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ocamlc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ocamlc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_CURL+:} false; then :
+if ${ac_cv_prog_OCAMLC+:} false; then :
$as_echo_n "(cached) " >&6
else
- case $CURL in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_CURL="$CURL" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ if test -n "$OCAMLC"; then
+ ac_cv_prog_OCAMLC="$OCAMLC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_CURL="$as_dir/$ac_word$ac_exec_ext"
+ ac_cv_prog_OCAMLC="${ac_tool_prefix}ocamlc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
@@ -4731,44 +5063,39 @@ done
done
IFS=$as_save_IFS
- test -z "$ac_cv_path_CURL" && ac_cv_path_CURL="no"
- ;;
-esac
fi
-CURL=$ac_cv_path_CURL
-if test -n "$CURL"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CURL" >&5
-$as_echo "$CURL" >&6; }
+fi
+OCAMLC=$ac_cv_prog_OCAMLC
+if test -n "$OCAMLC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLC" >&5
+$as_echo "$OCAMLC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
-if test x"${CURL}" = x"no"
-then
- as_fn_error $? "Unable to find curl-config, please install curl-config" "$LINENO" 5
fi
- # Extract the first word of "xml2-config", so it can be a program name with args.
-set dummy xml2-config; ac_word=$2
+if test -z "$ac_cv_prog_OCAMLC"; then
+ ac_ct_OCAMLC=$OCAMLC
+ # Extract the first word of "ocamlc", so it can be a program name with args.
+set dummy ocamlc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_XML+:} false; then :
+if ${ac_cv_prog_ac_ct_OCAMLC+:} false; then :
$as_echo_n "(cached) " >&6
else
- case $XML in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_XML="$XML" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ if test -n "$ac_ct_OCAMLC"; then
+ ac_cv_prog_ac_ct_OCAMLC="$ac_ct_OCAMLC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_XML="$as_dir/$ac_word$ac_exec_ext"
+ ac_cv_prog_ac_ct_OCAMLC="ocamlc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
@@ -4776,143 +5103,12 @@ done
done
IFS=$as_save_IFS
- test -z "$ac_cv_path_XML" && ac_cv_path_XML="no"
- ;;
-esac
fi
-XML=$ac_cv_path_XML
-if test -n "$XML"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XML" >&5
-$as_echo "$XML" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-if test x"${XML}" = x"no"
-then
- as_fn_error $? "Unable to find xml2-config, please install xml2-config" "$LINENO" 5
-fi
-
-fi
-for ac_prog in gawk mawk nawk awk
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_AWK+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$AWK"; then
- ac_cv_prog_AWK="$AWK" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_AWK="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-AWK=$ac_cv_prog_AWK
-if test -n "$AWK"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
-$as_echo "$AWK" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$AWK" && break
-done
-
-if test "x$ocamltools" = "xy"; then :
-
- # checking for ocamlc
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}ocamlc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ocamlc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_OCAMLC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$OCAMLC"; then
- ac_cv_prog_OCAMLC="$OCAMLC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_OCAMLC="${ac_tool_prefix}ocamlc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-OCAMLC=$ac_cv_prog_OCAMLC
-if test -n "$OCAMLC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLC" >&5
-$as_echo "$OCAMLC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_OCAMLC"; then
- ac_ct_OCAMLC=$OCAMLC
- # Extract the first word of "ocamlc", so it can be a program name with args.
-set dummy ocamlc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_OCAMLC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_OCAMLC"; then
- ac_cv_prog_ac_ct_OCAMLC="$ac_ct_OCAMLC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_OCAMLC="ocamlc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_OCAMLC=$ac_cv_prog_ac_ct_OCAMLC
-if test -n "$ac_ct_OCAMLC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OCAMLC" >&5
-$as_echo "$ac_ct_OCAMLC" >&6; }
+fi
+ac_ct_OCAMLC=$ac_cv_prog_ac_ct_OCAMLC
+if test -n "$ac_ct_OCAMLC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OCAMLC" >&5
+$as_echo "$ac_ct_OCAMLC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
@@ -5934,6 +6130,51 @@ fi
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AWK="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+if test "x$ocamltools" = "xy"; then :
+
if test "x$OCAMLC" = "xno" || test "x$OCAMLFIND" = "xno"; then :
if test "x$enable_ocamltools" = "xyes"; then :
@@ -5989,6 +6230,76 @@ fi
fi
fi
+
+
+
+
+
+
+
+
+
+
+if test "x$XENSTORE" = "x"; then :
+
+
+# Check whether --with-xenstored was given.
+if test "${with_xenstored+set}" = set; then :
+ withval=$with_xenstored;
+ if test "x$withval" = "xxenstored"; then :
+
+ xenstore=$withval
+ xenstored=$sbindir/xenstored
+
+fi
+ if test "x$withval" = "xoxenstored"; then :
+
+ xenstore=$withval
+ xenstored=$sbindir/oxenstored
+
+ if test "$ocamltools" = "n"; then :
+
+ as_fn_error $? "Missing ocaml dependencies for oxenstored, try installing ocaml ocaml-compiler-libs ocaml-runtime ocaml-findlib" "$LINENO" 5
+
+fi
+
+
+fi
+ if test "x$withval" != "xoxenstored" && test "x$withval" != "xxenstored"; then :
+
+ as_fn_error $? "Unsupported xenstored specified, supported types: oxenstored xenstored" "$LINENO" 5
+
+fi
+
+else
+
+
+ xenstore="oxenstored"
+ xenstored=$sbindir/oxenstored
+ if test "$ocamltools" = "n"; then :
+
+ xenstore="xenstored"
+ xenstored=$sbindir/xenstored
+
+fi
+
+
+fi
+
+
+fi
+
+
+ XENSTORE=$xenstore
+
+ if test "x$XENSTORED" = "x"; then :
+
+ XENSTORED=$xenstored
+
+fi
+
+
+
if test "x$xsmpolicy" = "xy"; then :
# check for a checkpolicy binary with support for -t xen
@@ -6750,6 +7061,8 @@ LDLFAGS=$ac_previous_ldflags
fi
+if ! $rump; then
+
# Extract the first word of "xgettext", so it can be a program name with args.
set dummy xgettext; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
@@ -7171,6 +7484,7 @@ fi
+
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
@@ -7299,6 +7613,7 @@ if test -n "$glib_CFLAGS"; then
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_glib_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.12" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
@@ -7315,6 +7630,7 @@ if test -n "$glib_LIBS"; then
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_glib_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.12" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
@@ -7334,9 +7650,9 @@ else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
- glib_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "glib-2.0 >= 2.12" 2>&1`
+ glib_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.12" 2>&1`
else
- glib_PKG_ERRORS=`$PKG_CONFIG --print-errors "glib-2.0 >= 2.12" 2>&1`
+ glib_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.12" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$glib_PKG_ERRORS" >&5
@@ -7619,6 +7935,8 @@ fi
+if test "x$enable_blktap1" = "xyes" || test "x$enable_blktap2" = "xyes"; then :
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for io_setup in -laio" >&5
$as_echo_n "checking for io_setup in -laio... " >&6; }
if ${ac_cv_lib_aio_io_setup+:} false; then :
@@ -7667,6 +7985,8 @@ else
fi
+fi
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for MD5 in -lcrypto" >&5
$as_echo_n "checking for MD5 in -lcrypto... " >&6; }
if ${ac_cv_lib_crypto_MD5+:} false; then :
@@ -8185,7 +8505,7 @@ fi
esac
# Checks for header files.
-for ac_header in yajl/yajl_version.h sys/eventfd.h
+for ac_header in yajl/yajl_version.h sys/eventfd.h valgrind/memcheck.h utmp.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -8199,6 +8519,389 @@ fi
done
+# Check for libnl3 >=3.2.8. If present enable remus network buffering.
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBNL3" >&5
+$as_echo_n "checking for LIBNL3... " >&6; }
+
+if test -n "$LIBNL3_CFLAGS"; then
+ pkg_cv_LIBNL3_CFLAGS="$LIBNL3_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnl-3.0 >= 3.2.8 libnl-route-3.0 >= 3.2.8\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libnl-3.0 >= 3.2.8 libnl-route-3.0 >= 3.2.8") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBNL3_CFLAGS=`$PKG_CONFIG --cflags "libnl-3.0 >= 3.2.8 libnl-route-3.0 >= 3.2.8" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBNL3_LIBS"; then
+ pkg_cv_LIBNL3_LIBS="$LIBNL3_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnl-3.0 >= 3.2.8 libnl-route-3.0 >= 3.2.8\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libnl-3.0 >= 3.2.8 libnl-route-3.0 >= 3.2.8") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBNL3_LIBS=`$PKG_CONFIG --libs "libnl-3.0 >= 3.2.8 libnl-route-3.0 >= 3.2.8" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ LIBNL3_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libnl-3.0 >= 3.2.8 libnl-route-3.0 >= 3.2.8" 2>&1`
+ else
+ LIBNL3_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libnl-3.0 >= 3.2.8 libnl-route-3.0 >= 3.2.8" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBNL3_PKG_ERRORS" >&5
+
+ libnl3_lib="n"
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ libnl3_lib="n"
+else
+ LIBNL3_CFLAGS=$pkg_cv_LIBNL3_CFLAGS
+ LIBNL3_LIBS=$pkg_cv_LIBNL3_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ libnl3_lib="y"
+fi
+
+if test "x$libnl3_lib" = "xn" ; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Disabling support for Remus network buffering.
+ Please install libnl3 libraries, command line tools and devel
+ headers - version 3.2.8 or higher" >&5
+$as_echo "$as_me: WARNING: Disabling support for Remus network buffering.
+ Please install libnl3 libraries, command line tools and devel
+ headers - version 3.2.8 or higher" >&2;}
+ remus_netbuf=n
+
+
+else
+
+ remus_netbuf=y
+
+
+fi
+
+
+
+
+fi # ! $rump
+
+
+
+
+# Check whether --enable-systemd was given.
+if test "${enable_systemd+set}" = set; then :
+ enableval=$enable_systemd;
+fi
+
+
+if test "x$enable_systemd" = "xno"; then :
+
+ ax_cv_systemd="n"
+
+elif test "x$enable_systemd" = "xyes"; then :
+
+ ax_cv_systemd="y"
+
+elif test -z $ax_cv_systemd; then :
+
+ ax_cv_systemd="n"
+
+fi
+systemd=$ax_cv_systemd
+
+
+
+
+# Check whether --with-systemd was given.
+if test "${with_systemd+set}" = set; then :
+ withval=$with_systemd; SYSTEMD_DIR="$withval"
+else
+ SYSTEMD_DIR=""
+fi
+
+
+
+
+# Check whether --with-systemd-modules-load was given.
+if test "${with_systemd_modules_load+set}" = set; then :
+ withval=$with_systemd_modules_load; SYSTEMD_MODULES_LOAD="$withval"
+else
+ SYSTEMD_MODULES_LOAD=""
+fi
+
+
+
+
+
+ ac_fn_c_check_header_mongrel "$LINENO" "systemd/sd-daemon.h" "ac_cv_header_systemd_sd_daemon_h" "$ac_includes_default"
+if test "x$ac_cv_header_systemd_sd_daemon_h" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sd_listen_fds in -lsystemd-daemon" >&5
+$as_echo_n "checking for sd_listen_fds in -lsystemd-daemon... " >&6; }
+if ${ac_cv_lib_systemd_daemon_sd_listen_fds+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsystemd-daemon $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sd_listen_fds ();
+int
+main ()
+{
+return sd_listen_fds ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_systemd_daemon_sd_listen_fds=yes
+else
+ ac_cv_lib_systemd_daemon_sd_listen_fds=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_systemd_daemon_sd_listen_fds" >&5
+$as_echo "$ac_cv_lib_systemd_daemon_sd_listen_fds" >&6; }
+if test "x$ac_cv_lib_systemd_daemon_sd_listen_fds" = xyes; then :
+ systemd="y"
+fi
+
+
+fi
+
+
+
+
+ if test "x$enable_systemd" != "xno"; then :
+
+ if test "x$systemd" = "xy" ; then :
+
+
+$as_echo "#define HAVE_SYSTEMD 1" >>confdefs.h
+
+ systemd=y
+
+ ac_fn_c_check_header_mongrel "$LINENO" "systemd/sd-daemon.h" "ac_cv_header_systemd_sd_daemon_h" "$ac_includes_default"
+if test "x$ac_cv_header_systemd_sd_daemon_h" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sd_listen_fds in -lsystemd-daemon" >&5
+$as_echo_n "checking for sd_listen_fds in -lsystemd-daemon... " >&6; }
+if ${ac_cv_lib_systemd_daemon_sd_listen_fds+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsystemd-daemon $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sd_listen_fds ();
+int
+main ()
+{
+return sd_listen_fds ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_systemd_daemon_sd_listen_fds=yes
+else
+ ac_cv_lib_systemd_daemon_sd_listen_fds=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_systemd_daemon_sd_listen_fds" >&5
+$as_echo "$ac_cv_lib_systemd_daemon_sd_listen_fds" >&6; }
+if test "x$ac_cv_lib_systemd_daemon_sd_listen_fds" = xyes; then :
+ libsystemddaemon="y"
+fi
+
+
+fi
+
+
+ if test "x$libsystemddaemon" = x; then :
+
+ as_fn_error $? "Unable to find a suitable libsystemd-daemon library" "$LINENO" 5
+
+fi
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SYSTEMD" >&5
+$as_echo_n "checking for SYSTEMD... " >&6; }
+
+if test -n "$SYSTEMD_CFLAGS"; then
+ pkg_cv_SYSTEMD_CFLAGS="$SYSTEMD_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-daemon\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd-daemon") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_SYSTEMD_CFLAGS=`$PKG_CONFIG --cflags "libsystemd-daemon" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$SYSTEMD_LIBS"; then
+ pkg_cv_SYSTEMD_LIBS="$SYSTEMD_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-daemon\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd-daemon") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_SYSTEMD_LIBS=`$PKG_CONFIG --libs "libsystemd-daemon" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ SYSTEMD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd-daemon" 2>&1`
+ else
+ SYSTEMD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd-daemon" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$SYSTEMD_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libsystemd-daemon) were not met:
+
+$SYSTEMD_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables SYSTEMD_CFLAGS
+and SYSTEMD_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables SYSTEMD_CFLAGS
+and SYSTEMD_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ SYSTEMD_CFLAGS=$pkg_cv_SYSTEMD_CFLAGS
+ SYSTEMD_LIBS=$pkg_cv_SYSTEMD_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+
+
+ if test "x$SYSTEMD_DIR" = x; then :
+
+ SYSTEMD_DIR="\$(prefix)/lib/systemd/system/"
+
+fi
+
+ if test "x$SYSTEMD_DIR" = x; then :
+
+ as_fn_error $? "SYSTEMD_DIR is unset" "$LINENO" 5
+
+fi
+
+ if test "x$SYSTEMD_MODULES_LOAD" = x; then :
+
+ SYSTEMD_MODULES_LOAD="\$(prefix)/lib/modules-load.d/"
+
+fi
+
+ if test "x$SYSTEMD_MODULES_LOAD" = x; then :
+
+ as_fn_error $? "SYSTEMD_MODULES_LOAD is unset" "$LINENO" 5
+
+fi
+
+
+else
+ systemd=n
+fi
+
+else
+ systemd=n
+fi
+
+
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
@@ -8705,7 +9408,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by Xen Hypervisor Tools $as_me 4.4, which was
+This file was extended by Xen Hypervisor Tools $as_me 4.5, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -8768,7 +9471,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-Xen Hypervisor Tools config.status 4.4
+Xen Hypervisor Tools config.status 4.5
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -8892,6 +9595,26 @@ for ac_config_target in $ac_config_targets
do
case $ac_config_target in
"../config/Tools.mk") CONFIG_FILES="$CONFIG_FILES ../config/Tools.mk" ;;
+ "hotplug/FreeBSD/rc.d/xencommons") CONFIG_FILES="$CONFIG_FILES hotplug/FreeBSD/rc.d/xencommons" ;;
+ "hotplug/Linux/init.d/sysconfig.xencommons") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/init.d/sysconfig.xencommons" ;;
+ "hotplug/Linux/init.d/xen-watchdog") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/init.d/xen-watchdog" ;;
+ "hotplug/Linux/init.d/xencommons") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/init.d/xencommons" ;;
+ "hotplug/Linux/init.d/xendomains") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/init.d/xendomains" ;;
+ "hotplug/Linux/systemd/proc-xen.mount") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/systemd/proc-xen.mount" ;;
+ "hotplug/Linux/systemd/var-lib-xenstored.mount") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/systemd/var-lib-xenstored.mount" ;;
+ "hotplug/Linux/systemd/xen-init-dom0.service") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/systemd/xen-init-dom0.service" ;;
+ "hotplug/Linux/systemd/xen-qemu-dom0-disk-backend.service") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/systemd/xen-qemu-dom0-disk-backend.service" ;;
+ "hotplug/Linux/systemd/xen-watchdog.service") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/systemd/xen-watchdog.service" ;;
+ "hotplug/Linux/systemd/xenconsoled.service") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/systemd/xenconsoled.service" ;;
+ "hotplug/Linux/systemd/xendomains.service") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/systemd/xendomains.service" ;;
+ "hotplug/Linux/systemd/xenstored.service") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/systemd/xenstored.service" ;;
+ "hotplug/Linux/systemd/xenstored.socket") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/systemd/xenstored.socket" ;;
+ "hotplug/Linux/systemd/xenstored_ro.socket") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/systemd/xenstored_ro.socket" ;;
+ "hotplug/Linux/vif-setup") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/vif-setup" ;;
+ "hotplug/Linux/xen-backend.rules") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/xen-backend.rules" ;;
+ "hotplug/Linux/xen-hotplug-common.sh") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/xen-hotplug-common.sh" ;;
+ "hotplug/Linux/xendomains") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/xendomains" ;;
+ "hotplug/NetBSD/rc.d/xencommons") CONFIG_FILES="$CONFIG_FILES hotplug/NetBSD/rc.d/xencommons" ;;
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
@@ -9480,25 +10203,3 @@ $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
-if test "x$xend" = "xy" ; then :
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You have enabled the xend toolstack.
-
-xend is deprecated and scheduled for removal. Please migrate to another
-toolstack ASAP.
-
-See http://wiki.xen.org/wiki/Choice_of_Toolstacks for information on
-other alternatives, including xl which is designed to be a drop in
-replacement for xm (http://wiki.xen.org/wiki/XL).
-" >&5
-$as_echo "$as_me: WARNING: You have enabled the xend toolstack.
-
-xend is deprecated and scheduled for removal. Please migrate to another
-toolstack ASAP.
-
-See http://wiki.xen.org/wiki/Choice_of_Toolstacks for information on
-other alternatives, including xl which is designed to be a drop in
-replacement for xm (http://wiki.xen.org/wiki/XL).
-" >&2;}
-
-fi
diff --git a/tools/configure.ac b/tools/configure.ac
index 884d63d..1ac63a3 100644
--- a/tools/configure.ac
+++ b/tools/configure.ac
@@ -5,7 +5,29 @@ AC_PREREQ([2.67])
AC_INIT([Xen Hypervisor Tools], m4_esyscmd([../version.sh ../xen/Makefile]),
[xen-devel at lists.xen.org], [xen], [http://www.xen.org/])
AC_CONFIG_SRCDIR([libxl/libxl.c])
-AC_CONFIG_FILES([../config/Tools.mk])
+AC_CONFIG_FILES([
+../config/Tools.mk
+hotplug/FreeBSD/rc.d/xencommons
+hotplug/Linux/init.d/sysconfig.xencommons
+hotplug/Linux/init.d/xen-watchdog
+hotplug/Linux/init.d/xencommons
+hotplug/Linux/init.d/xendomains
+hotplug/Linux/systemd/proc-xen.mount
+hotplug/Linux/systemd/var-lib-xenstored.mount
+hotplug/Linux/systemd/xen-init-dom0.service
+hotplug/Linux/systemd/xen-qemu-dom0-disk-backend.service
+hotplug/Linux/systemd/xen-watchdog.service
+hotplug/Linux/systemd/xenconsoled.service
+hotplug/Linux/systemd/xendomains.service
+hotplug/Linux/systemd/xenstored.service
+hotplug/Linux/systemd/xenstored.socket
+hotplug/Linux/systemd/xenstored_ro.socket
+hotplug/Linux/vif-setup
+hotplug/Linux/xen-backend.rules
+hotplug/Linux/xen-hotplug-common.sh
+hotplug/Linux/xendomains
+hotplug/NetBSD/rc.d/xencommons
+])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_AUX_DIR([../])
@@ -20,6 +42,12 @@ APPEND_INCLUDES and APPEND_LIB instead when possible.])
AC_CANONICAL_HOST
+case $host_vendor in
+rumpxen) CONFIG_RUMP=y; rump=true ;;
+*) CONFIG_RUMP=n; rump=false ;;
+esac
+AC_SUBST(CONFIG_RUMP)
+
AC_SYS_LARGEFILE
case $ac_cv_sys_file_offset_bits in #(
@@ -34,11 +62,11 @@ AC_SUBST(FILE_OFFSET_BITS)
m4_include([../m4/savevar.m4])
m4_include([../m4/features.m4])
m4_include([../m4/path_or_fail.m4])
+m4_include([../m4/checkpolicy.m4])
+m4_include([../m4/set_cflags_ldflags.m4])
m4_include([../m4/python_version.m4])
m4_include([../m4/python_devel.m4])
m4_include([../m4/ocaml.m4])
-m4_include([../m4/checkpolicy.m4])
-m4_include([../m4/set_cflags_ldflags.m4])
m4_include([../m4/uuid.m4])
m4_include([../m4/pkg.m4])
m4_include([../m4/curses.m4])
@@ -47,28 +75,85 @@ m4_include([../m4/ptyfuncs.m4])
m4_include([../m4/extfs.m4])
m4_include([../m4/fetcher.m4])
m4_include([../m4/ax_compare_version.m4])
+m4_include([../m4/paths.m4])
+m4_include([../m4/systemd.m4])
+
+AX_XEN_EXPAND_CONFIG()
# Enable/disable options
+AX_ARG_DEFAULT_DISABLE([rpath], [Build tools with -Wl,-rpath,LIBDIR])
AX_ARG_DEFAULT_DISABLE([githttp], [Download GIT repositories via HTTP])
AX_ARG_DEFAULT_ENABLE([monitors], [Disable xenstat and xentop monitoring tools])
-AX_ARG_DEFAULT_DISABLE([xenapi], [Enable Xen API Bindings])
AX_ARG_DEFAULT_ENABLE([ocamltools], [Disable Ocaml tools])
AX_ARG_DEFAULT_ENABLE([xsmpolicy], [Disable XSM policy compilation])
AX_ARG_DEFAULT_DISABLE([ovmf], [Enable OVMF])
-AX_ARG_DEFAULT_ENABLE([rombios], [Disable ROM BIOS])
AX_ARG_DEFAULT_ENABLE([seabios], [Disable SeaBIOS])
AX_ARG_DEFAULT_ENABLE([debug], [Disable debug build of tools])
-AX_ARG_DEFAULT_DISABLE([xend], [Enable xend toolstack])
AX_ARG_DEFAULT_DISABLE([blktap1], [Enable blktap1 tools])
+AC_ARG_WITH([linux-backend-modules],
+ AS_HELP_STRING([--with-linux-backend-modules="mod1 mod2"],
+ [List of Linux backend module or modalias names to be autoloaded on startup.]),
+ [LINUX_BACKEND_MODULES="$withval"],
+ [case "$host_os" in
+*linux*)
+LINUX_BACKEND_MODULES="
+xen-evtchn
+xen-gntdev
+xen-gntalloc
+xen-blkback
+xen-netback
+xen-pciback
+evtchn
+gntdev
+netbk
+blkbk
+xen-scsibk
+usbbk
+pciback
+xen-acpi-processor
+blktap2
+blktap
+"
+;;
+*)
+LINUX_BACKEND_MODULES=
+;;
+esac])
+LINUX_BACKEND_MODULES="`eval echo $LINUX_BACKEND_MODULES`"
+AC_SUBST(LINUX_BACKEND_MODULES)
+
+dnl Enable blktap2 on Linux only.
+AC_ARG_ENABLE([blktap2],
+ AS_HELP_STRING([--enable-blktap2],
+ [Enable blktap2, (DEFAULT is on for Linux, otherwise off)]),,[
+ case "$host_os" in
+ linux*)
+ enable_blktap2="yes";;
+ *) enable_blktap2="no";;
+ esac
+])
+AS_IF([test "x$enable_blktap2" = "xyes"], [
+AC_DEFINE([HAVE_BLKTAP2], [1], [Blktap2 enabled])
+ blktap2=y],[
+ blktap2=n
+])
+AC_SUBST(blktap2)
+
+
AC_ARG_ENABLE([qemu-traditional],
AS_HELP_STRING([--enable-qemu-traditional],
- [Enable qemu traditional device model, (DEFAULT is on for x86, otherwise off)]),,[
+ [Enable qemu traditional device model, (DEFAULT is on for Linux or NetBSD x86, otherwise off)]),,[
case "$host_cpu" in
i[[3456]]86|x86_64)
enable_qemu_traditional="yes";;
*) enable_qemu_traditional="no";;
esac
+ case "$host_os" in
+ freebsd*)
+ enable_qemu_traditional="no";;
+ esac
+
])
AS_IF([test "x$enable_qemu_traditional" = "xyes"], [
AC_DEFINE([HAVE_QEMU_TRADITIONAL], [1], [Qemu traditional enabled])
@@ -77,6 +162,22 @@ AC_DEFINE([HAVE_QEMU_TRADITIONAL], [1], [Qemu traditional enabled])
])
AC_SUBST(qemu_traditional)
+AC_ARG_ENABLE([rombios],
+ AS_HELP_STRING([--enable-rombios],
+ [Enable ROMBIOS, (DEFAULT is on if qemu-traditional is enabled, otherwise off)]),,[
+ AS_IF([test "x$enable_qemu_traditional" = "xyes"], [
+ enable_rombios="yes"
+ ], [
+ enable_rombios="no"
+ ])
+])
+AS_IF([test "x$enable_rombios" = "xyes"], [
+AC_DEFINE([HAVE_ROMBIOS], [1], [ROMBIOS enabled])
+ rombios=y],[
+ rombios=n
+])
+AC_SUBST(rombios)
+
AC_ARG_WITH([system-qemu],
AS_HELP_STRING([--with-system-qemu@<:@=PATH@:>@],
[Use system supplied qemu PATH or qemu (taken from $PATH) as qemu-xen
@@ -90,6 +191,8 @@ AC_ARG_WITH([system-qemu],
case "$host_cpu" in
i[[3456]]86|x86_64)
qemu_xen=y;;
+ arm*|aarch64)
+ qemu_xen=y;;
*) qemu_xen=n;;
esac
])
@@ -120,6 +223,16 @@ AC_ARG_WITH([system-ovmf],
],[])
AC_SUBST(ovmf_path)
+AC_ARG_WITH([extra-qemuu-configure-args],
+ AS_HELP_STRING([--with-extra-qemuu-configure-args@<:@="--ARG1 ..."@:>@],
+ [List of additional configure options for upstream qemu]),[
+ case $withval in
+ no) EXTRA_QEMUU_CONFIGURE_ARGS= ;;
+ *) EXTRA_QEMUU_CONFIGURE_ARGS=$withval ;;
+ esac
+],[])
+AC_SUBST(EXTRA_QEMUU_CONFIGURE_ARGS)
+
AC_ARG_VAR([PREPEND_INCLUDES],
[List of include folders to prepend to CFLAGS (without -I)])
AC_ARG_VAR([PREPEND_LIB],
@@ -151,13 +264,11 @@ AC_PROG_INSTALL
AC_PATH_PROG([BISON], [bison])
AC_PATH_PROG([FLEX], [flex])
AX_PATH_PROG_OR_FAIL([PERL], [perl])
-AS_IF([test "x$xapi" = "xy"], [
- AX_PATH_PROG_OR_FAIL([CURL], [curl-config])
- AX_PATH_PROG_OR_FAIL([XML], [xml2-config])
-])
+
+AC_PROG_OCAML
+AC_PROG_FINDLIB
+
AS_IF([test "x$ocamltools" = "xy"], [
- AC_PROG_OCAML
- AC_PROG_FINDLIB
AS_IF([test "x$OCAMLC" = "xno" || test "x$OCAMLFIND" = "xno"], [
AS_IF([test "x$enable_ocamltools" = "xyes"], [
AC_MSG_ERROR([Ocaml tools enabled, but unable to find Ocaml])])
@@ -170,6 +281,11 @@ AS_IF([test "x$ocamltools" = "xy"], [
])
])
])
+
+m4_include([../m4/xenstored.m4])
+AX_XENSTORE_OPTIONS
+AX_XENSTORE_SET
+
AS_IF([test "x$xsmpolicy" = "xy"], [
AC_PROG_CHECKPOLICY
AS_IF([test "x$CHECKPOLICY" = "xno"], [
@@ -191,6 +307,8 @@ AS_IF([test "$cross_compiling" != yes], [
AX_CHECK_PYTHON_DEVEL()
])
+if ! $rump; then
+
AX_PATH_PROG_OR_FAIL([XGETTEXT], [xgettext])
dnl as86, ld86, bcc and iasl are only required when the host system is x86*.
dnl "host" here means the platform on which the hypervisor and tools is
@@ -220,7 +338,9 @@ AC_CHECK_HEADER([lzo/lzo1x.h], [
AC_CHECK_LIB([lzo2], [lzo1x_decompress], [zlib="$zlib -DHAVE_LZO1X -llzo2"])
])
AC_SUBST(zlib)
+AS_IF([test "x$enable_blktap1" = "xyes" || test "x$enable_blktap2" = "xyes"], [
AC_CHECK_LIB([aio], [io_setup], [], [AC_MSG_ERROR([Could not find libaio])])
+])
AC_SUBST(system_aio)
AC_CHECK_LIB([crypto], [MD5], [], [AC_MSG_ERROR([Could not find libcrypto])])
AX_CHECK_EXTFS
@@ -241,19 +361,26 @@ AC_CHECK_LIB([fdt], [fdt_create], [], [AC_MSG_ERROR([Could not find libfdt])])
esac
# Checks for header files.
-AC_CHECK_HEADERS([yajl/yajl_version.h sys/eventfd.h])
+AC_CHECK_HEADERS([yajl/yajl_version.h sys/eventfd.h valgrind/memcheck.h utmp.h])
-AC_OUTPUT()
+# Check for libnl3 >=3.2.8. If present enable remus network buffering.
+PKG_CHECK_MODULES(LIBNL3, [libnl-3.0 >= 3.2.8 libnl-route-3.0 >= 3.2.8],
+ [libnl3_lib="y"], [libnl3_lib="n"])
-AS_IF([test "x$xend" = "xy" ], [
- AC_MSG_WARN(
-[You have enabled the xend toolstack.
+AS_IF([test "x$libnl3_lib" = "xn" ], [
+ AC_MSG_WARN([Disabling support for Remus network buffering.
+ Please install libnl3 libraries, command line tools and devel
+ headers - version 3.2.8 or higher])
+ AC_SUBST(remus_netbuf, [n])
+ ],[
+ AC_SUBST(remus_netbuf, [y])
+])
-xend is deprecated and scheduled for removal. Please migrate to another
-toolstack ASAP.
+AC_SUBST(LIBNL3_LIBS)
+AC_SUBST(LIBNL3_CFLAGS)
+
+fi # ! $rump
+
+AX_AVAILABLE_SYSTEMD()
+AC_OUTPUT()
-See http://wiki.xen.org/wiki/Choice_of_Toolstacks for information on
-other alternatives, including xl which is designed to be a drop in
-replacement for xm (http://wiki.xen.org/wiki/XL).
-])
-])
diff --git a/tools/console/Makefile b/tools/console/Makefile
index 3e38252..6e55618 100644
--- a/tools/console/Makefile
+++ b/tools/console/Makefile
@@ -32,7 +32,7 @@ xenconsole: $(patsubst %.c,%.o,$(wildcard client/*.c))
install: $(BIN)
$(INSTALL_DIR) $(DESTDIR)/$(SBINDIR)
$(INSTALL_PROG) xenconsoled $(DESTDIR)/$(SBINDIR)
- $(INSTALL_DIR) $(DESTDIR)$(PRIVATE_BINDIR)
- $(INSTALL_PROG) xenconsole $(DESTDIR)$(PRIVATE_BINDIR)
+ $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN)
+ $(INSTALL_PROG) xenconsole $(DESTDIR)$(LIBEXEC_BIN)
-include $(DEPS)
diff --git a/tools/console/client/main.c b/tools/console/client/main.c
index 3242008..f4c783b 100644
--- a/tools/console/client/main.c
+++ b/tools/console/client/main.c
@@ -33,7 +33,6 @@
#include <getopt.h>
#include <sys/select.h>
#include <err.h>
-#include <errno.h>
#include <string.h>
#ifdef __sun__
#include <sys/stropts.h>
@@ -115,12 +114,12 @@ static int get_pty_fd(struct xs_handle *xs, char *path, int seconds)
/* We only watch for one thing, so no need to
* disambiguate: just read the pty path */
pty_path = xs_read(xs, XBT_NULL, path, &len);
- if (pty_path != NULL) {
+ if (pty_path != NULL && pty_path[0] != '\0') {
pty_fd = open(pty_path, O_RDWR | O_NOCTTY);
if (pty_fd == -1)
- err(errno, "Could not open tty `%s'", pty_path);
- free(pty_path);
+ warn("Could not open tty `%s'", pty_path);
}
+ free(pty_path);
}
} while (pty_fd == -1 && (now = time(NULL)) < start + seconds);
@@ -258,6 +257,13 @@ typedef enum {
CONSOLE_SERIAL,
} console_type;
+static struct termios stdin_old_attr;
+
+static void restore_term_stdin(void)
+{
+ restore_term(STDIN_FILENO, &stdin_old_attr);
+}
+
int main(int argc, char **argv)
{
struct termios attr;
@@ -384,9 +390,9 @@ int main(int argc, char **argv)
}
init_term(spty, &attr);
- init_term(STDIN_FILENO, &attr);
+ init_term(STDIN_FILENO, &stdin_old_attr);
+ atexit(restore_term_stdin); /* if this fails, oh dear */
console_loop(spty, xs, path);
- restore_term(STDIN_FILENO, &attr);
free(path);
free(dom_path);
diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index 007ecf4..ac08b5b 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -37,12 +37,16 @@
#include <sys/mman.h>
#include <time.h>
#include <assert.h>
+#include <sys/types.h>
#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <util.h>
#elif defined(__linux__)
#include <pty.h>
#elif defined(__sun__)
#include <stropts.h>
+#elif defined(__FreeBSD__)
+#include <sys/ioctl.h>
+#include <libutil.h>
#endif
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
@@ -272,8 +276,8 @@ static int create_hv_log(void)
dolog(LOG_ERR, "Failed to open log %s: %d (%s)",
logfile, errno, strerror(errno));
if (fd != -1 && log_time_hv) {
- if (write_with_timestamp(fd, "Logfile Opened",
- strlen("Logfile Opened"),
+ if (write_with_timestamp(fd, "Logfile Opened\n",
+ strlen("Logfile Opened\n"),
&log_time_hv_needts) < 0) {
dolog(LOG_ERR, "Failed to log opening timestamp "
"in %s: %d (%s)", logfile, errno,
@@ -318,8 +322,8 @@ static int create_domain_log(struct domain *dom)
dolog(LOG_ERR, "Failed to open log %s: %d (%s)",
logfile, errno, strerror(errno));
if (fd != -1 && log_time_guest) {
- if (write_with_timestamp(fd, "Logfile Opened",
- strlen("Logfile Opened"),
+ if (write_with_timestamp(fd, "Logfile Opened\n",
+ strlen("Logfile Opened\n"),
&log_time_guest_needts) < 0) {
dolog(LOG_ERR, "Failed to log opening timestamp "
"in %s: %d (%s)", logfile, errno,
@@ -903,19 +907,26 @@ static void handle_xs(void)
free(vec);
}
-static void handle_hv_logs(xc_evtchn *xce_handle)
+static void handle_hv_logs(xc_evtchn *xce_handle, bool force)
{
- char buffer[1024*16];
+ static char buffer[1024*16];
char *bufptr = buffer;
- unsigned int size = sizeof(buffer);
+ unsigned int size;
static uint32_t index = 0;
- evtchn_port_or_error_t port;
+ evtchn_port_or_error_t port = -1;
- if ((port = xc_evtchn_pending(xce_handle)) == -1)
+ if (!force && ((port = xc_evtchn_pending(xce_handle)) == -1))
return;
- if (xc_readconsolering(xc, bufptr, &size, 0, 1, &index) == 0 && size > 0) {
+ do
+ {
int logret;
+
+ size = sizeof(buffer);
+ if (xc_readconsolering(xc, bufptr, &size, 0, 1, &index) != 0 ||
+ size == 0)
+ break;
+
if (log_time_hv)
logret = write_with_timestamp(log_hv_fd, buffer, size,
&log_time_hv_needts);
@@ -925,9 +936,10 @@ static void handle_hv_logs(xc_evtchn *xce_handle)
if (logret < 0)
dolog(LOG_ERR, "Failed to write hypervisor log: "
"%d (%s)", errno, strerror(errno));
- }
+ } while (size == sizeof(buffer));
- (void)xc_evtchn_unmask(xce_handle, port);
+ if (port != -1)
+ (void)xc_evtchn_unmask(xce_handle, port);
}
static void handle_log_reload(void)
@@ -1013,6 +1025,8 @@ void handle_io(void)
"%d (%s)", errno, strerror(errno));
goto out;
}
+ /* Log the boot dmesg even if VIRQ_CON_RING isn't pending. */
+ handle_hv_logs(xce_handle, true);
}
xcg_handle = xc_gnttab_open(NULL, 0);
@@ -1123,7 +1137,7 @@ void handle_io(void)
errno, strerror(errno));
break;
} else if (fds[xce_pollfd_idx].revents & POLLIN)
- handle_hv_logs(xce_handle);
+ handle_hv_logs(xce_handle, false);
xce_pollfd_idx = -1;
}
diff --git a/tools/debugger/gdbsx/xg/xg_main.c b/tools/debugger/gdbsx/xg/xg_main.c
index 0fc3f82..c95e4ed 100644
--- a/tools/debugger/gdbsx/xg/xg_main.c
+++ b/tools/debugger/gdbsx/xg/xg_main.c
@@ -180,7 +180,7 @@ _domctl_hcall(uint32_t cmd, /* which domctl hypercall */
hypercall.op = __HYPERVISOR_domctl;
hypercall.arg[0] = (unsigned long)&domctl;
- rc = ioctl(_dom0_fd, IOCTL_PRIVCMD_HYPERCALL, (ulong)&hypercall);
+ rc = ioctl(_dom0_fd, IOCTL_PRIVCMD_HYPERCALL, &hypercall);
if (domctlarg && sz)
munlock(domctlarg, sz);
return rc;
@@ -220,7 +220,7 @@ _check_hyp(int guest_bitness)
hypercall.arg[0] = (unsigned long)XENVER_capabilities;
hypercall.arg[1] = (unsigned long)&xen_caps;
- rc = ioctl(_dom0_fd, IOCTL_PRIVCMD_HYPERCALL, (ulong)&hypercall);
+ rc = ioctl(_dom0_fd, IOCTL_PRIVCMD_HYPERCALL, &hypercall);
munlock(&xen_caps, sizeof(xen_caps));
XGTRC("XENCAPS:%s\n", xen_caps);
diff --git a/tools/debugger/kdd/Makefile b/tools/debugger/kdd/Makefile
index b569749..34b781f 100644
--- a/tools/debugger/kdd/Makefile
+++ b/tools/debugger/kdd/Makefile
@@ -10,7 +10,7 @@ OBJS := $(CFILES:.c=.o)
all: kdd
kdd: $(OBJS)
- $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+ $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(APPEND_LDFLAGS)
.PHONY: clean
clean:
diff --git a/tools/examples/Makefile b/tools/examples/Makefile
index df24e38..473580e 100644
--- a/tools/examples/Makefile
+++ b/tools/examples/Makefile
@@ -5,18 +5,6 @@ include $(XEN_ROOT)/tools/Rules.mk
XEN_READMES = README
XEN_READMES += README.incompatibilities
-XEN_CONFIGS-$(CONFIG_XEND) += xend-config.sxp
-XEN_CONFIGS-$(CONFIG_XEND) += xm-config.xml
-XEN_CONFIGS-$(CONFIG_XEND) += xmexample1
-XEN_CONFIGS-$(CONFIG_XEND) += xmexample2
-XEN_CONFIGS-$(CONFIG_XEND) += xmexample3
-XEN_CONFIGS-$(CONFIG_XEND) += xmexample.hvm
-XEN_CONFIGS-$(CONFIG_XEND) += xmexample.hvm-stubdom
-XEN_CONFIGS-$(CONFIG_XEND) += xmexample.pv-grub
-XEN_CONFIGS-$(CONFIG_XEND) += xmexample.nbd
-XEN_CONFIGS-$(CONFIG_XEND) += xend-pci-quirks.sxp
-XEN_CONFIGS-$(CONFIG_XEND) += xend-pci-permissive.sxp
-
XEN_CONFIGS += xlexample.hvm
XEN_CONFIGS += xlexample.pvlinux
XEN_CONFIGS += xl.conf
@@ -31,7 +19,7 @@ all:
build:
.PHONY: install
-install: all install-readmes install-configs $(HOTPLUGS)
+install: all install-readmes install-configs
.PHONY: install-readmes
install-readmes:
@@ -53,24 +41,5 @@ install-configs: $(XEN_CONFIGS)
$(INSTALL_DATA) $$i $(DESTDIR)$(XEN_CONFIG_DIR); \
done
-.PHONY: install-hotplug
-install-hotplug:
- [ -d $(DESTDIR)$(XEN_HOTPLUG_DIR) ] || \
- $(INSTALL_DIR) $(DESTDIR)$(XEN_HOTPLUG_DIR)
- set -e; for i in $(XEN_HOTPLUG_SCRIPTS); \
- do \
- $(INSTALL_PROG) $$i $(DESTDIR)$(XEN_HOTPLUG_DIR); \
- done
-
-.PHONY: install-udev
-install-udev:
- [ -d $(DESTDIR)$(UDEV_RULES_DIR) ] || \
- $(INSTALL_DIR) $(DESTDIR)$(UDEV_RULES_DIR)/rules.d
- set -e; for i in $(UDEV_RULES); \
- do \
- $(INSTALL_DATA) $$i $(DESTDIR)$(UDEV_RULES_DIR); \
- ln -sf ../$$i $(DESTDIR)$(UDEV_RULES_DIR)/rules.d; \
- done
-
.PHONY: clean
clean:
diff --git a/tools/examples/README b/tools/examples/README
index 2225d5c..115ca02 100644
--- a/tools/examples/README
+++ b/tools/examples/README
@@ -18,9 +18,6 @@ external-device-migrate - called by xend for migrating external devices
locking.sh - locking functions to prevent concurrent access to
critical sections inside script files
logging.sh - logging function to log output using syslog
-network-bridge - xen network start/stop script when using bridging
-network-nat - xen network start/stop script when using NAT
-network-route - xen network start/stop script when using routing
vif-bridge - virtual network start/stop script in bridged mode
vif-common.sh - sourced by vif-bridge
vif-nat - xen virtual network start/stop script in NAT mode
@@ -28,10 +25,9 @@ vif-route - xen virtual network start/stop script in routed mode
xen-backend.agent - calls block, vif-* scripts to add, remove, hotplug
devices
xen-backend.rules - hotplug script rules
-xend-config.sxp - default xend configuration file
xen-hotplug-common.sh - sourced by vif-common.sh
xen-network-common.sh - sourced by vif-common.sh
-xen-script-common.sh - sourced by network-bridge, xen-hotplug-common.sh
+xen-script-common.sh - sourced by xen-hotplug-common.sh
xmexample1 - example configuration script for 'xm create'
xmexample2 - a more complex configuration script for 'xm create'
xmexample3 - an advanced configuration script for 'xm create'
diff --git a/tools/examples/xend-config.sxp b/tools/examples/xend-config.sxp
deleted file mode 100644
index 0896a27..0000000
--- a/tools/examples/xend-config.sxp
+++ /dev/null
@@ -1,304 +0,0 @@
-# -*- sh -*-
-
-#
-# Xend configuration file.
-#
-
-# This example configuration is appropriate for an installation that
-# utilizes a bridged network configuration. Access to xend via http
-# is disabled.
-
-# Commented out entries show the default for that entry, unless otherwise
-# specified.
-
-#(logfile /var/log/xen/xend.log)
-#(loglevel DEBUG)
-
-# Uncomment the line below. Set the value to flask, acm, or dummy to
-# select a security module.
-
-#(xsm_module_name dummy)
-
-# The Xen-API server configuration.
-#
-# This value configures the ports, interfaces, and access controls for the
-# Xen-API server. Each entry in the list starts with either unix, a port
-# number, or an address:port pair. If this is "unix", then a UDP socket is
-# opened, and this entry applies to that. If it is a port, then Xend will
-# listen on all interfaces on that TCP port, and if it is an address:port
-# pair, then Xend will listen on the specified port, using the interface with
-# the specified address.
-#
-# The subsequent string configures the user-based access control for the
-# listener in question. This can be one of "none" or "pam", indicating either
-# that users should be allowed access unconditionally, or that the local
-# Pluggable Authentication Modules configuration should be used. If this
-# string is missing or empty, then "pam" is used.
-#
-# The final string gives the host-based access control for that listener. If
-# this is missing or empty, then all connections are accepted. Otherwise,
-# this should be a space-separated sequence of regular expressions; any host
-# with a fully-qualified domain name or an IP address that matches one of
-# these regular expressions will be accepted.
-#
-# Example: listen on TCP port 9363 on all interfaces, accepting connections
-# only from machines in example.com or localhost, and allow access through
-# the unix domain socket unconditionally:
-#
-# (xen-api-server ((9363 pam '^localhost$ example\\.com$')
-# (unix none)))
-#
-# Optionally, the TCP Xen-API server can use SSL by specifying the private
-# key and certificate location:
-#
-# (9367 pam '' xen-api.key xen-api.crt)
-#
-# Default:
-# (xen-api-server ((unix)))
-
-
-#(xend-http-server no)
-#(xend-unix-server no)
-#(xend-tcp-xmlrpc-server no)
-#(xend-unix-xmlrpc-server yes)
-#(xend-relocation-server no)
-(xend-relocation-server yes)
-#(xend-relocation-ssl-server no)
-#(xend-udev-event-server no)
-
-#(xend-unix-path /var/lib/xend/xend-socket)
-
-
-# Address and port xend should use for the legacy TCP XMLRPC interface,
-# if xend-tcp-xmlrpc-server is set.
-#(xend-tcp-xmlrpc-server-address 'localhost')
-#(xend-tcp-xmlrpc-server-port 8006)
-
-# SSL key and certificate to use for the legacy TCP XMLRPC interface.
-# Setting these will mean that this port serves only SSL connections as
-# opposed to plaintext ones.
-#(xend-tcp-xmlrpc-server-ssl-key-file xmlrpc.key)
-#(xend-tcp-xmlrpc-server-ssl-cert-file xmlrpc.crt)
-
-
-# Port xend should use for the HTTP interface, if xend-http-server is set.
-#(xend-port 8000)
-
-# Port xend should use for the relocation interface, if xend-relocation-server
-# is set.
-#(xend-relocation-port 8002)
-
-# Port xend should use for the ssl relocation interface, if
-# xend-relocation-ssl-server is set.
-#(xend-relocation-ssl-port 8003)
-
-# SSL key and certificate to use for the ssl relocation interface, if
-# xend-relocation-ssl-server is set.
-#(xend-relocation-server-ssl-key-file xmlrpc.key)
-#(xend-relocation-server-ssl-cert-file xmlrpc.crt)
-
-# Whether to use ssl as default when relocating.
-#(xend-relocation-ssl no)
-
-# Address xend should listen on for HTTP connections, if xend-http-server is
-# set.
-# Specifying 'localhost' prevents remote connections.
-# Specifying the empty string '' (the default) allows all connections.
-#(xend-address '')
-#(xend-address localhost)
-
-# Address xend should listen on for relocation-socket connections, if
-# xend-relocation-server is set.
-# Meaning and default as for xend-address above.
-# Also, interface name is allowed (e.g. eth0) there to get the
-# relocation address to be bound on.
-#(xend-relocation-address '')
-
-# The hosts allowed to talk to the relocation port. If this is empty (the
-# default), then all connections are allowed (assuming that the connection
-# arrives on a port and interface on which we are listening; see
-# xend-relocation-port and xend-relocation-address above). Otherwise, this
-# should be a space-separated sequence of regular expressions. Any host with
-# a fully-qualified domain name or an IP address that matches one of these
-# regular expressions will be accepted.
-#
-# For example:
-# (xend-relocation-hosts-allow '^localhost$ ^.*\\.example\\.org$')
-#
-#(xend-relocation-hosts-allow '')
-(xend-relocation-hosts-allow '^localhost$ ^localhost\\.localdomain$')
-
-# The limit (in kilobytes) on the size of the console buffer
-#(console-limit 1024)
-
-##
-# To bridge network traffic, like this:
-#
-# dom0: ----------------- bridge -> real eth0 -> the network
-# |
-# domU: fake eth0 -> vifN.0 -+
-#
-# use
-#
-# (network-script network-bridge)
-#
-# Your default ethernet device is used as the outgoing interface, by default.
-# To use a different one (e.g. eth1) use
-#
-# (network-script 'network-bridge netdev=eth1')
-#
-# The bridge is named eth0, by default (yes, really!)
-#
-
-# It is normally much better to create the bridge yourself in
-# /etc/network/interfaces. network-bridge start does nothing if you
-# already have a bridge, and network-bridge stop does nothing if the
-# default bridge name (normally eth0) is not a bridge. See
-# bridge-utils-interfaces(5) for full information on the syntax in
-# /etc/network/interfaces, but you probably want something like this:
-# iface xenbr0 inet static
-# address [etc]
-# netmask [etc]
-# [etc]
-# bridge_ports eth0
-#
-# To have network-bridge create a differently-named bridge, use:
-# (network-script 'network-bridge bridge=<name>')
-#
-# It is possible to use the network-bridge script in more complicated
-# scenarios, such as having two outgoing interfaces, with two bridges, and
-# two fake interfaces per guest domain. To do things like this, write
-# yourself a wrapper script, and call network-bridge from it, as appropriate.
-#
-(network-script network-bridge)
-
-# The script used to control virtual interfaces. This can be overridden on a
-# per-vif basis when creating a domain or a configuring a new vif. The
-# vif-bridge script is designed for use with the network-bridge script, or
-# similar configurations.
-#
-# If you have overridden the bridge name using
-# (network-script 'network-bridge bridge=<name>') then you may wish to do the
-# same here. The bridge name can also be set when creating a domain or
-# configuring a new vif, but a value specified here would act as a default.
-#
-# If you are using only one bridge, the vif-bridge script will discover that,
-# so there is no need to specify it explicitly. The default is to use
-# the bridge which is listed first in the output from brctl.
-#
-(vif-script vif-bridge)
-
-
-## Use the following if network traffic is routed, as an alternative to the
-# settings for bridged networking given above.
-#(network-script network-route)
-#(vif-script vif-route)
-
-
-## Use the following if network traffic is routed with NAT, as an alternative
-# to the settings for bridged networking given above.
-#(network-script network-nat)
-#(vif-script vif-nat)
-
-# dom0-min-mem is the lowest permissible memory level (in MB) for dom0.
-# This is a minimum both for auto-ballooning (as enabled by
-# enable-dom0-ballooning below) and for xm mem-set when applied to dom0.
-(dom0-min-mem 196)
-
-# Whether to enable auto-ballooning of dom0 to allow domUs to be created.
-# If enable-dom0-ballooning = no, dom0 will never balloon out.
-(enable-dom0-ballooning yes)
-
-# 32-bit paravirtual domains can only consume physical
-# memory below 168GB. On systems with memory beyond that address,
-# they'll be confined to memory below 128GB.
-# Using total_available_memory (in GB) to specify the amount of memory reserved
-# in the memory pool exclusively for 32-bit paravirtual domains.
-# Additionally you should use dom0_mem = <-Value> as a parameter in
-# xen kernel to reserve the memory for 32-bit paravirtual domains, default
-# is "0" (0GB).
-(total_available_memory 0)
-
-# In SMP system, dom0 will use dom0-cpus # of CPUS
-# If dom0-cpus = 0, dom0 will take all cpus available
-(dom0-cpus 0)
-
-# Whether to enable core-dumps when domains crash.
-#(enable-dump no)
-
-# The tool used for initiating virtual TPM migration
-#(external-migration-tool '')
-
-# The interface for VNC servers to listen on. Defaults
-# to 127.0.0.1 To restore old 'listen everywhere' behaviour
-# set this to 0.0.0.0
-#(vnc-listen '127.0.0.1')
-
-# The default password for VNC console on HVM domain.
-# Empty string is no authentication.
-(vncpasswd '')
-
-# The VNC server can be told to negotiate a TLS session
-# to encryption all traffic, and provide x509 cert to
-# clients enabling them to verify server identity. The
-# GTK-VNC widget, virt-viewer, virt-manager and VeNCrypt
-# all support the VNC extension for TLS used in QEMU. The
-# TightVNC/RealVNC/UltraVNC clients do not.
-#
-# To enable this create x509 certificates / keys in the
-# directory ${XEN_CONFIG_DIR} + vnc
-#
-# ca-cert.pem - The CA certificate
-# server-cert.pem - The Server certificate signed by the CA
-# server-key.pem - The server private key
-#
-# and then uncomment this next line
-# (vnc-tls 1)
-
-# The certificate dir can be pointed elsewhere..
-#
-# (vnc-x509-cert-dir vnc)
-
-# The server can be told to request & validate an x509
-# certificate from the client. Only clients with a cert
-# signed by the trusted CA will be able to connect. This
-# is more secure the password auth alone. Passwd auth can
-# used at the same time if desired. To enable client cert
-# checking uncomment this:
-#
-# (vnc-x509-verify 1)
-
-# The default keymap to use for the VM's virtual keyboard
-# when not specififed in VM's configuration
-#(keymap 'en-us')
-
-# Script to run when the label of a resource has changed.
-#(resource-label-change-script '')
-
-# 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)
-
-# Number of seconds xend will wait for device creation and
-# destruction
-#(device-create-timeout 100)
-#(device-destroy-timeout 100)
-
-# When assigning device to HVM guest, we use the strict check for HVM guest by
-# default. (For PV guest, we use loose check automatically if necessary.)
-# When we assign device to HVM guest, if we meet with the co-assignment
-# issues or the ACS issue, we could try changing the option to 'no' -- however,
-# we have to realize this may incur security issue and we can't make sure the
-# device assignment could really work properly even after we do this.
-#(pci-passthrough-strict-check yes)
-
-# If we have a very big scsi device configuration, start of xend is slow,
-# because xend scans all the device paths to build its internal PSCSI device
-# list. If we need only a few devices for assigning to a guest, we can reduce
-# the scan to this device. Set list list of device paths in same syntax like in
-# command lsscsi, e.g. ('16:0:0:0' '15:0')
-# (pscsi-device-mask ('*'))
-
diff --git a/tools/examples/xend-pci-permissive.sxp b/tools/examples/xend-pci-permissive.sxp
deleted file mode 100644
index 1a3fb90..0000000
--- a/tools/examples/xend-pci-permissive.sxp
+++ /dev/null
@@ -1,27 +0,0 @@
-###############################################################################
-# Configuration file for granting quiry PCI devices full write access to their
-# configuration space. This file should only be used when you are unable to
-# determine the exact registers required by your device. Even so, it should
-# be used only temporarily.
-#
-# SEND A MESSAGE TO xen-devel at lists.xensource.com IF YOU USE THIS FILE.
-#
-# Using this file should NOT be necessary. If you must use it to make some
-# device work, send a message to the above list with as much information about
-# your device as possible so the developers can make accomodations for it.
-# Once developers make the necessary updates you can remove the corresponding
-# entry for your device.
-###############################################################################
-# Entries are formated as follows: <vendor>:<device>[:<subvendor>:<subdevice>]
-#
-# Example: Appending to an existing list
-#
-# (unconstrained_dev_ids
-# ('XXXX:XXXX:XXXX:XXXX' # existing entry
-# 'YYYY:YYYY:YYYY:YYYY' # new entry 1
-# 'ZZZZ:ZZZZ') # new entry 2
-# )
-###############################################################################
-(unconstrained_dev_ids
- #('0123:4567:89AB:CDEF')
-)
diff --git a/tools/examples/xend-pci-quirks.sxp b/tools/examples/xend-pci-quirks.sxp
deleted file mode 100644
index 6bce4b8..0000000
--- a/tools/examples/xend-pci-quirks.sxp
+++ /dev/null
@@ -1,96 +0,0 @@
-###############################################################################
-# Configuration file for quirky PCI devices that require write-access to
-# parts of the configuration space. Use this file to specific PCI device
-# IDs and the configuration space fields to which those devices must be
-# able to write.
-#
-# Length is important, so be sure to match new entries with the
-# lengths of comparable existing entries.
-#
-# Additions to this file take effect as soon as a new domain with a
-# matching device is started. However, to remove a field that was
-# previously applied to a device you must unbind the device from
-# pciback.
-###############################################################################
-# This is a bogus entry to show how a new device would be added to the list
-#
-# (new_quirky_dev_name
-# (pci_ids
-# ('0123:4567:890A:BCEF')
-# )
-#
-# (pci_config_space_fields
-# ('12345678:1:00000000')
-# )
-# )
-###############################################################################
-
-(tg3
- (pci_ids
- # Entries are formated as follows:
- # <vendor>:<device>[:<subvendor>:<subdevice>]
- ('14e4:1644' # Broadcom Tigon3 5700
- '14e4:1645' # Broadcom Tigon3 5701
- '14e4:1646' # Broadcom Tigon3 5702
- '14e4:1647' # Broadcom Tigon3 5703
- '14e4:1648' # Broadcom Tigon3 5704
- '14e4:164d' # Broadcom Tigon3 5702FE
- '14e4:1653' # Broadcom Tigon3 5705
- '14e4:1654' # Broadcom Tigon3 5705_2
- '14e4:165d' # Broadcom Tigon3 5705M
- '14e4:165e' # Broadcom Tigon3 5705M_2
- '14e4:16a6' # Broadcom Tigon3 5702X
- '14e4:16a7' # Broadcom Tigon3 5703X
- '14e4:16a8' # Broadcom Tigon3 5704S
- '14e4:16c6' # Broadcom Tigon3 5702A3
- '14e4:16c7' # Broadcom Tigon3 5703A3
- '14e4:1696' # Broadcom Tigon3 5782
- '14e4:169c' # Broadcom Tigon3 5788
- '14e4:169d' # Broadcom Tigon3 5789
- '14e4:170d' # Broadcom Tigon3 5901
- '14e4:1649' # Broadcom Tigon3 5704S_2
- '14e4:166e' # Broadcom Tigon3 5705F
- '14e4:1658' # Broadcom Tigon3 5720
- '14e4:1659' # Broadcom Tigon3 5721
- '14e4:1676' # Broadcom Tigon3 5750
- '14e4:1677' # Broadcom Tigon3 5751
- '14e4:167c' # Broadcom Tigon3 5750M
- '14e4:167d' # Broadcom Tigon3 5751M
- '14e4:167e' # Broadcom Tigon3 5751F
- '14e4:1600' # Broadcom Tigon3 5752
- '14e4:1601' # Broadcom Tigon3 5752M
- '14e4:16f7' # Broadcom Tigon3 5753
- '14e4:16fd' # Broadcom Tigon3 5753M
- '14e4:16fe' # Broadcom Tigon3 5753F
- '14e4:1668' # Broadcom Tigon3 5714
- '14e4:1678' # Broadcom Tigon3 5715
- '14e4:166a' # Broadcom Tigon3 5780
- '14e4:166b' # Broadcom Tigon3 5780S
- '14e4:16dd' # Broadcom Tigon3 5781
- '1148:4400' # Syskonnect 9DXX
- '1148:4500' # Syskonnect 9MXX
- '173b:03e8' # Altima AC1000
- '173b:03e9' # Altima AC1001
- '173b:03eb' # Altima AC1003
- '173b:03ea' # Altima AC9100
- '106b:1645') # Apple Tigon3
- )
-
- (pci_config_space_fields
- # Entries are formated as follows:
- # <register>:<size>:<mask>
- # size is measured in bytes (1,2,4 are valid sizes)
- # mask is currently unused; use all zero's
- ('00000078:4:00000000' # TG3PCI_REG_BASE_ADDR
- '0000007c:4:00000000' # TG3PCI_MEM_WIN_BASE_ADDR
- '00000080:4:00000000' # TG3PCI_REG_DATA
- '00000084:4:00000000' # TG3PCI_MEM_WIN_DATA
- '00000090:4:00000000' # TG3PCI_MISC_LOCAL_CTRL
- '00000068:4:00000000' # TG3PCI_MISC_HOST_CTRL
- '0000009C:4:00000000' # TG3PCI_STD_RING_PROD_IDX + TG3_64BIT_REG_LOW
- '00000098:4:00000000' # TG3PCI_STD_RING_PROD_IDX + TG3_64BIT_REG_HIGH
- '000000a4:4:00000000' # TG3PCI_RCV_RET_RING_CON_IDX + TG3_64BIT_REG_LOW
- '000000a0:4:00000000' # TG3PCI_RCV_RET_RING_CON_IDX + TG3_64BIT_REG_HIGH
- '00000070:4:00000000') # TG3PCI_PCISTATE
- )
-)
diff --git a/tools/examples/xm-config.xml b/tools/examples/xm-config.xml
deleted file mode 100644
index 943b74d..0000000
--- a/tools/examples/xm-config.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<!--
-
-Copyright (C) 2006 XenSource Inc.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of version 2.1 of the GNU Lesser General Public
-License as published by the Free Software Foundation.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
--->
-
-<!--
-
-This is a configuration file for xm; it should be placed in
-/etc/xen/xm-config.xml. If this file is missing, then xm will fall back to
-the normal behaviour that's in Xen 3.0.4 and below. The settings here are
-most useful for experimenting with the Xen-API preview in Xen 3.0.4.
-
--->
-
-<xm>
- <!-- The server element describes how to talk to Xend. The type may be
- Xen-API or LegacyXMLRPC (the default). The URI is that of the
- server; you might try http://server:9363/ or
- httpu:///var/run/xend/xen-api.sock for the Xen-API, or
- httpu:///var/run/xend/xmlrpc.sock for the legacy server.
-
- The username and password attributes will be used to log in if Xen-API
- is being used.
- -->
- <!--
- <server type='Xen-API'
- uri='http://localhost:9363/'
- username='me'
- password='mypassword' />
- -->
-</xm>
diff --git a/tools/examples/xmexample.hvm b/tools/examples/xmexample.hvm
deleted file mode 100644
index 96b6cc4..0000000
--- a/tools/examples/xmexample.hvm
+++ /dev/null
@@ -1,373 +0,0 @@
-# -*- 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.
-#============================================================================
-
-#----------------------------------------------------------------------------
-# Kernel image file.
-kernel = "hvmloader"
-
-# The domain build function. HVM domain uses 'hvm'.
-builder='hvm'
-
-# 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 = 128
-
-# Shadow pagetable memory for the domain, in MB.
-# If not explicictly set, xend will pick an appropriate value.
-# Should be at least 2KB per MB of domain memory, plus a few MB per vcpu.
-# shadow_memory = 8
-
-# Whether to transparently share this domain's memory with other domains.
-# default = 0
-# memory_sharing = 0
-
-# A name for your domain. All domains must have different names.
-name = "ExampleHVMDomain"
-
-# 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"
-
-#-----------------------------------------------------------------------------
-# The number of cpus guest platform has, default=1
-#vcpus=1
-
-# Enable/disable HVM guest PAE, default=1 (enabled)
-#pae=1
-
-# Enable/disable HVM guest ACPI, default=1 (enabled)
-#acpi=1
-
-# Enable/disable HVM APIC mode, default=1 (enabled)
-# Note that this option is ignored if vcpus > 1
-#apic=1
-
-# Enable/disable extended power management support within HVM guest, i.e., beyond
-# S3, S4, S5 within guest like exposing battery meter.
-# 0 (default option, extended power management support disabled)
-# 1 (pass-through mode; uses pass-through as needed; efficient but limited in scope)
-# 2 (non pass-through mode; extended scope, likely to work on all applicable environment
-# but comparitively less efficient than pass-through mode)
-# xen_extended_power_mgmt=0
-
-# 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
-
-# Optionally define mac and/or bridge for the network interfaces.
-# Random MACs are assigned if not given.
-#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0, model=ne2k_pci' ]
-# type=ioemu specify the NIC is an ioemu device not netfront
-vif = [ 'type=ioemu, bridge=xenbr0' ]
-
-#----------------------------------------------------------------------------
-# 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,r' ]
-disk = [ 'file:/var/images/min-el3-i386.img,hda,w', ',hdc:cdrom,r' ]
-
-#----------------------------------------------------------------------------
-# 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'
-
-#============================================================================
-
-# Device Model to be used
-device_model = 'qemu-dm'
-
-#-----------------------------------------------------------------------------
-# boot on floppy (a), hard disk (c), Network (n) or CD-ROM (d)
-# default: hard disk, cd-rom, floppy
-#boot="cda"
-
-#-----------------------------------------------------------------------------
-# write to temporary files instead of disk image files
-#snapshot=1
-
-#----------------------------------------------------------------------------
-# enable SDL library for graphics, default = 0
-sdl=0
-
-#----------------------------------------------------------------------------
-# enable OpenGL for texture rendering inside the SDL window, default = 1
-# valid only if sdl is enabled.
-opengl=1
-
-#----------------------------------------------------------------------------
-# enable VNC library for graphics, default = 1
-vnc=1
-
-#----------------------------------------------------------------------------
-# address that should be listened on for the VNC server if vnc is set.
-# default is to use 'vnc-listen' setting from
-# auxbin.xen_configdir() + /xend-config.sxp
-#vnclisten="127.0.0.1"
-
-#----------------------------------------------------------------------------
-# set VNC display number, default = domid
-#vncdisplay=1
-
-#----------------------------------------------------------------------------
-# try to find an unused port for the VNC server, default = 1
-#vncunused=1
-
-#----------------------------------------------------------------------------
-# set password for domain's VNC console
-# default is depents on vncpasswd in xend-config.sxp
-vncpasswd=''
-
-#----------------------------------------------------------------------------
-# no graphics, use serial port
-#nographic=0
-
-#----------------------------------------------------------------------------
-# enable stdvga, default = 0 (use cirrus logic device model)
-stdvga=0
-
-#-----------------------------------------------------------------------------
-# serial port re-direct to pty deivce, /dev/pts/n
-# then xm console or minicom can connect
-serial='pty'
-
-#----------------------------------------------------------------------------
-# tsc_mode : TSC mode (0=default, 1=native TSC, 2=never emulate, 3=pvrdtscp)
-# emulate TSC provides synced TSC for all vcpus, but lose perfomrance.
-# native TSC leverages hardware's TSC(no perf loss), but vcpu's TSC may lose
-# sync due to hardware's unreliable/unsynced TSC between CPUs.
-# default intelligently uses native TSC on machines where it is safe, but
-# switches to emulated if necessary after save/restore/migration
-# pvrdtscp is for intelligent apps that use special Xen-only paravirtualized
-# cpuid instructions to obtain offset/scaling/migration info and maximize
-# performance within pools of machines that support the rdtscp instruction
-tsc_mode=0
-
-#-----------------------------------------------------------------------------
-# Qemu Monitor, default is disable
-# Use ctrl-alt-2 to connect
-#monitor=1
-
-
-#-----------------------------------------------------------------------------
-# enable sound card support, [sb16|es1370|all|..,..], default none
-#soundhw='sb16'
-
-
-#-----------------------------------------------------------------------------
-# set the real time clock to local time [default=0 i.e. set to utc]
-#localtime=1
-
-
-#-----------------------------------------------------------------------------
-# set the real time clock offset in seconds [default=0 i.e. same as dom0]
-#rtc_timeoffset=3600
-
-#-----------------------------------------------------------------------------
-# start in full screen
-#full-screen=1
-
-
-#-----------------------------------------------------------------------------
-# Enable USB support (specific devices specified at runtime through the
-# monitor window)
-#usb=1
-
-# Enable USB mouse support (only enable one of the following, `mouse' for
-# PS/2 protocol relative mouse, `tablet' for
-# absolute mouse)
-#usbdevice='mouse'
-#usbdevice='tablet'
-
-#-----------------------------------------------------------------------------
-# Set keyboard layout, default is en-us keyboard.
-#keymap='ja'
-
-#-----------------------------------------------------------------------------
-# Enable/disable xen platform PCI device, default=1 (enabled)
-#xen_platform_pci=1
-
-#-----------------------------------------------------------------------------
-# Configure guest CPUID responses:
-#
-#cpuid=[ '1:ecx=xxxxxxxxxxx00xxxxxxxxxxxxxxxxxxx,
-# eax=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' ]
-# - Unset the SSE4 features (CPUID.1[ECX][20-19])
-# - Default behaviour for all other bits in ECX And EAX registers.
-#
-# Each successive character represent a lesser-significant bit:
-# '1' -> force the corresponding bit to 1
-# '0' -> force to 0
-# 'x' -> Get a safe value (pass through and mask with the default policy)
-# 'k' -> pass through the host bit value
-# 's' -> as 'k' but preserve across save/restore and migration
-#
-# Expose to the guest multi-core cpu instead of multiple processors
-# Example for intel, expose a 8-core processor :
-#cpuid=['1:edx=xxx1xxxxxxxxxxxxxxxxxxxxxxxxxxxx,
-# ebx=xxxxxxxx00010000xxxxxxxxxxxxxxxx',
-# '4,0:eax=001111xxxxxxxxxxxxxxxxxxxxxxxxxx']
-# - CPUID.1[EDX][HT] : Enable HT
-# - CPUID.1[EBX] : Number of vcpus * 2
-# - CPUID.4,0[EAX] : Number of vcpus * 2 - 1
-#vcpus=8
-#
-# Example for amd, expose a 5-core processor :
-# cpuid = ['1:ebx=xxxxxxxx00001010xxxxxxxxxxxxxxxx,
-# edx=xxx1xxxxxxxxxxxxxxxxxxxxxxxxxxxx',
-# '0x80000001:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1x',
-# '0x80000008:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxx001001']
-# - CPUID.1[EBX] : Threads per Core * Cores per Socket (2 * #vcpus)
-# - CPUID.1[EDX][HT] : Enable HT
-# - CPUID.0x80000001[CmpLegacy] : Use legacy method
-# - CPUID.0x80000008[ECX] : #vcpus * 2 - 1
-#vcpus=5
-#
-# Downgrade the cpuid to make a better compatibility for migration :
-# Look like a generic 686 :
-# cpuid = [ '0:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0',
-# '1:eax=0x06b1,
-# ecx=xxxxxxxxxxx0000xx00xxx0000000xx0,
-# edx=xxx00000xxxxxxx0xxxxxxxxx0xxxxxx',
-# '4:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0',
-# '0x80000000:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0']
-# with the highest leaf
-# - CPUID.0[EAX] : Set the highest leaf
-# - CPUID.1[EAX] : 686
-# - CPUID.1[ECX] : Mask some features
-# - CPUID.1[EDX] : Mask some features
-# - CPUID.4 : Reply like the highest leaf, in our case CPUID.3
-# - CPUID.0x80000000 : No extension we are on a Pentium III, reply like the
-# highest leaf (CPUID.3).
-#
-# Configure host CPUID consistency checks, which must be satisfied for this
-# VM to be allowed to run on this host's processor type:
-#cpuid_check=[ '1:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxx1xxxxx' ]
-# - Host must have VMX feature flag set
-#
-# The format is similar to the above for 'cpuid':
-# '1' -> the bit must be '1'
-# '0' -> the bit must be '0'
-# 'x' -> we don't care (do not check)
-# 's' -> the bit must be the same as on the host that started this VM
-
-#-----------------------------------------------------------------------------
-# Configure passthrough PCI{,-X,e} devices:
-#
-# pci=[ '[SSSS:]BB:DD.F[,option1[,option2[...]]]', ... ]
-#
-# [SSSS]:BB:DD.F "bus segment:bus:device.function"(1) of the device to
-# be assigned, bus segment is optional. All fields are
-# in hexadecimal and no field should be longer than that
-# as shown in the pattern. Successful assignment may need
-# certain hardware support and additional configurations
-# (e.g. VT-d, see docs/misc/vtd.txt for more details).
-#
-# (1) bus segment is sometimes also referred to as the PCI "domain",
-# not to be confused with Xen domain.
-#
-#
-# optionN per-device options in "key=val" format. Current
-# available options are:
-# - msitranslate=0|1
-# per-device overriden of pci_msitranslate, see below
-# - power_mgmt=0|1
-# per-device overriden of pci_power_mgmt, see below
-#
-#pci=[ '07:00.0', '07:00.1' ]
-
-# MSI-INTx translation for MSI capable devices:
-#
-# If it's set, Xen will enable MSI for the device that supports it even
-# if the guest don't use MSI. In the case, an IO-APIC type interrupt will
-# be injected to the guest every time a corresponding MSI message is
-# received.
-# If the guest enables MSI or MSI-X, the translation is automatically
-# turned off.
-#
-#pci_msitranslate=1
-
-# PCI Power Management:
-#
-# If it's set, the guest OS will be able to program D0-D3hot states of the
-# PCI device for the purpose of low power consumption.
-#
-#pci_power_mgmt=0
-
-# Enable graphics passthrough:
-#
-# If it's set, and specify graphics device BDF in pci passthrough option,
-# like pci=['xx:xx.x'], it enables graphics passthrough, default=0 (disabled)
-#gfx_passthru=0
-
-#-----------------------------------------------------------------------------
-# 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 --git a/tools/examples/xmexample.hvm-stubdom b/tools/examples/xmexample.hvm-stubdom
deleted file mode 100644
index a425e83..0000000
--- a/tools/examples/xmexample.hvm-stubdom
+++ /dev/null
@@ -1,317 +0,0 @@
-# -*- 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.
-#============================================================================
-#
-# This is a version using a stubdomain for device model
-# The differences with xmexample.hvm are marked with "STUBDOM"
-
-#----------------------------------------------------------------------------
-# Kernel image file.
-kernel = "hvmloader"
-
-# The domain build function. HVM domain uses 'hvm'.
-builder='hvm'
-
-# 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 = 128
-
-# Shadow pagetable memory for the domain, in MB.
-# If not explicictly set, xend will pick an appropriate value.
-# Should be at least 2KB per MB of domain memory, plus a few MB per vcpu.
-# shadow_memory = 8
-
-# A name for your domain. All domains must have different names.
-name = "xmexample.hvm"
-
-# 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"
-
-#-----------------------------------------------------------------------------
-# The number of cpus guest platform has, default=1
-#vcpus=1
-
-# Enable/disable HVM guest PAE, default=1 (enabled)
-#pae=1
-
-# Enable/disable HVM guest ACPI, default=1 (enabled)
-#acpi=1
-
-# Enable/disable HVM APIC mode, default=1 (enabled)
-# Note that this option is ignored if vcpus > 1
-#apic=1
-
-# 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
-
-# Optionally define mac and/or bridge for the network interfaces.
-# Random MACs are assigned if not given.
-#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0, model=ne2k_pci' ]
-# type=ioemu specify the NIC is an ioemu device not netfront
-vif = [ 'type=ioemu, bridge=xenbr0' ]
-
-#----------------------------------------------------------------------------
-# 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 = [ 'file:/var/images/min-el3-i386.img,hda,w', 'phy:/dev/cdrom,hdc:cdrom,r' ]
-
-#----------------------------------------------------------------------------
-# 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'
-
-#============================================================================
-
-# Device Model to be used
-#
-# STUBDOM: this is a script that creates the stub domain running the device
-# model
-device_model = 'stubdom-dm'
-
-#-----------------------------------------------------------------------------
-# boot on floppy (a), hard disk (c), Network (n) or CD-ROM (d)
-# default: hard disk, cd-rom, floppy
-boot="cda"
-
-#-----------------------------------------------------------------------------
-# write to temporary files instead of disk image files
-#snapshot=1
-
-#----------------------------------------------------------------------------
-# enable SDL library for graphics, default = 0
-#
-sdl=0
-
-#----------------------------------------------------------------------------
-# enable OpenGL for texture rendering inside the SDL window, default = 1
-# valid only if sdl is enabled.
-#
-opengl=1
-
-#----------------------------------------------------------------------------
-# enable VNC library for graphics, default = 1
-vnc=1
-
-#----------------------------------------------------------------------------
-# address that should be listened on for the VNC server if vnc is set.
-# default is to use 'vnc-listen' setting from
-# auxbin.xen_configdir() + /xend-config.sxp
-#vnclisten="127.0.0.1"
-
-#----------------------------------------------------------------------------
-# set VNC display number, default = domid
-#vncdisplay=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
-# default is depents on vncpasswd in xend-config.sxp
-vncpasswd=''
-
-#----------------------------------------------------------------------------
-# no graphics, use serial port
-#nographic=0
-
-#----------------------------------------------------------------------------
-# enable stdvga, default = 0 (use cirrus logic device model)
-stdvga=0
-
-#-----------------------------------------------------------------------------
-# serial port re-direct to pty deivce, /dev/pts/n
-# then xm console or minicom can connect
-#
-# In the stubdoms case this option adds a secondary console to the
-# stubdom because there is always one for logging.
-# To connect to the guest serial you can use "xm console -n 1"
-# followed by the domain name of the stubdom.
-#serial='pty'
-
-
-#-----------------------------------------------------------------------------
-# Qemu Monitor, default is disable
-# Use ctrl-alt-2 to connect
-#monitor=1
-
-
-#-----------------------------------------------------------------------------
-# enable sound card support, [sb16|es1370|all|..,..], default none
-#
-# STUBDOM: not supported
-#soundhw='sb16'
-
-
-#-----------------------------------------------------------------------------
-# set the real time clock to local time [default=0 i.e. set to utc]
-#localtime=1
-
-
-#-----------------------------------------------------------------------------
-# set the real time clock offset in seconds [default=0 i.e. same as dom0]
-#rtc_timeoffset=3600
-
-#-----------------------------------------------------------------------------
-# start in full screen
-#full-screen=1
-
-
-#-----------------------------------------------------------------------------
-# Enable USB support (specific devices specified at runtime through the
-# monitor window)
-#usb=1
-
-# Enable USB mouse support (only enable one of the following, `mouse' for
-# PS/2 protocol relative mouse, `tablet' for
-# absolute mouse)
-#usbdevice='mouse'
-#usbdevice='tablet'
-
-#-----------------------------------------------------------------------------
-# Set keyboard layout, default is en-us keyboard.
-#keymap='ja'
-
-#-----------------------------------------------------------------------------
-# Configure guest CPUID responses:
-#
-#cpuid=[ '1:ecx=xxxxxxxxxxx00xxxxxxxxxxxxxxxxxxx,
-# eax=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' ]
-# - Unset the SSE4 features (CPUID.1[ECX][20-19])
-# - Default behaviour for all other bits in ECX And EAX registers.
-#
-# Each successive character represent a lesser-significant bit:
-# '1' -> force the corresponding bit to 1
-# '0' -> force to 0
-# 'x' -> Get a safe value (pass through and mask with the default policy)
-# 'k' -> pass through the host bit value
-# 's' -> as 'k' but preserve across save/restore and migration
-#
-# Expose to the guest multi-core cpu instead of multiple processors
-# Example for intel, expose a 8-core processor :
-#cpuid=['1:edx=xxx1xxxxxxxxxxxxxxxxxxxxxxxxxxxx,
-# ebx=xxxxxxxx00010000xxxxxxxxxxxxxxxx',
-# '4,0:eax=001111xxxxxxxxxxxxxxxxxxxxxxxxxx']
-# - CPUID.1[EDX][HT] : Enable HT
-# - CPUID.1[EBX] : Number of vcpus * 2
-# - CPUID.4,0[EAX] : Number of vcpus * 2 - 1
-#vcpus=8
-#
-# Example for amd, expose a 5-core processor :
-# cpuid = ['1:ebx=xxxxxxxx00001010xxxxxxxxxxxxxxxx,
-# edx=xxx1xxxxxxxxxxxxxxxxxxxxxxxxxxxx',
-# '0x80000001:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1x',
-# '0x80000008:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxx001001']
-# - CPUID.1[EBX] : Threads per Core * Cores per Socket (2 * #vcpus)
-# - CPUID.1[EDX][HT] : Enable HT
-# - CPUID.0x80000001[CmpLegacy] : Use legacy method
-# - CPUID.0x80000008[ECX] : #vcpus * 2 - 1
-#vcpus=5
-#
-# Downgrade the cpuid to make a better compatibility for migration :
-# Look like a generic 686 :
-# cpuid = [ '0:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0',
-# '1:eax=0x06b1,
-# ecx=xxxxxxxxxx0000xx00xxx0000000xx0,
-# edx=xx00000xxxxxxx0xxxxxxxxx0xxxxxx',
-# '4:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0',
-# '0x80000000:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0']
-# with the highest leaf
-# - CPUID.0[EAX] : Set the highest leaf
-# - CPUID.1[EAX] : 686
-# - CPUID.1[ECX] : Mask some features
-# - CPUID.1[EDX] : Mask some features
-# - CPUID.4 : Reply like the highest leaf, in our case CPUID.3
-# - CPUID.0x80000000 : No extension we are on a Pentium III, reply like the
-# highest leaf (CPUID.3).
-#
-# Configure host CPUID consistency checks, which must be satisfied for this
-# VM to be allowed to run on this host's processor type:
-#cpuid_check=[ '1:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxx1xxxxx' ]
-# - Host must have VMX feature flag set
-#
-# The format is similar to the above for 'cpuid':
-# '1' -> the bit must be '1'
-# '0' -> the bit must be '0'
-# 'x' -> we don't care (do not check)
-# 's' -> the bit must be the same as on the host that started this VM
-
-
-#-----------------------------------------------------------------------------
-# 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 --git a/tools/examples/xmexample.nbd b/tools/examples/xmexample.nbd
deleted file mode 100644
index 7fdb74e..0000000
--- a/tools/examples/xmexample.nbd
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- mode: python; -*-
-#
-# xm create configuration example.
-#
-# This configuration is appropriate for using Network Block Device (NBD)
-# filesystems.
-#
-# Each of these parameters will need changing to match your setup.
-#
-
-kernel = "/boot/vmlinuz-2.6.13-15b-xen"
-ramdisk = "/boot/initrd-2.6.13-15b-xen"
-
-# 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 = 128
-
-name = "nbd4"
-vif = [ '' ]
-# Please change PORT
-disk = [ 'nbd:134.100.233.115 20004,hda1,w' ]
-dhcp = "dhcp"
-hostname= "nbd4"
-root = "/dev/hda1 ro"
-extra = "3"
diff --git a/tools/examples/xmexample.pv-grub b/tools/examples/xmexample.pv-grub
deleted file mode 100644
index e04e6c1..0000000
--- a/tools/examples/xmexample.pv-grub
+++ /dev/null
@@ -1,172 +0,0 @@
-# -*- 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 = "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 = 128
-
-# 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 = [ 'sdl=1' ]
-#
-# This uses environment variables XAUTHORITY and DISPLAY. You
-# can override that:
-#
-# vfb = [ 'sdl=1,xauthority=/home/bozo/.Xauthority,display=:1' ]
-#
-# To create one using the VNC backend and sensible defaults:
-#
-# vfb = [ 'vnc=1' ]
-#
-# 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 = [ 'vnc=1,vnclisten=127.0.0.1,vncdisplay=1' ]
-#
-# Or you can bind the first unused port above 5900:
-#
-# vfb = [ 'vnc=1,vnclisten=0.0.0.0,vncunused=1' ]
-#
-# You can override the password:
-#
-# vfb = [ 'vnc=1,vncpasswd=MYPASSWD' ]
-#
-# Empty password disables authentication. Defaults to the vncpasswd
-# configured in xend-config.sxp.
-
-#----------------------------------------------------------------------------
-# 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 --git a/tools/examples/xmexample1 b/tools/examples/xmexample1
deleted file mode 100644
index c951200..0000000
--- a/tools/examples/xmexample1
+++ /dev/null
@@ -1,197 +0,0 @@
-# -*- 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.
-#============================================================================
-
-#----------------------------------------------------------------------------
-# Kernel image file.
-kernel = "/boot/vmlinuz-2.6.10-xenU"
-
-# Optional ramdisk.
-#ramdisk = "/boot/initrd.gz"
-
-# The domain build function. Default is 'linux'.
-#builder='linux'
-
-# 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 = [ 'sdl=1' ]
-#
-# This uses environment variables XAUTHORITY and DISPLAY. You
-# can override that:
-#
-# vfb = [ 'sdl=1,xauthority=/home/bozo/.Xauthority,display=:1' ]
-#
-# To create one using the VNC backend and sensible defaults:
-#
-# vfb = [ 'vnc=1' ]
-#
-# 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 = [ 'vnc=1,vnclisten=127.0.0.1,vncdisplay=1' ]
-#
-# Or you can bind the first unused port above 5900:
-#
-# vfb = [ 'vnc=1,vnclisten=0.0.0.0,vncunused=1' ]
-#
-# You can override the password:
-#
-# vfb = [ 'vnc=1,vncpasswd=MYPASSWD' ]
-#
-# Empty password disables authentication. Defaults to the vncpasswd
-# configured in xend-config.sxp.
-
-#----------------------------------------------------------------------------
-# 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'
-
-# Sets runlevel 4.
-extra = "4"
-
-#----------------------------------------------------------------------------
-# 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 --git a/tools/examples/xmexample2 b/tools/examples/xmexample2
deleted file mode 100644
index 8c5137e..0000000
--- a/tools/examples/xmexample2
+++ /dev/null
@@ -1,232 +0,0 @@
-# -*- mode: python; -*-
-#============================================================================
-# Example Python setup script for 'xm create'.
-# This script sets the parameters used when a domain is created using 'xm create'.
-#
-# This is a relatively advanced script that uses a parameter, vmid, to control
-# the settings. So this script can be used to start a set of domains by
-# setting the vmid parameter on the 'xm create' command line. For example:
-#
-# xm create vmid=1
-# xm create vmid=2
-# xm create vmid=3
-#
-# The vmid is purely a script variable, and has no effect on the the domain
-# id assigned to the new domain.
-#============================================================================
-
-# Define script variables here.
-# xm_vars is defined automatically, use xm_vars.var() to define a variable.
-
-# This function checks that 'vmid' has been given a valid value.
-# It is called automatically by 'xm create'.
-def vmid_check(var, val):
- val = int(val)
- if val <= 0:
- raise ValueError
- return val
-
-# Define the 'vmid' variable so that 'xm create' knows about it.
-xm_vars.var('vmid',
- use="Virtual machine id. Integer greater than 0.",
- check=vmid_check)
-
-# Check the defined variables have valid values..
-xm_vars.check()
-
-#----------------------------------------------------------------------------
-# Kernel image file.
-kernel = "/boot/vmlinuz-2.6.10-xenU"
-
-# Optional ramdisk.
-#ramdisk = "/boot/initrd.gz"
-
-# The domain build function. Default is 'linux'.
-#builder='linux'
-
-# 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 the new domain. All domains have to have different names,
-# so we use the vmid to create a name.
-name = "VM%d" % vmid
-
-# 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
-#cpus = "%s" % vmid # set based on vmid (mod number of CPUs)
-
-# Number of Virtual CPUS to use, default is 1
-#vcpus = 1
-vcpus = 4 # make your domain a 4-way
-
-#----------------------------------------------------------------------------
-# 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.
-
-# This makes the disk device depend on the vmid - assuming
-# that devices sda7, sda8 etc. exist. The device is exported
-# to all domains as sda1.
-# All domains get sda6 read-only (to use for /usr, see below).
-disk = [ 'phy:sda%d,sda1,w' % (7+vmid),
- 'phy:sda6,sda6,r' ]
-
-#----------------------------------------------------------------------------
-# Define frame buffer device.
-#
-# By default, no frame buffer device is configured.
-#
-# To create one using the SDL backend and sensible defaults:
-#
-# vfb = [ 'sdl=1' ]
-#
-# This uses environment variables XAUTHORITY and DISPLAY. You
-# can override that:
-#
-# vfb = [ 'sdl=1,xauthority=/home/bozo/.Xauthority,display=:1' ]
-#
-# To create one using the VNC backend and sensible defaults:
-#
-# vfb = [ 'vnc=1' ]
-#
-# 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 = [ 'vnc=1,vnclisten=127.0.0.1,vncdisplay=%d' % vmid ]
-#
-# Or you can bind the first unused port above 5900:
-#
-# vfb = [ 'vnc=1,vnclisten=0.0.0.0,vncunused=1' ]
-#
-# You can override the password:
-#
-# vfb = [ 'vnc=1,vncpasswd=MYPASSWD' ]
-#
-# Empty password disables authentication. Defaults to the vncpasswd
-# configured in xend-config.sxp.
-
-#----------------------------------------------------------------------------
-# 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/sda1 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'
-
-# Sets runlevel 4 and the device for /usr.
-extra = "4 VMID=%d usr=/dev/sda6" % vmid
-
-#----------------------------------------------------------------------------
-# 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 --git a/tools/examples/xmexample3 b/tools/examples/xmexample3
deleted file mode 100644
index ae799f9..0000000
--- a/tools/examples/xmexample3
+++ /dev/null
@@ -1,218 +0,0 @@
-# -*- mode: python; -*-
-#============================================================================
-# Example Python setup script for 'xm create'.
-# This script sets the parameters used when a domain is created using 'xm create'.
-#
-# This is a relatively advanced script that uses a parameter, vmid, to control
-# the settings. So this script can be used to start a set of domains by
-# setting the vmid parameter on the 'xm create' command line. For example:
-#
-# xm create vmid=1
-# xm create vmid=2
-# xm create vmid=3
-#
-# The vmid is purely a script variable, and has no effect on the the domain
-# id assigned to the new domain.
-#============================================================================
-
-# Define script variables here.
-# xm_vars is defined automatically, use xm_vars.var() to define a variable.
-
-# This function checks that 'vmid' has been given a valid value.
-# It is called automatically by 'xm create'.
-def vmid_check(var, val):
- val = int(val)
- if val <= 0:
- raise ValueError
- return val
-
-# Define the 'vmid' variable so that 'xm create' knows about it.
-xm_vars.var('vmid',
- use="Virtual machine id. Integer greater than 0.",
- check=vmid_check)
-
-# Check the defined variables have valid values..
-xm_vars.check()
-
-#----------------------------------------------------------------------------
-# Kernel image file.
-kernel = "/path/to/domU/kernel"
-
-# Optional ramdisk.
-#ramdisk = "/boot/initrd.gz"
-
-# The domain build function. Default is 'linux'.
-#builder='linux'
-
-# 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 the new domain. All domains have to have different names,
-# so we use the vmid to create a name.
-name = "VM%d" % vmid
-
-# 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
-cpus = "%s" % vmid # set based on vmid (mod number of CPUs)
-
-#----------------------------------------------------------------------------
-# Define network interfaces.
-
-# Optionally define mac and/or bridge for the network interfaces.
-# Random MACs are assigned if not given.
-
-vif = [ 'ip=192.168.%d.1/24' % (vmid)]
-
-#----------------------------------------------------------------------------
-# 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.
-
-# This makes the disk device depend on the vmid - assuming
-# tHat devices sda7, sda8 etc. exist. The device is exported
-# to all domains as sda1.
-# All domains get sda6 read-only (to use for /usr, see below).
-disk = [ 'phy:hda%d,hda1,w' % (vmid)]
-
-#----------------------------------------------------------------------------
-# Define frame buffer device.
-#
-# By default, no frame buffer device is configured.
-#
-# To create one using the SDL backend and sensible defaults:
-#
-# vfb = [ 'sdl=1' ]
-#
-# This uses environment variables XAUTHORITY and DISPLAY. You
-# can override that:
-#
-# vfb = [ 'sdl=1,xauthority=/home/bozo/.Xauthority,display=:1' ]
-#
-# To create one using the VNC backend and sensible defaults:
-#
-# vfb = [ 'vnc=1' ]
-#
-# 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 = [ 'vnc=1,vnclisten=127.0.0.1,vncdisplay=%d' % vmid ]
-#
-# Or you can bind the first unused port above 5900:
-#
-# vfb = [ 'vnc=1,vnclisten=0.0.0.0,vncunused=1' ]
-#
-# You can override the password:
-#
-# vfb = [ 'vnc=1,vncpasswd=MYPASSWD' ]
-#
-# Empty password disables authentication. Defaults to the vncpasswd
-# configured in xend-config.sxp.
-
-#----------------------------------------------------------------------------
-# 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="off"
-ip="192.168.%d.2" % (vmid)
-# Set netmask.
-netmask="255.255.255.0"
-# Set default gateway.
-gateway="192.168.%d.1" % (vmid)
-# Set the hostname.
-hostname= "domain-%d.xeno" % vmid
-
-# Set root device.
-root = "/dev/hda1 ro"
-
-# Root device for nfs.
-#root = "/dev/nfs"
-# The nfs server.
-#nfs_server = "10.212.4.103"
-# Root directory on the nfs server.
-#nfs_root = "/path/to/root/filesystem"
-
-# Sets runlevel 4 and the device for /usr.
-extra = "4 VMID=%d" % vmid
-
-#----------------------------------------------------------------------------
-# 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 --git a/tools/firmware/Makefile b/tools/firmware/Makefile
index cb13212..ca5df42 100644
--- a/tools/firmware/Makefile
+++ b/tools/firmware/Makefile
@@ -17,13 +17,15 @@ SUBDIRS-$(CONFIG_ROMBIOS) += vgabios
SUBDIRS-$(CONFIG_ROMBIOS) += etherboot
SUBDIRS-y += hvmloader
+LD32BIT-$(CONFIG_FreeBSD) := LD32BIT_FLAG=-melf_i386_fbsd
+
ovmf-dir:
GIT=$(GIT) $(XEN_ROOT)/scripts/git-checkout.sh $(OVMF_UPSTREAM_URL) $(OVMF_UPSTREAM_REVISION) ovmf-dir
cp ovmf-makefile ovmf-dir/Makefile;
seabios-dir:
- GIT=$(GIT) $(XEN_ROOT)/scripts/git-checkout.sh $(SEABIOS_UPSTREAM_URL) $(SEABIOS_UPSTREAM_TAG) seabios-dir
- cp seabios-config seabios-dir/.config;
+ GIT=$(GIT) $(XEN_ROOT)/scripts/git-checkout.sh $(SEABIOS_UPSTREAM_URL) $(SEABIOS_UPSTREAM_REVISION) seabios-dir
+ $(MAKE) -C seabios-dir defconfig
.PHONY: all
all: $(SUBDIRS-y)
@@ -36,7 +38,7 @@ ifeq ($(CONFIG_ROMBIOS),y)
false ; \
fi
endif
- $(MAKE) PYTHON=$(PYTHON) subdirs-$@
+ $(MAKE) $(LD32BIT-y) CC=$(CC) PYTHON=$(PYTHON) subdirs-$@
.PHONY: install
@@ -60,7 +62,7 @@ subdir-distclean-seabios-dir: .phony
rm -rf seabios-dir seabios-dir-remote
.PHONY: ovmf-dir-force-update
-ovmf-dir-force-update:
+ovmf-dir-force-update: ovmf-dir
set -ex; \
if [ "$(OVMF_UPSTREAM_REVISION)" ]; then \
cd ovmf-dir-remote; \
@@ -74,15 +76,27 @@ subdir-clean-ovmf:
fi
.PHONY: seabios-dir-force-update
-seabios-dir-force-update:
+seabios-dir-force-update: seabios-dir
set -ex; \
- if [ "$(SEABIOS_UPSTREAM_TAG)" ]; then \
+ if [ "$(SEABIOS_UPSTREAM_REVISION)" ]; then \
cd seabios-dir-remote; \
$(GIT) fetch origin; \
- $(GIT) reset --hard $(SEABIOS_UPSTREAM_TAG); \
+ $(GIT) reset --hard $(SEABIOS_UPSTREAM_REVISION); \
fi
subdir-clean-seabios-dir:
set -e; if test -d seabios-dir/.; then \
$(MAKE) -C seabios-dir clean; \
fi
+
+subtree-force-update:
+ifeq ($(CONFIG_SEABIOS),y)
+ $(MAKE) seabios-dir-force-update
+endif
+ifeq ($(CONFIG_OVMF),y)
+ $(MAKE) ovmf-dir-force-update
+endif
+
+subtree-force-update-all:
+ $(MAKE) seabios-dir-force-update
+ $(MAKE) ovmf-dir-force-update
diff --git a/tools/firmware/hvmloader/Makefile b/tools/firmware/hvmloader/Makefile
index 00ee952..46a79c5 100644
--- a/tools/firmware/hvmloader/Makefile
+++ b/tools/firmware/hvmloader/Makefile
@@ -31,6 +31,7 @@ CFLAGS += $(CFLAGS_xeninclude)
OBJS = hvmloader.o mp_tables.o util.o smbios.o
OBJS += smp.o cacheattr.o xenbus.o
OBJS += e820.o pci.o pir.o ctype.o
+OBJS += hvm_param.o
ifeq ($(debug),y)
OBJS += tests.o
endif
diff --git a/tools/firmware/hvmloader/acpi/build.c b/tools/firmware/hvmloader/acpi/build.c
index f1dd3f0..1431296 100644
--- a/tools/firmware/hvmloader/acpi/build.c
+++ b/tools/firmware/hvmloader/acpi/build.c
@@ -24,6 +24,7 @@
#include "../config.h"
#include "../util.h"
#include <xen/hvm/hvm_xs_strings.h>
+#include <xen/hvm/params.h>
#define ACPI_MAX_SECONDARY_TABLES 16
@@ -51,6 +52,7 @@ struct acpi_info {
uint32_t madt_csum_addr; /* 12 - Address of MADT checksum */
uint32_t madt_lapic0_addr; /* 16 - Address of first MADT LAPIC struct */
uint32_t vm_gid_addr; /* 20 - Address of VM generation id buffer */
+ uint64_t pci_hi_min, pci_hi_len; /* 24, 32 - PCI I/O hole boundaries */
};
/* Number of processor objects in the chosen DSDT. */
@@ -361,7 +363,6 @@ static int construct_secondary_tables(unsigned long *table_ptrs,
static int new_vm_gid(struct acpi_info *acpi_info)
{
uint64_t vm_gid[2], *buf;
- char addr[12];
const char * s;
char *end;
@@ -382,12 +383,9 @@ static int new_vm_gid(struct acpi_info *acpi_info)
return 0;
memcpy(buf, vm_gid, sizeof(vm_gid));
- /* set into ACPI table and XenStore the address */
+ /* set into ACPI table and HVM param the address */
acpi_info->vm_gid_addr = virt_to_phys(buf);
- if ( snprintf(addr, sizeof(addr), "0x%lx", virt_to_phys(buf))
- >= sizeof(addr) )
- return 0;
- xenstore_write("hvmloader/generation-id-address", addr);
+ hvm_param_set(HVM_PARAM_VM_GENERATION_ID_ADDR, acpi_info->vm_gid_addr);
return 1;
}
@@ -525,6 +523,11 @@ void acpi_build_tables(struct acpi_config *config, unsigned int physical)
acpi_info->hpet_present = hpet_exists(ACPI_HPET_ADDRESS);
acpi_info->pci_min = pci_mem_start;
acpi_info->pci_len = pci_mem_end - pci_mem_start;
+ if ( pci_hi_mem_end > pci_hi_mem_start )
+ {
+ acpi_info->pci_hi_min = pci_hi_mem_start;
+ acpi_info->pci_hi_len = pci_hi_mem_end - pci_hi_mem_start;
+ }
return;
diff --git a/tools/firmware/hvmloader/acpi/dsdt.asl b/tools/firmware/hvmloader/acpi/dsdt.asl
index 247a8ad..5610385 100644
--- a/tools/firmware/hvmloader/acpi/dsdt.asl
+++ b/tools/firmware/hvmloader/acpi/dsdt.asl
@@ -45,7 +45,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "Xen", "HVM", 0)
Scope (\_SB)
{
/* ACPI_INFO_PHYSICAL_ADDRESS == 0xFC000000 */
- OperationRegion(BIOS, SystemMemory, 0xFC000000, 24)
+ OperationRegion(BIOS, SystemMemory, 0xFC000000, 40)
Field(BIOS, ByteAcc, NoLock, Preserve) {
UAR1, 1,
UAR2, 1,
@@ -56,7 +56,11 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "Xen", "HVM", 0)
PLEN, 32,
MSUA, 32, /* MADT checksum address */
MAPA, 32, /* MADT LAPIC0 address */
- VGIA, 32 /* VM generation id address */
+ VGIA, 32, /* VM generation id address */
+ LMIN, 32,
+ HMIN, 32,
+ LLEN, 32,
+ HLEN, 32
}
/* Fix HCT test for 0x400 pci memory:
@@ -136,7 +140,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "Xen", "HVM", 0)
/* reserve memory for pci devices */
DWordMemory(
ResourceProducer, PosDecode, MinFixed, MaxFixed,
- Cacheable, ReadWrite,
+ WriteCombining, ReadWrite,
0x00000000,
0x000A0000,
0x000BFFFF,
@@ -145,13 +149,24 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "Xen", "HVM", 0)
DWordMemory(
ResourceProducer, PosDecode, MinFixed, MaxFixed,
- Cacheable, ReadWrite,
+ NonCacheable, ReadWrite,
0x00000000,
0xF0000000,
0xF4FFFFFF,
0x00000000,
0x05000000,
,, _Y01)
+
+ QWordMemory (
+ ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ NonCacheable, ReadWrite,
+ 0x0000000000000000,
+ 0x0000000FFFFFFFF0,
+ 0x0000000FFFFFFFFF,
+ 0x0000000000000000,
+ 0x0000000000000010,
+ ,, _Y02)
+
})
CreateDWordField(PRT0, \_SB.PCI0._CRS._Y01._MIN, MMIN)
@@ -163,6 +178,43 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "Xen", "HVM", 0)
Add(MMIN, MLEN, MMAX)
Subtract(MMAX, One, MMAX)
+ /*
+ * WinXP / Win2K3 blue-screen for operations on 64-bit values.
+ * Therefore we need to split the 64-bit calculations needed
+ * here, but different iasl versions evaluate name references
+ * to integers differently:
+ * Year (approximate) 2006 2008 2012
+ * \_SB.PCI0._CRS._Y02 zero valid valid
+ * \_SB.PCI0._CRS._Y02._MIN valid valid huge
+ */
+ If(LEqual(Zero, \_SB.PCI0._CRS._Y02)) {
+ Subtract(\_SB.PCI0._CRS._Y02._MIN, 14, Local0)
+ } Else {
+ Store(\_SB.PCI0._CRS._Y02, Local0)
+ }
+ CreateDWordField(PRT0, Add(Local0, 14), MINL)
+ CreateDWordField(PRT0, Add(Local0, 18), MINH)
+ CreateDWordField(PRT0, Add(Local0, 22), MAXL)
+ CreateDWordField(PRT0, Add(Local0, 26), MAXH)
+ CreateDWordField(PRT0, Add(Local0, 38), LENL)
+ CreateDWordField(PRT0, Add(Local0, 42), LENH)
+
+ Store(\_SB.LMIN, MINL)
+ Store(\_SB.HMIN, MINH)
+ Store(\_SB.LLEN, LENL)
+ Store(\_SB.HLEN, LENH)
+ Add(MINL, LENL, MAXL)
+ Add(MINH, LENH, MAXH)
+ If(LLess(MAXL, MINL)) {
+ Add(MAXH, One, MAXH)
+ }
+ If(LOr(MINH, LENL)) {
+ If(LEqual(MAXL, 0)) {
+ Subtract(MAXH, One, MAXH)
+ }
+ Subtract(MAXL, One, MAXL)
+ }
+
Return (PRT0)
}
diff --git a/tools/firmware/hvmloader/cacheattr.c b/tools/firmware/hvmloader/cacheattr.c
index 2f6c2f6..de8d39c 100644
--- a/tools/firmware/hvmloader/cacheattr.c
+++ b/tools/firmware/hvmloader/cacheattr.c
@@ -97,20 +97,33 @@ void cacheattr_init(void)
nr_var_ranges = (uint8_t)mtrr_cap;
if ( nr_var_ranges != 0 )
{
- unsigned long base = pci_mem_start, size;
- int i;
+ uint64_t base = pci_mem_start, size;
- for ( i = 0; (base != pci_mem_end) && (i < nr_var_ranges); i++ )
+ for ( i = 0; !(base >> 32) && (i < nr_var_ranges); i++ )
{
size = PAGE_SIZE;
while ( !(base & size) )
size <<= 1;
- while ( ((base + size) < base) || ((base + size) > pci_mem_end) )
+ while ( ((base + size) < base) || ((base + size - 1) >> 32) )
size >>= 1;
wrmsr(MSR_MTRRphysBase(i), base);
- wrmsr(MSR_MTRRphysMask(i),
- (~(uint64_t)(size-1) & addr_mask) | (1u << 11));
+ wrmsr(MSR_MTRRphysMask(i), (~(size - 1) & addr_mask) | (1u << 11));
+
+ base += size;
+ }
+
+ for ( base = pci_hi_mem_start;
+ (base != pci_hi_mem_end) && (i < nr_var_ranges); i++ )
+ {
+ size = PAGE_SIZE;
+ while ( !(base & size) )
+ size <<= 1;
+ while ( (base + size < base) || (base + size > pci_hi_mem_end) )
+ size >>= 1;
+
+ wrmsr(MSR_MTRRphysBase(i), base);
+ wrmsr(MSR_MTRRphysMask(i), (~(size - 1) & addr_mask) | (1u << 11));
base += size;
}
diff --git a/tools/firmware/hvmloader/config.h b/tools/firmware/hvmloader/config.h
index 6641197..b838cf9 100644
--- a/tools/firmware/hvmloader/config.h
+++ b/tools/firmware/hvmloader/config.h
@@ -53,11 +53,10 @@ extern struct bios_config ovmf_config;
#define PCI_ISA_IRQ_MASK 0x0c20U /* ISA IRQs 5,10,11 are PCI connected */
/* MMIO hole: Hardcoded defaults, which can be dynamically expanded. */
-#define PCI_MEM_START 0xf0000000
#define PCI_MEM_END 0xfc000000
extern unsigned long pci_mem_start, pci_mem_end;
-
+extern uint64_t pci_hi_mem_start, pci_hi_mem_end;
/* Memory map. */
#define SCRATCH_PHYSICAL_ADDRESS 0x00010000
diff --git a/tools/firmware/hvmloader/hvm_param.c b/tools/firmware/hvmloader/hvm_param.c
new file mode 100644
index 0000000..f7d8720
--- /dev/null
+++ b/tools/firmware/hvmloader/hvm_param.c
@@ -0,0 +1,36 @@
+/*
+ * hvm_param.c: get/set HVM params.
+ *
+ * Copyright (C) 2014 Citrix Systems R&D Ltd.
+ */
+#include "util.h"
+#include "config.h"
+#include "hypercall.h"
+
+#include <xen/hvm/params.h>
+
+int hvm_param_get(uint32_t index, uint64_t *value)
+{
+ struct xen_hvm_param p;
+ int ret;
+
+ p.domid = DOMID_SELF;
+ p.index = index;
+
+ ret = hypercall_hvm_op(HVMOP_get_param, &p);
+ if (ret == 0)
+ *value = p.value;
+
+ return ret;
+}
+
+int hvm_param_set(uint32_t index, uint64_t value)
+{
+ struct xen_hvm_param p;
+
+ p.domid = DOMID_SELF;
+ p.index = index;
+ p.value = value;
+
+ return hypercall_hvm_op(HVMOP_set_param, &p);
+}
diff --git a/tools/firmware/hvmloader/hvmloader.c b/tools/firmware/hvmloader/hvmloader.c
index 1cc8cf2..7b0da38 100644
--- a/tools/firmware/hvmloader/hvmloader.c
+++ b/tools/firmware/hvmloader/hvmloader.c
@@ -176,14 +176,10 @@ static void cmos_write_memory_size(void)
static void init_vm86_tss(void)
{
void *tss;
- struct xen_hvm_param p;
tss = mem_alloc(128, 128);
memset(tss, 0, 128);
- p.domid = DOMID_SELF;
- p.index = HVM_PARAM_VM86_TSS;
- p.value = virt_to_phys(tss);
- hypercall_hvm_op(HVMOP_set_param, &p);
+ hvm_param_set(HVM_PARAM_VM86_TSS, virt_to_phys(tss));
printf("vm86 TSS at %08lx\n", virt_to_phys(tss));
}
@@ -314,12 +310,6 @@ int main(void)
if ( acpi_enabled )
{
- struct xen_hvm_param p = {
- .domid = DOMID_SELF,
- .index = HVM_PARAM_ACPI_IOPORTS_LOCATION,
- .value = 1,
- };
-
if ( bios->acpi_build_tables )
{
printf("Loading ACPI ...\n");
@@ -328,7 +318,7 @@ int main(void)
acpi_enable_sci();
- hypercall_hvm_op(HVMOP_set_param, &p);
+ hvm_param_set(HVM_PARAM_ACPI_IOPORTS_LOCATION, 1);
}
init_vm86_tss();
diff --git a/tools/firmware/hvmloader/pci.c b/tools/firmware/hvmloader/pci.c
index 627e8cb..4e8d803 100644
--- a/tools/firmware/hvmloader/pci.c
+++ b/tools/firmware/hvmloader/pci.c
@@ -28,10 +28,12 @@
#include <xen/memory.h>
#include <xen/hvm/ioreq.h>
#include <xen/hvm/hvm_xs_strings.h>
+#include <xen/hvm/e820.h>
#include <stdbool.h>
-unsigned long pci_mem_start = PCI_MEM_START;
+unsigned long pci_mem_start = HVM_BELOW_4G_MMIO_START;
unsigned long pci_mem_end = PCI_MEM_END;
+uint64_t pci_hi_mem_start = 0, pci_hi_mem_end = 0;
enum virtual_vga virtual_vga = VGA_none;
unsigned long igd_opregion_pgbase = 0;
@@ -58,6 +60,7 @@ void pci_setup(void)
uint64_t bar_sz;
} *bars = (struct bars *)scratch_start;
unsigned int i, nr_bars = 0;
+ uint64_t mmio_hole_size = 0;
const char *s;
/*
@@ -85,6 +88,10 @@ void pci_setup(void)
printf("Relocating guest memory for lowmem MMIO space %s\n",
allow_memory_relocate?"enabled":"disabled");
+ s = xenstore_read("platform/mmio_hole_size", NULL);
+ if ( s )
+ mmio_hole_size = strtoll(s, NULL, 0);
+
/* Program PCI-ISA bridge with appropriate link routes. */
isa_irq = 0;
for ( link = 0; link < 4; link++ )
@@ -236,26 +243,49 @@ void pci_setup(void)
pci_writew(devfn, PCI_COMMAND, cmd);
}
- /*
- * At the moment qemu-xen can't deal with relocated memory regions.
- * It's too close to the release to make a proper fix; for now,
- * only allow the MMIO hole to grow large enough to move guest memory
- * if we're running qemu-traditional. Items that don't fit will be
- * relocated into the 64-bit address space.
- *
- * This loop now does the following:
- * - If allow_memory_relocate, increase the MMIO hole until it's
- * big enough, or until it's 2GiB
- * - If !allow_memory_relocate, increase the MMIO hole until it's
- * big enough, or until it's 2GiB, or until it overlaps guest
- * memory
- */
- while ( (mmio_total > (pci_mem_end - pci_mem_start))
- && ((pci_mem_start << 1) != 0)
- && (allow_memory_relocate
- || (((pci_mem_start << 1) >> PAGE_SHIFT)
- >= hvm_info->low_mem_pgend)) )
- pci_mem_start <<= 1;
+ if ( mmio_hole_size )
+ {
+ uint64_t max_ram_below_4g = (1ULL << 32) - mmio_hole_size;
+
+ if ( max_ram_below_4g > HVM_BELOW_4G_MMIO_START )
+ {
+ printf("max_ram_below_4g=0x"PRIllx
+ " too big for mmio_hole_size=0x"PRIllx
+ " has been ignored.\n",
+ PRIllx_arg(max_ram_below_4g),
+ PRIllx_arg(mmio_hole_size));
+ }
+ else
+ {
+ pci_mem_start = max_ram_below_4g;
+ printf("pci_mem_start=0x%lx (was 0x%x) for mmio_hole_size=%lu\n",
+ pci_mem_start, HVM_BELOW_4G_MMIO_START,
+ (long)mmio_hole_size);
+ }
+ }
+ else
+ {
+ /*
+ * At the moment qemu-xen can't deal with relocated memory regions.
+ * It's too close to the release to make a proper fix; for now,
+ * only allow the MMIO hole to grow large enough to move guest memory
+ * if we're running qemu-traditional. Items that don't fit will be
+ * relocated into the 64-bit address space.
+ *
+ * This loop now does the following:
+ * - If allow_memory_relocate, increase the MMIO hole until it's
+ * big enough, or until it's 2GiB
+ * - If !allow_memory_relocate, increase the MMIO hole until it's
+ * big enough, or until it's 2GiB, or until it overlaps guest
+ * memory
+ */
+ while ( (mmio_total > (pci_mem_end - pci_mem_start))
+ && ((pci_mem_start << 1) != 0)
+ && (allow_memory_relocate
+ || (((pci_mem_start << 1) >> PAGE_SHIFT)
+ >= hvm_info->low_mem_pgend)) )
+ pci_mem_start <<= 1;
+ }
if ( mmio_total > (pci_mem_end - pci_mem_start) )
{
@@ -345,9 +375,8 @@ void pci_setup(void)
if ( high_mem_resource.base & (bar_sz - 1) )
high_mem_resource.base = high_mem_resource.base -
(high_mem_resource.base & (bar_sz - 1)) + bar_sz;
- else
- high_mem_resource.base = high_mem_resource.base -
- (high_mem_resource.base & (bar_sz - 1));
+ if ( !pci_hi_mem_start )
+ pci_hi_mem_start = high_mem_resource.base;
resource = &high_mem_resource;
bar_data &= ~PCI_BASE_ADDRESS_MEM_MASK;
}
@@ -398,6 +427,16 @@ void pci_setup(void)
pci_writew(devfn, PCI_COMMAND, cmd);
}
+ if ( pci_hi_mem_start )
+ {
+ /*
+ * Make end address alignment match the start address one's so that
+ * fewer variable range MTRRs are needed to cover the range.
+ */
+ pci_hi_mem_end = ((high_mem_resource.base - 1) |
+ ((pci_hi_mem_start & -pci_hi_mem_start) - 1)) + 1;
+ }
+
if ( vga_devfn != 256 )
{
/*
diff --git a/tools/firmware/hvmloader/util.h b/tools/firmware/hvmloader/util.h
index 9ccb905..a70e4aa 100644
--- a/tools/firmware/hvmloader/util.h
+++ b/tools/firmware/hvmloader/util.h
@@ -3,6 +3,7 @@
#include <stdarg.h>
#include <stdint.h>
+#include <stddef.h>
#include <xen/xen.h>
#include <xen/hvm/hvm_info_table.h>
@@ -174,7 +175,6 @@ int printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
int vprintf(const char *fmt, va_list ap);
/* Buffer output */
-typedef unsigned long size_t;
int snprintf(char *buf, size_t size, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
/* Populate specified memory hole with RAM. */
@@ -210,6 +210,15 @@ const char *xenstore_read(const char *path, const char *default_resp);
*/
int xenstore_write(const char *path, const char *value);
+
+/* Get a HVM param.
+ */
+int hvm_param_get(uint32_t index, uint64_t *value);
+
+/* Set a HVM param.
+ */
+int hvm_param_set(uint32_t index, uint64_t value);
+
/* Setup PCI bus */
void pci_setup(void);
diff --git a/tools/firmware/hvmloader/xenbus.c b/tools/firmware/hvmloader/xenbus.c
index fe72e97..f900a1e 100644
--- a/tools/firmware/hvmloader/xenbus.c
+++ b/tools/firmware/hvmloader/xenbus.c
@@ -37,25 +37,34 @@ static struct xenstore_domain_interface *rings; /* Shared ring with dom0 */
static evtchn_port_t event; /* Event-channel to dom0 */
static char payload[XENSTORE_PAYLOAD_MAX + 1]; /* Unmarshalling area */
+static void ring_wait(void)
+{
+ struct shared_info *shinfo = get_shared_info();
+ struct sched_poll poll;
+
+ memset(&poll, 0, sizeof(poll));
+ set_xen_guest_handle(poll.ports, &event);
+ poll.nr_ports = 1;
+
+ while ( !test_and_clear_bit(event, shinfo->evtchn_pending) )
+ hypercall_sched_op(SCHEDOP_poll, &poll);
+}
+
/* Connect our xenbus client to the backend.
* Call once, before any other xenbus actions. */
void xenbus_setup(void)
{
- xen_hvm_param_t param;
+ uint64_t val;
/* Ask Xen where the xenbus shared page is. */
- param.domid = DOMID_SELF;
- param.index = HVM_PARAM_STORE_PFN;
- if ( hypercall_hvm_op(HVMOP_get_param, ¶m) )
+ if ( hvm_param_get(HVM_PARAM_STORE_PFN, &val) )
BUG();
- rings = (void *) (unsigned long) (param.value << PAGE_SHIFT);
+ rings = (void *) (unsigned long) (val << PAGE_SHIFT);
/* Ask Xen where the xenbus event channel is. */
- param.domid = DOMID_SELF;
- param.index = HVM_PARAM_STORE_EVTCHN;
- if ( hypercall_hvm_op(HVMOP_get_param, ¶m) )
+ if ( hvm_param_get(HVM_PARAM_STORE_EVTCHN, &val) )
BUG();
- event = param.value;
+ event = val;
printf("Xenbus rings @0x%lx, event channel %lu\n",
(unsigned long) rings, (unsigned long) event);
@@ -65,14 +74,26 @@ void xenbus_setup(void)
void xenbus_shutdown(void)
{
struct shared_info *shinfo = get_shared_info();
+ evtchn_send_t send;
ASSERT(rings != NULL);
- /* We zero out the whole ring -- the backend can handle this, and it's
- * not going to surprise any frontends since it's equivalent to never
- * having used the rings. */
- memset(rings, 0, sizeof *rings);
-
+ if (rings->server_features & XENSTORE_SERVER_FEATURE_RECONNECTION) {
+ rings->connection = XENSTORE_RECONNECT;
+ send.port = event;
+ hypercall_event_channel_op(EVTCHNOP_send, &send);
+ while (*(volatile uint32_t*)&rings->connection == XENSTORE_RECONNECT)
+ ring_wait ();
+ } else {
+ /* If the backend reads the state while we're erasing it then the
+ * ring state will become corrupted, preventing guest frontends from
+ * connecting. This is rare. To help diagnose the failure, we fill
+ * the ring with XS_INVALID packets. */
+ memset(rings->req, 0xff, XENSTORE_RING_SIZE);
+ memset(rings->rsp, 0xff, XENSTORE_RING_SIZE);
+ rings->req_cons = rings->req_prod = 0;
+ rings->rsp_cons = rings->rsp_prod = 0;
+ }
/* Clear the event-channel state too. */
memset(shinfo->vcpu_info, 0, sizeof(shinfo->vcpu_info));
memset(shinfo->evtchn_pending, 0, sizeof(shinfo->evtchn_pending));
@@ -81,19 +102,6 @@ void xenbus_shutdown(void)
rings = NULL;
}
-static void ring_wait(void)
-{
- struct shared_info *shinfo = get_shared_info();
- struct sched_poll poll;
-
- memset(&poll, 0, sizeof(poll));
- set_xen_guest_handle(poll.ports, &event);
- poll.nr_ports = 1;
-
- while ( !test_and_clear_bit(event, shinfo->evtchn_pending) )
- hypercall_sched_op(SCHEDOP_poll, &poll);
-}
-
/* Helper functions: copy data in and out of the ring */
static void ring_write(const char *data, uint32_t len)
{
diff --git a/tools/firmware/seabios-config b/tools/firmware/seabios-config
deleted file mode 100644
index a497162..0000000
--- a/tools/firmware/seabios-config
+++ /dev/null
@@ -1,97 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# SeaBIOS Configuration
-# Mon Sep 23 12:59:01 2013
-#
-
-#
-# General Features
-#
-# CONFIG_COREBOOT is not set
-CONFIG_QEMU=y
-# CONFIG_CSM is not set
-CONFIG_QEMU_HARDWARE=y
-CONFIG_XEN=y
-CONFIG_THREADS=y
-# CONFIG_THREAD_OPTIONROMS is not set
-CONFIG_RELOCATE_INIT=y
-CONFIG_BOOTMENU=y
-# CONFIG_BOOTSPLASH is not set
-CONFIG_BOOTORDER=y
-CONFIG_ENTRY_EXTRASTACK=y
-
-#
-# Hardware support
-#
-CONFIG_ATA=y
-CONFIG_ATA_DMA=y
-CONFIG_ATA_PIO32=y
-CONFIG_AHCI=y
-CONFIG_VIRTIO_BLK=y
-CONFIG_VIRTIO_SCSI=y
-CONFIG_ESP_SCSI=y
-CONFIG_LSI_SCSI=y
-CONFIG_MEGASAS=y
-CONFIG_FLOPPY=y
-CONFIG_PS2PORT=y
-CONFIG_USB=y
-CONFIG_USB_UHCI=y
-CONFIG_USB_OHCI=y
-CONFIG_USB_EHCI=y
-CONFIG_USB_MSC=y
-CONFIG_USB_UAS=y
-CONFIG_USB_HUB=y
-CONFIG_USB_KEYBOARD=y
-CONFIG_USB_MOUSE=y
-CONFIG_SERIAL=y
-CONFIG_LPT=y
-CONFIG_USE_SMM=y
-CONFIG_MTRR_INIT=y
-CONFIG_PMTIMER=y
-
-#
-# BIOS interfaces
-#
-CONFIG_DRIVES=y
-CONFIG_CDROM_BOOT=y
-CONFIG_CDROM_EMU=y
-CONFIG_PCIBIOS=y
-CONFIG_APMBIOS=y
-CONFIG_PNPBIOS=y
-CONFIG_OPTIONROMS=y
-# CONFIG_OPTIONROMS_DEPLOYED is not set
-CONFIG_PMM=y
-CONFIG_BOOT=y
-CONFIG_KEYBOARD=y
-CONFIG_KBD_CALL_INT15_4F=y
-CONFIG_MOUSE=y
-CONFIG_S3_RESUME=y
-CONFIG_VGAHOOKS=y
-# CONFIG_DISABLE_A20 is not set
-
-#
-# BIOS Tables
-#
-CONFIG_PIRTABLE=y
-CONFIG_MPTABLE=y
-CONFIG_SMBIOS=y
-CONFIG_ACPI=y
-CONFIG_ACPI_DSDT=y
-
-#
-# VGA ROM
-#
-CONFIG_NO_VGABIOS=y
-# CONFIG_VGA_STANDARD_VGA is not set
-# CONFIG_VGA_CIRRUS is not set
-# CONFIG_VGA_BOCHS is not set
-# CONFIG_VGA_GEODEGX2 is not set
-# CONFIG_VGA_GEODELX is not set
-# CONFIG_BUILD_VGABIOS is not set
-
-#
-# Debugging
-#
-CONFIG_DEBUG_LEVEL=1
-# CONFIG_DEBUG_SERIAL is not set
-CONFIG_DEBUG_IO=y
diff --git a/tools/flask/policy/Makefile b/tools/flask/policy/Makefile
index a1c0f11..5d8cfbf 100644
--- a/tools/flask/policy/Makefile
+++ b/tools/flask/policy/Makefile
@@ -32,7 +32,7 @@ M4 ?= m4
# include the Xen policy type (needed for static device policy).
OUTPUT_POLICY = 24
-POLICY_FILENAME = xenpolicy.$(OUTPUT_POLICY)
+POLICY_FILENAME = xenpolicy-$(shell $(MAKE) -C $(XEN_ROOT)/xen xenversion --no-print-directory)
POLICY_LOADPATH = /boot
# policy source layout
diff --git a/tools/flask/policy/policy/modules/xen/xen.if b/tools/flask/policy/policy/modules/xen/xen.if
index dedc035..fa69c9d 100644
--- a/tools/flask/policy/policy/modules/xen/xen.if
+++ b/tools/flask/policy/policy/modules/xen/xen.if
@@ -49,7 +49,7 @@ define(`create_domain_common', `
getdomaininfo hypercall setvcpucontext setextvcpucontext
getscheduler getvcpuinfo getvcpuextstate getaddrsize
getaffinity setaffinity };
- allow $1 $2:domain2 { set_cpuid settsc setscheduler setclaim set_max_evtchn };
+ allow $1 $2:domain2 { set_cpuid settsc setscheduler setclaim set_max_evtchn set_vnumainfo get_vnumainfo psr_cmt_op configure_domain };
allow $1 $2:security check_context;
allow $1 $2:shadow enable;
allow $1 $2:mmu { map_read map_write adjust memorymap physmap pinpage mmuext_op };
@@ -81,6 +81,7 @@ define(`manage_domain', `
allow $1 $2:domain { getdomaininfo getvcpuinfo getaffinity
getaddrsize pause unpause trigger shutdown destroy
setaffinity setdomainmaxmem getscheduler };
+ allow $1 $2:domain2 set_vnumainfo;
')
# migrate_domain_out(priv, target)
diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te
index bb59fe8..d214470 100644
--- a/tools/flask/policy/policy/modules/xen/xen.te
+++ b/tools/flask/policy/policy/modules/xen/xen.te
@@ -64,6 +64,10 @@ allow dom0_t xen_t:xen {
getidle debug getcpuinfo heap pm_op mca_op lockprof cpupool_op tmem_op
tmem_control getscheduler setscheduler
};
+allow dom0_t xen_t:xen2 {
+ resource_op
+ psr_cmt_op
+};
allow dom0_t xen_t:mmu memorymap;
# Allow dom0 to use these domctls on itself. For domctls acting on other
@@ -76,7 +80,7 @@ allow dom0_t dom0_t:domain {
getpodtarget setpodtarget set_misc_info set_virq_handler
};
allow dom0_t dom0_t:domain2 {
- set_cpuid gettsc settsc setscheduler set_max_evtchn
+ set_cpuid gettsc settsc setscheduler set_max_evtchn set_vnumainfo get_vnumainfo psr_cmt_op
};
allow dom0_t dom0_t:resource { add remove };
diff --git a/tools/flask/utils/Makefile b/tools/flask/utils/Makefile
index 458f9aa..c87f15c 100644
--- a/tools/flask/utils/Makefile
+++ b/tools/flask/utils/Makefile
@@ -1,7 +1,7 @@
XEN_ROOT=$(CURDIR)/../../..
include $(XEN_ROOT)/tools/Rules.mk
-CFLAGS += -Wall -g -Werror
+CFLAGS += -Werror
CFLAGS += $(CFLAGS_libxenctrl)
TESTDIR = testsuite/tmp
diff --git a/tools/flask/utils/loadpolicy.c b/tools/flask/utils/loadpolicy.c
index 2edcf97..47b5139 100644
--- a/tools/flask/utils/loadpolicy.c
+++ b/tools/flask/utils/loadpolicy.c
@@ -61,7 +61,7 @@ int main (int argCnt, const char *args[])
#ifdef USE_MMAP
polMem = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, polFd, 0);
- if ( !polMem )
+ if ( polMem == MAP_FAILED )
{
fprintf(stderr, "Error occurred mapping policy file in memory: %s\n",
strerror(errno));
diff --git a/tools/hotplug/FreeBSD/Makefile b/tools/hotplug/FreeBSD/Makefile
new file mode 100644
index 0000000..6aba64a
--- /dev/null
+++ b/tools/hotplug/FreeBSD/Makefile
@@ -0,0 +1,42 @@
+XEN_ROOT = $(CURDIR)/../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+# Xen script dir and scripts to go there.
+XEN_SCRIPTS = vif-bridge
+
+XEN_SCRIPT_DATA =
+
+XEN_RCD_PROG = rc.d/xencommons
+
+.PHONY: all
+all:
+
+.PHONY: build
+build:
+
+.PHONY: install
+install: install-scripts install-rcd
+
+.PHONY: install-scripts
+install-scripts:
+ $(INSTALL_DIR) $(DESTDIR)$(XEN_SCRIPT_DIR)
+ set -e; for i in $(XEN_SCRIPTS); \
+ do \
+ $(INSTALL_PROG) $$i $(DESTDIR)$(XEN_SCRIPT_DIR); \
+ done
+ set -e; for i in $(XEN_SCRIPT_DATA); \
+ do \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(XEN_SCRIPT_DIR); \
+ done
+
+.PHONY: install-rcd
+install-rcd:
+ $(INSTALL_DIR) $(DESTDIR)$(INITD_DIR)
+ set -e; for i in $(XEN_RCD_PROG); \
+ do \
+ $(INSTALL_PROG) $$i $(DESTDIR)$(INITD_DIR); \
+ done
+ $(INSTALL_DATA) ../common/hotplugpath.sh $(DESTDIR)$(XEN_SCRIPT_DIR)
+
+.PHONY: clean
+clean:
diff --git a/tools/hotplug/FreeBSD/rc.d/xencommons.in b/tools/hotplug/FreeBSD/rc.d/xencommons.in
new file mode 100644
index 0000000..900990b
--- /dev/null
+++ b/tools/hotplug/FreeBSD/rc.d/xencommons.in
@@ -0,0 +1,120 @@
+#!/bin/sh
+#
+# PROVIDE: xencommons
+# REQUIRE: DAEMON
+
+. /etc/rc.subr
+
+. @XEN_SCRIPT_DIR@/hotplugpath.sh
+
+LD_LIBRARY_PATH="${LIBDIR}"
+export LD_LIBRARY_PATH
+
+name="xencommons"
+start_precmd="xen_precmd"
+start_cmd="xen_startcmd"
+stop_cmd="xen_stop"
+status_cmd="xen_status"
+extra_commands="status"
+required_files="/dev/xen/privcmd"
+
+XENSTORED_PIDFILE="/var/run/xenstored.pid"
+XENCONSOLED_PIDFILE="/var/run/xenconsoled.pid"
+#XENCONSOLED_TRACE="/var/log/xen/xenconsole-trace.log"
+#XENSTORED_TRACE="/var/log/xen/xenstore-trace.log"
+
+xen_precmd()
+{
+ mkdir -p /var/run/xenstored || exit 1
+}
+
+xen_startcmd()
+{
+ local time=0
+ local timeout=30
+
+ xenstored_pid=$(check_pidfile ${XENSTORED_PIDFILE} ${SBINDIR}/xenstored)
+ if test -z "$xenstored_pid"; then
+ printf "Cleaning xenstore database.\n"
+ if [ -z "${XENSTORED_ROOTDIR}" ]; then
+ XENSTORED_ROOTDIR="@XEN_LIB_STORED@"
+ fi
+ rm -f ${XENSTORED_ROOTDIR}/tdb* >/dev/null 2>&1
+ printf "Starting xenservices: xenstored, xenconsoled."
+ XENSTORED_ARGS=" --pid-file ${XENSTORED_PIDFILE}"
+ if [ -n "${XENSTORED_TRACE}" ]; then
+ XENSTORED_ARGS="${XENSTORED_ARGS} -T /var/log/xen/xenstored-trace.log"
+ fi
+ ${SBINDIR}/xenstored ${XENSTORED_ARGS}
+ while [ $time -lt $timeout ] && ! `${BINDIR}/xenstore-read -s / >/dev/null 2>&1` ; do
+ printf "."
+ time=$(($time+1))
+ sleep 1
+ done
+ else
+ printf "Starting xenservices: xenconsoled."
+ fi
+
+ XENCONSOLED_ARGS=""
+ if [ -n "${XENCONSOLED_TRACE}" ]; then
+ XENCONSOLED_ARGS="${XENCONSOLED_ARGS} --log=${XENCONSOLED_TRACE}"
+ fi
+
+ ${SBINDIR}/xenconsoled ${XENCONSOLED_ARGS}
+
+ printf "\n"
+
+ printf "Setting domain 0 name, domid and JSON config...\n"
+ ${LIBEXEC_BIN}/xen-init-dom0
+}
+
+xen_stop()
+{
+ pids=""
+ printf "Stopping xencommons.\n"
+ printf "WARNING: Not stopping xenstored, as it cannot be restarted.\n"
+
+ rc_pid=$(check_pidfile ${XENCONSOLED_PIDFILE} ${SBINDIR}/xenconsoled)
+ pids="$pids $rc_pid"
+
+ kill -${sig_stop:-TERM} $pids
+ wait_for_pids $pids
+}
+
+xen_status()
+{
+ xenstored_pid=$(check_pidfile ${XENSTORED_PIDFILE} ${SBINDIR}/xenstored)
+ if test -n ${xenstored_pid}; then
+ pids="$pids $xenstored_pid"
+ fi
+
+ xenconsoled_pid=$(check_pidfile ${XENCONSOLED_PIDFILE} ${SBINDIR}/xenconsoled)
+ if test -n ${xenconsoled_pid}; then
+ pids="$pids $xenconsoled_pid"
+ fi
+
+ if test -n "$xenconsoled_pid" -a -n "$xenstored_pid";
+ then
+ echo "xencommons are running as pids $pids."
+ return 0
+ fi
+ if test -z "$xenconsoled_pid" -a -z "$xenstored_pid";
+ then
+ echo "xencommons are not running."
+ return 0
+ fi
+
+ if test -n $xenstored_pid; then
+ echo "xenstored is running as pid $xenstored_pid."
+ else
+ echo "xenstored is not running."
+ fi
+ if test -n $xenconsoled_pid; then
+ echo "xenconsoled is running as pid $xenconsoled_pid."
+ else
+ echo "xenconsoled is not running."
+ fi
+}
+
+load_rc_config $name
+run_rc_command "$1"
diff --git a/tools/hotplug/FreeBSD/vif-bridge b/tools/hotplug/FreeBSD/vif-bridge
new file mode 100644
index 0000000..d350df4
--- /dev/null
+++ b/tools/hotplug/FreeBSD/vif-bridge
@@ -0,0 +1,41 @@
+#!/bin/sh -e
+#
+# FreeBSD hotplug script for attaching xnb* interfaces to bridges
+#
+# Parameters:
+# $1: xenstore backend path of the vif
+# $2: action, either "add" or "remove"
+#
+# Environment variables:
+# $iface_dev: name of the backend device (xnb<domid>.<handle>)
+#
+
+DIR=$(dirname "$0")
+. "${DIR}/hotplugpath.sh"
+
+PATH=${BINDIR}:${SBINDIR}:${LIBEXEC_BIN}:/bin:/usr/bin:/sbin:/usr/sbin
+export PATH
+
+path=$1
+action=$2
+
+case $action in
+add)
+ bridge=$(xenstore-read "$path/bridge")
+ ifconfig $bridge addm $iface_dev
+ ifconfig $iface_dev up
+ exit 0
+ ;;
+remove)
+ if [ "$emulated" -eq 1 ]; then
+ bridge=$(xenstore-read "$path/bridge")
+ ifconfig $iface_dev down
+ ifconfig $bridge deletem $iface_dev
+ ifconfig $iface_dev destroy
+ fi
+ exit 0
+ ;;
+*)
+ exit 0
+ ;;
+esac
diff --git a/tools/hotplug/Linux/Makefile b/tools/hotplug/Linux/Makefile
index 47655f6..1706c05 100644
--- a/tools/hotplug/Linux/Makefile
+++ b/tools/hotplug/Linux/Makefile
@@ -2,20 +2,21 @@ XEN_ROOT = $(CURDIR)/../../..
include $(XEN_ROOT)/tools/Rules.mk
# Init scripts.
-XEND_INITD = init.d/xend
XENDOMAINS_INITD = init.d/xendomains
+XENDOMAINS_LIBEXEC = xendomains
XENDOMAINS_SYSCONFIG = init.d/sysconfig.xendomains
XENCOMMONS_INITD = init.d/xencommons
XENCOMMONS_SYSCONFIG = init.d/sysconfig.xencommons
# Xen script dir and scripts to go there.
-XEN_SCRIPTS = network-bridge vif-bridge
-XEN_SCRIPTS += network-route vif-route
-XEN_SCRIPTS += network-nat vif-nat
+XEN_SCRIPTS = vif-bridge
+XEN_SCRIPTS += vif-route
+XEN_SCRIPTS += vif-nat
XEN_SCRIPTS += vif-openvswitch
XEN_SCRIPTS += vif2
XEN_SCRIPTS += vif-setup
+XEN_SCRIPTS-$(CONFIG_REMUS_NETBUF) += remus-netbuf-setup
XEN_SCRIPTS += block
XEN_SCRIPTS += block-enbd block-nbd
XEN_SCRIPTS-$(CONFIG_BLKTAP1) += blktap
@@ -23,33 +24,34 @@ XEN_SCRIPTS += xen-hotplug-cleanup
XEN_SCRIPTS += external-device-migrate
XEN_SCRIPTS += vscsi
XEN_SCRIPTS += block-iscsi
+XEN_SCRIPTS += block-drbd-probe
XEN_SCRIPTS += $(XEN_SCRIPTS-y)
+SUBDIRS-$(CONFIG_SYSTEMD) += systemd
+
XEN_SCRIPT_DATA = xen-script-common.sh locking.sh logging.sh
XEN_SCRIPT_DATA += xen-hotplug-common.sh xen-network-common.sh vif-common.sh
XEN_SCRIPT_DATA += block-common.sh
UDEV_RULES_DIR = $(CONFIG_DIR)/udev
-UDEV_RULES-$(CONFIG_XEND) = xend.rules
UDEV_RULES = xen-backend.rules $(UDEV_RULES-y)
.PHONY: all
-all:
+all: subdirs-all
.PHONY: build
build:
.PHONY: install
-install: all install-initd install-scripts install-udev
+install: install-initd install-scripts install-udev subdirs-install
# See docs/misc/distro_mapping.txt for INITD_DIR location
.PHONY: install-initd
install-initd:
[ -d $(DESTDIR)$(INITD_DIR) ] || $(INSTALL_DIR) $(DESTDIR)$(INITD_DIR)
[ -d $(DESTDIR)$(SYSCONFIG_DIR) ] || $(INSTALL_DIR) $(DESTDIR)$(SYSCONFIG_DIR)
-ifeq ($(CONFIG_XEND),y)
- $(INSTALL_PROG) $(XEND_INITD) $(DESTDIR)$(INITD_DIR)
-endif
+ [ -d $(DESTDIR)$(LIBEXEC_BIN) ] || $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN)
+ $(INSTALL_PROG) $(XENDOMAINS_LIBEXEC) $(DESTDIR)$(LIBEXEC_BIN)
$(INSTALL_PROG) $(XENDOMAINS_INITD) $(DESTDIR)$(INITD_DIR)
$(INSTALL_DATA) $(XENDOMAINS_SYSCONFIG) $(DESTDIR)$(SYSCONFIG_DIR)/xendomains
$(INSTALL_PROG) $(XENCOMMONS_INITD) $(DESTDIR)$(INITD_DIR)
@@ -79,4 +81,4 @@ install-udev:
done
.PHONY: clean
-clean:
+clean: subdirs-clean
diff --git a/tools/hotplug/Linux/block-drbd-probe b/tools/hotplug/Linux/block-drbd-probe
new file mode 100755
index 0000000..247a9d0
--- /dev/null
+++ b/tools/hotplug/Linux/block-drbd-probe
@@ -0,0 +1,87 @@
+#! /bin/bash
+#
+# Copyright (C) 2014 FUJITSU LIMITED
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Usage:
+# block-drbd-probe devicename
+#
+# Return value:
+# 0: the device is drbd device
+# 1: the device is not drbd device
+# 2: unkown error
+# 3: the drbd device does not use protocol D
+# 4: the drbd device is not ready
+
+set -e
+
+drbd_res=
+
+function get_res_name()
+{
+ local drbd_dev=$1
+ local drbd_dev_list=($(drbdadm sh-dev all))
+ local drbd_res_list=($(drbdadm sh-resource all))
+ local temp_drbd_dev temp_drbd_res
+ local found=0
+
+ for temp_drbd_dev in ${drbd_dev_list[@]}; do
+ if [[ "$temp_drbd_dev" == "$drbd_dev" ]]; then
+ found=1
+ break
+ fi
+ done
+
+ if [[ $found -eq 0 ]]; then
+ return 1
+ fi
+
+ for temp_drbd_res in ${drbd_res_list[@]}; do
+ temp_drbd_dev=$(drbdadm sh-dev $temp_drbd_res)
+ if [[ "$temp_drbd_dev" == "$drbd_dev" ]]; then
+ drbd_res="$temp_drbd_res"
+ return 0
+ fi
+ done
+
+ # OOPS
+ return 2
+}
+
+get_res_name $1
+rc=$?
+if [[ $rc -ne 0 ]]; then
+ exit $rc
+fi
+
+# check protocol
+drbdsetup $1 show | grep -q "protocol D;"
+if [[ $? -ne 0 ]]; then
+ exit 3
+fi
+
+# check connect status
+state=$(drbdadm cstate "$drbd_res")
+if [[ "$state" != "Connected" ]]; then
+ exit 4
+fi
+
+# check role
+role=$(drbdadm role "$drbd_res")
+if [[ "$role" != "Primary/Secondary" ]]; then
+ exit 4
+fi
+
+exit 0
diff --git a/tools/hotplug/Linux/init.d/sysconfig.xencommons b/tools/hotplug/Linux/init.d/sysconfig.xencommons
deleted file mode 100644
index 25f7f00..0000000
--- a/tools/hotplug/Linux/init.d/sysconfig.xencommons
+++ /dev/null
@@ -1,33 +0,0 @@
-## Path: System/Virtualization
-## Type: string
-## Default: "none"
-#
-# Log xenconsoled messages (cf xl dmesg)
-#XENCONSOLED_TRACE=[none|guest|hv|all]
-
-## Type: string
-## Default: xenstored
-#
-# Select xenstored implementation
-#XENSTORED=[oxenstored|xenstored]
-
-## Type: string
-## Default: Not defined, tracing off
-#
-# Log xenstored messages
-#XENSTORED_TRACE=[yes|on|1]
-
-## Type: string
-## Default: "/var/lib/xenstored"
-#
-# Running xenstored on XENSTORED_ROOTDIR
-#XENSTORED_ROOTDIR=/var/lib/xenstored
-
-## Type: string
-## Default: Not defined, xenbackendd debug mode off
-#
-# Running xenbackendd in debug mode
-#XENBACKENDD_DEBUG=[yes|on|1]
-
-# qemu path
-#QEMU_XEN=/usr/lib/xen/bin/qemu-system-i386
diff --git a/tools/hotplug/Linux/init.d/sysconfig.xencommons.in b/tools/hotplug/Linux/init.d/sysconfig.xencommons.in
new file mode 100644
index 0000000..c12fc8a
--- /dev/null
+++ b/tools/hotplug/Linux/init.d/sysconfig.xencommons.in
@@ -0,0 +1,42 @@
+## Path: System/Virtualization
+## Type: string
+## Default: "none"
+#
+# Log xenconsoled messages (cf xl dmesg)
+#XENCONSOLED_TRACE=[none|guest|hv|all]
+
+## Type: string
+## Default: xenstored
+#
+# Select xenstore implementation, this can be either
+# of these below. If using systemd it's preferred that you
+# just edit the xenstored.service unit file and change
+# the XENSTORED variable there.
+#
+# This can be either of:
+# * @sbindir@/oxenstored
+# * @sbindir@/xenstored
+#
+# Changing this requires a reboot to take effect.
+#XENSTORED=@XENSTORED@
+
+## Type: string
+## Default: Not defined, tracing off
+#
+# Log xenstored messages
+#XENSTORED_TRACE=[yes|on|1]
+
+## Type: string
+## Default: "@XEN_LIB_STORED@"
+#
+# Running xenstored on XENSTORED_ROOTDIR
+#XENSTORED_ROOTDIR=@XEN_LIB_STORED@
+
+## Type: string
+## Default: Not defined, xenbackendd debug mode off
+#
+# Running xenbackendd in debug mode
+#XENBACKENDD_DEBUG=[yes|on|1]
+
+# qemu path
+#QEMU_XEN=@LIBEXEC_BIN@/qemu-system-i386
diff --git a/tools/hotplug/Linux/init.d/xen-watchdog b/tools/hotplug/Linux/init.d/xen-watchdog
deleted file mode 100644
index 3592fda..0000000
--- a/tools/hotplug/Linux/init.d/xen-watchdog
+++ /dev/null
@@ -1,90 +0,0 @@
-#! /bin/bash
-#
-# xen-watchdog
-#
-# chkconfig: 2345 21 79
-# description: Run domain watchdog daemon
-### BEGIN INIT INFO
-# Provides: xen-watchdog
-# Required-Start: $syslog $remote_fs
-# Should-Start: xend
-# Required-Stop: $syslog $remote_fs
-# Should-Stop: xend
-# Default-Start: 2 3 5
-# Default-Stop: 0 1 6
-# Short-Description: Start/stop xen-watchdog
-# Description: Run domain watchdog daemon.
-### END INIT INFO
-#
-
-. /etc/xen/scripts/hotplugpath.sh
-
-DAEMON=${SBINDIR}/xenwatchdogd
-base=$(basename $DAEMON)
-
-# Source function library.
-if [ -e /etc/init.d/functions ] ; then
- . /etc/init.d/functions
-elif [ -e /lib/lsb/init-functions ] ; then
- . /lib/lsb/init-functions
- success () {
- log_success_msg $*
- }
- failure () {
- log_failure_msg $*
- }
-else
- success () {
- echo $*
- }
- failure () {
- echo $*
- }
-fi
-
-start() {
- local r
- echo -n $"Starting domain watchdog daemon: "
-
- $DAEMON 30 15
- r=$?
- [ "$r" -eq 0 ] && success $"$base startup" || failure $"$base startup"
- echo
-
- return $r
-}
-
-stop() {
- local r
- echo -n $"Stopping domain watchdog daemon: "
-
- killall -USR1 $base 2>/dev/null
- r=$?
- [ "$r" -eq 0 ] && success $"$base stop" || failure $"$base stop"
- echo
-
- return $r
-}
-
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- restart)
- stop
- start
- ;;
- status)
- ;;
- condrestart)
- stop
- start
- ;;
- *)
- echo $"Usage: $0 {start|stop|status|restart|condrestart}"
- exit 1
-esac
-
diff --git a/tools/hotplug/Linux/init.d/xen-watchdog.in b/tools/hotplug/Linux/init.d/xen-watchdog.in
new file mode 100644
index 0000000..32c7268
--- /dev/null
+++ b/tools/hotplug/Linux/init.d/xen-watchdog.in
@@ -0,0 +1,90 @@
+#! /bin/bash
+#
+# xen-watchdog
+#
+# chkconfig: 2345 21 79
+# description: Run domain watchdog daemon
+### BEGIN INIT INFO
+# Provides: xen-watchdog
+# Required-Start: $syslog $remote_fs
+# Should-Start: xend
+# Required-Stop: $syslog $remote_fs
+# Should-Stop: xend
+# Default-Start: 2 3 5
+# Default-Stop: 0 1 6
+# Short-Description: Start/stop xen-watchdog
+# Description: Run domain watchdog daemon.
+### END INIT INFO
+#
+
+. @XEN_SCRIPT_DIR@/hotplugpath.sh
+
+DAEMON=${SBINDIR}/xenwatchdogd
+base=$(basename $DAEMON)
+
+# Source function library.
+if [ -e /etc/init.d/functions ] ; then
+ . /etc/init.d/functions
+elif [ -e /lib/lsb/init-functions ] ; then
+ . /lib/lsb/init-functions
+ success () {
+ log_success_msg $*
+ }
+ failure () {
+ log_failure_msg $*
+ }
+else
+ success () {
+ echo $*
+ }
+ failure () {
+ echo $*
+ }
+fi
+
+start() {
+ local r
+ echo -n $"Starting domain watchdog daemon: "
+
+ $DAEMON 30 15
+ r=$?
+ [ "$r" -eq 0 ] && success $"$base startup" || failure $"$base startup"
+ echo
+
+ return $r
+}
+
+stop() {
+ local r
+ echo -n $"Stopping domain watchdog daemon: "
+
+ killall -USR1 $base 2>/dev/null
+ r=$?
+ [ "$r" -eq 0 ] && success $"$base stop" || failure $"$base stop"
+ echo
+
+ return $r
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ restart)
+ stop
+ start
+ ;;
+ status)
+ ;;
+ condrestart)
+ stop
+ start
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart}"
+ exit 1
+esac
+
diff --git a/tools/hotplug/Linux/init.d/xencommons b/tools/hotplug/Linux/init.d/xencommons
deleted file mode 100644
index 4ebd636..0000000
--- a/tools/hotplug/Linux/init.d/xencommons
+++ /dev/null
@@ -1,167 +0,0 @@
-#!/bin/bash
-#
-# xencommons Script to start and stop xenstored and xenconsoled
-#
-# Author: Ian Jackson <ian.jackson at eu.citrix.com>
-#
-# chkconfig: 2345 70 10
-# description: Starts and stops xenstored and xenconsoled
-### BEGIN INIT INFO
-# Provides: xenstored xenconsoled
-# Required-Start: $syslog $remote_fs
-# Should-Start:
-# Required-Stop: $syslog $remote_fs
-# Should-Stop:
-# Default-Start: 2 3 5
-# Default-Stop: 0 1 6
-# Short-Description: Start/stop xenstored and xenconsoled
-# Description: Starts and stops the daemons neeeded for xl/xend
-### END INIT INFO
-
-. /etc/xen/scripts/hotplugpath.sh
-
-if [ -d /etc/sysconfig ]; then
- xencommons_config=/etc/sysconfig
-else
- xencommons_config=/etc/default
-fi
-
-test -f $xencommons_config/xencommons && . $xencommons_config/xencommons
-
-XENCONSOLED_PIDFILE=/var/run/xenconsoled.pid
-QEMU_PIDFILE=/var/run/qemu-dom0.pid
-shopt -s extglob
-
-# not running in Xen dom0 or domU
-if ! test -d /proc/xen ; then
- exit 0
-fi
-
-# mount xenfs in dom0 or domU with a pv_ops kernel
-if test "x$1" = xstart && \
- ! test -f /proc/xen/capabilities && \
- ! grep '^xenfs ' /proc/mounts >/dev/null;
-then
- mount -t xenfs xenfs /proc/xen
-fi
-
-# run this script only in dom0:
-# no capabilities file in xenlinux domU kernel
-# empty capabilities file in pv_ops domU kernel
-if test -f /proc/xen/capabilities && \
- ! grep -q "control_d" /proc/xen/capabilities ; then
- exit 0
-fi
-
-do_start () {
- local time=0
- local timeout=30
-
- modprobe xen-evtchn 2>/dev/null
- modprobe xen-gntdev 2>/dev/null
- modprobe xen-gntalloc 2>/dev/null
- modprobe xen-blkback 2>/dev/null
- modprobe xen-netback 2>/dev/null
- modprobe xen-pciback 2>/dev/null
- modprobe evtchn 2>/dev/null
- modprobe gntdev 2>/dev/null
- modprobe netbk 2>/dev/null
- modprobe blkbk 2>/dev/null
- modprobe xen-scsibk 2>/dev/null
- modprobe usbbk 2>/dev/null
- modprobe pciback 2>/dev/null
- modprobe xen-acpi-processor 2>/dev/null
- modprobe blktap2 2>/dev/null || modprobe blktap 2>/dev/null
- mkdir -p /var/run/xen
-
- if ! `${BINDIR}/xenstore-read -s / >/dev/null 2>&1`
- then
- test -z "$XENSTORED_ROOTDIR" && XENSTORED_ROOTDIR="/var/lib/xenstored"
- rm -f "$XENSTORED_ROOTDIR"/tdb* &>/dev/null
- test -z "$XENSTORED_TRACE" || XENSTORED_ARGS=" -T /var/log/xen/xenstored-trace.log"
-
- if [ -n "$XENSTORED" ] ; then
- echo -n Starting $XENSTORED...
- $XENSTORED --pid-file /var/run/xenstored.pid $XENSTORED_ARGS
- elif [ -x ${SBINDIR}/oxenstored ] ; then
- echo -n Starting oxenstored...
- ${SBINDIR}/oxenstored --pid-file /var/run/xenstored.pid $XENSTORED_ARGS
- elif [ -x ${SBINDIR}/xenstored ] ; then
- echo -n Starting C xenstored...
- ${SBINDIR}/xenstored --pid-file /var/run/xenstored.pid $XENSTORED_ARGS
- else
- echo "No xenstored found"
- exit 1
- fi
-
- # Wait for xenstored to actually come up, timing out after 30 seconds
- while [ $time -lt $timeout ] && ! `${BINDIR}/xenstore-read -s / >/dev/null 2>&1` ; do
- echo -n .
- time=$(($time+1))
- sleep 1
- done
- echo
-
- # Exit if we timed out
- if ! [ $time -lt $timeout ] ; then
- echo Could not start xenstored
- exit 1
- fi
-
- echo Setting domain 0 name and domid...
- ${BINDIR}/xenstore-write "/local/domain/0/name" "Domain-0"
- ${BINDIR}/xenstore-write "/local/domain/0/domid" 0
- fi
-
- echo Starting xenconsoled...
- test -z "$XENCONSOLED_TRACE" || XENCONSOLED_ARGS=" --log=$XENCONSOLED_TRACE"
- ${SBINDIR}/xenconsoled --pid-file=$XENCONSOLED_PIDFILE $XENCONSOLED_ARGS
- echo Starting QEMU as disk backend for dom0
- test -z "$QEMU_XEN" && QEMU_XEN="${LIBEXEC}/qemu-system-i386"
- $QEMU_XEN -xen-domid 0 -xen-attach -name dom0 -nographic -M xenpv -daemonize \
- -monitor /dev/null -serial /dev/null -parallel /dev/null \
- -pidfile $QEMU_PIDFILE
-}
-do_stop () {
- echo Stopping xenconsoled
- if read 2>/dev/null <$XENCONSOLED_PIDFILE pid; then
- kill $pid
- while kill -9 $pid >/dev/null 2>&1; do sleep 0.1; done
- rm -f $XENCONSOLED_PIDFILE
- fi
-
- echo Stopping QEMU
- if read 2>/dev/null <$QEMU_PIDFILE pid; then
- kill $pid
- while kill -9 $pid >/dev/null 2>&1; do sleep 0.1; done
- rm -f $QEMU_PIDFILE
- fi
-
- echo WARNING: Not stopping xenstored, as it cannot be restarted.
-}
-
-case "$1" in
- start)
- do_start
- ;;
- status)
- ${BINDIR}/xenstore-read -s /
- ;;
- stop)
- do_stop
- ;;
- reload)
- echo >&2 'Reload not available; use force-reload'; exit 1
- ;;
- force-reload|restart)
- do_stop
- do_start
- ;;
- *)
- # do not advertise unreasonable commands that there is no reason
- # to use with this device
- echo $"Usage: $0 {start|stop|status|restart|force-reload}"
- exit 1
-esac
-
-exit $?
diff --git a/tools/hotplug/Linux/init.d/xencommons.in b/tools/hotplug/Linux/init.d/xencommons.in
new file mode 100644
index 0000000..a1095c2
--- /dev/null
+++ b/tools/hotplug/Linux/init.d/xencommons.in
@@ -0,0 +1,148 @@
+#!/bin/bash
+#
+# xencommons Script to start and stop xenstored and xenconsoled
+#
+# Author: Ian Jackson <ian.jackson at eu.citrix.com>
+#
+# chkconfig: 2345 70 10
+# description: Starts and stops xenstored and xenconsoled
+### BEGIN INIT INFO
+# Provides: xenstored xenconsoled
+# Required-Start: $syslog $remote_fs
+# Should-Start:
+# Required-Stop: $syslog $remote_fs
+# Should-Stop:
+# Default-Start: 2 3 5
+# Default-Stop: 0 1 6
+# Short-Description: Start/stop xenstored and xenconsoled
+# Description: Starts and stops the daemons neeeded for xl/xend
+### END INIT INFO
+
+XENSTORED=@XENSTORED@
+BACKEND_MODULES="@LINUX_BACKEND_MODULES@"
+
+. @XEN_SCRIPT_DIR@/hotplugpath.sh
+
+xencommons_config=@CONFIG_DIR@/@CONFIG_LEAF_DIR@
+
+test -f $xencommons_config/xencommons && . $xencommons_config/xencommons
+
+XENCONSOLED_PIDFILE=/var/run/xenconsoled.pid
+QEMU_PIDFILE=/var/run/qemu-dom0.pid
+shopt -s extglob
+
+# not running in Xen dom0 or domU
+if ! test -d /proc/xen ; then
+ exit 0
+fi
+
+# mount xenfs in dom0 or domU with a pv_ops kernel
+if test "x$1" = xstart && \
+ ! test -f /proc/xen/capabilities && \
+ ! grep '^xenfs ' /proc/mounts >/dev/null;
+then
+ mount -t xenfs xenfs /proc/xen
+fi
+
+# run this script only in dom0:
+# no capabilities file in xenlinux domU kernel
+# empty capabilities file in pv_ops domU kernel
+if test -f /proc/xen/capabilities && \
+ ! grep -q "control_d" /proc/xen/capabilities ; then
+ exit 0
+fi
+
+do_start () {
+ local time=0
+ local timeout=30
+ local mod
+
+ for mod in $BACKEND_MODULES ; do modprobe "$mod" &>/dev/null ; done
+
+ mkdir -p ${XEN_RUN_DIR}
+ mkdir -p ${XEN_LOCK_DIR}
+
+ if ! `${BINDIR}/xenstore-read -s / >/dev/null 2>&1`
+ then
+ test -z "$XENSTORED_ROOTDIR" && XENSTORED_ROOTDIR="@XEN_LIB_STORED@"
+ rm -f "$XENSTORED_ROOTDIR"/tdb* &>/dev/null
+ test -z "$XENSTORED_TRACE" || XENSTORED_ARGS=" -T /var/log/xen/xenstored-trace.log"
+
+ if [ -n "$XENSTORED" ] ; then
+ echo -n Starting $XENSTORED...
+ $XENSTORED --pid-file /var/run/xenstored.pid $XENSTORED_ARGS
+ else
+ echo "No xenstored found"
+ exit 1
+ fi
+
+ # Wait for xenstored to actually come up, timing out after 30 seconds
+ while [ $time -lt $timeout ] && ! `${BINDIR}/xenstore-read -s / >/dev/null 2>&1` ; do
+ echo -n .
+ time=$(($time+1))
+ sleep 1
+ done
+ echo
+
+ # Exit if we timed out
+ if ! [ $time -lt $timeout ] ; then
+ echo Could not start xenstored
+ exit 1
+ fi
+
+ echo Setting domain 0 name, domid and JSON config...
+ ${LIBEXEC_BIN}/xen-init-dom0
+ fi
+
+ echo Starting xenconsoled...
+ test -z "$XENCONSOLED_TRACE" || XENCONSOLED_ARGS=" --log=$XENCONSOLED_TRACE"
+ ${SBINDIR}/xenconsoled --pid-file=$XENCONSOLED_PIDFILE $XENCONSOLED_ARGS
+ echo Starting QEMU as disk backend for dom0
+ test -z "$QEMU_XEN" && QEMU_XEN="${LIBEXEC_BIN}/qemu-system-i386"
+ $QEMU_XEN -xen-domid 0 -xen-attach -name dom0 -nographic -M xenpv -daemonize \
+ -monitor /dev/null -serial /dev/null -parallel /dev/null \
+ -pidfile $QEMU_PIDFILE
+}
+do_stop () {
+ echo Stopping xenconsoled
+ if read 2>/dev/null <$XENCONSOLED_PIDFILE pid; then
+ kill $pid
+ while kill -9 $pid >/dev/null 2>&1; do sleep 0.1; done
+ rm -f $XENCONSOLED_PIDFILE
+ fi
+
+ echo Stopping QEMU
+ if read 2>/dev/null <$QEMU_PIDFILE pid; then
+ kill $pid
+ while kill -9 $pid >/dev/null 2>&1; do sleep 0.1; done
+ rm -f $QEMU_PIDFILE
+ fi
+
+ echo WARNING: Not stopping xenstored, as it cannot be restarted.
+}
+
+case "$1" in
+ start)
+ do_start
+ ;;
+ status)
+ ${BINDIR}/xenstore-read -s /
+ ;;
+ stop)
+ do_stop
+ ;;
+ reload)
+ echo >&2 'Reload not available; use force-reload'; exit 1
+ ;;
+ force-reload|restart)
+ do_stop
+ do_start
+ ;;
+ *)
+ # do not advertise unreasonable commands that there is no reason
+ # to use with this device
+ echo $"Usage: $0 {start|stop|status|restart|force-reload}"
+ exit 1
+esac
+
+exit $?
diff --git a/tools/hotplug/Linux/init.d/xend b/tools/hotplug/Linux/init.d/xend
deleted file mode 100755
index 8921383..0000000
--- a/tools/hotplug/Linux/init.d/xend
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/bin/bash
-#
-# xend Script to start and stop the Xen control daemon.
-#
-# Author: Keir Fraser <keir.fraser at cl.cam.ac.uk>
-#
-# chkconfig: 2345 98 01
-# description: Starts and stops the Xen control daemon.
-### BEGIN INIT INFO
-# Provides: xend
-# Required-Start: $syslog $remote_fs xenstored xenconsoled
-# Should-Start:
-# Required-Stop: $syslog $remote_fs xenstored xenconsoled
-# Should-Stop:
-# Default-Start: 2 3 5
-# Default-Stop: 0 1 6
-# Short-Description: Start/stop xend
-# Description: Starts and stops the Xen control daemon.
-### END INIT INFO
-
-. /etc/xen/scripts/hotplugpath.sh
-
-shopt -s extglob
-
-# Wait for Xend to be up
-function await_daemons_up
-{
- i=1
- rets=10
- ${SBINDIR}/xend status
- while [ $? -ne 0 -a $i -lt $rets ]; do
- sleep 1
- echo -n .
- i=$(($i + 1))
- ${SBINDIR}/xend status
- done
-}
-
-case "$1" in
- start)
- echo "WARNING: Enabling the xend toolstack."
- echo "xend is deprecated and scheduled for removal. Please migrate"
- echo "to another toolstack ASAP."
-
- if [ -z "`ps -C xenconsoled -o pid=`" ]; then
- echo "xencommons should be started first."
- exit 1
- fi
- # mkdir shouldn't be needed as most distros have this already created. Default to using subsys.
- # See docs/misc/distro_mapping.txt
- mkdir -p /var/lock
- if [ -d /var/lock/subsys ] ; then
- touch /var/lock/subsys/xend
- else
- touch /var/lock/xend
- fi
- ${SBINDIR}/xend start
- await_daemons_up
- ;;
- stop)
- ${SBINDIR}/xend stop
- rm -f /var/lock/subsys/xend /var/lock/xend
- ;;
- status)
- ${SBINDIR}/xend status
- ;;
- reload)
- ${SBINDIR}/xend reload
- ;;
- restart|force-reload)
- ${SBINDIR}/xend restart
- await_daemons_up
- ;;
- *)
- # do not advertise unreasonable commands that there is no reason
- # to use with this device
- echo $"Usage: $0 {start|stop|status|restart|reload|force-reload}"
- exit 1
-esac
-
-exit $?
-
diff --git a/tools/hotplug/Linux/init.d/xendomains b/tools/hotplug/Linux/init.d/xendomains
deleted file mode 100644
index 59f1e3d..0000000
--- a/tools/hotplug/Linux/init.d/xendomains
+++ /dev/null
@@ -1,585 +0,0 @@
-#!/bin/bash
-#
-# /etc/init.d/xendomains
-# Start / stop domains automatically when domain 0 boots / shuts down.
-#
-# chkconfig: 345 99 00
-# description: Start / stop Xen domains.
-#
-# This script offers fairly basic functionality. It should work on Redhat
-# but also on LSB-compliant SuSE releases and on Debian with the LSB package
-# installed. (LSB is the Linux Standard Base)
-#
-# Based on the example in the "Designing High Quality Integrated Linux
-# Applications HOWTO" by Avi Alkalay
-# <http://www.tldp.org/HOWTO/HighQuality-Apps-HOWTO/>
-#
-### BEGIN INIT INFO
-# Provides: xendomains
-# Required-Start: $syslog $remote_fs xenstored xenconsoled
-# Should-Start: xend
-# Required-Stop: $syslog $remote_fs xenstored xenconsoled
-# Should-Stop: xend
-# Default-Start: 2 3 5
-# Default-Stop: 0 1 6
-# Short-Description: Start/stop secondary xen domains
-# Description: Start / stop domains automatically when domain 0
-# boots / shuts down.
-### END INIT INFO
-
-. /etc/xen/scripts/hotplugpath.sh
-
-CMD=${SBINDIR}/xm
-HEADCOMP="LinuxGuestRecord"
-$CMD list &> /dev/null
-if test $? -ne 0
-then
- CMD=${SBINDIR}/xl
- HEADCOMP="Xen saved domain"
-fi
-
-$CMD list &> /dev/null
-if test $? -ne 0
-then
- exit 0;
-fi
-
-# Correct exit code would probably be 5, but it's enough
-# if xend complains if we're not running as privileged domain
-if ! [ -e /proc/xen/privcmd ]; then
- exit 0
-fi
-
-# See docs/misc/distro_mapping.txt
-if [ -d /var/lock/subsys ]; then
- LOCKFILE=/var/lock/subsys/xendomains
-else
- LOCKFILE=/var/lock/xendomains
-fi
-
-if [ -d /etc/sysconfig ]; then
- XENDOM_CONFIG=/etc/sysconfig/xendomains
-else
- XENDOM_CONFIG=/etc/default/xendomains
-fi
-
-test -r $XENDOM_CONFIG || { echo "$XENDOM_CONFIG not existing";
- if [ "$1" = "stop" ]; then exit 0;
- else exit 6; fi; }
-
-. $XENDOM_CONFIG
-
-# Use the SUSE rc_ init script functions;
-# emulate them on LSB, RH and other systems
-if test -e /etc/rc.status; then
- # SUSE rc script library
- . /etc/rc.status
-else
- _cmd=$1
- declare -a _SMSG
- if test "${_cmd}" = "status"; then
- _SMSG=(running dead dead unused unknown)
- _RC_UNUSED=3
- else
- _SMSG=(done failed failed missed failed skipped unused failed failed)
- _RC_UNUSED=6
- fi
- if test -e /etc/init.d/functions; then
- # REDHAT
- . /etc/init.d/functions
- echo_rc()
- {
- #echo -n " [${_SMSG[${_RC_RV}]}] "
- if test ${_RC_RV} = 0; then
- success " [${_SMSG[${_RC_RV}]}] "
- else
- failure " [${_SMSG[${_RC_RV}]}] "
- fi
- }
- elif test -e /lib/lsb/init-functions; then
- # LSB
- . /lib/lsb/init-functions
- if alias log_success_msg >/dev/null 2>/dev/null; then
- echo_rc()
- {
- echo " [${_SMSG[${_RC_RV}]}] "
- }
- else
- echo_rc()
- {
- if test ${_RC_RV} = 0; then
- log_success_msg " [${_SMSG[${_RC_RV}]}] "
- else
- log_failure_msg " [${_SMSG[${_RC_RV}]}] "
- fi
- }
- fi
- else
- # emulate it
- echo_rc()
- {
- echo " [${_SMSG[${_RC_RV}]}] "
- }
- fi
- rc_reset() { _RC_RV=0; }
- rc_failed()
- {
- if test -z "$1"; then
- _RC_RV=1;
- elif test "$1" != "0"; then
- _RC_RV=$1;
- fi
- return ${_RC_RV}
- }
- rc_check()
- {
- return rc_failed $?
- }
- rc_status()
- {
- rc_failed $?
- if test "$1" = "-r"; then _RC_RV=0; shift; fi
- if test "$1" = "-s"; then rc_failed 5; echo_rc; rc_failed 3; shift; fi
- if test "$1" = "-u"; then rc_failed ${_RC_UNUSED}; echo_rc; rc_failed 3; shift; fi
- if test "$1" = "-v"; then echo_rc; shift; fi
- if test "$1" = "-r"; then _RC_RV=0; shift; fi
- return ${_RC_RV}
- }
- rc_exit() { exit ${_RC_RV}; }
- rc_active()
- {
- if test -z "$RUNLEVEL"; then read RUNLEVEL REST < <(/sbin/runlevel); fi
- if test -e /etc/init.d/S[0-9][0-9]${1}; then return 0; fi
- return 1
- }
-fi
-
-if ! which usleep >&/dev/null
-then
- usleep()
- {
- if [ -n "$1" ]
- then
- sleep $(( $1 / 1000000 ))
- fi
- }
-fi
-
-# Reset status of this service
-rc_reset
-
-##
-# Returns 0 (success) if the given parameter names a directory, and that
-# directory is not empty.
-#
-contains_something()
-{
- if [ -d "$1" ] && [ `/bin/ls $1 | wc -l` -gt 0 ]
- then
- return 0
- else
- return 1
- fi
-}
-
-# read name from xen config file
-rdname()
-{
- NM=$($CMD create --quiet --dryrun --defconfig "$1" |
- sed -n 's/^.*(name \(.*\))$/\1/p;s/^.*"name": "\(.*\)",$/\1/p')
-}
-
-rdnames()
-{
- NAMES=
- if ! contains_something "$XENDOMAINS_AUTO"
- then
- return
- fi
- for dom in $XENDOMAINS_AUTO/*; do
- rdname $dom
- if test -z $NAMES; then
- NAMES=$NM;
- else
- NAMES="$NAMES|$NM"
- fi
- done
-}
-
-LIST_GREP='(domain\|(domid\|(name\|^ {$\|"name":\|"domid":'
-parseln()
-{
- if [[ "$1" =~ '(domain' ]] || [[ "$1" = "{" ]]; then
- name=;id=
- elif [[ "$1" =~ '(name' ]]; then
- name=$(echo $1 | sed -e 's/^.*(name \(.*\))$/\1/')
- elif [[ "$1" =~ '(domid' ]]; then
- id=$(echo $1 | sed -e 's/^.*(domid \(.*\))$/\1/')
- elif [[ "$1" =~ '"name":' ]]; then
- name=$(echo $1 | sed -e 's/^.*"name": "\(.*\)",$/\1/')
- elif [[ "$1" =~ '"domid":' ]]; then
- id=$(echo $1 | sed -e 's/^.*"domid": \(.*\),$/\1/')
- fi
-
- [ -n "$name" -a -n "$id" ] && return 0 || return 1
-}
-
-is_running()
-{
- rdname $1
- RC=1
- name=;id=
- while read LN; do
- parseln "$LN" || continue
- if test $id = 0; then continue; fi
- case $name in
- ($NM)
- RC=0
- ;;
- esac
- done < <($CMD list -l | grep "$LIST_GREP")
- return $RC
-}
-
-start()
-{
- if [ -f $LOCKFILE ]; then
- echo -e "xendomains already running (lockfile exists)"
- return;
- fi
-
- saved_domains=" "
- if [ "$XENDOMAINS_RESTORE" = "true" ] &&
- contains_something "$XENDOMAINS_SAVE"
- then
- mkdir -p $(dirname "$LOCKFILE")
- touch $LOCKFILE
- echo -n "Restoring Xen domains:"
- saved_domains=`ls $XENDOMAINS_SAVE`
- for dom in $XENDOMAINS_SAVE/*; do
- if [ -f $dom ] ; then
- HEADER=`head -c 16 $dom | head -n 1 2> /dev/null`
- if [ "$HEADER" = "$HEADCOMP" ]; then
- echo -n " ${dom##*/}"
- XMR=`$CMD restore $dom 2>&1 1>/dev/null`
- #$CMD restore $dom
- if [ $? -ne 0 ]; then
- echo -e "\nAn error occurred while restoring domain ${dom##*/}:\n$XMR"
- rc_failed $?
- echo -e '!'
- else
- # mv $dom ${dom%/*}/.${dom##*/}
- rm $dom
- fi
- fi
- fi
- done
- echo -e
- fi
-
- if contains_something "$XENDOMAINS_AUTO"
- then
- touch $LOCKFILE
- echo -n "Starting auto Xen domains:"
- # We expect config scripts for auto starting domains to be in
- # XENDOMAINS_AUTO - they could just be symlinks to files elsewhere
-
- # Create all domains with config files in XENDOMAINS_AUTO.
- # TODO: We should record which domain name belongs
- # so we have the option to selectively shut down / migrate later
- # If a domain statefile from $XENDOMAINS_SAVE matches a domain name
- # in $XENDOMAINS_AUTO, do not try to start that domain; if it didn't
- # restore correctly it requires administrative attention.
- for dom in $XENDOMAINS_AUTO/*; do
- echo -n " ${dom##*/}"
- shortdom=$(echo $dom | sed -n 's/^.*\/\(.*\)$/\1/p')
- echo $saved_domains | grep -w $shortdom > /dev/null
- if [ $? -eq 0 ] || is_running $dom; then
- echo -n "(skip)"
- else
- XMC=`$CMD create --quiet --defconfig $dom`
- if [ $? -ne 0 ]; then
- echo -e "\nAn error occurred while creating domain ${dom##*/}: $XMC\n"
- rc_failed $?
- echo -e '!'
- else
- usleep $XENDOMAINS_CREATE_USLEEP
- fi
- fi
- done
- fi
-}
-
-all_zombies()
-{
- name=;id=
- while read LN; do
- parseln "$LN" || continue
- if test $id = 0; then continue; fi
- if test "$state" != "-b---d" -a "$state" != "-----d"; then
- return 1;
- fi
- done < <($CMD list -l | grep "$LIST_GREP")
- return 0
-}
-
-# Wait for max $XENDOMAINS_STOP_MAXWAIT for $CMD $1 to finish;
-# if it has not exited by that time kill it, so the init script will
-# succeed within a finite amount of time; if $2 is nonnull, it will
-# kill the command as well as soon as no domain (except for zombies)
-# are left (used for shutdown --all). Third parameter, if any, suppresses
-# output of dots per working state (formatting issues)
-watchdog_xencmd()
-{
- if test -z "$XENDOMAINS_STOP_MAXWAIT" -o "$XENDOMAINS_STOP_MAXWAIT" = "0"; then
- exit
- fi
-
- usleep 20000
- for no in `seq 0 $XENDOMAINS_STOP_MAXWAIT`; do
- # exit if $CMD save/migrate/shutdown is finished
- PSAX=`ps axlw | grep "$CMD $1" | grep -v grep`
- if test -z "$PSAX"; then exit; fi
- if ! test -n "$3"; then echo -n '.'; fi
- sleep 1
- # go to kill immediately if there's only zombies left
- if all_zombies && test -n "$2"; then break; fi
- done
- sleep 1
- read PSF PSUID PSPID PSPPID < <(echo "$PSAX")
- # kill $CMD $1
- kill $PSPID >/dev/null 2>&1
-
- echo -e .
-}
-
-stop()
-{
- exec 3>&2 2> /dev/null
-
- # Collect list of domains to shut down
- if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
- rdnames
- fi
- echo -n "Shutting down Xen domains:"
- name=;id=
- while read LN; do
- parseln "$LN" || continue
- if test $id = 0; then continue; fi
- echo -n " $name"
- if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
- eval "
- case \"\$name\" in
- ($NAMES)
- # nothing
- ;;
- (*)
- echo -e '(skip)'
- continue
- ;;
- esac
- "
- fi
- # XENDOMAINS_SYSRQ chould be something like just "s"
- # or "s e i u" or even "s e s i u o"
- # for the latter, you should set XENDOMAINS_USLEEP to 1200000 or so
- if test -n "$XENDOMAINS_SYSRQ"; then
- for sysrq in $XENDOMAINS_SYSRQ; do
- echo -n "(SR-$sysrq)"
- XMR=`$CMD sysrq $id $sysrq 2>&1 1>/dev/null`
- if test $? -ne 0; then
- echo -e "\nAn error occurred while doing sysrq on domain:\n$XMR\n"
- rc_failed $?
- echo -n '!'
- fi
- # usleep just ignores empty arg
- usleep $XENDOMAINS_USLEEP
- done
- fi
- if test "$state" = "-b---d" -o "$state" = "-----d"; then
- echo -n "(zomb)"
- continue
- fi
- if test -n "$XENDOMAINS_MIGRATE"; then
- echo -n "(migr)"
- watchdog_xencmd migrate &
- WDOG_PID=$!
- XMR=`$CMD migrate $id $XENDOMAINS_MIGRATE 2>&1 1>/dev/null`
- if test $? -ne 0; then
- echo -e "\nAn error occurred while migrating domain:\n$XMR\n"
- rc_failed $?
- echo -e '!'
-
- kill $WDOG_PID >/dev/null 2>&1
- else
- kill $WDOG_PID >/dev/null 2>&1
-
- echo -e .
- usleep 1000
- continue
- fi
- fi
- if test -n "$XENDOMAINS_SAVE"; then
- echo -n "(save)"
- watchdog_xencmd save &
- WDOG_PID=$!
- mkdir -p "$XENDOMAINS_SAVE"
- XMR=`$CMD save $id $XENDOMAINS_SAVE/$name 2>&1 1>/dev/null`
- if test $? -ne 0; then
- echo -e "\nAn error occurred while saving domain:\n$XMR\n"
- rc_failed $?
- echo -e '!'
- kill $WDOG_PID >/dev/null 2>&1
- else
- kill $WDOG_PID >/dev/null 2>&1
- echo -e .
- usleep 1000
- continue
- fi
- fi
- if test -n "$XENDOMAINS_SHUTDOWN"; then
- # XENDOMAINS_SHUTDOWN should be "--wait"
- echo -n "(shut)"
- watchdog_xencmd shutdown &
- WDOG_PID=$!
- XMR=`$CMD shutdown $XENDOMAINS_SHUTDOWN $id 2>&1 1>/dev/null`
- if test $? -ne 0; then
- echo -e "\nAn error occurred while shutting down domain:\n$XMR\n"
- rc_failed $?
- echo -e '!'
- fi
- kill $WDOG_PID >/dev/null 2>&1
- fi
- done < <($CMD list -l | grep "$LIST_GREP")
-
- # NB. this shuts down ALL Xen domains (politely), not just the ones in
- # AUTODIR/*
- # This is because it's easier to do ;-) but arguably if this script is run
- # on system shutdown then it's also the right thing to do.
- if ! all_zombies && test -n "$XENDOMAINS_SHUTDOWN_ALL"; then
- # XENDOMAINS_SHUTDOWN_ALL should be "--all --wait"
- echo -n " SHUTDOWN_ALL "
- watchdog_xencmd shutdown 1 false &
- WDOG_PID=$!
- XMR=`$CMD shutdown $XENDOMAINS_SHUTDOWN_ALL 2>&1 1>/dev/null`
- if test $? -ne 0; then
- echo -e "\nAn error occurred while shutting down all domains: $XMR\n"
- rc_failed $?
- echo -e '!'
- fi
- kill $WDOG_PID >/dev/null 2>&1
- fi
-
- # Unconditionally delete lock file
- rm -f $LOCKFILE
-
- exec 2>&3
-}
-
-check_domain_up()
-{
- name=;id=
- while read LN; do
- parseln "$LN" || continue
- if test $id = 0; then continue; fi
- case $name in
- ($1)
- return 0
- ;;
- esac
- done < <($CMD list -l | grep "$LIST_GREP")
- return 1
-}
-
-check_all_auto_domains_up()
-{
- if ! contains_something "$XENDOMAINS_AUTO"
- then
- return 0
- fi
- missing=
- for nm in $XENDOMAINS_AUTO/*; do
- rdname $nm
- found=0
- if check_domain_up "$NM"; then
- echo -n " $name"
- else
- missing="$missing $NM"
- fi
- done
- if test -n "$missing"; then
- echo -n " MISS AUTO:$missing"
- return 1
- fi
- return 0
-}
-
-check_all_saved_domains_up()
-{
- if ! contains_something "$XENDOMAINS_SAVE"
- then
- return 0
- fi
- missing=`/bin/ls $XENDOMAINS_SAVE`
- echo -n " MISS SAVED: " $missing
- return 1
-}
-
-# This does NOT necessarily restart all running domains: instead it
-# stops all running domains and then boots all the domains specified in
-# AUTODIR. If other domains have been started manually then they will
-# not get restarted.
-# Commented out to avoid confusion!
-
-restart()
-{
- stop
- start
-}
-
-reload()
-{
- restart
-}
-
-
-case "$1" in
- start)
- start
- rc_status
- if test -f $LOCKFILE; then rc_status -v; fi
- ;;
-
- stop)
- stop
- rc_status -v
- ;;
-
- restart)
- restart
- ;;
- reload)
- reload
- ;;
-
- status)
- echo -n "Checking for xendomains:"
- if test ! -f $LOCKFILE; then
- rc_failed 3
- else
- check_all_auto_domains_up
- rc_status
- check_all_saved_domains_up
- rc_status
- fi
- rc_status -v
- ;;
-
- *)
- echo "Usage: $0 {start|stop|restart|reload|status}"
- rc_failed 3
- rc_status -v
- ;;
-esac
-
-rc_exit
diff --git a/tools/hotplug/Linux/init.d/xendomains.in b/tools/hotplug/Linux/init.d/xendomains.in
new file mode 100644
index 0000000..dcd330c
--- /dev/null
+++ b/tools/hotplug/Linux/init.d/xendomains.in
@@ -0,0 +1,50 @@
+#!/bin/bash
+#
+# /etc/init.d/xendomains
+# Wrapper to start / stop domains automatically when domain 0 boots / shuts down
+#
+# chkconfig: 345 99 00
+# description: Helper to start / stop Xen domains.
+#
+# This script is a wrapper init helper for the real workload horse script.
+# It should work on LSB-compliant systems.
+#
+### BEGIN INIT INFO
+# Provides: xendomains
+# Required-Start: $syslog $remote_fs xenstored xenconsoled
+# Should-Start: xend
+# Required-Stop: $syslog $remote_fs xenstored xenconsoled
+# Should-Stop: xend
+# Default-Start: 2 3 5
+# Default-Stop: 0 1 6
+# Short-Description: Wrapper to start/stop secondary xen domains
+# Description: Wrapper for starting / stopping domains automatically
+# when domain 0 boots / shuts down on systems using init.
+# The $LIBEXEC_BIN/xendomains helper is shared between init and
+# systemd systems.
+### END INIT INFO
+
+. @XEN_SCRIPT_DIR@/hotplugpath.sh
+
+case "$1" in
+ start)
+ $LIBEXEC_BIN/xendomains start
+ ;;
+ stop)
+ $LIBEXEC_BIN/xendomains stop
+ ;;
+ restart)
+ $LIBEXEC_BIN/xendomains restart
+ ;;
+ reload)
+ $LIBEXEC_BIN/xendomains reload
+ ;;
+ status)
+ $LIBEXEC_BIN/xendomains status
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|restart|reload|status}"
+ exit 3
+ ;;
+esac
+exit $?
diff --git a/tools/hotplug/Linux/network-bridge b/tools/hotplug/Linux/network-bridge
deleted file mode 100644
index 9aa9dda..0000000
--- a/tools/hotplug/Linux/network-bridge
+++ /dev/null
@@ -1,339 +0,0 @@
-#!/bin/bash
-#============================================================================
-# Default Xen network start/stop script.
-# Xend calls a network script when it starts.
-# The script name to use is defined in ${XEN_CONFIG_DIR}/xend-config.sxp
-# in the network-script field.
-#
-# This script creates a bridge (default ${netdev}), adds a device
-# (defaults to the device on the default gateway route) to it, copies
-# the IP addresses from the device to the bridge and adjusts the routes
-# accordingly.
-#
-# If all goes well, this should ensure that networking stays up.
-# However, some configurations are upset by this, especially
-# NFS roots. If the bridged setup does not meet your needs,
-# configure a different script, for example using routing instead.
-#
-# Usage:
-#
-# network-bridge (start|stop|status) {VAR=VAL}*
-#
-# Vars:
-#
-# bridge The bridge to use (default ${netdev}).
-# netdev The interface to add to the bridge (default gateway device).
-# antispoof Whether to use iptables to prevent spoofing (default no).
-#
-# Internal Vars:
-# pdev="p${netdev}"
-# tdev=tmpbridge
-#
-# start:
-# Creates the bridge as tdev
-# Copies the IP and MAC addresses from pdev to bridge
-# Renames netdev to be pdev
-# Renames tdev to bridge
-# Enslaves pdev to bridge
-#
-# stop:
-# Removes pdev from the bridge
-# Transfers addresses, routes from bridge to pdev
-# Renames bridge to tdev
-# Renames pdev to netdev
-# Deletes tdev
-#
-# status:
-# Print addresses, interfaces, routes
-#
-#============================================================================
-
-
-dir=$(dirname "$0")
-. "$dir/logging.sh"
-. "$dir/xen-script-common.sh"
-. "$dir/xen-network-common.sh"
-. "$dir/locking.sh"
-
-findCommand "$@"
-evalVariables "$@"
-
-is_network_root () {
- local rootfs=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $3; }}' /etc/mtab)
- local rootopts=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' /etc/mtab)
-
- [[ "$rootfs" =~ "^nfs" ]] || [[ "$rootopts" =~ "_netdev" ]] && has_nfsroot=1 || has_nfsroot=0
- if [ $has_nfsroot -eq 1 ]; then
- local bparms=$(cat /proc/cmdline)
- for p in $bparms; do
- local ipaddr=$(echo $p | awk /nfsroot=/'{ print substr($1,9,index($1,":")-9) }')
- if [ "$ipaddr" != "" ]; then
- local nfsdev=$(ip route get $ipaddr | awk /$ipaddr/'{ print $3 }')
- [[ "$nfsdev" == "$netdev" ]] && return 0 || return 1
- fi
- done
- fi
- return 1
-}
-
-find_alt_device () {
- local interf=$1
- local prefix=${interf%[[:digit:]]}
- local ifs=$(ip link show | grep " $prefix" |\
- awk '{ printf ("%s",substr($2,1,length($2)-1)) }' |\
- sed s/$interf//)
- echo "$ifs"
-}
-
-netdev=${netdev:-$(ip route list 0.0.0.0/0 | \
- sed 's/.*dev \([a-z]\+[0-9]\+\).*$/\1/')}
-if is_network_root ; then
- altdevs=$(find_alt_device $netdev)
- for netdev in $altdevs; do break; done
- if [ -z "$netdev" ]; then
- [ -x /usr/bin/logger ] && /usr/bin/logger "network-bridge: bridging not supported on network root; not starting"
- exit
- fi
-fi
-netdev=${netdev:-eth0}
-bridge=${bridge:-${netdev}}
-antispoof=${antispoof:-no}
-
-pdev="p${netdev}"
-tdev=tmpbridge
-
-get_ip_info() {
- addr_pfx=`ip addr show dev $1 | egrep '^ *inet' | sed -e 's/ *inet //' -e 's/ .*//'`
- gateway=`ip route show dev $1 | fgrep default | sed 's/default via //'`
-}
-
-do_ifup() {
- if [ $1 != "${netdev}" ] || ! ifup $1 ; then
- if [ -n "$addr_pfx" ] ; then
- # use the info from get_ip_info()
- ip addr flush $1
- ip addr add ${addr_pfx} dev $1
- fi
- ip link set dev $1 up
- if [ -n "$gateway" ] ; then
- ip route add default via ${gateway}
- fi
- fi
-}
-
-# Usage: transfer_addrs src dst
-# Copy all IP addresses (including aliases) from device $src to device $dst.
-transfer_addrs () {
- local src=$1
- local dst=$2
- # Don't bother if $dst already has IP addresses.
- if ip addr show dev ${dst} | egrep -q '^ *inet ' ; then
- return
- fi
- # Address lines start with 'inet' and have the device in them.
- # Replace 'inet' with 'ip addr add' and change the device name $src
- # to 'dev $src'.
- ip addr show dev ${src} | egrep '^ *inet ' | sed -e "
-s/inet/ip addr add/
-s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+/[0-9]\+\)@\1@
-s/${src}/dev ${dst} label ${dst}/
-s/secondary//
-" | sh -e
- # Remove automatic routes on destination device
- ip route list | sed -ne "
-/dev ${dst}\( \|$\)/ {
- s/^/ip route del /
- p
-}" | sh -e
-}
-
-# Usage: transfer_routes src dst
-# Get all IP routes to device $src, delete them, and
-# add the same routes to device $dst.
-# The original routes have to be deleted, otherwise adding them
-# for $dst fails (duplicate routes).
-transfer_routes () {
- local src=$1
- local dst=$2
- # List all routes and grep the ones with $src in.
- # Stick 'ip route del' on the front to delete.
- # Change $src to $dst and use 'ip route add' to add.
- ip route list | sed -ne "
-/dev ${src}\( \|$\)/ {
- h
- s/^/ip route del /
- P
- g
- s/${src}/${dst}/
- s/^/ip route add /
- P
- d
-}" | sh -e
-}
-
-
-##
-# link_exists interface
-#
-# Returns 0 if the interface named exists (whether up or down), 1 otherwise.
-#
-link_exists()
-{
- if ip link show "$1" >/dev/null 2>/dev/null
- then
- return 0
- else
- return 1
- fi
-}
-
-# Set the default forwarding policy for $dev to drop.
-# Allow forwarding to the bridge.
-antispoofing () {
- iptables -P FORWARD DROP
- iptables -F FORWARD
- iptables -A FORWARD -m physdev --physdev-in ${pdev} -j ACCEPT
-}
-
-# Usage: show_status dev bridge
-# Print ifconfig and routes.
-show_status () {
- local dev=$1
- local bridge=$2
-
- echo '============================================================'
- ip addr show ${dev}
- ip addr show ${bridge}
- echo ' '
- brctl show ${bridge}
- echo ' '
- ip route list
- echo ' '
- route -n
- echo '============================================================'
-}
-
-op_start () {
- if [ "${bridge}" = "null" ] ; then
- return
- fi
-
- if [ `brctl show | wc -l` != 1 ]; then
- return
- fi
-
- if link_exists "$pdev"; then
- # The device is already up.
- return
- fi
-
- claim_lock "network-bridge"
-
- create_bridge ${tdev}
-
- preiftransfer ${netdev}
- transfer_addrs ${netdev} ${tdev}
- # Remember slaves for bonding interface.
- if [ -e /sys/class/net/${netdev}/bonding/slaves ]; then
- slaves=`cat /sys/class/net/${netdev}/bonding/slaves`
- fi
- # Remember the IP details for do_ifup.
- get_ip_info ${netdev}
- if ! ifdown ${netdev}; then
- ip link set ${netdev} down
- ip addr flush ${netdev}
- fi
- ip link set ${netdev} name ${pdev}
- ip link set ${tdev} name ${bridge}
-
- setup_physical_bridge_port ${pdev}
-
- # Restore slaves
- if [ -n "${slaves}" ]; then
- ip link set ${pdev} up
- ifenslave ${pdev} ${slaves}
- fi
- add_to_bridge2 ${bridge} ${pdev}
- do_ifup ${bridge}
-
- if [ ${antispoof} = 'yes' ] ; then
- antispoofing
- fi
-
- release_lock "network-bridge"
-}
-
-op_stop () {
- if [ "${bridge}" = "null" ]; then
- return
- fi
- if ! link_exists "$bridge"; then
- return
- fi
- if ! [ -e "/sys/class/net/${bridge}/brif/${pdev}" ]; then
- # $bridge is not a bridge to which pdev is enslaved
- return
- fi
-
- claim_lock "network-bridge"
-
- transfer_addrs ${bridge} ${pdev}
- if ! ifdown ${bridge}; then
- get_ip_info ${bridge}
- fi
- ip link set ${pdev} down
- ip addr flush ${bridge}
-
- brctl delif ${bridge} ${pdev}
- ip link set ${bridge} down
-
- ip link set ${bridge} name ${tdev}
- ip link set ${pdev} name ${netdev}
- do_ifup ${netdev}
-
- brctl delbr ${tdev}
-
- release_lock "network-bridge"
-}
-
-# adds $dev to $bridge but waits for $dev to be in running state first
-add_to_bridge2() {
- local bridge=$1
- local dev=$2
- local maxtries=10
-
- echo -n "Waiting for ${dev} to negotiate link."
- ip link set ${dev} up
- for i in `seq ${maxtries}` ; do
- if ifconfig ${dev} | grep -q RUNNING ; then
- break
- else
- echo -n '.'
- sleep 1
- fi
- done
-
- if [ ${i} -eq ${maxtries} ] ; then echo -n '(link isnt in running state)' ; fi
- echo
-
- add_to_bridge ${bridge} ${dev}
-}
-
-case "$command" in
- start)
- op_start
- ;;
-
- stop)
- op_stop
- ;;
-
- status)
- show_status ${netdev} ${bridge}
- ;;
-
- *)
- echo "Unknown command: $command" >&2
- echo 'Valid commands are: start, stop, status' >&2
- exit 1
-esac
diff --git a/tools/hotplug/Linux/network-nat b/tools/hotplug/Linux/network-nat
deleted file mode 100644
index eb1740e..0000000
--- a/tools/hotplug/Linux/network-nat
+++ /dev/null
@@ -1,124 +0,0 @@
-#!/bin/bash
-#============================================================================
-# Default Xen network start/stop script when using NAT.
-# Xend calls a network script when it starts.
-# The script name to use is defined in ${XEN_CONFIG_DIR}/xend-config.sxp
-# in the network-script field.
-#
-# Usage:
-#
-# network-nat (start|stop|status) {VAR=VAL}*
-#
-# Vars:
-#
-# netdev The gateway interface (default eth0).
-# antispoof Whether to use iptables to prevent spoofing (default no).
-# dhcp Whether to alter the local DHCP configuration (default no).
-#
-#============================================================================
-
-dir=$(dirname "$0")
-. "$dir/hotplugpath.sh"
-. "$dir/xen-script-common.sh"
-. "$dir/xen-network-common.sh"
-
-findCommand "$@"
-evalVariables "$@"
-
-netdev=${netdev:-eth0}
-# antispoofing not yet implemented
-antispoof=${antispoof:-no}
-
-# turn on dhcp feature by default if dhcpd is installed
-if [ -f /etc/dhcpd.conf ]
-then
- dhcp=${dhcp:-yes}
-else
- dhcp=${dhcp:-no}
-fi
-
-
-if [ "$dhcp" != 'no' ]
-then
- dhcpd_conf_file=$(find_dhcpd_conf_file)
- dhcpd_init_file=$(find_dhcpd_init_file)
- if [ -z "$dhcpd_conf_file" ] || [ -z "$dhcpd_init_file" ]
- then
- echo 'Failed to find dhcpd configuration or init file.' >&2
- exit 1
- fi
-fi
-
-domain_name=`cat /etc/resolv.conf | grep -v "#" | grep -E 'search|domain' -i | tail -n 1 | awk '{ print $2 }'`
-nameserver=`cat /etc/resolv.conf | grep -v "#" | grep "nameserver" -i -m 1 | awk '{ print $2 }'`
-
-function dhcp_start()
-{
- if ! grep -q "subnet 10.0.0.0" "$dhcpd_conf_file"
- then
- echo >>"$dhcpd_conf_file" "subnet 10.0.0.0 netmask 255.255.0.0 {\
- option domain-name \"$domain_name\";\
- option domain-name-servers $nameserver; }"
- fi
-
- "$dhcpd_init_file" restart
-}
-
-
-function dhcp_stop()
-{
- local tmpfile=$(mktemp)
- grep -v "subnet 10.0.0.0" "$dhcpd_conf_file" >"$tmpfile"
- if diff "$tmpfile" "$dhcpd_conf_file" >&/dev/null
- then
- rm "$tmpfile"
- else
- mv "$tmpfile" "$dhcpd_conf_file"
- fi
-
- "$dhcpd_init_file" restart
-}
-
-
-op_start() {
- echo 1 >/proc/sys/net/ipv4/ip_forward
- iptables -t nat -A POSTROUTING -o ${netdev} -j MASQUERADE
- [ "$dhcp" != 'no' ] && dhcp_start
-}
-
-
-op_stop() {
- [ "$dhcp" != 'no' ] && dhcp_stop
- iptables -t nat -D POSTROUTING -o ${netdev} -j MASQUERADE
-}
-
-
-show_status() {
- echo '============================================================'
- ifconfig
- echo ' '
- ip route list
- echo ' '
- route -n
- echo '============================================================'
-
-}
-
-case "$command" in
- start)
- op_start
- ;;
-
- stop)
- op_stop
- ;;
-
- status)
- show_status
- ;;
-
- *)
- echo "Unknown command: $command" >&2
- echo 'Valid commands are: start, stop, status' >&2
- exit 1
-esac
diff --git a/tools/hotplug/Linux/network-route b/tools/hotplug/Linux/network-route
deleted file mode 100644
index 8f6a1be..0000000
--- a/tools/hotplug/Linux/network-route
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/bash
-#============================================================================
-# Default Xen network start/stop script.
-# Xend calls a network script when it starts.
-# The script name to use is defined in ${XEN_CONFIG_DIR}/xend-config.sxp
-# in the network-script field.
-#
-# Usage:
-#
-# network-route (start|stop|status) {VAR=VAL}*
-#
-# Vars:
-#
-# netdev The gateway interface (default eth0).
-# antispoof Whether to use iptables to prevent spoofing (default yes).
-#
-#============================================================================
-
-dir=$(dirname "$0")
-. "$dir/hotplugpath.sh"
-. "$dir/xen-script-common.sh"
-
-evalVariables "$@"
-
-netdev=${netdev:-eth0}
-
-echo 1 >/proc/sys/net/ipv4/ip_forward
-echo 1 >/proc/sys/net/ipv4/conf/${netdev}/proxy_arp
diff --git a/tools/hotplug/Linux/remus-netbuf-setup b/tools/hotplug/Linux/remus-netbuf-setup
new file mode 100644
index 0000000..87dfa69
--- /dev/null
+++ b/tools/hotplug/Linux/remus-netbuf-setup
@@ -0,0 +1,230 @@
+#!/bin/bash
+#============================================================================
+# ${XEN_SCRIPT_DIR}/remus-netbuf-setup
+#
+# Script for attaching a network buffer to the specified vif (in any mode).
+# The hotplugging system will call this script when starting remus via libxl
+# API, libxl_domain_remus_start.
+#
+# Usage:
+# remus-netbuf-setup (setup|teardown)
+#
+# Environment vars:
+# vifname vif interface name (required).
+# XENBUS_PATH path in Xenstore, where the REMUS_IFB device details will be
+# stored or read from (required).
+# (libxl passes /libxl/<domid>/remus/netbuf/<devid>)
+# REMUS_IFB ifb interface to be cleaned up (required). [for teardown op only]
+
+# Written to the store: (setup operation)
+# XENBUS_PATH/ifb=<ifbdevName> the REMUS_IFB device serving
+# as the intermediate buffer through which the interface's network output
+# can be controlled.
+#
+
+# Remus network buffering requirements:
+
+# We need to buffer (queue) egress traffic from every vif attached to
+# the guest and release the buffers when the checkpoint associated
+# with them has been committed at the backup host. We achieve this
+# with the help of the plug queuing discipline (sch_plug module).
+# Simply put, Remus' network buffering imposes traffic
+# shaping on the guest's vif(s).
+
+# Limitations and Workarounds:
+
+# Egress traffic from a vif appears as ingress traffic to dom0. Linux
+# supports policing (dropping packets) but not traffic shaping
+# (queuing packets) on ingress traffic. The standard workaround to
+# this limitation is to attach an ingress qdisc to the guest vif,
+# redirect all egress traffic from the guest to an intermediate
+# queuing interface, and apply egress rules to it. The IFB
+# (Intermediate Functional Block) device serves the purpose of an
+# intermediate queuing interface.
+#
+
+# The following commands install a network buffer on a
+# guest's vif (vif1.0) using an IFB device (ifb0):
+#
+# ip link set dev ifb0 up
+# tc qdisc add dev vif1.0 ingress
+# tc filter add dev vif1.0 parent ffff: proto ip \
+# prio 10 u32 match u32 0 0 action mirred egress redirect dev ifb0
+# nl-qdisc-add --dev=ifb0 --parent root plug
+# nl-qdisc-add --dev=ifb0 --parent root --update plug --limit=10000000
+# (10MB limit on buffer)
+#
+# So order of operations when installing a network buffer on vif1.0
+# 1. find a free ifb and bring up the device
+# 2. redirect traffic from vif1.0 to ifb:
+# 2.1 add ingress qdisc to vif1.0 (to capture outgoing packets from guest)
+# 2.2 use tc filter command with actions mirred egress + redirect
+# 3. install plug_qdisc on ifb device, with which we can buffer/release
+# guest's network output from vif1.0
+#
+# Note:
+# 1. If the setup process fails, the script's cleanup is limited to removing the
+# ingress qdisc on the guest vif, so that its traffic can flow normally.
+# The chosen ifb device is not torn down. Libxl has to execute the
+# teardown op to remove other qdiscs and subsequently free the IFB device.
+#
+# 2. The teardown op may be invoked multiple times by libxl.
+
+#============================================================================
+
+# Unlike other vif scripts, vif-common is not needed here as it executes vif
+#specific setup code such as renaming.
+dir=$(dirname "$0")
+. "$dir/xen-hotplug-common.sh"
+
+findCommand "$@"
+
+if [ "$command" != "setup" -a "$command" != "teardown" ]
+then
+ echo "Invalid command: $command"
+ log err "Invalid command: $command"
+ exit 1
+fi
+
+evalVariables "$@"
+
+: ${vifname:?}
+: ${XENBUS_PATH:?}
+
+check_libnl_tools() {
+ if ! command -v nl-qdisc-list > /dev/null 2>&1; then
+ fatal "Unable to find nl-qdisc-list tool"
+ fi
+ if ! command -v nl-qdisc-add > /dev/null 2>&1; then
+ fatal "Unable to find nl-qdisc-add tool"
+ fi
+ if ! command -v nl-qdisc-delete > /dev/null 2>&1; then
+ fatal "Unable to find nl-qdisc-delete tool"
+ fi
+}
+
+# We only check for modules. We don't load them.
+# User/Admin is supposed to load ifb during boot time,
+# ensuring that there are enough free ifbs in the system.
+# Other modules will be loaded automatically by tc commands.
+check_modules() {
+ for m in ifb sch_plug sch_ingress act_mirred cls_u32
+ do
+ if ! modinfo $m > /dev/null 2>&1; then
+ fatal "Unable to find $m kernel module"
+ fi
+ done
+}
+
+#return 0 if the ifb is free
+check_ifb() {
+ local installed=`nl-qdisc-list -d $1`
+ [ -n "$installed" ] && return 1
+
+ for domid in `xenstore-list "/local/domain" 2>/dev/null || true`
+ do
+ [ $domid -eq 0 ] && continue
+ xenstore-exists "/libxl/$domid/remus/netbuf" || continue
+ for devid in `xenstore-list "/libxl/$domid/remus/netbuf" 2>/dev/null || true`
+ do
+ local path="/libxl/$domid/remus/netbuf/$devid/ifb"
+ xenstore-exists $path || continue
+ local ifb=`xenstore-read "$path" 2>/dev/null || true`
+ [ "$ifb" = "$1" ] && return 1
+ done
+ done
+
+ return 0
+}
+
+setup_ifb() {
+
+ for ifb in `ifconfig -a -s|egrep ^ifb|cut -d ' ' -f1`
+ do
+ check_ifb "$ifb" || continue
+ REMUS_IFB="$ifb"
+ break
+ done
+
+ if [ -z "$REMUS_IFB" ]
+ then
+ fatal "Unable to find a free ifb device for $vifname"
+ fi
+
+ #not using xenstore_write that automatically exits on error
+ #because we need to cleanup
+ xenstore_write "$XENBUS_PATH/ifb" "$REMUS_IFB"
+ do_or_die ip link set dev "$REMUS_IFB" up
+}
+
+redirect_vif_traffic() {
+ local vif=$1
+ local ifb=$2
+
+ do_or_die tc qdisc add dev "$vif" ingress
+
+ tc filter add dev "$vif" parent ffff: proto ip prio 10 \
+ u32 match u32 0 0 action mirred egress redirect dev "$ifb" >/dev/null 2>&1
+
+ if [ $? -ne 0 ]
+ then
+ do_without_error tc qdisc del dev "$vif" ingress
+ fatal "Failed to redirect traffic from $vif to $ifb"
+ fi
+}
+
+add_plug_qdisc() {
+ local vif=$1
+ local ifb=$2
+
+ nl-qdisc-add --dev="$ifb" --parent root plug >/dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ do_without_error tc qdisc del dev "$vif" ingress
+ fatal "Failed to add plug qdisc to $ifb"
+ fi
+
+ #set ifb buffering limit in bytes. Its okay if this command fails
+ nl-qdisc-add --dev="$ifb" --parent root \
+ --update plug --limit=10000000 >/dev/null 2>&1 || true
+}
+
+teardown_netbuf() {
+ local vif=$1
+ local ifb=$2
+
+ #Check if the XENBUS_PATH/ifb exists and has IFB name same as REMUS_IFB.
+ #Otherwise, if the teardown op is called multiple times, then we may end
+ #up freeing another domain's allocated IFB inside the if loop.
+ xenstore-exists "$XENBUS_PATH/ifb" && \
+ local ifb2=`xenstore-read "$XENBUS_PATH/ifb" 2>/dev/null || true`
+
+ if [[ "$ifb2" && "$ifb2" == "$ifb" ]]; then
+ do_without_error ip link set dev "$ifb" down
+ do_without_error nl-qdisc-delete --dev="$ifb" --parent root plug >/dev/null 2>&1
+ xenstore-rm -t "$XENBUS_PATH/ifb" 2>/dev/null || true
+ fi
+ do_without_error tc qdisc del dev "$vif" ingress
+ xenstore-rm -t "$XENBUS_PATH/hotplug-status" 2>/dev/null || true
+ xenstore-rm -t "$XENBUS_PATH/hotplug-error" 2>/dev/null || true
+}
+
+case "$command" in
+ setup)
+ check_libnl_tools
+ check_modules
+
+ claim_lock "pickifb"
+ setup_ifb
+ redirect_vif_traffic "$vifname" "$REMUS_IFB"
+ add_plug_qdisc "$vifname" "$REMUS_IFB"
+ release_lock "pickifb"
+
+ success
+ ;;
+ teardown)
+ teardown_netbuf "$vifname" "$REMUS_IFB"
+ ;;
+esac
+
+log debug "Successful remus-netbuf-setup $command for $vifname, ifb $REMUS_IFB."
diff --git a/tools/hotplug/Linux/systemd/Makefile b/tools/hotplug/Linux/systemd/Makefile
new file mode 100644
index 0000000..51c10fe
--- /dev/null
+++ b/tools/hotplug/Linux/systemd/Makefile
@@ -0,0 +1,47 @@
+XEN_ROOT = $(CURDIR)/../../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+XEN_SYSTEMD_MODULES = xen.conf
+
+XEN_SYSTEMD_MOUNT = proc-xen.mount
+XEN_SYSTEMD_MOUNT += var-lib-xenstored.mount
+
+XEN_SYSTEMD_SOCKET = xenstored.socket
+XEN_SYSTEMD_SOCKET += xenstored_ro.socket
+
+XEN_SYSTEMD_SERVICE = xenstored.service
+XEN_SYSTEMD_SERVICE += xenconsoled.service
+XEN_SYSTEMD_SERVICE += xen-qemu-dom0-disk-backend.service
+XEN_SYSTEMD_SERVICE += xendomains.service
+XEN_SYSTEMD_SERVICE += xen-watchdog.service
+XEN_SYSTEMD_SERVICE += xen-init-dom0.service
+
+ALL_XEN_SYSTEMD = $(XEN_SYSTEMD_MODULES) \
+ $(XEN_SYSTEMD_MOUNT) \
+ $(XEN_SYSTEMD_SOCKET) \
+ $(XEN_SYSTEMD_SERVICE)
+
+.PHONY: all
+all: $(ALL_XEN_SYSTEMD)
+
+.PHONY: clean
+clean:
+ rm -f $(XEN_SYSTEMD_MODULES)
+
+.PHONY: install
+install: $(ALL_XEN_SYSTEMD)
+ [ -d $(DESTDIR)$(XEN_SYSTEMD_DIR) ] || \
+ $(INSTALL_DIR) $(DESTDIR)$(XEN_SYSTEMD_DIR)
+ [ -d $(DESTDIR)$(XEN_SYSTEMD_MODULES_LOAD) ] || \
+ $(INSTALL_DIR) $(DESTDIR)$(XEN_SYSTEMD_MODULES_LOAD)
+ $(INSTALL_DATA) *.socket $(DESTDIR)$(XEN_SYSTEMD_DIR)
+ $(INSTALL_DATA) *.service $(DESTDIR)$(XEN_SYSTEMD_DIR)
+ $(INSTALL_DATA) *.mount $(DESTDIR)$(XEN_SYSTEMD_DIR)
+ $(INSTALL_DATA) *.conf $(DESTDIR)$(XEN_SYSTEMD_MODULES_LOAD)
+
+$(XEN_SYSTEMD_MODULES):
+ rm -f $@.tmp
+ for mod in $(LINUX_BACKEND_MODULES) ; do \
+ echo $$mod ; \
+ done > $@.tmp
+ $(call move-if-changed,$@.tmp,$@)
diff --git a/tools/hotplug/Linux/systemd/proc-xen.mount.in b/tools/hotplug/Linux/systemd/proc-xen.mount.in
new file mode 100644
index 0000000..64ebe7f
--- /dev/null
+++ b/tools/hotplug/Linux/systemd/proc-xen.mount.in
@@ -0,0 +1,10 @@
+[Unit]
+Description=Mount /proc/xen files
+ConditionPathExists=/proc/xen
+ConditionPathExists=!/proc/xen/capabilities
+RefuseManualStop=true
+
+[Mount]
+What=xenfs
+Where=/proc/xen
+Type=xenfs
diff --git a/tools/hotplug/Linux/systemd/show_service_dependencies.sh b/tools/hotplug/Linux/systemd/show_service_dependencies.sh
new file mode 100644
index 0000000..e3e4c68
--- /dev/null
+++ b/tools/hotplug/Linux/systemd/show_service_dependencies.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# dot(1) from graphviz, display(1) from ImageMagick
+# Usage: bash $0 tools/hotplug/Linux/systemd/*.in
+(
+echo " digraph systemd {"
+for file in "$@"
+do
+ if test -f "$file"
+ then
+ unit=${file##*/}
+ unit=${unit%.in}
+ requires="`grep ^Requires= $file | cut -f 2- -d =`"
+ before="`grep ^Before= $file | cut -f 2- -d =`"
+ after="`grep ^After= $file | cut -f 2- -d =`"
+ echo "\"$unit\" [fillcolor=lightgray color=black fontcolor=black style=filled];"
+ for i in $requires
+ do
+ echo "\"$i\" -> \"$unit\" [color=red];"
+ done
+ for i in $after
+ do
+ echo "\"$i\" -> \"$unit\" [color=blue];"
+ done
+ for i in $before
+ do
+ echo "\"$unit\" -> \"$i\" [color=green];"
+ done
+ fi
+done
+echo "}"
+) | dot -Tpng | display -
diff --git a/tools/hotplug/Linux/systemd/var-lib-xenstored.mount.in b/tools/hotplug/Linux/systemd/var-lib-xenstored.mount.in
new file mode 100644
index 0000000..d5e04db
--- /dev/null
+++ b/tools/hotplug/Linux/systemd/var-lib-xenstored.mount.in
@@ -0,0 +1,14 @@
+[Unit]
+Description=mount xenstore file system
+Requires=proc-xen.mount
+After=proc-xen.mount
+ConditionPathExists=/proc/xen/capabilities
+RefuseManualStop=true
+
+[Mount]
+Environment=XENSTORED_MOUNT_CTX=none
+EnvironmentFile=- at CONFIG_DIR@/@CONFIG_LEAF_DIR@/xenstored
+What=xenstore
+Where=@XEN_LIB_STORED@
+Type=tmpfs
+Options=mode=755,context="$XENSTORED_MOUNT_CTX"
diff --git a/tools/hotplug/Linux/systemd/xen-init-dom0.service.in b/tools/hotplug/Linux/systemd/xen-init-dom0.service.in
new file mode 100644
index 0000000..4d4cb23
--- /dev/null
+++ b/tools/hotplug/Linux/systemd/xen-init-dom0.service.in
@@ -0,0 +1,14 @@
+[Unit]
+Description=xen-init-dom0, initialise Dom0 configuration (xenstore nodes, JSON configuration stub)
+Requires=xenstored.socket proc-xen.mount
+After=xenstored.socket proc-xen.mount
+ConditionPathExists=/proc/xen/capabilities
+
+[Service]
+Type=oneshot
+RemainAfterExit=true
+ExecStartPre=/bin/grep -q control_d /proc/xen/capabilities
+ExecStart=@LIBEXEC_BIN@/xen-init-dom0
+
+[Install]
+WantedBy=multi-user.target
diff --git a/tools/hotplug/Linux/systemd/xen-qemu-dom0-disk-backend.service.in b/tools/hotplug/Linux/systemd/xen-qemu-dom0-disk-backend.service.in
new file mode 100644
index 0000000..6b9c96e
--- /dev/null
+++ b/tools/hotplug/Linux/systemd/xen-qemu-dom0-disk-backend.service.in
@@ -0,0 +1,21 @@
+[Unit]
+Description=qemu for xen dom0 disk backend
+Requires=proc-xen.mount xenstored.socket
+After=proc-xen.mount xenstored.socket xenconsoled.service
+Before=xendomains.service libvirtd.service libvirt-guests.service
+RefuseManualStop=true
+ConditionPathExists=/proc/xen/capabilities
+
+[Service]
+Type=simple
+EnvironmentFile=- at CONFIG_DIR@/@CONFIG_LEAF_DIR@/xenstored
+PIDFile=@XEN_RUN_DIR@/qemu-dom0.pid
+ExecStartPre=/bin/grep -q control_d /proc/xen/capabilities
+ExecStartPre=/bin/mkdir -p @XEN_RUN_DIR@
+ExecStart=@LIBEXEC_BIN@/qemu-system-i386 -xen-domid 0 \
+ -xen-attach -name dom0 -nographic -M xenpv -daemonize \
+ -monitor /dev/null -serial /dev/null -parallel /dev/null \
+ -pidfile @XEN_RUN_DIR@/qemu-dom0.pid
+
+[Install]
+WantedBy=multi-user.target
diff --git a/tools/hotplug/Linux/systemd/xen-watchdog.service.in b/tools/hotplug/Linux/systemd/xen-watchdog.service.in
new file mode 100644
index 0000000..1eecd2a
--- /dev/null
+++ b/tools/hotplug/Linux/systemd/xen-watchdog.service.in
@@ -0,0 +1,13 @@
+[Unit]
+Description=Xen-watchdog - run xen watchdog daemon
+Requires=proc-xen.mount
+After=proc-xen.mount xendomains.service
+ConditionPathExists=/proc/xen/capabilities
+
+[Service]
+Type=forking
+ExecStart=@sbindir@/xenwatchdogd 30 15
+KillSignal=USR1
+
+[Install]
+WantedBy=multi-user.target
diff --git a/tools/hotplug/Linux/systemd/xenconsoled.service.in b/tools/hotplug/Linux/systemd/xenconsoled.service.in
new file mode 100644
index 0000000..2c5d99f
--- /dev/null
+++ b/tools/hotplug/Linux/systemd/xenconsoled.service.in
@@ -0,0 +1,19 @@
+[Unit]
+Description=Xenconsoled - handles logging from guest consoles and hypervisor
+Requires=proc-xen.mount xenstored.socket
+After=proc-xen.mount xenstored.socket
+ConditionPathExists=/proc/xen/capabilities
+
+[Service]
+Type=simple
+Environment=XENCONSOLED_ARGS=
+Environment=XENCONSOLED_LOG=none
+Environment=XENCONSOLED_LOG_DIR=@XEN_LOG_DIR@/console
+EnvironmentFile=- at CONFIG_DIR@/@CONFIG_LEAF_DIR@/xenconsoled
+PIDFile=@XEN_RUN_DIR@/xenconsoled.pid
+ExecStartPre=/bin/grep -q control_d /proc/xen/capabilities
+ExecStartPre=/bin/mkdir -p ${XENCONSOLED_LOG_DIR}
+ExecStart=@sbindir@/xenconsoled --pid-file @XEN_RUN_DIR@/xenconsoled.pid --log=${XENCONSOLED_LOG} --log-dir=${XENCONSOLED_LOG_DIR} $XENCONSOLED_ARGS
+
+[Install]
+WantedBy=multi-user.target
diff --git a/tools/hotplug/Linux/systemd/xendomains.service.in b/tools/hotplug/Linux/systemd/xendomains.service.in
new file mode 100644
index 0000000..757278f
--- /dev/null
+++ b/tools/hotplug/Linux/systemd/xendomains.service.in
@@ -0,0 +1,16 @@
+[Unit]
+Description=Xendomains - start and stop guests on boot and shutdown
+Requires=proc-xen.mount xenstored.socket
+After=proc-xen.mount xenstored.socket xenconsoled.service xen-init-dom0.service
+ConditionPathExists=/proc/xen/capabilities
+
+[Service]
+Type=oneshot
+RemainAfterExit=true
+ExecStartPre=/bin/grep -q control_d /proc/xen/capabilities
+ExecStart=- at LIBEXEC_BIN@/xendomains start
+ExecStop=@LIBEXEC_BIN@/xendomains stop
+ExecReload=@LIBEXEC_BIN@/xendomains restart
+
+[Install]
+WantedBy=multi-user.target
diff --git a/tools/hotplug/Linux/systemd/xenstored.service.in b/tools/hotplug/Linux/systemd/xenstored.service.in
new file mode 100644
index 0000000..780bdd6
--- /dev/null
+++ b/tools/hotplug/Linux/systemd/xenstored.service.in
@@ -0,0 +1,24 @@
+[Unit]
+Description=The Xen xenstore
+Requires=xenstored_ro.socket xenstored.socket proc-xen.mount var-lib-xenstored.mount
+After=proc-xen.mount var-lib-xenstored.mount
+Before=libvirtd.service libvirt-guests.service
+RefuseManualStop=true
+ConditionPathExists=/proc/xen/capabilities
+
+[Service]
+Type=notify
+Environment=XENSTORED_ARGS=
+Environment=XENSTORED_ROOTDIR=@XEN_LIB_STORED@
+Environment=XENSTORED=@XENSTORED@
+EnvironmentFile=- at CONFIG_DIR@/@CONFIG_LEAF_DIR@/xencommons
+ExecStartPre=/bin/grep -q control_d /proc/xen/capabilities
+ExecStartPre=-/bin/rm -f @XEN_LIB_STORED@/tdb*
+ExecStartPre=/bin/mkdir -p @XEN_RUN_DIR@
+ExecStart=/bin/sh -c "exec $XENSTORED --no-fork $XENSTORED_ARGS"
+
+[Install]
+WantedBy=multi-user.target
+Also=xenstored_ro.socket xenstored.socket
+Also=proc-xen.mount
+Also=var-lib-xenstored.mount
diff --git a/tools/hotplug/Linux/systemd/xenstored.socket.in b/tools/hotplug/Linux/systemd/xenstored.socket.in
new file mode 100644
index 0000000..2e8ee04
--- /dev/null
+++ b/tools/hotplug/Linux/systemd/xenstored.socket.in
@@ -0,0 +1,13 @@
+[Unit]
+Description=xenstore socket
+Requires=proc-xen.mount var-lib-xenstored.mount
+After=proc-xen.mount var-lib-xenstored.mount
+ConditionPathExists=/proc/xen/capabilities
+
+[Socket]
+ListenStream=/var/run/xenstored/socket
+SocketMode=0600
+Service=xenstored.service
+
+[Install]
+WantedBy=sockets.target
diff --git a/tools/hotplug/Linux/systemd/xenstored_ro.socket.in b/tools/hotplug/Linux/systemd/xenstored_ro.socket.in
new file mode 100644
index 0000000..140ad94
--- /dev/null
+++ b/tools/hotplug/Linux/systemd/xenstored_ro.socket.in
@@ -0,0 +1,13 @@
+[Unit]
+Description=xenstore ro socket
+Requires=proc-xen.mount var-lib-xenstored.mount
+After=proc-xen.mount var-lib-xenstored.mount
+ConditionPathExists=/proc/xen/capabilities
+
+[Socket]
+ListenStream=/var/run/xenstored/socket_ro
+SocketMode=0660
+Service=xenstored.service
+
+[Install]
+WantedBy=sockets.target
diff --git a/tools/hotplug/Linux/vif-bridge b/tools/hotplug/Linux/vif-bridge
index b7dcbd6..3d72ca4 100644
--- a/tools/hotplug/Linux/vif-bridge
+++ b/tools/hotplug/Linux/vif-bridge
@@ -3,10 +3,6 @@
# ${XEN_SCRIPT_DIR}/vif-bridge
#
# Script for configuring a vif in bridged mode.
-# The hotplugging system will call this script if it is specified either in
-# the device configuration given to Xend, or the default Xend configuration
-# in ${XEN_CONFIG_DIR}/xend-config.sxp. If the script is specified in
-# neither of those places, then this script is the default.
#
# Usage:
# vif-bridge (add|remove|online|offline)
@@ -97,9 +93,7 @@ case "$command" in
;;
esac
-if [ "$type_if" = vif ]; then
- handle_iptable
-fi
+handle_iptable
call_hooks vif post
diff --git a/tools/hotplug/Linux/vif-common.sh b/tools/hotplug/Linux/vif-common.sh
index 73ee241..28ddae5 100644
--- a/tools/hotplug/Linux/vif-common.sh
+++ b/tools/hotplug/Linux/vif-common.sh
@@ -123,7 +123,7 @@ ip=$(xenstore_read_default "$XENBUS_PATH/ip" "$ip")
frob_iptable()
{
- if [ "$command" == "online" ]
+ if [ "$command" == "online" -o "$command" == "add" ]
then
local c="-I"
else
@@ -135,7 +135,7 @@ frob_iptable()
iptables "$c" FORWARD -m physdev --physdev-is-bridged --physdev-out "$dev" \
-j ACCEPT 2>/dev/null
- if [ "$command" == "online" -a $? -ne 0 ]
+ if [ \( "$command" == "online" -o "$command" == "add" \) -a $? -ne 0 ]
then
log err "iptables setup failed. This may affect guest networking."
fi
diff --git a/tools/hotplug/Linux/vif-nat b/tools/hotplug/Linux/vif-nat
index 0b900d5..a76d9c7 100644
--- a/tools/hotplug/Linux/vif-nat
+++ b/tools/hotplug/Linux/vif-nat
@@ -3,10 +3,6 @@
# ${XEN_SCRIPT_DIR}/vif-nat
#
# Script for configuring a vif in routed-nat mode.
-# The hotplugging system will call this script if it is specified either in
-# the device configuration given to Xend, or the default Xend configuration
-# in ${XEN_CONFIG_DIR}/xend-config.sxp. If the script is specified in
-# neither of those places, then vif-bridge is the default.
#
# Usage:
# vif-nat (add|remove|online|offline)
diff --git a/tools/hotplug/Linux/vif-openvswitch b/tools/hotplug/Linux/vif-openvswitch
index a8e4fc7..18bfb6c 100644
--- a/tools/hotplug/Linux/vif-openvswitch
+++ b/tools/hotplug/Linux/vif-openvswitch
@@ -3,10 +3,6 @@
# ${XEN_SCRIPT_DIR}/vif-openvswitch
#
# Script for configuring a vif in openvswitch mode.
-# The hotplugging system will call this script if it is specified either in
-# the device configuration given to Xend, or the default Xend configuration
-# in ${XEN_CONFIG_DIR}/xend-config.sxp. If the script is specified in
-# neither of those places, then this script is the default.
#
# Usage:
# vif-openvswitch (add|remove|online|offline)
diff --git a/tools/hotplug/Linux/vif-route b/tools/hotplug/Linux/vif-route
index 02f1403..c149ffc 100644
--- a/tools/hotplug/Linux/vif-route
+++ b/tools/hotplug/Linux/vif-route
@@ -3,10 +3,6 @@
# ${XEN_SCRIPT_DIR}/vif-route
#
# Script for configuring a vif in routed mode.
-# The hotplugging system will call this script if it is specified either in
-# the device configuration given to Xend, or the default Xend configuration
-# in ${XEN_CONFIG_DIR}/xend-config.sxp. If the script is specified in
-# neither of those places, then vif-bridge is the default.
#
# Usage:
# vif-route (add|remove|online|offline)
diff --git a/tools/hotplug/Linux/vif-setup b/tools/hotplug/Linux/vif-setup
deleted file mode 100644
index bcc462e..0000000
--- a/tools/hotplug/Linux/vif-setup
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-if test "$script"
-then
- exec $script $*
-else
- exec /etc/xen/scripts/vif-bridge $*
-fi
-
diff --git a/tools/hotplug/Linux/vif-setup.in b/tools/hotplug/Linux/vif-setup.in
new file mode 100644
index 0000000..c3bc662
--- /dev/null
+++ b/tools/hotplug/Linux/vif-setup.in
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+if test "$script"
+then
+ exec $script $*
+else
+ exec @XEN_SCRIPT_DIR@/vif-bridge $*
+fi
+
diff --git a/tools/hotplug/Linux/xen-backend.rules b/tools/hotplug/Linux/xen-backend.rules
deleted file mode 100644
index a0d409e..0000000
--- a/tools/hotplug/Linux/xen-backend.rules
+++ /dev/null
@@ -1,15 +0,0 @@
-SUBSYSTEM=="xen-backend", KERNEL=="tap*", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scripts/blktap $env{ACTION}"
-SUBSYSTEM=="xen-backend", KERNEL=="vbd*", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scripts/block $env{ACTION}"
-SUBSYSTEM=="xen-backend", KERNEL=="vif2-*", RUN+="/etc/xen/scripts/vif2 $env{ACTION}"
-SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ENV{UDEV_CALL}="1", ACTION=="online", RUN+="/etc/xen/scripts/vif-setup online type_if=vif"
-SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ENV{UDEV_CALL}="1", ACTION=="offline", RUN+="/etc/xen/scripts/vif-setup offline type_if=vif"
-SUBSYSTEM=="xen-backend", KERNEL=="vscsi*", RUN+="/etc/xen/scripts/vscsi $env{ACTION}"
-SUBSYSTEM=="xen-backend", ACTION=="remove", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scripts/xen-hotplug-cleanup"
-KERNEL=="evtchn", NAME="xen/%k"
-SUBSYSTEM=="xen", KERNEL=="blktap[0-9]*", NAME="xen/%k", MODE="0600"
-SUBSYSTEM=="blktap2", KERNEL=="blktap[0-9]*", NAME="xen/blktap-2/%k", MODE="0600"
-KERNEL=="blktap-control", NAME="xen/blktap-2/control", MODE="0600"
-KERNEL=="gntdev", NAME="xen/%k", MODE="0600"
-KERNEL=="pci_iomul", NAME="xen/%k", MODE="0600"
-KERNEL=="tapdev[a-z]*", NAME="xen/blktap-2/tapdev%m", MODE="0600"
-SUBSYSTEM=="net", KERNEL=="vif*-emu", ACTION=="add", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap"
diff --git a/tools/hotplug/Linux/xen-backend.rules.in b/tools/hotplug/Linux/xen-backend.rules.in
new file mode 100644
index 0000000..7d2f914
--- /dev/null
+++ b/tools/hotplug/Linux/xen-backend.rules.in
@@ -0,0 +1,15 @@
+SUBSYSTEM=="xen-backend", KERNEL=="tap*", ENV{UDEV_CALL}="1", RUN+="@XEN_SCRIPT_DIR@/blktap $env{ACTION}"
+SUBSYSTEM=="xen-backend", KERNEL=="vbd*", ENV{UDEV_CALL}="1", RUN+="@XEN_SCRIPT_DIR@/block $env{ACTION}"
+SUBSYSTEM=="xen-backend", KERNEL=="vif2-*", RUN+="@XEN_SCRIPT_DIR@/vif2 $env{ACTION}"
+SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ENV{UDEV_CALL}="1", ACTION=="online", RUN+="@XEN_SCRIPT_DIR@/vif-setup online type_if=vif"
+SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ENV{UDEV_CALL}="1", ACTION=="offline", RUN+="@XEN_SCRIPT_DIR@/vif-setup offline type_if=vif"
+SUBSYSTEM=="xen-backend", KERNEL=="vscsi*", RUN+="@XEN_SCRIPT_DIR@/vscsi $env{ACTION}"
+SUBSYSTEM=="xen-backend", ACTION=="remove", ENV{UDEV_CALL}="1", RUN+="@XEN_SCRIPT_DIR@/xen-hotplug-cleanup"
+KERNEL=="evtchn", NAME="xen/%k"
+SUBSYSTEM=="xen", KERNEL=="blktap[0-9]*", NAME="xen/%k", MODE="0600"
+SUBSYSTEM=="blktap2", KERNEL=="blktap[0-9]*", NAME="xen/blktap-2/%k", MODE="0600"
+KERNEL=="blktap-control", NAME="xen/blktap-2/control", MODE="0600"
+KERNEL=="gntdev", NAME="xen/%k", MODE="0600"
+KERNEL=="pci_iomul", NAME="xen/%k", MODE="0600"
+KERNEL=="tapdev[a-z]*", NAME="xen/blktap-2/tapdev%m", MODE="0600"
+SUBSYSTEM=="net", KERNEL=="vif*-emu", ACTION=="add", ENV{UDEV_CALL}="1", RUN+="@XEN_SCRIPT_DIR@/vif-setup $env{ACTION} type_if=tap"
diff --git a/tools/hotplug/Linux/xen-hotplug-common.sh b/tools/hotplug/Linux/xen-hotplug-common.sh
deleted file mode 100644
index 7af4688..0000000
--- a/tools/hotplug/Linux/xen-hotplug-common.sh
+++ /dev/null
@@ -1,120 +0,0 @@
-#
-# Copyright (c) 2005 XenSource Ltd.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-# Hack to prevent the execution of hotplug scripts from udev if the domain
-# has been launched from libxl
-if [ -n "${UDEV_CALL}" ] && \
- xenstore-read "libxl/disable_udev" >/dev/null 2>&1; then
- exit 0
-fi
-
-dir=$(dirname "$0")
-. "$dir/hotplugpath.sh"
-. "$dir/logging.sh"
-. "$dir/xen-script-common.sh"
-. "$dir/locking.sh"
-
-exec 2>>/var/log/xen/xen-hotplug.log
-
-export PATH="${BINDIR}:${SBINDIR}:${LIBEXEC}:${PRIVATE_BINDIR}:/sbin:/bin:/usr/bin:/usr/sbin:$PATH"
-export LD_LIBRARY_PATH="${LIBDIR}${LD_LIBRARY_PATH+:}$LD_LIBRARY_PATH"
-export LANG="POSIX"
-unset $(set | grep ^LC_ | cut -d= -f1)
-
-fatal() {
- _xenstore_write "$XENBUS_PATH/hotplug-error" "$*" \
- "$XENBUS_PATH/hotplug-status" error
- log err "$@"
- exit 1
-}
-
-success() {
- # Tell DevController that backend is "connected"
- xenstore_write "$XENBUS_PATH/hotplug-status" connected
-}
-
-do_or_die() {
- "$@" || fatal "$@ failed"
-}
-
-do_without_error() {
- "$@" 2>/dev/null || log debug "$@ failed"
-}
-
-sigerr() {
- fatal "$0 failed; error detected."
-}
-
-trap sigerr ERR
-
-
-##
-# xenstore_read <path>+
-#
-# Read each of the given paths, returning each result on a separate line, or
-# exit this script if any of the paths is missing.
-#
-xenstore_read() {
- local v=$(xenstore-read "$@" || true)
- [ "$v" != "" ] || fatal "xenstore-read $@ failed."
- echo "$v"
-}
-
-
-##
-# xenstore_read_default <path> <default>
-#
-# Read the given path, returning the value there or the given default if the
-# path is not present.
-#
-xenstore_read_default() {
- xenstore-read "$1" 2>/dev/null || echo "$2"
-}
-
-
-##
-# _xenstore_write (<path> <value>)+
-#
-# Write each of the key/value pairs to the store.
-#
-_xenstore_write() {
- log debug "Writing $@ to xenstore."
- xenstore-write "$@"
-}
-
-##
-# xenstore_write (<path> <value>)+
-#
-# Write each of the key/value pairs to the store, and exit this script if any
-# such writing fails.
-#
-xenstore_write() {
- _xenstore_write "$@" || fatal "Writing $@ to xenstore failed."
-}
-
-##
-# call_hooks <devtype> <hook>
-#
-# Execute each hook in the <hook> directory.
-#
-call_hooks() {
- for f in /etc/xen/scripts/${1}-${2}.d/*.hook; do
- if [ -x "$f" ]; then . "$f"; fi
- done
-}
-
-log debug "$@" "XENBUS_PATH=$XENBUS_PATH"
diff --git a/tools/hotplug/Linux/xen-hotplug-common.sh.in b/tools/hotplug/Linux/xen-hotplug-common.sh.in
new file mode 100644
index 0000000..1deafe1
--- /dev/null
+++ b/tools/hotplug/Linux/xen-hotplug-common.sh.in
@@ -0,0 +1,120 @@
+#
+# Copyright (c) 2005 XenSource Ltd.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+# Hack to prevent the execution of hotplug scripts from udev if the domain
+# has been launched from libxl
+if [ -n "${UDEV_CALL}" ] && \
+ xenstore-read "libxl/disable_udev" >/dev/null 2>&1; then
+ exit 0
+fi
+
+dir=$(dirname "$0")
+. "$dir/hotplugpath.sh"
+. "$dir/logging.sh"
+. "$dir/xen-script-common.sh"
+. "$dir/locking.sh"
+
+exec 2>>/var/log/xen/xen-hotplug.log
+
+export PATH="${BINDIR}:${SBINDIR}:${LIBEXEC_BIN}:/sbin:/bin:/usr/bin:/usr/sbin:$PATH"
+export LD_LIBRARY_PATH="${LIBDIR}${LD_LIBRARY_PATH+:}$LD_LIBRARY_PATH"
+export LANG="POSIX"
+unset $(set | grep ^LC_ | cut -d= -f1)
+
+fatal() {
+ _xenstore_write "$XENBUS_PATH/hotplug-error" "$*" \
+ "$XENBUS_PATH/hotplug-status" error
+ log err "$@"
+ exit 1
+}
+
+success() {
+ # Tell DevController that backend is "connected"
+ xenstore_write "$XENBUS_PATH/hotplug-status" connected
+}
+
+do_or_die() {
+ "$@" || fatal "$@ failed"
+}
+
+do_without_error() {
+ "$@" 2>/dev/null || log debug "$@ failed"
+}
+
+sigerr() {
+ fatal "$0 failed; error detected."
+}
+
+trap sigerr ERR
+
+
+##
+# xenstore_read <path>+
+#
+# Read each of the given paths, returning each result on a separate line, or
+# exit this script if any of the paths is missing.
+#
+xenstore_read() {
+ local v=$(xenstore-read "$@" || true)
+ [ "$v" != "" ] || fatal "xenstore-read $@ failed."
+ echo "$v"
+}
+
+
+##
+# xenstore_read_default <path> <default>
+#
+# Read the given path, returning the value there or the given default if the
+# path is not present.
+#
+xenstore_read_default() {
+ xenstore-read "$1" 2>/dev/null || echo "$2"
+}
+
+
+##
+# _xenstore_write (<path> <value>)+
+#
+# Write each of the key/value pairs to the store.
+#
+_xenstore_write() {
+ log debug "Writing $@ to xenstore."
+ xenstore-write "$@"
+}
+
+##
+# xenstore_write (<path> <value>)+
+#
+# Write each of the key/value pairs to the store, and exit this script if any
+# such writing fails.
+#
+xenstore_write() {
+ _xenstore_write "$@" || fatal "Writing $@ to xenstore failed."
+}
+
+##
+# call_hooks <devtype> <hook>
+#
+# Execute each hook in the <hook> directory.
+#
+call_hooks() {
+ for f in @XEN_SCRIPT_DIR@/${1}-${2}.d/*.hook; do
+ if [ -x "$f" ]; then . "$f"; fi
+ done
+}
+
+log debug "$@" "XENBUS_PATH=$XENBUS_PATH"
diff --git a/tools/hotplug/Linux/xend.rules b/tools/hotplug/Linux/xend.rules
deleted file mode 100644
index 4d79ac0..0000000
--- a/tools/hotplug/Linux/xend.rules
+++ /dev/null
@@ -1,4 +0,0 @@
-SUBSYSTEM=="pci", RUN+="socket:/org/xen/xend/udev_event"
-SUBSYSTEM=="scsi", RUN+="socket:/org/xen/xend/udev_event"
-SUBSYSTEM=="usb", RUN+="socket:/org/xen/xend/udev_event"
-#SUBSYSTEM=="net", KERNEL!="vif[0-9]*.[0-9]*|tap[0-9]*.[0-9]*", RUN+="socket:/org/xen/xend/udev_event"
diff --git a/tools/hotplug/Linux/xendomains.in b/tools/hotplug/Linux/xendomains.in
new file mode 100644
index 0000000..2e65ac6
--- /dev/null
+++ b/tools/hotplug/Linux/xendomains.in
@@ -0,0 +1,575 @@
+#!/bin/bash
+#
+# /etc/init.d/xendomains
+# Start / stop domains automatically when domain 0 boots / shuts down.
+#
+# chkconfig: 345 99 00
+# description: Start / stop Xen domains.
+#
+# This script offers fairly basic functionality. It should work on Redhat
+# but also on LSB-compliant SuSE releases and on Debian with the LSB package
+# installed. (LSB is the Linux Standard Base)
+#
+# Based on the example in the "Designing High Quality Integrated Linux
+# Applications HOWTO" by Avi Alkalay
+# <http://www.tldp.org/HOWTO/HighQuality-Apps-HOWTO/>
+#
+### BEGIN INIT INFO
+# Provides: xendomains
+# Required-Start: $syslog $remote_fs xenstored xenconsoled
+# Should-Start: xend
+# Required-Stop: $syslog $remote_fs xenstored xenconsoled
+# Should-Stop: xend
+# Default-Start: 2 3 5
+# Default-Stop: 0 1 6
+# Short-Description: Start/stop secondary xen domains
+# Description: Start / stop domains automatically when domain 0
+# boots / shuts down.
+### END INIT INFO
+
+. @XEN_SCRIPT_DIR@/hotplugpath.sh
+
+CMD=${SBINDIR}/xl
+HEADCOMP="Xen saved domain"
+$CMD list &> /dev/null
+if test $? -ne 0
+then
+ exit $?
+fi
+
+$CMD list &> /dev/null
+if test $? -ne 0
+then
+ exit 0;
+fi
+
+# Correct exit code would probably be 5, but it's enough
+# if xend complains if we're not running as privileged domain
+if ! [ -e /proc/xen/privcmd ]; then
+ exit 0
+fi
+
+LOCKFILE=${XEN_LOCK_DIR}/xendomains
+
+XENDOM_CONFIG=@CONFIG_DIR@/@CONFIG_LEAF_DIR@/xendomains
+
+test -r $XENDOM_CONFIG || { echo "$XENDOM_CONFIG not existing";
+ if [ "$1" = "stop" ]; then exit 0;
+ else exit 6; fi; }
+
+. $XENDOM_CONFIG
+
+# Use the SUSE rc_ init script functions;
+# emulate them on LSB, RH and other systems
+if test -e /etc/rc.status; then
+ # SUSE rc script library
+ . /etc/rc.status
+else
+ _cmd=$1
+ declare -a _SMSG
+ if test "${_cmd}" = "status"; then
+ _SMSG=(running dead dead unused unknown)
+ _RC_UNUSED=3
+ else
+ _SMSG=(done failed failed missed failed skipped unused failed failed)
+ _RC_UNUSED=6
+ fi
+ if test -e /etc/init.d/functions; then
+ # REDHAT
+ . /etc/init.d/functions
+ echo_rc()
+ {
+ #echo -n " [${_SMSG[${_RC_RV}]}] "
+ if test ${_RC_RV} = 0; then
+ success " [${_SMSG[${_RC_RV}]}] "
+ else
+ failure " [${_SMSG[${_RC_RV}]}] "
+ fi
+ }
+ elif test -e /lib/lsb/init-functions; then
+ # LSB
+ . /lib/lsb/init-functions
+ if alias log_success_msg >/dev/null 2>/dev/null; then
+ echo_rc()
+ {
+ echo " [${_SMSG[${_RC_RV}]}] "
+ }
+ else
+ echo_rc()
+ {
+ if test ${_RC_RV} = 0; then
+ log_success_msg " [${_SMSG[${_RC_RV}]}] "
+ else
+ log_failure_msg " [${_SMSG[${_RC_RV}]}] "
+ fi
+ }
+ fi
+ else
+ # emulate it
+ echo_rc()
+ {
+ echo " [${_SMSG[${_RC_RV}]}] "
+ }
+ fi
+ rc_reset() { _RC_RV=0; }
+ rc_failed()
+ {
+ if test -z "$1"; then
+ _RC_RV=1;
+ elif test "$1" != "0"; then
+ _RC_RV=$1;
+ fi
+ return ${_RC_RV}
+ }
+ rc_check()
+ {
+ return rc_failed $?
+ }
+ rc_status()
+ {
+ rc_failed $?
+ if test "$1" = "-r"; then _RC_RV=0; shift; fi
+ if test "$1" = "-s"; then rc_failed 5; echo_rc; rc_failed 3; shift; fi
+ if test "$1" = "-u"; then rc_failed ${_RC_UNUSED}; echo_rc; rc_failed 3; shift; fi
+ if test "$1" = "-v"; then echo_rc; shift; fi
+ if test "$1" = "-r"; then _RC_RV=0; shift; fi
+ return ${_RC_RV}
+ }
+ rc_exit() { exit ${_RC_RV}; }
+ rc_active()
+ {
+ if test -z "$RUNLEVEL"; then read RUNLEVEL REST < <(/sbin/runlevel); fi
+ if test -e /etc/init.d/S[0-9][0-9]${1}; then return 0; fi
+ return 1
+ }
+fi
+
+if ! which usleep >&/dev/null
+then
+ usleep()
+ {
+ if [ -n "$1" ]
+ then
+ sleep $(( $1 / 1000000 ))
+ fi
+ }
+fi
+
+# Reset status of this service
+rc_reset
+
+##
+# Returns 0 (success) if the given parameter names a directory, and that
+# directory is not empty.
+#
+contains_something()
+{
+ if [ -d "$1" ] && [ `/bin/ls $1 | wc -l` -gt 0 ]
+ then
+ return 0
+ else
+ return 1
+ fi
+}
+
+# read name from xen config file
+rdname()
+{
+ NM=$($CMD create --quiet --dryrun --defconfig "$1" |
+ sed -n 's/^.*(name \(.*\))$/\1/p;s/^.*"name": "\(.*\)",$/\1/p')
+}
+
+rdnames()
+{
+ NAMES=
+ if ! contains_something "$XENDOMAINS_AUTO"
+ then
+ return
+ fi
+ for dom in $XENDOMAINS_AUTO/*; do
+ rdname $dom
+ if test -z $NAMES; then
+ NAMES=$NM;
+ else
+ NAMES="$NAMES|$NM"
+ fi
+ done
+}
+
+LIST_GREP='(domain\|(domid\|(name\|^ {$\|"name":\|"domid":'
+parseln()
+{
+ if [[ "$1" =~ '(domain' ]] || [[ "$1" = "{" ]]; then
+ name=;id=
+ elif [[ "$1" =~ '(name' ]]; then
+ name=$(echo $1 | sed -e 's/^.*(name \(.*\))$/\1/')
+ elif [[ "$1" =~ '(domid' ]]; then
+ id=$(echo $1 | sed -e 's/^.*(domid \(.*\))$/\1/')
+ elif [[ "$1" =~ '"name":' ]]; then
+ name=$(echo $1 | sed -e 's/^.*"name": "\(.*\)",$/\1/')
+ elif [[ "$1" =~ '"domid":' ]]; then
+ id=$(echo $1 | sed -e 's/^.*"domid": \(.*\),$/\1/')
+ fi
+
+ [ -n "$name" -a -n "$id" ] && return 0 || return 1
+}
+
+is_running()
+{
+ rdname $1
+ RC=1
+ name=;id=
+ while read LN; do
+ parseln "$LN" || continue
+ if test $id = 0; then continue; fi
+ case $name in
+ ($NM)
+ RC=0
+ ;;
+ esac
+ done < <($CMD list -l | grep "$LIST_GREP")
+ return $RC
+}
+
+start()
+{
+ if [ -f $LOCKFILE ]; then
+ echo -e "xendomains already running (lockfile exists)"
+ return;
+ fi
+
+ saved_domains=" "
+ if [ "$XENDOMAINS_RESTORE" = "true" ] &&
+ contains_something "$XENDOMAINS_SAVE"
+ then
+ mkdir -p $(dirname "$LOCKFILE")
+ touch $LOCKFILE
+ echo -n "Restoring Xen domains:"
+ saved_domains=`ls $XENDOMAINS_SAVE`
+ for dom in $XENDOMAINS_SAVE/*; do
+ if [ -f $dom ] ; then
+ HEADER=`head -c 16 $dom | head -n 1 2> /dev/null`
+ if [ "$HEADER" = "$HEADCOMP" ]; then
+ echo -n " ${dom##*/}"
+ XMR=`$CMD restore $dom 2>&1 1>/dev/null`
+ #$CMD restore $dom
+ if [ $? -ne 0 ]; then
+ echo -e "\nAn error occurred while restoring domain ${dom##*/}:\n$XMR"
+ rc_failed $?
+ echo -e '!'
+ else
+ # mv $dom ${dom%/*}/.${dom##*/}
+ rm $dom
+ fi
+ fi
+ fi
+ done
+ echo -e
+ fi
+
+ if contains_something "$XENDOMAINS_AUTO"
+ then
+ touch $LOCKFILE
+ echo -n "Starting auto Xen domains:"
+ # We expect config scripts for auto starting domains to be in
+ # XENDOMAINS_AUTO - they could just be symlinks to files elsewhere
+
+ # Create all domains with config files in XENDOMAINS_AUTO.
+ # TODO: We should record which domain name belongs
+ # so we have the option to selectively shut down / migrate later
+ # If a domain statefile from $XENDOMAINS_SAVE matches a domain name
+ # in $XENDOMAINS_AUTO, do not try to start that domain; if it didn't
+ # restore correctly it requires administrative attention.
+ for dom in $XENDOMAINS_AUTO/*; do
+ echo -n " ${dom##*/}"
+ shortdom=$(echo $dom | sed -n 's/^.*\/\(.*\)$/\1/p')
+ echo $saved_domains | grep -w $shortdom > /dev/null
+ if [ $? -eq 0 ] || is_running $dom; then
+ echo -n "(skip)"
+ else
+ XMC=`$CMD create --quiet --defconfig $dom`
+ if [ $? -ne 0 ]; then
+ echo -e "\nAn error occurred while creating domain ${dom##*/}: $XMC\n"
+ rc_failed $?
+ echo -e '!'
+ else
+ usleep $XENDOMAINS_CREATE_USLEEP
+ fi
+ fi
+ done
+ fi
+}
+
+all_zombies()
+{
+ name=;id=
+ while read LN; do
+ parseln "$LN" || continue
+ if test $id = 0; then continue; fi
+ if test "$state" != "-b---d" -a "$state" != "-----d"; then
+ return 1;
+ fi
+ done < <($CMD list -l | grep "$LIST_GREP")
+ return 0
+}
+
+# Wait for max $XENDOMAINS_STOP_MAXWAIT for $CMD $1 to finish;
+# if it has not exited by that time kill it, so the init script will
+# succeed within a finite amount of time; if $2 is nonnull, it will
+# kill the command as well as soon as no domain (except for zombies)
+# are left (used for shutdown --all). Third parameter, if any, suppresses
+# output of dots per working state (formatting issues)
+watchdog_xencmd()
+{
+ if test -z "$XENDOMAINS_STOP_MAXWAIT" -o "$XENDOMAINS_STOP_MAXWAIT" = "0"; then
+ exit
+ fi
+
+ usleep 20000
+ for no in `seq 0 $XENDOMAINS_STOP_MAXWAIT`; do
+ # exit if $CMD save/migrate/shutdown is finished
+ PSAX=`ps axlw | grep "$CMD $1" | grep -v grep`
+ if test -z "$PSAX"; then exit; fi
+ if ! test -n "$3"; then echo -n '.'; fi
+ sleep 1
+ # go to kill immediately if there's only zombies left
+ if all_zombies && test -n "$2"; then break; fi
+ done
+ sleep 1
+ read PSF PSUID PSPID PSPPID < <(echo "$PSAX")
+ # kill $CMD $1
+ kill $PSPID >/dev/null 2>&1
+
+ echo -e .
+}
+
+stop()
+{
+ exec 3>&2 2> /dev/null
+
+ # Collect list of domains to shut down
+ if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
+ rdnames
+ fi
+ echo -n "Shutting down Xen domains:"
+ name=;id=
+ while read LN; do
+ parseln "$LN" || continue
+ if test $id = 0; then continue; fi
+ echo -n " $name"
+ if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
+ eval "
+ case \"\$name\" in
+ ($NAMES)
+ # nothing
+ ;;
+ (*)
+ echo -e '(skip)'
+ continue
+ ;;
+ esac
+ "
+ fi
+ # XENDOMAINS_SYSRQ chould be something like just "s"
+ # or "s e i u" or even "s e s i u o"
+ # for the latter, you should set XENDOMAINS_USLEEP to 1200000 or so
+ if test -n "$XENDOMAINS_SYSRQ"; then
+ for sysrq in $XENDOMAINS_SYSRQ; do
+ echo -n "(SR-$sysrq)"
+ XMR=`$CMD sysrq $id $sysrq 2>&1 1>/dev/null`
+ if test $? -ne 0; then
+ echo -e "\nAn error occurred while doing sysrq on domain:\n$XMR\n"
+ rc_failed $?
+ echo -n '!'
+ fi
+ # usleep just ignores empty arg
+ usleep $XENDOMAINS_USLEEP
+ done
+ fi
+ if test "$state" = "-b---d" -o "$state" = "-----d"; then
+ echo -n "(zomb)"
+ continue
+ fi
+ if test -n "$XENDOMAINS_MIGRATE"; then
+ echo -n "(migr)"
+ watchdog_xencmd migrate &
+ WDOG_PID=$!
+ XMR=`$CMD migrate $id $XENDOMAINS_MIGRATE 2>&1 1>/dev/null`
+ if test $? -ne 0; then
+ echo -e "\nAn error occurred while migrating domain:\n$XMR\n"
+ rc_failed $?
+ echo -e '!'
+
+ kill $WDOG_PID >/dev/null 2>&1
+ else
+ kill $WDOG_PID >/dev/null 2>&1
+
+ echo -e .
+ usleep 1000
+ continue
+ fi
+ fi
+ if test -n "$XENDOMAINS_SAVE"; then
+ echo -n "(save)"
+ watchdog_xencmd save &
+ WDOG_PID=$!
+ mkdir -p "$XENDOMAINS_SAVE"
+ XMR=`$CMD save $id $XENDOMAINS_SAVE/$name 2>&1 1>/dev/null`
+ if test $? -ne 0; then
+ echo -e "\nAn error occurred while saving domain:\n$XMR\n"
+ rc_failed $?
+ echo -e '!'
+ kill $WDOG_PID >/dev/null 2>&1
+ else
+ kill $WDOG_PID >/dev/null 2>&1
+ echo -e .
+ usleep 1000
+ continue
+ fi
+ fi
+ if test -n "$XENDOMAINS_SHUTDOWN"; then
+ # XENDOMAINS_SHUTDOWN should be "--wait"
+ echo -n "(shut)"
+ watchdog_xencmd shutdown &
+ WDOG_PID=$!
+ XMR=`$CMD shutdown $XENDOMAINS_SHUTDOWN $id 2>&1 1>/dev/null`
+ if test $? -ne 0; then
+ echo -e "\nAn error occurred while shutting down domain:\n$XMR\n"
+ rc_failed $?
+ echo -e '!'
+ fi
+ kill $WDOG_PID >/dev/null 2>&1
+ fi
+ done < <($CMD list -l | grep "$LIST_GREP")
+
+ # NB. this shuts down ALL Xen domains (politely), not just the ones in
+ # AUTODIR/*
+ # This is because it's easier to do ;-) but arguably if this script is run
+ # on system shutdown then it's also the right thing to do.
+ if ! all_zombies && test -n "$XENDOMAINS_SHUTDOWN_ALL"; then
+ # XENDOMAINS_SHUTDOWN_ALL should be "--all --wait"
+ echo -n " SHUTDOWN_ALL "
+ watchdog_xencmd shutdown 1 false &
+ WDOG_PID=$!
+ XMR=`$CMD shutdown $XENDOMAINS_SHUTDOWN_ALL 2>&1 1>/dev/null`
+ if test $? -ne 0; then
+ echo -e "\nAn error occurred while shutting down all domains: $XMR\n"
+ rc_failed $?
+ echo -e '!'
+ fi
+ kill $WDOG_PID >/dev/null 2>&1
+ fi
+
+ # Unconditionally delete lock file
+ rm -f $LOCKFILE
+
+ exec 2>&3
+}
+
+check_domain_up()
+{
+ name=;id=
+ while read LN; do
+ parseln "$LN" || continue
+ if test $id = 0; then continue; fi
+ case $name in
+ ($1)
+ return 0
+ ;;
+ esac
+ done < <($CMD list -l | grep "$LIST_GREP")
+ return 1
+}
+
+check_all_auto_domains_up()
+{
+ if ! contains_something "$XENDOMAINS_AUTO"
+ then
+ return 0
+ fi
+ missing=
+ for nm in $XENDOMAINS_AUTO/*; do
+ rdname $nm
+ found=0
+ if check_domain_up "$NM"; then
+ echo -n " $name"
+ else
+ missing="$missing $NM"
+ fi
+ done
+ if test -n "$missing"; then
+ echo -n " MISS AUTO:$missing"
+ return 1
+ fi
+ return 0
+}
+
+check_all_saved_domains_up()
+{
+ if ! contains_something "$XENDOMAINS_SAVE"
+ then
+ return 0
+ fi
+ missing=`/bin/ls $XENDOMAINS_SAVE`
+ echo -n " MISS SAVED: " $missing
+ return 1
+}
+
+# This does NOT necessarily restart all running domains: instead it
+# stops all running domains and then boots all the domains specified in
+# AUTODIR. If other domains have been started manually then they will
+# not get restarted.
+# Commented out to avoid confusion!
+
+restart()
+{
+ stop
+ start
+}
+
+reload()
+{
+ restart
+}
+
+
+case "$1" in
+ start)
+ start
+ rc_status
+ if test -f $LOCKFILE; then rc_status -v; fi
+ ;;
+
+ stop)
+ stop
+ rc_status -v
+ ;;
+
+ restart)
+ restart
+ ;;
+ reload)
+ reload
+ ;;
+
+ status)
+ echo -n "Checking for xendomains:"
+ if test ! -f $LOCKFILE; then
+ rc_failed 3
+ else
+ check_all_auto_domains_up
+ rc_status
+ check_all_saved_domains_up
+ rc_status
+ fi
+ rc_status -v
+ ;;
+
+ *)
+ echo "Usage: $0 {start|stop|restart|reload|status}"
+ rc_failed 3
+ rc_status -v
+ ;;
+esac
+
+rc_exit
diff --git a/tools/hotplug/Makefile b/tools/hotplug/Makefile
index f147b59..14ae9a8 100644
--- a/tools/hotplug/Makefile
+++ b/tools/hotplug/Makefile
@@ -4,6 +4,7 @@ include $(XEN_ROOT)/tools/Rules.mk
SUBDIRS-y := common
SUBDIRS-$(CONFIG_NetBSD) += NetBSD
SUBDIRS-$(CONFIG_Linux) += Linux
+SUBDIRS-$(CONFIG_FreeBSD) += FreeBSD
.PHONY: all clean install
all clean install: %: subdirs-%
diff --git a/tools/hotplug/NetBSD/Makefile b/tools/hotplug/NetBSD/Makefile
index 3d7f222..0a370b8 100644
--- a/tools/hotplug/NetBSD/Makefile
+++ b/tools/hotplug/NetBSD/Makefile
@@ -8,8 +8,7 @@ XEN_SCRIPTS += vif-bridge
XEN_SCRIPTS += vif-ip
XEN_SCRIPT_DATA =
-XEN_RCD_PROG-$(CONFIG_XEND) = rc.d/xend
-XEN_RCD_PROG = rc.d/xencommons $(XEN_RCD_PROG-y) rc.d/xendomains rc.d/xen-watchdog
+XEN_RCD_PROG = rc.d/xencommons rc.d/xendomains rc.d/xen-watchdog
.PHONY: all
all:
@@ -18,7 +17,7 @@ all:
build:
.PHONY: install
-install: all install-scripts install-rcd
+install: install-scripts install-rcd
.PHONY: install-scripts
install-scripts:
@@ -34,12 +33,12 @@ install-scripts:
.PHONY: install-rcd
install-rcd:
- $(INSTALL_DIR) $(DESTDIR)$(CONFIG_DIR)/rc.d
+ $(INSTALL_DIR) $(DESTDIR)$(INITD_DIR)
set -e; for i in $(XEN_RCD_PROG); \
do \
- $(INSTALL_PROG) $$i $(DESTDIR)$(CONFIG_DIR)/rc.d; \
+ $(INSTALL_PROG) $$i $(DESTDIR)$(INITD_DIR); \
done
- $(INSTALL_DATA) ../common/hotplugpath.sh $(DESTDIR)$(CONFIG_DIR)/rc.d/xen-hotplugpath.sh
+ $(INSTALL_DATA) ../common/hotplugpath.sh $(DESTDIR)$(INITD_DIR)/xen-hotplugpath.sh
.PHONY: clean
clean:
diff --git a/tools/hotplug/NetBSD/block b/tools/hotplug/NetBSD/block
index f1146b5..b2e9af5 100644
--- a/tools/hotplug/NetBSD/block
+++ b/tools/hotplug/NetBSD/block
@@ -7,7 +7,7 @@
DIR=$(dirname "$0")
. "${DIR}/hotplugpath.sh"
-PATH=${BINDIR}:${SBINDIR}:${LIBEXEC}:${PRIVATE_BINDIR}:/bin:/usr/bin:/sbin:/usr/sbin
+PATH=${BINDIR}:${SBINDIR}:${LIBEXEC_BIN}:/bin:/usr/bin:/sbin:/usr/sbin
export PATH
error() {
diff --git a/tools/hotplug/NetBSD/rc.d/xencommons b/tools/hotplug/NetBSD/rc.d/xencommons
deleted file mode 100644
index b1c3531..0000000
--- a/tools/hotplug/NetBSD/rc.d/xencommons
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/bin/sh
-#
-# PROVIDE: xencommons
-# REQUIRE: DAEMON
-
-. /etc/rc.subr
-
-DIR=$(dirname "$0")
-. "${DIR}/xen-hotplugpath.sh"
-
-LD_LIBRARY_PATH="${LIBDIR}"
-export LD_LIBRARY_PATH
-
-name="xencommons"
-rcvar=xend
-start_precmd="xen_precmd"
-start_cmd="xen_startcmd"
-stop_cmd="xen_stop"
-status_cmd="xen_status"
-extra_commands="status"
-required_files="/kern/xen/privcmd"
-
-XENSTORED_PIDFILE="/var/run/xenstored.pid"
-XENCONSOLED_PIDFILE="/var/run/xenconsoled.pid"
-XENBACKENDD_PIDFILE="/var/run/xenbackendd.pid"
-#XENBACKENDD_DEBUG=1
-#XENCONSOLED_TRACE="/var/log/xen/xenconsole-trace.log"
-#XENSTORED_TRACE="/var/log/xen/xenstore-trace.log"
-
-xen_precmd()
-{
- mkdir -p /var/run/xenstored || exit 1
-}
-
-xen_startcmd()
-{
- local time=0
- local timeout=30
-
- xenstored_pid=$(check_pidfile ${XENSTORED_PIDFILE} ${SBINDIR}/xenstored)
- if test -z "$xenstored_pid"; then
- printf "Cleaning xenstore database.\n"
- if [ -z "${XENSTORED_ROOTDIR}" ]; then
- XENSTORED_ROOTDIR="/var/lib/xenstored"
- fi
- rm -f ${XENSTORED_ROOTDIR}/tdb* >/dev/null 2>&1
- printf "Starting xenservices: xenstored, xenconsoled."
- XENSTORED_ARGS=" --pid-file ${XENSTORED_PIDFILE}"
- if [ -n "${XENSTORED_TRACE}" ]; then
- XENSTORED_ARGS="${XENSTORED_ARGS} -T /var/log/xen/xenstored-trace.log"
- fi
- ${SBINDIR}/xenstored ${XENSTORED_ARGS}
- while [ $time -lt $timeout ] && ! `${BINDIR}/xenstore-read -s / >/dev/null 2>&1` ; do
- printf "."
- time=$(($time+1))
- sleep 1
- done
- else
- printf "Starting xenservices: xenconsoled."
- fi
-
- XENCONSOLED_ARGS=""
- if [ -n "${XENCONSOLED_TRACE}" ]; then
- XENCONSOLED_ARGS="${XENCONSOLED_ARGS} --log=${XENCONSOLED_TRACE}"
- fi
-
- ${SBINDIR}/xenconsoled ${XENCONSOLED_ARGS}
-
- printf "\n"
-
- printf "Setting domain 0 name and domid.\n"
- ${BINDIR}/xenstore-write "/local/domain/0/name" "Domain-0"
- ${BINDIR}/xenstore-write "/local/domain/0/domid" 0
-}
-
-xen_stop()
-{
- pids=""
- printf "Stopping xencommons.\n"
- printf "WARNING: Not stopping xenstored, as it cannot be restarted.\n"
-
- rc_pid=$(check_pidfile ${XENCONSOLED_PIDFILE} ${SBINDIR}/xenconsoled)
- pids="$pids $rc_pid"
-
- kill -${sig_stop:-TERM} $pids
- wait_for_pids $pids
-}
-
-xen_status()
-{
- xenstored_pid=$(check_pidfile ${XENSTORED_PIDFILE} ${SBINDIR}/xenstored)
- if test -n ${xenstored_pid}; then
- pids="$pids $xenstored_pid"
- fi
-
- xenconsoled_pid=$(check_pidfile ${XENCONSOLED_PIDFILE} ${SBINDIR}/xenconsoled)
- if test -n ${xenconsoled_pid}; then
- pids="$pids $xenconsoled_pid"
- fi
-
- if test -n "$xenconsoled_pid" -a -n "$xenstored_pid";
- then
- echo "xencommons are running as pids $pids."
- return 0
- fi
- if test -z "$xenconsoled_pid" -a -z "$xenstored_pid";
- then
- echo "xencommons are not running."
- return 0
- fi
-
- if test -n $xenstored_pid; then
- echo "xenstored is running as pid $xenstored_pid."
- else
- echo "xenstored is not running."
- fi
- if test -n $xenconsoled_pid; then
- echo "xenconsoled is running as pid $xenconsoled_pid."
- else
- echo "xenconsoled is not running."
- fi
-}
-
-load_rc_config $name
-run_rc_command "$1"
diff --git a/tools/hotplug/NetBSD/rc.d/xencommons.in b/tools/hotplug/NetBSD/rc.d/xencommons.in
new file mode 100644
index 0000000..db03f22
--- /dev/null
+++ b/tools/hotplug/NetBSD/rc.d/xencommons.in
@@ -0,0 +1,124 @@
+#!/bin/sh
+#
+# PROVIDE: xencommons
+# REQUIRE: DAEMON
+
+. /etc/rc.subr
+
+DIR=$(dirname "$0")
+. "${DIR}/xen-hotplugpath.sh"
+
+LD_LIBRARY_PATH="${LIBDIR}"
+export LD_LIBRARY_PATH
+
+name="xencommons"
+rcvar=xend
+start_precmd="xen_precmd"
+start_cmd="xen_startcmd"
+stop_cmd="xen_stop"
+status_cmd="xen_status"
+extra_commands="status"
+required_files="/kern/xen/privcmd"
+
+XENSTORED_PIDFILE="/var/run/xenstored.pid"
+XENCONSOLED_PIDFILE="/var/run/xenconsoled.pid"
+XENBACKENDD_PIDFILE="/var/run/xenbackendd.pid"
+#XENBACKENDD_DEBUG=1
+#XENCONSOLED_TRACE="/var/log/xen/xenconsole-trace.log"
+#XENSTORED_TRACE="/var/log/xen/xenstore-trace.log"
+
+xen_precmd()
+{
+ mkdir -p /var/run/xenstored || exit 1
+}
+
+xen_startcmd()
+{
+ local time=0
+ local timeout=30
+
+ xenstored_pid=$(check_pidfile ${XENSTORED_PIDFILE} ${SBINDIR}/xenstored)
+ if test -z "$xenstored_pid"; then
+ printf "Cleaning xenstore database.\n"
+ if [ -z "${XENSTORED_ROOTDIR}" ]; then
+ XENSTORED_ROOTDIR="@XEN_LIB_STORED@"
+ fi
+ rm -f ${XENSTORED_ROOTDIR}/tdb* >/dev/null 2>&1
+ printf "Starting xenservices: xenstored, xenconsoled."
+ XENSTORED_ARGS=" --pid-file ${XENSTORED_PIDFILE}"
+ if [ -n "${XENSTORED_TRACE}" ]; then
+ XENSTORED_ARGS="${XENSTORED_ARGS} -T /var/log/xen/xenstored-trace.log"
+ fi
+ ${SBINDIR}/xenstored ${XENSTORED_ARGS}
+ while [ $time -lt $timeout ] && ! `${BINDIR}/xenstore-read -s / >/dev/null 2>&1` ; do
+ printf "."
+ time=$(($time+1))
+ sleep 1
+ done
+ else
+ printf "Starting xenservices: xenconsoled."
+ fi
+
+ XENCONSOLED_ARGS=""
+ if [ -n "${XENCONSOLED_TRACE}" ]; then
+ XENCONSOLED_ARGS="${XENCONSOLED_ARGS} --log=${XENCONSOLED_TRACE}"
+ fi
+
+ ${SBINDIR}/xenconsoled ${XENCONSOLED_ARGS}
+
+ printf "\n"
+
+ printf "Setting domain 0 name, domid and JSON config...\n"
+ ${LIBEXEC_BIN}/xen-init-dom0
+}
+
+xen_stop()
+{
+ pids=""
+ printf "Stopping xencommons.\n"
+ printf "WARNING: Not stopping xenstored, as it cannot be restarted.\n"
+
+ rc_pid=$(check_pidfile ${XENCONSOLED_PIDFILE} ${SBINDIR}/xenconsoled)
+ pids="$pids $rc_pid"
+
+ kill -${sig_stop:-TERM} $pids
+ wait_for_pids $pids
+}
+
+xen_status()
+{
+ xenstored_pid=$(check_pidfile ${XENSTORED_PIDFILE} ${SBINDIR}/xenstored)
+ if test -n ${xenstored_pid}; then
+ pids="$pids $xenstored_pid"
+ fi
+
+ xenconsoled_pid=$(check_pidfile ${XENCONSOLED_PIDFILE} ${SBINDIR}/xenconsoled)
+ if test -n ${xenconsoled_pid}; then
+ pids="$pids $xenconsoled_pid"
+ fi
+
+ if test -n "$xenconsoled_pid" -a -n "$xenstored_pid";
+ then
+ echo "xencommons are running as pids $pids."
+ return 0
+ fi
+ if test -z "$xenconsoled_pid" -a -z "$xenstored_pid";
+ then
+ echo "xencommons are not running."
+ return 0
+ fi
+
+ if test -n $xenstored_pid; then
+ echo "xenstored is running as pid $xenstored_pid."
+ else
+ echo "xenstored is not running."
+ fi
+ if test -n $xenconsoled_pid; then
+ echo "xenconsoled is running as pid $xenconsoled_pid."
+ else
+ echo "xenconsoled is not running."
+ fi
+}
+
+load_rc_config $name
+run_rc_command "$1"
diff --git a/tools/hotplug/NetBSD/rc.d/xend b/tools/hotplug/NetBSD/rc.d/xend
deleted file mode 100644
index ac5f2ca..0000000
--- a/tools/hotplug/NetBSD/rc.d/xend
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/bin/sh
-#
-# PROVIDE: xend
-# REQUIRE: xencommons
-
-. /etc/rc.subr
-
-DIR=$(dirname "$0")
-. "${DIR}/xen-hotplugpath.sh"
-
-LD_LIBRARY_PATH="${LIBDIR}"
-export LD_LIBRARY_PATH PYTHONPATH
-PATH="${PATH}:${SBINDIR}"
-export PATH
-
-name="xend"
-rcvar=$name
-start_precmd="xend_precmd"
-start_cmd="xend_startcmd"
-stop_cmd="xend_stop"
-status_cmd="xend_status"
-extra_commands="status"
-required_files="/kern/xen/privcmd"
-
-XENBACKENDD_PIDFILE="/var/run/xenbackendd.pid"
-#XENBACKENDD_DEBUG=1
-
-xend_precmd()
-{
- mkdir -p /var/run/xend || exit 1
- mkdir -p /var/run/xend/boot || exit 1
-}
-
-xend_startcmd()
-{
- printf "Starting xenbackendd.\n"
-
- XENBACKENDD_ARGS=""
- if [ -n "${XENBACKENDD_DEBUG}" ]; then
- XENBACKENDD_ARGS="${XENBACKENDD_ARGS} -d"
- fi
-
- ${SBINDIR}/xenbackendd ${XENBACKENDD_ARGS}
-
- printf "Starting xend.\n"
- ${SBINDIR}/xend start >/dev/null 2>&1
-}
-
-xend_stop()
-{
- printf "Stopping xenbackendd, xend\n"
- xb_pid=$(check_pidfile ${XENBACKENDD_PIDFILE} ${SBINDIR}/xenbackendd)
- if test -n "$xb_pid";
- then
- kill -${sig_stop:-TERM} $xb_pid
- fi
- while pgrep -f ${SBINDIR}/xend >/dev/null 2>&1; do
- pkill -${sig_stop:-KILL} -f ${SBINDIR}/xend
- done
- wait_for_pids $xb_pid
- rm -f /var/lock/subsys/xend /var/lock/xend /var/run/xenbackendd.pid
-}
-
-xend_status()
-{
- ${SBINDIR}/xend status
-}
-
-load_rc_config $name
-run_rc_command "$1"
-
diff --git a/tools/hotplug/NetBSD/rc.d/xendomains b/tools/hotplug/NetBSD/rc.d/xendomains
index 3e62038..b0e7111 100644
--- a/tools/hotplug/NetBSD/rc.d/xendomains
+++ b/tools/hotplug/NetBSD/rc.d/xendomains
@@ -1,7 +1,7 @@
#!/bin/sh
#
# PROVIDE: xendomains
-# REQUIRE: xend
+# REQUIRE: xencommons
# KEYWORD: shutdown
#
# xendomains This required variable is a whitespace-separated
diff --git a/tools/hotplug/NetBSD/vif-bridge b/tools/hotplug/NetBSD/vif-bridge
index 64162a8..960303e 100644
--- a/tools/hotplug/NetBSD/vif-bridge
+++ b/tools/hotplug/NetBSD/vif-bridge
@@ -7,7 +7,7 @@
DIR=$(dirname "$0")
. "${DIR}/hotplugpath.sh"
-PATH=${BINDIR}:${SBINDIR}:${LIBEXEC}:${PRIVATE_BINDIR}:/bin:/usr/bin:/sbin:/usr/sbin
+PATH=${BINDIR}:${SBINDIR}:${LIBEXEC_BIN}:/bin:/usr/bin:/sbin:/usr/sbin
export PATH
xpath=$1
diff --git a/tools/hotplug/NetBSD/vif-ip b/tools/hotplug/NetBSD/vif-ip
index 583e277..28c43de 100644
--- a/tools/hotplug/NetBSD/vif-ip
+++ b/tools/hotplug/NetBSD/vif-ip
@@ -7,7 +7,7 @@
DIR=$(dirname "$0")
. "${DIR}/hotplugpath.sh"
-PATH=${BINDIR}:${SBINDIR}:${LIBEXEC}:${PRIVATE_BINDIR}:/bin:/usr/bin:/sbin:/usr/sbin
+PATH=${BINDIR}:${SBINDIR}:${LIBEXEC_BIN}:/bin:/usr/bin:/sbin:/usr/sbin
export PATH
xpath=$1
diff --git a/tools/hotplug/common/Makefile b/tools/hotplug/common/Makefile
index 18d87aa..5623abb 100644
--- a/tools/hotplug/common/Makefile
+++ b/tools/hotplug/common/Makefile
@@ -16,10 +16,10 @@ $(eval $(genpath-target))
all: build
.PHONY: build
-build: genpath
+build: $(HOTPLUGPATH)
.PHONY: install
-install: all install-scripts
+install: install-scripts
.PHONY: install-scripts
install-scripts: build
diff --git a/tools/include/xen-sys/FreeBSD/evtchn.h b/tools/include/xen-sys/FreeBSD/evtchn.h
new file mode 100644
index 0000000..7f9a348
--- /dev/null
+++ b/tools/include/xen-sys/FreeBSD/evtchn.h
@@ -0,0 +1,87 @@
+/******************************************************************************
+ * evtchn.h
+ *
+ * Interface to /dev/xen/evtchn.
+ *
+ * Copyright (c) 2003-2005, K A Fraser
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __XEN_EVTCHN_H__
+#define __XEN_EVTCHN_H__
+
+/*
+ * Bind a fresh port to VIRQ @virq.
+ */
+#define IOCTL_EVTCHN_BIND_VIRQ \
+ _IOWR('E', 4, struct ioctl_evtchn_bind_virq)
+struct ioctl_evtchn_bind_virq {
+ unsigned int virq;
+ unsigned int port;
+};
+
+/*
+ * Bind a fresh port to remote <@remote_domain, @remote_port>.
+ */
+#define IOCTL_EVTCHN_BIND_INTERDOMAIN \
+ _IOWR('E', 5, struct ioctl_evtchn_bind_interdomain)
+struct ioctl_evtchn_bind_interdomain {
+ unsigned int remote_domain, remote_port;
+ unsigned int port;
+};
+
+/*
+ * Allocate a fresh port for binding to @remote_domain.
+ */
+#define IOCTL_EVTCHN_BIND_UNBOUND_PORT \
+ _IOWR('E', 6, struct ioctl_evtchn_bind_unbound_port)
+struct ioctl_evtchn_bind_unbound_port {
+ unsigned int remote_domain;
+ unsigned int port;
+};
+
+/*
+ * Unbind previously allocated @port.
+ */
+#define IOCTL_EVTCHN_UNBIND \
+ _IOW('E', 7, struct ioctl_evtchn_unbind)
+struct ioctl_evtchn_unbind {
+ unsigned int port;
+};
+
+/*
+ * Send event to previously allocated @port.
+ */
+#define IOCTL_EVTCHN_NOTIFY \
+ _IOW('E', 8, struct ioctl_evtchn_notify)
+struct ioctl_evtchn_notify {
+ unsigned int port;
+};
+
+/* Clear and reinitialise the event buffer. Clear error condition. */
+#define IOCTL_EVTCHN_RESET \
+ _IO('E', 9)
+
+#endif /* __XEN_EVTCHN_H__ */
diff --git a/tools/include/xen-sys/FreeBSD/privcmd.h b/tools/include/xen-sys/FreeBSD/privcmd.h
new file mode 100644
index 0000000..0434d4d
--- /dev/null
+++ b/tools/include/xen-sys/FreeBSD/privcmd.h
@@ -0,0 +1,64 @@
+/******************************************************************************
+ * privcmd.h
+ *
+ * Interface to /proc/xen/privcmd.
+ *
+ * Copyright (c) 2003-2005, K A Fraser
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (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.
+ */
+
+#ifndef __XEN_PRIVCMD_H__
+#define __XEN_PRIVCMD_H__
+
+struct ioctl_privcmd_hypercall
+{
+ unsigned long op; /* hypercall number */
+ unsigned long arg[5]; /* arguments */
+ long retval; /* return value */
+};
+typedef struct ioctl_privcmd_hypercall privcmd_hypercall_t;
+
+struct ioctl_privcmd_mmapbatch {
+ int num; /* number of pages to populate */
+ domid_t dom; /* target domain */
+ unsigned long addr; /* virtual address */
+ const xen_pfn_t *arr; /* array of mfns */
+ int *err; /* array of error codes */
+};
+typedef struct ioctl_privcmd_mmapbatch privcmd_mmapbatch_t;
+
+typedef struct privcmd_mmap_entry {
+ unsigned long va;
+ unsigned long mfn;
+ unsigned long npages;
+} privcmd_mmap_entry_t;
+
+#define IOCTL_PRIVCMD_HYPERCALL \
+ _IOWR('E', 0, struct ioctl_privcmd_hypercall)
+#define IOCTL_PRIVCMD_MMAPBATCH \
+ _IOWR('E', 1, struct ioctl_privcmd_mmapbatch)
+
+#endif /* !__XEN_PRIVCMD_H__ */
diff --git a/tools/include/xen-sys/NetBSDRump/privcmd.h b/tools/include/xen-sys/NetBSDRump/privcmd.h
new file mode 100644
index 0000000..efdcae9
--- /dev/null
+++ b/tools/include/xen-sys/NetBSDRump/privcmd.h
@@ -0,0 +1,31 @@
+
+#ifndef __NetBSDRump_PRIVCMD_H__
+#define __NetBSDRump_PRIVCMD_H__
+
+typedef struct privcmd_hypercall
+{
+ unsigned long op;
+ unsigned long arg[5];
+ long retval;
+} privcmd_hypercall_t;
+
+typedef struct privcmd_mmap_entry {
+ unsigned long va;
+ unsigned long mfn;
+ unsigned long npages;
+} privcmd_mmap_entry_t;
+
+typedef struct privcmd_mmap {
+ int num;
+ domid_t dom; /* target domain */
+ privcmd_mmap_entry_t *entry;
+} privcmd_mmap_t;
+
+typedef struct privcmd_mmapbatch {
+ int num; /* number of pages to populate */
+ domid_t dom; /* target domain */
+ unsigned long addr; /* virtual address */
+ unsigned long *arr; /* array of mfns - top nibble set on err */
+} privcmd_mmapbatch_t;
+
+#endif
diff --git a/tools/libfsimage/common/Makefile b/tools/libfsimage/common/Makefile
index cbd60b4..fb306f4 100644
--- a/tools/libfsimage/common/Makefile
+++ b/tools/libfsimage/common/Makefile
@@ -40,7 +40,7 @@ libfsimage.so.$(MAJOR): libfsimage.so.$(MAJOR).$(MINOR)
ln -sf $< $@
libfsimage.so.$(MAJOR).$(MINOR): $(PIC_OBJS)
- $(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libfsimage.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(PTHREAD_LIBS)
+ $(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libfsimage.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
-include $(DEPS)
diff --git a/tools/libvchan/init.c b/tools/libvchan/init.c
index c080a1c..de10817 100644
--- a/tools/libvchan/init.c
+++ b/tools/libvchan/init.c
@@ -129,9 +129,9 @@ out:
return ring_ref;
out_unmap_left:
if (pages_left)
- xc_gntshr_munmap(ctrl->gntshr, ctrl->read.buffer, pages_left * PAGE_SIZE);
+ xc_gntshr_munmap(ctrl->gntshr, ctrl->read.buffer, pages_left);
out_ring:
- xc_gntshr_munmap(ctrl->gntshr, ring, PAGE_SIZE);
+ xc_gntshr_munmap(ctrl->gntshr, ring, 1);
ring_ref = -1;
ctrl->ring = NULL;
ctrl->write.order = ctrl->read.order = 0;
@@ -204,9 +204,9 @@ static int init_gnt_cli(struct libxenvchan *ctrl, int domain, uint32_t ring_ref)
out_unmap_left:
if (ctrl->write.order >= PAGE_SHIFT)
xc_gnttab_munmap(ctrl->gnttab, ctrl->write.buffer,
- 1 << ctrl->write.order);
+ 1 << (ctrl->write.order - PAGE_SHIFT));
out_unmap_ring:
- xc_gnttab_munmap(ctrl->gnttab, ctrl->ring, PAGE_SIZE);
+ xc_gnttab_munmap(ctrl->gnttab, ctrl->ring, 1);
ctrl->ring = 0;
ctrl->write.order = ctrl->read.order = 0;
rv = -1;
diff --git a/tools/libvchan/io.c b/tools/libvchan/io.c
index 804c63c..e66bc4e 100644
--- a/tools/libvchan/io.c
+++ b/tools/libvchan/io.c
@@ -118,7 +118,7 @@ static inline int send_notify(struct libxenvchan *ctrl, uint8_t bit)
static inline int raw_get_data_ready(struct libxenvchan *ctrl)
{
uint32_t ready = rd_prod(ctrl) - rd_cons(ctrl);
- if (ready >= rd_ring_size(ctrl))
+ if (ready > rd_ring_size(ctrl))
/* We have no way to return errors. Locking up the ring is
* better than the alternatives. */
return 0;
@@ -365,10 +365,10 @@ void libxenvchan_close(struct libxenvchan *ctrl)
if (ctrl->ring) {
if (ctrl->is_server) {
ctrl->ring->srv_live = 0;
- xc_gntshr_munmap(ctrl->gntshr, ctrl->ring, PAGE_SIZE);
+ xc_gntshr_munmap(ctrl->gntshr, ctrl->ring, 1);
} else {
ctrl->ring->cli_live = 0;
- xc_gnttab_munmap(ctrl->gnttab, ctrl->ring, PAGE_SIZE);
+ xc_gnttab_munmap(ctrl->gnttab, ctrl->ring, 1);
}
}
if (ctrl->event) {
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 2cca2b2..bd2ca6c 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -1,7 +1,7 @@
XEN_ROOT = $(CURDIR)/../..
include $(XEN_ROOT)/tools/Rules.mk
-MAJOR = 4.4
+MAJOR = 4.5
MINOR = 0
CTRL_SRCS-y :=
@@ -20,6 +20,7 @@ CTRL_SRCS-y += xc_sedf.c
CTRL_SRCS-y += xc_csched.c
CTRL_SRCS-y += xc_csched2.c
CTRL_SRCS-y += xc_arinc653.c
+CTRL_SRCS-y += xc_rt.c
CTRL_SRCS-y += xc_tbuf.c
CTRL_SRCS-y += xc_pm.c
CTRL_SRCS-y += xc_cpu_hotplug.c
@@ -34,8 +35,11 @@ CTRL_SRCS-y += xc_foreign_memory.c
CTRL_SRCS-y += xc_kexec.c
CTRL_SRCS-y += xtl_core.c
CTRL_SRCS-y += xtl_logger_stdio.c
+CTRL_SRCS-y += xc_resource.c
+CTRL_SRCS-$(CONFIG_X86) += xc_psr.c
CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c
CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c xc_linux_osdep.c
+CTRL_SRCS-$(CONFIG_FreeBSD) += xc_freebsd.c xc_freebsd_osdep.c
CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c
CTRL_SRCS-$(CONFIG_NetBSD) += xc_netbsd.c
CTRL_SRCS-$(CONFIG_MiniOS) += xc_minios.c
@@ -88,17 +92,13 @@ OSDEP_SRCS-y += xenctrl_osdep_ENOSYS.c
-include $(XEN_TARGET_ARCH)/Makefile
CFLAGS += -Werror -Wmissing-prototypes
-CFLAGS += -I. $(CFLAGS_xeninclude)
+CFLAGS += -I. -I./include $(CFLAGS_xeninclude)
# Needed for posix_fadvise64() in xc_linux.c
CFLAGS-$(CONFIG_Linux) += -D_GNU_SOURCE
CFLAGS += $(PTHREAD_CFLAGS)
-# Define this to make it possible to run valgrind on code linked with these
-# libraries.
-#CFLAGS += -DVALGRIND -O0 -ggdb3
-
CTRL_LIB_OBJS := $(patsubst %.c,%.o,$(CTRL_SRCS-y))
CTRL_PIC_OBJS := $(patsubst %.c,%.opic,$(CTRL_SRCS-y))
@@ -108,20 +108,31 @@ GUEST_PIC_OBJS := $(patsubst %.c,%.opic,$(GUEST_SRCS-y))
OSDEP_LIB_OBJS := $(patsubst %.c,%.o,$(OSDEP_SRCS-y))
OSDEP_PIC_OBJS := $(patsubst %.c,%.opic,$(OSDEP_SRCS-y))
+$(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) $(OSDEP_LIB_OBJS) \
+$(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS) $(OSDEP_PIC_OBJS) : CFLAGS += -include $(XEN_ROOT)/tools/config.h
+
LIB := libxenctrl.a
-ifneq ($(stubdom),y)
+ifneq ($(nosharedlibs),y)
LIB += libxenctrl.so libxenctrl.so.$(MAJOR) libxenctrl.so.$(MAJOR).$(MINOR)
endif
LIB += libxenguest.a
-ifneq ($(stubdom),y)
+ifneq ($(nosharedlibs),y)
LIB += libxenguest.so libxenguest.so.$(MAJOR) libxenguest.so.$(MAJOR).$(MINOR)
endif
-ifneq ($(stubdom),y)
+ifneq ($(nosharedlibs),y)
LIB += xenctrl_osdep_ENOSYS.so
endif
+genpath-target = $(call buildmakevars2header,_paths.h)
+$(eval $(genpath-target))
+
+xc_private.h: _paths.h
+
+$(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) $(OSDEP_LIB_OBJS) \
+$(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS) $(OSDEP_PIC_OBJS): xc_private.h
+
.PHONY: all
all: build
@@ -136,16 +147,16 @@ libs: $(LIB)
install: build
$(INSTALL_DIR) $(DESTDIR)$(LIBDIR)
$(INSTALL_DIR) $(DESTDIR)$(INCLUDEDIR)
- $(INSTALL_PROG) libxenctrl.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)
+ $(INSTALL_SHLIB) libxenctrl.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)
$(INSTALL_DATA) libxenctrl.a $(DESTDIR)$(LIBDIR)
- ln -sf libxenctrl.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libxenctrl.so.$(MAJOR)
- ln -sf libxenctrl.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libxenctrl.so
- $(INSTALL_DATA) xenctrl.h xenctrlosdep.h xentoollog.h $(DESTDIR)$(INCLUDEDIR)
- $(INSTALL_PROG) libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)
+ $(SYMLINK_SHLIB) libxenctrl.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libxenctrl.so.$(MAJOR)
+ $(SYMLINK_SHLIB) libxenctrl.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libxenctrl.so
+ $(INSTALL_DATA) include/xenctrl.h include/xenctrlosdep.h include/xentoollog.h $(DESTDIR)$(INCLUDEDIR)
+ $(INSTALL_SHLIB) libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)
$(INSTALL_DATA) libxenguest.a $(DESTDIR)$(LIBDIR)
- ln -sf libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libxenguest.so.$(MAJOR)
- ln -sf libxenguest.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libxenguest.so
- $(INSTALL_DATA) xenguest.h $(DESTDIR)$(INCLUDEDIR)
+ $(SYMLINK_SHLIB) libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libxenguest.so.$(MAJOR)
+ $(SYMLINK_SHLIB) libxenguest.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libxenguest.so
+ $(INSTALL_DATA) include/xenguest.h $(DESTDIR)$(INCLUDEDIR)
.PHONY: TAGS
TAGS:
@@ -154,6 +165,7 @@ TAGS:
.PHONY: clean
clean:
rm -rf *.rpm $(LIB) *~ $(DEPS) \
+ _paths.h \
$(CTRL_LIB_OBJS) $(CTRL_PIC_OBJS) \
$(GUEST_LIB_OBJS) $(GUEST_PIC_OBJS) \
$(OSDEP_LIB_OBJS) $(OSDEP_PIC_OBJS)
@@ -174,9 +186,9 @@ libxenctrl.a: $(CTRL_LIB_OBJS)
$(AR) rc $@ $^
libxenctrl.so: libxenctrl.so.$(MAJOR)
- ln -sf $< $@
+ $(SYMLINK_SHLIB) $< $@
libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR)
- ln -sf $< $@
+ $(SYMLINK_SHLIB) $< $@
libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS)
$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(DLOPEN_LIBS) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
@@ -187,9 +199,9 @@ libxenguest.a: $(GUEST_LIB_OBJS)
$(AR) rc $@ $^
libxenguest.so: libxenguest.so.$(MAJOR)
- ln -sf $< $@
+ $(SYMLINK_SHLIB) $< $@
libxenguest.so.$(MAJOR): libxenguest.so.$(MAJOR).$(MINOR)
- ln -sf $< $@
+ $(SYMLINK_SHLIB) $< $@
ifeq ($(CONFIG_MiniOS),y)
zlib-options =
@@ -205,7 +217,7 @@ libxenguest.so.$(MAJOR).$(MINOR): $(GUEST_PIC_OBJS) libxenctrl.so
$(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $(GUEST_PIC_OBJS) $(COMPRESSION_LIBS) -lz $(LDLIBS_libxenctrl) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
xenctrl_osdep_ENOSYS.so: $(OSDEP_PIC_OBJS) libxenctrl.so
- $(CC) -g $(LDFLAGS) $(SHLIB_LDFLAGS) -o $@ $(OSDEP_PIC_OBJS) $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
+ $(CC) $(LDFLAGS) $(SHLIB_LDFLAGS) -o $@ $(OSDEP_PIC_OBJS) $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
-include $(DEPS)
diff --git a/tools/libxc/include/xc_dom.h b/tools/libxc/include/xc_dom.h
new file mode 100644
index 0000000..07d7224
--- /dev/null
+++ b/tools/libxc/include/xc_dom.h
@@ -0,0 +1,403 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <xen/libelf/libelf.h>
+
+#define INVALID_P2M_ENTRY ((xen_pfn_t)-1)
+
+/* --- typedefs and structs ---------------------------------------- */
+
+typedef uint64_t xen_vaddr_t;
+typedef uint64_t xen_paddr_t;
+
+#define PRIpfn PRI_xen_pfn
+
+struct xc_dom_seg {
+ xen_vaddr_t vstart;
+ xen_vaddr_t vend;
+ xen_pfn_t pfn;
+};
+
+struct xc_dom_mem {
+ struct xc_dom_mem *next;
+ void *ptr;
+ enum {
+ XC_DOM_MEM_TYPE_MALLOC_INTERNAL,
+ XC_DOM_MEM_TYPE_MALLOC_EXTERNAL,
+ XC_DOM_MEM_TYPE_MMAP,
+ } type;
+ size_t len;
+ unsigned char memory[0];
+};
+
+struct xc_dom_phys {
+ struct xc_dom_phys *next;
+ void *ptr;
+ xen_pfn_t first;
+ xen_pfn_t count;
+};
+
+struct xc_dom_image {
+ /* files */
+ void *kernel_blob;
+ size_t kernel_size;
+ void *ramdisk_blob;
+ size_t ramdisk_size;
+ void *devicetree_blob;
+ size_t devicetree_size;
+
+ size_t max_kernel_size;
+ size_t max_ramdisk_size;
+ size_t max_devicetree_size;
+
+ /* arguments and parameters */
+ char *cmdline;
+ uint32_t f_requested[XENFEAT_NR_SUBMAPS];
+
+ /* info from (elf) kernel image */
+ struct elf_dom_parms parms;
+ char *guest_type;
+
+ /* memory layout */
+ struct xc_dom_seg kernel_seg;
+ /* If ramdisk_seg.vstart is non zero then the ramdisk will be
+ * loaded at that address, otherwise it will automatically placed.
+ *
+ * If automatic placement is used and the ramdisk is gzip
+ * compressed then it will be decompressed as it is loaded. If the
+ * ramdisk has been explicitly placed then it is loaded as is
+ * otherwise decompressing risks undoing the manual placement.
+ */
+ struct xc_dom_seg ramdisk_seg;
+ struct xc_dom_seg p2m_seg;
+ struct xc_dom_seg pgtables_seg;
+ struct xc_dom_seg devicetree_seg;
+ xen_pfn_t start_info_pfn;
+ xen_pfn_t console_pfn;
+ xen_pfn_t xenstore_pfn;
+ xen_pfn_t shared_info_pfn;
+ xen_pfn_t bootstack_pfn;
+ xen_vaddr_t virt_alloc_end;
+ xen_vaddr_t bsd_symtab_start;
+
+ /* initial page tables */
+ unsigned int pgtables;
+ unsigned int pg_l4;
+ unsigned int pg_l3;
+ unsigned int pg_l2;
+ unsigned int pg_l1;
+ unsigned int alloc_bootstack;
+ unsigned int extra_pages;
+ xen_vaddr_t virt_pgtab_end;
+
+ /* other state info */
+ uint32_t f_active[XENFEAT_NR_SUBMAPS];
+ /*
+ * p2m_host maps guest physical addresses an offset from
+ * rambase_pfn (see below) into gfns.
+ *
+ * For a pure PV guest this means that it maps GPFNs into MFNs for
+ * a hybrid guest this means that it maps GPFNs to GPFNS.
+ *
+ * Note that the input is offset by rambase.
+ */
+ xen_pfn_t *p2m_host;
+ void *p2m_guest;
+
+ /* physical memory
+ *
+ * An x86 PV guest has a single contiguous block of physical RAM,
+ * consisting of total_pages starting at rambase_pfn.
+ *
+ * An ARM guest has GUEST_RAM_BANKS regions of RAM, with
+ * rambank_size[i] pages in each. The lowest RAM address
+ * (corresponding to the base of the p2m arrays above) is stored
+ * in rambase_pfn.
+ */
+ xen_pfn_t rambase_pfn;
+ xen_pfn_t total_pages;
+ struct xc_dom_phys *phys_pages;
+ int realmodearea_log;
+#if defined (__arm__) || defined(__aarch64__)
+ xen_pfn_t rambank_size[GUEST_RAM_BANKS];
+#endif
+
+ /* malloc memory pool */
+ struct xc_dom_mem *memblocks;
+
+ /* memory footprint stats */
+ size_t alloc_malloc;
+ size_t alloc_mem_map;
+ size_t alloc_file_map;
+ size_t alloc_domU_map;
+
+ /* misc xen domain config stuff */
+ unsigned long flags;
+ unsigned int console_evtchn;
+ unsigned int xenstore_evtchn;
+ domid_t console_domid;
+ domid_t xenstore_domid;
+ xen_pfn_t shared_info_mfn;
+ int pvh_enabled;
+
+ xc_interface *xch;
+ domid_t guest_domid;
+ int8_t vhpt_size_log2; /* for IA64 */
+ int8_t superpages;
+ int claim_enabled; /* 0 by default, 1 enables it */
+ int shadow_enabled;
+
+ int xen_version;
+ xen_capabilities_info_t xen_caps;
+
+ /* kernel loader, arch hooks */
+ struct xc_dom_loader *kernel_loader;
+ void *private_loader;
+
+ /* kernel loader */
+ struct xc_dom_arch *arch_hooks;
+ /* allocate up to virt_alloc_end */
+ int (*allocate) (struct xc_dom_image * dom, xen_vaddr_t up_to);
+};
+
+/* --- pluggable kernel loader ------------------------------------- */
+
+struct xc_dom_loader {
+ char *name;
+ /* Sadly the error returns from these functions are not consistent: */
+ elf_negerrnoval (*probe) (struct xc_dom_image * dom);
+ elf_negerrnoval (*parser) (struct xc_dom_image * dom);
+ elf_errorstatus (*loader) (struct xc_dom_image * dom);
+
+ struct xc_dom_loader *next;
+};
+
+#define __init __attribute__ ((constructor))
+void xc_dom_register_loader(struct xc_dom_loader *loader);
+
+/* --- arch specific hooks ----------------------------------------- */
+
+struct xc_dom_arch {
+ /* pagetable setup */
+ int (*alloc_magic_pages) (struct xc_dom_image * dom);
+ int (*count_pgtables) (struct xc_dom_image * dom);
+ int (*setup_pgtables) (struct xc_dom_image * dom);
+
+ /* arch-specific data structs setup */
+ int (*start_info) (struct xc_dom_image * dom);
+ int (*shared_info) (struct xc_dom_image * dom, void *shared_info);
+ int (*vcpu) (struct xc_dom_image * dom, void *vcpu_ctxt);
+
+ char *guest_type;
+ char *native_protocol;
+ int page_shift;
+ int sizeof_pfn;
+
+ struct xc_dom_arch *next;
+};
+void xc_dom_register_arch_hooks(struct xc_dom_arch *hooks);
+
+#define XC_DOM_PAGE_SHIFT(dom) ((dom)->arch_hooks->page_shift)
+#define XC_DOM_PAGE_SIZE(dom) (1 << (dom)->arch_hooks->page_shift)
+
+/* --- main functions ---------------------------------------------- */
+
+struct xc_dom_image *xc_dom_allocate(xc_interface *xch,
+ const char *cmdline, const char *features);
+void xc_dom_release_phys(struct xc_dom_image *dom);
+void xc_dom_release(struct xc_dom_image *dom);
+int xc_dom_rambase_init(struct xc_dom_image *dom, uint64_t rambase);
+int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb);
+
+/* Set this larger if you have enormous ramdisks/kernels. Note that
+ * you should trust all kernels not to be maliciously large (e.g. to
+ * exhaust all dom0 memory) if you do this (see CVE-2012-4544 /
+ * XSA-25). You can also set the default independently for
+ * ramdisks/kernels in xc_dom_allocate() or call
+ * xc_dom_{kernel,ramdisk}_max_size.
+ */
+#ifndef XC_DOM_DECOMPRESS_MAX
+#define XC_DOM_DECOMPRESS_MAX (1024*1024*1024) /* 1GB */
+#endif
+
+int xc_dom_kernel_check_size(struct xc_dom_image *dom, size_t sz);
+int xc_dom_kernel_max_size(struct xc_dom_image *dom, size_t sz);
+
+int xc_dom_ramdisk_check_size(struct xc_dom_image *dom, size_t sz);
+int xc_dom_ramdisk_max_size(struct xc_dom_image *dom, size_t sz);
+
+int xc_dom_devicetree_max_size(struct xc_dom_image *dom, size_t sz);
+
+size_t xc_dom_check_gzip(xc_interface *xch,
+ void *blob, size_t ziplen);
+int xc_dom_do_gunzip(xc_interface *xch,
+ void *src, size_t srclen, void *dst, size_t dstlen);
+int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size);
+
+int xc_dom_kernel_file(struct xc_dom_image *dom, const char *filename);
+int xc_dom_ramdisk_file(struct xc_dom_image *dom, const char *filename);
+int xc_dom_kernel_mem(struct xc_dom_image *dom, const void *mem,
+ size_t memsize);
+int xc_dom_ramdisk_mem(struct xc_dom_image *dom, const void *mem,
+ size_t memsize);
+int xc_dom_devicetree_file(struct xc_dom_image *dom, const char *filename);
+int xc_dom_devicetree_mem(struct xc_dom_image *dom, const void *mem,
+ size_t memsize);
+
+int xc_dom_parse_image(struct xc_dom_image *dom);
+struct xc_dom_arch *xc_dom_find_arch_hooks(xc_interface *xch, char *guest_type);
+int xc_dom_build_image(struct xc_dom_image *dom);
+int xc_dom_update_guest_p2m(struct xc_dom_image *dom);
+
+int xc_dom_boot_xen_init(struct xc_dom_image *dom, xc_interface *xch,
+ domid_t domid);
+int xc_dom_boot_mem_init(struct xc_dom_image *dom);
+void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn,
+ xen_pfn_t count);
+int xc_dom_boot_image(struct xc_dom_image *dom);
+int xc_dom_compat_check(struct xc_dom_image *dom);
+int xc_dom_gnttab_init(struct xc_dom_image *dom);
+int xc_dom_gnttab_hvm_seed(xc_interface *xch, domid_t domid,
+ xen_pfn_t console_gmfn,
+ xen_pfn_t xenstore_gmfn,
+ domid_t console_domid,
+ domid_t xenstore_domid);
+int xc_dom_gnttab_seed(xc_interface *xch, domid_t domid,
+ xen_pfn_t console_gmfn,
+ xen_pfn_t xenstore_gmfn,
+ domid_t console_domid,
+ domid_t xenstore_domid);
+int xc_dom_feature_translated(struct xc_dom_image *dom);
+
+/* --- debugging bits ---------------------------------------------- */
+
+int xc_dom_loginit(xc_interface *xch);
+
+void xc_dom_printf(xc_interface *xch, const char *fmt, ...)
+ __attribute__ ((format(printf, 2, 3)));
+void xc_dom_panic_func(xc_interface *xch,
+ const char *file, int line, xc_error_code err,
+ const char *fmt, ...)
+ __attribute__ ((format(printf, 5, 6)));
+
+#define xc_dom_panic(xch, err, fmt, args...) \
+ xc_dom_panic_func(xch, __FILE__, __LINE__, err, fmt, ## args)
+#define xc_dom_trace(mark) \
+ xc_dom_printf("%s:%d: trace %s\n", __FILE__, __LINE__, mark)
+
+void xc_dom_log_memory_footprint(struct xc_dom_image *dom);
+
+/* --- simple memory pool ------------------------------------------ */
+
+void *xc_dom_malloc(struct xc_dom_image *dom, size_t size);
+int xc_dom_register_external(struct xc_dom_image *dom, void *ptr, size_t size);
+void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size);
+void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
+ const char *filename, size_t * size,
+ const size_t max_size);
+char *xc_dom_strdup(struct xc_dom_image *dom, const char *str);
+
+/* --- alloc memory pool ------------------------------------------- */
+
+int xc_dom_alloc_page(struct xc_dom_image *dom, char *name);
+int xc_dom_alloc_segment(struct xc_dom_image *dom,
+ struct xc_dom_seg *seg, char *name,
+ xen_vaddr_t start, xen_vaddr_t size);
+
+/* --- misc bits --------------------------------------------------- */
+
+void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first,
+ xen_pfn_t count);
+void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t first,
+ xen_pfn_t count, xen_pfn_t *count_out);
+void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn);
+void xc_dom_unmap_all(struct xc_dom_image *dom);
+
+static inline void *xc_dom_seg_to_ptr_pages(struct xc_dom_image *dom,
+ struct xc_dom_seg *seg,
+ xen_pfn_t *pages_out)
+{
+ xen_vaddr_t segsize = seg->vend - seg->vstart;
+ unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
+ xen_pfn_t pages = (segsize + page_size - 1) / page_size;
+ void *retval;
+
+ retval = xc_dom_pfn_to_ptr(dom, seg->pfn, pages);
+
+ *pages_out = retval ? pages : 0;
+ return retval;
+}
+
+static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
+ struct xc_dom_seg *seg)
+{
+ xen_pfn_t dummy;
+
+ return xc_dom_seg_to_ptr_pages(dom, seg, &dummy);
+}
+
+static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom,
+ xen_vaddr_t vaddr,
+ size_t *safe_region_out)
+{
+ unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
+ xen_pfn_t page = (vaddr - dom->parms.virt_base) / page_size;
+ unsigned int offset = (vaddr - dom->parms.virt_base) % page_size;
+ xen_pfn_t safe_region_count;
+ void *ptr;
+
+ *safe_region_out = 0;
+ ptr = xc_dom_pfn_to_ptr_retcount(dom, page, 0, &safe_region_count);
+ if ( ptr == NULL )
+ return ptr;
+ *safe_region_out = (safe_region_count << XC_DOM_PAGE_SHIFT(dom)) - offset;
+ return ptr + offset;
+}
+
+static inline xen_pfn_t xc_dom_p2m_host(struct xc_dom_image *dom, xen_pfn_t pfn)
+{
+ if (dom->shadow_enabled)
+ return pfn;
+ if (pfn < dom->rambase_pfn || pfn >= dom->rambase_pfn + dom->total_pages)
+ return INVALID_MFN;
+ return dom->p2m_host[pfn - dom->rambase_pfn];
+}
+
+static inline xen_pfn_t xc_dom_p2m_guest(struct xc_dom_image *dom,
+ xen_pfn_t pfn)
+{
+ if (xc_dom_feature_translated(dom))
+ return pfn;
+ if (pfn < dom->rambase_pfn || pfn >= dom->rambase_pfn + dom->total_pages)
+ return INVALID_MFN;
+ return dom->p2m_host[pfn - dom->rambase_pfn];
+}
+
+/* --- arch bits --------------------------------------------------- */
+
+int arch_setup_meminit(struct xc_dom_image *dom);
+int arch_setup_bootearly(struct xc_dom_image *dom);
+int arch_setup_bootlate(struct xc_dom_image *dom);
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
new file mode 100644
index 0000000..0ad8b8d
--- /dev/null
+++ b/tools/libxc/include/xenctrl.h
@@ -0,0 +1,2717 @@
+/******************************************************************************
+ * xenctrl.h
+ *
+ * A library for low-level access to the Xen control interfaces.
+ *
+ * Copyright (c) 2003-2004, K A Fraser.
+ *
+ * xc_gnttab functions:
+ * Copyright (c) 2007-2008, D G Murray <Derek.Murray at cl.cam.ac.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef XENCTRL_H
+#define XENCTRL_H
+
+/* Tell the Xen public headers we are a user-space tools build. */
+#ifndef __XEN_TOOLS__
+#define __XEN_TOOLS__ 1
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <xen/xen.h>
+#include <xen/domctl.h>
+#include <xen/physdev.h>
+#include <xen/sysctl.h>
+#include <xen/version.h>
+#include <xen/event_channel.h>
+#include <xen/sched.h>
+#include <xen/memory.h>
+#include <xen/grant_table.h>
+#include <xen/hvm/params.h>
+#include <xen/xsm/flask_op.h>
+#include <xen/tmem.h>
+#include <xen/kexec.h>
+#include <xen/platform.h>
+
+#include "xentoollog.h"
+
+#if defined(__i386__) || defined(__x86_64__)
+#include <xen/foreign/x86_32.h>
+#include <xen/foreign/x86_64.h>
+#include <xen/arch-x86/xen-mca.h>
+#endif
+
+#define XC_PAGE_SHIFT 12
+#define XC_PAGE_SIZE (1UL << XC_PAGE_SHIFT)
+#define XC_PAGE_MASK (~(XC_PAGE_SIZE-1))
+
+#define INVALID_MFN (~0UL)
+
+/*
+ * DEFINITIONS FOR CPU BARRIERS
+ */
+
+#define xen_barrier() asm volatile ( "" : : : "memory")
+
+#if defined(__i386__)
+#define xen_mb() asm volatile ( "lock; addl $0,0(%%esp)" : : : "memory" )
+#define xen_rmb() xen_barrier()
+#define xen_wmb() xen_barrier()
+#elif defined(__x86_64__)
+#define xen_mb() asm volatile ( "mfence" : : : "memory")
+#define xen_rmb() xen_barrier()
+#define xen_wmb() xen_barrier()
+#elif defined(__arm__)
+#define xen_mb() asm volatile ("dmb" : : : "memory")
+#define xen_rmb() asm volatile ("dmb" : : : "memory")
+#define xen_wmb() asm volatile ("dmb" : : : "memory")
+#elif defined(__aarch64__)
+#define xen_mb() asm volatile ("dmb sy" : : : "memory")
+#define xen_rmb() asm volatile ("dmb sy" : : : "memory")
+#define xen_wmb() asm volatile ("dmb sy" : : : "memory")
+#else
+#error "Define barriers"
+#endif
+
+
+#define XENCTRL_HAS_XC_INTERFACE 1
+/* In Xen 4.0 and earlier, xc_interface_open and xc_evtchn_open would
+ * both return ints being the file descriptor. In 4.1 and later, they
+ * return an xc_interface* and xc_evtchn*, respectively - ie, a
+ * pointer to an opaque struct. This #define is provided in 4.1 and
+ * later, allowing out-of-tree callers to more easily distinguish
+ * between, and be compatible with, both versions.
+ */
+
+
+/*
+ * GENERAL
+ *
+ * Unless otherwise specified, each function here returns zero or a
+ * non-null pointer on success; or in case of failure, sets errno and
+ * returns -1 or a null pointer.
+ *
+ * Unless otherwise specified, errors result in a call to the error
+ * handler function, which by default prints a message to the
+ * FILE* passed as the caller_data, which by default is stderr.
+ * (This is described below as "logging errors".)
+ *
+ * The error handler can safely trash errno, as libxc saves it across
+ * the callback.
+ */
+
+typedef struct xc_interface_core xc_interface;
+typedef struct xc_interface_core xc_evtchn;
+typedef struct xc_interface_core xc_gnttab;
+typedef struct xc_interface_core xc_gntshr;
+
+enum xc_error_code {
+ XC_ERROR_NONE = 0,
+ XC_INTERNAL_ERROR = 1,
+ XC_INVALID_KERNEL = 2,
+ XC_INVALID_PARAM = 3,
+ XC_OUT_OF_MEMORY = 4,
+ /* new codes need to be added to xc_error_level_to_desc too */
+};
+
+typedef enum xc_error_code xc_error_code;
+
+
+/*
+ * INITIALIZATION FUNCTIONS
+ */
+
+/**
+ * This function opens a handle to the hypervisor interface. This function can
+ * be called multiple times within a single process. Multiple processes can
+ * have an open hypervisor interface at the same time.
+ *
+ * Note:
+ * After fork a child process must not use any opened xc interface
+ * handle inherited from their parent. They must open a new handle if
+ * they want to interact with xc.
+ *
+ * Each call to this function should have a corresponding call to
+ * xc_interface_close().
+ *
+ * This function can fail if the caller does not have superuser permission or
+ * if a Xen-enabled kernel is not currently running.
+ *
+ * @return a handle to the hypervisor interface
+ */
+xc_interface *xc_interface_open(xentoollog_logger *logger,
+ xentoollog_logger *dombuild_logger,
+ unsigned open_flags);
+ /* if logger==NULL, will log to stderr
+ * if dombuild_logger=NULL, will log to a file
+ */
+
+/*
+ * Note: if XC_OPENFLAG_NON_REENTRANT is passed then libxc must not be
+ * called reentrantly and the calling application is responsible for
+ * providing mutual exclusion surrounding all libxc calls itself.
+ *
+ * In particular xc_{get,clear}_last_error only remain valid for the
+ * duration of the critical section containing the call which failed.
+ */
+enum xc_open_flags {
+ XC_OPENFLAG_DUMMY = 1<<0, /* do not actually open a xenctrl interface */
+ XC_OPENFLAG_NON_REENTRANT = 1<<1, /* assume library is only every called from a single thread */
+};
+
+/**
+ * This function closes an open hypervisor interface.
+ *
+ * This function can fail if the handle does not represent an open interface or
+ * if there were problems closing the interface. In the latter case
+ * the interface is still closed.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @return 0 on success, -1 otherwise.
+ */
+int xc_interface_close(xc_interface *xch);
+
+/**
+ * Query the active OS interface (i.e. that which would be returned by
+ * xc_interface_open) to find out if it is fake (i.e. backends onto
+ * something other than an actual Xen hypervisor).
+ *
+ * @return 0 is "real", >0 if fake, -1 on error.
+ */
+int xc_interface_is_fake(void);
+
+/*
+ * HYPERCALL SAFE MEMORY BUFFER
+ *
+ * Ensure that memory which is passed to a hypercall has been
+ * specially allocated in order to be safe to access from the
+ * hypervisor.
+ *
+ * Each user data pointer is shadowed by an xc_hypercall_buffer data
+ * structure. You should never define an xc_hypercall_buffer type
+ * directly, instead use the DECLARE_HYPERCALL_BUFFER* macros below.
+ *
+ * The strucuture should be considered opaque and all access should be
+ * via the macros and helper functions defined below.
+ *
+ * Once the buffer is declared the user is responsible for explicitly
+ * allocating and releasing the memory using
+ * xc_hypercall_buffer_alloc(_pages) and
+ * xc_hypercall_buffer_free(_pages).
+ *
+ * Once the buffer has been allocated the user can initialise the data
+ * via the normal pointer. The xc_hypercall_buffer structure is
+ * transparently referenced by the helper macros (such as
+ * xen_set_guest_handle) in order to check at compile time that the
+ * correct type of memory is being used.
+ */
+struct xc_hypercall_buffer {
+ /* Hypercall safe memory buffer. */
+ void *hbuf;
+
+ /*
+ * Reference to xc_hypercall_buffer passed as argument to the
+ * current function.
+ */
+ struct xc_hypercall_buffer *param_shadow;
+
+ /*
+ * Direction of copy for bounce buffering.
+ */
+ int dir;
+
+ /* Used iff dir != 0. */
+ void *ubuf;
+ size_t sz;
+};
+typedef struct xc_hypercall_buffer xc_hypercall_buffer_t;
+
+/*
+ * Construct the name of the hypercall buffer for a given variable.
+ * For internal use only
+ */
+#define XC__HYPERCALL_BUFFER_NAME(_name) xc__hypercall_buffer_##_name
+
+/*
+ * Returns the hypercall_buffer associated with a variable.
+ */
+#define HYPERCALL_BUFFER(_name) \
+ ({ xc_hypercall_buffer_t _hcbuf_buf1; \
+ typeof(XC__HYPERCALL_BUFFER_NAME(_name)) *_hcbuf_buf2 = \
+ &XC__HYPERCALL_BUFFER_NAME(_name); \
+ (void)(&_hcbuf_buf1 == _hcbuf_buf2); \
+ (_hcbuf_buf2)->param_shadow ? \
+ (_hcbuf_buf2)->param_shadow : (_hcbuf_buf2); \
+ })
+
+#define HYPERCALL_BUFFER_INIT_NO_BOUNCE .dir = 0, .sz = 0, .ubuf = (void *)-1
+
+/*
+ * Defines a hypercall buffer and user pointer with _name of _type.
+ *
+ * The user accesses the data as normal via _name which will be
+ * transparently converted to the hypercall buffer as necessary.
+ */
+#define DECLARE_HYPERCALL_BUFFER(_type, _name) \
+ _type *_name = NULL; \
+ xc_hypercall_buffer_t XC__HYPERCALL_BUFFER_NAME(_name) = { \
+ .hbuf = NULL, \
+ .param_shadow = NULL, \
+ HYPERCALL_BUFFER_INIT_NO_BOUNCE \
+ }
+
+/*
+ * Like DECLARE_HYPERCALL_BUFFER() but using an already allocated
+ * hypercall buffer, _hbuf.
+ *
+ * Useful when a hypercall buffer is passed to a function and access
+ * via the user pointer is required.
+ *
+ * See DECLARE_HYPERCALL_BUFFER_ARGUMENT() if the user pointer is not
+ * required.
+ */
+#define DECLARE_HYPERCALL_BUFFER_SHADOW(_type, _name, _hbuf) \
+ _type *_name = _hbuf->hbuf; \
+ xc_hypercall_buffer_t XC__HYPERCALL_BUFFER_NAME(_name) = { \
+ .hbuf = (void *)-1, \
+ .param_shadow = _hbuf, \
+ HYPERCALL_BUFFER_INIT_NO_BOUNCE \
+ }
+
+/*
+ * Declare the necessary data structure to allow a hypercall buffer
+ * passed as an argument to a function to be used in the normal way.
+ */
+#define DECLARE_HYPERCALL_BUFFER_ARGUMENT(_name) \
+ xc_hypercall_buffer_t XC__HYPERCALL_BUFFER_NAME(_name) = { \
+ .hbuf = (void *)-1, \
+ .param_shadow = _name, \
+ HYPERCALL_BUFFER_INIT_NO_BOUNCE \
+ }
+
+/*
+ * Get the hypercall buffer data pointer in a form suitable for use
+ * directly as a hypercall argument.
+ */
+#define HYPERCALL_BUFFER_AS_ARG(_name) \
+ ({ xc_hypercall_buffer_t _hcbuf_arg1; \
+ typeof(XC__HYPERCALL_BUFFER_NAME(_name)) *_hcbuf_arg2 = \
+ HYPERCALL_BUFFER(_name); \
+ (void)(&_hcbuf_arg1 == _hcbuf_arg2); \
+ (unsigned long)(_hcbuf_arg2)->hbuf; \
+ })
+
+/*
+ * Set a xen_guest_handle in a type safe manner, ensuring that the
+ * data pointer has been correctly allocated.
+ */
+#undef set_xen_guest_handle
+#define set_xen_guest_handle(_hnd, _val) \
+ do { \
+ xc_hypercall_buffer_t _hcbuf_hnd1; \
+ typeof(XC__HYPERCALL_BUFFER_NAME(_val)) *_hcbuf_hnd2 = \
+ HYPERCALL_BUFFER(_val); \
+ (void) (&_hcbuf_hnd1 == _hcbuf_hnd2); \
+ set_xen_guest_handle_raw(_hnd, (_hcbuf_hnd2)->hbuf); \
+ } while (0)
+
+/* Use with set_xen_guest_handle in place of NULL */
+extern xc_hypercall_buffer_t XC__HYPERCALL_BUFFER_NAME(HYPERCALL_BUFFER_NULL);
+
+/*
+ * Allocate and free hypercall buffers with byte granularity.
+ */
+void *xc__hypercall_buffer_alloc(xc_interface *xch, xc_hypercall_buffer_t *b, size_t size);
+#define xc_hypercall_buffer_alloc(_xch, _name, _size) xc__hypercall_buffer_alloc(_xch, HYPERCALL_BUFFER(_name), _size)
+void xc__hypercall_buffer_free(xc_interface *xch, xc_hypercall_buffer_t *b);
+#define xc_hypercall_buffer_free(_xch, _name) xc__hypercall_buffer_free(_xch, HYPERCALL_BUFFER(_name))
+
+/*
+ * Allocate and free hypercall buffers with page alignment.
+ */
+void *xc__hypercall_buffer_alloc_pages(xc_interface *xch, xc_hypercall_buffer_t *b, int nr_pages);
+#define xc_hypercall_buffer_alloc_pages(_xch, _name, _nr) xc__hypercall_buffer_alloc_pages(_xch, HYPERCALL_BUFFER(_name), _nr)
+void xc__hypercall_buffer_free_pages(xc_interface *xch, xc_hypercall_buffer_t *b, int nr_pages);
+#define xc_hypercall_buffer_free_pages(_xch, _name, _nr) xc__hypercall_buffer_free_pages(_xch, HYPERCALL_BUFFER(_name), _nr)
+
+/*
+ * Array of hypercall buffers.
+ *
+ * Create an array with xc_hypercall_buffer_array_create() and
+ * populate it by declaring one hypercall buffer in a loop and
+ * allocating the buffer with xc_hypercall_buffer_array_alloc().
+ *
+ * To access a previously allocated buffers, declare a new hypercall
+ * buffer and call xc_hypercall_buffer_array_get().
+ *
+ * Destroy the array with xc_hypercall_buffer_array_destroy() to free
+ * the array and all its alocated hypercall buffers.
+ */
+struct xc_hypercall_buffer_array;
+typedef struct xc_hypercall_buffer_array xc_hypercall_buffer_array_t;
+
+xc_hypercall_buffer_array_t *xc_hypercall_buffer_array_create(xc_interface *xch, unsigned n);
+void *xc__hypercall_buffer_array_alloc(xc_interface *xch, xc_hypercall_buffer_array_t *array,
+ unsigned index, xc_hypercall_buffer_t *hbuf, size_t size);
+#define xc_hypercall_buffer_array_alloc(_xch, _array, _index, _name, _size) \
+ xc__hypercall_buffer_array_alloc(_xch, _array, _index, HYPERCALL_BUFFER(_name), _size)
+void *xc__hypercall_buffer_array_get(xc_interface *xch, xc_hypercall_buffer_array_t *array,
+ unsigned index, xc_hypercall_buffer_t *hbuf);
+#define xc_hypercall_buffer_array_get(_xch, _array, _index, _name, _size) \
+ xc__hypercall_buffer_array_get(_xch, _array, _index, HYPERCALL_BUFFER(_name))
+void xc_hypercall_buffer_array_destroy(xc_interface *xc, xc_hypercall_buffer_array_t *array);
+
+/*
+ * CPUMAP handling
+ */
+typedef uint8_t *xc_cpumap_t;
+
+/* return maximum number of cpus the hypervisor supports */
+int xc_get_max_cpus(xc_interface *xch);
+
+/* return the number of online cpus */
+int xc_get_online_cpus(xc_interface *xch);
+
+/* return array size for cpumap */
+int xc_get_cpumap_size(xc_interface *xch);
+
+/* allocate a cpumap */
+xc_cpumap_t xc_cpumap_alloc(xc_interface *xch);
+
+/*
+ * NODEMAP handling
+ */
+typedef uint8_t *xc_nodemap_t;
+
+/* return maximum number of NUMA nodes the hypervisor supports */
+int xc_get_max_nodes(xc_interface *xch);
+
+/* return array size for nodemap */
+int xc_get_nodemap_size(xc_interface *xch);
+
+/* allocate a nodemap */
+xc_nodemap_t xc_nodemap_alloc(xc_interface *xch);
+
+/*
+ * DOMAIN DEBUGGING FUNCTIONS
+ */
+
+typedef struct xc_core_header {
+ unsigned int xch_magic;
+ unsigned int xch_nr_vcpus;
+ unsigned int xch_nr_pages;
+ unsigned int xch_ctxt_offset;
+ unsigned int xch_index_offset;
+ unsigned int xch_pages_offset;
+} xc_core_header_t;
+
+#define XC_CORE_MAGIC 0xF00FEBED
+#define XC_CORE_MAGIC_HVM 0xF00FEBEE
+
+/*
+ * DOMAIN MANAGEMENT FUNCTIONS
+ */
+
+typedef struct xc_dominfo {
+ uint32_t domid;
+ uint32_t ssidref;
+ unsigned int dying:1, crashed:1, shutdown:1,
+ paused:1, blocked:1, running:1,
+ hvm:1, debugged:1, pvh:1;
+ unsigned int shutdown_reason; /* only meaningful if shutdown==1 */
+ unsigned long nr_pages; /* current number, not maximum */
+ unsigned long nr_outstanding_pages;
+ unsigned long nr_shared_pages;
+ unsigned long nr_paged_pages;
+ unsigned long shared_info_frame;
+ uint64_t cpu_time;
+ unsigned long max_memkb;
+ unsigned int nr_online_vcpus;
+ unsigned int max_vcpu_id;
+ xen_domain_handle_t handle;
+ unsigned int cpupool;
+} xc_dominfo_t;
+
+typedef xen_domctl_getdomaininfo_t xc_domaininfo_t;
+
+typedef union
+{
+#if defined(__i386__) || defined(__x86_64__)
+ vcpu_guest_context_x86_64_t x64;
+ vcpu_guest_context_x86_32_t x32;
+#endif
+ vcpu_guest_context_t c;
+} vcpu_guest_context_any_t;
+
+typedef union
+{
+#if defined(__i386__) || defined(__x86_64__)
+ shared_info_x86_64_t x64;
+ shared_info_x86_32_t x32;
+#endif
+ shared_info_t s;
+} shared_info_any_t;
+
+#if defined(__i386__) || defined(__x86_64__)
+typedef union
+{
+ start_info_x86_64_t x64;
+ start_info_x86_32_t x32;
+ start_info_t s;
+} start_info_any_t;
+#endif
+
+int xc_domain_create(xc_interface *xch,
+ uint32_t ssidref,
+ xen_domain_handle_t handle,
+ uint32_t flags,
+ uint32_t *pdomid);
+
+#if defined(__arm__) || defined(__aarch64__)
+typedef xen_domctl_arm_configuredomain_t xc_domain_configuration_t;
+
+int xc_domain_configure(xc_interface *xch, uint32_t domid,
+ xc_domain_configuration_t *config);
+#endif
+
+/* Functions to produce a dump of a given domain
+ * xc_domain_dumpcore - produces a dump to a specified file
+ * xc_domain_dumpcore_via_callback - produces a dump, using a specified
+ * callback function
+ */
+int xc_domain_dumpcore(xc_interface *xch,
+ uint32_t domid,
+ const char *corename);
+
+/* Define the callback function type for xc_domain_dumpcore_via_callback.
+ *
+ * This function is called by the coredump code for every "write",
+ * and passes an opaque object for the use of the function and
+ * created by the caller of xc_domain_dumpcore_via_callback.
+ */
+typedef int (dumpcore_rtn_t)(xc_interface *xch,
+ void *arg, char *buffer, unsigned int length);
+
+int xc_domain_dumpcore_via_callback(xc_interface *xch,
+ uint32_t domid,
+ void *arg,
+ dumpcore_rtn_t dump_rtn);
+
+/*
+ * This function sets the maximum number of vcpus that a domain may create.
+ *
+ * @parm xch a handle to an open hypervisor interface.
+ * @parm domid the domain id in which vcpus are to be created.
+ * @parm max the maximum number of vcpus that the domain may create.
+ * @return 0 on success, -1 on failure.
+ */
+int xc_domain_max_vcpus(xc_interface *xch,
+ uint32_t domid,
+ unsigned int max);
+
+/**
+ * This function pauses a domain. A paused domain still exists in memory
+ * however it does not receive any timeslices from the hypervisor.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain id to pause
+ * @return 0 on success, -1 on failure.
+ */
+int xc_domain_pause(xc_interface *xch,
+ uint32_t domid);
+/**
+ * This function unpauses a domain. The domain should have been previously
+ * paused.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain id to unpause
+ * return 0 on success, -1 on failure
+ */
+int xc_domain_unpause(xc_interface *xch,
+ uint32_t domid);
+
+/**
+ * This function will destroy a domain. Destroying a domain removes the domain
+ * completely from memory. This function should be called after sending the
+ * domain a SHUTDOWN control message to free up the domain resources.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain id to destroy
+ * @return 0 on success, -1 on failure
+ */
+int xc_domain_destroy(xc_interface *xch,
+ uint32_t domid);
+
+
+/**
+ * This function resumes a suspended domain. The domain should have
+ * been previously suspended.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain id to resume
+ * @parm fast use cooperative resume (guest must support this)
+ * return 0 on success, -1 on failure
+ */
+int xc_domain_resume(xc_interface *xch,
+ uint32_t domid,
+ int fast);
+
+/**
+ * This function will shutdown a domain. This is intended for use in
+ * fully-virtualized domains where this operation is analogous to the
+ * sched_op operations in a paravirtualized domain. The caller is
+ * expected to give the reason for the shutdown.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain id to destroy
+ * @parm reason is the reason (SHUTDOWN_xxx) for the shutdown
+ * @return 0 on success, -1 on failure
+ */
+int xc_domain_shutdown(xc_interface *xch,
+ uint32_t domid,
+ int reason);
+
+int xc_watchdog(xc_interface *xch,
+ uint32_t id,
+ uint32_t timeout);
+
+/**
+ * This function explicitly sets the host NUMA nodes the domain will
+ * have affinity with.
+ *
+ * @parm xch a handle to an open hypervisor interface.
+ * @parm domid the domain id one wants to set the affinity of.
+ * @parm nodemap the map of the affine nodes.
+ * @return 0 on success, -1 on failure.
+ */
+int xc_domain_node_setaffinity(xc_interface *xch,
+ uint32_t domind,
+ xc_nodemap_t nodemap);
+
+/**
+ * This function retrieves the host NUMA nodes the domain has
+ * affinity with.
+ *
+ * @parm xch a handle to an open hypervisor interface.
+ * @parm domid the domain id one wants to get the node affinity of.
+ * @parm nodemap the map of the affine nodes.
+ * @return 0 on success, -1 on failure.
+ */
+int xc_domain_node_getaffinity(xc_interface *xch,
+ uint32_t domind,
+ xc_nodemap_t nodemap);
+
+/**
+ * This function specifies the CPU affinity for a vcpu.
+ *
+ * There are two kinds of affinity. Soft affinity is on what CPUs a vcpu
+ * prefers to run. Hard affinity is on what CPUs a vcpu is allowed to run.
+ * If flags contains XEN_VCPUAFFINITY_SOFT, the soft affinity it is set to
+ * what cpumap_soft_inout contains. If flags contains XEN_VCPUAFFINITY_HARD,
+ * the hard affinity is set to what cpumap_hard_inout contains. Both flags
+ * can be set at the same time, in which case both soft and hard affinity are
+ * set to what the respective parameter contains.
+ *
+ * The function also returns the effective hard or/and soft affinity, still
+ * via the cpumap_soft_inout and cpumap_hard_inout parameters. Effective
+ * affinity is, in case of soft affinity, the intersection of soft affinity,
+ * hard affinity and the cpupool's online CPUs for the domain, and is returned
+ * in cpumap_soft_inout, if XEN_VCPUAFFINITY_SOFT is set in flags. In case of
+ * hard affinity, it is the intersection between hard affinity and the
+ * cpupool's online CPUs, and is returned in cpumap_hard_inout, if
+ * XEN_VCPUAFFINITY_HARD is set in flags. If both flags are set, both soft
+ * and hard affinity are returned in the respective parameter.
+ *
+ * We do report it back as effective affinity is what the Xen scheduler will
+ * actually use, and we thus allow checking whether or not that matches with,
+ * or at least is good enough for, the caller's purposes.
+ *
+ * @param xch a handle to an open hypervisor interface.
+ * @param domid the id of the domain to which the vcpu belongs
+ * @param vcpu the vcpu id wihin the domain
+ * @param cpumap_hard_inout specifies(/returns) the (effective) hard affinity
+ * @param cpumap_soft_inout specifies(/returns) the (effective) soft affinity
+ * @param flags what we want to set
+ */
+int xc_vcpu_setaffinity(xc_interface *xch,
+ uint32_t domid,
+ int vcpu,
+ xc_cpumap_t cpumap_hard_inout,
+ xc_cpumap_t cpumap_soft_inout,
+ uint32_t flags);
+
+/**
+ * This function retrieves hard and soft CPU affinity of a vcpu,
+ * depending on what flags are set.
+ *
+ * Soft affinity is returned in cpumap_soft if XEN_VCPUAFFINITY_SOFT is set.
+ * Hard affinity is returned in cpumap_hard if XEN_VCPUAFFINITY_HARD is set.
+ *
+ * @param xch a handle to an open hypervisor interface.
+ * @param domid the id of the domain to which the vcpu belongs
+ * @param vcpu the vcpu id wihin the domain
+ * @param cpumap_hard is where hard affinity is returned
+ * @param cpumap_soft is where soft affinity is returned
+ * @param flags what we want get
+ */
+int xc_vcpu_getaffinity(xc_interface *xch,
+ uint32_t domid,
+ int vcpu,
+ xc_cpumap_t cpumap_hard,
+ xc_cpumap_t cpumap_soft,
+ uint32_t flags);
+
+
+/**
+ * This function will return the guest_width (in bytes) for the
+ * specified domain.
+ *
+ * @param xch a handle to an open hypervisor interface.
+ * @param domid the domain id one wants the address size width of.
+ * @param addr_size the address size.
+ */
+int xc_domain_get_guest_width(xc_interface *xch, uint32_t domid,
+ unsigned int *guest_width);
+
+
+/**
+ * This function will return information about one or more domains. It is
+ * designed to iterate over the list of domains. If a single domain is
+ * requested, this function will return the next domain in the list - if
+ * one exists. It is, therefore, important in this case to make sure the
+ * domain requested was the one returned.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm first_domid the first domain to enumerate information from. Domains
+ * are currently enumerate in order of creation.
+ * @parm max_doms the number of elements in info
+ * @parm info an array of max_doms size that will contain the information for
+ * the enumerated domains.
+ * @return the number of domains enumerated or -1 on error
+ */
+int xc_domain_getinfo(xc_interface *xch,
+ uint32_t first_domid,
+ unsigned int max_doms,
+ xc_dominfo_t *info);
+
+
+/**
+ * This function will set the execution context for the specified vcpu.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain to set the vcpu context for
+ * @parm vcpu the vcpu number for the context
+ * @parm ctxt pointer to the the cpu context with the values to set
+ * @return the number of domains enumerated or -1 on error
+ */
+int xc_vcpu_setcontext(xc_interface *xch,
+ uint32_t domid,
+ uint32_t vcpu,
+ vcpu_guest_context_any_t *ctxt);
+/**
+ * This function will return information about one or more domains, using a
+ * single hypercall. The domain information will be stored into the supplied
+ * array of xc_domaininfo_t structures.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm first_domain the first domain to enumerate information from.
+ * Domains are currently enumerate in order of creation.
+ * @parm max_domains the number of elements in info
+ * @parm info an array of max_doms size that will contain the information for
+ * the enumerated domains.
+ * @return the number of domains enumerated or -1 on error
+ */
+int xc_domain_getinfolist(xc_interface *xch,
+ uint32_t first_domain,
+ unsigned int max_domains,
+ xc_domaininfo_t *info);
+
+/**
+ * This function set p2m for broken page
+ * &parm xch a handle to an open hypervisor interface
+ * @parm domid the domain id which broken page belong to
+ * @parm pfn the pfn number of the broken page
+ * @return 0 on success, -1 on failure
+ */
+int xc_set_broken_page_p2m(xc_interface *xch,
+ uint32_t domid,
+ unsigned long pfn);
+
+/**
+ * This function returns information about the context of a hvm domain
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain to get information from
+ * @parm ctxt_buf a pointer to a structure to store the execution context of
+ * the hvm domain
+ * @parm size the size of ctxt_buf in bytes
+ * @return 0 on success, -1 on failure
+ */
+int xc_domain_hvm_getcontext(xc_interface *xch,
+ uint32_t domid,
+ uint8_t *ctxt_buf,
+ uint32_t size);
+
+
+/**
+ * This function returns one element of the context of a hvm domain
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain to get information from
+ * @parm typecode which type of elemnt required
+ * @parm instance which instance of the type
+ * @parm ctxt_buf a pointer to a structure to store the execution context of
+ * the hvm domain
+ * @parm size the size of ctxt_buf (must be >= HVM_SAVE_LENGTH(typecode))
+ * @return 0 on success, -1 on failure
+ */
+int xc_domain_hvm_getcontext_partial(xc_interface *xch,
+ uint32_t domid,
+ uint16_t typecode,
+ uint16_t instance,
+ void *ctxt_buf,
+ uint32_t size);
+
+/**
+ * This function will set the context for hvm domain
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain to set the hvm domain context for
+ * @parm hvm_ctxt pointer to the the hvm context with the values to set
+ * @parm size the size of hvm_ctxt in bytes
+ * @return 0 on success, -1 on failure
+ */
+int xc_domain_hvm_setcontext(xc_interface *xch,
+ uint32_t domid,
+ uint8_t *hvm_ctxt,
+ uint32_t size);
+
+/**
+ * This function will return guest IO ABI protocol
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain to get IO ABI protocol for
+ * @return guest protocol on success, NULL on failure
+ */
+const char *xc_domain_get_native_protocol(xc_interface *xch,
+ uint32_t domid);
+
+/**
+ * This function returns information about the execution context of a
+ * particular vcpu of a domain.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain to get information from
+ * @parm vcpu the vcpu number
+ * @parm ctxt a pointer to a structure to store the execution context of the
+ * domain
+ * @return 0 on success, -1 on failure
+ */
+int xc_vcpu_getcontext(xc_interface *xch,
+ uint32_t domid,
+ uint32_t vcpu,
+ vcpu_guest_context_any_t *ctxt);
+
+typedef xen_domctl_getvcpuinfo_t xc_vcpuinfo_t;
+int xc_vcpu_getinfo(xc_interface *xch,
+ uint32_t domid,
+ uint32_t vcpu,
+ xc_vcpuinfo_t *info);
+
+long long xc_domain_get_cpu_usage(xc_interface *xch,
+ domid_t domid,
+ int vcpu);
+
+int xc_domain_sethandle(xc_interface *xch, uint32_t domid,
+ xen_domain_handle_t handle);
+
+typedef xen_domctl_shadow_op_stats_t xc_shadow_op_stats_t;
+int xc_shadow_control(xc_interface *xch,
+ uint32_t domid,
+ unsigned int sop,
+ xc_hypercall_buffer_t *dirty_bitmap,
+ unsigned long pages,
+ unsigned long *mb,
+ uint32_t mode,
+ xc_shadow_op_stats_t *stats);
+
+int xc_sedf_domain_set(xc_interface *xch,
+ uint32_t domid,
+ uint64_t period, uint64_t slice,
+ uint64_t latency, uint16_t extratime,
+ uint16_t weight);
+
+int xc_sedf_domain_get(xc_interface *xch,
+ uint32_t domid,
+ uint64_t* period, uint64_t *slice,
+ uint64_t *latency, uint16_t *extratime,
+ uint16_t *weight);
+
+int xc_sched_credit_domain_set(xc_interface *xch,
+ uint32_t domid,
+ struct xen_domctl_sched_credit *sdom);
+
+int xc_sched_credit_domain_get(xc_interface *xch,
+ uint32_t domid,
+ struct xen_domctl_sched_credit *sdom);
+int xc_sched_credit_params_set(xc_interface *xch,
+ uint32_t cpupool_id,
+ struct xen_sysctl_credit_schedule *schedule);
+int xc_sched_credit_params_get(xc_interface *xch,
+ uint32_t cpupool_id,
+ struct xen_sysctl_credit_schedule *schedule);
+int xc_sched_credit2_domain_set(xc_interface *xch,
+ uint32_t domid,
+ struct xen_domctl_sched_credit2 *sdom);
+
+int xc_sched_credit2_domain_get(xc_interface *xch,
+ uint32_t domid,
+ struct xen_domctl_sched_credit2 *sdom);
+
+int xc_sched_rtds_domain_set(xc_interface *xch,
+ uint32_t domid,
+ struct xen_domctl_sched_rtds *sdom);
+int xc_sched_rtds_domain_get(xc_interface *xch,
+ uint32_t domid,
+ struct xen_domctl_sched_rtds *sdom);
+
+int
+xc_sched_arinc653_schedule_set(
+ xc_interface *xch,
+ uint32_t cpupool_id,
+ struct xen_sysctl_arinc653_schedule *schedule);
+
+int
+xc_sched_arinc653_schedule_get(
+ xc_interface *xch,
+ uint32_t cpupool_id,
+ struct xen_sysctl_arinc653_schedule *schedule);
+
+/**
+ * This function sends a trigger to a domain.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain id to send trigger
+ * @parm trigger the trigger type
+ * @parm vcpu the vcpu number to send trigger
+ * return 0 on success, -1 on failure
+ */
+int xc_domain_send_trigger(xc_interface *xch,
+ uint32_t domid,
+ uint32_t trigger,
+ uint32_t vcpu);
+
+/**
+ * This function enables or disable debugging of a domain.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain id to send trigger
+ * @parm enable true to enable debugging
+ * return 0 on success, -1 on failure
+ */
+int xc_domain_setdebugging(xc_interface *xch,
+ uint32_t domid,
+ unsigned int enable);
+
+/**
+ * This function audits the (top level) p2m of a domain
+ * and returns the different error counts, if any.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain id whose top level p2m we
+ * want to audit
+ * @parm orphans count of m2p entries for valid
+ * domain pages containing an invalid value
+ * @parm m2p_bad count of m2p entries mismatching the
+ * associated p2m entry for this domain
+ * @parm p2m_bad count of p2m entries for this domain
+ * mismatching the associated m2p entry
+ * return 0 on success, -1 on failure
+ * errno values on failure include:
+ * -ENOSYS: not implemented
+ * -EFAULT: could not copy results back to guest
+ */
+int xc_domain_p2m_audit(xc_interface *xch,
+ uint32_t domid,
+ uint64_t *orphans,
+ uint64_t *m2p_bad,
+ uint64_t *p2m_bad);
+
+/**
+ * This function sets or clears the requirement that an access memory
+ * event listener is required on the domain.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain id to send trigger
+ * @parm enable true to require a listener
+ * return 0 on success, -1 on failure
+ */
+int xc_domain_set_access_required(xc_interface *xch,
+ uint32_t domid,
+ unsigned int required);
+/**
+ * This function sets the handler of global VIRQs sent by the hypervisor
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain id which will handle the VIRQ
+ * @parm virq the virq number (VIRQ_*)
+ * return 0 on success, -1 on failure
+ */
+int xc_domain_set_virq_handler(xc_interface *xch, uint32_t domid, int virq);
+
+/**
+ * Set the maximum event channel port a domain may bind.
+ *
+ * This does not affect ports that are already bound.
+ *
+ * @param xch a handle to an open hypervisor interface
+ * @param domid the domain id
+ * @param max_port maximum port number
+ */
+int xc_domain_set_max_evtchn(xc_interface *xch, uint32_t domid,
+ uint32_t max_port);
+
+/*
+ * CPUPOOL MANAGEMENT FUNCTIONS
+ */
+
+typedef struct xc_cpupoolinfo {
+ uint32_t cpupool_id;
+ uint32_t sched_id;
+ uint32_t n_dom;
+ xc_cpumap_t cpumap;
+} xc_cpupoolinfo_t;
+
+/**
+ * Create a new cpupool.
+ *
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm ppoolid pointer to the new cpupool id (in/out)
+ * @parm sched_id id of scheduler to use for pool
+ * return 0 on success, -1 on failure
+ */
+int xc_cpupool_create(xc_interface *xch,
+ uint32_t *ppoolid,
+ uint32_t sched_id);
+
+/**
+ * Destroy a cpupool. Pool must be unused and have no cpu assigned.
+ *
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm poolid id of the cpupool to destroy
+ * return 0 on success, -1 on failure
+ */
+int xc_cpupool_destroy(xc_interface *xch,
+ uint32_t poolid);
+
+/**
+ * Get cpupool info. Returns info for up to the specified number of cpupools
+ * starting at the given id.
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm poolid lowest id for which info is returned
+ * return cpupool info ptr (to be freed via xc_cpupool_infofree)
+ */
+xc_cpupoolinfo_t *xc_cpupool_getinfo(xc_interface *xch,
+ uint32_t poolid);
+
+/**
+ * Free cpupool info. Used to free info obtained via xc_cpupool_getinfo.
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm info area to free
+ */
+void xc_cpupool_infofree(xc_interface *xch,
+ xc_cpupoolinfo_t *info);
+
+/**
+ * Add cpu to a cpupool. cpu may be -1 indicating the first unassigned.
+ *
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm poolid id of the cpupool
+ * @parm cpu cpu number to add
+ * return 0 on success, -1 on failure
+ */
+int xc_cpupool_addcpu(xc_interface *xch,
+ uint32_t poolid,
+ int cpu);
+
+/**
+ * Remove cpu from cpupool. cpu may be -1 indicating the last cpu of the pool.
+ *
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm poolid id of the cpupool
+ * @parm cpu cpu number to remove
+ * return 0 on success, -1 on failure
+ */
+int xc_cpupool_removecpu(xc_interface *xch,
+ uint32_t poolid,
+ int cpu);
+
+/**
+ * Move domain to another cpupool.
+ *
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm poolid id of the destination cpupool
+ * @parm domid id of the domain to move
+ * return 0 on success, -1 on failure
+ */
+int xc_cpupool_movedomain(xc_interface *xch,
+ uint32_t poolid,
+ uint32_t domid);
+
+/**
+ * Return map of cpus not in any cpupool.
+ *
+ * @parm xc_handle a handle to an open hypervisor interface
+ * return cpumap array on success, NULL else
+ */
+xc_cpumap_t xc_cpupool_freeinfo(xc_interface *xch);
+
+
+/*
+ * EVENT CHANNEL FUNCTIONS
+ *
+ * None of these do any logging.
+ */
+
+/* A port identifier is guaranteed to fit in 31 bits. */
+typedef int evtchn_port_or_error_t;
+
+/**
+ * This function allocates an unbound port. Ports are named endpoints used for
+ * interdomain communication. This function is most useful in opening a
+ * well-known port within a domain to receive events on.
+ *
+ * NOTE: If you are allocating a *local* unbound port, you probably want to
+ * use xc_evtchn_bind_unbound_port(). This function is intended for allocating
+ * ports *only* during domain creation.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm dom the ID of the local domain (the 'allocatee')
+ * @parm remote_dom the ID of the domain who will later bind
+ * @return allocated port (in @dom) on success, -1 on failure
+ */
+evtchn_port_or_error_t
+xc_evtchn_alloc_unbound(xc_interface *xch,
+ uint32_t dom,
+ uint32_t remote_dom);
+
+int xc_evtchn_reset(xc_interface *xch,
+ uint32_t dom);
+
+typedef struct evtchn_status xc_evtchn_status_t;
+int xc_evtchn_status(xc_interface *xch, xc_evtchn_status_t *status);
+
+/*
+ * Return a handle to the event channel driver, or NULL on failure, in
+ * which case errno will be set appropriately.
+ *
+ * Note:
+ * After fork a child process must not use any opened xc evtchn
+ * handle inherited from their parent. They must open a new handle if
+ * they want to interact with xc.
+ *
+ * Before Xen pre-4.1 this function would sometimes report errors with perror.
+ */
+xc_evtchn *xc_evtchn_open(xentoollog_logger *logger,
+ unsigned open_flags);
+
+/*
+ * Close a handle previously allocated with xc_evtchn_open().
+ */
+int xc_evtchn_close(xc_evtchn *xce);
+
+/*
+ * Return an fd that can be select()ed on.
+ *
+ * Note that due to bugs, setting this fd to non blocking may not
+ * work: you would hope that it would result in xc_evtchn_pending
+ * failing with EWOULDBLOCK if there are no events signaled, but in
+ * fact it may block. (Bug is present in at least Linux 3.12, and
+ * perhaps on other platforms or later version.)
+ *
+ * To be safe, you must use poll() or select() before each call to
+ * xc_evtchn_pending. If you have multiple threads (or processes)
+ * sharing a single xce handle this will not work, and there is no
+ * straightforward workaround. Please design your program some other
+ * way.
+ */
+int xc_evtchn_fd(xc_evtchn *xce);
+
+/*
+ * Notify the given event channel. Returns -1 on failure, in which case
+ * errno will be set appropriately.
+ */
+int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port);
+
+/*
+ * Returns a new event port awaiting interdomain connection from the given
+ * domain ID, or -1 on failure, in which case errno will be set appropriately.
+ */
+evtchn_port_or_error_t
+xc_evtchn_bind_unbound_port(xc_evtchn *xce, int domid);
+
+/*
+ * Returns a new event port bound to the remote port for the given domain ID,
+ * or -1 on failure, in which case errno will be set appropriately.
+ */
+evtchn_port_or_error_t
+xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid,
+ evtchn_port_t remote_port);
+
+/*
+ * Bind an event channel to the given VIRQ. Returns the event channel bound to
+ * the VIRQ, or -1 on failure, in which case errno will be set appropriately.
+ */
+evtchn_port_or_error_t
+xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq);
+
+/*
+ * Unbind the given event channel. Returns -1 on failure, in which case errno
+ * will be set appropriately.
+ */
+int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port);
+
+/*
+ * Return the next event channel to become pending, or -1 on failure, in which
+ * case errno will be set appropriately.
+ *
+ * At the hypervisor level the event channel will have been masked,
+ * and then cleared, by the underlying machinery (evtchn kernel
+ * driver, or equivalent). So if the event channel is signaled again
+ * after it is returned here, it will be queued up, and delivered
+ * again after you unmask it. (See the documentation in the Xen
+ * public header event_channel.h.)
+ *
+ * On receiving the notification from xc_evtchn_pending, you should
+ * normally: check (by other means) what work needs doing; do the
+ * necessary work (if any); unmask the event channel with
+ * xc_evtchn_unmask (if you want to receive any further
+ * notifications).
+ */
+evtchn_port_or_error_t
+xc_evtchn_pending(xc_evtchn *xce);
+
+/*
+ * Unmask the given event channel. Returns -1 on failure, in which case errno
+ * will be set appropriately.
+ */
+int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port);
+
+int xc_physdev_pci_access_modify(xc_interface *xch,
+ uint32_t domid,
+ int bus,
+ int dev,
+ int func,
+ int enable);
+
+int xc_readconsolering(xc_interface *xch,
+ char *buffer,
+ unsigned int *pnr_chars,
+ int clear, int incremental, uint32_t *pindex);
+
+int xc_send_debug_keys(xc_interface *xch, char *keys);
+
+typedef xen_sysctl_physinfo_t xc_physinfo_t;
+typedef xen_sysctl_topologyinfo_t xc_topologyinfo_t;
+typedef xen_sysctl_numainfo_t xc_numainfo_t;
+
+typedef uint32_t xc_cpu_to_node_t;
+typedef uint32_t xc_cpu_to_socket_t;
+typedef uint32_t xc_cpu_to_core_t;
+typedef uint64_t xc_node_to_memsize_t;
+typedef uint64_t xc_node_to_memfree_t;
+typedef uint32_t xc_node_to_node_dist_t;
+
+int xc_physinfo(xc_interface *xch, xc_physinfo_t *info);
+int xc_topologyinfo(xc_interface *xch, xc_topologyinfo_t *info);
+int xc_numainfo(xc_interface *xch, xc_numainfo_t *info);
+
+int xc_sched_id(xc_interface *xch,
+ int *sched_id);
+
+int xc_machphys_mfn_list(xc_interface *xch,
+ unsigned long max_extents,
+ xen_pfn_t *extent_start);
+
+typedef xen_sysctl_cpuinfo_t xc_cpuinfo_t;
+int xc_getcpuinfo(xc_interface *xch, int max_cpus,
+ xc_cpuinfo_t *info, int *nr_cpus);
+
+int xc_domain_setmaxmem(xc_interface *xch,
+ uint32_t domid,
+ unsigned int max_memkb);
+
+int xc_domain_set_memmap_limit(xc_interface *xch,
+ uint32_t domid,
+ unsigned long map_limitkb);
+
+int xc_domain_setvnuma(xc_interface *xch,
+ uint32_t domid,
+ uint32_t nr_vnodes,
+ uint32_t nr_regions,
+ uint32_t nr_vcpus,
+ xen_vmemrange_t *vmemrange,
+ unsigned int *vdistance,
+ unsigned int *vcpu_to_vnode,
+ unsigned int *vnode_to_pnode);
+
+#if defined(__i386__) || defined(__x86_64__)
+/*
+ * PC BIOS standard E820 types and structure.
+ */
+#define E820_RAM 1
+#define E820_RESERVED 2
+#define E820_ACPI 3
+#define E820_NVS 4
+#define E820_UNUSABLE 5
+
+#define E820MAX (128)
+
+struct e820entry {
+ uint64_t addr;
+ uint64_t size;
+ uint32_t type;
+} __attribute__((packed));
+int xc_domain_set_memory_map(xc_interface *xch,
+ uint32_t domid,
+ struct e820entry entries[],
+ uint32_t nr_entries);
+
+int xc_get_machine_memory_map(xc_interface *xch,
+ struct e820entry entries[],
+ uint32_t max_entries);
+#endif
+int xc_domain_set_time_offset(xc_interface *xch,
+ uint32_t domid,
+ int32_t time_offset_seconds);
+
+int xc_domain_set_tsc_info(xc_interface *xch,
+ uint32_t domid,
+ uint32_t tsc_mode,
+ uint64_t elapsed_nsec,
+ uint32_t gtsc_khz,
+ uint32_t incarnation);
+
+int xc_domain_get_tsc_info(xc_interface *xch,
+ uint32_t domid,
+ uint32_t *tsc_mode,
+ uint64_t *elapsed_nsec,
+ uint32_t *gtsc_khz,
+ uint32_t *incarnation);
+
+int xc_domain_disable_migrate(xc_interface *xch, uint32_t domid);
+
+int xc_domain_maximum_gpfn(xc_interface *xch, domid_t domid);
+
+int xc_domain_increase_reservation(xc_interface *xch,
+ uint32_t domid,
+ unsigned long nr_extents,
+ unsigned int extent_order,
+ unsigned int mem_flags,
+ xen_pfn_t *extent_start);
+
+int xc_domain_increase_reservation_exact(xc_interface *xch,
+ uint32_t domid,
+ unsigned long nr_extents,
+ unsigned int extent_order,
+ unsigned int mem_flags,
+ xen_pfn_t *extent_start);
+
+int xc_domain_decrease_reservation(xc_interface *xch,
+ uint32_t domid,
+ unsigned long nr_extents,
+ unsigned int extent_order,
+ xen_pfn_t *extent_start);
+
+int xc_domain_decrease_reservation_exact(xc_interface *xch,
+ uint32_t domid,
+ unsigned long nr_extents,
+ unsigned int extent_order,
+ xen_pfn_t *extent_start);
+
+int xc_domain_add_to_physmap(xc_interface *xch,
+ uint32_t domid,
+ unsigned int space,
+ unsigned long idx,
+ xen_pfn_t gpfn);
+
+int xc_domain_populate_physmap(xc_interface *xch,
+ uint32_t domid,
+ unsigned long nr_extents,
+ unsigned int extent_order,
+ unsigned int mem_flags,
+ xen_pfn_t *extent_start);
+
+int xc_domain_populate_physmap_exact(xc_interface *xch,
+ uint32_t domid,
+ unsigned long nr_extents,
+ unsigned int extent_order,
+ unsigned int mem_flags,
+ xen_pfn_t *extent_start);
+
+int xc_domain_claim_pages(xc_interface *xch,
+ uint32_t domid,
+ unsigned long nr_pages);
+
+int xc_domain_memory_exchange_pages(xc_interface *xch,
+ int domid,
+ unsigned long nr_in_extents,
+ unsigned int in_order,
+ xen_pfn_t *in_extents,
+ unsigned long nr_out_extents,
+ unsigned int out_order,
+ xen_pfn_t *out_extents);
+
+int xc_domain_set_pod_target(xc_interface *xch,
+ uint32_t domid,
+ uint64_t target_pages,
+ uint64_t *tot_pages,
+ uint64_t *pod_cache_pages,
+ uint64_t *pod_entries);
+
+int xc_domain_get_pod_target(xc_interface *xch,
+ uint32_t domid,
+ uint64_t *tot_pages,
+ uint64_t *pod_cache_pages,
+ uint64_t *pod_entries);
+
+int xc_domain_ioport_permission(xc_interface *xch,
+ uint32_t domid,
+ uint32_t first_port,
+ uint32_t nr_ports,
+ uint32_t allow_access);
+
+int xc_domain_irq_permission(xc_interface *xch,
+ uint32_t domid,
+ uint8_t pirq,
+ uint8_t allow_access);
+
+int xc_domain_iomem_permission(xc_interface *xch,
+ uint32_t domid,
+ unsigned long first_mfn,
+ unsigned long nr_mfns,
+ uint8_t allow_access);
+
+int xc_domain_pin_memory_cacheattr(xc_interface *xch,
+ uint32_t domid,
+ uint64_t start,
+ uint64_t end,
+ uint32_t type);
+
+unsigned long xc_make_page_below_4G(xc_interface *xch, uint32_t domid,
+ unsigned long mfn);
+
+typedef xen_sysctl_perfc_desc_t xc_perfc_desc_t;
+typedef xen_sysctl_perfc_val_t xc_perfc_val_t;
+int xc_perfc_reset(xc_interface *xch);
+int xc_perfc_query_number(xc_interface *xch,
+ int *nbr_desc,
+ int *nbr_val);
+int xc_perfc_query(xc_interface *xch,
+ xc_hypercall_buffer_t *desc,
+ xc_hypercall_buffer_t *val);
+
+typedef xen_sysctl_lockprof_data_t xc_lockprof_data_t;
+int xc_lockprof_reset(xc_interface *xch);
+int xc_lockprof_query_number(xc_interface *xch,
+ uint32_t *n_elems);
+int xc_lockprof_query(xc_interface *xch,
+ uint32_t *n_elems,
+ uint64_t *time,
+ xc_hypercall_buffer_t *data);
+
+void *xc_memalign(xc_interface *xch, size_t alignment, size_t size);
+
+/**
+ * Memory maps a range within one domain to a local address range. Mappings
+ * should be unmapped with munmap and should follow the same rules as mmap
+ * regarding page alignment. Returns NULL on failure.
+ *
+ * @parm xch a handle on an open hypervisor interface
+ * @parm dom the domain to map memory from
+ * @parm size the amount of memory to map (in multiples of page size)
+ * @parm prot same flag as in mmap().
+ * @parm mfn the frame address to map.
+ */
+void *xc_map_foreign_range(xc_interface *xch, uint32_t dom,
+ int size, int prot,
+ unsigned long mfn );
+
+void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
+ const xen_pfn_t *arr, int num );
+
+/**
+ * DEPRECATED - use xc_map_foreign_bulk() instead.
+ *
+ * Like xc_map_foreign_pages(), except it can succeeed partially.
+ * When a page cannot be mapped, its PFN in @arr is or'ed with
+ * 0xF0000000 to indicate the error.
+ */
+void *xc_map_foreign_batch(xc_interface *xch, uint32_t dom, int prot,
+ xen_pfn_t *arr, int num );
+
+/**
+ * Like xc_map_foreign_pages(), except it can succeed partially.
+ * When a page cannot be mapped, its respective field in @err is
+ * set to the corresponding errno value.
+ */
+void *xc_map_foreign_bulk(xc_interface *xch, uint32_t dom, int prot,
+ const xen_pfn_t *arr, int *err, unsigned int num);
+
+/**
+ * Translates a virtual address in the context of a given domain and
+ * vcpu returning the GFN containing the address (that is, an MFN for
+ * PV guests, a PFN for HVM guests). Returns 0 for failure.
+ *
+ * @parm xch a handle on an open hypervisor interface
+ * @parm dom the domain to perform the translation in
+ * @parm vcpu the vcpu to perform the translation on
+ * @parm virt the virtual address to translate
+ */
+unsigned long xc_translate_foreign_address(xc_interface *xch, uint32_t dom,
+ int vcpu, unsigned long long virt);
+
+
+/**
+ * DEPRECATED. Avoid using this, as it does not correctly account for PFNs
+ * without a backing MFN.
+ */
+int xc_get_pfn_list(xc_interface *xch, uint32_t domid, uint64_t *pfn_buf,
+ unsigned long max_pfns);
+
+int xc_copy_to_domain_page(xc_interface *xch, uint32_t domid,
+ unsigned long dst_pfn, const char *src_page);
+
+int xc_clear_domain_pages(xc_interface *xch, uint32_t domid,
+ unsigned long dst_pfn, int num);
+
+static inline int xc_clear_domain_page(xc_interface *xch, uint32_t domid,
+ unsigned long dst_pfn)
+{
+ return xc_clear_domain_pages(xch, domid, dst_pfn, 1);
+}
+
+int xc_mmuext_op(xc_interface *xch, struct mmuext_op *op, unsigned int nr_ops,
+ domid_t dom);
+
+/* System wide memory properties */
+long xc_maximum_ram_page(xc_interface *xch);
+
+/* Get current total pages allocated to a domain. */
+long xc_get_tot_pages(xc_interface *xch, uint32_t domid);
+
+/**
+ * This function retrieves the the number of bytes available
+ * in the heap in a specific range of address-widths and nodes.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain to query
+ * @parm min_width the smallest address width to query (0 if don't care)
+ * @parm max_width the largest address width to query (0 if don't care)
+ * @parm node the node to query (-1 for all)
+ * @parm *bytes caller variable to put total bytes counted
+ * @return 0 on success, <0 on failure.
+ */
+int xc_availheap(xc_interface *xch, int min_width, int max_width, int node,
+ uint64_t *bytes);
+
+/*
+ * Trace Buffer Operations
+ */
+
+/**
+ * xc_tbuf_enable - enable tracing buffers
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm cnt size of tracing buffers to create (in pages)
+ * @parm mfn location to store mfn of the trace buffers to
+ * @parm size location to store the size (in bytes) of a trace buffer to
+ *
+ * Gets the machine address of the trace pointer area and the size of the
+ * per CPU buffers.
+ */
+int xc_tbuf_enable(xc_interface *xch, unsigned long pages,
+ unsigned long *mfn, unsigned long *size);
+
+/*
+ * Disable tracing buffers.
+ */
+int xc_tbuf_disable(xc_interface *xch);
+
+/**
+ * This function sets the size of the trace buffers. Setting the size
+ * is currently a one-shot operation that may be performed either at boot
+ * time or via this interface, not both. The buffer size must be set before
+ * enabling tracing.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm size the size in pages per cpu for the trace buffers
+ * @return 0 on success, -1 on failure.
+ */
+int xc_tbuf_set_size(xc_interface *xch, unsigned long size);
+
+/**
+ * This function retrieves the current size of the trace buffers.
+ * Note that the size returned is in terms of bytes, not pages.
+
+ * @parm xch a handle to an open hypervisor interface
+ * @parm size will contain the size in bytes for the trace buffers
+ * @return 0 on success, -1 on failure.
+ */
+int xc_tbuf_get_size(xc_interface *xch, unsigned long *size);
+
+int xc_tbuf_set_cpu_mask(xc_interface *xch, uint32_t mask);
+
+int xc_tbuf_set_evt_mask(xc_interface *xch, uint32_t mask);
+
+int xc_domctl(xc_interface *xch, struct xen_domctl *domctl);
+int xc_sysctl(xc_interface *xch, struct xen_sysctl *sysctl);
+
+int xc_version(xc_interface *xch, int cmd, void *arg);
+
+int xc_flask_op(xc_interface *xch, xen_flask_op_t *op);
+
+/*
+ * Subscribe to domain suspend via evtchn.
+ * Returns -1 on failure, in which case errno will be set appropriately.
+ * Just calls XEN_DOMCTL_subscribe - see the caveats for that domctl
+ * (in its doc comment in domctl.h).
+ */
+int xc_domain_subscribe_for_suspend(
+ xc_interface *xch, domid_t domid, evtchn_port_t port);
+
+/**************************
+ * GRANT TABLE OPERATIONS *
+ **************************/
+
+/*
+ * These functions sometimes log messages as above, but not always.
+ */
+
+/*
+ * Note:
+ * After fork a child process must not use any opened xc gnttab
+ * handle inherited from their parent. They must open a new handle if
+ * they want to interact with xc.
+ *
+ * Return an fd onto the grant table driver. Logs errors.
+ */
+xc_gnttab *xc_gnttab_open(xentoollog_logger *logger,
+ unsigned open_flags);
+
+/*
+ * Close a handle previously allocated with xc_gnttab_open().
+ * Never logs errors.
+ */
+int xc_gnttab_close(xc_gnttab *xcg);
+
+/*
+ * Memory maps a grant reference from one domain to a local address range.
+ * Mappings should be unmapped with xc_gnttab_munmap. Logs errors.
+ *
+ * @parm xcg a handle on an open grant table interface
+ * @parm domid the domain to map memory from
+ * @parm ref the grant reference ID to map
+ * @parm prot same flag as in mmap()
+ */
+void *xc_gnttab_map_grant_ref(xc_gnttab *xcg,
+ uint32_t domid,
+ uint32_t ref,
+ int prot);
+
+/**
+ * Memory maps one or more grant references from one or more domains to a
+ * contiguous local address range. Mappings should be unmapped with
+ * xc_gnttab_munmap. Logs errors.
+ *
+ * @parm xcg a handle on an open grant table interface
+ * @parm count the number of grant references to be mapped
+ * @parm domids an array of @count domain IDs by which the corresponding @refs
+ * were granted
+ * @parm refs an array of @count grant references to be mapped
+ * @parm prot same flag as in mmap()
+ */
+void *xc_gnttab_map_grant_refs(xc_gnttab *xcg,
+ uint32_t count,
+ uint32_t *domids,
+ uint32_t *refs,
+ int prot);
+
+/**
+ * Memory maps one or more grant references from one domain to a
+ * contiguous local address range. Mappings should be unmapped with
+ * xc_gnttab_munmap. Logs errors.
+ *
+ * @parm xcg a handle on an open grant table interface
+ * @parm count the number of grant references to be mapped
+ * @parm domid the domain to map memory from
+ * @parm refs an array of @count grant references to be mapped
+ * @parm prot same flag as in mmap()
+ */
+void *xc_gnttab_map_domain_grant_refs(xc_gnttab *xcg,
+ uint32_t count,
+ uint32_t domid,
+ uint32_t *refs,
+ int prot);
+
+/**
+ * Memory maps a grant reference from one domain to a local address range.
+ * Mappings should be unmapped with xc_gnttab_munmap. If notify_offset or
+ * notify_port are not -1, this version will attempt to set up an unmap
+ * notification at the given offset and event channel. When the page is
+ * unmapped, the byte at the given offset will be zeroed and a wakeup will be
+ * sent to the given event channel. Logs errors.
+ *
+ * @parm xcg a handle on an open grant table interface
+ * @parm domid the domain to map memory from
+ * @parm ref the grant reference ID to map
+ * @parm prot same flag as in mmap()
+ * @parm notify_offset The byte offset in the page to use for unmap
+ * notification; -1 for none.
+ * @parm notify_port The event channel port to use for unmap notify, or -1
+ */
+void *xc_gnttab_map_grant_ref_notify(xc_gnttab *xcg,
+ uint32_t domid,
+ uint32_t ref,
+ int prot,
+ uint32_t notify_offset,
+ evtchn_port_t notify_port);
+
+/*
+ * Unmaps the @count pages starting at @start_address, which were mapped by a
+ * call to xc_gnttab_map_grant_ref or xc_gnttab_map_grant_refs. Never logs.
+ */
+int xc_gnttab_munmap(xc_gnttab *xcg,
+ void *start_address,
+ uint32_t count);
+
+/*
+ * Sets the maximum number of grants that may be mapped by the given instance
+ * to @count. Never logs.
+ *
+ * N.B. This function must be called after opening the handle, and before any
+ * other functions are invoked on it.
+ *
+ * N.B. When variable-length grants are mapped, fragmentation may be observed,
+ * and it may not be possible to satisfy requests up to the maximum number
+ * of grants.
+ */
+int xc_gnttab_set_max_grants(xc_gnttab *xcg,
+ uint32_t count);
+
+int xc_gnttab_op(xc_interface *xch, int cmd,
+ void * op, int op_size, int count);
+/* Logs iff hypercall bounce fails, otherwise doesn't. */
+
+int xc_gnttab_get_version(xc_interface *xch, int domid); /* Never logs */
+grant_entry_v1_t *xc_gnttab_map_table_v1(xc_interface *xch, int domid, int *gnt_num);
+grant_entry_v2_t *xc_gnttab_map_table_v2(xc_interface *xch, int domid, int *gnt_num);
+/* Sometimes these don't set errno [fixme], and sometimes they don't log. */
+
+/*
+ * Return an fd onto the grant sharing driver. Logs errors.
+ *
+ * Note:
+ * After fork a child process must not use any opened xc gntshr
+ * handle inherited from their parent. They must open a new handle if
+ * they want to interact with xc.
+ *
+ */
+xc_gntshr *xc_gntshr_open(xentoollog_logger *logger,
+ unsigned open_flags);
+
+/*
+ * Close a handle previously allocated with xc_gntshr_open().
+ * Never logs errors.
+ */
+int xc_gntshr_close(xc_gntshr *xcg);
+
+/*
+ * Creates and shares pages with another domain.
+ *
+ * @parm xcg a handle to an open grant sharing instance
+ * @parm domid the domain to share memory with
+ * @parm count the number of pages to share
+ * @parm refs the grant references of the pages (output)
+ * @parm writable true if the other domain can write to the pages
+ * @return local mapping of the pages
+ */
+void *xc_gntshr_share_pages(xc_gntshr *xcg, uint32_t domid,
+ int count, uint32_t *refs, int writable);
+
+/*
+ * Creates and shares a page with another domain, with unmap notification.
+ *
+ * @parm xcg a handle to an open grant sharing instance
+ * @parm domid the domain to share memory with
+ * @parm refs the grant reference of the pages (output)
+ * @parm writable true if the other domain can write to the page
+ * @parm notify_offset The byte offset in the page to use for unmap
+ * notification; -1 for none.
+ * @parm notify_port The event channel port to use for unmap notify, or -1
+ * @return local mapping of the page
+ */
+void *xc_gntshr_share_page_notify(xc_gntshr *xcg, uint32_t domid,
+ uint32_t *ref, int writable,
+ uint32_t notify_offset,
+ evtchn_port_t notify_port);
+/*
+ * Unmaps the @count pages starting at @start_address, which were mapped by a
+ * call to xc_gntshr_share_*. Never logs.
+ */
+int xc_gntshr_munmap(xc_gntshr *xcg, void *start_address, uint32_t count);
+
+int xc_physdev_map_pirq(xc_interface *xch,
+ int domid,
+ int index,
+ int *pirq);
+
+int xc_physdev_map_pirq_msi(xc_interface *xch,
+ int domid,
+ int index,
+ int *pirq,
+ int devfn,
+ int bus,
+ int entry_nr,
+ uint64_t table_base);
+
+int xc_physdev_unmap_pirq(xc_interface *xch,
+ int domid,
+ int pirq);
+
+int xc_hvm_set_pci_intx_level(
+ xc_interface *xch, domid_t dom,
+ uint8_t domain, uint8_t bus, uint8_t device, uint8_t intx,
+ unsigned int level);
+int xc_hvm_set_isa_irq_level(
+ xc_interface *xch, domid_t dom,
+ uint8_t isa_irq,
+ unsigned int level);
+
+int xc_hvm_set_pci_link_route(
+ xc_interface *xch, domid_t dom, uint8_t link, uint8_t isa_irq);
+
+int xc_hvm_inject_msi(
+ xc_interface *xch, domid_t dom, uint64_t addr, uint32_t data);
+
+/*
+ * Track dirty bit changes in the VRAM area
+ *
+ * All of this is done atomically:
+ * - get the dirty bitmap since the last call
+ * - set up dirty tracking area for period up to the next call
+ * - clear the dirty tracking area.
+ *
+ * Returns -ENODATA and does not fill bitmap if the area has changed since the
+ * last call.
+ */
+int xc_hvm_track_dirty_vram(
+ xc_interface *xch, domid_t dom,
+ uint64_t first_pfn, uint64_t nr,
+ unsigned long *bitmap);
+
+/*
+ * Notify that some pages got modified by the Device Model
+ */
+int xc_hvm_modified_memory(
+ xc_interface *xch, domid_t dom, uint64_t first_pfn, uint64_t nr);
+
+/*
+ * Set a range of memory to a specific type.
+ * Allowed types are HVMMEM_ram_rw, HVMMEM_ram_ro, HVMMEM_mmio_dm
+ */
+int xc_hvm_set_mem_type(
+ xc_interface *xch, domid_t dom, hvmmem_type_t memtype, uint64_t first_pfn, uint64_t nr);
+
+/*
+ * Injects a hardware/software CPU trap, to take effect the next time the HVM
+ * resumes.
+ */
+int xc_hvm_inject_trap(
+ xc_interface *xch, domid_t dom, int vcpu, uint32_t vector,
+ uint32_t type, uint32_t error_code, uint32_t insn_len,
+ uint64_t cr2);
+
+/*
+ * LOGGING AND ERROR REPORTING
+ */
+
+
+#define XC_MAX_ERROR_MSG_LEN 1024
+typedef struct xc_error {
+ enum xc_error_code code;
+ char message[XC_MAX_ERROR_MSG_LEN];
+} xc_error;
+
+
+/*
+ * Convert an error code or level into a text description. Return values
+ * are pointers to fixed strings and do not need to be freed.
+ * Do not fail, but return pointers to generic strings if fed bogus input.
+ */
+const char *xc_error_code_to_desc(int code);
+
+/*
+ * Convert an errno value to a text description.
+ */
+const char *xc_strerror(xc_interface *xch, int errcode);
+
+
+/*
+ * Return a pointer to the last error with level XC_REPORT_ERROR. This
+ * pointer and the data pointed to are only valid until the next call
+ * to libxc in the same thread.
+ */
+const xc_error *xc_get_last_error(xc_interface *handle);
+
+/*
+ * Clear the last error
+ */
+void xc_clear_last_error(xc_interface *xch);
+
+int xc_hvm_param_set(xc_interface *handle, domid_t dom, uint32_t param, uint64_t value);
+int xc_hvm_param_get(xc_interface *handle, domid_t dom, uint32_t param, uint64_t *value);
+
+/* Deprecated: use xc_hvm_param_set/get() instead. */
+int xc_set_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long value);
+int xc_get_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long *value);
+
+/*
+ * IOREQ Server API. (See section on IOREQ Servers in public/hvm_op.h).
+ */
+
+/**
+ * This function instantiates an IOREQ Server.
+ *
+ * @parm xch a handle to an open hypervisor interface.
+ * @parm domid the domain id to be serviced
+ * @parm handle_bufioreq should the IOREQ Server handle buffered requests?
+ * @parm id pointer to an ioservid_t to receive the IOREQ Server id.
+ * @return 0 on success, -1 on failure.
+ */
+int xc_hvm_create_ioreq_server(xc_interface *xch,
+ domid_t domid,
+ int handle_bufioreq,
+ ioservid_t *id);
+
+/**
+ * This function retrieves the necessary information to allow an
+ * emulator to use an IOREQ Server.
+ *
+ * @parm xch a handle to an open hypervisor interface.
+ * @parm domid the domain id to be serviced
+ * @parm id the IOREQ Server id.
+ * @parm ioreq_pfn pointer to a xen_pfn_t to receive the synchronous ioreq gmfn
+ * @parm bufioreq_pfn pointer to a xen_pfn_t to receive the buffered ioreq gmfn
+ * @parm bufioreq_port pointer to a evtchn_port_t to receive the buffered ioreq event channel
+ * @return 0 on success, -1 on failure.
+ */
+int xc_hvm_get_ioreq_server_info(xc_interface *xch,
+ domid_t domid,
+ ioservid_t id,
+ xen_pfn_t *ioreq_pfn,
+ xen_pfn_t *bufioreq_pfn,
+ evtchn_port_t *bufioreq_port);
+
+/**
+ * This function sets IOREQ Server state. An IOREQ Server
+ * will not be passed emulation requests until it is in
+ * the enabled state.
+ * Note that the contents of the ioreq_pfn and bufioreq_pfn are
+ * not meaningful until the IOREQ Server is in the enabled state.
+ *
+ * @parm xch a handle to an open hypervisor interface.
+ * @parm domid the domain id to be serviced
+ * @parm id the IOREQ Server id.
+ * @parm enabled the state.
+ * @return 0 on success, -1 on failure.
+ */
+int xc_hvm_set_ioreq_server_state(xc_interface *xch,
+ domid_t domid,
+ ioservid_t id,
+ int enabled);
+
+/**
+ * This function registers a range of memory or I/O ports for emulation.
+ *
+ * @parm xch a handle to an open hypervisor interface.
+ * @parm domid the domain id to be serviced
+ * @parm id the IOREQ Server id.
+ * @parm is_mmio is this a range of ports or memory
+ * @parm start start of range
+ * @parm end end of range (inclusive).
+ * @return 0 on success, -1 on failure.
+ */
+int xc_hvm_map_io_range_to_ioreq_server(xc_interface *xch,
+ domid_t domid,
+ ioservid_t id,
+ int is_mmio,
+ uint64_t start,
+ uint64_t end);
+
+/**
+ * This function deregisters a range of memory or I/O ports for emulation.
+ *
+ * @parm xch a handle to an open hypervisor interface.
+ * @parm domid the domain id to be serviced
+ * @parm id the IOREQ Server id.
+ * @parm is_mmio is this a range of ports or memory
+ * @parm start start of range
+ * @parm end end of range (inclusive).
+ * @return 0 on success, -1 on failure.
+ */
+int xc_hvm_unmap_io_range_from_ioreq_server(xc_interface *xch,
+ domid_t domid,
+ ioservid_t id,
+ int is_mmio,
+ uint64_t start,
+ uint64_t end);
+
+/**
+ * This function registers a PCI device for config space emulation.
+ *
+ * @parm xch a handle to an open hypervisor interface.
+ * @parm domid the domain id to be serviced
+ * @parm id the IOREQ Server id.
+ * @parm segment the PCI segment of the device
+ * @parm bus the PCI bus of the device
+ * @parm device the 'slot' number of the device
+ * @parm function the function number of the device
+ * @return 0 on success, -1 on failure.
+ */
+int xc_hvm_map_pcidev_to_ioreq_server(xc_interface *xch,
+ domid_t domid,
+ ioservid_t id,
+ uint16_t segment,
+ uint8_t bus,
+ uint8_t device,
+ uint8_t function);
+
+/**
+ * This function deregisters a PCI device for config space emulation.
+ *
+ * @parm xch a handle to an open hypervisor interface.
+ * @parm domid the domain id to be serviced
+ * @parm id the IOREQ Server id.
+ * @parm segment the PCI segment of the device
+ * @parm bus the PCI bus of the device
+ * @parm device the 'slot' number of the device
+ * @parm function the function number of the device
+ * @return 0 on success, -1 on failure.
+ */
+int xc_hvm_unmap_pcidev_from_ioreq_server(xc_interface *xch,
+ domid_t domid,
+ ioservid_t id,
+ uint16_t segment,
+ uint8_t bus,
+ uint8_t device,
+ uint8_t function);
+
+/**
+ * This function destroys an IOREQ Server.
+ *
+ * @parm xch a handle to an open hypervisor interface.
+ * @parm domid the domain id to be serviced
+ * @parm id the IOREQ Server id.
+ * @return 0 on success, -1 on failure.
+ */
+int xc_hvm_destroy_ioreq_server(xc_interface *xch,
+ domid_t domid,
+ ioservid_t id);
+
+/* HVM guest pass-through */
+int xc_assign_device(xc_interface *xch,
+ uint32_t domid,
+ uint32_t machine_bdf);
+
+int xc_get_device_group(xc_interface *xch,
+ uint32_t domid,
+ uint32_t machine_bdf,
+ uint32_t max_sdevs,
+ uint32_t *num_sdevs,
+ uint32_t *sdev_array);
+
+int xc_test_assign_device(xc_interface *xch,
+ uint32_t domid,
+ uint32_t machine_bdf);
+
+int xc_deassign_device(xc_interface *xch,
+ uint32_t domid,
+ uint32_t machine_bdf);
+
+int xc_domain_memory_mapping(xc_interface *xch,
+ uint32_t domid,
+ unsigned long first_gfn,
+ unsigned long first_mfn,
+ unsigned long nr_mfns,
+ uint32_t add_mapping);
+
+int xc_domain_ioport_mapping(xc_interface *xch,
+ uint32_t domid,
+ uint32_t first_gport,
+ uint32_t first_mport,
+ uint32_t nr_ports,
+ uint32_t add_mapping);
+
+int xc_domain_update_msi_irq(
+ xc_interface *xch,
+ uint32_t domid,
+ uint32_t gvec,
+ uint32_t pirq,
+ uint32_t gflags,
+ uint64_t gtable);
+
+int xc_domain_unbind_msi_irq(xc_interface *xch,
+ uint32_t domid,
+ uint32_t gvec,
+ uint32_t pirq,
+ uint32_t gflags);
+
+int xc_domain_bind_pt_irq(xc_interface *xch,
+ uint32_t domid,
+ uint8_t machine_irq,
+ uint8_t irq_type,
+ uint8_t bus,
+ uint8_t device,
+ uint8_t intx,
+ uint8_t isa_irq);
+
+int xc_domain_unbind_pt_irq(xc_interface *xch,
+ uint32_t domid,
+ uint8_t machine_irq,
+ uint8_t irq_type,
+ uint8_t bus,
+ uint8_t device,
+ uint8_t intx,
+ uint8_t isa_irq);
+
+int xc_domain_bind_pt_pci_irq(xc_interface *xch,
+ uint32_t domid,
+ uint8_t machine_irq,
+ uint8_t bus,
+ uint8_t device,
+ uint8_t intx);
+
+int xc_domain_bind_pt_isa_irq(xc_interface *xch,
+ uint32_t domid,
+ uint8_t machine_irq);
+
+int xc_domain_set_machine_address_size(xc_interface *xch,
+ uint32_t domid,
+ unsigned int width);
+int xc_domain_get_machine_address_size(xc_interface *xch,
+ uint32_t domid);
+
+int xc_domain_suppress_spurious_page_faults(xc_interface *xch,
+ uint32_t domid);
+
+/* Set the target domain */
+int xc_domain_set_target(xc_interface *xch,
+ uint32_t domid,
+ uint32_t target);
+
+/* Control the domain for debug */
+int xc_domain_debug_control(xc_interface *xch,
+ uint32_t domid,
+ uint32_t sop,
+ uint32_t vcpu);
+
+#if defined(__i386__) || defined(__x86_64__)
+int xc_cpuid_check(xc_interface *xch,
+ const unsigned int *input,
+ const char **config,
+ char **config_transformed);
+int xc_cpuid_set(xc_interface *xch,
+ domid_t domid,
+ const unsigned int *input,
+ const char **config,
+ char **config_transformed);
+int xc_cpuid_apply_policy(xc_interface *xch,
+ domid_t domid);
+void xc_cpuid_to_str(const unsigned int *regs,
+ char **strs); /* some strs[] may be NULL if ENOMEM */
+int xc_mca_op(xc_interface *xch, struct xen_mc *mc);
+#endif
+
+struct xc_px_val {
+ uint64_t freq; /* Px core frequency */
+ uint64_t residency; /* Px residency time */
+ uint64_t count; /* Px transition count */
+};
+
+struct xc_px_stat {
+ uint8_t total; /* total Px states */
+ uint8_t usable; /* usable Px states */
+ uint8_t last; /* last Px state */
+ uint8_t cur; /* current Px state */
+ uint64_t *trans_pt; /* Px transition table */
+ struct xc_px_val *pt;
+};
+
+int xc_pm_get_max_px(xc_interface *xch, int cpuid, int *max_px);
+int xc_pm_get_pxstat(xc_interface *xch, int cpuid, struct xc_px_stat *pxpt);
+int xc_pm_reset_pxstat(xc_interface *xch, int cpuid);
+
+struct xc_cx_stat {
+ uint32_t nr; /* entry nr in triggers[]/residencies[], incl C0 */
+ uint32_t last; /* last Cx state */
+ uint64_t idle_time; /* idle time from boot */
+ uint64_t *triggers; /* Cx trigger counts */
+ uint64_t *residencies; /* Cx residencies */
+ uint32_t nr_pc; /* entry nr in pc[] */
+ uint32_t nr_cc; /* entry nr in cc[] */
+ uint64_t *pc; /* 1-biased indexing (i.e. excl C0) */
+ uint64_t *cc; /* 1-biased indexing (i.e. excl C0) */
+};
+typedef struct xc_cx_stat xc_cx_stat_t;
+
+int xc_pm_get_max_cx(xc_interface *xch, int cpuid, int *max_cx);
+int xc_pm_get_cxstat(xc_interface *xch, int cpuid, struct xc_cx_stat *cxpt);
+int xc_pm_reset_cxstat(xc_interface *xch, int cpuid);
+
+int xc_cpu_online(xc_interface *xch, int cpu);
+int xc_cpu_offline(xc_interface *xch, int cpu);
+
+/*
+ * cpufreq para name of this structure named
+ * same as sysfs file name of native linux
+ */
+typedef xen_userspace_t xc_userspace_t;
+typedef xen_ondemand_t xc_ondemand_t;
+
+struct xc_get_cpufreq_para {
+ /* IN/OUT variable */
+ uint32_t cpu_num;
+ uint32_t freq_num;
+ uint32_t gov_num;
+
+ /* for all governors */
+ /* OUT variable */
+ uint32_t *affected_cpus;
+ uint32_t *scaling_available_frequencies;
+ char *scaling_available_governors;
+ char scaling_driver[CPUFREQ_NAME_LEN];
+
+ uint32_t cpuinfo_cur_freq;
+ uint32_t cpuinfo_max_freq;
+ uint32_t cpuinfo_min_freq;
+ uint32_t scaling_cur_freq;
+
+ char scaling_governor[CPUFREQ_NAME_LEN];
+ uint32_t scaling_max_freq;
+ uint32_t scaling_min_freq;
+
+ /* for specific governor */
+ union {
+ xc_userspace_t userspace;
+ xc_ondemand_t ondemand;
+ } u;
+
+ int32_t turbo_enabled;
+};
+
+int xc_get_cpufreq_para(xc_interface *xch, int cpuid,
+ struct xc_get_cpufreq_para *user_para);
+int xc_set_cpufreq_gov(xc_interface *xch, int cpuid, char *govname);
+int xc_set_cpufreq_para(xc_interface *xch, int cpuid,
+ int ctrl_type, int ctrl_value);
+int xc_get_cpufreq_avgfreq(xc_interface *xch, int cpuid, int *avg_freq);
+
+int xc_set_sched_opt_smt(xc_interface *xch, uint32_t value);
+int xc_set_vcpu_migration_delay(xc_interface *xch, uint32_t value);
+int xc_get_vcpu_migration_delay(xc_interface *xch, uint32_t *value);
+
+int xc_get_cpuidle_max_cstate(xc_interface *xch, uint32_t *value);
+int xc_set_cpuidle_max_cstate(xc_interface *xch, uint32_t value);
+
+int xc_enable_turbo(xc_interface *xch, int cpuid);
+int xc_disable_turbo(xc_interface *xch, int cpuid);
+/**
+ * tmem operations
+ */
+
+struct tmem_oid {
+ uint64_t oid[3];
+};
+
+int xc_tmem_control_oid(xc_interface *xch, int32_t pool_id, uint32_t subop,
+ uint32_t cli_id, uint32_t arg1, uint32_t arg2,
+ struct tmem_oid oid, void *buf);
+int xc_tmem_control(xc_interface *xch,
+ int32_t pool_id, uint32_t subop, uint32_t cli_id,
+ uint32_t arg1, uint32_t arg2, uint64_t arg3, void *buf);
+int xc_tmem_auth(xc_interface *xch, int cli_id, char *uuid_str, int arg1);
+int xc_tmem_save(xc_interface *xch, int dom, int live, int fd, int field_marker);
+int xc_tmem_save_extra(xc_interface *xch, int dom, int fd, int field_marker);
+void xc_tmem_save_done(xc_interface *xch, int dom);
+int xc_tmem_restore(xc_interface *xch, int dom, int fd);
+int xc_tmem_restore_extra(xc_interface *xch, int dom, int fd);
+
+/**
+ * Mem paging operations.
+ * Paging is supported only on the x86 architecture in 64 bit mode, with
+ * Hardware-Assisted Paging (i.e. Intel EPT, AMD NPT). Moreover, AMD NPT
+ * support is considered experimental.
+ */
+int xc_mem_paging_enable(xc_interface *xch, domid_t domain_id, uint32_t *port);
+int xc_mem_paging_disable(xc_interface *xch, domid_t domain_id);
+int xc_mem_paging_nominate(xc_interface *xch, domid_t domain_id,
+ unsigned long gfn);
+int xc_mem_paging_evict(xc_interface *xch, domid_t domain_id, unsigned long gfn);
+int xc_mem_paging_prep(xc_interface *xch, domid_t domain_id, unsigned long gfn);
+int xc_mem_paging_load(xc_interface *xch, domid_t domain_id,
+ unsigned long gfn, void *buffer);
+
+/**
+ * Access tracking operations.
+ * Supported only on Intel EPT 64 bit processors.
+ */
+
+/*
+ * Enables mem_access and returns the mapped ring page.
+ * Will return NULL on error.
+ * Caller has to unmap this page when done.
+ */
+void *xc_mem_access_enable(xc_interface *xch, domid_t domain_id, uint32_t *port);
+void *xc_mem_access_enable_introspection(xc_interface *xch, domid_t domain_id,
+ uint32_t *port);
+int xc_mem_access_disable(xc_interface *xch, domid_t domain_id);
+int xc_mem_access_resume(xc_interface *xch, domid_t domain_id);
+
+/*
+ * Set a range of memory to a specific access.
+ * Allowed types are XENMEM_access_default, XENMEM_access_n, any combination of
+ * XENMEM_access_ + (rwx), and XENMEM_access_rx2rw
+ */
+int xc_set_mem_access(xc_interface *xch, domid_t domain_id,
+ xenmem_access_t access, uint64_t first_pfn,
+ uint32_t nr);
+
+/*
+ * Gets the mem access for the given page (returned in access on success)
+ */
+int xc_get_mem_access(xc_interface *xch, domid_t domain_id,
+ uint64_t pfn, xenmem_access_t *access);
+
+/***
+ * Memory sharing operations.
+ *
+ * Unles otherwise noted, these calls return 0 on succes, -1 and errno on
+ * failure.
+ *
+ * Sharing is supported only on the x86 architecture in 64 bit mode, with
+ * Hardware-Assisted Paging (i.e. Intel EPT, AMD NPT). Moreover, AMD NPT
+ * support is considered experimental.
+
+ * Calls below return ENOSYS if not in the x86_64 architecture.
+ * Calls below return ENODEV if the domain does not support HAP.
+ * Calls below return ESRCH if the specified domain does not exist.
+ * Calls below return EPERM if the caller is unprivileged for this domain.
+ */
+
+/* Turn on/off sharing for the domid, depending on the enable flag.
+ *
+ * Returns EXDEV if trying to enable and the domain has had a PCI device
+ * assigned for passthrough (these two features are mutually exclusive).
+ *
+ * When sharing for a domain is turned off, the domain may still reference
+ * shared pages. Unsharing happens lazily. */
+int xc_memshr_control(xc_interface *xch,
+ domid_t domid,
+ int enable);
+
+/* Create a communication ring in which the hypervisor will place ENOMEM
+ * notifications.
+ *
+ * ENOMEM happens when unsharing pages: a Copy-on-Write duplicate needs to be
+ * allocated, and thus the out-of-memory error occurr.
+ *
+ * For complete examples on how to plumb a notification ring, look into
+ * xenpaging or xen-access.
+ *
+ * On receipt of a notification, the helper should ensure there is memory
+ * available to the domain before retrying.
+ *
+ * If a domain encounters an ENOMEM condition when sharing and this ring
+ * has not been set up, the hypervisor will crash the domain.
+ *
+ * Fails with:
+ * EINVAL if port is NULL
+ * EINVAL if the sharing ring has already been enabled
+ * ENOSYS if no guest gfn has been specified to host the ring via an hvm param
+ * EINVAL if the gfn for the ring has not been populated
+ * ENOENT if the gfn for the ring is paged out, or cannot be unshared
+ * EINVAL if the gfn for the ring cannot be written to
+ * EINVAL if the domain is dying
+ * ENOSPC if an event channel cannot be allocated for the ring
+ * ENOMEM if memory cannot be allocated for internal data structures
+ * EINVAL or EACCESS if the request is denied by the security policy
+ */
+
+int xc_memshr_ring_enable(xc_interface *xch,
+ domid_t domid,
+ uint32_t *port);
+/* Disable the ring for ENOMEM communication.
+ * May fail with EINVAL if the ring was not enabled in the first place.
+ */
+int xc_memshr_ring_disable(xc_interface *xch,
+ domid_t domid);
+
+/*
+ * Calls below return EINVAL if sharing has not been enabled for the domain
+ * Calls below return EINVAL if the domain is dying
+ */
+/* Once a reponse to an ENOMEM notification is prepared, the tool can
+ * notify the hypervisor to re-schedule the faulting vcpu of the domain with an
+ * event channel kick and/or this call. */
+int xc_memshr_domain_resume(xc_interface *xch,
+ domid_t domid);
+
+/* Select a page for sharing.
+ *
+ * A 64 bit opaque handle will be stored in handle. The hypervisor ensures
+ * that if the page is modified, the handle will be invalidated, and future
+ * users of it will fail. If the page has already been selected and is still
+ * associated to a valid handle, the existing handle will be returned.
+ *
+ * May fail with:
+ * EINVAL if the gfn is not populated or not sharable (mmio, etc)
+ * ENOMEM if internal data structures cannot be allocated
+ * E2BIG if the page is being referenced by other subsytems (e.g. qemu)
+ * ENOENT or EEXIST if there are internal hypervisor errors.
+ */
+int xc_memshr_nominate_gfn(xc_interface *xch,
+ domid_t domid,
+ unsigned long gfn,
+ uint64_t *handle);
+/* Same as above, but instead of a guest frame number, the input is a grant
+ * reference provided by the guest.
+ *
+ * May fail with EINVAL if the grant reference is invalid.
+ */
+int xc_memshr_nominate_gref(xc_interface *xch,
+ domid_t domid,
+ grant_ref_t gref,
+ uint64_t *handle);
+
+/* The three calls below may fail with
+ * 10 (or -XENMEM_SHARING_OP_S_HANDLE_INVALID) if the handle passed as source
+ * is invalid.
+ * 9 (or -XENMEM_SHARING_OP_C_HANDLE_INVALID) if the handle passed as client is
+ * invalid.
+ */
+/* Share two nominated guest pages.
+ *
+ * If the call succeeds, both pages will point to the same backing frame (or
+ * mfn). The hypervisor will verify the handles are still valid, but it will
+ * not perform any sanity checking on the contens of the pages (the selection
+ * mechanism for sharing candidates is entirely up to the user-space tool).
+ *
+ * After successful sharing, the client handle becomes invalid. Both <domain,
+ * gfn> tuples point to the same mfn with the same handle, the one specified as
+ * source. Either 3-tuple can be specified later for further re-sharing.
+ */
+int xc_memshr_share_gfns(xc_interface *xch,
+ domid_t source_domain,
+ unsigned long source_gfn,
+ uint64_t source_handle,
+ domid_t client_domain,
+ unsigned long client_gfn,
+ uint64_t client_handle);
+
+/* Same as above, but share two grant references instead.
+ *
+ * May fail with EINVAL if either grant reference is invalid.
+ */
+int xc_memshr_share_grefs(xc_interface *xch,
+ domid_t source_domain,
+ grant_ref_t source_gref,
+ uint64_t source_handle,
+ domid_t client_domain,
+ grant_ref_t client_gref,
+ uint64_t client_handle);
+
+/* Allows to add to the guest physmap of the client domain a shared frame
+ * directly.
+ *
+ * May additionally fail with
+ * 9 (-XENMEM_SHARING_OP_C_HANDLE_INVALID) if the physmap entry for the gfn is
+ * not suitable.
+ * ENOMEM if internal data structures cannot be allocated.
+ * ENOENT if there is an internal hypervisor error.
+ */
+int xc_memshr_add_to_physmap(xc_interface *xch,
+ domid_t source_domain,
+ unsigned long source_gfn,
+ uint64_t source_handle,
+ domid_t client_domain,
+ unsigned long client_gfn);
+
+/* Debug calls: return the number of pages referencing the shared frame backing
+ * the input argument. Should be one or greater.
+ *
+ * May fail with EINVAL if there is no backing shared frame for the input
+ * argument.
+ */
+int xc_memshr_debug_gfn(xc_interface *xch,
+ domid_t domid,
+ unsigned long gfn);
+/* May additionally fail with EINVAL if the grant reference is invalid. */
+int xc_memshr_debug_gref(xc_interface *xch,
+ domid_t domid,
+ grant_ref_t gref);
+
+/* Audits the share subsystem.
+ *
+ * Returns ENOSYS if not supported (may not be compiled into the hypervisor).
+ *
+ * Returns the number of errors found during auditing otherwise. May be (should
+ * be!) zero.
+ *
+ * If debugtrace support has been compiled into the hypervisor and is enabled,
+ * verbose descriptions for the errors are available in the hypervisor console.
+ */
+int xc_memshr_audit(xc_interface *xch);
+
+/* Stats reporting.
+ *
+ * At any point in time, the following equality should hold for a host:
+ *
+ * Let dominfo(d) be the xc_dominfo_t struct filled by a call to
+ * xc_domain_getinfo(d)
+ *
+ * The summation of dominfo(d)->shr_pages for all domains in the system
+ * should be equal to
+ * xc_sharing_freed_pages + xc_sharing_used_frames
+ */
+/*
+ * This function returns the total number of pages freed by using sharing
+ * on the system. For example, if two domains contain a single entry in
+ * their p2m table that points to the same shared page (and no other pages
+ * in the system are shared), then this function should return 1.
+ */
+long xc_sharing_freed_pages(xc_interface *xch);
+
+/*
+ * This function returns the total number of frames occupied by shared
+ * pages on the system. This is independent of the number of domains
+ * pointing at these frames. For example, in the above scenario this
+ * should return 1. (And dominfo(d) for each of the two domains should return 1
+ * as well).
+ *
+ * Note that some of these sharing_used_frames may be referenced by
+ * a single domain page, and thus not realize any savings. The same
+ * applies to some of the pages counted in dominfo(d)->shr_pages.
+ */
+long xc_sharing_used_frames(xc_interface *xch);
+/*** End sharing interface ***/
+
+int xc_flask_load(xc_interface *xc_handle, char *buf, uint32_t size);
+int xc_flask_context_to_sid(xc_interface *xc_handle, char *buf, uint32_t size, uint32_t *sid);
+int xc_flask_sid_to_context(xc_interface *xc_handle, int sid, char *buf, uint32_t size);
+int xc_flask_getenforce(xc_interface *xc_handle);
+int xc_flask_setenforce(xc_interface *xc_handle, int mode);
+int xc_flask_getbool_byid(xc_interface *xc_handle, int id, char *name, uint32_t size, int *curr, int *pend);
+int xc_flask_getbool_byname(xc_interface *xc_handle, char *name, int *curr, int *pend);
+int xc_flask_setbool(xc_interface *xc_handle, char *name, int value, int commit);
+int xc_flask_add_pirq(xc_interface *xc_handle, unsigned int pirq, char *scontext);
+int xc_flask_add_ioport(xc_interface *xc_handle, unsigned long low, unsigned long high,
+ char *scontext);
+int xc_flask_add_iomem(xc_interface *xc_handle, unsigned long low, unsigned long high,
+ char *scontext);
+int xc_flask_add_device(xc_interface *xc_handle, unsigned long device, char *scontext);
+int xc_flask_del_pirq(xc_interface *xc_handle, unsigned int pirq);
+int xc_flask_del_ioport(xc_interface *xc_handle, unsigned long low, unsigned long high);
+int xc_flask_del_iomem(xc_interface *xc_handle, unsigned long low, unsigned long high);
+int xc_flask_del_device(xc_interface *xc_handle, unsigned long device);
+int xc_flask_access(xc_interface *xc_handle, const char *scon, const char *tcon,
+ uint16_t tclass, uint32_t req,
+ uint32_t *allowed, uint32_t *decided,
+ uint32_t *auditallow, uint32_t *auditdeny,
+ uint32_t *seqno);
+int xc_flask_avc_cachestats(xc_interface *xc_handle, char *buf, int size);
+int xc_flask_policyvers(xc_interface *xc_handle);
+int xc_flask_avc_hashstats(xc_interface *xc_handle, char *buf, int size);
+int xc_flask_getavc_threshold(xc_interface *xc_handle);
+int xc_flask_setavc_threshold(xc_interface *xc_handle, int threshold);
+int xc_flask_relabel_domain(xc_interface *xch, int domid, uint32_t sid);
+
+struct elf_binary;
+void xc_elf_set_logfile(xc_interface *xch, struct elf_binary *elf,
+ int verbose);
+/* Useful for callers who also use libelf. */
+
+/**
+ * Checkpoint Compression
+ */
+typedef struct compression_ctx comp_ctx;
+comp_ctx *xc_compression_create_context(xc_interface *xch,
+ unsigned long p2m_size);
+void xc_compression_free_context(xc_interface *xch, comp_ctx *ctx);
+
+/**
+ * Add a page to compression page buffer, to be compressed later.
+ *
+ * returns 0 if the page was successfully added to the page buffer
+ *
+ * returns -1 if there is no space in buffer. In this case, the
+ * application should call xc_compression_compress_pages to compress
+ * the buffer (or atleast part of it), thereby freeing some space in
+ * the page buffer.
+ *
+ * returns -2 if the pfn is out of bounds, where the bound is p2m_size
+ * parameter passed during xc_compression_create_context.
+ */
+int xc_compression_add_page(xc_interface *xch, comp_ctx *ctx, char *page,
+ unsigned long pfn, int israw);
+
+/**
+ * Delta compress pages in the compression buffer and inserts the
+ * compressed data into the supplied compression buffer compbuf, whose
+ * size is compbuf_size.
+ * After compression, the pages are copied to the internal LRU cache.
+ *
+ * This function compresses as many pages as possible into the
+ * supplied compression buffer. It maintains an internal iterator to
+ * keep track of pages in the input buffer that are yet to be compressed.
+ *
+ * returns -1 if the compression buffer has run out of space.
+ * returns 1 on success.
+ * returns 0 if no more pages are left to be compressed.
+ * When the return value is non-zero, compbuf_len indicates the actual
+ * amount of data present in compbuf (<=compbuf_size).
+ */
+int xc_compression_compress_pages(xc_interface *xch, comp_ctx *ctx,
+ char *compbuf, unsigned long compbuf_size,
+ unsigned long *compbuf_len);
+
+/**
+ * Resets the internal page buffer that holds dirty pages before compression.
+ * Also resets the iterators.
+ */
+void xc_compression_reset_pagebuf(xc_interface *xch, comp_ctx *ctx);
+
+/**
+ * Caller must supply the compression buffer (compbuf),
+ * its size (compbuf_size) and a reference to index variable (compbuf_pos)
+ * that is used internally. Each call pulls out one page from the compressed
+ * chunk and copies it to dest.
+ */
+int xc_compression_uncompress_page(xc_interface *xch, char *compbuf,
+ unsigned long compbuf_size,
+ unsigned long *compbuf_pos, char *dest);
+
+/*
+ * Execute an image previously loaded with xc_kexec_load().
+ *
+ * Does not return on success.
+ *
+ * Fails with:
+ * ENOENT if the specified image has not been loaded.
+ */
+int xc_kexec_exec(xc_interface *xch, int type);
+
+/*
+ * Find the machine address and size of certain memory areas.
+ *
+ * KEXEC_RANGE_MA_CRASH crash area
+ * KEXEC_RANGE_MA_XEN Xen itself
+ * KEXEC_RANGE_MA_CPU CPU note for CPU number 'nr'
+ * KEXEC_RANGE_MA_XENHEAP xenheap
+ * KEXEC_RANGE_MA_EFI_MEMMAP EFI Memory Map
+ * KEXEC_RANGE_MA_VMCOREINFO vmcoreinfo
+ *
+ * Fails with:
+ * EINVAL if the range or CPU number isn't valid.
+ */
+int xc_kexec_get_range(xc_interface *xch, int range, int nr,
+ uint64_t *size, uint64_t *start);
+
+/*
+ * Load a kexec image into memory.
+ *
+ * The image may be of type KEXEC_TYPE_DEFAULT (executed on request)
+ * or KEXEC_TYPE_CRASH (executed on a crash).
+ *
+ * The image architecture may be a 32-bit variant of the hypervisor
+ * architecture (e.g, EM_386 on a x86-64 hypervisor).
+ *
+ * Fails with:
+ * ENOMEM if there is insufficient memory for the new image.
+ * EINVAL if the image does not fit into the crash area or the entry
+ * point isn't within one of segments.
+ * EBUSY if another image is being executed.
+ */
+int xc_kexec_load(xc_interface *xch, uint8_t type, uint16_t arch,
+ uint64_t entry_maddr,
+ uint32_t nr_segments, xen_kexec_segment_t *segments);
+
+/*
+ * Unload a kexec image.
+ *
+ * This prevents a KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH image from
+ * being executed. The crash images are not cleared from the crash
+ * region.
+ */
+int xc_kexec_unload(xc_interface *xch, int type);
+
+typedef xenpf_resource_entry_t xc_resource_entry_t;
+
+/*
+ * Generic resource operation which contains multiple non-preemptible
+ * resource access entries that passed to xc_resource_op().
+ */
+struct xc_resource_op {
+ uint64_t result; /* on return, check this field first */
+ uint32_t cpu; /* which cpu to run */
+ uint32_t nr_entries; /* number of resource entries */
+ xc_resource_entry_t *entries;
+};
+
+typedef struct xc_resource_op xc_resource_op_t;
+int xc_resource_op(xc_interface *xch, uint32_t nr_ops, xc_resource_op_t *ops);
+
+#if defined(__i386__) || defined(__x86_64__)
+enum xc_psr_cmt_type {
+ XC_PSR_CMT_L3_OCCUPANCY,
+};
+typedef enum xc_psr_cmt_type xc_psr_cmt_type;
+int xc_psr_cmt_attach(xc_interface *xch, uint32_t domid);
+int xc_psr_cmt_detach(xc_interface *xch, uint32_t domid);
+int xc_psr_cmt_get_domain_rmid(xc_interface *xch, uint32_t domid,
+ uint32_t *rmid);
+int xc_psr_cmt_get_total_rmid(xc_interface *xch, uint32_t *total_rmid);
+int xc_psr_cmt_get_l3_upscaling_factor(xc_interface *xch,
+ uint32_t *upscaling_factor);
+int xc_psr_cmt_get_l3_cache_size(xc_interface *xch, uint32_t cpu,
+ uint32_t *l3_cache_size);
+int xc_psr_cmt_get_data(xc_interface *xch, uint32_t rmid,
+ uint32_t cpu, uint32_t psr_cmt_type, uint64_t *monitor_data);
+int xc_psr_cmt_enabled(xc_interface *xch);
+#endif
+
+#endif /* XENCTRL_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/include/xenctrlosdep.h b/tools/libxc/include/xenctrlosdep.h
new file mode 100644
index 0000000..e97944b
--- /dev/null
+++ b/tools/libxc/include/xenctrlosdep.h
@@ -0,0 +1,173 @@
+/******************************************************************************
+ *
+ * Interface to OS specific low-level operations
+ *
+ * Copyright (c) 2010, Citrix Systems Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * This interface defines the interactions between the Xen control
+ * libraries and the OS facilities used to communicate with the
+ * hypervisor.
+ *
+ * It is possible to override the default (native) implementation by
+ * setting the XENCTRL_OSDEP environment variable to point to a
+ * plugin library. Userspace can use this facility to intercept
+ * hypervisor operations. This can be used e.g. to implement a
+ * userspace simulator for Xen hypercalls.
+ *
+ * The plugin must contain a data structure:
+ * xc_osdep_info_t xc_osdep_info;
+ *
+ * xc_osdep_init:
+ * Must return a suitable struct xc_osdep_ops pointer or NULL on failure.
+ */
+
+#ifndef XC_OSDEP_H
+#define XC_OSDEP_H
+
+/* Tell the Xen public headers we are a user-space tools build. */
+#ifndef __XEN_TOOLS__
+#define __XEN_TOOLS__ 1
+#endif
+
+#include <sys/mman.h>
+#include <sys/types.h>
+
+#include <xen/sys/privcmd.h>
+
+enum xc_osdep_type {
+ XC_OSDEP_PRIVCMD,
+ XC_OSDEP_EVTCHN,
+ XC_OSDEP_GNTTAB,
+ XC_OSDEP_GNTSHR,
+};
+
+/* Opaque handle internal to the backend */
+typedef unsigned long xc_osdep_handle;
+
+#define XC_OSDEP_OPEN_ERROR ((xc_osdep_handle)-1)
+
+struct xc_osdep_ops
+{
+ /* Opens an interface.
+ *
+ * Must return an opaque handle on success or
+ * XC_OSDEP_OPEN_ERROR on failure
+ */
+ xc_osdep_handle (*open)(xc_interface *xch);
+
+ int (*close)(xc_interface *xch, xc_osdep_handle h);
+
+ union {
+ struct {
+ void *(*alloc_hypercall_buffer)(xc_interface *xch, xc_osdep_handle h, int npages);
+ void (*free_hypercall_buffer)(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages);
+
+ int (*hypercall)(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall);
+
+ void *(*map_foreign_batch)(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int prot,
+ xen_pfn_t *arr, int num);
+ void *(*map_foreign_bulk)(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int prot,
+ const xen_pfn_t *arr, int *err, unsigned int num);
+ void *(*map_foreign_range)(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int size, int prot,
+ unsigned long mfn);
+ void *(*map_foreign_ranges)(xc_interface *xch, xc_osdep_handle h, uint32_t dom, size_t size, int prot,
+ size_t chunksize, privcmd_mmap_entry_t entries[],
+ int nentries);
+ } privcmd;
+ struct {
+ int (*fd)(xc_evtchn *xce, xc_osdep_handle h);
+
+ int (*notify)(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port);
+
+ evtchn_port_or_error_t (*bind_unbound_port)(xc_evtchn *xce, xc_osdep_handle h, int domid);
+ evtchn_port_or_error_t (*bind_interdomain)(xc_evtchn *xce, xc_osdep_handle h, int domid,
+ evtchn_port_t remote_port);
+ evtchn_port_or_error_t (*bind_virq)(xc_evtchn *xce, xc_osdep_handle h, unsigned int virq);
+
+ int (*unbind)(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port);
+
+ evtchn_port_or_error_t (*pending)(xc_evtchn *xce, xc_osdep_handle h);
+ int (*unmask)(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port);
+ } evtchn;
+ struct {
+#define XC_GRANT_MAP_SINGLE_DOMAIN 0x1
+ void *(*grant_map)(xc_gnttab *xcg, xc_osdep_handle h,
+ uint32_t count, int flags, int prot,
+ uint32_t *domids, uint32_t *refs,
+ uint32_t notify_offset,
+ evtchn_port_t notify_port);
+ int (*munmap)(xc_gnttab *xcg, xc_osdep_handle h,
+ void *start_address,
+ uint32_t count);
+ int (*set_max_grants)(xc_gnttab *xcg, xc_osdep_handle h, uint32_t count);
+ } gnttab;
+ struct {
+ void *(*share_pages)(xc_gntshr *xcg, xc_osdep_handle h,
+ uint32_t domid, int count,
+ uint32_t *refs, int writable,
+ uint32_t notify_offset,
+ evtchn_port_t notify_port);
+ int (*munmap)(xc_gntshr *xcg, xc_osdep_handle h,
+ void *start_address, uint32_t count);
+ } gntshr;
+ } u;
+};
+typedef struct xc_osdep_ops xc_osdep_ops;
+
+typedef xc_osdep_ops *(*xc_osdep_init_fn)(xc_interface *xch, enum xc_osdep_type);
+
+struct xc_osdep_info
+{
+ /* Describes this backend. */
+ const char *name;
+
+ /* Returns ops function. */
+ xc_osdep_init_fn init;
+
+ /* True if this interface backs onto a fake Xen. */
+ int fake;
+
+ /* For internal use by loader. */
+ void *dl_handle;
+};
+typedef struct xc_osdep_info xc_osdep_info_t;
+
+/* All backends, including the builtin backend, must supply this structure. */
+extern xc_osdep_info_t xc_osdep_info;
+
+/* Stub for not yet converted OSes */
+void *xc_map_foreign_bulk_compat(xc_interface *xch, xc_osdep_handle h,
+ uint32_t dom, int prot,
+ const xen_pfn_t *arr, int *err, unsigned int num);
+
+/* Report errors through xc_interface */
+void xc_osdep_log(xc_interface *xch, xentoollog_level level, int code,
+ const char *fmt, ...) __attribute__((format(printf, 4, 5)));
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/include/xenguest.h b/tools/libxc/include/xenguest.h
new file mode 100644
index 0000000..40bbac8
--- /dev/null
+++ b/tools/libxc/include/xenguest.h
@@ -0,0 +1,325 @@
+/******************************************************************************
+ * xenguest.h
+ *
+ * A library for guest domain management in Xen.
+ *
+ * Copyright (c) 2003-2004, K A Fraser.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef XENGUEST_H
+#define XENGUEST_H
+
+#define XCFLAGS_LIVE (1 << 0)
+#define XCFLAGS_DEBUG (1 << 1)
+#define XCFLAGS_HVM (1 << 2)
+#define XCFLAGS_STDVGA (1 << 3)
+#define XCFLAGS_CHECKPOINT_COMPRESS (1 << 4)
+
+#define X86_64_B_SIZE 64
+#define X86_32_B_SIZE 32
+
+/* callbacks provided by xc_domain_save */
+struct save_callbacks {
+ /* Called after expiration of checkpoint interval,
+ * to suspend the guest.
+ */
+ int (*suspend)(void* data);
+
+ /* Called after the guest's dirty pages have been
+ * copied into an output buffer.
+ * Callback function resumes the guest & the device model,
+ * returns to xc_domain_save.
+ * xc_domain_save then flushes the output buffer, while the
+ * guest continues to run.
+ */
+ int (*postcopy)(void* data);
+
+ /* Called after the memory checkpoint has been flushed
+ * out into the network. Typical actions performed in this
+ * callback include:
+ * (a) send the saved device model state (for HVM guests),
+ * (b) wait for checkpoint ack
+ * (c) release the network output buffer pertaining to the acked checkpoint.
+ * (c) sleep for the checkpoint interval.
+ *
+ * returns:
+ * 0: terminate checkpointing gracefully
+ * 1: take another checkpoint */
+ int (*checkpoint)(void* data);
+
+ /* Enable qemu-dm logging dirty pages to xen */
+ int (*switch_qemu_logdirty)(int domid, unsigned enable, void *data); /* HVM only */
+
+ /* Save toolstack specific data
+ * @param buf the buffer with the data to be saved
+ * @param len the length of the buffer
+ * The callee allocates the buffer, the caller frees it (buffer must
+ * be free'able).
+ */
+ int (*toolstack_save)(uint32_t domid, uint8_t **buf, uint32_t *len, void *data);
+
+ /* to be provided as the last argument to each callback function */
+ void* data;
+};
+
+/**
+ * This function will save a running domain.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm fd the file descriptor to save a domain to
+ * @parm dom the id of the domain
+ * @return 0 on success, -1 on failure
+ */
+int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
+ uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
+ struct save_callbacks* callbacks, int hvm);
+
+
+/* callbacks provided by xc_domain_restore */
+struct restore_callbacks {
+ /* callback to restore toolstack specific data */
+ int (*toolstack_restore)(uint32_t domid, const uint8_t *buf,
+ uint32_t size, void* data);
+
+ /* to be provided as the last argument to each callback function */
+ void* data;
+};
+
+/**
+ * This function will restore a saved domain.
+ *
+ * Domain is restored in a suspended state ready to be unpaused.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm fd the file descriptor to restore a domain from
+ * @parm dom the id of the domain
+ * @parm store_evtchn the store event channel for this domain to use
+ * @parm store_mfn returned with the mfn of the store page
+ * @parm hvm non-zero if this is a HVM restore
+ * @parm pae non-zero if this HVM domain has PAE support enabled
+ * @parm superpages non-zero to allocate guest memory with superpages
+ * @parm checkpointed_stream non-zero if the far end of the stream is using checkpointing
+ * @parm callbacks non-NULL to receive a callback to restore toolstack
+ * specific data
+ * @return 0 on success, -1 on failure
+ */
+int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
+ unsigned int store_evtchn, unsigned long *store_mfn,
+ domid_t store_domid, unsigned int console_evtchn,
+ unsigned long *console_mfn, domid_t console_domid,
+ unsigned int hvm, unsigned int pae, int superpages,
+ int checkpointed_stream,
+ struct restore_callbacks *callbacks);
+/**
+ * xc_domain_restore writes a file to disk that contains the device
+ * model saved state.
+ * The pathname of this file is XC_DEVICE_MODEL_RESTORE_FILE; The domid
+ * of the new domain is automatically appended to the filename,
+ * separated by a ".".
+ */
+#define XC_DEVICE_MODEL_RESTORE_FILE "/var/lib/xen/qemu-resume"
+
+/**
+ * This function will create a domain for a paravirtualized Linux
+ * using file names pointing to kernel and ramdisk
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the id of the domain
+ * @parm mem_mb memory size in megabytes
+ * @parm image_name name of the kernel image file
+ * @parm ramdisk_name name of the ramdisk image file
+ * @parm cmdline command line string
+ * @parm flags domain creation flags
+ * @parm store_evtchn the store event channel for this domain to use
+ * @parm store_mfn returned with the mfn of the store page
+ * @parm console_evtchn the console event channel for this domain to use
+ * @parm conole_mfn returned with the mfn of the console page
+ * @return 0 on success, -1 on failure
+ */
+int xc_linux_build(xc_interface *xch,
+ uint32_t domid,
+ unsigned int mem_mb,
+ const char *image_name,
+ const char *ramdisk_name,
+ const char *cmdline,
+ const char *features,
+ unsigned long flags,
+ unsigned int store_evtchn,
+ unsigned long *store_mfn,
+ unsigned int console_evtchn,
+ unsigned long *console_mfn);
+
+/** The same interface, but the dom structure is managed by the caller */
+struct xc_dom_image;
+int xc_dom_linux_build(xc_interface *xch,
+ struct xc_dom_image *dom,
+ uint32_t domid,
+ unsigned int mem_mb,
+ const char *image_name,
+ const char *ramdisk_name,
+ unsigned long flags,
+ unsigned int store_evtchn,
+ unsigned long *store_mfn,
+ unsigned int console_evtchn,
+ unsigned long *console_mfn);
+
+/**
+ * This function will create a domain for a paravirtualized Linux
+ * using buffers for kernel and initrd
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the id of the domain
+ * @parm mem_mb memory size in megabytes
+ * @parm image_buffer buffer containing kernel image
+ * @parm image_size size of the kernel image buffer
+ * @parm initrd_buffer name of the ramdisk image file
+ * @parm initrd_size size of the ramdisk buffer
+ * @parm cmdline command line string
+ * @parm flags domain creation flags
+ * @parm store_evtchn the store event channel for this domain to use
+ * @parm store_mfn returned with the mfn of the store page
+ * @parm console_evtchn the console event channel for this domain to use
+ * @parm conole_mfn returned with the mfn of the console page
+ * @return 0 on success, -1 on failure
+ */
+int xc_linux_build_mem(xc_interface *xch,
+ uint32_t domid,
+ unsigned int mem_mb,
+ const char *image_buffer,
+ unsigned long image_size,
+ const char *initrd_buffer,
+ unsigned long initrd_size,
+ const char *cmdline,
+ const char *features,
+ unsigned long flags,
+ unsigned int store_evtchn,
+ unsigned long *store_mfn,
+ unsigned int console_evtchn,
+ unsigned long *console_mfn);
+
+struct xc_hvm_firmware_module {
+ uint8_t *data;
+ uint32_t length;
+ uint64_t guest_addr_out;
+};
+
+struct xc_hvm_build_args {
+ uint64_t mem_size; /* Memory size in bytes. */
+ uint64_t mem_target; /* Memory target in bytes. */
+ uint64_t mmio_size; /* Size of the MMIO hole in bytes. */
+ const char *image_file_name; /* File name of the image to load. */
+
+ /* Extra ACPI tables passed to HVMLOADER */
+ struct xc_hvm_firmware_module acpi_module;
+
+ /* Extra SMBIOS structures passed to HVMLOADER */
+ struct xc_hvm_firmware_module smbios_module;
+ /* Whether to use claim hypercall (1 - enable, 0 - disable). */
+ int claim_enabled;
+};
+
+/**
+ * Build a HVM domain.
+ * @parm xch libxc context handle.
+ * @parm domid domain ID for the new domain.
+ * @parm hvm_args parameters for the new domain.
+ *
+ * The memory size and image file parameters are required, the rest
+ * are optional.
+ */
+int xc_hvm_build(xc_interface *xch, uint32_t domid,
+ struct xc_hvm_build_args *hvm_args);
+
+int xc_hvm_build_target_mem(xc_interface *xch,
+ uint32_t domid,
+ int memsize,
+ int target,
+ const char *image_name);
+
+/*
+ * Sets *lockfd to -1.
+ * Has deallocated everything even on error.
+ */
+int xc_suspend_evtchn_release(xc_interface *xch, xc_evtchn *xce, int domid, int suspend_evtchn, int *lockfd);
+
+/**
+ * This function eats the initial notification.
+ * xce must not be used for anything else
+ * See xc_suspend_evtchn_init_sane re lockfd.
+ */
+int xc_suspend_evtchn_init_exclusive(xc_interface *xch, xc_evtchn *xce,
+ int domid, int port, int *lockfd);
+
+/* xce must not be used for anything else */
+int xc_await_suspend(xc_interface *xch, xc_evtchn *xce, int suspend_evtchn);
+
+/**
+ * The port will be signaled immediately after this call
+ * The caller should check the domain status and look for the next event
+ * On success, *lockfd will be set to >=0 and *lockfd must be preserved
+ * and fed to xc_suspend_evtchn_release. (On error *lockfd is
+ * undefined and xc_suspend_evtchn_release is not allowed.)
+ */
+int xc_suspend_evtchn_init_sane(xc_interface *xch, xc_evtchn *xce,
+ int domid, int port, int *lockfd);
+
+int xc_get_bit_size(xc_interface *xch,
+ const char *image_name, const char *cmdline,
+ const char *features, int *type);
+
+int xc_mark_page_online(xc_interface *xch, unsigned long start,
+ unsigned long end, uint32_t *status);
+
+int xc_mark_page_offline(xc_interface *xch, unsigned long start,
+ unsigned long end, uint32_t *status);
+
+int xc_query_page_offline_status(xc_interface *xch, unsigned long start,
+ unsigned long end, uint32_t *status);
+
+int xc_exchange_page(xc_interface *xch, int domid, xen_pfn_t mfn);
+
+
+/**
+ * Memory related information, such as PFN types, the P2M table,
+ * the guest word width and the guest page table levels.
+ */
+struct xc_domain_meminfo {
+ unsigned int pt_levels;
+ unsigned int guest_width;
+ xen_pfn_t *pfn_type;
+ xen_pfn_t *p2m_table;
+ unsigned long p2m_size;
+};
+
+int xc_map_domain_meminfo(xc_interface *xch, int domid,
+ struct xc_domain_meminfo *minfo);
+
+int xc_unmap_domain_meminfo(xc_interface *xch, struct xc_domain_meminfo *mem);
+
+/**
+ * This function map m2p table
+ * @parm xch a handle to an open hypervisor interface
+ * @parm max_mfn the max pfn
+ * @parm prot the flags to map, such as read/write etc
+ * @parm mfn0 return the first mfn, can be NULL
+ * @return mapped m2p table on success, NULL on failure
+ */
+xen_pfn_t *xc_map_m2p(xc_interface *xch,
+ unsigned long max_mfn,
+ int prot,
+ unsigned long *mfn0);
+#endif /* XENGUEST_H */
diff --git a/tools/libxc/include/xentoollog.h b/tools/libxc/include/xentoollog.h
new file mode 100644
index 0000000..85d3da9
--- /dev/null
+++ b/tools/libxc/include/xentoollog.h
@@ -0,0 +1,137 @@
+/*
+ * xentoollog.h
+ *
+ * Copyright (c) 2010 Citrix
+ * Part of a generic logging interface used by various dom0 userland libraries.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef XENTOOLLOG_H
+#define XENTOOLLOG_H
+
+#include <stdio.h>
+#include <stdarg.h>
+
+
+/*---------- common declarations and types ----------*/
+
+typedef enum xentoollog_level {
+ XTL_NONE, /* sentinel etc, never used for logging */
+ XTL_DEBUG,
+ XTL_VERBOSE,
+ XTL_DETAIL,
+ XTL_PROGRESS, /* also used for "progress" messages */
+ XTL_INFO,
+ XTL_NOTICE,
+ XTL_WARN,
+ XTL_ERROR,
+ XTL_CRITICAL,
+ XTL_NUM_LEVELS
+} xentoollog_level;
+
+typedef struct xentoollog_logger xentoollog_logger;
+struct xentoollog_logger {
+ void (*vmessage)(struct xentoollog_logger *logger,
+ xentoollog_level level,
+ int errnoval /* or -1 */,
+ const char *context /* eg "xc", "xl", may be 0 */,
+ const char *format /* without level, context, \n */,
+ va_list al)
+ __attribute__((format(printf,5,0)));
+ void (*progress)(struct xentoollog_logger *logger,
+ const char *context /* see above */,
+ const char *doing_what /* no \r,\n */,
+ int percent, unsigned long done, unsigned long total)
+ /* null function pointer is ok.
+ * will always be called with done==0 for each new
+ * context/doing_what */;
+ void (*destroy)(struct xentoollog_logger *logger);
+ /* each logger can put its necessary data here */
+};
+
+
+/*---------- facilities for consuming log messages ----------*/
+
+#define XTL_STDIOSTREAM_SHOW_PID 001u
+#define XTL_STDIOSTREAM_SHOW_DATE 002u
+#define XTL_STDIOSTREAM_HIDE_PROGRESS 004u
+#define XTL_STDIOSTREAM_PROGRESS_USE_CR 010u /* default is to */
+#define XTL_STDIOSTREAM_PROGRESS_NO_CR 020u /* use \r to ttys */
+
+typedef struct xentoollog_logger_stdiostream xentoollog_logger_stdiostream;
+
+xentoollog_logger_stdiostream *xtl_createlogger_stdiostream
+ (FILE *f, xentoollog_level min_level, unsigned flags);
+ /* may return 0 if malloc fails, in which case error was logged */
+ /* destroy on this logger does not close the file */
+
+void xtl_stdiostream_set_minlevel(xentoollog_logger_stdiostream*,
+ xentoollog_level min_level);
+void xtl_stdiostream_adjust_flags(xentoollog_logger_stdiostream*,
+ unsigned set_flags, unsigned clear_flags);
+ /* if set_flags and clear_flags overlap, set_flags takes precedence */
+
+void xtl_logger_destroy(struct xentoollog_logger *logger /* 0 is ok */);
+
+
+/*---------- facilities for generating log messages ----------*/
+
+void xtl_logv(struct xentoollog_logger *logger,
+ xentoollog_level level,
+ int errnoval /* or -1 */,
+ const char *context /* eg "xc", "xenstore", "xl", may be 0 */,
+ const char *format /* does not contain \n */,
+ va_list) __attribute__((format(printf,5,0)));
+
+void xtl_log(struct xentoollog_logger *logger,
+ xentoollog_level level,
+ int errnoval /* or -1 */,
+ const char *context /* eg "xc", "xenstore", "xl" */,
+ const char *format /* does not contain \n */,
+ ...) __attribute__((format(printf,5,6)));
+
+void xtl_progress(struct xentoollog_logger *logger,
+ const char *context /* see above, may be 0 */,
+ const char *doing_what,
+ unsigned long done, unsigned long total);
+
+
+/*---------- facilities for defining log message consumers ----------*/
+
+const char *xtl_level_to_string(xentoollog_level); /* never fails */
+
+
+#define XTL_NEW_LOGGER(LOGGER,buffer) ({ \
+ xentoollog_logger_##LOGGER *new_consumer; \
+ \
+ (buffer).vtable.vmessage = LOGGER##_vmessage; \
+ (buffer).vtable.progress = LOGGER##_progress; \
+ (buffer).vtable.destroy = LOGGER##_destroy; \
+ \
+ new_consumer = malloc(sizeof(*new_consumer)); \
+ if (!new_consumer) { \
+ xtl_log((xentoollog_logger*)&buffer, \
+ XTL_CRITICAL, errno, "xtl", \
+ "failed to allocate memory for new message logger"); \
+ } else { \
+ *new_consumer = buffer; \
+ } \
+ \
+ new_consumer; \
+});
+
+
+#endif /* XENTOOLLOG_H */
diff --git a/tools/libxc/xc_bitops.h b/tools/libxc/xc_bitops.h
index d8e0c16..dfce3b8 100644
--- a/tools/libxc/xc_bitops.h
+++ b/tools/libxc/xc_bitops.h
@@ -60,4 +60,12 @@ static inline int test_and_set_bit(int nr, unsigned long *addr)
return oldbit;
}
+static inline void bitmap_or(unsigned long *dst, const unsigned long *other,
+ int nr_bits)
+{
+ int i, nr_longs = (bitmap_size(nr_bits) / sizeof(unsigned long));
+ for ( i = 0; i < nr_longs; ++i )
+ dst[i] |= other[i];
+}
+
#endif /* XC_BITOPS_H */
diff --git a/tools/libxc/xc_compression.c b/tools/libxc/xc_compression.c
index 8f0b89d..d42e651 100644
--- a/tools/libxc/xc_compression.c
+++ b/tools/libxc/xc_compression.c
@@ -32,7 +32,6 @@
#include <unistd.h>
#include <sys/types.h>
#include <inttypes.h>
-#include <errno.h>
#include "xc_private.h"
#include "xenctrl.h"
#include "xg_save_restore.h"
diff --git a/tools/libxc/xc_core.c b/tools/libxc/xc_core.c
index 4bc1abb..dfa424b 100644
--- a/tools/libxc/xc_core.c
+++ b/tools/libxc/xc_core.c
@@ -497,7 +497,7 @@ xc_domain_dumpcore_via_callback(xc_interface *xch,
ctxt = calloc(sizeof(*ctxt), info.max_vcpu_id + 1);
if ( !ctxt )
{
- PERROR("Could not allocate vcpu context array", domid);
+ PERROR("Could not allocate vcpu context array");
goto out;
}
diff --git a/tools/libxc/xc_core_x86.c b/tools/libxc/xc_core_x86.c
index e328dcf..f05060a 100644
--- a/tools/libxc/xc_core_x86.c
+++ b/tools/libxc/xc_core_x86.c
@@ -24,10 +24,6 @@
#define GET_FIELD(_p, _f) ((dinfo->guest_width==8) ? ((_p)->x64._f) : ((_p)->x32._f))
-#ifndef MAX
-#define MAX(_a, _b) ((_a) >= (_b) ? (_a) : (_b))
-#endif
-
int
xc_core_arch_gpfn_may_present(struct xc_core_arch_context *arch_ctxt,
unsigned long pfn)
diff --git a/tools/libxc/xc_cpufeature.h b/tools/libxc/xc_cpufeature.h
index c464e3a..66cc82e 100644
--- a/tools/libxc/xc_cpufeature.h
+++ b/tools/libxc/xc_cpufeature.h
@@ -125,6 +125,7 @@
#define X86_FEATURE_NODEID_MSR 19 /* NodeId MSR */
#define X86_FEATURE_TBM 21 /* trailing bit manipulations */
#define X86_FEATURE_TOPOEXT 22 /* topology extensions CPUID leafs */
+#define X86_FEATURE_DBEXT 26 /* data breakpoint extension */
/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx) */
#define X86_FEATURE_FSGSBASE 0 /* {RD,WR}{FS,GS}BASE instructions */
@@ -137,5 +138,9 @@
#define X86_FEATURE_ERMS 9 /* Enhanced REP MOVSB/STOSB */
#define X86_FEATURE_INVPCID 10 /* Invalidate Process Context ID */
#define X86_FEATURE_RTM 11 /* Restricted Transactional Memory */
+#define X86_FEATURE_RDSEED 18 /* RDSEED instruction */
+#define X86_FEATURE_ADX 19 /* ADCX, ADOX instructions */
+#define X86_FEATURE_SMAP 20 /* Supervisor Mode Access Protection */
+
#endif /* __LIBXC_CPUFEATURE_H */
diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
index bbbf9b8..a18b1ff 100644
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -21,6 +21,7 @@
*/
#include <stdlib.h>
+#include <stdbool.h>
#include "xc_private.h"
#include "xc_cpufeature.h"
#include <xen/hvm/params.h>
@@ -33,13 +34,6 @@
#define DEF_MAX_INTELEXT 0x80000008u
#define DEF_MAX_AMDEXT 0x8000001cu
-static int hypervisor_is_64bit(xc_interface *xch)
-{
- xen_capabilities_info_t xen_caps = "";
- return ((xc_version(xch, XENVER_capabilities, &xen_caps) == 0) &&
- (strstr(xen_caps, "x86_64") != NULL));
-}
-
static void cpuid(const unsigned int *input, unsigned int *regs)
{
unsigned int count = (input[1] == XEN_CPUID_INPUT_UNUSED) ? 0 : input[1];
@@ -94,13 +88,11 @@ static void amd_xc_cpuid_policy(
break;
case 0x80000001: {
- int is_64bit = hypervisor_is_64bit(xch) && is_pae;
-
if ( !is_pae )
clear_bit(X86_FEATURE_PAE, regs[3]);
/* Filter all other features according to a whitelist. */
- regs[2] &= ((is_64bit ? bitmaskof(X86_FEATURE_LAHF_LM) : 0) |
+ regs[2] &= (bitmaskof(X86_FEATURE_LAHF_LM) |
bitmaskof(X86_FEATURE_CMP_LEGACY) |
(is_nestedhvm ? bitmaskof(X86_FEATURE_SVM) : 0) |
bitmaskof(X86_FEATURE_CR8_LEGACY) |
@@ -110,12 +102,13 @@ static void amd_xc_cpuid_policy(
bitmaskof(X86_FEATURE_3DNOWPREFETCH) |
bitmaskof(X86_FEATURE_OSVW) |
bitmaskof(X86_FEATURE_XOP) |
+ bitmaskof(X86_FEATURE_LWP) |
bitmaskof(X86_FEATURE_FMA4) |
bitmaskof(X86_FEATURE_TBM) |
- bitmaskof(X86_FEATURE_LWP));
+ bitmaskof(X86_FEATURE_DBEXT));
regs[3] &= (0x0183f3ff | /* features shared with 0x00000001:EDX */
- (is_pae ? bitmaskof(X86_FEATURE_NX) : 0) |
- (is_64bit ? bitmaskof(X86_FEATURE_LM) : 0) |
+ bitmaskof(X86_FEATURE_NX) |
+ bitmaskof(X86_FEATURE_LM) |
bitmaskof(X86_FEATURE_SYSCALL) |
bitmaskof(X86_FEATURE_MP) |
bitmaskof(X86_FEATURE_MMXEXT) |
@@ -193,15 +186,14 @@ static void intel_xc_cpuid_policy(
break;
case 0x80000001: {
- int is_64bit = hypervisor_is_64bit(xch) && is_pae;
-
/* Only a few features are advertised in Intel's 0x80000001. */
- regs[2] &= (is_64bit ? bitmaskof(X86_FEATURE_LAHF_LM) : 0) |
- bitmaskof(X86_FEATURE_ABM);
- regs[3] &= ((is_pae ? bitmaskof(X86_FEATURE_NX) : 0) |
- (is_64bit ? bitmaskof(X86_FEATURE_LM) : 0) |
- (is_64bit ? bitmaskof(X86_FEATURE_SYSCALL) : 0) |
- (is_64bit ? bitmaskof(X86_FEATURE_RDTSCP) : 0));
+ regs[2] &= (bitmaskof(X86_FEATURE_LAHF_LM) |
+ bitmaskof(X86_FEATURE_3DNOWPREFETCH) |
+ bitmaskof(X86_FEATURE_ABM));
+ regs[3] &= (bitmaskof(X86_FEATURE_NX) |
+ bitmaskof(X86_FEATURE_LM) |
+ bitmaskof(X86_FEATURE_SYSCALL) |
+ bitmaskof(X86_FEATURE_RDTSCP));
break;
}
@@ -274,13 +266,12 @@ static void xc_cpuid_hvm_policy(
{
DECLARE_DOMCTL;
char brand[13];
- unsigned long nestedhvm;
- unsigned long pae;
+ uint64_t val;
int is_pae, is_nestedhvm;
uint64_t xfeature_mask;
- xc_get_hvm_param(xch, domid, HVM_PARAM_PAE_ENABLED, &pae);
- is_pae = !!pae;
+ xc_hvm_param_get(xch, domid, HVM_PARAM_PAE_ENABLED, &val);
+ is_pae = !!val;
/* Detecting Xen's atitude towards XSAVE */
memset(&domctl, 0, sizeof(domctl));
@@ -289,8 +280,8 @@ static void xc_cpuid_hvm_policy(
do_domctl(xch, &domctl);
xfeature_mask = domctl.u.vcpuextstate.xfeature_mask;
- xc_get_hvm_param(xch, domid, HVM_PARAM_NESTEDHVM, &nestedhvm);
- is_nestedhvm = !!nestedhvm;
+ xc_hvm_param_get(xch, domid, HVM_PARAM_NESTEDHVM, &val);
+ is_nestedhvm = !!val;
switch ( input[0] )
{
@@ -371,6 +362,9 @@ static void xc_cpuid_hvm_policy(
bitmaskof(X86_FEATURE_ERMS) |
bitmaskof(X86_FEATURE_INVPCID) |
bitmaskof(X86_FEATURE_RTM) |
+ bitmaskof(X86_FEATURE_RDSEED) |
+ bitmaskof(X86_FEATURE_ADX) |
+ bitmaskof(X86_FEATURE_SMAP) |
bitmaskof(X86_FEATURE_FSGSBASE));
} else
regs[1] = 0;
@@ -386,7 +380,10 @@ static void xc_cpuid_hvm_policy(
break;
case 0x80000001:
- if ( !is_pae ) {
+ if ( !is_pae )
+ {
+ clear_bit(X86_FEATURE_LAHF_LM, regs[2]);
+ clear_bit(X86_FEATURE_LM, regs[3]);
clear_bit(X86_FEATURE_NX, regs[3]);
clear_bit(X86_FEATURE_PSE36, regs[3]);
}
@@ -433,11 +430,11 @@ static void xc_cpuid_hvm_policy(
static void xc_cpuid_pv_policy(
xc_interface *xch, domid_t domid,
- const unsigned int *input, unsigned int *regs)
+ const unsigned int *input, unsigned int *regs, bool pvh)
{
DECLARE_DOMCTL;
unsigned int guest_width;
- int guest_64bit, xen_64bit = hypervisor_is_64bit(xch);
+ int guest_64bit;
char brand[13];
uint64_t xfeature_mask;
@@ -456,8 +453,10 @@ static void xc_cpuid_pv_policy(
if ( (input[0] & 0x7fffffff) == 0x00000001 )
{
clear_bit(X86_FEATURE_VME, regs[3]);
- clear_bit(X86_FEATURE_PSE, regs[3]);
- clear_bit(X86_FEATURE_PGE, regs[3]);
+ if ( !pvh ) {
+ clear_bit(X86_FEATURE_PSE, regs[3]);
+ clear_bit(X86_FEATURE_PGE, regs[3]);
+ }
clear_bit(X86_FEATURE_MCE, regs[3]);
clear_bit(X86_FEATURE_MCA, regs[3]);
clear_bit(X86_FEATURE_MTRR, regs[3]);
@@ -467,7 +466,7 @@ static void xc_cpuid_pv_policy(
switch ( input[0] )
{
case 0x00000001:
- if ( !xen_64bit || strstr(brand, "AMD") )
+ if ( strstr(brand, "AMD") )
clear_bit(X86_FEATURE_SEP, regs[3]);
clear_bit(X86_FEATURE_DS, regs[3]);
clear_bit(X86_FEATURE_ACC, regs[3]);
@@ -502,6 +501,8 @@ static void xc_cpuid_pv_policy(
bitmaskof(X86_FEATURE_BMI2) |
bitmaskof(X86_FEATURE_ERMS) |
bitmaskof(X86_FEATURE_RTM) |
+ bitmaskof(X86_FEATURE_RDSEED) |
+ bitmaskof(X86_FEATURE_ADX) |
bitmaskof(X86_FEATURE_FSGSBASE));
else
regs[1] = 0;
@@ -524,7 +525,8 @@ static void xc_cpuid_pv_policy(
{
set_bit(X86_FEATURE_SYSCALL, regs[3]);
}
- clear_bit(X86_FEATURE_PAGE1GB, regs[3]);
+ if ( !pvh )
+ clear_bit(X86_FEATURE_PAGE1GB, regs[3]);
clear_bit(X86_FEATURE_RDTSCP, regs[3]);
clear_bit(X86_FEATURE_SVM, regs[2]);
@@ -555,13 +557,24 @@ static int xc_cpuid_policy(
{
xc_dominfo_t info;
+ /*
+ * For hypervisor leaves (0x4000XXXX) only 0x4000xx00.EAX[7:0] bits (max
+ * number of leaves) can be set by user. Hypervisor will enforce this so
+ * all other bits are don't-care and we can set them to zero.
+ */
+ if ( (input[0] & 0xffff0000) == 0x40000000 )
+ {
+ regs[0] = regs[1] = regs[2] = regs[3] = 0;
+ return 0;
+ }
+
if ( xc_domain_getinfo(xch, domid, 1, &info) == 0 )
return -EINVAL;
if ( info.hvm )
xc_cpuid_hvm_policy(xch, domid, input, regs);
else
- xc_cpuid_pv_policy(xch, domid, input, regs);
+ xc_cpuid_pv_policy(xch, domid, input, regs, info.pvh);
return 0;
}
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
deleted file mode 100644
index c9af0ce..0000000
--- a/tools/libxc/xc_dom.h
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <xen/libelf/libelf.h>
-
-#define INVALID_P2M_ENTRY ((xen_pfn_t)-1)
-
-/* --- typedefs and structs ---------------------------------------- */
-
-typedef uint64_t xen_vaddr_t;
-typedef uint64_t xen_paddr_t;
-
-#define PRIpfn PRI_xen_pfn
-
-struct xc_dom_seg {
- xen_vaddr_t vstart;
- xen_vaddr_t vend;
- xen_pfn_t pfn;
-};
-
-struct xc_dom_mem {
- struct xc_dom_mem *next;
- void *mmap_ptr;
- size_t mmap_len;
- unsigned char memory[0];
-};
-
-struct xc_dom_phys {
- struct xc_dom_phys *next;
- void *ptr;
- xen_pfn_t first;
- xen_pfn_t count;
-};
-
-struct xc_dom_image {
- /* files */
- void *kernel_blob;
- size_t kernel_size;
- void *ramdisk_blob;
- size_t ramdisk_size;
- void *devicetree_blob;
- size_t devicetree_size;
-
- size_t max_kernel_size;
- size_t max_ramdisk_size;
- size_t max_devicetree_size;
-
- /* arguments and parameters */
- char *cmdline;
- uint32_t f_requested[XENFEAT_NR_SUBMAPS];
-
- /* info from (elf) kernel image */
- struct elf_dom_parms parms;
- char *guest_type;
-
- /* memory layout */
- struct xc_dom_seg kernel_seg;
- /* If ramdisk_seg.vstart is non zero then the ramdisk will be
- * loaded at that address, otherwise it will automatically placed.
- *
- * If automatic placement is used and the ramdisk is gzip
- * compressed then it will be decompressed as it is loaded. If the
- * ramdisk has been explicitly placed then it is loaded as is
- * otherwise decompressing risks undoing the manual placement.
- */
- struct xc_dom_seg ramdisk_seg;
- struct xc_dom_seg p2m_seg;
- struct xc_dom_seg pgtables_seg;
- struct xc_dom_seg devicetree_seg;
- xen_pfn_t start_info_pfn;
- xen_pfn_t console_pfn;
- xen_pfn_t xenstore_pfn;
- xen_pfn_t shared_info_pfn;
- xen_pfn_t bootstack_pfn;
- xen_vaddr_t virt_alloc_end;
- xen_vaddr_t bsd_symtab_start;
-
- /* initial page tables */
- unsigned int pgtables;
- unsigned int pg_l4;
- unsigned int pg_l3;
- unsigned int pg_l2;
- unsigned int pg_l1;
- unsigned int alloc_bootstack;
- unsigned int extra_pages;
- xen_vaddr_t virt_pgtab_end;
-
- /* other state info */
- uint32_t f_active[XENFEAT_NR_SUBMAPS];
- /*
- * p2m_host maps guest physical addresses an offset from
- * rambase_pfn (see below) into gfns.
- *
- * For a pure PV guest this means that it maps GPFNs into MFNs for
- * a hybrid guest this means that it maps GPFNs to GPFNS.
- *
- * Note that the input is offset by rambase.
- */
- xen_pfn_t *p2m_host;
- void *p2m_guest;
-
- /* physical memory
- *
- * A PV guest has a single contiguous block of physical RAM,
- * consisting of total_pages starting at rambase_pfn.
- */
- xen_pfn_t rambase_pfn;
- xen_pfn_t total_pages;
- struct xc_dom_phys *phys_pages;
- int realmodearea_log;
-
- /* malloc memory pool */
- struct xc_dom_mem *memblocks;
-
- /* memory footprint stats */
- size_t alloc_malloc;
- size_t alloc_mem_map;
- size_t alloc_file_map;
- size_t alloc_domU_map;
-
- /* misc xen domain config stuff */
- unsigned long flags;
- unsigned int console_evtchn;
- unsigned int xenstore_evtchn;
- domid_t console_domid;
- domid_t xenstore_domid;
- xen_pfn_t shared_info_mfn;
- int pvh_enabled;
-
- xc_interface *xch;
- domid_t guest_domid;
- int8_t vhpt_size_log2; /* for IA64 */
- int8_t superpages;
- int claim_enabled; /* 0 by default, 1 enables it */
- int shadow_enabled;
-
- int xen_version;
- xen_capabilities_info_t xen_caps;
-
- /* kernel loader, arch hooks */
- struct xc_dom_loader *kernel_loader;
- void *private_loader;
-
- /* kernel loader */
- struct xc_dom_arch *arch_hooks;
- /* allocate up to virt_alloc_end */
- int (*allocate) (struct xc_dom_image * dom, xen_vaddr_t up_to);
-};
-
-/* --- pluggable kernel loader ------------------------------------- */
-
-struct xc_dom_loader {
- char *name;
- /* Sadly the error returns from these functions are not consistent: */
- elf_negerrnoval (*probe) (struct xc_dom_image * dom);
- elf_negerrnoval (*parser) (struct xc_dom_image * dom);
- elf_errorstatus (*loader) (struct xc_dom_image * dom);
-
- struct xc_dom_loader *next;
-};
-
-#define __init __attribute__ ((constructor))
-void xc_dom_register_loader(struct xc_dom_loader *loader);
-
-/* --- arch specific hooks ----------------------------------------- */
-
-struct xc_dom_arch {
- /* pagetable setup */
- int (*alloc_magic_pages) (struct xc_dom_image * dom);
- int (*count_pgtables) (struct xc_dom_image * dom);
- int (*setup_pgtables) (struct xc_dom_image * dom);
-
- /* arch-specific data structs setup */
- int (*start_info) (struct xc_dom_image * dom);
- int (*shared_info) (struct xc_dom_image * dom, void *shared_info);
- int (*vcpu) (struct xc_dom_image * dom, void *vcpu_ctxt);
-
- char *guest_type;
- char *native_protocol;
- int page_shift;
- int sizeof_pfn;
-
- struct xc_dom_arch *next;
-};
-void xc_dom_register_arch_hooks(struct xc_dom_arch *hooks);
-
-#define XC_DOM_PAGE_SHIFT(dom) ((dom)->arch_hooks->page_shift)
-#define XC_DOM_PAGE_SIZE(dom) (1 << (dom)->arch_hooks->page_shift)
-
-/* --- main functions ---------------------------------------------- */
-
-struct xc_dom_image *xc_dom_allocate(xc_interface *xch,
- const char *cmdline, const char *features);
-void xc_dom_release_phys(struct xc_dom_image *dom);
-void xc_dom_release(struct xc_dom_image *dom);
-int xc_dom_rambase_init(struct xc_dom_image *dom, uint64_t rambase);
-int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb);
-
-/* Set this larger if you have enormous ramdisks/kernels. Note that
- * you should trust all kernels not to be maliciously large (e.g. to
- * exhaust all dom0 memory) if you do this (see CVE-2012-4544 /
- * XSA-25). You can also set the default independently for
- * ramdisks/kernels in xc_dom_allocate() or call
- * xc_dom_{kernel,ramdisk}_max_size.
- */
-#ifndef XC_DOM_DECOMPRESS_MAX
-#define XC_DOM_DECOMPRESS_MAX (1024*1024*1024) /* 1GB */
-#endif
-
-int xc_dom_kernel_check_size(struct xc_dom_image *dom, size_t sz);
-int xc_dom_kernel_max_size(struct xc_dom_image *dom, size_t sz);
-
-int xc_dom_ramdisk_check_size(struct xc_dom_image *dom, size_t sz);
-int xc_dom_ramdisk_max_size(struct xc_dom_image *dom, size_t sz);
-
-int xc_dom_devicetree_max_size(struct xc_dom_image *dom, size_t sz);
-
-size_t xc_dom_check_gzip(xc_interface *xch,
- void *blob, size_t ziplen);
-int xc_dom_do_gunzip(xc_interface *xch,
- void *src, size_t srclen, void *dst, size_t dstlen);
-int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size);
-
-int xc_dom_kernel_file(struct xc_dom_image *dom, const char *filename);
-int xc_dom_ramdisk_file(struct xc_dom_image *dom, const char *filename);
-int xc_dom_kernel_mem(struct xc_dom_image *dom, const void *mem,
- size_t memsize);
-int xc_dom_ramdisk_mem(struct xc_dom_image *dom, const void *mem,
- size_t memsize);
-int xc_dom_devicetree_file(struct xc_dom_image *dom, const char *filename);
-int xc_dom_devicetree_mem(struct xc_dom_image *dom, const void *mem,
- size_t memsize);
-
-int xc_dom_parse_image(struct xc_dom_image *dom);
-struct xc_dom_arch *xc_dom_find_arch_hooks(xc_interface *xch, char *guest_type);
-int xc_dom_build_image(struct xc_dom_image *dom);
-int xc_dom_update_guest_p2m(struct xc_dom_image *dom);
-
-int xc_dom_boot_xen_init(struct xc_dom_image *dom, xc_interface *xch,
- domid_t domid);
-int xc_dom_boot_mem_init(struct xc_dom_image *dom);
-void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn,
- xen_pfn_t count);
-int xc_dom_boot_image(struct xc_dom_image *dom);
-int xc_dom_compat_check(struct xc_dom_image *dom);
-int xc_dom_gnttab_init(struct xc_dom_image *dom);
-int xc_dom_gnttab_hvm_seed(xc_interface *xch, domid_t domid,
- xen_pfn_t console_gmfn,
- xen_pfn_t xenstore_gmfn,
- domid_t console_domid,
- domid_t xenstore_domid);
-int xc_dom_gnttab_seed(xc_interface *xch, domid_t domid,
- xen_pfn_t console_gmfn,
- xen_pfn_t xenstore_gmfn,
- domid_t console_domid,
- domid_t xenstore_domid);
-int xc_dom_feature_translated(struct xc_dom_image *dom);
-
-/* --- debugging bits ---------------------------------------------- */
-
-int xc_dom_loginit(xc_interface *xch);
-
-void xc_dom_printf(xc_interface *xch, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
-void xc_dom_panic_func(xc_interface *xch,
- const char *file, int line, xc_error_code err,
- const char *fmt, ...)
- __attribute__ ((format(printf, 5, 6)));
-
-#define xc_dom_panic(xch, err, fmt, args...) \
- xc_dom_panic_func(xch, __FILE__, __LINE__, err, fmt, ## args)
-#define xc_dom_trace(mark) \
- xc_dom_printf("%s:%d: trace %s\n", __FILE__, __LINE__, mark)
-
-void xc_dom_log_memory_footprint(struct xc_dom_image *dom);
-
-/* --- simple memory pool ------------------------------------------ */
-
-void *xc_dom_malloc(struct xc_dom_image *dom, size_t size);
-void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size);
-void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
- const char *filename, size_t * size,
- const size_t max_size);
-char *xc_dom_strdup(struct xc_dom_image *dom, const char *str);
-
-/* --- alloc memory pool ------------------------------------------- */
-
-int xc_dom_alloc_page(struct xc_dom_image *dom, char *name);
-int xc_dom_alloc_segment(struct xc_dom_image *dom,
- struct xc_dom_seg *seg, char *name,
- xen_vaddr_t start, xen_vaddr_t size);
-
-/* --- misc bits --------------------------------------------------- */
-
-void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first,
- xen_pfn_t count);
-void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t first,
- xen_pfn_t count, xen_pfn_t *count_out);
-void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn);
-void xc_dom_unmap_all(struct xc_dom_image *dom);
-
-static inline void *xc_dom_seg_to_ptr_pages(struct xc_dom_image *dom,
- struct xc_dom_seg *seg,
- xen_pfn_t *pages_out)
-{
- xen_vaddr_t segsize = seg->vend - seg->vstart;
- unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
- xen_pfn_t pages = (segsize + page_size - 1) / page_size;
- void *retval;
-
- retval = xc_dom_pfn_to_ptr(dom, seg->pfn, pages);
-
- *pages_out = retval ? pages : 0;
- return retval;
-}
-
-static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
- struct xc_dom_seg *seg)
-{
- xen_pfn_t dummy;
-
- return xc_dom_seg_to_ptr_pages(dom, seg, &dummy);
-}
-
-static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom,
- xen_vaddr_t vaddr,
- size_t *safe_region_out)
-{
- unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
- xen_pfn_t page = (vaddr - dom->parms.virt_base) / page_size;
- unsigned int offset = (vaddr - dom->parms.virt_base) % page_size;
- xen_pfn_t safe_region_count;
- void *ptr;
-
- *safe_region_out = 0;
- ptr = xc_dom_pfn_to_ptr_retcount(dom, page, 0, &safe_region_count);
- if ( ptr == NULL )
- return ptr;
- *safe_region_out = (safe_region_count << XC_DOM_PAGE_SHIFT(dom)) - offset;
- return ptr + offset;
-}
-
-static inline xen_pfn_t xc_dom_p2m_host(struct xc_dom_image *dom, xen_pfn_t pfn)
-{
- if (dom->shadow_enabled)
- return pfn;
- if (pfn < dom->rambase_pfn || pfn >= dom->rambase_pfn + dom->total_pages)
- return INVALID_MFN;
- return dom->p2m_host[pfn - dom->rambase_pfn];
-}
-
-static inline xen_pfn_t xc_dom_p2m_guest(struct xc_dom_image *dom,
- xen_pfn_t pfn)
-{
- if (xc_dom_feature_translated(dom))
- return pfn;
- if (pfn < dom->rambase_pfn || pfn >= dom->rambase_pfn + dom->total_pages)
- return INVALID_MFN;
- return dom->p2m_host[pfn - dom->rambase_pfn];
-}
-
-/* --- arch bits --------------------------------------------------- */
-
-int arch_setup_meminit(struct xc_dom_image *dom);
-int arch_setup_bootearly(struct xc_dom_image *dom);
-int arch_setup_bootlate(struct xc_dom_image *dom);
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libxc/xc_dom_arm.c b/tools/libxc/xc_dom_arm.c
index d5831a2..9b31b1f 100644
--- a/tools/libxc/xc_dom_arm.c
+++ b/tools/libxc/xc_dom_arm.c
@@ -18,6 +18,7 @@
* Copyright (c) 2011, Citrix Systems
*/
#include <inttypes.h>
+#include <assert.h>
#include <xen/xen.h>
#include <xen/io/protocols.h>
@@ -29,6 +30,13 @@
#define CONSOLE_PFN_OFFSET 0
#define XENSTORE_PFN_OFFSET 1
+#define LPAE_SHIFT 9
+
+#define PFN_4K_SHIFT (0)
+#define PFN_2M_SHIFT (PFN_4K_SHIFT+LPAE_SHIFT)
+#define PFN_1G_SHIFT (PFN_2M_SHIFT+LPAE_SHIFT)
+#define PFN_512G_SHIFT (PFN_1G_SHIFT+LPAE_SHIFT)
+
/* get guest IO ABI protocol */
const char *xc_domain_get_native_protocol(xc_interface *xch,
uint32_t domid)
@@ -58,12 +66,15 @@ static int setup_pgtables_arm(struct xc_dom_image *dom)
static int alloc_magic_pages(struct xc_dom_image *dom)
{
int rc, i;
+ const xen_pfn_t base = GUEST_MAGIC_BASE >> XC_PAGE_SHIFT;
xen_pfn_t p2m[NR_MAGIC_PAGES];
+ XC_BUILD_BUG_ON(NR_MAGIC_PAGES > GUEST_MAGIC_SIZE >> XC_PAGE_SHIFT);
+
DOMPRINTF_CALLED(dom->xch);
for (i = 0; i < NR_MAGIC_PAGES; i++)
- p2m[i] = dom->rambase_pfn + dom->total_pages + i;
+ p2m[i] = base + i;
rc = xc_domain_populate_physmap_exact(
dom->xch, dom->guest_domid, NR_MAGIC_PAGES,
@@ -71,19 +82,19 @@ static int alloc_magic_pages(struct xc_dom_image *dom)
if ( rc < 0 )
return rc;
- dom->console_pfn = dom->rambase_pfn + dom->total_pages + CONSOLE_PFN_OFFSET;
- dom->xenstore_pfn = dom->rambase_pfn + dom->total_pages + XENSTORE_PFN_OFFSET;
+ dom->console_pfn = base + CONSOLE_PFN_OFFSET;
+ dom->xenstore_pfn = base + XENSTORE_PFN_OFFSET;
xc_clear_domain_page(dom->xch, dom->guest_domid, dom->console_pfn);
xc_clear_domain_page(dom->xch, dom->guest_domid, dom->xenstore_pfn);
- xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_PFN,
+ xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_PFN,
dom->console_pfn);
- xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_STORE_PFN,
+ xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_STORE_PFN,
dom->xenstore_pfn);
/* allocated by toolstack */
- xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_EVTCHN,
+ xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_EVTCHN,
dom->console_evtchn);
- xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_STORE_EVTCHN,
+ xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_STORE_EVTCHN,
dom->xenstore_evtchn);
return 0;
@@ -226,7 +237,7 @@ static int set_mode(xc_interface *xch, domid_t domid, char *guest_type)
domctl.domain = domid;
domctl.cmd = XEN_DOMCTL_set_address_size;
- for ( i = 0; i < sizeof(types)/sizeof(types[0]); i++ )
+ for ( i = 0; i < ARRAY_SIZE(types); i++ )
if ( !strcmp(types[i].guest, guest_type) )
domctl.u.address_size.size = types[i].size;
if ( domctl.u.address_size.size == 0 )
@@ -245,16 +256,143 @@ static int set_mode(xc_interface *xch, domid_t domid, char *guest_type)
return rc;
}
+/* >0: success, *nr_pfns set to number actually populated
+ * 0: didn't try with this pfn shift (e.g. misaligned base etc)
+ * <0: ERROR
+ */
+static int populate_one_size(struct xc_dom_image *dom, int pfn_shift,
+ xen_pfn_t base_pfn, xen_pfn_t *nr_pfns,
+ xen_pfn_t *extents)
+{
+ /* The mask for this level */
+ const uint64_t mask = ((uint64_t)1<<(pfn_shift))-1;
+ /* The shift, mask and next boundary for the level above this one */
+ const int next_shift = pfn_shift + LPAE_SHIFT;
+ const uint64_t next_mask = ((uint64_t)1<<next_shift)-1;
+ const xen_pfn_t next_boundary
+ = (base_pfn + ((uint64_t)1<<next_shift)) & ~next_mask;
+
+ int nr, i, count;
+ xen_pfn_t end_pfn = base_pfn + *nr_pfns;
+
+ /* No level zero super pages with current hardware */
+ if ( pfn_shift == PFN_512G_SHIFT )
+ return 0;
+
+ /* base is misaligned for this level */
+ if ( mask & base_pfn )
+ return 0;
+
+ /*
+ * If base is not aligned at the next level up then try and make
+ * it so for next time around.
+ */
+ if ( (base_pfn & next_mask) && end_pfn > next_boundary )
+ end_pfn = next_boundary;
+
+ count = ( end_pfn - base_pfn ) >> pfn_shift;
+
+ /* Nothing to allocate */
+ if ( !count )
+ return 0;
+
+ for ( i = 0 ; i < count ; i ++ )
+ extents[i] = base_pfn + (i<<pfn_shift);
+
+ nr = xc_domain_populate_physmap(dom->xch, dom->guest_domid, count,
+ pfn_shift, 0, extents);
+ if ( nr <= 0 ) return nr;
+ DOMPRINTF("%s: populated %#x/%#x entries with shift %d",
+ __FUNCTION__, nr, count, pfn_shift);
+
+ *nr_pfns = nr << pfn_shift;
+
+ return 1;
+}
+
+static int populate_guest_memory(struct xc_dom_image *dom,
+ xen_pfn_t base_pfn, xen_pfn_t nr_pfns)
+{
+ int rc = 0;
+ xen_pfn_t allocsz, pfn, *extents;
+
+ extents = calloc(1024*1024,sizeof(xen_pfn_t));
+ if ( extents == NULL )
+ {
+ DOMPRINTF("%s: Unable to allocate extent array", __FUNCTION__);
+ return -1;
+ }
+
+ DOMPRINTF("%s: populating RAM @ %016"PRIx64"-%016"PRIx64" (%"PRId64"MB)",
+ __FUNCTION__,
+ (uint64_t)base_pfn << XC_PAGE_SHIFT,
+ (uint64_t)(base_pfn + nr_pfns) << XC_PAGE_SHIFT,
+ (uint64_t)nr_pfns >> (20-XC_PAGE_SHIFT));
+
+ for ( pfn = 0; pfn < nr_pfns; pfn += allocsz )
+ {
+ allocsz = min_t(int, 1024*1024, nr_pfns - pfn);
+#if 0 /* Enable this to exercise/debug the code which tries to realign
+ * to a superpage boundary, by misaligning at the start. */
+ if ( pfn == 0 )
+ {
+ allocsz = 1;
+ rc = populate_one_size(dom, PFN_4K_SHIFT,
+ base_pfn + pfn, &allocsz, extents);
+ if (rc < 0) break;
+ if (rc > 0) continue;
+ /* Failed to allocate a single page? */
+ break;
+ }
+#endif
+
+ rc = populate_one_size(dom, PFN_512G_SHIFT,
+ base_pfn + pfn, &allocsz, extents);
+ if ( rc < 0 ) break;
+ if ( rc > 0 ) continue;
+
+ rc = populate_one_size(dom, PFN_1G_SHIFT,
+ base_pfn + pfn, &allocsz, extents);
+ if ( rc < 0 ) break;
+ if ( rc > 0 ) continue;
+
+ rc = populate_one_size(dom, PFN_2M_SHIFT,
+ base_pfn + pfn, &allocsz, extents);
+ if ( rc < 0 ) break;
+ if ( rc > 0 ) continue;
+
+ rc = populate_one_size(dom, PFN_4K_SHIFT,
+ base_pfn + pfn, &allocsz, extents);
+ if ( rc < 0 ) break;
+ if ( rc == 0 )
+ {
+ DOMPRINTF("%s: Not enough RAM", __FUNCTION__);
+ errno = ENOMEM;
+ rc = -1;
+ goto out;
+ }
+ }
+
+ for ( pfn = 0; pfn < nr_pfns; pfn++ )
+ dom->p2m_host[pfn] = base_pfn + pfn;
+
+out:
+ free(extents);
+ return rc < 0 ? rc : 0;
+}
+
int arch_setup_meminit(struct xc_dom_image *dom)
{
- int rc;
- xen_pfn_t pfn, allocsz, i;
+ int i, rc;
+ xen_pfn_t pfn;
uint64_t modbase;
+ uint64_t ramsize = (uint64_t)dom->total_pages << XC_PAGE_SHIFT;
+
+ const uint64_t bankbase[] = GUEST_RAM_BANK_BASES;
+ const uint64_t bankmax[] = GUEST_RAM_BANK_SIZES;
+
/* Convenient */
- const uint64_t rambase = dom->rambase_pfn << XC_PAGE_SHIFT;
- const uint64_t ramsize = dom->total_pages << XC_PAGE_SHIFT;
- const uint64_t ramend = rambase + ramsize;
const uint64_t kernbase = dom->kernel_seg.vstart;
const uint64_t kernend = ROUNDUP(dom->kernel_seg.vend, 21/*2MB*/);
const uint64_t kernsize = kernend - kernbase;
@@ -263,21 +401,31 @@ int arch_setup_meminit(struct xc_dom_image *dom)
const uint64_t ramdisk_size = dom->ramdisk_blob ?
ROUNDUP(dom->ramdisk_size, XC_PAGE_SHIFT) : 0;
const uint64_t modsize = dtb_size + ramdisk_size;
- const uint64_t ram128mb = rambase + (128<<20);
+ const uint64_t ram128mb = bankbase[0] + (128<<20);
+
+ xen_pfn_t p2m_size;
+ uint64_t bank0end;
- if ( modsize + kernsize > ramsize )
+ assert(dom->rambase_pfn << XC_PAGE_SHIFT == bankbase[0]);
+
+ if ( modsize + kernsize > bankmax[0] )
{
DOMPRINTF("%s: Not enough memory for the kernel+dtb+initrd",
__FUNCTION__);
return -1;
}
- if ( ramsize > GUEST_RAM_SIZE - NR_MAGIC_PAGES*XC_PAGE_SIZE )
+ if ( ramsize == 0 )
+ {
+ DOMPRINTF("%s: ram size is 0", __FUNCTION__);
+ return -1;
+ }
+
+ if ( ramsize > GUEST_RAM_MAX )
{
DOMPRINTF("%s: ram size is too large for guest address space: "
"%"PRIx64" > %llx",
- __FUNCTION__, ramsize,
- GUEST_RAM_SIZE - NR_MAGIC_PAGES*XC_PAGE_SIZE);
+ __FUNCTION__, ramsize, GUEST_RAM_MAX);
return -1;
}
@@ -287,26 +435,33 @@ int arch_setup_meminit(struct xc_dom_image *dom)
dom->shadow_enabled = 1;
- dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * dom->total_pages);
+ for ( i = 0; ramsize && i < GUEST_RAM_BANKS; i++ )
+ {
+ uint64_t banksize = ramsize > bankmax[i] ? bankmax[i] : ramsize;
+
+ ramsize -= banksize;
+
+ p2m_size = ( bankbase[i] + banksize - bankbase[0] ) >> XC_PAGE_SHIFT;
+
+ dom->rambank_size[i] = banksize >> XC_PAGE_SHIFT;
+ }
+
+ assert(dom->rambank_size[0] != 0);
+ assert(ramsize == 0); /* Too much RAM is rejected above */
+
+ dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * p2m_size);
if ( dom->p2m_host == NULL )
return -EINVAL;
+ for ( pfn = 0; pfn < p2m_size; pfn++ )
+ dom->p2m_host[pfn] = INVALID_MFN;
- /* setup initial p2m */
- for ( pfn = 0; pfn < dom->total_pages; pfn++ )
- dom->p2m_host[pfn] = pfn + dom->rambase_pfn;
-
- /* allocate guest memory */
- for ( i = rc = allocsz = 0;
- (i < dom->total_pages) && !rc;
- i += allocsz )
+ /* setup initial p2m and allocate guest memory */
+ for ( i = 0; dom->rambank_size[i] && i < GUEST_RAM_BANKS; i++ )
{
- allocsz = dom->total_pages - i;
- if ( allocsz > 1024*1024 )
- allocsz = 1024*1024;
-
- rc = xc_domain_populate_physmap_exact(
- dom->xch, dom->guest_domid, allocsz,
- 0, 0, &dom->p2m_host[i]);
+ if ((rc = populate_guest_memory(dom,
+ bankbase[i] >> XC_PAGE_SHIFT,
+ dom->rambank_size[i])))
+ return rc;
}
/*
@@ -317,11 +472,13 @@ int arch_setup_meminit(struct xc_dom_image *dom)
* If changing this then consider
* xen/arch/arm/kernel.c:place_modules as well.
*/
- if ( ramend >= ram128mb + modsize && kernend < ram128mb )
+ bank0end = bankbase[0] + ((uint64_t)dom->rambank_size[0] << XC_PAGE_SHIFT);
+
+ if ( bank0end >= ram128mb + modsize && kernend < ram128mb )
modbase = ram128mb;
- else if ( ramend - modsize > kernend )
- modbase = ramend - modsize;
- else if (kernbase - rambase > modsize )
+ else if ( bank0end - modsize > kernend )
+ modbase = bank0end - modsize;
+ else if (kernbase - bankbase[0] > modsize )
modbase = kernbase - modsize;
else
return -1;
diff --git a/tools/libxc/xc_dom_bzimageloader.c b/tools/libxc/xc_dom_bzimageloader.c
index 2225699..964ebdc 100644
--- a/tools/libxc/xc_dom_bzimageloader.c
+++ b/tools/libxc/xc_dom_bzimageloader.c
@@ -161,6 +161,13 @@ static int xc_try_bzip2_decode(
total = (((uint64_t)stream.total_out_hi32) << 32) | stream.total_out_lo32;
+ if ( xc_dom_register_external(dom, out_buf, total) )
+ {
+ DOMPRINTF("BZIP2: Error registering stream output");
+ free(out_buf);
+ goto bzip2_cleanup;
+ }
+
DOMPRINTF("%s: BZIP2 decompress OK, 0x%zx -> 0x%lx",
__FUNCTION__, *size, (long unsigned int) total);
@@ -305,6 +312,13 @@ static int _xc_try_lzma_decode(
}
}
+ if ( xc_dom_register_external(dom, out_buf, stream->total_out) )
+ {
+ DOMPRINTF("%s: Error registering stream output", what);
+ free(out_buf);
+ goto lzma_cleanup;
+ }
+
DOMPRINTF("%s: %s decompress OK, 0x%zx -> 0x%zx",
__FUNCTION__, what, *size, (size_t)stream->total_out);
@@ -464,7 +478,13 @@ static int xc_try_lzo1x_decode(
dst_len = lzo_read_32(cur);
if ( !dst_len )
+ {
+ msg = "Error registering stream output";
+ if ( xc_dom_register_external(dom, out_buf, out_len) )
+ break;
+
return 0;
+ }
if ( dst_len > LZOP_MAX_BLOCK_SIZE )
{
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
index baa62a1..ecbf981 100644
--- a/tools/libxc/xc_dom_core.c
+++ b/tools/libxc/xc_dom_core.c
@@ -132,6 +132,7 @@ void *xc_dom_malloc(struct xc_dom_image *dom, size_t size)
return NULL;
}
memset(block, 0, sizeof(*block) + size);
+ block->type = XC_DOM_MEM_TYPE_MALLOC_INTERNAL;
block->next = dom->memblocks;
dom->memblocks = block;
dom->alloc_malloc += sizeof(*block) + size;
@@ -151,23 +152,45 @@ void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
return NULL;
}
memset(block, 0, sizeof(*block));
- block->mmap_len = size;
- block->mmap_ptr = mmap(NULL, block->mmap_len,
- PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
- -1, 0);
- if ( block->mmap_ptr == MAP_FAILED )
+ block->len = size;
+ block->ptr = mmap(NULL, block->len,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
+ -1, 0);
+ if ( block->ptr == MAP_FAILED )
{
DOMPRINTF("%s: mmap failed", __FUNCTION__);
free(block);
return NULL;
}
+ block->type = XC_DOM_MEM_TYPE_MMAP;
block->next = dom->memblocks;
dom->memblocks = block;
dom->alloc_malloc += sizeof(*block);
- dom->alloc_mem_map += block->mmap_len;
+ dom->alloc_mem_map += block->len;
if ( size > (100 * 1024) )
print_mem(dom, __FUNCTION__, size);
- return block->mmap_ptr;
+ return block->ptr;
+}
+
+int xc_dom_register_external(struct xc_dom_image *dom, void *ptr, size_t size)
+{
+ struct xc_dom_mem *block;
+
+ block = malloc(sizeof(*block));
+ if ( block == NULL )
+ {
+ DOMPRINTF("%s: allocation failed", __FUNCTION__);
+ return -1;
+ }
+ memset(block, 0, sizeof(*block));
+ block->ptr = ptr;
+ block->len = size;
+ block->type = XC_DOM_MEM_TYPE_MALLOC_EXTERNAL;
+ block->next = dom->memblocks;
+ dom->memblocks = block;
+ dom->alloc_malloc += sizeof(*block);
+ dom->alloc_mem_map += block->len;
+ return 0;
}
void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
@@ -212,24 +235,25 @@ void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
}
memset(block, 0, sizeof(*block));
- block->mmap_len = *size;
- block->mmap_ptr = mmap(NULL, block->mmap_len, PROT_READ,
+ block->len = *size;
+ block->ptr = mmap(NULL, block->len, PROT_READ,
MAP_SHARED, fd, 0);
- if ( block->mmap_ptr == MAP_FAILED ) {
+ if ( block->ptr == MAP_FAILED ) {
xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
"failed to mmap file: %s",
strerror(errno));
goto err;
}
+ block->type = XC_DOM_MEM_TYPE_MMAP;
block->next = dom->memblocks;
dom->memblocks = block;
dom->alloc_malloc += sizeof(*block);
- dom->alloc_file_map += block->mmap_len;
+ dom->alloc_file_map += block->len;
close(fd);
if ( *size > (100 * 1024) )
print_mem(dom, __FUNCTION__, *size);
- return block->mmap_ptr;
+ return block->ptr;
err:
if ( fd != -1 )
@@ -246,8 +270,17 @@ static void xc_dom_free_all(struct xc_dom_image *dom)
while ( (block = dom->memblocks) != NULL )
{
dom->memblocks = block->next;
- if ( block->mmap_ptr )
- munmap(block->mmap_ptr, block->mmap_len);
+ switch ( block->type )
+ {
+ case XC_DOM_MEM_TYPE_MALLOC_INTERNAL:
+ break;
+ case XC_DOM_MEM_TYPE_MALLOC_EXTERNAL:
+ free(block->ptr);
+ break;
+ case XC_DOM_MEM_TYPE_MMAP:
+ munmap(block->ptr, block->len);
+ break;
+ }
free(block);
}
}
diff --git a/tools/libxc/xc_dom_decompress_lz4.c b/tools/libxc/xc_dom_decompress_lz4.c
index 08272fe..b6a33f2 100644
--- a/tools/libxc/xc_dom_decompress_lz4.c
+++ b/tools/libxc/xc_dom_decompress_lz4.c
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
-#include <endian.h>
#include <stdint.h>
#include "xg_private.h"
@@ -104,6 +103,11 @@ int xc_try_lz4_decode(
if (size == 0)
{
+ if ( xc_dom_register_external(dom, output, out_len) )
+ {
+ msg = "Error registering stream output";
+ goto exit_2;
+ }
*blob = output;
*psize = out_len;
return 0;
diff --git a/tools/libxc/xc_dom_decompress_unsafe_lzo1x.c b/tools/libxc/xc_dom_decompress_unsafe_lzo1x.c
index 57c73e3..59888b9 100644
--- a/tools/libxc/xc_dom_decompress_unsafe_lzo1x.c
+++ b/tools/libxc/xc_dom_decompress_unsafe_lzo1x.c
@@ -10,6 +10,7 @@
typedef uint8_t u8;
typedef uint32_t u32;
typedef uint16_t u16;
+typedef uint64_t u64;
#define likely(a) a
#define noinline
diff --git a/tools/libxc/xc_dom_decompress_unsafe_xz.c b/tools/libxc/xc_dom_decompress_unsafe_xz.c
index 2a32d40..fe7a7f4 100644
--- a/tools/libxc/xc_dom_decompress_unsafe_xz.c
+++ b/tools/libxc/xc_dom_decompress_unsafe_xz.c
@@ -34,17 +34,6 @@ static inline u32 le32_to_cpup(const u32 *p)
return cpu_to_le32(*p);
}
-#define min(x,y) ({ \
- const typeof(x) _x = (x); \
- const typeof(y) _y = (y); \
- (void) (&_x == &_y); \
- _x < _y ? _x : _y; })
-
-#define min_t(type,x,y) \
- ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
-#define max_t(type,x,y) \
- ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
-
#define __force
#define always_inline
diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c
index e034d62..bf06fe4 100644
--- a/tools/libxc/xc_dom_x86.c
+++ b/tools/libxc/xc_dom_x86.c
@@ -716,7 +716,7 @@ static int x86_compat(xc_interface *xch, domid_t domid, char *guest_type)
memset(&domctl, 0, sizeof(domctl));
domctl.domain = domid;
domctl.cmd = XEN_DOMCTL_set_address_size;
- for ( i = 0; i < sizeof(types)/sizeof(types[0]); i++ )
+ for ( i = 0; i < ARRAY_SIZE(types); i++ )
if ( !strcmp(types[i].guest, guest_type) )
domctl.u.address_size.size = types[i].size;
if ( domctl.u.address_size.size == 0 )
@@ -887,7 +887,7 @@ int arch_setup_bootlate(struct xc_dom_image *dom)
xen_pfn_t shinfo;
int i, rc;
- for ( i = 0; i < sizeof(types) / sizeof(types[0]); i++ )
+ for ( i = 0; i < ARRAY_SIZE(types); i++ )
if ( !strcmp(types[i].guest, dom->guest_type) )
pgd_type = types[i].pgd_type;
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index 369c3f3..b864872 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -48,15 +48,45 @@ int xc_domain_create(xc_interface *xch,
return 0;
}
+#if defined(__arm__) || defined(__aarch64__)
+int xc_domain_configure(xc_interface *xch, uint32_t domid,
+ xc_domain_configuration_t *config)
+{
+ int rc;
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_arm_configure_domain;
+ domctl.domain = (domid_t)domid;
+ /* xc_domain_configure_t is an alias of xen_domctl_arm_configuredomain */
+ memcpy(&domctl.u.configuredomain, config, sizeof(*config));
+
+ rc = do_domctl(xch, &domctl);
+ if ( !rc )
+ memcpy(config, &domctl.u.configuredomain, sizeof(*config));
+
+ return rc;
+}
+#endif
+
int xc_domain_cacheflush(xc_interface *xch, uint32_t domid,
xen_pfn_t start_pfn, xen_pfn_t nr_pfns)
{
+#if defined (__i386__) || defined (__x86_64__)
+ /*
+ * The x86 architecture provides cache coherency guarantees which prevent
+ * the need for this hypercall. Avoid the overhead of making a hypercall
+ * just for Xen to return -ENOSYS.
+ */
+ errno = ENOSYS;
+ return -1;
+#else
DECLARE_DOMCTL;
domctl.cmd = XEN_DOMCTL_cacheflush;
domctl.domain = (domid_t)domid;
domctl.u.cacheflush.start_pfn = start_pfn;
domctl.u.cacheflush.nr_pfns = nr_pfns;
return do_domctl(xch, &domctl);
+#endif
}
int xc_domain_pause(xc_interface *xch,
@@ -202,10 +232,15 @@ int xc_domain_node_getaffinity(xc_interface *xch,
int xc_vcpu_setaffinity(xc_interface *xch,
uint32_t domid,
int vcpu,
- xc_cpumap_t cpumap)
+ xc_cpumap_t cpumap_hard_inout,
+ xc_cpumap_t cpumap_soft_inout,
+ uint32_t flags)
{
DECLARE_DOMCTL;
- DECLARE_HYPERCALL_BUFFER(uint8_t, local);
+ DECLARE_HYPERCALL_BOUNCE(cpumap_hard_inout, 0,
+ XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
+ DECLARE_HYPERCALL_BOUNCE(cpumap_soft_inout, 0,
+ XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
int ret = -1;
int cpusize;
@@ -213,31 +248,37 @@ int xc_vcpu_setaffinity(xc_interface *xch,
if (cpusize <= 0)
{
PERROR("Could not get number of cpus");
- goto out;
+ return -1;
}
- local = xc_hypercall_buffer_alloc(xch, local, cpusize);
- if ( local == NULL )
+ HYPERCALL_BOUNCE_SET_SIZE(cpumap_hard_inout, cpusize);
+ HYPERCALL_BOUNCE_SET_SIZE(cpumap_soft_inout, cpusize);
+
+ if ( xc_hypercall_bounce_pre(xch, cpumap_hard_inout) ||
+ xc_hypercall_bounce_pre(xch, cpumap_soft_inout) )
{
- PERROR("Could not allocate memory for setvcpuaffinity domctl hypercall");
+ PERROR("Could not allocate hcall buffers for DOMCTL_setvcpuaffinity");
goto out;
}
domctl.cmd = XEN_DOMCTL_setvcpuaffinity;
domctl.domain = (domid_t)domid;
- domctl.u.vcpuaffinity.vcpu = vcpu;
-
- memcpy(local, cpumap, cpusize);
-
- set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap.bitmap, local);
+ domctl.u.vcpuaffinity.vcpu = vcpu;
+ domctl.u.vcpuaffinity.flags = flags;
- domctl.u.vcpuaffinity.cpumap.nr_bits = cpusize * 8;
+ set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap_hard.bitmap,
+ cpumap_hard_inout);
+ domctl.u.vcpuaffinity.cpumap_hard.nr_bits = cpusize * 8;
+ set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap_soft.bitmap,
+ cpumap_soft_inout);
+ domctl.u.vcpuaffinity.cpumap_soft.nr_bits = cpusize * 8;
ret = do_domctl(xch, &domctl);
- xc_hypercall_buffer_free(xch, local);
-
out:
+ xc_hypercall_bounce_post(xch, cpumap_hard_inout);
+ xc_hypercall_bounce_post(xch, cpumap_soft_inout);
+
return ret;
}
@@ -245,10 +286,13 @@ int xc_vcpu_setaffinity(xc_interface *xch,
int xc_vcpu_getaffinity(xc_interface *xch,
uint32_t domid,
int vcpu,
- xc_cpumap_t cpumap)
+ xc_cpumap_t cpumap_hard,
+ xc_cpumap_t cpumap_soft,
+ uint32_t flags)
{
DECLARE_DOMCTL;
- DECLARE_HYPERCALL_BUFFER(uint8_t, local);
+ DECLARE_HYPERCALL_BOUNCE(cpumap_hard, 0, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+ DECLARE_HYPERCALL_BOUNCE(cpumap_soft, 0, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
int ret = -1;
int cpusize;
@@ -256,29 +300,37 @@ int xc_vcpu_getaffinity(xc_interface *xch,
if (cpusize <= 0)
{
PERROR("Could not get number of cpus");
- goto out;
+ return -1;
}
- local = xc_hypercall_buffer_alloc(xch, local, cpusize);
- if (local == NULL)
+ HYPERCALL_BOUNCE_SET_SIZE(cpumap_hard, cpusize);
+ HYPERCALL_BOUNCE_SET_SIZE(cpumap_soft, cpusize);
+
+ if ( xc_hypercall_bounce_pre(xch, cpumap_hard) ||
+ xc_hypercall_bounce_pre(xch, cpumap_soft) )
{
- PERROR("Could not allocate memory for getvcpuaffinity domctl hypercall");
+ PERROR("Could not allocate hcall buffers for DOMCTL_getvcpuaffinity");
goto out;
}
domctl.cmd = XEN_DOMCTL_getvcpuaffinity;
domctl.domain = (domid_t)domid;
domctl.u.vcpuaffinity.vcpu = vcpu;
+ domctl.u.vcpuaffinity.flags = flags;
- set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap.bitmap, local);
- domctl.u.vcpuaffinity.cpumap.nr_bits = cpusize * 8;
+ set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap_hard.bitmap,
+ cpumap_hard);
+ domctl.u.vcpuaffinity.cpumap_hard.nr_bits = cpusize * 8;
+ set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap_soft.bitmap,
+ cpumap_soft);
+ domctl.u.vcpuaffinity.cpumap_soft.nr_bits = cpusize * 8;
ret = do_domctl(xch, &domctl);
- memcpy(cpumap, local, cpusize);
+ out:
+ xc_hypercall_bounce_post(xch, cpumap_hard);
+ xc_hypercall_bounce_post(xch, cpumap_soft);
- xc_hypercall_buffer_free(xch, local);
-out:
return ret;
}
@@ -326,6 +378,7 @@ int xc_domain_getinfo(xc_interface *xch,
info->running = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_running);
info->hvm = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_hvm_guest);
info->debugged = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_debugged);
+ info->pvh = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_pvh_guest);
info->shutdown_reason =
(domctl.u.getdomaininfo.flags>>XEN_DOMINF_shutdownshift) &
@@ -1242,7 +1295,7 @@ int xc_domain_send_trigger(xc_interface *xch,
return do_domctl(xch, &domctl);
}
-int xc_set_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long value)
+int xc_hvm_param_set(xc_interface *handle, domid_t dom, uint32_t param, uint64_t value)
{
DECLARE_HYPERCALL;
DECLARE_HYPERCALL_BUFFER(xen_hvm_param_t, arg);
@@ -1263,7 +1316,7 @@ int xc_set_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long
return rc;
}
-int xc_get_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long *value)
+int xc_hvm_param_get(xc_interface *handle, domid_t dom, uint32_t param, uint64_t *value)
{
DECLARE_HYPERCALL;
DECLARE_HYPERCALL_BUFFER(xen_hvm_param_t, arg);
@@ -1284,6 +1337,276 @@ int xc_get_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long
return rc;
}
+int xc_set_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long value)
+{
+ return xc_hvm_param_set(handle, dom, param, value);
+}
+
+int xc_get_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long *value)
+{
+ uint64_t v;
+ int ret;
+
+ ret = xc_hvm_param_get(handle, dom, param, &v);
+ if (ret < 0)
+ return ret;
+ *value = v;
+ return 0;
+}
+
+int xc_hvm_create_ioreq_server(xc_interface *xch,
+ domid_t domid,
+ int handle_bufioreq,
+ ioservid_t *id)
+{
+ DECLARE_HYPERCALL;
+ DECLARE_HYPERCALL_BUFFER(xen_hvm_create_ioreq_server_t, arg);
+ int rc;
+
+ arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
+ if ( arg == NULL )
+ return -1;
+
+ hypercall.op = __HYPERVISOR_hvm_op;
+ hypercall.arg[0] = HVMOP_create_ioreq_server;
+ hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
+
+ arg->domid = domid;
+ arg->handle_bufioreq = !!handle_bufioreq;
+
+ rc = do_xen_hypercall(xch, &hypercall);
+
+ *id = arg->id;
+
+ xc_hypercall_buffer_free(xch, arg);
+ return rc;
+}
+
+int xc_hvm_get_ioreq_server_info(xc_interface *xch,
+ domid_t domid,
+ ioservid_t id,
+ xen_pfn_t *ioreq_pfn,
+ xen_pfn_t *bufioreq_pfn,
+ evtchn_port_t *bufioreq_port)
+{
+ DECLARE_HYPERCALL;
+ DECLARE_HYPERCALL_BUFFER(xen_hvm_get_ioreq_server_info_t, arg);
+ int rc;
+
+ arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
+ if ( arg == NULL )
+ return -1;
+
+ hypercall.op = __HYPERVISOR_hvm_op;
+ hypercall.arg[0] = HVMOP_get_ioreq_server_info;
+ hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
+
+ arg->domid = domid;
+ arg->id = id;
+
+ rc = do_xen_hypercall(xch, &hypercall);
+ if ( rc != 0 )
+ goto done;
+
+ if ( ioreq_pfn )
+ *ioreq_pfn = arg->ioreq_pfn;
+
+ if ( bufioreq_pfn )
+ *bufioreq_pfn = arg->bufioreq_pfn;
+
+ if ( bufioreq_port )
+ *bufioreq_port = arg->bufioreq_port;
+
+done:
+ xc_hypercall_buffer_free(xch, arg);
+ return rc;
+}
+
+int xc_hvm_map_io_range_to_ioreq_server(xc_interface *xch, domid_t domid,
+ ioservid_t id, int is_mmio,
+ uint64_t start, uint64_t end)
+{
+ DECLARE_HYPERCALL;
+ DECLARE_HYPERCALL_BUFFER(xen_hvm_io_range_t, arg);
+ int rc;
+
+ arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
+ if ( arg == NULL )
+ return -1;
+
+ hypercall.op = __HYPERVISOR_hvm_op;
+ hypercall.arg[0] = HVMOP_map_io_range_to_ioreq_server;
+ hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
+
+ arg->domid = domid;
+ arg->id = id;
+ arg->type = is_mmio ? HVMOP_IO_RANGE_MEMORY : HVMOP_IO_RANGE_PORT;
+ arg->start = start;
+ arg->end = end;
+
+ rc = do_xen_hypercall(xch, &hypercall);
+
+ xc_hypercall_buffer_free(xch, arg);
+ return rc;
+}
+
+int xc_hvm_unmap_io_range_from_ioreq_server(xc_interface *xch, domid_t domid,
+ ioservid_t id, int is_mmio,
+ uint64_t start, uint64_t end)
+{
+ DECLARE_HYPERCALL;
+ DECLARE_HYPERCALL_BUFFER(xen_hvm_io_range_t, arg);
+ int rc;
+
+ arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
+ if ( arg == NULL )
+ return -1;
+
+ hypercall.op = __HYPERVISOR_hvm_op;
+ hypercall.arg[0] = HVMOP_unmap_io_range_from_ioreq_server;
+ hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
+
+ arg->domid = domid;
+ arg->id = id;
+ arg->type = is_mmio ? HVMOP_IO_RANGE_MEMORY : HVMOP_IO_RANGE_PORT;
+ arg->start = start;
+ arg->end = end;
+
+ rc = do_xen_hypercall(xch, &hypercall);
+
+ xc_hypercall_buffer_free(xch, arg);
+ return rc;
+}
+
+int xc_hvm_map_pcidev_to_ioreq_server(xc_interface *xch, domid_t domid,
+ ioservid_t id, uint16_t segment,
+ uint8_t bus, uint8_t device,
+ uint8_t function)
+{
+ DECLARE_HYPERCALL;
+ DECLARE_HYPERCALL_BUFFER(xen_hvm_io_range_t, arg);
+ int rc;
+
+ if (device > 0x1f || function > 0x7) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
+ if ( arg == NULL )
+ return -1;
+
+ hypercall.op = __HYPERVISOR_hvm_op;
+ hypercall.arg[0] = HVMOP_map_io_range_to_ioreq_server;
+ hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
+
+ arg->domid = domid;
+ arg->id = id;
+ arg->type = HVMOP_IO_RANGE_PCI;
+
+ /*
+ * The underlying hypercall will deal with ranges of PCI SBDF
+ * but, for simplicity, the API only uses singletons.
+ */
+ arg->start = arg->end = HVMOP_PCI_SBDF((uint64_t)segment,
+ (uint64_t)bus,
+ (uint64_t)device,
+ (uint64_t)function);
+
+ rc = do_xen_hypercall(xch, &hypercall);
+
+ xc_hypercall_buffer_free(xch, arg);
+ return rc;
+}
+
+int xc_hvm_unmap_pcidev_from_ioreq_server(xc_interface *xch, domid_t domid,
+ ioservid_t id, uint16_t segment,
+ uint8_t bus, uint8_t device,
+ uint8_t function)
+{
+ DECLARE_HYPERCALL;
+ DECLARE_HYPERCALL_BUFFER(xen_hvm_io_range_t, arg);
+ int rc;
+
+ if (device > 0x1f || function > 0x7) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
+ if ( arg == NULL )
+ return -1;
+
+ hypercall.op = __HYPERVISOR_hvm_op;
+ hypercall.arg[0] = HVMOP_unmap_io_range_from_ioreq_server;
+ hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
+
+ arg->domid = domid;
+ arg->id = id;
+ arg->type = HVMOP_IO_RANGE_PCI;
+ arg->start = arg->end = HVMOP_PCI_SBDF((uint64_t)segment,
+ (uint64_t)bus,
+ (uint64_t)device,
+ (uint64_t)function);
+
+ rc = do_xen_hypercall(xch, &hypercall);
+
+ xc_hypercall_buffer_free(xch, arg);
+ return rc;
+}
+
+int xc_hvm_destroy_ioreq_server(xc_interface *xch,
+ domid_t domid,
+ ioservid_t id)
+{
+ DECLARE_HYPERCALL;
+ DECLARE_HYPERCALL_BUFFER(xen_hvm_destroy_ioreq_server_t, arg);
+ int rc;
+
+ arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
+ if ( arg == NULL )
+ return -1;
+
+ hypercall.op = __HYPERVISOR_hvm_op;
+ hypercall.arg[0] = HVMOP_destroy_ioreq_server;
+ hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
+
+ arg->domid = domid;
+ arg->id = id;
+
+ rc = do_xen_hypercall(xch, &hypercall);
+
+ xc_hypercall_buffer_free(xch, arg);
+ return rc;
+}
+
+int xc_hvm_set_ioreq_server_state(xc_interface *xch,
+ domid_t domid,
+ ioservid_t id,
+ int enabled)
+{
+ DECLARE_HYPERCALL;
+ DECLARE_HYPERCALL_BUFFER(xen_hvm_set_ioreq_server_state_t, arg);
+ int rc;
+
+ arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
+ if ( arg == NULL )
+ return -1;
+
+ hypercall.op = __HYPERVISOR_hvm_op;
+ hypercall.arg[0] = HVMOP_set_ioreq_server_state;
+ hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
+
+ arg->domid = domid;
+ arg->id = id;
+ arg->enabled = !!enabled;
+
+ rc = do_xen_hypercall(xch, &hypercall);
+
+ xc_hypercall_buffer_free(xch, arg);
+ return rc;
+}
+
int xc_domain_setdebugging(xc_interface *xch,
uint32_t domid,
unsigned int enable)
@@ -1449,16 +1772,22 @@ int xc_domain_bind_pt_irq(
bind->hvm_domid = domid;
bind->irq_type = irq_type;
bind->machine_irq = machine_irq;
- if ( irq_type == PT_IRQ_TYPE_PCI ||
- irq_type == PT_IRQ_TYPE_MSI_TRANSLATE )
+ switch ( irq_type )
{
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
bind->u.pci.bus = bus;
- bind->u.pci.device = device;
+ bind->u.pci.device = device;
bind->u.pci.intx = intx;
- }
- else if ( irq_type == PT_IRQ_TYPE_ISA )
+ break;
+ case PT_IRQ_TYPE_ISA:
bind->u.isa.isa_irq = isa_irq;
-
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
rc = do_domctl(xch, &domctl);
return rc;
}
@@ -1484,11 +1813,22 @@ int xc_domain_unbind_pt_irq(
bind->hvm_domid = domid;
bind->irq_type = irq_type;
bind->machine_irq = machine_irq;
- bind->u.pci.bus = bus;
- bind->u.pci.device = device;
- bind->u.pci.intx = intx;
- bind->u.isa.isa_irq = isa_irq;
-
+ switch ( irq_type )
+ {
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
+ bind->u.pci.bus = bus;
+ bind->u.pci.device = device;
+ bind->u.pci.intx = intx;
+ break;
+ case PT_IRQ_TYPE_ISA:
+ bind->u.isa.isa_irq = isa_irq;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
rc = do_domctl(xch, &domctl);
return rc;
}
@@ -1518,12 +1858,13 @@ int xc_domain_bind_pt_isa_irq(
int xc_unmap_domain_meminfo(xc_interface *xch, struct xc_domain_meminfo *minfo)
{
- struct domain_info_context _di = { .guest_width = minfo->guest_width };
+ struct domain_info_context _di = { .guest_width = minfo->guest_width,
+ .p2m_size = minfo->p2m_size};
struct domain_info_context *dinfo = &_di;
free(minfo->pfn_type);
if ( minfo->p2m_table )
- munmap(minfo->p2m_table, P2M_FLL_ENTRIES * PAGE_SIZE);
+ munmap(minfo->p2m_table, P2M_FL_ENTRIES * PAGE_SIZE);
minfo->p2m_table = NULL;
return 0;
@@ -1608,8 +1949,8 @@ int xc_map_domain_meminfo(xc_interface *xch, int domid,
goto failed;
}
for ( i = 0; i < minfo->p2m_size; i++ )
- minfo->pfn_type[i] = pfn_to_mfn(i, minfo->p2m_table,
- minfo->guest_width);
+ minfo->pfn_type[i] = xc_pfn_to_mfn(i, minfo->p2m_table,
+ minfo->guest_width);
/* Retrieve PFN types in batches */
for ( i = 0; i < minfo->p2m_size ; i+=1024 )
@@ -1634,7 +1975,7 @@ failed:
}
if ( minfo->p2m_table )
{
- munmap(minfo->p2m_table, P2M_FLL_ENTRIES * PAGE_SIZE);
+ munmap(minfo->p2m_table, P2M_FL_ENTRIES * PAGE_SIZE);
minfo->p2m_table = NULL;
}
@@ -1650,6 +1991,16 @@ int xc_domain_memory_mapping(
uint32_t add_mapping)
{
DECLARE_DOMCTL;
+ xc_dominfo_t info;
+
+ if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 ||
+ info.domid != domid )
+ {
+ PERROR("Could not get info for domain");
+ return -EINVAL;
+ }
+ if ( !xc_core_arch_auto_translated_physmap(&info) )
+ return 0;
domctl.cmd = XEN_DOMCTL_memory_mapping;
domctl.domain = domid;
@@ -1814,6 +2165,74 @@ int xc_domain_set_max_evtchn(xc_interface *xch, uint32_t domid,
return do_domctl(xch, &domctl);
}
+/* Plumbing Xen with vNUMA topology */
+int xc_domain_setvnuma(xc_interface *xch,
+ uint32_t domid,
+ uint32_t nr_vnodes,
+ uint32_t nr_vmemranges,
+ uint32_t nr_vcpus,
+ xen_vmemrange_t *vmemrange,
+ unsigned int *vdistance,
+ unsigned int *vcpu_to_vnode,
+ unsigned int *vnode_to_pnode)
+{
+ int rc;
+ DECLARE_DOMCTL;
+ DECLARE_HYPERCALL_BOUNCE(vmemrange, sizeof(*vmemrange) * nr_vmemranges,
+ XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
+ DECLARE_HYPERCALL_BOUNCE(vdistance, sizeof(*vdistance) *
+ nr_vnodes * nr_vnodes,
+ XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
+ DECLARE_HYPERCALL_BOUNCE(vcpu_to_vnode, sizeof(*vcpu_to_vnode) * nr_vcpus,
+ XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
+ DECLARE_HYPERCALL_BOUNCE(vnode_to_pnode, sizeof(*vnode_to_pnode) *
+ nr_vnodes,
+ XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
+ errno = EINVAL;
+
+ if ( nr_vnodes == 0 || nr_vmemranges == 0 ||
+ nr_vmemranges < nr_vnodes || nr_vcpus == 0 )
+ return -1;
+
+ if ( !vdistance || !vcpu_to_vnode || !vmemrange || !vnode_to_pnode )
+ {
+ PERROR("%s: Cant set vnuma without initializing topology", __func__);
+ return -1;
+ }
+
+ if ( xc_hypercall_bounce_pre(xch, vmemrange) ||
+ xc_hypercall_bounce_pre(xch, vdistance) ||
+ xc_hypercall_bounce_pre(xch, vcpu_to_vnode) ||
+ xc_hypercall_bounce_pre(xch, vnode_to_pnode) )
+ {
+ rc = -1;
+ goto vnumaset_fail;
+
+ }
+
+ set_xen_guest_handle(domctl.u.vnuma.vmemrange, vmemrange);
+ set_xen_guest_handle(domctl.u.vnuma.vdistance, vdistance);
+ set_xen_guest_handle(domctl.u.vnuma.vcpu_to_vnode, vcpu_to_vnode);
+ set_xen_guest_handle(domctl.u.vnuma.vnode_to_pnode, vnode_to_pnode);
+
+ domctl.cmd = XEN_DOMCTL_setvnumainfo;
+ domctl.domain = (domid_t)domid;
+ domctl.u.vnuma.nr_vnodes = nr_vnodes;
+ domctl.u.vnuma.nr_vmemranges = nr_vmemranges;
+ domctl.u.vnuma.nr_vcpus = nr_vcpus;
+ domctl.u.vnuma.pad = 0;
+
+ rc = do_domctl(xch, &domctl);
+
+ vnumaset_fail:
+ xc_hypercall_bounce_post(xch, vmemrange);
+ xc_hypercall_bounce_post(xch, vdistance);
+ xc_hypercall_bounce_post(xch, vcpu_to_vnode);
+ xc_hypercall_bounce_post(xch, vnode_to_pnode);
+
+ return rc;
+}
+
/*
* Local variables:
* mode: C
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
index 1f6ce50..d8bd9b3 100644
--- a/tools/libxc/xc_domain_restore.c
+++ b/tools/libxc/xc_domain_restore.c
@@ -38,6 +38,7 @@
#include <stdlib.h>
#include <unistd.h>
+#include <inttypes.h>
#include "xg_private.h"
#include "xg_save_restore.h"
@@ -101,7 +102,7 @@ static ssize_t rdexact(xc_interface *xch, struct restore_ctx *ctx,
errno = 0;
}
if ( len <= 0 ) {
- ERROR("%s failed (read rc: %d, errno: %d)", __func__, len, errno);
+ ERROR("%s failed (read rc: %zd, errno: %d)", __func__, len, errno);
return -1;
}
offset += len;
@@ -248,7 +249,7 @@ static int uncanonicalize_pagetable(
static xen_pfn_t *load_p2m_frame_list(
xc_interface *xch, struct restore_ctx *ctx,
int io_fd, int *pae_extended_cr3, int *ext_vcpucontext,
- int *vcpuextstate, uint32_t *vcpuextstate_size)
+ uint32_t *vcpuextstate_size)
{
xen_pfn_t *p2m_frame_list;
vcpu_guest_context_any_t ctxt;
@@ -316,7 +317,7 @@ static xen_pfn_t *load_p2m_frame_list(
tot_bytes -= chunk_bytes;
chunk_bytes = 0;
- if ( GET_FIELD(&ctxt, vm_assist)
+ if ( GET_FIELD(&ctxt, vm_assist, dinfo->guest_width)
& (1UL << VMASST_TYPE_pae_extended_cr3) )
*pae_extended_cr3 = 1;
}
@@ -326,7 +327,6 @@ static xen_pfn_t *load_p2m_frame_list(
}
else if ( !strncmp(chunk_sig, "xcnt", 4) )
{
- *vcpuextstate = 1;
if ( RDEXACT(io_fd, vcpuextstate_size, sizeof(*vcpuextstate_size)) )
{
PERROR("read extended vcpu state size failed");
@@ -339,7 +339,7 @@ static xen_pfn_t *load_p2m_frame_list(
/* Any remaining bytes of this chunk: read and discard. */
while ( chunk_bytes )
{
- unsigned long sz = MIN(chunk_bytes, sizeof(xen_pfn_t));
+ unsigned long sz = min_t(unsigned long, chunk_bytes, sizeof(xen_pfn_t));
if ( RDEXACT(io_fd, &p2m_fl_zero, sz) )
{
PERROR("read-and-discard extended-info chunk bytes failed");
@@ -443,7 +443,7 @@ static int compat_buffer_qemu(xc_interface *xch, struct restore_ctx *ctx,
}
if ( memcmp(qbuf, "QEVM", 4) ) {
- ERROR("Invalid QEMU magic: 0x%08x", *(unsigned long*)qbuf);
+ ERROR("Invalid QEMU magic: 0x%08"PRIx32, *(uint32_t*)qbuf);
free(qbuf);
return -1;
}
@@ -520,7 +520,7 @@ static int buffer_tail_hvm(xc_interface *xch, struct restore_ctx *ctx,
struct tailbuf_hvm *buf, int fd,
unsigned int max_vcpu_id, uint64_t *vcpumap,
int ext_vcpucontext,
- int vcpuextstate, uint32_t vcpuextstate_size)
+ uint32_t vcpuextstate_size)
{
uint8_t *tmp;
unsigned char qemusig[21];
@@ -588,7 +588,6 @@ static int buffer_tail_pv(xc_interface *xch, struct restore_ctx *ctx,
struct tailbuf_pv *buf, int fd,
unsigned int max_vcpu_id, uint64_t *vcpumap,
int ext_vcpucontext,
- int vcpuextstate,
uint32_t vcpuextstate_size)
{
unsigned int i;
@@ -629,9 +628,7 @@ static int buffer_tail_pv(xc_interface *xch, struct restore_ctx *ctx,
: sizeof(vcpu_guest_context_x86_32_t)) * buf->vcpucount;
if ( ext_vcpucontext )
vcpulen += 128 * buf->vcpucount;
- if ( vcpuextstate ) {
- vcpulen += vcpuextstate_size * buf->vcpucount;
- }
+ vcpulen += vcpuextstate_size * buf->vcpucount;
if ( !(buf->vcpubuf) ) {
if ( !(buf->vcpubuf = malloc(vcpulen)) ) {
@@ -671,16 +668,14 @@ static int buffer_tail_pv(xc_interface *xch, struct restore_ctx *ctx,
static int buffer_tail(xc_interface *xch, struct restore_ctx *ctx,
tailbuf_t *buf, int fd, unsigned int max_vcpu_id,
uint64_t *vcpumap, int ext_vcpucontext,
- int vcpuextstate, uint32_t vcpuextstate_size)
+ uint32_t vcpuextstate_size)
{
if ( buf->ishvm )
return buffer_tail_hvm(xch, ctx, &buf->u.hvm, fd, max_vcpu_id, vcpumap,
- ext_vcpucontext, vcpuextstate,
- vcpuextstate_size);
+ ext_vcpucontext, vcpuextstate_size);
else
return buffer_tail_pv(xch, ctx, &buf->u.pv, fd, max_vcpu_id, vcpumap,
- ext_vcpucontext, vcpuextstate,
- vcpuextstate_size);
+ ext_vcpucontext, vcpuextstate_size);
}
static void tailbuf_free_hvm(struct tailbuf_hvm *buf)
@@ -746,6 +741,8 @@ typedef struct {
uint64_t acpi_ioport_location;
uint64_t viridian;
uint64_t vm_generationid_addr;
+ uint64_t ioreq_server_pfn;
+ uint64_t nr_ioreq_server_pages;
struct toolstack_data_t tdata;
} pagebuf_t;
@@ -925,7 +922,7 @@ static int pagebuf_get_one(xc_interface *xch, struct restore_ctx *ctx,
if ( RDEXACT(fd, &buf->viridian, sizeof(uint32_t)) ||
RDEXACT(fd, &buf->viridian, sizeof(uint64_t)) )
{
- PERROR("error read the viridian flag");
+ PERROR("error reading the viridian enlightenments");
return -1;
}
return pagebuf_get_one(xch, ctx, buf, fd, dom);
@@ -996,6 +993,26 @@ static int pagebuf_get_one(xc_interface *xch, struct restore_ctx *ctx,
DPRINTF("read generation id buffer address");
return pagebuf_get_one(xch, ctx, buf, fd, dom);
+ case XC_SAVE_ID_HVM_IOREQ_SERVER_PFN:
+ /* Skip padding 4 bytes then read the ioreq server gmfn base. */
+ if ( RDEXACT(fd, &buf->ioreq_server_pfn, sizeof(uint32_t)) ||
+ RDEXACT(fd, &buf->ioreq_server_pfn, sizeof(uint64_t)) )
+ {
+ PERROR("error read the ioreq server gmfn base");
+ return -1;
+ }
+ return pagebuf_get_one(xch, ctx, buf, fd, dom);
+
+ case XC_SAVE_ID_HVM_NR_IOREQ_SERVER_PAGES:
+ /* Skip padding 4 bytes then read the ioreq server gmfn count. */
+ if ( RDEXACT(fd, &buf->nr_ioreq_server_pages, sizeof(uint32_t)) ||
+ RDEXACT(fd, &buf->nr_ioreq_server_pages, sizeof(uint64_t)) )
+ {
+ PERROR("error read the ioreq server gmfn count");
+ return -1;
+ }
+ return pagebuf_get_one(xch, ctx, buf, fd, dom);
+
default:
if ( (count > MAX_BATCH_SIZE) || (count < 0) ) {
ERROR("Max batch size exceeded (%d). Giving up.", count);
@@ -1089,7 +1106,7 @@ static int pagebuf_get(xc_interface *xch, struct restore_ctx *ctx,
static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
xen_pfn_t* region_mfn, unsigned long* pfn_type, int pae_extended_cr3,
struct xc_mmu* mmu,
- pagebuf_t* pagebuf, int curbatch)
+ pagebuf_t* pagebuf, int curbatch, int *invalid_pages)
{
int i, j, curpage, nr_mfns;
int k, scount;
@@ -1104,6 +1121,12 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
struct domain_info_context *dinfo = &ctx->dinfo;
int* pfn_err = NULL;
int rc = -1;
+ int local_invalid_pages = 0;
+ /* We have handled curbatch pages before this batch, and there are
+ * *invalid_pages pages that are not in pagebuf->pages. So the first
+ * page for this page is (curbatch - *invalid_pages) page.
+ */
+ int first_page = curbatch - *invalid_pages;
unsigned long mfn, pfn, pagetype;
@@ -1276,10 +1299,13 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
pfn = pagebuf->pfn_types[i + curbatch] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
pagetype = pagebuf->pfn_types[i + curbatch] & XEN_DOMCTL_PFINFO_LTAB_MASK;
- if ( pagetype == XEN_DOMCTL_PFINFO_XTAB
+ if ( pagetype == XEN_DOMCTL_PFINFO_XTAB
|| pagetype == XEN_DOMCTL_PFINFO_XALLOC)
+ {
+ local_invalid_pages++;
/* a bogus/unmapped/allocate-only page: skip it */
continue;
+ }
if ( pagetype == XEN_DOMCTL_PFINFO_BROKEN )
{
@@ -1289,6 +1315,8 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
"dom=%d, pfn=%lx\n", dom, pfn);
goto err_mapped;
}
+
+ local_invalid_pages++;
continue;
}
@@ -1327,7 +1355,7 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
}
}
else
- memcpy(page, pagebuf->pages + (curpage + curbatch) * PAGE_SIZE,
+ memcpy(page, pagebuf->pages + (first_page + curpage) * PAGE_SIZE,
PAGE_SIZE);
pagetype &= XEN_DOMCTL_PFINFO_LTABTYPE_MASK;
@@ -1377,7 +1405,7 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
DPRINTF("************** pfn=%lx type=%lx gotcs=%08lx "
"actualcs=%08lx\n", pfn, pagebuf->pfn_types[pfn],
- csum_page(region_base + (i + curbatch)*PAGE_SIZE),
+ csum_page(region_base + i * PAGE_SIZE),
csum_page(buf));
for ( v = 0; v < 4; v++ )
@@ -1401,6 +1429,7 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
} /* end of 'batch' for loop */
rc = nraces;
+ *invalid_pages += local_invalid_pages;
err_mapped:
munmap(region_base, j*PAGE_SIZE);
@@ -1414,14 +1443,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
domid_t store_domid, unsigned int console_evtchn,
unsigned long *console_mfn, domid_t console_domid,
unsigned int hvm, unsigned int pae, int superpages,
- int no_incr_generationid, int checkpointed_stream,
- unsigned long *vm_generationid_addr,
+ int checkpointed_stream,
struct restore_callbacks *callbacks)
{
DECLARE_DOMCTL;
xc_dominfo_t info;
int rc = 1, frc, i, j, n, m, pae_extended_cr3 = 0, ext_vcpucontext = 0;
- int vcpuextstate = 0;
uint32_t vcpuextstate_size = 0;
unsigned long mfn, pfn;
int nraces = 0;
@@ -1527,7 +1554,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
/* Load the p2m frame list, plus potential extended info chunk */
p2m_frame_list = load_p2m_frame_list(xch, ctx,
io_fd, &pae_extended_cr3, &ext_vcpucontext,
- &vcpuextstate, &vcpuextstate_size);
+ &vcpuextstate_size);
if ( !p2m_frame_list )
goto out;
@@ -1606,7 +1633,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
loadpages:
for ( ; ; )
{
- int j, curbatch;
+ int j, curbatch, invalid_pages;
xc_report_progress_step(xch, n, dinfo->p2m_size);
@@ -1630,66 +1657,33 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
}
/* should this be deferred? does it change? */
if ( pagebuf.identpt )
- xc_set_hvm_param(xch, dom, HVM_PARAM_IDENT_PT, pagebuf.identpt);
+ xc_hvm_param_set(xch, dom, HVM_PARAM_IDENT_PT, pagebuf.identpt);
if ( pagebuf.paging_ring_pfn )
- xc_set_hvm_param(xch, dom, HVM_PARAM_PAGING_RING_PFN, pagebuf.paging_ring_pfn);
+ xc_hvm_param_set(xch, dom, HVM_PARAM_PAGING_RING_PFN, pagebuf.paging_ring_pfn);
if ( pagebuf.access_ring_pfn )
- xc_set_hvm_param(xch, dom, HVM_PARAM_ACCESS_RING_PFN, pagebuf.access_ring_pfn);
+ xc_hvm_param_set(xch, dom, HVM_PARAM_ACCESS_RING_PFN, pagebuf.access_ring_pfn);
if ( pagebuf.sharing_ring_pfn )
- xc_set_hvm_param(xch, dom, HVM_PARAM_SHARING_RING_PFN, pagebuf.sharing_ring_pfn);
+ xc_hvm_param_set(xch, dom, HVM_PARAM_SHARING_RING_PFN, pagebuf.sharing_ring_pfn);
if ( pagebuf.vm86_tss )
- xc_set_hvm_param(xch, dom, HVM_PARAM_VM86_TSS, pagebuf.vm86_tss);
+ xc_hvm_param_set(xch, dom, HVM_PARAM_VM86_TSS, pagebuf.vm86_tss);
if ( pagebuf.console_pfn )
console_pfn = pagebuf.console_pfn;
- if ( pagebuf.vm_generationid_addr ) {
- if ( !no_incr_generationid ) {
- unsigned int offset;
- unsigned char *buf;
- unsigned long long generationid;
-
- /*
- * Map the VM generation id buffer and inject the new value.
- */
-
- pfn = pagebuf.vm_generationid_addr >> PAGE_SHIFT;
- offset = pagebuf.vm_generationid_addr & (PAGE_SIZE - 1);
-
- if ( (pfn >= dinfo->p2m_size) ||
- (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB) )
- {
- ERROR("generation id buffer frame is bad");
- goto out;
- }
-
- mfn = ctx->p2m[pfn];
- buf = xc_map_foreign_range(xch, dom, PAGE_SIZE,
- PROT_READ | PROT_WRITE, mfn);
- if ( buf == NULL )
- {
- ERROR("xc_map_foreign_range for generation id"
- " buffer failed");
- goto out;
- }
-
- generationid = *(unsigned long long *)(buf + offset);
- *(unsigned long long *)(buf + offset) = generationid + 1;
-
- munmap(buf, PAGE_SIZE);
- }
-
- *vm_generationid_addr = pagebuf.vm_generationid_addr;
- }
+ if ( pagebuf.vm_generationid_addr )
+ xc_hvm_param_set(xch, dom, HVM_PARAM_VM_GENERATION_ID_ADDR,
+ pagebuf.vm_generationid_addr);
break; /* our work here is done */
}
/* break pagebuf into batches */
curbatch = 0;
+ invalid_pages = 0;
while ( curbatch < j ) {
int brc;
brc = apply_batch(xch, dom, ctx, region_mfn, pfn_type,
- pae_extended_cr3, mmu, &pagebuf, curbatch);
+ pae_extended_cr3, mmu, &pagebuf, curbatch,
+ &invalid_pages);
if ( brc < 0 )
goto out;
@@ -1730,7 +1724,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
if ( !ctx->completed ) {
if ( buffer_tail(xch, ctx, &tailbuf, io_fd, max_vcpu_id, vcpumap,
- ext_vcpucontext, vcpuextstate, vcpuextstate_size) < 0 ) {
+ ext_vcpucontext, vcpuextstate_size) < 0 ) {
ERROR ("error buffering image tail");
goto out;
}
@@ -1753,15 +1747,40 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
}
if (pagebuf.viridian != 0)
- xc_set_hvm_param(xch, dom, HVM_PARAM_VIRIDIAN, 1);
+ xc_hvm_param_set(xch, dom, HVM_PARAM_VIRIDIAN, pagebuf.viridian);
+
+ /*
+ * If we are migrating in from a host that does not support
+ * secondary emulators then nr_ioreq_server_pages will be 0, since
+ * there will be no XC_SAVE_ID_HVM_NR_IOREQ_SERVER_PAGES chunk in
+ * the image.
+ * If we are migrating from a host that does support secondary
+ * emulators then the XC_SAVE_ID_HVM_NR_IOREQ_SERVER_PAGES chunk
+ * will exist and is guaranteed to have a non-zero value. The
+ * existence of that chunk also implies the existence of the
+ * XC_SAVE_ID_HVM_IOREQ_SERVER_PFN chunk, which is also guaranteed
+ * to have a non-zero value.
+ */
+ if (!pagebuf.nr_ioreq_server_pages ^ !pagebuf.ioreq_server_pfn) {
+ ERROR("Inconsistent IOREQ Server settings (nr=%"PRIx64", pfn=%"PRIx64")",
+ pagebuf.nr_ioreq_server_pages, pagebuf.ioreq_server_pfn);
+ } else {
+ if (pagebuf.nr_ioreq_server_pages != 0 &&
+ pagebuf.ioreq_server_pfn != 0) {
+ xc_hvm_param_set(xch, dom, HVM_PARAM_NR_IOREQ_SERVER_PAGES,
+ pagebuf.nr_ioreq_server_pages);
+ xc_hvm_param_set(xch, dom, HVM_PARAM_IOREQ_SERVER_PFN,
+ pagebuf.ioreq_server_pfn);
+ }
+ }
if (pagebuf.acpi_ioport_location == 1) {
DBGPRINTF("Use new firmware ioport from the checkpoint\n");
- xc_set_hvm_param(xch, dom, HVM_PARAM_ACPI_IOPORTS_LOCATION, 1);
+ xc_hvm_param_set(xch, dom, HVM_PARAM_ACPI_IOPORTS_LOCATION, 1);
} else if (pagebuf.acpi_ioport_location == 0) {
DBGPRINTF("Use old firmware ioport from the checkpoint\n");
} else {
- ERROR("Error, unknow acpi ioport location (%i)", pagebuf.acpi_ioport_location);
+ ERROR("Error, unknow acpi ioport location (%"PRId64")", pagebuf.acpi_ioport_location);
}
tdatatmp = tdata;
@@ -1778,20 +1797,29 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
if ( pagebuf_get(xch, ctx, &pagebuf, io_fd, dom) ) {
PERROR("error when buffering batch, finishing");
- goto out;
+ /*
+ * Remus: discard the current incomplete checkpoint and restore
+ * backup from the last complete checkpoint.
+ */
+ goto finish;
}
memset(&tmptail, 0, sizeof(tmptail));
tmptail.ishvm = hvm;
if ( buffer_tail(xch, ctx, &tmptail, io_fd, max_vcpu_id, vcpumap,
- ext_vcpucontext, vcpuextstate, vcpuextstate_size) < 0 ) {
+ ext_vcpucontext, vcpuextstate_size) < 0 ) {
ERROR ("error buffering image tail, finishing");
- goto out;
+ /*
+ * Remus: discard the current incomplete checkpoint and restore
+ * backup from the last complete checkpoint.
+ */
+ goto finish;
}
tailbuf_free(&tailbuf);
memcpy(&tailbuf, &tmptail, sizeof(tailbuf));
goto loadpages;
+ /* With Remus: restore from last complete checkpoint */
finish:
if ( hvm )
goto finish_hvm;
@@ -2013,7 +2041,9 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
DPRINTF("read VCPU %d\n", i);
if ( !new_ctxt_format )
- SET_FIELD(ctxt, flags, GET_FIELD(ctxt, flags) | VGCF_online);
+ SET_FIELD(ctxt, flags,
+ GET_FIELD(ctxt, flags, dinfo->guest_width) | VGCF_online,
+ dinfo->guest_width);
if ( i == 0 )
{
@@ -2027,7 +2057,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
* xc_domain_save and therefore the PFN is found in the
* edx register.
*/
- pfn = GET_FIELD(ctxt, user_regs.edx);
+ pfn = GET_FIELD(ctxt, user_regs.edx, dinfo->guest_width);
if ( (pfn >= dinfo->p2m_size) ||
(pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB) )
{
@@ -2035,7 +2065,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
goto out;
}
mfn = ctx->p2m[pfn];
- SET_FIELD(ctxt, user_regs.edx, mfn);
+ SET_FIELD(ctxt, user_regs.edx, mfn, dinfo->guest_width);
start_info = xc_map_foreign_range(
xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
if ( start_info == NULL )
@@ -2044,39 +2074,39 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
goto out;
}
- SET_FIELD(start_info, nr_pages, dinfo->p2m_size);
- SET_FIELD(start_info, shared_info, shared_info_frame<<PAGE_SHIFT);
- SET_FIELD(start_info, flags, 0);
- if ( GET_FIELD(start_info, store_mfn) > dinfo->p2m_size )
+ SET_FIELD(start_info, nr_pages, dinfo->p2m_size, dinfo->guest_width);
+ SET_FIELD(start_info, shared_info, shared_info_frame<<PAGE_SHIFT, dinfo->guest_width);
+ SET_FIELD(start_info, flags, 0, dinfo->guest_width);
+ if ( GET_FIELD(start_info, store_mfn, dinfo->guest_width) > dinfo->p2m_size )
{
ERROR("Suspend record xenstore frame number is bad");
munmap(start_info, PAGE_SIZE);
goto out;
}
- *store_mfn = ctx->p2m[GET_FIELD(start_info, store_mfn)];
- SET_FIELD(start_info, store_mfn, *store_mfn);
- SET_FIELD(start_info, store_evtchn, store_evtchn);
- if ( GET_FIELD(start_info, console.domU.mfn) > dinfo->p2m_size )
+ *store_mfn = ctx->p2m[GET_FIELD(start_info, store_mfn, dinfo->guest_width)];
+ SET_FIELD(start_info, store_mfn, *store_mfn, dinfo->guest_width);
+ SET_FIELD(start_info, store_evtchn, store_evtchn, dinfo->guest_width);
+ if ( GET_FIELD(start_info, console.domU.mfn, dinfo->guest_width) > dinfo->p2m_size )
{
ERROR("Suspend record console frame number is bad");
munmap(start_info, PAGE_SIZE);
goto out;
}
- *console_mfn = ctx->p2m[GET_FIELD(start_info, console.domU.mfn)];
- SET_FIELD(start_info, console.domU.mfn, *console_mfn);
- SET_FIELD(start_info, console.domU.evtchn, console_evtchn);
+ *console_mfn = ctx->p2m[GET_FIELD(start_info, console.domU.mfn, dinfo->guest_width)];
+ SET_FIELD(start_info, console.domU.mfn, *console_mfn, dinfo->guest_width);
+ SET_FIELD(start_info, console.domU.evtchn, console_evtchn, dinfo->guest_width);
munmap(start_info, PAGE_SIZE);
}
/* Uncanonicalise each GDT frame number. */
- if ( GET_FIELD(ctxt, gdt_ents) > 8192 )
+ if ( GET_FIELD(ctxt, gdt_ents, dinfo->guest_width) > 8192 )
{
ERROR("GDT entry count out of range");
goto out;
}
- for ( j = 0; (512*j) < GET_FIELD(ctxt, gdt_ents); j++ )
+ for ( j = 0; (512*j) < GET_FIELD(ctxt, gdt_ents, dinfo->guest_width); j++ )
{
- pfn = GET_FIELD(ctxt, gdt_frames[j]);
+ pfn = GET_FIELD(ctxt, gdt_frames[j], dinfo->guest_width);
if ( (pfn >= dinfo->p2m_size) ||
(pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB) )
{
@@ -2084,10 +2114,10 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
j, (unsigned long)pfn);
goto out;
}
- SET_FIELD(ctxt, gdt_frames[j], ctx->p2m[pfn]);
+ SET_FIELD(ctxt, gdt_frames[j], ctx->p2m[pfn], dinfo->guest_width);
}
/* Uncanonicalise the page table base pointer. */
- pfn = UNFOLD_CR3(GET_FIELD(ctxt, ctrlreg[3]));
+ pfn = UNFOLD_CR3(GET_FIELD(ctxt, ctrlreg[3], dinfo->guest_width));
if ( pfn >= dinfo->p2m_size )
{
@@ -2104,7 +2134,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
(unsigned long)ctx->pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
goto out;
}
- SET_FIELD(ctxt, ctrlreg[3], FOLD_CR3(ctx->p2m[pfn]));
+ SET_FIELD(ctxt, ctrlreg[3], FOLD_CR3(ctx->p2m[pfn]), dinfo->guest_width);
/* Guest pagetable (x86/64) stored in otherwise-unused CR1. */
if ( (ctx->pt_levels == 4) && (ctxt->x64.ctrlreg[1] & 1) )
@@ -2147,7 +2177,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
}
vcpu_ext_state_restore:
- if ( !vcpuextstate )
+ if ( !vcpuextstate_size )
continue;
memcpy(&domctl.u.vcpuextstate.xfeature_mask, vcpup,
@@ -2194,16 +2224,16 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
}
/* restore saved vcpu_info and arch specific info */
- MEMCPY_FIELD(new_shared_info, old_shared_info, vcpu_info);
- MEMCPY_FIELD(new_shared_info, old_shared_info, arch);
+ MEMCPY_FIELD(new_shared_info, old_shared_info, vcpu_info, dinfo->guest_width);
+ MEMCPY_FIELD(new_shared_info, old_shared_info, arch, dinfo->guest_width);
/* clear any pending events and the selector */
- MEMSET_ARRAY_FIELD(new_shared_info, evtchn_pending, 0);
+ MEMSET_ARRAY_FIELD(new_shared_info, evtchn_pending, 0, dinfo->guest_width);
for ( i = 0; i < XEN_LEGACY_MAX_VCPUS; i++ )
- SET_FIELD(new_shared_info, vcpu_info[i].evtchn_pending_sel, 0);
+ SET_FIELD(new_shared_info, vcpu_info[i].evtchn_pending_sel, 0, dinfo->guest_width);
/* mask event channels */
- MEMSET_ARRAY_FIELD(new_shared_info, evtchn_mask, 0xff);
+ MEMSET_ARRAY_FIELD(new_shared_info, evtchn_mask, 0xff, dinfo->guest_width);
/* leave wallclock time. set by hypervisor */
munmap(new_shared_info, PAGE_SIZE);
@@ -2288,15 +2318,15 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
goto out;
}
- if ( (frc = xc_set_hvm_param(xch, dom,
+ if ( (frc = xc_hvm_param_set(xch, dom,
HVM_PARAM_IOREQ_PFN, tailbuf.u.hvm.magicpfns[0]))
- || (frc = xc_set_hvm_param(xch, dom,
+ || (frc = xc_hvm_param_set(xch, dom,
HVM_PARAM_BUFIOREQ_PFN, tailbuf.u.hvm.magicpfns[1]))
- || (frc = xc_set_hvm_param(xch, dom,
+ || (frc = xc_hvm_param_set(xch, dom,
HVM_PARAM_STORE_PFN, tailbuf.u.hvm.magicpfns[2]))
- || (frc = xc_set_hvm_param(xch, dom,
+ || (frc = xc_hvm_param_set(xch, dom,
HVM_PARAM_PAE_ENABLED, pae))
- || (frc = xc_set_hvm_param(xch, dom,
+ || (frc = xc_hvm_param_set(xch, dom,
HVM_PARAM_STORE_EVTCHN,
store_evtchn)) )
{
@@ -2310,7 +2340,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
PERROR("error zeroing console page");
goto out;
}
- if ( (frc = xc_set_hvm_param(xch, dom,
+ if ( (frc = xc_hvm_param_set(xch, dom,
HVM_PARAM_CONSOLE_PFN, console_pfn)) ) {
PERROR("error setting HVM param: %i", frc);
goto out;
diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
index 42c4752..254fdb3 100644
--- a/tools/libxc/xc_domain_save.c
+++ b/tools/libxc/xc_domain_save.c
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
+#include <assert.h>
#include "xc_private.h"
#include "xc_bitops.h"
@@ -150,6 +151,7 @@ static inline int outbuf_write(xc_interface *xch,
struct outbuf* ob, void* buf, size_t len)
{
if ( len > ob->size - ob->pos ) {
+ errno = ERANGE;
DBGPRINTF("outbuf_write: %zu > %zu@%zu\n", len, ob->size - ob->pos, ob->pos);
return -1;
}
@@ -387,12 +389,12 @@ static void *map_frame_list_list(xc_interface *xch, uint32_t dom,
int count = 100;
void *p;
struct domain_info_context *dinfo = &ctx->dinfo;
- uint64_t fll = GET_FIELD(shinfo, arch.pfn_to_mfn_frame_list_list);
+ uint64_t fll = GET_FIELD(shinfo, arch.pfn_to_mfn_frame_list_list, dinfo->guest_width);
while ( count-- && (fll == 0) )
{
usleep(10000);
- fll = GET_FIELD(shinfo, arch.pfn_to_mfn_frame_list_list);
+ fll = GET_FIELD(shinfo, arch.pfn_to_mfn_frame_list_list, dinfo->guest_width);
}
if ( fll == 0 )
@@ -800,13 +802,12 @@ static int save_tsc_info(xc_interface *xch, uint32_t dom, int io_fd)
int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
uint32_t max_factor, uint32_t flags,
- struct save_callbacks* callbacks, int hvm,
- unsigned long vm_generationid_addr)
+ struct save_callbacks* callbacks, int hvm)
{
xc_dominfo_t info;
DECLARE_DOMCTL;
- int rc = 1, frc, i, j, last_iter = 0, iter = 0;
+ int rc, frc, i, j, last_iter = 0, iter = 0;
int live = (flags & XCFLAGS_LIVE);
int debug = (flags & XCFLAGS_DEBUG);
int superpages = !!hvm;
@@ -899,7 +900,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
{
ERROR("No switch_qemu_logdirty callback provided.");
errno = EINVAL;
- return 1;
+ goto exit;
}
outbuf_init(xch, &ob_pagebuf, OUTBUF_SIZE);
@@ -914,13 +915,13 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
&ctx->max_mfn, &ctx->hvirt_start, &ctx->pt_levels, &dinfo->guest_width) )
{
ERROR("Unable to get platform info.");
- return 1;
+ goto exit;
}
if ( xc_domain_getinfo(xch, dom, 1, &info) != 1 )
{
PERROR("Could not get domain info");
- return 1;
+ goto exit;
}
shared_info_frame = info.shared_info_frame;
@@ -942,6 +943,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( dinfo->p2m_size > ~XEN_DOMCTL_PFINFO_LTAB_MASK )
{
+ errno = E2BIG;
ERROR("Cannot save this big a guest");
goto out;
}
@@ -1012,6 +1014,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( !to_send || !to_fix || !to_skip )
{
+ errno = ENOMEM;
ERROR("Couldn't allocate to_send array");
goto out;
}
@@ -1030,6 +1033,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
hvm_buf = malloc(hvm_buf_size);
if ( !hvm_buf )
{
+ errno = ENOMEM;
ERROR("Couldn't allocate memory");
goto out;
}
@@ -1598,6 +1602,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( info.max_vcpu_id >= XC_SR_MAX_VCPUS )
{
+ errno = E2BIG;
ERROR("Too many VCPUS in guest!");
goto out;
}
@@ -1628,7 +1633,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
} chunk = { 0, };
chunk.id = XC_SAVE_ID_HVM_GENERATION_ID_ADDR;
- chunk.data = vm_generationid_addr;
+ xc_hvm_param_get(xch, dom, HVM_PARAM_VM_GENERATION_ID_ADDR, &chunk.data);
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1639,8 +1644,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
chunk.id = XC_SAVE_ID_HVM_IDENT_PT;
chunk.data = 0;
- xc_get_hvm_param(xch, dom, HVM_PARAM_IDENT_PT,
- (unsigned long *)&chunk.data);
+ xc_hvm_param_get(xch, dom, HVM_PARAM_IDENT_PT, &chunk.data);
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1651,8 +1655,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
chunk.id = XC_SAVE_ID_HVM_PAGING_RING_PFN;
chunk.data = 0;
- xc_get_hvm_param(xch, dom, HVM_PARAM_PAGING_RING_PFN,
- (unsigned long *)&chunk.data);
+ xc_hvm_param_get(xch, dom, HVM_PARAM_PAGING_RING_PFN, &chunk.data);
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1663,8 +1666,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
chunk.id = XC_SAVE_ID_HVM_ACCESS_RING_PFN;
chunk.data = 0;
- xc_get_hvm_param(xch, dom, HVM_PARAM_ACCESS_RING_PFN,
- (unsigned long *)&chunk.data);
+ xc_hvm_param_get(xch, dom, HVM_PARAM_ACCESS_RING_PFN, &chunk.data);
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1675,8 +1677,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
chunk.id = XC_SAVE_ID_HVM_SHARING_RING_PFN;
chunk.data = 0;
- xc_get_hvm_param(xch, dom, HVM_PARAM_SHARING_RING_PFN,
- (unsigned long *)&chunk.data);
+ xc_hvm_param_get(xch, dom, HVM_PARAM_SHARING_RING_PFN, &chunk.data);
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1687,8 +1688,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
chunk.id = XC_SAVE_ID_HVM_VM86_TSS;
chunk.data = 0;
- xc_get_hvm_param(xch, dom, HVM_PARAM_VM86_TSS,
- (unsigned long *)&chunk.data);
+ xc_hvm_param_get(xch, dom, HVM_PARAM_VM86_TSS, &chunk.data);
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1699,8 +1699,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
chunk.id = XC_SAVE_ID_HVM_CONSOLE_PFN;
chunk.data = 0;
- xc_get_hvm_param(xch, dom, HVM_PARAM_CONSOLE_PFN,
- (unsigned long *)&chunk.data);
+ xc_hvm_param_get(xch, dom, HVM_PARAM_CONSOLE_PFN, &chunk.data);
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1711,8 +1710,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
chunk.id = XC_SAVE_ID_HVM_ACPI_IOPORTS_LOCATION;
chunk.data = 0;
- xc_get_hvm_param(xch, dom, HVM_PARAM_ACPI_IOPORTS_LOCATION,
- (unsigned long *)&chunk.data);
+ xc_hvm_param_get(xch, dom, HVM_PARAM_ACPI_IOPORTS_LOCATION, &chunk.data);
if ((chunk.data != 0) && wrexact(io_fd, &chunk, sizeof(chunk)))
{
@@ -1722,8 +1720,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
chunk.id = XC_SAVE_ID_HVM_VIRIDIAN;
chunk.data = 0;
- xc_get_hvm_param(xch, dom, HVM_PARAM_VIRIDIAN,
- (unsigned long *)&chunk.data);
+ xc_hvm_param_get(xch, dom, HVM_PARAM_VIRIDIAN, &chunk.data);
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1731,6 +1728,28 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
PERROR("Error when writing the viridian flag");
goto out;
}
+
+ chunk.id = XC_SAVE_ID_HVM_IOREQ_SERVER_PFN;
+ chunk.data = 0;
+ xc_hvm_param_get(xch, dom, HVM_PARAM_IOREQ_SERVER_PFN, &chunk.data);
+
+ if ( (chunk.data != 0) &&
+ wrexact(io_fd, &chunk, sizeof(chunk)) )
+ {
+ PERROR("Error when writing the ioreq server gmfn base");
+ goto out;
+ }
+
+ chunk.id = XC_SAVE_ID_HVM_NR_IOREQ_SERVER_PAGES;
+ chunk.data = 0;
+ xc_hvm_param_get(xch, dom, HVM_PARAM_NR_IOREQ_SERVER_PAGES, &chunk.data);
+
+ if ( (chunk.data != 0) &&
+ wrexact(io_fd, &chunk, sizeof(chunk)) )
+ {
+ PERROR("Error when writing the ioreq server gmfn count");
+ goto out;
+ }
}
if ( callbacks != NULL && callbacks->toolstack_save != NULL )
@@ -1797,12 +1816,9 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
/* Save magic-page locations. */
memset(magic_pfns, 0, sizeof(magic_pfns));
- xc_get_hvm_param(xch, dom, HVM_PARAM_IOREQ_PFN,
- (unsigned long *)&magic_pfns[0]);
- xc_get_hvm_param(xch, dom, HVM_PARAM_BUFIOREQ_PFN,
- (unsigned long *)&magic_pfns[1]);
- xc_get_hvm_param(xch, dom, HVM_PARAM_STORE_PFN,
- (unsigned long *)&magic_pfns[2]);
+ xc_hvm_param_get(xch, dom, HVM_PARAM_IOREQ_PFN, &magic_pfns[0]);
+ xc_hvm_param_get(xch, dom, HVM_PARAM_BUFIOREQ_PFN, &magic_pfns[1]);
+ xc_hvm_param_get(xch, dom, HVM_PARAM_STORE_PFN, &magic_pfns[2]);
if ( wrexact(io_fd, magic_pfns, sizeof(magic_pfns)) )
{
PERROR("Error when writing to state file (7)");
@@ -1830,8 +1846,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
}
/* HVM guests are done now */
- rc = 0;
- goto out;
+ goto success;
}
/* PV guests only from now on */
@@ -1885,13 +1900,14 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
* reason==SHUTDOWN_suspend and is therefore found in the edx
* register.
*/
- mfn = GET_FIELD(&ctxt, user_regs.edx);
+ mfn = GET_FIELD(&ctxt, user_regs.edx, dinfo->guest_width);
if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
{
+ errno = ERANGE;
ERROR("Suspend record is not in range of pseudophys map");
goto out;
}
- SET_FIELD(&ctxt, user_regs.edx, mfn_to_pfn(mfn));
+ SET_FIELD(&ctxt, user_regs.edx, mfn_to_pfn(mfn), dinfo->guest_width);
for ( i = 0; i <= info.max_vcpu_id; i++ )
{
@@ -1905,32 +1921,37 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
}
/* Canonicalise each GDT frame number. */
- for ( j = 0; (512*j) < GET_FIELD(&ctxt, gdt_ents); j++ )
+ for ( j = 0; (512*j) < GET_FIELD(&ctxt, gdt_ents, dinfo->guest_width); j++ )
{
- mfn = GET_FIELD(&ctxt, gdt_frames[j]);
+ mfn = GET_FIELD(&ctxt, gdt_frames[j], dinfo->guest_width);
if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
{
+ errno = ERANGE;
ERROR("GDT frame is not in range of pseudophys map");
goto out;
}
- SET_FIELD(&ctxt, gdt_frames[j], mfn_to_pfn(mfn));
+ SET_FIELD(&ctxt, gdt_frames[j], mfn_to_pfn(mfn), dinfo->guest_width);
}
/* Canonicalise the page table base pointer. */
- if ( !MFN_IS_IN_PSEUDOPHYS_MAP(UNFOLD_CR3(
- GET_FIELD(&ctxt, ctrlreg[3]))) )
+ if ( !MFN_IS_IN_PSEUDOPHYS_MAP(
+ UNFOLD_CR3(GET_FIELD(&ctxt, ctrlreg[3], dinfo->guest_width))) )
{
+ errno = ERANGE;
ERROR("PT base is not in range of pseudophys map");
goto out;
}
SET_FIELD(&ctxt, ctrlreg[3],
- FOLD_CR3(mfn_to_pfn(UNFOLD_CR3(GET_FIELD(&ctxt, ctrlreg[3])))));
+ FOLD_CR3(mfn_to_pfn(UNFOLD_CR3(
+ GET_FIELD(&ctxt, ctrlreg[3], dinfo->guest_width)
+ ))), dinfo->guest_width);
/* Guest pagetable (x86/64) stored in otherwise-unused CR1. */
if ( (ctx->pt_levels == 4) && ctxt.x64.ctrlreg[1] )
{
if ( !MFN_IS_IN_PSEUDOPHYS_MAP(UNFOLD_CR3(ctxt.x64.ctrlreg[1])) )
{
+ errno = ERANGE;
ERROR("PT base is not in range of pseudophys map");
goto out;
}
@@ -1962,6 +1983,26 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
goto out;
}
+ /* Check there are no PV MSRs in use. */
+ domctl.cmd = XEN_DOMCTL_get_vcpu_msrs;
+ domctl.domain = dom;
+ memset(&domctl.u, 0, sizeof(domctl.u));
+ domctl.u.vcpu_msrs.vcpu = i;
+ domctl.u.vcpu_msrs.msr_count = 0;
+ set_xen_guest_handle_raw(domctl.u.vcpu_msrs.msrs, (void*)1);
+
+ if ( xc_domctl(xch, &domctl) < 0 )
+ {
+ if ( errno == ENOBUFS )
+ {
+ errno = EOPNOTSUPP;
+ PERROR("Unable to migrate PV guest using MSRs (yet)");
+ }
+ else
+ PERROR("Error querying maximum number of MSRs for VCPU%d", i);
+ goto out;
+ }
+
/* Start to fetch CPU eXtended States */
/* Get buffer size first */
domctl.cmd = XEN_DOMCTL_getvcpuextstate;
@@ -2012,7 +2053,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
*/
memcpy(page, live_shinfo, PAGE_SIZE);
SET_FIELD(((shared_info_any_t *)page),
- arch.pfn_to_mfn_frame_list_list, 0);
+ arch.pfn_to_mfn_frame_list_list, 0, dinfo->guest_width);
if ( wrexact(io_fd, page, PAGE_SIZE) )
{
PERROR("Error when writing to state file (1)");
@@ -2027,9 +2068,14 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
}
/* Success! */
- rc = 0;
+ success:
+ rc = errno = 0;
+ goto out_rc;
out:
+ rc = errno;
+ assert(rc);
+ out_rc:
completed = 1;
if ( !rc && callbacks->postcopy )
@@ -2044,13 +2090,11 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if (wrcompressed(io_fd) < 0)
{
ERROR("Error when writing compressed data, after postcopy\n");
- rc = 1;
goto out;
}
/* Append the tailbuf data to the main outbuf */
if ( wrexact(io_fd, ob_tailbuf.buf, ob_tailbuf.pos) )
{
- rc = 1;
PERROR("Error when copying tailbuf into outbuf");
goto out;
}
@@ -2059,7 +2103,8 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
/* Flush last write and discard cache for file. */
if ( ob && outbuf_flush(xch, ob, io_fd) < 0 ) {
PERROR("Error when flushing output buffer");
- rc = 1;
+ if (!rc)
+ rc = errno;
}
discard_file_cache(xch, io_fd, 1 /* flush */);
@@ -2074,7 +2119,6 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
/* reset stats timer */
print_stats(xch, dom, 0, &time_stats, &shadow_stats, 0);
- rc = 1;
/* last_iter = 1; */
if ( suspend_and_state(callbacks->suspend, callbacks->data, xch,
io_fd, dom, &info) )
@@ -2130,9 +2174,11 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
free(hvm_buf);
outbuf_free(&ob_pagebuf);
- DPRINTF("Save exit of domid %u with rc=%d\n", dom, rc);
+ errno = rc;
+exit:
+ DPRINTF("Save exit of domid %u with errno=%d\n", dom, errno);
- return !!rc;
+ return !!errno;
}
/*
diff --git a/tools/libxc/xc_flask.c b/tools/libxc/xc_flask.c
index 4294a25..bb117f7 100644
--- a/tools/libxc/xc_flask.c
+++ b/tools/libxc/xc_flask.c
@@ -19,7 +19,6 @@
#include "xc_private.h"
#include <unistd.h>
#include <stdio.h>
-#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
@@ -28,7 +27,6 @@
#include <stdlib.h>
#include <stdint.h>
#include <sys/ioctl.h>
-#include <stdint.h>
#define OCON_ISID 0 /* initial SIDs */
#define OCON_PIRQ 1 /* physical irqs */
diff --git a/tools/libxc/xc_foreign_memory.c b/tools/libxc/xc_foreign_memory.c
index 7dfc817..43abf01 100644
--- a/tools/libxc/xc_foreign_memory.c
+++ b/tools/libxc/xc_foreign_memory.c
@@ -27,7 +27,7 @@ void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
int i, *err;
if (num < 0) {
- errno = -EINVAL;
+ errno = EINVAL;
return NULL;
}
diff --git a/tools/libxc/xc_freebsd.c b/tools/libxc/xc_freebsd.c
new file mode 100644
index 0000000..8e70a91
--- /dev/null
+++ b/tools/libxc/xc_freebsd.c
@@ -0,0 +1,72 @@
+/******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "xc_private.h"
+
+/* Optionally flush file to disk and discard page cache */
+void discard_file_cache(xc_interface *xch, int fd, int flush)
+{
+ off_t cur = 0;
+ int saved_errno = errno;
+
+ if ( flush && (fsync(fd) < 0) )
+ goto out;
+
+ /*
+ * Calculate last page boundary of amount written so far
+ * unless we are flushing in which case entire cache
+ * is discarded.
+ */
+ if ( !flush )
+ {
+ if ( (cur = lseek(fd, 0, SEEK_CUR)) == (off_t)-1 )
+ cur = 0;
+ cur &= ~(XC_PAGE_SIZE-1);
+ }
+
+ /* Discard from the buffer cache. */
+ if ( posix_fadvise(fd, 0, cur, POSIX_FADV_DONTNEED) < 0 )
+ goto out;
+
+ out:
+ errno = saved_errno;
+}
+
+void *xc_memalign(xc_interface *xch, size_t alignment, size_t size)
+{
+ int ret;
+ void *ptr;
+
+ ret = posix_memalign(&ptr, alignment, size);
+ if ( ret != 0 || !ptr )
+ return NULL;
+
+ return ptr;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/xc_freebsd_osdep.c b/tools/libxc/xc_freebsd_osdep.c
new file mode 100644
index 0000000..151d3bf
--- /dev/null
+++ b/tools/libxc/xc_freebsd_osdep.c
@@ -0,0 +1,405 @@
+ /******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * xc_gnttab functions:
+ * Copyright (c) 2007-2008, D G Murray <Derek.Murray at cl.cam.ac.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#include <xen/memory.h>
+#include <xen/sys/evtchn.h>
+
+#include "xenctrl.h"
+#include "xenctrlosdep.h"
+
+#define PRIVCMD_DEV "/dev/xen/privcmd"
+#define EVTCHN_DEV "/dev/xen/evtchn"
+
+#define PERROR(_m, _a...) xc_osdep_log(xch,XTL_ERROR,XC_INTERNAL_ERROR,_m \
+ " (%d = %s)", ## _a , errno, xc_strerror(xch, errno))
+
+/*------------------------- Privcmd device interface -------------------------*/
+static xc_osdep_handle freebsd_privcmd_open(xc_interface *xch)
+{
+ int flags, saved_errno;
+ int fd = open(PRIVCMD_DEV, O_RDWR);
+
+ if ( fd == -1 )
+ {
+ PERROR("Could not obtain handle on privileged command interface "
+ PRIVCMD_DEV);
+ return XC_OSDEP_OPEN_ERROR;
+ }
+
+ /*
+ * Although we return the file handle as the 'xc handle' the API
+ * does not specify / guarentee that this integer is in fact
+ * a file handle. Thus we must take responsiblity to ensure
+ * it doesn't propagate (ie leak) outside the process.
+ */
+ if ( (flags = fcntl(fd, F_GETFD)) < 0 )
+ {
+ PERROR("Could not get file handle flags");
+ goto error;
+ }
+
+ flags |= FD_CLOEXEC;
+
+ if ( fcntl(fd, F_SETFD, flags) < 0 )
+ {
+ PERROR("Could not set file handle flags");
+ goto error;
+ }
+
+ return (xc_osdep_handle)fd;
+
+ error:
+ saved_errno = errno;
+ close(fd);
+ errno = saved_errno;
+
+ return XC_OSDEP_OPEN_ERROR;
+}
+
+static int freebsd_privcmd_close(xc_interface *xch, xc_osdep_handle h)
+{
+ int fd = (int)h;
+
+ return close(fd);
+}
+
+/*------------------------ Privcmd hypercall interface -----------------------*/
+static void *freebsd_privcmd_alloc_hypercall_buffer(xc_interface *xch,
+ xc_osdep_handle h,
+ int npages)
+{
+ size_t size = npages * XC_PAGE_SIZE;
+ void *p;
+
+ /* Address returned by mmap is page aligned. */
+ p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
+ -1, 0);
+ if (p == NULL)
+ return NULL;
+
+ /*
+ * Since FreeBSD doesn't have the MAP_LOCKED flag,
+ * lock memory using mlock.
+ */
+ if ( mlock(p, size) < 0 )
+ {
+ munmap(p, size);
+ return NULL;
+ }
+
+ return p;
+}
+
+static void freebsd_privcmd_free_hypercall_buffer(xc_interface *xch,
+ xc_osdep_handle h, void *ptr,
+ int npages)
+{
+
+ /* Unlock pages */
+ munlock(ptr, npages * XC_PAGE_SIZE);
+
+ munmap(ptr, npages * XC_PAGE_SIZE);
+}
+
+static int freebsd_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h,
+ privcmd_hypercall_t *hypercall)
+{
+ int fd = (int)h;
+ int ret;
+
+ ret = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
+
+ return (ret == 0) ? hypercall->retval : ret;
+}
+
+/*----------------------- Privcmd foreign map interface ----------------------*/
+static void *freebsd_privcmd_map_foreign_bulk(xc_interface *xch,
+ xc_osdep_handle h,
+ uint32_t dom, int prot,
+ const xen_pfn_t *arr, int *err,
+ unsigned int num)
+{
+ int fd = (int)h;
+ privcmd_mmapbatch_t ioctlx;
+ void *addr;
+ int rc;
+
+ addr = mmap(NULL, num << XC_PAGE_SHIFT, prot, MAP_SHARED, fd, 0);
+ if ( addr == MAP_FAILED )
+ {
+ PERROR("xc_map_foreign_batch: mmap failed");
+ return NULL;
+ }
+
+ ioctlx.num = num;
+ ioctlx.dom = dom;
+ ioctlx.addr = (unsigned long)addr;
+ ioctlx.arr = arr;
+ ioctlx.err = err;
+
+ rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx);
+ if ( rc < 0 )
+ {
+ int saved_errno = errno;
+ PERROR("xc_map_foreign_batch: ioctl failed");
+ (void)munmap(addr, num << XC_PAGE_SHIFT);
+ errno = saved_errno;
+ return NULL;
+ }
+
+ return addr;
+}
+
+static void *freebsd_privcmd_map_foreign_range(xc_interface *xch,
+ xc_osdep_handle h,
+ uint32_t dom, int size, int prot,
+ unsigned long mfn)
+{
+ xen_pfn_t *arr;
+ int num;
+ int i;
+ void *ret;
+
+ num = (size + XC_PAGE_SIZE - 1) >> XC_PAGE_SHIFT;
+ arr = calloc(num, sizeof(xen_pfn_t));
+ if ( arr == NULL )
+ return NULL;
+
+ for ( i = 0; i < num; i++ )
+ arr[i] = mfn + i;
+
+ ret = xc_map_foreign_pages(xch, dom, prot, arr, num);
+ free(arr);
+ return ret;
+}
+
+static void *freebsd_privcmd_map_foreign_ranges(xc_interface *xch,
+ xc_osdep_handle h,
+ uint32_t dom, size_t size,
+ int prot, size_t chunksize,
+ privcmd_mmap_entry_t entries[],
+ int nentries)
+{
+ xen_pfn_t *arr;
+ int num_per_entry;
+ int num;
+ int i;
+ int j;
+ void *ret;
+
+ num_per_entry = chunksize >> XC_PAGE_SHIFT;
+ num = num_per_entry * nentries;
+ arr = calloc(num, sizeof(xen_pfn_t));
+ if ( arr == NULL )
+ return NULL;
+
+ for ( i = 0; i < nentries; i++ )
+ for ( j = 0; j < num_per_entry; j++ )
+ arr[i * num_per_entry + j] = entries[i].mfn + j;
+
+ ret = xc_map_foreign_pages(xch, dom, prot, arr, num);
+ free(arr);
+ return ret;
+}
+
+/*----------------------------- Privcmd handlers -----------------------------*/
+static struct xc_osdep_ops freebsd_privcmd_ops = {
+ .open = &freebsd_privcmd_open,
+ .close = &freebsd_privcmd_close,
+
+ .u.privcmd = {
+ .alloc_hypercall_buffer = &freebsd_privcmd_alloc_hypercall_buffer,
+ .free_hypercall_buffer = &freebsd_privcmd_free_hypercall_buffer,
+
+ .hypercall = &freebsd_privcmd_hypercall,
+
+ .map_foreign_bulk = &freebsd_privcmd_map_foreign_bulk,
+ .map_foreign_range = &freebsd_privcmd_map_foreign_range,
+ .map_foreign_ranges = &freebsd_privcmd_map_foreign_ranges,
+ },
+};
+
+/*-------------------------- Evtchn device interface -------------------------*/
+static xc_osdep_handle
+freebsd_evtchn_open(xc_evtchn *xce)
+{
+ int fd = open(EVTCHN_DEV, O_RDWR);
+ if ( fd == -1 )
+ return XC_OSDEP_OPEN_ERROR;
+
+ return (xc_osdep_handle)fd;
+}
+
+static int
+freebsd_evtchn_close(xc_evtchn *xce, xc_osdep_handle h)
+{
+ int fd = (int)h;
+ return close(fd);
+}
+
+static int
+freebsd_evtchn_fd(xc_evtchn *xce, xc_osdep_handle h)
+{
+ return (int)h;
+}
+
+/*------------------------------ Evtchn interface ----------------------------*/
+static int
+freebsd_evtchn_notify(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+{
+ int fd = (int)h;
+ struct ioctl_evtchn_notify notify;
+
+ notify.port = port;
+
+ return ioctl(fd, IOCTL_EVTCHN_NOTIFY, ¬ify);
+}
+
+static evtchn_port_or_error_t
+freebsd_evtchn_bind_unbound_port(xc_evtchn *xce, xc_osdep_handle h, int domid)
+{
+ int ret, fd = (int)h;
+ struct ioctl_evtchn_bind_unbound_port bind;
+
+ bind.remote_domain = domid;
+
+ ret = ioctl(fd, IOCTL_EVTCHN_BIND_UNBOUND_PORT, &bind);
+ return ( ret == 0 ) ? bind.port : ret;
+}
+
+static evtchn_port_or_error_t
+freebsd_evtchn_bind_interdomain(xc_evtchn *xce, xc_osdep_handle h, int domid,
+ evtchn_port_t remote_port)
+{
+ int ret, fd = (int)h;
+ struct ioctl_evtchn_bind_interdomain bind;
+
+ bind.remote_domain = domid;
+ bind.remote_port = remote_port;
+
+ ret = ioctl(fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
+ return ( ret == 0 ) ? bind.port : ret;
+}
+
+static evtchn_port_or_error_t
+freebsd_evtchn_bind_virq(xc_evtchn *xce, xc_osdep_handle h, unsigned int virq)
+{
+ int ret, fd = (int)h;
+ struct ioctl_evtchn_bind_virq bind;
+
+ bind.virq = virq;
+
+ ret = ioctl(fd, IOCTL_EVTCHN_BIND_VIRQ, &bind);
+ return ( ret == 0 ) ? bind.port : ret;
+}
+
+static int
+freebsd_evtchn_unbind(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+{
+ int fd = (int)h;
+ struct ioctl_evtchn_unbind unbind;
+
+ unbind.port = port;
+
+ return ioctl(fd, IOCTL_EVTCHN_UNBIND, &unbind);
+}
+
+static evtchn_port_or_error_t
+freebsd_evtchn_pending(xc_evtchn *xce, xc_osdep_handle h)
+{
+ int fd = (int)h;
+ evtchn_port_t port;
+
+ if ( read(fd, &port, sizeof(port)) != sizeof(port) )
+ return -1;
+
+ return port;
+}
+
+static int
+freebsd_evtchn_unmask(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+{
+ int fd = (int)h;
+
+ if ( write(fd, &port, sizeof(port)) != sizeof(port) )
+ return -1;
+ return 0;
+}
+
+/*----------------------------- Evtchn handlers ------------------------------*/
+static struct xc_osdep_ops freebsd_evtchn_ops = {
+ .open = &freebsd_evtchn_open,
+ .close = &freebsd_evtchn_close,
+
+ .u.evtchn = {
+ .fd = &freebsd_evtchn_fd,
+ .notify = &freebsd_evtchn_notify,
+ .bind_unbound_port = &freebsd_evtchn_bind_unbound_port,
+ .bind_interdomain = &freebsd_evtchn_bind_interdomain,
+ .bind_virq = &freebsd_evtchn_bind_virq,
+ .unbind = &freebsd_evtchn_unbind,
+ .pending = &freebsd_evtchn_pending,
+ .unmask = &freebsd_evtchn_unmask,
+ },
+};
+
+/*---------------------------- FreeBSD interface -----------------------------*/
+static struct xc_osdep_ops *
+freebsd_osdep_init(xc_interface *xch, enum xc_osdep_type type)
+{
+ switch ( type )
+ {
+ case XC_OSDEP_PRIVCMD:
+ return &freebsd_privcmd_ops;
+ case XC_OSDEP_EVTCHN:
+ return &freebsd_evtchn_ops;
+ default:
+ return NULL;
+ }
+}
+
+xc_osdep_info_t xc_osdep_info = {
+ .name = "FreeBSD Native OS interface",
+ .init = &freebsd_osdep_init,
+ .fake = 0,
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/xc_gnttab.c b/tools/libxc/xc_gnttab.c
index 79dab40..4076e47 100644
--- a/tools/libxc/xc_gnttab.c
+++ b/tools/libxc/xc_gnttab.c
@@ -18,7 +18,6 @@
*/
#include "xc_private.h"
-#include <errno.h>
int xc_gnttab_op(xc_interface *xch, int cmd, void * op, int op_size, int count)
{
@@ -76,7 +75,7 @@ static void *_gnttab_map_table(xc_interface *xch, int domid, int *gnt_num)
if ( rc || (query.status != GNTST_okay) )
{
- ERROR("Could not query dom's grant size\n", domid);
+ ERROR("Could not query dom%d's grant size\n", domid);
return NULL;
}
diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c
index dd3b522..c81a25b 100644
--- a/tools/libxc/xc_hvm_build_x86.c
+++ b/tools/libxc/xc_hvm_build_x86.c
@@ -49,6 +49,9 @@
#define NR_SPECIAL_PAGES 8
#define special_pfn(x) (0xff000u - NR_SPECIAL_PAGES + (x))
+#define NR_IOREQ_SERVER_PAGES 8
+#define ioreq_server_pfn(x) (special_pfn(0) - NR_IOREQ_SERVER_PAGES + (x))
+
#define VGA_HOLE_SIZE (0x20)
static int modules_init(struct xc_hvm_build_args *args,
@@ -114,7 +117,7 @@ static void build_hvm_info(void *hvm_info_page, uint64_t mem_size,
/* Memory parameters. */
hvm_info->low_mem_pgend = lowmem_end >> PAGE_SHIFT;
hvm_info->high_mem_pgend = highmem_end >> PAGE_SHIFT;
- hvm_info->reserved_mem_pgstart = special_pfn(0);
+ hvm_info->reserved_mem_pgstart = ioreq_server_pfn(0);
/* Finish with the checksum. */
for ( i = 0, sum = 0; i < hvm_info->length; i++ )
@@ -257,6 +260,8 @@ static int setup_guest(xc_interface *xch,
stat_1gb_pages = 0;
int pod_mode = 0;
int claim_enabled = args->claim_enabled;
+ xen_pfn_t special_array[NR_SPECIAL_PAGES];
+ xen_pfn_t ioreq_server_array[NR_IOREQ_SERVER_PAGES];
if ( nr_pages > target_pages )
pod_mode = XENMEMF_populate_on_demand;
@@ -283,15 +288,11 @@ static int setup_guest(xc_interface *xch,
goto error_out;
}
- DPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n"
- " Loader: %016"PRIx64"->%016"PRIx64"\n"
- " Modules: %016"PRIx64"->%016"PRIx64"\n"
- " TOTAL: %016"PRIx64"->%016"PRIx64"\n"
- " ENTRY ADDRESS: %016"PRIx64"\n",
- elf.pstart, elf.pend,
- m_start, m_end,
- v_start, v_end,
- elf_uval(&elf, elf.ehdr, e_entry));
+ DPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n");
+ DPRINTF(" Loader: %016"PRIx64"->%016"PRIx64"\n", elf.pstart, elf.pend);
+ DPRINTF(" Modules: %016"PRIx64"->%016"PRIx64"\n", m_start, m_end);
+ DPRINTF(" TOTAL: %016"PRIx64"->%016"PRIx64"\n", v_start, v_end);
+ DPRINTF(" ENTRY: %016"PRIx64"\n", elf_uval(&elf, elf.ehdr, e_entry));
if ( (page_array = malloc(nr_pages * sizeof(xen_pfn_t))) == NULL )
{
@@ -453,11 +454,10 @@ static int setup_guest(xc_interface *xch,
goto error_out;
}
- DPRINTF("PHYSICAL MEMORY ALLOCATION:\n"
- " 4KB PAGES: 0x%016lx\n"
- " 2MB PAGES: 0x%016lx\n"
- " 1GB PAGES: 0x%016lx\n",
- stat_normal_pages, stat_2mb_pages, stat_1gb_pages);
+ DPRINTF("PHYSICAL MEMORY ALLOCATION:\n");
+ DPRINTF(" 4KB PAGES: 0x%016lx\n", stat_normal_pages);
+ DPRINTF(" 2MB PAGES: 0x%016lx\n", stat_2mb_pages);
+ DPRINTF(" 1GB PAGES: 0x%016lx\n", stat_1gb_pages);
if ( loadelfimage(xch, &elf, dom, page_array) != 0 )
goto error_out;
@@ -474,34 +474,59 @@ static int setup_guest(xc_interface *xch,
/* Allocate and clear special pages. */
for ( i = 0; i < NR_SPECIAL_PAGES; i++ )
+ special_array[i] = special_pfn(i);
+
+ rc = xc_domain_populate_physmap_exact(xch, dom, NR_SPECIAL_PAGES, 0, 0,
+ special_array);
+ if ( rc != 0 )
{
- xen_pfn_t pfn = special_pfn(i);
- rc = xc_domain_populate_physmap_exact(xch, dom, 1, 0, 0, &pfn);
- if ( rc != 0 )
- {
- PERROR("Could not allocate %d'th special page.", i);
- goto error_out;
- }
- if ( xc_clear_domain_page(xch, dom, special_pfn(i)) )
- goto error_out;
+ PERROR("Could not allocate special pages.");
+ goto error_out;
}
- xc_set_hvm_param(xch, dom, HVM_PARAM_STORE_PFN,
+ if ( xc_clear_domain_pages(xch, dom, special_pfn(0), NR_SPECIAL_PAGES) )
+ goto error_out;
+
+ xc_hvm_param_set(xch, dom, HVM_PARAM_STORE_PFN,
special_pfn(SPECIALPAGE_XENSTORE));
- xc_set_hvm_param(xch, dom, HVM_PARAM_BUFIOREQ_PFN,
+ xc_hvm_param_set(xch, dom, HVM_PARAM_BUFIOREQ_PFN,
special_pfn(SPECIALPAGE_BUFIOREQ));
- xc_set_hvm_param(xch, dom, HVM_PARAM_IOREQ_PFN,
+ xc_hvm_param_set(xch, dom, HVM_PARAM_IOREQ_PFN,
special_pfn(SPECIALPAGE_IOREQ));
- xc_set_hvm_param(xch, dom, HVM_PARAM_CONSOLE_PFN,
+ xc_hvm_param_set(xch, dom, HVM_PARAM_CONSOLE_PFN,
special_pfn(SPECIALPAGE_CONSOLE));
- xc_set_hvm_param(xch, dom, HVM_PARAM_PAGING_RING_PFN,
+ xc_hvm_param_set(xch, dom, HVM_PARAM_PAGING_RING_PFN,
special_pfn(SPECIALPAGE_PAGING));
- xc_set_hvm_param(xch, dom, HVM_PARAM_ACCESS_RING_PFN,
+ xc_hvm_param_set(xch, dom, HVM_PARAM_ACCESS_RING_PFN,
special_pfn(SPECIALPAGE_ACCESS));
- xc_set_hvm_param(xch, dom, HVM_PARAM_SHARING_RING_PFN,
+ xc_hvm_param_set(xch, dom, HVM_PARAM_SHARING_RING_PFN,
special_pfn(SPECIALPAGE_SHARING));
/*
+ * Allocate and clear additional ioreq server pages. The default
+ * server will use the IOREQ and BUFIOREQ special pages above.
+ */
+ for ( i = 0; i < NR_IOREQ_SERVER_PAGES; i++ )
+ ioreq_server_array[i] = ioreq_server_pfn(i);
+
+ rc = xc_domain_populate_physmap_exact(xch, dom, NR_IOREQ_SERVER_PAGES, 0, 0,
+ ioreq_server_array);
+ if ( rc != 0 )
+ {
+ PERROR("Could not allocate ioreq server pages.");
+ goto error_out;
+ }
+
+ if ( xc_clear_domain_pages(xch, dom, ioreq_server_pfn(0), NR_IOREQ_SERVER_PAGES) )
+ goto error_out;
+
+ /* Tell the domain where the pages are and how many there are */
+ xc_hvm_param_set(xch, dom, HVM_PARAM_IOREQ_SERVER_PFN,
+ ioreq_server_pfn(0));
+ xc_hvm_param_set(xch, dom, HVM_PARAM_NR_IOREQ_SERVER_PAGES,
+ NR_IOREQ_SERVER_PAGES);
+
+ /*
* Identity-map page table is required for running with CR0.PG=0 when
* using Intel EPT. Create a 32-bit non-PAE page directory of superpages.
*/
@@ -513,7 +538,7 @@ static int setup_guest(xc_interface *xch,
ident_pt[i] = ((i << 22) | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER |
_PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE);
munmap(ident_pt, PAGE_SIZE);
- xc_set_hvm_param(xch, dom, HVM_PARAM_IDENT_PT,
+ xc_hvm_param_set(xch, dom, HVM_PARAM_IDENT_PT,
special_pfn(SPECIALPAGE_IDENT_PT) << PAGE_SHIFT);
/* Insert JMP <rel32> instruction at address 0x0 to reach entry point. */
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
index 73860a2..a19e4b6 100644
--- a/tools/libxc/xc_linux_osdep.c
+++ b/tools/libxc/xc_linux_osdep.c
@@ -92,14 +92,32 @@ static void *linux_privcmd_alloc_hypercall_buffer(xc_interface *xch, xc_osdep_ha
{
size_t size = npages * XC_PAGE_SIZE;
void *p;
+ int rc, saved_errno;
/* Address returned by mmap is page aligned. */
p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, -1, 0);
+ if ( p == MAP_FAILED )
+ {
+ PERROR("xc_alloc_hypercall_buffer: mmap failed");
+ return NULL;
+ }
/* Do not copy the VMA to child process on fork. Avoid the page being COW
on hypercall. */
- madvise(p, npages * XC_PAGE_SIZE, MADV_DONTFORK);
+ rc = madvise(p, npages * XC_PAGE_SIZE, MADV_DONTFORK);
+ if ( rc < 0 )
+ {
+ PERROR("xc_alloc_hypercall_buffer: madvise failed");
+ goto out;
+ }
+
return p;
+
+out:
+ saved_errno = errno;
+ (void)munmap(p, size);
+ errno = saved_errno;
+ return NULL;
}
static void linux_privcmd_free_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages)
@@ -829,7 +847,7 @@ static void *linux_gntshr_share_pages(xc_gntshr *xch, xc_osdep_handle h,
static int linux_gntshr_munmap(xc_gntshr *xcg, xc_osdep_handle h,
void *start_address, uint32_t count)
{
- return munmap(start_address, count);
+ return munmap(start_address, count * XC_PAGE_SIZE);
}
static struct xc_osdep_ops linux_gntshr_ops = {
diff --git a/tools/libxc/xc_mem_access.c b/tools/libxc/xc_mem_access.c
index a50c145..55d0e9f 100644
--- a/tools/libxc/xc_mem_access.c
+++ b/tools/libxc/xc_mem_access.c
@@ -22,21 +22,19 @@
*/
#include "xc_private.h"
+#include <xen/memory.h>
-
-int xc_mem_access_enable(xc_interface *xch, domid_t domain_id,
- uint32_t *port)
+void *xc_mem_access_enable(xc_interface *xch, domid_t domain_id, uint32_t *port)
{
- if ( !port )
- {
- errno = EINVAL;
- return -1;
- }
+ return xc_mem_event_enable(xch, domain_id, HVM_PARAM_ACCESS_RING_PFN,
+ port, 0);
+}
- return xc_mem_event_control(xch, domain_id,
- XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE,
- XEN_DOMCTL_MEM_EVENT_OP_ACCESS,
- port);
+void *xc_mem_access_enable_introspection(xc_interface *xch, domid_t domain_id,
+ uint32_t *port)
+{
+ return xc_mem_event_enable(xch, domain_id, HVM_PARAM_ACCESS_RING_PFN,
+ port, 1);
}
int xc_mem_access_disable(xc_interface *xch, domid_t domain_id)
@@ -47,12 +45,54 @@ int xc_mem_access_disable(xc_interface *xch, domid_t domain_id)
NULL);
}
-int xc_mem_access_resume(xc_interface *xch, domid_t domain_id, unsigned long gfn)
+int xc_mem_access_resume(xc_interface *xch, domid_t domain_id)
+{
+ xen_mem_access_op_t mao =
+ {
+ .op = XENMEM_access_op_resume,
+ .domid = domain_id
+ };
+
+ return do_memory_op(xch, XENMEM_access_op, &mao, sizeof(mao));
+}
+
+int xc_set_mem_access(xc_interface *xch,
+ domid_t domain_id,
+ xenmem_access_t access,
+ uint64_t first_pfn,
+ uint32_t nr)
+{
+ xen_mem_access_op_t mao =
+ {
+ .op = XENMEM_access_op_set_access,
+ .domid = domain_id,
+ .access = access,
+ .pfn = first_pfn,
+ .nr = nr
+ };
+
+ return do_memory_op(xch, XENMEM_access_op, &mao, sizeof(mao));
+}
+
+int xc_get_mem_access(xc_interface *xch,
+ domid_t domain_id,
+ uint64_t pfn,
+ xenmem_access_t *access)
{
- return xc_mem_event_memop(xch, domain_id,
- XENMEM_access_op_resume,
- XENMEM_access_op,
- gfn, NULL);
+ int rc;
+ xen_mem_access_op_t mao =
+ {
+ .op = XENMEM_access_op_get_access,
+ .domid = domain_id,
+ .pfn = pfn
+ };
+
+ rc = do_memory_op(xch, XENMEM_access_op, &mao, sizeof(mao));
+
+ if ( rc == 0 )
+ *access = mao.access;
+
+ return rc;
}
/*
diff --git a/tools/libxc/xc_mem_event.c b/tools/libxc/xc_mem_event.c
index d43a0af..8c0be4e 100644
--- a/tools/libxc/xc_mem_event.c
+++ b/tools/libxc/xc_mem_event.c
@@ -56,3 +56,123 @@ int xc_mem_event_memop(xc_interface *xch, domid_t domain_id,
return do_memory_op(xch, mode, &meo, sizeof(meo));
}
+void *xc_mem_event_enable(xc_interface *xch, domid_t domain_id, int param,
+ uint32_t *port, int enable_introspection)
+{
+ void *ring_page = NULL;
+ uint64_t pfn;
+ xen_pfn_t ring_pfn, mmap_pfn;
+ unsigned int op, mode;
+ int rc1, rc2, saved_errno;
+
+ if ( !port )
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /* Pause the domain for ring page setup */
+ rc1 = xc_domain_pause(xch, domain_id);
+ if ( rc1 != 0 )
+ {
+ PERROR("Unable to pause domain\n");
+ return NULL;
+ }
+
+ /* Get the pfn of the ring page */
+ rc1 = xc_hvm_param_get(xch, domain_id, param, &pfn);
+ if ( rc1 != 0 )
+ {
+ PERROR("Failed to get pfn of ring page\n");
+ goto out;
+ }
+
+ ring_pfn = pfn;
+ mmap_pfn = pfn;
+ ring_page = xc_map_foreign_batch(xch, domain_id, PROT_READ | PROT_WRITE,
+ &mmap_pfn, 1);
+ if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
+ {
+ /* Map failed, populate ring page */
+ rc1 = xc_domain_populate_physmap_exact(xch, domain_id, 1, 0, 0,
+ &ring_pfn);
+ if ( rc1 != 0 )
+ {
+ PERROR("Failed to populate ring pfn\n");
+ goto out;
+ }
+
+ mmap_pfn = ring_pfn;
+ ring_page = xc_map_foreign_batch(xch, domain_id, PROT_READ | PROT_WRITE,
+ &mmap_pfn, 1);
+ if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
+ {
+ PERROR("Could not map the ring page\n");
+ goto out;
+ }
+ }
+
+ switch ( param )
+ {
+ case HVM_PARAM_PAGING_RING_PFN:
+ op = XEN_DOMCTL_MEM_EVENT_OP_PAGING_ENABLE;
+ mode = XEN_DOMCTL_MEM_EVENT_OP_PAGING;
+ break;
+
+ case HVM_PARAM_ACCESS_RING_PFN:
+ if ( enable_introspection )
+ op = XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE_INTROSPECTION;
+ else
+ op = XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE;
+ mode = XEN_DOMCTL_MEM_EVENT_OP_ACCESS;
+ break;
+
+ case HVM_PARAM_SHARING_RING_PFN:
+ op = XEN_DOMCTL_MEM_EVENT_OP_SHARING_ENABLE;
+ mode = XEN_DOMCTL_MEM_EVENT_OP_SHARING;
+ break;
+
+ /*
+ * This is for the outside chance that the HVM_PARAM is valid but is invalid
+ * as far as mem_event goes.
+ */
+ default:
+ errno = EINVAL;
+ rc1 = -1;
+ goto out;
+ }
+
+ rc1 = xc_mem_event_control(xch, domain_id, op, mode, port);
+ if ( rc1 != 0 )
+ {
+ PERROR("Failed to enable mem_event\n");
+ goto out;
+ }
+
+ /* Remove the ring_pfn from the guest's physmap */
+ rc1 = xc_domain_decrease_reservation_exact(xch, domain_id, 1, 0, &ring_pfn);
+ if ( rc1 != 0 )
+ PERROR("Failed to remove ring page from guest physmap");
+
+ out:
+ saved_errno = errno;
+
+ rc2 = xc_domain_unpause(xch, domain_id);
+ if ( rc1 != 0 || rc2 != 0 )
+ {
+ if ( rc2 != 0 )
+ {
+ if ( rc1 == 0 )
+ saved_errno = errno;
+ PERROR("Unable to unpause domain");
+ }
+
+ if ( ring_page )
+ munmap(ring_page, XC_PAGE_SIZE);
+ ring_page = NULL;
+
+ errno = saved_errno;
+ }
+
+ return ring_page;
+}
diff --git a/tools/libxc/xc_mem_paging.c b/tools/libxc/xc_mem_paging.c
index 269cbdd..8aa7d4d 100644
--- a/tools/libxc/xc_mem_paging.c
+++ b/tools/libxc/xc_mem_paging.c
@@ -76,7 +76,7 @@ int xc_mem_paging_load(xc_interface *xch, domid_t domain_id,
{
int rc, old_errno;
- errno = -EINVAL;
+ errno = EINVAL;
if ( !buffer )
return -1;
diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
index dec4d73..e703684 100644
--- a/tools/libxc/xc_minios.c
+++ b/tools/libxc/xc_minios.c
@@ -29,7 +29,6 @@
#include <mini-os/events.h>
#include <mini-os/wait.h>
#include <sys/mman.h>
-#include <errno.h>
#include <xen/memory.h>
#include <unistd.h>
@@ -88,7 +87,7 @@ static int minios_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcm
int i, ret;
call.op = hypercall->op;
- for (i = 0; i < sizeof(hypercall->arg) / sizeof(*hypercall->arg); i++)
+ for (i = 0; i < ARRAY_SIZE(hypercall->arg); i++)
call.args[i] = hypercall->arg[i];
ret = HYPERVISOR_multicall(&call, 1);
@@ -350,7 +349,7 @@ static int minios_evtchn_unbind(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t
}
}
printf("Warning: couldn't find port %"PRId32" for xc handle %x\n", port, fd);
- errno = -EINVAL;
+ errno = EINVAL;
return -1;
}
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index 3303454..e253a58 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -320,6 +320,7 @@ int xc_lockprof_query_number(xc_interface *xch,
DECLARE_SYSCTL;
sysctl.cmd = XEN_SYSCTL_lockprof_op;
+ sysctl.u.lockprof_op.max_elem = 0;
sysctl.u.lockprof_op.cmd = XEN_SYSCTL_LOCKPROF_query;
set_xen_guest_handle(sysctl.u.lockprof_op.data, HYPERCALL_BUFFER_NULL);
@@ -593,67 +594,6 @@ int xc_hvm_set_mem_type(
return rc;
}
-int xc_hvm_set_mem_access(
- xc_interface *xch, domid_t dom, hvmmem_access_t mem_access, uint64_t first_pfn, uint64_t nr)
-{
- DECLARE_HYPERCALL;
- DECLARE_HYPERCALL_BUFFER(struct xen_hvm_set_mem_access, arg);
- int rc;
-
- arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
- if ( arg == NULL )
- {
- PERROR("Could not allocate memory for xc_hvm_set_mem_access hypercall");
- return -1;
- }
-
- arg->domid = dom;
- arg->hvmmem_access = mem_access;
- arg->first_pfn = first_pfn;
- arg->nr = nr;
-
- hypercall.op = __HYPERVISOR_hvm_op;
- hypercall.arg[0] = HVMOP_set_mem_access;
- hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
- rc = do_xen_hypercall(xch, &hypercall);
-
- xc_hypercall_buffer_free(xch, arg);
-
- return rc;
-}
-
-int xc_hvm_get_mem_access(
- xc_interface *xch, domid_t dom, uint64_t pfn, hvmmem_access_t* mem_access)
-{
- DECLARE_HYPERCALL;
- DECLARE_HYPERCALL_BUFFER(struct xen_hvm_get_mem_access, arg);
- int rc;
-
- arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
- if ( arg == NULL )
- {
- PERROR("Could not allocate memory for xc_hvm_get_mem_access hypercall");
- return -1;
- }
-
- arg->domid = dom;
- arg->pfn = pfn;
-
- hypercall.op = __HYPERVISOR_hvm_op;
- hypercall.arg[0] = HVMOP_get_mem_access;
- hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
- rc = do_xen_hypercall(xch, &hypercall);
-
- if ( !rc )
- *mem_access = arg->hvmmem_access;
-
- xc_hypercall_buffer_free(xch, arg);
-
- return rc;
-}
-
int xc_hvm_inject_trap(
xc_interface *xch, domid_t dom, int vcpu, uint32_t vector,
uint32_t type, uint32_t error_code, uint32_t insn_len,
diff --git a/tools/libxc/xc_msr_x86.h b/tools/libxc/xc_msr_x86.h
new file mode 100644
index 0000000..7c3e1a3
--- /dev/null
+++ b/tools/libxc/xc_msr_x86.h
@@ -0,0 +1,36 @@
+/*
+ * xc_msr_x86.h
+ *
+ * MSR definition macros
+ *
+ * Copyright (C) 2014 Intel Corporation
+ * Author Dongxiao Xu <dongxiao.xu at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#ifndef XC_MSR_X86_H
+#define XC_MSR_X86_H
+
+#define MSR_IA32_CMT_EVTSEL 0x00000c8d
+#define MSR_IA32_CMT_CTR 0x00000c8e
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/xc_nomigrate.c b/tools/libxc/xc_nomigrate.c
index fb6d53e..76978a0 100644
--- a/tools/libxc/xc_nomigrate.c
+++ b/tools/libxc/xc_nomigrate.c
@@ -23,8 +23,7 @@
int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
uint32_t max_factor, uint32_t flags,
- struct save_callbacks* callbacks, int hvm,
- unsigned long vm_generationid_addr)
+ struct save_callbacks* callbacks, int hvm)
{
errno = ENOSYS;
return -1;
@@ -35,8 +34,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
domid_t store_domid, unsigned int console_evtchn,
unsigned long *console_mfn, domid_t console_domid,
unsigned int hvm, unsigned int pae, int superpages,
- int no_incr_generationid, int checkpointed_stream,
- unsigned long *vm_generationid_addr,
+ int checkpointed_stream,
struct restore_callbacks *callbacks)
{
errno = ENOSYS;
diff --git a/tools/libxc/xc_offline_page.c b/tools/libxc/xc_offline_page.c
index 0b4cdf9..3147203 100644
--- a/tools/libxc/xc_offline_page.c
+++ b/tools/libxc/xc_offline_page.c
@@ -272,8 +272,8 @@ static int change_pte(xc_interface *xch, int domid,
for (i = 0; i < minfo->p2m_size; i++)
{
- xen_pfn_t table_mfn = pfn_to_mfn(i, minfo->p2m_table,
- minfo->guest_width);
+ xen_pfn_t table_mfn = xc_pfn_to_mfn(i, minfo->p2m_table,
+ minfo->guest_width);
uint64_t pte, new_pte;
int j;
diff --git a/tools/libxc/xc_pm.c b/tools/libxc/xc_pm.c
index 0da2d89..e4e0fb9 100644
--- a/tools/libxc/xc_pm.c
+++ b/tools/libxc/xc_pm.c
@@ -19,7 +19,6 @@
*
*/
-#include <errno.h>
#include <stdbool.h>
#include "xc_private.h"
@@ -124,45 +123,53 @@ int xc_pm_get_max_cx(xc_interface *xch, int cpuid, int *max_cx)
int xc_pm_get_cxstat(xc_interface *xch, int cpuid, struct xc_cx_stat *cxpt)
{
DECLARE_SYSCTL;
- DECLARE_NAMED_HYPERCALL_BOUNCE(triggers, cxpt->triggers, 0, XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
- DECLARE_NAMED_HYPERCALL_BOUNCE(residencies, cxpt->residencies, 0, XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
- int max_cx, ret;
+ DECLARE_NAMED_HYPERCALL_BOUNCE(triggers, cxpt->triggers,
+ cxpt->nr * sizeof(*cxpt->triggers),
+ XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+ DECLARE_NAMED_HYPERCALL_BOUNCE(residencies, cxpt->residencies,
+ cxpt->nr * sizeof(*cxpt->residencies),
+ XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+ DECLARE_NAMED_HYPERCALL_BOUNCE(pc, cxpt->pc,
+ cxpt->nr_pc * sizeof(*cxpt->pc),
+ XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+ DECLARE_NAMED_HYPERCALL_BOUNCE(cc, cxpt->cc,
+ cxpt->nr_cc * sizeof(*cxpt->cc),
+ XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+ int ret = -1;
- if( !cxpt->triggers || !cxpt->residencies )
- return -EINVAL;
-
- if ( (ret = xc_pm_get_max_cx(xch, cpuid, &max_cx)) )
- goto unlock_0;
-
- HYPERCALL_BOUNCE_SET_SIZE(triggers, max_cx * sizeof(uint64_t));
- HYPERCALL_BOUNCE_SET_SIZE(residencies, max_cx * sizeof(uint64_t));
-
- ret = -1;
if ( xc_hypercall_bounce_pre(xch, triggers) )
goto unlock_0;
if ( xc_hypercall_bounce_pre(xch, residencies) )
goto unlock_1;
+ if ( xc_hypercall_bounce_pre(xch, pc) )
+ goto unlock_2;
+ if ( xc_hypercall_bounce_pre(xch, cc) )
+ goto unlock_3;
sysctl.cmd = XEN_SYSCTL_get_pmstat;
sysctl.u.get_pmstat.type = PMSTAT_get_cxstat;
sysctl.u.get_pmstat.cpuid = cpuid;
+ sysctl.u.get_pmstat.u.getcx.nr = cxpt->nr;
+ sysctl.u.get_pmstat.u.getcx.nr_pc = cxpt->nr_pc;
+ sysctl.u.get_pmstat.u.getcx.nr_cc = cxpt->nr_cc;
set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.triggers, triggers);
set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.residencies, residencies);
+ set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.pc, pc);
+ set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.cc, cc);
if ( (ret = xc_sysctl(xch, &sysctl)) )
- goto unlock_2;
+ goto unlock_4;
cxpt->nr = sysctl.u.get_pmstat.u.getcx.nr;
cxpt->last = sysctl.u.get_pmstat.u.getcx.last;
cxpt->idle_time = sysctl.u.get_pmstat.u.getcx.idle_time;
- cxpt->pc2 = sysctl.u.get_pmstat.u.getcx.pc2;
- cxpt->pc3 = sysctl.u.get_pmstat.u.getcx.pc3;
- cxpt->pc6 = sysctl.u.get_pmstat.u.getcx.pc6;
- cxpt->pc7 = sysctl.u.get_pmstat.u.getcx.pc7;
- cxpt->cc3 = sysctl.u.get_pmstat.u.getcx.cc3;
- cxpt->cc6 = sysctl.u.get_pmstat.u.getcx.cc6;
- cxpt->cc7 = sysctl.u.get_pmstat.u.getcx.cc7;
+ cxpt->nr_pc = sysctl.u.get_pmstat.u.getcx.nr_pc;
+ cxpt->nr_cc = sysctl.u.get_pmstat.u.getcx.nr_cc;
+unlock_4:
+ xc_hypercall_bounce_post(xch, cc);
+unlock_3:
+ xc_hypercall_bounce_post(xch, pc);
unlock_2:
xc_hypercall_bounce_post(xch, residencies);
unlock_1:
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
index 0478f52..1c214dd 100644
--- a/tools/libxc/xc_private.c
+++ b/tools/libxc/xc_private.c
@@ -33,6 +33,10 @@
#define XENCTRL_OSDEP "XENCTRL_OSDEP"
+#if !defined (__MINIOS__) && !defined(__RUMPUSER_XEN__)
+#define DO_DYNAMIC_OSDEP
+#endif
+
/*
* Returns a (shallow) copy of the xc_osdep_info_t for the
* active OS interface.
@@ -50,7 +54,7 @@
static int xc_osdep_get_info(xc_interface *xch, xc_osdep_info_t *info)
{
int rc = -1;
-#ifndef __MINIOS__
+#ifdef DO_DYNAMIC_OSDEP
const char *lib = getenv(XENCTRL_OSDEP);
xc_osdep_info_t *pinfo;
void *dl_handle = NULL;
@@ -86,7 +90,7 @@ static int xc_osdep_get_info(xc_interface *xch, xc_osdep_info_t *info)
info->dl_handle = dl_handle;
}
else
-#endif
+#endif /*DO_DYNAMIC_OSDEP*/
{
*info = xc_osdep_info;
info->dl_handle = NULL;
@@ -94,21 +98,21 @@ static int xc_osdep_get_info(xc_interface *xch, xc_osdep_info_t *info)
rc = 0;
-#ifndef __MINIOS__
+#ifdef DO_DYNAMIC_OSDEP
out:
if ( dl_handle && rc == -1 )
dlclose(dl_handle);
-#endif
+#endif /*DO_DYNAMIC_OSDEP*/
return rc;
}
static void xc_osdep_put(xc_osdep_info_t *info)
{
-#ifndef __MINIOS__
+#ifdef DO_DYNAMIC_OSDEP
if ( info->dl_handle )
dlclose(info->dl_handle);
-#endif
+#endif /*DO_DYNAMIC_OSDEP*/
}
static const char *xc_osdep_type_name(enum xc_osdep_type type)
@@ -588,10 +592,6 @@ int xc_get_pfn_list(xc_interface *xch,
DECLARE_HYPERCALL_BOUNCE(pfn_buf, max_pfns * sizeof(*pfn_buf), XC_HYPERCALL_BUFFER_BOUNCE_OUT);
int ret;
-#ifdef VALGRIND
- memset(pfn_buf, 0, max_pfns * sizeof(*pfn_buf));
-#endif
-
if ( xc_hypercall_bounce_pre(xch, pfn_buf) )
{
PERROR("xc_get_pfn_list: pfn_buf bounce failed");
@@ -632,17 +632,19 @@ int xc_copy_to_domain_page(xc_interface *xch,
return 0;
}
-int xc_clear_domain_page(xc_interface *xch,
- uint32_t domid,
- unsigned long dst_pfn)
+int xc_clear_domain_pages(xc_interface *xch,
+ uint32_t domid,
+ unsigned long dst_pfn,
+ int num)
{
+ size_t size = num * PAGE_SIZE;
void *vaddr = xc_map_foreign_range(
- xch, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
+ xch, domid, size, PROT_WRITE, dst_pfn);
if ( vaddr == NULL )
return -1;
- memset(vaddr, 0, PAGE_SIZE);
- munmap(vaddr, PAGE_SIZE);
- xc_domain_cacheflush(xch, domid, dst_pfn, 1);
+ memset(vaddr, 0, size);
+ munmap(vaddr, size);
+ xc_domain_cacheflush(xch, domid, dst_pfn, num);
return 0;
}
@@ -707,11 +709,6 @@ int xc_version(xc_interface *xch, int cmd, void *arg)
return -ENOMEM;
}
-#ifdef VALGRIND
- if (sz != 0)
- memset(hypercall_bounce_get(bounce), 0, sz);
-#endif
-
rc = do_xen_version(xch, cmd, HYPERCALL_BUFFER(arg));
if ( sz != 0 )
diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
index a610f0c..45b8644 100644
--- a/tools/libxc/xc_private.h
+++ b/tools/libxc/xc_private.h
@@ -29,27 +29,25 @@
#include <stdlib.h>
#include <sys/ioctl.h>
+#include "_paths.h"
#include "xenctrl.h"
#include "xenctrlosdep.h"
#include <xen/sys/privcmd.h>
-/* valgrind cannot see when a hypercall has filled in some values. For this
- reason, we must zero the privcmd_hypercall_t or domctl/sysctl instance
- before a call, if using valgrind. */
-#ifdef VALGRIND
-#define DECLARE_HYPERCALL privcmd_hypercall_t hypercall = { 0 }
-#define DECLARE_DOMCTL struct xen_domctl domctl = { 0 }
-#define DECLARE_SYSCTL struct xen_sysctl sysctl = { 0 }
-#define DECLARE_PHYSDEV_OP struct physdev_op physdev_op = { 0 }
-#define DECLARE_FLASK_OP struct xen_flask_op op = { 0 }
+#if defined(HAVE_VALGRIND_MEMCHECK_H) && !defined(NDEBUG) && !defined(__MINIOS__)
+/* Compile in Valgrind client requests? */
+#include <valgrind/memcheck.h>
#else
+#define VALGRIND_MAKE_MEM_UNDEFINED(addr, len) /* addr, len */
+#endif
+
#define DECLARE_HYPERCALL privcmd_hypercall_t hypercall
#define DECLARE_DOMCTL struct xen_domctl domctl
#define DECLARE_SYSCTL struct xen_sysctl sysctl
#define DECLARE_PHYSDEV_OP struct physdev_op physdev_op
#define DECLARE_FLASK_OP struct xen_flask_op op
-#endif
+#define DECLARE_PLATFORM_OP struct xen_platform_op platform_op
#undef PAGE_SHIFT
#undef PAGE_SIZE
@@ -59,7 +57,16 @@
#define PAGE_MASK XC_PAGE_MASK
/* Force a compilation error if condition is true */
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+#define XC_BUILD_BUG_ON(p) ({ _Static_assert(!(p), "!(" #p ")"); })
+#else
#define XC_BUILD_BUG_ON(p) ((void)sizeof(struct { int:-!!(p); }))
+#endif
+
+#ifndef ARRAY_SIZE /* MiniOS leaks ARRAY_SIZE into our namespace as part of a
+ * stubdom build. It shouldn't... */
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+#endif
/*
** Define max dirty page cache to permit during save/restore -- need to balance
@@ -104,7 +111,8 @@ struct xc_interface_core {
xc_osdep_handle ops_handle; /* opaque data for xc_osdep_ops */
};
-void xc_report_error(xc_interface *xch, int code, const char *fmt, ...);
+void xc_report_error(xc_interface *xch, int code, const char *fmt, ...)
+ __attribute__((format(printf,3,4)));
void xc_reportv(xc_interface *xch, xentoollog_logger *lg, xentoollog_level,
int code, const char *fmt, va_list args)
__attribute__((format(printf,5,0)));
@@ -119,13 +127,28 @@ void xc_report_progress_step(xc_interface *xch,
/* anamorphic macros: struct xc_interface *xch must be in scope */
-#define IPRINTF(_f, _a...) xc_report(xch, xch->error_handler, XTL_INFO,0, _f , ## _a)
-#define DPRINTF(_f, _a...) xc_report(xch, xch->error_handler, XTL_DETAIL,0, _f , ## _a)
-#define DBGPRINTF(_f, _a...) xc_report(xch, xch->error_handler, XTL_DEBUG,0, _f , ## _a)
-
-#define ERROR(_m, _a...) xc_report_error(xch,XC_INTERNAL_ERROR,_m , ## _a )
-#define PERROR(_m, _a...) xc_report_error(xch,XC_INTERNAL_ERROR,_m \
- " (%d = %s)", ## _a , errno, xc_strerror(xch, errno))
+#define IPRINTF(_f, _a...) do { int IPRINTF_errno = errno; \
+ xc_report(xch, xch->error_handler, XTL_INFO,0, _f , ## _a); \
+ errno = IPRINTF_errno; \
+ } while (0)
+#define DPRINTF(_f, _a...) do { int DPRINTF_errno = errno; \
+ xc_report(xch, xch->error_handler, XTL_DETAIL,0, _f , ## _a); \
+ errno = DPRINTF_errno; \
+ } while (0)
+#define DBGPRINTF(_f, _a...) do { int DBGPRINTF_errno = errno; \
+ xc_report(xch, xch->error_handler, XTL_DEBUG,0, _f , ## _a); \
+ errno = DBGPRINTF_errno; \
+ } while (0)
+
+#define ERROR(_m, _a...) do { int ERROR_errno = errno; \
+ xc_report_error(xch,XC_INTERNAL_ERROR,_m , ## _a ); \
+ errno = ERROR_errno; \
+ } while (0)
+#define PERROR(_m, _a...) do { int PERROR_errno = errno; \
+ xc_report_error(xch,XC_INTERNAL_ERROR,_m " (%d = %s)", \
+ ## _a , errno, xc_strerror(xch, errno)); \
+ errno = PERROR_errno; \
+ } while (0)
/*
* HYPERCALL ARGUMENT BUFFERS
@@ -289,6 +312,56 @@ static inline int do_sysctl(xc_interface *xch, struct xen_sysctl *sysctl)
return ret;
}
+static inline int do_platform_op(xc_interface *xch,
+ struct xen_platform_op *platform_op)
+{
+ int ret = -1;
+ DECLARE_HYPERCALL;
+ DECLARE_HYPERCALL_BOUNCE(platform_op, sizeof(*platform_op),
+ XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
+
+ platform_op->interface_version = XENPF_INTERFACE_VERSION;
+
+ if ( xc_hypercall_bounce_pre(xch, platform_op) )
+ {
+ PERROR("Could not bounce buffer for platform_op hypercall");
+ return -1;
+ }
+
+ hypercall.op = __HYPERVISOR_platform_op;
+ hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(platform_op);
+ if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 )
+ {
+ if ( errno == EACCES )
+ DPRINTF("platform operation failed -- need to"
+ " rebuild the user-space tool set?\n");
+ }
+
+ xc_hypercall_bounce_post(xch, platform_op);
+ return ret;
+}
+
+static inline int do_multicall_op(xc_interface *xch,
+ xc_hypercall_buffer_t *call_list,
+ uint32_t nr_calls)
+{
+ int ret = -1;
+ DECLARE_HYPERCALL;
+ DECLARE_HYPERCALL_BUFFER_ARGUMENT(call_list);
+
+ hypercall.op = __HYPERVISOR_multicall;
+ hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(call_list);
+ hypercall.arg[1] = nr_calls;
+ if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 )
+ {
+ if ( errno == EACCES )
+ DPRINTF("multicall operation failed -- need to"
+ " rebuild the user-space tool set?\n");
+ }
+
+ return ret;
+}
+
int do_memory_op(xc_interface *xch, int cmd, void *arg, size_t len);
void *xc_map_foreign_ranges(xc_interface *xch, uint32_t dom,
@@ -328,7 +401,38 @@ int xc_ffs16(uint16_t x);
int xc_ffs32(uint32_t x);
int xc_ffs64(uint64_t x);
+#define min(X, Y) ({ \
+ const typeof (X) _x = (X); \
+ const typeof (Y) _y = (Y); \
+ (void) (&_x == &_y); \
+ (_x < _y) ? _x : _y; })
+#define max(X, Y) ({ \
+ const typeof (X) _x = (X); \
+ const typeof (Y) _y = (Y); \
+ (void) (&_x == &_y); \
+ (_x > _y) ? _x : _y; })
+
+#define min_t(type,x,y) \
+ ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+#define max_t(type,x,y) \
+ ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
+
#define DOMPRINTF(fmt, args...) xc_dom_printf(dom->xch, fmt, ## args)
#define DOMPRINTF_CALLED(xch) xc_dom_printf((xch), "%s: called", __FUNCTION__)
+/**
+ * mem_event operations. Internal use only.
+ */
+int xc_mem_event_control(xc_interface *xch, domid_t domain_id, unsigned int op,
+ unsigned int mode, uint32_t *port);
+int xc_mem_event_memop(xc_interface *xch, domid_t domain_id,
+ unsigned int op, unsigned int mode,
+ uint64_t gfn, void *buffer);
+/*
+ * Enables mem_event and returns the mapped ring page indicated by param.
+ * param can be HVM_PARAM_PAGING/ACCESS/SHARING_RING_PFN
+ */
+void *xc_mem_event_enable(xc_interface *xch, domid_t domain_id, int param,
+ uint32_t *port, int enable_introspection);
+
#endif /* __XC_PRIVATE_H__ */
diff --git a/tools/libxc/xc_psr.c b/tools/libxc/xc_psr.c
new file mode 100644
index 0000000..872e6dc
--- /dev/null
+++ b/tools/libxc/xc_psr.c
@@ -0,0 +1,215 @@
+/*
+ * xc_psr.c
+ *
+ * platform shared resource related API functions.
+ *
+ * Copyright (C) 2014 Intel Corporation
+ * Author Dongxiao Xu <dongxiao.xu at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "xc_private.h"
+#include "xc_msr_x86.h"
+
+#define IA32_CMT_CTR_ERROR_MASK (0x3ull << 62)
+
+#define EVTID_L3_OCCUPANCY 0x1
+
+int xc_psr_cmt_attach(xc_interface *xch, uint32_t domid)
+{
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_psr_cmt_op;
+ domctl.domain = (domid_t)domid;
+ domctl.u.psr_cmt_op.cmd = XEN_DOMCTL_PSR_CMT_OP_ATTACH;
+
+ return do_domctl(xch, &domctl);
+}
+
+int xc_psr_cmt_detach(xc_interface *xch, uint32_t domid)
+{
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_psr_cmt_op;
+ domctl.domain = (domid_t)domid;
+ domctl.u.psr_cmt_op.cmd = XEN_DOMCTL_PSR_CMT_OP_DETACH;
+
+ return do_domctl(xch, &domctl);
+}
+
+int xc_psr_cmt_get_domain_rmid(xc_interface *xch, uint32_t domid,
+ uint32_t *rmid)
+{
+ int rc;
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_psr_cmt_op;
+ domctl.domain = (domid_t)domid;
+ domctl.u.psr_cmt_op.cmd = XEN_DOMCTL_PSR_CMT_OP_QUERY_RMID;
+
+ rc = do_domctl(xch, &domctl);
+
+ if ( !rc )
+ *rmid = domctl.u.psr_cmt_op.data;
+
+ return rc;
+}
+
+int xc_psr_cmt_get_total_rmid(xc_interface *xch, uint32_t *total_rmid)
+{
+ static int val = 0;
+ int rc;
+ DECLARE_SYSCTL;
+
+ if ( val )
+ {
+ *total_rmid = val;
+ return 0;
+ }
+
+ sysctl.cmd = XEN_SYSCTL_psr_cmt_op;
+ sysctl.u.psr_cmt_op.cmd = XEN_SYSCTL_PSR_CMT_get_total_rmid;
+ sysctl.u.psr_cmt_op.flags = 0;
+
+ rc = xc_sysctl(xch, &sysctl);
+ if ( !rc )
+ val = *total_rmid = sysctl.u.psr_cmt_op.u.data;
+
+ return rc;
+}
+
+int xc_psr_cmt_get_l3_upscaling_factor(xc_interface *xch,
+ uint32_t *upscaling_factor)
+{
+ static int val = 0;
+ int rc;
+ DECLARE_SYSCTL;
+
+ if ( val )
+ {
+ *upscaling_factor = val;
+ return 0;
+ }
+
+ sysctl.cmd = XEN_SYSCTL_psr_cmt_op;
+ sysctl.u.psr_cmt_op.cmd =
+ XEN_SYSCTL_PSR_CMT_get_l3_upscaling_factor;
+ sysctl.u.psr_cmt_op.flags = 0;
+
+ rc = xc_sysctl(xch, &sysctl);
+ if ( !rc )
+ val = *upscaling_factor = sysctl.u.psr_cmt_op.u.data;
+
+ return rc;
+}
+
+int xc_psr_cmt_get_l3_cache_size(xc_interface *xch, uint32_t cpu,
+ uint32_t *l3_cache_size)
+{
+ static int val = 0;
+ int rc;
+ DECLARE_SYSCTL;
+
+ if ( val )
+ {
+ *l3_cache_size = val;
+ return 0;
+ }
+
+ sysctl.cmd = XEN_SYSCTL_psr_cmt_op;
+ sysctl.u.psr_cmt_op.cmd =
+ XEN_SYSCTL_PSR_CMT_get_l3_cache_size;
+ sysctl.u.psr_cmt_op.flags = 0;
+ sysctl.u.psr_cmt_op.u.l3_cache.cpu = cpu;
+
+ rc = xc_sysctl(xch, &sysctl);
+ if ( !rc )
+ val = *l3_cache_size= sysctl.u.psr_cmt_op.u.data;
+
+ return rc;
+}
+
+int xc_psr_cmt_get_data(xc_interface *xch, uint32_t rmid,
+ uint32_t cpu, xc_psr_cmt_type type, uint64_t *monitor_data)
+{
+ xc_resource_op_t op;
+ xc_resource_entry_t entries[2];
+ uint32_t evtid;
+ int rc;
+
+ switch ( type )
+ {
+ case XC_PSR_CMT_L3_OCCUPANCY:
+ evtid = EVTID_L3_OCCUPANCY;
+ break;
+ default:
+ return -1;
+ }
+
+ entries[0].u.cmd = XEN_RESOURCE_OP_MSR_WRITE;
+ entries[0].idx = MSR_IA32_CMT_EVTSEL;
+ entries[0].val = (uint64_t)rmid << 32 | evtid;
+ entries[0].rsvd = 0;
+
+ entries[1].u.cmd = XEN_RESOURCE_OP_MSR_READ;
+ entries[1].idx = MSR_IA32_CMT_CTR;
+ entries[1].val = 0;
+ entries[1].rsvd = 0;
+
+ op.cpu = cpu;
+ op.nr_entries = 2;
+ op.entries = entries;
+
+ rc = xc_resource_op(xch, 1, &op);
+ if ( rc < 0 )
+ return rc;
+
+ if ( op.result !=2 || entries[1].val & IA32_CMT_CTR_ERROR_MASK )
+ return -1;
+
+ *monitor_data = entries[1].val;
+
+ return 0;
+}
+
+int xc_psr_cmt_enabled(xc_interface *xch)
+{
+ static int val = -1;
+ int rc;
+ DECLARE_SYSCTL;
+
+ if ( val >= 0 )
+ return val;
+
+ sysctl.cmd = XEN_SYSCTL_psr_cmt_op;
+ sysctl.u.psr_cmt_op.cmd = XEN_SYSCTL_PSR_CMT_enabled;
+ sysctl.u.psr_cmt_op.flags = 0;
+
+ rc = do_sysctl(xch, &sysctl);
+ if ( !rc )
+ {
+ val = sysctl.u.psr_cmt_op.u.data;
+ return val;
+ }
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/xc_resource.c b/tools/libxc/xc_resource.c
new file mode 100644
index 0000000..3abadbd
--- /dev/null
+++ b/tools/libxc/xc_resource.c
@@ -0,0 +1,150 @@
+/*
+ * xc_resource.c
+ *
+ * Generic resource access API
+ *
+ * Copyright (C) 2014 Intel Corporation
+ * Author Dongxiao Xu <dongxiao.xu at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "xc_private.h"
+
+static int xc_resource_op_one(xc_interface *xch, xc_resource_op_t *op)
+{
+ int rc;
+ DECLARE_PLATFORM_OP;
+ DECLARE_NAMED_HYPERCALL_BOUNCE(entries, op->entries,
+ op->nr_entries * sizeof(*op->entries),
+ XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
+
+ if ( xc_hypercall_bounce_pre(xch, entries) )
+ return -1;
+
+ platform_op.cmd = XENPF_resource_op;
+ platform_op.u.resource_op.nr_entries = op->nr_entries;
+ platform_op.u.resource_op.cpu = op->cpu;
+ set_xen_guest_handle(platform_op.u.resource_op.entries, entries);
+
+ rc = do_platform_op(xch, &platform_op);
+ op->result = rc;
+
+ xc_hypercall_bounce_post(xch, entries);
+
+ return rc;
+}
+
+static int xc_resource_op_multi(xc_interface *xch, uint32_t nr_ops, xc_resource_op_t *ops)
+{
+ int rc, i, entries_size;
+ xc_resource_op_t *op;
+ multicall_entry_t *call;
+ DECLARE_HYPERCALL_BUFFER(multicall_entry_t, call_list);
+ xc_hypercall_buffer_array_t *platform_ops, *entries_list = NULL;
+
+ call_list = xc_hypercall_buffer_alloc(xch, call_list,
+ sizeof(*call_list) * nr_ops);
+ if ( !call_list )
+ return -1;
+
+ platform_ops = xc_hypercall_buffer_array_create(xch, nr_ops);
+ if ( !platform_ops )
+ {
+ rc = -1;
+ goto out;
+ }
+
+ entries_list = xc_hypercall_buffer_array_create(xch, nr_ops);
+ if ( !entries_list )
+ {
+ rc = -1;
+ goto out;
+ }
+
+ for ( i = 0; i < nr_ops; i++ )
+ {
+ DECLARE_HYPERCALL_BUFFER(xen_platform_op_t, platform_op);
+ DECLARE_HYPERCALL_BUFFER(xc_resource_entry_t, entries);
+
+ op = ops + i;
+
+ platform_op = xc_hypercall_buffer_array_alloc(xch, platform_ops, i,
+ platform_op, sizeof(xen_platform_op_t));
+ if ( !platform_op )
+ {
+ rc = -1;
+ goto out;
+ }
+
+ entries_size = sizeof(xc_resource_entry_t) * op->nr_entries;
+ entries = xc_hypercall_buffer_array_alloc(xch, entries_list, i,
+ entries, entries_size);
+ if ( !entries)
+ {
+ rc = -1;
+ goto out;
+ }
+ memcpy(entries, op->entries, entries_size);
+
+ call = call_list + i;
+ call->op = __HYPERVISOR_platform_op;
+ call->args[0] = HYPERCALL_BUFFER_AS_ARG(platform_op);
+
+ platform_op->interface_version = XENPF_INTERFACE_VERSION;
+ platform_op->cmd = XENPF_resource_op;
+ platform_op->u.resource_op.cpu = op->cpu;
+ platform_op->u.resource_op.nr_entries = op->nr_entries;
+ set_xen_guest_handle(platform_op->u.resource_op.entries, entries);
+ }
+
+ rc = do_multicall_op(xch, HYPERCALL_BUFFER(call_list), nr_ops);
+
+ for ( i = 0; i < nr_ops; i++ )
+ {
+ DECLARE_HYPERCALL_BUFFER(xc_resource_entry_t, entries);
+ op = ops + i;
+
+ call = call_list + i;
+ op->result = call->result;
+
+ entries_size = sizeof(xc_resource_entry_t) * op->nr_entries;
+ entries = xc_hypercall_buffer_array_get(xch, entries_list, i,
+ entries, entries_size);
+ memcpy(op->entries, entries, entries_size);
+ }
+
+out:
+ xc_hypercall_buffer_array_destroy(xch, entries_list);
+ xc_hypercall_buffer_array_destroy(xch, platform_ops);
+ xc_hypercall_buffer_free(xch, call_list);
+ return rc;
+}
+
+int xc_resource_op(xc_interface *xch, uint32_t nr_ops, xc_resource_op_t *ops)
+{
+ if ( nr_ops == 1 )
+ return xc_resource_op_one(xch, ops);
+ else if ( nr_ops > 1 )
+ return xc_resource_op_multi(xch, nr_ops, ops);
+ else
+ return -1;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/xc_resume.c b/tools/libxc/xc_resume.c
index 18b4818..e67bebd 100644
--- a/tools/libxc/xc_resume.c
+++ b/tools/libxc/xc_resume.c
@@ -33,17 +33,26 @@ static int modify_returncode(xc_interface *xch, uint32_t domid)
struct domain_info_context *dinfo = &_dinfo;
int rc;
- if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 )
+ if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 ||
+ info.domid != domid )
{
PERROR("Could not get domain info");
return -1;
}
+ if ( !info.shutdown || (info.shutdown_reason != SHUTDOWN_suspend) )
+ {
+ ERROR("Dom %d not suspended: (shutdown %d, reason %d)", domid,
+ info.shutdown, info.shutdown_reason);
+ errno = EINVAL;
+ return -1;
+ }
+
if ( info.hvm )
{
/* HVM guests without PV drivers have no return code to modify. */
- unsigned long irq = 0;
- xc_get_hvm_param(xch, domid, HVM_PARAM_CALLBACK_IRQ, &irq);
+ uint64_t irq = 0;
+ xc_hvm_param_get(xch, domid, HVM_PARAM_CALLBACK_IRQ, &irq);
if ( !irq )
return 0;
@@ -65,7 +74,7 @@ static int modify_returncode(xc_interface *xch, uint32_t domid)
if ( (rc = xc_vcpu_getcontext(xch, domid, 0, &ctxt)) != 0 )
return rc;
- SET_FIELD(&ctxt, user_regs.eax, 1);
+ SET_FIELD(&ctxt, user_regs.eax, 1, dinfo->guest_width);
if ( (rc = xc_vcpu_setcontext(xch, domid, 0, &ctxt)) != 0 )
return rc;
@@ -193,7 +202,7 @@ static int xc_domain_resume_any(xc_interface *xch, uint32_t domid)
goto out;
}
- mfn = GET_FIELD(&ctxt, user_regs.edx);
+ mfn = GET_FIELD(&ctxt, user_regs.edx, dinfo->guest_width);
start_info = xc_map_foreign_range(xch, domid, PAGE_SIZE,
PROT_READ | PROT_WRITE, mfn);
diff --git a/tools/libxc/xc_rt.c b/tools/libxc/xc_rt.c
new file mode 100644
index 0000000..b2d1cc5
--- /dev/null
+++ b/tools/libxc/xc_rt.c
@@ -0,0 +1,65 @@
+/****************************************************************************
+ *
+ * File: xc_rt.c
+ * Author: Sisu Xi
+ * Meng Xu
+ *
+ * Description: XC Interface to the rtds scheduler
+ * Note: VCPU's parameter (period, budget) is in microsecond (us).
+ * All VCPUs of the same domain have same period and budget.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "xc_private.h"
+
+int xc_sched_rtds_domain_set(xc_interface *xch,
+ uint32_t domid,
+ struct xen_domctl_sched_rtds *sdom)
+{
+ int rc;
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_scheduler_op;
+ domctl.domain = (domid_t) domid;
+ domctl.u.scheduler_op.sched_id = XEN_SCHEDULER_RTDS;
+ domctl.u.scheduler_op.cmd = XEN_DOMCTL_SCHEDOP_putinfo;
+ domctl.u.scheduler_op.u.rtds.period = sdom->period;
+ domctl.u.scheduler_op.u.rtds.budget = sdom->budget;
+
+ rc = do_domctl(xch, &domctl);
+
+ return rc;
+}
+
+int xc_sched_rtds_domain_get(xc_interface *xch,
+ uint32_t domid,
+ struct xen_domctl_sched_rtds *sdom)
+{
+ int rc;
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_scheduler_op;
+ domctl.domain = (domid_t) domid;
+ domctl.u.scheduler_op.sched_id = XEN_SCHEDULER_RTDS;
+ domctl.u.scheduler_op.cmd = XEN_DOMCTL_SCHEDOP_getinfo;
+
+ rc = do_domctl(xch, &domctl);
+
+ if ( rc == 0 )
+ *sdom = domctl.u.scheduler_op.u.rtds;
+
+ return rc;
+}
diff --git a/tools/libxc/xc_suspend.c b/tools/libxc/xc_suspend.c
index 1ace411..e22f4ac 100644
--- a/tools/libxc/xc_suspend.c
+++ b/tools/libxc/xc_suspend.c
@@ -14,65 +14,115 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <unistd.h>
+#include <fcntl.h>
+
#include "xc_private.h"
#include "xenguest.h"
-#define SUSPEND_LOCK_FILE "/var/lib/xen/suspend_evtchn"
-static int lock_suspend_event(xc_interface *xch, int domid)
+#define SUSPEND_LOCK_FILE XEN_RUN_DIR "/suspend-evtchn-%d.lock"
+
+/*
+ * locking
+ */
+
+#define ERR(x) do{ \
+ ERROR("Can't " #x " lock file for suspend event channel %s: %s\n", \
+ suspend_file, strerror(errno)); \
+ goto err; \
+}while(0)
+
+#define SUSPEND_FILE_BUFLEN (sizeof(SUSPEND_LOCK_FILE) + 10)
+
+static void get_suspend_file(char buf[], int domid)
{
- int fd, rc;
- mode_t mask;
- char buf[128];
- char suspend_file[256];
-
- snprintf(suspend_file, sizeof(suspend_file), "%s_%d_lock.d",
- SUSPEND_LOCK_FILE, domid);
- mask = umask(022);
- fd = open(suspend_file, O_CREAT | O_EXCL | O_RDWR, 0666);
- if (fd < 0)
- {
- ERROR("Can't create lock file for suspend event channel %s\n",
- suspend_file);
- return -EINVAL;
+ snprintf(buf, SUSPEND_FILE_BUFLEN, SUSPEND_LOCK_FILE, domid);
+}
+
+static int lock_suspend_event(xc_interface *xch, int domid, int *lockfd)
+{
+ int fd = -1, r;
+ char suspend_file[SUSPEND_FILE_BUFLEN];
+ struct stat ours, theirs;
+ struct flock fl;
+
+ get_suspend_file(suspend_file, domid);
+
+ *lockfd = -1;
+
+ for (;;) {
+ if (fd >= 0)
+ close (fd);
+
+ fd = open(suspend_file, O_CREAT | O_RDWR, 0600);
+ if (fd < 0)
+ ERR("create");
+
+ r = fcntl(fd, F_SETFD, FD_CLOEXEC);
+ if (r)
+ ERR("fcntl F_SETFD FD_CLOEXEC");
+
+ memset(&fl, 0, sizeof(fl));
+ fl.l_type = F_WRLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_len = 1;
+ r = fcntl(fd, F_SETLK, &fl);
+ if (r)
+ ERR("fcntl F_SETLK");
+
+ r = fstat(fd, &ours);
+ if (r)
+ ERR("fstat");
+
+ r = stat(suspend_file, &theirs);
+ if (r) {
+ if (errno == ENOENT)
+ /* try again */
+ continue;
+ ERR("stat");
+ }
+
+ if (ours.st_ino != theirs.st_ino)
+ /* someone else must have removed it while we were locking it */
+ continue;
+
+ break;
}
- umask(mask);
- snprintf(buf, sizeof(buf), "%10ld", (long)getpid());
- rc = write_exact(fd, buf, strlen(buf));
- close(fd);
+ *lockfd = fd;
+ return 0;
+
+ err:
+ if (fd >= 0)
+ close(fd);
- return rc;
+ return -1;
}
-static int unlock_suspend_event(xc_interface *xch, int domid)
+static int unlock_suspend_event(xc_interface *xch, int domid, int *lockfd)
{
- int fd, pid, n;
- char buf[128];
- char suspend_file[256];
+ int r;
+ char suspend_file[SUSPEND_FILE_BUFLEN];
- snprintf(suspend_file, sizeof(suspend_file), "%s_%d_lock.d",
- SUSPEND_LOCK_FILE, domid);
- fd = open(suspend_file, O_RDWR);
+ if (*lockfd < 0)
+ return 0;
- if (fd < 0)
- return -EINVAL;
+ get_suspend_file(suspend_file, domid);
- n = read(fd, buf, 127);
+ r = unlink(suspend_file);
+ if (r)
+ ERR("unlink");
- close(fd);
+ r = close(*lockfd);
+ *lockfd = -1;
+ if (r)
+ ERR("close");
- if (n > 0)
- {
- sscanf(buf, "%d", &pid);
- /* We are the owner, so we can simply delete the file */
- if (pid == getpid())
- {
- unlink(suspend_file);
- return 0;
- }
- }
+ err:
+ if (*lockfd >= 0)
+ close(*lockfd);
- return -EPERM;
+ return -1;
}
int xc_await_suspend(xc_interface *xch, xc_evtchn *xce, int suspend_evtchn)
@@ -94,20 +144,26 @@ int xc_await_suspend(xc_interface *xch, xc_evtchn *xce, int suspend_evtchn)
return 0;
}
-int xc_suspend_evtchn_release(xc_interface *xch, xc_evtchn *xce, int domid, int suspend_evtchn)
+/* Internal callers are allowed to call this with suspend_evtchn<0
+ * but *lockfd>0. */
+int xc_suspend_evtchn_release(xc_interface *xch, xc_evtchn *xce,
+ int domid, int suspend_evtchn, int *lockfd)
{
if (suspend_evtchn >= 0)
xc_evtchn_unbind(xce, suspend_evtchn);
- return unlock_suspend_event(xch, domid);
+ return unlock_suspend_event(xch, domid, lockfd);
}
-int xc_suspend_evtchn_init(xc_interface *xch, xc_evtchn *xce, int domid, int port)
+int xc_suspend_evtchn_init_sane(xc_interface *xch, xc_evtchn *xce,
+ int domid, int port, int *lockfd)
{
int rc, suspend_evtchn = -1;
- if (lock_suspend_event(xch, domid))
- return -EINVAL;
+ if (lock_suspend_event(xch, domid, lockfd)) {
+ errno = EINVAL;
+ goto cleanup;
+ }
suspend_evtchn = xc_evtchn_bind_interdomain(xce, domid, port);
if (suspend_evtchn < 0) {
@@ -121,14 +177,25 @@ int xc_suspend_evtchn_init(xc_interface *xch, xc_evtchn *xce, int domid, int por
goto cleanup;
}
- /* event channel is pending immediately after binding */
- xc_await_suspend(xch, xce, suspend_evtchn);
-
return suspend_evtchn;
cleanup:
- if (suspend_evtchn != -1)
- xc_suspend_evtchn_release(xch, xce, domid, suspend_evtchn);
+ xc_suspend_evtchn_release(xch, xce, domid, suspend_evtchn, lockfd);
return -1;
}
+
+int xc_suspend_evtchn_init_exclusive(xc_interface *xch, xc_evtchn *xce,
+ int domid, int port, int *lockfd)
+{
+ int suspend_evtchn;
+
+ suspend_evtchn = xc_suspend_evtchn_init_sane(xch, xce, domid, port, lockfd);
+ if (suspend_evtchn < 0)
+ return suspend_evtchn;
+
+ /* event channel is pending immediately after binding */
+ xc_await_suspend(xch, xce, suspend_evtchn);
+
+ return suspend_evtchn;
+}
diff --git a/tools/libxc/xc_tbuf.c b/tools/libxc/xc_tbuf.c
index 4fb7bb1..8777492 100644
--- a/tools/libxc/xc_tbuf.c
+++ b/tools/libxc/xc_tbuf.c
@@ -32,7 +32,7 @@ static int tbuf_enable(xc_interface *xch, int enable)
sysctl.cmd = XEN_SYSCTL_tbuf_op;
sysctl.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
- if (enable)
+ if ( enable )
sysctl.u.tbuf_op.cmd = XEN_SYSCTL_TBUFOP_enable;
else
sysctl.u.tbuf_op.cmd = XEN_SYSCTL_TBUFOP_disable;
@@ -121,7 +121,7 @@ int xc_tbuf_set_cpu_mask(xc_interface *xch, uint32_t mask)
uint64_t mask64 = mask;
bytemap = xc_hypercall_buffer_alloc(xch, bytemap, sizeof(mask64));
- if (bytemap == NULL)
+ if ( bytemap == NULL )
{
PERROR("Could not allocate memory for xc_tbuf_set_cpu_mask hypercall");
goto out;
diff --git a/tools/libxc/xc_tmem.c b/tools/libxc/xc_tmem.c
index 61e1549..3261e10 100644
--- a/tools/libxc/xc_tmem.c
+++ b/tools/libxc/xc_tmem.c
@@ -70,11 +70,6 @@ int xc_tmem_control(xc_interface *xch,
op.u.ctrl.oid[1] = 0;
op.u.ctrl.oid[2] = 0;
-#ifdef VALGRIND
- if (arg1 != 0)
- memset(buf, 0, arg1);
-#endif
-
if ( subop == TMEMC_LIST && arg1 != 0 )
{
if ( buf == NULL )
@@ -120,11 +115,6 @@ int xc_tmem_control_oid(xc_interface *xch,
op.u.ctrl.oid[1] = oid.oid[1];
op.u.ctrl.oid[2] = oid.oid[2];
-#ifdef VALGRIND
- if (arg1 != 0)
- memset(buf, 0, arg1);
-#endif
-
if ( subop == TMEMC_LIST && arg1 != 0 )
{
if ( buf == NULL )
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
deleted file mode 100644
index 13f816b..0000000
--- a/tools/libxc/xenctrl.h
+++ /dev/null
@@ -1,2430 +0,0 @@
-/******************************************************************************
- * xenctrl.h
- *
- * A library for low-level access to the Xen control interfaces.
- *
- * Copyright (c) 2003-2004, K A Fraser.
- *
- * xc_gnttab functions:
- * Copyright (c) 2007-2008, D G Murray <Derek.Murray at cl.cam.ac.uk>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef XENCTRL_H
-#define XENCTRL_H
-
-/* Tell the Xen public headers we are a user-space tools build. */
-#ifndef __XEN_TOOLS__
-#define __XEN_TOOLS__ 1
-#endif
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <xen/xen.h>
-#include <xen/domctl.h>
-#include <xen/physdev.h>
-#include <xen/sysctl.h>
-#include <xen/version.h>
-#include <xen/event_channel.h>
-#include <xen/sched.h>
-#include <xen/memory.h>
-#include <xen/grant_table.h>
-#include <xen/hvm/params.h>
-#include <xen/xsm/flask_op.h>
-#include <xen/tmem.h>
-#include <xen/kexec.h>
-
-#include "xentoollog.h"
-
-#if defined(__i386__) || defined(__x86_64__)
-#include <xen/foreign/x86_32.h>
-#include <xen/foreign/x86_64.h>
-#include <xen/arch-x86/xen-mca.h>
-#endif
-
-#define XC_PAGE_SHIFT 12
-#define XC_PAGE_SIZE (1UL << XC_PAGE_SHIFT)
-#define XC_PAGE_MASK (~(XC_PAGE_SIZE-1))
-
-#define INVALID_MFN (~0UL)
-
-/*
- * DEFINITIONS FOR CPU BARRIERS
- */
-
-#define xen_barrier() asm volatile ( "" : : : "memory")
-
-#if defined(__i386__)
-#define xen_mb() asm volatile ( "lock; addl $0,0(%%esp)" : : : "memory" )
-#define xen_rmb() xen_barrier()
-#define xen_wmb() xen_barrier()
-#elif defined(__x86_64__)
-#define xen_mb() asm volatile ( "mfence" : : : "memory")
-#define xen_rmb() xen_barrier()
-#define xen_wmb() xen_barrier()
-#elif defined(__arm__)
-#define xen_mb() asm volatile ("dmb" : : : "memory")
-#define xen_rmb() asm volatile ("dmb" : : : "memory")
-#define xen_wmb() asm volatile ("dmb" : : : "memory")
-#elif defined(__aarch64__)
-#define xen_mb() asm volatile ("dmb sy" : : : "memory")
-#define xen_rmb() asm volatile ("dmb sy" : : : "memory")
-#define xen_wmb() asm volatile ("dmb sy" : : : "memory")
-#else
-#error "Define barriers"
-#endif
-
-
-#define XENCTRL_HAS_XC_INTERFACE 1
-/* In Xen 4.0 and earlier, xc_interface_open and xc_evtchn_open would
- * both return ints being the file descriptor. In 4.1 and later, they
- * return an xc_interface* and xc_evtchn*, respectively - ie, a
- * pointer to an opaque struct. This #define is provided in 4.1 and
- * later, allowing out-of-tree callers to more easily distinguish
- * between, and be compatible with, both versions.
- */
-
-
-/*
- * GENERAL
- *
- * Unless otherwise specified, each function here returns zero or a
- * non-null pointer on success; or in case of failure, sets errno and
- * returns -1 or a null pointer.
- *
- * Unless otherwise specified, errors result in a call to the error
- * handler function, which by default prints a message to the
- * FILE* passed as the caller_data, which by default is stderr.
- * (This is described below as "logging errors".)
- *
- * The error handler can safely trash errno, as libxc saves it across
- * the callback.
- */
-
-typedef struct xc_interface_core xc_interface;
-typedef struct xc_interface_core xc_evtchn;
-typedef struct xc_interface_core xc_gnttab;
-typedef struct xc_interface_core xc_gntshr;
-typedef enum xc_error_code xc_error_code;
-
-
-/*
- * INITIALIZATION FUNCTIONS
- */
-
-/**
- * This function opens a handle to the hypervisor interface. This function can
- * be called multiple times within a single process. Multiple processes can
- * have an open hypervisor interface at the same time.
- *
- * Note:
- * After fork a child process must not use any opened xc interface
- * handle inherited from their parent. They must open a new handle if
- * they want to interact with xc.
- *
- * Each call to this function should have a corresponding call to
- * xc_interface_close().
- *
- * This function can fail if the caller does not have superuser permission or
- * if a Xen-enabled kernel is not currently running.
- *
- * @return a handle to the hypervisor interface
- */
-xc_interface *xc_interface_open(xentoollog_logger *logger,
- xentoollog_logger *dombuild_logger,
- unsigned open_flags);
- /* if logger==NULL, will log to stderr
- * if dombuild_logger=NULL, will log to a file
- */
-
-/*
- * Note: if XC_OPENFLAG_NON_REENTRANT is passed then libxc must not be
- * called reentrantly and the calling application is responsible for
- * providing mutual exclusion surrounding all libxc calls itself.
- *
- * In particular xc_{get,clear}_last_error only remain valid for the
- * duration of the critical section containing the call which failed.
- */
-enum xc_open_flags {
- XC_OPENFLAG_DUMMY = 1<<0, /* do not actually open a xenctrl interface */
- XC_OPENFLAG_NON_REENTRANT = 1<<1, /* assume library is only every called from a single thread */
-};
-
-/**
- * This function closes an open hypervisor interface.
- *
- * This function can fail if the handle does not represent an open interface or
- * if there were problems closing the interface. In the latter case
- * the interface is still closed.
- *
- * @parm xch a handle to an open hypervisor interface
- * @return 0 on success, -1 otherwise.
- */
-int xc_interface_close(xc_interface *xch);
-
-/**
- * Query the active OS interface (i.e. that which would be returned by
- * xc_interface_open) to find out if it is fake (i.e. backends onto
- * something other than an actual Xen hypervisor).
- *
- * @return 0 is "real", >0 if fake, -1 on error.
- */
-int xc_interface_is_fake(void);
-
-/*
- * HYPERCALL SAFE MEMORY BUFFER
- *
- * Ensure that memory which is passed to a hypercall has been
- * specially allocated in order to be safe to access from the
- * hypervisor.
- *
- * Each user data pointer is shadowed by an xc_hypercall_buffer data
- * structure. You should never define an xc_hypercall_buffer type
- * directly, instead use the DECLARE_HYPERCALL_BUFFER* macros below.
- *
- * The strucuture should be considered opaque and all access should be
- * via the macros and helper functions defined below.
- *
- * Once the buffer is declared the user is responsible for explicitly
- * allocating and releasing the memory using
- * xc_hypercall_buffer_alloc(_pages) and
- * xc_hypercall_buffer_free(_pages).
- *
- * Once the buffer has been allocated the user can initialise the data
- * via the normal pointer. The xc_hypercall_buffer structure is
- * transparently referenced by the helper macros (such as
- * xen_set_guest_handle) in order to check at compile time that the
- * correct type of memory is being used.
- */
-struct xc_hypercall_buffer {
- /* Hypercall safe memory buffer. */
- void *hbuf;
-
- /*
- * Reference to xc_hypercall_buffer passed as argument to the
- * current function.
- */
- struct xc_hypercall_buffer *param_shadow;
-
- /*
- * Direction of copy for bounce buffering.
- */
- int dir;
-
- /* Used iff dir != 0. */
- void *ubuf;
- size_t sz;
-};
-typedef struct xc_hypercall_buffer xc_hypercall_buffer_t;
-
-/*
- * Construct the name of the hypercall buffer for a given variable.
- * For internal use only
- */
-#define XC__HYPERCALL_BUFFER_NAME(_name) xc__hypercall_buffer_##_name
-
-/*
- * Returns the hypercall_buffer associated with a variable.
- */
-#define HYPERCALL_BUFFER(_name) \
- ({ xc_hypercall_buffer_t _hcbuf_buf1; \
- typeof(XC__HYPERCALL_BUFFER_NAME(_name)) *_hcbuf_buf2 = \
- &XC__HYPERCALL_BUFFER_NAME(_name); \
- (void)(&_hcbuf_buf1 == _hcbuf_buf2); \
- (_hcbuf_buf2)->param_shadow ? \
- (_hcbuf_buf2)->param_shadow : (_hcbuf_buf2); \
- })
-
-#define HYPERCALL_BUFFER_INIT_NO_BOUNCE .dir = 0, .sz = 0, .ubuf = (void *)-1
-
-/*
- * Defines a hypercall buffer and user pointer with _name of _type.
- *
- * The user accesses the data as normal via _name which will be
- * transparently converted to the hypercall buffer as necessary.
- */
-#define DECLARE_HYPERCALL_BUFFER(_type, _name) \
- _type *_name = NULL; \
- xc_hypercall_buffer_t XC__HYPERCALL_BUFFER_NAME(_name) = { \
- .hbuf = NULL, \
- .param_shadow = NULL, \
- HYPERCALL_BUFFER_INIT_NO_BOUNCE \
- }
-
-/*
- * Declare the necessary data structure to allow a hypercall buffer
- * passed as an argument to a function to be used in the normal way.
- */
-#define DECLARE_HYPERCALL_BUFFER_ARGUMENT(_name) \
- xc_hypercall_buffer_t XC__HYPERCALL_BUFFER_NAME(_name) = { \
- .hbuf = (void *)-1, \
- .param_shadow = _name, \
- HYPERCALL_BUFFER_INIT_NO_BOUNCE \
- }
-
-/*
- * Get the hypercall buffer data pointer in a form suitable for use
- * directly as a hypercall argument.
- */
-#define HYPERCALL_BUFFER_AS_ARG(_name) \
- ({ xc_hypercall_buffer_t _hcbuf_arg1; \
- typeof(XC__HYPERCALL_BUFFER_NAME(_name)) *_hcbuf_arg2 = \
- HYPERCALL_BUFFER(_name); \
- (void)(&_hcbuf_arg1 == _hcbuf_arg2); \
- (unsigned long)(_hcbuf_arg2)->hbuf; \
- })
-
-/*
- * Set a xen_guest_handle in a type safe manner, ensuring that the
- * data pointer has been correctly allocated.
- */
-#undef set_xen_guest_handle
-#define set_xen_guest_handle(_hnd, _val) \
- do { \
- xc_hypercall_buffer_t _hcbuf_hnd1; \
- typeof(XC__HYPERCALL_BUFFER_NAME(_val)) *_hcbuf_hnd2 = \
- HYPERCALL_BUFFER(_val); \
- (void) (&_hcbuf_hnd1 == _hcbuf_hnd2); \
- set_xen_guest_handle_raw(_hnd, (_hcbuf_hnd2)->hbuf); \
- } while (0)
-
-/* Use with set_xen_guest_handle in place of NULL */
-extern xc_hypercall_buffer_t XC__HYPERCALL_BUFFER_NAME(HYPERCALL_BUFFER_NULL);
-
-/*
- * Allocate and free hypercall buffers with byte granularity.
- */
-void *xc__hypercall_buffer_alloc(xc_interface *xch, xc_hypercall_buffer_t *b, size_t size);
-#define xc_hypercall_buffer_alloc(_xch, _name, _size) xc__hypercall_buffer_alloc(_xch, HYPERCALL_BUFFER(_name), _size)
-void xc__hypercall_buffer_free(xc_interface *xch, xc_hypercall_buffer_t *b);
-#define xc_hypercall_buffer_free(_xch, _name) xc__hypercall_buffer_free(_xch, HYPERCALL_BUFFER(_name))
-
-/*
- * Allocate and free hypercall buffers with page alignment.
- */
-void *xc__hypercall_buffer_alloc_pages(xc_interface *xch, xc_hypercall_buffer_t *b, int nr_pages);
-#define xc_hypercall_buffer_alloc_pages(_xch, _name, _nr) xc__hypercall_buffer_alloc_pages(_xch, HYPERCALL_BUFFER(_name), _nr)
-void xc__hypercall_buffer_free_pages(xc_interface *xch, xc_hypercall_buffer_t *b, int nr_pages);
-#define xc_hypercall_buffer_free_pages(_xch, _name, _nr) xc__hypercall_buffer_free_pages(_xch, HYPERCALL_BUFFER(_name), _nr)
-
-/*
- * Array of hypercall buffers.
- *
- * Create an array with xc_hypercall_buffer_array_create() and
- * populate it by declaring one hypercall buffer in a loop and
- * allocating the buffer with xc_hypercall_buffer_array_alloc().
- *
- * To access a previously allocated buffers, declare a new hypercall
- * buffer and call xc_hypercall_buffer_array_get().
- *
- * Destroy the array with xc_hypercall_buffer_array_destroy() to free
- * the array and all its alocated hypercall buffers.
- */
-struct xc_hypercall_buffer_array;
-typedef struct xc_hypercall_buffer_array xc_hypercall_buffer_array_t;
-
-xc_hypercall_buffer_array_t *xc_hypercall_buffer_array_create(xc_interface *xch, unsigned n);
-void *xc__hypercall_buffer_array_alloc(xc_interface *xch, xc_hypercall_buffer_array_t *array,
- unsigned index, xc_hypercall_buffer_t *hbuf, size_t size);
-#define xc_hypercall_buffer_array_alloc(_xch, _array, _index, _name, _size) \
- xc__hypercall_buffer_array_alloc(_xch, _array, _index, HYPERCALL_BUFFER(_name), _size)
-void *xc__hypercall_buffer_array_get(xc_interface *xch, xc_hypercall_buffer_array_t *array,
- unsigned index, xc_hypercall_buffer_t *hbuf);
-#define xc_hypercall_buffer_array_get(_xch, _array, _index, _name, _size) \
- xc__hypercall_buffer_array_get(_xch, _array, _index, HYPERCALL_BUFFER(_name))
-void xc_hypercall_buffer_array_destroy(xc_interface *xc, xc_hypercall_buffer_array_t *array);
-
-/*
- * CPUMAP handling
- */
-typedef uint8_t *xc_cpumap_t;
-
-/* return maximum number of cpus the hypervisor supports */
-int xc_get_max_cpus(xc_interface *xch);
-
-/* return the number of online cpus */
-int xc_get_online_cpus(xc_interface *xch);
-
-/* return array size for cpumap */
-int xc_get_cpumap_size(xc_interface *xch);
-
-/* allocate a cpumap */
-xc_cpumap_t xc_cpumap_alloc(xc_interface *xch);
-
-/*
- * NODEMAP handling
- */
-typedef uint8_t *xc_nodemap_t;
-
-/* return maximum number of NUMA nodes the hypervisor supports */
-int xc_get_max_nodes(xc_interface *xch);
-
-/* return array size for nodemap */
-int xc_get_nodemap_size(xc_interface *xch);
-
-/* allocate a nodemap */
-xc_nodemap_t xc_nodemap_alloc(xc_interface *xch);
-
-/*
- * DOMAIN DEBUGGING FUNCTIONS
- */
-
-typedef struct xc_core_header {
- unsigned int xch_magic;
- unsigned int xch_nr_vcpus;
- unsigned int xch_nr_pages;
- unsigned int xch_ctxt_offset;
- unsigned int xch_index_offset;
- unsigned int xch_pages_offset;
-} xc_core_header_t;
-
-#define XC_CORE_MAGIC 0xF00FEBED
-#define XC_CORE_MAGIC_HVM 0xF00FEBEE
-
-/*
- * DOMAIN MANAGEMENT FUNCTIONS
- */
-
-typedef struct xc_dominfo {
- uint32_t domid;
- uint32_t ssidref;
- unsigned int dying:1, crashed:1, shutdown:1,
- paused:1, blocked:1, running:1,
- hvm:1, debugged:1;
- unsigned int shutdown_reason; /* only meaningful if shutdown==1 */
- unsigned long nr_pages; /* current number, not maximum */
- unsigned long nr_outstanding_pages;
- unsigned long nr_shared_pages;
- unsigned long nr_paged_pages;
- unsigned long shared_info_frame;
- uint64_t cpu_time;
- unsigned long max_memkb;
- unsigned int nr_online_vcpus;
- unsigned int max_vcpu_id;
- xen_domain_handle_t handle;
- unsigned int cpupool;
-} xc_dominfo_t;
-
-typedef xen_domctl_getdomaininfo_t xc_domaininfo_t;
-
-typedef union
-{
-#if defined(__i386__) || defined(__x86_64__)
- vcpu_guest_context_x86_64_t x64;
- vcpu_guest_context_x86_32_t x32;
-#endif
- vcpu_guest_context_t c;
-} vcpu_guest_context_any_t;
-
-typedef union
-{
-#if defined(__i386__) || defined(__x86_64__)
- shared_info_x86_64_t x64;
- shared_info_x86_32_t x32;
-#endif
- shared_info_t s;
-} shared_info_any_t;
-
-#if defined(__i386__) || defined(__x86_64__)
-typedef union
-{
- start_info_x86_64_t x64;
- start_info_x86_32_t x32;
- start_info_t s;
-} start_info_any_t;
-#endif
-
-int xc_domain_create(xc_interface *xch,
- uint32_t ssidref,
- xen_domain_handle_t handle,
- uint32_t flags,
- uint32_t *pdomid);
-
-
-/* Functions to produce a dump of a given domain
- * xc_domain_dumpcore - produces a dump to a specified file
- * xc_domain_dumpcore_via_callback - produces a dump, using a specified
- * callback function
- */
-int xc_domain_dumpcore(xc_interface *xch,
- uint32_t domid,
- const char *corename);
-
-/* Define the callback function type for xc_domain_dumpcore_via_callback.
- *
- * This function is called by the coredump code for every "write",
- * and passes an opaque object for the use of the function and
- * created by the caller of xc_domain_dumpcore_via_callback.
- */
-typedef int (dumpcore_rtn_t)(xc_interface *xch,
- void *arg, char *buffer, unsigned int length);
-
-int xc_domain_dumpcore_via_callback(xc_interface *xch,
- uint32_t domid,
- void *arg,
- dumpcore_rtn_t dump_rtn);
-
-/*
- * This function sets the maximum number of vcpus that a domain may create.
- *
- * @parm xch a handle to an open hypervisor interface.
- * @parm domid the domain id in which vcpus are to be created.
- * @parm max the maximum number of vcpus that the domain may create.
- * @return 0 on success, -1 on failure.
- */
-int xc_domain_max_vcpus(xc_interface *xch,
- uint32_t domid,
- unsigned int max);
-
-/**
- * This function pauses a domain. A paused domain still exists in memory
- * however it does not receive any timeslices from the hypervisor.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain id to pause
- * @return 0 on success, -1 on failure.
- */
-int xc_domain_pause(xc_interface *xch,
- uint32_t domid);
-/**
- * This function unpauses a domain. The domain should have been previously
- * paused.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain id to unpause
- * return 0 on success, -1 on failure
- */
-int xc_domain_unpause(xc_interface *xch,
- uint32_t domid);
-
-/**
- * This function will destroy a domain. Destroying a domain removes the domain
- * completely from memory. This function should be called after sending the
- * domain a SHUTDOWN control message to free up the domain resources.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain id to destroy
- * @return 0 on success, -1 on failure
- */
-int xc_domain_destroy(xc_interface *xch,
- uint32_t domid);
-
-
-/**
- * This function resumes a suspended domain. The domain should have
- * been previously suspended.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain id to resume
- * @parm fast use cooperative resume (guest must support this)
- * return 0 on success, -1 on failure
- */
-int xc_domain_resume(xc_interface *xch,
- uint32_t domid,
- int fast);
-
-/**
- * This function will shutdown a domain. This is intended for use in
- * fully-virtualized domains where this operation is analogous to the
- * sched_op operations in a paravirtualized domain. The caller is
- * expected to give the reason for the shutdown.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain id to destroy
- * @parm reason is the reason (SHUTDOWN_xxx) for the shutdown
- * @return 0 on success, -1 on failure
- */
-int xc_domain_shutdown(xc_interface *xch,
- uint32_t domid,
- int reason);
-
-int xc_watchdog(xc_interface *xch,
- uint32_t id,
- uint32_t timeout);
-
-/**
- * This function explicitly sets the host NUMA nodes the domain will
- * have affinity with.
- *
- * @parm xch a handle to an open hypervisor interface.
- * @parm domid the domain id one wants to set the affinity of.
- * @parm nodemap the map of the affine nodes.
- * @return 0 on success, -1 on failure.
- */
-int xc_domain_node_setaffinity(xc_interface *xch,
- uint32_t domind,
- xc_nodemap_t nodemap);
-
-/**
- * This function retrieves the host NUMA nodes the domain has
- * affinity with.
- *
- * @parm xch a handle to an open hypervisor interface.
- * @parm domid the domain id one wants to get the node affinity of.
- * @parm nodemap the map of the affine nodes.
- * @return 0 on success, -1 on failure.
- */
-int xc_domain_node_getaffinity(xc_interface *xch,
- uint32_t domind,
- xc_nodemap_t nodemap);
-
-int xc_vcpu_setaffinity(xc_interface *xch,
- uint32_t domid,
- int vcpu,
- xc_cpumap_t cpumap);
-int xc_vcpu_getaffinity(xc_interface *xch,
- uint32_t domid,
- int vcpu,
- xc_cpumap_t cpumap);
-
-
-/**
- * This function will return the guest_width (in bytes) for the
- * specified domain.
- *
- * @param xch a handle to an open hypervisor interface.
- * @param domid the domain id one wants the address size width of.
- * @param addr_size the address size.
- */
-int xc_domain_get_guest_width(xc_interface *xch, uint32_t domid,
- unsigned int *guest_width);
-
-
-/**
- * This function will return information about one or more domains. It is
- * designed to iterate over the list of domains. If a single domain is
- * requested, this function will return the next domain in the list - if
- * one exists. It is, therefore, important in this case to make sure the
- * domain requested was the one returned.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm first_domid the first domain to enumerate information from. Domains
- * are currently enumerate in order of creation.
- * @parm max_doms the number of elements in info
- * @parm info an array of max_doms size that will contain the information for
- * the enumerated domains.
- * @return the number of domains enumerated or -1 on error
- */
-int xc_domain_getinfo(xc_interface *xch,
- uint32_t first_domid,
- unsigned int max_doms,
- xc_dominfo_t *info);
-
-
-/**
- * This function will set the execution context for the specified vcpu.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain to set the vcpu context for
- * @parm vcpu the vcpu number for the context
- * @parm ctxt pointer to the the cpu context with the values to set
- * @return the number of domains enumerated or -1 on error
- */
-int xc_vcpu_setcontext(xc_interface *xch,
- uint32_t domid,
- uint32_t vcpu,
- vcpu_guest_context_any_t *ctxt);
-/**
- * This function will return information about one or more domains, using a
- * single hypercall. The domain information will be stored into the supplied
- * array of xc_domaininfo_t structures.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm first_domain the first domain to enumerate information from.
- * Domains are currently enumerate in order of creation.
- * @parm max_domains the number of elements in info
- * @parm info an array of max_doms size that will contain the information for
- * the enumerated domains.
- * @return the number of domains enumerated or -1 on error
- */
-int xc_domain_getinfolist(xc_interface *xch,
- uint32_t first_domain,
- unsigned int max_domains,
- xc_domaininfo_t *info);
-
-/**
- * This function set p2m for broken page
- * &parm xch a handle to an open hypervisor interface
- * @parm domid the domain id which broken page belong to
- * @parm pfn the pfn number of the broken page
- * @return 0 on success, -1 on failure
- */
-int xc_set_broken_page_p2m(xc_interface *xch,
- uint32_t domid,
- unsigned long pfn);
-
-/**
- * This function returns information about the context of a hvm domain
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain to get information from
- * @parm ctxt_buf a pointer to a structure to store the execution context of
- * the hvm domain
- * @parm size the size of ctxt_buf in bytes
- * @return 0 on success, -1 on failure
- */
-int xc_domain_hvm_getcontext(xc_interface *xch,
- uint32_t domid,
- uint8_t *ctxt_buf,
- uint32_t size);
-
-
-/**
- * This function returns one element of the context of a hvm domain
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain to get information from
- * @parm typecode which type of elemnt required
- * @parm instance which instance of the type
- * @parm ctxt_buf a pointer to a structure to store the execution context of
- * the hvm domain
- * @parm size the size of ctxt_buf (must be >= HVM_SAVE_LENGTH(typecode))
- * @return 0 on success, -1 on failure
- */
-int xc_domain_hvm_getcontext_partial(xc_interface *xch,
- uint32_t domid,
- uint16_t typecode,
- uint16_t instance,
- void *ctxt_buf,
- uint32_t size);
-
-/**
- * This function will set the context for hvm domain
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain to set the hvm domain context for
- * @parm hvm_ctxt pointer to the the hvm context with the values to set
- * @parm size the size of hvm_ctxt in bytes
- * @return 0 on success, -1 on failure
- */
-int xc_domain_hvm_setcontext(xc_interface *xch,
- uint32_t domid,
- uint8_t *hvm_ctxt,
- uint32_t size);
-
-/**
- * This function will return guest IO ABI protocol
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain to get IO ABI protocol for
- * @return guest protocol on success, NULL on failure
- */
-const char *xc_domain_get_native_protocol(xc_interface *xch,
- uint32_t domid);
-
-/**
- * This function returns information about the execution context of a
- * particular vcpu of a domain.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain to get information from
- * @parm vcpu the vcpu number
- * @parm ctxt a pointer to a structure to store the execution context of the
- * domain
- * @return 0 on success, -1 on failure
- */
-int xc_vcpu_getcontext(xc_interface *xch,
- uint32_t domid,
- uint32_t vcpu,
- vcpu_guest_context_any_t *ctxt);
-
-typedef xen_domctl_getvcpuinfo_t xc_vcpuinfo_t;
-int xc_vcpu_getinfo(xc_interface *xch,
- uint32_t domid,
- uint32_t vcpu,
- xc_vcpuinfo_t *info);
-
-long long xc_domain_get_cpu_usage(xc_interface *xch,
- domid_t domid,
- int vcpu);
-
-int xc_domain_sethandle(xc_interface *xch, uint32_t domid,
- xen_domain_handle_t handle);
-
-typedef xen_domctl_shadow_op_stats_t xc_shadow_op_stats_t;
-int xc_shadow_control(xc_interface *xch,
- uint32_t domid,
- unsigned int sop,
- xc_hypercall_buffer_t *dirty_bitmap,
- unsigned long pages,
- unsigned long *mb,
- uint32_t mode,
- xc_shadow_op_stats_t *stats);
-
-int xc_sedf_domain_set(xc_interface *xch,
- uint32_t domid,
- uint64_t period, uint64_t slice,
- uint64_t latency, uint16_t extratime,
- uint16_t weight);
-
-int xc_sedf_domain_get(xc_interface *xch,
- uint32_t domid,
- uint64_t* period, uint64_t *slice,
- uint64_t *latency, uint16_t *extratime,
- uint16_t *weight);
-
-int xc_sched_credit_domain_set(xc_interface *xch,
- uint32_t domid,
- struct xen_domctl_sched_credit *sdom);
-
-int xc_sched_credit_domain_get(xc_interface *xch,
- uint32_t domid,
- struct xen_domctl_sched_credit *sdom);
-int xc_sched_credit_params_set(xc_interface *xch,
- uint32_t cpupool_id,
- struct xen_sysctl_credit_schedule *schedule);
-int xc_sched_credit_params_get(xc_interface *xch,
- uint32_t cpupool_id,
- struct xen_sysctl_credit_schedule *schedule);
-int xc_sched_credit2_domain_set(xc_interface *xch,
- uint32_t domid,
- struct xen_domctl_sched_credit2 *sdom);
-
-int xc_sched_credit2_domain_get(xc_interface *xch,
- uint32_t domid,
- struct xen_domctl_sched_credit2 *sdom);
-
-int
-xc_sched_arinc653_schedule_set(
- xc_interface *xch,
- uint32_t cpupool_id,
- struct xen_sysctl_arinc653_schedule *schedule);
-
-int
-xc_sched_arinc653_schedule_get(
- xc_interface *xch,
- uint32_t cpupool_id,
- struct xen_sysctl_arinc653_schedule *schedule);
-
-/**
- * This function sends a trigger to a domain.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain id to send trigger
- * @parm trigger the trigger type
- * @parm vcpu the vcpu number to send trigger
- * return 0 on success, -1 on failure
- */
-int xc_domain_send_trigger(xc_interface *xch,
- uint32_t domid,
- uint32_t trigger,
- uint32_t vcpu);
-
-/**
- * This function enables or disable debugging of a domain.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain id to send trigger
- * @parm enable true to enable debugging
- * return 0 on success, -1 on failure
- */
-int xc_domain_setdebugging(xc_interface *xch,
- uint32_t domid,
- unsigned int enable);
-
-/**
- * This function audits the (top level) p2m of a domain
- * and returns the different error counts, if any.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain id whose top level p2m we
- * want to audit
- * @parm orphans count of m2p entries for valid
- * domain pages containing an invalid value
- * @parm m2p_bad count of m2p entries mismatching the
- * associated p2m entry for this domain
- * @parm p2m_bad count of p2m entries for this domain
- * mismatching the associated m2p entry
- * return 0 on success, -1 on failure
- * errno values on failure include:
- * -ENOSYS: not implemented
- * -EFAULT: could not copy results back to guest
- */
-int xc_domain_p2m_audit(xc_interface *xch,
- uint32_t domid,
- uint64_t *orphans,
- uint64_t *m2p_bad,
- uint64_t *p2m_bad);
-
-/**
- * This function sets or clears the requirement that an access memory
- * event listener is required on the domain.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain id to send trigger
- * @parm enable true to require a listener
- * return 0 on success, -1 on failure
- */
-int xc_domain_set_access_required(xc_interface *xch,
- uint32_t domid,
- unsigned int required);
-/**
- * This function sets the handler of global VIRQs sent by the hypervisor
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain id which will handle the VIRQ
- * @parm virq the virq number (VIRQ_*)
- * return 0 on success, -1 on failure
- */
-int xc_domain_set_virq_handler(xc_interface *xch, uint32_t domid, int virq);
-
-/**
- * Set the maximum event channel port a domain may bind.
- *
- * This does not affect ports that are already bound.
- *
- * @param xch a handle to an open hypervisor interface
- * @param domid the domain id
- * @param max_port maximum port number
- */
-int xc_domain_set_max_evtchn(xc_interface *xch, uint32_t domid,
- uint32_t max_port);
-
-/*
- * CPUPOOL MANAGEMENT FUNCTIONS
- */
-
-typedef struct xc_cpupoolinfo {
- uint32_t cpupool_id;
- uint32_t sched_id;
- uint32_t n_dom;
- xc_cpumap_t cpumap;
-} xc_cpupoolinfo_t;
-
-/**
- * Create a new cpupool.
- *
- * @parm xc_handle a handle to an open hypervisor interface
- * @parm ppoolid pointer to the new cpupool id (in/out)
- * @parm sched_id id of scheduler to use for pool
- * return 0 on success, -1 on failure
- */
-int xc_cpupool_create(xc_interface *xch,
- uint32_t *ppoolid,
- uint32_t sched_id);
-
-/**
- * Destroy a cpupool. Pool must be unused and have no cpu assigned.
- *
- * @parm xc_handle a handle to an open hypervisor interface
- * @parm poolid id of the cpupool to destroy
- * return 0 on success, -1 on failure
- */
-int xc_cpupool_destroy(xc_interface *xch,
- uint32_t poolid);
-
-/**
- * Get cpupool info. Returns info for up to the specified number of cpupools
- * starting at the given id.
- * @parm xc_handle a handle to an open hypervisor interface
- * @parm poolid lowest id for which info is returned
- * return cpupool info ptr (to be freed via xc_cpupool_infofree)
- */
-xc_cpupoolinfo_t *xc_cpupool_getinfo(xc_interface *xch,
- uint32_t poolid);
-
-/**
- * Free cpupool info. Used to free info obtained via xc_cpupool_getinfo.
- * @parm xc_handle a handle to an open hypervisor interface
- * @parm info area to free
- */
-void xc_cpupool_infofree(xc_interface *xch,
- xc_cpupoolinfo_t *info);
-
-/**
- * Add cpu to a cpupool. cpu may be -1 indicating the first unassigned.
- *
- * @parm xc_handle a handle to an open hypervisor interface
- * @parm poolid id of the cpupool
- * @parm cpu cpu number to add
- * return 0 on success, -1 on failure
- */
-int xc_cpupool_addcpu(xc_interface *xch,
- uint32_t poolid,
- int cpu);
-
-/**
- * Remove cpu from cpupool. cpu may be -1 indicating the last cpu of the pool.
- *
- * @parm xc_handle a handle to an open hypervisor interface
- * @parm poolid id of the cpupool
- * @parm cpu cpu number to remove
- * return 0 on success, -1 on failure
- */
-int xc_cpupool_removecpu(xc_interface *xch,
- uint32_t poolid,
- int cpu);
-
-/**
- * Move domain to another cpupool.
- *
- * @parm xc_handle a handle to an open hypervisor interface
- * @parm poolid id of the destination cpupool
- * @parm domid id of the domain to move
- * return 0 on success, -1 on failure
- */
-int xc_cpupool_movedomain(xc_interface *xch,
- uint32_t poolid,
- uint32_t domid);
-
-/**
- * Return map of cpus not in any cpupool.
- *
- * @parm xc_handle a handle to an open hypervisor interface
- * return cpumap array on success, NULL else
- */
-xc_cpumap_t xc_cpupool_freeinfo(xc_interface *xch);
-
-
-/*
- * EVENT CHANNEL FUNCTIONS
- *
- * None of these do any logging.
- */
-
-/* A port identifier is guaranteed to fit in 31 bits. */
-typedef int evtchn_port_or_error_t;
-
-/**
- * This function allocates an unbound port. Ports are named endpoints used for
- * interdomain communication. This function is most useful in opening a
- * well-known port within a domain to receive events on.
- *
- * NOTE: If you are allocating a *local* unbound port, you probably want to
- * use xc_evtchn_bind_unbound_port(). This function is intended for allocating
- * ports *only* during domain creation.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm dom the ID of the local domain (the 'allocatee')
- * @parm remote_dom the ID of the domain who will later bind
- * @return allocated port (in @dom) on success, -1 on failure
- */
-evtchn_port_or_error_t
-xc_evtchn_alloc_unbound(xc_interface *xch,
- uint32_t dom,
- uint32_t remote_dom);
-
-int xc_evtchn_reset(xc_interface *xch,
- uint32_t dom);
-
-typedef struct evtchn_status xc_evtchn_status_t;
-int xc_evtchn_status(xc_interface *xch, xc_evtchn_status_t *status);
-
-/*
- * Return a handle to the event channel driver, or NULL on failure, in
- * which case errno will be set appropriately.
- *
- * Note:
- * After fork a child process must not use any opened xc evtchn
- * handle inherited from their parent. They must open a new handle if
- * they want to interact with xc.
- *
- * Before Xen pre-4.1 this function would sometimes report errors with perror.
- */
-xc_evtchn *xc_evtchn_open(xentoollog_logger *logger,
- unsigned open_flags);
-
-/*
- * Close a handle previously allocated with xc_evtchn_open().
- */
-int xc_evtchn_close(xc_evtchn *xce);
-
-/*
- * Return an fd that can be select()ed on.
- *
- * Note that due to bugs, setting this fd to non blocking may not
- * work: you would hope that it would result in xc_evtchn_pending
- * failing with EWOULDBLOCK if there are no events signaled, but in
- * fact it may block. (Bug is present in at least Linux 3.12, and
- * perhaps on other platforms or later version.)
- *
- * To be safe, you must use poll() or select() before each call to
- * xc_evtchn_pending. If you have multiple threads (or processes)
- * sharing a single xce handle this will not work, and there is no
- * straightforward workaround. Please design your program some other
- * way.
- */
-int xc_evtchn_fd(xc_evtchn *xce);
-
-/*
- * Notify the given event channel. Returns -1 on failure, in which case
- * errno will be set appropriately.
- */
-int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port);
-
-/*
- * Returns a new event port awaiting interdomain connection from the given
- * domain ID, or -1 on failure, in which case errno will be set appropriately.
- */
-evtchn_port_or_error_t
-xc_evtchn_bind_unbound_port(xc_evtchn *xce, int domid);
-
-/*
- * Returns a new event port bound to the remote port for the given domain ID,
- * or -1 on failure, in which case errno will be set appropriately.
- */
-evtchn_port_or_error_t
-xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid,
- evtchn_port_t remote_port);
-
-/*
- * Bind an event channel to the given VIRQ. Returns the event channel bound to
- * the VIRQ, or -1 on failure, in which case errno will be set appropriately.
- */
-evtchn_port_or_error_t
-xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq);
-
-/*
- * Unbind the given event channel. Returns -1 on failure, in which case errno
- * will be set appropriately.
- */
-int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port);
-
-/*
- * Return the next event channel to become pending, or -1 on failure, in which
- * case errno will be set appropriately.
- *
- * At the hypervisor level the event channel will have been masked,
- * and then cleared, by the underlying machinery (evtchn kernel
- * driver, or equivalent). So if the event channel is signaled again
- * after it is returned here, it will be queued up, and delivered
- * again after you unmask it. (See the documentation in the Xen
- * public header event_channel.h.)
- *
- * On receiving the notification from xc_evtchn_pending, you should
- * normally: check (by other means) what work needs doing; do the
- * necessary work (if any); unmask the event channel with
- * xc_evtchn_unmask (if you want to receive any further
- * notifications).
- */
-evtchn_port_or_error_t
-xc_evtchn_pending(xc_evtchn *xce);
-
-/*
- * Unmask the given event channel. Returns -1 on failure, in which case errno
- * will be set appropriately.
- */
-int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port);
-
-int xc_physdev_pci_access_modify(xc_interface *xch,
- uint32_t domid,
- int bus,
- int dev,
- int func,
- int enable);
-
-int xc_readconsolering(xc_interface *xch,
- char *buffer,
- unsigned int *pnr_chars,
- int clear, int incremental, uint32_t *pindex);
-
-int xc_send_debug_keys(xc_interface *xch, char *keys);
-
-typedef xen_sysctl_physinfo_t xc_physinfo_t;
-typedef xen_sysctl_topologyinfo_t xc_topologyinfo_t;
-typedef xen_sysctl_numainfo_t xc_numainfo_t;
-
-typedef uint32_t xc_cpu_to_node_t;
-typedef uint32_t xc_cpu_to_socket_t;
-typedef uint32_t xc_cpu_to_core_t;
-typedef uint64_t xc_node_to_memsize_t;
-typedef uint64_t xc_node_to_memfree_t;
-typedef uint32_t xc_node_to_node_dist_t;
-
-int xc_physinfo(xc_interface *xch, xc_physinfo_t *info);
-int xc_topologyinfo(xc_interface *xch, xc_topologyinfo_t *info);
-int xc_numainfo(xc_interface *xch, xc_numainfo_t *info);
-
-int xc_sched_id(xc_interface *xch,
- int *sched_id);
-
-int xc_machphys_mfn_list(xc_interface *xch,
- unsigned long max_extents,
- xen_pfn_t *extent_start);
-
-typedef xen_sysctl_cpuinfo_t xc_cpuinfo_t;
-int xc_getcpuinfo(xc_interface *xch, int max_cpus,
- xc_cpuinfo_t *info, int *nr_cpus);
-
-int xc_domain_setmaxmem(xc_interface *xch,
- uint32_t domid,
- unsigned int max_memkb);
-
-int xc_domain_set_memmap_limit(xc_interface *xch,
- uint32_t domid,
- unsigned long map_limitkb);
-
-#if defined(__i386__) || defined(__x86_64__)
-/*
- * PC BIOS standard E820 types and structure.
- */
-#define E820_RAM 1
-#define E820_RESERVED 2
-#define E820_ACPI 3
-#define E820_NVS 4
-#define E820_UNUSABLE 5
-
-#define E820MAX (128)
-
-struct e820entry {
- uint64_t addr;
- uint64_t size;
- uint32_t type;
-} __attribute__((packed));
-int xc_domain_set_memory_map(xc_interface *xch,
- uint32_t domid,
- struct e820entry entries[],
- uint32_t nr_entries);
-
-int xc_get_machine_memory_map(xc_interface *xch,
- struct e820entry entries[],
- uint32_t max_entries);
-#endif
-int xc_domain_set_time_offset(xc_interface *xch,
- uint32_t domid,
- int32_t time_offset_seconds);
-
-int xc_domain_set_tsc_info(xc_interface *xch,
- uint32_t domid,
- uint32_t tsc_mode,
- uint64_t elapsed_nsec,
- uint32_t gtsc_khz,
- uint32_t incarnation);
-
-int xc_domain_get_tsc_info(xc_interface *xch,
- uint32_t domid,
- uint32_t *tsc_mode,
- uint64_t *elapsed_nsec,
- uint32_t *gtsc_khz,
- uint32_t *incarnation);
-
-int xc_domain_disable_migrate(xc_interface *xch, uint32_t domid);
-
-int xc_domain_maximum_gpfn(xc_interface *xch, domid_t domid);
-
-int xc_domain_increase_reservation(xc_interface *xch,
- uint32_t domid,
- unsigned long nr_extents,
- unsigned int extent_order,
- unsigned int mem_flags,
- xen_pfn_t *extent_start);
-
-int xc_domain_increase_reservation_exact(xc_interface *xch,
- uint32_t domid,
- unsigned long nr_extents,
- unsigned int extent_order,
- unsigned int mem_flags,
- xen_pfn_t *extent_start);
-
-int xc_domain_decrease_reservation(xc_interface *xch,
- uint32_t domid,
- unsigned long nr_extents,
- unsigned int extent_order,
- xen_pfn_t *extent_start);
-
-int xc_domain_decrease_reservation_exact(xc_interface *xch,
- uint32_t domid,
- unsigned long nr_extents,
- unsigned int extent_order,
- xen_pfn_t *extent_start);
-
-int xc_domain_add_to_physmap(xc_interface *xch,
- uint32_t domid,
- unsigned int space,
- unsigned long idx,
- xen_pfn_t gpfn);
-
-int xc_domain_populate_physmap(xc_interface *xch,
- uint32_t domid,
- unsigned long nr_extents,
- unsigned int extent_order,
- unsigned int mem_flags,
- xen_pfn_t *extent_start);
-
-int xc_domain_populate_physmap_exact(xc_interface *xch,
- uint32_t domid,
- unsigned long nr_extents,
- unsigned int extent_order,
- unsigned int mem_flags,
- xen_pfn_t *extent_start);
-
-int xc_domain_claim_pages(xc_interface *xch,
- uint32_t domid,
- unsigned long nr_pages);
-
-int xc_domain_memory_exchange_pages(xc_interface *xch,
- int domid,
- unsigned long nr_in_extents,
- unsigned int in_order,
- xen_pfn_t *in_extents,
- unsigned long nr_out_extents,
- unsigned int out_order,
- xen_pfn_t *out_extents);
-
-int xc_domain_set_pod_target(xc_interface *xch,
- uint32_t domid,
- uint64_t target_pages,
- uint64_t *tot_pages,
- uint64_t *pod_cache_pages,
- uint64_t *pod_entries);
-
-int xc_domain_get_pod_target(xc_interface *xch,
- uint32_t domid,
- uint64_t *tot_pages,
- uint64_t *pod_cache_pages,
- uint64_t *pod_entries);
-
-int xc_domain_ioport_permission(xc_interface *xch,
- uint32_t domid,
- uint32_t first_port,
- uint32_t nr_ports,
- uint32_t allow_access);
-
-int xc_domain_irq_permission(xc_interface *xch,
- uint32_t domid,
- uint8_t pirq,
- uint8_t allow_access);
-
-int xc_domain_iomem_permission(xc_interface *xch,
- uint32_t domid,
- unsigned long first_mfn,
- unsigned long nr_mfns,
- uint8_t allow_access);
-
-int xc_domain_pin_memory_cacheattr(xc_interface *xch,
- uint32_t domid,
- uint64_t start,
- uint64_t end,
- uint32_t type);
-
-unsigned long xc_make_page_below_4G(xc_interface *xch, uint32_t domid,
- unsigned long mfn);
-
-typedef xen_sysctl_perfc_desc_t xc_perfc_desc_t;
-typedef xen_sysctl_perfc_val_t xc_perfc_val_t;
-int xc_perfc_reset(xc_interface *xch);
-int xc_perfc_query_number(xc_interface *xch,
- int *nbr_desc,
- int *nbr_val);
-int xc_perfc_query(xc_interface *xch,
- xc_hypercall_buffer_t *desc,
- xc_hypercall_buffer_t *val);
-
-typedef xen_sysctl_lockprof_data_t xc_lockprof_data_t;
-int xc_lockprof_reset(xc_interface *xch);
-int xc_lockprof_query_number(xc_interface *xch,
- uint32_t *n_elems);
-int xc_lockprof_query(xc_interface *xch,
- uint32_t *n_elems,
- uint64_t *time,
- xc_hypercall_buffer_t *data);
-
-void *xc_memalign(xc_interface *xch, size_t alignment, size_t size);
-
-/**
- * Memory maps a range within one domain to a local address range. Mappings
- * should be unmapped with munmap and should follow the same rules as mmap
- * regarding page alignment. Returns NULL on failure.
- *
- * @parm xch a handle on an open hypervisor interface
- * @parm dom the domain to map memory from
- * @parm size the amount of memory to map (in multiples of page size)
- * @parm prot same flag as in mmap().
- * @parm mfn the frame address to map.
- */
-void *xc_map_foreign_range(xc_interface *xch, uint32_t dom,
- int size, int prot,
- unsigned long mfn );
-
-void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
- const xen_pfn_t *arr, int num );
-
-/**
- * DEPRECATED - use xc_map_foreign_bulk() instead.
- *
- * Like xc_map_foreign_pages(), except it can succeeed partially.
- * When a page cannot be mapped, its PFN in @arr is or'ed with
- * 0xF0000000 to indicate the error.
- */
-void *xc_map_foreign_batch(xc_interface *xch, uint32_t dom, int prot,
- xen_pfn_t *arr, int num );
-
-/**
- * Like xc_map_foreign_pages(), except it can succeed partially.
- * When a page cannot be mapped, its respective field in @err is
- * set to the corresponding errno value.
- */
-void *xc_map_foreign_bulk(xc_interface *xch, uint32_t dom, int prot,
- const xen_pfn_t *arr, int *err, unsigned int num);
-
-/**
- * Translates a virtual address in the context of a given domain and
- * vcpu returning the GFN containing the address (that is, an MFN for
- * PV guests, a PFN for HVM guests). Returns 0 for failure.
- *
- * @parm xch a handle on an open hypervisor interface
- * @parm dom the domain to perform the translation in
- * @parm vcpu the vcpu to perform the translation on
- * @parm virt the virtual address to translate
- */
-unsigned long xc_translate_foreign_address(xc_interface *xch, uint32_t dom,
- int vcpu, unsigned long long virt);
-
-
-/**
- * DEPRECATED. Avoid using this, as it does not correctly account for PFNs
- * without a backing MFN.
- */
-int xc_get_pfn_list(xc_interface *xch, uint32_t domid, uint64_t *pfn_buf,
- unsigned long max_pfns);
-
-int xc_copy_to_domain_page(xc_interface *xch, uint32_t domid,
- unsigned long dst_pfn, const char *src_page);
-
-int xc_clear_domain_page(xc_interface *xch, uint32_t domid,
- unsigned long dst_pfn);
-
-int xc_mmuext_op(xc_interface *xch, struct mmuext_op *op, unsigned int nr_ops,
- domid_t dom);
-
-/* System wide memory properties */
-long xc_maximum_ram_page(xc_interface *xch);
-
-/* Get current total pages allocated to a domain. */
-long xc_get_tot_pages(xc_interface *xch, uint32_t domid);
-
-/**
- * This function retrieves the the number of bytes available
- * in the heap in a specific range of address-widths and nodes.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the domain to query
- * @parm min_width the smallest address width to query (0 if don't care)
- * @parm max_width the largest address width to query (0 if don't care)
- * @parm node the node to query (-1 for all)
- * @parm *bytes caller variable to put total bytes counted
- * @return 0 on success, <0 on failure.
- */
-int xc_availheap(xc_interface *xch, int min_width, int max_width, int node,
- uint64_t *bytes);
-
-/*
- * Trace Buffer Operations
- */
-
-/**
- * xc_tbuf_enable - enable tracing buffers
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm cnt size of tracing buffers to create (in pages)
- * @parm mfn location to store mfn of the trace buffers to
- * @parm size location to store the size (in bytes) of a trace buffer to
- *
- * Gets the machine address of the trace pointer area and the size of the
- * per CPU buffers.
- */
-int xc_tbuf_enable(xc_interface *xch, unsigned long pages,
- unsigned long *mfn, unsigned long *size);
-
-/*
- * Disable tracing buffers.
- */
-int xc_tbuf_disable(xc_interface *xch);
-
-/**
- * This function sets the size of the trace buffers. Setting the size
- * is currently a one-shot operation that may be performed either at boot
- * time or via this interface, not both. The buffer size must be set before
- * enabling tracing.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm size the size in pages per cpu for the trace buffers
- * @return 0 on success, -1 on failure.
- */
-int xc_tbuf_set_size(xc_interface *xch, unsigned long size);
-
-/**
- * This function retrieves the current size of the trace buffers.
- * Note that the size returned is in terms of bytes, not pages.
-
- * @parm xch a handle to an open hypervisor interface
- * @parm size will contain the size in bytes for the trace buffers
- * @return 0 on success, -1 on failure.
- */
-int xc_tbuf_get_size(xc_interface *xch, unsigned long *size);
-
-int xc_tbuf_set_cpu_mask(xc_interface *xch, uint32_t mask);
-
-int xc_tbuf_set_evt_mask(xc_interface *xch, uint32_t mask);
-
-int xc_domctl(xc_interface *xch, struct xen_domctl *domctl);
-int xc_sysctl(xc_interface *xch, struct xen_sysctl *sysctl);
-
-int xc_version(xc_interface *xch, int cmd, void *arg);
-
-int xc_flask_op(xc_interface *xch, xen_flask_op_t *op);
-
-/*
- * Subscribe to domain suspend via evtchn.
- * Returns -1 on failure, in which case errno will be set appropriately.
- * Just calls XEN_DOMCTL_subscribe - see the caveats for that domctl
- * (in its doc comment in domctl.h).
- */
-int xc_domain_subscribe_for_suspend(
- xc_interface *xch, domid_t domid, evtchn_port_t port);
-
-/**************************
- * GRANT TABLE OPERATIONS *
- **************************/
-
-/*
- * These functions sometimes log messages as above, but not always.
- */
-
-/*
- * Note:
- * After fork a child process must not use any opened xc gnttab
- * handle inherited from their parent. They must open a new handle if
- * they want to interact with xc.
- *
- * Return an fd onto the grant table driver. Logs errors.
- */
-xc_gnttab *xc_gnttab_open(xentoollog_logger *logger,
- unsigned open_flags);
-
-/*
- * Close a handle previously allocated with xc_gnttab_open().
- * Never logs errors.
- */
-int xc_gnttab_close(xc_gnttab *xcg);
-
-/*
- * Memory maps a grant reference from one domain to a local address range.
- * Mappings should be unmapped with xc_gnttab_munmap. Logs errors.
- *
- * @parm xcg a handle on an open grant table interface
- * @parm domid the domain to map memory from
- * @parm ref the grant reference ID to map
- * @parm prot same flag as in mmap()
- */
-void *xc_gnttab_map_grant_ref(xc_gnttab *xcg,
- uint32_t domid,
- uint32_t ref,
- int prot);
-
-/**
- * Memory maps one or more grant references from one or more domains to a
- * contiguous local address range. Mappings should be unmapped with
- * xc_gnttab_munmap. Logs errors.
- *
- * @parm xcg a handle on an open grant table interface
- * @parm count the number of grant references to be mapped
- * @parm domids an array of @count domain IDs by which the corresponding @refs
- * were granted
- * @parm refs an array of @count grant references to be mapped
- * @parm prot same flag as in mmap()
- */
-void *xc_gnttab_map_grant_refs(xc_gnttab *xcg,
- uint32_t count,
- uint32_t *domids,
- uint32_t *refs,
- int prot);
-
-/**
- * Memory maps one or more grant references from one domain to a
- * contiguous local address range. Mappings should be unmapped with
- * xc_gnttab_munmap. Logs errors.
- *
- * @parm xcg a handle on an open grant table interface
- * @parm count the number of grant references to be mapped
- * @parm domid the domain to map memory from
- * @parm refs an array of @count grant references to be mapped
- * @parm prot same flag as in mmap()
- */
-void *xc_gnttab_map_domain_grant_refs(xc_gnttab *xcg,
- uint32_t count,
- uint32_t domid,
- uint32_t *refs,
- int prot);
-
-/**
- * Memory maps a grant reference from one domain to a local address range.
- * Mappings should be unmapped with xc_gnttab_munmap. If notify_offset or
- * notify_port are not -1, this version will attempt to set up an unmap
- * notification at the given offset and event channel. When the page is
- * unmapped, the byte at the given offset will be zeroed and a wakeup will be
- * sent to the given event channel. Logs errors.
- *
- * @parm xcg a handle on an open grant table interface
- * @parm domid the domain to map memory from
- * @parm ref the grant reference ID to map
- * @parm prot same flag as in mmap()
- * @parm notify_offset The byte offset in the page to use for unmap
- * notification; -1 for none.
- * @parm notify_port The event channel port to use for unmap notify, or -1
- */
-void *xc_gnttab_map_grant_ref_notify(xc_gnttab *xcg,
- uint32_t domid,
- uint32_t ref,
- int prot,
- uint32_t notify_offset,
- evtchn_port_t notify_port);
-
-/*
- * Unmaps the @count pages starting at @start_address, which were mapped by a
- * call to xc_gnttab_map_grant_ref or xc_gnttab_map_grant_refs. Never logs.
- */
-int xc_gnttab_munmap(xc_gnttab *xcg,
- void *start_address,
- uint32_t count);
-
-/*
- * Sets the maximum number of grants that may be mapped by the given instance
- * to @count. Never logs.
- *
- * N.B. This function must be called after opening the handle, and before any
- * other functions are invoked on it.
- *
- * N.B. When variable-length grants are mapped, fragmentation may be observed,
- * and it may not be possible to satisfy requests up to the maximum number
- * of grants.
- */
-int xc_gnttab_set_max_grants(xc_gnttab *xcg,
- uint32_t count);
-
-int xc_gnttab_op(xc_interface *xch, int cmd,
- void * op, int op_size, int count);
-/* Logs iff hypercall bounce fails, otherwise doesn't. */
-
-int xc_gnttab_get_version(xc_interface *xch, int domid); /* Never logs */
-grant_entry_v1_t *xc_gnttab_map_table_v1(xc_interface *xch, int domid, int *gnt_num);
-grant_entry_v2_t *xc_gnttab_map_table_v2(xc_interface *xch, int domid, int *gnt_num);
-/* Sometimes these don't set errno [fixme], and sometimes they don't log. */
-
-/*
- * Return an fd onto the grant sharing driver. Logs errors.
- *
- * Note:
- * After fork a child process must not use any opened xc gntshr
- * handle inherited from their parent. They must open a new handle if
- * they want to interact with xc.
- *
- */
-xc_gntshr *xc_gntshr_open(xentoollog_logger *logger,
- unsigned open_flags);
-
-/*
- * Close a handle previously allocated with xc_gntshr_open().
- * Never logs errors.
- */
-int xc_gntshr_close(xc_gntshr *xcg);
-
-/*
- * Creates and shares pages with another domain.
- *
- * @parm xcg a handle to an open grant sharing instance
- * @parm domid the domain to share memory with
- * @parm count the number of pages to share
- * @parm refs the grant references of the pages (output)
- * @parm writable true if the other domain can write to the pages
- * @return local mapping of the pages
- */
-void *xc_gntshr_share_pages(xc_gntshr *xcg, uint32_t domid,
- int count, uint32_t *refs, int writable);
-
-/*
- * Creates and shares a page with another domain, with unmap notification.
- *
- * @parm xcg a handle to an open grant sharing instance
- * @parm domid the domain to share memory with
- * @parm refs the grant reference of the pages (output)
- * @parm writable true if the other domain can write to the page
- * @parm notify_offset The byte offset in the page to use for unmap
- * notification; -1 for none.
- * @parm notify_port The event channel port to use for unmap notify, or -1
- * @return local mapping of the page
- */
-void *xc_gntshr_share_page_notify(xc_gntshr *xcg, uint32_t domid,
- uint32_t *ref, int writable,
- uint32_t notify_offset,
- evtchn_port_t notify_port);
-/*
- * Unmaps the @count pages starting at @start_address, which were mapped by a
- * call to xc_gntshr_share_*. Never logs.
- */
-int xc_gntshr_munmap(xc_gntshr *xcg, void *start_address, uint32_t count);
-
-int xc_physdev_map_pirq(xc_interface *xch,
- int domid,
- int index,
- int *pirq);
-
-int xc_physdev_map_pirq_msi(xc_interface *xch,
- int domid,
- int index,
- int *pirq,
- int devfn,
- int bus,
- int entry_nr,
- uint64_t table_base);
-
-int xc_physdev_unmap_pirq(xc_interface *xch,
- int domid,
- int pirq);
-
-int xc_hvm_set_pci_intx_level(
- xc_interface *xch, domid_t dom,
- uint8_t domain, uint8_t bus, uint8_t device, uint8_t intx,
- unsigned int level);
-int xc_hvm_set_isa_irq_level(
- xc_interface *xch, domid_t dom,
- uint8_t isa_irq,
- unsigned int level);
-
-int xc_hvm_set_pci_link_route(
- xc_interface *xch, domid_t dom, uint8_t link, uint8_t isa_irq);
-
-int xc_hvm_inject_msi(
- xc_interface *xch, domid_t dom, uint64_t addr, uint32_t data);
-
-/*
- * Track dirty bit changes in the VRAM area
- *
- * All of this is done atomically:
- * - get the dirty bitmap since the last call
- * - set up dirty tracking area for period up to the next call
- * - clear the dirty tracking area.
- *
- * Returns -ENODATA and does not fill bitmap if the area has changed since the
- * last call.
- */
-int xc_hvm_track_dirty_vram(
- xc_interface *xch, domid_t dom,
- uint64_t first_pfn, uint64_t nr,
- unsigned long *bitmap);
-
-/*
- * Notify that some pages got modified by the Device Model
- */
-int xc_hvm_modified_memory(
- xc_interface *xch, domid_t dom, uint64_t first_pfn, uint64_t nr);
-
-/*
- * Set a range of memory to a specific type.
- * Allowed types are HVMMEM_ram_rw, HVMMEM_ram_ro, HVMMEM_mmio_dm
- */
-int xc_hvm_set_mem_type(
- xc_interface *xch, domid_t dom, hvmmem_type_t memtype, uint64_t first_pfn, uint64_t nr);
-
-/*
- * Set a range of memory to a specific access.
- * Allowed types are HVMMEM_access_default, HVMMEM_access_n, any combination of
- * HVM_access_ + (rwx), and HVM_access_rx2rw
- */
-int xc_hvm_set_mem_access(
- xc_interface *xch, domid_t dom, hvmmem_access_t memaccess, uint64_t first_pfn, uint64_t nr);
-
-/*
- * Gets the mem access for the given page (returned in memacess on success)
- */
-int xc_hvm_get_mem_access(
- xc_interface *xch, domid_t dom, uint64_t pfn, hvmmem_access_t* memaccess);
-
-/*
- * Injects a hardware/software CPU trap, to take effect the next time the HVM
- * resumes.
- */
-int xc_hvm_inject_trap(
- xc_interface *xch, domid_t dom, int vcpu, uint32_t vector,
- uint32_t type, uint32_t error_code, uint32_t insn_len,
- uint64_t cr2);
-
-/*
- * LOGGING AND ERROR REPORTING
- */
-
-
-enum xc_error_code {
- XC_ERROR_NONE = 0,
- XC_INTERNAL_ERROR = 1,
- XC_INVALID_KERNEL = 2,
- XC_INVALID_PARAM = 3,
- XC_OUT_OF_MEMORY = 4,
- /* new codes need to be added to xc_error_level_to_desc too */
-};
-
-#define XC_MAX_ERROR_MSG_LEN 1024
-typedef struct xc_error {
- enum xc_error_code code;
- char message[XC_MAX_ERROR_MSG_LEN];
-} xc_error;
-
-
-/*
- * Convert an error code or level into a text description. Return values
- * are pointers to fixed strings and do not need to be freed.
- * Do not fail, but return pointers to generic strings if fed bogus input.
- */
-const char *xc_error_code_to_desc(int code);
-
-/*
- * Convert an errno value to a text description.
- */
-const char *xc_strerror(xc_interface *xch, int errcode);
-
-
-/*
- * Return a pointer to the last error with level XC_REPORT_ERROR. This
- * pointer and the data pointed to are only valid until the next call
- * to libxc in the same thread.
- */
-const xc_error *xc_get_last_error(xc_interface *handle);
-
-/*
- * Clear the last error
- */
-void xc_clear_last_error(xc_interface *xch);
-
-
-int xc_set_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long value);
-int xc_get_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long *value);
-
-/* HVM guest pass-through */
-int xc_assign_device(xc_interface *xch,
- uint32_t domid,
- uint32_t machine_bdf);
-
-int xc_get_device_group(xc_interface *xch,
- uint32_t domid,
- uint32_t machine_bdf,
- uint32_t max_sdevs,
- uint32_t *num_sdevs,
- uint32_t *sdev_array);
-
-int xc_test_assign_device(xc_interface *xch,
- uint32_t domid,
- uint32_t machine_bdf);
-
-int xc_deassign_device(xc_interface *xch,
- uint32_t domid,
- uint32_t machine_bdf);
-
-int xc_domain_memory_mapping(xc_interface *xch,
- uint32_t domid,
- unsigned long first_gfn,
- unsigned long first_mfn,
- unsigned long nr_mfns,
- uint32_t add_mapping);
-
-int xc_domain_ioport_mapping(xc_interface *xch,
- uint32_t domid,
- uint32_t first_gport,
- uint32_t first_mport,
- uint32_t nr_ports,
- uint32_t add_mapping);
-
-int xc_domain_update_msi_irq(
- xc_interface *xch,
- uint32_t domid,
- uint32_t gvec,
- uint32_t pirq,
- uint32_t gflags,
- uint64_t gtable);
-
-int xc_domain_unbind_msi_irq(xc_interface *xch,
- uint32_t domid,
- uint32_t gvec,
- uint32_t pirq,
- uint32_t gflags);
-
-int xc_domain_bind_pt_irq(xc_interface *xch,
- uint32_t domid,
- uint8_t machine_irq,
- uint8_t irq_type,
- uint8_t bus,
- uint8_t device,
- uint8_t intx,
- uint8_t isa_irq);
-
-int xc_domain_unbind_pt_irq(xc_interface *xch,
- uint32_t domid,
- uint8_t machine_irq,
- uint8_t irq_type,
- uint8_t bus,
- uint8_t device,
- uint8_t intx,
- uint8_t isa_irq);
-
-int xc_domain_bind_pt_pci_irq(xc_interface *xch,
- uint32_t domid,
- uint8_t machine_irq,
- uint8_t bus,
- uint8_t device,
- uint8_t intx);
-
-int xc_domain_bind_pt_isa_irq(xc_interface *xch,
- uint32_t domid,
- uint8_t machine_irq);
-
-int xc_domain_set_machine_address_size(xc_interface *xch,
- uint32_t domid,
- unsigned int width);
-int xc_domain_get_machine_address_size(xc_interface *xch,
- uint32_t domid);
-
-int xc_domain_suppress_spurious_page_faults(xc_interface *xch,
- uint32_t domid);
-
-/* Set the target domain */
-int xc_domain_set_target(xc_interface *xch,
- uint32_t domid,
- uint32_t target);
-
-/* Control the domain for debug */
-int xc_domain_debug_control(xc_interface *xch,
- uint32_t domid,
- uint32_t sop,
- uint32_t vcpu);
-
-#if defined(__i386__) || defined(__x86_64__)
-int xc_cpuid_check(xc_interface *xch,
- const unsigned int *input,
- const char **config,
- char **config_transformed);
-int xc_cpuid_set(xc_interface *xch,
- domid_t domid,
- const unsigned int *input,
- const char **config,
- char **config_transformed);
-int xc_cpuid_apply_policy(xc_interface *xch,
- domid_t domid);
-void xc_cpuid_to_str(const unsigned int *regs,
- char **strs); /* some strs[] may be NULL if ENOMEM */
-int xc_mca_op(xc_interface *xch, struct xen_mc *mc);
-#endif
-
-struct xc_px_val {
- uint64_t freq; /* Px core frequency */
- uint64_t residency; /* Px residency time */
- uint64_t count; /* Px transition count */
-};
-
-struct xc_px_stat {
- uint8_t total; /* total Px states */
- uint8_t usable; /* usable Px states */
- uint8_t last; /* last Px state */
- uint8_t cur; /* current Px state */
- uint64_t *trans_pt; /* Px transition table */
- struct xc_px_val *pt;
-};
-
-int xc_pm_get_max_px(xc_interface *xch, int cpuid, int *max_px);
-int xc_pm_get_pxstat(xc_interface *xch, int cpuid, struct xc_px_stat *pxpt);
-int xc_pm_reset_pxstat(xc_interface *xch, int cpuid);
-
-struct xc_cx_stat {
- uint32_t nr; /* entry nr in triggers & residencies, including C0 */
- uint32_t last; /* last Cx state */
- uint64_t idle_time; /* idle time from boot */
- uint64_t *triggers; /* Cx trigger counts */
- uint64_t *residencies; /* Cx residencies */
- uint64_t pc2;
- uint64_t pc3;
- uint64_t pc6;
- uint64_t pc7;
- uint64_t cc3;
- uint64_t cc6;
- uint64_t cc7;
-};
-typedef struct xc_cx_stat xc_cx_stat_t;
-
-int xc_pm_get_max_cx(xc_interface *xch, int cpuid, int *max_cx);
-int xc_pm_get_cxstat(xc_interface *xch, int cpuid, struct xc_cx_stat *cxpt);
-int xc_pm_reset_cxstat(xc_interface *xch, int cpuid);
-
-int xc_cpu_online(xc_interface *xch, int cpu);
-int xc_cpu_offline(xc_interface *xch, int cpu);
-
-/*
- * cpufreq para name of this structure named
- * same as sysfs file name of native linux
- */
-typedef xen_userspace_t xc_userspace_t;
-typedef xen_ondemand_t xc_ondemand_t;
-
-struct xc_get_cpufreq_para {
- /* IN/OUT variable */
- uint32_t cpu_num;
- uint32_t freq_num;
- uint32_t gov_num;
-
- /* for all governors */
- /* OUT variable */
- uint32_t *affected_cpus;
- uint32_t *scaling_available_frequencies;
- char *scaling_available_governors;
- char scaling_driver[CPUFREQ_NAME_LEN];
-
- uint32_t cpuinfo_cur_freq;
- uint32_t cpuinfo_max_freq;
- uint32_t cpuinfo_min_freq;
- uint32_t scaling_cur_freq;
-
- char scaling_governor[CPUFREQ_NAME_LEN];
- uint32_t scaling_max_freq;
- uint32_t scaling_min_freq;
-
- /* for specific governor */
- union {
- xc_userspace_t userspace;
- xc_ondemand_t ondemand;
- } u;
-
- int32_t turbo_enabled;
-};
-
-int xc_get_cpufreq_para(xc_interface *xch, int cpuid,
- struct xc_get_cpufreq_para *user_para);
-int xc_set_cpufreq_gov(xc_interface *xch, int cpuid, char *govname);
-int xc_set_cpufreq_para(xc_interface *xch, int cpuid,
- int ctrl_type, int ctrl_value);
-int xc_get_cpufreq_avgfreq(xc_interface *xch, int cpuid, int *avg_freq);
-
-int xc_set_sched_opt_smt(xc_interface *xch, uint32_t value);
-int xc_set_vcpu_migration_delay(xc_interface *xch, uint32_t value);
-int xc_get_vcpu_migration_delay(xc_interface *xch, uint32_t *value);
-
-int xc_get_cpuidle_max_cstate(xc_interface *xch, uint32_t *value);
-int xc_set_cpuidle_max_cstate(xc_interface *xch, uint32_t value);
-
-int xc_enable_turbo(xc_interface *xch, int cpuid);
-int xc_disable_turbo(xc_interface *xch, int cpuid);
-/**
- * tmem operations
- */
-
-struct tmem_oid {
- uint64_t oid[3];
-};
-
-int xc_tmem_control_oid(xc_interface *xch, int32_t pool_id, uint32_t subop,
- uint32_t cli_id, uint32_t arg1, uint32_t arg2,
- struct tmem_oid oid, void *buf);
-int xc_tmem_control(xc_interface *xch,
- int32_t pool_id, uint32_t subop, uint32_t cli_id,
- uint32_t arg1, uint32_t arg2, uint64_t arg3, void *buf);
-int xc_tmem_auth(xc_interface *xch, int cli_id, char *uuid_str, int arg1);
-int xc_tmem_save(xc_interface *xch, int dom, int live, int fd, int field_marker);
-int xc_tmem_save_extra(xc_interface *xch, int dom, int fd, int field_marker);
-void xc_tmem_save_done(xc_interface *xch, int dom);
-int xc_tmem_restore(xc_interface *xch, int dom, int fd);
-int xc_tmem_restore_extra(xc_interface *xch, int dom, int fd);
-
-/**
- * mem_event operations. Internal use only.
- */
-int xc_mem_event_control(xc_interface *xch, domid_t domain_id, unsigned int op,
- unsigned int mode, uint32_t *port);
-int xc_mem_event_memop(xc_interface *xch, domid_t domain_id,
- unsigned int op, unsigned int mode,
- uint64_t gfn, void *buffer);
-
-/**
- * Mem paging operations.
- * Paging is supported only on the x86 architecture in 64 bit mode, with
- * Hardware-Assisted Paging (i.e. Intel EPT, AMD NPT). Moreover, AMD NPT
- * support is considered experimental.
- */
-int xc_mem_paging_enable(xc_interface *xch, domid_t domain_id, uint32_t *port);
-int xc_mem_paging_disable(xc_interface *xch, domid_t domain_id);
-int xc_mem_paging_nominate(xc_interface *xch, domid_t domain_id,
- unsigned long gfn);
-int xc_mem_paging_evict(xc_interface *xch, domid_t domain_id, unsigned long gfn);
-int xc_mem_paging_prep(xc_interface *xch, domid_t domain_id, unsigned long gfn);
-int xc_mem_paging_load(xc_interface *xch, domid_t domain_id,
- unsigned long gfn, void *buffer);
-
-/**
- * Access tracking operations.
- * Supported only on Intel EPT 64 bit processors.
- */
-int xc_mem_access_enable(xc_interface *xch, domid_t domain_id, uint32_t *port);
-int xc_mem_access_disable(xc_interface *xch, domid_t domain_id);
-int xc_mem_access_resume(xc_interface *xch, domid_t domain_id,
- unsigned long gfn);
-
-/***
- * Memory sharing operations.
- *
- * Unles otherwise noted, these calls return 0 on succes, -1 and errno on
- * failure.
- *
- * Sharing is supported only on the x86 architecture in 64 bit mode, with
- * Hardware-Assisted Paging (i.e. Intel EPT, AMD NPT). Moreover, AMD NPT
- * support is considered experimental.
-
- * Calls below return ENOSYS if not in the x86_64 architecture.
- * Calls below return ENODEV if the domain does not support HAP.
- * Calls below return ESRCH if the specified domain does not exist.
- * Calls below return EPERM if the caller is unprivileged for this domain.
- */
-
-/* Turn on/off sharing for the domid, depending on the enable flag.
- *
- * Returns EXDEV if trying to enable and the domain has had a PCI device
- * assigned for passthrough (these two features are mutually exclusive).
- *
- * When sharing for a domain is turned off, the domain may still reference
- * shared pages. Unsharing happens lazily. */
-int xc_memshr_control(xc_interface *xch,
- domid_t domid,
- int enable);
-
-/* Create a communication ring in which the hypervisor will place ENOMEM
- * notifications.
- *
- * ENOMEM happens when unsharing pages: a Copy-on-Write duplicate needs to be
- * allocated, and thus the out-of-memory error occurr.
- *
- * For complete examples on how to plumb a notification ring, look into
- * xenpaging or xen-access.
- *
- * On receipt of a notification, the helper should ensure there is memory
- * available to the domain before retrying.
- *
- * If a domain encounters an ENOMEM condition when sharing and this ring
- * has not been set up, the hypervisor will crash the domain.
- *
- * Fails with:
- * EINVAL if port is NULL
- * EINVAL if the sharing ring has already been enabled
- * ENOSYS if no guest gfn has been specified to host the ring via an hvm param
- * EINVAL if the gfn for the ring has not been populated
- * ENOENT if the gfn for the ring is paged out, or cannot be unshared
- * EINVAL if the gfn for the ring cannot be written to
- * EINVAL if the domain is dying
- * ENOSPC if an event channel cannot be allocated for the ring
- * ENOMEM if memory cannot be allocated for internal data structures
- * EINVAL or EACCESS if the request is denied by the security policy
- */
-
-int xc_memshr_ring_enable(xc_interface *xch,
- domid_t domid,
- uint32_t *port);
-/* Disable the ring for ENOMEM communication.
- * May fail with EINVAL if the ring was not enabled in the first place.
- */
-int xc_memshr_ring_disable(xc_interface *xch,
- domid_t domid);
-
-/*
- * Calls below return EINVAL if sharing has not been enabled for the domain
- * Calls below return EINVAL if the domain is dying
- */
-/* Once a reponse to an ENOMEM notification is prepared, the tool can
- * notify the hypervisor to re-schedule the faulting vcpu of the domain with an
- * event channel kick and/or this call. */
-int xc_memshr_domain_resume(xc_interface *xch,
- domid_t domid);
-
-/* Select a page for sharing.
- *
- * A 64 bit opaque handle will be stored in handle. The hypervisor ensures
- * that if the page is modified, the handle will be invalidated, and future
- * users of it will fail. If the page has already been selected and is still
- * associated to a valid handle, the existing handle will be returned.
- *
- * May fail with:
- * EINVAL if the gfn is not populated or not sharable (mmio, etc)
- * ENOMEM if internal data structures cannot be allocated
- * E2BIG if the page is being referenced by other subsytems (e.g. qemu)
- * ENOENT or EEXIST if there are internal hypervisor errors.
- */
-int xc_memshr_nominate_gfn(xc_interface *xch,
- domid_t domid,
- unsigned long gfn,
- uint64_t *handle);
-/* Same as above, but instead of a guest frame number, the input is a grant
- * reference provided by the guest.
- *
- * May fail with EINVAL if the grant reference is invalid.
- */
-int xc_memshr_nominate_gref(xc_interface *xch,
- domid_t domid,
- grant_ref_t gref,
- uint64_t *handle);
-
-/* The three calls below may fail with
- * 10 (or -XENMEM_SHARING_OP_S_HANDLE_INVALID) if the handle passed as source
- * is invalid.
- * 9 (or -XENMEM_SHARING_OP_C_HANDLE_INVALID) if the handle passed as client is
- * invalid.
- */
-/* Share two nominated guest pages.
- *
- * If the call succeeds, both pages will point to the same backing frame (or
- * mfn). The hypervisor will verify the handles are still valid, but it will
- * not perform any sanity checking on the contens of the pages (the selection
- * mechanism for sharing candidates is entirely up to the user-space tool).
- *
- * After successful sharing, the client handle becomes invalid. Both <domain,
- * gfn> tuples point to the same mfn with the same handle, the one specified as
- * source. Either 3-tuple can be specified later for further re-sharing.
- */
-int xc_memshr_share_gfns(xc_interface *xch,
- domid_t source_domain,
- unsigned long source_gfn,
- uint64_t source_handle,
- domid_t client_domain,
- unsigned long client_gfn,
- uint64_t client_handle);
-
-/* Same as above, but share two grant references instead.
- *
- * May fail with EINVAL if either grant reference is invalid.
- */
-int xc_memshr_share_grefs(xc_interface *xch,
- domid_t source_domain,
- grant_ref_t source_gref,
- uint64_t source_handle,
- domid_t client_domain,
- grant_ref_t client_gref,
- uint64_t client_handle);
-
-/* Allows to add to the guest physmap of the client domain a shared frame
- * directly.
- *
- * May additionally fail with
- * 9 (-XENMEM_SHARING_OP_C_HANDLE_INVALID) if the physmap entry for the gfn is
- * not suitable.
- * ENOMEM if internal data structures cannot be allocated.
- * ENOENT if there is an internal hypervisor error.
- */
-int xc_memshr_add_to_physmap(xc_interface *xch,
- domid_t source_domain,
- unsigned long source_gfn,
- uint64_t source_handle,
- domid_t client_domain,
- unsigned long client_gfn);
-
-/* Debug calls: return the number of pages referencing the shared frame backing
- * the input argument. Should be one or greater.
- *
- * May fail with EINVAL if there is no backing shared frame for the input
- * argument.
- */
-int xc_memshr_debug_gfn(xc_interface *xch,
- domid_t domid,
- unsigned long gfn);
-/* May additionally fail with EINVAL if the grant reference is invalid. */
-int xc_memshr_debug_gref(xc_interface *xch,
- domid_t domid,
- grant_ref_t gref);
-
-/* Audits the share subsystem.
- *
- * Returns ENOSYS if not supported (may not be compiled into the hypervisor).
- *
- * Returns the number of errors found during auditing otherwise. May be (should
- * be!) zero.
- *
- * If debugtrace support has been compiled into the hypervisor and is enabled,
- * verbose descriptions for the errors are available in the hypervisor console.
- */
-int xc_memshr_audit(xc_interface *xch);
-
-/* Stats reporting.
- *
- * At any point in time, the following equality should hold for a host:
- *
- * Let dominfo(d) be the xc_dominfo_t struct filled by a call to
- * xc_domain_getinfo(d)
- *
- * The summation of dominfo(d)->shr_pages for all domains in the system
- * should be equal to
- * xc_sharing_freed_pages + xc_sharing_used_frames
- */
-/*
- * This function returns the total number of pages freed by using sharing
- * on the system. For example, if two domains contain a single entry in
- * their p2m table that points to the same shared page (and no other pages
- * in the system are shared), then this function should return 1.
- */
-long xc_sharing_freed_pages(xc_interface *xch);
-
-/*
- * This function returns the total number of frames occupied by shared
- * pages on the system. This is independent of the number of domains
- * pointing at these frames. For example, in the above scenario this
- * should return 1. (And dominfo(d) for each of the two domains should return 1
- * as well).
- *
- * Note that some of these sharing_used_frames may be referenced by
- * a single domain page, and thus not realize any savings. The same
- * applies to some of the pages counted in dominfo(d)->shr_pages.
- */
-long xc_sharing_used_frames(xc_interface *xch);
-/*** End sharing interface ***/
-
-int xc_flask_load(xc_interface *xc_handle, char *buf, uint32_t size);
-int xc_flask_context_to_sid(xc_interface *xc_handle, char *buf, uint32_t size, uint32_t *sid);
-int xc_flask_sid_to_context(xc_interface *xc_handle, int sid, char *buf, uint32_t size);
-int xc_flask_getenforce(xc_interface *xc_handle);
-int xc_flask_setenforce(xc_interface *xc_handle, int mode);
-int xc_flask_getbool_byid(xc_interface *xc_handle, int id, char *name, uint32_t size, int *curr, int *pend);
-int xc_flask_getbool_byname(xc_interface *xc_handle, char *name, int *curr, int *pend);
-int xc_flask_setbool(xc_interface *xc_handle, char *name, int value, int commit);
-int xc_flask_add_pirq(xc_interface *xc_handle, unsigned int pirq, char *scontext);
-int xc_flask_add_ioport(xc_interface *xc_handle, unsigned long low, unsigned long high,
- char *scontext);
-int xc_flask_add_iomem(xc_interface *xc_handle, unsigned long low, unsigned long high,
- char *scontext);
-int xc_flask_add_device(xc_interface *xc_handle, unsigned long device, char *scontext);
-int xc_flask_del_pirq(xc_interface *xc_handle, unsigned int pirq);
-int xc_flask_del_ioport(xc_interface *xc_handle, unsigned long low, unsigned long high);
-int xc_flask_del_iomem(xc_interface *xc_handle, unsigned long low, unsigned long high);
-int xc_flask_del_device(xc_interface *xc_handle, unsigned long device);
-int xc_flask_access(xc_interface *xc_handle, const char *scon, const char *tcon,
- uint16_t tclass, uint32_t req,
- uint32_t *allowed, uint32_t *decided,
- uint32_t *auditallow, uint32_t *auditdeny,
- uint32_t *seqno);
-int xc_flask_avc_cachestats(xc_interface *xc_handle, char *buf, int size);
-int xc_flask_policyvers(xc_interface *xc_handle);
-int xc_flask_avc_hashstats(xc_interface *xc_handle, char *buf, int size);
-int xc_flask_getavc_threshold(xc_interface *xc_handle);
-int xc_flask_setavc_threshold(xc_interface *xc_handle, int threshold);
-int xc_flask_relabel_domain(xc_interface *xch, int domid, uint32_t sid);
-
-struct elf_binary;
-void xc_elf_set_logfile(xc_interface *xch, struct elf_binary *elf,
- int verbose);
-/* Useful for callers who also use libelf. */
-
-/**
- * Checkpoint Compression
- */
-typedef struct compression_ctx comp_ctx;
-comp_ctx *xc_compression_create_context(xc_interface *xch,
- unsigned long p2m_size);
-void xc_compression_free_context(xc_interface *xch, comp_ctx *ctx);
-
-/**
- * Add a page to compression page buffer, to be compressed later.
- *
- * returns 0 if the page was successfully added to the page buffer
- *
- * returns -1 if there is no space in buffer. In this case, the
- * application should call xc_compression_compress_pages to compress
- * the buffer (or atleast part of it), thereby freeing some space in
- * the page buffer.
- *
- * returns -2 if the pfn is out of bounds, where the bound is p2m_size
- * parameter passed during xc_compression_create_context.
- */
-int xc_compression_add_page(xc_interface *xch, comp_ctx *ctx, char *page,
- unsigned long pfn, int israw);
-
-/**
- * Delta compress pages in the compression buffer and inserts the
- * compressed data into the supplied compression buffer compbuf, whose
- * size is compbuf_size.
- * After compression, the pages are copied to the internal LRU cache.
- *
- * This function compresses as many pages as possible into the
- * supplied compression buffer. It maintains an internal iterator to
- * keep track of pages in the input buffer that are yet to be compressed.
- *
- * returns -1 if the compression buffer has run out of space.
- * returns 1 on success.
- * returns 0 if no more pages are left to be compressed.
- * When the return value is non-zero, compbuf_len indicates the actual
- * amount of data present in compbuf (<=compbuf_size).
- */
-int xc_compression_compress_pages(xc_interface *xch, comp_ctx *ctx,
- char *compbuf, unsigned long compbuf_size,
- unsigned long *compbuf_len);
-
-/**
- * Resets the internal page buffer that holds dirty pages before compression.
- * Also resets the iterators.
- */
-void xc_compression_reset_pagebuf(xc_interface *xch, comp_ctx *ctx);
-
-/**
- * Caller must supply the compression buffer (compbuf),
- * its size (compbuf_size) and a reference to index variable (compbuf_pos)
- * that is used internally. Each call pulls out one page from the compressed
- * chunk and copies it to dest.
- */
-int xc_compression_uncompress_page(xc_interface *xch, char *compbuf,
- unsigned long compbuf_size,
- unsigned long *compbuf_pos, char *dest);
-
-/*
- * Execute an image previously loaded with xc_kexec_load().
- *
- * Does not return on success.
- *
- * Fails with:
- * ENOENT if the specified image has not been loaded.
- */
-int xc_kexec_exec(xc_interface *xch, int type);
-
-/*
- * Find the machine address and size of certain memory areas.
- *
- * KEXEC_RANGE_MA_CRASH crash area
- * KEXEC_RANGE_MA_XEN Xen itself
- * KEXEC_RANGE_MA_CPU CPU note for CPU number 'nr'
- * KEXEC_RANGE_MA_XENHEAP xenheap
- * KEXEC_RANGE_MA_EFI_MEMMAP EFI Memory Map
- * KEXEC_RANGE_MA_VMCOREINFO vmcoreinfo
- *
- * Fails with:
- * EINVAL if the range or CPU number isn't valid.
- */
-int xc_kexec_get_range(xc_interface *xch, int range, int nr,
- uint64_t *size, uint64_t *start);
-
-/*
- * Load a kexec image into memory.
- *
- * The image may be of type KEXEC_TYPE_DEFAULT (executed on request)
- * or KEXEC_TYPE_CRASH (executed on a crash).
- *
- * The image architecture may be a 32-bit variant of the hypervisor
- * architecture (e.g, EM_386 on a x86-64 hypervisor).
- *
- * Fails with:
- * ENOMEM if there is insufficient memory for the new image.
- * EINVAL if the image does not fit into the crash area or the entry
- * point isn't within one of segments.
- * EBUSY if another image is being executed.
- */
-int xc_kexec_load(xc_interface *xch, uint8_t type, uint16_t arch,
- uint64_t entry_maddr,
- uint32_t nr_segments, xen_kexec_segment_t *segments);
-
-/*
- * Unload a kexec image.
- *
- * This prevents a KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH image from
- * being executed. The crash images are not cleared from the crash
- * region.
- */
-int xc_kexec_unload(xc_interface *xch, int type);
-
-#endif /* XENCTRL_H */
diff --git a/tools/libxc/xenctrl_osdep_ENOSYS.c b/tools/libxc/xenctrl_osdep_ENOSYS.c
index 4821342..dd59dcd 100644
--- a/tools/libxc/xenctrl_osdep_ENOSYS.c
+++ b/tools/libxc/xenctrl_osdep_ENOSYS.c
@@ -15,19 +15,23 @@
static xc_osdep_handle ENOSYS_privcmd_open(xc_interface *xch)
{
- IPRINTF(xch, "ENOSYS_privcmd: opening handle %p\n", (void *)1);
+ IPRINTF(xch, "ENOSYS_privcmd: opening handle %d\n", 1);
return (xc_osdep_handle)1; /*dummy*/
}
static int ENOSYS_privcmd_close(xc_interface *xch, xc_osdep_handle h)
{
- IPRINTF(xch, "ENOSYS_privcmd: closing handle %p\n", h);
+ IPRINTF(xch, "ENOSYS_privcmd: closing handle %lx\n", h);
return 0;
}
static int ENOSYS_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
{
- IPRINTF(xch, "ENOSYS_privcmd %p: hypercall: %02lld(%#llx,%#llx,%#llx,%#llx,%#llx)\n",
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+ IPRINTF(xch, "ENOSYS_privcmd %lx: hypercall: %02lu(%#lx,%#lx,%#lx,%#lx,%#lx)\n",
+#else
+ IPRINTF(xch, "ENOSYS_privcmd %lx: hypercall: %02lld(%#llx,%#llx,%#llx,%#llx,%#llx)\n",
+#endif
h, hypercall->op,
hypercall->arg[0], hypercall->arg[1], hypercall->arg[2],
hypercall->arg[3], hypercall->arg[4]);
@@ -37,21 +41,21 @@ static int ENOSYS_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcm
static void *ENOSYS_privcmd_map_foreign_batch(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int prot,
xen_pfn_t *arr, int num)
{
- IPRINTF(xch, "ENOSYS_privcmd %p: map_foreign_batch: dom%d prot %#x arr %p num %d\n", h, dom, prot, arr, num);
+ IPRINTF(xch, "ENOSYS_privcmd %lx: map_foreign_batch: dom%d prot %#x arr %p num %d\n", h, dom, prot, arr, num);
return MAP_FAILED;
}
static void *ENOSYS_privcmd_map_foreign_bulk(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int prot,
const xen_pfn_t *arr, int *err, unsigned int num)
{
- IPRINTF(xch, "ENOSYS_privcmd %p: map_foreign_buld: dom%d prot %#x arr %p err %p num %d\n", h, dom, prot, arr, err, num);
+ IPRINTF(xch, "ENOSYS_privcmd %lx map_foreign_buld: dom%d prot %#x arr %p err %p num %d\n", h, dom, prot, arr, err, num);
return MAP_FAILED;
}
static void *ENOSYS_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int size, int prot,
unsigned long mfn)
{
- IPRINTF(xch, "ENOSYS_privcmd %p: map_foreign_range: dom%d size %#x prot %#x mfn %ld\n", h, dom, size, prot, mfn);
+ IPRINTF(xch, "ENOSYS_privcmd %lx map_foreign_range: dom%d size %#x prot %#x mfn %ld\n", h, dom, size, prot, mfn);
return MAP_FAILED;
}
@@ -59,7 +63,7 @@ static void *ENOSYS_privcmd_map_foreign_ranges(xc_interface *xch, xc_osdep_handl
size_t chunksize, privcmd_mmap_entry_t entries[],
int nentries)
{
- IPRINTF(xch, "ENOSYS_privcmd %p: map_foreign_ranges: dom%d size %zd prot %#x chunksize %zd entries %p num %d\n", h, dom, size, prot, chunksize, entries, nentries);
+ IPRINTF(xch, "ENOSYS_privcmd %lx map_foreign_ranges: dom%d size %zd prot %#x chunksize %zd entries %p num %d\n", h, dom, size, prot, chunksize, entries, nentries);
return MAP_FAILED;
}
@@ -85,59 +89,59 @@ static xc_osdep_handle ENOSYS_evtchn_open(xc_interface *xce)
static int ENOSYS_evtchn_close(xc_interface *xce, xc_osdep_handle h)
{
- IPRINTF(xce, "ENOSYS_evtchn: closing handle %p\n", h);
+ IPRINTF(xce, "ENOSYS_evtchn: closing handle %lx\n", h);
return 0;
}
static int ENOSYS_evtchn_fd(xc_interface *xce, xc_osdep_handle h)
{
- IPRINTF(xce, "ENOSYS_fd %p: fd\n", h);
+ IPRINTF(xce, "ENOSYS_fd %lx fd\n", h);
return (int)h;
}
static int ENOSYS_evtchn_notify(xc_interface *xce, xc_osdep_handle h, evtchn_port_t port)
{
- IPRINTF(xce, "ENOSYS_evtchn %p: notify: %d\n", h, port);
+ IPRINTF(xce, "ENOSYS_evtchn %lx notify: %d\n", h, port);
return -ENOSYS;
}
static int ENOSYS_evtchn_bind_unbound_port(xc_interface *xce, xc_osdep_handle h, int domid)
{
- IPRINTF(xce, "ENOSYS_evtchn %p: bind_unbound_port: dom%d\n", h, domid);
+ IPRINTF(xce, "ENOSYS_evtchn %lx bind_unbound_port: dom%d\n", h, domid);
return -ENOSYS;
}
static int ENOSYS_evtchn_bind_interdomain(xc_interface *xce, xc_osdep_handle h, int domid, evtchn_port_t remote_port)
{
- IPRINTF(xce, "ENOSYS_evtchn %p: bind_interdomain: dmo%d %d\n", h, domid, remote_port);
+ IPRINTF(xce, "ENOSYS_evtchn %lx bind_interdomain: dmo%d %d\n", h, domid, remote_port);
return -ENOSYS;
}
static int ENOSYS_evtchn_bind_virq(xc_interface *xce, xc_osdep_handle h, unsigned int virq)
{
- IPRINTF(xce, "ENOSYS_evtchn %p: bind_virq: %d\n", h, virq);
+ IPRINTF(xce, "ENOSYS_evtchn %lx bind_virq: %d\n", h, virq);
return -ENOSYS;
}
static int ENOSYS_evtchn_unbind(xc_interface *xce, xc_osdep_handle h, evtchn_port_t port)
{
- IPRINTF(xce, "ENOSYS_evtchn %p: unbind: %d\n", h, port);
+ IPRINTF(xce, "ENOSYS_evtchn %lx unbind: %d\n", h, port);
return -ENOSYS;
}
static evtchn_port_or_error_t ENOSYS_evtchn_pending(xc_interface *xce, xc_osdep_handle h)
{
- IPRINTF(xce, "ENOSYS_evtchn %p: pending\n", h);
+ IPRINTF(xce, "ENOSYS_evtchn %lx pending\n", h);
return -ENOSYS;
}
static int ENOSYS_evtchn_unmask(xc_interface *xce, xc_osdep_handle h, evtchn_port_t port)
{
- IPRINTF(xce, "ENOSYS_evtchn %p: unmask: %d\n", h, port);
+ IPRINTF(xce, "ENOSYS_evtchn %lx unmask: %d\n", h, port);
return -ENOSYS;
}
diff --git a/tools/libxc/xenctrlosdep.h b/tools/libxc/xenctrlosdep.h
deleted file mode 100644
index e610a24..0000000
--- a/tools/libxc/xenctrlosdep.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/******************************************************************************
- *
- * Interface to OS specific low-level operations
- *
- * Copyright (c) 2010, Citrix Systems Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * This interface defines the interactions between the Xen control
- * libraries and the OS facilities used to communicate with the
- * hypervisor.
- *
- * It is possible to override the default (native) implementation by
- * setting the XENCTRL_OSDEP environment variable to point to a
- * plugin library. Userspace can use this facility to intercept
- * hypervisor operations. This can be used e.g. to implement a
- * userspace simulator for Xen hypercalls.
- *
- * The plugin must contain a data structure:
- * xc_osdep_info_t xc_osdep_info;
- *
- * xc_osdep_init:
- * Must return a suitable struct xc_osdep_ops pointer or NULL on failure.
- */
-
-#ifndef XC_OSDEP_H
-#define XC_OSDEP_H
-
-/* Tell the Xen public headers we are a user-space tools build. */
-#ifndef __XEN_TOOLS__
-#define __XEN_TOOLS__ 1
-#endif
-
-#include <sys/mman.h>
-#include <sys/types.h>
-
-#include <xen/sys/privcmd.h>
-
-enum xc_osdep_type {
- XC_OSDEP_PRIVCMD,
- XC_OSDEP_EVTCHN,
- XC_OSDEP_GNTTAB,
- XC_OSDEP_GNTSHR,
-};
-
-/* Opaque handle internal to the backend */
-typedef unsigned long xc_osdep_handle;
-
-#define XC_OSDEP_OPEN_ERROR ((xc_osdep_handle)-1)
-
-struct xc_osdep_ops
-{
- /* Opens an interface.
- *
- * Must return an opaque handle on success or
- * XC_OSDEP_OPEN_ERROR on failure
- */
- xc_osdep_handle (*open)(xc_interface *xch);
-
- int (*close)(xc_interface *xch, xc_osdep_handle h);
-
- union {
- struct {
- void *(*alloc_hypercall_buffer)(xc_interface *xch, xc_osdep_handle h, int npages);
- void (*free_hypercall_buffer)(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages);
-
- int (*hypercall)(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall);
-
- void *(*map_foreign_batch)(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int prot,
- xen_pfn_t *arr, int num);
- void *(*map_foreign_bulk)(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int prot,
- const xen_pfn_t *arr, int *err, unsigned int num);
- void *(*map_foreign_range)(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int size, int prot,
- unsigned long mfn);
- void *(*map_foreign_ranges)(xc_interface *xch, xc_osdep_handle h, uint32_t dom, size_t size, int prot,
- size_t chunksize, privcmd_mmap_entry_t entries[],
- int nentries);
- } privcmd;
- struct {
- int (*fd)(xc_evtchn *xce, xc_osdep_handle h);
-
- int (*notify)(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port);
-
- evtchn_port_or_error_t (*bind_unbound_port)(xc_evtchn *xce, xc_osdep_handle h, int domid);
- evtchn_port_or_error_t (*bind_interdomain)(xc_evtchn *xce, xc_osdep_handle h, int domid,
- evtchn_port_t remote_port);
- evtchn_port_or_error_t (*bind_virq)(xc_evtchn *xce, xc_osdep_handle h, unsigned int virq);
-
- int (*unbind)(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port);
-
- evtchn_port_or_error_t (*pending)(xc_evtchn *xce, xc_osdep_handle h);
- int (*unmask)(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port);
- } evtchn;
- struct {
-#define XC_GRANT_MAP_SINGLE_DOMAIN 0x1
- void *(*grant_map)(xc_gnttab *xcg, xc_osdep_handle h,
- uint32_t count, int flags, int prot,
- uint32_t *domids, uint32_t *refs,
- uint32_t notify_offset,
- evtchn_port_t notify_port);
- int (*munmap)(xc_gnttab *xcg, xc_osdep_handle h,
- void *start_address,
- uint32_t count);
- int (*set_max_grants)(xc_gnttab *xcg, xc_osdep_handle h, uint32_t count);
- } gnttab;
- struct {
- void *(*share_pages)(xc_gntshr *xcg, xc_osdep_handle h,
- uint32_t domid, int count,
- uint32_t *refs, int writable,
- uint32_t notify_offset,
- evtchn_port_t notify_port);
- int (*munmap)(xc_gntshr *xcg, xc_osdep_handle h,
- void *start_address, uint32_t count);
- } gntshr;
- } u;
-};
-typedef struct xc_osdep_ops xc_osdep_ops;
-
-typedef xc_osdep_ops *(*xc_osdep_init_fn)(xc_interface *xch, enum xc_osdep_type);
-
-struct xc_osdep_info
-{
- /* Describes this backend. */
- const char *name;
-
- /* Returns ops function. */
- xc_osdep_init_fn init;
-
- /* True if this interface backs onto a fake Xen. */
- int fake;
-
- /* For internal use by loader. */
- void *dl_handle;
-};
-typedef struct xc_osdep_info xc_osdep_info_t;
-
-/* All backends, including the builtin backend, must supply this structure. */
-extern xc_osdep_info_t xc_osdep_info;
-
-/* Stub for not yet converted OSes */
-void *xc_map_foreign_bulk_compat(xc_interface *xch, xc_osdep_handle h,
- uint32_t dom, int prot,
- const xen_pfn_t *arr, int *err, unsigned int num);
-
-/* Report errors through xc_interface */
-void xc_osdep_log(xc_interface *xch, xentoollog_level level, int code, const char *fmt, ...);
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h
deleted file mode 100644
index a0e30e1..0000000
--- a/tools/libxc/xenguest.h
+++ /dev/null
@@ -1,308 +0,0 @@
-/******************************************************************************
- * xenguest.h
- *
- * A library for guest domain management in Xen.
- *
- * Copyright (c) 2003-2004, K A Fraser.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef XENGUEST_H
-#define XENGUEST_H
-
-#define XCFLAGS_LIVE (1 << 0)
-#define XCFLAGS_DEBUG (1 << 1)
-#define XCFLAGS_HVM (1 << 2)
-#define XCFLAGS_STDVGA (1 << 3)
-#define XCFLAGS_CHECKPOINT_COMPRESS (1 << 4)
-
-#define X86_64_B_SIZE 64
-#define X86_32_B_SIZE 32
-
-/* callbacks provided by xc_domain_save */
-struct save_callbacks {
- /* Called after expiration of checkpoint interval,
- * to suspend the guest.
- */
- int (*suspend)(void* data);
-
- /* Called after the guest's dirty pages have been
- * copied into an output buffer.
- * Callback function resumes the guest & the device model,
- * returns to xc_domain_save.
- * xc_domain_save then flushes the output buffer, while the
- * guest continues to run.
- */
- int (*postcopy)(void* data);
-
- /* Called after the memory checkpoint has been flushed
- * out into the network. Typical actions performed in this
- * callback include:
- * (a) send the saved device model state (for HVM guests),
- * (b) wait for checkpoint ack
- * (c) release the network output buffer pertaining to the acked checkpoint.
- * (c) sleep for the checkpoint interval.
- *
- * returns:
- * 0: terminate checkpointing gracefully
- * 1: take another checkpoint */
- int (*checkpoint)(void* data);
-
- /* Enable qemu-dm logging dirty pages to xen */
- int (*switch_qemu_logdirty)(int domid, unsigned enable, void *data); /* HVM only */
-
- /* Save toolstack specific data
- * @param buf the buffer with the data to be saved
- * @param len the length of the buffer
- * The callee allocates the buffer, the caller frees it (buffer must
- * be free'able).
- */
- int (*toolstack_save)(uint32_t domid, uint8_t **buf, uint32_t *len, void *data);
-
- /* to be provided as the last argument to each callback function */
- void* data;
-};
-
-/**
- * This function will save a running domain.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm fd the file descriptor to save a domain to
- * @parm dom the id of the domain
- * @return 0 on success, -1 on failure
- */
-int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
- uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
- struct save_callbacks* callbacks, int hvm,
- unsigned long vm_generationid_addr);
-
-
-/* callbacks provided by xc_domain_restore */
-struct restore_callbacks {
- /* callback to restore toolstack specific data */
- int (*toolstack_restore)(uint32_t domid, const uint8_t *buf,
- uint32_t size, void* data);
-
- /* to be provided as the last argument to each callback function */
- void* data;
-};
-
-/**
- * This function will restore a saved domain.
- *
- * Domain is restored in a suspended state ready to be unpaused.
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm fd the file descriptor to restore a domain from
- * @parm dom the id of the domain
- * @parm store_evtchn the store event channel for this domain to use
- * @parm store_mfn returned with the mfn of the store page
- * @parm hvm non-zero if this is a HVM restore
- * @parm pae non-zero if this HVM domain has PAE support enabled
- * @parm superpages non-zero to allocate guest memory with superpages
- * @parm no_incr_generationid non-zero if generation id is NOT to be incremented
- * @parm checkpointed_stream non-zero if the far end of the stream is using checkpointing
- * @parm vm_generationid_addr returned with the address of the generation id buffer
- * @parm callbacks non-NULL to receive a callback to restore toolstack
- * specific data
- * @return 0 on success, -1 on failure
- */
-int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
- unsigned int store_evtchn, unsigned long *store_mfn,
- domid_t store_domid, unsigned int console_evtchn,
- unsigned long *console_mfn, domid_t console_domid,
- unsigned int hvm, unsigned int pae, int superpages,
- int no_incr_generationid, int checkpointed_stream,
- unsigned long *vm_generationid_addr,
- struct restore_callbacks *callbacks);
-/**
- * xc_domain_restore writes a file to disk that contains the device
- * model saved state.
- * The pathname of this file is XC_DEVICE_MODEL_RESTORE_FILE; The domid
- * of the new domain is automatically appended to the filename,
- * separated by a ".".
- */
-#define XC_DEVICE_MODEL_RESTORE_FILE "/var/lib/xen/qemu-resume"
-
-/**
- * This function will create a domain for a paravirtualized Linux
- * using file names pointing to kernel and ramdisk
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the id of the domain
- * @parm mem_mb memory size in megabytes
- * @parm image_name name of the kernel image file
- * @parm ramdisk_name name of the ramdisk image file
- * @parm cmdline command line string
- * @parm flags domain creation flags
- * @parm store_evtchn the store event channel for this domain to use
- * @parm store_mfn returned with the mfn of the store page
- * @parm console_evtchn the console event channel for this domain to use
- * @parm conole_mfn returned with the mfn of the console page
- * @return 0 on success, -1 on failure
- */
-int xc_linux_build(xc_interface *xch,
- uint32_t domid,
- unsigned int mem_mb,
- const char *image_name,
- const char *ramdisk_name,
- const char *cmdline,
- const char *features,
- unsigned long flags,
- unsigned int store_evtchn,
- unsigned long *store_mfn,
- unsigned int console_evtchn,
- unsigned long *console_mfn);
-
-/** The same interface, but the dom structure is managed by the caller */
-struct xc_dom_image;
-int xc_dom_linux_build(xc_interface *xch,
- struct xc_dom_image *dom,
- uint32_t domid,
- unsigned int mem_mb,
- const char *image_name,
- const char *ramdisk_name,
- unsigned long flags,
- unsigned int store_evtchn,
- unsigned long *store_mfn,
- unsigned int console_evtchn,
- unsigned long *console_mfn);
-
-/**
- * This function will create a domain for a paravirtualized Linux
- * using buffers for kernel and initrd
- *
- * @parm xch a handle to an open hypervisor interface
- * @parm domid the id of the domain
- * @parm mem_mb memory size in megabytes
- * @parm image_buffer buffer containing kernel image
- * @parm image_size size of the kernel image buffer
- * @parm initrd_buffer name of the ramdisk image file
- * @parm initrd_size size of the ramdisk buffer
- * @parm cmdline command line string
- * @parm flags domain creation flags
- * @parm store_evtchn the store event channel for this domain to use
- * @parm store_mfn returned with the mfn of the store page
- * @parm console_evtchn the console event channel for this domain to use
- * @parm conole_mfn returned with the mfn of the console page
- * @return 0 on success, -1 on failure
- */
-int xc_linux_build_mem(xc_interface *xch,
- uint32_t domid,
- unsigned int mem_mb,
- const char *image_buffer,
- unsigned long image_size,
- const char *initrd_buffer,
- unsigned long initrd_size,
- const char *cmdline,
- const char *features,
- unsigned long flags,
- unsigned int store_evtchn,
- unsigned long *store_mfn,
- unsigned int console_evtchn,
- unsigned long *console_mfn);
-
-struct xc_hvm_firmware_module {
- uint8_t *data;
- uint32_t length;
- uint64_t guest_addr_out;
-};
-
-struct xc_hvm_build_args {
- uint64_t mem_size; /* Memory size in bytes. */
- uint64_t mem_target; /* Memory target in bytes. */
- uint64_t mmio_size; /* Size of the MMIO hole in bytes. */
- const char *image_file_name; /* File name of the image to load. */
-
- /* Extra ACPI tables passed to HVMLOADER */
- struct xc_hvm_firmware_module acpi_module;
-
- /* Extra SMBIOS structures passed to HVMLOADER */
- struct xc_hvm_firmware_module smbios_module;
- /* Whether to use claim hypercall (1 - enable, 0 - disable). */
- int claim_enabled;
-};
-
-/**
- * Build a HVM domain.
- * @parm xch libxc context handle.
- * @parm domid domain ID for the new domain.
- * @parm hvm_args parameters for the new domain.
- *
- * The memory size and image file parameters are required, the rest
- * are optional.
- */
-int xc_hvm_build(xc_interface *xch, uint32_t domid,
- struct xc_hvm_build_args *hvm_args);
-
-int xc_hvm_build_target_mem(xc_interface *xch,
- uint32_t domid,
- int memsize,
- int target,
- const char *image_name);
-
-int xc_suspend_evtchn_release(xc_interface *xch, xc_evtchn *xce, int domid, int suspend_evtchn);
-
-int xc_suspend_evtchn_init(xc_interface *xch, xc_evtchn *xce, int domid, int port);
-
-int xc_await_suspend(xc_interface *xch, xc_evtchn *xce, int suspend_evtchn);
-
-int xc_get_bit_size(xc_interface *xch,
- const char *image_name, const char *cmdline,
- const char *features, int *type);
-
-int xc_mark_page_online(xc_interface *xch, unsigned long start,
- unsigned long end, uint32_t *status);
-
-int xc_mark_page_offline(xc_interface *xch, unsigned long start,
- unsigned long end, uint32_t *status);
-
-int xc_query_page_offline_status(xc_interface *xch, unsigned long start,
- unsigned long end, uint32_t *status);
-
-int xc_exchange_page(xc_interface *xch, int domid, xen_pfn_t mfn);
-
-
-/**
- * Memory related information, such as PFN types, the P2M table,
- * the guest word width and the guest page table levels.
- */
-struct xc_domain_meminfo {
- unsigned int pt_levels;
- unsigned int guest_width;
- xen_pfn_t *pfn_type;
- xen_pfn_t *p2m_table;
- unsigned long p2m_size;
-};
-
-int xc_map_domain_meminfo(xc_interface *xch, int domid,
- struct xc_domain_meminfo *minfo);
-
-int xc_unmap_domain_meminfo(xc_interface *xch, struct xc_domain_meminfo *mem);
-
-/**
- * This function map m2p table
- * @parm xch a handle to an open hypervisor interface
- * @parm max_mfn the max pfn
- * @parm prot the flags to map, such as read/write etc
- * @parm mfn0 return the first mfn, can be NULL
- * @return mapped m2p table on success, NULL on failure
- */
-xen_pfn_t *xc_map_m2p(xc_interface *xch,
- unsigned long max_mfn,
- int prot,
- unsigned long *mfn0);
-#endif /* XENGUEST_H */
diff --git a/tools/libxc/xentoollog.h b/tools/libxc/xentoollog.h
deleted file mode 100644
index 6d36dd9..0000000
--- a/tools/libxc/xentoollog.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * xentoollog.h
- *
- * Copyright (c) 2010 Citrix
- * Part of a generic logging interface used by various dom0 userland libraries.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef XENTOOLLOG_H
-#define XENTOOLLOG_H
-
-#include <stdio.h>
-#include <stdarg.h>
-
-
-/*---------- common declarations and types ----------*/
-
-typedef enum xentoollog_level {
- XTL_NONE, /* sentinel etc, never used for logging */
- XTL_DEBUG,
- XTL_VERBOSE,
- XTL_DETAIL,
- XTL_PROGRESS, /* also used for "progress" messages */
- XTL_INFO,
- XTL_NOTICE,
- XTL_WARN,
- XTL_ERROR,
- XTL_CRITICAL,
- XTL_NUM_LEVELS
-} xentoollog_level;
-
-typedef struct xentoollog_logger xentoollog_logger;
-struct xentoollog_logger {
- void (*vmessage)(struct xentoollog_logger *logger,
- xentoollog_level level,
- int errnoval /* or -1 */,
- const char *context /* eg "xc", "xl", may be 0 */,
- const char *format /* without level, context, \n */,
- va_list al)
- __attribute__((format(printf,5,0)));
- void (*progress)(struct xentoollog_logger *logger,
- const char *context /* see above */,
- const char *doing_what /* no \r,\n */,
- int percent, unsigned long done, unsigned long total)
- /* null function pointer is ok.
- * will always be called with done==0 for each new
- * context/doing_what */;
- void (*destroy)(struct xentoollog_logger *logger);
- /* each logger can put its necessary data here */
-};
-
-
-/*---------- facilities for consuming log messages ----------*/
-
-#define XTL_STDIOSTREAM_SHOW_PID 01u
-#define XTL_STDIOSTREAM_SHOW_DATE 02u
-#define XTL_STDIOSTREAM_HIDE_PROGRESS 04u
-
-typedef struct xentoollog_logger_stdiostream xentoollog_logger_stdiostream;
-
-xentoollog_logger_stdiostream *xtl_createlogger_stdiostream
- (FILE *f, xentoollog_level min_level, unsigned flags);
- /* may return 0 if malloc fails, in which case error was logged */
- /* destroy on this logger does not close the file */
-
-void xtl_stdiostream_set_minlevel(xentoollog_logger_stdiostream*,
- xentoollog_level min_level);
-void xtl_stdiostream_adjust_flags(xentoollog_logger_stdiostream*,
- unsigned set_flags, unsigned clear_flags);
- /* if set_flags and clear_flags overlap, set_flags takes precedence */
-
-void xtl_logger_destroy(struct xentoollog_logger *logger /* 0 is ok */);
-
-
-/*---------- facilities for generating log messages ----------*/
-
-void xtl_logv(struct xentoollog_logger *logger,
- xentoollog_level level,
- int errnoval /* or -1 */,
- const char *context /* eg "xc", "xenstore", "xl", may be 0 */,
- const char *format /* does not contain \n */,
- va_list) __attribute__((format(printf,5,0)));
-
-void xtl_log(struct xentoollog_logger *logger,
- xentoollog_level level,
- int errnoval /* or -1 */,
- const char *context /* eg "xc", "xenstore", "xl" */,
- const char *format /* does not contain \n */,
- ...) __attribute__((format(printf,5,6)));
-
-void xtl_progress(struct xentoollog_logger *logger,
- const char *context /* see above, may be 0 */,
- const char *doing_what,
- unsigned long done, unsigned long total);
-
-
-/*---------- facilities for defining log message consumers ----------*/
-
-const char *xtl_level_to_string(xentoollog_level); /* never fails */
-
-
-#define XTL_NEW_LOGGER(LOGGER,buffer) ({ \
- xentoollog_logger_##LOGGER *new_consumer; \
- \
- (buffer).vtable.vmessage = LOGGER##_vmessage; \
- (buffer).vtable.progress = LOGGER##_progress; \
- (buffer).vtable.destroy = LOGGER##_destroy; \
- \
- new_consumer = malloc(sizeof(*new_consumer)); \
- if (!new_consumer) { \
- xtl_log((xentoollog_logger*)&buffer, \
- XTL_CRITICAL, errno, "xtl", \
- "failed to allocate memory for new message logger"); \
- } else { \
- *new_consumer = buffer; \
- } \
- \
- new_consumer; \
-});
-
-
-#endif /* XENTOOLLOG_H */
diff --git a/tools/libxc/xg_private.c b/tools/libxc/xg_private.c
index a914068..c52cb44 100644
--- a/tools/libxc/xg_private.c
+++ b/tools/libxc/xg_private.c
@@ -21,7 +21,6 @@
#include <stdlib.h>
#include <unistd.h>
#include <zlib.h>
-#include <malloc.h>
#include "xg_private.h"
diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h
index 5ff2124..1910361 100644
--- a/tools/libxc/xg_private.h
+++ b/tools/libxc/xg_private.h
@@ -120,10 +120,6 @@ typedef uint64_t l4_pgentry_64_t;
#define PAGE_SIZE_X86 (1UL << PAGE_SHIFT_X86)
#define PAGE_MASK_X86 (~(PAGE_SIZE_X86-1))
-#define PAGE_SHIFT_IA64 14
-#define PAGE_SIZE_IA64 (1UL << PAGE_SHIFT_IA64)
-#define PAGE_MASK_IA64 (~(PAGE_SIZE_IA64-1))
-
#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
#define NRPAGES(x) (ROUNDUP(x, PAGE_SHIFT) >> PAGE_SHIFT)
@@ -136,13 +132,19 @@ struct domain_info_context {
unsigned long p2m_size;
};
-static inline xen_pfn_t pfn_to_mfn(xen_pfn_t pfn, xen_pfn_t *p2m, int gwidth)
+static inline xen_pfn_t xc_pfn_to_mfn(xen_pfn_t pfn, xen_pfn_t *p2m,
+ unsigned gwidth)
{
- return ((xen_pfn_t) ((gwidth==8)?
- (((uint64_t *)p2m)[(pfn)]):
- ((((uint32_t *)p2m)[(pfn)]) == 0xffffffffU ?
- (-1UL) :
- (((uint32_t *)p2m)[(pfn)]))));
+ if ( gwidth == sizeof(uint64_t) )
+ /* 64 bit guest. Need to truncate their pfns for 32 bit toolstacks. */
+ return ((uint64_t *)p2m)[pfn];
+ else
+ {
+ /* 32 bit guest. Need to expand INVALID_MFN for 64 bit toolstacks. */
+ uint32_t mfn = ((uint32_t *)p2m)[pfn];
+
+ return mfn == ~0U ? INVALID_MFN : mfn;
+ }
}
/* Number of xen_pfn_t in a page */
@@ -157,7 +159,7 @@ static inline xen_pfn_t pfn_to_mfn(xen_pfn_t pfn, xen_pfn_t *p2m, int gwidth)
/* Size in bytes of the pfn_to_mfn_frame_list */
#define P2M_GUEST_FL_SIZE ((P2M_FL_ENTRIES) * (dinfo->guest_width))
#define P2M_TOOLS_FL_SIZE ((P2M_FL_ENTRIES) * \
- MAX((sizeof (xen_pfn_t)), dinfo->guest_width))
+ max_t(size_t, sizeof(xen_pfn_t), dinfo->guest_width))
/* Masks for PTE<->PFN conversions */
#define MADDR_BITS_X86 ((dinfo->guest_width == 8) ? 52 : 44)
diff --git a/tools/libxc/xg_save_restore.h b/tools/libxc/xg_save_restore.h
index f859621..bdd9009 100644
--- a/tools/libxc/xg_save_restore.h
+++ b/tools/libxc/xg_save_restore.h
@@ -259,6 +259,9 @@
#define XC_SAVE_ID_HVM_ACCESS_RING_PFN -16
#define XC_SAVE_ID_HVM_SHARING_RING_PFN -17
#define XC_SAVE_ID_TOOLSTACK -18 /* Optional toolstack specific info */
+/* These are a pair; it is an error for one to exist without the other */
+#define XC_SAVE_ID_HVM_IOREQ_SERVER_PFN -19
+#define XC_SAVE_ID_HVM_NR_IOREQ_SERVER_PAGES -20
/*
** We process save/restore/migrate in batches of pages; the below
@@ -357,10 +360,10 @@ static inline int get_platform_info(xc_interface *xch, uint32_t dom,
#define is_mapped(pfn_type) (!((pfn_type) & 0x80000000UL))
-#define GET_FIELD(_p, _f) ((dinfo->guest_width==8) ? ((_p)->x64._f) : ((_p)->x32._f))
+#define GET_FIELD(_p, _f, _w) (((_w) == 8) ? ((_p)->x64._f) : ((_p)->x32._f))
-#define SET_FIELD(_p, _f, _v) do { \
- if (dinfo->guest_width == 8) \
+#define SET_FIELD(_p, _f, _v, _w) do { \
+ if ((_w) == 8) \
(_p)->x64._f = (_v); \
else \
(_p)->x32._f = (_v); \
@@ -376,23 +379,16 @@ static inline int get_platform_info(xc_interface *xch, uint32_t dom,
? ((uint64_t)(_c)) << 12 \
: (((uint32_t)(_c) << 12) | ((uint32_t)(_c) >> 20))))
-#define MEMCPY_FIELD(_d, _s, _f) do { \
- if (dinfo->guest_width == 8) \
+#define MEMCPY_FIELD(_d, _s, _f, _w) do { \
+ if ((_w) == 8) \
memcpy(&(_d)->x64._f, &(_s)->x64._f,sizeof((_d)->x64._f)); \
else \
memcpy(&(_d)->x32._f, &(_s)->x32._f,sizeof((_d)->x32._f)); \
} while (0)
-#define MEMSET_ARRAY_FIELD(_p, _f, _v) do { \
- if (dinfo->guest_width == 8) \
+#define MEMSET_ARRAY_FIELD(_p, _f, _v, _w) do { \
+ if ((_w) == 8) \
memset(&(_p)->x64._f[0], (_v), sizeof((_p)->x64._f)); \
else \
memset(&(_p)->x32._f[0], (_v), sizeof((_p)->x32._f)); \
} while (0)
-
-#ifndef MAX
-#define MAX(_a, _b) ((_a) >= (_b) ? (_a) : (_b))
-#endif
-#ifndef MIN
-#define MIN(_a, _b) ((_a) <= (_b) ? (_a) : (_b))
-#endif
diff --git a/tools/libxc/xtl_logger_stdio.c b/tools/libxc/xtl_logger_stdio.c
index aa5501f..d8646e0 100644
--- a/tools/libxc/xtl_logger_stdio.c
+++ b/tools/libxc/xtl_logger_stdio.c
@@ -28,6 +28,7 @@
#include <string.h>
#include <stdlib.h>
#include <errno.h>
+#include <stdbool.h>
struct xentoollog_logger_stdiostream {
xentoollog_logger vtable;
@@ -35,7 +36,7 @@ struct xentoollog_logger_stdiostream {
xentoollog_level min_level;
unsigned flags;
int progress_erase_len, progress_last_percent;
- int tty;
+ bool progress_use_cr;
};
static void progress_erase(xentoollog_logger_stdiostream *lg) {
@@ -63,7 +64,7 @@ static void stdiostream_vmessage(xentoollog_logger *logger_in,
fprintf(lg->f, "%04d-%02d-%02d %02d:%02d:%02d %s ",
lt->tm_year+1900, lt->tm_mon+1, lt->tm_mday,
lt->tm_hour, lt->tm_min, lt->tm_sec,
- tzname[daylight ? !!lt->tm_isdst : 0]);
+ tzname[!!lt->tm_isdst]);
}
if (lg->flags & XTL_STDIOSTREAM_SHOW_PID)
fprintf(lg->f, "[%lu] ", (unsigned long)getpid());
@@ -119,7 +120,7 @@ static void stdiostream_progress(struct xentoollog_logger *logger_in,
lg->progress_last_percent = percent;
- if (!lg->tty) {
+ if (!lg->progress_use_cr) {
stdiostream_message(logger_in, this_level, context,
"%s: %lu/%lu %3d%%",
doing_what, done, total, percent);
@@ -167,7 +168,18 @@ xentoollog_logger_stdiostream *xtl_createlogger_stdiostream
newlogger.f = f;
newlogger.min_level = min_level;
newlogger.flags = flags;
- newlogger.tty = isatty(fileno(newlogger.f)) > 0;
+
+ switch (flags & (XTL_STDIOSTREAM_PROGRESS_USE_CR |
+ XTL_STDIOSTREAM_PROGRESS_NO_CR)) {
+ case XTL_STDIOSTREAM_PROGRESS_USE_CR: newlogger.progress_use_cr = 1; break;
+ case XTL_STDIOSTREAM_PROGRESS_NO_CR: newlogger.progress_use_cr = 0; break;
+ case 0:
+ newlogger.progress_use_cr = isatty(fileno(newlogger.f)) > 0;
+ break;
+ default:
+ errno = EINVAL;
+ return 0;
+ }
if (newlogger.flags & XTL_STDIOSTREAM_SHOW_DATE) tzset();
diff --git a/tools/libxen/COPYING b/tools/libxen/COPYING
deleted file mode 100644
index b124cf5..0000000
--- a/tools/libxen/COPYING
+++ /dev/null
@@ -1,510 +0,0 @@
-
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations
-below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it
-becomes a de-facto standard. To achieve this, non-free programs must
-be allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control
-compilation and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at least
- three years, to give the same user the materials specified in
- Subsection 6a, above, for a charge no more than the cost of
- performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply, and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License
-may add an explicit geographical distribution limitation excluding those
-countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms
-of the ordinary General Public License).
-
- To apply these terms, attach the following notices to the library.
-It is safest to attach them to the start of each source file to most
-effectively convey the exclusion of warranty; and each file should
-have at least the "copyright" line and a pointer to where the full
-notice is found.
-
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or
-your school, if any, to sign a "copyright disclaimer" for the library,
-if necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James
- Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/tools/libxen/Makefile b/tools/libxen/Makefile
deleted file mode 100644
index b66f0bc..0000000
--- a/tools/libxen/Makefile
+++ /dev/null
@@ -1,74 +0,0 @@
-#
-# Copyright (c) 2006-2007, XenSource Inc.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-XEN_ROOT=$(CURDIR)/../..
-include $(XEN_ROOT)/tools/Rules.mk
-
-MAJOR = 1.0
-MINOR = 0
-
-CFLAGS += -Iinclude \
- $(shell $(XML2_CONFIG) --cflags) \
- $(shell $(CURL_CONFIG) --cflags) \
- -fPIC
-
-LDFLAGS += $(shell $(XML2_CONFIG) --libs) \
- $(shell $(CURL_CONFIG) --libs)
-
-LIBXENAPI_HDRS = $(wildcard include/xen/api/*.h) include/xen/api/xen_all.h
-LIBXENAPI_OBJS = $(patsubst %.c, %.o, $(wildcard src/*.c))
-
-TEST_PROGRAMS = test/test_bindings test/test_event_handling
-
-.PHONY: all
-all: libxenapi.so libxenapi.a
-
-libxenapi.so: libxenapi.so.$(MAJOR)
- ln -sf $< $@
-
-libxenapi.so.$(MAJOR): libxenapi.so.$(MAJOR).$(MINOR)
- ln -sf $< $@
-
-libxenapi.so.$(MAJOR).$(MINOR): $(LIBXENAPI_OBJS)
- $(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenapi.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(APPEND_LDFLAGS)
-
-libxenapi.a: $(LIBXENAPI_OBJS)
- $(AR) rcs libxenapi.a $^
-
-$(TEST_PROGRAMS): test/%: test/%.o libxenapi.so
- $(CC) $(LDFLAGS) -o $@ $< -L . -lxenapi $(APPEND_LDFLAGS)
-
-
-.PHONY: install
-install: all
- $(INSTALL_DIR) $(DESTDIR)$(INCLUDEDIR)/xen/api
- $(INSTALL_DIR) $(DESTDIR)$(LIBDIR)
- $(INSTALL_PROG) libxenapi.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)
- ln -sf libxenapi.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libxenapi.so.$(MAJOR)
- ln -sf libxenapi.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libxenapi.so
- $(INSTALL_DATA) libxenapi.a $(DESTDIR)$(LIBDIR)
- set -e; for i in $(LIBXENAPI_HDRS); do \
- $(INSTALL_DATA) $$i $(DESTDIR)$(INCLUDEDIR)/xen/api; \
- done
-
-
-.PHONY: clean
-clean:
- rm -f `find -name *.o`
- rm -f libxenapi.so*
- rm -f libxenapi.a
- rm -f $(TEST_PROGRAMS)
diff --git a/tools/libxen/Makefile.dist b/tools/libxen/Makefile.dist
deleted file mode 100644
index 7088362..0000000
--- a/tools/libxen/Makefile.dist
+++ /dev/null
@@ -1,115 +0,0 @@
-#
-# Copyright (c) 2006-2007, XenSource Inc.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-MAJOR = 1.0
-MINOR = 0
-
-CFLAGS = -Iinclude \
- $(shell xml2-config --cflags) \
- $(shell curl-config --cflags) \
- -W -Wall -Wmissing-prototypes -Werror -std=c99 -O2 -fPIC
-
-LDFLAGS = $(shell xml2-config --libs) \
- $(shell curl-config --libs)
-
-# -h for Solaris
-SONAME_LDFLAG ?= -soname
-# -R /usr/sfw/$(LIBDIR) -shared for Solaris
-SHLIB_LDFLAGS ?= -shared
-
-# ginstall for Solaris
-INSTALL = install
-INSTALL_DIR = $(INSTALL) -d -m0755 -p
-INSTALL_DATA = $(INSTALL) -m0644 -p
-
-LIBXENAPI_HDRS = $(wildcard include/*.h)
-LIBXENAPI_OBJS = $(patsubst %.c, %.o, $(wildcard src/*.c))
-
-TEST_PROGRAMS = test/test_bindings test/test_event_handling
-
-TARBALL_DEST = libxenapi-$(MAJOR).$(MINOR)
-
-.PHONY: all
-all: $(TEST_PROGRAMS)
-
-libxenapi.so: libxenapi.so.$(MAJOR)
- ln -sf $< $@
-
-libxenapi.so.$(MAJOR): libxenapi.so.$(MAJOR).$(MINOR)
- ln -sf $< $@
-
-libxenapi.so.$(MAJOR).$(MINOR): $(LIBXENAPI_OBJS)
- $(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenapi.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^
-
-libxenapi.a: $(LIBXENAPI_OBJS)
- $(AR) rcs libxenapi.a $^
-
-$(TEST_PROGRAMS): test/%: test/%.o libxenapi.so
- $(CC) $(LDFLAGS) -o $@ $< -L . -lxenapi
-
-
-.PHONY: install
-install: all
- $(INSTALL_DIR) $(DESTDIR)$(INCLUDEDIR)/xen/api
- $(INSTALL_DIR) $(DESTDIR)$(LIBDIR)
- $(INSTALL_PROG) libxenapi.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)
- ln -sf libxenapi.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libxenapi.so.$(MAJOR)
- ln -sf libxenapi.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libxenapi.so
- $(INSTALL_DATA) libxenapi.a $(DESTDIR)$(LIBDIR)
- set -e; for i in $(LIBXENAPI_HDRS); do \
- $(INSTALL_DATA) $$i $(DESTDIR)$(INCLUDEDIR)/xen/api; \
- done
-
-
-.PHONY: tarball
-tarball: $(TARBALL_DEST).tar.bz2
-
-$(TARBALL_DEST).tar.bz2: all
- rm -Rf $(TARBALL_DEST)
- mkdir -p $(TARBALL_DEST)/include/xen/api
- mkdir -p $(TARBALL_DEST)/src
- mkdir -p $(TARBALL_DEST)/test
- cp COPYING $(TARBALL_DEST)
- cp Makefile.dist $(TARBALL_DEST)/Makefile
- cp Makefile.dist $(TARBALL_DEST)/Makefile.dist
- cp README $(TARBALL_DEST)
- cp include/*.h $(TARBALL_DEST)/include
- cp include/xen/api/*.h $(TARBALL_DEST)/include/xen/api
- cp src/*.c $(TARBALL_DEST)/src
- cp test/*.c $(TARBALL_DEST)/test
- fakeroot chown root:root -R $(TARBALL_DEST)
- fakeroot tar cjf $(TARBALL_DEST).tar.bz2 $(TARBALL_DEST)
-
-
-.PHONY: clean
-clean:
- rm -f `find -name *.o`
- rm -f libxenapi.so*
- rm -f libxenapi.a
- rm -f $(TEST_PROGRAMS)
-
-
-.PHONY: uberheader
-uberheader: include/xen/api/xen_all.h
-include/xen/api/xen_all.h::
- echo "/* This file is autogenerated */" >$@
- echo "#ifndef XEN_API_XEN_ALL_H" >>$@
- echo "#define XEN_API_XEN_ALL_H" >>$@
- ls include/xen/api/*.h | grep -v xen_all.h | grep -v _decl.h | \
- sed 's,^include/\(.*\)$$,#include <\1>,g' >>$@
- echo "#endif" >>$@
diff --git a/tools/libxen/README b/tools/libxen/README
deleted file mode 100644
index 2dd79f4..0000000
--- a/tools/libxen/README
+++ /dev/null
@@ -1,55 +0,0 @@
-Xen API C Bindings
-==================
-
-This distribution is the source code to the proposed Xen API C bindings.
-
-The Xen API project will define an XML-RPC protocol for remote and local
-management of Xen-based systems, and a set of bindings for these XML-RPC calls
-into a number of languages (this package contains those to the C language).
-
-The intention is to standardise these XML-RPC calls, and then the Xen project
-will guarantee that that wire protocol will be supported for the long term.
-The bindings will also be supported in the Xen tree, giving a stable
-foundation for Xen management tools and middlewares, in particular the Xen CIM
-providers and libvirt.
-
-THIS IS A WORK IN PROGRESS. The API and bindings are under active design and
-development, and this is a snapshot release for developers only. Both the API
-and the C bindings are scheduled to be stabilised by the Xen 3.0.4 release
-i.e. October 2006 at the earliest.
-
-These bindings are open-source (LGPL), and will be committed as libraries to
-the Xen trees for all to use after the Xen 3.0.3 release.
-
-We welcome any discussion about this library and the API in general. Please
-join the Xen-API mailing list if you are interested in this project. I (Ewan
-Mellor) will collate all the feedback from that list and push out new versions
-of the document and the bindings as and when.
-
-
-URLs
-----
-
-Xen-API wiki page:
-http://wiki.xensource.com/xenwiki/XenApi
-
-Xen-API mailing list:
- http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-api
-
-
-Usage
------
-
-The bindings depend upon libxml2, the XML toolkit from the GNOME project; the
-test program depends upon libcurl3 also. On Debian, you need the packages
-libxml2-dev and libcurl3-dev.
-
-To compile, type make. To compile the test also, type make
-test/test_bindings, remembering the additional dependency.
-
-To run the test, do
-
-LD_LIBRARY_PATH=. ./test/test_bindings <url> <username> <password>
-
-where <url> is the fragment of the server URL that follows the http://, for
-example "localhost:8005/RPC2".
diff --git a/tools/libxen/include/xen/api/xen_all.h b/tools/libxen/include/xen/api/xen_all.h
deleted file mode 100644
index 45ac171..0000000
--- a/tools/libxen/include/xen/api/xen_all.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* This file is autogenerated */
-#ifndef XEN_API_XEN_ALL_H
-#define XEN_API_XEN_ALL_H
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_console.h>
-#include <xen/api/xen_console_protocol.h>
-#include <xen/api/xen_crashdump.h>
-#include <xen/api/xen_event.h>
-#include <xen/api/xen_event_operation.h>
-#include <xen/api/xen_host_cpu.h>
-#include <xen/api/xen_host.h>
-#include <xen/api/xen_host_metrics.h>
-#include <xen/api/xen_int_float_map.h>
-#include <xen/api/xen_int_int_map.h>
-#include <xen/api/xen_int_string_set_map.h>
-#include <xen/api/xen_network.h>
-#include <xen/api/xen_on_crash_behaviour.h>
-#include <xen/api/xen_on_normal_exit.h>
-#include <xen/api/xen_pbd.h>
-#include <xen/api/xen_pif.h>
-#include <xen/api/xen_pif_metrics.h>
-#include <xen/api/xen_sr.h>
-#include <xen/api/xen_string_set.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_user.h>
-#include <xen/api/xen_vbd.h>
-#include <xen/api/xen_vbd_metrics.h>
-#include <xen/api/xen_vbd_mode.h>
-#include <xen/api/xen_vbd_type.h>
-#include <xen/api/xen_vdi.h>
-#include <xen/api/xen_vdi_type.h>
-#include <xen/api/xen_vif.h>
-#include <xen/api/xen_vif_metrics.h>
-#include <xen/api/xen_vm_guest_metrics.h>
-#include <xen/api/xen_vm.h>
-#include <xen/api/xen_vm_metrics.h>
-#include <xen/api/xen_vm_power_state.h>
-#include <xen/api/xen_xspolicy.h>
-#include <xen/api/xen_cpu_pool.h>
-#endif
diff --git a/tools/libxen/include/xen/api/xen_common.h b/tools/libxen/include/xen/api/xen_common.h
deleted file mode 100644
index ebcebd9..0000000
--- a/tools/libxen/include/xen/api/xen_common.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2006 XenSource, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_COMMON_H
-#define XEN_COMMON_H
-
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <time.h>
-
-#include "xen/api/xen_host_decl.h"
-
-
-typedef bool (*xen_result_func)(const void *data, size_t len,
- void *result_handle);
-
-
-/**
- * len does not include a terminating \0.
- */
-typedef int (*xen_call_func)(const void *, size_t len, void *user_handle,
- void *result_handle,
- xen_result_func result_func);
-
-
-typedef struct
-{
- xen_call_func call_func;
- void *handle;
- const char *session_id;
- bool ok;
- char **error_description;
- int error_description_count;
-} xen_session;
-
-
-typedef struct xen_session_record
-{
- char *uuid;
- struct xen_host_record_opt *this_host;
- char *this_user;
- time_t last_active;
-} xen_session_record;
-
-
-/**
- * Allocate a xen_session_record.
- */
-extern xen_session_record *
-xen_session_record_alloc(void);
-
-
-/**
- * Free the given xen_session_record, and all referenced values. The
- * given record must have been allocated by this library.
- */
-extern void
-xen_session_record_free(xen_session_record *record);
-
-
-struct xen_task_;
-typedef struct xen_task_ * xen_task_id;
-
-
-typedef struct
-{
- int progress;
- long eta;
- /* !!! RESULT */
-} xen_task_status;
-
-
-typedef struct
-{
- int major;
- int minor;
- int patch;
- char *extraversion;
-} xen_version;
-
-
-/**
- * Free the given xen_version, and all referenced values.
- */
-extern void xen_version_free(xen_version *version);
-
-
-/**
- * Return the version of this client-side library. This will be the major,
- * minor, and extraversion of the Xen release with which it was released,
- * plus the library's own version as the patch.
- */
-extern xen_version *xen_get_client_side_version(void);
-
-
-extern bool
-xen_uuid_string_to_bytes(char *uuid, char **bytes);
-
-
-extern bool
-xen_uuid_bytes_to_string(char *bytes, char **uuid);
-
-
-extern void
-xen_uuid_free(char *uuid);
-
-
-extern void
-xen_uuid_bytes_free(char *bytes);
-
-
-/**
- * Initialise this library. Call this before starting to use this library.
- * Note that since this library depends upon libxml2, you should also call
- * xmlInitParser as appropriate for your program.
- */
-extern
-void xen_init(void);
-
-
-/**
- * Clear up this library. Call when you have finished using this library.
- * Note that since this library depends upon libxml2, you should also call
- * xmlCleanupParser as appropriate for your program.
- */
-extern
-void xen_fini(void);
-
-
-/**
- * Log in at the server, and allocate a xen_session to represent this session.
- */
-extern xen_session *
-xen_session_login_with_password(xen_call_func call_func, void *handle,
- const char *uname, const char *pwd);
-
-
-/**
- * Log out at the server, and free the xen_session.
- */
-extern void
-xen_session_logout(xen_session *session);
-
-
-/**
- * Clear any error condition recorded on this session.
- */
-void
-xen_session_clear_error(xen_session *session);
-
-
-/**
- * Get the UUID of the second given session. Set *result to point at a
- * string, yours to free.
- */
-extern bool
-xen_session_get_uuid(xen_session *session, char **result,
- xen_session *self_session);
-
-
-/**
- * Get the this_host field of the second given session. Set *result to be a
- * handle to that host.
- */
-extern bool
-xen_session_get_this_host(xen_session *session, xen_host *result,
- xen_session *self_session);
-
-
-/**
- * Get the this_user field of the second given session. Set *result to point
- * at a string, yours to free.
- */
-extern bool
-xen_session_get_this_user(xen_session *session, char **result,
- xen_session *self_session);
-
-
-/**
- * Get the last_active field of the given session, and place it in *result.
- */
-extern bool
-xen_session_get_last_active(xen_session *session, time_t *result,
- xen_session *self_session);
-
-/**
- * Get a record containing the current state of the second given session.
- */
-extern bool
-xen_session_get_record(xen_session *session, xen_session_record **result,
- xen_session *self_session);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_console.h b/tools/libxen/include/xen/api/xen_console.h
deleted file mode 100644
index 19bfdeb..0000000
--- a/tools/libxen/include/xen/api/xen_console.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_CONSOLE_H
-#define XEN_CONSOLE_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_console_decl.h>
-#include <xen/api/xen_console_protocol.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vm_decl.h>
-
-
-/*
- * The console class.
- *
- * A console.
- */
-
-
-/**
- * Free the given xen_console. The given handle must have been
- * allocated by this library.
- */
-extern void
-xen_console_free(xen_console console);
-
-
-typedef struct xen_console_set
-{
- size_t size;
- xen_console *contents[];
-} xen_console_set;
-
-/**
- * Allocate a xen_console_set of the given size.
- */
-extern xen_console_set *
-xen_console_set_alloc(size_t size);
-
-/**
- * Free the given xen_console_set. The given set must have been
- * allocated by this library.
- */
-extern void
-xen_console_set_free(xen_console_set *set);
-
-
-typedef struct xen_console_record
-{
- xen_console handle;
- char *uuid;
- enum xen_console_protocol protocol;
- char *location;
- struct xen_vm_record_opt *vm;
- xen_string_string_map *other_config;
-} xen_console_record;
-
-/**
- * Allocate a xen_console_record.
- */
-extern xen_console_record *
-xen_console_record_alloc(void);
-
-/**
- * Free the given xen_console_record, and all referenced values. The
- * given record must have been allocated by this library.
- */
-extern void
-xen_console_record_free(xen_console_record *record);
-
-
-typedef struct xen_console_record_opt
-{
- bool is_record;
- union
- {
- xen_console handle;
- xen_console_record *record;
- } u;
-} xen_console_record_opt;
-
-/**
- * Allocate a xen_console_record_opt.
- */
-extern xen_console_record_opt *
-xen_console_record_opt_alloc(void);
-
-/**
- * Free the given xen_console_record_opt, and all referenced values.
- * The given record_opt must have been allocated by this library.
- */
-extern void
-xen_console_record_opt_free(xen_console_record_opt *record_opt);
-
-
-typedef struct xen_console_record_set
-{
- size_t size;
- xen_console_record *contents[];
-} xen_console_record_set;
-
-/**
- * Allocate a xen_console_record_set of the given size.
- */
-extern xen_console_record_set *
-xen_console_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_console_record_set, and all referenced values.
- * The given set must have been allocated by this library.
- */
-extern void
-xen_console_record_set_free(xen_console_record_set *set);
-
-
-
-typedef struct xen_console_record_opt_set
-{
- size_t size;
- xen_console_record_opt *contents[];
-} xen_console_record_opt_set;
-
-/**
- * Allocate a xen_console_record_opt_set of the given size.
- */
-extern xen_console_record_opt_set *
-xen_console_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_console_record_opt_set, and all referenced
- * values. The given set must have been allocated by this library.
- */
-extern void
-xen_console_record_opt_set_free(xen_console_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given console.
- */
-extern bool
-xen_console_get_record(xen_session *session, xen_console_record **result, xen_console console);
-
-
-/**
- * Get a reference to the console instance with the specified UUID.
- */
-extern bool
-xen_console_get_by_uuid(xen_session *session, xen_console *result, char *uuid);
-
-
-/**
- * Create a new console instance, and return its handle.
- */
-extern bool
-xen_console_create(xen_session *session, xen_console *result, xen_console_record *record);
-
-
-/**
- * Destroy the specified console instance.
- */
-extern bool
-xen_console_destroy(xen_session *session, xen_console console);
-
-
-/**
- * Get the uuid field of the given console.
- */
-extern bool
-xen_console_get_uuid(xen_session *session, char **result, xen_console console);
-
-
-/**
- * Get the protocol field of the given console.
- */
-extern bool
-xen_console_get_protocol(xen_session *session, enum xen_console_protocol *result, xen_console console);
-
-
-/**
- * Get the location field of the given console.
- */
-extern bool
-xen_console_get_location(xen_session *session, char **result, xen_console console);
-
-
-/**
- * Get the VM field of the given console.
- */
-extern bool
-xen_console_get_vm(xen_session *session, xen_vm *result, xen_console console);
-
-
-/**
- * Get the other_config field of the given console.
- */
-extern bool
-xen_console_get_other_config(xen_session *session, xen_string_string_map **result, xen_console console);
-
-
-/**
- * Set the other_config field of the given console.
- */
-extern bool
-xen_console_set_other_config(xen_session *session, xen_console console, xen_string_string_map *other_config);
-
-
-/**
- * Add the given key-value pair to the other_config field of the given
- * console.
- */
-extern bool
-xen_console_add_to_other_config(xen_session *session, xen_console console, char *key, char *value);
-
-
-/**
- * Remove the given key and its corresponding value from the
- * other_config field of the given console. If the key is not in that Map,
- * then do nothing.
- */
-extern bool
-xen_console_remove_from_other_config(xen_session *session, xen_console console, char *key);
-
-
-/**
- * Return a list of all the consoles known to the system.
- */
-extern bool
-xen_console_get_all(xen_session *session, struct xen_console_set **result);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_console_decl.h b/tools/libxen/include/xen/api/xen_console_decl.h
deleted file mode 100644
index 432ff76..0000000
--- a/tools/libxen/include/xen/api/xen_console_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_CONSOLE_DECL_H
-#define XEN_CONSOLE_DECL_H
-
-typedef void *xen_console;
-
-struct xen_console_set;
-struct xen_console_record;
-struct xen_console_record_set;
-struct xen_console_record_opt;
-struct xen_console_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_console_protocol.h b/tools/libxen/include/xen/api/xen_console_protocol.h
deleted file mode 100644
index 413ad7a..0000000
--- a/tools/libxen/include/xen/api/xen_console_protocol.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_CONSOLE_PROTOCOL_H
-#define XEN_CONSOLE_PROTOCOL_H
-
-
-#include <xen/api/xen_common.h>
-
-
-enum xen_console_protocol
-{
- /**
- * VT100 terminal
- */
- XEN_CONSOLE_PROTOCOL_VT100,
-
- /**
- * Remote FrameBuffer protocol (as used in VNC)
- */
- XEN_CONSOLE_PROTOCOL_RFB,
-
- /**
- * Remote Desktop Protocol
- */
- XEN_CONSOLE_PROTOCOL_RDP
-};
-
-
-typedef struct xen_console_protocol_set
-{
- size_t size;
- enum xen_console_protocol contents[];
-} xen_console_protocol_set;
-
-/**
- * Allocate a xen_console_protocol_set of the given size.
- */
-extern xen_console_protocol_set *
-xen_console_protocol_set_alloc(size_t size);
-
-/**
- * Free the given xen_console_protocol_set. The given set must have
- * been allocated by this library.
- */
-extern void
-xen_console_protocol_set_free(xen_console_protocol_set *set);
-
-
-/**
- * Return the name corresponding to the given code. This string must
- * not be modified or freed.
- */
-extern const char *
-xen_console_protocol_to_string(enum xen_console_protocol val);
-
-
-/**
- * Return the correct code for the given string, or set the session
- * object to failure and return an undefined value if the given string does
- * not match a known code.
- */
-extern enum xen_console_protocol
-xen_console_protocol_from_string(xen_session *session, const char *str);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_cpu_pool.h b/tools/libxen/include/xen/api/xen_cpu_pool.h
deleted file mode 100644
index 423c076..0000000
--- a/tools/libxen/include/xen/api/xen_cpu_pool.h
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_CPU_POOL_H
-#define XEN_CPU_POOL_H
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_string_set.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_host_cpu_decl.h>
-#include <xen/api/xen_host.h>
-#include <xen/api/xen_vm_decl.h>
-#include <xen/api/xen_vm.h>
-#include <xen/api/xen_cpu_pool_decl.h>
-
-/*
- * The cpu_pool class.
- *
- * Management of CPU pools.
- */
-
-
-/**
- * Free the given xen_cpu_pool. The given handle must have been allocated
- * by this library.
- */
-extern void
-xen_cpu_pool_free(xen_cpu_pool cpu_pool);
-
-
-typedef struct xen_cpu_pool_set
-{
- size_t size;
- xen_cpu_pool *contents[];
-} xen_cpu_pool_set;
-
-/**
- * Allocate a xen_cpu_pool_set of the given size.
- */
-extern xen_cpu_pool_set *
-xen_cpu_pool_set_alloc(size_t size);
-
-/**
- * Free the given xen_cpu_pool_set. The given set must have been allocated
- * by this library.
- */
-extern void
-xen_cpu_pool_set_free(xen_cpu_pool_set *set);
-
-
-typedef struct xen_cpu_pool_record
-{
- xen_cpu_pool handle;
- char *uuid;
- char *name_label;
- char *name_description;
- struct xen_host_record_opt *resident_on;
- bool auto_power_on;
- struct xen_vm_record_opt_set *started_vms;
- int64_t ncpu;
- char *sched_policy;
- struct xen_string_set *proposed_cpus;
- struct xen_host_cpu_record_opt_set *host_cpus;
- bool activated;
- xen_string_string_map *other_config;
-} xen_cpu_pool_record;
-
-/**
- * Allocate a xen_cpu_pool_record.
- */
-extern xen_cpu_pool_record *
-xen_cpu_pool_record_alloc(void);
-
-/**
- * Free the given xen_cpu_pool_record, and all referenced values. The given
- * record must have been allocated by this library.
- */
-extern void
-xen_cpu_pool_record_free(xen_cpu_pool_record *record);
-
-
-typedef struct xen_cpu_pool_record_opt
-{
- bool is_record;
- union
- {
- xen_cpu_pool handle;
- xen_cpu_pool_record *record;
- } u;
-} xen_cpu_pool_record_opt;
-
-/**
- * Allocate a xen_cpu_pool_record_opt.
- */
-extern xen_cpu_pool_record_opt *
-xen_cpu_pool_record_opt_alloc(void);
-
-/**
- * Free the given xen_cpu_pool_record_opt, and all referenced values. The
- * given record_opt must have been allocated by this library.
- */
-extern void
-xen_cpu_pool_record_opt_free(xen_cpu_pool_record_opt *record_opt);
-
-
-typedef struct xen_cpu_pool_record_set
-{
- size_t size;
- xen_cpu_pool_record *contents[];
-} xen_cpu_pool_record_set;
-
-/**
- * Allocate a xen_cpu_pool_record_set of the given size.
- */
-extern xen_cpu_pool_record_set *
-xen_cpu_pool_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_cpu_pool_record_set, and all referenced values. The
- * given set must have been allocated by this library.
- */
-extern void
-xen_cpu_pool_record_set_free(xen_cpu_pool_record_set *set);
-
-
-
-typedef struct xen_cpu_pool_record_opt_set
-{
- size_t size;
- xen_cpu_pool_record_opt *contents[];
-} xen_cpu_pool_record_opt_set;
-
-/**
- * Allocate a xen_cpu_pool_record_opt_set of the given size.
- */
-extern xen_cpu_pool_record_opt_set *
-xen_cpu_pool_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_cpu_pool_record_opt_set, and all referenced values.
- * The given set must have been allocated by this library.
- */
-extern void
-xen_cpu_pool_record_opt_set_free(xen_cpu_pool_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given cpu_pool.
- */
-extern bool
-xen_cpu_pool_get_record(xen_session *session, xen_cpu_pool_record **result,
- xen_cpu_pool cpu_pool);
-
-
-/**
- * Get a reference to the cpu_pool instance with the specified UUID.
- */
-extern bool
-xen_cpu_pool_get_by_uuid(xen_session *session, xen_cpu_pool *result, char *uuid);
-
-
-/**
- * Create a new cpu_pool instance, and return its handle.
- */
-extern bool
-xen_cpu_pool_create(xen_session *session, xen_cpu_pool *result,
- xen_cpu_pool_record *record);
-
-
-/**
- * Destroy the specified VBD instance.
- */
-extern bool
-xen_cpu_pool_destroy(xen_session *session, xen_cpu_pool cpu_pool);
-
-
-/**
- * Get the uuid field of the given cpu_pool.
- */
-extern bool
-xen_cpu_pool_get_uuid(xen_session *session, char **result, xen_cpu_pool cpu_pool);
-
-
-/**
- * Deactivate the given cpu_pool.
- */
-extern bool
-xen_cpu_pool_deactivate(xen_session *session, xen_cpu_pool cpu_pool);
-
-
-/**
- * Activate the given cpu_pool.
- */
-extern bool
-xen_cpu_pool_activate(xen_session *session, xen_cpu_pool cpu_pool);
-
-
-/**
- * Add a physical cpu to the active pool.
- */
-extern bool
-xen_cpu_pool_add_host_CPU_live(xen_session *session, xen_cpu_pool cpu_pool,
- xen_host_cpu host_cpu);
-
-
-/**
- * Remove a physical cpu from the active pool.
- */
-extern bool
-xen_cpu_pool_remove_host_CPU_live(xen_session *session, xen_cpu_pool cpu_pool,
- xen_host_cpu host_cpu);
-
-
-/**
- * Return a list of all the cpu_pools known to the system.
- */
-extern bool
-xen_cpu_pool_get_all(xen_session *session, struct xen_cpu_pool_set **result);
-
-
-/**
- * Get the uuid field of the cpu_pool with given name.
- */
-extern bool
-xen_cpu_pool_get_by_name_label(xen_session *session,
- struct xen_cpu_pool_set **result, char *label);
-
-
-/**
- * Get activation state of given cpu_pool.
- */
-extern bool
-xen_cpu_pool_get_activated(xen_session *session, bool *result,
- xen_cpu_pool cpu_pool);
-
-
-/**
- * Get auto_power_on option of given cpu_pool.
- */
-extern bool
-xen_cpu_pool_get_auto_power_on(xen_session *session, bool *result,
- xen_cpu_pool cpu_pool);
-
-
-/**
- * Get host_cpu refs of all physical cpus of cpu_pool.
- */
-extern bool
-xen_cpu_pool_get_host_CPUs(xen_session *session, struct xen_host_cpu_set **result,
- xen_cpu_pool cpu_pool);
-
-
-/**
- * Get name description field of given cpu_pool.
- */
-extern bool
-xen_cpu_pool_get_name_description(xen_session *session, char **result,
- xen_cpu_pool cpu_pool);
-
-
-/**
- * Get name label field of given cpu_pool.
- */
-extern bool
-xen_cpu_pool_get_name_label(xen_session *session, char **result,
- xen_cpu_pool cpu_pool);
-
-
-/**
- * Get count of physical cpus to attach to cpu_pool on activation.
- */
-extern bool
-xen_cpu_pool_get_ncpu(xen_session *session, int64_t *result,
- xen_cpu_pool cpu_pool);
-
-
-/**
- * Get proposed_CPUs field of given cpu_pool.
- */
-extern bool
-xen_cpu_pool_get_proposed_CPUs(xen_session *session, struct xen_string_set **result,
- xen_cpu_pool cpu_pool);
-
-
-/**
- * Get the other_config field of the given cpu_pool.
- */
-extern bool
-xen_cpu_pool_get_other_config(xen_session *session, xen_string_string_map **result,
- xen_cpu_pool cpu_pool);
-
-
-/**
- * Get host the cpu_pool is resident on.
- */
-extern bool
-xen_cpu_pool_get_resident_on(xen_session *session, xen_host *result,
- xen_cpu_pool cpu_pool);
-
-
-/**
- * Get sched_policy field of given cpu_pool.
- */
-extern bool
-xen_cpu_pool_get_sched_policy(xen_session *session, char **result,
- xen_cpu_pool cpu_pool);
-
-
-/**
- * Get set of started vms in given cpu_pool.
- */
-extern bool
-xen_cpu_pool_get_started_VMs(xen_session *session, xen_vm_set **result,
- xen_cpu_pool cpu_pool);
-
-
-/**
- * Set auto_power_on field of given cpu_pool.
- */
-extern bool
-xen_cpu_pool_set_auto_power_on(xen_session *session, xen_cpu_pool cpu_pool,
- bool auto_power_on);
-
-
-/**
- * Set proposed_CPUs field of given cpu_pool.
- */
-extern bool
-xen_cpu_pool_set_proposed_CPUs(xen_session *session, xen_cpu_pool cpu_pool,
- xen_string_set *proposed_cpus);
-
-
-/**
- * Add a proposed cpu to proposed_CPUs field of given cpu_pool.
- */
-extern bool
-xen_cpu_pool_add_to_proposed_CPUs(xen_session *session, xen_cpu_pool cpu_pool,
- char* proposed_cpu);
-
-
-/**
- * Remove a proposed cpu from proposed_CPUs field of given cpu_pool.
- */
-extern bool
-xen_cpu_pool_remove_from_proposed_CPUs(xen_session *session, xen_cpu_pool cpu_pool,
- char* proposed_cpu);
-
-
-/**
- * Set name_label field of given cpu_pool.
- */
-extern bool
-xen_cpu_pool_set_name_label(xen_session *session, xen_cpu_pool cpu_pool,
- char *label);
-
-
-/**
- * Set name_description field of given cpu_pool.
- */
-extern bool
-xen_cpu_pool_set_name_description(xen_session *session, xen_cpu_pool cpu_pool,
- char *descr);
-
-
-/**
- * Set ncpu field of given cpu_pool.
- */
-extern bool
-xen_cpu_pool_set_ncpu(xen_session *session, xen_cpu_pool cpu_pool, int64_t ncpu);
-
-
-/**
- * Set the other_config field of the given cpu_pool.
- */
-extern bool
-xen_cpu_pool_set_other_config(xen_session *session, xen_cpu_pool cpu_pool,
- xen_string_string_map *other_config);
-
-
-/**
- * Add the given key-value pair to the other_config field of the given
- * cpu_pool.
- */
-extern bool
-xen_cpu_pool_add_to_other_config(xen_session *session, xen_cpu_pool cpu_pool,
- char *key, char *value);
-
-
-/**
- * Remove the given key and its corresponding value from the
- * other_config field of the given cpu_pool. If the key is not in that Map, then
- * do nothing.
- */
-extern bool
-xen_cpu_pool_remove_from_other_config(xen_session *session, xen_cpu_pool cpu_pool,
- char *key);
-
-/**
- * Set sched_policy of given cpu_pool.
- */
-extern bool
-xen_cpu_pool_set_sched_policy(xen_session *session, xen_cpu_pool cpu_pool,
- char *sched_policy);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_cpu_pool_decl.h b/tools/libxen/include/xen/api/xen_cpu_pool_decl.h
deleted file mode 100644
index 62878dd..0000000
--- a/tools/libxen/include/xen/api/xen_cpu_pool_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_CPU_POOL_DECL_H
-#define XEN_CPU_POOL_DECL_H
-
-typedef void *xen_cpu_pool;
-
-struct xen_cpu_pool_set;
-struct xen_cpu_pool_record;
-struct xen_cpu_pool_record_set;
-struct xen_cpu_pool_record_opt;
-struct xen_cpu_pool_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_crashdump.h b/tools/libxen/include/xen/api/xen_crashdump.h
deleted file mode 100644
index 145e041..0000000
--- a/tools/libxen/include/xen/api/xen_crashdump.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_CRASHDUMP_H
-#define XEN_CRASHDUMP_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_crashdump_decl.h>
-#include <xen/api/xen_vdi_decl.h>
-#include <xen/api/xen_vm_decl.h>
-
-
-/*
- * The crashdump class.
- *
- * A VM crashdump.
- */
-
-
-/**
- * Free the given xen_crashdump. The given handle must have been
- * allocated by this library.
- */
-extern void
-xen_crashdump_free(xen_crashdump crashdump);
-
-
-typedef struct xen_crashdump_set
-{
- size_t size;
- xen_crashdump *contents[];
-} xen_crashdump_set;
-
-/**
- * Allocate a xen_crashdump_set of the given size.
- */
-extern xen_crashdump_set *
-xen_crashdump_set_alloc(size_t size);
-
-/**
- * Free the given xen_crashdump_set. The given set must have been
- * allocated by this library.
- */
-extern void
-xen_crashdump_set_free(xen_crashdump_set *set);
-
-
-typedef struct xen_crashdump_record
-{
- xen_crashdump handle;
- char *uuid;
- struct xen_vm_record_opt *vm;
- struct xen_vdi_record_opt *vdi;
-} xen_crashdump_record;
-
-/**
- * Allocate a xen_crashdump_record.
- */
-extern xen_crashdump_record *
-xen_crashdump_record_alloc(void);
-
-/**
- * Free the given xen_crashdump_record, and all referenced values. The
- * given record must have been allocated by this library.
- */
-extern void
-xen_crashdump_record_free(xen_crashdump_record *record);
-
-
-typedef struct xen_crashdump_record_opt
-{
- bool is_record;
- union
- {
- xen_crashdump handle;
- xen_crashdump_record *record;
- } u;
-} xen_crashdump_record_opt;
-
-/**
- * Allocate a xen_crashdump_record_opt.
- */
-extern xen_crashdump_record_opt *
-xen_crashdump_record_opt_alloc(void);
-
-/**
- * Free the given xen_crashdump_record_opt, and all referenced values.
- * The given record_opt must have been allocated by this library.
- */
-extern void
-xen_crashdump_record_opt_free(xen_crashdump_record_opt *record_opt);
-
-
-typedef struct xen_crashdump_record_set
-{
- size_t size;
- xen_crashdump_record *contents[];
-} xen_crashdump_record_set;
-
-/**
- * Allocate a xen_crashdump_record_set of the given size.
- */
-extern xen_crashdump_record_set *
-xen_crashdump_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_crashdump_record_set, and all referenced values.
- * The given set must have been allocated by this library.
- */
-extern void
-xen_crashdump_record_set_free(xen_crashdump_record_set *set);
-
-
-
-typedef struct xen_crashdump_record_opt_set
-{
- size_t size;
- xen_crashdump_record_opt *contents[];
-} xen_crashdump_record_opt_set;
-
-/**
- * Allocate a xen_crashdump_record_opt_set of the given size.
- */
-extern xen_crashdump_record_opt_set *
-xen_crashdump_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_crashdump_record_opt_set, and all referenced
- * values. The given set must have been allocated by this library.
- */
-extern void
-xen_crashdump_record_opt_set_free(xen_crashdump_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given crashdump.
- */
-extern bool
-xen_crashdump_get_record(xen_session *session, xen_crashdump_record **result, xen_crashdump crashdump);
-
-
-/**
- * Get a reference to the crashdump instance with the specified UUID.
- */
-extern bool
-xen_crashdump_get_by_uuid(xen_session *session, xen_crashdump *result, char *uuid);
-
-
-/**
- * Get the uuid field of the given crashdump.
- */
-extern bool
-xen_crashdump_get_uuid(xen_session *session, char **result, xen_crashdump crashdump);
-
-
-/**
- * Get the VM field of the given crashdump.
- */
-extern bool
-xen_crashdump_get_vm(xen_session *session, xen_vm *result, xen_crashdump crashdump);
-
-
-/**
- * Get the VDI field of the given crashdump.
- */
-extern bool
-xen_crashdump_get_vdi(xen_session *session, xen_vdi *result, xen_crashdump crashdump);
-
-
-/**
- * Destroy the specified crashdump.
- */
-extern bool
-xen_crashdump_destroy(xen_session *session, xen_crashdump self);
-
-
-/**
- * Return a list of all the crashdumps known to the system.
- */
-extern bool
-xen_crashdump_get_all(xen_session *session, struct xen_crashdump_set **result);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_crashdump_decl.h b/tools/libxen/include/xen/api/xen_crashdump_decl.h
deleted file mode 100644
index 4eb6d54..0000000
--- a/tools/libxen/include/xen/api/xen_crashdump_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_CRASHDUMP_DECL_H
-#define XEN_CRASHDUMP_DECL_H
-
-typedef void *xen_crashdump;
-
-struct xen_crashdump_set;
-struct xen_crashdump_record;
-struct xen_crashdump_record_set;
-struct xen_crashdump_record_opt;
-struct xen_crashdump_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_event.h b/tools/libxen/include/xen/api/xen_event.h
deleted file mode 100644
index 6a2845b..0000000
--- a/tools/libxen/include/xen/api/xen_event.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_EVENT_H
-#define XEN_EVENT_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_event_decl.h>
-#include <xen/api/xen_event_operation.h>
-#include <xen/api/xen_string_set.h>
-
-
-/*
- * The event class.
- *
- * Asynchronous event registration and handling.
- */
-
-
-
-typedef struct xen_event_record
-{
- int64_t id;
- time_t timestamp;
- char *class;
- enum xen_event_operation operation;
- char *ref;
- char *obj_uuid;
-} xen_event_record;
-
-/**
- * Allocate a xen_event_record.
- */
-extern xen_event_record *
-xen_event_record_alloc(void);
-
-/**
- * Free the given xen_event_record, and all referenced values. The
- * given record must have been allocated by this library.
- */
-extern void
-xen_event_record_free(xen_event_record *record);
-
-
-typedef struct xen_event_record_set
-{
- size_t size;
- xen_event_record *contents[];
-} xen_event_record_set;
-
-/**
- * Allocate a xen_event_record_set of the given size.
- */
-extern xen_event_record_set *
-xen_event_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_event_record_set, and all referenced values. The
- * given set must have been allocated by this library.
- */
-extern void
-xen_event_record_set_free(xen_event_record_set *set);
-
-
-/**
- * Registers this session with the event system. Specifying the empty
- * list will register for all classes.
- */
-extern bool
-xen_event_register(xen_session *session, struct xen_string_set *classes);
-
-
-/**
- * Unregisters this session with the event system.
- */
-extern bool
-xen_event_unregister(xen_session *session, struct xen_string_set *classes);
-
-
-/**
- * Blocking call which returns a (possibly empty) batch of events.
- */
-extern bool
-xen_event_next(xen_session *session, struct xen_event_record_set **result);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_event_decl.h b/tools/libxen/include/xen/api/xen_event_decl.h
deleted file mode 100644
index 856991f..0000000
--- a/tools/libxen/include/xen/api/xen_event_decl.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_EVENT_DECL_H
-#define XEN_EVENT_DECL_H
-
-struct xen_event_record;
-struct xen_event_record_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_event_operation.h b/tools/libxen/include/xen/api/xen_event_operation.h
deleted file mode 100644
index 31cce20..0000000
--- a/tools/libxen/include/xen/api/xen_event_operation.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_EVENT_OPERATION_H
-#define XEN_EVENT_OPERATION_H
-
-
-#include <xen/api/xen_common.h>
-
-
-enum xen_event_operation
-{
- /**
- * An object has been created
- */
- XEN_EVENT_OPERATION_ADD,
-
- /**
- * An object has been deleted
- */
- XEN_EVENT_OPERATION_DEL,
-
- /**
- * An object has been modified
- */
- XEN_EVENT_OPERATION_MOD
-};
-
-
-typedef struct xen_event_operation_set
-{
- size_t size;
- enum xen_event_operation contents[];
-} xen_event_operation_set;
-
-/**
- * Allocate a xen_event_operation_set of the given size.
- */
-extern xen_event_operation_set *
-xen_event_operation_set_alloc(size_t size);
-
-/**
- * Free the given xen_event_operation_set. The given set must have
- * been allocated by this library.
- */
-extern void
-xen_event_operation_set_free(xen_event_operation_set *set);
-
-
-/**
- * Return the name corresponding to the given code. This string must
- * not be modified or freed.
- */
-extern const char *
-xen_event_operation_to_string(enum xen_event_operation val);
-
-
-/**
- * Return the correct code for the given string, or set the session
- * object to failure and return an undefined value if the given string does
- * not match a known code.
- */
-extern enum xen_event_operation
-xen_event_operation_from_string(xen_session *session, const char *str);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_host.h b/tools/libxen/include/xen/api/xen_host.h
deleted file mode 100644
index f3ca5b9..0000000
--- a/tools/libxen/include/xen/api/xen_host.h
+++ /dev/null
@@ -1,505 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_HOST_H
-#define XEN_HOST_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_host_cpu_decl.h>
-#include <xen/api/xen_host_decl.h>
-#include <xen/api/xen_host_metrics_decl.h>
-#include <xen/api/xen_pbd_decl.h>
-#include <xen/api/xen_pif_decl.h>
-#include <xen/api/xen_sr_decl.h>
-#include <xen/api/xen_string_set.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vm_decl.h>
-#include <xen/api/xen_cpu_pool_decl.h>
-
-/*
- * The host class.
- *
- * A physical host.
- */
-
-
-/**
- * Free the given xen_host. The given handle must have been allocated
- * by this library.
- */
-extern void
-xen_host_free(xen_host host);
-
-
-typedef struct xen_host_set
-{
- size_t size;
- xen_host *contents[];
-} xen_host_set;
-
-/**
- * Allocate a xen_host_set of the given size.
- */
-extern xen_host_set *
-xen_host_set_alloc(size_t size);
-
-/**
- * Free the given xen_host_set. The given set must have been allocated
- * by this library.
- */
-extern void
-xen_host_set_free(xen_host_set *set);
-
-
-typedef struct xen_host_record
-{
- xen_host handle;
- char *uuid;
- char *name_label;
- char *name_description;
- int64_t api_version_major;
- int64_t api_version_minor;
- char *api_version_vendor;
- xen_string_string_map *api_version_vendor_implementation;
- bool enabled;
- xen_string_string_map *software_version;
- xen_string_string_map *other_config;
- struct xen_string_set *capabilities;
- xen_string_string_map *cpu_configuration;
- char *sched_policy;
- struct xen_string_set *supported_bootloaders;
- struct xen_vm_record_opt_set *resident_vms;
- xen_string_string_map *logging;
- struct xen_pif_record_opt_set *pifs;
- struct xen_sr_record_opt *suspend_image_sr;
- struct xen_sr_record_opt *crash_dump_sr;
- struct xen_pbd_record_opt_set *pbds;
- struct xen_host_cpu_record_opt_set *host_cpus;
- struct xen_host_metrics_record_opt *metrics;
- struct xen_cpu_pool_record_opt_set *resident_cpu_pools;
-} xen_host_record;
-
-/**
- * Allocate a xen_host_record.
- */
-extern xen_host_record *
-xen_host_record_alloc(void);
-
-/**
- * Free the given xen_host_record, and all referenced values. The
- * given record must have been allocated by this library.
- */
-extern void
-xen_host_record_free(xen_host_record *record);
-
-
-typedef struct xen_host_record_opt
-{
- bool is_record;
- union
- {
- xen_host handle;
- xen_host_record *record;
- } u;
-} xen_host_record_opt;
-
-/**
- * Allocate a xen_host_record_opt.
- */
-extern xen_host_record_opt *
-xen_host_record_opt_alloc(void);
-
-/**
- * Free the given xen_host_record_opt, and all referenced values. The
- * given record_opt must have been allocated by this library.
- */
-extern void
-xen_host_record_opt_free(xen_host_record_opt *record_opt);
-
-
-typedef struct xen_host_record_set
-{
- size_t size;
- xen_host_record *contents[];
-} xen_host_record_set;
-
-/**
- * Allocate a xen_host_record_set of the given size.
- */
-extern xen_host_record_set *
-xen_host_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_host_record_set, and all referenced values. The
- * given set must have been allocated by this library.
- */
-extern void
-xen_host_record_set_free(xen_host_record_set *set);
-
-
-
-typedef struct xen_host_record_opt_set
-{
- size_t size;
- xen_host_record_opt *contents[];
-} xen_host_record_opt_set;
-
-/**
- * Allocate a xen_host_record_opt_set of the given size.
- */
-extern xen_host_record_opt_set *
-xen_host_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_host_record_opt_set, and all referenced values.
- * The given set must have been allocated by this library.
- */
-extern void
-xen_host_record_opt_set_free(xen_host_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given host.
- */
-extern bool
-xen_host_get_record(xen_session *session, xen_host_record **result, xen_host host);
-
-
-/**
- * Get a reference to the host instance with the specified UUID.
- */
-extern bool
-xen_host_get_by_uuid(xen_session *session, xen_host *result, char *uuid);
-
-
-/**
- * Get all the host instances with the given label.
- */
-extern bool
-xen_host_get_by_name_label(xen_session *session, struct xen_host_set **result, char *label);
-
-
-/**
- * Get the uuid field of the given host.
- */
-extern bool
-xen_host_get_uuid(xen_session *session, char **result, xen_host host);
-
-
-/**
- * Get the name/label field of the given host.
- */
-extern bool
-xen_host_get_name_label(xen_session *session, char **result, xen_host host);
-
-
-/**
- * Get the name/description field of the given host.
- */
-extern bool
-xen_host_get_name_description(xen_session *session, char **result, xen_host host);
-
-
-/**
- * Get the API_version/major field of the given host.
- */
-extern bool
-xen_host_get_api_version_major(xen_session *session, int64_t *result, xen_host host);
-
-
-/**
- * Get the API_version/minor field of the given host.
- */
-extern bool
-xen_host_get_api_version_minor(xen_session *session, int64_t *result, xen_host host);
-
-
-/**
- * Get the API_version/vendor field of the given host.
- */
-extern bool
-xen_host_get_api_version_vendor(xen_session *session, char **result, xen_host host);
-
-
-/**
- * Get the API_version/vendor_implementation field of the given host.
- */
-extern bool
-xen_host_get_api_version_vendor_implementation(xen_session *session, xen_string_string_map **result, xen_host host);
-
-
-/**
- * Get the enabled field of the given host.
- */
-extern bool
-xen_host_get_enabled(xen_session *session, bool *result, xen_host host);
-
-
-/**
- * Get the software_version field of the given host.
- */
-extern bool
-xen_host_get_software_version(xen_session *session, xen_string_string_map **result, xen_host host);
-
-
-/**
- * Get the other_config field of the given host.
- */
-extern bool
-xen_host_get_other_config(xen_session *session, xen_string_string_map **result, xen_host host);
-
-
-/**
- * Get the capabilities field of the given host.
- */
-extern bool
-xen_host_get_capabilities(xen_session *session, struct xen_string_set **result, xen_host host);
-
-
-/**
- * Get the cpu_configuration field of the given host.
- */
-extern bool
-xen_host_get_cpu_configuration(xen_session *session, xen_string_string_map **result, xen_host host);
-
-
-/**
- * Get the sched_policy field of the given host.
- */
-extern bool
-xen_host_get_sched_policy(xen_session *session, char **result, xen_host host);
-
-
-/**
- * Get the supported_bootloaders field of the given host.
- */
-extern bool
-xen_host_get_supported_bootloaders(xen_session *session, struct xen_string_set **result, xen_host host);
-
-
-/**
- * Get the resident_VMs field of the given host.
- */
-extern bool
-xen_host_get_resident_vms(xen_session *session, struct xen_vm_set **result, xen_host host);
-
-
-/**
- * Get the logging field of the given host.
- */
-extern bool
-xen_host_get_logging(xen_session *session, xen_string_string_map **result, xen_host host);
-
-
-/**
- * Get the PIFs field of the given host.
- */
-extern bool
-xen_host_get_pifs(xen_session *session, struct xen_pif_set **result, xen_host host);
-
-
-/**
- * Get the suspend_image_sr field of the given host.
- */
-extern bool
-xen_host_get_suspend_image_sr(xen_session *session, xen_sr *result, xen_host host);
-
-
-/**
- * Get the crash_dump_sr field of the given host.
- */
-extern bool
-xen_host_get_crash_dump_sr(xen_session *session, xen_sr *result, xen_host host);
-
-
-/**
- * Get the PBDs field of the given host.
- */
-extern bool
-xen_host_get_pbds(xen_session *session, struct xen_pbd_set **result, xen_host host);
-
-
-/**
- * Get the host_CPUs field of the given host.
- */
-extern bool
-xen_host_get_host_cpus(xen_session *session, struct xen_host_cpu_set **result, xen_host host);
-
-
-/**
- * Get the metrics field of the given host.
- */
-extern bool
-xen_host_get_metrics(xen_session *session, xen_host_metrics *result, xen_host host);
-
-
-/**
- * Set the name/label field of the given host.
- */
-extern bool
-xen_host_set_name_label(xen_session *session, xen_host host, char *label);
-
-
-/**
- * Set the name/description field of the given host.
- */
-extern bool
-xen_host_set_name_description(xen_session *session, xen_host host, char *description);
-
-
-/**
- * Set the other_config field of the given host.
- */
-extern bool
-xen_host_set_other_config(xen_session *session, xen_host host, xen_string_string_map *other_config);
-
-
-/**
- * Add the given key-value pair to the other_config field of the given
- * host.
- */
-extern bool
-xen_host_add_to_other_config(xen_session *session, xen_host host, char *key, char *value);
-
-
-/**
- * Remove the given key and its corresponding value from the
- * other_config field of the given host. If the key is not in that Map, then
- * do nothing.
- */
-extern bool
-xen_host_remove_from_other_config(xen_session *session, xen_host host, char *key);
-
-
-/**
- * Set the logging field of the given host.
- */
-extern bool
-xen_host_set_logging(xen_session *session, xen_host host, xen_string_string_map *logging);
-
-
-/**
- * Add the given key-value pair to the logging field of the given host.
- */
-extern bool
-xen_host_add_to_logging(xen_session *session, xen_host host, char *key, char *value);
-
-
-/**
- * Remove the given key and its corresponding value from the logging
- * field of the given host. If the key is not in that Map, then do nothing.
- */
-extern bool
-xen_host_remove_from_logging(xen_session *session, xen_host host, char *key);
-
-
-/**
- * Set the suspend_image_sr field of the given host.
- */
-extern bool
-xen_host_set_suspend_image_sr(xen_session *session, xen_host host, xen_sr suspend_image_sr);
-
-
-/**
- * Set the crash_dump_sr field of the given host.
- */
-extern bool
-xen_host_set_crash_dump_sr(xen_session *session, xen_host host, xen_sr crash_dump_sr);
-
-
-/**
- * Puts the host into a state in which no new VMs can be started.
- * Currently active VMs on the host continue to execute.
- */
-extern bool
-xen_host_disable(xen_session *session, xen_host host);
-
-
-/**
- * Puts the host into a state in which new VMs can be started.
- */
-extern bool
-xen_host_enable(xen_session *session, xen_host host);
-
-
-/**
- * Shutdown the host. (This function can only be called if there are no
- * currently running VMs on the host and it is disabled.).
- */
-extern bool
-xen_host_shutdown(xen_session *session, xen_host host);
-
-
-/**
- * Reboot the host. (This function can only be called if there are no
- * currently running VMs on the host and it is disabled.).
- */
-extern bool
-xen_host_reboot(xen_session *session, xen_host host);
-
-
-/**
- * Get the host xen dmesg.
- */
-extern bool
-xen_host_dmesg(xen_session *session, char **result, xen_host host);
-
-
-/**
- * Get the host xen dmesg, and clear the buffer.
- */
-extern bool
-xen_host_dmesg_clear(xen_session *session, char **result, xen_host host);
-
-
-/**
- * Get the host's log file.
- */
-extern bool
-xen_host_get_log(xen_session *session, char **result, xen_host host);
-
-
-/**
- * Inject the given string as debugging keys into Xen.
- */
-extern bool
-xen_host_send_debug_keys(xen_session *session, xen_host host, char *keys);
-
-
-/**
- * List all supported methods.
- */
-extern bool
-xen_host_list_methods(xen_session *session, struct xen_string_set **result);
-
-
-/**
- * Return a list of all the hosts known to the system.
- */
-extern bool
-xen_host_get_all(xen_session *session, struct xen_host_set **result);
-
-
-/**
- * Get list of resident cpu pools.
- */
-extern bool
-xen_host_get_resident_cpu_pools(xen_session *session, struct xen_cpu_pool_set **result,
- xen_host host);
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_host_cpu.h b/tools/libxen/include/xen/api/xen_host_cpu.h
deleted file mode 100644
index 761c8f5..0000000
--- a/tools/libxen/include/xen/api/xen_host_cpu.h
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_HOST_CPU_H
-#define XEN_HOST_CPU_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_host_cpu_decl.h>
-#include <xen/api/xen_host_decl.h>
-#include <xen/api/xen_cpu_pool_decl.h>
-
-
-/*
- * The host_cpu class.
- *
- * A physical CPU.
- */
-
-
-/**
- * Free the given xen_host_cpu. The given handle must have been
- * allocated by this library.
- */
-extern void
-xen_host_cpu_free(xen_host_cpu host_cpu);
-
-
-typedef struct xen_host_cpu_set
-{
- size_t size;
- xen_host_cpu *contents[];
-} xen_host_cpu_set;
-
-/**
- * Allocate a xen_host_cpu_set of the given size.
- */
-extern xen_host_cpu_set *
-xen_host_cpu_set_alloc(size_t size);
-
-/**
- * Free the given xen_host_cpu_set. The given set must have been
- * allocated by this library.
- */
-extern void
-xen_host_cpu_set_free(xen_host_cpu_set *set);
-
-
-typedef struct xen_host_cpu_record
-{
- xen_host_cpu handle;
- char *uuid;
- struct xen_host_record_opt *host;
- int64_t number;
- char *vendor;
- int64_t speed;
- char *modelname;
- char *stepping;
- char *flags;
- char *features;
- double utilisation;
- struct xen_cpu_pool_record_opt_set *cpu_pools;
-} xen_host_cpu_record;
-
-/**
- * Allocate a xen_host_cpu_record.
- */
-extern xen_host_cpu_record *
-xen_host_cpu_record_alloc(void);
-
-/**
- * Free the given xen_host_cpu_record, and all referenced values. The
- * given record must have been allocated by this library.
- */
-extern void
-xen_host_cpu_record_free(xen_host_cpu_record *record);
-
-
-typedef struct xen_host_cpu_record_opt
-{
- bool is_record;
- union
- {
- xen_host_cpu handle;
- xen_host_cpu_record *record;
- } u;
-} xen_host_cpu_record_opt;
-
-/**
- * Allocate a xen_host_cpu_record_opt.
- */
-extern xen_host_cpu_record_opt *
-xen_host_cpu_record_opt_alloc(void);
-
-/**
- * Free the given xen_host_cpu_record_opt, and all referenced values.
- * The given record_opt must have been allocated by this library.
- */
-extern void
-xen_host_cpu_record_opt_free(xen_host_cpu_record_opt *record_opt);
-
-
-typedef struct xen_host_cpu_record_set
-{
- size_t size;
- xen_host_cpu_record *contents[];
-} xen_host_cpu_record_set;
-
-/**
- * Allocate a xen_host_cpu_record_set of the given size.
- */
-extern xen_host_cpu_record_set *
-xen_host_cpu_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_host_cpu_record_set, and all referenced values.
- * The given set must have been allocated by this library.
- */
-extern void
-xen_host_cpu_record_set_free(xen_host_cpu_record_set *set);
-
-
-
-typedef struct xen_host_cpu_record_opt_set
-{
- size_t size;
- xen_host_cpu_record_opt *contents[];
-} xen_host_cpu_record_opt_set;
-
-/**
- * Allocate a xen_host_cpu_record_opt_set of the given size.
- */
-extern xen_host_cpu_record_opt_set *
-xen_host_cpu_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_host_cpu_record_opt_set, and all referenced
- * values. The given set must have been allocated by this library.
- */
-extern void
-xen_host_cpu_record_opt_set_free(xen_host_cpu_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given host_cpu.
- */
-extern bool
-xen_host_cpu_get_record(xen_session *session, xen_host_cpu_record **result, xen_host_cpu host_cpu);
-
-
-/**
- * Get a reference to the host_cpu instance with the specified UUID.
- */
-extern bool
-xen_host_cpu_get_by_uuid(xen_session *session, xen_host_cpu *result, char *uuid);
-
-
-/**
- * Get the uuid field of the given host_cpu.
- */
-extern bool
-xen_host_cpu_get_uuid(xen_session *session, char **result, xen_host_cpu host_cpu);
-
-
-/**
- * Get the host field of the given host_cpu.
- */
-extern bool
-xen_host_cpu_get_host(xen_session *session, xen_host *result, xen_host_cpu host_cpu);
-
-
-/**
- * Get the number field of the given host_cpu.
- */
-extern bool
-xen_host_cpu_get_number(xen_session *session, int64_t *result, xen_host_cpu host_cpu);
-
-
-/**
- * Get the vendor field of the given host_cpu.
- */
-extern bool
-xen_host_cpu_get_vendor(xen_session *session, char **result, xen_host_cpu host_cpu);
-
-
-/**
- * Get the speed field of the given host_cpu.
- */
-extern bool
-xen_host_cpu_get_speed(xen_session *session, int64_t *result, xen_host_cpu host_cpu);
-
-
-/**
- * Get the modelname field of the given host_cpu.
- */
-extern bool
-xen_host_cpu_get_modelname(xen_session *session, char **result, xen_host_cpu host_cpu);
-
-
-/**
- * Get the stepping field of the given host_cpu.
- */
-extern bool
-xen_host_cpu_get_stepping(xen_session *session, char **result, xen_host_cpu host_cpu);
-
-
-/**
- * Get the flags field of the given host_cpu.
- */
-extern bool
-xen_host_cpu_get_flags(xen_session *session, char **result, xen_host_cpu host_cpu);
-
-
-/**
- * Get the features field of the given host_cpu.
- */
-extern bool
-xen_host_cpu_get_features(xen_session *session, char **result, xen_host_cpu host_cpu);
-
-
-/**
- * Get the utilisation field of the given host_cpu.
- */
-extern bool
-xen_host_cpu_get_utilisation(xen_session *session, double *result, xen_host_cpu host_cpu);
-
-
-/**
- * Return a list of all the host_cpus known to the system.
- */
-extern bool
-xen_host_cpu_get_all(xen_session *session, struct xen_host_cpu_set **result);
-
-
-/**
- * Get the ref of the cpu_pool to which the host_cpu belongs.
- */
-extern bool
-xen_host_cpu_get_cpu_pool(xen_session *session, struct xen_cpu_pool_set **result, xen_host_cpu host_cpu);
-
-
-/**
- * Return a list of all the host_cpus not assigned to a cpu_pool.
- */
-extern bool
-xen_host_cpu_get_unassigned_cpus(xen_session *session, struct xen_host_cpu_set **result);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_host_cpu_decl.h b/tools/libxen/include/xen/api/xen_host_cpu_decl.h
deleted file mode 100644
index 1e9be29..0000000
--- a/tools/libxen/include/xen/api/xen_host_cpu_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_HOST_CPU_DECL_H
-#define XEN_HOST_CPU_DECL_H
-
-typedef void *xen_host_cpu;
-
-struct xen_host_cpu_set;
-struct xen_host_cpu_record;
-struct xen_host_cpu_record_set;
-struct xen_host_cpu_record_opt;
-struct xen_host_cpu_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_host_decl.h b/tools/libxen/include/xen/api/xen_host_decl.h
deleted file mode 100644
index 79d974b..0000000
--- a/tools/libxen/include/xen/api/xen_host_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_HOST_DECL_H
-#define XEN_HOST_DECL_H
-
-typedef void *xen_host;
-
-struct xen_host_set;
-struct xen_host_record;
-struct xen_host_record_set;
-struct xen_host_record_opt;
-struct xen_host_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_host_metrics.h b/tools/libxen/include/xen/api/xen_host_metrics.h
deleted file mode 100644
index 2055362..0000000
--- a/tools/libxen/include/xen/api/xen_host_metrics.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_HOST_METRICS_H
-#define XEN_HOST_METRICS_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_host_metrics_decl.h>
-
-
-/*
- * The host_metrics class.
- *
- * The metrics associated with a host.
- */
-
-
-/**
- * Free the given xen_host_metrics. The given handle must have been
- * allocated by this library.
- */
-extern void
-xen_host_metrics_free(xen_host_metrics host_metrics);
-
-
-typedef struct xen_host_metrics_set
-{
- size_t size;
- xen_host_metrics *contents[];
-} xen_host_metrics_set;
-
-/**
- * Allocate a xen_host_metrics_set of the given size.
- */
-extern xen_host_metrics_set *
-xen_host_metrics_set_alloc(size_t size);
-
-/**
- * Free the given xen_host_metrics_set. The given set must have been
- * allocated by this library.
- */
-extern void
-xen_host_metrics_set_free(xen_host_metrics_set *set);
-
-
-typedef struct xen_host_metrics_record
-{
- xen_host_metrics handle;
- char *uuid;
- int64_t memory_total;
- int64_t memory_free;
- time_t last_updated;
-} xen_host_metrics_record;
-
-/**
- * Allocate a xen_host_metrics_record.
- */
-extern xen_host_metrics_record *
-xen_host_metrics_record_alloc(void);
-
-/**
- * Free the given xen_host_metrics_record, and all referenced values.
- * The given record must have been allocated by this library.
- */
-extern void
-xen_host_metrics_record_free(xen_host_metrics_record *record);
-
-
-typedef struct xen_host_metrics_record_opt
-{
- bool is_record;
- union
- {
- xen_host_metrics handle;
- xen_host_metrics_record *record;
- } u;
-} xen_host_metrics_record_opt;
-
-/**
- * Allocate a xen_host_metrics_record_opt.
- */
-extern xen_host_metrics_record_opt *
-xen_host_metrics_record_opt_alloc(void);
-
-/**
- * Free the given xen_host_metrics_record_opt, and all referenced
- * values. The given record_opt must have been allocated by this library.
- */
-extern void
-xen_host_metrics_record_opt_free(xen_host_metrics_record_opt *record_opt);
-
-
-typedef struct xen_host_metrics_record_set
-{
- size_t size;
- xen_host_metrics_record *contents[];
-} xen_host_metrics_record_set;
-
-/**
- * Allocate a xen_host_metrics_record_set of the given size.
- */
-extern xen_host_metrics_record_set *
-xen_host_metrics_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_host_metrics_record_set, and all referenced
- * values. The given set must have been allocated by this library.
- */
-extern void
-xen_host_metrics_record_set_free(xen_host_metrics_record_set *set);
-
-
-
-typedef struct xen_host_metrics_record_opt_set
-{
- size_t size;
- xen_host_metrics_record_opt *contents[];
-} xen_host_metrics_record_opt_set;
-
-/**
- * Allocate a xen_host_metrics_record_opt_set of the given size.
- */
-extern xen_host_metrics_record_opt_set *
-xen_host_metrics_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_host_metrics_record_opt_set, and all referenced
- * values. The given set must have been allocated by this library.
- */
-extern void
-xen_host_metrics_record_opt_set_free(xen_host_metrics_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given host_metrics.
- */
-extern bool
-xen_host_metrics_get_record(xen_session *session, xen_host_metrics_record **result, xen_host_metrics host_metrics);
-
-
-/**
- * Get a reference to the host_metrics instance with the specified
- * UUID.
- */
-extern bool
-xen_host_metrics_get_by_uuid(xen_session *session, xen_host_metrics *result, char *uuid);
-
-
-/**
- * Get the uuid field of the given host_metrics.
- */
-extern bool
-xen_host_metrics_get_uuid(xen_session *session, char **result, xen_host_metrics host_metrics);
-
-
-/**
- * Get the memory/total field of the given host_metrics.
- */
-extern bool
-xen_host_metrics_get_memory_total(xen_session *session, int64_t *result, xen_host_metrics host_metrics);
-
-
-/**
- * Get the memory/free field of the given host_metrics.
- */
-extern bool
-xen_host_metrics_get_memory_free(xen_session *session, int64_t *result, xen_host_metrics host_metrics);
-
-
-/**
- * Get the last_updated field of the given host_metrics.
- */
-extern bool
-xen_host_metrics_get_last_updated(xen_session *session, time_t *result, xen_host_metrics host_metrics);
-
-
-/**
- * Return a list of all the host_metrics instances known to the system.
- */
-extern bool
-xen_host_metrics_get_all(xen_session *session, struct xen_host_metrics_set **result);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_host_metrics_decl.h b/tools/libxen/include/xen/api/xen_host_metrics_decl.h
deleted file mode 100644
index 8b73554..0000000
--- a/tools/libxen/include/xen/api/xen_host_metrics_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_HOST_METRICS_DECL_H
-#define XEN_HOST_METRICS_DECL_H
-
-typedef void *xen_host_metrics;
-
-struct xen_host_metrics_set;
-struct xen_host_metrics_record;
-struct xen_host_metrics_record_set;
-struct xen_host_metrics_record_opt;
-struct xen_host_metrics_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_int_float_map.h b/tools/libxen/include/xen/api/xen_int_float_map.h
deleted file mode 100644
index 058c45e..0000000
--- a/tools/libxen/include/xen/api/xen_int_float_map.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_INT_FLOAT_MAP_H
-#define XEN_INT_FLOAT_MAP_H
-
-
-#include <xen/api/xen_common.h>
-
-
-typedef struct xen_int_float_map_contents
-{
- int64_t key;
- double val;
-} xen_int_float_map_contents;
-
-
-typedef struct xen_int_float_map
-{
- size_t size;
- xen_int_float_map_contents contents[];
-} xen_int_float_map;
-
-/**
- * Allocate a xen_int_float_map of the given size.
- */
-extern xen_int_float_map *
-xen_int_float_map_alloc(size_t size);
-
-/**
- * Free the given xen_int_float_map, and all referenced values. The
- * given map must have been allocated by this library.
- */
-extern void
-xen_int_float_map_free(xen_int_float_map *map);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_int_int_map.h b/tools/libxen/include/xen/api/xen_int_int_map.h
deleted file mode 100644
index 71295a6..0000000
--- a/tools/libxen/include/xen/api/xen_int_int_map.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_INT_INT_MAP_H
-#define XEN_INT_INT_MAP_H
-
-
-#include <xen/api/xen_common.h>
-
-
-typedef struct xen_int_int_map_contents
-{
- int64_t key;
- int64_t val;
-} xen_int_int_map_contents;
-
-
-typedef struct xen_int_int_map
-{
- size_t size;
- xen_int_int_map_contents contents[];
-} xen_int_int_map;
-
-/**
- * Allocate a xen_int_int_map of the given size.
- */
-extern xen_int_int_map *
-xen_int_int_map_alloc(size_t size);
-
-/**
- * Free the given xen_int_int_map, and all referenced values. The
- * given map must have been allocated by this library.
- */
-extern void
-xen_int_int_map_free(xen_int_int_map *map);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_int_string_set_map.h b/tools/libxen/include/xen/api/xen_int_string_set_map.h
deleted file mode 100644
index bca1a6b..0000000
--- a/tools/libxen/include/xen/api/xen_int_string_set_map.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_INT_STRING_SET_MAP_H
-#define XEN_INT_STRING_SET_MAP_H
-
-
-#include <xen/api/xen_common.h>
-
-
-typedef struct xen_int_string_set_map_contents
-{
- int64_t key;
- struct xen_string_set *val;
-} xen_int_string_set_map_contents;
-
-
-typedef struct xen_int_string_set_map
-{
- size_t size;
- xen_int_string_set_map_contents contents[];
-} xen_int_string_set_map;
-
-/**
- * Allocate a xen_int_string_set_map of the given size.
- */
-extern xen_int_string_set_map *
-xen_int_string_set_map_alloc(size_t size);
-
-/**
- * Free the given xen_int_string_set_map, and all referenced values.
- * The given map must have been allocated by this library.
- */
-extern void
-xen_int_string_set_map_free(xen_int_string_set_map *map);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_network.h b/tools/libxen/include/xen/api/xen_network.h
deleted file mode 100644
index bf8295a..0000000
--- a/tools/libxen/include/xen/api/xen_network.h
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_NETWORK_H
-#define XEN_NETWORK_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_network_decl.h>
-#include <xen/api/xen_pif_decl.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vif_decl.h>
-
-
-/*
- * The network class.
- *
- * A virtual network.
- */
-
-
-/**
- * Free the given xen_network. The given handle must have been
- * allocated by this library.
- */
-extern void
-xen_network_free(xen_network network);
-
-
-typedef struct xen_network_set
-{
- size_t size;
- xen_network *contents[];
-} xen_network_set;
-
-/**
- * Allocate a xen_network_set of the given size.
- */
-extern xen_network_set *
-xen_network_set_alloc(size_t size);
-
-/**
- * Free the given xen_network_set. The given set must have been
- * allocated by this library.
- */
-extern void
-xen_network_set_free(xen_network_set *set);
-
-
-typedef struct xen_network_record
-{
- xen_network handle;
- char *uuid;
- char *name_label;
- char *name_description;
- struct xen_vif_record_opt_set *vifs;
- struct xen_pif_record_opt_set *pifs;
- xen_string_string_map *other_config;
-} xen_network_record;
-
-/**
- * Allocate a xen_network_record.
- */
-extern xen_network_record *
-xen_network_record_alloc(void);
-
-/**
- * Free the given xen_network_record, and all referenced values. The
- * given record must have been allocated by this library.
- */
-extern void
-xen_network_record_free(xen_network_record *record);
-
-
-typedef struct xen_network_record_opt
-{
- bool is_record;
- union
- {
- xen_network handle;
- xen_network_record *record;
- } u;
-} xen_network_record_opt;
-
-/**
- * Allocate a xen_network_record_opt.
- */
-extern xen_network_record_opt *
-xen_network_record_opt_alloc(void);
-
-/**
- * Free the given xen_network_record_opt, and all referenced values.
- * The given record_opt must have been allocated by this library.
- */
-extern void
-xen_network_record_opt_free(xen_network_record_opt *record_opt);
-
-
-typedef struct xen_network_record_set
-{
- size_t size;
- xen_network_record *contents[];
-} xen_network_record_set;
-
-/**
- * Allocate a xen_network_record_set of the given size.
- */
-extern xen_network_record_set *
-xen_network_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_network_record_set, and all referenced values.
- * The given set must have been allocated by this library.
- */
-extern void
-xen_network_record_set_free(xen_network_record_set *set);
-
-
-
-typedef struct xen_network_record_opt_set
-{
- size_t size;
- xen_network_record_opt *contents[];
-} xen_network_record_opt_set;
-
-/**
- * Allocate a xen_network_record_opt_set of the given size.
- */
-extern xen_network_record_opt_set *
-xen_network_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_network_record_opt_set, and all referenced
- * values. The given set must have been allocated by this library.
- */
-extern void
-xen_network_record_opt_set_free(xen_network_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given network.
- */
-extern bool
-xen_network_get_record(xen_session *session, xen_network_record **result, xen_network network);
-
-
-/**
- * Get a reference to the network instance with the specified UUID.
- */
-extern bool
-xen_network_get_by_uuid(xen_session *session, xen_network *result, char *uuid);
-
-
-/**
- * Create a new network instance, and return its handle.
- */
-extern bool
-xen_network_create(xen_session *session, xen_network *result, xen_network_record *record);
-
-
-/**
- * Destroy the specified network instance.
- */
-extern bool
-xen_network_destroy(xen_session *session, xen_network network);
-
-
-/**
- * Get all the network instances with the given label.
- */
-extern bool
-xen_network_get_by_name_label(xen_session *session, struct xen_network_set **result, char *label);
-
-
-/**
- * Get the uuid field of the given network.
- */
-extern bool
-xen_network_get_uuid(xen_session *session, char **result, xen_network network);
-
-
-/**
- * Get the name/label field of the given network.
- */
-extern bool
-xen_network_get_name_label(xen_session *session, char **result, xen_network network);
-
-
-/**
- * Get the name/description field of the given network.
- */
-extern bool
-xen_network_get_name_description(xen_session *session, char **result, xen_network network);
-
-
-/**
- * Get the VIFs field of the given network.
- */
-extern bool
-xen_network_get_vifs(xen_session *session, struct xen_vif_set **result, xen_network network);
-
-
-/**
- * Get the PIFs field of the given network.
- */
-extern bool
-xen_network_get_pifs(xen_session *session, struct xen_pif_set **result, xen_network network);
-
-
-/**
- * Get the other_config field of the given network.
- */
-extern bool
-xen_network_get_other_config(xen_session *session, xen_string_string_map **result, xen_network network);
-
-
-/**
- * Set the name/label field of the given network.
- */
-extern bool
-xen_network_set_name_label(xen_session *session, xen_network network, char *label);
-
-
-/**
- * Set the name/description field of the given network.
- */
-extern bool
-xen_network_set_name_description(xen_session *session, xen_network network, char *description);
-
-
-/**
- * Set the other_config field of the given network.
- */
-extern bool
-xen_network_set_other_config(xen_session *session, xen_network network, xen_string_string_map *other_config);
-
-
-/**
- * Add the given key-value pair to the other_config field of the given
- * network.
- */
-extern bool
-xen_network_add_to_other_config(xen_session *session, xen_network network, char *key, char *value);
-
-
-/**
- * Remove the given key and its corresponding value from the
- * other_config field of the given network. If the key is not in that Map,
- * then do nothing.
- */
-extern bool
-xen_network_remove_from_other_config(xen_session *session, xen_network network, char *key);
-
-
-/**
- * Return a list of all the networks known to the system.
- */
-extern bool
-xen_network_get_all(xen_session *session, struct xen_network_set **result);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_network_decl.h b/tools/libxen/include/xen/api/xen_network_decl.h
deleted file mode 100644
index dbfb3e9..0000000
--- a/tools/libxen/include/xen/api/xen_network_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_NETWORK_DECL_H
-#define XEN_NETWORK_DECL_H
-
-typedef void *xen_network;
-
-struct xen_network_set;
-struct xen_network_record;
-struct xen_network_record_set;
-struct xen_network_record_opt;
-struct xen_network_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_on_crash_behaviour.h b/tools/libxen/include/xen/api/xen_on_crash_behaviour.h
deleted file mode 100644
index 47792c6..0000000
--- a/tools/libxen/include/xen/api/xen_on_crash_behaviour.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_ON_CRASH_BEHAVIOUR_H
-#define XEN_ON_CRASH_BEHAVIOUR_H
-
-
-#include <xen/api/xen_common.h>
-
-
-enum xen_on_crash_behaviour
-{
- /**
- * destroy the VM state
- */
- XEN_ON_CRASH_BEHAVIOUR_DESTROY,
-
- /**
- * record a coredump and then destroy the VM state
- */
- XEN_ON_CRASH_BEHAVIOUR_COREDUMP_AND_DESTROY,
-
- /**
- * restart the VM
- */
- XEN_ON_CRASH_BEHAVIOUR_RESTART,
-
- /**
- * record a coredump and then restart the VM
- */
- XEN_ON_CRASH_BEHAVIOUR_COREDUMP_AND_RESTART,
-
- /**
- * leave the crashed VM as-is
- */
- XEN_ON_CRASH_BEHAVIOUR_PRESERVE,
-
- /**
- * rename the crashed VM and start a new copy
- */
- XEN_ON_CRASH_BEHAVIOUR_RENAME_RESTART
-};
-
-
-typedef struct xen_on_crash_behaviour_set
-{
- size_t size;
- enum xen_on_crash_behaviour contents[];
-} xen_on_crash_behaviour_set;
-
-/**
- * Allocate a xen_on_crash_behaviour_set of the given size.
- */
-extern xen_on_crash_behaviour_set *
-xen_on_crash_behaviour_set_alloc(size_t size);
-
-/**
- * Free the given xen_on_crash_behaviour_set. The given set must have
- * been allocated by this library.
- */
-extern void
-xen_on_crash_behaviour_set_free(xen_on_crash_behaviour_set *set);
-
-
-/**
- * Return the name corresponding to the given code. This string must
- * not be modified or freed.
- */
-extern const char *
-xen_on_crash_behaviour_to_string(enum xen_on_crash_behaviour val);
-
-
-/**
- * Return the correct code for the given string, or set the session
- * object to failure and return an undefined value if the given string does
- * not match a known code.
- */
-extern enum xen_on_crash_behaviour
-xen_on_crash_behaviour_from_string(xen_session *session, const char *str);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_on_normal_exit.h b/tools/libxen/include/xen/api/xen_on_normal_exit.h
deleted file mode 100644
index cd5a813..0000000
--- a/tools/libxen/include/xen/api/xen_on_normal_exit.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_ON_NORMAL_EXIT_H
-#define XEN_ON_NORMAL_EXIT_H
-
-
-#include <xen/api/xen_common.h>
-
-
-enum xen_on_normal_exit
-{
- /**
- * destroy the VM state
- */
- XEN_ON_NORMAL_EXIT_DESTROY,
-
- /**
- * restart the VM
- */
- XEN_ON_NORMAL_EXIT_RESTART
-};
-
-
-typedef struct xen_on_normal_exit_set
-{
- size_t size;
- enum xen_on_normal_exit contents[];
-} xen_on_normal_exit_set;
-
-/**
- * Allocate a xen_on_normal_exit_set of the given size.
- */
-extern xen_on_normal_exit_set *
-xen_on_normal_exit_set_alloc(size_t size);
-
-/**
- * Free the given xen_on_normal_exit_set. The given set must have been
- * allocated by this library.
- */
-extern void
-xen_on_normal_exit_set_free(xen_on_normal_exit_set *set);
-
-
-/**
- * Return the name corresponding to the given code. This string must
- * not be modified or freed.
- */
-extern const char *
-xen_on_normal_exit_to_string(enum xen_on_normal_exit val);
-
-
-/**
- * Return the correct code for the given string, or set the session
- * object to failure and return an undefined value if the given string does
- * not match a known code.
- */
-extern enum xen_on_normal_exit
-xen_on_normal_exit_from_string(xen_session *session, const char *str);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_pbd.h b/tools/libxen/include/xen/api/xen_pbd.h
deleted file mode 100644
index 224d2d4..0000000
--- a/tools/libxen/include/xen/api/xen_pbd.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_PBD_H
-#define XEN_PBD_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_host_decl.h>
-#include <xen/api/xen_pbd_decl.h>
-#include <xen/api/xen_sr_decl.h>
-#include <xen/api/xen_string_string_map.h>
-
-
-/*
- * The PBD class.
- *
- * The physical block devices through which hosts access SRs.
- */
-
-
-/**
- * Free the given xen_pbd. The given handle must have been allocated
- * by this library.
- */
-extern void
-xen_pbd_free(xen_pbd pbd);
-
-
-typedef struct xen_pbd_set
-{
- size_t size;
- xen_pbd *contents[];
-} xen_pbd_set;
-
-/**
- * Allocate a xen_pbd_set of the given size.
- */
-extern xen_pbd_set *
-xen_pbd_set_alloc(size_t size);
-
-/**
- * Free the given xen_pbd_set. The given set must have been allocated
- * by this library.
- */
-extern void
-xen_pbd_set_free(xen_pbd_set *set);
-
-
-typedef struct xen_pbd_record
-{
- xen_pbd handle;
- char *uuid;
- struct xen_host_record_opt *host;
- struct xen_sr_record_opt *sr;
- xen_string_string_map *device_config;
- bool currently_attached;
-} xen_pbd_record;
-
-/**
- * Allocate a xen_pbd_record.
- */
-extern xen_pbd_record *
-xen_pbd_record_alloc(void);
-
-/**
- * Free the given xen_pbd_record, and all referenced values. The given
- * record must have been allocated by this library.
- */
-extern void
-xen_pbd_record_free(xen_pbd_record *record);
-
-
-typedef struct xen_pbd_record_opt
-{
- bool is_record;
- union
- {
- xen_pbd handle;
- xen_pbd_record *record;
- } u;
-} xen_pbd_record_opt;
-
-/**
- * Allocate a xen_pbd_record_opt.
- */
-extern xen_pbd_record_opt *
-xen_pbd_record_opt_alloc(void);
-
-/**
- * Free the given xen_pbd_record_opt, and all referenced values. The
- * given record_opt must have been allocated by this library.
- */
-extern void
-xen_pbd_record_opt_free(xen_pbd_record_opt *record_opt);
-
-
-typedef struct xen_pbd_record_set
-{
- size_t size;
- xen_pbd_record *contents[];
-} xen_pbd_record_set;
-
-/**
- * Allocate a xen_pbd_record_set of the given size.
- */
-extern xen_pbd_record_set *
-xen_pbd_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_pbd_record_set, and all referenced values. The
- * given set must have been allocated by this library.
- */
-extern void
-xen_pbd_record_set_free(xen_pbd_record_set *set);
-
-
-
-typedef struct xen_pbd_record_opt_set
-{
- size_t size;
- xen_pbd_record_opt *contents[];
-} xen_pbd_record_opt_set;
-
-/**
- * Allocate a xen_pbd_record_opt_set of the given size.
- */
-extern xen_pbd_record_opt_set *
-xen_pbd_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_pbd_record_opt_set, and all referenced values.
- * The given set must have been allocated by this library.
- */
-extern void
-xen_pbd_record_opt_set_free(xen_pbd_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given PBD.
- */
-extern bool
-xen_pbd_get_record(xen_session *session, xen_pbd_record **result, xen_pbd pbd);
-
-
-/**
- * Get a reference to the PBD instance with the specified UUID.
- */
-extern bool
-xen_pbd_get_by_uuid(xen_session *session, xen_pbd *result, char *uuid);
-
-
-/**
- * Create a new PBD instance, and return its handle.
- */
-extern bool
-xen_pbd_create(xen_session *session, xen_pbd *result, xen_pbd_record *record);
-
-
-/**
- * Destroy the specified PBD instance.
- */
-extern bool
-xen_pbd_destroy(xen_session *session, xen_pbd pbd);
-
-
-/**
- * Get the uuid field of the given PBD.
- */
-extern bool
-xen_pbd_get_uuid(xen_session *session, char **result, xen_pbd pbd);
-
-
-/**
- * Get the host field of the given PBD.
- */
-extern bool
-xen_pbd_get_host(xen_session *session, xen_host *result, xen_pbd pbd);
-
-
-/**
- * Get the SR field of the given PBD.
- */
-extern bool
-xen_pbd_get_sr(xen_session *session, xen_sr *result, xen_pbd pbd);
-
-
-/**
- * Get the device_config field of the given PBD.
- */
-extern bool
-xen_pbd_get_device_config(xen_session *session, xen_string_string_map **result, xen_pbd pbd);
-
-
-/**
- * Get the currently_attached field of the given PBD.
- */
-extern bool
-xen_pbd_get_currently_attached(xen_session *session, bool *result, xen_pbd pbd);
-
-
-/**
- * Return a list of all the PBDs known to the system.
- */
-extern bool
-xen_pbd_get_all(xen_session *session, struct xen_pbd_set **result);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_pbd_decl.h b/tools/libxen/include/xen/api/xen_pbd_decl.h
deleted file mode 100644
index c7e324e..0000000
--- a/tools/libxen/include/xen/api/xen_pbd_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_PBD_DECL_H
-#define XEN_PBD_DECL_H
-
-typedef void *xen_pbd;
-
-struct xen_pbd_set;
-struct xen_pbd_record;
-struct xen_pbd_record_set;
-struct xen_pbd_record_opt;
-struct xen_pbd_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_pif.h b/tools/libxen/include/xen/api/xen_pif.h
deleted file mode 100644
index d36efd0..0000000
--- a/tools/libxen/include/xen/api/xen_pif.h
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_PIF_H
-#define XEN_PIF_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_host_decl.h>
-#include <xen/api/xen_network_decl.h>
-#include <xen/api/xen_pif_decl.h>
-#include <xen/api/xen_pif_metrics_decl.h>
-
-
-/*
- * The PIF class.
- *
- * A physical network interface (note separate VLANs are represented as
- * several PIFs).
- */
-
-
-/**
- * Free the given xen_pif. The given handle must have been allocated
- * by this library.
- */
-extern void
-xen_pif_free(xen_pif pif);
-
-
-typedef struct xen_pif_set
-{
- size_t size;
- xen_pif *contents[];
-} xen_pif_set;
-
-/**
- * Allocate a xen_pif_set of the given size.
- */
-extern xen_pif_set *
-xen_pif_set_alloc(size_t size);
-
-/**
- * Free the given xen_pif_set. The given set must have been allocated
- * by this library.
- */
-extern void
-xen_pif_set_free(xen_pif_set *set);
-
-
-typedef struct xen_pif_record
-{
- xen_pif handle;
- char *uuid;
- char *device;
- struct xen_network_record_opt *network;
- struct xen_host_record_opt *host;
- char *mac;
- int64_t mtu;
- int64_t vlan;
- struct xen_pif_metrics_record_opt *metrics;
-} xen_pif_record;
-
-/**
- * Allocate a xen_pif_record.
- */
-extern xen_pif_record *
-xen_pif_record_alloc(void);
-
-/**
- * Free the given xen_pif_record, and all referenced values. The given
- * record must have been allocated by this library.
- */
-extern void
-xen_pif_record_free(xen_pif_record *record);
-
-
-typedef struct xen_pif_record_opt
-{
- bool is_record;
- union
- {
- xen_pif handle;
- xen_pif_record *record;
- } u;
-} xen_pif_record_opt;
-
-/**
- * Allocate a xen_pif_record_opt.
- */
-extern xen_pif_record_opt *
-xen_pif_record_opt_alloc(void);
-
-/**
- * Free the given xen_pif_record_opt, and all referenced values. The
- * given record_opt must have been allocated by this library.
- */
-extern void
-xen_pif_record_opt_free(xen_pif_record_opt *record_opt);
-
-
-typedef struct xen_pif_record_set
-{
- size_t size;
- xen_pif_record *contents[];
-} xen_pif_record_set;
-
-/**
- * Allocate a xen_pif_record_set of the given size.
- */
-extern xen_pif_record_set *
-xen_pif_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_pif_record_set, and all referenced values. The
- * given set must have been allocated by this library.
- */
-extern void
-xen_pif_record_set_free(xen_pif_record_set *set);
-
-
-
-typedef struct xen_pif_record_opt_set
-{
- size_t size;
- xen_pif_record_opt *contents[];
-} xen_pif_record_opt_set;
-
-/**
- * Allocate a xen_pif_record_opt_set of the given size.
- */
-extern xen_pif_record_opt_set *
-xen_pif_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_pif_record_opt_set, and all referenced values.
- * The given set must have been allocated by this library.
- */
-extern void
-xen_pif_record_opt_set_free(xen_pif_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given PIF.
- */
-extern bool
-xen_pif_get_record(xen_session *session, xen_pif_record **result, xen_pif pif);
-
-
-/**
- * Get a reference to the PIF instance with the specified UUID.
- */
-extern bool
-xen_pif_get_by_uuid(xen_session *session, xen_pif *result, char *uuid);
-
-
-/**
- * Get the uuid field of the given PIF.
- */
-extern bool
-xen_pif_get_uuid(xen_session *session, char **result, xen_pif pif);
-
-
-/**
- * Get the device field of the given PIF.
- */
-extern bool
-xen_pif_get_device(xen_session *session, char **result, xen_pif pif);
-
-
-/**
- * Get the network field of the given PIF.
- */
-extern bool
-xen_pif_get_network(xen_session *session, xen_network *result, xen_pif pif);
-
-
-/**
- * Get the host field of the given PIF.
- */
-extern bool
-xen_pif_get_host(xen_session *session, xen_host *result, xen_pif pif);
-
-
-/**
- * Get the MAC field of the given PIF.
- */
-extern bool
-xen_pif_get_mac(xen_session *session, char **result, xen_pif pif);
-
-
-/**
- * Get the MTU field of the given PIF.
- */
-extern bool
-xen_pif_get_mtu(xen_session *session, int64_t *result, xen_pif pif);
-
-
-/**
- * Get the VLAN field of the given PIF.
- */
-extern bool
-xen_pif_get_vlan(xen_session *session, int64_t *result, xen_pif pif);
-
-
-/**
- * Get the metrics field of the given PIF.
- */
-extern bool
-xen_pif_get_metrics(xen_session *session, xen_pif_metrics *result, xen_pif pif);
-
-
-/**
- * Set the device field of the given PIF.
- */
-extern bool
-xen_pif_set_device(xen_session *session, xen_pif pif, char *device);
-
-
-/**
- * Set the MAC field of the given PIF.
- */
-extern bool
-xen_pif_set_mac(xen_session *session, xen_pif pif, char *mac);
-
-
-/**
- * Set the MTU field of the given PIF.
- */
-extern bool
-xen_pif_set_mtu(xen_session *session, xen_pif pif, int64_t mtu);
-
-
-/**
- * Set the VLAN field of the given PIF.
- */
-extern bool
-xen_pif_set_vlan(xen_session *session, xen_pif pif, int64_t vlan);
-
-
-/**
- * Create a VLAN interface from an existing physical interface.
- */
-extern bool
-xen_pif_create_vlan(xen_session *session, xen_pif *result, char *device, xen_network network, xen_host host, int64_t vlan);
-
-
-/**
- * Destroy the interface (provided it is a synthetic interface like a
- * VLAN; fail if it is a physical interface).
- */
-extern bool
-xen_pif_destroy(xen_session *session, xen_pif self);
-
-
-/**
- * Return a list of all the PIFs known to the system.
- */
-extern bool
-xen_pif_get_all(xen_session *session, struct xen_pif_set **result);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_pif_decl.h b/tools/libxen/include/xen/api/xen_pif_decl.h
deleted file mode 100644
index 6d49bdb..0000000
--- a/tools/libxen/include/xen/api/xen_pif_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_PIF_DECL_H
-#define XEN_PIF_DECL_H
-
-typedef void *xen_pif;
-
-struct xen_pif_set;
-struct xen_pif_record;
-struct xen_pif_record_set;
-struct xen_pif_record_opt;
-struct xen_pif_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_pif_metrics.h b/tools/libxen/include/xen/api/xen_pif_metrics.h
deleted file mode 100644
index 06b9d26..0000000
--- a/tools/libxen/include/xen/api/xen_pif_metrics.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_PIF_METRICS_H
-#define XEN_PIF_METRICS_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_pif_metrics_decl.h>
-
-
-/*
- * The PIF_metrics class.
- *
- * The metrics associated with a physical network interface.
- */
-
-
-/**
- * Free the given xen_pif_metrics. The given handle must have been
- * allocated by this library.
- */
-extern void
-xen_pif_metrics_free(xen_pif_metrics pif_metrics);
-
-
-typedef struct xen_pif_metrics_set
-{
- size_t size;
- xen_pif_metrics *contents[];
-} xen_pif_metrics_set;
-
-/**
- * Allocate a xen_pif_metrics_set of the given size.
- */
-extern xen_pif_metrics_set *
-xen_pif_metrics_set_alloc(size_t size);
-
-/**
- * Free the given xen_pif_metrics_set. The given set must have been
- * allocated by this library.
- */
-extern void
-xen_pif_metrics_set_free(xen_pif_metrics_set *set);
-
-
-typedef struct xen_pif_metrics_record
-{
- xen_pif_metrics handle;
- char *uuid;
- double io_read_kbs;
- double io_write_kbs;
- time_t last_updated;
-} xen_pif_metrics_record;
-
-/**
- * Allocate a xen_pif_metrics_record.
- */
-extern xen_pif_metrics_record *
-xen_pif_metrics_record_alloc(void);
-
-/**
- * Free the given xen_pif_metrics_record, and all referenced values.
- * The given record must have been allocated by this library.
- */
-extern void
-xen_pif_metrics_record_free(xen_pif_metrics_record *record);
-
-
-typedef struct xen_pif_metrics_record_opt
-{
- bool is_record;
- union
- {
- xen_pif_metrics handle;
- xen_pif_metrics_record *record;
- } u;
-} xen_pif_metrics_record_opt;
-
-/**
- * Allocate a xen_pif_metrics_record_opt.
- */
-extern xen_pif_metrics_record_opt *
-xen_pif_metrics_record_opt_alloc(void);
-
-/**
- * Free the given xen_pif_metrics_record_opt, and all referenced
- * values. The given record_opt must have been allocated by this library.
- */
-extern void
-xen_pif_metrics_record_opt_free(xen_pif_metrics_record_opt *record_opt);
-
-
-typedef struct xen_pif_metrics_record_set
-{
- size_t size;
- xen_pif_metrics_record *contents[];
-} xen_pif_metrics_record_set;
-
-/**
- * Allocate a xen_pif_metrics_record_set of the given size.
- */
-extern xen_pif_metrics_record_set *
-xen_pif_metrics_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_pif_metrics_record_set, and all referenced
- * values. The given set must have been allocated by this library.
- */
-extern void
-xen_pif_metrics_record_set_free(xen_pif_metrics_record_set *set);
-
-
-
-typedef struct xen_pif_metrics_record_opt_set
-{
- size_t size;
- xen_pif_metrics_record_opt *contents[];
-} xen_pif_metrics_record_opt_set;
-
-/**
- * Allocate a xen_pif_metrics_record_opt_set of the given size.
- */
-extern xen_pif_metrics_record_opt_set *
-xen_pif_metrics_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_pif_metrics_record_opt_set, and all referenced
- * values. The given set must have been allocated by this library.
- */
-extern void
-xen_pif_metrics_record_opt_set_free(xen_pif_metrics_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given PIF_metrics.
- */
-extern bool
-xen_pif_metrics_get_record(xen_session *session, xen_pif_metrics_record **result, xen_pif_metrics pif_metrics);
-
-
-/**
- * Get a reference to the PIF_metrics instance with the specified UUID.
- */
-extern bool
-xen_pif_metrics_get_by_uuid(xen_session *session, xen_pif_metrics *result, char *uuid);
-
-
-/**
- * Get the uuid field of the given PIF_metrics.
- */
-extern bool
-xen_pif_metrics_get_uuid(xen_session *session, char **result, xen_pif_metrics pif_metrics);
-
-
-/**
- * Get the io/read_kbs field of the given PIF_metrics.
- */
-extern bool
-xen_pif_metrics_get_io_read_kbs(xen_session *session, double *result, xen_pif_metrics pif_metrics);
-
-
-/**
- * Get the io/write_kbs field of the given PIF_metrics.
- */
-extern bool
-xen_pif_metrics_get_io_write_kbs(xen_session *session, double *result, xen_pif_metrics pif_metrics);
-
-
-/**
- * Get the last_updated field of the given PIF_metrics.
- */
-extern bool
-xen_pif_metrics_get_last_updated(xen_session *session, time_t *result, xen_pif_metrics pif_metrics);
-
-
-/**
- * Return a list of all the PIF_metrics instances known to the system.
- */
-extern bool
-xen_pif_metrics_get_all(xen_session *session, struct xen_pif_metrics_set **result);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_pif_metrics_decl.h b/tools/libxen/include/xen/api/xen_pif_metrics_decl.h
deleted file mode 100644
index f6ef2fd..0000000
--- a/tools/libxen/include/xen/api/xen_pif_metrics_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_PIF_METRICS_DECL_H
-#define XEN_PIF_METRICS_DECL_H
-
-typedef void *xen_pif_metrics;
-
-struct xen_pif_metrics_set;
-struct xen_pif_metrics_record;
-struct xen_pif_metrics_record_set;
-struct xen_pif_metrics_record_opt;
-struct xen_pif_metrics_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_sr.h b/tools/libxen/include/xen/api/xen_sr.h
deleted file mode 100644
index 08204a2..0000000
--- a/tools/libxen/include/xen/api/xen_sr.h
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_SR_H
-#define XEN_SR_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_pbd_decl.h>
-#include <xen/api/xen_sr_decl.h>
-#include <xen/api/xen_string_set.h>
-#include <xen/api/xen_vdi_decl.h>
-
-
-/*
- * The SR class.
- *
- * A storage repository.
- */
-
-
-/**
- * Free the given xen_sr. The given handle must have been allocated by
- * this library.
- */
-extern void
-xen_sr_free(xen_sr sr);
-
-
-typedef struct xen_sr_set
-{
- size_t size;
- xen_sr *contents[];
-} xen_sr_set;
-
-/**
- * Allocate a xen_sr_set of the given size.
- */
-extern xen_sr_set *
-xen_sr_set_alloc(size_t size);
-
-/**
- * Free the given xen_sr_set. The given set must have been allocated
- * by this library.
- */
-extern void
-xen_sr_set_free(xen_sr_set *set);
-
-
-typedef struct xen_sr_record
-{
- xen_sr handle;
- char *uuid;
- char *name_label;
- char *name_description;
- struct xen_vdi_record_opt_set *vdis;
- struct xen_pbd_record_opt_set *pbds;
- int64_t virtual_allocation;
- int64_t physical_utilisation;
- int64_t physical_size;
- char *type;
- char *content_type;
-} xen_sr_record;
-
-/**
- * Allocate a xen_sr_record.
- */
-extern xen_sr_record *
-xen_sr_record_alloc(void);
-
-/**
- * Free the given xen_sr_record, and all referenced values. The given
- * record must have been allocated by this library.
- */
-extern void
-xen_sr_record_free(xen_sr_record *record);
-
-
-typedef struct xen_sr_record_opt
-{
- bool is_record;
- union
- {
- xen_sr handle;
- xen_sr_record *record;
- } u;
-} xen_sr_record_opt;
-
-/**
- * Allocate a xen_sr_record_opt.
- */
-extern xen_sr_record_opt *
-xen_sr_record_opt_alloc(void);
-
-/**
- * Free the given xen_sr_record_opt, and all referenced values. The
- * given record_opt must have been allocated by this library.
- */
-extern void
-xen_sr_record_opt_free(xen_sr_record_opt *record_opt);
-
-
-typedef struct xen_sr_record_set
-{
- size_t size;
- xen_sr_record *contents[];
-} xen_sr_record_set;
-
-/**
- * Allocate a xen_sr_record_set of the given size.
- */
-extern xen_sr_record_set *
-xen_sr_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_sr_record_set, and all referenced values. The
- * given set must have been allocated by this library.
- */
-extern void
-xen_sr_record_set_free(xen_sr_record_set *set);
-
-
-
-typedef struct xen_sr_record_opt_set
-{
- size_t size;
- xen_sr_record_opt *contents[];
-} xen_sr_record_opt_set;
-
-/**
- * Allocate a xen_sr_record_opt_set of the given size.
- */
-extern xen_sr_record_opt_set *
-xen_sr_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_sr_record_opt_set, and all referenced values.
- * The given set must have been allocated by this library.
- */
-extern void
-xen_sr_record_opt_set_free(xen_sr_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given SR.
- */
-extern bool
-xen_sr_get_record(xen_session *session, xen_sr_record **result, xen_sr sr);
-
-
-/**
- * Get a reference to the SR instance with the specified UUID.
- */
-extern bool
-xen_sr_get_by_uuid(xen_session *session, xen_sr *result, char *uuid);
-
-
-/**
- * Get all the SR instances with the given label.
- */
-extern bool
-xen_sr_get_by_name_label(xen_session *session, struct xen_sr_set **result, char *label);
-
-
-/**
- * Get the uuid field of the given SR.
- */
-extern bool
-xen_sr_get_uuid(xen_session *session, char **result, xen_sr sr);
-
-
-/**
- * Get the name/label field of the given SR.
- */
-extern bool
-xen_sr_get_name_label(xen_session *session, char **result, xen_sr sr);
-
-
-/**
- * Get the name/description field of the given SR.
- */
-extern bool
-xen_sr_get_name_description(xen_session *session, char **result, xen_sr sr);
-
-
-/**
- * Get the VDIs field of the given SR.
- */
-extern bool
-xen_sr_get_vdis(xen_session *session, struct xen_vdi_set **result, xen_sr sr);
-
-
-/**
- * Get the PBDs field of the given SR.
- */
-extern bool
-xen_sr_get_pbds(xen_session *session, struct xen_pbd_set **result, xen_sr sr);
-
-
-/**
- * Get the virtual_allocation field of the given SR.
- */
-extern bool
-xen_sr_get_virtual_allocation(xen_session *session, int64_t *result, xen_sr sr);
-
-
-/**
- * Get the physical_utilisation field of the given SR.
- */
-extern bool
-xen_sr_get_physical_utilisation(xen_session *session, int64_t *result, xen_sr sr);
-
-
-/**
- * Get the physical_size field of the given SR.
- */
-extern bool
-xen_sr_get_physical_size(xen_session *session, int64_t *result, xen_sr sr);
-
-
-/**
- * Get the type field of the given SR.
- */
-extern bool
-xen_sr_get_type(xen_session *session, char **result, xen_sr sr);
-
-
-/**
- * Get the content_type field of the given SR.
- */
-extern bool
-xen_sr_get_content_type(xen_session *session, char **result, xen_sr sr);
-
-
-/**
- * Set the name/label field of the given SR.
- */
-extern bool
-xen_sr_set_name_label(xen_session *session, xen_sr sr, char *label);
-
-
-/**
- * Set the name/description field of the given SR.
- */
-extern bool
-xen_sr_set_name_description(xen_session *session, xen_sr sr, char *description);
-
-
-/**
- * Return a set of all the SR types supported by the system.
- */
-extern bool
-xen_sr_get_supported_types(xen_session *session, struct xen_string_set **result);
-
-
-/**
- * Return a list of all the SRs known to the system.
- */
-extern bool
-xen_sr_get_all(xen_session *session, struct xen_sr_set **result);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_sr_decl.h b/tools/libxen/include/xen/api/xen_sr_decl.h
deleted file mode 100644
index ae7d4f6..0000000
--- a/tools/libxen/include/xen/api/xen_sr_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_SR_DECL_H
-#define XEN_SR_DECL_H
-
-typedef void *xen_sr;
-
-struct xen_sr_set;
-struct xen_sr_record;
-struct xen_sr_record_set;
-struct xen_sr_record_opt;
-struct xen_sr_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_string_set.h b/tools/libxen/include/xen/api/xen_string_set.h
deleted file mode 100644
index a14af94..0000000
--- a/tools/libxen/include/xen/api/xen_string_set.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_STRING_SET_H
-#define XEN_STRING_SET_H
-
-
-#include "xen_common.h"
-
-
-typedef struct xen_string_set
-{
- size_t size;
- char *contents[];
-} xen_string_set;
-
-
-/**
- * Allocate a xen_string_set of the given size.
- */
-extern xen_string_set *
-xen_string_set_alloc(size_t size);
-
-/**
- * Free the given xen_string_set. The given set must have been allocated
- * by this library.
- */
-extern void
-xen_string_set_free(xen_string_set *set);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_string_string_map.h b/tools/libxen/include/xen/api/xen_string_string_map.h
deleted file mode 100644
index d800442..0000000
--- a/tools/libxen/include/xen/api/xen_string_string_map.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_STRING_STRING_MAP_H
-#define XEN_STRING_STRING_MAP_H
-
-
-#include <xen/api/xen_common.h>
-
-
-typedef struct xen_string_string_map_contents
-{
- char *key;
- char *val;
-} xen_string_string_map_contents;
-
-
-typedef struct xen_string_string_map
-{
- size_t size;
- xen_string_string_map_contents contents[];
-} xen_string_string_map;
-
-/**
- * Allocate a xen_string_string_map of the given size.
- */
-extern xen_string_string_map *
-xen_string_string_map_alloc(size_t size);
-
-/**
- * Free the given xen_string_string_map, and all referenced values.
- * The given map must have been allocated by this library.
- */
-extern void
-xen_string_string_map_free(xen_string_string_map *map);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_user.h b/tools/libxen/include/xen/api/xen_user.h
deleted file mode 100644
index a6d9dd9..0000000
--- a/tools/libxen/include/xen/api/xen_user.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_USER_H
-#define XEN_USER_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_user_decl.h>
-
-
-/*
- * The user class.
- *
- * A user of the system.
- */
-
-
-/**
- * Free the given xen_user. The given handle must have been allocated
- * by this library.
- */
-extern void
-xen_user_free(xen_user user);
-
-
-typedef struct xen_user_set
-{
- size_t size;
- xen_user *contents[];
-} xen_user_set;
-
-/**
- * Allocate a xen_user_set of the given size.
- */
-extern xen_user_set *
-xen_user_set_alloc(size_t size);
-
-/**
- * Free the given xen_user_set. The given set must have been allocated
- * by this library.
- */
-extern void
-xen_user_set_free(xen_user_set *set);
-
-
-typedef struct xen_user_record
-{
- xen_user handle;
- char *uuid;
- char *short_name;
- char *fullname;
-} xen_user_record;
-
-/**
- * Allocate a xen_user_record.
- */
-extern xen_user_record *
-xen_user_record_alloc(void);
-
-/**
- * Free the given xen_user_record, and all referenced values. The
- * given record must have been allocated by this library.
- */
-extern void
-xen_user_record_free(xen_user_record *record);
-
-
-typedef struct xen_user_record_opt
-{
- bool is_record;
- union
- {
- xen_user handle;
- xen_user_record *record;
- } u;
-} xen_user_record_opt;
-
-/**
- * Allocate a xen_user_record_opt.
- */
-extern xen_user_record_opt *
-xen_user_record_opt_alloc(void);
-
-/**
- * Free the given xen_user_record_opt, and all referenced values. The
- * given record_opt must have been allocated by this library.
- */
-extern void
-xen_user_record_opt_free(xen_user_record_opt *record_opt);
-
-
-typedef struct xen_user_record_set
-{
- size_t size;
- xen_user_record *contents[];
-} xen_user_record_set;
-
-/**
- * Allocate a xen_user_record_set of the given size.
- */
-extern xen_user_record_set *
-xen_user_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_user_record_set, and all referenced values. The
- * given set must have been allocated by this library.
- */
-extern void
-xen_user_record_set_free(xen_user_record_set *set);
-
-
-
-typedef struct xen_user_record_opt_set
-{
- size_t size;
- xen_user_record_opt *contents[];
-} xen_user_record_opt_set;
-
-/**
- * Allocate a xen_user_record_opt_set of the given size.
- */
-extern xen_user_record_opt_set *
-xen_user_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_user_record_opt_set, and all referenced values.
- * The given set must have been allocated by this library.
- */
-extern void
-xen_user_record_opt_set_free(xen_user_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given user.
- */
-extern bool
-xen_user_get_record(xen_session *session, xen_user_record **result, xen_user user);
-
-
-/**
- * Get a reference to the user instance with the specified UUID.
- */
-extern bool
-xen_user_get_by_uuid(xen_session *session, xen_user *result, char *uuid);
-
-
-/**
- * Create a new user instance, and return its handle.
- */
-extern bool
-xen_user_create(xen_session *session, xen_user *result, xen_user_record *record);
-
-
-/**
- * Destroy the specified user instance.
- */
-extern bool
-xen_user_destroy(xen_session *session, xen_user user);
-
-
-/**
- * Get the uuid field of the given user.
- */
-extern bool
-xen_user_get_uuid(xen_session *session, char **result, xen_user user);
-
-
-/**
- * Get the short_name field of the given user.
- */
-extern bool
-xen_user_get_short_name(xen_session *session, char **result, xen_user user);
-
-
-/**
- * Get the fullname field of the given user.
- */
-extern bool
-xen_user_get_fullname(xen_session *session, char **result, xen_user user);
-
-
-/**
- * Set the fullname field of the given user.
- */
-extern bool
-xen_user_set_fullname(xen_session *session, xen_user user, char *fullname);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_user_decl.h b/tools/libxen/include/xen/api/xen_user_decl.h
deleted file mode 100644
index 723a8bf..0000000
--- a/tools/libxen/include/xen/api/xen_user_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_USER_DECL_H
-#define XEN_USER_DECL_H
-
-typedef void *xen_user;
-
-struct xen_user_set;
-struct xen_user_record;
-struct xen_user_record_set;
-struct xen_user_record_opt;
-struct xen_user_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vbd.h b/tools/libxen/include/xen/api/xen_vbd.h
deleted file mode 100644
index 9806c5e..0000000
--- a/tools/libxen/include/xen/api/xen_vbd.h
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VBD_H
-#define XEN_VBD_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_string_set.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vbd_decl.h>
-#include <xen/api/xen_vbd_metrics_decl.h>
-#include <xen/api/xen_vbd_mode.h>
-#include <xen/api/xen_vbd_type.h>
-#include <xen/api/xen_vdi_decl.h>
-#include <xen/api/xen_vm_decl.h>
-
-
-/*
- * The VBD class.
- *
- * A virtual block device.
- */
-
-
-/**
- * Free the given xen_vbd. The given handle must have been allocated
- * by this library.
- */
-extern void
-xen_vbd_free(xen_vbd vbd);
-
-
-typedef struct xen_vbd_set
-{
- size_t size;
- xen_vbd *contents[];
-} xen_vbd_set;
-
-/**
- * Allocate a xen_vbd_set of the given size.
- */
-extern xen_vbd_set *
-xen_vbd_set_alloc(size_t size);
-
-/**
- * Free the given xen_vbd_set. The given set must have been allocated
- * by this library.
- */
-extern void
-xen_vbd_set_free(xen_vbd_set *set);
-
-
-typedef struct xen_vbd_record
-{
- xen_vbd handle;
- char *uuid;
- struct xen_vm_record_opt *vm;
- struct xen_vdi_record_opt *vdi;
- char *device;
- bool bootable;
- enum xen_vbd_mode mode;
- enum xen_vbd_type type;
- bool currently_attached;
- int64_t status_code;
- char *status_detail;
- xen_string_string_map *runtime_properties;
- char *qos_algorithm_type;
- xen_string_string_map *qos_algorithm_params;
- struct xen_string_set *qos_supported_algorithms;
- struct xen_vbd_metrics_record_opt *metrics;
-} xen_vbd_record;
-
-/**
- * Allocate a xen_vbd_record.
- */
-extern xen_vbd_record *
-xen_vbd_record_alloc(void);
-
-/**
- * Free the given xen_vbd_record, and all referenced values. The given
- * record must have been allocated by this library.
- */
-extern void
-xen_vbd_record_free(xen_vbd_record *record);
-
-
-typedef struct xen_vbd_record_opt
-{
- bool is_record;
- union
- {
- xen_vbd handle;
- xen_vbd_record *record;
- } u;
-} xen_vbd_record_opt;
-
-/**
- * Allocate a xen_vbd_record_opt.
- */
-extern xen_vbd_record_opt *
-xen_vbd_record_opt_alloc(void);
-
-/**
- * Free the given xen_vbd_record_opt, and all referenced values. The
- * given record_opt must have been allocated by this library.
- */
-extern void
-xen_vbd_record_opt_free(xen_vbd_record_opt *record_opt);
-
-
-typedef struct xen_vbd_record_set
-{
- size_t size;
- xen_vbd_record *contents[];
-} xen_vbd_record_set;
-
-/**
- * Allocate a xen_vbd_record_set of the given size.
- */
-extern xen_vbd_record_set *
-xen_vbd_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_vbd_record_set, and all referenced values. The
- * given set must have been allocated by this library.
- */
-extern void
-xen_vbd_record_set_free(xen_vbd_record_set *set);
-
-
-
-typedef struct xen_vbd_record_opt_set
-{
- size_t size;
- xen_vbd_record_opt *contents[];
-} xen_vbd_record_opt_set;
-
-/**
- * Allocate a xen_vbd_record_opt_set of the given size.
- */
-extern xen_vbd_record_opt_set *
-xen_vbd_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_vbd_record_opt_set, and all referenced values.
- * The given set must have been allocated by this library.
- */
-extern void
-xen_vbd_record_opt_set_free(xen_vbd_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given VBD.
- */
-extern bool
-xen_vbd_get_record(xen_session *session, xen_vbd_record **result, xen_vbd vbd);
-
-
-/**
- * Get a reference to the VBD instance with the specified UUID.
- */
-extern bool
-xen_vbd_get_by_uuid(xen_session *session, xen_vbd *result, char *uuid);
-
-
-/**
- * Create a new VBD instance, and return its handle.
- */
-extern bool
-xen_vbd_create(xen_session *session, xen_vbd *result, xen_vbd_record *record);
-
-
-/**
- * Destroy the specified VBD instance.
- */
-extern bool
-xen_vbd_destroy(xen_session *session, xen_vbd vbd);
-
-
-/**
- * Get the uuid field of the given VBD.
- */
-extern bool
-xen_vbd_get_uuid(xen_session *session, char **result, xen_vbd vbd);
-
-
-/**
- * Get the VM field of the given VBD.
- */
-extern bool
-xen_vbd_get_vm(xen_session *session, xen_vm *result, xen_vbd vbd);
-
-
-/**
- * Get the VDI field of the given VBD.
- */
-extern bool
-xen_vbd_get_vdi(xen_session *session, xen_vdi *result, xen_vbd vbd);
-
-
-/**
- * Get the device field of the given VBD.
- */
-extern bool
-xen_vbd_get_device(xen_session *session, char **result, xen_vbd vbd);
-
-
-/**
- * Get the bootable field of the given VBD.
- */
-extern bool
-xen_vbd_get_bootable(xen_session *session, bool *result, xen_vbd vbd);
-
-
-/**
- * Get the mode field of the given VBD.
- */
-extern bool
-xen_vbd_get_mode(xen_session *session, enum xen_vbd_mode *result, xen_vbd vbd);
-
-
-/**
- * Get the type field of the given VBD.
- */
-extern bool
-xen_vbd_get_type(xen_session *session, enum xen_vbd_type *result, xen_vbd vbd);
-
-
-/**
- * Get the currently_attached field of the given VBD.
- */
-extern bool
-xen_vbd_get_currently_attached(xen_session *session, bool *result, xen_vbd vbd);
-
-
-/**
- * Get the status_code field of the given VBD.
- */
-extern bool
-xen_vbd_get_status_code(xen_session *session, int64_t *result, xen_vbd vbd);
-
-
-/**
- * Get the status_detail field of the given VBD.
- */
-extern bool
-xen_vbd_get_status_detail(xen_session *session, char **result, xen_vbd vbd);
-
-
-/**
- * Get the runtime_properties field of the given VBD.
- */
-extern bool
-xen_vbd_get_runtime_properties(xen_session *session, xen_string_string_map **result, xen_vbd vbd);
-
-
-/**
- * Get the qos/algorithm_type field of the given VBD.
- */
-extern bool
-xen_vbd_get_qos_algorithm_type(xen_session *session, char **result, xen_vbd vbd);
-
-
-/**
- * Get the qos/algorithm_params field of the given VBD.
- */
-extern bool
-xen_vbd_get_qos_algorithm_params(xen_session *session, xen_string_string_map **result, xen_vbd vbd);
-
-
-/**
- * Get the qos/supported_algorithms field of the given VBD.
- */
-extern bool
-xen_vbd_get_qos_supported_algorithms(xen_session *session, struct xen_string_set **result, xen_vbd vbd);
-
-
-/**
- * Get the metrics field of the given VBD.
- */
-extern bool
-xen_vbd_get_metrics(xen_session *session, xen_vbd_metrics *result, xen_vbd vbd);
-
-
-/**
- * Set the device field of the given VBD.
- */
-extern bool
-xen_vbd_set_device(xen_session *session, xen_vbd vbd, char *device);
-
-
-/**
- * Set the bootable field of the given VBD.
- */
-extern bool
-xen_vbd_set_bootable(xen_session *session, xen_vbd vbd, bool bootable);
-
-
-/**
- * Set the mode field of the given VBD.
- */
-extern bool
-xen_vbd_set_mode(xen_session *session, xen_vbd vbd, enum xen_vbd_mode mode);
-
-
-/**
- * Set the type field of the given VBD.
- */
-extern bool
-xen_vbd_set_type(xen_session *session, xen_vbd vbd, enum xen_vbd_type type);
-
-
-/**
- * Set the qos/algorithm_type field of the given VBD.
- */
-extern bool
-xen_vbd_set_qos_algorithm_type(xen_session *session, xen_vbd vbd, char *algorithm_type);
-
-
-/**
- * Set the qos/algorithm_params field of the given VBD.
- */
-extern bool
-xen_vbd_set_qos_algorithm_params(xen_session *session, xen_vbd vbd, xen_string_string_map *algorithm_params);
-
-
-/**
- * Add the given key-value pair to the qos/algorithm_params field of
- * the given VBD.
- */
-extern bool
-xen_vbd_add_to_qos_algorithm_params(xen_session *session, xen_vbd vbd, char *key, char *value);
-
-
-/**
- * Remove the given key and its corresponding value from the
- * qos/algorithm_params field of the given VBD. If the key is not in that
- * Map, then do nothing.
- */
-extern bool
-xen_vbd_remove_from_qos_algorithm_params(xen_session *session, xen_vbd vbd, char *key);
-
-
-/**
- * Change the media in the device for CDROM-like devices only. For
- * other devices, detach the VBD and attach a new one.
- */
-extern bool
-xen_vbd_media_change(xen_session *session, xen_vbd vbd, xen_vdi vdi);
-
-
-/**
- * Hotplug the specified VBD, dynamically attaching it to the running
- * VM.
- */
-extern bool
-xen_vbd_plug(xen_session *session, xen_vbd self);
-
-
-/**
- * Hot-unplug the specified VBD, dynamically unattaching it from the
- * running VM.
- */
-extern bool
-xen_vbd_unplug(xen_session *session, xen_vbd self);
-
-
-/**
- * Return a list of all the VBDs known to the system.
- */
-extern bool
-xen_vbd_get_all(xen_session *session, struct xen_vbd_set **result);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vbd_decl.h b/tools/libxen/include/xen/api/xen_vbd_decl.h
deleted file mode 100644
index 018af3b..0000000
--- a/tools/libxen/include/xen/api/xen_vbd_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VBD_DECL_H
-#define XEN_VBD_DECL_H
-
-typedef void *xen_vbd;
-
-struct xen_vbd_set;
-struct xen_vbd_record;
-struct xen_vbd_record_set;
-struct xen_vbd_record_opt;
-struct xen_vbd_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vbd_metrics.h b/tools/libxen/include/xen/api/xen_vbd_metrics.h
deleted file mode 100644
index 1cb1a2b..0000000
--- a/tools/libxen/include/xen/api/xen_vbd_metrics.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VBD_METRICS_H
-#define XEN_VBD_METRICS_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_vbd_metrics_decl.h>
-
-
-/*
- * The VBD_metrics class.
- *
- * The metrics associated with a virtual block device.
- */
-
-
-/**
- * Free the given xen_vbd_metrics. The given handle must have been
- * allocated by this library.
- */
-extern void
-xen_vbd_metrics_free(xen_vbd_metrics vbd_metrics);
-
-
-typedef struct xen_vbd_metrics_set
-{
- size_t size;
- xen_vbd_metrics *contents[];
-} xen_vbd_metrics_set;
-
-/**
- * Allocate a xen_vbd_metrics_set of the given size.
- */
-extern xen_vbd_metrics_set *
-xen_vbd_metrics_set_alloc(size_t size);
-
-/**
- * Free the given xen_vbd_metrics_set. The given set must have been
- * allocated by this library.
- */
-extern void
-xen_vbd_metrics_set_free(xen_vbd_metrics_set *set);
-
-
-typedef struct xen_vbd_metrics_record
-{
- xen_vbd_metrics handle;
- char *uuid;
- double io_read_kbs;
- double io_write_kbs;
- time_t last_updated;
-} xen_vbd_metrics_record;
-
-/**
- * Allocate a xen_vbd_metrics_record.
- */
-extern xen_vbd_metrics_record *
-xen_vbd_metrics_record_alloc(void);
-
-/**
- * Free the given xen_vbd_metrics_record, and all referenced values.
- * The given record must have been allocated by this library.
- */
-extern void
-xen_vbd_metrics_record_free(xen_vbd_metrics_record *record);
-
-
-typedef struct xen_vbd_metrics_record_opt
-{
- bool is_record;
- union
- {
- xen_vbd_metrics handle;
- xen_vbd_metrics_record *record;
- } u;
-} xen_vbd_metrics_record_opt;
-
-/**
- * Allocate a xen_vbd_metrics_record_opt.
- */
-extern xen_vbd_metrics_record_opt *
-xen_vbd_metrics_record_opt_alloc(void);
-
-/**
- * Free the given xen_vbd_metrics_record_opt, and all referenced
- * values. The given record_opt must have been allocated by this library.
- */
-extern void
-xen_vbd_metrics_record_opt_free(xen_vbd_metrics_record_opt *record_opt);
-
-
-typedef struct xen_vbd_metrics_record_set
-{
- size_t size;
- xen_vbd_metrics_record *contents[];
-} xen_vbd_metrics_record_set;
-
-/**
- * Allocate a xen_vbd_metrics_record_set of the given size.
- */
-extern xen_vbd_metrics_record_set *
-xen_vbd_metrics_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_vbd_metrics_record_set, and all referenced
- * values. The given set must have been allocated by this library.
- */
-extern void
-xen_vbd_metrics_record_set_free(xen_vbd_metrics_record_set *set);
-
-
-
-typedef struct xen_vbd_metrics_record_opt_set
-{
- size_t size;
- xen_vbd_metrics_record_opt *contents[];
-} xen_vbd_metrics_record_opt_set;
-
-/**
- * Allocate a xen_vbd_metrics_record_opt_set of the given size.
- */
-extern xen_vbd_metrics_record_opt_set *
-xen_vbd_metrics_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_vbd_metrics_record_opt_set, and all referenced
- * values. The given set must have been allocated by this library.
- */
-extern void
-xen_vbd_metrics_record_opt_set_free(xen_vbd_metrics_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given VBD_metrics.
- */
-extern bool
-xen_vbd_metrics_get_record(xen_session *session, xen_vbd_metrics_record **result, xen_vbd_metrics vbd_metrics);
-
-
-/**
- * Get a reference to the VBD_metrics instance with the specified UUID.
- */
-extern bool
-xen_vbd_metrics_get_by_uuid(xen_session *session, xen_vbd_metrics *result, char *uuid);
-
-
-/**
- * Get the uuid field of the given VBD_metrics.
- */
-extern bool
-xen_vbd_metrics_get_uuid(xen_session *session, char **result, xen_vbd_metrics vbd_metrics);
-
-
-/**
- * Get the io/read_kbs field of the given VBD_metrics.
- */
-extern bool
-xen_vbd_metrics_get_io_read_kbs(xen_session *session, double *result, xen_vbd_metrics vbd_metrics);
-
-
-/**
- * Get the io/write_kbs field of the given VBD_metrics.
- */
-extern bool
-xen_vbd_metrics_get_io_write_kbs(xen_session *session, double *result, xen_vbd_metrics vbd_metrics);
-
-
-/**
- * Get the last_updated field of the given VBD_metrics.
- */
-extern bool
-xen_vbd_metrics_get_last_updated(xen_session *session, time_t *result, xen_vbd_metrics vbd_metrics);
-
-
-/**
- * Return a list of all the VBD_metrics instances known to the system.
- */
-extern bool
-xen_vbd_metrics_get_all(xen_session *session, struct xen_vbd_metrics_set **result);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vbd_metrics_decl.h b/tools/libxen/include/xen/api/xen_vbd_metrics_decl.h
deleted file mode 100644
index 501aa8f..0000000
--- a/tools/libxen/include/xen/api/xen_vbd_metrics_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VBD_METRICS_DECL_H
-#define XEN_VBD_METRICS_DECL_H
-
-typedef void *xen_vbd_metrics;
-
-struct xen_vbd_metrics_set;
-struct xen_vbd_metrics_record;
-struct xen_vbd_metrics_record_set;
-struct xen_vbd_metrics_record_opt;
-struct xen_vbd_metrics_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vbd_mode.h b/tools/libxen/include/xen/api/xen_vbd_mode.h
deleted file mode 100644
index 8cab27e..0000000
--- a/tools/libxen/include/xen/api/xen_vbd_mode.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VBD_MODE_H
-#define XEN_VBD_MODE_H
-
-
-#include <xen/api/xen_common.h>
-
-
-enum xen_vbd_mode
-{
- /**
- * disk is mounted read-only
- */
- XEN_VBD_MODE_RO,
-
- /**
- * disk is mounted read-write
- */
- XEN_VBD_MODE_RW
-};
-
-
-typedef struct xen_vbd_mode_set
-{
- size_t size;
- enum xen_vbd_mode contents[];
-} xen_vbd_mode_set;
-
-/**
- * Allocate a xen_vbd_mode_set of the given size.
- */
-extern xen_vbd_mode_set *
-xen_vbd_mode_set_alloc(size_t size);
-
-/**
- * Free the given xen_vbd_mode_set. The given set must have been
- * allocated by this library.
- */
-extern void
-xen_vbd_mode_set_free(xen_vbd_mode_set *set);
-
-
-/**
- * Return the name corresponding to the given code. This string must
- * not be modified or freed.
- */
-extern const char *
-xen_vbd_mode_to_string(enum xen_vbd_mode val);
-
-
-/**
- * Return the correct code for the given string, or set the session
- * object to failure and return an undefined value if the given string does
- * not match a known code.
- */
-extern enum xen_vbd_mode
-xen_vbd_mode_from_string(xen_session *session, const char *str);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vbd_type.h b/tools/libxen/include/xen/api/xen_vbd_type.h
deleted file mode 100644
index d19aef8..0000000
--- a/tools/libxen/include/xen/api/xen_vbd_type.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VBD_TYPE_H
-#define XEN_VBD_TYPE_H
-
-
-#include <xen/api/xen_common.h>
-
-
-enum xen_vbd_type
-{
- /**
- * VBD will appear to guest as CD
- */
- XEN_VBD_TYPE_CD,
-
- /**
- * VBD will appear to guest as disk
- */
- XEN_VBD_TYPE_DISK
-};
-
-
-typedef struct xen_vbd_type_set
-{
- size_t size;
- enum xen_vbd_type contents[];
-} xen_vbd_type_set;
-
-/**
- * Allocate a xen_vbd_type_set of the given size.
- */
-extern xen_vbd_type_set *
-xen_vbd_type_set_alloc(size_t size);
-
-/**
- * Free the given xen_vbd_type_set. The given set must have been
- * allocated by this library.
- */
-extern void
-xen_vbd_type_set_free(xen_vbd_type_set *set);
-
-
-/**
- * Return the name corresponding to the given code. This string must
- * not be modified or freed.
- */
-extern const char *
-xen_vbd_type_to_string(enum xen_vbd_type val);
-
-
-/**
- * Return the correct code for the given string, or set the session
- * object to failure and return an undefined value if the given string does
- * not match a known code.
- */
-extern enum xen_vbd_type
-xen_vbd_type_from_string(xen_session *session, const char *str);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vdi.h b/tools/libxen/include/xen/api/xen_vdi.h
deleted file mode 100644
index a6ad303..0000000
--- a/tools/libxen/include/xen/api/xen_vdi.h
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VDI_H
-#define XEN_VDI_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_crashdump_decl.h>
-#include <xen/api/xen_sr_decl.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vbd_decl.h>
-#include <xen/api/xen_vdi_decl.h>
-#include <xen/api/xen_vdi_type.h>
-
-
-/*
- * The VDI class.
- *
- * A virtual disk image.
- */
-
-
-/**
- * Free the given xen_vdi. The given handle must have been allocated
- * by this library.
- */
-extern void
-xen_vdi_free(xen_vdi vdi);
-
-
-typedef struct xen_vdi_set
-{
- size_t size;
- xen_vdi *contents[];
-} xen_vdi_set;
-
-/**
- * Allocate a xen_vdi_set of the given size.
- */
-extern xen_vdi_set *
-xen_vdi_set_alloc(size_t size);
-
-/**
- * Free the given xen_vdi_set. The given set must have been allocated
- * by this library.
- */
-extern void
-xen_vdi_set_free(xen_vdi_set *set);
-
-
-typedef struct xen_vdi_record
-{
- xen_vdi handle;
- char *uuid;
- char *name_label;
- char *name_description;
- struct xen_sr_record_opt *sr;
- struct xen_vbd_record_opt_set *vbds;
- struct xen_crashdump_record_opt_set *crash_dumps;
- int64_t virtual_size;
- int64_t physical_utilisation;
- enum xen_vdi_type type;
- bool sharable;
- bool read_only;
- xen_string_string_map *other_config;
-} xen_vdi_record;
-
-/**
- * Allocate a xen_vdi_record.
- */
-extern xen_vdi_record *
-xen_vdi_record_alloc(void);
-
-/**
- * Free the given xen_vdi_record, and all referenced values. The given
- * record must have been allocated by this library.
- */
-extern void
-xen_vdi_record_free(xen_vdi_record *record);
-
-
-typedef struct xen_vdi_record_opt
-{
- bool is_record;
- union
- {
- xen_vdi handle;
- xen_vdi_record *record;
- } u;
-} xen_vdi_record_opt;
-
-/**
- * Allocate a xen_vdi_record_opt.
- */
-extern xen_vdi_record_opt *
-xen_vdi_record_opt_alloc(void);
-
-/**
- * Free the given xen_vdi_record_opt, and all referenced values. The
- * given record_opt must have been allocated by this library.
- */
-extern void
-xen_vdi_record_opt_free(xen_vdi_record_opt *record_opt);
-
-
-typedef struct xen_vdi_record_set
-{
- size_t size;
- xen_vdi_record *contents[];
-} xen_vdi_record_set;
-
-/**
- * Allocate a xen_vdi_record_set of the given size.
- */
-extern xen_vdi_record_set *
-xen_vdi_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_vdi_record_set, and all referenced values. The
- * given set must have been allocated by this library.
- */
-extern void
-xen_vdi_record_set_free(xen_vdi_record_set *set);
-
-
-
-typedef struct xen_vdi_record_opt_set
-{
- size_t size;
- xen_vdi_record_opt *contents[];
-} xen_vdi_record_opt_set;
-
-/**
- * Allocate a xen_vdi_record_opt_set of the given size.
- */
-extern xen_vdi_record_opt_set *
-xen_vdi_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_vdi_record_opt_set, and all referenced values.
- * The given set must have been allocated by this library.
- */
-extern void
-xen_vdi_record_opt_set_free(xen_vdi_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given VDI.
- */
-extern bool
-xen_vdi_get_record(xen_session *session, xen_vdi_record **result, xen_vdi vdi);
-
-
-/**
- * Get a reference to the VDI instance with the specified UUID.
- */
-extern bool
-xen_vdi_get_by_uuid(xen_session *session, xen_vdi *result, char *uuid);
-
-
-/**
- * Create a new VDI instance, and return its handle.
- */
-extern bool
-xen_vdi_create(xen_session *session, xen_vdi *result, xen_vdi_record *record);
-
-
-/**
- * Destroy the specified VDI instance.
- */
-extern bool
-xen_vdi_destroy(xen_session *session, xen_vdi vdi);
-
-
-/**
- * Get all the VDI instances with the given label.
- */
-extern bool
-xen_vdi_get_by_name_label(xen_session *session, struct xen_vdi_set **result, char *label);
-
-
-/**
- * Get the uuid field of the given VDI.
- */
-extern bool
-xen_vdi_get_uuid(xen_session *session, char **result, xen_vdi vdi);
-
-
-/**
- * Get the name/label field of the given VDI.
- */
-extern bool
-xen_vdi_get_name_label(xen_session *session, char **result, xen_vdi vdi);
-
-
-/**
- * Get the name/description field of the given VDI.
- */
-extern bool
-xen_vdi_get_name_description(xen_session *session, char **result, xen_vdi vdi);
-
-
-/**
- * Get the SR field of the given VDI.
- */
-extern bool
-xen_vdi_get_sr(xen_session *session, xen_sr *result, xen_vdi vdi);
-
-
-/**
- * Get the VBDs field of the given VDI.
- */
-extern bool
-xen_vdi_get_vbds(xen_session *session, struct xen_vbd_set **result, xen_vdi vdi);
-
-
-/**
- * Get the crash_dumps field of the given VDI.
- */
-extern bool
-xen_vdi_get_crash_dumps(xen_session *session, struct xen_crashdump_set **result, xen_vdi vdi);
-
-
-/**
- * Get the virtual_size field of the given VDI.
- */
-extern bool
-xen_vdi_get_virtual_size(xen_session *session, int64_t *result, xen_vdi vdi);
-
-
-/**
- * Get the physical_utilisation field of the given VDI.
- */
-extern bool
-xen_vdi_get_physical_utilisation(xen_session *session, int64_t *result, xen_vdi vdi);
-
-
-/**
- * Get the type field of the given VDI.
- */
-extern bool
-xen_vdi_get_type(xen_session *session, enum xen_vdi_type *result, xen_vdi vdi);
-
-
-/**
- * Get the sharable field of the given VDI.
- */
-extern bool
-xen_vdi_get_sharable(xen_session *session, bool *result, xen_vdi vdi);
-
-
-/**
- * Get the read_only field of the given VDI.
- */
-extern bool
-xen_vdi_get_read_only(xen_session *session, bool *result, xen_vdi vdi);
-
-
-/**
- * Get the other_config field of the given VDI.
- */
-extern bool
-xen_vdi_get_other_config(xen_session *session, xen_string_string_map **result, xen_vdi vdi);
-
-
-/**
- * Set the name/label field of the given VDI.
- */
-extern bool
-xen_vdi_set_name_label(xen_session *session, xen_vdi vdi, char *label);
-
-
-/**
- * Set the name/description field of the given VDI.
- */
-extern bool
-xen_vdi_set_name_description(xen_session *session, xen_vdi vdi, char *description);
-
-
-/**
- * Set the virtual_size field of the given VDI.
- */
-extern bool
-xen_vdi_set_virtual_size(xen_session *session, xen_vdi vdi, int64_t virtual_size);
-
-
-/**
- * Set the sharable field of the given VDI.
- */
-extern bool
-xen_vdi_set_sharable(xen_session *session, xen_vdi vdi, bool sharable);
-
-
-/**
- * Set the read_only field of the given VDI.
- */
-extern bool
-xen_vdi_set_read_only(xen_session *session, xen_vdi vdi, bool read_only);
-
-
-/**
- * Set the other_config field of the given VDI.
- */
-extern bool
-xen_vdi_set_other_config(xen_session *session, xen_vdi vdi, xen_string_string_map *other_config);
-
-
-/**
- * Add the given key-value pair to the other_config field of the given
- * VDI.
- */
-extern bool
-xen_vdi_add_to_other_config(xen_session *session, xen_vdi vdi, char *key, char *value);
-
-
-/**
- * Remove the given key and its corresponding value from the
- * other_config field of the given VDI. If the key is not in that Map, then
- * do nothing.
- */
-extern bool
-xen_vdi_remove_from_other_config(xen_session *session, xen_vdi vdi, char *key);
-
-
-/**
- * Return a list of all the VDIs known to the system.
- */
-extern bool
-xen_vdi_get_all(xen_session *session, struct xen_vdi_set **result);
-
-
-/**
- * Set the security label of a VDI.
- */
-extern bool
-xen_vdi_set_security_label(xen_session *session, int64_t *result, xen_vdi vdi,
- char *label, char *oldlabel);
-
-/**
- * Get the security label of a VDI.
- */
-extern bool
-xen_vdi_get_security_label(xen_session *session, char **result, xen_vdi vdi);
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vdi_decl.h b/tools/libxen/include/xen/api/xen_vdi_decl.h
deleted file mode 100644
index 13a328e..0000000
--- a/tools/libxen/include/xen/api/xen_vdi_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VDI_DECL_H
-#define XEN_VDI_DECL_H
-
-typedef void *xen_vdi;
-
-struct xen_vdi_set;
-struct xen_vdi_record;
-struct xen_vdi_record_set;
-struct xen_vdi_record_opt;
-struct xen_vdi_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vdi_type.h b/tools/libxen/include/xen/api/xen_vdi_type.h
deleted file mode 100644
index d98a2ab..0000000
--- a/tools/libxen/include/xen/api/xen_vdi_type.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VDI_TYPE_H
-#define XEN_VDI_TYPE_H
-
-
-#include <xen/api/xen_common.h>
-
-
-enum xen_vdi_type
-{
- /**
- * a disk that may be replaced on upgrade
- */
- XEN_VDI_TYPE_SYSTEM,
-
- /**
- * a disk that is always preserved on upgrade
- */
- XEN_VDI_TYPE_USER,
-
- /**
- * a disk that may be reformatted on upgrade
- */
- XEN_VDI_TYPE_EPHEMERAL,
-
- /**
- * a disk that stores a suspend image
- */
- XEN_VDI_TYPE_SUSPEND,
-
- /**
- * a disk that stores VM crashdump information
- */
- XEN_VDI_TYPE_CRASHDUMP
-};
-
-
-typedef struct xen_vdi_type_set
-{
- size_t size;
- enum xen_vdi_type contents[];
-} xen_vdi_type_set;
-
-/**
- * Allocate a xen_vdi_type_set of the given size.
- */
-extern xen_vdi_type_set *
-xen_vdi_type_set_alloc(size_t size);
-
-/**
- * Free the given xen_vdi_type_set. The given set must have been
- * allocated by this library.
- */
-extern void
-xen_vdi_type_set_free(xen_vdi_type_set *set);
-
-
-/**
- * Return the name corresponding to the given code. This string must
- * not be modified or freed.
- */
-extern const char *
-xen_vdi_type_to_string(enum xen_vdi_type val);
-
-
-/**
- * Return the correct code for the given string, or set the session
- * object to failure and return an undefined value if the given string does
- * not match a known code.
- */
-extern enum xen_vdi_type
-xen_vdi_type_from_string(xen_session *session, const char *str);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vif.h b/tools/libxen/include/xen/api/xen_vif.h
deleted file mode 100644
index 3fb8d71..0000000
--- a/tools/libxen/include/xen/api/xen_vif.h
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VIF_H
-#define XEN_VIF_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_network_decl.h>
-#include <xen/api/xen_string_set.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vif_decl.h>
-#include <xen/api/xen_vif_metrics_decl.h>
-#include <xen/api/xen_vm_decl.h>
-
-
-/*
- * The VIF class.
- *
- * A virtual network interface.
- */
-
-
-/**
- * Free the given xen_vif. The given handle must have been allocated
- * by this library.
- */
-extern void
-xen_vif_free(xen_vif vif);
-
-
-typedef struct xen_vif_set
-{
- size_t size;
- xen_vif *contents[];
-} xen_vif_set;
-
-/**
- * Allocate a xen_vif_set of the given size.
- */
-extern xen_vif_set *
-xen_vif_set_alloc(size_t size);
-
-/**
- * Free the given xen_vif_set. The given set must have been allocated
- * by this library.
- */
-extern void
-xen_vif_set_free(xen_vif_set *set);
-
-
-typedef struct xen_vif_record
-{
- xen_vif handle;
- char *uuid;
- char *device;
- struct xen_network_record_opt *network;
- struct xen_vm_record_opt *vm;
- char *mac;
- int64_t mtu;
- bool currently_attached;
- int64_t status_code;
- char *status_detail;
- xen_string_string_map *runtime_properties;
- char *qos_algorithm_type;
- xen_string_string_map *qos_algorithm_params;
- struct xen_string_set *qos_supported_algorithms;
- struct xen_vif_metrics_record_opt *metrics;
-} xen_vif_record;
-
-/**
- * Allocate a xen_vif_record.
- */
-extern xen_vif_record *
-xen_vif_record_alloc(void);
-
-/**
- * Free the given xen_vif_record, and all referenced values. The given
- * record must have been allocated by this library.
- */
-extern void
-xen_vif_record_free(xen_vif_record *record);
-
-
-typedef struct xen_vif_record_opt
-{
- bool is_record;
- union
- {
- xen_vif handle;
- xen_vif_record *record;
- } u;
-} xen_vif_record_opt;
-
-/**
- * Allocate a xen_vif_record_opt.
- */
-extern xen_vif_record_opt *
-xen_vif_record_opt_alloc(void);
-
-/**
- * Free the given xen_vif_record_opt, and all referenced values. The
- * given record_opt must have been allocated by this library.
- */
-extern void
-xen_vif_record_opt_free(xen_vif_record_opt *record_opt);
-
-
-typedef struct xen_vif_record_set
-{
- size_t size;
- xen_vif_record *contents[];
-} xen_vif_record_set;
-
-/**
- * Allocate a xen_vif_record_set of the given size.
- */
-extern xen_vif_record_set *
-xen_vif_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_vif_record_set, and all referenced values. The
- * given set must have been allocated by this library.
- */
-extern void
-xen_vif_record_set_free(xen_vif_record_set *set);
-
-
-
-typedef struct xen_vif_record_opt_set
-{
- size_t size;
- xen_vif_record_opt *contents[];
-} xen_vif_record_opt_set;
-
-/**
- * Allocate a xen_vif_record_opt_set of the given size.
- */
-extern xen_vif_record_opt_set *
-xen_vif_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_vif_record_opt_set, and all referenced values.
- * The given set must have been allocated by this library.
- */
-extern void
-xen_vif_record_opt_set_free(xen_vif_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given VIF.
- */
-extern bool
-xen_vif_get_record(xen_session *session, xen_vif_record **result, xen_vif vif);
-
-
-/**
- * Get a reference to the VIF instance with the specified UUID.
- */
-extern bool
-xen_vif_get_by_uuid(xen_session *session, xen_vif *result, char *uuid);
-
-
-/**
- * Create a new VIF instance, and return its handle.
- */
-extern bool
-xen_vif_create(xen_session *session, xen_vif *result, xen_vif_record *record);
-
-
-/**
- * Destroy the specified VIF instance.
- */
-extern bool
-xen_vif_destroy(xen_session *session, xen_vif vif);
-
-
-/**
- * Get the uuid field of the given VIF.
- */
-extern bool
-xen_vif_get_uuid(xen_session *session, char **result, xen_vif vif);
-
-
-/**
- * Get the device field of the given VIF.
- */
-extern bool
-xen_vif_get_device(xen_session *session, char **result, xen_vif vif);
-
-
-/**
- * Get the network field of the given VIF.
- */
-extern bool
-xen_vif_get_network(xen_session *session, xen_network *result, xen_vif vif);
-
-
-/**
- * Get the VM field of the given VIF.
- */
-extern bool
-xen_vif_get_vm(xen_session *session, xen_vm *result, xen_vif vif);
-
-
-/**
- * Get the MAC field of the given VIF.
- */
-extern bool
-xen_vif_get_mac(xen_session *session, char **result, xen_vif vif);
-
-
-/**
- * Get the MTU field of the given VIF.
- */
-extern bool
-xen_vif_get_mtu(xen_session *session, int64_t *result, xen_vif vif);
-
-
-/**
- * Get the currently_attached field of the given VIF.
- */
-extern bool
-xen_vif_get_currently_attached(xen_session *session, bool *result, xen_vif vif);
-
-
-/**
- * Get the status_code field of the given VIF.
- */
-extern bool
-xen_vif_get_status_code(xen_session *session, int64_t *result, xen_vif vif);
-
-
-/**
- * Get the status_detail field of the given VIF.
- */
-extern bool
-xen_vif_get_status_detail(xen_session *session, char **result, xen_vif vif);
-
-
-/**
- * Get the runtime_properties field of the given VIF.
- */
-extern bool
-xen_vif_get_runtime_properties(xen_session *session, xen_string_string_map **result, xen_vif vif);
-
-
-/**
- * Get the qos/algorithm_type field of the given VIF.
- */
-extern bool
-xen_vif_get_qos_algorithm_type(xen_session *session, char **result, xen_vif vif);
-
-
-/**
- * Get the qos/algorithm_params field of the given VIF.
- */
-extern bool
-xen_vif_get_qos_algorithm_params(xen_session *session, xen_string_string_map **result, xen_vif vif);
-
-
-/**
- * Get the qos/supported_algorithms field of the given VIF.
- */
-extern bool
-xen_vif_get_qos_supported_algorithms(xen_session *session, struct xen_string_set **result, xen_vif vif);
-
-
-/**
- * Get the metrics field of the given VIF.
- */
-extern bool
-xen_vif_get_metrics(xen_session *session, xen_vif_metrics *result, xen_vif vif);
-
-
-/**
- * Set the device field of the given VIF.
- */
-extern bool
-xen_vif_set_device(xen_session *session, xen_vif vif, char *device);
-
-
-/**
- * Set the MAC field of the given VIF.
- */
-extern bool
-xen_vif_set_mac(xen_session *session, xen_vif vif, char *mac);
-
-
-/**
- * Set the MTU field of the given VIF.
- */
-extern bool
-xen_vif_set_mtu(xen_session *session, xen_vif vif, int64_t mtu);
-
-
-/**
- * Set the qos/algorithm_type field of the given VIF.
- */
-extern bool
-xen_vif_set_qos_algorithm_type(xen_session *session, xen_vif vif, char *algorithm_type);
-
-
-/**
- * Set the qos/algorithm_params field of the given VIF.
- */
-extern bool
-xen_vif_set_qos_algorithm_params(xen_session *session, xen_vif vif, xen_string_string_map *algorithm_params);
-
-
-/**
- * Add the given key-value pair to the qos/algorithm_params field of
- * the given VIF.
- */
-extern bool
-xen_vif_add_to_qos_algorithm_params(xen_session *session, xen_vif vif, char *key, char *value);
-
-
-/**
- * Remove the given key and its corresponding value from the
- * qos/algorithm_params field of the given VIF. If the key is not in that
- * Map, then do nothing.
- */
-extern bool
-xen_vif_remove_from_qos_algorithm_params(xen_session *session, xen_vif vif, char *key);
-
-
-/**
- * Hotplug the specified VIF, dynamically attaching it to the running
- * VM.
- */
-extern bool
-xen_vif_plug(xen_session *session, xen_vif self);
-
-
-/**
- * Hot-unplug the specified VIF, dynamically unattaching it from the
- * running VM.
- */
-extern bool
-xen_vif_unplug(xen_session *session, xen_vif self);
-
-
-/**
- * Return a list of all the VIFs known to the system.
- */
-extern bool
-xen_vif_get_all(xen_session *session, struct xen_vif_set **result);
-
-
-/**
- * Set the security label of a VIF.
- */
-extern bool
-xen_vif_set_security_label(xen_session *session, int64_t *result, xen_vif vif,
- char *label, char *oldlabel);
-
-
-/**
- * Get the security label of a VIF.
- */
-extern bool
-xen_vif_get_security_label(xen_session *session, char **result, xen_vif vif);
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vif_decl.h b/tools/libxen/include/xen/api/xen_vif_decl.h
deleted file mode 100644
index 0d4c59d..0000000
--- a/tools/libxen/include/xen/api/xen_vif_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VIF_DECL_H
-#define XEN_VIF_DECL_H
-
-typedef void *xen_vif;
-
-struct xen_vif_set;
-struct xen_vif_record;
-struct xen_vif_record_set;
-struct xen_vif_record_opt;
-struct xen_vif_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vif_metrics.h b/tools/libxen/include/xen/api/xen_vif_metrics.h
deleted file mode 100644
index a363137..0000000
--- a/tools/libxen/include/xen/api/xen_vif_metrics.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VIF_METRICS_H
-#define XEN_VIF_METRICS_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_vif_metrics_decl.h>
-
-
-/*
- * The VIF_metrics class.
- *
- * The metrics associated with a virtual network device.
- */
-
-
-/**
- * Free the given xen_vif_metrics. The given handle must have been
- * allocated by this library.
- */
-extern void
-xen_vif_metrics_free(xen_vif_metrics vif_metrics);
-
-
-typedef struct xen_vif_metrics_set
-{
- size_t size;
- xen_vif_metrics *contents[];
-} xen_vif_metrics_set;
-
-/**
- * Allocate a xen_vif_metrics_set of the given size.
- */
-extern xen_vif_metrics_set *
-xen_vif_metrics_set_alloc(size_t size);
-
-/**
- * Free the given xen_vif_metrics_set. The given set must have been
- * allocated by this library.
- */
-extern void
-xen_vif_metrics_set_free(xen_vif_metrics_set *set);
-
-
-typedef struct xen_vif_metrics_record
-{
- xen_vif_metrics handle;
- char *uuid;
- double io_read_kbs;
- double io_write_kbs;
- time_t last_updated;
-} xen_vif_metrics_record;
-
-/**
- * Allocate a xen_vif_metrics_record.
- */
-extern xen_vif_metrics_record *
-xen_vif_metrics_record_alloc(void);
-
-/**
- * Free the given xen_vif_metrics_record, and all referenced values.
- * The given record must have been allocated by this library.
- */
-extern void
-xen_vif_metrics_record_free(xen_vif_metrics_record *record);
-
-
-typedef struct xen_vif_metrics_record_opt
-{
- bool is_record;
- union
- {
- xen_vif_metrics handle;
- xen_vif_metrics_record *record;
- } u;
-} xen_vif_metrics_record_opt;
-
-/**
- * Allocate a xen_vif_metrics_record_opt.
- */
-extern xen_vif_metrics_record_opt *
-xen_vif_metrics_record_opt_alloc(void);
-
-/**
- * Free the given xen_vif_metrics_record_opt, and all referenced
- * values. The given record_opt must have been allocated by this library.
- */
-extern void
-xen_vif_metrics_record_opt_free(xen_vif_metrics_record_opt *record_opt);
-
-
-typedef struct xen_vif_metrics_record_set
-{
- size_t size;
- xen_vif_metrics_record *contents[];
-} xen_vif_metrics_record_set;
-
-/**
- * Allocate a xen_vif_metrics_record_set of the given size.
- */
-extern xen_vif_metrics_record_set *
-xen_vif_metrics_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_vif_metrics_record_set, and all referenced
- * values. The given set must have been allocated by this library.
- */
-extern void
-xen_vif_metrics_record_set_free(xen_vif_metrics_record_set *set);
-
-
-
-typedef struct xen_vif_metrics_record_opt_set
-{
- size_t size;
- xen_vif_metrics_record_opt *contents[];
-} xen_vif_metrics_record_opt_set;
-
-/**
- * Allocate a xen_vif_metrics_record_opt_set of the given size.
- */
-extern xen_vif_metrics_record_opt_set *
-xen_vif_metrics_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_vif_metrics_record_opt_set, and all referenced
- * values. The given set must have been allocated by this library.
- */
-extern void
-xen_vif_metrics_record_opt_set_free(xen_vif_metrics_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given VIF_metrics.
- */
-extern bool
-xen_vif_metrics_get_record(xen_session *session, xen_vif_metrics_record **result, xen_vif_metrics vif_metrics);
-
-
-/**
- * Get a reference to the VIF_metrics instance with the specified UUID.
- */
-extern bool
-xen_vif_metrics_get_by_uuid(xen_session *session, xen_vif_metrics *result, char *uuid);
-
-
-/**
- * Get the uuid field of the given VIF_metrics.
- */
-extern bool
-xen_vif_metrics_get_uuid(xen_session *session, char **result, xen_vif_metrics vif_metrics);
-
-
-/**
- * Get the io/read_kbs field of the given VIF_metrics.
- */
-extern bool
-xen_vif_metrics_get_io_read_kbs(xen_session *session, double *result, xen_vif_metrics vif_metrics);
-
-
-/**
- * Get the io/write_kbs field of the given VIF_metrics.
- */
-extern bool
-xen_vif_metrics_get_io_write_kbs(xen_session *session, double *result, xen_vif_metrics vif_metrics);
-
-
-/**
- * Get the last_updated field of the given VIF_metrics.
- */
-extern bool
-xen_vif_metrics_get_last_updated(xen_session *session, time_t *result, xen_vif_metrics vif_metrics);
-
-
-/**
- * Return a list of all the VIF_metrics instances known to the system.
- */
-extern bool
-xen_vif_metrics_get_all(xen_session *session, struct xen_vif_metrics_set **result);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vif_metrics_decl.h b/tools/libxen/include/xen/api/xen_vif_metrics_decl.h
deleted file mode 100644
index 5734723..0000000
--- a/tools/libxen/include/xen/api/xen_vif_metrics_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VIF_METRICS_DECL_H
-#define XEN_VIF_METRICS_DECL_H
-
-typedef void *xen_vif_metrics;
-
-struct xen_vif_metrics_set;
-struct xen_vif_metrics_record;
-struct xen_vif_metrics_record_set;
-struct xen_vif_metrics_record_opt;
-struct xen_vif_metrics_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vm.h b/tools/libxen/include/xen/api/xen_vm.h
deleted file mode 100644
index 8be7d2b..0000000
--- a/tools/libxen/include/xen/api/xen_vm.h
+++ /dev/null
@@ -1,931 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VM_H
-#define XEN_VM_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_console_decl.h>
-#include <xen/api/xen_crashdump_decl.h>
-#include <xen/api/xen_host_decl.h>
-#include <xen/api/xen_on_crash_behaviour.h>
-#include <xen/api/xen_on_normal_exit.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vbd_decl.h>
-#include <xen/api/xen_vdi_decl.h>
-#include <xen/api/xen_vif_decl.h>
-#include <xen/api/xen_vm_decl.h>
-#include <xen/api/xen_vm_guest_metrics_decl.h>
-#include <xen/api/xen_vm_metrics_decl.h>
-#include <xen/api/xen_vm_power_state.h>
-#include <xen/api/xen_cpu_pool_decl.h>
-
-
-/*
- * The VM class.
- *
- * A virtual machine (or 'guest').
- */
-
-
-/**
- * Free the given xen_vm. The given handle must have been allocated by
- * this library.
- */
-extern void
-xen_vm_free(xen_vm vm);
-
-
-typedef struct xen_vm_set
-{
- size_t size;
- xen_vm *contents[];
-} xen_vm_set;
-
-/**
- * Allocate a xen_vm_set of the given size.
- */
-extern xen_vm_set *
-xen_vm_set_alloc(size_t size);
-
-/**
- * Free the given xen_vm_set. The given set must have been allocated
- * by this library.
- */
-extern void
-xen_vm_set_free(xen_vm_set *set);
-
-
-typedef struct xen_vm_record
-{
- xen_vm handle;
- char *uuid;
- enum xen_vm_power_state power_state;
- char *name_label;
- char *name_description;
- int64_t user_version;
- bool is_a_template;
- bool auto_power_on;
- struct xen_vdi_record_opt *suspend_vdi;
- struct xen_host_record_opt *resident_on;
- int64_t memory_static_max;
- int64_t memory_dynamic_max;
- int64_t memory_dynamic_min;
- int64_t memory_static_min;
- xen_string_string_map *vcpus_params;
- int64_t vcpus_max;
- int64_t vcpus_at_startup;
- enum xen_on_normal_exit actions_after_shutdown;
- enum xen_on_normal_exit actions_after_reboot;
- enum xen_on_crash_behaviour actions_after_crash;
- struct xen_console_record_opt_set *consoles;
- struct xen_vif_record_opt_set *vifs;
- struct xen_vbd_record_opt_set *vbds;
- struct xen_crashdump_record_opt_set *crash_dumps;
- char *pv_bootloader;
- char *pv_kernel;
- char *pv_ramdisk;
- char *pv_args;
- char *pv_bootloader_args;
- char *hvm_boot_policy;
- xen_string_string_map *hvm_boot_params;
- xen_string_string_map *platform;
- char *pci_bus;
- xen_string_string_map *other_config;
- int64_t domid;
- bool is_control_domain;
- struct xen_vm_metrics_record_opt *metrics;
- struct xen_vm_guest_metrics_record_opt *guest_metrics;
- char *security_label;
- char *pool_name;
- struct xen_cpu_pool_record_opt_set *cpu_pool;
-} xen_vm_record;
-
-/**
- * Allocate a xen_vm_record.
- */
-extern xen_vm_record *
-xen_vm_record_alloc(void);
-
-/**
- * Free the given xen_vm_record, and all referenced values. The given
- * record must have been allocated by this library.
- */
-extern void
-xen_vm_record_free(xen_vm_record *record);
-
-
-typedef struct xen_vm_record_opt
-{
- bool is_record;
- union
- {
- xen_vm handle;
- xen_vm_record *record;
- } u;
-} xen_vm_record_opt;
-
-/**
- * Allocate a xen_vm_record_opt.
- */
-extern xen_vm_record_opt *
-xen_vm_record_opt_alloc(void);
-
-/**
- * Free the given xen_vm_record_opt, and all referenced values. The
- * given record_opt must have been allocated by this library.
- */
-extern void
-xen_vm_record_opt_free(xen_vm_record_opt *record_opt);
-
-
-typedef struct xen_vm_record_set
-{
- size_t size;
- xen_vm_record *contents[];
-} xen_vm_record_set;
-
-/**
- * Allocate a xen_vm_record_set of the given size.
- */
-extern xen_vm_record_set *
-xen_vm_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_vm_record_set, and all referenced values. The
- * given set must have been allocated by this library.
- */
-extern void
-xen_vm_record_set_free(xen_vm_record_set *set);
-
-
-
-typedef struct xen_vm_record_opt_set
-{
- size_t size;
- xen_vm_record_opt *contents[];
-} xen_vm_record_opt_set;
-
-/**
- * Allocate a xen_vm_record_opt_set of the given size.
- */
-extern xen_vm_record_opt_set *
-xen_vm_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_vm_record_opt_set, and all referenced values.
- * The given set must have been allocated by this library.
- */
-extern void
-xen_vm_record_opt_set_free(xen_vm_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given VM.
- */
-extern bool
-xen_vm_get_record(xen_session *session, xen_vm_record **result, xen_vm vm);
-
-
-/**
- * Get a reference to the VM instance with the specified UUID.
- */
-extern bool
-xen_vm_get_by_uuid(xen_session *session, xen_vm *result, char *uuid);
-
-
-/**
- * Create a new VM instance, and return its handle.
- */
-extern bool
-xen_vm_create(xen_session *session, xen_vm *result, xen_vm_record *record);
-
-
-/**
- * Destroy the specified VM. The VM is completely removed from the
- * system. This function can only be called when the VM is in the Halted
- * State.
- */
-extern bool
-xen_vm_destroy(xen_session *session, xen_vm vm);
-
-
-/**
- * Get all the VM instances with the given label.
- */
-extern bool
-xen_vm_get_by_name_label(xen_session *session, struct xen_vm_set **result, char *label);
-
-
-/**
- * Get the uuid field of the given VM.
- */
-extern bool
-xen_vm_get_uuid(xen_session *session, char **result, xen_vm vm);
-
-
-/**
- * Get the power_state field of the given VM.
- */
-extern bool
-xen_vm_get_power_state(xen_session *session, enum xen_vm_power_state *result, xen_vm vm);
-
-
-/**
- * Get the name/label field of the given VM.
- */
-extern bool
-xen_vm_get_name_label(xen_session *session, char **result, xen_vm vm);
-
-
-/**
- * Get the name/description field of the given VM.
- */
-extern bool
-xen_vm_get_name_description(xen_session *session, char **result, xen_vm vm);
-
-
-/**
- * Get the user_version field of the given VM.
- */
-extern bool
-xen_vm_get_user_version(xen_session *session, int64_t *result, xen_vm vm);
-
-
-/**
- * Get the is_a_template field of the given VM.
- */
-extern bool
-xen_vm_get_is_a_template(xen_session *session, bool *result, xen_vm vm);
-
-
-/**
- * Get the auto_power_on field of the given VM.
- */
-extern bool
-xen_vm_get_auto_power_on(xen_session *session, bool *result, xen_vm vm);
-
-
-/**
- * Get the suspend_VDI field of the given VM.
- */
-extern bool
-xen_vm_get_suspend_vdi(xen_session *session, xen_vdi *result, xen_vm vm);
-
-
-/**
- * Get the resident_on field of the given VM.
- */
-extern bool
-xen_vm_get_resident_on(xen_session *session, xen_host *result, xen_vm vm);
-
-
-/**
- * Get the memory/static_max field of the given VM.
- */
-extern bool
-xen_vm_get_memory_static_max(xen_session *session, int64_t *result, xen_vm vm);
-
-
-/**
- * Get the memory/dynamic_max field of the given VM.
- */
-extern bool
-xen_vm_get_memory_dynamic_max(xen_session *session, int64_t *result, xen_vm vm);
-
-
-/**
- * Get the memory/dynamic_min field of the given VM.
- */
-extern bool
-xen_vm_get_memory_dynamic_min(xen_session *session, int64_t *result, xen_vm vm);
-
-
-/**
- * Get the memory/static_min field of the given VM.
- */
-extern bool
-xen_vm_get_memory_static_min(xen_session *session, int64_t *result, xen_vm vm);
-
-
-/**
- * Get the VCPUs/params field of the given VM.
- */
-extern bool
-xen_vm_get_vcpus_params(xen_session *session, xen_string_string_map **result, xen_vm vm);
-
-
-/**
- * Get the VCPUs/max field of the given VM.
- */
-extern bool
-xen_vm_get_vcpus_max(xen_session *session, int64_t *result, xen_vm vm);
-
-
-/**
- * Get the VCPUs/at_startup field of the given VM.
- */
-extern bool
-xen_vm_get_vcpus_at_startup(xen_session *session, int64_t *result, xen_vm vm);
-
-
-/**
- * Get the actions/after_shutdown field of the given VM.
- */
-extern bool
-xen_vm_get_actions_after_shutdown(xen_session *session, enum xen_on_normal_exit *result, xen_vm vm);
-
-
-/**
- * Get the actions/after_reboot field of the given VM.
- */
-extern bool
-xen_vm_get_actions_after_reboot(xen_session *session, enum xen_on_normal_exit *result, xen_vm vm);
-
-
-/**
- * Get the actions/after_crash field of the given VM.
- */
-extern bool
-xen_vm_get_actions_after_crash(xen_session *session, enum xen_on_crash_behaviour *result, xen_vm vm);
-
-
-/**
- * Get the consoles field of the given VM.
- */
-extern bool
-xen_vm_get_consoles(xen_session *session, struct xen_console_set **result, xen_vm vm);
-
-
-/**
- * Get the VIFs field of the given VM.
- */
-extern bool
-xen_vm_get_vifs(xen_session *session, struct xen_vif_set **result, xen_vm vm);
-
-
-/**
- * Get the VBDs field of the given VM.
- */
-extern bool
-xen_vm_get_vbds(xen_session *session, struct xen_vbd_set **result, xen_vm vm);
-
-
-/**
- * Get the crash_dumps field of the given VM.
- */
-extern bool
-xen_vm_get_crash_dumps(xen_session *session, struct xen_crashdump_set **result, xen_vm vm);
-
-
-/**
- * Get the PV/bootloader field of the given VM.
- */
-extern bool
-xen_vm_get_pv_bootloader(xen_session *session, char **result, xen_vm vm);
-
-
-/**
- * Get the PV/kernel field of the given VM.
- */
-extern bool
-xen_vm_get_pv_kernel(xen_session *session, char **result, xen_vm vm);
-
-
-/**
- * Get the PV/ramdisk field of the given VM.
- */
-extern bool
-xen_vm_get_pv_ramdisk(xen_session *session, char **result, xen_vm vm);
-
-
-/**
- * Get the PV/args field of the given VM.
- */
-extern bool
-xen_vm_get_pv_args(xen_session *session, char **result, xen_vm vm);
-
-
-/**
- * Get the PV/bootloader_args field of the given VM.
- */
-extern bool
-xen_vm_get_pv_bootloader_args(xen_session *session, char **result, xen_vm vm);
-
-
-/**
- * Get the HVM/boot_policy field of the given VM.
- */
-extern bool
-xen_vm_get_hvm_boot_policy(xen_session *session, char **result, xen_vm vm);
-
-
-/**
- * Get the HVM/boot_params field of the given VM.
- */
-extern bool
-xen_vm_get_hvm_boot_params(xen_session *session, xen_string_string_map **result, xen_vm vm);
-
-
-/**
- * Get the platform field of the given VM.
- */
-extern bool
-xen_vm_get_platform(xen_session *session, xen_string_string_map **result, xen_vm vm);
-
-
-/**
- * Get the PCI_bus field of the given VM.
- */
-extern bool
-xen_vm_get_pci_bus(xen_session *session, char **result, xen_vm vm);
-
-
-/**
- * Get the other_config field of the given VM.
- */
-extern bool
-xen_vm_get_other_config(xen_session *session, xen_string_string_map **result, xen_vm vm);
-
-
-/**
- * Get the domid field of the given VM.
- */
-extern bool
-xen_vm_get_domid(xen_session *session, int64_t *result, xen_vm vm);
-
-
-/**
- * Get the is_control_domain field of the given VM.
- */
-extern bool
-xen_vm_get_is_control_domain(xen_session *session, bool *result, xen_vm vm);
-
-
-/**
- * Get the metrics field of the given VM.
- */
-extern bool
-xen_vm_get_metrics(xen_session *session, xen_vm_metrics *result, xen_vm vm);
-
-
-/**
- * Get the guest_metrics field of the given VM.
- */
-extern bool
-xen_vm_get_guest_metrics(xen_session *session, xen_vm_guest_metrics *result, xen_vm vm);
-
-
-/**
- * Set the name/label field of the given VM.
- */
-extern bool
-xen_vm_set_name_label(xen_session *session, xen_vm vm, char *label);
-
-
-/**
- * Set the name/description field of the given VM.
- */
-extern bool
-xen_vm_set_name_description(xen_session *session, xen_vm vm, char *description);
-
-
-/**
- * Set the user_version field of the given VM.
- */
-extern bool
-xen_vm_set_user_version(xen_session *session, xen_vm vm, int64_t user_version);
-
-
-/**
- * Set the is_a_template field of the given VM.
- */
-extern bool
-xen_vm_set_is_a_template(xen_session *session, xen_vm vm, bool is_a_template);
-
-
-/**
- * Set the auto_power_on field of the given VM.
- */
-extern bool
-xen_vm_set_auto_power_on(xen_session *session, xen_vm vm, bool auto_power_on);
-
-
-/**
- * Set the memory/static_max field of the given VM.
- */
-extern bool
-xen_vm_set_memory_static_max(xen_session *session, xen_vm vm, int64_t static_max);
-
-
-/**
- * Set the memory/dynamic_max field of the given VM.
- */
-extern bool
-xen_vm_set_memory_dynamic_max(xen_session *session, xen_vm vm, int64_t dynamic_max);
-
-
-/**
- * Set the memory/dynamic_min field of the given VM.
- */
-extern bool
-xen_vm_set_memory_dynamic_min(xen_session *session, xen_vm vm, int64_t dynamic_min);
-
-
-/**
- * Set the memory/static_min field of the given VM.
- */
-extern bool
-xen_vm_set_memory_static_min(xen_session *session, xen_vm vm, int64_t static_min);
-
-
-/**
- * Set the VCPUs/params field of the given VM.
- */
-extern bool
-xen_vm_set_vcpus_params(xen_session *session, xen_vm vm, xen_string_string_map *params);
-
-
-/**
- * Add the given key-value pair to the VCPUs/params field of the given
- * VM.
- */
-extern bool
-xen_vm_add_to_vcpus_params(xen_session *session, xen_vm vm, char *key, char *value);
-
-
-/**
- * Remove the given key and its corresponding value from the
- * VCPUs/params field of the given VM. If the key is not in that Map, then do
- * nothing.
- */
-extern bool
-xen_vm_remove_from_vcpus_params(xen_session *session, xen_vm vm, char *key);
-
-
-/**
- * Set the VCPUs/max field of the given VM.
- */
-extern bool
-xen_vm_set_vcpus_max(xen_session *session, xen_vm vm, int64_t max);
-
-
-/**
- * Set the VCPUs/at_startup field of the given VM.
- */
-extern bool
-xen_vm_set_vcpus_at_startup(xen_session *session, xen_vm vm, int64_t at_startup);
-
-
-/**
- * Set the actions/after_shutdown field of the given VM.
- */
-extern bool
-xen_vm_set_actions_after_shutdown(xen_session *session, xen_vm vm, enum xen_on_normal_exit after_shutdown);
-
-
-/**
- * Set the actions/after_reboot field of the given VM.
- */
-extern bool
-xen_vm_set_actions_after_reboot(xen_session *session, xen_vm vm, enum xen_on_normal_exit after_reboot);
-
-
-/**
- * Set the actions/after_crash field of the given VM.
- */
-extern bool
-xen_vm_set_actions_after_crash(xen_session *session, xen_vm vm, enum xen_on_crash_behaviour after_crash);
-
-
-/**
- * Set the PV/bootloader field of the given VM.
- */
-extern bool
-xen_vm_set_pv_bootloader(xen_session *session, xen_vm vm, char *bootloader);
-
-
-/**
- * Set the PV/kernel field of the given VM.
- */
-extern bool
-xen_vm_set_pv_kernel(xen_session *session, xen_vm vm, char *kernel);
-
-
-/**
- * Set the PV/ramdisk field of the given VM.
- */
-extern bool
-xen_vm_set_pv_ramdisk(xen_session *session, xen_vm vm, char *ramdisk);
-
-
-/**
- * Set the PV/args field of the given VM.
- */
-extern bool
-xen_vm_set_pv_args(xen_session *session, xen_vm vm, char *args);
-
-
-/**
- * Set the PV/bootloader_args field of the given VM.
- */
-extern bool
-xen_vm_set_pv_bootloader_args(xen_session *session, xen_vm vm, char *bootloader_args);
-
-
-/**
- * Set the HVM/boot_policy field of the given VM.
- */
-extern bool
-xen_vm_set_hvm_boot_policy(xen_session *session, xen_vm vm, char *boot_policy);
-
-
-/**
- * Set the HVM/boot_params field of the given VM.
- */
-extern bool
-xen_vm_set_hvm_boot_params(xen_session *session, xen_vm vm, xen_string_string_map *boot_params);
-
-
-/**
- * Add the given key-value pair to the HVM/boot_params field of the
- * given VM.
- */
-extern bool
-xen_vm_add_to_hvm_boot_params(xen_session *session, xen_vm vm, char *key, char *value);
-
-
-/**
- * Remove the given key and its corresponding value from the
- * HVM/boot_params field of the given VM. If the key is not in that Map, then
- * do nothing.
- */
-extern bool
-xen_vm_remove_from_hvm_boot_params(xen_session *session, xen_vm vm, char *key);
-
-
-/**
- * Set the platform field of the given VM.
- */
-extern bool
-xen_vm_set_platform(xen_session *session, xen_vm vm, xen_string_string_map *platform);
-
-
-/**
- * Add the given key-value pair to the platform field of the given VM.
- */
-extern bool
-xen_vm_add_to_platform(xen_session *session, xen_vm vm, char *key, char *value);
-
-
-/**
- * Remove the given key and its corresponding value from the platform
- * field of the given VM. If the key is not in that Map, then do nothing.
- */
-extern bool
-xen_vm_remove_from_platform(xen_session *session, xen_vm vm, char *key);
-
-
-/**
- * Set the PCI_bus field of the given VM.
- */
-extern bool
-xen_vm_set_pci_bus(xen_session *session, xen_vm vm, char *pci_bus);
-
-
-/**
- * Set the other_config field of the given VM.
- */
-extern bool
-xen_vm_set_other_config(xen_session *session, xen_vm vm, xen_string_string_map *other_config);
-
-
-/**
- * Add the given key-value pair to the other_config field of the given
- * VM.
- */
-extern bool
-xen_vm_add_to_other_config(xen_session *session, xen_vm vm, char *key, char *value);
-
-
-/**
- * Remove the given key and its corresponding value from the
- * other_config field of the given VM. If the key is not in that Map, then do
- * nothing.
- */
-extern bool
-xen_vm_remove_from_other_config(xen_session *session, xen_vm vm, char *key);
-
-
-/**
- * Clones the specified VM, making a new VM. Clone automatically
- * exploits the capabilities of the underlying storage repository in which the
- * VM's disk images are stored (e.g. Copy on Write). This function can only
- * be called when the VM is in the Halted State.
- */
-extern bool
-xen_vm_clone(xen_session *session, xen_vm *result, xen_vm vm, char *new_name);
-
-
-/**
- * Start the specified VM. This function can only be called with the
- * VM is in the Halted State.
- */
-extern bool
-xen_vm_start(xen_session *session, xen_vm vm, bool start_paused);
-
-
-/**
- * Pause the specified VM. This can only be called when the specified
- * VM is in the Running state.
- */
-extern bool
-xen_vm_pause(xen_session *session, xen_vm vm);
-
-
-/**
- * Resume the specified VM. This can only be called when the specified
- * VM is in the Paused state.
- */
-extern bool
-xen_vm_unpause(xen_session *session, xen_vm vm);
-
-
-/**
- * Attempt to cleanly shutdown the specified VM. (Note: this may not be
- * supported---e.g. if a guest agent is not installed).
- *
- * Once shutdown has been completed perform poweroff action specified in guest
- * configuration.
- *
- * This can only be called when the specified VM is in the Running state.
- */
-extern bool
-xen_vm_clean_shutdown(xen_session *session, xen_vm vm);
-
-
-/**
- * Attempt to cleanly shutdown the specified VM (Note: this may not be
- * supported---e.g. if a guest agent is not installed).
- *
- * Once shutdown has been completed perform reboot action specified in guest
- * configuration.
- *
- * This can only be called when the specified VM is in the Running state.
- */
-extern bool
-xen_vm_clean_reboot(xen_session *session, xen_vm vm);
-
-
-/**
- * Stop executing the specified VM without attempting a clean shutdown.
- * Then perform poweroff action specified in VM configuration.
- */
-extern bool
-xen_vm_hard_shutdown(xen_session *session, xen_vm vm);
-
-
-/**
- * Stop executing the specified VM without attempting a clean shutdown.
- * Then perform reboot action specified in VM configuration
- */
-extern bool
-xen_vm_hard_reboot(xen_session *session, xen_vm vm);
-
-
-/**
- * Suspend the specified VM to disk. This can only be called when the
- * specified VM is in the Running state.
- */
-extern bool
-xen_vm_suspend(xen_session *session, xen_vm vm);
-
-
-/**
- * Awaken the specified VM and resume it. This can only be called when
- * the specified VM is in the Suspended state.
- */
-extern bool
-xen_vm_resume(xen_session *session, xen_vm vm, bool start_paused);
-
-
-/**
- * Set this VM's VCPUs/at_startup value, and set the same value on the
- * VM, if running
- */
-extern bool
-xen_vm_set_vcpus_number_live(xen_session *session, xen_vm self, int64_t nvcpu);
-
-
-/**
- * Add the given key-value pair to VM.VCPUs_params, and apply that
- * value on the running VM.
- */
-extern bool
-xen_vm_add_to_vcpus_params_live(xen_session *session, xen_vm self, char *key, char *value);
-
-
-/**
- * Set memory_dynamic_max in database and on running VM.
- */
-extern bool
-xen_vm_set_memory_dynamic_max_live(xen_session *session, xen_vm self, int64_t max);
-
-
-/**
- * Set memory_dynamic_min in database and on running VM.
- */
-extern bool
-xen_vm_set_memory_dynamic_min_live(xen_session *session, xen_vm self, int64_t min);
-
-
-/**
- * Send the given key as a sysrq to this VM. The key is specified as a
- * single character (a String of length 1). This can only be called when the
- * specified VM is in the Running state.
- */
-extern bool
-xen_vm_send_sysrq(xen_session *session, xen_vm vm, char *key);
-
-
-/**
- * Send the named trigger to this VM. This can only be called when the
- * specified VM is in the Running state.
- */
-extern bool
-xen_vm_send_trigger(xen_session *session, xen_vm vm, char *trigger);
-
-
-/**
- * Migrate the VM to another host. This can only be called when the
- * specified VM is in the Running state.
- */
-extern bool
-xen_vm_migrate(xen_session *session, xen_vm vm, char *dest, bool live, xen_string_string_map *options);
-
-
-/**
- * Return a list of all the VMs known to the system.
- */
-extern bool
-xen_vm_get_all(xen_session *session, struct xen_vm_set **result);
-
-
-/**
- * Set the security label of a domain.
- */
-extern bool
-xen_vm_set_security_label(xen_session *session, int64_t *result, xen_vm vm,
- char *label, char *oldlabel);
-
-/**
- * Get the security label of a domain.
- */
-extern bool
-xen_vm_get_security_label(xen_session *session, char **result, xen_vm vm);
-
-
-/**
- * Get the cpu_pool ref field of a domain.
- */
-extern bool
-xen_vm_get_cpu_pool(xen_session *session, struct xen_cpu_pool_set **result, xen_vm vm);
-
-
-/**
- * Get the pool_name field of a domain.
- */
-extern bool
-xen_vm_get_pool_name(xen_session *session, char **result, xen_vm vm);
-
-
-/**
- * Set the pool_name field of a domain.
- */
-extern bool
-xen_vm_set_pool_name(xen_session *session, xen_vm vm, char *pool_name);
-
-
-/**
- * Migrate the VM to another cpu_pool (on the same host). This can only be
- * called when the specified VM is in the Running state.
- */
-extern bool
-xen_vm_cpu_pool_migrate(xen_session *session, xen_vm vm, xen_cpu_pool cpu_pool);
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vm_decl.h b/tools/libxen/include/xen/api/xen_vm_decl.h
deleted file mode 100644
index f4ca986..0000000
--- a/tools/libxen/include/xen/api/xen_vm_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VM_DECL_H
-#define XEN_VM_DECL_H
-
-typedef void *xen_vm;
-
-struct xen_vm_set;
-struct xen_vm_record;
-struct xen_vm_record_set;
-struct xen_vm_record_opt;
-struct xen_vm_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vm_guest_metrics.h b/tools/libxen/include/xen/api/xen_vm_guest_metrics.h
deleted file mode 100644
index fd4d23a..0000000
--- a/tools/libxen/include/xen/api/xen_vm_guest_metrics.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VM_GUEST_METRICS_H
-#define XEN_VM_GUEST_METRICS_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vm_guest_metrics_decl.h>
-
-
-/*
- * The VM_guest_metrics class.
- *
- * The metrics reported by the guest (as opposed to inferred from outside).
- */
-
-
-/**
- * Free the given xen_vm_guest_metrics. The given handle must have
- * been allocated by this library.
- */
-extern void
-xen_vm_guest_metrics_free(xen_vm_guest_metrics vm_guest_metrics);
-
-
-typedef struct xen_vm_guest_metrics_set
-{
- size_t size;
- xen_vm_guest_metrics *contents[];
-} xen_vm_guest_metrics_set;
-
-/**
- * Allocate a xen_vm_guest_metrics_set of the given size.
- */
-extern xen_vm_guest_metrics_set *
-xen_vm_guest_metrics_set_alloc(size_t size);
-
-/**
- * Free the given xen_vm_guest_metrics_set. The given set must have
- * been allocated by this library.
- */
-extern void
-xen_vm_guest_metrics_set_free(xen_vm_guest_metrics_set *set);
-
-
-typedef struct xen_vm_guest_metrics_record
-{
- xen_vm_guest_metrics handle;
- char *uuid;
- xen_string_string_map *os_version;
- xen_string_string_map *pv_drivers_version;
- xen_string_string_map *memory;
- xen_string_string_map *disks;
- xen_string_string_map *networks;
- xen_string_string_map *other;
- time_t last_updated;
-} xen_vm_guest_metrics_record;
-
-/**
- * Allocate a xen_vm_guest_metrics_record.
- */
-extern xen_vm_guest_metrics_record *
-xen_vm_guest_metrics_record_alloc(void);
-
-/**
- * Free the given xen_vm_guest_metrics_record, and all referenced
- * values. The given record must have been allocated by this library.
- */
-extern void
-xen_vm_guest_metrics_record_free(xen_vm_guest_metrics_record *record);
-
-
-typedef struct xen_vm_guest_metrics_record_opt
-{
- bool is_record;
- union
- {
- xen_vm_guest_metrics handle;
- xen_vm_guest_metrics_record *record;
- } u;
-} xen_vm_guest_metrics_record_opt;
-
-/**
- * Allocate a xen_vm_guest_metrics_record_opt.
- */
-extern xen_vm_guest_metrics_record_opt *
-xen_vm_guest_metrics_record_opt_alloc(void);
-
-/**
- * Free the given xen_vm_guest_metrics_record_opt, and all referenced
- * values. The given record_opt must have been allocated by this library.
- */
-extern void
-xen_vm_guest_metrics_record_opt_free(xen_vm_guest_metrics_record_opt *record_opt);
-
-
-typedef struct xen_vm_guest_metrics_record_set
-{
- size_t size;
- xen_vm_guest_metrics_record *contents[];
-} xen_vm_guest_metrics_record_set;
-
-/**
- * Allocate a xen_vm_guest_metrics_record_set of the given size.
- */
-extern xen_vm_guest_metrics_record_set *
-xen_vm_guest_metrics_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_vm_guest_metrics_record_set, and all referenced
- * values. The given set must have been allocated by this library.
- */
-extern void
-xen_vm_guest_metrics_record_set_free(xen_vm_guest_metrics_record_set *set);
-
-
-
-typedef struct xen_vm_guest_metrics_record_opt_set
-{
- size_t size;
- xen_vm_guest_metrics_record_opt *contents[];
-} xen_vm_guest_metrics_record_opt_set;
-
-/**
- * Allocate a xen_vm_guest_metrics_record_opt_set of the given size.
- */
-extern xen_vm_guest_metrics_record_opt_set *
-xen_vm_guest_metrics_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_vm_guest_metrics_record_opt_set, and all
- * referenced values. The given set must have been allocated by this library.
- */
-extern void
-xen_vm_guest_metrics_record_opt_set_free(xen_vm_guest_metrics_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given
- * VM_guest_metrics.
- */
-extern bool
-xen_vm_guest_metrics_get_record(xen_session *session, xen_vm_guest_metrics_record **result, xen_vm_guest_metrics vm_guest_metrics);
-
-
-/**
- * Get a reference to the VM_guest_metrics instance with the specified
- * UUID.
- */
-extern bool
-xen_vm_guest_metrics_get_by_uuid(xen_session *session, xen_vm_guest_metrics *result, char *uuid);
-
-
-/**
- * Get the uuid field of the given VM_guest_metrics.
- */
-extern bool
-xen_vm_guest_metrics_get_uuid(xen_session *session, char **result, xen_vm_guest_metrics vm_guest_metrics);
-
-
-/**
- * Get the os_version field of the given VM_guest_metrics.
- */
-extern bool
-xen_vm_guest_metrics_get_os_version(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics);
-
-
-/**
- * Get the PV_drivers_version field of the given VM_guest_metrics.
- */
-extern bool
-xen_vm_guest_metrics_get_pv_drivers_version(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics);
-
-
-/**
- * Get the memory field of the given VM_guest_metrics.
- */
-extern bool
-xen_vm_guest_metrics_get_memory(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics);
-
-
-/**
- * Get the disks field of the given VM_guest_metrics.
- */
-extern bool
-xen_vm_guest_metrics_get_disks(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics);
-
-
-/**
- * Get the networks field of the given VM_guest_metrics.
- */
-extern bool
-xen_vm_guest_metrics_get_networks(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics);
-
-
-/**
- * Get the other field of the given VM_guest_metrics.
- */
-extern bool
-xen_vm_guest_metrics_get_other(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics);
-
-
-/**
- * Get the last_updated field of the given VM_guest_metrics.
- */
-extern bool
-xen_vm_guest_metrics_get_last_updated(xen_session *session, time_t *result, xen_vm_guest_metrics vm_guest_metrics);
-
-
-/**
- * Return a list of all the VM_guest_metrics instances known to the
- * system.
- */
-extern bool
-xen_vm_guest_metrics_get_all(xen_session *session, struct xen_vm_guest_metrics_set **result);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vm_guest_metrics_decl.h b/tools/libxen/include/xen/api/xen_vm_guest_metrics_decl.h
deleted file mode 100644
index 837528b..0000000
--- a/tools/libxen/include/xen/api/xen_vm_guest_metrics_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VM_GUEST_METRICS_DECL_H
-#define XEN_VM_GUEST_METRICS_DECL_H
-
-typedef void *xen_vm_guest_metrics;
-
-struct xen_vm_guest_metrics_set;
-struct xen_vm_guest_metrics_record;
-struct xen_vm_guest_metrics_record_set;
-struct xen_vm_guest_metrics_record_opt;
-struct xen_vm_guest_metrics_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vm_metrics.h b/tools/libxen/include/xen/api/xen_vm_metrics.h
deleted file mode 100644
index 128c1a3..0000000
--- a/tools/libxen/include/xen/api/xen_vm_metrics.h
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VM_METRICS_H
-#define XEN_VM_METRICS_H
-
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_int_float_map.h>
-#include <xen/api/xen_int_int_map.h>
-#include <xen/api/xen_int_string_set_map.h>
-#include <xen/api/xen_string_set.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vm_metrics_decl.h>
-
-
-/*
- * The VM_metrics class.
- *
- * The metrics associated with a VM.
- */
-
-
-/**
- * Free the given xen_vm_metrics. The given handle must have been
- * allocated by this library.
- */
-extern void
-xen_vm_metrics_free(xen_vm_metrics vm_metrics);
-
-
-typedef struct xen_vm_metrics_set
-{
- size_t size;
- xen_vm_metrics *contents[];
-} xen_vm_metrics_set;
-
-/**
- * Allocate a xen_vm_metrics_set of the given size.
- */
-extern xen_vm_metrics_set *
-xen_vm_metrics_set_alloc(size_t size);
-
-/**
- * Free the given xen_vm_metrics_set. The given set must have been
- * allocated by this library.
- */
-extern void
-xen_vm_metrics_set_free(xen_vm_metrics_set *set);
-
-
-typedef struct xen_vm_metrics_record
-{
- xen_vm_metrics handle;
- char *uuid;
- int64_t memory_actual;
- int64_t vcpus_number;
- xen_int_float_map *vcpus_utilisation;
- xen_int_int_map *vcpus_cpu;
- xen_string_string_map *vcpus_params;
- xen_int_string_set_map *vcpus_flags;
- struct xen_string_set *state;
- time_t start_time;
- time_t last_updated;
-} xen_vm_metrics_record;
-
-/**
- * Allocate a xen_vm_metrics_record.
- */
-extern xen_vm_metrics_record *
-xen_vm_metrics_record_alloc(void);
-
-/**
- * Free the given xen_vm_metrics_record, and all referenced values.
- * The given record must have been allocated by this library.
- */
-extern void
-xen_vm_metrics_record_free(xen_vm_metrics_record *record);
-
-
-typedef struct xen_vm_metrics_record_opt
-{
- bool is_record;
- union
- {
- xen_vm_metrics handle;
- xen_vm_metrics_record *record;
- } u;
-} xen_vm_metrics_record_opt;
-
-/**
- * Allocate a xen_vm_metrics_record_opt.
- */
-extern xen_vm_metrics_record_opt *
-xen_vm_metrics_record_opt_alloc(void);
-
-/**
- * Free the given xen_vm_metrics_record_opt, and all referenced values.
- * The given record_opt must have been allocated by this library.
- */
-extern void
-xen_vm_metrics_record_opt_free(xen_vm_metrics_record_opt *record_opt);
-
-
-typedef struct xen_vm_metrics_record_set
-{
- size_t size;
- xen_vm_metrics_record *contents[];
-} xen_vm_metrics_record_set;
-
-/**
- * Allocate a xen_vm_metrics_record_set of the given size.
- */
-extern xen_vm_metrics_record_set *
-xen_vm_metrics_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_vm_metrics_record_set, and all referenced values.
- * The given set must have been allocated by this library.
- */
-extern void
-xen_vm_metrics_record_set_free(xen_vm_metrics_record_set *set);
-
-
-
-typedef struct xen_vm_metrics_record_opt_set
-{
- size_t size;
- xen_vm_metrics_record_opt *contents[];
-} xen_vm_metrics_record_opt_set;
-
-/**
- * Allocate a xen_vm_metrics_record_opt_set of the given size.
- */
-extern xen_vm_metrics_record_opt_set *
-xen_vm_metrics_record_opt_set_alloc(size_t size);
-
-/**
- * Free the given xen_vm_metrics_record_opt_set, and all referenced
- * values. The given set must have been allocated by this library.
- */
-extern void
-xen_vm_metrics_record_opt_set_free(xen_vm_metrics_record_opt_set *set);
-
-
-/**
- * Get a record containing the current state of the given VM_metrics.
- */
-extern bool
-xen_vm_metrics_get_record(xen_session *session, xen_vm_metrics_record **result, xen_vm_metrics vm_metrics);
-
-
-/**
- * Get a reference to the VM_metrics instance with the specified UUID.
- */
-extern bool
-xen_vm_metrics_get_by_uuid(xen_session *session, xen_vm_metrics *result, char *uuid);
-
-
-/**
- * Get the uuid field of the given VM_metrics.
- */
-extern bool
-xen_vm_metrics_get_uuid(xen_session *session, char **result, xen_vm_metrics vm_metrics);
-
-
-/**
- * Get the memory/actual field of the given VM_metrics.
- */
-extern bool
-xen_vm_metrics_get_memory_actual(xen_session *session, int64_t *result, xen_vm_metrics vm_metrics);
-
-
-/**
- * Get the VCPUs/number field of the given VM_metrics.
- */
-extern bool
-xen_vm_metrics_get_vcpus_number(xen_session *session, int64_t *result, xen_vm_metrics vm_metrics);
-
-
-/**
- * Get the VCPUs/utilisation field of the given VM_metrics.
- */
-extern bool
-xen_vm_metrics_get_vcpus_utilisation(xen_session *session, xen_int_float_map **result, xen_vm_metrics vm_metrics);
-
-
-/**
- * Get the VCPUs/CPU field of the given VM_metrics.
- */
-extern bool
-xen_vm_metrics_get_vcpus_cpu(xen_session *session, xen_int_int_map **result, xen_vm_metrics vm_metrics);
-
-
-/**
- * Get the VCPUs/params field of the given VM_metrics.
- */
-extern bool
-xen_vm_metrics_get_vcpus_params(xen_session *session, xen_string_string_map **result, xen_vm_metrics vm_metrics);
-
-
-/**
- * Get the VCPUs/flags field of the given VM_metrics.
- */
-extern bool
-xen_vm_metrics_get_vcpus_flags(xen_session *session, xen_int_string_set_map **result, xen_vm_metrics vm_metrics);
-
-
-/**
- * Get the state field of the given VM_metrics.
- */
-extern bool
-xen_vm_metrics_get_state(xen_session *session, struct xen_string_set **result, xen_vm_metrics vm_metrics);
-
-
-/**
- * Get the start_time field of the given VM_metrics.
- */
-extern bool
-xen_vm_metrics_get_start_time(xen_session *session, time_t *result, xen_vm_metrics vm_metrics);
-
-
-/**
- * Get the last_updated field of the given VM_metrics.
- */
-extern bool
-xen_vm_metrics_get_last_updated(xen_session *session, time_t *result, xen_vm_metrics vm_metrics);
-
-
-/**
- * Return a list of all the VM_metrics instances known to the system.
- */
-extern bool
-xen_vm_metrics_get_all(xen_session *session, struct xen_vm_metrics_set **result);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vm_metrics_decl.h b/tools/libxen/include/xen/api/xen_vm_metrics_decl.h
deleted file mode 100644
index 76810b5..0000000
--- a/tools/libxen/include/xen/api/xen_vm_metrics_decl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VM_METRICS_DECL_H
-#define XEN_VM_METRICS_DECL_H
-
-typedef void *xen_vm_metrics;
-
-struct xen_vm_metrics_set;
-struct xen_vm_metrics_record;
-struct xen_vm_metrics_record_set;
-struct xen_vm_metrics_record_opt;
-struct xen_vm_metrics_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_vm_power_state.h b/tools/libxen/include/xen/api/xen_vm_power_state.h
deleted file mode 100644
index b9b2acd..0000000
--- a/tools/libxen/include/xen/api/xen_vm_power_state.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_VM_POWER_STATE_H
-#define XEN_VM_POWER_STATE_H
-
-
-#include <xen/api/xen_common.h>
-
-
-enum xen_vm_power_state
-{
- /**
- * Halted
- */
- XEN_VM_POWER_STATE_HALTED,
-
- /**
- * Paused
- */
- XEN_VM_POWER_STATE_PAUSED,
-
- /**
- * Running
- */
- XEN_VM_POWER_STATE_RUNNING,
-
- /**
- * Suspended
- */
- XEN_VM_POWER_STATE_SUSPENDED,
-
- /**
- * Crashed
- */
- XEN_VM_POWER_STATE_CRASHED,
-
- /**
- * Some other unknown state
- */
- XEN_VM_POWER_STATE_UNKNOWN
-};
-
-
-typedef struct xen_vm_power_state_set
-{
- size_t size;
- enum xen_vm_power_state contents[];
-} xen_vm_power_state_set;
-
-/**
- * Allocate a xen_vm_power_state_set of the given size.
- */
-extern xen_vm_power_state_set *
-xen_vm_power_state_set_alloc(size_t size);
-
-/**
- * Free the given xen_vm_power_state_set. The given set must have been
- * allocated by this library.
- */
-extern void
-xen_vm_power_state_set_free(xen_vm_power_state_set *set);
-
-
-/**
- * Return the name corresponding to the given code. This string must
- * not be modified or freed.
- */
-extern const char *
-xen_vm_power_state_to_string(enum xen_vm_power_state val);
-
-
-/**
- * Return the correct code for the given string, or set the session
- * object to failure and return an undefined value if the given string does
- * not match a known code.
- */
-extern enum xen_vm_power_state
-xen_vm_power_state_from_string(xen_session *session, const char *str);
-
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_xspolicy.h b/tools/libxen/include/xen/api/xen_xspolicy.h
deleted file mode 100644
index f685f15..0000000
--- a/tools/libxen/include/xen/api/xen_xspolicy.h
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (c) 2007, IBM Corp.
- * Copyright (c) 2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_XSPOLICY_H
-#define XEN_XSPOLICY_H
-
-#include "xen_common.h"
-#include "xen_xspolicy_decl.h"
-#include "xen_string_string_map.h"
-
-
-/*
- * The XSPolicy and associated data structures.
- *
- */
-typedef int64_t xs_type;
-typedef int64_t xs_instantiationflags;
-
-enum xs_type {
- XS_POLICY_ACM = (1 << 0),
-};
-
-enum xs_instantiationflags {
- XS_INST_NONE = 0,
- XS_INST_BOOT = (1 << 0),
- XS_INST_LOAD = (1 << 1),
-};
-
-
-/* Error codes returned by xend following XSPolicy operations */
-#define XSERR_BASE 0x1000
-
-#define XSERR_SUCCESS 0
-#define XSERR_GENERAL_FAILURE 1 + XSERR_BASE
-#define XSERR_BAD_XML 2 + XSERR_BASE
-#define XSERR_XML_PROCESSING 3 + XSERR_BASE
-#define XSERR_POLICY_INCONSISTENT 4 + XSERR_BASE
-#define XSERR_FILE_ERROR 5 + XSERR_BASE
-#define XSERR_BAD_RESOURCE_FORMAT 6 + XSERR_BASE
-#define XSERR_BAD_LABEL_FORMAT 7 + XSERR_BASE
-#define XSERR_RESOURCE_NOT_LABELED 8 + XSERR_BASE
-#define XSERR_RESOURCE_ALREADY_LABELED 9 + XSERR_BASE
-#define XSERR_WRONG_POLICY_TYPE 10 + XSERR_BASE
-#define XSERR_BOOTPOLICY_INSTALLED 11 + XSERR_BASE
-#define XSERR_NO_DEFAULT_BOOT_TITLE 12 + XSERR_BASE
-#define XSERR_POLICY_LOAD_FAILED 13 + XSERR_BASE
-#define XSERR_POLICY_LOADED 14 + XSERR_BASE
-#define XSERR_POLICY_TYPE_UNSUPPORTED 15 + XSERR_BASE
-#define XSERR_BAD_CONFLICTSET 20 + XSERR_BASE
-#define XSERR_RESOURCE_IN_USE 21 + XSERR_BASE
-#define XSERR_BAD_POLICY_NAME 22 + XSERR_BASE
-#define XSERR_RESOURCE_ACCESS 23 + XSERR_BASE
-#define XSERR_HV_OP_FAILED 24 + XSERR_BASE
-#define XSERR_BOOTPOLICY_INSTALL_ERROR 25 + XSERR_BASE
-#define XSERR_VM_NOT_AUTHORIZED 26 + XSERR_BASE
-#define XSERR_VM_IN_CONFLICT 27 + XSERR_BASE
-
-
-/**
- * Free the given xen_xspolicy. The given handle must have been allocated
- * by this library.
- */
-extern void
-xen_xspolicy_free(xen_xspolicy xspolicy);
-
-
-typedef struct xen_xspolicy_set
-{
- size_t size;
- xen_xspolicy *contents[];
-} xen_xspolicy_set;
-
-/**
- * Allocate a xen_xspolicy_set of the given size.
- */
-extern xen_xspolicy_set *
-xen_xspolicy_set_alloc(size_t size);
-
-/**
- * Free the given xen_xspolicy_set. The given set must have been allocated
- * by this library.
- */
-extern void
-xen_xspolicy_set_free(xen_xspolicy_set *set);
-
-
-typedef struct xen_xspolicy_record
-{
- xen_xspolicy handle;
- char *uuid;
- char *repr;
- xs_instantiationflags flags;
- xs_type type;
-} xen_xspolicy_record;
-
-/**
- * Allocate a xen_xspolicy_record.
- */
-extern xen_xspolicy_record *
-xen_xspolicy_record_alloc(void);
-
-/**
- * Free the given xen_xspolicy_record, and all referenced values. The
- * given record must have been allocated by this library.
- */
-extern void
-xen_xspolicy_record_free(xen_xspolicy_record *record);
-
-
-typedef struct xen_xspolicy_record_opt
-{
- bool is_record;
- union
- {
- xen_xspolicy handle;
- xen_xspolicy_record *record;
- } u;
-} xen_xspolicy_record_opt;
-
-/**
- * Allocate a xen_xspolicy_record_opt.
- */
-extern xen_xspolicy_record_opt *
-xen_xspolicy_record_opt_alloc(void);
-
-/**
- * Free the given xen_xspolicy_record_opt, and all referenced values. The
- * given record_opt must have been allocated by this library.
- */
-extern void
-xen_xspolicy_record_opt_free(xen_xspolicy_record_opt *record_opt);
-
-
-typedef struct xen_xspolicy_record_set
-{
- size_t size;
- xen_xspolicy_record *contents[];
-} xen_xspolicy_record_set;
-
-/**
- * Allocate a xen_xspolicy_record_set of the given size.
- */
-extern xen_xspolicy_record_set *
-xen_xspolicy_record_set_alloc(size_t size);
-
-/**
- * Free the given xen_xspolicy_record_set, and all referenced values. The
- * given set must have been allocated by this library.
- */
-extern void
-xen_xspolicy_record_set_free(xen_xspolicy_record_set *set);
-
-/**
- * Data structures and function declarations for an XS Policy's state
- * information.
- */
-typedef struct xen_xs_policystate
-{
- xen_xspolicy_record_opt *xs_ref;
- int64_t xserr;
- char *repr;
- xs_type type;
- xs_instantiationflags flags;
- char *version;
- char *errors;
-} xen_xs_policystate;
-
-extern void
-xen_xs_policystate_free(xen_xs_policystate *state);
-
-
-/**
- * Get the referenced policy's record.
- */
-extern bool
-xen_xspolicy_get_record(xen_session *session, xen_xspolicy_record **result,
- xen_xspolicy xspolicy);
-
-/**
- * Get the UUID field of the given policy.
- */
-extern bool
-xen_xspolicy_get_uuid(xen_session *session, char **result,
- xen_xspolicy xspolicy);
-
-/**
- * Get a policy given it's UUID
- */
-extern bool
-xen_xspolicy_get_by_uuid(xen_session *session, xen_xspolicy *result,
- char *uuid);
-
-
-/**
- * Get the types of policies supported by the system.
- */
-extern bool
-xen_xspolicy_get_xstype(xen_session *session, xs_type *result);
-
-
-/**
- * Get information about the currently managed policy.
- * (The API allows only one policy to be on the system.)
- */
-extern bool
-xen_xspolicy_get_xspolicy(xen_session *session, xen_xs_policystate **result);
-
-/**
- * Activate the referenced policy by loading it into the hypervisor.
- */
-extern bool
-xen_xspolicy_activate_xspolicy(xen_session *session, int64_t *result,
- xen_xspolicy xspolicy,
- xs_instantiationflags flags);
-
-
-/**
- * Set the system's policy to the given information comprising
- * type of policy, the xml representation of the policy, some flags
- * on whether to load the policy immediately and whether to overwrite
- * an existing policy on the system.
- */
-extern bool
-xen_xspolicy_set_xspolicy(xen_session *session, xen_xs_policystate **result,
- xs_type type, char *repr, int64_t flags,
- bool overwrite);
-
-
-
-/**
- * Attempt to reset the system's policy to the DEFAULT policy for the
- * respective policy type. This is done by updating the system and therefore
- * underlies the same restrictions of a policy update. This operation may
- * for example fail if other domains than Domain-0 are running and have
- * different labels than Domain-0.
- */
-extern bool
-xen_xspolicy_reset_xspolicy(xen_session *session, xen_xs_policystate **result,
- xs_type type);
-
-
-/**
- * Remove any policy from having the system booted with.
- */
-extern bool
-xen_xspolicy_rm_xsbootpolicy(xen_session *session);
-
-/**
- * Retrieve all labeled resources.
- */
-extern bool
-xen_xspolicy_get_labeled_resources(xen_session *session,
- xen_string_string_map **resources);
-
-/**
- * Label a resource such as for example a hard drive partition or file
- */
-extern bool
-xen_xspolicy_set_resource_label(xen_session *session,
- char *resource, char *label,
- char *oldlabel);
-
-/**
- * Get the label of a resource.
- */
-extern bool
-xen_xspolicy_get_resource_label(xen_session *session, char **label,
- char *resource);
-
-/**
- * Check whether a VM with the given VM-label could run.
- */
-extern bool
-xen_xspolicy_can_run(xen_session *session, int64_t *result,
- char *security_label);
-
-#endif
diff --git a/tools/libxen/include/xen/api/xen_xspolicy_decl.h b/tools/libxen/include/xen/api/xen_xspolicy_decl.h
deleted file mode 100644
index 08e7252..0000000
--- a/tools/libxen/include/xen/api/xen_xspolicy_decl.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2007, IBM Corp.
- * Copyright (c) 2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_XSPOLICY_DECL_H
-#define XEN_XSPOLICY_DECL_H
-
-typedef void *xen_xspolicy;
-
-struct xen_xspolicy_set;
-struct xen_xspolicy_record;
-struct xen_xspolicy_record_set;
-struct xen_xspolicy_record_opt;
-struct xen_xspolicy_record_opt_set;
-
-#endif
diff --git a/tools/libxen/include/xen_console_protocol_internal.h b/tools/libxen/include/xen_console_protocol_internal.h
deleted file mode 100644
index d2ddaa0..0000000
--- a/tools/libxen/include/xen_console_protocol_internal.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/*
- * Declarations of the abstract types used during demarshalling of enum
- * xen_console_protocol. Internal to this library -- do not use from outside.
- */
-
-
-#ifndef XEN_CONSOLE_PROTOCOL_INTERNAL_H
-#define XEN_CONSOLE_PROTOCOL_INTERNAL_H
-
-
-#include "xen_internal.h"
-
-
-extern const abstract_type xen_console_protocol_abstract_type_;
-extern const abstract_type xen_console_protocol_set_abstract_type_;
-
-
-#endif
diff --git a/tools/libxen/include/xen_event_operation_internal.h b/tools/libxen/include/xen_event_operation_internal.h
deleted file mode 100644
index 3c4f70c..0000000
--- a/tools/libxen/include/xen_event_operation_internal.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/*
- * Declarations of the abstract types used during demarshalling of enum
- * xen_event_operation. Internal to this library -- do not use from outside.
- */
-
-
-#ifndef XEN_EVENT_OPERATION_INTERNAL_H
-#define XEN_EVENT_OPERATION_INTERNAL_H
-
-
-#include "xen_internal.h"
-
-
-extern const abstract_type xen_event_operation_abstract_type_;
-extern const abstract_type xen_event_operation_set_abstract_type_;
-
-
-#endif
diff --git a/tools/libxen/include/xen_internal.h b/tools/libxen/include/xen_internal.h
deleted file mode 100644
index 21f75de..0000000
--- a/tools/libxen/include/xen_internal.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2006-2007 XenSource, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_INTERNAL_H
-#define XEN_INTERNAL_H
-
-
-#include <inttypes.h>
-#include <stdbool.h>
-#include <stdlib.h>
-
-#include <xen/api/xen_common.h>
-
-
-enum abstract_typename
-{
- VOID,
- STRING,
- INT,
- FLOAT,
- BOOL,
- DATETIME,
- SET,
- MAP,
- STRUCT,
- REF,
- ENUM,
- ENUMSET
-};
-
-
-typedef struct
-{
- size_t size;
- void *contents[];
-} arbitrary_set;
-
-
-typedef struct struct_member struct_member;
-
-
-typedef struct abstract_type
-{
- enum abstract_typename typename;
- const struct abstract_type *child;
- const char * (*enum_marshaller)(int);
- int (*enum_demarshaller)(xen_session *, const char *);
- size_t struct_size;
- size_t member_count;
- const struct_member *members;
-} abstract_type;
-
-
-struct struct_member
-{
- const char *key;
- const struct abstract_type *type;
- int offset;
-};
-
-
-extern const abstract_type abstract_type_string;
-extern const abstract_type abstract_type_int;
-extern const abstract_type abstract_type_float;
-extern const abstract_type abstract_type_bool;
-extern const abstract_type abstract_type_datetime;
-extern const abstract_type abstract_type_ref;
-
-extern const abstract_type abstract_type_string_set;
-extern const abstract_type abstract_type_ref_set;
-
-extern const abstract_type abstract_type_string_string_map;
-extern const abstract_type abstract_type_int_float_map;
-extern const abstract_type abstract_type_int_int_map;
-extern const abstract_type abstract_type_int_string_set_map;
-
-
-typedef struct abstract_value
-{
- const abstract_type *type;
- union
- {
- const char *string_val;
- int64_t int_val;
- int enum_val;
- double float_val;
- bool bool_val;
- arbitrary_set *set_val;
- void *struct_val;
- time_t datetime_val;
- } u;
-} abstract_value;
-
-
-extern void
-xen_call_(xen_session *s, const char *method_name, abstract_value params[],
- int param_count, const abstract_type *result_type, void *value);
-
-
-#define XEN_CALL_(method_name__) \
- xen_call_(session, method_name__, param_values, \
- sizeof(param_values) / sizeof(param_values[0]), \
- &result_type, result) \
-
-
-extern char *
-xen_strdup_(const char *in);
-
-
-extern int
-xen_enum_lookup_(xen_session *session, const char *str,
- const char **lookup_table, int n);
-
-#define ENUM_LOOKUP(session__, str__, lookup_table__) \
- xen_enum_lookup_(session__, str__, lookup_table__, \
- sizeof(lookup_table__) / \
- sizeof(lookup_table__[0])) \
-
-#define XEN_ALLOC(type__) \
-type__ * \
-type__ ## _alloc() \
-{ \
- return calloc(1, sizeof(type__)); \
-} \
-
-
-#define XEN_FREE(type__) \
-void \
-type__ ## _free(type__ handle) \
-{ \
- free(handle); \
-} \
-
-
-#define XEN_SET_ALLOC_FREE(type__) \
- XEN_SET_ALLOC(type__) \
- XEN_SET_FREE(type__)
-
-
-#define XEN_SET_ALLOC(type__) \
-type__ ## _set * \
-type__ ## _set_alloc(size_t size) \
-{ \
- type__ ## _set *result = calloc(1, sizeof(type__ ## _set) + \
- size * sizeof(type__)); \
- result->size = size; \
- return result; \
-}
-
-
-#define XEN_SET_FREE(type__) \
-void type__ ## _set_free(type__ ## _set *set) \
-{ \
- if (set == NULL) \
- return; \
- for (size_t i = 0; i < set->size; i++) \
- type__ ## _free(set->contents[i]); \
- free(set); \
-}
-
-
-#define XEN_RECORD_OPT_FREE(type__) \
-void type__ ## _record_opt_free(type__ ## _record_opt *opt) { \
- if (opt == NULL) return; \
- if (opt->is_record) \
- type__ ## _record_free(opt->u.record); \
- else \
- type__ ## _free(opt->u.handle); \
- free(opt); \
-}
-
-
-#endif
diff --git a/tools/libxen/include/xen_on_crash_behaviour_internal.h b/tools/libxen/include/xen_on_crash_behaviour_internal.h
deleted file mode 100644
index bd6f1fa..0000000
--- a/tools/libxen/include/xen_on_crash_behaviour_internal.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/*
- * Declarations of the abstract types used during demarshalling of enum
- * xen_on_crash_behaviour. Internal to this library -- do not use from
- * outside.
- */
-
-
-#ifndef XEN_ON_CRASH_BEHAVIOUR_INTERNAL_H
-#define XEN_ON_CRASH_BEHAVIOUR_INTERNAL_H
-
-
-#include "xen_internal.h"
-
-
-extern const abstract_type xen_on_crash_behaviour_abstract_type_;
-extern const abstract_type xen_on_crash_behaviour_set_abstract_type_;
-
-
-#endif
diff --git a/tools/libxen/include/xen_on_normal_exit_internal.h b/tools/libxen/include/xen_on_normal_exit_internal.h
deleted file mode 100644
index ffff46a..0000000
--- a/tools/libxen/include/xen_on_normal_exit_internal.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/*
- * Declarations of the abstract types used during demarshalling of enum
- * xen_on_normal_exit. Internal to this library -- do not use from outside.
- */
-
-
-#ifndef XEN_ON_NORMAL_EXIT_INTERNAL_H
-#define XEN_ON_NORMAL_EXIT_INTERNAL_H
-
-
-#include "xen_internal.h"
-
-
-extern const abstract_type xen_on_normal_exit_abstract_type_;
-extern const abstract_type xen_on_normal_exit_set_abstract_type_;
-
-
-#endif
diff --git a/tools/libxen/include/xen_vbd_mode_internal.h b/tools/libxen/include/xen_vbd_mode_internal.h
deleted file mode 100644
index 4f05681..0000000
--- a/tools/libxen/include/xen_vbd_mode_internal.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/*
- * Declarations of the abstract types used during demarshalling of enum
- * xen_vbd_mode. Internal to this library -- do not use from outside.
- */
-
-
-#ifndef XEN_VBD_MODE_INTERNAL_H
-#define XEN_VBD_MODE_INTERNAL_H
-
-
-#include "xen_internal.h"
-
-
-extern const abstract_type xen_vbd_mode_abstract_type_;
-extern const abstract_type xen_vbd_mode_set_abstract_type_;
-
-
-#endif
diff --git a/tools/libxen/include/xen_vbd_type_internal.h b/tools/libxen/include/xen_vbd_type_internal.h
deleted file mode 100644
index 5f027cf..0000000
--- a/tools/libxen/include/xen_vbd_type_internal.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/*
- * Declarations of the abstract types used during demarshalling of enum
- * xen_vbd_type. Internal to this library -- do not use from outside.
- */
-
-
-#ifndef XEN_VBD_TYPE_INTERNAL_H
-#define XEN_VBD_TYPE_INTERNAL_H
-
-
-#include "xen_internal.h"
-
-
-extern const abstract_type xen_vbd_type_abstract_type_;
-extern const abstract_type xen_vbd_type_set_abstract_type_;
-
-
-#endif
diff --git a/tools/libxen/include/xen_vdi_type_internal.h b/tools/libxen/include/xen_vdi_type_internal.h
deleted file mode 100644
index 9c575ff..0000000
--- a/tools/libxen/include/xen_vdi_type_internal.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/*
- * Declarations of the abstract types used during demarshalling of enum
- * xen_vdi_type. Internal to this library -- do not use from outside.
- */
-
-
-#ifndef XEN_VDI_TYPE_INTERNAL_H
-#define XEN_VDI_TYPE_INTERNAL_H
-
-
-#include "xen_internal.h"
-
-
-extern const abstract_type xen_vdi_type_abstract_type_;
-extern const abstract_type xen_vdi_type_set_abstract_type_;
-
-
-#endif
diff --git a/tools/libxen/include/xen_vm_power_state_internal.h b/tools/libxen/include/xen_vm_power_state_internal.h
deleted file mode 100644
index a3f5af1..0000000
--- a/tools/libxen/include/xen_vm_power_state_internal.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/*
- * Declarations of the abstract types used during demarshalling of enum
- * xen_vm_power_state. Internal to this library -- do not use from outside.
- */
-
-
-#ifndef XEN_VM_POWER_STATE_INTERNAL_H
-#define XEN_VM_POWER_STATE_INTERNAL_H
-
-
-#include "xen_internal.h"
-
-
-extern const abstract_type xen_vm_power_state_abstract_type_;
-extern const abstract_type xen_vm_power_state_set_abstract_type_;
-
-
-#endif
diff --git a/tools/libxen/src/xen_common.c b/tools/libxen/src/xen_common.c
deleted file mode 100644
index f9da712..0000000
--- a/tools/libxen/src/xen_common.c
+++ /dev/null
@@ -1,1784 +0,0 @@
-/*
- * Copyright (c) 2006-2007 XenSource, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define _XOPEN_SOURCE
-#include <assert.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xmlsave.h>
-#include <libxml/xmlstring.h>
-#include <libxml/xpath.h>
-
-#include "xen/api/xen_common.h"
-#include "xen/api/xen_host.h"
-#include "xen_internal.h"
-#include "xen/api/xen_int_float_map.h"
-#include "xen/api/xen_int_int_map.h"
-#include "xen/api/xen_int_string_set_map.h"
-#include "xen/api/xen_string_string_map.h"
-
-
-/*
- * Whether to ignore missing structure entries. This is not something we
- * want to do, once the API has stabilised, as it indicates that the server is
- * broken, but at the moment, complaining is just slowing development down.
- */
-#define PERMISSIVE 1
-
-
-static xmlXPathCompExprPtr responsePath = NULL;
-static xmlXPathCompExprPtr faultPath = NULL;
-
-
-typedef struct
-{
- size_t size;
- void *contents[];
-} arbitrary_map;
-
-
-typedef struct
-{
- void *handle;
-} arbitrary_record;
-
-
-typedef struct
-{
- bool is_record;
- union
- {
- char *handle;
- arbitrary_record *record;
- } u;
-} arbitrary_record_opt;
-
-
-static char *
-make_body(const char *, abstract_value [], int);
-
-static void
-parse_result(xen_session *, const char *, const abstract_type *, void *);
-
-static void
-add_value(xmlNode *, const char *, const char *);
-static void
-add_param(xmlNode *, const char *, const char *);
-
-static xmlNode *
-add_param_struct(xmlNode *);
-static xmlNode *
-add_param_array(xmlNode *);
-static xmlNode *
-add_struct_array(xmlNode *, const char *);
-static xmlNode *
-add_nested_struct(xmlNode *, const char *);
-static void
-add_struct_member(xmlNode *, const char *, const char *, const char *);
-static void
-add_unnamed_value(xmlNode *, const char *, const char *, const char *);
-
-static void
-add_struct_value(const struct abstract_type *, void *,
- void (*)(xmlNode *, const char *, const char *,
- const char *),
- const char *, xmlNode *);
-
-static xmlNode *
-add_container(xmlNode *parent, const char *name);
-
-static void
-call_raw(xen_session *, const char *, abstract_value [], int,
- const abstract_type *, void *);
-
-static void
-parse_structmap_value(xen_session *, xmlNode *, const abstract_type *,
- void *);
-
-static size_t size_of_member(const abstract_type *);
-
-static const char *
-get_val_as_string(const struct abstract_type *, void *, char *, size_t);
-
-
-void
-xen_init(void)
-{
- responsePath =
- xmlXPathCompile(
- BAD_CAST(
- "/methodResponse/params/param/value/struct/member/value"));
- faultPath =
- xmlXPathCompile(
- BAD_CAST("/methodResponse/fault/value/struct/member/value"));
-}
-
-
-void
-xen_fini(void)
-{
- xmlXPathFreeCompExpr(responsePath);
- xmlXPathFreeCompExpr(faultPath);
- responsePath = NULL;
- faultPath = NULL;
-}
-
-
-void
-xen_session_record_free(xen_session_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->uuid);
- xen_host_record_opt_free(record->this_host);
- free(record->this_user);
- free(record);
-}
-
-
-xen_session *
-xen_session_login_with_password(xen_call_func call_func, void *handle,
- const char *uname, const char *pwd)
-{
- abstract_value params[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uname },
- { .type = &abstract_type_string,
- .u.string_val = pwd }
- };
-
- xen_session *session = malloc(sizeof(xen_session));
- session->call_func = call_func;
- session->handle = handle;
- session->session_id = NULL;
- session->ok = true;
- session->error_description = NULL;
- session->error_description_count = 0;
-
- call_raw(session, "session.login_with_password", params, 2,
- &abstract_type_string, &session->session_id);
-
- return session;
-}
-
-
-void
-xen_session_logout(xen_session *session)
-{
- abstract_value params[] =
- {
- };
- xen_call_(session, "session.logout", params, 0, NULL, NULL);
-
- if (session->error_description != NULL)
- {
- for (int i = 0; i < session->error_description_count; i++)
- {
- free(session->error_description[i]);
- }
- free(session->error_description);
- }
-
- free((char *)session->session_id);
- free(session);
-}
-
-
-void
-xen_session_clear_error(xen_session *session)
-{
- if (session->error_description != NULL)
- {
- for (int i = 0; i < session->error_description_count; i++)
- {
- free(session->error_description[i]);
- }
- free(session->error_description);
- }
- session->error_description = NULL;
- session->error_description_count = 0;
- session->ok = true;
-}
-
-
-bool
-xen_session_get_uuid(xen_session *session, char **result,
- xen_session *self_session)
-{
- abstract_value params[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = self_session->session_id }
- };
-
- xen_call_(session, "session.get_uuid", params, 1,
- &abstract_type_string, result);
- return session->ok;
-}
-
-
-bool
-xen_session_get_this_host(xen_session *session, xen_host *result,
- xen_session *self_session)
-{
- abstract_value params[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = self_session->session_id }
- };
-
- xen_call_(session, "session.get_this_host", params, 1,
- &abstract_type_string, result);
- return session->ok;
-}
-
-
-bool
-xen_session_get_this_user(xen_session *session, char **result,
- xen_session *self_session)
-{
- abstract_value params[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = self_session->session_id }
- };
-
- xen_call_(session, "session.get_this_user", params, 1,
- &abstract_type_string, result);
- return session->ok;
-}
-
-
-bool
-xen_session_get_last_active(xen_session *session, time_t *result,
- xen_session *self_session)
-{
- abstract_value params[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = self_session->session_id }
- };
-
- xen_call_(session, "session.get_last_active", params, 1,
- &abstract_type_datetime, result);
- return session->ok;
-}
-
-
-static const struct_member xen_session_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_session_record, uuid) },
- { .key = "this_host",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_session_record, this_host) },
- { .key = "this_user",
- .type = &abstract_type_string,
- .offset = offsetof(xen_session_record, this_user) },
- { .key = "last_active",
- .type = &abstract_type_datetime,
- .offset = offsetof(xen_session_record, last_active) },
- };
-
-const abstract_type xen_session_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_session_record),
- .member_count =
- sizeof(xen_session_record_struct_members) / sizeof(struct_member),
- .members = xen_session_record_struct_members
- };
-
-
-bool
-xen_session_get_record(xen_session *session, xen_session_record **result,
- xen_session *self_session)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = self_session->session_id }
- };
-
- abstract_type result_type = xen_session_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("session.get_record");
-
- return session->ok;
-}
-
-
-#define X "%02x"
-#define UUID_FORMAT X X X X "-" X X "-" X X "-" X X "-" X X X X X X
-
-
-bool
-xen_uuid_string_to_bytes(char *uuid, char **bytes)
-{
- unsigned int buf[16];
-
- *bytes = NULL;
-
- if (strlen(uuid) != 36)
- return false;
-
- if (16 != sscanf(uuid, UUID_FORMAT,
- buf + 0, buf + 1, buf + 2, buf + 3,
- buf + 4, buf + 5,
- buf + 6, buf + 7,
- buf + 8, buf + 9,
- buf + 10, buf + 11, buf + 12, buf + 13, buf + 14,
- buf + 15))
- {
- return false;
- }
-
- *bytes = malloc(16);
- if (*bytes == NULL)
- return false;
-
- for (int i = 0; i < 16; i++) {
- (*bytes)[i] = (char)buf[i];
- }
-
- return true;
-}
-
-
-bool
-xen_uuid_bytes_to_string(char *bytes, char **uuid)
-{
- *uuid = malloc(37);
- if (*uuid == NULL)
- return false;
-
- sprintf(*uuid, UUID_FORMAT,
- bytes[0], bytes[1], bytes[2], bytes[3],
- bytes[4], bytes[5],
- bytes[6], bytes[7],
- bytes[8], bytes[9],
- bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]);
-
- return true;
-}
-
-
-#undef UUID_FORMAT
-#undef X
-
-
-void
-xen_uuid_free(char *uuid)
-{
- free(uuid);
-}
-
-
-void
-xen_uuid_bytes_free(char *bytes)
-{
- free(bytes);
-}
-
-
-/**
- * @param value A pointer to the correct location as per the given
- * result_type. Will be populated if the call succeeds. In that case, and if
- * value is a char **, the char * itself must be freed by the caller.
- */
-void
-xen_call_(xen_session *s, const char *method_name,
- abstract_value params[], int param_count,
- const abstract_type *result_type, void *value)
-{
- abstract_value *full_params;
- if (!s->ok)
- {
- return;
- }
-
- full_params = malloc(sizeof(abstract_value) * (param_count + 1));
-
- full_params[0].type = &abstract_type_string;
- full_params[0].u.string_val = s->session_id;
-
- memcpy(full_params + 1, params, param_count * sizeof(abstract_value));
-
- call_raw(s, method_name, full_params, param_count + 1, result_type,
- value);
-
- free(full_params);
-}
-
-
-static bool
-bufferAdd(const void *data, size_t len, void *buffer)
-{
- return 0 == xmlBufferAdd((xmlBufferPtr)buffer, data, len);
-}
-
-
-static void
-call_raw(xen_session *s, const char *method_name,
- abstract_value params[], int param_count,
- const abstract_type *result_type, void *value)
-{
- xmlBufferPtr buffer = xmlBufferCreate();
- char *body = make_body(method_name, params, param_count);
- int error_code =
- s->call_func(body, strlen(body), s->handle, buffer, &bufferAdd);
- free(body);
- if (error_code)
- {
- char **strings = malloc(2 * sizeof(char *));
-
- strings[0] = xen_strdup_("TRANSPORT_FAULT");
- strings[1] = malloc(20);
- snprintf(strings[1], 20, "%d", error_code);
-
- s->ok = false;
- s->error_description = strings;
- s->error_description_count = 2;
- }
- else
- {
- parse_result(s, (char *)xmlBufferContent(buffer), result_type, value);
- }
- xmlBufferFree(buffer);
-}
-
-
-static void server_error(xen_session *session, const char *error_string)
-{
- char **strings;
- if (!session->ok)
- {
- /* Don't wipe out the earlier error message with this one. */
- return;
- }
-
- strings = malloc(2 * sizeof(char *));
-
- strings[0] = xen_strdup_("SERVER_FAULT");
- strings[1] = xen_strdup_(error_string);
-
- session->ok = false;
- session->error_description = strings;
- session->error_description_count = 2;
-}
-
-
-static void server_error_2(xen_session *session, const char *error_string,
- const char *param)
-{
- char **strings;
- if (!session->ok)
- {
- /* Don't wipe out the earlier error message with this one. */
- return;
- }
-
- strings = malloc(3 * sizeof(char *));
-
- strings[0] = xen_strdup_("SERVER_FAULT_2");
- strings[1] = xen_strdup_(error_string);
- strings[2] = xen_strdup_(param);
-
- session->ok = false;
- session->error_description = strings;
- session->error_description_count = 3;
-}
-
-
-static bool is_node(xmlNode *n, char *type)
-{
- return
- n->type == XML_ELEMENT_NODE &&
- 0 == strcmp((char *)n->name, type);
-}
-
-
-static bool is_container_node(xmlNode *n, char *type)
-{
- return
- is_node(n, type) &&
- n->children != NULL &&
- n->children == n->last &&
- n->children->type == XML_ELEMENT_NODE;
-}
-
-
-/**
- * @return The contents of the given value, or NULL if this is not a node with
- * the given type. If not NULL, the result must be freed with xmlFree().
- */
-static xmlChar *string_from_value(xmlNode *n, char *type)
-{
- /*
- <value><type>XYZ</type></value> is normal, but the XML-RPC spec also
- allows <value>XYZ</value> where XYZ is to be interpreted as a string.
- */
-
- if (is_container_node(n, "value") &&
- 0 == strcmp((char *)n->children->name, type))
- {
- return
- n->children->children == NULL ?
- xmlStrdup(BAD_CAST("")) :
- xmlNodeGetContent(n->children->children);
- }
- else if (0 == strcmp(type, "string") && is_node(n, "value"))
- {
- return
- n->children == NULL ?
- xmlStrdup(BAD_CAST("")) :
- xmlNodeGetContent(n->children);
- }
- else
- {
- return NULL;
- }
-}
-
-
-/**
- * Find the name node that is a child of the given one, and return its
- * contents, or NULL if this has no such node. If not NULL, the result must
- * be freed with xmlFree().
- */
-static xmlChar *string_from_name(xmlNode *n)
-{
- xmlNode *cur = n->children;
-
- while (cur != NULL)
- {
- if (0 == strcmp((char *)cur->name, "name"))
- {
- return xmlNodeGetContent(cur);
- }
- cur = cur->next;
- }
-
- return NULL;
-}
-
-
-static int count_children(xmlNode *n, const char *name)
-{
- int result = 0;
- xmlNode *cur = n->children;
-
- while (cur != NULL)
- {
- if (0 == strcmp((char *)cur->name, name))
- {
- result++;
- }
- cur = cur->next;
- }
-
- return result;
-}
-
-
-static void destring(xen_session *s, xmlChar *name, const abstract_type *type,
- void *value)
-{
- switch (type->typename)
- {
- case STRING:
- *((char **)value) = xen_strdup_((const char *)name);
- break;
-
- case INT:
- *((int64_t *)value) = atoll((const char *)name);
- break;
-
- case FLOAT:
- *((double *)value) = atof((const char *)name);
- break;
-
- default:
- server_error(s, "Invalid Map key type");
- }
-}
-
-
-/**
- * result_type : STRING => value : char **, the char * is yours.
- * result_type : ENUM => value : int *
- * result_type : INT => value : int64_t *
- * result_type : FLOAT => value : double *
- * result_type : BOOL => value : bool *
- * result_type : DATETIME => value : time_t *
- * result_type : SET => value : arbitrary_set **, the set is yours.
- * result_type : MAP => value : arbitrary_map **, the map is yours.
- * result_type : OPT => value : arbitrary_record_opt **,
- * the record is yours, the handle is
- * filled.
- * result_type : STRUCT => value : void **, the void * is yours.
- */
-static void parse_into(xen_session *s, xmlNode *value_node,
- const abstract_type *result_type, void *value,
- int slot)
-{
- if (result_type == NULL)
- {
- xmlChar *string = string_from_value(value_node, "string");
- if (string == NULL || strcmp((char *)string, ""))
- {
- server_error(s,
- "Expected Void from the server, but didn't get it");
- }
- else
- {
- free(string);
- }
-
- return;
- }
-
- switch (result_type->typename)
- {
- case STRING:
- {
- xmlChar *string = string_from_value(value_node, "string");
- if (string == NULL)
- {
- server_error(
- s, "Expected a String from the server, but didn't get one");
- }
- else
- {
- ((char **)value)[slot] = xen_strdup_((const char *)string);
- free(string);
- }
- }
- break;
-
- case ENUM:
- {
- xmlChar *string = string_from_value(value_node, "string");
- if (string == NULL)
- {
-#if PERMISSIVE
- fprintf(stderr,
- "Expected an Enum from the server, but didn't get one\n");
- ((int *)value)[slot] = 0;
-#else
- server_error(
- s, "Expected an Enum from the server, but didn't get one");
-#endif
- }
- else
- {
- ((int *)value)[slot] =
- result_type->enum_demarshaller(s, (const char *)string);
- free(string);
- }
- }
- break;
-
- case INT:
- {
- xmlChar *string = string_from_value(value_node, "string");
- if (string == NULL)
- {
- server_error(
- s, "Expected an Int from the server, but didn't get one");
- }
- else
- {
- ((int64_t *)value)[slot] = (int64_t)atoll((char *)string);
- free(string);
- }
- }
- break;
-
- case FLOAT:
- {
- xmlChar *string = string_from_value(value_node, "double");
- if (string == NULL)
- {
-#if PERMISSIVE
- fprintf(stderr,
- "Expected a Float from the server, but didn't get one\n");
- ((double *)value)[slot] = 0.0;
-#else
- server_error(
- s, "Expected a Float from the server, but didn't get one");
-#endif
- }
- else
- {
- ((double *)value)[slot] = atof((char *)string);
- free(string);
- }
- }
- break;
-
- case BOOL:
- {
- xmlChar *string = string_from_value(value_node, "boolean");
- if (string == NULL)
- {
-#if PERMISSIVE
- fprintf(stderr,
- "Expected a Bool from the server, but didn't get one\n");
- ((bool *)value)[slot] = false;
-#else
- server_error(
- s, "Expected a Bool from the server, but didn't get one");
-#endif
- }
- else
- {
- ((bool *)value)[slot] = (0 == strcmp((char *)string, "1"));
- free(string);
- }
- }
- break;
-
- case DATETIME:
- {
- xmlChar *string = string_from_value(value_node, "dateTime.iso8601");
- if (string == NULL)
- {
- server_error(
- s, "Expected an DateTime from the server but didn't get one");
- }
- else
- {
- struct tm tm;
- memset(&tm, 0, sizeof(tm));
- strptime((char *)string, "%Y%m%dT%H:%M:%S", &tm);
- ((time_t *)value)[slot] = (time_t)mktime(&tm);
- free(string);
- }
- }
- break;
-
- case SET:
- {
- if (!is_container_node(value_node, "value") ||
- !is_container_node(value_node->children, "array"))
- {
- server_error(s,
- "Expected Set from the server, but didn't get it");
- }
- else
- {
- arbitrary_set *set;
- xmlNode *cur, *data_node = value_node->children->children;
- int i, n = count_children(data_node, "value");
-
- const abstract_type *member_type = result_type->child;
- size_t member_size = size_of_member(member_type);
-
- set = calloc(1, sizeof(arbitrary_set) + member_size * n);
- set->size = n;
- i = 0;
- cur = data_node->children;
-
- while (cur != NULL)
- {
- if (0 == strcmp((char *)cur->name, "value"))
- {
- parse_into(s, cur, member_type, set->contents, i);
- i++;
- }
- cur = cur->next;
- }
-
- ((arbitrary_set **)value)[slot] = set;
- }
- }
- break;
-
- case MAP:
- {
- if (!is_container_node(value_node, "value") ||
- value_node->children->type != XML_ELEMENT_NODE ||
- 0 != strcmp((char *)value_node->children->name, "struct"))
- {
- server_error(s,
- "Expected Map from the server, but didn't get it");
- }
- else
- {
- arbitrary_map *map;
- xmlNode *cur, *struct_node = value_node->children;
- int i, n = count_children(struct_node, "member");
-
- size_t struct_size = result_type->struct_size;
-
- const struct struct_member *key_member = result_type->members;
- const struct struct_member *val_member = result_type->members + 1;
-
- map = calloc(1, sizeof(arbitrary_map) + struct_size * n);
- map->size = n;
- i = 0;
- cur = struct_node->children;
-
- while (cur != NULL)
- {
- if (0 == strcmp((char *)cur->name, "member"))
- {
- xmlChar *name;
- if (cur->children == NULL || cur->last == cur->children)
- {
- server_error(s, "Malformed Map");
- free(map);
- return;
- }
-
- name = string_from_name(cur);
- if (name == NULL)
- {
- server_error(s, "Malformed Map");
- free(map);
- return;
- }
-
- destring(s, name, key_member->type,
- ((void *)(map + 1)) +
- (i * struct_size) +
- key_member->offset);
- xmlFree(name);
- if (!s->ok)
- {
- free(map);
- return;
- }
-
- parse_structmap_value(s, cur, val_member->type,
- ((void *)(map + 1)) +
- (i * struct_size) +
- val_member->offset);
- if (!s->ok)
- {
- free(map);
- return;
- }
- i++;
- }
- cur = cur->next;
- }
-
- ((arbitrary_map **)value)[slot] = map;
- }
- }
- break;
-
- case STRUCT:
- {
- if (!is_container_node(value_node, "value") ||
- value_node->children->type != XML_ELEMENT_NODE ||
- 0 != strcmp((char *)value_node->children->name, "struct") ||
- value_node->children->children == NULL)
- {
- server_error(s,
- "Expected Map from the server, but didn't get it");
- }
- else
- {
- xmlNode *struct_node = value_node->children;
-
- void *result = calloc(1, result_type->struct_size);
- xmlNode *cur = struct_node->children;
-
- size_t member_count = result_type->member_count;
-
- const struct_member **checklist =
- malloc(sizeof(const struct_member *) * member_count);
- int seen_count = 0;
-
- while (cur != NULL)
- {
- if (0 == strcmp((char *)cur->name, "member"))
- {
- xmlChar *name;
- if (cur->children == NULL || cur->last == cur->children)
- {
- server_error(s, "Malformed Struct");
- free(result);
- free(checklist);
- return;
- }
-
- name = string_from_name(cur);
- if (name == NULL)
- {
- server_error(s, "Malformed Struct");
- free(result);
- free(checklist);
- return;
- }
-
- for (size_t i = 0; i < member_count; i++)
- {
- const struct_member *mem = result_type->members + i;
-
- if (0 == strcmp((char *)name, mem->key))
- {
- parse_structmap_value(s, cur, mem->type,
- result + mem->offset);
- checklist[seen_count] = mem;
- seen_count++;
- break;
- }
- }
-
- /* Note that we're skipping unknown fields implicitly.
- This means that we'll be forward compatible with
- new servers. */
-
- xmlFree(name);
-
- if (!s->ok)
- {
- free(result);
- free(checklist);
- return;
- }
- }
- cur = cur->next;
- }
-
- /* Check that we've filled all fields. */
- for (size_t i = 0; i < member_count; i++)
- {
- const struct_member *mem = result_type->members + i;
- int j;
-
- for (j = 0; j < seen_count; j++)
- {
- if (checklist[j] == mem)
- {
- break;
- }
- }
-
- if (j == seen_count)
- {
-#if PERMISSIVE
- fprintf(stderr,
- "Struct did not contain expected field %s.\n",
- mem->key);
-#else
- server_error_2(s,
- "Struct did not contain expected field",
- mem->key);
- free(result);
- free(checklist);
- return;
-#endif
- }
- }
-
- free(checklist);
- ((void **)value)[slot] = result;
- }
- }
- break;
-
- case REF:
- {
- arbitrary_record_opt *record_opt =
- calloc(1, sizeof(arbitrary_record_opt));
-
- record_opt->is_record = false;
- parse_into(s, value_node, &abstract_type_string,
- &(record_opt->u.handle), 0);
-
- ((arbitrary_record_opt **)value)[slot] = record_opt;
- }
- break;
-
- default:
- assert(false);
- }
-}
-
-
-static size_t size_of_member(const abstract_type *type)
-{
- switch (type->typename)
- {
- case STRING:
- return sizeof(char *);
-
-/*
- case INT:
- return sizeof(int64_t);
-
- case FLOAT:
- return sizeof(double);
-
- case BOOL:
- return sizeof(bool);
-*/
- case ENUM:
- return sizeof(int);
-
- case REF:
- return sizeof(arbitrary_record_opt *);
-
- case STRUCT:
- return type->struct_size;
-
- default:
- assert(false);
- }
-}
-
-
-static void parse_structmap_value(xen_session *s, xmlNode *n,
- const abstract_type *type, void *value)
-{
- xmlNode *cur = n->children;
-
- while (cur != NULL)
- {
- if (0 == strcmp((char *)cur->name, "value"))
- {
- parse_into(s, cur, type, value, 0);
- return;
- }
- cur = cur->next;
- }
-
- server_error(s, "Missing value in Map/Struct");
-}
-
-
-static void parse_fault(xen_session *session, xmlXPathContextPtr xpathCtx)
-{
- xmlNode *fault_node0, *fault_node1;
- xmlChar *fault_code_str, *fault_string_str;
- char **strings;
-
- xmlXPathObjectPtr xpathObj = xmlXPathCompiledEval(faultPath, xpathCtx);
- if (xpathObj == NULL)
- {
- server_error(session, "Method response is neither result nor fault");
- return;
- }
-
- if (xpathObj->type != XPATH_NODESET ||
- xpathObj->nodesetval->nodeNr != 2)
- {
- xmlXPathFreeObject(xpathObj);
- server_error(session, "Method response is neither result nor fault");
- return;
- }
-
- fault_node0 = xpathObj->nodesetval->nodeTab[0];
- fault_node1 = xpathObj->nodesetval->nodeTab[1];
-
- fault_code_str = string_from_value(fault_node0, "int");
- if (fault_code_str == NULL)
- {
- fault_code_str = string_from_value(fault_node0, "i4");
- }
- if (fault_code_str == NULL)
- {
- xmlXPathFreeObject(xpathObj);
- server_error(session, "Fault code is malformed");
- return;
- }
-
- fault_string_str = string_from_value(fault_node1, "string");
- if (fault_string_str == NULL)
- {
- xmlFree(fault_code_str);
- xmlXPathFreeObject(xpathObj);
- server_error(session, "Fault string is malformed");
- return;
- }
-
- strings = malloc(3 * sizeof(char *));
-
- strings[0] = xen_strdup_("FAULT");
- strings[1] = xen_strdup_((char *)fault_code_str);
- strings[2] = xen_strdup_((char *)fault_string_str);
-
- session->ok = false;
- session->error_description = strings;
- session->error_description_count = 3;
-
- xmlFree(fault_code_str);
- xmlFree(fault_string_str);
- xmlXPathFreeObject(xpathObj);
-}
-
-
-static void parse_failure(xen_session *session, xmlNode *node)
-{
- abstract_type error_description_type =
- { .typename = SET,
- .child = &abstract_type_string };
- arbitrary_set *error_descriptions;
-
- parse_into(session, node, &error_description_type, &error_descriptions,
- 0);
-
- if (session->ok)
- {
- char **c, **strings;
- int n;
-
- session->ok = false;
-
- c = (char **)error_descriptions->contents;
- n = error_descriptions->size;
-
- strings = malloc(n * sizeof(char *));
- for (int i = 0; i < n; i++)
- {
- strings[i] = c[i];
- }
-
- session->error_description_count = n;
- session->error_description = strings;
- }
-
- free(error_descriptions);
-}
-
-
-/**
- * Parameters as for xen_call_() above.
- */
-static void parse_result(xen_session *session, const char *result,
- const abstract_type *result_type, void *value)
-{
- xmlDocPtr doc =
- xmlReadMemory(result, strlen(result), "", NULL, XML_PARSE_NONET);
- xmlXPathContextPtr xpathCtx;
- xmlXPathObjectPtr xpathObj;
- xmlNode *node0, *node1;
- xmlChar *status_code;
-
- if (doc == NULL)
- {
- server_error(session, "Couldn't parse the server response");
- return;
- }
-
- xpathCtx = xmlXPathNewContext(doc);
- if (xpathCtx == NULL)
- {
- xmlFreeDoc(doc);
- server_error(session, "Couldn't create XPath context");
- return;
- }
-
- xpathObj = xmlXPathCompiledEval(responsePath, xpathCtx);
- if (xpathObj == NULL)
- {
- parse_fault(session, xpathCtx);
-
- xmlXPathFreeContext(xpathCtx);
- xmlFreeDoc(doc);
- return;
- }
-
- if (xpathObj->type != XPATH_NODESET ||
- xpathObj->nodesetval->nodeNr != 2)
- {
- parse_fault(session, xpathCtx);
-
- xmlXPathFreeObject(xpathObj);
- xmlXPathFreeContext(xpathCtx);
- xmlFreeDoc(doc);
- return;
- }
-
- node0 = xpathObj->nodesetval->nodeTab[0];
- node1 = xpathObj->nodesetval->nodeTab[1];
-
- status_code = string_from_value(node0, "string");
- if (status_code == NULL)
- {
- xmlXPathFreeObject(xpathObj);
- xmlXPathFreeContext(xpathCtx);
- xmlFreeDoc(doc);
- server_error(session, "Server response does not have a Status");
- return;
- }
-
- if (strcmp((char *)status_code, "Success"))
- {
- parse_failure(session, node1);
-
- xmlFree(status_code);
- xmlXPathFreeObject(xpathObj);
- xmlXPathFreeContext(xpathCtx);
- xmlFreeDoc(doc);
- return;
- }
-
- parse_into(session, node1, result_type, value, 0);
-
- xmlFree(status_code);
- xmlXPathFreeObject(xpathObj);
- xmlXPathFreeContext(xpathCtx);
- xmlFreeDoc(doc);
-}
-
-
-static void
-make_body_add_type(enum abstract_typename typename, abstract_value *v,
- xmlNode *params_node)
-{
- char buf[20];
- switch (typename)
- {
- case STRING:
- add_param(params_node, "string", v->u.string_val);
- break;
-
- case INT:
- snprintf(buf, sizeof(buf), "%"PRId64, v->u.int_val);
- add_param(params_node, "string", buf);
- break;
-
- case FLOAT:
- snprintf(buf, sizeof(buf), "%lf", v->u.float_val);
- add_param(params_node, "double", buf);
- break;
-
- case BOOL:
- add_param(params_node, "boolean", v->u.bool_val ? "1" : "0");
- break;
-
- case VOID:
- add_param(params_node, "string", "");
- break;
-
- case ENUM:
- add_param(params_node, "string",
- v->type->enum_marshaller(v->u.enum_val));
- break;
-
- case SET:
- {
- const struct abstract_type *member_type = v->type->child;
- arbitrary_set *set_val = v->u.struct_val;
- abstract_value v;
- xmlNode *data_node = add_param_array(params_node);
-
- for (size_t i = 0; i < set_val->size; i++)
- {
- switch (member_type->typename) {
- case STRING:
- v.u.string_val = (char *)set_val->contents[i];
- make_body_add_type(member_type->typename, &v, data_node);
- break;
- default:
- assert(false);
- }
- }
- }
- break;
-
- case STRUCT:
- {
- size_t member_count = v->type->member_count;
-
- xmlNode *struct_node = add_param_struct(params_node);
-
- for (size_t i = 0; i < member_count; i++)
- {
- const struct struct_member *mem = v->type->members + i;
- const char *key = mem->key;
- void *struct_value = v->u.struct_val;
-
- add_struct_value(mem->type, struct_value + mem->offset,
- add_struct_member, key, struct_node);
- }
- }
- break;
-
- case MAP:
- {
- const struct struct_member *member = v->type->members;
- arbitrary_map *map_val = v->u.struct_val;
- xmlNode *param_node = add_param_struct(params_node);
- for (size_t i = 0; i < map_val->size; i++) {
- enum abstract_typename typename_key = member[0].type->typename;
- enum abstract_typename typename_val = member[1].type->typename;
- int offset_key = member[0].offset;
- int offset_val = member[1].offset;
- int struct_size = v->type->struct_size;
-
- switch (typename_key) {
- case STRING: {
- char **addr = (void *)(map_val + 1) +
- (i * struct_size) +
- offset_key;
- char *key = *addr;
-
- switch (typename_val) {
- case STRING: {
- char *val;
- addr = (void *)(map_val + 1) +
- (i * struct_size) +
- offset_val;
- val = *addr;
- add_struct_member(param_node, key, "string", val);
- break;
- }
- default:
- assert(false);
- }
- break;
- }
- default:
- assert(false);
- }
- }
- }
- break;
-
-
- default:
- assert(false);
- }
-}
-
-
-static char *
-make_body(const char *method_name, abstract_value params[], int param_count)
-{
- xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
- xmlNode *params_node, *methodCall = xmlNewNode(NULL, BAD_CAST "methodCall");
- xmlBufferPtr buffer;
- xmlSaveCtxtPtr save_ctxt;
- xmlChar *content;
-
- xmlDocSetRootElement(doc, methodCall);
-
- xmlNewChild(methodCall, NULL, BAD_CAST "methodName",
- BAD_CAST method_name);
-
- params_node = xmlNewChild(methodCall, NULL, BAD_CAST "params", NULL);
-
- for (int p = 0; p < param_count; p++)
- {
- abstract_value *v = params + p;
- make_body_add_type(v->type->typename, v, params_node);
- }
-
- buffer = xmlBufferCreate();
- save_ctxt = xmlSaveToBuffer(buffer, NULL, XML_SAVE_NO_XHTML);
-
- if (xmlSaveDoc(save_ctxt, doc) == -1)
- {
- return NULL;
- }
-
- xmlFreeDoc(doc);
- xmlSaveClose(save_ctxt);
- content = xmlStrdup(xmlBufferContent(buffer));
- xmlBufferFree(buffer);
- return (char *)content;
-}
-
-
-static void
-add_struct_value(const struct abstract_type *type, void *value,
- void (*adder)(xmlNode *node, const char *key,
- const char *type, const char *val),
- const char *key, xmlNode *node)
-{
- char buf[20];
-
- switch (type->typename)
- {
- case REF:
- case STRING:
- case INT:
- case ENUM:
- {
- const char *val_as_string =
- get_val_as_string(type, value, buf, sizeof(buf));
- adder(node, key, "string", val_as_string);
- }
- break;
-
- case FLOAT:
- {
- double val = *(double *)value;
- snprintf(buf, sizeof(buf), "%lf", val);
- adder(node, key, "double", buf);
- }
- break;
-
- case BOOL:
- {
- bool val = *(bool *)value;
- adder(node, key, "boolean", val ? "1" : "0");
- }
- break;
-
- case SET:
- {
- const struct abstract_type *member_type = type->child;
- size_t member_size = size_of_member(member_type);
- arbitrary_set *set_val = *(arbitrary_set **)value;
-
- if (set_val != NULL)
- {
- xmlNode *data_node = add_struct_array(node, key);
-
- for (size_t i = 0; i < set_val->size; i++)
- {
- void *member_value = (char *)set_val->contents +
- (i * member_size);
- add_struct_value(member_type, member_value,
- add_unnamed_value, NULL, data_node);
- }
- }
- }
- break;
-
- case STRUCT:
- {
- assert(false);
- /* XXX Nested structures aren't supported yet, but
- fortunately we don't need them, because we don't have
- any "deep create" calls. This will need to be
- fixed. */
- }
- break;
-
- case MAP:
- {
- size_t member_size = type->struct_size;
- const struct abstract_type *l_type = type->members[0].type;
- const struct abstract_type *r_type = type->members[1].type;
- int l_offset = type->members[0].offset;
- int r_offset = type->members[1].offset;
-
- arbitrary_map *map_val = *(arbitrary_map **)value;
-
- if (map_val != NULL)
- {
- xmlNode *struct_node = add_nested_struct(node, key);
-
- for (size_t i = 0; i < map_val->size; i++)
- {
- void *contents = (void *)map_val->contents;
- void *l_value = contents + (i * member_size) + l_offset;
- void *r_value = contents + (i * member_size) + r_offset;
-
- const char *l_value_as_string =
- get_val_as_string(l_type, l_value, buf, sizeof(buf));
-
- add_struct_value(r_type, r_value, add_struct_member,
- l_value_as_string, struct_node);
- }
- }
- }
- break;
-
- default:
- assert(false);
- }
-}
-
-
-static const char *
-get_val_as_string(const struct abstract_type *type, void *value, char *buf,
- size_t bufsize)
-{
- switch (type->typename)
- {
- case REF:
- {
- arbitrary_record_opt *val = *(arbitrary_record_opt **)value;
- if (val != NULL)
- {
- if (val->is_record)
- {
- return val->u.record->handle;
- }
- else
- {
- return val->u.handle;
- }
- }
- else
- {
- return NULL;
- }
- }
- break;
-
- case STRING:
- {
- return *(char **)value;
- }
- break;
-
- case INT:
- {
- int64_t val = *(int64_t *)value;
- snprintf(buf, bufsize, "%"PRId64, val);
- return buf;
- }
- break;
-
- case ENUM:
- {
- int val = *(int *)value;
- return type->enum_marshaller(val);
- }
- break;
-
- default:
- assert(false);
- }
-}
-
-
-static xmlNode *
-add_container(xmlNode *parent, const char *name)
-{
- return xmlNewChild(parent, NULL, BAD_CAST name, NULL);
-}
-
-
-static void
-add_param(xmlNode *params_node, const char *type, const char *value)
-{
- xmlNode *param_node = add_container(params_node, "param");
- add_value(param_node, type, value);
-}
-
-
-static void
-add_value(xmlNode *parent, const char *type, const char *value)
-{
- xmlNode *value_node = add_container(parent, "value");
- xmlNewChild(value_node, NULL, BAD_CAST type, BAD_CAST value);
-}
-
-
-static void
-add_unnamed_value(xmlNode *parent, const char *name, const char *type,
- const char *value)
-{
- (void)name;
- add_value(parent, type, value);
-}
-
-
-static xmlNode *
-add_param_struct(xmlNode *params_node)
-{
- xmlNode *param_node = add_container(params_node, "param");
- xmlNode *value_node = add_container(param_node, "value");
-
- return xmlNewChild(value_node, NULL, BAD_CAST "struct", NULL);
-}
-
-
-static xmlNode *
-add_param_array(xmlNode *params_node)
-{
- xmlNode *param_node = add_container(params_node, "param");
- xmlNode *value_node = add_container(param_node, "value");
-
- return xmlNewChild(value_node, NULL, BAD_CAST "array", NULL);
-}
-
-
-static void
-add_struct_member(xmlNode *struct_node, const char *name, const char *type,
- const char *value)
-{
- xmlNode *member_node = add_container(struct_node, "member");
-
- xmlNewChild(member_node, NULL, BAD_CAST "name", BAD_CAST name);
-
- add_value(member_node, type, value);
-}
-
-
-static xmlNode *
-add_struct_array(xmlNode *struct_node, const char *name)
-{
- xmlNode *member_node = add_container(struct_node, "member");
- xmlNode *value_node, *array_node;
-
- xmlNewChild(member_node, NULL, BAD_CAST "name", BAD_CAST name);
-
- value_node = add_container(member_node, "value");
- array_node = add_container(value_node, "array");
-
- return add_container(array_node, "data");
-}
-
-
-static xmlNode *
-add_nested_struct(xmlNode *struct_node, const char *name)
-{
- xmlNode *member_node = add_container(struct_node, "member");
- xmlNode *value_node;
-
- xmlNewChild(member_node, NULL, BAD_CAST "name", BAD_CAST name);
-
- value_node = add_container(member_node, "value");
-
- return add_container(value_node, "struct");
-}
-
-
-int xen_enum_lookup_(xen_session *session, const char *str,
- const char **lookup_table, int n)
-{
- if (str != NULL)
- {
- for (int i = 0; i < n; i++)
- {
- if (0 == strcmp(str, lookup_table[i]))
- {
- return i;
- }
- }
- }
-
- server_error_2(session, "Bad enum string", str);
- return 0;
-}
-
-
-char *
-xen_strdup_(const char *in)
-{
- char *result = malloc(strlen(in) + 1);
- strcpy(result, in);
- return result;
-}
-
-
-const abstract_type abstract_type_string = { .typename = STRING };
-const abstract_type abstract_type_int = { .typename = INT };
-const abstract_type abstract_type_float = { .typename = FLOAT };
-const abstract_type abstract_type_bool = { .typename = BOOL };
-const abstract_type abstract_type_datetime = { .typename = DATETIME };
-const abstract_type abstract_type_ref = { .typename = REF };
-
-const abstract_type abstract_type_string_set =
- {
- .typename = SET,
- .child = &abstract_type_string
- };
-
-const abstract_type abstract_type_ref_set =
- {
- .typename = SET,
- .child = &abstract_type_ref
- };
-
-static const struct struct_member string_string_members[] =
-{
- {
- .type = &abstract_type_string,
- .offset = offsetof(xen_string_string_map_contents, key)
- },
- {
- .type = &abstract_type_string,
- .offset = offsetof(xen_string_string_map_contents, val)
- }
-};
-const abstract_type abstract_type_string_string_map =
- {
- .typename = MAP,
- .struct_size = sizeof(xen_string_string_map_contents),
- .members = string_string_members
- };
-
-static struct struct_member int_float_members[] =
-{
- {
- .type = &abstract_type_int,
- .offset = offsetof(xen_int_float_map_contents, key)
- },
- {
- .type = &abstract_type_float,
- .offset = offsetof(xen_int_float_map_contents, val)
- }
-};
-const abstract_type abstract_type_int_float_map =
- {
- .typename = MAP,
- .struct_size = sizeof(xen_int_float_map_contents),
- .members = int_float_members
- };
-
-static struct struct_member int_int_members[] =
-{
- {
- .type = &abstract_type_int,
- .offset = offsetof(xen_int_int_map_contents, key)
- },
- {
- .type = &abstract_type_int,
- .offset = offsetof(xen_int_int_map_contents, val)
- }
-};
-const abstract_type abstract_type_int_int_map =
- {
- .typename = MAP,
- .struct_size = sizeof(xen_int_int_map_contents),
- .members = int_int_members
- };
-
-static struct struct_member int_string_set_members[] =
-{
- {
- .type = &abstract_type_int,
- .offset = offsetof(xen_int_string_set_map_contents, key)
- },
- {
- .type = &abstract_type_string_set,
- .offset = offsetof(xen_int_string_set_map_contents, val)
- }
-};
-const abstract_type abstract_type_int_string_set_map =
- {
- .typename = MAP,
- .struct_size = sizeof(xen_int_string_set_map_contents),
- .members = int_string_set_members
- };
diff --git a/tools/libxen/src/xen_console.c b/tools/libxen/src/xen_console.c
deleted file mode 100644
index 2b45498..0000000
--- a/tools/libxen/src/xen_console.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_console_protocol_internal.h"
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_console.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vm.h>
-
-
-XEN_FREE(xen_console)
-XEN_SET_ALLOC_FREE(xen_console)
-XEN_ALLOC(xen_console_record)
-XEN_SET_ALLOC_FREE(xen_console_record)
-XEN_ALLOC(xen_console_record_opt)
-XEN_RECORD_OPT_FREE(xen_console)
-XEN_SET_ALLOC_FREE(xen_console_record_opt)
-
-
-static const struct_member xen_console_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_console_record, uuid) },
- { .key = "protocol",
- .type = &xen_console_protocol_abstract_type_,
- .offset = offsetof(xen_console_record, protocol) },
- { .key = "location",
- .type = &abstract_type_string,
- .offset = offsetof(xen_console_record, location) },
- { .key = "VM",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_console_record, vm) },
- { .key = "other_config",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_console_record, other_config) }
- };
-
-const abstract_type xen_console_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_console_record),
- .member_count =
- sizeof(xen_console_record_struct_members) / sizeof(struct_member),
- .members = xen_console_record_struct_members
- };
-
-
-void
-xen_console_record_free(xen_console_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record->location);
- xen_vm_record_opt_free(record->vm);
- xen_string_string_map_free(record->other_config);
- free(record);
-}
-
-
-bool
-xen_console_get_record(xen_session *session, xen_console_record **result, xen_console console)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = console }
- };
-
- abstract_type result_type = xen_console_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("console.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_console_get_by_uuid(xen_session *session, xen_console *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("console.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_console_create(xen_session *session, xen_console *result, xen_console_record *record)
-{
- abstract_value param_values[] =
- {
- { .type = &xen_console_record_abstract_type_,
- .u.struct_val = record }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("console.create");
- return session->ok;
-}
-
-
-bool
-xen_console_destroy(xen_session *session, xen_console console)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = console }
- };
-
- xen_call_(session, "console.destroy", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_console_get_protocol(xen_session *session, enum xen_console_protocol *result, xen_console console)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = console }
- };
-
- abstract_type result_type = xen_console_protocol_abstract_type_;
- XEN_CALL_("console.get_protocol");
- return session->ok;
-}
-
-
-bool
-xen_console_get_location(xen_session *session, char **result, xen_console console)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = console }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("console.get_location");
- return session->ok;
-}
-
-
-bool
-xen_console_get_vm(xen_session *session, xen_vm *result, xen_console console)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = console }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("console.get_VM");
- return session->ok;
-}
-
-
-bool
-xen_console_get_other_config(xen_session *session, xen_string_string_map **result, xen_console console)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = console }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("console.get_other_config");
- return session->ok;
-}
-
-
-bool
-xen_console_set_other_config(xen_session *session, xen_console console, xen_string_string_map *other_config)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = console },
- { .type = &abstract_type_string_string_map,
- .u.set_val = (arbitrary_set *)other_config }
- };
-
- xen_call_(session, "console.set_other_config", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_console_add_to_other_config(xen_session *session, xen_console console, char *key, char *value)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = console },
- { .type = &abstract_type_string,
- .u.string_val = key },
- { .type = &abstract_type_string,
- .u.string_val = value }
- };
-
- xen_call_(session, "console.add_to_other_config", param_values, 3, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_console_remove_from_other_config(xen_session *session, xen_console console, char *key)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = console },
- { .type = &abstract_type_string,
- .u.string_val = key }
- };
-
- xen_call_(session, "console.remove_from_other_config", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_console_get_all(xen_session *session, struct xen_console_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "console.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_console_get_uuid(xen_session *session, char **result, xen_console console)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = console }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("console.get_uuid");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_console_protocol.c b/tools/libxen/src/xen_console_protocol.c
deleted file mode 100644
index 031d64d..0000000
--- a/tools/libxen/src/xen_console_protocol.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_console_protocol.h>
-#include "xen_console_protocol_internal.h"
-
-
-/*
- * Maintain this in the same order as the enum declaration!
- */
-static const char *lookup_table[] =
-{
- "vt100",
- "rfb",
- "rdp"
-};
-
-
-extern xen_console_protocol_set *
-xen_console_protocol_set_alloc(size_t size)
-{
- return calloc(1, sizeof(xen_console_protocol_set) +
- size * sizeof(enum xen_console_protocol));
-}
-
-
-extern void
-xen_console_protocol_set_free(xen_console_protocol_set *set)
-{
- free(set);
-}
-
-
-const char *
-xen_console_protocol_to_string(enum xen_console_protocol val)
-{
- return lookup_table[val];
-}
-
-
-extern enum xen_console_protocol
-xen_console_protocol_from_string(xen_session *session, const char *str)
-{
- return ENUM_LOOKUP(session, str, lookup_table);
-}
-
-
-const abstract_type xen_console_protocol_abstract_type_ =
- {
- .typename = ENUM,
- .enum_marshaller =
- (const char *(*)(int))&xen_console_protocol_to_string,
- .enum_demarshaller =
- (int (*)(xen_session *, const char *))&xen_console_protocol_from_string
- };
-
-
-const abstract_type xen_console_protocol_set_abstract_type_ =
- {
- .typename = SET,
- .child = &xen_console_protocol_abstract_type_
- };
-
-
diff --git a/tools/libxen/src/xen_cpu_pool.c b/tools/libxen/src/xen_cpu_pool.c
deleted file mode 100644
index 5186da8..0000000
--- a/tools/libxen/src/xen_cpu_pool.c
+++ /dev/null
@@ -1,671 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_cpu_pool.h>
-#include <xen/api/xen_host_cpu.h>
-
-XEN_FREE(xen_cpu_pool)
-XEN_SET_ALLOC_FREE(xen_cpu_pool)
-XEN_ALLOC(xen_cpu_pool_record)
-XEN_SET_ALLOC_FREE(xen_cpu_pool_record)
-XEN_ALLOC(xen_cpu_pool_record_opt)
-XEN_RECORD_OPT_FREE(xen_cpu_pool)
-XEN_SET_ALLOC_FREE(xen_cpu_pool_record_opt)
-
-
-static const struct_member xen_cpu_pool_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_cpu_pool_record, uuid) },
- { .key = "name_label",
- .type = &abstract_type_string,
- .offset = offsetof(xen_cpu_pool_record, name_label) },
- { .key = "name_description",
- .type = &abstract_type_string,
- .offset = offsetof(xen_cpu_pool_record, name_description) },
- { .key = "resident_on",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_cpu_pool_record, resident_on) },
- { .key = "auto_power_on",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_cpu_pool_record, auto_power_on) },
- { .key = "started_VMs",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_cpu_pool_record, started_vms) },
- { .key = "ncpu",
- .type = &abstract_type_int,
- .offset = offsetof(xen_cpu_pool_record, ncpu) },
- { .key = "sched_policy",
- .type = &abstract_type_string,
- .offset = offsetof(xen_cpu_pool_record, sched_policy) },
- { .key = "proposed_CPUs",
- .type = &abstract_type_string_set,
- .offset = offsetof(xen_cpu_pool_record, proposed_cpus) },
- { .key = "host_CPUs",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_cpu_pool_record, host_cpus) },
- { .key = "activated",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_cpu_pool_record, activated) },
- { .key = "other_config",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_cpu_pool_record, other_config) },
- };
-
-
-const abstract_type xen_cpu_pool_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_cpu_pool_record),
- .member_count =
- sizeof(xen_cpu_pool_record_struct_members) / sizeof(struct_member),
- .members = xen_cpu_pool_record_struct_members
- };
-
-
-void
-xen_cpu_pool_record_free(xen_cpu_pool_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record->name_label);
- free(record->name_description);
- xen_host_record_opt_free(record->resident_on);
- xen_vm_record_opt_set_free(record->started_vms);
- free(record->sched_policy);
- xen_string_set_free(record->proposed_cpus);
- xen_host_cpu_record_opt_set_free(record->host_cpus);
- xen_string_string_map_free(record->other_config);
- free(record);
-}
-
-
-bool
-xen_cpu_pool_get_record(xen_session *session, xen_cpu_pool_record **result,
- xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool }
- };
-
- abstract_type result_type = xen_cpu_pool_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("cpu_pool.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_get_by_uuid(xen_session *session, xen_cpu_pool *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("cpu_pool.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_create(xen_session *session, xen_cpu_pool *result,
- xen_cpu_pool_record *record)
-{
- abstract_value param_values[] =
- {
- { .type = &xen_cpu_pool_record_abstract_type_,
- .u.struct_val = record }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("cpu_pool.create");
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_destroy(xen_session *session, xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool }
- };
-
- xen_call_(session, "cpu_pool.destroy", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_get_uuid(xen_session *session, char **result, xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("cpu_pool.get_uuid");
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_deactivate(xen_session *session, xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool },
- };
-
- xen_call_(session, "cpu_pool.deactivate", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_activate(xen_session *session, xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool },
- };
-
- xen_call_(session, "cpu_pool.activate", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_add_host_CPU_live(xen_session *session, xen_cpu_pool cpu_pool,
- xen_host_cpu host_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool },
- { .type = &abstract_type_string,
- .u.string_val = host_cpu },
- };
-
- xen_call_(session, "cpu_pool.add_host_CPU_live", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_remove_host_CPU_live(xen_session *session, xen_cpu_pool cpu_pool,
- xen_host_cpu host_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool },
- { .type = &abstract_type_string,
- .u.string_val = host_cpu },
- };
-
- xen_call_(session, "cpu_pool.remove_host_CPU_live", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_get_all(xen_session *session, struct xen_cpu_pool_set **result)
-{
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "cpu_pool.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_get_by_name_label(xen_session *session,
- struct xen_cpu_pool_set **result, char *label)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = label }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("cpu_pool.get_by_name_label");
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_get_activated(xen_session *session, bool *result,
- xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("cpu_pool.get_activated");
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_get_auto_power_on(xen_session *session, bool *result,
- xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("cpu_pool.get_auto_power_on");
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_get_host_CPUs(xen_session *session, struct xen_host_cpu_set **result,
- xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("cpu_pool.get_host_CPUs");
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_get_name_description(xen_session *session, char **result,
- xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("cpu_pool.get_name_description");
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_get_name_label(xen_session *session, char **result,
- xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("cpu_pool.get_name_label");
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_get_ncpu(xen_session *session, int64_t *result,
- xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("cpu_pool.get_ncpu");
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_get_proposed_CPUs(xen_session *session, struct xen_string_set **result,
- xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("cpu_pool.get_proposed_CPUs");
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_get_other_config(xen_session *session, xen_string_string_map **result,
- xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("cpu_pool.get_other_config");
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_get_resident_on(xen_session *session, xen_host *result,
- xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("cpu_pool.get_resident_on");
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_get_sched_policy(xen_session *session, char **result,
- xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("cpu_pool.get_sched_policy");
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_get_started_VMs(xen_session *session, xen_vm_set **result,
- xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("cpu_pool.get_started_VMs");
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_set_auto_power_on(xen_session *session, xen_cpu_pool cpu_pool,
- bool auto_power_on)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool },
- { .type = &abstract_type_bool,
- .u.bool_val = auto_power_on }
- };
-
- xen_call_(session, "cpu_pool.set_auto_power_on", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_set_proposed_CPUs(xen_session *session, xen_cpu_pool cpu_pool,
- xen_string_set *proposed_cpus)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool },
- { .type = &abstract_type_string_set,
- .u.set_val = (arbitrary_set *)proposed_cpus }
- };
-
- xen_call_(session, "cpu_pool.set_proposed_CPUs", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_add_to_proposed_CPUs(xen_session *session, xen_cpu_pool cpu_pool,
- char* proposed_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool },
- { .type = &abstract_type_string,
- .u.string_val = proposed_cpu }
- };
-
- xen_call_(session, "cpu_pool.add_to_proposed_CPUs", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_remove_from_proposed_CPUs(xen_session *session, xen_cpu_pool cpu_pool,
- char* proposed_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool },
- { .type = &abstract_type_string,
- .u.string_val = proposed_cpu }
- };
-
- xen_call_(session, "cpu_pool.remove_from_proposed_CPUs", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_set_name_label(xen_session *session, xen_cpu_pool cpu_pool,
- char *label)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool },
- { .type = &abstract_type_string,
- .u.string_val = label }
- };
-
- xen_call_(session, "cpu_pool.set_name_label", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_set_name_description(xen_session *session, xen_cpu_pool cpu_pool,
- char *descr)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool },
- { .type = &abstract_type_string,
- .u.string_val = descr }
- };
-
- xen_call_(session, "cpu_pool.set_name_description", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_set_ncpu(xen_session *session, xen_cpu_pool cpu_pool, int64_t ncpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool },
- { .type = &abstract_type_int,
- .u.int_val = ncpu }
- };
-
- xen_call_(session, "cpu_pool.set_ncpu", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_set_other_config(xen_session *session, xen_cpu_pool cpu_pool,
- xen_string_string_map *other_config)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool },
- { .type = &abstract_type_string_string_map,
- .u.set_val = (arbitrary_set *)other_config }
- };
-
- xen_call_(session, "cpu_pool.set_other_config", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_add_to_other_config(xen_session *session, xen_cpu_pool cpu_pool,
- char *key, char *value)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool },
- { .type = &abstract_type_string,
- .u.string_val = key },
- { .type = &abstract_type_string,
- .u.string_val = value }
- };
-
- xen_call_(session, "cpu_pool.add_to_other_config", param_values, 3, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_remove_from_other_config(xen_session *session, xen_cpu_pool cpu_pool,
- char *key)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool },
- { .type = &abstract_type_string,
- .u.string_val = key }
- };
-
- xen_call_(session, "cpu_pool.remove_from_other_config", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_cpu_pool_set_sched_policy(xen_session *session, xen_cpu_pool cpu_pool,
- char *sched_policy)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool },
- { .type = &abstract_type_string,
- .u.string_val = sched_policy }
- };
-
- xen_call_(session, "cpu_pool.set_sched_policy", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
diff --git a/tools/libxen/src/xen_crashdump.c b/tools/libxen/src/xen_crashdump.c
deleted file mode 100644
index ba2121b..0000000
--- a/tools/libxen/src/xen_crashdump.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_crashdump.h>
-#include <xen/api/xen_vdi.h>
-#include <xen/api/xen_vm.h>
-
-
-XEN_FREE(xen_crashdump)
-XEN_SET_ALLOC_FREE(xen_crashdump)
-XEN_ALLOC(xen_crashdump_record)
-XEN_SET_ALLOC_FREE(xen_crashdump_record)
-XEN_ALLOC(xen_crashdump_record_opt)
-XEN_RECORD_OPT_FREE(xen_crashdump)
-XEN_SET_ALLOC_FREE(xen_crashdump_record_opt)
-
-
-static const struct_member xen_crashdump_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_crashdump_record, uuid) },
- { .key = "VM",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_crashdump_record, vm) },
- { .key = "VDI",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_crashdump_record, vdi) }
- };
-
-const abstract_type xen_crashdump_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_crashdump_record),
- .member_count =
- sizeof(xen_crashdump_record_struct_members) / sizeof(struct_member),
- .members = xen_crashdump_record_struct_members
- };
-
-
-void
-xen_crashdump_record_free(xen_crashdump_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- xen_vm_record_opt_free(record->vm);
- xen_vdi_record_opt_free(record->vdi);
- free(record);
-}
-
-
-bool
-xen_crashdump_get_record(xen_session *session, xen_crashdump_record **result, xen_crashdump crashdump)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = crashdump }
- };
-
- abstract_type result_type = xen_crashdump_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("crashdump.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_crashdump_get_by_uuid(xen_session *session, xen_crashdump *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("crashdump.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_crashdump_get_vm(xen_session *session, xen_vm *result, xen_crashdump crashdump)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = crashdump }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("crashdump.get_VM");
- return session->ok;
-}
-
-
-bool
-xen_crashdump_get_vdi(xen_session *session, xen_vdi *result, xen_crashdump crashdump)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = crashdump }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("crashdump.get_VDI");
- return session->ok;
-}
-
-
-bool
-xen_crashdump_destroy(xen_session *session, xen_crashdump self)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = self }
- };
-
- xen_call_(session, "crashdump.destroy", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_crashdump_get_all(xen_session *session, struct xen_crashdump_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "crashdump.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_crashdump_get_uuid(xen_session *session, char **result, xen_crashdump crashdump)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = crashdump }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("crashdump.get_uuid");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_event.c b/tools/libxen/src/xen_event.c
deleted file mode 100644
index 30e8d60..0000000
--- a/tools/libxen/src/xen_event.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_event_operation_internal.h"
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_event.h>
-
-
-XEN_ALLOC(xen_event_record)
-XEN_SET_ALLOC_FREE(xen_event_record)
-
-
-static const struct_member xen_event_record_struct_members[] =
- {
- { .key = "id",
- .type = &abstract_type_int,
- .offset = offsetof(xen_event_record, id) },
- { .key = "timestamp",
- .type = &abstract_type_datetime,
- .offset = offsetof(xen_event_record, timestamp) },
- { .key = "class",
- .type = &abstract_type_string,
- .offset = offsetof(xen_event_record, class) },
- { .key = "operation",
- .type = &xen_event_operation_abstract_type_,
- .offset = offsetof(xen_event_record, operation) },
- { .key = "ref",
- .type = &abstract_type_string,
- .offset = offsetof(xen_event_record, ref) },
- { .key = "obj_uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_event_record, obj_uuid) }
- };
-
-const abstract_type xen_event_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_event_record),
- .member_count =
- sizeof(xen_event_record_struct_members) / sizeof(struct_member),
- .members = xen_event_record_struct_members
- };
-
-
-const abstract_type xen_event_record_set_abstract_type_ =
- {
- .typename = SET,
- .child = &xen_event_record_abstract_type_
- };
-
-
-void
-xen_event_record_free(xen_event_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->class);
- free(record->ref);
- free(record->obj_uuid);
- free(record);
-}
-
-
-bool
-xen_event_register(xen_session *session, struct xen_string_set *classes)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string_set,
- .u.set_val = (arbitrary_set *)classes }
- };
-
- xen_call_(session, "event.register", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_event_unregister(xen_session *session, struct xen_string_set *classes)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string_set,
- .u.set_val = (arbitrary_set *)classes }
- };
-
- xen_call_(session, "event.unregister", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_event_next(xen_session *session, struct xen_event_record_set **result)
-{
-
- abstract_type result_type = xen_event_record_set_abstract_type_;
-
- *result = NULL;
- xen_call_(session, "event.next", NULL, 0, &result_type, result);
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_event_operation.c b/tools/libxen/src/xen_event_operation.c
deleted file mode 100644
index 48a7c36..0000000
--- a/tools/libxen/src/xen_event_operation.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_event_operation.h>
-#include "xen_event_operation_internal.h"
-
-
-/*
- * Maintain this in the same order as the enum declaration!
- */
-static const char *lookup_table[] =
-{
- "add",
- "del",
- "mod"
-};
-
-
-extern xen_event_operation_set *
-xen_event_operation_set_alloc(size_t size)
-{
- return calloc(1, sizeof(xen_event_operation_set) +
- size * sizeof(enum xen_event_operation));
-}
-
-
-extern void
-xen_event_operation_set_free(xen_event_operation_set *set)
-{
- free(set);
-}
-
-
-const char *
-xen_event_operation_to_string(enum xen_event_operation val)
-{
- return lookup_table[val];
-}
-
-
-extern enum xen_event_operation
-xen_event_operation_from_string(xen_session *session, const char *str)
-{
- return ENUM_LOOKUP(session, str, lookup_table);
-}
-
-
-const abstract_type xen_event_operation_abstract_type_ =
- {
- .typename = ENUM,
- .enum_marshaller =
- (const char *(*)(int))&xen_event_operation_to_string,
- .enum_demarshaller =
- (int (*)(xen_session *, const char *))&xen_event_operation_from_string
- };
-
-
diff --git a/tools/libxen/src/xen_host.c b/tools/libxen/src/xen_host.c
deleted file mode 100644
index b456f5d..0000000
--- a/tools/libxen/src/xen_host.c
+++ /dev/null
@@ -1,915 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_host.h>
-#include <xen/api/xen_host_cpu.h>
-#include <xen/api/xen_host_metrics.h>
-#include <xen/api/xen_pbd.h>
-#include <xen/api/xen_pif.h>
-#include <xen/api/xen_sr.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vm.h>
-#include <xen/api/xen_cpu_pool.h>
-
-
-XEN_FREE(xen_host)
-XEN_SET_ALLOC_FREE(xen_host)
-XEN_ALLOC(xen_host_record)
-XEN_SET_ALLOC_FREE(xen_host_record)
-XEN_ALLOC(xen_host_record_opt)
-XEN_RECORD_OPT_FREE(xen_host)
-XEN_SET_ALLOC_FREE(xen_host_record_opt)
-
-
-static const struct_member xen_host_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_host_record, uuid) },
- { .key = "name_label",
- .type = &abstract_type_string,
- .offset = offsetof(xen_host_record, name_label) },
- { .key = "name_description",
- .type = &abstract_type_string,
- .offset = offsetof(xen_host_record, name_description) },
- { .key = "API_version_major",
- .type = &abstract_type_int,
- .offset = offsetof(xen_host_record, api_version_major) },
- { .key = "API_version_minor",
- .type = &abstract_type_int,
- .offset = offsetof(xen_host_record, api_version_minor) },
- { .key = "API_version_vendor",
- .type = &abstract_type_string,
- .offset = offsetof(xen_host_record, api_version_vendor) },
- { .key = "API_version_vendor_implementation",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_host_record, api_version_vendor_implementation) },
- { .key = "enabled",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_host_record, enabled) },
- { .key = "software_version",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_host_record, software_version) },
- { .key = "other_config",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_host_record, other_config) },
- { .key = "capabilities",
- .type = &abstract_type_string_set,
- .offset = offsetof(xen_host_record, capabilities) },
- { .key = "cpu_configuration",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_host_record, cpu_configuration) },
- { .key = "sched_policy",
- .type = &abstract_type_string,
- .offset = offsetof(xen_host_record, sched_policy) },
- { .key = "supported_bootloaders",
- .type = &abstract_type_string_set,
- .offset = offsetof(xen_host_record, supported_bootloaders) },
- { .key = "resident_VMs",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_host_record, resident_vms) },
- { .key = "logging",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_host_record, logging) },
- { .key = "PIFs",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_host_record, pifs) },
- { .key = "suspend_image_sr",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_host_record, suspend_image_sr) },
- { .key = "crash_dump_sr",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_host_record, crash_dump_sr) },
- { .key = "PBDs",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_host_record, pbds) },
- { .key = "host_CPUs",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_host_record, host_cpus) },
- { .key = "metrics",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_host_record, metrics) },
- { .key = "resident_cpu_pools",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_host_record, resident_cpu_pools) }
- };
-
-const abstract_type xen_host_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_host_record),
- .member_count =
- sizeof(xen_host_record_struct_members) / sizeof(struct_member),
- .members = xen_host_record_struct_members
- };
-
-
-void
-xen_host_record_free(xen_host_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record->name_label);
- free(record->name_description);
- free(record->api_version_vendor);
- xen_string_string_map_free(record->api_version_vendor_implementation);
- xen_string_string_map_free(record->software_version);
- xen_string_string_map_free(record->other_config);
- xen_string_set_free(record->capabilities);
- xen_string_string_map_free(record->cpu_configuration);
- free(record->sched_policy);
- xen_string_set_free(record->supported_bootloaders);
- xen_vm_record_opt_set_free(record->resident_vms);
- xen_string_string_map_free(record->logging);
- xen_pif_record_opt_set_free(record->pifs);
- xen_sr_record_opt_free(record->suspend_image_sr);
- xen_sr_record_opt_free(record->crash_dump_sr);
- xen_pbd_record_opt_set_free(record->pbds);
- xen_host_cpu_record_opt_set_free(record->host_cpus);
- xen_host_metrics_record_opt_free(record->metrics);
- xen_cpu_pool_record_opt_set_free(record->resident_cpu_pools);
- free(record);
-}
-
-
-bool
-xen_host_get_record(xen_session *session, xen_host_record **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = xen_host_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("host.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_host_get_by_uuid(xen_session *session, xen_host *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_host_get_by_name_label(xen_session *session, struct xen_host_set **result, char *label)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = label }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("host.get_by_name_label");
- return session->ok;
-}
-
-
-bool
-xen_host_get_name_label(xen_session *session, char **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host.get_name_label");
- return session->ok;
-}
-
-
-bool
-xen_host_get_name_description(xen_session *session, char **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host.get_name_description");
- return session->ok;
-}
-
-
-bool
-xen_host_get_api_version_major(xen_session *session, int64_t *result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("host.get_API_version_major");
- return session->ok;
-}
-
-
-bool
-xen_host_get_api_version_minor(xen_session *session, int64_t *result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("host.get_API_version_minor");
- return session->ok;
-}
-
-
-bool
-xen_host_get_api_version_vendor(xen_session *session, char **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host.get_API_version_vendor");
- return session->ok;
-}
-
-
-bool
-xen_host_get_api_version_vendor_implementation(xen_session *session, xen_string_string_map **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("host.get_API_version_vendor_implementation");
- return session->ok;
-}
-
-
-bool
-xen_host_get_enabled(xen_session *session, bool *result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("host.get_enabled");
- return session->ok;
-}
-
-
-bool
-xen_host_get_software_version(xen_session *session, xen_string_string_map **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("host.get_software_version");
- return session->ok;
-}
-
-
-bool
-xen_host_get_other_config(xen_session *session, xen_string_string_map **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("host.get_other_config");
- return session->ok;
-}
-
-
-bool
-xen_host_get_capabilities(xen_session *session, struct xen_string_set **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("host.get_capabilities");
- return session->ok;
-}
-
-
-bool
-xen_host_get_cpu_configuration(xen_session *session, xen_string_string_map **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("host.get_cpu_configuration");
- return session->ok;
-}
-
-
-bool
-xen_host_get_sched_policy(xen_session *session, char **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host.get_sched_policy");
- return session->ok;
-}
-
-
-bool
-xen_host_get_supported_bootloaders(xen_session *session, struct xen_string_set **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("host.get_supported_bootloaders");
- return session->ok;
-}
-
-
-bool
-xen_host_get_resident_vms(xen_session *session, struct xen_vm_set **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("host.get_resident_VMs");
- return session->ok;
-}
-
-
-bool
-xen_host_get_logging(xen_session *session, xen_string_string_map **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("host.get_logging");
- return session->ok;
-}
-
-
-bool
-xen_host_get_pifs(xen_session *session, struct xen_pif_set **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("host.get_PIFs");
- return session->ok;
-}
-
-
-bool
-xen_host_get_suspend_image_sr(xen_session *session, xen_sr *result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host.get_suspend_image_sr");
- return session->ok;
-}
-
-
-bool
-xen_host_get_crash_dump_sr(xen_session *session, xen_sr *result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host.get_crash_dump_sr");
- return session->ok;
-}
-
-
-bool
-xen_host_get_pbds(xen_session *session, struct xen_pbd_set **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("host.get_PBDs");
- return session->ok;
-}
-
-
-bool
-xen_host_get_host_cpus(xen_session *session, struct xen_host_cpu_set **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("host.get_host_CPUs");
- return session->ok;
-}
-
-
-bool
-xen_host_get_metrics(xen_session *session, xen_host_metrics *result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host.get_metrics");
- return session->ok;
-}
-
-
-bool
-xen_host_set_name_label(xen_session *session, xen_host host, char *label)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host },
- { .type = &abstract_type_string,
- .u.string_val = label }
- };
-
- xen_call_(session, "host.set_name_label", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_host_set_name_description(xen_session *session, xen_host host, char *description)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host },
- { .type = &abstract_type_string,
- .u.string_val = description }
- };
-
- xen_call_(session, "host.set_name_description", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_host_set_other_config(xen_session *session, xen_host host, xen_string_string_map *other_config)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host },
- { .type = &abstract_type_string_string_map,
- .u.set_val = (arbitrary_set *)other_config }
- };
-
- xen_call_(session, "host.set_other_config", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_host_add_to_other_config(xen_session *session, xen_host host, char *key, char *value)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host },
- { .type = &abstract_type_string,
- .u.string_val = key },
- { .type = &abstract_type_string,
- .u.string_val = value }
- };
-
- xen_call_(session, "host.add_to_other_config", param_values, 3, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_host_remove_from_other_config(xen_session *session, xen_host host, char *key)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host },
- { .type = &abstract_type_string,
- .u.string_val = key }
- };
-
- xen_call_(session, "host.remove_from_other_config", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_host_set_logging(xen_session *session, xen_host host, xen_string_string_map *logging)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host },
- { .type = &abstract_type_string_string_map,
- .u.set_val = (arbitrary_set *)logging }
- };
-
- xen_call_(session, "host.set_logging", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_host_add_to_logging(xen_session *session, xen_host host, char *key, char *value)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host },
- { .type = &abstract_type_string,
- .u.string_val = key },
- { .type = &abstract_type_string,
- .u.string_val = value }
- };
-
- xen_call_(session, "host.add_to_logging", param_values, 3, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_host_remove_from_logging(xen_session *session, xen_host host, char *key)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host },
- { .type = &abstract_type_string,
- .u.string_val = key }
- };
-
- xen_call_(session, "host.remove_from_logging", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_host_set_suspend_image_sr(xen_session *session, xen_host host, xen_sr suspend_image_sr)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host },
- { .type = &abstract_type_string,
- .u.string_val = suspend_image_sr }
- };
-
- xen_call_(session, "host.set_suspend_image_sr", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_host_set_crash_dump_sr(xen_session *session, xen_host host, xen_sr crash_dump_sr)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host },
- { .type = &abstract_type_string,
- .u.string_val = crash_dump_sr }
- };
-
- xen_call_(session, "host.set_crash_dump_sr", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_host_disable(xen_session *session, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- xen_call_(session, "host.disable", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_host_enable(xen_session *session, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- xen_call_(session, "host.enable", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_host_shutdown(xen_session *session, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- xen_call_(session, "host.shutdown", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_host_reboot(xen_session *session, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- xen_call_(session, "host.reboot", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_host_dmesg(xen_session *session, char **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host.dmesg");
- return session->ok;
-}
-
-
-bool
-xen_host_dmesg_clear(xen_session *session, char **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host.dmesg_clear");
- return session->ok;
-}
-
-
-bool
-xen_host_get_log(xen_session *session, char **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host.get_log");
- return session->ok;
-}
-
-
-bool
-xen_host_send_debug_keys(xen_session *session, xen_host host, char *keys)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host },
- { .type = &abstract_type_string,
- .u.string_val = keys }
- };
-
- xen_call_(session, "host.send_debug_keys", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_host_list_methods(xen_session *session, struct xen_string_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "host.list_methods", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_host_get_all(xen_session *session, struct xen_host_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "host.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_host_get_uuid(xen_session *session, char **result, xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host.get_uuid");
- return session->ok;
-}
-
-
-bool
-xen_host_get_resident_cpu_pools(xen_session *session, struct xen_cpu_pool_set **result,
- xen_host host)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("host.get_resident_cpu_pools");
- return session->ok;
-}
-
diff --git a/tools/libxen/src/xen_host_cpu.c b/tools/libxen/src/xen_host_cpu.c
deleted file mode 100644
index 85d88f6..0000000
--- a/tools/libxen/src/xen_host_cpu.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_host.h>
-#include <xen/api/xen_host_cpu.h>
-#include <xen/api/xen_cpu_pool.h>
-
-
-XEN_FREE(xen_host_cpu)
-XEN_SET_ALLOC_FREE(xen_host_cpu)
-XEN_ALLOC(xen_host_cpu_record)
-XEN_SET_ALLOC_FREE(xen_host_cpu_record)
-XEN_ALLOC(xen_host_cpu_record_opt)
-XEN_RECORD_OPT_FREE(xen_host_cpu)
-XEN_SET_ALLOC_FREE(xen_host_cpu_record_opt)
-
-
-static const struct_member xen_host_cpu_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_host_cpu_record, uuid) },
- { .key = "host",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_host_cpu_record, host) },
- { .key = "number",
- .type = &abstract_type_int,
- .offset = offsetof(xen_host_cpu_record, number) },
- { .key = "vendor",
- .type = &abstract_type_string,
- .offset = offsetof(xen_host_cpu_record, vendor) },
- { .key = "speed",
- .type = &abstract_type_int,
- .offset = offsetof(xen_host_cpu_record, speed) },
- { .key = "modelname",
- .type = &abstract_type_string,
- .offset = offsetof(xen_host_cpu_record, modelname) },
- { .key = "stepping",
- .type = &abstract_type_string,
- .offset = offsetof(xen_host_cpu_record, stepping) },
- { .key = "flags",
- .type = &abstract_type_string,
- .offset = offsetof(xen_host_cpu_record, flags) },
- { .key = "features",
- .type = &abstract_type_string,
- .offset = offsetof(xen_host_cpu_record, features) },
- { .key = "utilisation",
- .type = &abstract_type_float,
- .offset = offsetof(xen_host_cpu_record, utilisation) },
- { .key = "cpu_pool",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_host_cpu_record, cpu_pools) },
- };
-
-const abstract_type xen_host_cpu_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_host_cpu_record),
- .member_count =
- sizeof(xen_host_cpu_record_struct_members) / sizeof(struct_member),
- .members = xen_host_cpu_record_struct_members
- };
-
-
-void
-xen_host_cpu_record_free(xen_host_cpu_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- xen_host_record_opt_free(record->host);
- free(record->vendor);
- free(record->modelname);
- free(record->stepping);
- free(record->flags);
- free(record->features);
- xen_cpu_pool_record_opt_set_free(record->cpu_pools);
- free(record);
-}
-
-
-bool
-xen_host_cpu_get_record(xen_session *session, xen_host_cpu_record **result, xen_host_cpu host_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_cpu }
- };
-
- abstract_type result_type = xen_host_cpu_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("host_cpu.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_host_cpu_get_by_uuid(xen_session *session, xen_host_cpu *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host_cpu.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_host_cpu_get_host(xen_session *session, xen_host *result, xen_host_cpu host_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_cpu }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host_cpu.get_host");
- return session->ok;
-}
-
-
-bool
-xen_host_cpu_get_number(xen_session *session, int64_t *result, xen_host_cpu host_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_cpu }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("host_cpu.get_number");
- return session->ok;
-}
-
-
-bool
-xen_host_cpu_get_vendor(xen_session *session, char **result, xen_host_cpu host_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_cpu }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host_cpu.get_vendor");
- return session->ok;
-}
-
-
-bool
-xen_host_cpu_get_speed(xen_session *session, int64_t *result, xen_host_cpu host_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_cpu }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("host_cpu.get_speed");
- return session->ok;
-}
-
-
-bool
-xen_host_cpu_get_modelname(xen_session *session, char **result, xen_host_cpu host_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_cpu }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host_cpu.get_modelname");
- return session->ok;
-}
-
-
-bool
-xen_host_cpu_get_stepping(xen_session *session, char **result, xen_host_cpu host_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_cpu }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host_cpu.get_stepping");
- return session->ok;
-}
-
-
-bool
-xen_host_cpu_get_flags(xen_session *session, char **result, xen_host_cpu host_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_cpu }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host_cpu.get_flags");
- return session->ok;
-}
-
-
-bool
-xen_host_cpu_get_features(xen_session *session, char **result, xen_host_cpu host_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_cpu }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host_cpu.get_features");
- return session->ok;
-}
-
-
-bool
-xen_host_cpu_get_utilisation(xen_session *session, double *result, xen_host_cpu host_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_cpu }
- };
-
- abstract_type result_type = abstract_type_float;
-
- XEN_CALL_("host_cpu.get_utilisation");
- return session->ok;
-}
-
-
-bool
-xen_host_cpu_get_all(xen_session *session, struct xen_host_cpu_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "host_cpu.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_host_cpu_get_uuid(xen_session *session, char **result, xen_host_cpu host_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_cpu }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host_cpu.get_uuid");
- return session->ok;
-}
-
-
-bool
-xen_host_cpu_get_cpu_pool(xen_session *session, struct xen_cpu_pool_set **result, xen_host_cpu host_cpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_cpu }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("host_cpu.get_cpu_pool");
- return session->ok;
-}
-
-
-bool
-xen_host_cpu_get_unassigned_cpus(xen_session *session, struct xen_host_cpu_set **result)
-{
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "host_cpu.get_unassigned_cpus", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-
diff --git a/tools/libxen/src/xen_host_metrics.c b/tools/libxen/src/xen_host_metrics.c
deleted file mode 100644
index 976f4c5..0000000
--- a/tools/libxen/src/xen_host_metrics.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_host_metrics.h>
-
-
-XEN_FREE(xen_host_metrics)
-XEN_SET_ALLOC_FREE(xen_host_metrics)
-XEN_ALLOC(xen_host_metrics_record)
-XEN_SET_ALLOC_FREE(xen_host_metrics_record)
-XEN_ALLOC(xen_host_metrics_record_opt)
-XEN_RECORD_OPT_FREE(xen_host_metrics)
-XEN_SET_ALLOC_FREE(xen_host_metrics_record_opt)
-
-
-static const struct_member xen_host_metrics_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_host_metrics_record, uuid) },
- { .key = "memory_total",
- .type = &abstract_type_int,
- .offset = offsetof(xen_host_metrics_record, memory_total) },
- { .key = "memory_free",
- .type = &abstract_type_int,
- .offset = offsetof(xen_host_metrics_record, memory_free) },
- { .key = "last_updated",
- .type = &abstract_type_datetime,
- .offset = offsetof(xen_host_metrics_record, last_updated) }
- };
-
-const abstract_type xen_host_metrics_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_host_metrics_record),
- .member_count =
- sizeof(xen_host_metrics_record_struct_members) / sizeof(struct_member),
- .members = xen_host_metrics_record_struct_members
- };
-
-
-void
-xen_host_metrics_record_free(xen_host_metrics_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record);
-}
-
-
-bool
-xen_host_metrics_get_record(xen_session *session, xen_host_metrics_record **result, xen_host_metrics host_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_metrics }
- };
-
- abstract_type result_type = xen_host_metrics_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("host_metrics.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_host_metrics_get_by_uuid(xen_session *session, xen_host_metrics *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host_metrics.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_host_metrics_get_memory_total(xen_session *session, int64_t *result, xen_host_metrics host_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_metrics }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("host_metrics.get_memory_total");
- return session->ok;
-}
-
-
-bool
-xen_host_metrics_get_memory_free(xen_session *session, int64_t *result, xen_host_metrics host_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_metrics }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("host_metrics.get_memory_free");
- return session->ok;
-}
-
-
-bool
-xen_host_metrics_get_last_updated(xen_session *session, time_t *result, xen_host_metrics host_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_metrics }
- };
-
- abstract_type result_type = abstract_type_datetime;
-
- XEN_CALL_("host_metrics.get_last_updated");
- return session->ok;
-}
-
-
-bool
-xen_host_metrics_get_all(xen_session *session, struct xen_host_metrics_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "host_metrics.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_host_metrics_get_uuid(xen_session *session, char **result, xen_host_metrics host_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = host_metrics }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("host_metrics.get_uuid");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_int_float_map.c b/tools/libxen/src/xen_int_float_map.c
deleted file mode 100644
index ed3bf48..0000000
--- a/tools/libxen/src/xen_int_float_map.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_int_float_map.h>
-
-
-xen_int_float_map *
-xen_int_float_map_alloc(size_t size)
-{
- xen_int_float_map *result = calloc(1, sizeof(xen_int_float_map) +
- size * sizeof(struct xen_int_float_map_contents));
- result->size = size;
- return result;
-}
-
-
-void
-xen_int_float_map_free(xen_int_float_map *map)
-{
- free(map);
-}
diff --git a/tools/libxen/src/xen_int_int_map.c b/tools/libxen/src/xen_int_int_map.c
deleted file mode 100644
index 3d87c22..0000000
--- a/tools/libxen/src/xen_int_int_map.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_int_int_map.h>
-
-
-xen_int_int_map *
-xen_int_int_map_alloc(size_t size)
-{
- xen_int_int_map *result = calloc(1, sizeof(xen_int_int_map) +
- size * sizeof(struct xen_int_int_map_contents));
- result->size = size;
- return result;
-}
-
-
-void
-xen_int_int_map_free(xen_int_int_map *map)
-{
- free(map);
-}
diff --git a/tools/libxen/src/xen_int_string_set_map.c b/tools/libxen/src/xen_int_string_set_map.c
deleted file mode 100644
index 7a22cfd..0000000
--- a/tools/libxen/src/xen_int_string_set_map.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_int_string_set_map.h>
-#include <xen/api/xen_string_set.h>
-
-
-xen_int_string_set_map *
-xen_int_string_set_map_alloc(size_t size)
-{
- xen_int_string_set_map *result = calloc(1, sizeof(xen_int_string_set_map) +
- size * sizeof(struct xen_int_string_set_map_contents));
- result->size = size;
- return result;
-}
-
-
-void
-xen_int_string_set_map_free(xen_int_string_set_map *map)
-{
- size_t n;
-
- if (map == NULL)
- {
- return;
- }
-
- n = map->size;
- for (size_t i = 0; i < n; i++)
- {
-
- xen_string_set_free(map->contents[i].val);
- }
-
- free(map);
-}
diff --git a/tools/libxen/src/xen_network.c b/tools/libxen/src/xen_network.c
deleted file mode 100644
index 4b03ead..0000000
--- a/tools/libxen/src/xen_network.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_network.h>
-#include <xen/api/xen_pif.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vif.h>
-
-
-XEN_FREE(xen_network)
-XEN_SET_ALLOC_FREE(xen_network)
-XEN_ALLOC(xen_network_record)
-XEN_SET_ALLOC_FREE(xen_network_record)
-XEN_ALLOC(xen_network_record_opt)
-XEN_RECORD_OPT_FREE(xen_network)
-XEN_SET_ALLOC_FREE(xen_network_record_opt)
-
-
-static const struct_member xen_network_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_network_record, uuid) },
- { .key = "name_label",
- .type = &abstract_type_string,
- .offset = offsetof(xen_network_record, name_label) },
- { .key = "name_description",
- .type = &abstract_type_string,
- .offset = offsetof(xen_network_record, name_description) },
- { .key = "VIFs",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_network_record, vifs) },
- { .key = "PIFs",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_network_record, pifs) },
- { .key = "other_config",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_network_record, other_config) }
- };
-
-const abstract_type xen_network_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_network_record),
- .member_count =
- sizeof(xen_network_record_struct_members) / sizeof(struct_member),
- .members = xen_network_record_struct_members
- };
-
-
-void
-xen_network_record_free(xen_network_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record->name_label);
- free(record->name_description);
- xen_vif_record_opt_set_free(record->vifs);
- xen_pif_record_opt_set_free(record->pifs);
- xen_string_string_map_free(record->other_config);
- free(record);
-}
-
-
-bool
-xen_network_get_record(xen_session *session, xen_network_record **result, xen_network network)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = network }
- };
-
- abstract_type result_type = xen_network_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("network.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_network_get_by_uuid(xen_session *session, xen_network *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("network.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_network_create(xen_session *session, xen_network *result, xen_network_record *record)
-{
- abstract_value param_values[] =
- {
- { .type = &xen_network_record_abstract_type_,
- .u.struct_val = record }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("network.create");
- return session->ok;
-}
-
-
-bool
-xen_network_destroy(xen_session *session, xen_network network)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = network }
- };
-
- xen_call_(session, "network.destroy", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_network_get_by_name_label(xen_session *session, struct xen_network_set **result, char *label)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = label }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("network.get_by_name_label");
- return session->ok;
-}
-
-
-bool
-xen_network_get_name_label(xen_session *session, char **result, xen_network network)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = network }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("network.get_name_label");
- return session->ok;
-}
-
-
-bool
-xen_network_get_name_description(xen_session *session, char **result, xen_network network)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = network }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("network.get_name_description");
- return session->ok;
-}
-
-
-bool
-xen_network_get_vifs(xen_session *session, struct xen_vif_set **result, xen_network network)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = network }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("network.get_VIFs");
- return session->ok;
-}
-
-
-bool
-xen_network_get_pifs(xen_session *session, struct xen_pif_set **result, xen_network network)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = network }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("network.get_PIFs");
- return session->ok;
-}
-
-
-bool
-xen_network_get_other_config(xen_session *session, xen_string_string_map **result, xen_network network)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = network }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("network.get_other_config");
- return session->ok;
-}
-
-
-bool
-xen_network_set_name_label(xen_session *session, xen_network network, char *label)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = network },
- { .type = &abstract_type_string,
- .u.string_val = label }
- };
-
- xen_call_(session, "network.set_name_label", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_network_set_name_description(xen_session *session, xen_network network, char *description)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = network },
- { .type = &abstract_type_string,
- .u.string_val = description }
- };
-
- xen_call_(session, "network.set_name_description", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_network_set_other_config(xen_session *session, xen_network network, xen_string_string_map *other_config)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = network },
- { .type = &abstract_type_string_string_map,
- .u.set_val = (arbitrary_set *)other_config }
- };
-
- xen_call_(session, "network.set_other_config", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_network_add_to_other_config(xen_session *session, xen_network network, char *key, char *value)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = network },
- { .type = &abstract_type_string,
- .u.string_val = key },
- { .type = &abstract_type_string,
- .u.string_val = value }
- };
-
- xen_call_(session, "network.add_to_other_config", param_values, 3, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_network_remove_from_other_config(xen_session *session, xen_network network, char *key)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = network },
- { .type = &abstract_type_string,
- .u.string_val = key }
- };
-
- xen_call_(session, "network.remove_from_other_config", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_network_get_all(xen_session *session, struct xen_network_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "network.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_network_get_uuid(xen_session *session, char **result, xen_network network)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = network }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("network.get_uuid");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_on_crash_behaviour.c b/tools/libxen/src/xen_on_crash_behaviour.c
deleted file mode 100644
index abd25db..0000000
--- a/tools/libxen/src/xen_on_crash_behaviour.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_on_crash_behaviour.h>
-#include "xen_on_crash_behaviour_internal.h"
-
-
-/*
- * Maintain this in the same order as the enum declaration!
- */
-static const char *lookup_table[] =
-{
- "destroy",
- "coredump_and_destroy",
- "restart",
- "coredump_and_restart",
- "preserve",
- "rename_restart"
-};
-
-
-extern xen_on_crash_behaviour_set *
-xen_on_crash_behaviour_set_alloc(size_t size)
-{
- return calloc(1, sizeof(xen_on_crash_behaviour_set) +
- size * sizeof(enum xen_on_crash_behaviour));
-}
-
-
-extern void
-xen_on_crash_behaviour_set_free(xen_on_crash_behaviour_set *set)
-{
- free(set);
-}
-
-
-const char *
-xen_on_crash_behaviour_to_string(enum xen_on_crash_behaviour val)
-{
- return lookup_table[val];
-}
-
-
-extern enum xen_on_crash_behaviour
-xen_on_crash_behaviour_from_string(xen_session *session, const char *str)
-{
- return ENUM_LOOKUP(session, str, lookup_table);
-}
-
-
-const abstract_type xen_on_crash_behaviour_abstract_type_ =
- {
- .typename = ENUM,
- .enum_marshaller =
- (const char *(*)(int))&xen_on_crash_behaviour_to_string,
- .enum_demarshaller =
- (int (*)(xen_session *, const char *))&xen_on_crash_behaviour_from_string
- };
-
-
-const abstract_type xen_on_crash_behaviour_set_abstract_type_ =
- {
- .typename = SET,
- .child = &xen_on_crash_behaviour_abstract_type_
- };
-
-
diff --git a/tools/libxen/src/xen_on_normal_exit.c b/tools/libxen/src/xen_on_normal_exit.c
deleted file mode 100644
index bbb4e27..0000000
--- a/tools/libxen/src/xen_on_normal_exit.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_on_normal_exit.h>
-#include "xen_on_normal_exit_internal.h"
-
-
-/*
- * Maintain this in the same order as the enum declaration!
- */
-static const char *lookup_table[] =
-{
- "destroy",
- "restart"
-};
-
-
-extern xen_on_normal_exit_set *
-xen_on_normal_exit_set_alloc(size_t size)
-{
- return calloc(1, sizeof(xen_on_normal_exit_set) +
- size * sizeof(enum xen_on_normal_exit));
-}
-
-
-extern void
-xen_on_normal_exit_set_free(xen_on_normal_exit_set *set)
-{
- free(set);
-}
-
-
-const char *
-xen_on_normal_exit_to_string(enum xen_on_normal_exit val)
-{
- return lookup_table[val];
-}
-
-
-extern enum xen_on_normal_exit
-xen_on_normal_exit_from_string(xen_session *session, const char *str)
-{
- return ENUM_LOOKUP(session, str, lookup_table);
-}
-
-
-const abstract_type xen_on_normal_exit_abstract_type_ =
- {
- .typename = ENUM,
- .enum_marshaller =
- (const char *(*)(int))&xen_on_normal_exit_to_string,
- .enum_demarshaller =
- (int (*)(xen_session *, const char *))&xen_on_normal_exit_from_string
- };
-
-
-const abstract_type xen_on_normal_exit_set_abstract_type_ =
- {
- .typename = SET,
- .child = &xen_on_normal_exit_abstract_type_
- };
-
-
diff --git a/tools/libxen/src/xen_pbd.c b/tools/libxen/src/xen_pbd.c
deleted file mode 100644
index d3702ef..0000000
--- a/tools/libxen/src/xen_pbd.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_host.h>
-#include <xen/api/xen_pbd.h>
-#include <xen/api/xen_sr.h>
-#include <xen/api/xen_string_string_map.h>
-
-
-XEN_FREE(xen_pbd)
-XEN_SET_ALLOC_FREE(xen_pbd)
-XEN_ALLOC(xen_pbd_record)
-XEN_SET_ALLOC_FREE(xen_pbd_record)
-XEN_ALLOC(xen_pbd_record_opt)
-XEN_RECORD_OPT_FREE(xen_pbd)
-XEN_SET_ALLOC_FREE(xen_pbd_record_opt)
-
-
-static const struct_member xen_pbd_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_pbd_record, uuid) },
- { .key = "host",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_pbd_record, host) },
- { .key = "SR",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_pbd_record, sr) },
- { .key = "device_config",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_pbd_record, device_config) },
- { .key = "currently_attached",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_pbd_record, currently_attached) }
- };
-
-const abstract_type xen_pbd_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_pbd_record),
- .member_count =
- sizeof(xen_pbd_record_struct_members) / sizeof(struct_member),
- .members = xen_pbd_record_struct_members
- };
-
-
-void
-xen_pbd_record_free(xen_pbd_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- xen_host_record_opt_free(record->host);
- xen_sr_record_opt_free(record->sr);
- xen_string_string_map_free(record->device_config);
- free(record);
-}
-
-
-bool
-xen_pbd_get_record(xen_session *session, xen_pbd_record **result, xen_pbd pbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pbd }
- };
-
- abstract_type result_type = xen_pbd_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("PBD.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_pbd_get_by_uuid(xen_session *session, xen_pbd *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("PBD.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_pbd_create(xen_session *session, xen_pbd *result, xen_pbd_record *record)
-{
- abstract_value param_values[] =
- {
- { .type = &xen_pbd_record_abstract_type_,
- .u.struct_val = record }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("PBD.create");
- return session->ok;
-}
-
-
-bool
-xen_pbd_destroy(xen_session *session, xen_pbd pbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pbd }
- };
-
- xen_call_(session, "PBD.destroy", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_pbd_get_host(xen_session *session, xen_host *result, xen_pbd pbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pbd }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("PBD.get_host");
- return session->ok;
-}
-
-
-bool
-xen_pbd_get_sr(xen_session *session, xen_sr *result, xen_pbd pbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pbd }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("PBD.get_SR");
- return session->ok;
-}
-
-
-bool
-xen_pbd_get_device_config(xen_session *session, xen_string_string_map **result, xen_pbd pbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pbd }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("PBD.get_device_config");
- return session->ok;
-}
-
-
-bool
-xen_pbd_get_currently_attached(xen_session *session, bool *result, xen_pbd pbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pbd }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("PBD.get_currently_attached");
- return session->ok;
-}
-
-
-bool
-xen_pbd_get_all(xen_session *session, struct xen_pbd_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "PBD.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_pbd_get_uuid(xen_session *session, char **result, xen_pbd pbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pbd }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("PBD.get_uuid");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_pif.c b/tools/libxen/src/xen_pif.c
deleted file mode 100644
index 7cf9a74..0000000
--- a/tools/libxen/src/xen_pif.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_host.h>
-#include <xen/api/xen_network.h>
-#include <xen/api/xen_pif.h>
-#include <xen/api/xen_pif_metrics.h>
-
-
-XEN_FREE(xen_pif)
-XEN_SET_ALLOC_FREE(xen_pif)
-XEN_ALLOC(xen_pif_record)
-XEN_SET_ALLOC_FREE(xen_pif_record)
-XEN_ALLOC(xen_pif_record_opt)
-XEN_RECORD_OPT_FREE(xen_pif)
-XEN_SET_ALLOC_FREE(xen_pif_record_opt)
-
-
-static const struct_member xen_pif_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_pif_record, uuid) },
- { .key = "device",
- .type = &abstract_type_string,
- .offset = offsetof(xen_pif_record, device) },
- { .key = "network",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_pif_record, network) },
- { .key = "host",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_pif_record, host) },
- { .key = "MAC",
- .type = &abstract_type_string,
- .offset = offsetof(xen_pif_record, mac) },
- { .key = "MTU",
- .type = &abstract_type_int,
- .offset = offsetof(xen_pif_record, mtu) },
- { .key = "VLAN",
- .type = &abstract_type_int,
- .offset = offsetof(xen_pif_record, vlan) },
- { .key = "metrics",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_pif_record, metrics) }
- };
-
-const abstract_type xen_pif_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_pif_record),
- .member_count =
- sizeof(xen_pif_record_struct_members) / sizeof(struct_member),
- .members = xen_pif_record_struct_members
- };
-
-
-void
-xen_pif_record_free(xen_pif_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record->device);
- xen_network_record_opt_free(record->network);
- xen_host_record_opt_free(record->host);
- free(record->mac);
- xen_pif_metrics_record_opt_free(record->metrics);
- free(record);
-}
-
-
-bool
-xen_pif_get_record(xen_session *session, xen_pif_record **result, xen_pif pif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif }
- };
-
- abstract_type result_type = xen_pif_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("PIF.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_pif_get_by_uuid(xen_session *session, xen_pif *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("PIF.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_pif_get_device(xen_session *session, char **result, xen_pif pif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("PIF.get_device");
- return session->ok;
-}
-
-
-bool
-xen_pif_get_network(xen_session *session, xen_network *result, xen_pif pif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("PIF.get_network");
- return session->ok;
-}
-
-
-bool
-xen_pif_get_host(xen_session *session, xen_host *result, xen_pif pif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("PIF.get_host");
- return session->ok;
-}
-
-
-bool
-xen_pif_get_mac(xen_session *session, char **result, xen_pif pif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("PIF.get_MAC");
- return session->ok;
-}
-
-
-bool
-xen_pif_get_mtu(xen_session *session, int64_t *result, xen_pif pif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("PIF.get_MTU");
- return session->ok;
-}
-
-
-bool
-xen_pif_get_vlan(xen_session *session, int64_t *result, xen_pif pif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("PIF.get_VLAN");
- return session->ok;
-}
-
-
-bool
-xen_pif_get_metrics(xen_session *session, xen_pif_metrics *result, xen_pif pif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("PIF.get_metrics");
- return session->ok;
-}
-
-
-bool
-xen_pif_set_device(xen_session *session, xen_pif pif, char *device)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif },
- { .type = &abstract_type_string,
- .u.string_val = device }
- };
-
- xen_call_(session, "PIF.set_device", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_pif_set_mac(xen_session *session, xen_pif pif, char *mac)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif },
- { .type = &abstract_type_string,
- .u.string_val = mac }
- };
-
- xen_call_(session, "PIF.set_MAC", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_pif_set_mtu(xen_session *session, xen_pif pif, int64_t mtu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif },
- { .type = &abstract_type_int,
- .u.int_val = mtu }
- };
-
- xen_call_(session, "PIF.set_MTU", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_pif_set_vlan(xen_session *session, xen_pif pif, int64_t vlan)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif },
- { .type = &abstract_type_int,
- .u.int_val = vlan }
- };
-
- xen_call_(session, "PIF.set_VLAN", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_pif_create_vlan(xen_session *session, xen_pif *result, char *device, xen_network network, xen_host host, int64_t vlan)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = device },
- { .type = &abstract_type_string,
- .u.string_val = network },
- { .type = &abstract_type_string,
- .u.string_val = host },
- { .type = &abstract_type_int,
- .u.int_val = vlan }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("PIF.create_VLAN");
- return session->ok;
-}
-
-
-bool
-xen_pif_destroy(xen_session *session, xen_pif self)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = self }
- };
-
- xen_call_(session, "PIF.destroy", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_pif_get_all(xen_session *session, struct xen_pif_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "PIF.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_pif_get_uuid(xen_session *session, char **result, xen_pif pif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("PIF.get_uuid");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_pif_metrics.c b/tools/libxen/src/xen_pif_metrics.c
deleted file mode 100644
index f150f7f..0000000
--- a/tools/libxen/src/xen_pif_metrics.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_pif_metrics.h>
-
-
-XEN_FREE(xen_pif_metrics)
-XEN_SET_ALLOC_FREE(xen_pif_metrics)
-XEN_ALLOC(xen_pif_metrics_record)
-XEN_SET_ALLOC_FREE(xen_pif_metrics_record)
-XEN_ALLOC(xen_pif_metrics_record_opt)
-XEN_RECORD_OPT_FREE(xen_pif_metrics)
-XEN_SET_ALLOC_FREE(xen_pif_metrics_record_opt)
-
-
-static const struct_member xen_pif_metrics_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_pif_metrics_record, uuid) },
- { .key = "io_read_kbs",
- .type = &abstract_type_float,
- .offset = offsetof(xen_pif_metrics_record, io_read_kbs) },
- { .key = "io_write_kbs",
- .type = &abstract_type_float,
- .offset = offsetof(xen_pif_metrics_record, io_write_kbs) },
- { .key = "last_updated",
- .type = &abstract_type_datetime,
- .offset = offsetof(xen_pif_metrics_record, last_updated) }
- };
-
-const abstract_type xen_pif_metrics_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_pif_metrics_record),
- .member_count =
- sizeof(xen_pif_metrics_record_struct_members) / sizeof(struct_member),
- .members = xen_pif_metrics_record_struct_members
- };
-
-
-void
-xen_pif_metrics_record_free(xen_pif_metrics_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record);
-}
-
-
-bool
-xen_pif_metrics_get_record(xen_session *session, xen_pif_metrics_record **result, xen_pif_metrics pif_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif_metrics }
- };
-
- abstract_type result_type = xen_pif_metrics_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("PIF_metrics.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_pif_metrics_get_by_uuid(xen_session *session, xen_pif_metrics *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("PIF_metrics.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_pif_metrics_get_io_read_kbs(xen_session *session, double *result, xen_pif_metrics pif_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif_metrics }
- };
-
- abstract_type result_type = abstract_type_float;
-
- XEN_CALL_("PIF_metrics.get_io_read_kbs");
- return session->ok;
-}
-
-
-bool
-xen_pif_metrics_get_io_write_kbs(xen_session *session, double *result, xen_pif_metrics pif_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif_metrics }
- };
-
- abstract_type result_type = abstract_type_float;
-
- XEN_CALL_("PIF_metrics.get_io_write_kbs");
- return session->ok;
-}
-
-
-bool
-xen_pif_metrics_get_last_updated(xen_session *session, time_t *result, xen_pif_metrics pif_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif_metrics }
- };
-
- abstract_type result_type = abstract_type_datetime;
-
- XEN_CALL_("PIF_metrics.get_last_updated");
- return session->ok;
-}
-
-
-bool
-xen_pif_metrics_get_all(xen_session *session, struct xen_pif_metrics_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "PIF_metrics.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_pif_metrics_get_uuid(xen_session *session, char **result, xen_pif_metrics pif_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = pif_metrics }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("PIF_metrics.get_uuid");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_sr.c b/tools/libxen/src/xen_sr.c
deleted file mode 100644
index b2ff310..0000000
--- a/tools/libxen/src/xen_sr.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_pbd.h>
-#include <xen/api/xen_sr.h>
-#include <xen/api/xen_vdi.h>
-
-
-XEN_FREE(xen_sr)
-XEN_SET_ALLOC_FREE(xen_sr)
-XEN_ALLOC(xen_sr_record)
-XEN_SET_ALLOC_FREE(xen_sr_record)
-XEN_ALLOC(xen_sr_record_opt)
-XEN_RECORD_OPT_FREE(xen_sr)
-XEN_SET_ALLOC_FREE(xen_sr_record_opt)
-
-
-static const struct_member xen_sr_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_sr_record, uuid) },
- { .key = "name_label",
- .type = &abstract_type_string,
- .offset = offsetof(xen_sr_record, name_label) },
- { .key = "name_description",
- .type = &abstract_type_string,
- .offset = offsetof(xen_sr_record, name_description) },
- { .key = "VDIs",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_sr_record, vdis) },
- { .key = "PBDs",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_sr_record, pbds) },
- { .key = "virtual_allocation",
- .type = &abstract_type_int,
- .offset = offsetof(xen_sr_record, virtual_allocation) },
- { .key = "physical_utilisation",
- .type = &abstract_type_int,
- .offset = offsetof(xen_sr_record, physical_utilisation) },
- { .key = "physical_size",
- .type = &abstract_type_int,
- .offset = offsetof(xen_sr_record, physical_size) },
- { .key = "type",
- .type = &abstract_type_string,
- .offset = offsetof(xen_sr_record, type) },
- { .key = "content_type",
- .type = &abstract_type_string,
- .offset = offsetof(xen_sr_record, content_type) }
- };
-
-const abstract_type xen_sr_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_sr_record),
- .member_count =
- sizeof(xen_sr_record_struct_members) / sizeof(struct_member),
- .members = xen_sr_record_struct_members
- };
-
-
-void
-xen_sr_record_free(xen_sr_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record->name_label);
- free(record->name_description);
- xen_vdi_record_opt_set_free(record->vdis);
- xen_pbd_record_opt_set_free(record->pbds);
- free(record->type);
- free(record->content_type);
- free(record);
-}
-
-
-bool
-xen_sr_get_record(xen_session *session, xen_sr_record **result, xen_sr sr)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = sr }
- };
-
- abstract_type result_type = xen_sr_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("SR.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_sr_get_by_uuid(xen_session *session, xen_sr *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("SR.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_sr_get_by_name_label(xen_session *session, struct xen_sr_set **result, char *label)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = label }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("SR.get_by_name_label");
- return session->ok;
-}
-
-
-bool
-xen_sr_get_name_label(xen_session *session, char **result, xen_sr sr)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = sr }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("SR.get_name_label");
- return session->ok;
-}
-
-
-bool
-xen_sr_get_name_description(xen_session *session, char **result, xen_sr sr)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = sr }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("SR.get_name_description");
- return session->ok;
-}
-
-
-bool
-xen_sr_get_vdis(xen_session *session, struct xen_vdi_set **result, xen_sr sr)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = sr }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("SR.get_VDIs");
- return session->ok;
-}
-
-
-bool
-xen_sr_get_pbds(xen_session *session, struct xen_pbd_set **result, xen_sr sr)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = sr }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("SR.get_PBDs");
- return session->ok;
-}
-
-
-bool
-xen_sr_get_virtual_allocation(xen_session *session, int64_t *result, xen_sr sr)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = sr }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("SR.get_virtual_allocation");
- return session->ok;
-}
-
-
-bool
-xen_sr_get_physical_utilisation(xen_session *session, int64_t *result, xen_sr sr)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = sr }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("SR.get_physical_utilisation");
- return session->ok;
-}
-
-
-bool
-xen_sr_get_physical_size(xen_session *session, int64_t *result, xen_sr sr)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = sr }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("SR.get_physical_size");
- return session->ok;
-}
-
-
-bool
-xen_sr_get_type(xen_session *session, char **result, xen_sr sr)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = sr }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("SR.get_type");
- return session->ok;
-}
-
-
-bool
-xen_sr_get_content_type(xen_session *session, char **result, xen_sr sr)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = sr }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("SR.get_content_type");
- return session->ok;
-}
-
-
-bool
-xen_sr_set_name_label(xen_session *session, xen_sr sr, char *label)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = sr },
- { .type = &abstract_type_string,
- .u.string_val = label }
- };
-
- xen_call_(session, "SR.set_name_label", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_sr_set_name_description(xen_session *session, xen_sr sr, char *description)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = sr },
- { .type = &abstract_type_string,
- .u.string_val = description }
- };
-
- xen_call_(session, "SR.set_name_description", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_sr_get_supported_types(xen_session *session, struct xen_string_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "SR.get_supported_types", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_sr_get_all(xen_session *session, struct xen_sr_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "SR.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_sr_get_uuid(xen_session *session, char **result, xen_sr sr)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = sr }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("SR.get_uuid");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_string_set.c b/tools/libxen/src/xen_string_set.c
deleted file mode 100644
index 11bc6ce..0000000
--- a/tools/libxen/src/xen_string_set.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include "xen_internal.h"
-#include <xen/api/xen_string_set.h>
-
-
-xen_string_set *
-xen_string_set_alloc(size_t size)
-{
- xen_string_set *result = calloc(1, sizeof(xen_string_set) +
- size * sizeof(char *));
- result->size = size;
- return result;
-}
-
-void
-xen_string_set_free(xen_string_set *set)
-{
- size_t n;
- if (set == NULL)
- {
- return;
- }
- n = set->size;
- for (size_t i = 0; i < n; i++)
- {
- free(set->contents[i]);
- }
-
- free(set);
-}
diff --git a/tools/libxen/src/xen_string_set.h b/tools/libxen/src/xen_string_set.h
deleted file mode 100644
index a14af94..0000000
--- a/tools/libxen/src/xen_string_set.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_STRING_SET_H
-#define XEN_STRING_SET_H
-
-
-#include "xen_common.h"
-
-
-typedef struct xen_string_set
-{
- size_t size;
- char *contents[];
-} xen_string_set;
-
-
-/**
- * Allocate a xen_string_set of the given size.
- */
-extern xen_string_set *
-xen_string_set_alloc(size_t size);
-
-/**
- * Free the given xen_string_set. The given set must have been allocated
- * by this library.
- */
-extern void
-xen_string_set_free(xen_string_set *set);
-
-
-#endif
diff --git a/tools/libxen/src/xen_string_string_map.c b/tools/libxen/src/xen_string_string_map.c
deleted file mode 100644
index 2cf7997..0000000
--- a/tools/libxen/src/xen_string_string_map.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_string_string_map.h>
-
-
-xen_string_string_map *
-xen_string_string_map_alloc(size_t size)
-{
- xen_string_string_map *result = calloc(1, sizeof(xen_string_string_map) +
- size * sizeof(struct xen_string_string_map_contents));
- result->size = size;
- return result;
-}
-
-
-void
-xen_string_string_map_free(xen_string_string_map *map)
-{
- size_t n;
- if (map == NULL)
- {
- return;
- }
-
- n = map->size;
- for (size_t i = 0; i < n; i++)
- {
- free(map->contents[i].key);
- free(map->contents[i].val);
- }
-
- free(map);
-}
diff --git a/tools/libxen/src/xen_user.c b/tools/libxen/src/xen_user.c
deleted file mode 100644
index 377f8f8..0000000
--- a/tools/libxen/src/xen_user.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_user.h>
-
-
-XEN_FREE(xen_user)
-XEN_SET_ALLOC_FREE(xen_user)
-XEN_ALLOC(xen_user_record)
-XEN_SET_ALLOC_FREE(xen_user_record)
-XEN_ALLOC(xen_user_record_opt)
-XEN_RECORD_OPT_FREE(xen_user)
-XEN_SET_ALLOC_FREE(xen_user_record_opt)
-
-
-static const struct_member xen_user_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_user_record, uuid) },
- { .key = "short_name",
- .type = &abstract_type_string,
- .offset = offsetof(xen_user_record, short_name) },
- { .key = "fullname",
- .type = &abstract_type_string,
- .offset = offsetof(xen_user_record, fullname) }
- };
-
-const abstract_type xen_user_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_user_record),
- .member_count =
- sizeof(xen_user_record_struct_members) / sizeof(struct_member),
- .members = xen_user_record_struct_members
- };
-
-
-void
-xen_user_record_free(xen_user_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record->short_name);
- free(record->fullname);
- free(record);
-}
-
-
-bool
-xen_user_get_record(xen_session *session, xen_user_record **result, xen_user user)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = user }
- };
-
- abstract_type result_type = xen_user_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("user.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_user_get_by_uuid(xen_session *session, xen_user *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("user.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_user_create(xen_session *session, xen_user *result, xen_user_record *record)
-{
- abstract_value param_values[] =
- {
- { .type = &xen_user_record_abstract_type_,
- .u.struct_val = record }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("user.create");
- return session->ok;
-}
-
-
-bool
-xen_user_destroy(xen_session *session, xen_user user)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = user }
- };
-
- xen_call_(session, "user.destroy", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_user_get_short_name(xen_session *session, char **result, xen_user user)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = user }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("user.get_short_name");
- return session->ok;
-}
-
-
-bool
-xen_user_get_fullname(xen_session *session, char **result, xen_user user)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = user }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("user.get_fullname");
- return session->ok;
-}
-
-
-bool
-xen_user_set_fullname(xen_session *session, xen_user user, char *fullname)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = user },
- { .type = &abstract_type_string,
- .u.string_val = fullname }
- };
-
- xen_call_(session, "user.set_fullname", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_user_get_uuid(xen_session *session, char **result, xen_user user)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = user }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("user.get_uuid");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_vbd.c b/tools/libxen/src/xen_vbd.c
deleted file mode 100644
index 9efbca4..0000000
--- a/tools/libxen/src/xen_vbd.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include "xen_vbd_mode_internal.h"
-#include "xen_vbd_type_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vbd.h>
-#include <xen/api/xen_vbd_metrics.h>
-#include <xen/api/xen_vdi.h>
-#include <xen/api/xen_vm.h>
-
-
-XEN_FREE(xen_vbd)
-XEN_SET_ALLOC_FREE(xen_vbd)
-XEN_ALLOC(xen_vbd_record)
-XEN_SET_ALLOC_FREE(xen_vbd_record)
-XEN_ALLOC(xen_vbd_record_opt)
-XEN_RECORD_OPT_FREE(xen_vbd)
-XEN_SET_ALLOC_FREE(xen_vbd_record_opt)
-
-
-static const struct_member xen_vbd_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vbd_record, uuid) },
- { .key = "VM",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_vbd_record, vm) },
- { .key = "VDI",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_vbd_record, vdi) },
- { .key = "device",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vbd_record, device) },
- { .key = "bootable",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_vbd_record, bootable) },
- { .key = "mode",
- .type = &xen_vbd_mode_abstract_type_,
- .offset = offsetof(xen_vbd_record, mode) },
- { .key = "type",
- .type = &xen_vbd_type_abstract_type_,
- .offset = offsetof(xen_vbd_record, type) },
- { .key = "currently_attached",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_vbd_record, currently_attached) },
- { .key = "status_code",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vbd_record, status_code) },
- { .key = "status_detail",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vbd_record, status_detail) },
- { .key = "runtime_properties",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vbd_record, runtime_properties) },
- { .key = "qos_algorithm_type",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vbd_record, qos_algorithm_type) },
- { .key = "qos_algorithm_params",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vbd_record, qos_algorithm_params) },
- { .key = "qos_supported_algorithms",
- .type = &abstract_type_string_set,
- .offset = offsetof(xen_vbd_record, qos_supported_algorithms) },
- { .key = "metrics",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_vbd_record, metrics) }
- };
-
-const abstract_type xen_vbd_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_vbd_record),
- .member_count =
- sizeof(xen_vbd_record_struct_members) / sizeof(struct_member),
- .members = xen_vbd_record_struct_members
- };
-
-
-void
-xen_vbd_record_free(xen_vbd_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- xen_vm_record_opt_free(record->vm);
- xen_vdi_record_opt_free(record->vdi);
- free(record->device);
- free(record->status_detail);
- xen_string_string_map_free(record->runtime_properties);
- free(record->qos_algorithm_type);
- xen_string_string_map_free(record->qos_algorithm_params);
- xen_string_set_free(record->qos_supported_algorithms);
- xen_vbd_metrics_record_opt_free(record->metrics);
- free(record);
-}
-
-
-bool
-xen_vbd_get_record(xen_session *session, xen_vbd_record **result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = xen_vbd_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("VBD.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_by_uuid(xen_session *session, xen_vbd *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VBD.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_vbd_create(xen_session *session, xen_vbd *result, xen_vbd_record *record)
-{
- abstract_value param_values[] =
- {
- { .type = &xen_vbd_record_abstract_type_,
- .u.struct_val = record }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VBD.create");
- return session->ok;
-}
-
-
-bool
-xen_vbd_destroy(xen_session *session, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- xen_call_(session, "VBD.destroy", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_vm(xen_session *session, xen_vm *result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VBD.get_VM");
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_vdi(xen_session *session, xen_vdi *result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VBD.get_VDI");
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_device(xen_session *session, char **result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VBD.get_device");
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_bootable(xen_session *session, bool *result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("VBD.get_bootable");
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_mode(xen_session *session, enum xen_vbd_mode *result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = xen_vbd_mode_abstract_type_;
- XEN_CALL_("VBD.get_mode");
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_type(xen_session *session, enum xen_vbd_type *result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = xen_vbd_type_abstract_type_;
- XEN_CALL_("VBD.get_type");
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_currently_attached(xen_session *session, bool *result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("VBD.get_currently_attached");
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_status_code(xen_session *session, int64_t *result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VBD.get_status_code");
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_status_detail(xen_session *session, char **result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VBD.get_status_detail");
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_runtime_properties(xen_session *session, xen_string_string_map **result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VBD.get_runtime_properties");
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_qos_algorithm_type(xen_session *session, char **result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VBD.get_qos_algorithm_type");
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_qos_algorithm_params(xen_session *session, xen_string_string_map **result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VBD.get_qos_algorithm_params");
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_qos_supported_algorithms(xen_session *session, struct xen_string_set **result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("VBD.get_qos_supported_algorithms");
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_metrics(xen_session *session, xen_vbd_metrics *result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VBD.get_metrics");
- return session->ok;
-}
-
-
-bool
-xen_vbd_set_device(xen_session *session, xen_vbd vbd, char *device)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd },
- { .type = &abstract_type_string,
- .u.string_val = device }
- };
-
- xen_call_(session, "VBD.set_device", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vbd_set_bootable(xen_session *session, xen_vbd vbd, bool bootable)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd },
- { .type = &abstract_type_bool,
- .u.bool_val = bootable }
- };
-
- xen_call_(session, "VBD.set_bootable", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vbd_set_mode(xen_session *session, xen_vbd vbd, enum xen_vbd_mode mode)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd },
- { .type = &xen_vbd_mode_abstract_type_,
- .u.enum_val = mode }
- };
-
- xen_call_(session, "VBD.set_mode", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vbd_set_type(xen_session *session, xen_vbd vbd, enum xen_vbd_type type)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd },
- { .type = &xen_vbd_type_abstract_type_,
- .u.enum_val = type }
- };
-
- xen_call_(session, "VBD.set_type", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vbd_set_qos_algorithm_type(xen_session *session, xen_vbd vbd, char *algorithm_type)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd },
- { .type = &abstract_type_string,
- .u.string_val = algorithm_type }
- };
-
- xen_call_(session, "VBD.set_qos_algorithm_type", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vbd_set_qos_algorithm_params(xen_session *session, xen_vbd vbd, xen_string_string_map *algorithm_params)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd },
- { .type = &abstract_type_string_string_map,
- .u.set_val = (arbitrary_set *)algorithm_params }
- };
-
- xen_call_(session, "VBD.set_qos_algorithm_params", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vbd_add_to_qos_algorithm_params(xen_session *session, xen_vbd vbd, char *key, char *value)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd },
- { .type = &abstract_type_string,
- .u.string_val = key },
- { .type = &abstract_type_string,
- .u.string_val = value }
- };
-
- xen_call_(session, "VBD.add_to_qos_algorithm_params", param_values, 3, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vbd_remove_from_qos_algorithm_params(xen_session *session, xen_vbd vbd, char *key)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd },
- { .type = &abstract_type_string,
- .u.string_val = key }
- };
-
- xen_call_(session, "VBD.remove_from_qos_algorithm_params", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vbd_media_change(xen_session *session, xen_vbd vbd, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd },
- { .type = &abstract_type_string,
- .u.string_val = vdi }
- };
-
- xen_call_(session, "VBD.media_change", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vbd_plug(xen_session *session, xen_vbd self)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = self }
- };
-
- xen_call_(session, "VBD.plug", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vbd_unplug(xen_session *session, xen_vbd self)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = self }
- };
-
- xen_call_(session, "VBD.unplug", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_all(xen_session *session, struct xen_vbd_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "VBD.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_vbd_get_uuid(xen_session *session, char **result, xen_vbd vbd)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VBD.get_uuid");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_vbd_metrics.c b/tools/libxen/src/xen_vbd_metrics.c
deleted file mode 100644
index c4f336c..0000000
--- a/tools/libxen/src/xen_vbd_metrics.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_vbd_metrics.h>
-
-
-XEN_FREE(xen_vbd_metrics)
-XEN_SET_ALLOC_FREE(xen_vbd_metrics)
-XEN_ALLOC(xen_vbd_metrics_record)
-XEN_SET_ALLOC_FREE(xen_vbd_metrics_record)
-XEN_ALLOC(xen_vbd_metrics_record_opt)
-XEN_RECORD_OPT_FREE(xen_vbd_metrics)
-XEN_SET_ALLOC_FREE(xen_vbd_metrics_record_opt)
-
-
-static const struct_member xen_vbd_metrics_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vbd_metrics_record, uuid) },
- { .key = "io_read_kbs",
- .type = &abstract_type_float,
- .offset = offsetof(xen_vbd_metrics_record, io_read_kbs) },
- { .key = "io_write_kbs",
- .type = &abstract_type_float,
- .offset = offsetof(xen_vbd_metrics_record, io_write_kbs) },
- { .key = "last_updated",
- .type = &abstract_type_datetime,
- .offset = offsetof(xen_vbd_metrics_record, last_updated) }
- };
-
-const abstract_type xen_vbd_metrics_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_vbd_metrics_record),
- .member_count =
- sizeof(xen_vbd_metrics_record_struct_members) / sizeof(struct_member),
- .members = xen_vbd_metrics_record_struct_members
- };
-
-
-void
-xen_vbd_metrics_record_free(xen_vbd_metrics_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record);
-}
-
-
-bool
-xen_vbd_metrics_get_record(xen_session *session, xen_vbd_metrics_record **result, xen_vbd_metrics vbd_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd_metrics }
- };
-
- abstract_type result_type = xen_vbd_metrics_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("VBD_metrics.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_vbd_metrics_get_by_uuid(xen_session *session, xen_vbd_metrics *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VBD_metrics.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_vbd_metrics_get_io_read_kbs(xen_session *session, double *result, xen_vbd_metrics vbd_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd_metrics }
- };
-
- abstract_type result_type = abstract_type_float;
-
- XEN_CALL_("VBD_metrics.get_io_read_kbs");
- return session->ok;
-}
-
-
-bool
-xen_vbd_metrics_get_io_write_kbs(xen_session *session, double *result, xen_vbd_metrics vbd_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd_metrics }
- };
-
- abstract_type result_type = abstract_type_float;
-
- XEN_CALL_("VBD_metrics.get_io_write_kbs");
- return session->ok;
-}
-
-
-bool
-xen_vbd_metrics_get_last_updated(xen_session *session, time_t *result, xen_vbd_metrics vbd_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd_metrics }
- };
-
- abstract_type result_type = abstract_type_datetime;
-
- XEN_CALL_("VBD_metrics.get_last_updated");
- return session->ok;
-}
-
-
-bool
-xen_vbd_metrics_get_all(xen_session *session, struct xen_vbd_metrics_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "VBD_metrics.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_vbd_metrics_get_uuid(xen_session *session, char **result, xen_vbd_metrics vbd_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vbd_metrics }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VBD_metrics.get_uuid");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_vbd_mode.c b/tools/libxen/src/xen_vbd_mode.c
deleted file mode 100644
index 71abc42..0000000
--- a/tools/libxen/src/xen_vbd_mode.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_vbd_mode.h>
-#include "xen_vbd_mode_internal.h"
-
-
-/*
- * Maintain this in the same order as the enum declaration!
- */
-static const char *lookup_table[] =
-{
- "RO",
- "RW"
-};
-
-
-extern xen_vbd_mode_set *
-xen_vbd_mode_set_alloc(size_t size)
-{
- return calloc(1, sizeof(xen_vbd_mode_set) +
- size * sizeof(enum xen_vbd_mode));
-}
-
-
-extern void
-xen_vbd_mode_set_free(xen_vbd_mode_set *set)
-{
- free(set);
-}
-
-
-const char *
-xen_vbd_mode_to_string(enum xen_vbd_mode val)
-{
- return lookup_table[val];
-}
-
-
-extern enum xen_vbd_mode
-xen_vbd_mode_from_string(xen_session *session, const char *str)
-{
- return ENUM_LOOKUP(session, str, lookup_table);
-}
-
-
-const abstract_type xen_vbd_mode_abstract_type_ =
- {
- .typename = ENUM,
- .enum_marshaller =
- (const char *(*)(int))&xen_vbd_mode_to_string,
- .enum_demarshaller =
- (int (*)(xen_session *, const char *))&xen_vbd_mode_from_string
- };
-
-
-const abstract_type xen_vbd_mode_set_abstract_type_ =
- {
- .typename = SET,
- .child = &xen_vbd_mode_abstract_type_
- };
-
-
diff --git a/tools/libxen/src/xen_vbd_type.c b/tools/libxen/src/xen_vbd_type.c
deleted file mode 100644
index 0572635..0000000
--- a/tools/libxen/src/xen_vbd_type.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_vbd_type.h>
-#include "xen_vbd_type_internal.h"
-
-
-/*
- * Maintain this in the same order as the enum declaration!
- */
-static const char *lookup_table[] =
-{
- "CD",
- "Disk"
-};
-
-
-extern xen_vbd_type_set *
-xen_vbd_type_set_alloc(size_t size)
-{
- return calloc(1, sizeof(xen_vbd_type_set) +
- size * sizeof(enum xen_vbd_type));
-}
-
-
-extern void
-xen_vbd_type_set_free(xen_vbd_type_set *set)
-{
- free(set);
-}
-
-
-const char *
-xen_vbd_type_to_string(enum xen_vbd_type val)
-{
- return lookup_table[val];
-}
-
-
-extern enum xen_vbd_type
-xen_vbd_type_from_string(xen_session *session, const char *str)
-{
- return ENUM_LOOKUP(session, str, lookup_table);
-}
-
-
-const abstract_type xen_vbd_type_abstract_type_ =
- {
- .typename = ENUM,
- .enum_marshaller =
- (const char *(*)(int))&xen_vbd_type_to_string,
- .enum_demarshaller =
- (int (*)(xen_session *, const char *))&xen_vbd_type_from_string
- };
-
-
-const abstract_type xen_vbd_type_set_abstract_type_ =
- {
- .typename = SET,
- .child = &xen_vbd_type_abstract_type_
- };
-
-
diff --git a/tools/libxen/src/xen_vdi.c b/tools/libxen/src/xen_vdi.c
deleted file mode 100644
index f2182cc..0000000
--- a/tools/libxen/src/xen_vdi.c
+++ /dev/null
@@ -1,575 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include "xen_vdi_type_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_crashdump.h>
-#include <xen/api/xen_sr.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vbd.h>
-#include <xen/api/xen_vdi.h>
-
-
-XEN_FREE(xen_vdi)
-XEN_SET_ALLOC_FREE(xen_vdi)
-XEN_ALLOC(xen_vdi_record)
-XEN_SET_ALLOC_FREE(xen_vdi_record)
-XEN_ALLOC(xen_vdi_record_opt)
-XEN_RECORD_OPT_FREE(xen_vdi)
-XEN_SET_ALLOC_FREE(xen_vdi_record_opt)
-
-
-static const struct_member xen_vdi_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vdi_record, uuid) },
- { .key = "name_label",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vdi_record, name_label) },
- { .key = "name_description",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vdi_record, name_description) },
- { .key = "SR",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_vdi_record, sr) },
- { .key = "VBDs",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_vdi_record, vbds) },
- { .key = "crash_dumps",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_vdi_record, crash_dumps) },
- { .key = "virtual_size",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vdi_record, virtual_size) },
- { .key = "physical_utilisation",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vdi_record, physical_utilisation) },
- { .key = "type",
- .type = &xen_vdi_type_abstract_type_,
- .offset = offsetof(xen_vdi_record, type) },
- { .key = "sharable",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_vdi_record, sharable) },
- { .key = "read_only",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_vdi_record, read_only) },
- { .key = "other_config",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vdi_record, other_config) }
- };
-
-const abstract_type xen_vdi_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_vdi_record),
- .member_count =
- sizeof(xen_vdi_record_struct_members) / sizeof(struct_member),
- .members = xen_vdi_record_struct_members
- };
-
-
-void
-xen_vdi_record_free(xen_vdi_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record->name_label);
- free(record->name_description);
- xen_sr_record_opt_free(record->sr);
- xen_vbd_record_opt_set_free(record->vbds);
- xen_crashdump_record_opt_set_free(record->crash_dumps);
- xen_string_string_map_free(record->other_config);
- free(record);
-}
-
-
-bool
-xen_vdi_get_record(xen_session *session, xen_vdi_record **result, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi }
- };
-
- abstract_type result_type = xen_vdi_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("VDI.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_by_uuid(xen_session *session, xen_vdi *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VDI.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_vdi_create(xen_session *session, xen_vdi *result, xen_vdi_record *record)
-{
- abstract_value param_values[] =
- {
- { .type = &xen_vdi_record_abstract_type_,
- .u.struct_val = record }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VDI.create");
- return session->ok;
-}
-
-
-bool
-xen_vdi_destroy(xen_session *session, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi }
- };
-
- xen_call_(session, "VDI.destroy", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_by_name_label(xen_session *session, struct xen_vdi_set **result, char *label)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = label }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("VDI.get_by_name_label");
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_name_label(xen_session *session, char **result, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VDI.get_name_label");
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_name_description(xen_session *session, char **result, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VDI.get_name_description");
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_sr(xen_session *session, xen_sr *result, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VDI.get_SR");
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_vbds(xen_session *session, struct xen_vbd_set **result, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("VDI.get_VBDs");
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_crash_dumps(xen_session *session, struct xen_crashdump_set **result, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("VDI.get_crash_dumps");
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_virtual_size(xen_session *session, int64_t *result, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VDI.get_virtual_size");
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_physical_utilisation(xen_session *session, int64_t *result, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VDI.get_physical_utilisation");
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_type(xen_session *session, enum xen_vdi_type *result, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi }
- };
-
- abstract_type result_type = xen_vdi_type_abstract_type_;
- XEN_CALL_("VDI.get_type");
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_sharable(xen_session *session, bool *result, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("VDI.get_sharable");
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_read_only(xen_session *session, bool *result, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("VDI.get_read_only");
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_other_config(xen_session *session, xen_string_string_map **result, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VDI.get_other_config");
- return session->ok;
-}
-
-
-bool
-xen_vdi_set_name_label(xen_session *session, xen_vdi vdi, char *label)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi },
- { .type = &abstract_type_string,
- .u.string_val = label }
- };
-
- xen_call_(session, "VDI.set_name_label", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vdi_set_name_description(xen_session *session, xen_vdi vdi, char *description)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi },
- { .type = &abstract_type_string,
- .u.string_val = description }
- };
-
- xen_call_(session, "VDI.set_name_description", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vdi_set_virtual_size(xen_session *session, xen_vdi vdi, int64_t virtual_size)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi },
- { .type = &abstract_type_int,
- .u.int_val = virtual_size }
- };
-
- xen_call_(session, "VDI.set_virtual_size", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vdi_set_sharable(xen_session *session, xen_vdi vdi, bool sharable)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi },
- { .type = &abstract_type_bool,
- .u.bool_val = sharable }
- };
-
- xen_call_(session, "VDI.set_sharable", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vdi_set_read_only(xen_session *session, xen_vdi vdi, bool read_only)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi },
- { .type = &abstract_type_bool,
- .u.bool_val = read_only }
- };
-
- xen_call_(session, "VDI.set_read_only", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vdi_set_other_config(xen_session *session, xen_vdi vdi, xen_string_string_map *other_config)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi },
- { .type = &abstract_type_string_string_map,
- .u.set_val = (arbitrary_set *)other_config }
- };
-
- xen_call_(session, "VDI.set_other_config", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vdi_add_to_other_config(xen_session *session, xen_vdi vdi, char *key, char *value)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi },
- { .type = &abstract_type_string,
- .u.string_val = key },
- { .type = &abstract_type_string,
- .u.string_val = value }
- };
-
- xen_call_(session, "VDI.add_to_other_config", param_values, 3, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vdi_remove_from_other_config(xen_session *session, xen_vdi vdi, char *key)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi },
- { .type = &abstract_type_string,
- .u.string_val = key }
- };
-
- xen_call_(session, "VDI.remove_from_other_config", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_all(xen_session *session, struct xen_vdi_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "VDI.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_uuid(xen_session *session, char **result, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VDI.get_uuid");
- return session->ok;
-}
-
-
-bool
-xen_vdi_set_security_label(xen_session *session, int64_t *result, xen_vdi vdi,
- char *label, char *oldlabel)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi },
- { .type = &abstract_type_string,
- .u.string_val = label },
- { .type = &abstract_type_string,
- .u.string_val = oldlabel },
- };
-
- abstract_type result_type = abstract_type_int;
-
- *result = 0;
- XEN_CALL_("VDI.set_security_label");
- return session->ok;
-}
-
-
-bool
-xen_vdi_get_security_label(xen_session *session, char **result, xen_vdi vdi)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi },
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VDI.get_security_label");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_vdi_type.c b/tools/libxen/src/xen_vdi_type.c
deleted file mode 100644
index 4f0bda7..0000000
--- a/tools/libxen/src/xen_vdi_type.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_vdi_type.h>
-#include "xen_vdi_type_internal.h"
-
-
-/*
- * Maintain this in the same order as the enum declaration!
- */
-static const char *lookup_table[] =
-{
- "system",
- "user",
- "ephemeral",
- "suspend",
- "crashdump"
-};
-
-
-extern xen_vdi_type_set *
-xen_vdi_type_set_alloc(size_t size)
-{
- return calloc(1, sizeof(xen_vdi_type_set) +
- size * sizeof(enum xen_vdi_type));
-}
-
-
-extern void
-xen_vdi_type_set_free(xen_vdi_type_set *set)
-{
- free(set);
-}
-
-
-const char *
-xen_vdi_type_to_string(enum xen_vdi_type val)
-{
- return lookup_table[val];
-}
-
-
-extern enum xen_vdi_type
-xen_vdi_type_from_string(xen_session *session, const char *str)
-{
- return ENUM_LOOKUP(session, str, lookup_table);
-}
-
-
-const abstract_type xen_vdi_type_abstract_type_ =
- {
- .typename = ENUM,
- .enum_marshaller =
- (const char *(*)(int))&xen_vdi_type_to_string,
- .enum_demarshaller =
- (int (*)(xen_session *, const char *))&xen_vdi_type_from_string
- };
-
-
-const abstract_type xen_vdi_type_set_abstract_type_ =
- {
- .typename = SET,
- .child = &xen_vdi_type_abstract_type_
- };
-
-
diff --git a/tools/libxen/src/xen_vif.c b/tools/libxen/src/xen_vif.c
deleted file mode 100644
index ac6147f..0000000
--- a/tools/libxen/src/xen_vif.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_network.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vif.h>
-#include <xen/api/xen_vif_metrics.h>
-#include <xen/api/xen_vm.h>
-
-
-XEN_FREE(xen_vif)
-XEN_SET_ALLOC_FREE(xen_vif)
-XEN_ALLOC(xen_vif_record)
-XEN_SET_ALLOC_FREE(xen_vif_record)
-XEN_ALLOC(xen_vif_record_opt)
-XEN_RECORD_OPT_FREE(xen_vif)
-XEN_SET_ALLOC_FREE(xen_vif_record_opt)
-
-
-static const struct_member xen_vif_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vif_record, uuid) },
- { .key = "device",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vif_record, device) },
- { .key = "network",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_vif_record, network) },
- { .key = "VM",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_vif_record, vm) },
- { .key = "MAC",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vif_record, mac) },
- { .key = "MTU",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vif_record, mtu) },
- { .key = "currently_attached",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_vif_record, currently_attached) },
- { .key = "status_code",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vif_record, status_code) },
- { .key = "status_detail",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vif_record, status_detail) },
- { .key = "runtime_properties",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vif_record, runtime_properties) },
- { .key = "qos_algorithm_type",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vif_record, qos_algorithm_type) },
- { .key = "qos_algorithm_params",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vif_record, qos_algorithm_params) },
- { .key = "qos_supported_algorithms",
- .type = &abstract_type_string_set,
- .offset = offsetof(xen_vif_record, qos_supported_algorithms) },
- { .key = "metrics",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_vif_record, metrics) }
- };
-
-const abstract_type xen_vif_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_vif_record),
- .member_count =
- sizeof(xen_vif_record_struct_members) / sizeof(struct_member),
- .members = xen_vif_record_struct_members
- };
-
-
-void
-xen_vif_record_free(xen_vif_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record->device);
- xen_network_record_opt_free(record->network);
- xen_vm_record_opt_free(record->vm);
- free(record->mac);
- free(record->status_detail);
- xen_string_string_map_free(record->runtime_properties);
- free(record->qos_algorithm_type);
- xen_string_string_map_free(record->qos_algorithm_params);
- xen_string_set_free(record->qos_supported_algorithms);
- xen_vif_metrics_record_opt_free(record->metrics);
- free(record);
-}
-
-
-bool
-xen_vif_get_record(xen_session *session, xen_vif_record **result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- abstract_type result_type = xen_vif_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("VIF.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_vif_get_by_uuid(xen_session *session, xen_vif *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VIF.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_vif_create(xen_session *session, xen_vif *result, xen_vif_record *record)
-{
- abstract_value param_values[] =
- {
- { .type = &xen_vif_record_abstract_type_,
- .u.struct_val = record }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VIF.create");
- return session->ok;
-}
-
-
-bool
-xen_vif_destroy(xen_session *session, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- xen_call_(session, "VIF.destroy", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vif_get_device(xen_session *session, char **result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VIF.get_device");
- return session->ok;
-}
-
-
-bool
-xen_vif_get_network(xen_session *session, xen_network *result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VIF.get_network");
- return session->ok;
-}
-
-
-bool
-xen_vif_get_vm(xen_session *session, xen_vm *result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VIF.get_VM");
- return session->ok;
-}
-
-
-bool
-xen_vif_get_mac(xen_session *session, char **result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VIF.get_MAC");
- return session->ok;
-}
-
-
-bool
-xen_vif_get_mtu(xen_session *session, int64_t *result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VIF.get_MTU");
- return session->ok;
-}
-
-
-bool
-xen_vif_get_currently_attached(xen_session *session, bool *result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("VIF.get_currently_attached");
- return session->ok;
-}
-
-
-bool
-xen_vif_get_status_code(xen_session *session, int64_t *result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VIF.get_status_code");
- return session->ok;
-}
-
-
-bool
-xen_vif_get_status_detail(xen_session *session, char **result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VIF.get_status_detail");
- return session->ok;
-}
-
-
-bool
-xen_vif_get_runtime_properties(xen_session *session, xen_string_string_map **result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VIF.get_runtime_properties");
- return session->ok;
-}
-
-
-bool
-xen_vif_get_qos_algorithm_type(xen_session *session, char **result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VIF.get_qos_algorithm_type");
- return session->ok;
-}
-
-
-bool
-xen_vif_get_qos_algorithm_params(xen_session *session, xen_string_string_map **result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VIF.get_qos_algorithm_params");
- return session->ok;
-}
-
-
-bool
-xen_vif_get_qos_supported_algorithms(xen_session *session, struct xen_string_set **result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("VIF.get_qos_supported_algorithms");
- return session->ok;
-}
-
-
-bool
-xen_vif_get_metrics(xen_session *session, xen_vif_metrics *result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VIF.get_metrics");
- return session->ok;
-}
-
-
-bool
-xen_vif_set_device(xen_session *session, xen_vif vif, char *device)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif },
- { .type = &abstract_type_string,
- .u.string_val = device }
- };
-
- xen_call_(session, "VIF.set_device", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vif_set_mac(xen_session *session, xen_vif vif, char *mac)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif },
- { .type = &abstract_type_string,
- .u.string_val = mac }
- };
-
- xen_call_(session, "VIF.set_MAC", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vif_set_mtu(xen_session *session, xen_vif vif, int64_t mtu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif },
- { .type = &abstract_type_int,
- .u.int_val = mtu }
- };
-
- xen_call_(session, "VIF.set_MTU", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vif_set_qos_algorithm_type(xen_session *session, xen_vif vif, char *algorithm_type)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif },
- { .type = &abstract_type_string,
- .u.string_val = algorithm_type }
- };
-
- xen_call_(session, "VIF.set_qos_algorithm_type", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vif_set_qos_algorithm_params(xen_session *session, xen_vif vif, xen_string_string_map *algorithm_params)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif },
- { .type = &abstract_type_string_string_map,
- .u.set_val = (arbitrary_set *)algorithm_params }
- };
-
- xen_call_(session, "VIF.set_qos_algorithm_params", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vif_add_to_qos_algorithm_params(xen_session *session, xen_vif vif, char *key, char *value)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif },
- { .type = &abstract_type_string,
- .u.string_val = key },
- { .type = &abstract_type_string,
- .u.string_val = value }
- };
-
- xen_call_(session, "VIF.add_to_qos_algorithm_params", param_values, 3, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vif_remove_from_qos_algorithm_params(xen_session *session, xen_vif vif, char *key)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif },
- { .type = &abstract_type_string,
- .u.string_val = key }
- };
-
- xen_call_(session, "VIF.remove_from_qos_algorithm_params", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vif_plug(xen_session *session, xen_vif self)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = self }
- };
-
- xen_call_(session, "VIF.plug", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vif_unplug(xen_session *session, xen_vif self)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = self }
- };
-
- xen_call_(session, "VIF.unplug", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vif_get_all(xen_session *session, struct xen_vif_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "VIF.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_vif_get_uuid(xen_session *session, char **result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VIF.get_uuid");
- return session->ok;
-}
-
-
-bool
-xen_vif_set_security_label(xen_session *session, int64_t *result, xen_vif vif,
- char *label, char *oldlabel)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif },
- { .type = &abstract_type_string,
- .u.string_val = label },
- { .type = &abstract_type_string,
- .u.string_val = oldlabel },
- };
-
- abstract_type result_type = abstract_type_int;
-
- *result = 0;
- XEN_CALL_("VIF.set_security_label");
- return session->ok;
-}
-
-
-bool
-xen_vif_get_security_label(xen_session *session, char **result, xen_vif vif)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif },
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VIF.get_security_label");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_vif_metrics.c b/tools/libxen/src/xen_vif_metrics.c
deleted file mode 100644
index 9b876e5..0000000
--- a/tools/libxen/src/xen_vif_metrics.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_vif_metrics.h>
-
-
-XEN_FREE(xen_vif_metrics)
-XEN_SET_ALLOC_FREE(xen_vif_metrics)
-XEN_ALLOC(xen_vif_metrics_record)
-XEN_SET_ALLOC_FREE(xen_vif_metrics_record)
-XEN_ALLOC(xen_vif_metrics_record_opt)
-XEN_RECORD_OPT_FREE(xen_vif_metrics)
-XEN_SET_ALLOC_FREE(xen_vif_metrics_record_opt)
-
-
-static const struct_member xen_vif_metrics_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vif_metrics_record, uuid) },
- { .key = "io_read_kbs",
- .type = &abstract_type_float,
- .offset = offsetof(xen_vif_metrics_record, io_read_kbs) },
- { .key = "io_write_kbs",
- .type = &abstract_type_float,
- .offset = offsetof(xen_vif_metrics_record, io_write_kbs) },
- { .key = "last_updated",
- .type = &abstract_type_datetime,
- .offset = offsetof(xen_vif_metrics_record, last_updated) }
- };
-
-const abstract_type xen_vif_metrics_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_vif_metrics_record),
- .member_count =
- sizeof(xen_vif_metrics_record_struct_members) / sizeof(struct_member),
- .members = xen_vif_metrics_record_struct_members
- };
-
-
-void
-xen_vif_metrics_record_free(xen_vif_metrics_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record);
-}
-
-
-bool
-xen_vif_metrics_get_record(xen_session *session, xen_vif_metrics_record **result, xen_vif_metrics vif_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif_metrics }
- };
-
- abstract_type result_type = xen_vif_metrics_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("VIF_metrics.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_vif_metrics_get_by_uuid(xen_session *session, xen_vif_metrics *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VIF_metrics.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_vif_metrics_get_io_read_kbs(xen_session *session, double *result, xen_vif_metrics vif_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif_metrics }
- };
-
- abstract_type result_type = abstract_type_float;
-
- XEN_CALL_("VIF_metrics.get_io_read_kbs");
- return session->ok;
-}
-
-
-bool
-xen_vif_metrics_get_io_write_kbs(xen_session *session, double *result, xen_vif_metrics vif_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif_metrics }
- };
-
- abstract_type result_type = abstract_type_float;
-
- XEN_CALL_("VIF_metrics.get_io_write_kbs");
- return session->ok;
-}
-
-
-bool
-xen_vif_metrics_get_last_updated(xen_session *session, time_t *result, xen_vif_metrics vif_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif_metrics }
- };
-
- abstract_type result_type = abstract_type_datetime;
-
- XEN_CALL_("VIF_metrics.get_last_updated");
- return session->ok;
-}
-
-
-bool
-xen_vif_metrics_get_all(xen_session *session, struct xen_vif_metrics_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "VIF_metrics.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_vif_metrics_get_uuid(xen_session *session, char **result, xen_vif_metrics vif_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vif_metrics }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VIF_metrics.get_uuid");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_vm.c b/tools/libxen/src/xen_vm.c
deleted file mode 100644
index dcd650c..0000000
--- a/tools/libxen/src/xen_vm.c
+++ /dev/null
@@ -1,1837 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include "xen_on_crash_behaviour_internal.h"
-#include "xen_on_normal_exit_internal.h"
-#include "xen_vm_power_state_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_console.h>
-#include <xen/api/xen_crashdump.h>
-#include <xen/api/xen_host.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vbd.h>
-#include <xen/api/xen_vdi.h>
-#include <xen/api/xen_vif.h>
-#include <xen/api/xen_vm.h>
-#include <xen/api/xen_vm_guest_metrics.h>
-#include <xen/api/xen_vm_metrics.h>
-#include <xen/api/xen_cpu_pool.h>
-
-
-XEN_FREE(xen_vm)
-XEN_SET_ALLOC_FREE(xen_vm)
-XEN_ALLOC(xen_vm_record)
-XEN_SET_ALLOC_FREE(xen_vm_record)
-XEN_ALLOC(xen_vm_record_opt)
-XEN_RECORD_OPT_FREE(xen_vm)
-XEN_SET_ALLOC_FREE(xen_vm_record_opt)
-
-
-static const struct_member xen_vm_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vm_record, uuid) },
- { .key = "power_state",
- .type = &xen_vm_power_state_abstract_type_,
- .offset = offsetof(xen_vm_record, power_state) },
- { .key = "name_label",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vm_record, name_label) },
- { .key = "name_description",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vm_record, name_description) },
- { .key = "user_version",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vm_record, user_version) },
- { .key = "is_a_template",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_vm_record, is_a_template) },
- { .key = "auto_power_on",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_vm_record, auto_power_on) },
- { .key = "suspend_VDI",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_vm_record, suspend_vdi) },
- { .key = "resident_on",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_vm_record, resident_on) },
- { .key = "memory_static_max",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vm_record, memory_static_max) },
- { .key = "memory_dynamic_max",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vm_record, memory_dynamic_max) },
- { .key = "memory_dynamic_min",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vm_record, memory_dynamic_min) },
- { .key = "memory_static_min",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vm_record, memory_static_min) },
- { .key = "VCPUs_params",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vm_record, vcpus_params) },
- { .key = "VCPUs_max",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vm_record, vcpus_max) },
- { .key = "VCPUs_at_startup",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vm_record, vcpus_at_startup) },
- { .key = "actions_after_shutdown",
- .type = &xen_on_normal_exit_abstract_type_,
- .offset = offsetof(xen_vm_record, actions_after_shutdown) },
- { .key = "actions_after_reboot",
- .type = &xen_on_normal_exit_abstract_type_,
- .offset = offsetof(xen_vm_record, actions_after_reboot) },
- { .key = "actions_after_crash",
- .type = &xen_on_crash_behaviour_abstract_type_,
- .offset = offsetof(xen_vm_record, actions_after_crash) },
- { .key = "consoles",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_vm_record, consoles) },
- { .key = "VIFs",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_vm_record, vifs) },
- { .key = "VBDs",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_vm_record, vbds) },
- { .key = "crash_dumps",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_vm_record, crash_dumps) },
- { .key = "PV_bootloader",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vm_record, pv_bootloader) },
- { .key = "PV_kernel",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vm_record, pv_kernel) },
- { .key = "PV_ramdisk",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vm_record, pv_ramdisk) },
- { .key = "PV_args",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vm_record, pv_args) },
- { .key = "PV_bootloader_args",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vm_record, pv_bootloader_args) },
- { .key = "HVM_boot_policy",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vm_record, hvm_boot_policy) },
- { .key = "HVM_boot_params",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vm_record, hvm_boot_params) },
- { .key = "platform",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vm_record, platform) },
- { .key = "PCI_bus",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vm_record, pci_bus) },
- { .key = "other_config",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vm_record, other_config) },
- { .key = "domid",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vm_record, domid) },
- { .key = "is_control_domain",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_vm_record, is_control_domain) },
- { .key = "metrics",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_vm_record, metrics) },
- { .key = "guest_metrics",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_vm_record, guest_metrics) },
- { .key = "security_label",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vm_record, security_label) },
- { .key = "pool_name",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vm_record, pool_name) },
- { .key = "cpu_pool",
- .type = &abstract_type_ref_set,
- .offset = offsetof(xen_vm_record, cpu_pool) },
- };
-
-const abstract_type xen_vm_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_vm_record),
- .member_count =
- sizeof(xen_vm_record_struct_members) / sizeof(struct_member),
- .members = xen_vm_record_struct_members
- };
-
-
-void
-xen_vm_record_free(xen_vm_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record->name_label);
- free(record->name_description);
- xen_vdi_record_opt_free(record->suspend_vdi);
- xen_host_record_opt_free(record->resident_on);
- xen_string_string_map_free(record->vcpus_params);
- xen_console_record_opt_set_free(record->consoles);
- xen_vif_record_opt_set_free(record->vifs);
- xen_vbd_record_opt_set_free(record->vbds);
- xen_crashdump_record_opt_set_free(record->crash_dumps);
- free(record->pv_bootloader);
- free(record->pv_kernel);
- free(record->pv_ramdisk);
- free(record->pv_args);
- free(record->pv_bootloader_args);
- free(record->hvm_boot_policy);
- xen_string_string_map_free(record->hvm_boot_params);
- xen_string_string_map_free(record->platform);
- free(record->pci_bus);
- xen_string_string_map_free(record->other_config);
- xen_vm_metrics_record_opt_free(record->metrics);
- xen_vm_guest_metrics_record_opt_free(record->guest_metrics);
- xen_cpu_pool_record_opt_set_free(record->cpu_pool);
- free(record->security_label);
- free(record);
-}
-
-
-bool
-xen_vm_get_record(xen_session *session, xen_vm_record **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = xen_vm_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("VM.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_vm_get_by_uuid(xen_session *session, xen_vm *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_vm_create(xen_session *session, xen_vm *result, xen_vm_record *record)
-{
- abstract_value param_values[] =
- {
- { .type = &xen_vm_record_abstract_type_,
- .u.struct_val = record }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.create");
- return session->ok;
-}
-
-
-bool
-xen_vm_destroy(xen_session *session, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- xen_call_(session, "VM.destroy", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_get_by_name_label(xen_session *session, struct xen_vm_set **result, char *label)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = label }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("VM.get_by_name_label");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_power_state(xen_session *session, enum xen_vm_power_state *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = xen_vm_power_state_abstract_type_;
- XEN_CALL_("VM.get_power_state");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_name_label(xen_session *session, char **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_name_label");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_name_description(xen_session *session, char **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_name_description");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_user_version(xen_session *session, int64_t *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VM.get_user_version");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_is_a_template(xen_session *session, bool *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("VM.get_is_a_template");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_auto_power_on(xen_session *session, bool *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("VM.get_auto_power_on");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_suspend_vdi(xen_session *session, xen_vdi *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_suspend_VDI");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_resident_on(xen_session *session, xen_host *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_resident_on");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_memory_static_max(xen_session *session, int64_t *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VM.get_memory_static_max");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_memory_dynamic_max(xen_session *session, int64_t *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VM.get_memory_dynamic_max");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_memory_dynamic_min(xen_session *session, int64_t *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VM.get_memory_dynamic_min");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_memory_static_min(xen_session *session, int64_t *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VM.get_memory_static_min");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_vcpus_params(xen_session *session, xen_string_string_map **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VM.get_VCPUs_params");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_vcpus_max(xen_session *session, int64_t *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VM.get_VCPUs_max");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_vcpus_at_startup(xen_session *session, int64_t *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VM.get_VCPUs_at_startup");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_actions_after_shutdown(xen_session *session, enum xen_on_normal_exit *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = xen_on_normal_exit_abstract_type_;
- XEN_CALL_("VM.get_actions_after_shutdown");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_actions_after_reboot(xen_session *session, enum xen_on_normal_exit *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = xen_on_normal_exit_abstract_type_;
- XEN_CALL_("VM.get_actions_after_reboot");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_actions_after_crash(xen_session *session, enum xen_on_crash_behaviour *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = xen_on_crash_behaviour_abstract_type_;
- XEN_CALL_("VM.get_actions_after_crash");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_consoles(xen_session *session, struct xen_console_set **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("VM.get_consoles");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_vifs(xen_session *session, struct xen_vif_set **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("VM.get_VIFs");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_vbds(xen_session *session, struct xen_vbd_set **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("VM.get_VBDs");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_crash_dumps(xen_session *session, struct xen_crashdump_set **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("VM.get_crash_dumps");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_pv_bootloader(xen_session *session, char **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_PV_bootloader");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_pv_kernel(xen_session *session, char **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_PV_kernel");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_pv_ramdisk(xen_session *session, char **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_PV_ramdisk");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_pv_args(xen_session *session, char **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_PV_args");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_pv_bootloader_args(xen_session *session, char **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_PV_bootloader_args");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_hvm_boot_policy(xen_session *session, char **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_HVM_boot_policy");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_hvm_boot_params(xen_session *session, xen_string_string_map **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VM.get_HVM_boot_params");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_platform(xen_session *session, xen_string_string_map **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VM.get_platform");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_pci_bus(xen_session *session, char **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_PCI_bus");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_other_config(xen_session *session, xen_string_string_map **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VM.get_other_config");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_domid(xen_session *session, int64_t *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VM.get_domid");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_is_control_domain(xen_session *session, bool *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("VM.get_is_control_domain");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_metrics(xen_session *session, xen_vm_metrics *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_metrics");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_guest_metrics(xen_session *session, xen_vm_guest_metrics *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_guest_metrics");
- return session->ok;
-}
-
-
-bool
-xen_vm_set_name_label(xen_session *session, xen_vm vm, char *label)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = label }
- };
-
- xen_call_(session, "VM.set_name_label", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_name_description(xen_session *session, xen_vm vm, char *description)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = description }
- };
-
- xen_call_(session, "VM.set_name_description", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_user_version(xen_session *session, xen_vm vm, int64_t user_version)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_int,
- .u.int_val = user_version }
- };
-
- xen_call_(session, "VM.set_user_version", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_is_a_template(xen_session *session, xen_vm vm, bool is_a_template)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_bool,
- .u.bool_val = is_a_template }
- };
-
- xen_call_(session, "VM.set_is_a_template", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_auto_power_on(xen_session *session, xen_vm vm, bool auto_power_on)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_bool,
- .u.bool_val = auto_power_on }
- };
-
- xen_call_(session, "VM.set_auto_power_on", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_memory_static_max(xen_session *session, xen_vm vm, int64_t static_max)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_int,
- .u.int_val = static_max }
- };
-
- xen_call_(session, "VM.set_memory_static_max", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_memory_dynamic_max(xen_session *session, xen_vm vm, int64_t dynamic_max)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_int,
- .u.int_val = dynamic_max }
- };
-
- xen_call_(session, "VM.set_memory_dynamic_max", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_memory_dynamic_min(xen_session *session, xen_vm vm, int64_t dynamic_min)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_int,
- .u.int_val = dynamic_min }
- };
-
- xen_call_(session, "VM.set_memory_dynamic_min", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_memory_static_min(xen_session *session, xen_vm vm, int64_t static_min)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_int,
- .u.int_val = static_min }
- };
-
- xen_call_(session, "VM.set_memory_static_min", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_vcpus_params(xen_session *session, xen_vm vm, xen_string_string_map *params)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string_string_map,
- .u.set_val = (arbitrary_set *)params }
- };
-
- xen_call_(session, "VM.set_VCPUs_params", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_add_to_vcpus_params(xen_session *session, xen_vm vm, char *key, char *value)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = key },
- { .type = &abstract_type_string,
- .u.string_val = value }
- };
-
- xen_call_(session, "VM.add_to_VCPUs_params", param_values, 3, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_remove_from_vcpus_params(xen_session *session, xen_vm vm, char *key)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = key }
- };
-
- xen_call_(session, "VM.remove_from_VCPUs_params", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_vcpus_max(xen_session *session, xen_vm vm, int64_t max)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_int,
- .u.int_val = max }
- };
-
- xen_call_(session, "VM.set_VCPUs_max", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_vcpus_at_startup(xen_session *session, xen_vm vm, int64_t at_startup)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_int,
- .u.int_val = at_startup }
- };
-
- xen_call_(session, "VM.set_VCPUs_at_startup", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_actions_after_shutdown(xen_session *session, xen_vm vm, enum xen_on_normal_exit after_shutdown)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &xen_on_normal_exit_abstract_type_,
- .u.enum_val = after_shutdown }
- };
-
- xen_call_(session, "VM.set_actions_after_shutdown", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_actions_after_reboot(xen_session *session, xen_vm vm, enum xen_on_normal_exit after_reboot)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &xen_on_normal_exit_abstract_type_,
- .u.enum_val = after_reboot }
- };
-
- xen_call_(session, "VM.set_actions_after_reboot", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_actions_after_crash(xen_session *session, xen_vm vm, enum xen_on_crash_behaviour after_crash)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &xen_on_crash_behaviour_abstract_type_,
- .u.enum_val = after_crash }
- };
-
- xen_call_(session, "VM.set_actions_after_crash", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_pv_bootloader(xen_session *session, xen_vm vm, char *bootloader)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = bootloader }
- };
-
- xen_call_(session, "VM.set_PV_bootloader", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_pv_kernel(xen_session *session, xen_vm vm, char *kernel)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = kernel }
- };
-
- xen_call_(session, "VM.set_PV_kernel", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_pv_ramdisk(xen_session *session, xen_vm vm, char *ramdisk)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = ramdisk }
- };
-
- xen_call_(session, "VM.set_PV_ramdisk", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_pv_args(xen_session *session, xen_vm vm, char *args)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = args }
- };
-
- xen_call_(session, "VM.set_PV_args", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_pv_bootloader_args(xen_session *session, xen_vm vm, char *bootloader_args)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = bootloader_args }
- };
-
- xen_call_(session, "VM.set_PV_bootloader_args", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_hvm_boot_policy(xen_session *session, xen_vm vm, char *boot_policy)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = boot_policy }
- };
-
- xen_call_(session, "VM.set_HVM_boot_policy", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_hvm_boot_params(xen_session *session, xen_vm vm, xen_string_string_map *boot_params)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string_string_map,
- .u.set_val = (arbitrary_set *)boot_params }
- };
-
- xen_call_(session, "VM.set_HVM_boot_params", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_add_to_hvm_boot_params(xen_session *session, xen_vm vm, char *key, char *value)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = key },
- { .type = &abstract_type_string,
- .u.string_val = value }
- };
-
- xen_call_(session, "VM.add_to_HVM_boot_params", param_values, 3, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_remove_from_hvm_boot_params(xen_session *session, xen_vm vm, char *key)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = key }
- };
-
- xen_call_(session, "VM.remove_from_HVM_boot_params", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_platform(xen_session *session, xen_vm vm, xen_string_string_map *platform)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string_string_map,
- .u.set_val = (arbitrary_set *)platform }
- };
-
- xen_call_(session, "VM.set_platform", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_add_to_platform(xen_session *session, xen_vm vm, char *key, char *value)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = key },
- { .type = &abstract_type_string,
- .u.string_val = value }
- };
-
- xen_call_(session, "VM.add_to_platform", param_values, 3, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_remove_from_platform(xen_session *session, xen_vm vm, char *key)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = key }
- };
-
- xen_call_(session, "VM.remove_from_platform", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_pci_bus(xen_session *session, xen_vm vm, char *pci_bus)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = pci_bus }
- };
-
- xen_call_(session, "VM.set_PCI_bus", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_other_config(xen_session *session, xen_vm vm, xen_string_string_map *other_config)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string_string_map,
- .u.set_val = (arbitrary_set *)other_config }
- };
-
- xen_call_(session, "VM.set_other_config", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_add_to_other_config(xen_session *session, xen_vm vm, char *key, char *value)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = key },
- { .type = &abstract_type_string,
- .u.string_val = value }
- };
-
- xen_call_(session, "VM.add_to_other_config", param_values, 3, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_remove_from_other_config(xen_session *session, xen_vm vm, char *key)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = key }
- };
-
- xen_call_(session, "VM.remove_from_other_config", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_clone(xen_session *session, xen_vm *result, xen_vm vm, char *new_name)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = new_name }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.clone");
- return session->ok;
-}
-
-
-bool
-xen_vm_start(xen_session *session, xen_vm vm, bool start_paused)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_bool,
- .u.bool_val = start_paused }
- };
-
- xen_call_(session, "VM.start", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_pause(xen_session *session, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- xen_call_(session, "VM.pause", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_unpause(xen_session *session, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- xen_call_(session, "VM.unpause", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_clean_shutdown(xen_session *session, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- xen_call_(session, "VM.clean_shutdown", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_clean_reboot(xen_session *session, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- xen_call_(session, "VM.clean_reboot", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_hard_shutdown(xen_session *session, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- xen_call_(session, "VM.hard_shutdown", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_hard_reboot(xen_session *session, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- xen_call_(session, "VM.hard_reboot", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_suspend(xen_session *session, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- xen_call_(session, "VM.suspend", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_resume(xen_session *session, xen_vm vm, bool start_paused)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_bool,
- .u.bool_val = start_paused }
- };
-
- xen_call_(session, "VM.resume", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_vcpus_number_live(xen_session *session, xen_vm self, int64_t nvcpu)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = self },
- { .type = &abstract_type_int,
- .u.int_val = nvcpu }
- };
-
- xen_call_(session, "VM.set_VCPUs_number_live", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_add_to_vcpus_params_live(xen_session *session, xen_vm self, char *key, char *value)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = self },
- { .type = &abstract_type_string,
- .u.string_val = key },
- { .type = &abstract_type_string,
- .u.string_val = value }
- };
-
- xen_call_(session, "VM.add_to_VCPUs_params_live", param_values, 3, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_memory_dynamic_max_live(xen_session *session, xen_vm self, int64_t max)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = self },
- { .type = &abstract_type_int,
- .u.int_val = max }
- };
-
- xen_call_(session, "VM.set_memory_dynamic_max_live", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_memory_dynamic_min_live(xen_session *session, xen_vm self, int64_t min)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = self },
- { .type = &abstract_type_int,
- .u.int_val = min }
- };
-
- xen_call_(session, "VM.set_memory_dynamic_min_live", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_send_sysrq(xen_session *session, xen_vm vm, char *key)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = key }
- };
-
- xen_call_(session, "VM.send_sysrq", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_send_trigger(xen_session *session, xen_vm vm, char *trigger)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = trigger }
- };
-
- xen_call_(session, "VM.send_trigger", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_migrate(xen_session *session, xen_vm vm, char *dest, bool live, xen_string_string_map *options)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = dest },
- { .type = &abstract_type_bool,
- .u.bool_val = live },
- { .type = &abstract_type_string_string_map,
- .u.set_val = (arbitrary_set *)options }
- };
-
- xen_call_(session, "VM.migrate", param_values, 4, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_get_all(xen_session *session, struct xen_vm_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "VM.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_vm_get_uuid(xen_session *session, char **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_uuid");
- return session->ok;
-}
-
-
-bool
-xen_vm_set_security_label(xen_session *session, int64_t *result, xen_vm vm,
- char *label, char *oldlabel)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = label },
- { .type = &abstract_type_string,
- .u.string_val = oldlabel },
- };
-
- abstract_type result_type = abstract_type_int;
-
- *result = 0;
- XEN_CALL_("VM.set_security_label");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_security_label(xen_session *session, char **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_security_label");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_cpu_pool(xen_session *session, struct xen_cpu_pool_set **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("VM.get_cpu_pool");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_pool_name(xen_session *session, char **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_pool_name");
- return session->ok;
-}
-
-
-bool
-xen_vm_set_pool_name(xen_session *session, xen_vm vm, char *pool_name)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = pool_name }
- };
-
- xen_call_(session, "VM.set_pool_name", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_cpu_pool_migrate(xen_session *session, xen_vm vm, xen_cpu_pool cpu_pool)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = cpu_pool }
- };
-
- xen_call_(session, "VM.cpu_pool_migrate", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
diff --git a/tools/libxen/src/xen_vm_guest_metrics.c b/tools/libxen/src/xen_vm_guest_metrics.c
deleted file mode 100644
index 251b65e..0000000
--- a/tools/libxen/src/xen_vm_guest_metrics.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vm_guest_metrics.h>
-
-
-XEN_FREE(xen_vm_guest_metrics)
-XEN_SET_ALLOC_FREE(xen_vm_guest_metrics)
-XEN_ALLOC(xen_vm_guest_metrics_record)
-XEN_SET_ALLOC_FREE(xen_vm_guest_metrics_record)
-XEN_ALLOC(xen_vm_guest_metrics_record_opt)
-XEN_RECORD_OPT_FREE(xen_vm_guest_metrics)
-XEN_SET_ALLOC_FREE(xen_vm_guest_metrics_record_opt)
-
-
-static const struct_member xen_vm_guest_metrics_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vm_guest_metrics_record, uuid) },
- { .key = "os_version",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vm_guest_metrics_record, os_version) },
- { .key = "PV_drivers_version",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vm_guest_metrics_record, pv_drivers_version) },
- { .key = "memory",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vm_guest_metrics_record, memory) },
- { .key = "disks",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vm_guest_metrics_record, disks) },
- { .key = "networks",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vm_guest_metrics_record, networks) },
- { .key = "other",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vm_guest_metrics_record, other) },
- { .key = "last_updated",
- .type = &abstract_type_datetime,
- .offset = offsetof(xen_vm_guest_metrics_record, last_updated) }
- };
-
-const abstract_type xen_vm_guest_metrics_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_vm_guest_metrics_record),
- .member_count =
- sizeof(xen_vm_guest_metrics_record_struct_members) / sizeof(struct_member),
- .members = xen_vm_guest_metrics_record_struct_members
- };
-
-
-void
-xen_vm_guest_metrics_record_free(xen_vm_guest_metrics_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- xen_string_string_map_free(record->os_version);
- xen_string_string_map_free(record->pv_drivers_version);
- xen_string_string_map_free(record->memory);
- xen_string_string_map_free(record->disks);
- xen_string_string_map_free(record->networks);
- xen_string_string_map_free(record->other);
- free(record);
-}
-
-
-bool
-xen_vm_guest_metrics_get_record(xen_session *session, xen_vm_guest_metrics_record **result, xen_vm_guest_metrics vm_guest_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_guest_metrics }
- };
-
- abstract_type result_type = xen_vm_guest_metrics_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("VM_guest_metrics.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_vm_guest_metrics_get_by_uuid(xen_session *session, xen_vm_guest_metrics *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM_guest_metrics.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_vm_guest_metrics_get_os_version(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_guest_metrics }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VM_guest_metrics.get_os_version");
- return session->ok;
-}
-
-
-bool
-xen_vm_guest_metrics_get_pv_drivers_version(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_guest_metrics }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VM_guest_metrics.get_PV_drivers_version");
- return session->ok;
-}
-
-
-bool
-xen_vm_guest_metrics_get_memory(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_guest_metrics }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VM_guest_metrics.get_memory");
- return session->ok;
-}
-
-
-bool
-xen_vm_guest_metrics_get_disks(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_guest_metrics }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VM_guest_metrics.get_disks");
- return session->ok;
-}
-
-
-bool
-xen_vm_guest_metrics_get_networks(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_guest_metrics }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VM_guest_metrics.get_networks");
- return session->ok;
-}
-
-
-bool
-xen_vm_guest_metrics_get_other(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_guest_metrics }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VM_guest_metrics.get_other");
- return session->ok;
-}
-
-
-bool
-xen_vm_guest_metrics_get_last_updated(xen_session *session, time_t *result, xen_vm_guest_metrics vm_guest_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_guest_metrics }
- };
-
- abstract_type result_type = abstract_type_datetime;
-
- XEN_CALL_("VM_guest_metrics.get_last_updated");
- return session->ok;
-}
-
-
-bool
-xen_vm_guest_metrics_get_all(xen_session *session, struct xen_vm_guest_metrics_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "VM_guest_metrics.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_vm_guest_metrics_get_uuid(xen_session *session, char **result, xen_vm_guest_metrics vm_guest_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_guest_metrics }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM_guest_metrics.get_uuid");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_vm_metrics.c b/tools/libxen/src/xen_vm_metrics.c
deleted file mode 100644
index 7f2ab94..0000000
--- a/tools/libxen/src/xen_vm_metrics.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_common.h>
-#include <xen/api/xen_int_float_map.h>
-#include <xen/api/xen_int_int_map.h>
-#include <xen/api/xen_int_string_set_map.h>
-#include <xen/api/xen_string_string_map.h>
-#include <xen/api/xen_vm_metrics.h>
-
-
-XEN_FREE(xen_vm_metrics)
-XEN_SET_ALLOC_FREE(xen_vm_metrics)
-XEN_ALLOC(xen_vm_metrics_record)
-XEN_SET_ALLOC_FREE(xen_vm_metrics_record)
-XEN_ALLOC(xen_vm_metrics_record_opt)
-XEN_RECORD_OPT_FREE(xen_vm_metrics)
-XEN_SET_ALLOC_FREE(xen_vm_metrics_record_opt)
-
-
-static const struct_member xen_vm_metrics_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vm_metrics_record, uuid) },
- { .key = "memory_actual",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vm_metrics_record, memory_actual) },
- { .key = "VCPUs_number",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vm_metrics_record, vcpus_number) },
- { .key = "VCPUs_utilisation",
- .type = &abstract_type_int_float_map,
- .offset = offsetof(xen_vm_metrics_record, vcpus_utilisation) },
- { .key = "VCPUs_CPU",
- .type = &abstract_type_int_int_map,
- .offset = offsetof(xen_vm_metrics_record, vcpus_cpu) },
- { .key = "VCPUs_params",
- .type = &abstract_type_string_string_map,
- .offset = offsetof(xen_vm_metrics_record, vcpus_params) },
- { .key = "VCPUs_flags",
- .type = &abstract_type_int_string_set_map,
- .offset = offsetof(xen_vm_metrics_record, vcpus_flags) },
- { .key = "state",
- .type = &abstract_type_string_set,
- .offset = offsetof(xen_vm_metrics_record, state) },
- { .key = "start_time",
- .type = &abstract_type_datetime,
- .offset = offsetof(xen_vm_metrics_record, start_time) },
- { .key = "last_updated",
- .type = &abstract_type_datetime,
- .offset = offsetof(xen_vm_metrics_record, last_updated) }
- };
-
-const abstract_type xen_vm_metrics_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_vm_metrics_record),
- .member_count =
- sizeof(xen_vm_metrics_record_struct_members) / sizeof(struct_member),
- .members = xen_vm_metrics_record_struct_members
- };
-
-
-void
-xen_vm_metrics_record_free(xen_vm_metrics_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- xen_int_float_map_free(record->vcpus_utilisation);
- xen_int_int_map_free(record->vcpus_cpu);
- xen_string_string_map_free(record->vcpus_params);
- xen_int_string_set_map_free(record->vcpus_flags);
- xen_string_set_free(record->state);
- free(record);
-}
-
-
-bool
-xen_vm_metrics_get_record(xen_session *session, xen_vm_metrics_record **result, xen_vm_metrics vm_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_metrics }
- };
-
- abstract_type result_type = xen_vm_metrics_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("VM_metrics.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_vm_metrics_get_by_uuid(xen_session *session, xen_vm_metrics *result, char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM_metrics.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_vm_metrics_get_memory_actual(xen_session *session, int64_t *result, xen_vm_metrics vm_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_metrics }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VM_metrics.get_memory_actual");
- return session->ok;
-}
-
-
-bool
-xen_vm_metrics_get_vcpus_number(xen_session *session, int64_t *result, xen_vm_metrics vm_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_metrics }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VM_metrics.get_VCPUs_number");
- return session->ok;
-}
-
-
-bool
-xen_vm_metrics_get_vcpus_utilisation(xen_session *session, xen_int_float_map **result, xen_vm_metrics vm_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_metrics }
- };
-
- abstract_type result_type = abstract_type_int_float_map;
-
- *result = NULL;
- XEN_CALL_("VM_metrics.get_VCPUs_utilisation");
- return session->ok;
-}
-
-
-bool
-xen_vm_metrics_get_vcpus_cpu(xen_session *session, xen_int_int_map **result, xen_vm_metrics vm_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_metrics }
- };
-
- abstract_type result_type = abstract_type_int_int_map;
-
- *result = NULL;
- XEN_CALL_("VM_metrics.get_VCPUs_CPU");
- return session->ok;
-}
-
-
-bool
-xen_vm_metrics_get_vcpus_params(xen_session *session, xen_string_string_map **result, xen_vm_metrics vm_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_metrics }
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("VM_metrics.get_VCPUs_params");
- return session->ok;
-}
-
-
-bool
-xen_vm_metrics_get_vcpus_flags(xen_session *session, xen_int_string_set_map **result, xen_vm_metrics vm_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_metrics }
- };
-
- abstract_type result_type = abstract_type_int_string_set_map;
-
- *result = NULL;
- XEN_CALL_("VM_metrics.get_VCPUs_flags");
- return session->ok;
-}
-
-
-bool
-xen_vm_metrics_get_state(xen_session *session, struct xen_string_set **result, xen_vm_metrics vm_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_metrics }
- };
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- XEN_CALL_("VM_metrics.get_state");
- return session->ok;
-}
-
-
-bool
-xen_vm_metrics_get_start_time(xen_session *session, time_t *result, xen_vm_metrics vm_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_metrics }
- };
-
- abstract_type result_type = abstract_type_datetime;
-
- XEN_CALL_("VM_metrics.get_start_time");
- return session->ok;
-}
-
-
-bool
-xen_vm_metrics_get_last_updated(xen_session *session, time_t *result, xen_vm_metrics vm_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_metrics }
- };
-
- abstract_type result_type = abstract_type_datetime;
-
- XEN_CALL_("VM_metrics.get_last_updated");
- return session->ok;
-}
-
-
-bool
-xen_vm_metrics_get_all(xen_session *session, struct xen_vm_metrics_set **result)
-{
-
- abstract_type result_type = abstract_type_string_set;
-
- *result = NULL;
- xen_call_(session, "VM_metrics.get_all", NULL, 0, &result_type, result);
- return session->ok;
-}
-
-
-bool
-xen_vm_metrics_get_uuid(xen_session *session, char **result, xen_vm_metrics vm_metrics)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm_metrics }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM_metrics.get_uuid");
- return session->ok;
-}
diff --git a/tools/libxen/src/xen_vm_power_state.c b/tools/libxen/src/xen_vm_power_state.c
deleted file mode 100644
index 377f9ec..0000000
--- a/tools/libxen/src/xen_vm_power_state.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2006-2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-
-#include "xen_internal.h"
-#include <xen/api/xen_vm_power_state.h>
-#include "xen_vm_power_state_internal.h"
-
-
-/*
- * Maintain this in the same order as the enum declaration!
- */
-static const char *lookup_table[] =
-{
- "Halted",
- "Paused",
- "Running",
- "Suspended",
- "Crashed",
- "Unknown"
-};
-
-
-extern xen_vm_power_state_set *
-xen_vm_power_state_set_alloc(size_t size)
-{
- return calloc(1, sizeof(xen_vm_power_state_set) +
- size * sizeof(enum xen_vm_power_state));
-}
-
-
-extern void
-xen_vm_power_state_set_free(xen_vm_power_state_set *set)
-{
- free(set);
-}
-
-
-const char *
-xen_vm_power_state_to_string(enum xen_vm_power_state val)
-{
- return lookup_table[val];
-}
-
-
-extern enum xen_vm_power_state
-xen_vm_power_state_from_string(xen_session *session, const char *str)
-{
- return ENUM_LOOKUP(session, str, lookup_table);
-}
-
-
-const abstract_type xen_vm_power_state_abstract_type_ =
- {
- .typename = ENUM,
- .enum_marshaller =
- (const char *(*)(int))&xen_vm_power_state_to_string,
- .enum_demarshaller =
- (int (*)(xen_session *, const char *))&xen_vm_power_state_from_string
- };
-
-
-const abstract_type xen_vm_power_state_set_abstract_type_ =
- {
- .typename = SET,
- .child = &xen_vm_power_state_abstract_type_
- };
-
-
diff --git a/tools/libxen/src/xen_xspolicy.c b/tools/libxen/src/xen_xspolicy.c
deleted file mode 100644
index fe0dc25..0000000
--- a/tools/libxen/src/xen_xspolicy.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Copyright (c) 2007, IBM Corp.
- * Copyright (c) 2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include "xen/api/xen_common.h"
-#include "xen/api/xen_xspolicy.h"
-
-
-XEN_FREE(xen_xspolicy)
-XEN_SET_ALLOC_FREE(xen_xspolicy)
-XEN_RECORD_OPT_FREE(xen_xspolicy)
-
-static const struct_member xen_xspolicy_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_xspolicy_record, uuid) },
- { .key = "flags",
- .type = &abstract_type_int,
- .offset = offsetof(xen_xspolicy_record, flags) },
- { .key = "repr",
- .type = &abstract_type_string,
- .offset = offsetof(xen_xspolicy_record, repr) },
- { .key = "type",
- .type = &abstract_type_int,
- .offset = offsetof(xen_xspolicy_record, type) },
- };
-
-const abstract_type xen_xspolicy_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_xspolicy_record),
- .member_count =
- sizeof(xen_xspolicy_record_struct_members) / sizeof(struct_member),
- .members = xen_xspolicy_record_struct_members
- };
-
-
-static const struct_member xen_xs_policystate_struct_members[] =
- {
- { .key = "xs_ref",
- .type = &abstract_type_ref,
- .offset = offsetof(xen_xs_policystate, xs_ref) },
- { .key = "xserr",
- .type = &abstract_type_int,
- .offset = offsetof(xen_xs_policystate, xserr) },
- { .key = "repr",
- .type = &abstract_type_string,
- .offset = offsetof(xen_xs_policystate, repr) },
- { .key = "type",
- .type = &abstract_type_int,
- .offset = offsetof(xen_xs_policystate, type) },
- { .key = "flags",
- .type = &abstract_type_int,
- .offset = offsetof(xen_xs_policystate, flags) },
- { .key = "version",
- .type = &abstract_type_string,
- .offset = offsetof(xen_xs_policystate, version) },
- { .key = "errors",
- .type = &abstract_type_string,
- .offset = offsetof(xen_xs_policystate, errors) },
- };
-
-const abstract_type xen_xs_policystate_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_xs_policystate),
- .member_count =
- sizeof(xen_xs_policystate_struct_members) /
- sizeof(struct_member),
- .members = xen_xs_policystate_struct_members,
- };
-
-
-
-
-void
-xen_xs_policystate_free(xen_xs_policystate *state)
-{
- if (state == NULL)
- {
- return;
- }
- xen_xspolicy_record_opt_free(state->xs_ref);
- free(state->repr);
- free(state->errors);
- free(state->version);
- free(state);
-}
-
-
-void
-xen_xspolicy_record_free(xen_xspolicy_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record->repr);
- free(record);
-}
-
-
-bool
-xen_xspolicy_get_record(xen_session *session, xen_xspolicy_record **result,
- xen_xspolicy xspolicy)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = xspolicy }
- };
-
- abstract_type result_type = xen_xspolicy_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("XSPolicy.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_xspolicy_get_uuid(xen_session *session, char **result,
- xen_xspolicy xspolicy)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = xspolicy }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("XSPolicy.get_uuid");
- return session->ok;
-}
-
-
-bool
-xen_xspolicy_get_by_uuid(xen_session *session, xen_xspolicy *result,
- char *uuid)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = uuid }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("XSPolicy.get_by_uuid");
- return session->ok;
-}
-
-
-bool
-xen_xspolicy_get_xstype(xen_session *session, xs_type *result)
-{
- abstract_value param_values[] =
- {
- };
-
- abstract_type result_type = abstract_type_int;
-
- *result = 0;
- XEN_CALL_("XSPolicy.get_xstype");
- return session->ok;
-}
-
-
-bool
-xen_xspolicy_set_xspolicy(xen_session *session, xen_xs_policystate **result,
- xs_type type, char *repr,
- xs_instantiationflags flags,
- bool overwrite)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_int,
- .u.int_val = type },
- { .type = &abstract_type_string,
- .u.string_val = repr },
- { .type = &abstract_type_int,
- .u.int_val = flags },
- { .type = &abstract_type_bool,
- .u.bool_val = overwrite }
- };
-
- abstract_type result_type = xen_xs_policystate_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("XSPolicy.set_xspolicy");
- return session->ok;
-}
-
-
-bool
-xen_xspolicy_reset_xspolicy(xen_session *session, xen_xs_policystate **result,
- xs_type type)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_int,
- .u.int_val = type },
- };
-
- abstract_type result_type = xen_xs_policystate_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("XSPolicy.reset_xspolicy");
- return session->ok;
-}
-
-
-bool
-xen_xspolicy_get_xspolicy(xen_session *session, xen_xs_policystate **result)
-{
- abstract_value param_values[] =
- {
- };
-
- abstract_type result_type = xen_xs_policystate_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("XSPolicy.get_xspolicy");
- return session->ok;
-}
-
-
-bool
-xen_xspolicy_get_labeled_resources(xen_session *session,
- xen_string_string_map **result)
-{
- abstract_value param_values[] =
- {
- };
-
- abstract_type result_type = abstract_type_string_string_map;
-
- *result = NULL;
- XEN_CALL_("XSPolicy.get_labeled_resources");
- return session->ok;
-}
-
-
-bool
-xen_xspolicy_set_resource_label(xen_session *session,
- char *resource, char *label,
- char *oldlabel)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = resource },
- { .type = &abstract_type_string,
- .u.string_val = label },
- { .type = &abstract_type_string,
- .u.string_val = oldlabel },
- };
-
- xen_call_(session, "XSPolicy.set_resource_label", param_values, 3,
- NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_xspolicy_get_resource_label(xen_session *session, char **result,
- char *resource)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = resource },
- };
-
- abstract_type result_type = abstract_type_string;
- XEN_CALL_("XSPolicy.get_resource_label");
- return session->ok;
-}
-
-
-bool
-xen_xspolicy_rm_xsbootpolicy(xen_session *session)
-{
- abstract_value param_values[] =
- {
- };
-
- xen_call_(session, "XSPolicy.rm_xsbootpolicy", param_values, 0,
- NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_xspolicy_activate_xspolicy(xen_session *session,
- xs_instantiationflags *result,
- xen_xspolicy xspolicy,
- xs_instantiationflags flags)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = xspolicy },
- { .type = &abstract_type_int,
- .u.int_val = flags },
- };
-
- abstract_type result_type = abstract_type_int;
-
- *result = 0;
- XEN_CALL_("XSPolicy.activate_xspolicy");
- return session->ok;
-}
-
-
-bool
-xen_xspolicy_can_run(xen_session *session, int64_t *result,
- char *security_label)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = security_label }
- };
-
- abstract_type result_type = abstract_type_int;
-
- *result = 0;
- XEN_CALL_("XSPolicy.can_run");
- return session->ok;
-}
diff --git a/tools/libxen/test/test_bindings.c b/tools/libxen/test/test_bindings.c
deleted file mode 100644
index 27ae572..0000000
--- a/tools/libxen/test/test_bindings.c
+++ /dev/null
@@ -1,1453 +0,0 @@
-/*
- * Copyright (c) 2006-2007 XenSource, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define _GNU_SOURCE
-#include <assert.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <libxml/parser.h>
-#include <curl/curl.h>
-#include <xen/api/xen_all.h>
-
-//#define PRINT_XML
-//////////////#define POOL_TESTS
-
-static void usage()
-{
- fprintf(stderr,
-"Usage:\n"
-"\n"
-" test_bindings <url> <username> <password>\n"
-"\n"
-"where\n"
-" <url> is a fragment of the server's URL, e.g. localhost:8005/RPC2;\n"
-" <username> is the username to use at the server; and\n"
-" <password> is the password.\n");
-
- exit(EXIT_FAILURE);
-}
-
-
-static char *url;
-
-
-typedef struct
-{
- xen_result_func func;
- void *handle;
-} xen_comms;
-
-
-static xen_vm create_new_vm(xen_session *session, bool hvm);
-static void print_session_info(xen_session *session);
-static void print_methods(xen_session *session);
-static void print_vm_power_state(xen_session *session, xen_vm vm);
-static void print_vm_metrics(xen_session *session, xen_vm vm);
-
-
-static size_t
-write_func(void *ptr, size_t size, size_t nmemb, xen_comms *comms)
-{
- size_t n = size * nmemb;
-#ifdef PRINT_XML
- printf("\n\n---Result from server -----------------------\n");
- printf("%s\n",((char*) ptr));
- fflush(stdout);
-#endif
- return comms->func(ptr, n, comms->handle) ? n : 0;
-}
-
-
-static int
-call_func(const void *data, size_t len, void *user_handle,
- void *result_handle, xen_result_func result_func)
-{
- (void)user_handle;
-
-#ifdef PRINT_XML
- printf("\n\n---Data to server: -----------------------\n");
- printf("%s\n",((char*) data));
- fflush(stdout);
-#endif
-
- CURL *curl = curl_easy_init();
- if (!curl) {
- return -1;
- }
-
- xen_comms comms = {
- .func = result_func,
- .handle = result_handle
- };
-
- curl_easy_setopt(curl, CURLOPT_URL, url);
- curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
- curl_easy_setopt(curl, CURLOPT_MUTE, 1);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_func);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &comms);
- curl_easy_setopt(curl, CURLOPT_POST, 1);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
-
- CURLcode result = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-
- return result;
-}
-
-
-static void print_error(xen_session *session)
-{
- fprintf(stderr, "Error: %d", session->error_description_count);
- for (int i = 0; i < session->error_description_count; i++)
- {
- fprintf(stderr, "%s ", session->error_description[i]);
- }
- fprintf(stderr, "\n");
-}
-
-
-#ifdef POOL_TESTS
-#define NAME_DESCRIPTION "TestPool"
-#define NAME_DESCRIPTION_2 "TestPool-2"
-#define NAME_LABEL "Pool-1"
-#define NAME_LABEL_2 "Pool-2"
-#define SCHED_NAME "credit"
-#define NCPU_VAL 2
-#define NCPU_VAL_2 1
-
-
-static int pool_tests(xen_session *session, xen_host host)
-{
- int rc = 1;
- xen_cpu_pool_set *pools = NULL;
- xen_host_record *host_record = NULL;
- xen_cpu_pool_record_opt *cpu_pool_opt = NULL;
- xen_cpu_pool_record *cpu_pool_rec = NULL;
- xen_host_cpu_set *host_cpu_set = NULL;
- xen_host_cpu_record *host_cpu_record = NULL;
- xen_vm_set *vm_set = NULL;
- xen_cpu_pool pool = NULL;
- xen_cpu_pool pool_out = NULL;
- xen_string_string_map *pool_other_config = NULL;
- xen_vm_record *vm_record = NULL;
- xen_string_set *proposed_cpus = NULL;
- xen_host res_host = NULL;
- char *name_description = NULL;
- char *name_label = NULL;
- char *sched_policy = NULL;
- char *pool_uuid = NULL;
- int64_t ncpu;
-
- for (int loop= 0; loop < 1; loop++)
- {
- // Test extensions of class host
- printf("Test cpu_pool extension of host class -----------------------------------------\n");
-
- printf("host.get_resident_cpu_pools\n");
- if (!xen_host_get_resident_cpu_pools(session, &pools, host))
- {
- break;
- }
- if (pools->size != 1)
- {
- printf("Wrong pool count; only one pool expected\n");
- break;
- }
- printf("Pool UUID %s\n", (char*)pools->contents[0]);
- xen_cpu_pool_set_free(pools);
- pools = NULL;
-
- printf("host.get_record\n");
- if (!xen_host_get_record(session, &host_record, host))
- {
- break;
- }
- printf("Pool count %d\n", (int)host_record->resident_cpu_pools->size);
- if (host_record->resident_cpu_pools->size != 1)
- {
- break;
- }
- cpu_pool_opt = host_record->resident_cpu_pools->contents[0];
- printf("Pool UUID %s\n", (char*)cpu_pool_opt->u.handle);
- xen_host_record_free(host_record);
- host_record = NULL;
- cpu_pool_opt = NULL;
-
-
- // Test extensions of class host_cpu
- printf("host_cpu.get_all\n");
- if (!xen_host_cpu_get_all(session, &host_cpu_set))
- {
- break;
- }
-
- printf("host_cpu.get_cpu_pool & host_cpu.get_record\n");
- for (int i= 0; i < host_cpu_set->size; i++)
- {
- if (!xen_host_cpu_get_cpu_pool(session, &pools, host_cpu_set->contents[i]))
- {
- break;
- }
- if (pools->size > 1)
- {
- printf("Wrong pool count (xen_host_cpu_get_cpu_pool)\n");
- break;
- }
-
- printf("host_cpu (get_cpu_pool) %s, cpu_pool %s\n", (char*)host_cpu_set->contents[i],
- pools->size != 0 ? (char*)pools->contents[0] : "(None)");
-
- if (!xen_host_cpu_get_record(session, &host_cpu_record, host_cpu_set->contents[i]))
- {
- break;
- }
- if (host_cpu_record->cpu_pools->size > 1)
- {
- printf("Wrong pool count (xen_host_cpu_get_record)\n");
- break;
- }
-
- printf("host_cpu (get_record) %s, cpu_pool %s\n", (char*)host_cpu_set->contents[i],
- host_cpu_record->cpu_pools->size != 0
- ? (char*)((xen_cpu_pool_record_opt*)(host_cpu_record->cpu_pools->contents[0])->u.handle)
- : "(None)");
-
- }
- xen_host_cpu_record_free(host_cpu_record);
- host_cpu_record = NULL;
- xen_host_cpu_set_free(host_cpu_set);
- host_cpu_set = NULL;
- xen_cpu_pool_set_free(pools);
- pools = NULL;
-
- printf("host_cpu.get_unassigned_cpus\n");
- if (!xen_host_cpu_get_unassigned_cpus(session, &host_cpu_set))
- {
- break;
- }
- printf("Free cpus (not bound to a pool)\n");
- for (int i= 0; i < host_cpu_set->size; i++)
- {
- printf(" cpu UUID %s\n", (char*)host_cpu_set->contents[i]);
- }
- xen_host_cpu_set_free(host_cpu_set);
- host_cpu_set = NULL;
-
-
- printf("vm.get_record\n");
- if (!xen_vm_get_all(session, &vm_set))
- {
- break;
- }
-
- if (!xen_vm_get_record(session, &vm_record, vm_set->contents[0]))
- {
- break;
- }
- printf("VM %s, pool_name %s, cpu_pool %s\n", (char*)vm_set->contents[0],
- vm_record->pool_name, (char*)vm_record->cpu_pool->contents[0]);
-
- xen_vm_record_free(vm_record);
- vm_record = NULL;
-
- printf("vm.get_cpu_pool\n");
- if (!xen_vm_get_cpu_pool(session, &pools, vm_set->contents[0]))
- {
- break;
- }
- printf("vm_get_cpu_pool %s\n", (char*)pools->contents[0]);
-
- xen_vm_set_free(vm_set);
- xen_cpu_pool_set_free(pools);
- vm_set = NULL;
- pools = NULL;
-
-
- // Class cpu_pool
-
- // create
- pool_other_config = xen_string_string_map_alloc(1);
- pool_other_config->contents[0].key = strdup("type");
- pool_other_config->contents[0].val = strdup("bs2000");
- xen_string_set *proposed_CPUs_set = xen_string_set_alloc(1);
- proposed_CPUs_set->contents[0] = strdup("3");
-
- xen_cpu_pool_record new_cpu_pool_record =
- {
- .name_label = NAME_LABEL,
- .name_description = NAME_DESCRIPTION,
- .auto_power_on = false,
- .ncpu = NCPU_VAL,
- .sched_policy = SCHED_NAME,
- .proposed_cpus = proposed_CPUs_set,
- .other_config = pool_other_config,
- };
-
- printf("cpu_pool.create\n");
- if (!xen_cpu_pool_create(session, &pool, &new_cpu_pool_record))
- {
- break;
- }
- printf("New Pool UUID %s\n", (char*)pool);
- xen_string_set_free(proposed_CPUs_set);
- proposed_CPUs_set = NULL;
- xen_string_string_map_free(pool_other_config);
- pool_other_config = NULL;
-
- // get_by_name_label
- printf("cpu_pool.get_by_name_label\n");
- if (!xen_cpu_pool_get_by_name_label(session, &pools, "Pool-1"))
- {
- break;
- }
- if (strcmp((char*)pools->contents[0], (char*)pool) != 0)
- {
- break;
- }
- xen_cpu_pool_set_free(pools);
- pools = NULL;
-
-
- // get_by_uuid
- printf("cpu_pool.get_by_uuid\n");
- if (!xen_cpu_pool_get_by_uuid(session, &pool_out, pool))
- {
- break;
- }
- if (strcmp((char*)pool_out, (char*)pool) != 0)
- {
- printf("Wrong pool returned\n");
- break;
- }
- xen_cpu_pool_free(pool_out);
- pool_out = NULL;
-
- // get_all
- printf("cpu_pool.get_all\n");
- if (!xen_cpu_pool_get_all(session, &pools))
- {
- break;
- }
- if (pools->size != 2)
- {
- printf("Wrong pool count (%d)\n", (int)pools->size);
- break;
- }
- xen_cpu_pool_set_free(pools);
- pools = NULL;
-
-
- // get_activated
- printf("cpu_pool.get_activated\n");
- bool activated_state = true;
- if (!xen_cpu_pool_get_activated(session, &activated_state, pool))
- {
- break;
- }
- if (activated_state)
- {
- printf("Pool must not be activated\n");
- break;
- }
-
-
- // get_auto_power_on
- printf("cpu_pool.get_auto_power_on\n");
- bool power_state = true;
- if (!xen_cpu_pool_get_auto_power_on(session, &power_state, pool))
- {
- break;
- }
- if (power_state)
- {
- printf("Pool must not have attibute 'auto_power_on'\n");
- break;
- }
-
- // get_host_CPUs
- printf("cpu_pool.get_host_CPUs\n");
- if (!xen_cpu_pool_get_host_CPUs(session, &host_cpu_set, pool))
- {
- break;
- }
- if (host_cpu_set->size != 0)
- {
- printf("Pool must not have any attached cpus\n");
- break;
- }
- xen_host_cpu_set_free(host_cpu_set);
- host_cpu_set = NULL;
-
-
- // get_name_description
- printf("cpu_pool.get_name_description\n");
- if (!xen_cpu_pool_get_name_description(session, &name_description, pool))
- {
- break;
- }
- if (strcmp(NAME_DESCRIPTION, name_description) != 0)
- {
- printf("Pool has wrong name_description\n");
- break;
- }
- free(name_description);
- name_description = NULL;
-
-
- // get_name_label
- printf("cpu_pool.get_name_label\n");
- if (!xen_cpu_pool_get_name_label(session, &name_label, pool))
- {
- break;
- }
- if (strcmp(NAME_LABEL, name_label) != 0)
- {
- printf("Pool has wrong name_label\n");
- break;
- }
- free(name_label);
- name_label = NULL;
-
- // get_ncpu
- printf("cpu_pool.get_ncpu\n");
- if (!xen_cpu_pool_get_ncpu(session, &ncpu, pool))
- {
- break;
- }
- if (NCPU_VAL != ncpu)
- {
- printf("Pool has wrong ncpu\n");
- break;
- }
-
- // get_proposed_CPUs
- printf("cpu_pool.get_proposed_CPUs\n");
- if (!xen_cpu_pool_get_proposed_CPUs(session, &proposed_cpus, pool))
- {
- break;
- }
- if (proposed_cpus->size != 1)
- {
- printf("Pool has wrong proposed_cpus count\n");
- break;
- }
- xen_string_set_free(proposed_cpus);
- proposed_cpus = NULL;
-
-
- // get_other_config
- printf("cpu_pool.get_other_config\n");
- if (!xen_cpu_pool_get_other_config(session, &pool_other_config, pool))
- {
- break;
- }
- if (pool_other_config->size != 1)
- {
- printf("Pool has wrong other_config element count\n");
- break;
- }
- if ((strcmp(pool_other_config->contents[0].key, "type") != 0) ||
- (strcmp(pool_other_config->contents[0].val, "bs2000") != 0))
- {
- printf("Pool has wrong other_config attributes\n");
- break;
- }
- xen_string_string_map_free(pool_other_config);
- pool_other_config = NULL;
-
-
- // get_record
- printf("cpu_pool.get_record\n");
- if (!xen_cpu_pool_get_record(session, &cpu_pool_rec, pool))
- {
- break;
- }
- if ( (strcmp(cpu_pool_rec->name_label, NAME_LABEL) != 0) ||
- (strcmp(cpu_pool_rec->name_description, NAME_DESCRIPTION) != 0) ||
- (cpu_pool_rec->auto_power_on) ||
- (cpu_pool_rec->ncpu != NCPU_VAL) ||
- (cpu_pool_rec->started_vms->size != 0) ||
- (strcmp(cpu_pool_rec->sched_policy, SCHED_NAME) != 0) ||
- (cpu_pool_rec->proposed_cpus->size != 1) ||
- (cpu_pool_rec->host_cpus->size != 0) ||
- (cpu_pool_rec->activated) ||
- (strcmp(cpu_pool_rec->resident_on->u.handle, host) != 0) ||
- (strcmp(cpu_pool_rec->uuid, pool) != 0) ||
- (cpu_pool_rec->other_config->size != 1))
- {
- printf("Wrong record output\n");
- break;
- }
- xen_cpu_pool_record_free(cpu_pool_rec);
- cpu_pool_rec = NULL;
-
-
- // get_resident_on
- printf("cpu_pool.get_resident_on\n");
- if (!xen_cpu_pool_get_resident_on(session, &res_host, pool))
- {
- break;
- }
- if (strcmp(res_host, host) != 0)
- {
- printf("Wrong resident host returned\n");
- break;
- }
- xen_host_free(res_host);
- res_host = NULL;
-
-
- // get_sched_policy
- printf("cpu_pool.get_sched_policy\n");
- if (!xen_cpu_pool_get_sched_policy(session, &sched_policy, pool))
- {
- break;
- }
- if (strcmp(sched_policy, SCHED_NAME) != 0)
- {
- printf("Wrong sched_policy returned\n");
- break;
- }
- free(sched_policy);
- sched_policy = NULL;
-
-
- // get_started_VMs
- printf("cpu_pool.get_started_VMs\n");
- if (!xen_cpu_pool_get_started_VMs(session, &vm_set, pool))
- {
- break;
- }
- if (vm_set->size != 0)
- {
- printf("Wrong count of started VMs\n");
- break;
- }
- xen_vm_set_free(vm_set);
- vm_set = NULL;
-
-
- // get_uuid
- printf("cpu_pool.get_uuid\n");
- if (!xen_cpu_pool_get_uuid(session, &pool_uuid, pool))
- {
- break;
- }
- if (strcmp(pool_uuid, pool) != 0)
- {
- printf("Wrong Pool UUID returnd\n");
- break;
- }
- free(pool_uuid);
- pool_uuid = NULL;
-
-
- // set_auto_power_on
- printf("cpu_pool.set_auto_power_on\n");
- if (!xen_cpu_pool_set_auto_power_on(session, pool, true))
- break;
-
-
- // set_proposed_CPUs
- printf("cpu_pool.set_proposed_CPUs\n");
- proposed_CPUs_set = xen_string_set_alloc(2);
- proposed_CPUs_set->contents[0] = strdup("2");
- proposed_CPUs_set->contents[1] = strdup("4");
- if (!xen_cpu_pool_set_proposed_CPUs(session, pool, proposed_CPUs_set))
- break;
- xen_string_set_free(proposed_CPUs_set);
- proposed_CPUs_set = NULL;
-
-
- // add_to_proposed_CPUs
- printf("cpu_pool.add_to_proposed_CPUs\n");
- if (!xen_cpu_pool_add_to_proposed_CPUs(session, pool, "3"))
- break;
-
-
- // remove_from_proposed_CPUs
- printf("cpu_pool.remove_from_proposed_CPUs\n");
- if (!xen_cpu_pool_remove_from_proposed_CPUs(session, pool, "4"))
- break;
-
-
- // set_name_label
- printf("cpu_pool.set_name_label\n");
- if (!xen_cpu_pool_set_name_label(session, pool, NAME_LABEL_2))
- break;
-
-
- // set_name_description
- printf("cpu_pool.set_name_description\n");
- if (!xen_cpu_pool_set_name_description(session, pool, NAME_DESCRIPTION_2))
- break;
-
-
- // set_ncpu
- printf("cpu_pool.set_ncpu\n");
- if (!xen_cpu_pool_set_ncpu(session, pool, NCPU_VAL_2))
- break;
-
-
- // set_other_config
- printf("cpu_pool.set_other_config\n");
- pool_other_config = xen_string_string_map_alloc(2);
- pool_other_config->contents[0].key = strdup("test1");
- pool_other_config->contents[0].val = strdup("field1");
- pool_other_config->contents[1].key = strdup("test2");
- pool_other_config->contents[1].val = strdup("field2");
- if (!xen_cpu_pool_set_other_config(session, pool, pool_other_config))
- break;
- xen_string_string_map_free(pool_other_config);
- pool_other_config = NULL;
-
-
- // add_to_other_config
- printf("cpu_pool.add_to_other_config\n");
- if (!xen_cpu_pool_add_to_other_config(session, pool, "test3", "field3"))
- break;
-
-
- // remove_from_other_config
- printf("cpu_pool.remove_from_other_config\n");
- if (!xen_cpu_pool_remove_from_other_config(session, pool, "test2"))
- break;
-
-
- // set_sched_policy
- printf("cpu_pool.set_sched_policy\n");
- if (!xen_cpu_pool_set_sched_policy(session, pool, SCHED_NAME))
- break;
-
-
- // check get_record again
- printf("check cpu_pool record\n");
- if (!xen_cpu_pool_get_record(session, &cpu_pool_rec, pool))
- {
- break;
- }
- if ( (strcmp(cpu_pool_rec->name_label, NAME_LABEL_2) != 0) ||
- (strcmp(cpu_pool_rec->name_description, NAME_DESCRIPTION_2) != 0) ||
- (!cpu_pool_rec->auto_power_on) ||
- (cpu_pool_rec->ncpu != NCPU_VAL_2) ||
- (cpu_pool_rec->started_vms->size != 0) ||
- (strcmp(cpu_pool_rec->sched_policy, SCHED_NAME) != 0) ||
- (cpu_pool_rec->proposed_cpus->size != 2) ||
- (cpu_pool_rec->host_cpus->size != 0) ||
- (cpu_pool_rec->activated) ||
- (strcmp(cpu_pool_rec->resident_on->u.handle, host) != 0) ||
- (strcmp(cpu_pool_rec->uuid, pool) != 0) ||
- (cpu_pool_rec->other_config->size != 2))
- {
- printf("Wrong record output\n");
- break;
- }
- xen_cpu_pool_record_free(cpu_pool_rec);
- cpu_pool_rec = NULL;
-
-
- // activate pool
- printf("cpu_pool.activate\n");
- if (!xen_cpu_pool_activate(session, pool))
- break;
-
-
- // add_host_CPU_live
- printf("cpu_pool.add_host_CPU_live\n");
- if (!xen_host_cpu_get_unassigned_cpus(session, &host_cpu_set))
- {
- break;
- }
- if (host_cpu_set->size < 1)
- {
- printf("No free CPU found\n");
- break;
- }
- if (!xen_cpu_pool_add_host_CPU_live(session, pool, host_cpu_set->contents[0]))
- break;
-
-
- // remove_host_CPU_live
- printf("cpu_pool.remove_host_CPU_live\n");
- if (!xen_cpu_pool_remove_host_CPU_live(session, pool, host_cpu_set->contents[0]))
- break;
-
- xen_host_cpu_set_free(host_cpu_set);
- host_cpu_set = NULL;
-
-
- // check get_record again
- printf("check cpu_pool record\n");
- if (!xen_cpu_pool_get_record(session, &cpu_pool_rec, pool))
- {
- break;
- }
- if ( (strcmp(cpu_pool_rec->name_label, NAME_LABEL_2) != 0) ||
- (strcmp(cpu_pool_rec->name_description, NAME_DESCRIPTION_2) != 0) ||
- (!cpu_pool_rec->auto_power_on) ||
- (cpu_pool_rec->ncpu != NCPU_VAL_2) ||
- (cpu_pool_rec->started_vms->size != 0) ||
- (strcmp(cpu_pool_rec->sched_policy, SCHED_NAME) != 0) ||
- (cpu_pool_rec->proposed_cpus->size != 2) ||
- (cpu_pool_rec->host_cpus->size != 1) ||
- (!cpu_pool_rec->activated) ||
- (strcmp(cpu_pool_rec->resident_on->u.handle, host) != 0) ||
- (strcmp(cpu_pool_rec->uuid, pool) != 0) ||
- (cpu_pool_rec->other_config->size != 2))
- {
- printf("Wrong record output\n");
- break;
- }
- xen_cpu_pool_record_free(cpu_pool_rec);
- cpu_pool_rec = NULL;
-
-
- // deactivate pool
- printf("cpu_pool.deactivate\n");
- if (!xen_cpu_pool_deactivate(session, pool))
- break;
-
-
- // Pool delete
- if (!xen_cpu_pool_destroy(session, pool))
- {
- break;
- }
- xen_cpu_pool_free(pool);
- pool = NULL;
-
- // Tests OK
- printf("Pool Tests OK\n");
- rc= 0;
- }
-
- if (rc != 0)
- {
- print_error(session);
- }
-
- xen_cpu_pool_set_free(pools);
- xen_host_record_free(host_record);
- xen_cpu_pool_record_opt_free(cpu_pool_opt);
- xen_host_cpu_set_free(host_cpu_set);
- xen_host_cpu_record_free(host_cpu_record);
- xen_vm_set_free(vm_set);
- xen_cpu_pool_free(pool);
- xen_cpu_pool_free(pool_out);
- xen_string_string_map_free(pool_other_config);
- xen_vm_record_free(vm_record);
- xen_string_set_free(proposed_cpus);
- free(name_description);
- free(name_label);
- free(sched_policy);
- free(pool_uuid);
- xen_cpu_pool_record_free(cpu_pool_rec);
- xen_host_free(res_host);
-
- return rc;
-}
-#endif
-
-
-int main(int argc, char **argv)
-{
- if (argc != 4)
- {
- usage();
- }
-
- url = argv[1];
- char *username = argv[2];
- char *password = argv[3];
-
- xmlInitParser();
- xen_init();
- curl_global_init(CURL_GLOBAL_ALL);
-
-#define CLEANUP \
- do { \
- xen_session_logout(session); \
- curl_global_cleanup(); \
- xen_fini(); \
- xmlCleanupParser(); \
- } while(0) \
-
-
- xen_session *session =
- xen_session_login_with_password(call_func, NULL, username, password);
-
- print_session_info(session);
- if (!session->ok)
- {
- /* Error has been logged, just clean up. */
- CLEANUP;
- return 1;
- }
-
- print_methods(session);
- if (!session->ok)
- {
- /* Error has been logged, just clean up. */
- CLEANUP;
- return 1;
- }
-
- xen_vm vm;
- if (!xen_vm_get_by_uuid(session, &vm,
- "00000000-0000-0000-0000-000000000000"))
- {
- print_error(session);
- CLEANUP;
- return 1;
- }
-
- char *vm_uuid;
- if (!xen_vm_get_uuid(session, &vm_uuid, vm))
- {
- print_error(session);
- xen_vm_free(vm);
- CLEANUP;
- return 1;
- }
-
- char *vm_uuid_bytes;
- if (!xen_uuid_string_to_bytes(vm_uuid, &vm_uuid_bytes))
- {
- fprintf(stderr, "xen_uuid_string_to_bytes failed.\n");
- xen_uuid_free(vm_uuid);
- xen_vm_free(vm);
- CLEANUP;
- return 1;
- }
-
- xen_vm_record *vm_record;
- if (!xen_vm_get_record(session, &vm_record, vm))
- {
- print_error(session);
- xen_uuid_bytes_free(vm_uuid_bytes);
- xen_uuid_free(vm_uuid);
- xen_vm_free(vm);
- CLEANUP;
- return 1;
- }
-
- xen_host host;
- if (!xen_session_get_this_host(session, &host, session))
- {
- print_error(session);
- xen_vm_record_free(vm_record);
- xen_uuid_bytes_free(vm_uuid_bytes);
- xen_uuid_free(vm_uuid);
- xen_vm_free(vm);
- CLEANUP;
- return 1;
- }
-
- xen_string_string_map *versions;
- if (!xen_host_get_software_version(session, &versions, host))
- {
- print_error(session);
- xen_host_free(host);
- xen_vm_record_free(vm_record);
- xen_uuid_bytes_free(vm_uuid_bytes);
- xen_uuid_free(vm_uuid);
- xen_vm_free(vm);
- CLEANUP;
- return 1;
- }
-
- char *dmesg;
- if (!xen_host_dmesg(session, &dmesg, host))
- {
- print_error(session);
- xen_string_string_map_free(versions);
- xen_host_free(host);
- xen_vm_record_free(vm_record);
- xen_uuid_bytes_free(vm_uuid_bytes);
- xen_uuid_free(vm_uuid);
- xen_vm_free(vm);
- CLEANUP;
- return 1;
- }
-
- xen_string_set *supported_bootloaders;
- if (!xen_host_get_supported_bootloaders(session, &supported_bootloaders,
- host))
- {
- print_error(session);
- free(dmesg);
- xen_string_string_map_free(versions);
- xen_host_free(host);
- xen_vm_record_free(vm_record);
- xen_uuid_bytes_free(vm_uuid_bytes);
- xen_uuid_free(vm_uuid);
- xen_vm_free(vm);
- CLEANUP;
- return 1;
- }
-
- xen_string_set *capabilities;
- if (!xen_host_get_capabilities(session, &capabilities, host))
- {
- print_error(session);
- free(dmesg);
- xen_string_set_free(supported_bootloaders);
- xen_string_string_map_free(versions);
- xen_host_free(host);
- xen_vm_record_free(vm_record);
- xen_uuid_bytes_free(vm_uuid_bytes);
- xen_uuid_free(vm_uuid);
- xen_vm_free(vm);
- CLEANUP;
- return 1;
- }
-
- xen_string_string_map *cpu_configuration;
- if (!xen_host_get_cpu_configuration(session, &cpu_configuration, host))
- {
- print_error(session);
- free(dmesg);
- xen_string_set_free(capabilities);
- xen_string_set_free(supported_bootloaders);
- xen_string_string_map_free(versions);
- xen_host_free(host);
- xen_vm_record_free(vm_record);
- xen_uuid_bytes_free(vm_uuid_bytes);
- xen_uuid_free(vm_uuid);
- xen_vm_free(vm);
- CLEANUP;
- return 1;
- }
-
- char *sched_policy;
- if (!xen_host_get_sched_policy(session, &sched_policy, host))
- {
- print_error(session);
- xen_string_string_map_free(cpu_configuration);
- xen_string_set_free(capabilities);
- xen_string_set_free(supported_bootloaders);
- xen_string_string_map_free(versions);
- xen_host_free(host);
- xen_vm_record_free(vm_record);
- xen_uuid_bytes_free(vm_uuid_bytes);
- xen_uuid_free(vm_uuid);
- xen_vm_free(vm);
- CLEANUP;
- return 1;
- }
-
- printf("%s.\n", vm_uuid);
-
- printf("In bytes, the VM UUID is ");
- for (int i = 0; i < 15; i++)
- {
- printf("%x, ", (unsigned int)vm_uuid_bytes[i]);
- }
- printf("%x.\n", (unsigned int)vm_uuid_bytes[15]);
-
- printf("%zd.\n", versions->size);
-
- for (size_t i = 0; i < versions->size; i++)
- {
- printf("%s -> %s.\n", versions->contents[i].key,
- versions->contents[i].val);
- }
-
- printf("Host dmesg follows:\n%s\n\n", dmesg);
-
- printf("Host supports the following bootloaders:");
- for (size_t i = 0; i < supported_bootloaders->size; i++)
- {
- printf(" %s", supported_bootloaders->contents[i]);
- }
- printf("\n");
-
- printf("Host has the following capabilities:");
- for (size_t i = 0; i < capabilities->size; i++)
- {
- printf(" %s", capabilities->contents[i]);
- }
- printf("\n");
-
- printf("Host has the following CPU configuration:\n");
- for (size_t i = 0; i < cpu_configuration->size; i++)
- {
- printf(" %s -> %s.\n", cpu_configuration->contents[i].key,
- cpu_configuration->contents[i].val);
- }
-
- printf("Current scheduler policy: %s.\n\n", sched_policy);
-
- printf("%s.\n", vm_record->uuid);
-
- printf("Resident on %s.\n", (char *)vm_record->resident_on->u.handle);
-
- printf("%s.\n", xen_vm_power_state_to_string(vm_record->power_state));
-
- xen_uuid_bytes_free(vm_uuid_bytes);
- xen_uuid_free(vm_uuid);
-
- xen_vm_record_free(vm_record);
-
-#ifdef POOL_TESTS
- if (pool_tests(session, host) != 0)
- return 1;
-#endif
-
- xen_host_free(host);
- xen_string_string_map_free(versions);
- free(dmesg);
- xen_string_set_free(supported_bootloaders);
- xen_string_set_free(capabilities);
- xen_string_string_map_free(cpu_configuration);
- free(sched_policy);
-
- print_vm_metrics(session, vm);
- if (!session->ok)
- {
- /* Error has been logged, just clean up. */
- xen_vm_free(vm);
- CLEANUP;
- return 1;
- }
-
- xen_vm_free(vm);
-
- xen_vm new_vm = create_new_vm(session, true);
- if (!session->ok)
- {
- /* Error has been logged, just clean up. */
- CLEANUP;
- return 1;
- }
-
- print_vm_power_state(session, new_vm);
- if (!session->ok)
- {
- /* Error has been logged, just clean up. */
- xen_vm_free(new_vm);
- CLEANUP;
- return 1;
- }
-
- xen_vm_free(new_vm);
- CLEANUP;
-
- return 0;
-}
-
-
-/**
- * Creation of a new VM, using the Named Parameters idiom. Allocate the
- * xen_vm_record here, but the sets through the library. Either
- * allocation patterns can be used, as long as the allocation and free are
- * paired correctly.
- */
-static xen_vm create_new_vm(xen_session *session, bool hvm)
-{
- xen_string_string_map *vcpus_params = xen_string_string_map_alloc(1);
- vcpus_params->contents[0].key = strdup("weight");
- vcpus_params->contents[0].val = strdup("300");
-
- xen_string_string_map *hvm_boot_params;
- if (hvm)
- {
- hvm_boot_params = xen_string_string_map_alloc(1);
- hvm_boot_params->contents[0].key = strdup("order");
- hvm_boot_params->contents[0].val = strdup("cd");
- }
- else
- {
- hvm_boot_params = NULL;
- }
-
- xen_vm_record vm_record =
- {
- .name_label = hvm ? "NewHVM" : "NewPV",
- .name_description = hvm ? "New HVM VM" : "New PV VM",
- .user_version = 1,
- .is_a_template = false,
- .memory_static_max = 256 * 1024 * 1024,
- .memory_dynamic_max = 256 * 1024 * 1024,
- .memory_dynamic_min = 128 * 1024 * 1024,
- .memory_static_min = 128 * 1024 * 1024,
- .vcpus_params = vcpus_params,
- .vcpus_max = 4,
- .vcpus_at_startup = 2,
- .actions_after_shutdown = XEN_ON_NORMAL_EXIT_DESTROY,
- .actions_after_reboot = XEN_ON_NORMAL_EXIT_RESTART,
- .actions_after_crash = XEN_ON_CRASH_BEHAVIOUR_RESTART,
- .hvm_boot_policy = hvm ? "BIOS order" : NULL,
- .hvm_boot_params = hvm ? hvm_boot_params : NULL,
- .pv_bootloader = hvm ? NULL : "pygrub",
- .pv_kernel = hvm ? NULL : "/boot/vmlinuz-2.6.16.33-xen",
- };
-
- xen_vm vm;
- xen_vm_create(session, &vm, &vm_record);
-
- xen_string_string_map_free(vcpus_params);
- xen_string_string_map_free(hvm_boot_params);
-
- if (!session->ok)
- {
- fprintf(stderr, "VM creation failed.\n");
- print_error(session);
- return NULL;
- }
-
-
- /*
- * Create a new disk for the new VM.
- */
- xen_sr_set *srs;
- if (!xen_sr_get_by_name_label(session, &srs, "QCoW") ||
- srs->size < 1)
- {
- fprintf(stderr, "SR lookup failed.\n");
- print_error(session);
- xen_vm_free(vm);
- return NULL;
- }
-
- xen_sr_record_opt sr_record =
- {
- .u.handle = srs->contents[0]
- };
- xen_vdi_record vdi0_record =
- {
- .name_label = "MyRootFS",
- .name_description = "MyRootFS description",
- .sr = &sr_record,
- .virtual_size = (INT64_C(1) << 30), // 1GiB
- .type = XEN_VDI_TYPE_SYSTEM,
- .sharable = false,
- .read_only = false
- };
-
- xen_vdi vdi0;
- if (!xen_vdi_create(session, &vdi0, &vdi0_record))
- {
- fprintf(stderr, "VDI creation failed.\n");
- print_error(session);
-
- xen_sr_set_free(srs);
- xen_vm_free(vm);
- return NULL;
- }
-
-
- xen_vm_record_opt vm_record_opt =
- {
- .u.handle = vm
- };
- xen_vdi_record_opt vdi0_record_opt =
- {
- .u.handle = vdi0
- };
- xen_vbd_record vbd0_record =
- {
- .vm = &vm_record_opt,
- .vdi = &vdi0_record_opt,
- .device = "xvda1",
- .mode = XEN_VBD_MODE_RW,
- .bootable = 1,
- };
-
- xen_vbd vbd0;
- if (!xen_vbd_create(session, &vbd0, &vbd0_record))
- {
- fprintf(stderr, "VBD creation failed.\n");
- print_error(session);
-
- xen_vdi_free(vdi0);
- xen_sr_set_free(srs);
- xen_vm_free(vm);
- return NULL;
- }
-
- xen_console vnc_console = NULL;
- if (hvm) {
- xen_console_record vnc_console_record =
- {
- .protocol = XEN_CONSOLE_PROTOCOL_RFB,
- .vm = &vm_record_opt,
- };
-
- if (!xen_console_create(session, &vnc_console, &vnc_console_record))
- {
- fprintf(stderr, "VNC console creation failed.\n");
- print_error(session);
-
- xen_vbd_free(vbd0);
- xen_vdi_free(vdi0);
- xen_sr_set_free(srs);
- xen_vm_free(vm);
- return NULL;
- }
- }
-
- char *vm_uuid;
- char *vdi0_uuid;
- char *vbd0_uuid;
- char *vnc_uuid = NULL;
-
- xen_vm_get_uuid(session, &vm_uuid, vm);
- xen_vdi_get_uuid(session, &vdi0_uuid, vdi0);
- xen_vbd_get_uuid(session, &vbd0_uuid, vbd0);
- if (hvm) {
- xen_console_get_uuid(session, &vnc_uuid, vnc_console);
- }
-
- if (!session->ok)
- {
- fprintf(stderr, "get_uuid call failed.\n");
- print_error(session);
-
- xen_uuid_free(vm_uuid);
- xen_uuid_free(vdi0_uuid);
- xen_uuid_free(vbd0_uuid);
- xen_uuid_free(vnc_uuid);
- xen_vbd_free(vbd0);
- xen_vdi_free(vdi0);
- xen_console_free(vnc_console);
- xen_sr_set_free(srs);
- xen_vm_free(vm);
- return NULL;
- }
-
- if (hvm) {
- printf("Created a new HVM VM, with UUID %s, VDI UUID %s, VBD "
- "UUID %s, and VNC console UUID %s.\n",
- vm_uuid, vdi0_uuid, vbd0_uuid, vnc_uuid);
- }
- else {
- printf("Created a new PV VM, with UUID %s, VDI UUID %s, and VBD "
- "UUID %s.\n",
- vm_uuid, vdi0_uuid, vbd0_uuid);
- }
-
- xen_uuid_free(vm_uuid);
- xen_uuid_free(vdi0_uuid);
- xen_uuid_free(vbd0_uuid);
- xen_uuid_free(vnc_uuid);
- xen_vbd_free(vbd0);
- xen_vdi_free(vdi0);
- xen_console_free(vnc_console);
- xen_sr_set_free(srs);
-
- return vm;
-}
-
-
-/**
- * Print the power state for the given VM.
- */
-static void print_vm_power_state(xen_session *session, xen_vm vm)
-{
- char *vm_uuid;
- enum xen_vm_power_state power_state;
-
- if (!xen_vm_get_uuid(session, &vm_uuid, vm))
- {
- print_error(session);
- return;
- }
-
- if (!xen_vm_get_power_state(session, &power_state, vm))
- {
- xen_uuid_free(vm_uuid);
- print_error(session);
- return;
- }
-
- printf("VM %s power state is %s.\n", vm_uuid,
- xen_vm_power_state_to_string(power_state));
-
- xen_uuid_free(vm_uuid);
-
- fflush(stdout);
-}
-
-
-/**
- * Workaround for whinging GCCs, as suggested by strftime(3).
- */
-static size_t my_strftime(char *s, size_t max, const char *fmt,
- const struct tm *tm)
-{
- return strftime(s, max, fmt, tm);
-}
-
-
-/**
- * Print some session details.
- */
-static void print_session_info(xen_session *session)
-{
- xen_session_record *record;
- if (!xen_session_get_record(session, &record, session))
- {
- print_error(session);
- return;
- }
-
- printf("Session UUID: %s.\n", record->uuid);
- printf("Session user: %s.\n", record->this_user);
- char time[256];
- struct tm *tm = localtime(&record->last_active);
- my_strftime(time, 256, "Session last active: %c, local time.\n", tm);
- printf(time);
-
- char *uuid = NULL;
- char *this_user = NULL;
- xen_session_get_uuid(session, &uuid, session);
- xen_session_get_this_user(session, &this_user, session);
-
- if (!session->ok)
- {
- free(uuid);
- free(this_user);
- xen_session_record_free(record);
- print_error(session);
- return;
- }
-
- assert(!strcmp(record->uuid, uuid));
- assert(!strcmp(record->this_user, this_user));
-
- free(uuid);
- free(this_user);
- xen_session_record_free(record);
-
- fflush(stdout);
-}
-
-
-static int pstrcmp(const void *p1, const void *p2)
-{
- return strcmp(*(char **)p1, *(char **)p2);
-}
-
-
-/**
- * Print the list of supported methods.
- */
-static void print_methods(xen_session *session)
-{
- xen_string_set *methods;
-
- if (!xen_host_list_methods(session, &methods))
- {
- print_error(session);
- goto done;
- }
-
- printf("%zd.\n", methods->size);
- qsort(methods->contents, methods->size, sizeof(char *), pstrcmp);
-
- printf("Supported methods:\n");
- for (size_t i = 0; i < methods->size; i++)
- {
- printf(" %s\n", methods->contents[i]);
- }
- fflush(stdout);
-
-done:
- xen_string_set_free(methods);
-}
-
-
-/**
- * Print the metrics for the given VM.
- */
-static void print_vm_metrics(xen_session *session, xen_vm vm)
-{
- xen_vm_metrics vm_metrics;
- if (!xen_vm_get_metrics(session, &vm_metrics, vm))
- {
- print_error(session);
- return;
- }
-
- xen_vm_metrics_record *vm_metrics_record;
- if (!xen_vm_metrics_get_record(session, &vm_metrics_record, vm_metrics))
- {
- xen_vm_metrics_free(vm_metrics);
- print_error(session);
- return;
- }
-
- char time[256];
- struct tm *tm = localtime(&vm_metrics_record->last_updated);
- my_strftime(time, 256, "Metrics updated at %c, local time.\n", tm);
- printf(time);
-
- tm = localtime(&vm_metrics_record->start_time);
- my_strftime(time, 256, "VM running since %c, local time.\n", tm);
- printf(time);
-
- for (size_t i = 0; i < vm_metrics_record->vcpus_utilisation->size; i++)
- {
- printf("%"PRId64" -> %lf.\n",
- vm_metrics_record->vcpus_utilisation->contents[i].key,
- vm_metrics_record->vcpus_utilisation->contents[i].val);
- }
-
- printf("VCPU -> PCPU mapping:\n");
- for (size_t i = 0; i < vm_metrics_record->vcpus_cpu->size; i++)
- {
- printf(" %"PRId64" -> %"PRId64".\n",
- vm_metrics_record->vcpus_cpu->contents[i].key,
- vm_metrics_record->vcpus_cpu->contents[i].val);
- }
-
- printf("Live scheduling parameters:\n");
- for (size_t i = 0; i < vm_metrics_record->vcpus_params->size; i++)
- {
- printf(" %s -> %s.\n",
- vm_metrics_record->vcpus_params->contents[i].key,
- vm_metrics_record->vcpus_params->contents[i].val);
- }
-
- for (size_t i = 0; i < vm_metrics_record->vcpus_flags->size; i++)
- {
- printf("%"PRId64" -> ",
- vm_metrics_record->vcpus_flags->contents[i].key);
- xen_string_set *s = vm_metrics_record->vcpus_flags->contents[i].val;
- for (size_t j = 0; j < s->size; j++)
- {
- printf("%s", s->contents[j]);
- if (j + 1 != s->size)
- {
- printf(", ");
- }
- }
- printf("\n");
- }
-
- xen_vm_metrics_record_free(vm_metrics_record);
- xen_vm_metrics_free(vm_metrics);
-
- fflush(stdout);
-}
diff --git a/tools/libxen/test/test_event_handling.c b/tools/libxen/test/test_event_handling.c
deleted file mode 100644
index 188b585..0000000
--- a/tools/libxen/test/test_event_handling.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (c) 2006-2007 XenSource, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define _GNU_SOURCE
-#include <assert.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <libxml/parser.h>
-#include <curl/curl.h>
-#include <xen/api/xen_event.h>
-
-//#define PRINT_XML
-
-static void usage()
-{
- fprintf(stderr,
-"Usage:\n"
-"\n"
-" test_event_handling <server> <username> <password>\n"
-"\n"
-"where\n"
-" <server> is the server's host and port, e.g. localhost:9363;\n"
-" <username> is the username to use at the server; and\n"
-" <password> is the password.\n");
-
- exit(EXIT_FAILURE);
-}
-
-
-static char *url;
-
-
-typedef struct
-{
- xen_result_func func;
- void *handle;
-} xen_comms;
-
-
-static size_t
-write_func(void *ptr, size_t size, size_t nmemb, xen_comms *comms)
-{
- size_t n = size * nmemb;
-#ifdef PRINT_XML
- printf("\n\n---Result from server -----------------------\n");
- printf("%s\n",((char*) ptr));
- fflush(stdout);
-#endif
- return comms->func(ptr, n, comms->handle) ? n : 0;
-}
-
-
-static int
-call_func(const void *data, size_t len, void *user_handle,
- void *result_handle, xen_result_func result_func)
-{
- (void)user_handle;
-
-#ifdef PRINT_XML
- printf("\n\n---Data to server: -----------------------\n");
- printf("%s\n",((char*) data));
- fflush(stdout);
-#endif
-
- CURL *curl = curl_easy_init();
- if (!curl) {
- return -1;
- }
-
- xen_comms comms = {
- .func = result_func,
- .handle = result_handle
- };
-
- curl_easy_setopt(curl, CURLOPT_URL, url);
- curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
- curl_easy_setopt(curl, CURLOPT_MUTE, 1);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_func);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &comms);
- curl_easy_setopt(curl, CURLOPT_POST, 1);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
-
- CURLcode result = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-
- return result;
-}
-
-
-static void print_error(xen_session *session)
-{
- fprintf(stderr, "Error: %d", session->error_description_count);
- for (int i = 0; i < session->error_description_count; i++)
- {
- fprintf(stderr, "%s ", session->error_description[i]);
- }
- fprintf(stderr, "\n");
-}
-
-
-/**
- * Workaround for whinging GCCs, as suggested by strftime(3).
- */
-static size_t my_strftime(char *s, size_t max, const char *fmt,
- const struct tm *tm)
-{
- return strftime(s, max, fmt, tm);
-}
-
-
-int main(int argc, char **argv)
-{
- if (argc != 4)
- {
- usage();
- }
-
- url = argv[1];
- char *username = argv[2];
- char *password = argv[3];
-
- xmlInitParser();
- xen_init();
- curl_global_init(CURL_GLOBAL_ALL);
-
-#define CLEANUP \
- do { \
- xen_session_logout(session); \
- curl_global_cleanup(); \
- xen_fini(); \
- xmlCleanupParser(); \
- } while(0) \
-
-
- xen_session *session =
- xen_session_login_with_password(call_func, NULL, username, password);
-
- struct xen_string_set *classes = xen_string_set_alloc(0);
- xen_event_register(session, classes);
- xen_string_set_free(classes);
-
- if (!session->ok)
- {
- print_error(session);
- CLEANUP;
- return 1;
- }
-
- while (true)
- {
- struct xen_event_record_set *events;
- if (!xen_event_next(session, &events))
- {
- print_error(session);
- CLEANUP;
- return 1;
- }
-
- for (size_t i = 0; i < events->size; i++)
- {
- xen_event_record *ev = events->contents[i];
- char time[256];
- struct tm *tm = localtime(&ev->timestamp);
- my_strftime(time, 256, "%c, local time", tm);
- printf("Event received: ID = %"PRId64", %s.\n", ev->id, time);
- switch (ev->operation)
- {
- case XEN_EVENT_OPERATION_ADD:
- printf("%s created with UUID %s.\n", ev->class, ev->obj_uuid);
- break;
-
- case XEN_EVENT_OPERATION_DEL:
- printf("%s with UUID %s deleted.\n", ev->class, ev->obj_uuid);
- break;
-
- case XEN_EVENT_OPERATION_MOD:
- printf("%s with UUID %s modified.\n", ev->class, ev->obj_uuid);
- break;
- default:
- assert(false);
- }
- }
-
- xen_event_record_set_free(events);
- }
-
- CLEANUP;
-
- return 0;
-}
diff --git a/tools/libxl/CODING_STYLE b/tools/libxl/CODING_STYLE
index 110a48f..f5b5890 100644
--- a/tools/libxl/CODING_STYLE
+++ b/tools/libxl/CODING_STYLE
@@ -1,6 +1,191 @@
-Libxenlight Coding Style
+LIBXENLIGHT CODING STYLE
========================
+
+AN APOLOGY AND WARNING
+----------------------
+
+Much of the code in libxl does not yet follow this coding style
+document in every respect. However, new code is expected to conform.
+
+Patches to improve the style of existing code are welcome. Please
+separate these out from functional changes.
+
+If it is not feasible to conform fully to the style while patching old
+code, without doing substantial style reengineering first, we may
+accept patches which contain nonconformant elements, provided that
+they don't make the coding style problem worse overall.
+
+In this case, the new code should conform to the prevailing style in
+the area being touched.
+
+
+MEMORY ALLOCATION
+-----------------
+
+Memory allocation for libxl-internal purposes should normally be done
+with the provided gc mechanisms; there is then no need to free. See
+"libxl memory management" in libxl.h.
+
+
+CONVENTIONAL VARIABLE NAMES
+---------------------------
+
+The following local variable names should be used where applicable:
+
+ int rc; /* a libxl error code - and not anything else */
+ int r; /* the return value from a system call (or libxc call) */
+
+ uint32_t domid;
+ libxl__gc *gc;
+ libxl__egc *egc;
+ libxl__ao *ao;
+
+ libxl_foo_bar_state *fbs; /* local variable */
+ libxl_foo_bar_state foo_bar; /* inside another state struct */
+
+
+CONVENIENCE MACROS
+------------------
+
+There are a number of convenience macros which shorten the program and
+avoid opportunity for mistakes. In some cases non-use of the macros
+produces functional bugs or incorrect error handling. Use the macros
+whenever they are applicable. For example:
+
+ Usually, don't use: Instead, use (see libxl_internal.h):
+ libxl__log[v] LOG, LOGE, LOGEV
+ libxl__sprintf GCSPRINTF
+ libxl__*alloc et al. GCNEW, GCNEW_ARRAY, GCREALLOC_ARRAY
+ malloc et al. GCNEW, GCNEW_ARRAY, GCREALLOC_ARRAY with NOGC
+ isalnum etc. directly CTYPE
+ libxl__ctx_[un]lock CTX_LOCK, CTX_UNLOCK
+ gc=...; ao=...; EGC_GC, AO_GC, STATE_AO_GC
+ explicit gc creation GC_INIT, GC_FREE
+
+
+ERROR HANDLING
+--------------
+
+Unless, there are good reasons to do otherwise, the following error
+handling and cleanup paradigm should be used:
+
+ * All local variables referring to resources which might need
+ cleaning up are declared at the top of the function, and
+ initialised to a sentinel value indicating "nothing allocated".
+ For example,
+ libxl_evgen_disk_eject *evg = NULL;
+ int nullfd = -1;
+
+ * If the function is to return a libxl error value, `rc' is
+ used to contain the error code, but it is NOT initialised:
+ int rc;
+
+ * There is only one error cleanup path out of the function. It
+ starts with a label `out:'. That error cleanup path checks for
+ each allocated resource and frees it iff necessary. It then
+ returns rc. For example,
+ out:
+ if (evg) libxl__evdisable_disk_eject(gc, evg);
+ if (nullfd >= 0) close(nullfd);
+ return rc;
+
+ * Function calls which might fail (ie most function calls) are
+ handled by putting the return/status value into a variable, and
+ then checking it in a separate statement:
+ char *dompath = libxl__xs_get_dompath(gc, bl->domid);
+ if (!dompath) { rc = ERROR_FAIL; goto out; }
+
+ * If a resource is freed in the main body of the function (for
+ example, in a loop), the corresponding variable has to be reset to
+ the sentinel at the point where it's freed.
+
+Whether to use the `out' path for successful returns as well as error
+returns is a matter of taste and convenience for the specific
+function. Not reusing the out path is fine if the duplicated function
+exit code is only `CTX_UNLOCK; GC_FREE;' (or similar).
+
+If you reuse the `out' path for successful returns, there may be
+resources which are to be returned to the caller rather than freed.
+In that case you have to reset the local variable to `nothing here',
+to avoid the resource being freed on the out path. That resetting
+should be done immediately after the resource value is stored at the
+applicable _r function parameter (or equivalent). Do not test `rc' in
+the out section, to discover whether to free things.
+
+The uses of the single-line formatting in the examples above are
+permitted exceptions to the usual libxl code formatting rules.
+
+
+
+IDEMPOTENT DATA STRUCTURE CONSTRUCTION/DESTRUCTION
+--------------------------------------------------
+
+Nontrivial data structures (in structs) should come with an idempotent
+_dispose function, which must free all resources associated with the
+data structure (but not free the struct itself).
+
+Such a struct should also come with an _init function which
+initialises the struct so that _dispose is a no-op.
+
+
+ASYNCHRONOUS/LONG-RUNNING OPERATIONS
+------------------------------------
+
+All long-running operations in libxl need to use the asynchronous
+operation machinery. Consult the programmer documentation in
+libxl_internal.h for details - search for "Machinery for asynchronous
+operations".
+
+The code for asynchronous operations should be laid out in
+chronological order. That is, where there is a chain of callback
+functions, each subsequent function should be, textually, the next
+function in the file. This will normally involve predeclaring the
+callback functions. Synchronous helper functions should be separated
+out into a section preceding the main callback chain.
+
+Control flow arrangements in asynchronous operations should be made as
+simple as possible, because it can otherwise be very hard to see
+through the tangle.
+
+
+When inventing a new sub-operation in asynchronous code, consider
+whether to structure it formally as a sub-operation with its own state
+structure. (See, for example, libxl__datacopier_*.)
+
+An ao-suboperation state structure should contain, in this order:
+ * fields that the caller must fill in, and which are,
+ effectively, the parameters to the operation, including:
+ - libxl__ao *ao
+ - the callback function pointer(s), which
+ should be named callback or callback_*.
+ * shared information fields or ones used for returning information
+ to the calling operation
+ * private fields
+These sections should be clearly demarcated by comments.
+
+An asynchronous operation should normally have an idempotent stop or
+cancel function. It should normally also have an _init function for
+its state struct, which arranges that the stop is a no-op.
+
+The permitted order of calls into your ao operation's methods must be
+documented in comments, if it is nontrivial.
+
+
+When using an ao sub-operation, you should normally:
+ * Physically include the sub-operation state struct in your
+ own state struct;
+ * Use CONTAINER_OF to find your own state struct at the start of
+ your implementations of the sub-operation callback functions;
+ * Unconditionally initialise the sub-operation's struct (with its
+ _init method) in your own _init method.
+ * Unconditionally cancel or destroy the sub-operation in your own
+ cancel or destroy method.
+
+
+FORMATTING AND NAMING
+---------------------
+
Blatantly copied from qemu and linux with few modifications.
@@ -72,7 +257,10 @@ variable that is used to hold a temporary value.
Local variables used to store return values should have descriptive name
like "rc" or "ret". Following the same reasoning the label used as exit
-path should be called "out" or "error".
+path should be called "out".
+
+Function arguments which are used to return values to the caller
+should be suffixed `_r' or `_out'.
Variables, type names and function names are
lower_case_with_underscores.
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 755b666..df08c8a 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -5,7 +5,7 @@
XEN_ROOT = $(CURDIR)/../..
include $(XEN_ROOT)/tools/Rules.mk
-MAJOR = 4.4
+MAJOR = 4.5
MINOR = 0
XLUMAJOR = 4.3
@@ -21,11 +21,17 @@ endif
LIBXL_LIBS =
LIBXL_LIBS = $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(LDLIBS_libblktapctl) $(PTYFUNCS_LIBS) $(LIBUUID_LIBS)
+ifeq ($(CONFIG_REMUS_NETBUF),y)
+LIBXL_LIBS += $(LIBNL3_LIBS)
+endif
CFLAGS_LIBXL += $(CFLAGS_libxenctrl)
CFLAGS_LIBXL += $(CFLAGS_libxenguest)
CFLAGS_LIBXL += $(CFLAGS_libxenstore)
CFLAGS_LIBXL += $(CFLAGS_libblktapctl)
+ifeq ($(CONFIG_REMUS_NETBUF),y)
+CFLAGS_LIBXL += $(LIBNL3_CFLAGS)
+endif
CFLAGS_LIBXL += -Wshadow
LIBXL_LIBS-$(CONFIG_ARM) += -lfdt
@@ -43,7 +49,16 @@ LIBXL_OBJS-y += libxl_blktap2.o
else
LIBXL_OBJS-y += libxl_noblktap2.o
endif
-LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid.o libxl_x86.o
+
+ifeq ($(CONFIG_REMUS_NETBUF),y)
+LIBXL_OBJS-y += libxl_netbuffer.o
+else
+LIBXL_OBJS-y += libxl_nonetbuffer.o
+endif
+
+LIBXL_OBJS-y += libxl_remus_device.o libxl_remus_disk_drbd.o
+
+LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid.o libxl_x86.o libxl_psr.o
LIBXL_OBJS-$(CONFIG_ARM) += libxl_nocpuid.o libxl_arm.o
ifeq ($(CONFIG_NetBSD),y)
@@ -52,10 +67,14 @@ else
ifeq ($(CONFIG_Linux),y)
LIBXL_OBJS-y += libxl_linux.o
else
+ifeq ($(CONFIG_FreeBSD),y)
+LIBXL_OBJS-y += libxl_freebsd.o
+else
$(error Your Operating System is not supported by libxenlight, \
please check libxl_linux.c and libxl_netbsd.c to see how to get it ported)
endif
endif
+endif
ifeq ($(FLEX),)
%.c %.h:: %.l
@@ -77,6 +96,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
libxl_json.o libxl_aoutils.o libxl_numa.o \
libxl_save_callout.o _libxl_save_msgs_callout.o \
libxl_qmp.o libxl_event.o libxl_fork.o $(LIBXL_OBJS-y)
+LIBXL_OBJS += libxl_genid.o
LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o
LIBXL_TESTS += timedereg
@@ -105,7 +125,7 @@ LIBXLU_OBJS = libxlu_cfg_y.o libxlu_cfg_l.o libxlu_cfg.o \
libxlu_disk_l.o libxlu_disk.o libxlu_vif.o libxlu_pci.o
$(LIBXLU_OBJS): CFLAGS += $(CFLAGS_libxenctrl) # For xentoollog.h
-CLIENTS = xl testidl libxl-save-helper
+CLIENTS = xl testidl libxl-save-helper xen-init-dom0
CFLAGS_XL += $(CFLAGS_libxenlight)
CFLAGS_XL += -Wshadow
@@ -116,6 +136,10 @@ $(XL_OBJS) $(TEST_PROG_OBJS) _libxl.api-for-check: \
$(XL_OBJS): CFLAGS += $(CFLAGS_XL)
$(XL_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config.h # libxl_json.h needs it.
+XEN_INIT_DOM0_OBJS = xen-init-dom0.o
+$(XEN_INIT_DOM0_OBJS): CFLAGS += $(CFLAGS_libxenctrl)
+$(XEN_INIT_DOM0_OBJS): CFLAGS += $(CFLAGS_libxenstore)
+
SAVE_HELPER_OBJS = libxl_save_helper.o _libxl_save_msgs_helper.o
$(SAVE_HELPER_OBJS): CFLAGS += $(CFLAGS_libxenctrl)
@@ -130,7 +154,7 @@ all: $(CLIENTS) $(TEST_PROGS) \
$(AUTOSRCS) $(AUTOINCS)
$(LIBXL_OBJS) $(LIBXLU_OBJS) $(XL_OBJS) $(SAVE_HELPER_OBJS) \
- $(LIBXL_TEST_OBJS) $(TEST_PROG_OBJS): \
+ $(LIBXL_TEST_OBJS) $(TEST_PROG_OBJS) $(XEN_INIT_DOM0_OBJS): \
$(AUTOINCS) libxl.api-ok
%.c %.h:: %.y
@@ -141,7 +165,7 @@ $(LIBXL_OBJS) $(LIBXLU_OBJS) $(XL_OBJS) $(SAVE_HELPER_OBJS) \
@rm -f $*.[ch]
$(FLEX) --header-file=$*.h --outfile=$*.c $<
-genpath-target = $(call buildmakevars2file,_paths.h.tmp)
+genpath-target = $(call buildmakevars2header,_paths.h)
$(eval $(genpath-target))
libxl.api-ok: check-libxl-api-rules _libxl.api-for-check
@@ -154,11 +178,6 @@ _%.api-for-check: %.h $(AUTOINCS)
>$@.new
mv -f $@.new $@
-_paths.h: genpath
- sed -e "s/\([^=]*\)=\(.*\)/#define \1 \2/g" $@.tmp >$@.2.tmp
- rm -f $@.tmp
- $(call move-if-changed,$@.2.tmp,$@)
-
_libxl_list.h: $(XEN_INCLUDE)/xen-external/bsd-sys-queue-h-seddery $(XEN_INCLUDE)/xen-external/bsd-sys-queue.h
$(PERL) $^ --prefix=libxl >$@.new
$(call move-if-changed,$@.new,$@)
@@ -169,27 +188,29 @@ _libxl_save_msgs_helper.h _libxl_save_msgs_callout.h: \
$(PERL) -w $< $@ >$@.new
$(call move-if-changed,$@.new,$@)
-libxl.h: _libxl_types.h
+libxl.h: _libxl_types.h _libxl_list.h
libxl_json.h: _libxl_types_json.h
-libxl_internal.h: _libxl_types_internal.h _paths.h
+libxl_internal.h: _libxl_types_internal.h _libxl_types_private.h _libxl_types_internal_private.h _paths.h
libxl_internal_json.h: _libxl_types_internal_json.h
xl.h: _paths.h
$(LIBXL_OBJS) $(LIBXL_TEST_OBJS) $(LIBXLU_OBJS) \
- $(XL_OBJS) $(TEST_PROG_OBJS) $(SAVE_HELPER_OBJS): libxl.h
+ $(XL_OBJS) $(TEST_PROG_OBJS) $(SAVE_HELPER_OBJS) $(XEN_INIT_DOM0_OBJS): libxl.h
$(LIBXL_OBJS) $(LIBXL_TEST_OBJS): libxl_internal.h
-_libxl_type%.h _libxl_type%_json.h _libxl_type%.c: libxl_type%.idl gentypes.py idl.py
- $(PYTHON) gentypes.py libxl_type$*.idl __libxl_type$*.h __libxl_type$*_json.h __libxl_type$*.c
+_libxl_type%.h _libxl_type%_json.h _libxl_type%_private.h _libxl_type%.c: libxl_type%.idl gentypes.py idl.py
+ $(PYTHON) gentypes.py libxl_type$*.idl __libxl_type$*.h __libxl_type$*_private.h \
+ __libxl_type$*_json.h __libxl_type$*.c
$(call move-if-changed,__libxl_type$*.h,_libxl_type$*.h)
+ $(call move-if-changed,__libxl_type$*_private.h,_libxl_type$*_private.h)
$(call move-if-changed,__libxl_type$*_json.h,_libxl_type$*_json.h)
$(call move-if-changed,__libxl_type$*.c,_libxl_type$*.c)
libxenlight.so: libxenlight.so.$(MAJOR)
- ln -sf $< $@
+ $(SYMLINK_SHLIB) $< $@
libxenlight.so.$(MAJOR): libxenlight.so.$(MAJOR).$(MINOR)
- ln -sf $< $@
+ $(SYMLINK_SHLIB) $< $@
libxenlight.so.$(MAJOR).$(MINOR): $(LIBXL_OBJS)
$(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenlight.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LIBXL_LIBS) $(APPEND_LDFLAGS)
@@ -201,10 +222,10 @@ libxenlight.a: $(LIBXL_OBJS)
$(AR) rcs libxenlight.a $^
libxlutil.so: libxlutil.so.$(XLUMAJOR)
- ln -sf $< $@
+ $(SYMLINK_SHLIB) $< $@
libxlutil.so.$(XLUMAJOR): libxlutil.so.$(XLUMAJOR).$(XLUMINOR)
- ln -sf $< $@
+ $(SYMLINK_SHLIB) $< $@
libxlutil.so.$(XLUMAJOR).$(XLUMINOR): $(LIBXLU_OBJS)
$(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxlutil.so.$(XLUMAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LIBXLU_LIBS) $(APPEND_LDFLAGS)
@@ -215,6 +236,9 @@ libxlutil.a: $(LIBXLU_OBJS)
xl: $(XL_OBJS) libxlutil.so libxenlight.so
$(CC) $(LDFLAGS) -o $@ $(XL_OBJS) libxlutil.so $(LDLIBS_libxenlight) $(LDLIBS_libxenctrl) -lyajl $(APPEND_LDFLAGS)
+xen-init-dom0: $(XEN_INIT_DOM0_OBJS) libxenlight.so
+ $(CC) $(LDFLAGS) -o $@ $(XEN_INIT_DOM0_OBJS) $(LDLIBS_libxenstore) $(LDLIBS_libxenlight) $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
+
test_%: test_%.o test_common.o libxlutil.so libxenlight_test.so
$(CC) $(LDFLAGS) -o $@ $^ $(filter-out %libxenlight.so, $(LDLIBS_libxenlight)) $(LDLIBS_libxenctrl) -lyajl $(APPEND_LDFLAGS)
@@ -230,17 +254,17 @@ install: all
$(INSTALL_DIR) $(DESTDIR)$(LIBDIR)
$(INSTALL_DIR) $(DESTDIR)$(INCLUDEDIR)
$(INSTALL_DIR) $(DESTDIR)$(BASH_COMPLETION_DIR)
- $(INSTALL_DIR) $(DESTDIR)$(XEN_RUN_DIR)
- $(INSTALL_DIR) $(DESTDIR)$(PRIVATE_BINDIR)
+ $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN)
$(INSTALL_PROG) xl $(DESTDIR)$(SBINDIR)
- $(INSTALL_PROG) libxl-save-helper $(DESTDIR)$(PRIVATE_BINDIR)
- $(INSTALL_PROG) libxenlight.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)
- ln -sf libxenlight.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libxenlight.so.$(MAJOR)
- ln -sf libxenlight.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libxenlight.so
+ $(INSTALL_PROG) xen-init-dom0 $(DESTDIR)$(LIBEXEC_BIN)
+ $(INSTALL_PROG) libxl-save-helper $(DESTDIR)$(LIBEXEC_BIN)
+ $(INSTALL_SHLIB) libxenlight.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)
+ $(SYMLINK_SHLIB) libxenlight.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libxenlight.so.$(MAJOR)
+ $(SYMLINK_SHLIB) libxenlight.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libxenlight.so
$(INSTALL_DATA) libxenlight.a $(DESTDIR)$(LIBDIR)
- $(INSTALL_PROG) libxlutil.so.$(XLUMAJOR).$(XLUMINOR) $(DESTDIR)$(LIBDIR)
- ln -sf libxlutil.so.$(XLUMAJOR).$(XLUMINOR) $(DESTDIR)$(LIBDIR)/libxlutil.so.$(XLUMAJOR)
- ln -sf libxlutil.so.$(XLUMAJOR) $(DESTDIR)$(LIBDIR)/libxlutil.so
+ $(INSTALL_SHLIB) libxlutil.so.$(XLUMAJOR).$(XLUMINOR) $(DESTDIR)$(LIBDIR)
+ $(SYMLINK_SHLIB) libxlutil.so.$(XLUMAJOR).$(XLUMINOR) $(DESTDIR)$(LIBDIR)/libxlutil.so.$(XLUMAJOR)
+ $(SYMLINK_SHLIB) libxlutil.so.$(XLUMAJOR) $(DESTDIR)$(LIBDIR)/libxlutil.so
$(INSTALL_DATA) libxlutil.a $(DESTDIR)$(LIBDIR)
$(INSTALL_DATA) libxl.h libxl_event.h libxl_json.h _libxl_types.h _libxl_types_json.h _libxl_list.h libxl_utils.h libxl_uuid.h $(DESTDIR)$(INCLUDEDIR)
$(INSTALL_DATA) bash-completion $(DESTDIR)$(BASH_COMPLETION_DIR)/xl.sh
diff --git a/tools/libxl/check-xl-disk-parse b/tools/libxl/check-xl-disk-parse
index 797277c..1bec4ca 100755
--- a/tools/libxl/check-xl-disk-parse
+++ b/tools/libxl/check-xl-disk-parse
@@ -61,7 +61,9 @@ disk: {
"script": null,
"removable": 0,
"readwrite": 1,
- "is_cdrom": 0
+ "is_cdrom": 0,
+ "direct_io_safe": false,
+ "discard_enable": "True"
}
END
@@ -82,7 +84,9 @@ disk: {
"script": null,
"removable": 1,
"readwrite": 0,
- "is_cdrom": 1
+ "is_cdrom": 1,
+ "direct_io_safe": false,
+ "discard_enable": "False"
}
END
@@ -104,7 +108,9 @@ disk: {
"script": null,
"removable": 0,
"readwrite": 1,
- "is_cdrom": 0
+ "is_cdrom": 0,
+ "direct_io_safe": false,
+ "discard_enable": "True"
}
EOF
@@ -121,7 +127,9 @@ disk: {
"script": null,
"removable": 1,
"readwrite": 0,
- "is_cdrom": 1
+ "is_cdrom": 1,
+ "direct_io_safe": false,
+ "discard_enable": "False"
}
EOF
@@ -142,7 +150,9 @@ disk: {
"script": null,
"removable": 1,
"readwrite": 0,
- "is_cdrom": 1
+ "is_cdrom": 1,
+ "direct_io_safe": false,
+ "discard_enable": "False"
}
EOF
@@ -160,7 +170,9 @@ disk: {
"script": "block-iscsi",
"removable": 0,
"readwrite": 1,
- "is_cdrom": 0
+ "is_cdrom": 0,
+ "direct_io_safe": false,
+ "discard_enable": "True"
}
EOF
@@ -180,7 +192,9 @@ disk: {
"script": "block-drbd",
"removable": 0,
"readwrite": 1,
- "is_cdrom": 0
+ "is_cdrom": 0,
+ "direct_io_safe": false,
+ "discard_enable": "True"
}
EOF
@@ -189,4 +203,63 @@ EOF
# http://www.drbd.org/users-guide-emb/s-xen-configure-domu.html
one 0 drbd:app01,hda,w
+expected <<END
+disk: {
+ "backend_domid": 0,
+ "backend_domname": null,
+ "pdev_path": "/some/disk/image.raw",
+ "vdev": "hda",
+ "backend": "unknown",
+ "format": "raw",
+ "script": null,
+ "removable": 0,
+ "readwrite": 1,
+ "is_cdrom": 0,
+ "direct_io_safe": false,
+ "discard_enable": "True"
+}
+
+END
+one 0 discard=on vdev=hda target=/some/disk/image.raw
+one 0 discard=1 vdev=hda target=/some/disk/image.raw
+
+expected <<END
+disk: {
+ "backend_domid": 0,
+ "backend_domname": null,
+ "pdev_path": "/some/disk/image.raw",
+ "vdev": "hda",
+ "backend": "unknown",
+ "format": "raw",
+ "script": null,
+ "removable": 0,
+ "readwrite": 1,
+ "is_cdrom": 0,
+ "direct_io_safe": false,
+ "discard_enable": "False"
+}
+
+END
+one 0 discard vdev=hda target=/some/disk/image.raw
+one 0 discard vdev=hda target=/some/disk/image.raw
+
+expected <<END
+disk: {
+ "backend_domid": 0,
+ "backend_domname": null,
+ "pdev_path": "/some/disk/image.iso",
+ "vdev": "hda",
+ "backend": "unknown",
+ "format": "raw",
+ "script": null,
+ "removable": 1,
+ "readwrite": 0,
+ "is_cdrom": 1,
+ "direct_io_safe": false,
+ "discard_enable": "False"
+}
+
+END
+one 0 cdrom no-discard vdev=hda target=/some/disk/image.iso
+
complete
diff --git a/tools/libxl/gentest.py b/tools/libxl/gentest.py
index 722b7f4..95323d1 100644
--- a/tools/libxl/gentest.py
+++ b/tools/libxl/gentest.py
@@ -52,7 +52,7 @@ def gen_rand_init(ty, v, indent = " ", parent = None):
s += " break;\n"
s += "}\n"
elif isinstance(ty, idl.Struct) \
- and (parent is None or ty.json_fn is None):
+ and (parent is None or ty.json_gen_fn is None):
for f in [f for f in ty.fields if not f.const]:
(nparent,fexpr) = ty.member(v, f, parent is None)
s += gen_rand_init(f.type, fexpr, "", nparent)
@@ -60,7 +60,7 @@ def gen_rand_init(ty, v, indent = " ", parent = None):
s += "%s(%s);\n" % (ty.rand_init,
ty.pass_arg(v, isref=parent is None,
passby=idl.PASS_BY_REFERENCE))
- elif ty.typename in ["libxl_uuid", "libxl_mac", "libxl_hwcap"]:
+ elif ty.typename in ["libxl_uuid", "libxl_mac", "libxl_hwcap", "libxl_ms_vm_genid"]:
s += "rand_bytes((uint8_t *)%s, sizeof(*%s));\n" % (v,v)
elif ty.typename in ["libxl_domid", "libxl_devid"] or isinstance(ty, idl.Number):
s += "%s = rand() %% (sizeof(%s)*8);\n" % \
@@ -225,10 +225,11 @@ int main(int argc, char **argv)
""")
for ty in types:
- f.write(" %s %s_val;\n" % (ty.typename, ty.typename))
+ f.write(" %s %s_val, %s_val_new;\n" % \
+ (ty.typename, ty.typename, ty.typename))
f.write("""
int rc;
- char *s;
+ char *s, *new_s;
xentoollog_logger_stdiostream *logger;
libxl_ctx *ctx;
@@ -240,22 +241,75 @@ int main(int argc, char **argv)
exit(1);
}
""")
- f.write(" printf(\"Testing TYPE_to_json()\\n\");\n")
+ f.write(" printf(\"Testing TYPE_to/from_json()\\n\");\n")
f.write(" printf(\"----------------------\\n\");\n")
f.write(" printf(\"\\n\");\n")
- for ty in [t for t in types if t.json_fn is not None]:
+ for ty in [t for t in types if t.json_gen_fn is not None]:
arg = ty.typename + "_val"
f.write(" %s_rand_init(%s);\n" % (ty.typename, \
ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
+ if not isinstance(ty, idl.Enumeration):
+ f.write(" %s_init(%s_new);\n" % (ty.typename, \
+ ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
f.write(" s = %s_to_json(ctx, %s);\n" % \
(ty.typename, ty.pass_arg(arg, isref=False)))
f.write(" printf(\"%%s: %%s\\n\", \"%s\", s);\n" % ty.typename)
f.write(" if (s == NULL) abort();\n")
+ f.write(" rc = %s_from_json(ctx, &%s_val_new, s);\n" % \
+ (ty.typename, ty.typename))
+ f.write(" if (rc) abort();\n")
+ f.write(" new_s = %s_to_json(ctx, %s_new);\n" % \
+ (ty.typename, ty.pass_arg(arg, isref=False)))
+ f.write(" if (new_s == NULL) abort();\n")
+ f.write(" if (strcmp(s, new_s)) {\n")
+ f.write(" printf(\"Huh? Regenerated string different from original string.\\n\");\n")
+ f.write(" printf(\"Regenerated string: %s\\n\", new_s);\n")
+ f.write(" abort();\n")
+ f.write(" }\n")
f.write(" free(s);\n")
+ f.write(" free(new_s);\n")
if ty.dispose_fn is not None:
f.write(" %s(&%s_val);\n" % (ty.dispose_fn, ty.typename))
+ f.write(" %s(&%s_val_new);\n" % (ty.dispose_fn, ty.typename))
f.write("\n")
+ f.write(" printf(\"Testing TYPE_copy()\\n\");\n")
+ f.write(" printf(\"----------------------\\n\");\n")
+ f.write(" printf(\"\\n\");\n")
+ for ty in [t for t in types if t.copy_fn is not None]:
+ f.write(" printf(\"Testing %s_copy, \");\n" % ty.typename)
+ arg = ty.typename + "_val"
+ f.write(" %s_init(%s);\n" % (ty.typename, \
+ ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
+ f.write(" %s_rand_init(%s);\n" % (ty.typename, \
+ ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
+ f.write(" %s_init(%s_new);\n" % (ty.typename, \
+ ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
+ f.write(" %s_copy(ctx, %s_new, %s);\n" % (ty.typename, \
+ ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE), \
+ ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
+ f.write(" s = %s_to_json(ctx, %s);\n" % \
+ (ty.typename, ty.pass_arg(arg, isref=False)))
+ f.write(" if (s == NULL) abort();\n")
+ f.write(" new_s = %s_to_json(ctx, %s_new);\n" % \
+ (ty.typename, ty.pass_arg(arg, isref=False)))
+ f.write(" if (new_s == NULL) abort();\n")
+ f.write(" if (strcmp(s, new_s)) {\n")
+ f.write(" printf(\"Huh? Deep copy for %s failed. Regenerated string different from original string.\\n\");\n" \
+ % ty.typename)
+ f.write(" printf(\"Original string: %s\\n\", s);\n")
+ f.write(" printf(\"Regenerated string: %s\\n\", new_s);\n")
+ f.write(" abort();\n")
+ f.write(" }\n")
+ f.write(" free(s);\n")
+ f.write(" free(new_s);\n")
+ if ty.dispose_fn is not None:
+ f.write(" %s(&%s_val);\n" % (ty.dispose_fn, ty.typename))
+ f.write(" %s(&%s_val_new);\n" % (ty.dispose_fn, ty.typename))
+ f.write(" printf(\"done\\n\");\n")
+ f.write("\n")
+
+ f.write(" printf(\"\\n\");\n")
f.write(" printf(\"Testing Enumerations\\n\");\n")
f.write(" printf(\"--------------------\\n\");\n")
f.write(" printf(\"\\n\");\n")
diff --git a/tools/libxl/gentypes.py b/tools/libxl/gentypes.py
index be06257..3e73821 100644
--- a/tools/libxl/gentypes.py
+++ b/tools/libxl/gentypes.py
@@ -100,6 +100,61 @@ def libxl_C_type_dispose(ty, v, indent = " ", parent = None):
s = indent + s
return s.replace("\n", "\n%s" % indent).rstrip(indent)
+def libxl_C_type_copy(ty, v, w, indent = " ", vparent = None, wparent = None):
+ s = ""
+
+ if vparent is None:
+ s += "GC_INIT(ctx);\n";
+
+ if isinstance(ty, idl.KeyedUnion):
+ if vparent is None or wparent is None:
+ raise Exception("KeyedUnion type must have a parent")
+ s += "%s = %s;\n" % ((vparent + ty.keyvar.name), (wparent + ty.keyvar.name))
+ s += "switch (%s) {\n" % (wparent + ty.keyvar.name)
+ for f in ty.fields:
+ (vnparent,vfexpr) = ty.member(v, f, vparent is None)
+ (wnparent,wfexpr) = ty.member(w, f, wparent is None)
+ s += "case %s:\n" % f.enumname
+ if f.type is not None:
+ s += libxl_C_type_copy(f.type, vfexpr, wfexpr, indent + " ",
+ vnparent, wnparent)
+ s += " break;\n"
+ s += "}\n"
+ elif isinstance(ty, idl.Array):
+ if vparent is None or wparent is None:
+ raise Exception("Array type must have a parent")
+ s += "%s = libxl__calloc(NOGC, %s, sizeof(*%s));\n" % (ty.pass_arg(v, vparent is None),
+ (wparent + ty.lenvar.name),
+ ty.pass_arg(w, wparent is None))
+ s += "%s = %s;\n" % ((vparent + ty.lenvar.name), (wparent + ty.lenvar.name))
+ s += "{\n"
+ s += " int i;\n"
+ s += " for (i=0; i<%s; i++)\n" % (wparent + ty.lenvar.name)
+ s += libxl_C_type_copy(ty.elem_type, v+"[i]", w+"[i]",
+ indent + " ", vparent, wparent)
+ s += "}\n"
+ elif isinstance(ty, idl.Struct) and ((vparent is None and wparent is None) or ty.copy_fn is None):
+ for f in [f for f in ty.fields if not f.const and not f.type.private]:
+ (vnparent,vfexpr) = ty.member(v, f, vparent is None)
+ (wnparent,wfexpr) = ty.member(w, f, wparent is None)
+ s += libxl_C_type_copy(f.type, vfexpr, wfexpr, "", vnparent, wnparent)
+ else:
+ if ty.copy_fn is not None:
+ s += "%s(ctx, %s, %s);\n" % (ty.copy_fn,
+ ty.pass_arg(v, vparent is None, passby=idl.PASS_BY_REFERENCE),
+ ty.pass_arg(w, wparent is None, passby=idl.PASS_BY_REFERENCE))
+
+ else:
+ s += "%s = %s;\n" % (ty.pass_arg(v, vparent is None, passby=idl.PASS_BY_VALUE),
+ ty.pass_arg(w, wparent is None, passby=idl.PASS_BY_VALUE))
+
+ if vparent is None:
+ s += "GC_FREE;\n"
+
+ if s != "":
+ s = indent + s
+ return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
def libxl_init_members(ty, nesting = 0):
"""Returns a list of members of ty which require a separate init"""
@@ -186,6 +241,49 @@ def libxl_C_type_member_init(ty, field):
s += "\n"
return s
+def libxl_C_type_gen_map_key(f, parent, indent = ""):
+ s = ""
+ if isinstance(f.type, idl.KeyedUnion):
+ s += "switch (%s) {\n" % (parent + f.type.keyvar.name)
+ for x in f.type.fields:
+ v = f.type.keyvar.name + "." + x.name
+ s += "case %s:\n" % x.enumname
+ s += " s = yajl_gen_string(hand, (const unsigned char *)\"%s\", sizeof(\"%s\")-1);\n" % (v, v)
+ s += " if (s != yajl_gen_status_ok)\n"
+ s += " goto out;\n"
+ s += " break;\n"
+ s += "}\n"
+ else:
+ s += "s = yajl_gen_string(hand, (const unsigned char *)\"%s\", sizeof(\"%s\")-1);\n" % (f.name, f.name)
+ s += "if (s != yajl_gen_status_ok)\n"
+ s += " goto out;\n"
+ if s != "":
+ s = indent + s
+ return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+def get_init_val(f):
+ if f.init_val is not None:
+ return f.init_val
+ elif f.type.init_val is not None:
+ return f.type.init_val
+ return None
+
+def get_default_expr(f, nparent, fexpr):
+ if isinstance(f.type, idl.Aggregate):
+ return "1 /* always generate JSON output for aggregate type */"
+
+ if isinstance(f.type, idl.Array):
+ return "%s && %s" % (fexpr, nparent + f.type.lenvar.name)
+
+ init_val = get_init_val(f)
+ if init_val is not None:
+ return "%s != %s" % (fexpr, init_val)
+
+ if f.type.check_default_fn:
+ return "!%s(&%s)" % (f.type.check_default_fn, fexpr)
+
+ return "%s" % fexpr
+
def libxl_C_type_gen_json(ty, v, indent = " ", parent = None):
s = ""
if parent is None:
@@ -220,24 +318,35 @@ def libxl_C_type_gen_json(ty, v, indent = " ", parent = None):
s += "case %s:\n" % f.enumname
if f.type is not None:
s += libxl_C_type_gen_json(f.type, fexpr, indent + " ", nparent)
+ else:
+ s += " s = yajl_gen_map_open(hand);\n"
+ s += " if (s != yajl_gen_status_ok)\n"
+ s += " goto out;\n"
+ s += " s = yajl_gen_map_close(hand);\n"
+ s += " if (s != yajl_gen_status_ok)\n"
+ s += " goto out;\n"
s += " break;\n"
s += "}\n"
- elif isinstance(ty, idl.Struct) and (parent is None or ty.json_fn is None):
+ elif isinstance(ty, idl.Struct) and (parent is None or ty.json_gen_fn is None):
s += "s = yajl_gen_map_open(hand);\n"
s += "if (s != yajl_gen_status_ok)\n"
s += " goto out;\n"
- for f in [f for f in ty.fields if not f.const]:
+ for f in [f for f in ty.fields if not f.const and not f.type.private]:
(nparent,fexpr) = ty.member(v, f, parent is None)
- s += "s = yajl_gen_string(hand, (const unsigned char *)\"%s\", sizeof(\"%s\")-1);\n" % (f.name, f.name)
- s += "if (s != yajl_gen_status_ok)\n"
- s += " goto out;\n"
- s += libxl_C_type_gen_json(f.type, fexpr, "", nparent)
+ default_expr = get_default_expr(f, nparent, fexpr)
+ s += "if (%s) {\n" % default_expr
+
+ s += libxl_C_type_gen_map_key(f, nparent, " ")
+ s += libxl_C_type_gen_json(f.type, fexpr, " ", nparent)
+
+ s += "}\n"
+
s += "s = yajl_gen_map_close(hand);\n"
s += "if (s != yajl_gen_status_ok)\n"
s += " goto out;\n"
else:
- if ty.json_fn is not None:
- s += "s = %s(hand, %s);\n" % (ty.json_fn, ty.pass_arg(v, parent is None))
+ if ty.json_gen_fn is not None:
+ s += "s = %s(hand, %s);\n" % (ty.json_gen_fn, ty.pass_arg(v, parent is None))
s += "if (s != yajl_gen_status_ok)\n"
s += " goto out;\n"
@@ -258,6 +367,116 @@ def libxl_C_type_to_json(ty, v, indent = " "):
s = indent + s
return s.replace("\n", "\n%s" % indent).rstrip(indent)
+def libxl_C_type_parse_json(ty, w, v, indent = " ", parent = None, discriminator = None):
+ s = ""
+ if parent is None:
+ s += "int rc = 0;\n"
+ s += "const libxl__json_object *x = o;\n"
+
+ if isinstance(ty, idl.Array):
+ if parent is None:
+ raise Exception("Array type must have a parent")
+ if discriminator is not None:
+ raise Exception("Only KeyedUnion can have discriminator")
+ lenvar = parent + ty.lenvar.name
+ s += "{\n"
+ s += " libxl__json_object *t;\n"
+ s += " int i;\n"
+ s += " if (!libxl__json_object_is_array(x)) {\n"
+ s += " rc = -1;\n"
+ s += " goto out;\n"
+ s += " }\n"
+ s += " %s = x->u.array->count;\n" % lenvar
+ s += " %s = libxl__calloc(NOGC, %s, sizeof(*%s));\n" % (v, lenvar, v)
+ s += " if (!%s && %s != 0) {\n" % (v, lenvar)
+ s += " rc = -1;\n"
+ s += " goto out;\n"
+ s += " }\n"
+ s += " for (i=0; (t=libxl__json_array_get(x,i)); i++) {\n"
+ s += libxl_C_type_parse_json(ty.elem_type, "t", v+"[i]",
+ indent + " ", parent)
+ s += " }\n"
+ s += " if (i != %s) {\n" % lenvar
+ s += " rc = -1;\n"
+ s += " goto out;\n"
+ s += " }\n"
+ s += "}\n"
+ elif isinstance(ty, idl.Enumeration):
+ if discriminator is not None:
+ raise Exception("Only KeyedUnion can have discriminator")
+ s += "{\n"
+ s += " const char *enum_str;\n"
+ s += " if (!libxl__json_object_is_string(x)) {\n"
+ s += " rc = -1;\n"
+ s += " goto out;\n"
+ s += " }\n"
+ s += " enum_str = libxl__json_object_get_string(x);\n"
+ s += " rc = %s_from_string(enum_str, %s);\n" % (ty.typename, ty.pass_arg(v, parent is None, idl.PASS_BY_REFERENCE))
+ s += " if (rc)\n"
+ s += " goto out;\n"
+ s += "}\n"
+ elif isinstance(ty, idl.KeyedUnion):
+ if parent is None:
+ raise Exception("KeyedUnion type must have a parent")
+ if discriminator is None:
+ raise Excpetion("KeyedUnion type must have a discriminator")
+ for f in ty.fields:
+ if f.enumname != discriminator:
+ continue
+ (nparent,fexpr) = ty.member(v, f, parent is None)
+ if f.type is not None:
+ s += libxl_C_type_parse_json(f.type, w, fexpr, indent + " ", nparent)
+ elif isinstance(ty, idl.Struct) and (parent is None or ty.json_parse_fn is None):
+ if discriminator is not None:
+ raise Exception("Only KeyedUnion can have discriminator")
+ for f in [f for f in ty.fields if not f.const and not f.type.private]:
+ saved_var_name = "saved_%s" % f.name
+ s += "{\n"
+ s += " const libxl__json_object *%s = NULL;\n" % saved_var_name
+ s += " %s = x;\n" % saved_var_name
+ if isinstance(f.type, idl.KeyedUnion):
+ for x in f.type.fields:
+ s += " x = libxl__json_map_get(\"%s\", %s, JSON_MAP);\n" % \
+ (f.type.keyvar.name + "." + x.name, w)
+ s += " if (x) {\n"
+ (nparent, fexpr) = ty.member(v, f.type.keyvar, parent is None)
+ s += " %s_init_%s(%s, %s);\n" % (ty.typename, f.type.keyvar.name, v, x.enumname)
+ (nparent,fexpr) = ty.member(v, f, parent is None)
+ s += libxl_C_type_parse_json(f.type, "x", fexpr, " ", nparent, x.enumname)
+ s += " }\n"
+ else:
+ s += " x = libxl__json_map_get(\"%s\", %s, %s);\n" % (f.name, w, f.type.json_parse_type)
+ s += " if (x) {\n"
+ (nparent,fexpr) = ty.member(v, f, parent is None)
+ s += libxl_C_type_parse_json(f.type, "x", fexpr, " ", nparent)
+ s += " }\n"
+ s += " x = %s;\n" % saved_var_name
+ s += "}\n"
+ else:
+ if discriminator is not None:
+ raise Exception("Only KeyedUnion can have discriminator")
+ if ty.json_parse_fn is not None:
+ s += "rc = %s(gc, %s, &%s);\n" % (ty.json_parse_fn, w, v)
+ s += "if (rc)\n"
+ s += " goto out;\n"
+
+ if parent is None:
+ s += "out:\n"
+ s += "return rc;\n"
+
+ if s != "":
+ s = indent +s
+ return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+def libxl_C_type_from_json(ty, v, w, indent = " "):
+ s = ""
+ parse = "(libxl__json_parse_callback)&%s_parse_json" % (ty.namespace + "_" + ty.rawname)
+ s += "return libxl__object_from_json(ctx, \"%s\", %s, %s, %s);\n" % (ty.typename, parse, v, w)
+
+ if s != "":
+ s = indent + s
+ return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
def libxl_C_enum_to_string(ty, e, indent = " "):
s = ""
s += "switch(%s) {\n" % e
@@ -296,11 +515,11 @@ def libxl_C_enum_from_string(ty, str, e, indent = " "):
if __name__ == '__main__':
- if len(sys.argv) != 5:
- print >>sys.stderr, "Usage: gentypes.py <idl> <header> <header-json> <implementation>"
+ if len(sys.argv) != 6:
+ print >>sys.stderr, "Usage: gentypes.py <idl> <header> <header-private> <header-json> <implementation>"
sys.exit(1)
- (_, idlname, header, header_json, impl) = sys.argv
+ (_, idlname, header, header_private, header_json, impl) = sys.argv
(builtins,types) = idl.parse(idlname)
@@ -325,6 +544,9 @@ if __name__ == '__main__':
f.write(libxl_C_type_define(ty) + ";\n")
if ty.dispose_fn is not None:
f.write("%svoid %s(%s);\n" % (ty.hidden(), ty.dispose_fn, ty.make_arg("p")))
+ if ty.copy_fn is not None:
+ f.write("%svoid %s(libxl_ctx *ctx, %s, %s);\n" % (ty.hidden(), ty.copy_fn,
+ ty.make_arg("dst"), ty.make_arg("src")))
if ty.init_fn is not None:
f.write("%svoid %s(%s);\n" % (ty.hidden(), ty.init_fn, ty.make_arg("p")))
for field in libxl_init_members(ty):
@@ -334,8 +556,10 @@ if __name__ == '__main__':
f.write("%svoid %s(%s, %s);\n" % (ty.hidden(), ty.init_fn + "_" + ku.keyvar.name,
ty.make_arg("p"),
ku.keyvar.type.make_arg(ku.keyvar.name)))
- if ty.json_fn is not None:
+ if ty.json_gen_fn is not None:
f.write("%schar *%s_to_json(libxl_ctx *ctx, %s);\n" % (ty.hidden(), ty.typename, ty.make_arg("p")))
+ if ty.json_parse_fn is not None:
+ f.write("%sint %s_from_json(libxl_ctx *ctx, %s, const char *s);\n" % (ty.hidden(), ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
if isinstance(ty, idl.Enumeration):
f.write("%sconst char *%s_to_string(%s);\n" % (ty.hidden(), ty.typename, ty.make_arg("p")))
f.write("%sint %s_from_string(const char *s, %s);\n" % (ty.hidden(), ty.typename, ty.make_arg("e", passby=idl.PASS_BY_REFERENCE)))
@@ -362,13 +586,39 @@ if __name__ == '__main__':
""" % (header_json_define, header_json_define, " ".join(sys.argv)))
- for ty in [ty for ty in types if ty.json_fn is not None]:
+ for ty in [ty for ty in types if ty.json_gen_fn is not None]:
f.write("%syajl_gen_status %s_gen_json(yajl_gen hand, %s);\n" % (ty.hidden(), ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
f.write("\n")
f.write("""#endif /* %s */\n""" % header_json_define)
f.close()
+ print "outputting libxl type internal definitions to %s" % header_private
+
+ f = open(header_private, "w")
+
+ header_private_define = header_private.upper().replace('.','_')
+ f.write("""#ifndef %s
+#define %s
+
+/*
+ * DO NOT EDIT.
+ *
+ * This file is autogenerated by
+ * "%s"
+ */
+
+""" % (header_private_define, header_private_define, " ".join(sys.argv)))
+
+ for ty in [ty for ty in types if ty.json_parse_fn is not None]:
+ f.write("%sint %s_parse_json(libxl__gc *gc, const libxl__json_object *o, %s);\n" % \
+ (ty.hidden(), ty.namespace + "_" + ty.rawname,
+ ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
+
+ f.write("\n")
+ f.write("""#endif /* %s */\n""" % header_json_define)
+ f.close()
+
print "outputting libxl type implementations to %s" % impl
f = open(impl, "w")
@@ -398,6 +648,15 @@ if __name__ == '__main__':
f.write(" memset(p, LIBXL_DTOR_POISON, sizeof(*p));\n")
f.write("}\n")
f.write("\n")
+
+ for ty in [t for t in types if t.copy_fn and t.autogenerate_copy_fn]:
+ f.write("void %s(libxl_ctx *ctx, %s, %s)\n" % (ty.copy_fn,
+ ty.make_arg("dst", passby=idl.PASS_BY_REFERENCE),
+ ty.make_arg("src", passby=idl.PASS_BY_REFERENCE)))
+ f.write("{\n")
+ f.write(libxl_C_type_copy(ty, "dst", "src"))
+ f.write("}\n")
+ f.write("\n")
for ty in [t for t in types if t.init_fn is not None and t.autogenerate_init_fn]:
f.write(libxl_C_type_init(ty))
@@ -419,7 +678,7 @@ if __name__ == '__main__':
f.write("}\n")
f.write("\n")
- for ty in [t for t in types if t.json_fn is not None]:
+ for ty in [t for t in types if t.json_gen_fn is not None]:
f.write("yajl_gen_status %s_gen_json(yajl_gen hand, %s)\n" % (ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
f.write("{\n")
f.write(libxl_C_type_gen_json(ty, "p"))
@@ -432,4 +691,20 @@ if __name__ == '__main__':
f.write("}\n")
f.write("\n")
+ for ty in [t for t in types if t.json_parse_fn is not None]:
+ f.write("int %s_parse_json(libxl__gc *gc, const libxl__json_object *%s, %s)\n" % \
+ (ty.namespace + "_" + ty.rawname,"o",ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
+ f.write("{\n")
+ f.write(libxl_C_type_parse_json(ty, "o", "p"))
+ f.write("}\n")
+ f.write("\n")
+
+ f.write("int %s_from_json(libxl_ctx *ctx, %s, const char *s)\n" % (ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
+ f.write("{\n")
+ if not isinstance(ty, idl.Enumeration):
+ f.write(" %s_init(p);\n" % ty.typename)
+ f.write(libxl_C_type_from_json(ty, "p", "s"))
+ f.write("}\n")
+ f.write("\n")
+
f.close()
diff --git a/tools/libxl/idl.py b/tools/libxl/idl.py
index e4dc79b..437049e 100644
--- a/tools/libxl/idl.py
+++ b/tools/libxl/idl.py
@@ -60,14 +60,32 @@ class Type(object):
self.autogenerate_dispose_fn = kwargs.setdefault('autogenerate_dispose_fn', True)
+ if self.typename is not None:
+ self.copy_fn = kwargs.setdefault('copy_fn', self.typename + "_copy")
+ else:
+ self.copy_fn = kwargs.setdefault('copy_fn', None)
+
+ self.autogenerate_copy_fn = kwargs.setdefault('autogenerate_copy_fn', True)
+
self.init_fn = kwargs.setdefault('init_fn', None)
self.init_val = kwargs.setdefault('init_val', None)
self.autogenerate_init_fn = kwargs.setdefault('autogenerate_init_fn', False)
+ self.check_default_fn = kwargs.setdefault('check_default_fn', None)
+
if self.typename is not None and not self.private:
- self.json_fn = kwargs.setdefault('json_fn', self.typename + "_gen_json")
+ self.json_gen_fn = kwargs.setdefault('json_gen_fn', self.typename + "_gen_json")
+ self.json_parse_type = kwargs.setdefault('json_parse_type', "JSON_ANY")
+ if self.namespace is not None:
+ self.json_parse_fn = kwargs.setdefault('json_parse_fn',
+ self.namespace + "_" + self.rawname + "_parse_json")
+ else:
+ self.json_parse_fn = kwargs.setdefault('json_parse_fn',
+ self.typename + "_parse_json")
else:
- self.json_fn = kwargs.setdefault('json_fn', None)
+ self.json_gen_fn = kwargs.setdefault('json_gen_fn', None)
+ self.json_parse_type = kwargs.setdefault('json_parse_type', None)
+ self.json_parse_fn = kwargs.setdefault('json_parse_fn', None)
self.autogenerate_json = kwargs.setdefault('autogenerate_json', True)
@@ -117,8 +135,12 @@ class Number(Builtin):
def __init__(self, ctype, **kwargs):
kwargs.setdefault('namespace', None)
kwargs.setdefault('dispose_fn', None)
+ kwargs.setdefault('copy_fn', None)
kwargs.setdefault('signed', False)
- kwargs.setdefault('json_fn', "yajl_gen_integer")
+ kwargs.setdefault('json_gen_fn', "yajl_gen_integer")
+ kwargs.setdefault('json_parse_type', "JSON_INTEGER")
+ # json_parse_fn might be overriden on specific type
+ kwargs.setdefault('json_parse_fn', "libxl__int_parse_json")
self.signed = kwargs['signed']
Builtin.__init__(self, ctype, **kwargs)
@@ -126,6 +148,8 @@ class UInt(Number):
def __init__(self, w, **kwargs):
kwargs.setdefault('namespace', None)
kwargs.setdefault('dispose_fn', None)
+ kwargs.setdefault('json_parse_fn', "libxl__uint%d_parse_json" % w)
+ kwargs.setdefault('copy_fn', None)
Number.__init__(self, "uint%d_t" % w, **kwargs)
self.width = w
@@ -142,6 +166,8 @@ class EnumerationValue(object):
class Enumeration(Type):
def __init__(self, typename, values, **kwargs):
kwargs.setdefault('dispose_fn', None)
+ kwargs.setdefault('copy_fn', None)
+ kwargs.setdefault('json_parse_type', "JSON_STRING")
Type.__init__(self, typename, **kwargs)
self.value_namespace = kwargs.setdefault('value_namespace',
@@ -171,6 +197,7 @@ class Field(object):
class Aggregate(Type):
"""A type containing a collection of other types"""
def __init__(self, kind, typename, fields, **kwargs):
+ kwargs.setdefault('json_parse_type', "JSON_MAP")
Type.__init__(self, typename, **kwargs)
if self.typename is not None:
@@ -256,7 +283,10 @@ class KeyedUnion(Aggregate):
void = Builtin("void *", namespace = None)
bool = Builtin("bool", namespace = None,
- json_fn = "yajl_gen_bool",
+ copy_fn=None,
+ json_gen_fn = "yajl_gen_bool",
+ json_parse_type = "JSON_BOOL",
+ json_parse_fn = "libxl__bool_parse_json",
autogenerate_json = False)
size_t = Number("size_t", namespace = None)
@@ -266,16 +296,19 @@ integer = Number("int", namespace = None, signed = True)
uint8 = UInt(8)
uint16 = UInt(16)
uint32 = UInt(32)
-uint64 = UInt(64)
+uint64 = UInt(64, json_gen_fn = "libxl__uint64_gen_json")
-string = Builtin("char *", namespace = None, dispose_fn = "free",
- json_fn = "libxl__string_gen_json",
+string = Builtin("char *", namespace = None, copy_fn = "libxl_string_copy", dispose_fn = "free",
+ json_gen_fn = "libxl__string_gen_json",
+ json_parse_type = "JSON_STRING | JSON_NULL",
+ json_parse_fn = "libxl__string_parse_json",
autogenerate_json = False)
class Array(Type):
"""An array of the same type"""
def __init__(self, elem_type, lenvar_name, **kwargs):
kwargs.setdefault('dispose_fn', 'free')
+ kwargs.setdefault('json_parse_type', 'JSON_ARRAY')
Type.__init__(self, namespace=elem_type.namespace, typename=elem_type.rawname + " *", **kwargs)
lv_kwargs = dict([(x.lstrip('lenvar_'),y) for (x,y) in kwargs.items() if x.startswith('lenvar_')])
diff --git a/tools/libxl/idl.txt b/tools/libxl/idl.txt
index 439aede..7440fb3 100644
--- a/tools/libxl/idl.txt
+++ b/tools/libxl/idl.txt
@@ -44,6 +44,18 @@ Type.autogenerate_dispose_fn: (default: True)
Indicates if the above named Type.dispose_fn should be
autogenerated.
+Type.copy_fn: (default: typename + "_copy" or None if type == None)
+
+ The name of the C function which will deep copy all fields within
+ this type.
+
+Type.autogenerate_copy_fn: (default: True)
+
+ Indicates if the above named Type.copy_fn should be
+ autogenerated.
+
+Type.autogenerate_copy_fn
+
Type.init_val: (default: None)
C expression for the value to initialise instances of this type to.
@@ -60,14 +72,28 @@ Type.autogenerate_init_fn: (default: True if dir in [IN, BOTH])
Indicates if the above named Type.init_fn should be
autogenerated.
-Type.json_fn: (default: typename + "_gen_json" or None if type == None)
+Type.json_gen_fn: (default: typename + "_gen_json" or None if type == None)
The name of the C function which will generate a YAJL data structure
representing this type.
+Type.json_parse_fn: (default: typename + "_parse_json" or None if type == None)
+
+ The name of the C function which will parse a libxl JSON structure
+ representing this type to C type.
+
Type.autogenerate_json: (default: True)
- Indicates if the above named Type.json_fn should be autogenerated.
+ Indicates if the above named Type.json_*_fn should be autogenerated.
+
+Type.check_default_fn:
+
+ If it's set then calling this function shall return true if this type
+ has been set to default value (internal libxl implementation).
+
+ If this is not set, that means we can check the type against init_val
+ (if it has one) or zero to determine whether the value is default
+ value.
Other simple type-Classes
-------------------------
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 2d29ad2..f84f7c2 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -21,10 +21,20 @@
#define PAGE_TO_MEMKB(pages) ((pages) * 4)
#define BACKEND_STRING_SIZE 5
+/* Utility to read backend xenstore keys */
+#define READ_BACKEND(tgc, subpath) ({ \
+ rc = libxl__xs_read_checked(tgc, XBT_NULL, \
+ GCSPRINTF("%s/" subpath, be_path), \
+ &tmp); \
+ if (rc) goto out; \
+ (char*)tmp; \
+ });
+
int libxl_ctx_alloc(libxl_ctx **pctx, int version,
unsigned flags, xentoollog_logger * lg)
{
libxl_ctx *ctx = NULL;
+ libxl__gc gc_buf, *gc = NULL;
int rc;
if (version != LIBXL_VERSION) { rc = ERROR_VERSION; goto out; }
@@ -59,6 +69,10 @@ int libxl_ctx_alloc(libxl_ctx **pctx, int version,
LIBXL_SLIST_INIT(&ctx->watch_freeslots);
libxl__ev_fd_init(&ctx->watch_efd);
+ ctx->xce = 0;
+ LIBXL_LIST_INIT(&ctx->evtchns_waiting);
+ libxl__ev_fd_init(&ctx->evtchn_efd);
+
LIBXL_TAILQ_INIT(&ctx->death_list);
libxl__ev_xswatch_init(&ctx->death_watch);
@@ -66,6 +80,7 @@ int libxl_ctx_alloc(libxl_ctx **pctx, int version,
ctx->childproc_user = 0;
ctx->sigchld_selfpipe[0] = -1;
+ ctx->sigchld_selfpipe[1] = -1;
libxl__ev_fd_init(&ctx->sigchld_selfpipe_efd);
/* The mutex is special because we can't idempotently destroy it */
@@ -79,17 +94,19 @@ int libxl_ctx_alloc(libxl_ctx **pctx, int version,
}
/* Now ctx is safe for ctx_free; failures simply set rc and "goto out" */
+ LIBXL_INIT_GC(gc_buf,ctx);
+ gc = &gc_buf;
+ /* Now gc is useable */
rc = libxl__atfork_init(ctx);
if (rc) goto out;
- rc = libxl__poller_init(ctx, &ctx->poller_app);
+ rc = libxl__poller_init(gc, &ctx->poller_app);
if (rc) goto out;
ctx->xch = xc_interface_open(lg,lg,0);
if (!ctx->xch) {
- LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, errno,
- "cannot open libxc handle");
+ LOGEV(ERROR, errno, "cannot open libxc handle");
rc = ERROR_FAIL; goto out;
}
@@ -97,15 +114,17 @@ int libxl_ctx_alloc(libxl_ctx **pctx, int version,
if (!ctx->xsh)
ctx->xsh = xs_domain_open();
if (!ctx->xsh) {
- LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, errno,
- "cannot connect to xenstore");
+ LOGEV(ERROR, errno, "cannot connect to xenstore");
rc = ERROR_FAIL; goto out;
}
+ rc = libxl__ctx_evtchn_init(gc);
+
*pctx = ctx;
return 0;
out:
+ if (gc) libxl__free_all(gc);
libxl_ctx_free(ctx);
*pctx = NULL;
return rc;
@@ -144,16 +163,19 @@ int libxl_ctx_free(libxl_ctx *ctx)
for (i = 0; i < ctx->watch_nslots; i++)
assert(!libxl__watch_slot_contents(gc, i));
libxl__ev_fd_deregister(gc, &ctx->watch_efd);
+ libxl__ev_fd_deregister(gc, &ctx->evtchn_efd);
libxl__ev_fd_deregister(gc, &ctx->sigchld_selfpipe_efd);
/* Now there should be no more events requested from the application: */
assert(LIBXL_LIST_EMPTY(&ctx->efds));
assert(LIBXL_TAILQ_EMPTY(&ctx->etimes));
+ assert(LIBXL_LIST_EMPTY(&ctx->evtchns_waiting));
if (ctx->xch) xc_interface_close(ctx->xch);
libxl_version_info_dispose(&ctx->version_info);
if (ctx->xsh) xs_daemon_close(ctx->xsh);
+ if (ctx->xce) xc_evtchn_close(ctx->xce);
libxl__poller_dispose(&ctx->poller_app);
assert(LIBXL_LIST_EMPTY(&ctx->pollers_event));
@@ -193,6 +215,29 @@ void libxl_string_list_dispose(libxl_string_list *psl)
free(sl);
}
+void libxl_string_list_copy(libxl_ctx *ctx,
+ libxl_string_list *dst,
+ libxl_string_list *src)
+{
+ GC_INIT(ctx);
+ int i, len;
+
+ if (!*src) {
+ *dst = NULL;
+ goto out;
+ }
+
+ len = libxl_string_list_length(src);
+ /* one extra slot for sentinel */
+ *dst = libxl__calloc(NOGC, len + 1, sizeof(char *));
+
+ for (i = 0; i < len; i++)
+ (*dst)[i] = libxl__strdup(NOGC, (*src)[i]);
+
+out:
+ GC_FREE;
+}
+
int libxl_string_list_length(const libxl_string_list *psl)
{
int i = 0;
@@ -204,6 +249,19 @@ int libxl_string_list_length(const libxl_string_list *psl)
return i;
}
+int libxl_key_value_list_length(libxl_key_value_list *pkvl)
+{
+ int i = 0;
+ libxl_key_value_list kvl = *pkvl;
+
+ if (kvl) {
+ while (kvl[2 * i]) /* Only checks keys */
+ i++;
+ }
+
+ return i;
+}
+
void libxl_key_value_list_dispose(libxl_key_value_list *pkvl)
{
int i;
@@ -220,9 +278,33 @@ void libxl_key_value_list_dispose(libxl_key_value_list *pkvl)
free(kvl);
}
-#define LIBXL__DEFBOOL_DEFAULT (0)
-#define LIBXL__DEFBOOL_FALSE (-1)
-#define LIBXL__DEFBOOL_TRUE (1)
+void libxl_key_value_list_copy(libxl_ctx *ctx,
+ libxl_key_value_list *dst,
+ libxl_key_value_list *src)
+{
+ GC_INIT(ctx);
+ int i, len;
+
+ if (*src == NULL) {
+ *dst = NULL;
+ goto out;
+ }
+
+ len = libxl_key_value_list_length(src);
+ /* one extra slot for sentinel */
+ *dst = libxl__calloc(NOGC, len * 2 + 1, sizeof(char *));
+
+ for (i = 0; i < len * 2; i += 2) {
+ (*dst)[i] = libxl__strdup(NOGC, (*src)[i]);
+ if ((*src)[i+1])
+ (*dst)[i+1] = libxl__strdup(NOGC, (*src)[i+1]);
+ else
+ (*dst)[i+1] = NULL;
+ }
+
+out:
+ GC_FREE;
+}
void libxl_defbool_set(libxl_defbool *db, bool b)
{
@@ -254,11 +336,11 @@ bool libxl_defbool_val(libxl_defbool db)
const char *libxl_defbool_to_string(libxl_defbool b)
{
if (b.val < 0)
- return "False";
+ return LIBXL__DEFBOOL_STR_FALSE;
else if (b.val > 0)
- return "True";
+ return LIBXL__DEFBOOL_STR_TRUE;
else
- return "<default>";
+ return LIBXL__DEFBOOL_STR_DEFAULT;
}
/******************************************************************************/
@@ -277,6 +359,9 @@ int libxl__domain_rename(libxl__gc *gc, uint32_t domid,
uint32_t stub_dm_domid;
const char *stub_dm_old_name = NULL, *stub_dm_new_name = NULL;
int rc;
+ libxl_dominfo info;
+ char *uuid;
+ const char *vm_name_path;
dom_path = libxl__xs_get_dompath(gc, domid);
if (!dom_path) goto x_nomem;
@@ -347,6 +432,16 @@ int libxl__domain_rename(libxl__gc *gc, uint32_t domid,
goto x_fail;
}
+ /* update /vm/<uuid>/name */
+ rc = libxl_domain_info(ctx, &info, domid);
+ if (rc)
+ goto x_fail;
+
+ uuid = GCSPRINTF(LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info.uuid));
+ vm_name_path = GCSPRINTF("/vm/%s/name", uuid);
+ if (libxl__xs_write_checked(gc, trans, vm_name_path, new_name))
+ goto x_fail;
+
if (stub_dm_domid) {
rc = libxl__domain_rename(gc, stub_dm_domid,
stub_dm_old_name,
@@ -508,12 +603,18 @@ int libxl_domain_preserve(libxl_ctx *ctx, uint32_t domid,
return 0;
}
-static void xcinfo2xlinfo(const xc_domaininfo_t *xcinfo,
+static void xcinfo2xlinfo(libxl_ctx *ctx,
+ const xc_domaininfo_t *xcinfo,
libxl_dominfo *xlinfo)
{
+ size_t size;
+
memcpy(&(xlinfo->uuid), xcinfo->handle, sizeof(xen_domain_handle_t));
xlinfo->domid = xcinfo->domain;
xlinfo->ssidref = xcinfo->ssidref;
+ if (libxl_flask_sid_to_context(ctx, xlinfo->ssidref,
+ &xlinfo->ssid_label, &size) < 0)
+ xlinfo->ssid_label = NULL;
xlinfo->dying = !!(xcinfo->flags&XEN_DOMINF_dying);
xlinfo->shutdown = !!(xcinfo->flags&XEN_DOMINF_shutdown);
@@ -521,7 +622,7 @@ static void xcinfo2xlinfo(const xc_domaininfo_t *xcinfo,
xlinfo->blocked = !!(xcinfo->flags&XEN_DOMINF_blocked);
xlinfo->running = !!(xcinfo->flags&XEN_DOMINF_running);
- if (xlinfo->shutdown || xlinfo->dying)
+ if (xlinfo->shutdown)
xlinfo->shutdown_reason = (xcinfo->flags>>XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask;
else
xlinfo->shutdown_reason = LIBXL_SHUTDOWN_REASON_UNKNOWN;
@@ -554,13 +655,13 @@ libxl_dominfo * libxl_list_domain(libxl_ctx *ctx, int *nb_domain_out)
ret = xc_domain_getinfolist(ctx->xch, 0, 1024, info);
if (ret<0) {
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "geting domain info list");
+ LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting domain info list");
free(ptr);
return NULL;
}
for (i = 0; i < ret; i++) {
- xcinfo2xlinfo(&info[i], &ptr[i]);
+ xcinfo2xlinfo(ctx, &info[i], &ptr[i]);
}
*nb_domain_out = ret;
return ptr;
@@ -579,7 +680,7 @@ int libxl_domain_info(libxl_ctx *ctx, libxl_dominfo *info_r,
if (ret==0 || xcinfo.domain != domid) return ERROR_INVAL;
if (info_r)
- xcinfo2xlinfo(&xcinfo, info_r);
+ xcinfo2xlinfo(ctx, &xcinfo, info_r);
return 0;
}
@@ -607,6 +708,11 @@ static int cpupool_info(libxl__gc *gc,
}
info->poolid = xcinfo->cpupool_id;
+ info->pool_name = libxl_cpupoolid_to_name(CTX, info->poolid);
+ if (!info->pool_name) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
info->sched = xcinfo->sched_id;
info->n_dom = xcinfo->n_dom;
rc = libxl_cpu_bitmap_alloc(CTX, &info->cpumap, 0);
@@ -698,6 +804,10 @@ out:
return ptr;
}
+static void libxl__remus_setup_done(libxl__egc *egc,
+ libxl__remus_devices_state *rds, int rc);
+static void libxl__remus_setup_failed(libxl__egc *egc,
+ libxl__remus_devices_state *rds, int rc);
static void remus_failover_cb(libxl__egc *egc,
libxl__domain_suspend_state *dss, int rc);
@@ -716,6 +826,23 @@ int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info,
goto out;
}
+ libxl_defbool_setdefault(&info->allow_unsafe, false);
+ libxl_defbool_setdefault(&info->blackhole, false);
+ libxl_defbool_setdefault(&info->compression, true);
+ libxl_defbool_setdefault(&info->netbuf, true);
+ libxl_defbool_setdefault(&info->diskbuf, true);
+
+ if (!libxl_defbool_val(info->allow_unsafe) &&
+ (libxl_defbool_val(info->blackhole) ||
+ !libxl_defbool_val(info->netbuf) ||
+ !libxl_defbool_val(info->diskbuf))) {
+ LOG(ERROR, "Unsafe mode must be enabled to replicate to /dev/null,"
+ "disable network buffering and disk replication");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+
GCNEW(dss);
dss->ao = ao;
dss->callback = remus_failover_cb;
@@ -729,16 +856,63 @@ int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info,
assert(info);
- /* TBD: Remus setup - i.e. attach qdisc, enable disk buffering, etc */
+ /* Convenience aliases */
+ libxl__remus_devices_state *const rds = &dss->rds;
+
+ if (libxl_defbool_val(info->netbuf)) {
+ if (!libxl__netbuffer_enabled(gc)) {
+ LOG(ERROR, "Remus: No support for network buffering");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ rds->device_kind_flags |= (1 << LIBXL__DEVICE_KIND_VIF);
+ }
+
+ if (libxl_defbool_val(info->diskbuf))
+ rds->device_kind_flags |= (1 << LIBXL__DEVICE_KIND_VBD);
+
+ rds->ao = ao;
+ rds->domid = domid;
+ rds->callback = libxl__remus_setup_done;
/* Point of no return */
- libxl__domain_suspend(egc, dss);
+ libxl__remus_devices_setup(egc, rds);
return AO_INPROGRESS;
out:
return AO_ABORT(rc);
}
+static void libxl__remus_setup_done(libxl__egc *egc,
+ libxl__remus_devices_state *rds, int rc)
+{
+ libxl__domain_suspend_state *dss = CONTAINER_OF(rds, *dss, rds);
+ STATE_AO_GC(dss->ao);
+
+ if (!rc) {
+ libxl__domain_suspend(egc, dss);
+ return;
+ }
+
+ LOG(ERROR, "Remus: failed to setup device for guest with domid %u, rc %d",
+ dss->domid, rc);
+ rds->callback = libxl__remus_setup_failed;
+ libxl__remus_devices_teardown(egc, rds);
+}
+
+static void libxl__remus_setup_failed(libxl__egc *egc,
+ libxl__remus_devices_state *rds, int rc)
+{
+ libxl__domain_suspend_state *dss = CONTAINER_OF(rds, *dss, rds);
+ STATE_AO_GC(dss->ao);
+
+ if (rc)
+ LOG(ERROR, "Remus: failed to teardown device after setup failed"
+ " for guest with domid %u, rc %d", dss->domid, rc);
+
+ dss->callback(egc, dss, rc);
+}
+
static void remus_failover_cb(libxl__egc *egc,
libxl__domain_suspend_state *dss, int rc)
{
@@ -748,10 +922,6 @@ static void remus_failover_cb(libxl__egc *egc,
* backup died or some network error occurred preventing us
* from sending checkpoints.
*/
-
- /* TBD: Remus cleanup - i.e. detach qdisc, release other
- * resources.
- */
libxl__ao_complete(egc, ao, rc);
}
@@ -864,7 +1034,7 @@ int libxl__domain_pvcontrol_available(libxl__gc *gc, uint32_t domid)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
- unsigned long pvdriver = 0;
+ uint64_t pvdriver = 0;
int ret;
libxl_domain_type domtype = libxl__domain_type(gc, domid);
@@ -874,7 +1044,7 @@ int libxl__domain_pvcontrol_available(libxl__gc *gc, uint32_t domid)
if (domtype == LIBXL_DOMAIN_TYPE_PV)
return 1;
- ret = xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver);
+ ret = xc_hvm_param_get(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver);
if (ret<0) {
LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting HVM callback IRQ");
return ERROR_FAIL;
@@ -882,17 +1052,23 @@ int libxl__domain_pvcontrol_available(libxl__gc *gc, uint32_t domid)
return !!pvdriver;
}
-char * libxl__domain_pvcontrol_read(libxl__gc *gc, xs_transaction_t t,
- uint32_t domid)
+const char *libxl__domain_pvcontrol_xspath(libxl__gc *gc, uint32_t domid)
{
- const char *shutdown_path;
const char *dom_path;
dom_path = libxl__xs_get_dompath(gc, domid);
if (!dom_path)
return NULL;
- shutdown_path = libxl__sprintf(gc, "%s/control/shutdown", dom_path);
+ return GCSPRINTF("%s/control/shutdown", dom_path);
+}
+
+char * libxl__domain_pvcontrol_read(libxl__gc *gc, xs_transaction_t t,
+ uint32_t domid)
+{
+ const char *shutdown_path;
+
+ shutdown_path = libxl__domain_pvcontrol_xspath(gc, domid);
if (!shutdown_path)
return NULL;
@@ -903,13 +1079,8 @@ int libxl__domain_pvcontrol_write(libxl__gc *gc, xs_transaction_t t,
uint32_t domid, const char *cmd)
{
const char *shutdown_path;
- const char *dom_path;
-
- dom_path = libxl__xs_get_dompath(gc, domid);
- if (!dom_path)
- return ERROR_FAIL;
- shutdown_path = libxl__sprintf(gc, "%s/control/shutdown", dom_path);
+ shutdown_path = libxl__domain_pvcontrol_xspath(gc, domid);
if (!shutdown_path)
return ERROR_FAIL;
@@ -1445,6 +1616,7 @@ static void devices_destroy_cb(libxl__egc *egc,
uint32_t domid = dis->domid;
char *dom_path;
char *vm_path;
+ libxl__domain_userdata_lock *lock = NULL;
dom_path = libxl__xs_get_dompath(gc, domid);
if (!dom_path) {
@@ -1470,6 +1642,12 @@ static void devices_destroy_cb(libxl__egc *egc,
xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(gc,
"/local/domain/%d/hvmloader", domid));
+ /* This is async operation, we already hold CTX lock */
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
libxl__userdata_destroyall(gc, domid);
rc = xc_domain_destroy(ctx->xch, domid);
@@ -1481,6 +1659,7 @@ static void devices_destroy_cb(libxl__egc *egc,
rc = 0;
out:
+ if (lock) libxl__unlock_domain_userdata(lock);
dis->callback(egc, dis, rc);
return;
}
@@ -1635,8 +1814,12 @@ int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass)
vnc_port = libxl__xs_read(gc, XBT_NULL,
libxl__sprintf(gc,
"/local/domain/%d/console/vnc-port", domid));
- if ( vnc_port )
- port = atoi(vnc_port) - 5900;
+ if (!vnc_port) {
+ LOG(ERROR, "Cannot get vnc-port of domain %d", domid);
+ goto x_fail;
+ }
+
+ port = atoi(vnc_port) - 5900;
vnc_listen = libxl__xs_read(gc, XBT_NULL,
libxl__sprintf(gc,
@@ -1795,7 +1978,15 @@ void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
flexarray_t *front;
flexarray_t *back;
libxl__device *device;
- unsigned int rc;
+ int rc;
+ xs_transaction_t t = XBT_NULL;
+ libxl_domain_config d_config;
+ libxl_device_vtpm vtpm_saved;
+ libxl__domain_userdata_lock *lock = NULL;
+
+ libxl_domain_config_init(&d_config);
+ libxl_device_vtpm_init(&vtpm_saved);
+ libxl_device_vtpm_copy(CTX, &vtpm_saved, vtpm);
rc = libxl__device_vtpm_setdefault(gc, vtpm);
if (rc) goto out;
@@ -1810,6 +2001,8 @@ void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
}
}
+ libxl__update_config_vtpm(gc, &vtpm_saved, vtpm);
+
GCNEW(device);
rc = libxl__device_from_vtpm(gc, domid, vtpm, device);
if ( rc != 0 ) goto out;
@@ -1835,10 +2028,48 @@ void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
flexarray_append(front, "handle");
flexarray_append(front, GCSPRINTF("%d", vtpm->devid));
- libxl__device_generic_add(gc, XBT_NULL, device,
- libxl__xs_kvs_of_flexarray(gc, back, back->count),
- libxl__xs_kvs_of_flexarray(gc, front, front->count),
- NULL);
+ if (aodev->update_json) {
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
+
+ rc = libxl__get_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+
+ DEVICE_ADD(vtpm, vtpms, domid, &vtpm_saved, COMPARE_DEVID, &d_config);
+ }
+
+ for (;;) {
+ rc = libxl__xs_transaction_start(gc, &t);
+ if (rc) goto out;
+
+ rc = libxl__device_exists(gc, t, device);
+ if (rc < 0) goto out;
+ if (rc == 1) { /* already exists in xenstore */
+ LOG(ERROR, "device already exists in xenstore");
+ aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */
+ rc = ERROR_DEVICE_EXISTS;
+ goto out;
+ }
+
+ if (aodev->update_json) {
+ rc = libxl__set_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+ }
+
+ libxl__device_generic_add(gc, t, device,
+ libxl__xs_kvs_of_flexarray(gc, back,
+ back->count),
+ libxl__xs_kvs_of_flexarray(gc, front,
+ front->count),
+ NULL);
+
+ rc = libxl__xs_transaction_commit(gc, &t);
+ if (!rc) break;
+ if (rc < 0) goto out;
+ }
aodev->dev = device;
aodev->action = LIBXL__DEVICE_ACTION_ADD;
@@ -1846,6 +2077,10 @@ void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
rc = 0;
out:
+ libxl__xs_transaction_abort(gc, &t);
+ if (lock) libxl__unlock_domain_userdata(lock);
+ libxl_device_vtpm_dispose(&vtpm_saved);
+ libxl_domain_config_dispose(&d_config);
aodev->rc = rc;
if(rc) aodev->callback(egc, aodev);
return;
@@ -1986,7 +2221,7 @@ int libxl_devid_to_device_vtpm(libxl_ctx *ctx,
if(devid == vtpms[i].devid) {
vtpm->backend_domid = vtpms[i].backend_domid;
vtpm->devid = vtpms[i].devid;
- libxl_uuid_copy(&vtpm->uuid, &vtpms[i].uuid);
+ libxl_uuid_copy(ctx, &vtpm->uuid, &vtpms[i].uuid);
rc = 0;
break;
}
@@ -2003,6 +2238,8 @@ int libxl__device_disk_setdefault(libxl__gc *gc, libxl_device_disk *disk)
{
int rc;
+ libxl_defbool_setdefault(&disk->discard_enable, !!disk->readwrite);
+
rc = libxl__resolve_domid(gc, disk->backend_domname, &disk->backend_domid);
if (rc < 0) return rc;
@@ -2076,6 +2313,13 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
int rc;
libxl_ctx *ctx = gc->owner;
xs_transaction_t t = XBT_NULL;
+ libxl_domain_config d_config;
+ libxl_device_disk disk_saved;
+ libxl__domain_userdata_lock *lock = NULL;
+
+ libxl_domain_config_init(&d_config);
+ libxl_device_disk_init(&disk_saved);
+ libxl_device_disk_copy(ctx, &disk_saved, disk);
libxl_domain_type type = libxl__domain_type(gc, domid);
if (type == LIBXL_DOMAIN_TYPE_INVALID) {
@@ -2083,6 +2327,26 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
goto out;
}
+ /*
+ * get_vdev != NULL -> local attach
+ * get_vdev == NULL -> block attach
+ *
+ * We don't care about local attach state because it's only
+ * intermediate state.
+ */
+ if (!get_vdev && aodev->update_json) {
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
+
+ rc = libxl__get_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+
+ DEVICE_ADD(disk, disks, domid, &disk_saved, COMPARE_DISK, &d_config);
+ }
+
for (;;) {
rc = libxl__xs_transaction_start(gc, &t);
if (rc) goto out;
@@ -2110,6 +2374,15 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
goto out;
}
+ rc = libxl__device_exists(gc, t, device);
+ if (rc < 0) goto out;
+ if (rc == 1) { /* already exists in xenstore */
+ LOG(ERROR, "device already exists in xenstore");
+ aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */
+ rc = ERROR_DEVICE_EXISTS;
+ goto out;
+ }
+
switch (disk->backend) {
case LIBXL_DISK_BACKEND_PHY:
dev = disk->pdev_path;
@@ -2192,6 +2465,13 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
flexarray_append(back, disk->readwrite ? "w" : "r");
flexarray_append(back, "device-type");
flexarray_append(back, disk->is_cdrom ? "cdrom" : "disk");
+ if (disk->direct_io_safe) {
+ flexarray_append(back, "direct-io-safe");
+ flexarray_append(back, "1");
+ }
+ flexarray_append_pair(back, "discard-enable",
+ libxl_defbool_val(disk->discard_enable) ?
+ "1" : "0");
flexarray_append(front, "backend-id");
flexarray_append(front, libxl__sprintf(gc, "%d", disk->backend_domid));
@@ -2219,6 +2499,11 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
}
}
+ if (!get_vdev && aodev->update_json) {
+ rc = libxl__set_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+ }
+
libxl__device_generic_add(gc, t, device,
libxl__xs_kvs_of_flexarray(gc, back, back->count),
libxl__xs_kvs_of_flexarray(gc, front, front->count),
@@ -2237,6 +2522,9 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
out:
libxl__xs_transaction_abort(gc, &t);
+ if (lock) libxl__unlock_domain_userdata(lock);
+ libxl_device_disk_dispose(&disk_saved);
+ libxl_domain_config_dispose(&d_config);
aodev->rc = rc;
if (rc) aodev->callback(egc, aodev);
return;
@@ -2462,14 +2750,26 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
{
AO_CREATE(ctx, domid, ao_how);
int num = 0, i;
- libxl_device_disk *disks = NULL;
+ libxl_device_disk *disks = NULL, disk_saved, disk_empty;
+ libxl_domain_config d_config;
int rc, dm_ver;
-
libxl__device device;
const char * path;
char * tmp;
+ libxl__domain_userdata_lock *lock = NULL;
+ xs_transaction_t t = XBT_NULL;
+ flexarray_t *insert = NULL, *empty = NULL;
+
+ libxl_domain_config_init(&d_config);
+ libxl_device_disk_init(&disk_empty);
+ libxl_device_disk_init(&disk_saved);
+ libxl_device_disk_copy(ctx, &disk_saved, disk);
- flexarray_t *insert = NULL;
+ disk_empty.format = LIBXL_DISK_FORMAT_EMPTY;
+ disk_empty.vdev = libxl__strdup(NOGC, disk->vdev);
+ disk_empty.pdev_path = libxl__strdup(NOGC, "");
+ disk_empty.is_cdrom = 1;
+ libxl__device_disk_setdefault(gc, &disk_empty);
libxl_domain_type type = libxl__domain_type(gc, domid);
if (type == LIBXL_DOMAIN_TYPE_INVALID) {
@@ -2521,24 +2821,8 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
rc = libxl__device_from_disk(gc, domid, disk, &device);
if (rc) goto out;
- if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
- rc = libxl__qmp_insert_cdrom(gc, domid, disk);
- if (rc) goto out;
- }
-
path = libxl__device_backend_path(gc, &device);
- /* Sanity check: make sure the backend exists before writing here */
- tmp = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/frontend", path));
- if (!tmp)
- {
- LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Internal error: %s does not exist",
- libxl__sprintf(gc, "%s/frontend", path));
- rc = ERROR_FAIL;
- goto out;
- }
-
-
insert = flexarray_make(gc, 4, 1);
flexarray_append_pair(insert, "type",
@@ -2551,19 +2835,100 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
else
flexarray_append_pair(insert, "params", "");
- rc = libxl__xs_writev_atonce(gc, path,
- libxl__xs_kvs_of_flexarray(gc, insert, insert->count));
+ empty = flexarray_make(gc, 4, 1);
+ flexarray_append_pair(empty, "type",
+ libxl__device_disk_string_of_backend(disk->backend));
+ flexarray_append_pair(empty, "params", "");
+
+ /* Note: CTX lock is already held at this point so lock hierarchy
+ * is maintained.
+ */
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
+
+ /* We need to eject the original image first. This is implemented
+ * by inserting empty media. JSON is not updated.
+ */
+ if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
+ rc = libxl__qmp_insert_cdrom(gc, domid, &disk_empty);
+ if (rc) goto out;
+ }
+
+ for (;;) {
+ rc = libxl__xs_transaction_start(gc, &t);
+ if (rc) goto out;
+ /* Sanity check: make sure the backend exists before writing here */
+ tmp = libxl__xs_read(gc, t, libxl__sprintf(gc, "%s/frontend", path));
+ if (!tmp)
+ {
+ LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Internal error: %s does not exist",
+ libxl__sprintf(gc, "%s/frontend", path));
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = libxl__xs_writev(gc, t, path,
+ libxl__xs_kvs_of_flexarray(gc, empty, empty->count));
+ if (rc) goto out;
+
+ rc = libxl__xs_transaction_commit(gc, &t);
+ if (!rc) break;
+ if (rc < 0) goto out;
+ }
+
+ rc = libxl__get_domain_configuration(gc, domid, &d_config);
if (rc) goto out;
+ DEVICE_ADD(disk, disks, domid, &disk_saved, COMPARE_DISK, &d_config);
+
+ if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
+ rc = libxl__qmp_insert_cdrom(gc, domid, disk);
+ if (rc) goto out;
+ }
+
+ for (;;) {
+ rc = libxl__xs_transaction_start(gc, &t);
+ if (rc) goto out;
+ /* Sanity check: make sure the backend exists before writing here */
+ tmp = libxl__xs_read(gc, t, libxl__sprintf(gc, "%s/frontend", path));
+ if (!tmp)
+ {
+ LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Internal error: %s does not exist",
+ libxl__sprintf(gc, "%s/frontend", path));
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = libxl__set_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+
+ rc = libxl__xs_writev(gc, t, path,
+ libxl__xs_kvs_of_flexarray(gc, insert, insert->count));
+ if (rc) goto out;
+
+ rc = libxl__xs_transaction_commit(gc, &t);
+ if (!rc) break;
+ if (rc < 0) goto out;
+ }
+
/* success, no actual async */
libxl__ao_complete(egc, ao, 0);
rc = 0;
out:
+ libxl__xs_transaction_abort(gc, &t);
for (i = 0; i < num; i++)
libxl_device_disk_dispose(&disks[i]);
free(disks);
+ libxl_device_disk_dispose(&disk_empty);
+ libxl_device_disk_dispose(&disk_saved);
+ libxl_domain_config_dispose(&d_config);
+
+ if (lock) libxl__unlock_domain_userdata(lock);
if (rc) return AO_ABORT(rc);
return AO_INPROGRESS;
@@ -2678,7 +3043,7 @@ void libxl__device_disk_local_initiate_attach(libxl__egc *egc,
}
if (dev != NULL)
- dls->diskpath = strdup(dev);
+ dls->diskpath = libxl__strdup(gc, dev);
dls->callback(egc, dls, 0);
return;
@@ -2818,8 +3183,7 @@ int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic,
nic->model = strdup("rtl8139");
if (!nic->model) return ERROR_NOMEM;
}
- if (!nic->mac[0] && !nic->mac[1] && !nic->mac[2] &&
- !nic->mac[3] && !nic->mac[4] && !nic->mac[5]) {
+ if (libxl__mac_is_default(&nic->mac)) {
const uint8_t *r;
libxl_uuid uuid;
@@ -2892,7 +3256,15 @@ void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
flexarray_t *front;
flexarray_t *back;
libxl__device *device;
- unsigned int rc;
+ int rc;
+ xs_transaction_t t = XBT_NULL;
+ libxl_domain_config d_config;
+ libxl_device_nic nic_saved;
+ libxl__domain_userdata_lock *lock = NULL;
+
+ libxl_domain_config_init(&d_config);
+ libxl_device_nic_init(&nic_saved);
+ libxl_device_nic_copy(CTX, &nic_saved, nic);
rc = libxl__device_nic_setdefault(gc, nic, domid);
if (rc) goto out;
@@ -2907,6 +3279,8 @@ void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
}
}
+ libxl__update_config_nic(gc, &nic_saved, nic);
+
GCNEW(device);
rc = libxl__device_from_nic(gc, domid, nic, device);
if ( rc != 0 ) goto out;
@@ -2963,38 +3337,73 @@ void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
flexarray_append(front, "mac");
flexarray_append(front, libxl__sprintf(gc,
LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac)));
- libxl__device_generic_add(gc, XBT_NULL, device,
- libxl__xs_kvs_of_flexarray(gc, back, back->count),
- libxl__xs_kvs_of_flexarray(gc, front, front->count),
- NULL);
- aodev->dev = device;
- aodev->action = LIBXL__DEVICE_ACTION_ADD;
- libxl__wait_device_connection(egc, aodev);
+ if (aodev->update_json) {
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
- rc = 0;
-out:
- aodev->rc = rc;
- if (rc) aodev->callback(egc, aodev);
- return;
-}
+ rc = libxl__get_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
-static int libxl__device_nic_from_xs_be(libxl__gc *gc,
- const char *be_path,
- libxl_device_nic *nic)
-{
- const char *tmp;
- int rc;
+ DEVICE_ADD(nic, nics, domid, &nic_saved, COMPARE_DEVID, &d_config);
+ }
- libxl_device_nic_init(nic);
+ for (;;) {
+ rc = libxl__xs_transaction_start(gc, &t);
+ if (rc) goto out;
-#define READ_BACKEND(tgc, subpath) ({ \
- rc = libxl__xs_read_checked(tgc, XBT_NULL, \
- GCSPRINTF("%s/" subpath, be_path), \
- &tmp); \
- if (rc) goto out; \
- (char*)tmp; \
- });
+ rc = libxl__device_exists(gc, t, device);
+ if (rc < 0) goto out;
+ if (rc == 1) { /* already exists in xenstore */
+ LOG(ERROR, "device already exists in xenstore");
+ aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */
+ rc = ERROR_DEVICE_EXISTS;
+ goto out;
+ }
+
+ if (aodev->update_json) {
+ rc = libxl__set_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+ }
+
+ libxl__device_generic_add(gc, t, device,
+ libxl__xs_kvs_of_flexarray(gc, back,
+ back->count),
+ libxl__xs_kvs_of_flexarray(gc, front,
+ front->count),
+ NULL);
+
+ rc = libxl__xs_transaction_commit(gc, &t);
+ if (!rc) break;
+ if (rc < 0) goto out;
+ }
+
+ aodev->dev = device;
+ aodev->action = LIBXL__DEVICE_ACTION_ADD;
+ libxl__wait_device_connection(egc, aodev);
+
+ rc = 0;
+out:
+ libxl__xs_transaction_abort(gc, &t);
+ if (lock) libxl__unlock_domain_userdata(lock);
+ libxl_device_nic_dispose(&nic_saved);
+ libxl_domain_config_dispose(&d_config);
+ aodev->rc = rc;
+ if (rc) aodev->callback(egc, aodev);
+ return;
+}
+
+static int libxl__device_nic_from_xs_be(libxl__gc *gc,
+ const char *be_path,
+ libxl_device_nic *nic)
+{
+ const char *tmp;
+ int rc;
+
+ libxl_device_nic_init(nic);
tmp = READ_BACKEND(gc, "handle");
if (tmp)
@@ -3017,7 +3426,13 @@ static int libxl__device_nic_from_xs_be(libxl__gc *gc,
nic->script = READ_BACKEND(NOGC, "script");
/* vif_ioemu nics use the same xenstore entries as vif interfaces */
- nic->nictype = LIBXL_NIC_TYPE_VIF;
+ tmp = READ_BACKEND(gc, "type");
+ if (tmp) {
+ rc = libxl_nic_type_from_string(tmp, &nic->nictype);
+ if (rc) goto out;
+ } else {
+ nic->nictype = LIBXL_NIC_TYPE_VIF;
+ }
nic->model = NULL; /* XXX Only for TYPE_IOEMU */
nic->ifname = NULL; /* XXX Only for TYPE_IOEMU */
@@ -3158,9 +3573,9 @@ const char *libxl__device_nic_devname(libxl__gc *gc,
{
switch (type) {
case LIBXL_NIC_TYPE_VIF:
- return GCSPRINTF("vif%u.%d", domid, devid);
+ return GCSPRINTF(NETBACK_NIC_NAME, domid, devid);
case LIBXL_NIC_TYPE_VIF_IOEMU:
- return GCSPRINTF("vif%u.%d" TAP_DEVICE_SUFFIX, domid, devid);
+ return GCSPRINTF(NETBACK_NIC_NAME TAP_DEVICE_SUFFIX, domid, devid);
default:
abort();
}
@@ -3169,28 +3584,33 @@ const char *libxl__device_nic_devname(libxl__gc *gc,
/******************************************************************************/
int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
libxl__device_console *console,
- libxl__domain_build_state *state)
+ libxl__domain_build_state *state,
+ libxl__device *device)
{
flexarray_t *front, *ro_front;
flexarray_t *back;
- libxl__device device;
int rc;
if (console->devid && state) {
rc = ERROR_INVAL;
goto out;
}
+ if (!console->devid && (console->name || console->path)) {
+ LOG(ERROR, "Primary console has invalid configuration");
+ rc = ERROR_INVAL;
+ goto out;
+ }
front = flexarray_make(gc, 16, 1);
ro_front = flexarray_make(gc, 16, 1);
back = flexarray_make(gc, 16, 1);
- device.backend_devid = console->devid;
- device.backend_domid = console->backend_domid;
- device.backend_kind = LIBXL__DEVICE_KIND_CONSOLE;
- device.devid = console->devid;
- device.domid = domid;
- device.kind = LIBXL__DEVICE_KIND_CONSOLE;
+ device->backend_devid = console->devid;
+ device->backend_domid = console->backend_domid;
+ device->backend_kind = LIBXL__DEVICE_KIND_CONSOLE;
+ device->devid = console->devid;
+ device->domid = domid;
+ device->kind = LIBXL__DEVICE_KIND_CONSOLE;
flexarray_append(back, "frontend-id");
flexarray_append(back, libxl__sprintf(gc, "%d", domid));
@@ -3198,11 +3618,22 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
flexarray_append(back, "1");
flexarray_append(back, "state");
flexarray_append(back, libxl__sprintf(gc, "%d", 1));
- flexarray_append(back, "domain");
- flexarray_append(back, libxl__domid_to_name(gc, domid));
flexarray_append(back, "protocol");
flexarray_append(back, LIBXL_XENCONSOLE_PROTOCOL);
+ if (console->name) {
+ flexarray_append(ro_front, "name");
+ flexarray_append(ro_front, console->name);
+ }
+ if (console->connection) {
+ flexarray_append(back, "connection");
+ flexarray_append(back, console->connection);
+ }
+ if (console->path) {
+ flexarray_append(back, "path");
+ flexarray_append(back, console->path);
+ }
+
flexarray_append(front, "backend-id");
flexarray_append(front, libxl__sprintf(gc, "%d", console->backend_domid));
@@ -3229,8 +3660,7 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
flexarray_append(front, "protocol");
flexarray_append(front, LIBXL_XENCONSOLE_PROTOCOL);
}
-
- libxl__device_generic_add(gc, XBT_NULL, &device,
+ libxl__device_generic_add(gc, XBT_NULL, device,
libxl__xs_kvs_of_flexarray(gc, back, back->count),
libxl__xs_kvs_of_flexarray(gc, front, front->count),
libxl__xs_kvs_of_flexarray(gc, ro_front, ro_front->count));
@@ -3241,6 +3671,221 @@ out:
/******************************************************************************/
+int libxl__init_console_from_channel(libxl__gc *gc,
+ libxl__device_console *console,
+ int dev_num,
+ libxl_device_channel *channel)
+{
+ int rc;
+
+ libxl__device_console_init(console);
+
+ /* Perform validation first, allocate second. */
+
+ if (!channel->name) {
+ LOG(ERROR, "channel %d has no name", channel->devid);
+ return ERROR_INVAL;
+ }
+
+ if (channel->backend_domname) {
+ rc = libxl_domain_qualifier_to_domid(CTX, channel->backend_domname,
+ &channel->backend_domid);
+ if (rc < 0) return rc;
+ }
+
+ /* The xenstore 'output' node tells the backend what to connect the console
+ to. If the channel has "connection = pty" then the "output" node will be
+ set to "pty". If the channel has "connection = socket" then the "output"
+ node will be set to "chardev:libxl-channel%d". This tells the qemu
+ backend to proxy data between the console ring and the character device
+ with id "libxl-channel%d". These character devices are currently defined
+ on the qemu command-line via "-chardev" options in libxl_dm.c */
+
+ switch (channel->connection) {
+ case LIBXL_CHANNEL_CONNECTION_UNKNOWN:
+ LOG(ERROR, "channel %d has no defined connection; "
+ "to where should it be connected?", channel->devid);
+ return ERROR_INVAL;
+ case LIBXL_CHANNEL_CONNECTION_PTY:
+ console->connection = libxl__strdup(NOGC, "pty");
+ console->output = libxl__sprintf(NOGC, "pty");
+ break;
+ case LIBXL_CHANNEL_CONNECTION_SOCKET:
+ if (!channel->u.socket.path) {
+ LOG(ERROR, "channel %d has no path", channel->devid);
+ return ERROR_INVAL;
+ }
+ console->connection = libxl__strdup(NOGC, "socket");
+ console->path = libxl__strdup(NOGC, channel->u.socket.path);
+ console->output = libxl__sprintf(NOGC, "chardev:libxl-channel%d",
+ channel->devid);
+ break;
+ default:
+ /* We've forgotten to add the clause */
+ LOG(ERROR, "%s: missing implementation for channel connection %d",
+ __func__, channel->connection);
+ abort();
+ }
+
+ console->devid = dev_num;
+ console->consback = LIBXL__CONSOLE_BACKEND_IOEMU;
+ console->backend_domid = channel->backend_domid;
+ console->name = libxl__strdup(NOGC, channel->name);
+
+ return 0;
+}
+
+static int libxl__device_channel_from_xs_be(libxl__gc *gc,
+ const char *be_path,
+ libxl_device_channel *channel)
+{
+ const char *tmp;
+ int rc;
+
+ libxl_device_channel_init(channel);
+
+ /* READ_BACKEND is from libxl__device_nic_from_xs_be above */
+ channel->name = READ_BACKEND(NOGC, "name");
+ tmp = READ_BACKEND(gc, "connection");
+ if (!strcmp(tmp, "pty")) {
+ channel->connection = LIBXL_CHANNEL_CONNECTION_PTY;
+ } else if (!strcmp(tmp, "socket")) {
+ channel->connection = LIBXL_CHANNEL_CONNECTION_SOCKET;
+ channel->u.socket.path = READ_BACKEND(NOGC, "path");
+ } else {
+ rc = ERROR_INVAL;
+ goto out;
+ }
+
+ rc = 0;
+ out:
+ return rc;
+}
+
+static int libxl__append_channel_list_of_type(libxl__gc *gc,
+ uint32_t domid,
+ const char *type,
+ libxl_device_channel **channels,
+ int *nchannels)
+{
+ char *fe_path = NULL, *be_path = NULL;
+ char **dir = NULL;
+ unsigned int n = 0, devid = 0;
+ libxl_device_channel *next = NULL;
+ int rc = 0, i;
+
+ fe_path = GCSPRINTF("%s/device/%s",
+ libxl__xs_get_dompath(gc, domid), type);
+ dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &n);
+ if (!dir || !n)
+ goto out;
+
+ for (i = 0; i < n; i++) {
+ const char *p, *name;
+ libxl_device_channel *tmp;
+
+ p = libxl__sprintf(gc, "%s/%s", fe_path, dir[i]);
+ name = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/name", p));
+ /* 'channels' are consoles with names, so ignore all consoles
+ without names */
+ if (!name) continue;
+ be_path = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend", p));
+ tmp = realloc(*channels,
+ sizeof(libxl_device_channel) * (*nchannels + devid + 1));
+ if (!tmp) {
+ rc = ERROR_NOMEM;
+ goto out;
+ }
+ *channels = tmp;
+ next = *channels + *nchannels + devid;
+ rc = libxl__device_channel_from_xs_be(gc, be_path, next);
+ if (rc) goto out;
+ next->devid = devid;
+ devid++;
+ }
+ *nchannels += devid;
+ return 0;
+
+ out:
+ return rc;
+}
+
+libxl_device_channel *libxl_device_channel_list(libxl_ctx *ctx,
+ uint32_t domid,
+ int *num)
+{
+ GC_INIT(ctx);
+ libxl_device_channel *channels = NULL;
+ int rc;
+
+ *num = 0;
+
+ rc = libxl__append_channel_list_of_type(gc, domid, "console", &channels, num);
+ if (rc) goto out_err;
+
+ GC_FREE;
+ return channels;
+
+out_err:
+ LOG(ERROR, "Unable to list channels");
+ while (*num) {
+ (*num)--;
+ libxl_device_channel_dispose(&channels[*num]);
+ }
+ free(channels);
+ return NULL;
+}
+
+int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
+ libxl_device_channel *channel,
+ libxl_channelinfo *channelinfo)
+{
+ GC_INIT(ctx);
+ char *dompath, *fe_path;
+ char *val;
+
+ dompath = libxl__xs_get_dompath(gc, domid);
+ channelinfo->devid = channel->devid;
+
+ fe_path = libxl__sprintf(gc, "%s/device/console/%d", dompath,
+ channelinfo->devid + 1);
+ channelinfo->backend = xs_read(ctx->xsh, XBT_NULL,
+ libxl__sprintf(gc, "%s/backend",
+ fe_path), NULL);
+ if (!channelinfo->backend) {
+ GC_FREE;
+ return ERROR_FAIL;
+ }
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend-id", fe_path));
+ channelinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
+ channelinfo->state = val ? strtoul(val, NULL, 10) : -1;
+ channelinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
+ GCSPRINTF("%s/frontend",
+ channelinfo->backend), NULL);
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/frontend-id",
+ channelinfo->backend));
+ channelinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path));
+ channelinfo->rref = val ? strtoul(val, NULL, 10) : -1;
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/port", fe_path));
+ channelinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
+
+ channelinfo->connection = channel->connection;
+ switch (channel->connection) {
+ case LIBXL_CHANNEL_CONNECTION_PTY:
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/tty", fe_path));
+ channelinfo->u.pty.path = strdup(val);
+ break;
+ default:
+ break;
+ }
+ GC_FREE;
+ return 0;
+}
+
+/******************************************************************************/
+
int libxl__device_vkb_setdefault(libxl__gc *gc, libxl_device_vkb *vkb)
{
int rc;
@@ -3309,8 +3954,6 @@ int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid,
flexarray_append(back, "1");
flexarray_append(back, "state");
flexarray_append(back, libxl__sprintf(gc, "%d", 1));
- flexarray_append(back, "domain");
- flexarray_append(back, libxl__domid_to_name(gc, domid));
flexarray_append(front, "backend-id");
flexarray_append(front, libxl__sprintf(gc, "%d", vkb->backend_domid));
@@ -3407,7 +4050,6 @@ int libxl__device_vfb_add(libxl__gc *gc, uint32_t domid, libxl_device_vfb *vfb)
flexarray_append_pair(back, "frontend-id", libxl__sprintf(gc, "%d", domid));
flexarray_append_pair(back, "online", "1");
flexarray_append_pair(back, "state", libxl__sprintf(gc, "%d", 1));
- flexarray_append_pair(back, "domain", libxl__domid_to_name(gc, domid));
flexarray_append_pair(back, "vnc",
libxl_defbool_val(vfb->vnc.enable) ? "1" : "0");
flexarray_append_pair(back, "vnclisten", vfb->vnc.listen);
@@ -3505,6 +4147,10 @@ DEFINE_DEVICE_REMOVE(vfb, destroy, 1)
DEFINE_DEVICE_REMOVE(vtpm, remove, 0)
DEFINE_DEVICE_REMOVE(vtpm, destroy, 1)
+/* channel/console hotunplug is not implemented. There are 2 possibilities:
+ * 1. add support for secondary consoles to xenconsoled
+ * 2. dynamically add/remove qemu chardevs via qmp messages. */
+
#undef DEFINE_DEVICE_REMOVE
/******************************************************************************/
@@ -3526,7 +4172,9 @@ DEFINE_DEVICE_REMOVE(vtpm, destroy, 1)
\
GCNEW(aodev); \
libxl__prepare_ao_device(ao, aodev); \
+ aodev->action = LIBXL__DEVICE_ACTION_ADD; \
aodev->callback = device_addrm_aocomplete; \
+ aodev->update_json = true; \
libxl__device_##type##_add(egc, domid, type, aodev); \
\
return AO_INPROGRESS; \
@@ -3924,7 +4572,8 @@ out:
return rc;
}
-static int libxl__fill_dom0_memory_info(libxl__gc *gc, uint32_t *target_memkb)
+static int libxl__fill_dom0_memory_info(libxl__gc *gc, uint32_t *target_memkb,
+ uint32_t *max_memkb)
{
int rc;
libxl_dominfo info;
@@ -3958,6 +4607,17 @@ retry_transaction:
}
}
+ if (staticmax) {
+ *max_memkb = strtoul(staticmax, &endptr, 10);
+ if (*endptr != '\0') {
+ LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
+ "invalid memory static-max %s from %s\n",
+ staticmax, max_path);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ }
+
rc = libxl_domain_info(ctx, &info, 0);
if (rc < 0)
goto out;
@@ -3971,9 +4631,11 @@ retry_transaction:
(uint32_t) info.current_memkb);
*target_memkb = (uint32_t) info.current_memkb;
}
- if (staticmax == NULL)
+ if (staticmax == NULL) {
libxl__xs_write(gc, t, max_path, "%"PRIu32,
- (uint32_t) info.max_memkb);
+ (uint32_t) info.max_memkb);
+ *max_memkb = (uint32_t) info.max_memkb;
+ }
if (freememslack == NULL) {
free_mem_slack_kb = (uint32_t) (PAGE_TO_MEMKB(physinfo.total_pages) -
@@ -4004,12 +4666,12 @@ static int libxl__get_free_memory_slack(libxl__gc *gc, uint32_t *free_mem_slack)
int rc;
char *free_mem_slack_path = "/local/domain/0/memory/freemem-slack";
char *free_mem_slack_s, *endptr;
- uint32_t target_memkb;
+ uint32_t target_memkb, max_memkb;
retry:
free_mem_slack_s = libxl__xs_read(gc, XBT_NULL, free_mem_slack_path);
if (!free_mem_slack_s) {
- rc = libxl__fill_dom0_memory_info(gc, &target_memkb);
+ rc = libxl__fill_dom0_memory_info(gc, &target_memkb, &max_memkb);
if (rc < 0)
return rc;
goto retry;
@@ -4032,6 +4694,7 @@ int libxl_set_memory_target(libxl_ctx *ctx, uint32_t domid,
int rc = 1, abort_transaction = 0;
uint32_t memorykb = 0, videoram = 0;
uint32_t current_target_memkb = 0, new_target_memkb = 0;
+ uint32_t current_max_memkb = 0;
char *memmax, *endptr, *videoram_s = NULL, *target = NULL;
char *dompath = libxl__xs_get_dompath(gc, domid);
xc_domaininfo_t info;
@@ -4047,7 +4710,8 @@ retry_transaction:
if (!target && !domid) {
if (!xs_transaction_end(ctx->xsh, t, 1))
goto out_no_transaction;
- rc = libxl__fill_dom0_memory_info(gc, ¤t_target_memkb);
+ rc = libxl__fill_dom0_memory_info(gc, ¤t_target_memkb,
+ ¤t_max_memkb);
if (rc < 0)
goto out_no_transaction;
goto retry_transaction;
@@ -4143,10 +4807,13 @@ retry_transaction:
abort_transaction = 1;
goto out;
}
- xcinfo2xlinfo(&info, &ptr);
+
+ libxl_dominfo_init(&ptr);
+ xcinfo2xlinfo(ctx, &info, &ptr);
uuid = libxl__uuid2string(gc, ptr.uuid);
libxl__xs_write(gc, t, libxl__sprintf(gc, "/vm/%s/memory", uuid),
"%"PRIu32, new_target_memkb / 1024);
+ libxl_dominfo_dispose(&ptr);
out:
if (!xs_transaction_end(ctx->xsh, t, abort_transaction)
@@ -4159,38 +4826,75 @@ out_no_transaction:
return rc;
}
-int libxl_get_memory_target(libxl_ctx *ctx, uint32_t domid, uint32_t *out_target)
+/* out_target_memkb and out_max_memkb can be NULL */
+static int libxl__get_memory_target(libxl__gc *gc, uint32_t domid,
+ uint32_t *out_target_memkb,
+ uint32_t *out_max_memkb)
{
- GC_INIT(ctx);
- int rc = 1;
- char *target = NULL, *endptr = NULL;
+ int rc;
+ char *target = NULL, *static_max = NULL, *endptr = NULL;
char *dompath = libxl__xs_get_dompath(gc, domid);
- uint32_t target_memkb;
+ uint32_t target_memkb, max_memkb;
target = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc,
- "%s/memory/target", dompath));
- if (!target && !domid) {
- rc = libxl__fill_dom0_memory_info(gc, &target_memkb);
+ "%s/memory/target", dompath));
+ static_max = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc,
+ "%s/memory/static-max", dompath));
+
+ rc = ERROR_FAIL;
+ if ((!target || !static_max) && !domid) {
+ rc = libxl__fill_dom0_memory_info(gc, &target_memkb,
+ &max_memkb);
if (rc < 0)
goto out;
} else if (!target) {
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
+ LIBXL__LOG_ERRNO(CTX, LIBXL__LOG_ERROR,
"cannot get target memory info from %s/memory/target\n",
dompath);
goto out;
+ } else if (!static_max) {
+ LIBXL__LOG_ERRNO(CTX, LIBXL__LOG_ERROR,
+ "cannot get target memory info from %s/memory/static-max\n",
+ dompath);
+ goto out;
} else {
target_memkb = strtoul(target, &endptr, 10);
if (*endptr != '\0') {
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
+ LIBXL__LOG_ERRNO(CTX, LIBXL__LOG_ERROR,
"invalid memory target %s from %s/memory/target\n",
target, dompath);
goto out;
}
+ max_memkb = strtoul(static_max, &endptr, 10);
+ if (*endptr != '\0') {
+ LIBXL__LOG_ERRNO(CTX, LIBXL__LOG_ERROR,
+ "invalid memory target %s from %s/memory/static-max\n",
+ static_max, dompath);
+ goto out;
+ }
+
}
- *out_target = target_memkb;
+
+ if (out_target_memkb)
+ *out_target_memkb = target_memkb;
+
+ if (out_max_memkb)
+ *out_max_memkb = max_memkb;
+
rc = 0;
out:
+ return rc;
+}
+
+int libxl_get_memory_target(libxl_ctx *ctx, uint32_t domid,
+ uint32_t *out_target)
+{
+ GC_INIT(ctx);
+ int rc;
+
+ rc = libxl__get_memory_target(gc, domid, out_target, NULL);
+
GC_FREE;
return rc;
}
@@ -4306,7 +5010,7 @@ int libxl_wait_for_memory_target(libxl_ctx *ctx, uint32_t domid, int wait_secs)
rc = ERROR_FAIL;
out:
- return 0;
+ return rc;
}
int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
@@ -4551,6 +5255,12 @@ libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid,
GC_FREE;
return NULL;
}
+
+ if (domaininfo.max_vcpu_id == XEN_INVALID_MAX_VCPU_ID) {
+ GC_FREE;
+ return NULL;
+ }
+
*nr_cpus_out = libxl_get_max_cpus(ctx);
ret = ptr = libxl__calloc(NOGC, domaininfo.max_vcpu_id + 1,
sizeof(libxl_vcpuinfo));
@@ -4561,12 +5271,17 @@ libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid,
libxl_bitmap_init(&ptr->cpumap);
if (libxl_cpu_bitmap_alloc(ctx, &ptr->cpumap, 0))
goto err;
+ libxl_bitmap_init(&ptr->cpumap_soft);
+ if (libxl_cpu_bitmap_alloc(ctx, &ptr->cpumap_soft, 0))
+ goto err;
if (xc_vcpu_getinfo(ctx->xch, domid, *nr_vcpus_out, &vcpuinfo) == -1) {
LOGE(ERROR, "getting vcpu info");
goto err;
}
+
if (xc_vcpu_getaffinity(ctx->xch, domid, *nr_vcpus_out,
- ptr->cpumap.map) == -1) {
+ ptr->cpumap.map, ptr->cpumap_soft.map,
+ XEN_VCPUAFFINITY_SOFT|XEN_VCPUAFFINITY_HARD) == -1) {
LOGE(ERROR, "getting vcpu affinity");
goto err;
}
@@ -4582,33 +5297,105 @@ libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid,
err:
libxl_bitmap_dispose(&ptr->cpumap);
+ libxl_bitmap_dispose(&ptr->cpumap_soft);
free(ret);
GC_FREE;
return NULL;
}
int libxl_set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid,
- libxl_bitmap *cpumap)
+ const libxl_bitmap *cpumap_hard,
+ const libxl_bitmap *cpumap_soft)
{
- if (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid, cpumap->map)) {
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting vcpu affinity");
- return ERROR_FAIL;
+ GC_INIT(ctx);
+ libxl_bitmap hard, soft;
+ int rc, flags = 0;
+
+ libxl_bitmap_init(&hard);
+ libxl_bitmap_init(&soft);
+
+ if (!cpumap_hard && !cpumap_soft) {
+ rc = ERROR_INVAL;
+ goto out;
}
- return 0;
+
+ /*
+ * Xen wants writable hard and/or soft cpumaps, to put back in them
+ * the effective hard and/or soft affinity that will be used.
+ */
+ if (cpumap_hard) {
+ rc = libxl_cpu_bitmap_alloc(ctx, &hard, 0);
+ if (rc)
+ goto out;
+
+ libxl__bitmap_copy_best_effort(gc, &hard, cpumap_hard);
+ flags = XEN_VCPUAFFINITY_HARD;
+ }
+ if (cpumap_soft) {
+ rc = libxl_cpu_bitmap_alloc(ctx, &soft, 0);
+ if (rc)
+ goto out;
+
+ libxl__bitmap_copy_best_effort(gc, &soft, cpumap_soft);
+ flags |= XEN_VCPUAFFINITY_SOFT;
+ }
+
+ if (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid,
+ cpumap_hard ? hard.map : NULL,
+ cpumap_soft ? soft.map : NULL,
+ flags)) {
+ LOGE(ERROR, "setting vcpu affinity");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ /*
+ * Let's check the results. Hard affinity will never be empty, but it
+ * is possible that Xen will use something different from what we asked
+ * for various reasons. If that's the case, report it.
+ */
+ if (cpumap_hard &&
+ !libxl_bitmap_equal(cpumap_hard, &hard, 0))
+ LOG(DEBUG, "New hard affinity for vcpu %d has unreachable cpus",
+ vcpuid);
+ /*
+ * Soft affinity can both be different from what asked and empty. Check
+ * for (and report) both.
+ */
+ if (cpumap_soft) {
+ if (!libxl_bitmap_equal(cpumap_soft, &soft, 0))
+ LOG(DEBUG, "New soft affinity for vcpu %d has unreachable cpus",
+ vcpuid);
+ if (libxl_bitmap_is_empty(&soft))
+ LOG(WARN, "all cpus in soft affinity of vcpu %d are unreachable."
+ " Only hard affinity will be considered for scheduling",
+ vcpuid);
+ }
+
+ rc = 0;
+ out:
+ libxl_bitmap_dispose(&hard);
+ libxl_bitmap_dispose(&soft);
+ GC_FREE;
+ return rc;
}
int libxl_set_vcpuaffinity_all(libxl_ctx *ctx, uint32_t domid,
- unsigned int max_vcpus, libxl_bitmap *cpumap)
+ unsigned int max_vcpus,
+ const libxl_bitmap *cpumap_hard,
+ const libxl_bitmap *cpumap_soft)
{
+ GC_INIT(ctx);
int i, rc = 0;
for (i = 0; i < max_vcpus; i++) {
- if (libxl_set_vcpuaffinity(ctx, domid, i, cpumap)) {
- LIBXL__LOG(ctx, LIBXL__LOG_WARNING,
- "failed to set affinity for %d", i);
+ if (libxl_set_vcpuaffinity(ctx, domid, i, cpumap_hard, cpumap_soft)) {
+ LOG(WARN, "failed to set affinity for %d", i);
rc = ERROR_FAIL;
}
}
+
+ GC_FREE;
return rc;
}
@@ -4978,6 +5765,72 @@ static int sched_sedf_domain_set(libxl__gc *gc, uint32_t domid,
return 0;
}
+static int sched_rtds_domain_get(libxl__gc *gc, uint32_t domid,
+ libxl_domain_sched_params *scinfo)
+{
+ struct xen_domctl_sched_rtds sdom;
+ int rc;
+
+ rc = xc_sched_rtds_domain_get(CTX->xch, domid, &sdom);
+ if (rc != 0) {
+ LOGE(ERROR, "getting domain sched rtds");
+ return ERROR_FAIL;
+ }
+
+ libxl_domain_sched_params_init(scinfo);
+
+ scinfo->sched = LIBXL_SCHEDULER_RTDS;
+ scinfo->period = sdom.period;
+ scinfo->budget = sdom.budget;
+
+ return 0;
+}
+
+static int sched_rtds_domain_set(libxl__gc *gc, uint32_t domid,
+ const libxl_domain_sched_params *scinfo)
+{
+ struct xen_domctl_sched_rtds sdom;
+ int rc;
+
+ rc = xc_sched_rtds_domain_get(CTX->xch, domid, &sdom);
+ if (rc != 0) {
+ LOGE(ERROR, "getting domain sched rtds");
+ return ERROR_FAIL;
+ }
+
+ if (scinfo->period != LIBXL_DOMAIN_SCHED_PARAM_PERIOD_DEFAULT) {
+ if (scinfo->period < 1) {
+ LOG(ERROR, "VCPU period is not set or out of range, "
+ "valid values are larger than 1");
+ return ERROR_INVAL;
+ }
+ sdom.period = scinfo->period;
+ }
+
+ if (scinfo->budget != LIBXL_DOMAIN_SCHED_PARAM_BUDGET_DEFAULT) {
+ if (scinfo->budget < 1) {
+ LOG(ERROR, "VCPU budget is not set or out of range, "
+ "valid values are larger than 1");
+ return ERROR_INVAL;
+ }
+ sdom.budget = scinfo->budget;
+ }
+
+ if (sdom.budget > sdom.period) {
+ LOG(ERROR, "VCPU budget is larger than VCPU period, "
+ "VCPU budget should be no larger than VCPU period");
+ return ERROR_INVAL;
+ }
+
+ rc = xc_sched_rtds_domain_set(CTX->xch, domid, &sdom);
+ if (rc < 0) {
+ LOGE(ERROR, "setting domain sched rtds");
+ return ERROR_FAIL;
+ }
+
+ return 0;
+}
+
int libxl_domain_sched_params_set(libxl_ctx *ctx, uint32_t domid,
const libxl_domain_sched_params *scinfo)
{
@@ -5001,6 +5854,9 @@ int libxl_domain_sched_params_set(libxl_ctx *ctx, uint32_t domid,
case LIBXL_SCHEDULER_ARINC653:
ret=sched_arinc653_domain_set(gc, domid, scinfo);
break;
+ case LIBXL_SCHEDULER_RTDS:
+ ret=sched_rtds_domain_set(gc, domid, scinfo);
+ break;
default:
LOG(ERROR, "Unknown scheduler");
ret=ERROR_INVAL;
@@ -5031,6 +5887,9 @@ int libxl_domain_sched_params_get(libxl_ctx *ctx, uint32_t domid,
case LIBXL_SCHEDULER_CREDIT2:
ret=sched_credit2_domain_get(gc, domid, scinfo);
break;
+ case LIBXL_SCHEDULER_RTDS:
+ ret=sched_rtds_domain_get(gc, domid, scinfo);
+ break;
default:
LOG(ERROR, "Unknown scheduler");
ret=ERROR_INVAL;
@@ -5049,7 +5908,7 @@ static int libxl__domain_s3_resume(libxl__gc *gc, int domid)
case LIBXL_DOMAIN_TYPE_HVM:
switch (libxl__device_model_version_running(gc, domid)) {
case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
- rc = xc_set_hvm_param(CTX->xch, domid, HVM_PARAM_ACPI_S_STATE, 0);
+ rc = xc_hvm_param_set(CTX->xch, domid, HVM_PARAM_ACPI_S_STATE, 0);
break;
case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
rc = libxl__qmp_system_wakeup(gc, domid);
@@ -5648,6 +6507,207 @@ int libxl_fd_set_cloexec(libxl_ctx *ctx, int fd, int cloexec)
int libxl_fd_set_nonblock(libxl_ctx *ctx, int fd, int nonblock)
{ return fd_set_flags(ctx,fd, F_GETFL,F_SETFL,"FL", O_NONBLOCK, nonblock); }
+
+void libxl_hwcap_copy(libxl_ctx *ctx,libxl_hwcap *dst, libxl_hwcap *src)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ (*dst)[i] = (*src)[i];
+}
+
+void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, libxl_mac *src)
+{
+ int i;
+
+ for (i = 0; i < 6; i++)
+ (*dst)[i] = (*src)[i];
+}
+
+int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid,
+ libxl_domain_config *d_config)
+{
+ GC_INIT(ctx);
+ int rc;
+ libxl__domain_userdata_lock *lock = NULL;
+
+ CTX_LOCK;
+
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
+
+ rc = libxl__get_domain_configuration(gc, domid, d_config);
+ if (rc) {
+ LOG(ERROR, "fail to get domain configuration for domain %d", domid);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ /* Domain name */
+ {
+ char *domname;
+ domname = libxl_domid_to_name(ctx, domid);
+ if (!domname) {
+ LOG(ERROR, "fail to get domain name for domain %d", domid);
+ goto out;
+ }
+ free(d_config->c_info.name);
+ d_config->c_info.name = domname; /* steals allocation */
+ }
+
+ /* Domain UUID */
+ {
+ libxl_dominfo info;
+ rc = libxl_domain_info(ctx, &info, domid);
+ if (rc) {
+ LOG(ERROR, "fail to get domain info for domain %d", domid);
+ goto out;
+ }
+ libxl_uuid_copy(ctx, &d_config->c_info.uuid, &info.uuid);
+ }
+
+ /* Memory limits:
+ *
+ * Currently there are three memory limits:
+ * 1. "target" in xenstore (originally memory= in config file)
+ * 2. "static-max" in xenstore (originally maxmem= in config file)
+ * 3. "max_memkb" in hypervisor
+ *
+ * The third one is not visible and currently managed by
+ * toolstack. In order to rebuild a domain we only need to have
+ * "target" and "static-max".
+ */
+ {
+ uint32_t target_memkb = 0, max_memkb = 0;
+
+ /* "target" */
+ rc = libxl__get_memory_target(gc, domid, &target_memkb, &max_memkb);
+ if (rc) {
+ LOG(ERROR, "fail to get memory target for domain %d", domid);
+ goto out;
+ }
+ /* Target memory in xenstore is different from what user has
+ * asked for. The difference is video_memkb. See
+ * libxl_set_memory_target.
+ */
+ d_config->b_info.target_memkb = target_memkb +
+ d_config->b_info.video_memkb;
+
+ d_config->b_info.max_memkb = max_memkb;
+ }
+
+ /* Devices: disk, nic, vtpm, pcidev etc. */
+
+ /* The MERGE macro implements following logic:
+ * 0. retrieve JSON (done by now)
+ * 1. retrieve list of device from xenstore
+ * 2. use xenstore entries as primary reference and compare JSON
+ * entries with them.
+ * a. if a device is present in xenstore and in JSON, merge the
+ * two views.
+ * b. if a device is not present in xenstore but in JSON, delete
+ * it from the result.
+ * c. it's impossible to have an entry present in xenstore but
+ * not in JSON, because we maintain an invariant that every
+ * entry in xenstore must have a corresponding entry in JSON.
+ * 3. "merge" operates on "src" and "dst". "src" points to the
+ * entry retrieved from xenstore while "dst" points to the entry
+ * retrieve from JSON.
+ */
+#define MERGE(type, ptr, compare, merge) \
+ do { \
+ libxl_device_##type *p = NULL; \
+ int i, j, num; \
+ \
+ p = libxl_device_##type##_list(CTX, domid, &num); \
+ if (p == NULL) { \
+ LOG(DEBUG, \
+ "no %s from xenstore for domain %d", \
+ #type, domid); \
+ } \
+ \
+ for (i = 0; i < d_config->num_##ptr; i++) { \
+ libxl_device_##type *q = &d_config->ptr[i]; \
+ for (j = 0; j < num; j++) { \
+ if (compare(&p[j], q)) \
+ break; \
+ } \
+ \
+ if (j < num) { /* found in xenstore */ \
+ libxl_device_##type *dst, *src; \
+ dst = q; \
+ src = &p[j]; \
+ merge; \
+ } else { /* not found in xenstore */ \
+ LOG(WARN, \
+ "Device present in JSON but not in xenstore, ignored"); \
+ \
+ libxl_device_##type##_dispose(q); \
+ \
+ for (j = i; j < d_config->num_##ptr - 1; j++) \
+ memcpy(&d_config->ptr[j], &d_config->ptr[j+1], \
+ sizeof(libxl_device_##type)); \
+ \
+ d_config->ptr = \
+ libxl__realloc(NOGC, d_config->ptr, \
+ sizeof(libxl_device_##type) * \
+ (d_config->num_##ptr - 1)); \
+ \
+ /* rewind counters */ \
+ d_config->num_##ptr--; \
+ i--; \
+ } \
+ } \
+ \
+ for (i = 0; i < num; i++) \
+ libxl_device_##type##_dispose(&p[i]); \
+ free(p); \
+ } while (0);
+
+ MERGE(nic, nics, COMPARE_DEVID, {});
+
+ MERGE(vtpm, vtpms, COMPARE_DEVID, {});
+
+ MERGE(pci, pcidevs, COMPARE_PCI, {});
+
+ /* Take care of removable device. We maintain invariant in the
+ * insert / remove operation so that:
+ * 1. if xenstore is "empty" while JSON is not, the result
+ * is "empty"
+ * 2. if xenstore has a different media than JSON, use the
+ * one in JSON
+ * 3. if xenstore and JSON have the same media, well, you
+ * know the answer :-)
+ *
+ * Currently there is only one removable device -- CDROM.
+ * Look for libxl_cdrom_insert for reference.
+ */
+ MERGE(disk, disks, COMPARE_DISK, {
+ if (src->removable) {
+ if (!src->pdev_path || *src->pdev_path == '\0') {
+ /* 1, no media in drive */
+ free(dst->pdev_path);
+ dst->pdev_path = libxl__strdup(NOGC, "");
+ dst->format = LIBXL_DISK_FORMAT_EMPTY;
+ } else {
+ /* 2 and 3, use JSON, no need to touch anything */
+ ;
+ }
+ }
+ });
+
+#undef MERGE
+
+out:
+ if (lock) libxl__unlock_domain_userdata(lock);
+ CTX_UNLOCK;
+ GC_FREE;
+ return rc;
+}
+
/*
* Local variables:
* mode: C
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 06bbca6..41d6e8d 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -51,7 +51,7 @@
* In the event that a change is required which cannot be made
* backwards compatible in this manner a #define of the form
* LIBXL_HAVE_<interface> will always be added in order to make it
- * possible to write applciations which build against any version of
+ * possible to write applications which build against any version of
* libxl. Such changes are expected to be exceptional and used as a
* last resort. The barrier for backporting such a change to a stable
* branch will be very high.
@@ -67,6 +67,22 @@
* the same $(XEN_VERSION) (e.g. throughout a major release).
*/
+/* LIBXL_HAVE_USERDATA_UNLINK
+ *
+ * If it is defined, libxl has a library function called
+ * libxl_userdata_unlink.
+ */
+#define LIBXL_HAVE_USERDATA_UNLINK 1
+
+/* LIBXL_HAVE_CPUPOOL_QUALIFIER_TO_CPUPOOLID
+ *
+ * If this is defined, libxl has a library function called
+ * libxl_cpupool_qualifier_to_cpupoolid, which takes in a CPU pool
+ * qualifier in the form of number or string, then returns the ID of
+ * that CPU pool.
+ */
+#define LIBXL_HAVE_CPUPOOL_QUALIFIER_TO_CPUPOOLID 1
+
/*
* LIBXL_HAVE_FIRMWARE_PASSTHROUGH indicates the feature for
* passing in SMBIOS and ACPI firmware to HVM guests is present
@@ -95,6 +111,58 @@
#define LIBXL_HAVE_BUILDINFO_EVENT_CHANNELS 1
/*
+ * libxl_domain_build_info has the u.hvm.ms_vm_genid field.
+ */
+#define LIBXL_HAVE_BUILDINFO_HVM_MS_VM_GENID 1
+
+/*
+ * LIBXL_HAVE_VCPUINFO_SOFT_AFFINITY indicates that a 'cpumap_soft'
+ * field (of libxl_bitmap type) is present in libxl_vcpuinfo,
+ * containing the soft affinity of a vcpu.
+ */
+#define LIBXL_HAVE_VCPUINFO_SOFT_AFFINITY 1
+
+/*
+ * LIBXL_HAVE_DEVICE_DISK_DIRECT_IO_SAFE indicates that a
+ * 'direct_io_safe' field (of boolean type) is present in
+ * libxl_device_disk.
+ */
+#define LIBXL_HAVE_DEVICE_DISK_DIRECT_IO_SAFE 1
+
+/*
+ * The libxl_device_disk has the discard_enable field.
+ */
+#define LIBXL_HAVE_LIBXL_DEVICE_DISK_DISCARD_ENABLE 1
+
+/*
+ * LIBXL_HAVE_BUILDINFO_IOMEM_START_GFN indicates that it is possible
+ * to specify the start guest frame number used to map a range of I/O
+ * memory machine frame numbers via the 'gfn' field (of type uint64)
+ * of the 'iomem' structure. An array of iomem structures is embedded
+ * in libxl_domain_build_info and used to map the indicated memory
+ * ranges during domain build.
+ */
+#define LIBXL_HAVE_BUILDINFO_IOMEM_START_GFN 1
+
+/*
+ * LIBXL_HAVE_SCHED_RTDS indicates that the RTDS real time scheduler
+ * is available. A 'budget' field added in libxl_domain_sched_params.
+ */
+#define LIBXL_HAVE_SCHED_RTDS 1
+
+/*
+ * libxl_domain_build_info has u.hvm.viridian_enable and _disable bitmaps
+ * of the specified width.
+ */
+#define LIBXL_HAVE_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE 1
+#define LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH 64
+
+/*
+ * libxl_domain_build_info has the u.hvm.mmio_hole_memkb field.
+ */
+#define LIBXL_HAVE_BUILDINFO_HVM_MMIO_HOLE_MEMKB 1
+
+/*
* libxl ABI compatibility
*
* The only guarantee which libxl makes regarding ABI compatibility
@@ -233,6 +301,16 @@
* libxl_types.idl). The library provides a common set of methods for
* initialising and freeing these types.
*
+ * IDL-generated libxl types should be used as follows: the user must
+ * always call the "init" function before using a type, even if the
+ * variable is simply being passed by reference as an out parameter
+ * to a libxl function. The user must always calls "dispose" exactly
+ * once afterwards, to clean up, regardless of whether operations on
+ * this object succeeded or failed. See the xl code for examples.
+ *
+ * "init" is idempotent. We intend that "dispose" will become
+ * idempotent, but this is not currently the case.
+ *
* void libxl_<type>_init(<type> *p):
*
* Initialises the members of "p" to all defaults. These may either
@@ -269,6 +347,25 @@
* Frees any dynamically allocated memory used by the members of
* "p" but not the storage used by "p" itself (this allows for the
* allocation of arrays of types and for the composition of types).
+ *
+ * char *libxl_<type>_to_json(instance *p)
+ *
+ * Generates a JSON object from "p" in the form of a NULL terminated
+ * string.
+ *
+ * <type *> libxl_<type>_from_json(const char *json)
+ * int libxl_<type>_from_json(const char *json)
+ *
+ * Parses "json" and returns:
+ *
+ * an int value, if <type> is enumeration type. The value is the enum value
+ * representing the respective string in "json".
+ *
+ * an instance of <type>, if <type> is aggregate type. The returned
+ * instance has its fields filled in by the parser according to "json".
+ *
+ * If the parsing fails, caller cannot rely on the value / instance
+ * returned.
*/
#ifndef LIBXL_H
#define LIBXL_H
@@ -283,17 +380,51 @@
#include <xentoollog.h>
+typedef struct libxl__ctx libxl_ctx;
+
#include <libxl_uuid.h>
#include <_libxl_list.h>
/* API compatibility. */
#ifdef LIBXL_API_VERSION
#if LIBXL_API_VERSION != 0x040200 && LIBXL_API_VERSION != 0x040300 && \
- LIBXL_API_VERSION != 0x040400
+ LIBXL_API_VERSION != 0x040400 && LIBXL_API_VERSION != 0x040500
#error Unknown LIBXL_API_VERSION
#endif
#endif
+/* LIBXL_HAVE_RETRIEVE_DOMAIN_CONFIGURATION
+ *
+ * If this is defined we have libxl_retrieve_domain_configuration which
+ * returns the current configuration of a domain, which can be used to
+ * rebuild a domain.
+ */
+#define LIBXL_HAVE_RETRIEVE_DOMAIN_CONFIGURATION 1
+
+/*
+ * LIBXL_HAVE_BUILDINFO_VCPU_AFFINITY_ARRAYS
+ *
+ * If this is defined, then the libxl_domain_build_info structure will
+ * contain two arrays of libxl_bitmap-s, with all the necessary information
+ * to set the hard affinity (vcpu_hard_affinity) and the soft affinity
+ * (vcpu_soft_affinity) of the VCPUs.
+ *
+ * Note that, if the vcpu_hard_affinity array is used, libxl will ignore
+ * the content of the cpumap field of libxl_domain_build_info. That is to
+ * say, if the array is allocated and used by the caller, it is it and
+ * only it that determines the hard affinity of the domain's VCPUs.
+ *
+ * The number of libxl_bitmap-s in the arrays should be equal to the
+ * maximum number of VCPUs of the domain. If there only are N elements in
+ * an array, with N smaller the the maximum number of VCPUs, the hard or
+ * soft affinity (depending on which array we are talking about) will be
+ * set only for the first N VCPUs. The other VCPUs will just have affinity,
+ * both hard and soft, with all the host PCPUs.
+ * Each bitmap should be big enough to accommodate the maximum number of
+ * PCPUs of the host.
+ */
+#define LIBXL_HAVE_BUILDINFO_VCPU_AFFINITY_ARRAYS 1
+
/*
* LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST
*
@@ -445,6 +576,40 @@
#define LIBXL_HAVE_NO_SUSPEND_RESUME 1
#endif
+/*
+ * LIBXL_HAVE_DEVICE_PCI_SEIZE
+ *
+ * If this is defined, then the libxl_device_pci struct will contain
+ * the "seize" boolean field. If this field is set, libxl_pci_add will
+ * check to see if the device is currently assigned to pciback, and if not,
+ * it will attempt to do so (unbinding the device from the existing driver).
+ */
+#define LIBXL_HAVE_DEVICE_PCI_SEIZE 1
+
+/*
+ * LIBXL_HAVE_BUILDINFO_KERNEL
+ *
+ * If this is defined, then the libxl_domain_build_info structure will
+ * contain 'kernel', 'ramdisk', 'cmdline' fields. 'kernel' is a string
+ * to indicate kernel image location, 'ramdisk' is a string to indicate
+ * ramdisk location, 'cmdline' is a string to indicate the paramters which
+ * would be appended to kernel image.
+ *
+ * Both PV guest and HVM guest can use these fields for direct kernel boot.
+ * But for compatibility reason, u.pv.kernel, u.pv.ramdisk and u.pv.cmdline
+ * still exist.
+ */
+#define LIBXL_HAVE_BUILDINFO_KERNEL 1
+
+/*
+ * LIBXL_HAVE_DEVICE_CHANNEL
+ *
+ * If this is defined, then the libxl_device_channel struct exists
+ * and channels can be attached to a domain. Channels manifest as consoles
+ * with names, see docs/misc/console.txt.
+ */
+#define LIBXL_HAVE_DEVICE_CHANNEL 1
+
/* Functions annotated with LIBXL_EXTERNAL_CALLERS_ONLY may not be
* called from within libxl itself. Callers outside libxl, who
* do not #include libxl_internal.h, are fine. */
@@ -452,19 +617,86 @@
#define LIBXL_EXTERNAL_CALLERS_ONLY /* disappears for callers outside libxl */
#endif
+/*
+ * LIBXL_HAVE_UUID_COPY_CTX_PARAM
+ *
+ * If this is defined, libxl_uuid_copy has changed to take a libxl_ctx
+ * structure.
+ */
+#define LIBXL_HAVE_UUID_COPY_CTX_PARAM 1
+
+/*
+ * LIBXL_HAVE_SSID_LABEL
+ *
+ * If this is defined, then libxl IDL contains string of XSM security
+ * label in all XSM related structures.
+ *
+ * If set this string takes precedence over the numeric field.
+ */
+#define LIBXL_HAVE_SSID_LABEL 1
+
+/*
+ * LIBXL_HAVE_CPUPOOL_NAME
+ *
+ * If this is defined, then libxl IDL contains string of CPU pool
+ * name in all CPU pool related structures.
+ *
+ * If set this string takes precedence over the numeric field.
+ */
+#define LIBXL_HAVE_CPUPOOL_NAME 1
+
+/*
+ * LIBXL_HAVE_BUILDINFO_SERIAL_LIST
+ *
+ * If this is defined, then the libxl_domain_build_info structure will
+ * contain hvm.serial_list, a libxl_string_list type that contains
+ * a list of serial ports to specify on the qemu command-line.
+ *
+ * If it is set, callers may use either hvm.serial or
+ * hvm.serial_list, but not both; if both are set, libxl will
+ * throw an error.
+ *
+ * If this is not defined, callers can only use hvm.serial. Note
+ * that this means only one serial port can be added at domain build time.
+ */
+#define LIBXL_HAVE_BUILDINFO_SERIAL_LIST 1
+
+/*
+ * LIBXL_HAVE_REMUS
+ * If this is defined, then libxl supports remus.
+ */
+#define LIBXL_HAVE_REMUS 1
+
typedef uint8_t libxl_mac[6];
#define LIBXL_MAC_FMT "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx"
#define LIBXL_MAC_FMTLEN ((2*6)+5) /* 6 hex bytes plus 5 colons */
#define LIBXL_MAC_BYTES(mac) mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
+void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, libxl_mac *src);
+
+#if defined(__i386__) || defined(__x86_64__)
+/*
+ * LIBXL_HAVE_PSR_CMT
+ *
+ * If this is defined, the Cache Monitoring Technology feature is supported.
+ */
+#define LIBXL_HAVE_PSR_CMT 1
+#endif
typedef char **libxl_string_list;
void libxl_string_list_dispose(libxl_string_list *sl);
int libxl_string_list_length(const libxl_string_list *sl);
+void libxl_string_list_copy(libxl_ctx *ctx, libxl_string_list *dst,
+ libxl_string_list *src);
typedef char **libxl_key_value_list;
void libxl_key_value_list_dispose(libxl_key_value_list *kvl);
+int libxl_key_value_list_length(libxl_key_value_list *kvl);
+void libxl_key_value_list_copy(libxl_ctx *ctx,
+ libxl_key_value_list *dst,
+ libxl_key_value_list *src);
typedef uint32_t libxl_hwcap[8];
+void libxl_hwcap_copy(libxl_ctx *ctx, libxl_hwcap *dst, libxl_hwcap *src);
typedef uint64_t libxl_ev_user;
@@ -482,6 +714,10 @@ void libxl_bitmap_dispose(libxl_bitmap *map);
typedef struct libxl__cpuid_policy libxl_cpuid_policy;
typedef libxl_cpuid_policy * libxl_cpuid_policy_list;
void libxl_cpuid_dispose(libxl_cpuid_policy_list *cpuid_list);
+int libxl_cpuid_policy_list_length(libxl_cpuid_policy_list *l);
+void libxl_cpuid_policy_list_copy(libxl_ctx *ctx,
+ libxl_cpuid_policy_list *dst,
+ libxl_cpuid_policy_list *src);
#define LIBXL_PCI_FUNC_ALL (~0U)
@@ -526,11 +762,14 @@ bool libxl_defbool_val(libxl_defbool db);
const char *libxl_defbool_to_string(libxl_defbool b);
-typedef struct libxl__ctx libxl_ctx;
-
#define LIBXL_TIMER_MODE_DEFAULT -1
#define LIBXL_MEMKB_DEFAULT ~0ULL
+#define LIBXL_MS_VM_GENID_LEN 16
+typedef struct {
+ uint8_t bytes[LIBXL_MS_VM_GENID_LEN];
+} libxl_ms_vm_genid;
+
#include "_libxl_types.h"
const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx);
@@ -665,10 +904,15 @@ int static inline libxl_domain_create_restore_0x040200(
LIBXL_EXTERNAL_CALLERS_ONLY
{
libxl_domain_restore_params params;
- params.checkpointed_stream = 0;
+ int ret;
- return libxl_domain_create_restore(
+ libxl_domain_restore_params_init(¶ms);
+
+ ret = libxl_domain_create_restore(
ctx, d_config, domid, restore_fd, ¶ms, ao_how, aop_console_how);
+
+ libxl_domain_restore_params_dispose(¶ms);
+ return ret;
}
#define libxl_domain_create_restore libxl_domain_create_restore_0x040200
@@ -683,6 +927,14 @@ int static inline libxl_domain_create_restore_0x040200(
void libxl_domain_config_init(libxl_domain_config *d_config);
void libxl_domain_config_dispose(libxl_domain_config *d_config);
+/*
+ * Retrieve domain configuration and filled it in d_config. The
+ * returned configuration can be used to rebuild a domain. It only
+ * works with DomU.
+ */
+int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid,
+ libxl_domain_config *d_config);
+
int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd,
int flags, /* LIBXL_SUSPEND_* */
const libxl_asyncop_how *ao_how)
@@ -857,6 +1109,10 @@ void libxl_vtpminfo_list_free(libxl_vtpminfo *, int nr_vtpms);
* domain to connect to the device and therefore cannot block on the
* guest.
*
+ * device is an in/out parameter: fields left unspecified when the
+ * structure is passed in are filled in with appropriate values for
+ * the device created.
+ *
* libxl_device_<type>_remove(ctx, domid, device):
*
* Removes the given device from the specified domain by performing
@@ -919,6 +1175,17 @@ libxl_device_nic *libxl_device_nic_list(libxl_ctx *ctx, uint32_t domid, int *num
int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_nic *nic, libxl_nicinfo *nicinfo);
+/*
+ * Virtual Channels
+ * Channels manifest as consoles with names, see docs/misc/channels.txt
+ */
+libxl_device_channel *libxl_device_channel_list(libxl_ctx *ctx,
+ uint32_t domid,
+ int *num);
+int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
+ libxl_device_channel *channel,
+ libxl_channelinfo *channelinfo);
+
/* Virtual TPMs */
int libxl_device_vtpm_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vtpm *vtpm,
const libxl_asyncop_how *ao_how)
@@ -1038,6 +1305,14 @@ void libxl_cpuid_set(libxl_ctx *ctx, uint32_t domid,
* "xl" domain config file in xl format, Unix line endings
* "libvirt-xml" domain config file in libvirt XML format. See
* http://libvirt.org/formatdomain.html
+ * "domain-userdata-lock" lock file to protect domain userdata in libxl.
+ * It's a per-domain lock. Applications should
+ * not touch this file.
+ * "libxl-json" libxl_domain_config object in JSON format, generated
+ * by libxl. Applications should not access this file
+ * directly. This file is protected by domain-userdata-lock
+ * for against Read-Modify-Write operation and domain
+ * destruction.
*
* libxl does not enforce the registration of userdata userids or the
* semantics of the data. For specifications of the data formats
@@ -1057,12 +1332,28 @@ int libxl_userdata_retrieve(libxl_ctx *ctx, uint32_t domid,
* data_r and datalen_r may be 0.
* On error return, *data_r and *datalen_r are undefined.
*/
+int libxl_userdata_unlink(libxl_ctx *ctx, uint32_t domid,
+ const char *userdata_userid);
+
int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo);
int libxl_set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid,
- libxl_bitmap *cpumap);
+ const libxl_bitmap *cpumap_hard,
+ const libxl_bitmap *cpumap_soft);
int libxl_set_vcpuaffinity_all(libxl_ctx *ctx, uint32_t domid,
- unsigned int max_vcpus, libxl_bitmap *cpumap);
+ unsigned int max_vcpus,
+ const libxl_bitmap *cpumap_hard,
+ const libxl_bitmap *cpumap_soft);
+
+#if defined (LIBXL_API_VERSION) && LIBXL_API_VERSION < 0x040500
+
+#define libxl_set_vcpuaffinity(ctx, domid, vcpuid, map) \
+ libxl_set_vcpuaffinity((ctx), (domid), (vcpuid), (map), NULL)
+#define libxl_set_vcpuaffinity_all(ctx, domid, max_vcpus, map) \
+ libxl_set_vcpuaffinity_all((ctx), (domid), (max_vcpus), (map), NULL)
+
+#endif
+
int libxl_domain_set_nodeaffinity(libxl_ctx *ctx, uint32_t domid,
libxl_bitmap *nodemap);
int libxl_domain_get_nodeaffinity(libxl_ctx *ctx, uint32_t domid,
@@ -1085,6 +1376,7 @@ int libxl_sched_credit_params_set(libxl_ctx *ctx, uint32_t poolid,
#define LIBXL_DOMAIN_SCHED_PARAM_SLICE_DEFAULT -1
#define LIBXL_DOMAIN_SCHED_PARAM_LATENCY_DEFAULT -1
#define LIBXL_DOMAIN_SCHED_PARAM_EXTRATIME_DEFAULT -1
+#define LIBXL_DOMAIN_SCHED_PARAM_BUDGET_DEFAULT -1
int libxl_domain_sched_params_get(libxl_ctx *ctx, uint32_t domid,
libxl_domain_sched_params *params);
@@ -1141,6 +1433,23 @@ int libxl_flask_getenforce(libxl_ctx *ctx);
int libxl_flask_setenforce(libxl_ctx *ctx, int mode);
int libxl_flask_loadpolicy(libxl_ctx *ctx, void *policy, uint32_t size);
+int libxl_ms_vm_genid_generate(libxl_ctx *ctx, libxl_ms_vm_genid *id);
+bool libxl_ms_vm_genid_is_zero(const libxl_ms_vm_genid *id);
+void libxl_ms_vm_genid_copy(libxl_ctx *ctx, libxl_ms_vm_genid *dst,
+ libxl_ms_vm_genid *src);
+
+#ifdef LIBXL_HAVE_PSR_CMT
+int libxl_psr_cmt_attach(libxl_ctx *ctx, uint32_t domid);
+int libxl_psr_cmt_detach(libxl_ctx *ctx, uint32_t domid);
+int libxl_psr_cmt_domain_attached(libxl_ctx *ctx, uint32_t domid);
+int libxl_psr_cmt_enabled(libxl_ctx *ctx);
+int libxl_psr_cmt_get_total_rmid(libxl_ctx *ctx, uint32_t *total_rmid);
+int libxl_psr_cmt_get_l3_cache_size(libxl_ctx *ctx, uint32_t socketid,
+ uint32_t *l3_cache_size);
+int libxl_psr_cmt_get_cache_occupancy(libxl_ctx *ctx, uint32_t domid,
+ uint32_t socketid, uint32_t *l3_cache_occupancy);
+#endif
+
/* misc */
/* Each of these sets or clears the flag according to whether the
diff --git a/tools/libxl/libxl_aoutils.c b/tools/libxl/libxl_aoutils.c
index b4eb6e5..b10d2e1 100644
--- a/tools/libxl/libxl_aoutils.c
+++ b/tools/libxl/libxl_aoutils.c
@@ -16,6 +16,87 @@
#include "libxl_internal.h"
+/*----- xswait -----*/
+
+static libxl__ev_xswatch_callback xswait_xswatch_callback;
+static libxl__ev_time_callback xswait_timeout_callback;
+static void xswait_report_error(libxl__egc*, libxl__xswait_state*, int rc);
+
+void libxl__xswait_init(libxl__xswait_state *xswa)
+{
+ libxl__ev_time_init(&xswa->time_ev);
+ libxl__ev_xswatch_init(&xswa->watch_ev);
+}
+
+void libxl__xswait_stop(libxl__gc *gc, libxl__xswait_state *xswa)
+{
+ libxl__ev_time_deregister(gc, &xswa->time_ev);
+ libxl__ev_xswatch_deregister(gc, &xswa->watch_ev);
+}
+
+bool libxl__xswait_inuse(const libxl__xswait_state *xswa)
+{
+ bool time_inuse = libxl__ev_time_isregistered(&xswa->time_ev);
+ bool watch_inuse = libxl__ev_xswatch_isregistered(&xswa->watch_ev);
+ assert(time_inuse == watch_inuse);
+ return time_inuse;
+}
+
+int libxl__xswait_start(libxl__gc *gc, libxl__xswait_state *xswa)
+{
+ int rc;
+
+ rc = libxl__ev_time_register_rel(gc, &xswa->time_ev,
+ xswait_timeout_callback, xswa->timeout_ms);
+ if (rc) goto err;
+
+ rc = libxl__ev_xswatch_register(gc, &xswa->watch_ev,
+ xswait_xswatch_callback, xswa->path);
+ if (rc) goto err;
+
+ return 0;
+
+ err:
+ libxl__xswait_stop(gc, xswa);
+ return rc;
+}
+
+void xswait_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *xsw,
+ const char *watch_path, const char *event_path)
+{
+ EGC_GC;
+ libxl__xswait_state *xswa = CONTAINER_OF(xsw, *xswa, watch_ev);
+ int rc;
+ const char *data;
+
+ if (xswa->path[0] == '@') {
+ data = 0;
+ } else {
+ rc = libxl__xs_read_checked(gc, XBT_NULL, xswa->path, &data);
+ if (rc) { xswait_report_error(egc, xswa, rc); return; }
+ }
+
+ xswa->callback(egc, xswa, 0, data);
+}
+
+void xswait_timeout_callback(libxl__egc *egc, libxl__ev_time *ev,
+ const struct timeval *requested_abs)
+{
+ EGC_GC;
+ libxl__xswait_state *xswa = CONTAINER_OF(ev, *xswa, time_ev);
+ LOG(DEBUG, "%s: xswait timeout (path=%s)", xswa->what, xswa->path);
+ xswait_report_error(egc, xswa, ERROR_TIMEDOUT);
+}
+
+static void xswait_report_error(libxl__egc *egc, libxl__xswait_state *xswa,
+ int rc)
+{
+ EGC_GC;
+ libxl__xswait_stop(gc, xswa);
+ xswa->callback(egc, xswa, rc, 0);
+}
+
+
/*----- data copier -----*/
void libxl__datacopier_init(libxl__datacopier_state *dc)
@@ -370,3 +451,92 @@ int libxl__openptys(libxl__openpty_state *op,
return rc;
}
+static void async_exec_timeout(libxl__egc *egc,
+ libxl__ev_time *ev,
+ const struct timeval *requested_abs)
+{
+ libxl__async_exec_state *aes = CONTAINER_OF(ev, *aes, time);
+ STATE_AO_GC(aes->ao);
+
+ libxl__ev_time_deregister(gc, &aes->time);
+
+ assert(libxl__ev_child_inuse(&aes->child));
+ LOG(ERROR, "killing execution of %s because of timeout", aes->what);
+
+ if (kill(aes->child.pid, SIGKILL)) {
+ LOGEV(ERROR, errno, "unable to kill %s [%ld]",
+ aes->what, (unsigned long)aes->child.pid);
+ }
+
+ return;
+}
+
+static void async_exec_done(libxl__egc *egc,
+ libxl__ev_child *child,
+ pid_t pid, int status)
+{
+ libxl__async_exec_state *aes = CONTAINER_OF(child, *aes, child);
+ STATE_AO_GC(aes->ao);
+
+ libxl__ev_time_deregister(gc, &aes->time);
+
+ if (status) {
+ libxl_report_child_exitstatus(CTX, LIBXL__LOG_ERROR,
+ aes->what, pid, status);
+ }
+
+ aes->callback(egc, aes, status);
+}
+
+void libxl__async_exec_init(libxl__async_exec_state *aes)
+{
+ libxl__ev_time_init(&aes->time);
+ libxl__ev_child_init(&aes->child);
+}
+
+int libxl__async_exec_start(libxl__gc *gc, libxl__async_exec_state *aes)
+{
+ pid_t pid;
+
+ /* Convenience aliases */
+ libxl__ev_child *const child = &aes->child;
+ char ** const args = aes->args;
+
+ /* Set execution timeout */
+ if (libxl__ev_time_register_rel(gc, &aes->time,
+ async_exec_timeout,
+ aes->timeout_ms)) {
+ LOG(ERROR, "unable to register timeout for executing: %s", aes->what);
+ goto out;
+ }
+
+ LOG(DEBUG, "forking to execute: %s ", aes->what);
+
+ /* Fork and exec */
+ pid = libxl__ev_child_fork(gc, child, async_exec_done);
+ if (pid == -1) {
+ LOG(ERROR, "unable to fork");
+ goto out;
+ }
+
+ if (!pid) {
+ /* child */
+ libxl__exec(gc, aes->stdfds[0], aes->stdfds[1],
+ aes->stdfds[2], args[0], args, aes->env);
+ /* notreached */
+ abort();
+ }
+
+ return 0;
+
+out:
+ return ERROR_FAIL;
+}
+
+bool libxl__async_exec_inuse(const libxl__async_exec_state *aes)
+{
+ bool time_inuse = libxl__ev_time_isregistered(&aes->time);
+ bool child_inuse = libxl__ev_child_inuse(&aes->child);
+ assert(time_inuse == child_inuse);
+ return child_inuse;
+}
diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
index 4f0f0e2..448ac07 100644
--- a/tools/libxl/libxl_arm.c
+++ b/tools/libxl/libxl_arm.c
@@ -6,6 +6,35 @@
#include <libfdt.h>
#include <assert.h>
+/**
+ * IRQ line type.
+ * DT_IRQ_TYPE_NONE - default, unspecified type
+ * DT_IRQ_TYPE_EDGE_RISING - rising edge triggered
+ * DT_IRQ_TYPE_EDGE_FALLING - falling edge triggered
+ * DT_IRQ_TYPE_EDGE_BOTH - rising and falling edge triggered
+ * DT_IRQ_TYPE_LEVEL_HIGH - high level triggered
+ * DT_IRQ_TYPE_LEVEL_LOW - low level triggered
+ */
+#define DT_IRQ_TYPE_NONE 0x00000000
+#define DT_IRQ_TYPE_EDGE_RISING 0x00000001
+#define DT_IRQ_TYPE_EDGE_FALLING 0x00000002
+#define DT_IRQ_TYPE_EDGE_BOTH \
+ (DT_IRQ_TYPE_EDGE_FALLING | DT_IRQ_TYPE_EDGE_RISING)
+#define DT_IRQ_TYPE_LEVEL_HIGH 0x00000004
+#define DT_IRQ_TYPE_LEVEL_LOW 0x00000008
+
+static const char *gicv_to_string(uint8_t gic_version)
+{
+ switch (gic_version) {
+ case XEN_DOMCTL_CONFIG_GIC_V2:
+ return "V2";
+ case XEN_DOMCTL_CONFIG_GIC_V3:
+ return "V3";
+ default:
+ return "unknown";
+ }
+}
+
int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config,
uint32_t domid)
{
@@ -47,14 +76,20 @@ static void set_cell(be32 **cellp, int size, uint64_t val)
(*cellp) += cells;
}
-static void set_interrupt_ppi(gic_interrupt interrupt, unsigned int irq,
- unsigned int cpumask, unsigned int level)
+static void set_interrupt(gic_interrupt interrupt, unsigned int irq,
+ unsigned int cpumask, unsigned int level)
{
be32 *cells = interrupt;
+ int is_ppi = (irq < 32);
+
+ /* SGIs are not describe in the device tree */
+ assert(irq >= 16);
+
+ irq -= (is_ppi) ? 16: 32; /* PPIs start at 16, SPIs at 32 */
/* See linux Documentation/devictree/bindings/arm/gic.txt */
- set_cell(&cells, 1, 1); /* is a PPI */
- set_cell(&cells, 1, irq - 16); /* PPIs start at 16 */
+ set_cell(&cells, 1, is_ppi); /* is a PPI? */
+ set_cell(&cells, 1, irq);
set_cell(&cells, 1, (cpumask << 8) | level);
}
@@ -168,8 +203,8 @@ static int make_chosen_node(libxl__gc *gc, void *fdt, bool ramdisk,
res = fdt_begin_node(fdt, "chosen");
if (res) return res;
- if (info->u.pv.cmdline) {
- res = fdt_property_string(fdt, "bootargs", info->u.pv.cmdline);
+ if (info->cmdline) {
+ res = fdt_property_string(fdt, "bootargs", info->cmdline);
if (res) return res;
}
@@ -237,7 +272,7 @@ static int make_psci_node(libxl__gc *gc, void *fdt)
res = fdt_begin_node(fdt, "psci");
if (res) return res;
- res = fdt_property_compat(gc, fdt, 1, "arm,psci");
+ res = fdt_property_compat(gc, fdt, 2, "arm,psci-0.2","arm,psci");
if (res) return res;
res = fdt_property_string(fdt, "method", "hvc");
@@ -255,21 +290,70 @@ static int make_psci_node(libxl__gc *gc, void *fdt)
return 0;
}
-static int make_memory_node(libxl__gc *gc, void *fdt,
- unsigned long long base,
- unsigned long long size)
+static int make_memory_nodes(libxl__gc *gc, void *fdt,
+ const struct xc_dom_image *dom)
+{
+ int res, i;
+ const char *name;
+ const uint64_t bankbase[] = GUEST_RAM_BANK_BASES;
+
+ for (i = 0; i < GUEST_RAM_BANKS; i++) {
+ name = GCSPRINTF("memory@%"PRIx64, bankbase[i]);
+
+ LOG(DEBUG, "Creating placeholder node /%s", name);
+
+ res = fdt_begin_node(fdt, name);
+ if (res) return res;
+
+ res = fdt_property_string(fdt, "device_type", "memory");
+ if (res) return res;
+
+ res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
+ 1, 0, 0);
+ if (res) return res;
+
+ res = fdt_end_node(fdt);
+ if (res) return res;
+ }
+
+ return 0;
+}
+
+static int make_gicv2_node(libxl__gc *gc, void *fdt,
+ uint64_t gicd_base, uint64_t gicd_size,
+ uint64_t gicc_base, uint64_t gicc_size)
{
int res;
- const char *name = GCSPRINTF("memory@%08llx", base);
+ const char *name = GCSPRINTF("interrupt-controller@%"PRIx64, gicd_base);
res = fdt_begin_node(fdt, name);
if (res) return res;
- res = fdt_property_string(fdt, "device_type", "memory");
+ res = fdt_property_compat(gc, fdt, 2,
+ "arm,cortex-a15-gic",
+ "arm,cortex-a9-gic");
+ if (res) return res;
+
+
+ res = fdt_property_cell(fdt, "#interrupt-cells", 3);
+ if (res) return res;
+
+ res = fdt_property_cell(fdt, "#address-cells", 0);
+ if (res) return res;
+
+ res = fdt_property(fdt, "interrupt-controller", NULL, 0);
if (res) return res;
res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
- 1, (uint64_t)base, (uint64_t)size);
+ 2,
+ gicd_base, gicd_size,
+ gicc_base, gicc_size);
+ if (res) return res;
+
+ res = fdt_property_cell(fdt, "linux,phandle", PHANDLE_GIC);
+ if (res) return res;
+
+ res = fdt_property_cell(fdt, "phandle", PHANDLE_GIC);
if (res) return res;
res = fdt_end_node(fdt);
@@ -278,24 +362,21 @@ static int make_memory_node(libxl__gc *gc, void *fdt,
return 0;
}
-static int make_intc_node(libxl__gc *gc, void *fdt,
- unsigned long long gicd_base,
- unsigned long long gicd_size,
- unsigned long long gicc_base,
- unsigned long long gicc_size)
+static int make_gicv3_node(libxl__gc *gc, void *fdt)
{
int res;
- const char *name = GCSPRINTF("interrupt-controller@%08llx", gicd_base);
+ const uint64_t gicd_base = GUEST_GICV3_GICD_BASE;
+ const uint64_t gicd_size = GUEST_GICV3_GICD_SIZE;
+ const uint64_t gicr0_base = GUEST_GICV3_GICR0_BASE;
+ const uint64_t gicr0_size = GUEST_GICV3_GICR0_SIZE;
+ const char *name = GCSPRINTF("interrupt-controller@%"PRIx64, gicd_base);
res = fdt_begin_node(fdt, name);
if (res) return res;
- res = fdt_property_compat(gc, fdt, 2,
- "arm,cortex-a15-gic",
- "arm,cortex-a9-gic");
+ res = fdt_property_compat(gc, fdt, 1, "arm,gic-v3");
if (res) return res;
-
res = fdt_property_cell(fdt, "#interrupt-cells", 3);
if (res) return res;
@@ -305,10 +386,18 @@ static int make_intc_node(libxl__gc *gc, void *fdt,
res = fdt_property(fdt, "interrupt-controller", NULL, 0);
if (res) return res;
+ res = fdt_property_cell(fdt, "redistributor-stride",
+ GUEST_GICV3_RDIST_STRIDE);
+ if (res) return res;
+
+ res = fdt_property_cell(fdt, "#redistributor-regions",
+ GUEST_GICV3_RDIST_REGIONS);
+ if (res) return res;
+
res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
2,
- (uint64_t)gicd_base, (uint64_t)gicd_size,
- (uint64_t)gicc_base, (uint64_t)gicc_size);
+ gicd_base, gicd_size,
+ gicr0_base, gicr0_size);
if (res) return res;
res = fdt_property_cell(fdt, "linux,phandle", PHANDLE_GIC);
@@ -334,9 +423,9 @@ static int make_timer_node(libxl__gc *gc, void *fdt, const struct arch_info *ain
res = fdt_property_compat(gc, fdt, 1, ainfo->timer_compat);
if (res) return res;
- set_interrupt_ppi(ints[0], GUEST_TIMER_PHYS_S_PPI, 0xf, 0x8);
- set_interrupt_ppi(ints[1], GUEST_TIMER_PHYS_NS_PPI, 0xf, 0x8);
- set_interrupt_ppi(ints[2], GUEST_TIMER_VIRT_PPI, 0xf, 0x8);
+ set_interrupt(ints[0], GUEST_TIMER_PHYS_S_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
+ set_interrupt(ints[1], GUEST_TIMER_PHYS_NS_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
+ set_interrupt(ints[2], GUEST_TIMER_VIRT_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
res = fdt_property_interrupts(gc, fdt, ints, 3);
if (res) return res;
@@ -374,7 +463,7 @@ static int make_hypervisor_node(libxl__gc *gc, void *fdt,
* - Active-low level-sensitive
* - All cpus
*/
- set_interrupt_ppi(intr, GUEST_EVTCHN_PPI, 0xf, 0x8);
+ set_interrupt(intr, GUEST_EVTCHN_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
res = fdt_property_interrupts(gc, fdt, &intr, 1);
if (res) return res;
@@ -429,6 +518,7 @@ int libxl__arch_domain_init_hw_description(libxl__gc *gc,
libxl_domain_build_info *info,
struct xc_dom_image *dom)
{
+ xc_domain_configuration_t config;
void *fdt = NULL;
int rc, res;
size_t fdt_size = 0;
@@ -444,8 +534,16 @@ int libxl__arch_domain_init_hw_description(libxl__gc *gc,
ainfo = get_arch_info(gc, dom);
if (ainfo == NULL) return ERROR_FAIL;
+ LOG(DEBUG, "configure the domain");
+ config.gic_version = XEN_DOMCTL_CONFIG_GIC_DEFAULT;
+ if (xc_domain_configure(CTX->xch, dom->guest_domid, &config) != 0) {
+ LOG(ERROR, "couldn't configure the domain");
+ return ERROR_FAIL;
+ }
+
LOG(DEBUG, "constructing DTB for Xen version %d.%d guest",
vers->xen_version_major, vers->xen_version_minor);
+ LOG(DEBUG, " - vGIC version: %s", gicv_to_string(config.gic_version));
/*
* Call "call" handling FDR_ERR_*. Will either:
@@ -492,12 +590,22 @@ next_resize:
FDT( make_cpus_node(gc, fdt, info->max_vcpus, ainfo) );
FDT( make_psci_node(gc, fdt) );
- FDT( make_memory_node(gc, fdt,
- dom->rambase_pfn << XC_PAGE_SHIFT,
- info->target_memkb * 1024) );
- FDT( make_intc_node(gc, fdt,
- GUEST_GICD_BASE, GUEST_GICD_SIZE,
- GUEST_GICC_BASE, GUEST_GICD_SIZE) );
+ FDT( make_memory_nodes(gc, fdt, dom) );
+
+ switch (config.gic_version) {
+ case XEN_DOMCTL_CONFIG_GIC_V2:
+ FDT( make_gicv2_node(gc, fdt,
+ GUEST_GICD_BASE, GUEST_GICD_SIZE,
+ GUEST_GICC_BASE, GUEST_GICC_SIZE) );
+ break;
+ case XEN_DOMCTL_CONFIG_GIC_V3:
+ FDT( make_gicv3_node(gc, fdt) );
+ break;
+ default:
+ LOG(ERROR, "Unknown GIC version %d", config.gic_version);
+ rc = ERROR_FAIL;
+ goto out;
+ }
FDT( make_timer_node(gc, fdt, ainfo) );
FDT( make_hypervisor_node(gc, fdt, vers) );
@@ -524,11 +632,38 @@ out:
return rc;
}
+static void finalise_one_memory_node(libxl__gc *gc, void *fdt,
+ uint64_t base, uint64_t size)
+{
+ int node, res;
+ const char *name = GCSPRINTF("/memory@%"PRIx64, base);
+
+ node = fdt_path_offset(fdt, name);
+ assert(node > 0);
+
+ if (size == 0) {
+ LOG(DEBUG, "Nopping out placeholder node %s", name);
+ fdt_nop_node(fdt, node);
+ } else {
+ uint32_t regs[ROOT_ADDRESS_CELLS+ROOT_SIZE_CELLS];
+ be32 *cells = ®s[0];
+
+ LOG(DEBUG, "Populating placeholder node %s", name);
+
+ set_range(&cells, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS, base, size);
+
+ res = fdt_setprop_inplace(fdt, node, "reg", regs, sizeof(regs));
+ assert(!res);
+ }
+}
+
int libxl__arch_domain_finalise_hw_description(libxl__gc *gc,
libxl_domain_build_info *info,
struct xc_dom_image *dom)
{
void *fdt = dom->devicetree_blob;
+ int i;
+ const uint64_t bankbase[] = GUEST_RAM_BANK_BASES;
const struct xc_dom_seg *ramdisk = dom->ramdisk_blob ?
&dom->ramdisk_seg : NULL;
@@ -555,9 +690,16 @@ int libxl__arch_domain_finalise_hw_description(libxl__gc *gc,
assert(!res);
val = cpu_to_fdt64(ramdisk->vend);
- res = fdt_setprop_inplace(fdt, chosen,PROP_INITRD_END,
+ res = fdt_setprop_inplace(fdt, chosen, PROP_INITRD_END,
&val, sizeof(val));
assert(!res);
+
+ }
+
+ for (i = 0; i < GUEST_RAM_BANKS; i++) {
+ const uint64_t size = (uint64_t)dom->rambank_size[i] << XC_PAGE_SHIFT;
+
+ finalise_one_memory_node(gc, fdt, bankbase[i], size);
}
debug_dump_fdt(gc, fdt);
diff --git a/tools/libxl/libxl_bootloader.c b/tools/libxl/libxl_bootloader.c
index 3287bf7..79947d4 100644
--- a/tools/libxl/libxl_bootloader.c
+++ b/tools/libxl/libxl_bootloader.c
@@ -15,7 +15,9 @@
#include "libxl_osdeps.h" /* must come before any other headers */
#include <termios.h>
+#ifdef HAVE_UTMP_H
#include <utmp.h>
+#endif
#ifdef INCLUDE_LIBUTIL_H
#include INCLUDE_LIBUTIL_H
@@ -56,12 +58,12 @@ static void make_bootloader_args(libxl__gc *gc, libxl__bootloader_state *bl,
ARG(bootloader_path);
- if (info->u.pv.kernel)
- ARG(libxl__sprintf(gc, "--kernel=%s", info->u.pv.kernel));
- if (info->u.pv.ramdisk)
- ARG(libxl__sprintf(gc, "--ramdisk=%s", info->u.pv.ramdisk));
- if (info->u.pv.cmdline && *info->u.pv.cmdline != '\0')
- ARG(libxl__sprintf(gc, "--args=%s", info->u.pv.cmdline));
+ if (info->kernel)
+ ARG(libxl__sprintf(gc, "--kernel=%s", info->kernel));
+ if (info->ramdisk)
+ ARG(libxl__sprintf(gc, "--ramdisk=%s", info->ramdisk));
+ if (info->cmdline && *info->cmdline != '\0')
+ ARG(libxl__sprintf(gc, "--args=%s", info->cmdline));
ARG(libxl__sprintf(gc, "--output=%s", bl->outputpath));
ARG("--output-format=simple0");
@@ -325,9 +327,9 @@ void libxl__bootloader_run(libxl__egc *egc, libxl__bootloader_state *bl)
if (!info->u.pv.bootloader) {
LOG(DEBUG, "no bootloader configured, using user supplied kernel");
- bl->kernel->path = bl->info->u.pv.kernel;
- bl->ramdisk->path = bl->info->u.pv.ramdisk;
- bl->cmdline = bl->info->u.pv.cmdline;
+ bl->kernel->path = bl->info->kernel;
+ bl->ramdisk->path = bl->info->ramdisk;
+ bl->cmdline = bl->info->cmdline;
rc = 0;
goto out_ok;
}
diff --git a/tools/libxl/libxl_cpuid.c b/tools/libxl/libxl_cpuid.c
index dd21b78..7cfa6b7 100644
--- a/tools/libxl/libxl_cpuid.c
+++ b/tools/libxl/libxl_cpuid.c
@@ -14,6 +14,11 @@
#include "libxl_internal.h"
+int libxl__cpuid_policy_is_empty(libxl_cpuid_policy_list *pl)
+{
+ return !libxl_cpuid_policy_list_length(pl);
+}
+
void libxl_cpuid_dispose(libxl_cpuid_policy_list *p_cpuid_list)
{
int i, j;
@@ -26,6 +31,7 @@ void libxl_cpuid_dispose(libxl_cpuid_policy_list *p_cpuid_list)
if (cpuid_list[i].policy[j] != NULL)
free(cpuid_list[i].policy[j]);
}
+ free(cpuid_list);
return;
}
@@ -187,6 +193,7 @@ int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str)
{"svm_vmcbclean",0x8000000a, NA, CPUID_REG_EDX, 5, 1},
{"svm_decode", 0x8000000a, NA, CPUID_REG_EDX, 7, 1},
{"svm_pausefilt",0x8000000a, NA, CPUID_REG_EDX, 10, 1},
+ {"maxhvleaf", 0x40000000, NA, CPUID_REG_EAX, 0, 8},
{NULL, 0, NA, CPUID_REG_INV, 0, 0}
};
@@ -336,29 +343,29 @@ void libxl_cpuid_set(libxl_ctx *ctx, uint32_t domid,
(const char**)(cpuid[i].policy), cpuid_res);
}
+static const char *input_names[2] = { "leaf", "subleaf" };
+static const char *policy_names[4] = { "eax", "ebx", "ecx", "edx" };
+/*
+ * Aiming for:
+ * [
+ * { 'leaf': 'val-eax',
+ * 'subleaf': 'val-ecx',
+ * 'eax': 'filter',
+ * 'ebx': 'filter',
+ * 'ecx': 'filter',
+ * 'edx': 'filter' },
+ * { 'leaf': 'val-eax', ..., 'eax': 'filter', ... },
+ * ... etc ...
+ * ]
+ */
+
yajl_gen_status libxl_cpuid_policy_list_gen_json(yajl_gen hand,
libxl_cpuid_policy_list *pcpuid)
{
libxl_cpuid_policy_list cpuid = *pcpuid;
yajl_gen_status s;
- const char *input_names[2] = { "leaf", "subleaf" };
- const char *policy_names[4] = { "eax", "ebx", "ecx", "edx" };
int i, j;
- /*
- * Aiming for:
- * [
- * { 'leaf': 'val-eax',
- * 'subleaf': 'val-ecx',
- * 'eax': 'filter',
- * 'ebx': 'filter',
- * 'ecx': 'filter',
- * 'edx': 'filter' },
- * { 'leaf': 'val-eax', ..., 'eax': 'filter', ... },
- * ... etc ...
- * ]
- */
-
s = yajl_gen_array_open(hand);
if (s != yajl_gen_status_ok) goto out;
@@ -396,6 +403,109 @@ out:
return s;
}
+int libxl__cpuid_policy_list_parse_json(libxl__gc *gc,
+ const libxl__json_object *o,
+ libxl_cpuid_policy_list *p)
+{
+ int i, size;
+ libxl_cpuid_policy_list l;
+ flexarray_t *array;
+
+ if (!libxl__json_object_is_array(o))
+ return ERROR_FAIL;
+
+ array = libxl__json_object_get_array(o);
+ if (!array->count)
+ return 0;
+
+ size = array->count;
+ /* need one extra slot as sentinel */
+ l = *p = libxl__calloc(NOGC, size + 1, sizeof(libxl_cpuid_policy));
+
+ l[size].input[0] = XEN_CPUID_INPUT_UNUSED;
+ l[size].input[1] = XEN_CPUID_INPUT_UNUSED;
+
+ for (i = 0; i < size; i++) {
+ const libxl__json_object *t;
+ int j;
+
+ if (flexarray_get(array, i, (void**)&t) != 0)
+ return ERROR_FAIL;
+
+ if (!libxl__json_object_is_map(t))
+ return ERROR_FAIL;
+
+ for (j = 0; j < ARRAY_SIZE(l[0].input); j++) {
+ const libxl__json_object *r;
+
+ r = libxl__json_map_get(input_names[j], t, JSON_INTEGER);
+ if (!r)
+ l[i].input[j] = XEN_CPUID_INPUT_UNUSED;
+ else
+ l[i].input[j] = libxl__json_object_get_integer(r);
+ }
+
+ for (j = 0; j < ARRAY_SIZE(l[0].policy); j++) {
+ const libxl__json_object *r;
+
+ r = libxl__json_map_get(policy_names[j], t, JSON_STRING);
+ if (!r)
+ l[i].policy[j] = NULL;
+ else
+ l[i].policy[j] =
+ libxl__strdup(NOGC, libxl__json_object_get_string(r));
+ }
+ }
+
+ return 0;
+}
+
+int libxl_cpuid_policy_list_length(libxl_cpuid_policy_list *pl)
+{
+ int i = 0;
+ libxl_cpuid_policy_list l = *pl;
+
+ if (l) {
+ while (l[i].input[0] != XEN_CPUID_INPUT_UNUSED)
+ i++;
+ }
+
+ return i;
+}
+
+void libxl_cpuid_policy_list_copy(libxl_ctx *ctx,
+ libxl_cpuid_policy_list *dst,
+ libxl_cpuid_policy_list *src)
+{
+ GC_INIT(ctx);
+ int i, j, len;
+
+ if (*src == NULL) {
+ *dst = NULL;
+ goto out;
+ }
+
+ len = libxl_cpuid_policy_list_length(src);
+ /* one extra slot for sentinel */
+ *dst = libxl__calloc(NOGC, len + 1, sizeof(libxl_cpuid_policy));
+ (*dst)[len].input[0] = XEN_CPUID_INPUT_UNUSED;
+ (*dst)[len].input[1] = XEN_CPUID_INPUT_UNUSED;
+
+ for (i = 0; i < len; i++) {
+ for (j = 0; j < 2; j++)
+ (*dst)[i].input[j] = (*src)[i].input[j];
+ for (j = 0; j < 4; j++)
+ if ((*src)[i].policy[j])
+ (*dst)[i].policy[j] =
+ libxl__strdup(NOGC, (*src)[i].policy[j]);
+ else
+ (*dst)[i].policy[j] = NULL;
+ }
+
+out:
+ GC_FREE;
+}
+
/*
* Local variables:
* mode: C
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index a604cd8..1198225 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -23,6 +23,7 @@
#include <xc_dom.h>
#include <xenguest.h>
#include <xen/hvm/hvm_info_table.h>
+#include <xen/hvm/e820.h>
int libxl__domain_create_info_setdefault(libxl__gc *gc,
libxl_domain_create_info *c_info)
@@ -102,6 +103,8 @@ static int sched_params_valid(libxl__gc *gc,
int libxl__domain_build_info_setdefault(libxl__gc *gc,
libxl_domain_build_info *b_info)
{
+ int i;
+
if (b_info->type != LIBXL_DOMAIN_TYPE_HVM &&
b_info->type != LIBXL_DOMAIN_TYPE_PV)
return ERROR_INVAL;
@@ -187,20 +190,21 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
} else if (b_info->avail_vcpus.size > HVM_MAX_VCPUS)
return ERROR_FAIL;
- if (!b_info->cpumap.size) {
- if (libxl_cpu_bitmap_alloc(CTX, &b_info->cpumap, 0))
- return ERROR_FAIL;
- libxl_bitmap_set_any(&b_info->cpumap);
+ /* In libxl internals, we want to deal with vcpu_hard_affinity only! */
+ if (b_info->cpumap.size && !b_info->num_vcpu_hard_affinity) {
+ b_info->vcpu_hard_affinity = libxl__calloc(gc, b_info->max_vcpus,
+ sizeof(libxl_bitmap));
+ for (i = 0; i < b_info->max_vcpus; i++) {
+ if (libxl_cpu_bitmap_alloc(CTX, &b_info->vcpu_hard_affinity[i], 0))
+ return ERROR_FAIL;
+ libxl_bitmap_copy(CTX, &b_info->vcpu_hard_affinity[i],
+ &b_info->cpumap);
+ }
+ b_info->num_vcpu_hard_affinity = b_info->max_vcpus;
}
libxl_defbool_setdefault(&b_info->numa_placement, true);
- if (!b_info->nodemap.size) {
- if (libxl_node_bitmap_alloc(CTX, &b_info->nodemap, 0))
- return ERROR_FAIL;
- libxl_bitmap_set_any(&b_info->nodemap);
- }
-
if (b_info->max_memkb == LIBXL_MEMKB_DEFAULT)
b_info->max_memkb = 32 * 1024;
if (b_info->target_memkb == LIBXL_MEMKB_DEFAULT)
@@ -212,6 +216,10 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
libxl_defbool_setdefault(&b_info->disable_migrate, false);
+ for (i = 0 ; i < b_info->num_iomem; i++)
+ if (b_info->iomem[i].gfn == LIBXL_INVALID_GFN)
+ b_info->iomem[i].gfn = b_info->iomem[i].start;
+
if (!b_info->event_channels)
b_info->event_channels = 1023;
@@ -219,6 +227,8 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
case LIBXL_DOMAIN_TYPE_HVM:
if (b_info->shadow_memkb == LIBXL_MEMKB_DEFAULT)
b_info->shadow_memkb = 0;
+ if (b_info->u.hvm.mmio_hole_memkb == LIBXL_MEMKB_DEFAULT)
+ b_info->u.hvm.mmio_hole_memkb = 0;
if (!b_info->u.hvm.vga.kind)
b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
@@ -226,6 +236,10 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
switch (b_info->device_model_version) {
case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
switch (b_info->u.hvm.vga.kind) {
+ case LIBXL_VGA_INTERFACE_TYPE_NONE:
+ if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT)
+ b_info->video_memkb = 0;
+ break;
case LIBXL_VGA_INTERFACE_TYPE_STD:
if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT)
b_info->video_memkb = 8 * 1024;
@@ -246,6 +260,10 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
default:
switch (b_info->u.hvm.vga.kind) {
+ case LIBXL_VGA_INTERFACE_TYPE_NONE:
+ if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT)
+ b_info->video_memkb = 0;
+ break;
case LIBXL_VGA_INTERFACE_TYPE_STD:
if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT)
b_info->video_memkb = 16 * 1024;
@@ -284,6 +302,13 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
libxl_defbool_setdefault(&b_info->u.hvm.usb, false);
libxl_defbool_setdefault(&b_info->u.hvm.xen_platform_pci, true);
+ libxl_defbool_setdefault(&b_info->u.hvm.spice.enable, false);
+ if (!libxl_defbool_val(b_info->u.hvm.spice.enable) &&
+ (b_info->u.hvm.spice.usbredirection > 0) ){
+ b_info->u.hvm.spice.usbredirection = 0;
+ LOG(WARN, "spice disabled, disabling usbredirection");
+ }
+
if (!b_info->u.hvm.usbversion &&
(b_info->u.hvm.spice.usbredirection > 0) )
b_info->u.hvm.usbversion = 2;
@@ -316,7 +341,6 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
libxl_defbool_setdefault(&b_info->u.hvm.sdl.opengl, false);
}
- libxl_defbool_setdefault(&b_info->u.hvm.spice.enable, false);
if (libxl_defbool_val(b_info->u.hvm.spice.enable)) {
libxl_defbool_setdefault(&b_info->u.hvm.spice.disable_ticketing,
false);
@@ -333,10 +357,31 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
break;
case LIBXL_DOMAIN_TYPE_PV:
libxl_defbool_setdefault(&b_info->u.pv.e820_host, false);
+ if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT)
+ b_info->video_memkb = 0;
if (b_info->shadow_memkb == LIBXL_MEMKB_DEFAULT)
b_info->shadow_memkb = 0;
if (b_info->u.pv.slack_memkb == LIBXL_MEMKB_DEFAULT)
b_info->u.pv.slack_memkb = 0;
+
+ /* For compatibility, fill in b_info->kernel|ramdisk|cmdline
+ * with the value in u.pv, later processing will use
+ * b_info->kernel|ramdisk|cmdline only.
+ * User with old APIs that passes u.pv.kernel|ramdisk|cmdline
+ * is not affected.
+ */
+ if (!b_info->kernel && b_info->u.pv.kernel) {
+ b_info->kernel = b_info->u.pv.kernel;
+ b_info->u.pv.kernel = NULL;
+ }
+ if (!b_info->ramdisk && b_info->u.pv.ramdisk) {
+ b_info->ramdisk = b_info->u.pv.ramdisk;
+ b_info->u.pv.ramdisk = NULL;
+ }
+ if (!b_info->cmdline && b_info->u.pv.cmdline) {
+ b_info->cmdline = b_info->u.pv.cmdline;
+ b_info->u.pv.cmdline = NULL;
+ }
break;
default:
LIBXL__LOG(CTX, LIBXL__LOG_ERROR,
@@ -347,15 +392,16 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
return 0;
}
-static int init_console_info(libxl__device_console *console, int dev_num)
+static void init_console_info(libxl__gc *gc,
+ libxl__device_console *console,
+ int dev_num)
{
- memset(console, 0x00, sizeof(libxl__device_console));
+ libxl__device_console_init(console);
console->devid = dev_num;
console->consback = LIBXL__CONSOLE_BACKEND_XENCONSOLED;
- console->output = strdup("pty");
- if (!console->output)
- return ERROR_NOMEM;
- return 0;
+ console->output = libxl__strdup(NOGC, "pty");
+ /* console->{name,connection,path} are NULL on normal consoles.
+ Only 'channels' when mapped to consoles have a string name. */
}
int libxl__domain_build(libxl__gc *gc,
@@ -388,13 +434,25 @@ int libxl__domain_build(libxl__gc *gc,
vments[4] = "start_time";
vments[5] = libxl__sprintf(gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
- localents = libxl__calloc(gc, 7, sizeof(char *));
- localents[0] = "platform/acpi";
- localents[1] = libxl_defbool_val(info->u.hvm.acpi) ? "1" : "0";
- localents[2] = "platform/acpi_s3";
- localents[3] = libxl_defbool_val(info->u.hvm.acpi_s3) ? "1" : "0";
- localents[4] = "platform/acpi_s4";
- localents[5] = libxl_defbool_val(info->u.hvm.acpi_s4) ? "1" : "0";
+ localents = libxl__calloc(gc, 9, sizeof(char *));
+ i = 0;
+ localents[i++] = "platform/acpi";
+ localents[i++] = libxl_defbool_val(info->u.hvm.acpi) ? "1" : "0";
+ localents[i++] = "platform/acpi_s3";
+ localents[i++] = libxl_defbool_val(info->u.hvm.acpi_s3) ? "1" : "0";
+ localents[i++] = "platform/acpi_s4";
+ localents[i++] = libxl_defbool_val(info->u.hvm.acpi_s4) ? "1" : "0";
+ if (info->u.hvm.mmio_hole_memkb) {
+ uint64_t max_ram_below_4g =
+ (1ULL << 32) - (info->u.hvm.mmio_hole_memkb << 10);
+
+ if (max_ram_below_4g <= HVM_BELOW_4G_MMIO_START) {
+ localents[i++] = "platform/mmio_hole_size";
+ localents[i++] =
+ libxl__sprintf(gc, "%"PRIu64,
+ info->u.hvm.mmio_hole_memkb << 10);
+ }
+ }
break;
case LIBXL_DOMAIN_TYPE_PV:
@@ -471,18 +529,18 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_create_info *info,
*domid = -1;
/* Ultimately, handle is an array of 16 uint8_t, same as uuid */
- libxl_uuid_copy((libxl_uuid *)handle, &info->uuid);
+ libxl_uuid_copy(ctx, (libxl_uuid *)handle, &info->uuid);
ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags, domid);
if (ret < 0) {
- LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "domain creation fail");
+ LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "domain creation fail");
rc = ERROR_FAIL;
goto out;
}
ret = xc_cpupool_movedomain(ctx->xch, info->poolid, *domid);
if (ret < 0) {
- LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "domain move fail");
+ LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "domain move fail");
rc = ERROR_FAIL;
goto out;
}
@@ -576,12 +634,7 @@ retry_transaction:
ARRAY_SIZE(rwperm));
}
- if (info->type == LIBXL_DOMAIN_TYPE_HVM)
- libxl__xs_mkdir(gc, t,
- libxl__sprintf(gc, "%s/hvmloader/generation-id-address", dom_path),
- rwperm, ARRAY_SIZE(rwperm));
-
- vm_list = libxl_list_vm(ctx, &nb_vm);
+ vm_list = libxl_list_vm(ctx, &nb_vm);
if (!vm_list) {
LOG(ERROR, "cannot get number of running guests");
rc = ERROR_FAIL;
@@ -716,6 +769,63 @@ static void initiate_domain_create(libxl__egc *egc,
domid = 0;
+ if (d_config->c_info.ssid_label) {
+ char *s = d_config->c_info.ssid_label;
+ ret = libxl_flask_context_to_sid(ctx, s, strlen(s),
+ &d_config->c_info.ssidref);
+ if (ret) {
+ if (errno == ENOSYS) {
+ LOG(WARN, "XSM Disabled: init_seclabel not supported");
+ ret = 0;
+ } else {
+ LOG(ERROR, "Invalid init_seclabel: %s", s);
+ goto error_out;
+ }
+ }
+ }
+
+ if (d_config->b_info.exec_ssid_label) {
+ char *s = d_config->b_info.exec_ssid_label;
+ ret = libxl_flask_context_to_sid(ctx, s, strlen(s),
+ &d_config->b_info.exec_ssidref);
+ if (ret) {
+ if (errno == ENOSYS) {
+ LOG(WARN, "XSM Disabled: seclabel not supported");
+ ret = 0;
+ } else {
+ LOG(ERROR, "Invalid seclabel: %s", s);
+ goto error_out;
+ }
+ }
+ }
+
+ if (d_config->b_info.device_model_ssid_label) {
+ char *s = d_config->b_info.device_model_ssid_label;
+ ret = libxl_flask_context_to_sid(ctx, s, strlen(s),
+ &d_config->b_info.device_model_ssidref);
+ if (ret) {
+ if (errno == ENOSYS) {
+ LOG(WARN,"XSM Disabled: device_model_stubdomain_seclabel not supported");
+ ret = 0;
+ } else {
+ LOG(ERROR, "Invalid device_model_stubdomain_seclabel: %s", s);
+ goto error_out;
+ }
+ }
+ }
+
+ if (d_config->c_info.pool_name) {
+ d_config->c_info.poolid = -1;
+ libxl_cpupool_qualifier_to_cpupoolid(ctx, d_config->c_info.pool_name,
+ &d_config->c_info.poolid,
+ NULL);
+ }
+ if (!libxl_cpupoolid_is_valid(ctx, d_config->c_info.poolid)) {
+ LOG(ERROR, "Illegal pool specified: %s", d_config->c_info.pool_name);
+ ret = ERROR_INVAL;
+ goto error_out;
+ }
+
/* If target_memkb is smaller than max_memkb, the subsequent call
* to libxc when building HVM domain will enable PoD mode.
*/
@@ -791,7 +901,7 @@ static void initiate_domain_create(libxl__egc *egc,
}
if (restore_fd >= 0) {
- LOG(DEBUG, "restoring, not running bootloader\n");
+ LOG(DEBUG, "restoring, not running bootloader");
domcreate_bootloader_done(egc, &dcs->bl, 0);
} else {
LOG(DEBUG, "running bootloader");
@@ -895,7 +1005,7 @@ static void domcreate_bootloader_done(libxl__egc *egc,
goto out;
}
libxl__xc_domain_restore(egc, dcs,
- hvm, pae, superpages, 1);
+ hvm, pae, superpages);
return;
out:
@@ -903,7 +1013,7 @@ static void domcreate_bootloader_done(libxl__egc *egc,
}
void libxl__srm_callout_callback_restore_results(unsigned long store_mfn,
- unsigned long console_mfn, unsigned long genidad, void *user)
+ unsigned long console_mfn, void *user)
{
libxl__save_helper_state *shs = user;
libxl__domain_create_state *dcs = CONTAINER_OF(shs, *dcs, shs);
@@ -912,7 +1022,6 @@ void libxl__srm_callout_callback_restore_results(unsigned long store_mfn,
state->store_mfn = store_mfn;
state->console_mfn = console_mfn;
- state->vm_generationid_addr = genidad;
shs->need_results = 0;
}
@@ -924,7 +1033,7 @@ void libxl__xc_domain_restore_done(libxl__egc *egc, void *dcs_void,
libxl_ctx *ctx = libxl__gc_owner(gc);
char **vments = NULL, **localents = NULL;
struct timeval start_time;
- int i, esave, flags;
+ int i, esave;
/* convenience aliases */
const uint32_t domid = dcs->guest_domid;
@@ -992,17 +1101,7 @@ out:
}
esave = errno;
-
- flags = fcntl(fd, F_GETFL);
- if (flags == -1) {
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unable to get flags on restore fd");
- } else {
- flags &= ~O_NONBLOCK;
- if (fcntl(fd, F_SETFL, flags) == -1)
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unable to put restore fd"
- " back to blocking mode");
- }
-
+ libxl_fd_set_nonblock(ctx, fd, 0);
errno = esave;
domcreate_rebuild_done(egc, dcs, ret);
}
@@ -1099,20 +1198,45 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev,
"failed give dom%d access to iomem range %"PRIx64"-%"PRIx64,
domid, io->start, io->start + io->number - 1);
ret = ERROR_FAIL;
+ continue;
}
+ ret = xc_domain_memory_mapping(CTX->xch, domid,
+ io->gfn, io->start,
+ io->number, 1);
+ if (ret < 0) {
+ LOGE(ERROR,
+ "failed to map to dom%d iomem range %"PRIx64"-%"PRIx64
+ " to guest address %"PRIx64,
+ domid, io->start, io->start + io->number - 1, io->gfn);
+ ret = ERROR_FAIL;
+ }
+ }
+
+ /* For both HVM and PV the 0th console is a regular console. We
+ map channels to IOEMU consoles starting at 1 */
+ for (i = 0; i < d_config->num_channels; i++) {
+ libxl__device_console console;
+ libxl__device device;
+ ret = libxl__init_console_from_channel(gc, &console, i + 1,
+ &d_config->channels[i]);
+ if ( ret ) {
+ libxl__device_console_dispose(&console);
+ goto error_out;
+ }
+ libxl__device_console_add(gc, domid, &console, NULL, &device);
+ libxl__device_console_dispose(&console);
}
switch (d_config->c_info.type) {
case LIBXL_DOMAIN_TYPE_HVM:
{
libxl__device_console console;
+ libxl__device device;
libxl_device_vkb vkb;
- ret = init_console_info(&console, 0);
- if ( ret )
- goto error_out;
+ init_console_info(gc, &console, 0);
console.backend_domid = state->console_domid;
- libxl__device_console_add(gc, domid, &console, state);
+ libxl__device_console_add(gc, domid, &console, state, &device);
libxl__device_console_dispose(&console);
libxl_device_vkb_init(&vkb);
@@ -1124,28 +1248,37 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev,
libxl__spawn_stub_dm(egc, &dcs->dmss);
else
libxl__spawn_local_dm(egc, &dcs->dmss.dm);
+
+ /*
+ * Handle the domain's (and the related stubdomain's) access to
+ * the VGA framebuffer.
+ */
+ ret = libxl__grant_vga_iomem_permission(gc, domid, d_config);
+ if ( ret )
+ goto error_out;
+
return;
}
case LIBXL_DOMAIN_TYPE_PV:
{
int need_qemu = 0;
libxl__device_console console;
+ libxl__device device;
for (i = 0; i < d_config->num_vfbs; i++) {
libxl__device_vfb_add(gc, domid, &d_config->vfbs[i]);
libxl__device_vkb_add(gc, domid, &d_config->vkbs[i]);
}
- ret = init_console_info(&console, 0);
- if ( ret )
- goto error_out;
+ init_console_info(gc, &console, 0);
need_qemu = libxl__need_xenpv_qemu(gc, 1, &console,
d_config->num_vfbs, d_config->vfbs,
- d_config->num_disks, &d_config->disks[0]);
+ d_config->num_disks, &d_config->disks[0],
+ d_config->num_channels, &d_config->channels[0]);
console.backend_domid = state->console_domid;
- libxl__device_console_add(gc, domid, &console, state);
+ libxl__device_console_add(gc, domid, &console, state, &device);
libxl__device_console_dispose(&console);
if (need_qemu) {
@@ -1262,8 +1395,14 @@ static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *multidev,
goto error_out;
}
- for (i = 0; i < d_config->num_pcidevs; i++)
- libxl__device_pci_add(gc, domid, &d_config->pcidevs[i], 1);
+ for (i = 0; i < d_config->num_pcidevs; i++) {
+ ret = libxl__device_pci_add(gc, domid, &d_config->pcidevs[i], 1);
+ if (ret < 0) {
+ LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+ "libxl_device_pci_add failed: %d", ret);
+ goto error_out;
+ }
+ }
if (d_config->num_pcidevs > 0) {
ret = libxl__create_pci_backend(gc, domid, d_config->pcidevs,
@@ -1291,10 +1430,30 @@ static void domcreate_complete(libxl__egc *egc,
{
STATE_AO_GC(dcs->ao);
libxl_domain_config *const d_config = dcs->guest_config;
+ libxl_domain_config *d_config_saved = &dcs->guest_config_saved;
if (!rc && d_config->b_info.exec_ssidref)
rc = xc_flask_relabel_domain(CTX->xch, dcs->guest_domid, d_config->b_info.exec_ssidref);
+ if (!rc) {
+ libxl__domain_userdata_lock *lock;
+
+ /* Note that we hold CTX lock at this point so only need to
+ * take data store lock
+ */
+ lock = libxl__lock_domain_userdata(gc, dcs->guest_domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ } else {
+ libxl__update_domain_configuration(gc, d_config_saved, d_config);
+ rc = libxl__set_domain_configuration(gc, dcs->guest_domid,
+ d_config_saved);
+ libxl__unlock_domain_userdata(lock);
+ }
+ }
+
+ libxl_domain_config_dispose(d_config_saved);
+
if (rc) {
if (dcs->guest_domid) {
dcs->dds.ao = ao;
@@ -1345,6 +1504,8 @@ static int do_domain_create(libxl_ctx *ctx, libxl_domain_config *d_config,
GCNEW(cdcs);
cdcs->dcs.ao = ao;
cdcs->dcs.guest_config = d_config;
+ libxl_domain_config_init(&cdcs->dcs.guest_config_saved);
+ libxl_domain_config_copy(ctx, &cdcs->dcs.guest_config_saved, d_config);
cdcs->dcs.restore_fd = restore_fd;
cdcs->dcs.callback = domain_create_cb;
cdcs->dcs.checkpointed_stream = checkpointed_stream;
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 29ed547..4b51ded 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -40,6 +40,24 @@ char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device)
device->domid, device->devid);
}
+/* Returns 1 if device exists, 0 if not, ERROR_* (<0) on error. */
+int libxl__device_exists(libxl__gc *gc, xs_transaction_t t,
+ libxl__device *device)
+{
+ int rc;
+ char *be_path = libxl__device_backend_path(gc, device);
+ const char *dir;
+
+ rc = libxl__xs_read_checked(gc, t, be_path, &dir);
+
+ if (rc)
+ return rc;
+
+ if (dir)
+ return 1;
+ return 0;
+}
+
int libxl__parse_backend_path(libxl__gc *gc,
const char *path,
libxl__device *dev)
@@ -265,12 +283,6 @@ int libxl__device_disk_set_backend(libxl__gc *gc, libxl_device_disk *disk) {
disk->vdev, disk->pdev_path);
return ERROR_INVAL;
}
- if (!S_ISBLK(a.stab.st_mode) &
- !S_ISREG(a.stab.st_mode)) {
- LOG(ERROR, "Disk vdev=%s phys path is not a block dev or file: %s",
- disk->vdev, disk->pdev_path);
- return ERROR_INVAL;
- }
}
if (disk->backend != LIBXL_DISK_BACKEND_UNKNOWN) {
@@ -430,7 +442,7 @@ void libxl__prepare_ao_device(libxl__ao *ao, libxl__ao_device *aodev)
aodev->rc = 0;
aodev->dev = NULL;
aodev->num_exec = 0;
- /* Initialize timer for QEMU Bodge and hotplug execution */
+ /* Initialize timer for QEMU Bodge */
libxl__ev_time_init(&aodev->timeout);
/*
* Initialize xs_watch, because it's not used on all possible
@@ -440,6 +452,7 @@ void libxl__prepare_ao_device(libxl__ao *ao, libxl__ao_device *aodev)
aodev->active = 1;
/* We init this here because we might call device_hotplug_done
* without actually calling any hotplug script */
+ libxl__async_exec_init(&aodev->aes);
libxl__ev_child_init(&aodev->child);
}
@@ -467,15 +480,12 @@ void libxl__multidev_begin(libxl__ao *ao, libxl__multidev *multidev)
multidev->preparation = libxl__multidev_prepare(multidev);
}
-static void multidev_one_callback(libxl__egc *egc, libxl__ao_device *aodev);
-
-libxl__ao_device *libxl__multidev_prepare(libxl__multidev *multidev) {
+void libxl__multidev_prepare_with_aodev(libxl__multidev *multidev,
+ libxl__ao_device *aodev) {
STATE_AO_GC(multidev->ao);
- libxl__ao_device *aodev;
- GCNEW(aodev);
aodev->multidev = multidev;
- aodev->callback = multidev_one_callback;
+ aodev->callback = libxl__multidev_one_callback;
libxl__prepare_ao_device(ao, aodev);
if (multidev->used >= multidev->allocd) {
@@ -483,11 +493,19 @@ libxl__ao_device *libxl__multidev_prepare(libxl__multidev *multidev) {
GCREALLOC_ARRAY(multidev->array, multidev->allocd);
}
multidev->array[multidev->used++] = aodev;
+}
+
+libxl__ao_device *libxl__multidev_prepare(libxl__multidev *multidev) {
+ STATE_AO_GC(multidev->ao);
+ libxl__ao_device *aodev;
+
+ GCNEW(aodev);
+ libxl__multidev_prepare_with_aodev(multidev, aodev);
return aodev;
}
-static void multidev_one_callback(libxl__egc *egc, libxl__ao_device *aodev)
+void libxl__multidev_one_callback(libxl__egc *egc, libxl__ao_device *aodev)
{
STATE_AO_GC(aodev->ao);
libxl__multidev *multidev = aodev->multidev;
@@ -511,7 +529,7 @@ void libxl__multidev_prepared(libxl__egc *egc,
libxl__multidev *multidev, int rc)
{
multidev->preparation->rc = rc;
- multidev_one_callback(egc, multidev->preparation);
+ libxl__multidev_one_callback(egc, multidev->preparation);
}
/******************************************************************************/
@@ -707,12 +725,9 @@ static void device_backend_cleanup(libxl__gc *gc,
static void device_hotplug(libxl__egc *egc, libxl__ao_device *aodev);
-static void device_hotplug_timeout_cb(libxl__egc *egc, libxl__ev_time *ev,
- const struct timeval *requested_abs);
-
static void device_hotplug_child_death_cb(libxl__egc *egc,
- libxl__ev_child *child,
- pid_t pid, int status);
+ libxl__async_exec_state *aes,
+ int status);
static void device_destroy_be_timeout_cb(libxl__egc *egc, libxl__ev_time *ev,
const struct timeval *requested_abs);
@@ -954,11 +969,11 @@ static void device_backend_cleanup(libxl__gc *gc, libxl__ao_device *aodev)
static void device_hotplug(libxl__egc *egc, libxl__ao_device *aodev)
{
STATE_AO_GC(aodev->ao);
+ libxl__async_exec_state *aes = &aodev->aes;
char *be_path = libxl__device_backend_path(gc, aodev->dev);
char **args = NULL, **env = NULL;
int rc = 0;
- int hotplug;
- pid_t pid;
+ int hotplug, nullfd = -1;
uint32_t domid;
/*
@@ -1010,66 +1025,46 @@ static void device_hotplug(libxl__egc *egc, libxl__ao_device *aodev)
goto out;
}
- /* Set hotplug timeout */
- rc = libxl__ev_time_register_rel(gc, &aodev->timeout,
- device_hotplug_timeout_cb,
- LIBXL_HOTPLUG_TIMEOUT * 1000);
- if (rc) {
- LOG(ERROR, "unable to register timeout for hotplug device %s", be_path);
- goto out;
- }
-
- aodev->what = GCSPRINTF("%s %s", args[0], args[1]);
LOG(DEBUG, "calling hotplug script: %s %s", args[0], args[1]);
- /* fork and execute hotplug script */
- pid = libxl__ev_child_fork(gc, &aodev->child, device_hotplug_child_death_cb);
- if (pid == -1) {
- LOG(ERROR, "unable to fork");
+ nullfd = open("/dev/null", O_RDONLY);
+ if (nullfd < 0) {
+ LOG(ERROR, "unable to open /dev/null for hotplug script");
rc = ERROR_FAIL;
goto out;
}
- if (!pid) {
- /* child */
- libxl__exec(gc, -1, -1, -1, args[0], args, env);
- /* notreached */
- abort();
- }
+ aes->ao = ao;
+ aes->what = GCSPRINTF("%s %s", args[0], args[1]);
+ aes->env = env;
+ aes->args = args;
+ aes->callback = device_hotplug_child_death_cb;
+ aes->timeout_ms = LIBXL_HOTPLUG_TIMEOUT * 1000;
+ aes->stdfds[0] = nullfd;
+ aes->stdfds[1] = 2;
+ aes->stdfds[2] = -1;
+
+ rc = libxl__async_exec_start(gc, aes);
+ if (rc)
+ goto out;
- assert(libxl__ev_child_inuse(&aodev->child));
+ close(nullfd);
+ assert(libxl__async_exec_inuse(&aodev->aes));
return;
out:
+ if (nullfd >= 0) close(nullfd);
aodev->rc = rc;
device_hotplug_done(egc, aodev);
return;
}
-static void device_hotplug_timeout_cb(libxl__egc *egc, libxl__ev_time *ev,
- const struct timeval *requested_abs)
-{
- libxl__ao_device *aodev = CONTAINER_OF(ev, *aodev, timeout);
- STATE_AO_GC(aodev->ao);
-
- libxl__ev_time_deregister(gc, &aodev->timeout);
-
- assert(libxl__ev_child_inuse(&aodev->child));
- LOG(DEBUG, "killing hotplug script %s because of timeout", aodev->what);
- if (kill(aodev->child.pid, SIGKILL)) {
- LOGEV(ERROR, errno, "unable to kill hotplug script %s [%ld]",
- aodev->what, (unsigned long)aodev->child.pid);
- }
-
- return;
-}
-
static void device_hotplug_child_death_cb(libxl__egc *egc,
- libxl__ev_child *child,
- pid_t pid, int status)
+ libxl__async_exec_state *aes,
+ int status)
{
- libxl__ao_device *aodev = CONTAINER_OF(child, *aodev, child);
+ libxl__ao_device *aodev = CONTAINER_OF(aes, *aodev, aes);
STATE_AO_GC(aodev->ao);
char *be_path = libxl__device_backend_path(gc, aodev->dev);
char *hotplug_error;
@@ -1077,8 +1072,6 @@ static void device_hotplug_child_death_cb(libxl__egc *egc,
device_hotplug_clean(gc, aodev);
if (status) {
- libxl_report_child_exitstatus(CTX, LIBXL__LOG_ERROR,
- aodev->what, pid, status);
hotplug_error = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/hotplug-error", be_path));
if (hotplug_error)
@@ -1170,7 +1163,7 @@ static void device_hotplug_clean(libxl__gc *gc, libxl__ao_device *aodev)
/* Clean events and check reentrancy */
libxl__ev_time_deregister(gc, &aodev->timeout);
libxl__ev_xswatch_deregister(gc, &aodev->xs_watch);
- assert(!libxl__ev_child_inuse(&aodev->child));
+ assert(!libxl__async_exec_inuse(&aodev->aes));
}
static void devices_remove_callback(libxl__egc *egc,
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index f6f7bbd..3e191c3 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -18,10 +18,11 @@
#include "libxl_osdeps.h" /* must come before any other headers */
#include "libxl_internal.h"
+#include <xen/hvm/e820.h>
static const char *libxl_tapif_script(libxl__gc *gc)
{
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
return libxl__strdup(gc, "no");
#else
return libxl__sprintf(gc, "%s/qemu-ifup", libxl__xen_script_dir_path());
@@ -38,7 +39,7 @@ static const char *qemu_xen_path(libxl__gc *gc)
#ifdef QEMU_XEN_PATH
return QEMU_XEN_PATH;
#else
- return libxl__abs_path(gc, "qemu-system-i386", libxl__libexec_path());
+ return libxl__abs_path(gc, "qemu-system-i386", libxl__private_bindir_path());
#endif
}
@@ -73,7 +74,7 @@ const char *libxl__domain_device_model(libxl__gc *gc,
} else {
switch (info->device_model_version) {
case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
- dm = libxl__abs_path(gc, "qemu-dm", libxl__libexec_path());
+ dm = libxl__abs_path(gc, "qemu-dm", libxl__private_bindir_path());
break;
case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
dm = qemu_xen_path(gc);
@@ -196,8 +197,31 @@ static char ** libxl__build_device_model_args_old(libxl__gc *gc,
int nr_set_cpus = 0;
char *s;
- if (b_info->u.hvm.serial) {
- flexarray_vappend(dm_args, "-serial", b_info->u.hvm.serial, NULL);
+ if (b_info->kernel) {
+ LOG(ERROR, "HVM direct kernel boot is not supported by "
+ "qemu-xen-traditional");
+ return NULL;
+ }
+
+ if (b_info->u.hvm.serial || b_info->u.hvm.serial_list) {
+ if ( b_info->u.hvm.serial && b_info->u.hvm.serial_list )
+ {
+ LOG(ERROR, "Both serial and serial_list set");
+ return NULL;
+ }
+ if (b_info->u.hvm.serial) {
+ flexarray_vappend(dm_args,
+ "-serial", b_info->u.hvm.serial, NULL);
+ } else if (b_info->u.hvm.serial_list) {
+ char **p;
+ for (p = b_info->u.hvm.serial_list;
+ *p;
+ p++) {
+ flexarray_vappend(dm_args,
+ "-serial",
+ *p, NULL);
+ }
+ }
}
if (libxl_defbool_val(b_info->u.hvm.nographic) && (!sdl && !vnc)) {
@@ -217,6 +241,9 @@ static char ** libxl__build_device_model_args_old(libxl__gc *gc,
break;
case LIBXL_VGA_INTERFACE_TYPE_CIRRUS:
break;
+ case LIBXL_VGA_INTERFACE_TYPE_NONE:
+ flexarray_append_pair(dm_args, "-vga", "none");
+ break;
}
if (b_info->u.hvm.boot) {
@@ -227,8 +254,7 @@ static char ** libxl__build_device_model_args_old(libxl__gc *gc,
|| b_info->u.hvm.usbdevice_list) {
if ( b_info->u.hvm.usbdevice && b_info->u.hvm.usbdevice_list )
{
- LOG(ERROR, "%s: Both usbdevice and usbdevice_list set",
- __func__);
+ LOG(ERROR, "Both usbdevice and usbdevice_list set");
return NULL;
}
flexarray_append(dm_args, "-usb");
@@ -378,7 +404,8 @@ static char *dm_spice_options(libxl__gc *gc,
static char ** libxl__build_device_model_args_new(libxl__gc *gc,
const char *dm, int guest_domid,
const libxl_domain_config *guest_config,
- const libxl__domain_build_state *state)
+ const libxl__domain_build_state *state,
+ int *dm_state_fd)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
const libxl_domain_create_info *c_info = &guest_config->c_info;
@@ -390,9 +417,11 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
const libxl_vnc_info *vnc = libxl__dm_vnc(guest_config);
const libxl_sdl_info *sdl = dm_sdl(guest_config);
const char *keymap = dm_keymap(guest_config);
+ char *machinearg;
flexarray_t *dm_args;
- int i;
+ int i, connection, devid;
uint64_t ram_size;
+ const char *path, *chardev;
dm_args = flexarray_make(gc, 16, 1);
@@ -409,10 +438,31 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
flexarray_append(dm_args, "-mon");
flexarray_append(dm_args, "chardev=libxl-cmd,mode=control");
+ for (i = 0; i < guest_config->num_channels; i++) {
+ connection = guest_config->channels[i].connection;
+ devid = guest_config->channels[i].devid;
+ switch (connection) {
+ case LIBXL_CHANNEL_CONNECTION_PTY:
+ chardev = GCSPRINTF("pty,id=libxl-channel%d", devid);
+ break;
+ case LIBXL_CHANNEL_CONNECTION_SOCKET:
+ path = guest_config->channels[i].u.socket.path;
+ chardev = GCSPRINTF("socket,id=libxl-channel%d,path=%s,"
+ "server,nowait", devid, path);
+ break;
+ default:
+ /* We've forgotten to add the clause */
+ LOG(ERROR, "%s: unknown channel connection %d",
+ __func__, connection);
+ return NULL;
+ }
+ flexarray_append(dm_args, "-chardev");
+ flexarray_append(dm_args, (void*)chardev);
+ }
+
/*
* Remove default devices created by qemu. Qemu will create only devices
* defined by xen, since the devices not defined by xen are not usable.
- * Remove deleting of empty floppy no more needed with nodefault.
*/
flexarray_append(dm_args, "-nodefaults");
@@ -470,10 +520,6 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
/* XXX sdl->{display,xauthority} into $DISPLAY/$XAUTHORITY */
}
- /*if (info->type == LIBXL_DOMAIN_TYPE_PV && !b_info->nographic) {
- flexarray_vappend(dm_args, "-vga", "xenfb", NULL);
- } never was possible?*/
-
if (keymap) {
flexarray_vappend(dm_args, "-k", keymap, NULL);
}
@@ -481,8 +527,25 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
if (b_info->type == LIBXL_DOMAIN_TYPE_HVM) {
int ioemu_nics = 0;
- if (b_info->u.hvm.serial) {
- flexarray_vappend(dm_args, "-serial", b_info->u.hvm.serial, NULL);
+ if (b_info->u.hvm.serial || b_info->u.hvm.serial_list) {
+ if ( b_info->u.hvm.serial && b_info->u.hvm.serial_list )
+ {
+ LOG(ERROR, "Both serial and serial_list set");
+ return NULL;
+ }
+ if (b_info->u.hvm.serial) {
+ flexarray_vappend(dm_args,
+ "-serial", b_info->u.hvm.serial, NULL);
+ } else if (b_info->u.hvm.serial_list) {
+ char **p;
+ for (p = b_info->u.hvm.serial_list;
+ *p;
+ p++) {
+ flexarray_vappend(dm_args,
+ "-serial",
+ *p, NULL);
+ }
+ }
}
if (libxl_defbool_val(b_info->u.hvm.nographic) && (!sdl && !vnc)) {
@@ -507,14 +570,17 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
switch (b_info->u.hvm.vga.kind) {
case LIBXL_VGA_INTERFACE_TYPE_STD:
- flexarray_append_pair(dm_args, "-device", "VGA");
+ flexarray_append_pair(dm_args, "-device",
+ GCSPRINTF("VGA,vgamem_mb=%d",
+ libxl__sizekb_to_mb(b_info->video_memkb)));
break;
case LIBXL_VGA_INTERFACE_TYPE_CIRRUS:
- flexarray_append_pair(dm_args, "-device", "cirrus-vga");
- flexarray_append_pair(dm_args, "-global",
- GCSPRINTF("vga.vram_size_mb=%d",
+ flexarray_append_pair(dm_args, "-device",
+ GCSPRINTF("cirrus-vga,vgamem_mb=%d",
libxl__sizekb_to_mb(b_info->video_memkb)));
break;
+ case LIBXL_VGA_INTERFACE_TYPE_NONE:
+ break;
}
if (b_info->u.hvm.boot) {
@@ -526,8 +592,7 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
|| b_info->u.hvm.usbdevice_list) {
if ( b_info->u.hvm.usbdevice && b_info->u.hvm.usbdevice_list )
{
- LOG(ERROR, "%s: Both usbdevice and usbdevice_list set",
- __func__);
+ LOG(ERROR, "Both usbdevice and usbdevice_list set");
return NULL;
}
flexarray_append(dm_args, "-usb");
@@ -564,8 +629,8 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
"-device", "nec-usb-xhci,id=usb", NULL);
break;
default:
- LOG(ERROR, "%s: usbversion parameter is invalid, "
- "must be between 1 and 3", __func__);
+ LOG(ERROR, "usbversion parameter is invalid, "
+ "must be between 1 and 3");
return NULL;
}
if (b_info->u.hvm.spice.usbredirection >= 0 &&
@@ -576,8 +641,8 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
libxl__sprintf(gc, "usb-redir,chardev=usbrc%d,"
"id=usbrc%d", i, i), NULL);
} else {
- LOG(ERROR, "%s: usbredirection parameter is invalid, "
- "it must be between 1 and 4", __func__);
+ LOG(ERROR, "usbredirection parameter is invalid, "
+ "it must be between 1 and 4");
return NULL;
}
}
@@ -638,9 +703,9 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
if (state->saved_state) {
/* This file descriptor is meant to be used by QEMU */
- int migration_fd = open(state->saved_state, O_RDONLY);
+ *dm_state_fd = open(state->saved_state, O_RDONLY);
flexarray_append(dm_args, "-incoming");
- flexarray_append(dm_args, libxl__sprintf(gc, "fd:%d", migration_fd));
+ flexarray_append(dm_args, GCSPRINTF("fd:%d",*dm_state_fd));
}
for (i = 0; b_info->extra && b_info->extra[i] != NULL; i++)
flexarray_append(dm_args, b_info->extra[i]);
@@ -657,10 +722,24 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
/* Switching here to the machine "pc" which does not add
* the xen-platform device instead of the default "xenfv" machine.
*/
- flexarray_append(dm_args, "pc,accel=xen");
+ machinearg = libxl__sprintf(gc, "pc,accel=xen");
} else {
- flexarray_append(dm_args, "xenfv");
+ machinearg = libxl__sprintf(gc, "xenfv");
+ }
+ if (b_info->u.hvm.mmio_hole_memkb) {
+ uint64_t max_ram_below_4g = (1ULL << 32) -
+ (b_info->u.hvm.mmio_hole_memkb << 10);
+
+ if (max_ram_below_4g > HVM_BELOW_4G_MMIO_START) {
+ LOG(WARN, "mmio_hole_memkb=%"PRIu64
+ " invalid ignored.\n",
+ b_info->u.hvm.mmio_hole_memkb);
+ } else {
+ machinearg = libxl__sprintf(gc, "%s,max-ram-below-4g=%"PRIu64,
+ machinearg, max_ram_below_4g);
+ }
}
+ flexarray_append(dm_args, machinearg);
for (i = 0; b_info->extra_hvm && b_info->extra_hvm[i] != NULL; i++)
flexarray_append(dm_args, b_info->extra_hvm[i]);
break;
@@ -679,6 +758,7 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
libxl__device_disk_dev_number(disks[i].vdev, &disk, &part);
const char *format = qemu_disk_format_string(disks[i].format);
char *drive;
+ const char *pdev_path;
if (dev_number == -1) {
LIBXL__LOG(ctx, LIBXL__LOG_WARNING, "unable to determine"
@@ -708,6 +788,12 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
continue;
}
+ if (disks[i].backend == LIBXL_DISK_BACKEND_TAP)
+ pdev_path = libxl__blktap_devpath(gc, disks[i].pdev_path,
+ disks[i].format);
+ else
+ pdev_path = disks[i].pdev_path;
+
/*
* Explicit sd disks are passed through as is.
*
@@ -717,11 +803,11 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
if (strncmp(disks[i].vdev, "sd", 2) == 0)
drive = libxl__sprintf
(gc, "file=%s,if=scsi,bus=0,unit=%d,format=%s,cache=writeback",
- disks[i].pdev_path, disk, format);
+ pdev_path, disk, format);
else if (disk < 4)
drive = libxl__sprintf
(gc, "file=%s,if=ide,index=%d,media=disk,format=%s,cache=writeback",
- disks[i].pdev_path, disk, format);
+ pdev_path, disk, format);
else
continue; /* Do not emulate this disk */
}
@@ -746,7 +832,10 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
static char ** libxl__build_device_model_args(libxl__gc *gc,
const char *dm, int guest_domid,
const libxl_domain_config *guest_config,
- const libxl__domain_build_state *state)
+ const libxl__domain_build_state *state,
+ int *dm_state_fd)
+/* dm_state_fd may be NULL iff caller knows we are using old stubdom
+ * and therefore will be passing a filename rather than a fd. */
{
libxl_ctx *ctx = libxl__gc_owner(gc);
@@ -756,9 +845,11 @@ static char ** libxl__build_device_model_args(libxl__gc *gc,
guest_domid, guest_config,
state);
case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
+ assert(dm_state_fd != NULL);
+ assert(*dm_state_fd < 0);
return libxl__build_device_model_args_new(gc, dm,
guest_domid, guest_config,
- state);
+ state, dm_state_fd);
default:
LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unknown device model version %d",
guest_config->b_info.device_model_version);
@@ -909,7 +1000,11 @@ void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state *sdss)
dm_config->c_info.type = LIBXL_DOMAIN_TYPE_PV;
dm_config->c_info.name = libxl__stub_dm_name(gc,
libxl__domid_to_name(gc, guest_domid));
+ /* When we are here to launch stubdom, ssidref is a valid value
+ * already, no need to parse it again.
+ */
dm_config->c_info.ssidref = guest_config->b_info.device_model_ssidref;
+ dm_config->c_info.ssid_label = NULL;
libxl_uuid_generate(&dm_config->c_info.uuid);
@@ -966,7 +1061,7 @@ void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state *sdss)
goto out;
args = libxl__build_device_model_args(gc, "stubdom-dm", guest_domid,
- guest_config, d_state);
+ guest_config, d_state, NULL);
if (!args) {
ret = ERROR_FAIL;
goto out;
@@ -1066,6 +1161,7 @@ static void spawn_stub_launch_dm(libxl__egc *egc,
}
for (i = 0; i < num_console; i++) {
+ libxl__device device;
console[i].devid = i;
console[i].consback = LIBXL__CONSOLE_BACKEND_IOEMU;
/* STUBDOM_CONSOLE_LOGGING (console 0) is for minios logging
@@ -1096,7 +1192,8 @@ static void spawn_stub_launch_dm(libxl__egc *egc,
break;
}
ret = libxl__device_console_add(gc, dm_domid, &console[i],
- i == STUBDOM_CONSOLE_LOGGING ? stubdom_state : NULL);
+ i == STUBDOM_CONSOLE_LOGGING ? stubdom_state : NULL,
+ &device);
if (ret)
goto out;
}
@@ -1218,6 +1315,7 @@ void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss)
char *vm_path;
char **pass_stuff;
const char *dm;
+ int dm_state_fd = -1;
if (libxl_defbool_val(b_info->device_model_stubdomain)) {
abort();
@@ -1234,7 +1332,8 @@ void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss)
rc = ERROR_FAIL;
goto out;
}
- args = libxl__build_device_model_args(gc, dm, domid, guest_config, state);
+ args = libxl__build_device_model_args(gc, dm, domid, guest_config, state,
+ &dm_state_fd);
if (!args) {
rc = ERROR_FAIL;
goto out;
@@ -1327,6 +1426,7 @@ out_close:
if (null >= 0) close(null);
if (logfile_w >= 0) close(logfile_w);
out:
+ if (dm_state_fd >= 0) close(dm_state_fd);
if (rc)
device_model_spawn_outcome(egc, dmss, rc);
}
@@ -1516,7 +1616,8 @@ int libxl__destroy_device_model(libxl__gc *gc, uint32_t domid)
int libxl__need_xenpv_qemu(libxl__gc *gc,
int nr_consoles, libxl__device_console *consoles,
int nr_vfbs, libxl_device_vfb *vfbs,
- int nr_disks, libxl_device_disk *disks)
+ int nr_disks, libxl_device_disk *disks,
+ int nr_channels, libxl_device_channel *channels)
{
int i, ret = 0;
uint32_t domid;
@@ -1556,6 +1657,20 @@ int libxl__need_xenpv_qemu(libxl__gc *gc,
}
}
+ if (nr_channels > 0) {
+ ret = libxl__get_domid(gc, &domid);
+ if (ret) goto out;
+ for (i = 0; i < nr_channels; i++) {
+ if (channels[i].backend_domid == domid) {
+ /* xenconsoled is limited to the first console only.
+ Until this restriction is removed we must use qemu for
+ secondary consoles which includes all channels. */
+ ret = 1;
+ goto out;
+ }
+ }
+ }
+
out:
return ret;
}
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 69e6088..74ea84b 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -23,6 +23,7 @@
#include <xc_dom.h>
#include <xen/hvm/hvm_info_table.h>
#include <xen/hvm/hvm_xs_strings.h>
+#include <xen/hvm/e820.h>
libxl_domain_type libxl__domain_type(libxl__gc *gc, uint32_t domid)
{
@@ -201,6 +202,103 @@ static int numa_place_domain(libxl__gc *gc, uint32_t domid,
return rc;
}
+static unsigned long timer_mode(const libxl_domain_build_info *info)
+{
+ const libxl_timer_mode mode = info->u.hvm.timer_mode;
+ assert(mode >= LIBXL_TIMER_MODE_DELAY_FOR_MISSED_TICKS &&
+ mode <= LIBXL_TIMER_MODE_ONE_MISSED_TICK_PENDING);
+ return ((unsigned long)mode);
+}
+
+#if defined(__i386__) || defined(__x86_64__)
+static int hvm_set_viridian_features(libxl__gc *gc, uint32_t domid,
+ libxl_domain_build_info *const info)
+{
+ libxl_bitmap enlightenments;
+ libxl_viridian_enlightenment v;
+ uint64_t mask = 0;
+
+ libxl_bitmap_init(&enlightenments);
+ libxl_bitmap_alloc(CTX, &enlightenments,
+ LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
+
+ if (libxl_defbool_val(info->u.hvm.viridian)) {
+ /* Enable defaults */
+ libxl_bitmap_set(&enlightenments, LIBXL_VIRIDIAN_ENLIGHTENMENT_BASE);
+ libxl_bitmap_set(&enlightenments, LIBXL_VIRIDIAN_ENLIGHTENMENT_FREQ);
+ libxl_bitmap_set(&enlightenments, LIBXL_VIRIDIAN_ENLIGHTENMENT_TIME_REF_COUNT);
+ }
+
+ libxl_for_each_set_bit(v, info->u.hvm.viridian_enable) {
+ if (libxl_bitmap_test(&info->u.hvm.viridian_disable, v)) {
+ LIBXL__LOG(CTX, LIBXL__LOG_ERROR, "%s group both enabled and disabled",
+ libxl_viridian_enlightenment_to_string(v));
+ goto err;
+ }
+ if (libxl_viridian_enlightenment_to_string(v)) /* check validity */
+ libxl_bitmap_set(&enlightenments, v);
+ }
+
+ libxl_for_each_set_bit(v, info->u.hvm.viridian_disable)
+ if (libxl_viridian_enlightenment_to_string(v)) /* check validity */
+ libxl_bitmap_reset(&enlightenments, v);
+
+ /* The base set is a pre-requisite for all others */
+ if (!libxl_bitmap_is_empty(&enlightenments) &&
+ !libxl_bitmap_test(&enlightenments, LIBXL_VIRIDIAN_ENLIGHTENMENT_BASE)) {
+ LIBXL__LOG(CTX, LIBXL__LOG_ERROR, "base group not enabled");
+ goto err;
+ }
+
+ libxl_for_each_set_bit(v, enlightenments)
+ LOG(DETAIL, "%s group enabled", libxl_viridian_enlightenment_to_string(v));
+
+ if (libxl_bitmap_test(&enlightenments, LIBXL_VIRIDIAN_ENLIGHTENMENT_BASE)) {
+ mask |= HVMPV_base_freq;
+
+ if (!libxl_bitmap_test(&enlightenments, LIBXL_VIRIDIAN_ENLIGHTENMENT_FREQ))
+ mask |= HVMPV_no_freq;
+ }
+
+ if (libxl_bitmap_test(&enlightenments, LIBXL_VIRIDIAN_ENLIGHTENMENT_TIME_REF_COUNT))
+ mask |= HVMPV_time_ref_count;
+
+ if (mask != 0 &&
+ xc_hvm_param_set(CTX->xch,
+ domid,
+ HVM_PARAM_VIRIDIAN,
+ mask) != 0) {
+ LIBXL__LOG_ERRNO(CTX, LIBXL__LOG_ERROR,
+ "Couldn't set viridian feature mask (0x%"PRIx64")",
+ mask);
+ goto err;
+ }
+
+ libxl_bitmap_dispose(&enlightenments);
+ return 0;
+
+err:
+ libxl_bitmap_dispose(&enlightenments);
+ return ERROR_FAIL;
+}
+#endif
+
+static void hvm_set_conf_params(xc_interface *handle, uint32_t domid,
+ libxl_domain_build_info *const info)
+{
+ xc_hvm_param_set(handle, domid, HVM_PARAM_PAE_ENABLED,
+ libxl_defbool_val(info->u.hvm.pae));
+#if defined(__i386__) || defined(__x86_64__)
+ xc_hvm_param_set(handle, domid, HVM_PARAM_HPET_ENABLED,
+ libxl_defbool_val(info->u.hvm.hpet));
+#endif
+ xc_hvm_param_set(handle, domid, HVM_PARAM_TIMER_MODE, timer_mode(info));
+ xc_hvm_param_set(handle, domid, HVM_PARAM_VPT_ALIGN,
+ libxl_defbool_val(info->u.hvm.vpt_align));
+ xc_hvm_param_set(handle, domid, HVM_PARAM_NESTEDHVM,
+ libxl_defbool_val(info->u.hvm.nested_hvm));
+}
+
int libxl__build_pre(libxl__gc *gc, uint32_t domid,
libxl_domain_config *d_config, libxl__domain_build_state *state)
{
@@ -215,27 +313,97 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
}
/*
- * Check if the domain has any CPU affinity. If not, try to build
- * up one. In case numa_place_domain() find at least a suitable
- * candidate, it will affect info->nodemap accordingly; if it
- * does not, it just leaves it as it is. This means (unless
- * some weird error manifests) the subsequent call to
- * libxl_domain_set_nodeaffinity() will do the actual placement,
- * whatever that turns out to be.
+ * Check if the domain has any CPU or node affinity already. If not, try
+ * to build up the latter via automatic NUMA placement. In fact, in case
+ * numa_place_domain() manage to find a placement, in info->nodemap is
+ * updated accordingly; if it does not manage, info->nodemap is just left
+ * alone. It is then the the subsequent call to
+ * libxl_domain_set_nodeaffinity() that enacts the actual placement.
+ *
+ * As far as scheduling is concerned, we achieve NUMA-aware scheduling
+ * by having the results of placement affect the soft affinity of all
+ * the vcpus of the domain. Of course, we want that iff placement is
+ * enabled and actually happens, so we only change info->cpumap_soft to
+ * reflect the placement result if that is the case
*/
if (libxl_defbool_val(info->numa_placement)) {
- if (!libxl_bitmap_is_full(&info->cpumap)) {
+ libxl_bitmap cpumap_soft;
+
+ if (info->cpumap.size ||
+ info->num_vcpu_hard_affinity || info->num_vcpu_soft_affinity) {
LOG(ERROR, "Can run NUMA placement only if no vcpu "
- "affinity is specified");
+ "(hard or soft) affinity is specified explicitly");
+ return ERROR_INVAL;
+ }
+ if (info->nodemap.size) {
+ LOG(ERROR, "Can run NUMA placement only if the domain does not "
+ "have any NUMA node affinity set already");
return ERROR_INVAL;
}
- rc = numa_place_domain(gc, domid, info);
+ rc = libxl_node_bitmap_alloc(ctx, &info->nodemap, 0);
if (rc)
return rc;
+ libxl_bitmap_set_any(&info->nodemap);
+
+ rc = libxl_cpu_bitmap_alloc(ctx, &cpumap_soft, 0);
+ if (rc)
+ return rc;
+
+ rc = numa_place_domain(gc, domid, info);
+ if (rc) {
+ libxl_bitmap_dispose(&cpumap_soft);
+ return rc;
+ }
+
+ /*
+ * All we need to do now is converting the result of automatic
+ * placement from nodemap to cpumap, and then use such cpumap as
+ * the soft affinity for all the vcpus of the domain.
+ *
+ * When calling libxl_set_vcpuaffinity_all(), it is ok to use NULL
+ * as hard affinity, as we know we don't have one, or we won't be
+ * here.
+ */
+ libxl_nodemap_to_cpumap(ctx, &info->nodemap, &cpumap_soft);
+ libxl_set_vcpuaffinity_all(ctx, domid, info->max_vcpus,
+ NULL, &cpumap_soft);
+
+ libxl_bitmap_dispose(&cpumap_soft);
+ }
+ if (info->nodemap.size)
+ libxl_domain_set_nodeaffinity(ctx, domid, &info->nodemap);
+ /* As mentioned in libxl.h, vcpu_hard_array takes precedence */
+ if (info->num_vcpu_hard_affinity || info->num_vcpu_soft_affinity) {
+ libxl_bitmap *hard_affinity, *soft_affinity;
+ int i, n_vcpus;
+
+ n_vcpus = info->num_vcpu_hard_affinity > info->num_vcpu_soft_affinity ?
+ info->num_vcpu_hard_affinity : info->num_vcpu_soft_affinity;
+
+ for (i = 0; i < n_vcpus; i++) {
+ /*
+ * Prepare hard and soft affinity pointers in a way that allows
+ * us to issue only one call to libxl_set_vcpuaffinity(), setting,
+ * for each vcpu, both hard and soft affinity "atomically".
+ */
+ hard_affinity = NULL;
+ if (info->num_vcpu_hard_affinity &&
+ i < info->num_vcpu_hard_affinity)
+ hard_affinity = &info->vcpu_hard_affinity[i];
+
+ soft_affinity = NULL;
+ if (info->num_vcpu_soft_affinity &&
+ i < info->num_vcpu_soft_affinity)
+ soft_affinity = &info->vcpu_soft_affinity[i];
+
+ if (libxl_set_vcpuaffinity(ctx, domid, i,
+ hard_affinity, soft_affinity)) {
+ LOG(ERROR, "setting affinity failed on vcpu `%d'", i);
+ return ERROR_FAIL;
+ }
+ }
}
- libxl_domain_set_nodeaffinity(ctx, domid, &info->nodemap);
- libxl_set_vcpuaffinity_all(ctx, domid, info->max_vcpus, &info->cpumap);
if (xc_domain_setmaxmem(ctx->xch, domid, info->target_memkb +
LIBXL_MAXMEM_CONSTANT) < 0) {
@@ -253,7 +421,15 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
state->store_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->store_domid);
state->console_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->console_domid);
- state->vm_generationid_addr = 0;
+
+ if (info->type == LIBXL_DOMAIN_TYPE_HVM) {
+ hvm_set_conf_params(ctx->xch, domid, info);
+#if defined(__i386__) || defined(__x86_64__)
+ rc = hvm_set_viridian_features(gc, domid, info);
+ if (rc)
+ return rc;
+#endif
+ }
rc = libxl__arch_domain_create(gc, d_config, domid);
@@ -268,7 +444,7 @@ int libxl__build_post(libxl__gc *gc, uint32_t domid,
libxl_ctx *ctx = libxl__gc_owner(gc);
char *dom_path, *vm_path;
xs_transaction_t t;
- char **ents, **hvm_ents;
+ char **ents;
int i, rc;
rc = libxl_domain_sched_params_set(CTX, domid, &info->sched_params);
@@ -286,6 +462,16 @@ int libxl__build_post(libxl__gc *gc, uint32_t domid,
if (info->cpuid != NULL)
libxl_cpuid_set(ctx, domid, info->cpuid);
+ if (info->type == LIBXL_DOMAIN_TYPE_HVM
+ && !libxl_ms_vm_genid_is_zero(&info->u.hvm.ms_vm_genid)) {
+ rc = libxl__ms_vm_genid_set(gc, domid,
+ &info->u.hvm.ms_vm_genid);
+ if (rc) {
+ LOG(ERROR, "Failed to set VM Generation ID");
+ return rc;
+ }
+ }
+
ents = libxl__calloc(gc, 12 + (info->max_vcpus * 2) + 2, sizeof(char *));
ents[0] = "memory/static-max";
ents[1] = GCSPRINTF("%"PRId64, info->max_memkb);
@@ -305,13 +491,6 @@ int libxl__build_post(libxl__gc *gc, uint32_t domid,
? "online" : "offline";
}
- hvm_ents = NULL;
- if (info->type == LIBXL_DOMAIN_TYPE_HVM) {
- hvm_ents = libxl__calloc(gc, 3, sizeof(char *));
- hvm_ents[0] = "hvmloader/generation-id-address";
- hvm_ents[1] = GCSPRINTF("0x%lx", state->vm_generationid_addr);
- }
-
dom_path = libxl__xs_get_dompath(gc, domid);
if (!dom_path) {
return ERROR_FAIL;
@@ -322,9 +501,6 @@ retry_transaction:
t = xs_transaction_start(ctx->xsh);
libxl__xs_writev(gc, t, dom_path, ents);
- if (info->type == LIBXL_DOMAIN_TYPE_HVM)
- libxl__xs_writev(gc, t, dom_path, hvm_ents);
-
libxl__xs_writev(gc, t, dom_path, local_ents);
libxl__xs_writev(gc, t, vm_path, vms_ents);
@@ -453,13 +629,6 @@ out:
return ret == 0 ? 0 : ERROR_FAIL;
}
-static unsigned long timer_mode(const libxl_domain_build_info *info)
-{
- const libxl_timer_mode mode = info->u.hvm.timer_mode;
- assert(mode >= LIBXL_TIMER_MODE_DELAY_FOR_MISSED_TICKS &&
- mode <= LIBXL_TIMER_MODE_ONE_MISSED_TICK_PENDING);
- return ((unsigned long)mode);
-}
static int hvm_build_set_params(xc_interface *handle, uint32_t domid,
libxl_domain_build_info *info,
int store_evtchn, unsigned long *store_mfn,
@@ -468,6 +637,7 @@ static int hvm_build_set_params(xc_interface *handle, uint32_t domid,
{
struct hvm_info_table *va_hvm;
uint8_t *va_map, sum;
+ uint64_t str_mfn, cons_mfn;
int i;
va_map = xc_map_foreign_range(handle, domid,
@@ -486,23 +656,13 @@ static int hvm_build_set_params(xc_interface *handle, uint32_t domid,
va_hvm->checksum -= sum;
munmap(va_map, XC_PAGE_SIZE);
- xc_get_hvm_param(handle, domid, HVM_PARAM_STORE_PFN, store_mfn);
- xc_get_hvm_param(handle, domid, HVM_PARAM_CONSOLE_PFN, console_mfn);
- xc_set_hvm_param(handle, domid, HVM_PARAM_PAE_ENABLED,
- libxl_defbool_val(info->u.hvm.pae));
-#if defined(__i386__) || defined(__x86_64__)
- xc_set_hvm_param(handle, domid, HVM_PARAM_VIRIDIAN,
- libxl_defbool_val(info->u.hvm.viridian));
- xc_set_hvm_param(handle, domid, HVM_PARAM_HPET_ENABLED,
- libxl_defbool_val(info->u.hvm.hpet));
-#endif
- xc_set_hvm_param(handle, domid, HVM_PARAM_TIMER_MODE, timer_mode(info));
- xc_set_hvm_param(handle, domid, HVM_PARAM_VPT_ALIGN,
- libxl_defbool_val(info->u.hvm.vpt_align));
- xc_set_hvm_param(handle, domid, HVM_PARAM_NESTEDHVM,
- libxl_defbool_val(info->u.hvm.nested_hvm));
- xc_set_hvm_param(handle, domid, HVM_PARAM_STORE_EVTCHN, store_evtchn);
- xc_set_hvm_param(handle, domid, HVM_PARAM_CONSOLE_EVTCHN, console_evtchn);
+ xc_hvm_param_get(handle, domid, HVM_PARAM_STORE_PFN, &str_mfn);
+ xc_hvm_param_get(handle, domid, HVM_PARAM_CONSOLE_PFN, &cons_mfn);
+ xc_hvm_param_set(handle, domid, HVM_PARAM_STORE_EVTCHN, store_evtchn);
+ xc_hvm_param_set(handle, domid, HVM_PARAM_CONSOLE_EVTCHN, console_evtchn);
+
+ *store_mfn = str_mfn;
+ *console_mfn = cons_mfn;
xc_dom_gnttab_hvm_seed(handle, domid, *console_mfn, *store_mfn, console_domid, store_domid);
return 0;
@@ -641,6 +801,13 @@ int libxl__build_hvm(libxl__gc *gc, uint32_t domid,
args.mem_size = (uint64_t)(info->max_memkb - info->video_memkb) << 10;
args.mem_target = (uint64_t)(info->target_memkb - info->video_memkb) << 10;
args.claim_enabled = libxl_defbool_val(info->claim_mode);
+ if (info->u.hvm.mmio_hole_memkb) {
+ uint64_t max_ram_below_4g = (1ULL << 32) -
+ (info->u.hvm.mmio_hole_memkb << 10);
+
+ if (max_ram_below_4g < HVM_BELOW_4G_MMIO_START)
+ args.mmio_size = info->u.hvm.mmio_hole_memkb << 10;
+ }
if (libxl__domain_firmware(gc, info, &args)) {
LOG(ERROR, "initializing domain firmware failed");
goto out;
@@ -759,6 +926,8 @@ int libxl__toolstack_restore(uint32_t domid, const uint8_t *buf,
static void domain_suspend_done(libxl__egc *egc,
libxl__domain_suspend_state *dss, int rc);
+static void domain_suspend_callback_common_done(libxl__egc *egc,
+ libxl__domain_suspend_state *dss, int ok);
/*----- complicated callback, called by xc_domain_save -----*/
@@ -1024,40 +1193,69 @@ int libxl__domain_resume_device_model(libxl__gc *gc, uint32_t domid)
return 0;
}
-int libxl__domain_suspend_common_callback(void *user)
+static void domain_suspend_common_wait_guest(libxl__egc *egc,
+ libxl__domain_suspend_state *dss);
+static void domain_suspend_common_guest_suspended(libxl__egc *egc,
+ libxl__domain_suspend_state *dss);
+
+static void domain_suspend_common_pvcontrol_suspending(libxl__egc *egc,
+ libxl__xswait_state *xswa, int rc, const char *state);
+static void domain_suspend_common_wait_guest_evtchn(libxl__egc *egc,
+ libxl__ev_evtchn *evev);
+static void suspend_common_wait_guest_watch(libxl__egc *egc,
+ libxl__ev_xswatch *xsw, const char *watch_path, const char *event_path);
+static void suspend_common_wait_guest_check(libxl__egc *egc,
+ libxl__domain_suspend_state *dss);
+static void suspend_common_wait_guest_timeout(libxl__egc *egc,
+ libxl__ev_time *ev, const struct timeval *requested_abs);
+
+static void domain_suspend_common_failed(libxl__egc *egc,
+ libxl__domain_suspend_state *dss);
+static void domain_suspend_common_done(libxl__egc *egc,
+ libxl__domain_suspend_state *dss,
+ bool ok);
+
+static bool domain_suspend_pvcontrol_acked(const char *state) {
+ /* any value other than "suspend", including ENOENT (i.e. !state), is OK */
+ if (!state) return 1;
+ return strcmp(state,"suspend");
+}
+
+/* calls dss->callback_common_done when done */
+static void domain_suspend_callback_common(libxl__egc *egc,
+ libxl__domain_suspend_state *dss)
{
- libxl__save_helper_state *shs = user;
- libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
STATE_AO_GC(dss->ao);
- unsigned long hvm_s_state = 0, hvm_pvdrv = 0;
- int ret;
- char *state = "suspend";
- int watchdog;
- xs_transaction_t t;
+ uint64_t hvm_s_state = 0, hvm_pvdrv = 0;
+ int ret, rc;
/* Convenience aliases */
const uint32_t domid = dss->domid;
if (dss->hvm) {
- xc_get_hvm_param(CTX->xch, domid, HVM_PARAM_CALLBACK_IRQ, &hvm_pvdrv);
- xc_get_hvm_param(CTX->xch, domid, HVM_PARAM_ACPI_S_STATE, &hvm_s_state);
+ xc_hvm_param_get(CTX->xch, domid, HVM_PARAM_CALLBACK_IRQ, &hvm_pvdrv);
+ xc_hvm_param_get(CTX->xch, domid, HVM_PARAM_ACPI_S_STATE, &hvm_s_state);
}
- if ((hvm_s_state == 0) && (dss->suspend_eventchn >= 0)) {
+ if ((hvm_s_state == 0) && (dss->guest_evtchn.port >= 0)) {
LOG(DEBUG, "issuing %s suspend request via event channel",
dss->hvm ? "PVHVM" : "PV");
- ret = xc_evtchn_notify(dss->xce, dss->suspend_eventchn);
+ ret = xc_evtchn_notify(CTX->xce, dss->guest_evtchn.port);
if (ret < 0) {
LOG(ERROR, "xc_evtchn_notify failed ret=%d", ret);
- return 0;
- }
- ret = xc_await_suspend(CTX->xch, dss->xce, dss->suspend_eventchn);
- if (ret < 0) {
- LOG(ERROR, "xc_await_suspend failed ret=%d", ret);
- return 0;
+ goto err;
}
- dss->guest_responded = 1;
- goto guest_suspended;
+
+ dss->guest_evtchn.callback = domain_suspend_common_wait_guest_evtchn;
+ rc = libxl__ev_evtchn_wait(gc, &dss->guest_evtchn);
+ if (rc) goto err;
+
+ rc = libxl__ev_time_register_rel(gc, &dss->guest_timeout,
+ suspend_common_wait_guest_timeout,
+ 60*1000);
+ if (rc) goto err;
+
+ return;
}
if (dss->hvm && (!hvm_pvdrv || hvm_s_state)) {
@@ -1065,27 +1263,60 @@ int libxl__domain_suspend_common_callback(void *user)
ret = xc_domain_shutdown(CTX->xch, domid, SHUTDOWN_suspend);
if (ret < 0) {
LOGE(ERROR, "xc_domain_shutdown failed");
- return 0;
+ goto err;
}
/* The guest does not (need to) respond to this sort of request. */
dss->guest_responded = 1;
- } else {
- LOG(DEBUG, "issuing %s suspend request via XenBus control node",
- dss->hvm ? "PVHVM" : "PV");
+ domain_suspend_common_wait_guest(egc, dss);
+ return;
+ }
- libxl__domain_pvcontrol_write(gc, XBT_NULL, domid, "suspend");
+ LOG(DEBUG, "issuing %s suspend request via XenBus control node",
+ dss->hvm ? "PVHVM" : "PV");
- LOG(DEBUG, "wait for the guest to acknowledge suspend request");
- watchdog = 60;
- while (!strcmp(state, "suspend") && watchdog > 0) {
- usleep(100000);
+ libxl__domain_pvcontrol_write(gc, XBT_NULL, domid, "suspend");
- state = libxl__domain_pvcontrol_read(gc, XBT_NULL, domid);
- if (!state) state = "";
+ dss->pvcontrol.path = libxl__domain_pvcontrol_xspath(gc, domid);
+ if (!dss->pvcontrol.path) goto err;
- watchdog--;
- }
+ dss->pvcontrol.ao = ao;
+ dss->pvcontrol.what = "guest acknowledgement of suspend request";
+ dss->pvcontrol.timeout_ms = 60 * 1000;
+ dss->pvcontrol.callback = domain_suspend_common_pvcontrol_suspending;
+ libxl__xswait_start(gc, &dss->pvcontrol);
+ return;
+
+ err:
+ domain_suspend_common_failed(egc, dss);
+}
+
+static void domain_suspend_common_wait_guest_evtchn(libxl__egc *egc,
+ libxl__ev_evtchn *evev)
+{
+ libxl__domain_suspend_state *dss = CONTAINER_OF(evev, *dss, guest_evtchn);
+ STATE_AO_GC(dss->ao);
+ /* If we should be done waiting, suspend_common_wait_guest_check
+ * will end up calling domain_suspend_common_guest_suspended or
+ * domain_suspend_common_failed, both of which cancel the evtchn
+ * wait. So re-enable it now. */
+ libxl__ev_evtchn_wait(gc, &dss->guest_evtchn);
+ suspend_common_wait_guest_check(egc, dss);
+}
+static void domain_suspend_common_pvcontrol_suspending(libxl__egc *egc,
+ libxl__xswait_state *xswa, int rc, const char *state)
+{
+ libxl__domain_suspend_state *dss = CONTAINER_OF(xswa, *dss, pvcontrol);
+ STATE_AO_GC(dss->ao);
+ xs_transaction_t t = 0;
+
+ if (!rc && !domain_suspend_pvcontrol_acked(state))
+ /* keep waiting */
+ return;
+
+ libxl__xswait_stop(gc, &dss->pvcontrol);
+
+ if (rc == ERROR_TIMEDOUT) {
/*
* Guest appears to not be responding. Cancel the suspend
* request.
@@ -1095,71 +1326,166 @@ int libxl__domain_suspend_common_callback(void *user)
* against the guest catching up and acknowledging the request
* at the last minute.
*/
- if (!strcmp(state, "suspend")) {
- LOG(ERROR, "guest didn't acknowledge suspend, cancelling request");
- retry_transaction:
- t = xs_transaction_start(CTX->xsh);
+ for (;;) {
+ rc = libxl__xs_transaction_start(gc, &t);
+ if (rc) goto err;
- state = libxl__domain_pvcontrol_read(gc, t, domid);
- if (!state) state = "";
+ rc = libxl__xs_read_checked(gc, t, xswa->path, &state);
+ if (rc) goto err;
- if (!strcmp(state, "suspend"))
- libxl__domain_pvcontrol_write(gc, t, domid, "");
+ if (domain_suspend_pvcontrol_acked(state))
+ /* last minute ack */
+ break;
- if (!xs_transaction_end(CTX->xsh, t, 0))
- if (errno == EAGAIN)
- goto retry_transaction;
+ rc = libxl__xs_write_checked(gc, t, xswa->path, "");
+ if (rc) goto err;
+ rc = libxl__xs_transaction_commit(gc, &t);
+ if (!rc) {
+ LOG(ERROR,
+ "guest didn't acknowledge suspend, cancelling request");
+ goto err;
+ }
+ if (rc<0) goto err;
}
+ } else if (rc) {
+ /* some error in xswait's read of xenstore, already logged */
+ goto err;
+ }
- /*
- * Final check for guest acknowledgement. The guest may have
- * acknowledged while we were cancelling the request in which
- * case we lost the race while cancelling and should continue.
- */
- if (!strcmp(state, "suspend")) {
- LOG(ERROR, "guest didn't acknowledge suspend, request cancelled");
- return 0;
- }
+ assert(domain_suspend_pvcontrol_acked(state));
+ LOG(DEBUG, "guest acknowledged suspend request");
- LOG(DEBUG, "guest acknowledged suspend request");
- dss->guest_responded = 1;
- }
+ libxl__xs_transaction_abort(gc, &t);
+ dss->guest_responded = 1;
+ domain_suspend_common_wait_guest(egc,dss);
+ return;
+
+ err:
+ libxl__xs_transaction_abort(gc, &t);
+ domain_suspend_common_failed(egc, dss);
+ return;
+}
+
+static void domain_suspend_common_wait_guest(libxl__egc *egc,
+ libxl__domain_suspend_state *dss)
+{
+ STATE_AO_GC(dss->ao);
+ int rc;
LOG(DEBUG, "wait for the guest to suspend");
- watchdog = 60;
- while (watchdog > 0) {
- xc_domaininfo_t info;
-
- usleep(100000);
- ret = xc_domain_getinfolist(CTX->xch, domid, 1, &info);
- if (ret == 1 && info.domain == domid &&
- (info.flags & XEN_DOMINF_shutdown)) {
- int shutdown_reason;
-
- shutdown_reason = (info.flags >> XEN_DOMINF_shutdownshift)
- & XEN_DOMINF_shutdownmask;
- if (shutdown_reason == SHUTDOWN_suspend) {
- LOG(DEBUG, "guest has suspended");
- goto guest_suspended;
- }
- }
- watchdog--;
+ rc = libxl__ev_xswatch_register(gc, &dss->guest_watch,
+ suspend_common_wait_guest_watch,
+ "@releaseDomain");
+ if (rc) goto err;
+
+ rc = libxl__ev_time_register_rel(gc, &dss->guest_timeout,
+ suspend_common_wait_guest_timeout,
+ 60*1000);
+ if (rc) goto err;
+ return;
+
+ err:
+ domain_suspend_common_failed(egc, dss);
+}
+
+static void suspend_common_wait_guest_watch(libxl__egc *egc,
+ libxl__ev_xswatch *xsw, const char *watch_path, const char *event_path)
+{
+ libxl__domain_suspend_state *dss = CONTAINER_OF(xsw, *dss, guest_watch);
+ suspend_common_wait_guest_check(egc, dss);
+}
+
+static void suspend_common_wait_guest_check(libxl__egc *egc,
+ libxl__domain_suspend_state *dss)
+{
+ STATE_AO_GC(dss->ao);
+ xc_domaininfo_t info;
+ int ret;
+ int shutdown_reason;
+
+ /* Convenience aliases */
+ const uint32_t domid = dss->domid;
+
+ ret = xc_domain_getinfolist(CTX->xch, domid, 1, &info);
+ if (ret < 0) {
+ LOGE(ERROR, "unable to check for status of guest %"PRId32"", domid);
+ goto err;
+ }
+
+ if (!(ret == 1 && info.domain == domid)) {
+ LOGE(ERROR, "guest %"PRId32" we were suspending has been destroyed",
+ domid);
+ goto err;
}
- LOG(ERROR, "guest did not suspend");
- return 0;
+ if (!(info.flags & XEN_DOMINF_shutdown))
+ /* keep waiting */
+ return;
+
+ shutdown_reason = (info.flags >> XEN_DOMINF_shutdownshift)
+ & XEN_DOMINF_shutdownmask;
+ if (shutdown_reason != SHUTDOWN_suspend) {
+ LOG(DEBUG, "guest %"PRId32" we were suspending has shut down"
+ " with unexpected reason code %d", domid, shutdown_reason);
+ goto err;
+ }
+
+ LOG(DEBUG, "guest has suspended");
+ domain_suspend_common_guest_suspended(egc, dss);
+ return;
+
+ err:
+ domain_suspend_common_failed(egc, dss);
+}
+
+static void suspend_common_wait_guest_timeout(libxl__egc *egc,
+ libxl__ev_time *ev, const struct timeval *requested_abs)
+{
+ libxl__domain_suspend_state *dss = CONTAINER_OF(ev, *dss, guest_timeout);
+ STATE_AO_GC(dss->ao);
+ LOG(ERROR, "guest did not suspend, timed out");
+ domain_suspend_common_failed(egc, dss);
+}
+
+static void domain_suspend_common_guest_suspended(libxl__egc *egc,
+ libxl__domain_suspend_state *dss)
+{
+ STATE_AO_GC(dss->ao);
+ int ret;
+
+ libxl__ev_evtchn_cancel(gc, &dss->guest_evtchn);
+ libxl__ev_xswatch_deregister(gc, &dss->guest_watch);
+ libxl__ev_time_deregister(gc, &dss->guest_timeout);
- guest_suspended:
if (dss->hvm) {
ret = libxl__domain_suspend_device_model(gc, dss);
if (ret) {
LOG(ERROR, "libxl__domain_suspend_device_model failed ret=%d", ret);
- return 0;
+ domain_suspend_common_failed(egc, dss);
+ return;
}
}
- return 1;
+ domain_suspend_common_done(egc, dss, 1);
+}
+
+static void domain_suspend_common_failed(libxl__egc *egc,
+ libxl__domain_suspend_state *dss)
+{
+ domain_suspend_common_done(egc, dss, 0);
+}
+
+static void domain_suspend_common_done(libxl__egc *egc,
+ libxl__domain_suspend_state *dss,
+ bool ok)
+{
+ EGC_GC;
+ assert(!libxl__xswait_inuse(&dss->pvcontrol));
+ libxl__ev_evtchn_cancel(gc, &dss->guest_evtchn);
+ libxl__ev_xswatch_deregister(gc, &dss->guest_watch);
+ libxl__ev_time_deregister(gc, &dss->guest_timeout);
+ dss->callback_common_done(egc, dss, ok);
}
static inline char *physmap_path(libxl__gc *gc, uint32_t domid,
@@ -1246,32 +1572,116 @@ int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
return 0;
}
+static void libxl__domain_suspend_callback(void *data)
+{
+ libxl__save_helper_state *shs = data;
+ libxl__egc *egc = shs->egc;
+ libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
+
+ dss->callback_common_done = domain_suspend_callback_common_done;
+ domain_suspend_callback_common(egc, dss);
+}
+
+static void domain_suspend_callback_common_done(libxl__egc *egc,
+ libxl__domain_suspend_state *dss, int ok)
+{
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
+}
+
/*----- remus callbacks -----*/
+static void remus_domain_suspend_callback_common_done(libxl__egc *egc,
+ libxl__domain_suspend_state *dss, int ok);
+static void remus_devices_postsuspend_cb(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc);
+static void remus_devices_preresume_cb(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc);
+
+static void libxl__remus_domain_suspend_callback(void *data)
+{
+ libxl__save_helper_state *shs = data;
+ libxl__egc *egc = shs->egc;
+ libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
+
+ dss->callback_common_done = remus_domain_suspend_callback_common_done;
+ domain_suspend_callback_common(egc, dss);
+}
-static int libxl__remus_domain_suspend_callback(void *data)
+static void remus_domain_suspend_callback_common_done(libxl__egc *egc,
+ libxl__domain_suspend_state *dss, int ok)
{
- /* REMUS TODO: Issue disk and network checkpoint reqs. */
- return libxl__domain_suspend_common_callback(data);
+ if (!ok)
+ goto out;
+
+ libxl__remus_devices_state *const rds = &dss->rds;
+ rds->callback = remus_devices_postsuspend_cb;
+ libxl__remus_devices_postsuspend(egc, rds);
+ return;
+
+out:
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
+}
+
+static void remus_devices_postsuspend_cb(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc)
+{
+ int ok = 0;
+ libxl__domain_suspend_state *dss = CONTAINER_OF(rds, *dss, rds);
+
+ if (rc)
+ goto out;
+
+ ok = 1;
+
+out:
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
}
-static int libxl__remus_domain_resume_callback(void *data)
+static void libxl__remus_domain_resume_callback(void *data)
{
libxl__save_helper_state *shs = data;
+ libxl__egc *egc = shs->egc;
libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
STATE_AO_GC(dss->ao);
+ libxl__remus_devices_state *const rds = &dss->rds;
+ rds->callback = remus_devices_preresume_cb;
+ libxl__remus_devices_preresume(egc, rds);
+}
+
+static void remus_devices_preresume_cb(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc)
+{
+ int ok = 0;
+ libxl__domain_suspend_state *dss = CONTAINER_OF(rds, *dss, rds);
+ STATE_AO_GC(dss->ao);
+
+ if (rc)
+ goto out;
+
/* Resumes the domain and the device model */
- if (libxl__domain_resume(gc, dss->domid, /* Fast Suspend */1))
- return 0;
+ rc = libxl__domain_resume(gc, dss->domid, /* Fast Suspend */1);
+ if (rc)
+ goto out;
- /* REMUS TODO: Deal with disk. Start a new network output buffer */
- return 1;
+ ok = 1;
+
+out:
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
}
/*----- remus asynchronous checkpoint callback -----*/
static void remus_checkpoint_dm_saved(libxl__egc *egc,
libxl__domain_suspend_state *dss, int rc);
+static void remus_devices_commit_cb(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc);
+static void remus_next_checkpoint(libxl__egc *egc, libxl__ev_time *ev,
+ const struct timeval *requested_abs);
static void libxl__remus_domain_checkpoint_callback(void *data)
{
@@ -1291,10 +1701,73 @@ static void libxl__remus_domain_checkpoint_callback(void *data)
static void remus_checkpoint_dm_saved(libxl__egc *egc,
libxl__domain_suspend_state *dss, int rc)
{
- /* REMUS TODO: Wait for disk and memory ack, release network buffer */
- /* REMUS TODO: make this asynchronous */
- assert(!rc); /* REMUS TODO handle this error properly */
- usleep(dss->interval * 1000);
+ /* Convenience aliases */
+ libxl__remus_devices_state *const rds = &dss->rds;
+
+ STATE_AO_GC(dss->ao);
+
+ if (rc) {
+ LOG(ERROR, "Failed to save device model. Terminating Remus..");
+ goto out;
+ }
+
+ rds->callback = remus_devices_commit_cb;
+ libxl__remus_devices_commit(egc, rds);
+
+ return;
+
+out:
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, 0);
+}
+
+static void remus_devices_commit_cb(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc)
+{
+ libxl__domain_suspend_state *dss = CONTAINER_OF(rds, *dss, rds);
+
+ STATE_AO_GC(dss->ao);
+
+ if (rc) {
+ LOG(ERROR, "Failed to do device commit op."
+ " Terminating Remus..");
+ goto out;
+ }
+
+ /*
+ * At this point, we have successfully checkpointed the guest and
+ * committed it at the backup. We'll come back after the checkpoint
+ * interval to checkpoint the guest again. Until then, let the guest
+ * continue execution.
+ */
+
+ /* Set checkpoint interval timeout */
+ rc = libxl__ev_time_register_rel(gc, &dss->checkpoint_timeout,
+ remus_next_checkpoint,
+ dss->interval);
+
+ if (rc)
+ goto out;
+
+ return;
+
+out:
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, 0);
+}
+
+static void remus_next_checkpoint(libxl__egc *egc, libxl__ev_time *ev,
+ const struct timeval *requested_abs)
+{
+ libxl__domain_suspend_state *dss =
+ CONTAINER_OF(ev, *dss, checkpoint_timeout);
+
+ STATE_AO_GC(dss->ao);
+
+ /*
+ * Time to checkpoint the guest again. We return 1 to libxc
+ * (xc_domain_save.c). in order to continue executing the infinite loop
+ * (suspend, checkpoint, resume) in xc_domain_save().
+ */
libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, 1);
}
@@ -1305,7 +1778,6 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
STATE_AO_GC(dss->ao);
int port;
int rc = ERROR_FAIL;
- unsigned long vm_generationid_addr;
/* Convenience aliases */
const uint32_t domid = dss->domid;
@@ -1317,22 +1789,17 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
&dss->shs.callbacks.save.a;
logdirty_init(&dss->logdirty);
+ libxl__xswait_init(&dss->pvcontrol);
+ libxl__ev_evtchn_init(&dss->guest_evtchn);
+ libxl__ev_xswatch_init(&dss->guest_watch);
+ libxl__ev_time_init(&dss->guest_timeout);
switch (type) {
case LIBXL_DOMAIN_TYPE_HVM: {
- char *path;
- char *addr;
-
- path = GCSPRINTF("%s/hvmloader/generation-id-address",
- libxl__xs_get_dompath(gc, domid));
- addr = libxl__xs_read(gc, XBT_NULL, path);
-
- vm_generationid_addr = (addr) ? strtoul(addr, NULL, 0) : 0;
dss->hvm = 1;
break;
}
case LIBXL_DOMAIN_TYPE_PV:
- vm_generationid_addr = 0;
dss->hvm = 0;
break;
default:
@@ -1343,29 +1810,28 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
| (debug ? XCFLAGS_DEBUG : 0)
| (dss->hvm ? XCFLAGS_HVM : 0);
- dss->suspend_eventchn = -1;
+ dss->guest_evtchn.port = -1;
+ dss->guest_evtchn_lockfd = -1;
dss->guest_responded = 0;
dss->dm_savefile = libxl__device_model_savefile(gc, domid);
if (r_info != NULL) {
dss->interval = r_info->interval;
- if (r_info->compression)
+ if (libxl_defbool_val(r_info->compression))
dss->xcflags |= XCFLAGS_CHECKPOINT_COMPRESS;
}
- dss->xce = xc_evtchn_open(NULL, 0);
- if (dss->xce == NULL)
- goto out;
- else
- {
- port = xs_suspend_evtchn_port(dss->domid);
+ port = xs_suspend_evtchn_port(dss->domid);
- if (port >= 0) {
- dss->suspend_eventchn =
- xc_suspend_evtchn_init(CTX->xch, dss->xce, dss->domid, port);
+ if (port >= 0) {
+ dss->guest_evtchn.port =
+ xc_suspend_evtchn_init_exclusive(CTX->xch, CTX->xce,
+ dss->domid, port, &dss->guest_evtchn_lockfd);
- if (dss->suspend_eventchn < 0)
- LOG(WARN, "Suspend event channel initialization failed");
+ if (dss->guest_evtchn.port < 0) {
+ LOG(WARN, "Suspend event channel initialization failed");
+ rc = ERROR_FAIL;
+ goto out;
}
}
@@ -1375,12 +1841,12 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
callbacks->postcopy = libxl__remus_domain_resume_callback;
callbacks->checkpoint = libxl__remus_domain_checkpoint_callback;
} else
- callbacks->suspend = libxl__domain_suspend_common_callback;
+ callbacks->suspend = libxl__domain_suspend_callback;
callbacks->switch_qemu_logdirty = libxl__domain_suspend_common_switch_qemu_logdirty;
dss->shs.callbacks.save.toolstack_save = libxl__toolstack_save;
- libxl__xc_domain_save(egc, dss, vm_generationid_addr);
+ libxl__xc_domain_save(egc, dss);
return;
out:
@@ -1516,6 +1982,10 @@ static void save_device_model_datacopier_done(libxl__egc *egc,
dss->save_dm_callback(egc, dss, our_rc);
}
+static void remus_teardown_done(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc);
+
static void domain_suspend_done(libxl__egc *egc,
libxl__domain_suspend_state *dss, int rc)
{
@@ -1524,11 +1994,39 @@ static void domain_suspend_done(libxl__egc *egc,
/* Convenience aliases */
const uint32_t domid = dss->domid;
- if (dss->suspend_eventchn > 0)
- xc_suspend_evtchn_release(CTX->xch, dss->xce, domid,
- dss->suspend_eventchn);
- if (dss->xce != NULL)
- xc_evtchn_close(dss->xce);
+ libxl__ev_evtchn_cancel(gc, &dss->guest_evtchn);
+
+ if (dss->guest_evtchn.port > 0)
+ xc_suspend_evtchn_release(CTX->xch, CTX->xce, domid,
+ dss->guest_evtchn.port, &dss->guest_evtchn_lockfd);
+
+ if (!dss->remus) {
+ remus_teardown_done(egc, &dss->rds, rc);
+ return;
+ }
+
+ /*
+ * With Remus, if we reach this point, it means either
+ * backup died or some network error occurred preventing us
+ * from sending checkpoints. Teardown the network buffers and
+ * release netlink resources. This is an async op.
+ */
+ LOG(WARN, "Remus: Domain suspend terminated with rc %d,"
+ " teardown Remus devices...", rc);
+ dss->rds.callback = remus_teardown_done;
+ libxl__remus_devices_teardown(egc, &dss->rds);
+}
+
+static void remus_teardown_done(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc)
+{
+ libxl__domain_suspend_state *dss = CONTAINER_OF(rds, *dss, rds);
+ STATE_AO_GC(dss->ao);
+
+ if (rc)
+ LOG(ERROR, "Remus: failed to teardown device for guest with domid %u,"
+ " rc %d", dss->domid, rc);
dss->callback(egc, dss, rc);
}
@@ -1540,9 +2038,9 @@ char *libxl__uuid2string(libxl__gc *gc, const libxl_uuid uuid)
return GCSPRINTF(LIBXL_UUID_FMT, LIBXL_UUID_BYTES(uuid));
}
-static const char *userdata_path(libxl__gc *gc, uint32_t domid,
- const char *userdata_userid,
- const char *wh)
+const char *libxl__userdata_path(libxl__gc *gc, uint32_t domid,
+ const char *userdata_userid,
+ const char *wh)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
char *uuid_string;
@@ -1577,7 +2075,7 @@ void libxl__userdata_destroyall(libxl__gc *gc, uint32_t domid)
glob_t gl;
int r, i;
- pattern = userdata_path(gc, domid, "*", "?");
+ pattern = libxl__userdata_path(gc, domid, "*", "?");
if (!pattern)
goto out;
@@ -1590,25 +2088,28 @@ void libxl__userdata_destroyall(libxl__gc *gc, uint32_t domid)
if (r)
LOGE(ERROR, "glob failed for %s", pattern);
+ /* Note: don't delete domain-userdata-lock, it will be handled by
+ * unlock function.
+ */
for (i=0; i<gl.gl_pathc; i++) {
- userdata_delete(gc, gl.gl_pathv[i]);
+ if (!strstr(gl.gl_pathv[i], "domain-userdata-lock"))
+ userdata_delete(gc, gl.gl_pathv[i]);
}
globfree(&gl);
out:
return;
}
-int libxl_userdata_store(libxl_ctx *ctx, uint32_t domid,
- const char *userdata_userid,
- const uint8_t *data, int datalen)
+int libxl__userdata_store(libxl__gc *gc, uint32_t domid,
+ const char *userdata_userid,
+ const uint8_t *data, int datalen)
{
- GC_INIT(ctx);
const char *filename;
const char *newfilename;
int e, rc;
int fd = -1;
- filename = userdata_path(gc, domid, userdata_userid, "d");
+ filename = libxl__userdata_path(gc, domid, userdata_userid, "d");
if (!filename) {
rc = ERROR_NOMEM;
goto out;
@@ -1619,7 +2120,7 @@ int libxl_userdata_store(libxl_ctx *ctx, uint32_t domid,
goto out;
}
- newfilename = userdata_path(gc, domid, userdata_userid, "n");
+ newfilename = libxl__userdata_path(gc, domid, userdata_userid, "n");
if (!newfilename) {
rc = ERROR_NOMEM;
goto out;
@@ -1631,7 +2132,7 @@ int libxl_userdata_store(libxl_ctx *ctx, uint32_t domid,
if (fd < 0)
goto err;
- if (libxl_write_exactly(ctx, fd, data, datalen, "userdata", newfilename))
+ if (libxl_write_exactly(CTX, fd, data, datalen, "userdata", newfilename))
goto err;
if (close(fd) < 0) {
@@ -1653,36 +2154,60 @@ err:
}
if (rc)
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "cannot write/rename %s for %s",
+ LIBXL__LOG_ERRNO(CTX, LIBXL__LOG_ERROR, "cannot write/rename %s for %s",
newfilename, filename);
out:
- GC_FREE;
return rc;
}
-int libxl_userdata_retrieve(libxl_ctx *ctx, uint32_t domid,
- const char *userdata_userid,
- uint8_t **data_r, int *datalen_r)
+int libxl_userdata_store(libxl_ctx *ctx, uint32_t domid,
+ const char *userdata_userid,
+ const uint8_t *data, int datalen)
{
GC_INIT(ctx);
+ int rc;
+ libxl__domain_userdata_lock *lock;
+
+ CTX_LOCK;
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
+
+ rc = libxl__userdata_store(gc, domid, userdata_userid,
+ data, datalen);
+
+ libxl__unlock_domain_userdata(lock);
+
+out:
+ CTX_UNLOCK;
+ GC_FREE;
+ return rc;
+}
+
+int libxl__userdata_retrieve(libxl__gc *gc, uint32_t domid,
+ const char *userdata_userid,
+ uint8_t **data_r, int *datalen_r)
+{
const char *filename;
int e, rc;
int datalen = 0;
void *data = 0;
- filename = userdata_path(gc, domid, userdata_userid, "d");
+ filename = libxl__userdata_path(gc, domid, userdata_userid, "d");
if (!filename) {
rc = ERROR_NOMEM;
goto out;
}
- e = libxl_read_file_contents(ctx, filename, data_r ? &data : 0, &datalen);
+ e = libxl_read_file_contents(CTX, filename, data_r ? &data : 0, &datalen);
if (e && errno != ENOENT) {
rc = ERROR_FAIL;
goto out;
}
if (!e && !datalen) {
- LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "userdata file %s is empty", filename);
+ LIBXL__LOG(CTX, LIBXL__LOG_ERROR, "userdata file %s is empty", filename);
if (data_r) assert(!*data_r);
rc = ERROR_FAIL;
goto out;
@@ -1691,7 +2216,69 @@ int libxl_userdata_retrieve(libxl_ctx *ctx, uint32_t domid,
if (data_r) *data_r = data;
if (datalen_r) *datalen_r = datalen;
rc = 0;
+
+out:
+ return rc;
+}
+
+int libxl_userdata_retrieve(libxl_ctx *ctx, uint32_t domid,
+ const char *userdata_userid,
+ uint8_t **data_r, int *datalen_r)
+{
+ GC_INIT(ctx);
+ int rc;
+ libxl__domain_userdata_lock *lock;
+
+ CTX_LOCK;
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
+
+ rc = libxl__userdata_retrieve(gc, domid, userdata_userid,
+ data_r, datalen_r);
+
+
+ libxl__unlock_domain_userdata(lock);
+out:
+ CTX_UNLOCK;
+ GC_FREE;
+ return rc;
+}
+
+int libxl_userdata_unlink(libxl_ctx *ctx, uint32_t domid,
+ const char *userdata_userid)
+{
+ GC_INIT(ctx);
+ CTX_LOCK;
+
+ int rc;
+ libxl__domain_userdata_lock *lock = NULL;
+ const char *filename;
+
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
+
+ filename = libxl__userdata_path(gc, domid, userdata_userid, "d");
+ if (!filename) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ if (unlink(filename)) {
+ LOGE(ERROR, "error deleting userdata file: %s", filename);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = 0;
out:
+ if (lock)
+ libxl__unlock_domain_userdata(lock);
+ CTX_UNLOCK;
GC_FREE;
return rc;
}
diff --git a/tools/libxl/libxl_event.c b/tools/libxl/libxl_event.c
index ea8c744..22b1227 100644
--- a/tools/libxl/libxl_event.c
+++ b/tools/libxl/libxl_event.c
@@ -625,6 +625,159 @@ void libxl__ev_xswatch_deregister(libxl__gc *gc, libxl__ev_xswatch *w)
}
/*
+ * evtchn
+ */
+
+static int evtchn_revents_check(libxl__egc *egc, int revents)
+{
+ EGC_GC;
+
+ if (revents & ~POLLIN) {
+ LOG(ERROR, "unexpected poll event on event channel fd: %x", revents);
+ LIBXL__EVENT_DISASTER(egc,
+ "unexpected poll event on event channel fd", 0, 0);
+ libxl__ev_fd_deregister(gc, &CTX->evtchn_efd);
+ return ERROR_FAIL;
+ }
+
+ assert(revents & POLLIN);
+
+ return 0;
+}
+
+static void evtchn_fd_callback(libxl__egc *egc, libxl__ev_fd *ev,
+ int fd, short events, short revents)
+{
+ EGC_GC;
+ libxl__ev_evtchn *evev;
+ int r, rc;
+ evtchn_port_or_error_t port;
+ struct pollfd recheck;
+
+ rc = evtchn_revents_check(egc, revents);
+ if (rc) return;
+
+ for (;;) {
+ /* Check the fd again. The incoming revent may no longer be
+ * true, because the libxl ctx lock has not necessarily been
+ * held continuously since someone noticed the fd. Normally
+ * this wouldn't be a problem but evtchn devices don't always
+ * honour O_NONBLOCK (see xenctrl.h). */
+
+ recheck.fd = fd;
+ recheck.events = POLLIN;
+ recheck.revents = 0;
+ r = poll(&recheck, 1, 0);
+ DBG("ev_evtchn recheck r=%d revents=%#x", r, recheck.revents);
+ if (r < 0) {
+ LIBXL__EVENT_DISASTER(egc,
+ "unexpected failure polling event channel fd for recheck",
+ errno, 0);
+ return;
+ }
+ if (r == 0)
+ break;
+ rc = evtchn_revents_check(egc, recheck.revents);
+ if (rc) return;
+
+ /* OK, that's that workaround done. We can actually check for
+ * work for us to do: */
+
+ port = xc_evtchn_pending(CTX->xce);
+ if (port < 0) {
+ if (errno == EAGAIN)
+ break;
+ LIBXL__EVENT_DISASTER(egc,
+ "unexpected failure fetching occurring event port number from evtchn",
+ errno, 0);
+ return;
+ }
+
+ LIBXL_LIST_FOREACH(evev, &CTX->evtchns_waiting, entry)
+ if (port == evev->port)
+ goto found;
+ /* not found */
+ DBG("ev_evtchn port=%d no-one cared", port);
+ continue;
+
+ found:
+ DBG("ev_evtchn=%p port=%d signaled", evev, port);
+ evev->waiting = 0;
+ LIBXL_LIST_REMOVE(evev, entry);
+ evev->callback(egc, evev);
+ }
+}
+
+int libxl__ctx_evtchn_init(libxl__gc *gc) {
+ xc_evtchn *xce;
+ int rc, fd;
+
+ if (CTX->xce)
+ return 0;
+
+ xce = xc_evtchn_open(CTX->lg, 0);
+ if (!xce) {
+ LOGE(ERROR,"cannot open libxc evtchn handle");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ fd = xc_evtchn_fd(xce);
+ assert(fd >= 0);
+
+ rc = libxl_fd_set_nonblock(CTX, fd, 1);
+ if (rc) goto out;
+
+ rc = libxl__ev_fd_register(gc, &CTX->evtchn_efd,
+ evtchn_fd_callback, fd, POLLIN);
+ if (rc) goto out;
+
+ CTX->xce = xce;
+ return 0;
+
+ out:
+ xc_evtchn_close(xce);
+ return rc;
+}
+
+int libxl__ev_evtchn_wait(libxl__gc *gc, libxl__ev_evtchn *evev)
+{
+ int r, rc;
+
+ DBG("ev_evtchn=%p port=%d wait (was waiting=%d)",
+ evev, evev->port, evev->waiting);
+
+ if (evev->waiting)
+ return 0;
+
+ r = xc_evtchn_unmask(CTX->xce, evev->port);
+ if (r) {
+ LOGE(ERROR,"cannot unmask event channel %d",evev->port);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ evev->waiting = 1;
+ LIBXL_LIST_INSERT_HEAD(&CTX->evtchns_waiting, evev, entry);
+ return 0;
+
+ out:
+ return rc;
+}
+
+void libxl__ev_evtchn_cancel(libxl__gc *gc, libxl__ev_evtchn *evev)
+{
+ DBG("ev_evtchn=%p port=%d cancel (was waiting=%d)",
+ evev, evev->port, evev->waiting);
+
+ if (!evev->waiting)
+ return;
+
+ evev->waiting = 0;
+ LIBXL_LIST_REMOVE(evev, entry);
+}
+
+/*
* waiting for device state
*/
@@ -1347,13 +1500,13 @@ int libxl__self_pipe_eatall(int fd)
* Manipulation of pollers
*/
-int libxl__poller_init(libxl_ctx *ctx, libxl__poller *p)
+int libxl__poller_init(libxl__gc *gc, libxl__poller *p)
{
int rc;
p->fd_polls = 0;
p->fd_rindices = 0;
- rc = libxl__pipe_nonblock(ctx, p->wakeup_pipe);
+ rc = libxl__pipe_nonblock(CTX, p->wakeup_pipe);
if (rc) goto out;
return 0;
@@ -1370,25 +1523,20 @@ void libxl__poller_dispose(libxl__poller *p)
free(p->fd_rindices);
}
-libxl__poller *libxl__poller_get(libxl_ctx *ctx)
+libxl__poller *libxl__poller_get(libxl__gc *gc)
{
/* must be called with ctx locked */
int rc;
- libxl__poller *p = LIBXL_LIST_FIRST(&ctx->pollers_idle);
+ libxl__poller *p = LIBXL_LIST_FIRST(&CTX->pollers_idle);
if (p) {
LIBXL_LIST_REMOVE(p, entry);
return p;
}
- p = malloc(sizeof(*p));
- if (!p) {
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "cannot allocate poller");
- return 0;
- }
- memset(p, 0, sizeof(*p));
+ p = libxl__zalloc(NOGC, sizeof(*p));
- rc = libxl__poller_init(ctx, p);
+ rc = libxl__poller_init(gc, p);
if (rc) {
free(p);
return NULL;
@@ -1477,7 +1625,7 @@ int libxl_event_wait(libxl_ctx *ctx, libxl_event **event_r,
EGC_INIT(ctx);
CTX_LOCK;
- poller = libxl__poller_get(ctx);
+ poller = libxl__poller_get(gc);
if (!poller) { rc = ERROR_FAIL; goto out; }
for (;;) {
@@ -1653,7 +1801,7 @@ libxl__ao *libxl__ao_create(libxl_ctx *ctx, uint32_t domid,
if (how) {
ao->how = *how;
} else {
- ao->poller = libxl__poller_get(ctx);
+ ao->poller = libxl__poller_get(&ao->gc);
if (!ao->poller) goto out;
}
libxl__log(ctx,XTL_DEBUG,-1,file,line,func,
diff --git a/tools/libxl/libxl_exec.c b/tools/libxl/libxl_exec.c
index b6efa0f..478b4c2 100644
--- a/tools/libxl/libxl_exec.c
+++ b/tools/libxl/libxl_exec.c
@@ -77,11 +77,11 @@ void libxl__exec(libxl__gc *gc, int stdinfd, int stdoutfd, int stderrfd,
if (stderrfd != -1)
dup2(stderrfd, STDERR_FILENO);
- if (stdinfd != -1)
+ if (stdinfd > 2)
close(stdinfd);
- if (stdoutfd != -1 && stdoutfd != stdinfd)
+ if (stdoutfd > 2 && stdoutfd != stdinfd)
close(stdoutfd);
- if (stderrfd != -1 && stderrfd != stdinfd && stderrfd != stdoutfd)
+ if (stderrfd > 2 && stderrfd != stdinfd && stderrfd != stdoutfd)
close(stderrfd);
check_open_fds(arg0);
@@ -257,10 +257,8 @@ err:
*/
/* Event callbacks. */
-static void spawn_watch_event(libxl__egc *egc, libxl__ev_xswatch *xsw,
- const char *watch_path, const char *event_path);
-static void spawn_timeout(libxl__egc *egc, libxl__ev_time *ev,
- const struct timeval *requested_abs);
+static void spawn_watch_event(libxl__egc *egc, libxl__xswait_state *xswa,
+ int rc, const char *xsdata);
static void spawn_middle_death(libxl__egc *egc, libxl__ev_child *childw,
pid_t pid, int status);
@@ -274,8 +272,7 @@ static void spawn_fail(libxl__egc *egc, libxl__spawn_state *ss);
void libxl__spawn_init(libxl__spawn_state *ss)
{
libxl__ev_child_init(&ss->mid);
- libxl__ev_time_init(&ss->timeout);
- libxl__ev_xswatch_init(&ss->xswatch);
+ libxl__xswait_init(&ss->xswait);
}
int libxl__spawn_spawn(libxl__egc *egc, libxl__spawn_state *ss)
@@ -288,12 +285,12 @@ int libxl__spawn_spawn(libxl__egc *egc, libxl__spawn_state *ss)
libxl__spawn_init(ss);
ss->failed = ss->detaching = 0;
- rc = libxl__ev_time_register_rel(gc, &ss->timeout,
- spawn_timeout, ss->timeout_ms);
- if (rc) goto out_err;
-
- rc = libxl__ev_xswatch_register(gc, &ss->xswatch,
- spawn_watch_event, ss->xspath);
+ ss->xswait.ao = ao;
+ ss->xswait.what = GCSPRINTF("%s startup", ss->what);
+ ss->xswait.path = ss->xspath;
+ ss->xswait.timeout_ms = ss->timeout_ms;
+ ss->xswait.callback = spawn_watch_event;
+ rc = libxl__xswait_start(gc, &ss->xswait);
if (rc) goto out_err;
pid_t middle = libxl__ev_child_fork(gc, &ss->mid, spawn_middle_death);
@@ -350,8 +347,7 @@ int libxl__spawn_spawn(libxl__egc *egc, libxl__spawn_state *ss)
static void spawn_cleanup(libxl__gc *gc, libxl__spawn_state *ss)
{
assert(!libxl__ev_child_inuse(&ss->mid));
- libxl__ev_time_deregister(gc, &ss->timeout);
- libxl__ev_xswatch_deregister(gc, &ss->xswatch);
+ libxl__xswait_stop(gc, &ss->xswait);
}
static void spawn_detach(libxl__gc *gc, libxl__spawn_state *ss)
@@ -362,8 +358,7 @@ static void spawn_detach(libxl__gc *gc, libxl__spawn_state *ss)
int r;
assert(libxl__ev_child_inuse(&ss->mid));
- libxl__ev_time_deregister(gc, &ss->timeout);
- libxl__ev_xswatch_deregister(gc, &ss->xswatch);
+ libxl__xswait_stop(gc, &ss->xswait);
pid_t child = ss->mid.pid;
r = kill(child, SIGKILL);
@@ -387,25 +382,15 @@ static void spawn_fail(libxl__egc *egc, libxl__spawn_state *ss)
spawn_detach(gc, ss);
}
-static void spawn_timeout(libxl__egc *egc, libxl__ev_time *ev,
- const struct timeval *requested_abs)
-{
- /* Before event, was Attached. */
- EGC_GC;
- libxl__spawn_state *ss = CONTAINER_OF(ev, *ss, timeout);
- LOG(ERROR, "%s: startup timed out", ss->what);
- spawn_fail(egc, ss); /* must be last */
-}
-
-static void spawn_watch_event(libxl__egc *egc, libxl__ev_xswatch *xsw,
- const char *watch_path, const char *event_path)
+static void spawn_watch_event(libxl__egc *egc, libxl__xswait_state *xswa,
+ int rc, const char *p)
{
/* On entry, is Attached. */
EGC_GC;
- libxl__spawn_state *ss = CONTAINER_OF(xsw, *ss, xswatch);
- char *p = libxl__xs_read(gc, 0, ss->xspath);
- if (!p && errno != ENOENT) {
- LOG(ERROR, "%s: xenstore read of %s failed", ss->what, ss->xspath);
+ libxl__spawn_state *ss = CONTAINER_OF(xswa, *ss, xswait);
+ if (rc) {
+ if (rc == ERROR_TIMEDOUT)
+ LOG(ERROR, "%s: startup timed out", ss->what);
spawn_fail(egc, ss); /* must be last */
return;
}
diff --git a/tools/libxl/libxl_freebsd.c b/tools/libxl/libxl_freebsd.c
new file mode 100644
index 0000000..e8b88b3
--- /dev/null
+++ b/tools/libxl/libxl_freebsd.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2014
+ * Author Roger Pau Monne <roger.pau at entel.upc.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+
+int libxl__try_phy_backend(mode_t st_mode)
+{
+ if (S_ISREG(st_mode) || S_ISBLK(st_mode) || S_ISCHR(st_mode))
+ return 1;
+
+ return 0;
+}
+
+char *libxl__devid_to_localdev(libxl__gc *gc, int devid)
+{
+ /* TODO */
+ return NULL;
+}
+
+/* Hotplug scripts caller functions */
+static int libxl__hotplug_env_nic(libxl__gc *gc, libxl__device *dev, char ***env,
+ int num_exec)
+{
+ int nr = 0;
+ const int arraysize = 5;
+ libxl_nic_type type;
+
+ assert(dev->backend_kind == LIBXL__DEVICE_KIND_VIF);
+
+ /*
+ * On the first pass the PV interface is added to the bridge,
+ * on the second pass the tap interface will also be added.
+ */
+ type = num_exec == 0 ? LIBXL_NIC_TYPE_VIF : LIBXL_NIC_TYPE_VIF_IOEMU;
+
+ GCNEW_ARRAY(*env, arraysize);
+ (*env)[nr++] = "iface_dev";
+ (*env)[nr++] = (char *) libxl__device_nic_devname(gc, dev->domid,
+ dev->devid, type);
+ (*env)[nr++] = "emulated";
+ (*env)[nr++] = type == LIBXL_NIC_TYPE_VIF_IOEMU ? "1" : "0";
+ (*env)[nr++] = NULL;
+ assert(nr == arraysize);
+
+ return 0;
+}
+
+static int libxl__hotplug_nic(libxl__gc *gc, libxl__device *dev, char ***args,
+ libxl__device_action action)
+{
+ char *be_path = libxl__device_backend_path(gc, dev);
+ char *script;
+ int nr = 0, rc = 0, arraysize = 4;
+
+ assert(dev->backend_kind == LIBXL__DEVICE_KIND_VIF);
+
+ script = libxl__xs_read(gc, XBT_NULL,
+ GCSPRINTF("%s/%s", be_path, "script"));
+ if (!script) {
+ LOGEV(ERROR, errno, "unable to read script from %s", be_path);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ GCNEW_ARRAY(*args, arraysize);
+ (*args)[nr++] = script;
+ (*args)[nr++] = be_path;
+ (*args)[nr++] = GCSPRINTF("%s", action == LIBXL__DEVICE_ACTION_ADD ?
+ "add" : "remove");
+ (*args)[nr++] = NULL;
+ assert(nr == arraysize);
+
+out:
+ return rc;
+}
+
+int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev,
+ char ***args, char ***env,
+ libxl__device_action action,
+ int num_exec)
+{
+ libxl_nic_type nictype;
+ int rc;
+
+ if (dev->backend_kind != LIBXL__DEVICE_KIND_VIF || num_exec == 2)
+ return 0;
+
+ rc = libxl__nic_type(gc, dev, &nictype);
+ if (rc) {
+ LOG(ERROR, "error when fetching nic type");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ /*
+ * For PV domains only one pass is needed (because there's no emulated
+ * interface). For HVM domains two passes are needed in order to add
+ * both the PV and the tap interfaces to the bridge.
+ */
+ if (nictype == LIBXL_NIC_TYPE_VIF && num_exec != 0) {
+ rc = 0;
+ goto out;
+ }
+
+ rc = libxl__hotplug_env_nic(gc, dev, env, num_exec);
+ if (rc)
+ goto out;
+
+ rc = libxl__hotplug_nic(gc, dev, args, action);
+ if (!rc) rc = 1;
+
+out:
+ return rc;
+}
+
+libxl_device_model_version libxl__default_device_model(libxl__gc *gc)
+{
+ return LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN;
+}
diff --git a/tools/libxl/libxl_genid.c b/tools/libxl/libxl_genid.c
new file mode 100644
index 0000000..4e2f013
--- /dev/null
+++ b/tools/libxl/libxl_genid.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2014 Citrix Systems R&D Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+
+#include <xenctrl.h>
+#include <xen/hvm/params.h>
+
+/*
+ * Generate a random VM generation ID.
+ *
+ * Returns ERROR_FAIL if a suitable source of random numbers is not
+ * available.
+ *
+ * See Microsoft's "Virtual Machine Generation ID" specification for
+ * further details, including when a new generation ID is required.
+ *
+ * http://www.microsoft.com/en-us/download/details.aspx?id=30707
+ */
+int libxl_ms_vm_genid_generate(libxl_ctx *ctx, libxl_ms_vm_genid *id)
+{
+ GC_INIT(ctx);
+ int ret;
+
+ ret = libxl__random_bytes(gc, id->bytes, LIBXL_MS_VM_GENID_LEN);
+
+ GC_FREE;
+ return ret;
+}
+
+/*
+ * Is this VM generation ID all zeros?
+ */
+bool libxl_ms_vm_genid_is_zero(const libxl_ms_vm_genid *id)
+{
+ static const libxl_ms_vm_genid zero;
+
+ return memcmp(id->bytes, zero.bytes, LIBXL_MS_VM_GENID_LEN) == 0;
+}
+
+void libxl_ms_vm_genid_copy(libxl_ctx *ctx, libxl_ms_vm_genid *dst,
+ libxl_ms_vm_genid *src)
+{
+ memcpy(dst, src, LIBXL_MS_VM_GENID_LEN);
+}
+
+int libxl__ms_vm_genid_set(libxl__gc *gc, uint32_t domid,
+ const libxl_ms_vm_genid *id)
+{
+ libxl_ctx *ctx = libxl__gc_owner(gc);
+ const char *dom_path;
+ uint64_t genid[2];
+ uint64_t paddr = 0;
+ int rc;
+
+ memcpy(genid, id->bytes, LIBXL_MS_VM_GENID_LEN);
+
+ /*
+ * Set the "platform/generation-id" XenStore key to pass the ID to
+ * hvmloader.
+ */
+ dom_path = libxl__xs_get_dompath(gc, domid);
+ if (!dom_path) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ rc = libxl__xs_write(gc, XBT_NULL,
+ GCSPRINTF("%s/platform/generation-id", dom_path),
+ "%"PRIu64 ":%" PRIu64, genid[0], genid[1]);
+ if (rc < 0)
+ goto out;
+
+ /*
+ * Update the ID in guest memory (if available).
+ */
+ xc_hvm_param_get(ctx->xch, domid, HVM_PARAM_VM_GENERATION_ID_ADDR, &paddr);
+ if (paddr) {
+ void *vaddr;
+
+ vaddr = xc_map_foreign_range(ctx->xch, domid, XC_PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ paddr >> XC_PAGE_SHIFT);
+ if (vaddr == NULL) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ memcpy(vaddr + (paddr & ~XC_PAGE_MASK), genid, 2 * sizeof(*genid));
+ munmap(vaddr, XC_PAGE_SIZE);
+
+ /*
+ * The spec requires an ACPI Notify event is injected into the
+ * guest when the generation ID is changed.
+ *
+ * This is only called for domains that are suspended or newly
+ * created and they won't be in a state to receive such an
+ * event.
+ */
+ }
+
+ rc = 0;
+
+ out:
+ return rc;
+}
diff --git a/tools/libxl/libxl_internal.c b/tools/libxl/libxl_internal.c
index cf17658..00c3b1e 100644
--- a/tools/libxl/libxl_internal.c
+++ b/tools/libxl/libxl_internal.c
@@ -78,10 +78,19 @@ void libxl__free_all(libxl__gc *gc)
gc->alloc_maxsize = 0;
}
-void *libxl__zalloc(libxl__gc *gc, int bytes)
+void *libxl__malloc(libxl__gc *gc, size_t size)
{
- void *ptr = calloc(bytes, 1);
- if (!ptr) libxl__alloc_failed(CTX, __func__, bytes, 1);
+ void *ptr = malloc(size);
+ if (!ptr) libxl__alloc_failed(CTX, __func__, size, 1);
+
+ libxl__ptr_add(gc, ptr);
+ return ptr;
+}
+
+void *libxl__zalloc(libxl__gc *gc, size_t size)
+{
+ void *ptr = calloc(size, 1);
+ if (!ptr) libxl__alloc_failed(CTX, __func__, size, 1);
libxl__ptr_add(gc, ptr);
return ptr;
@@ -155,19 +164,19 @@ char *libxl__strndup(libxl__gc *gc, const char *c, size_t n)
if (!s) libxl__alloc_failed(CTX, __func__, n, 1);
+ libxl__ptr_add(gc, s);
+
return s;
}
char *libxl__dirname(libxl__gc *gc, const char *s)
{
- char *c;
- char *ptr = libxl__strdup(gc, s);
+ char *c = strrchr(s, '/');
- c = strrchr(ptr, '/');
if (!c)
return NULL;
- *c = '\0';
- return ptr;
+
+ return libxl__strndup(gc, s, c - s);
}
void libxl__logv(libxl_ctx *ctx, xentoollog_level msglevel, int errnoval,
@@ -237,7 +246,7 @@ int libxl__file_reference_map(libxl__file_reference *f)
ret = -1;
data = mmap(NULL, st_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (data == NULL)
+ if (data == MAP_FAILED)
goto out;
f->mapped = 1;
@@ -275,10 +284,12 @@ _hidden int libxl__parse_mac(const char *s, libxl_mac mac)
char *endptr;
int i;
- for (i = 0, tok = s; *tok && (i < 6); ++i, tok += 3) {
+ for (i = 0, tok = s; *tok && (i < 6); ++i, tok = endptr) {
mac[i] = strtol(tok, &endptr, 16);
if (endptr != (tok + 2) || (*endptr != '\0' && *endptr != ':') )
return ERROR_INVAL;
+ if (*endptr == ':')
+ endptr++;
}
if ( i != 6 )
return ERROR_INVAL;
@@ -298,6 +309,12 @@ _hidden int libxl__compare_macs(libxl_mac *a, libxl_mac *b)
return 0;
}
+_hidden int libxl__mac_is_default(libxl_mac *mac)
+{
+ return (!(*mac)[0] && !(*mac)[1] && !(*mac)[2] &&
+ !(*mac)[3] && !(*mac)[4] && !(*mac)[5]);
+}
+
_hidden int libxl__init_recursive_mutex(libxl_ctx *ctx, pthread_mutex_t *lock)
{
pthread_mutexattr_t attr;
@@ -366,6 +383,164 @@ out:
return rc;
}
+/* Portability note: this lock utilises flock(2) so a proper implementation of
+ * flock(2) is required.
+ */
+libxl__domain_userdata_lock *libxl__lock_domain_userdata(libxl__gc *gc,
+ uint32_t domid)
+{
+ libxl__domain_userdata_lock *lock = NULL;
+ const char *lockfile;
+ int fd;
+ struct stat stab, fstab;
+
+ lockfile = libxl__userdata_path(gc, domid, "domain-userdata-lock", "l");
+ if (!lockfile) goto out;
+
+ lock = libxl__zalloc(NOGC, sizeof(libxl__domain_userdata_lock));
+ lock->path = libxl__strdup(NOGC, lockfile);
+
+ while (true) {
+ libxl__carefd_begin();
+ fd = open(lockfile, O_RDWR|O_CREAT, 0666);
+ if (fd < 0)
+ LOGE(ERROR, "cannot open lockfile %s, errno=%d", lockfile, errno);
+ lock->lock_carefd = libxl__carefd_opened(CTX, fd);
+ if (fd < 0) goto out;
+
+ /* Lock the file in exclusive mode, wait indefinitely to
+ * acquire the lock
+ */
+ while (flock(fd, LOCK_EX)) {
+ switch (errno) {
+ case EINTR:
+ /* Signal received, retry */
+ continue;
+ default:
+ /* All other errno: EBADF, EINVAL, ENOLCK, EWOULDBLOCK */
+ LOGE(ERROR,
+ "unexpected error while trying to lock %s, fd=%d, errno=%d",
+ lockfile, fd, errno);
+ goto out;
+ }
+ }
+
+ if (fstat(fd, &fstab)) {
+ LOGE(ERROR, "cannot fstat %s, fd=%d, errno=%d",
+ lockfile, fd, errno);
+ goto out;
+ }
+ if (stat(lockfile, &stab)) {
+ if (errno != ENOENT) {
+ LOGE(ERROR, "cannot stat %s, errno=%d", lockfile, errno);
+ goto out;
+ }
+ } else {
+ if (stab.st_dev == fstab.st_dev && stab.st_ino == fstab.st_ino)
+ break;
+ }
+
+ libxl__carefd_close(lock->lock_carefd);
+ }
+
+ /* Check the domain is still there, if not we should release the
+ * lock and clean up.
+ */
+ if (libxl_domain_info(CTX, NULL, domid))
+ goto out;
+
+ return lock;
+
+out:
+ if (lock) libxl__unlock_domain_userdata(lock);
+ return NULL;
+}
+
+void libxl__unlock_domain_userdata(libxl__domain_userdata_lock *lock)
+{
+ if (lock->path) unlink(lock->path);
+ if (lock->lock_carefd) libxl__carefd_close(lock->lock_carefd);
+ free(lock->path);
+ free(lock);
+}
+
+int libxl__get_domain_configuration(libxl__gc *gc, uint32_t domid,
+ libxl_domain_config *d_config)
+{
+ uint8_t *data = NULL;
+ int rc, len;
+
+ rc = libxl__userdata_retrieve(gc, domid, "libxl-json", &data, &len);
+ if (rc) {
+ LOGEV(ERROR, rc,
+ "failed to retrieve domain configuration for domain %d", domid);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ if (len == 0) {
+ /* No logging, not necessary an error from caller's PoV. */
+ rc = ERROR_JSON_CONFIG_EMPTY;
+ goto out;
+ }
+ rc = libxl_domain_config_from_json(CTX, d_config, (const char *)data);
+
+out:
+ free(data);
+ return rc;
+}
+
+int libxl__set_domain_configuration(libxl__gc *gc, uint32_t domid,
+ libxl_domain_config *d_config)
+{
+ char *d_config_json;
+ int rc;
+
+ d_config_json = libxl_domain_config_to_json(CTX, d_config);
+ if (!d_config_json) {
+ LOGE(ERROR,
+ "failed to convert domain configuration to JSON for domain %d",
+ domid);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = libxl__userdata_store(gc, domid, "libxl-json",
+ (const uint8_t *)d_config_json,
+ strlen(d_config_json) + 1 /* include '\0' */);
+ if (rc) {
+ LOGEV(ERROR, rc, "failed to store domain configuration for domain %d",
+ domid);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+out:
+ free(d_config_json);
+ return rc;
+}
+
+void libxl__update_domain_configuration(libxl__gc *gc,
+ libxl_domain_config *dst,
+ const libxl_domain_config *src)
+{
+ int i;
+
+ /* update network interface information */
+ for (i = 0; i < src->num_nics; i++)
+ libxl__update_config_nic(gc, &dst->nics[i], &src->nics[i]);
+
+ /* update vtpm information */
+ for (i = 0; i < src->num_vtpms; i++)
+ libxl__update_config_vtpm(gc, &dst->vtpms[i], &src->vtpms[i]);
+
+ /* update guest UUID */
+ libxl_uuid_copy(CTX, &dst->c_info.uuid, &src->c_info.uuid);
+
+ /* video ram */
+ dst->b_info.video_memkb = src->b_info.video_memkb;
+}
+
/*
* Local variables:
* mode: C
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 9d17586..a38f695 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -43,6 +43,8 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
#include <xenstore.h>
#include <xenctrl.h>
@@ -91,6 +93,7 @@
#define LIBXL_PV_EXTRA_MEMORY 1024
#define LIBXL_HVM_EXTRA_MEMORY 2048
#define LIBXL_MIN_DOM0_MEM (128*1024)
+#define LIBXL_INVALID_GFN (~(uint64_t)0)
/* use 0 as the domid of the toolstack domain for now */
#define LIBXL_TOOLSTACK_DOMID 0
#define QEMU_SIGNATURE "DeviceModelRecord0002"
@@ -197,6 +200,17 @@ struct libxl__ev_xswatch {
uint32_t counterval;
};
+typedef struct libxl__ev_evtchn libxl__ev_evtchn;
+typedef void libxl__ev_evtchn_callback(libxl__egc *egc, libxl__ev_evtchn*);
+struct libxl__ev_evtchn {
+ /* caller must fill these in, and they must all remain valid */
+ libxl__ev_evtchn_callback *callback;
+ int port;
+ /* remainder is private for libxl__ev_evtchn_... */
+ bool waiting;
+ LIBXL_LIST_ENTRY(libxl__ev_evtchn) entry;
+};
+
/*
* An entry in the watch_slots table is either:
* 1. an entry in the free list, ie NULL or pointer to next free list entry
@@ -343,6 +357,10 @@ struct libxl__ctx {
uint32_t watch_counter; /* helps disambiguate slot reuse */
libxl__ev_fd watch_efd;
+ xc_evtchn *xce; /* waiting must be done only with libxl__ev_evtchn* */
+ LIBXL_LIST_HEAD(, libxl__ev_evtchn) evtchns_waiting;
+ libxl__ev_fd evtchn_efd;
+
LIBXL_TAILQ_HEAD(libxl__evgen_domain_death_list, libxl_evgen_domain_death)
death_list /* sorted by domid */,
death_reported;
@@ -489,8 +507,10 @@ static inline int libxl__gc_is_real(const libxl__gc *gc)
_hidden void libxl__ptr_add(libxl__gc *gc_opt, void *ptr /* may be NULL */) NN1;
/* if this is the outermost libxl callframe then free all pointers in @gc */
_hidden void libxl__free_all(libxl__gc *gc);
-/* allocate and zero @bytes. (similar to a gc'd malloc(3)+memzero()) */
-_hidden void *libxl__zalloc(libxl__gc *gc_opt, int bytes) NN1;
+/* allocate @size bytes. (a gc'd malloc(3)) */
+_hidden void *libxl__malloc(libxl__gc *gc_opt, size_t size) NN1;
+/* allocate and zero @size. (similar to a gc'd malloc(3)+memzero()) */
+_hidden void *libxl__zalloc(libxl__gc *gc_opt, size_t size) NN1;
/* allocate and zero memory for an array of @nmemb members of @size each.
* (similar to a gc'd calloc(3)). */
_hidden void *libxl__calloc(libxl__gc *gc_opt, size_t nmemb, size_t size) NN1;
@@ -626,6 +646,26 @@ int libxl__xs_rm_checked(libxl__gc *gc, xs_transaction_t t, const char *path);
* // other cleanups
* return rc;
* }
+ *
+ * Formally the states of *t are:
+ *
+ * name value of *t description
+ * Idle 0 no transaction exists
+ * Ready non-0 ready for work, nothing done yet
+ * Busy non-0 writes have been made but we are not finished
+ * Uncommitted non-0 writes have been made and should be committed
+ *
+ * libxl__xs_transaction_start: Idle -> Ready (on error: Idle)
+ *
+ * The transaction goes from Ready to Busy, and from Busy to
+ * Uncommitted, by the use of xenstore read and write operations
+ * (libxl__xs_..., xs_...) made by libxl__xs_transaction's caller.
+ *
+ * libxl__xs_transaction_commit: Ready/Uncommitted -> Idle
+ * on success (returns 0): xenstore has been updated
+ * on error (<0) or conflict (+1): updates discarded
+ *
+ * libxl__xs_transaction_abort: Any -> Idle (any updates discarded)
*/
int libxl__xs_transaction_start(libxl__gc *gc, xs_transaction_t *t);
int libxl__xs_transaction_commit(libxl__gc *gc, xs_transaction_t *t);
@@ -727,7 +767,7 @@ _hidden int libxl__ev_fd_modify(libxl__gc*, libxl__ev_fd *ev,
_hidden void libxl__ev_fd_deregister(libxl__gc*, libxl__ev_fd *ev);
static inline void libxl__ev_fd_init(libxl__ev_fd *efd)
{ efd->fd = -1; }
-static inline int libxl__ev_fd_isregistered(libxl__ev_fd *efd)
+static inline int libxl__ev_fd_isregistered(const libxl__ev_fd *efd)
{ return efd->fd >= 0; }
_hidden int libxl__ev_time_register_rel(libxl__gc*, libxl__ev_time *ev_out,
@@ -743,7 +783,7 @@ _hidden int libxl__ev_time_modify_abs(libxl__gc*, libxl__ev_time *ev,
_hidden void libxl__ev_time_deregister(libxl__gc*, libxl__ev_time *ev);
static inline void libxl__ev_time_init(libxl__ev_time *ev)
{ ev->func = 0; }
-static inline int libxl__ev_time_isregistered(libxl__ev_time *ev)
+static inline int libxl__ev_time_isregistered(const libxl__ev_time *ev)
{ return !!ev->func; }
@@ -759,6 +799,39 @@ static inline int libxl__ev_xswatch_isregistered(const libxl__ev_xswatch *xw)
/*
+ * The evtchn facility is one-shot per call to libxl__ev_evtchn_wait.
+ * You should call some suitable xc bind function on (or to obtain)
+ * the port, then libxl__ev_evtchn_wait.
+ *
+ * When the event is signaled then the callback will be made, once.
+ * Then you must call libxl__ev_evtchn_wait again, if desired.
+ *
+ * You must NOT call xc_evtchn_unmask. wait will do that for you.
+ *
+ * Calling libxl__ev_evtchn_cancel will arrange for libxl to disregard
+ * future occurrences of event. Both libxl__ev_evtchn_wait and
+ * libxl__ev_evtchn_cancel are idempotent.
+ *
+ * (Note of course that an event channel becomes signaled when it is
+ * first bound, so you will get one call to libxl__ev_evtchn_wait
+ * "right away"; unless you have won a very fast race, the condition
+ * you were waiting for won't exist yet so when you check for it
+ * you'll find you need to call wait again.)
+ *
+ * You must not wait on the same port twice at once (that is, with
+ * two separate libxl__ev_evtchn's).
+ */
+_hidden int libxl__ev_evtchn_wait(libxl__gc*, libxl__ev_evtchn *evev);
+_hidden void libxl__ev_evtchn_cancel(libxl__gc *gc, libxl__ev_evtchn *evev);
+
+static inline void libxl__ev_evtchn_init(libxl__ev_evtchn *evev)
+ { evev->waiting = 0; }
+static inline bool libxl__ev_evtchn_iswaiting(const libxl__ev_evtchn *evev)
+ { return evev->waiting; }
+
+_hidden int libxl__ctx_evtchn_init(libxl__gc *gc); /* for libxl_ctx_alloc */
+
+/*
* For making subprocesses. This is the only permitted mechanism for
* code in libxl to do so.
*
@@ -783,7 +856,7 @@ _hidden pid_t libxl__ev_child_fork(libxl__gc *gc, libxl__ev_child *childw_out,
libxl__ev_child_callback *death);
static inline void libxl__ev_child_init(libxl__ev_child *childw_out)
{ childw_out->pid = -1; }
-static inline int libxl__ev_child_inuse(libxl__ev_child *childw_out)
+static inline int libxl__ev_child_inuse(const libxl__ev_child *childw_out)
{ return childw_out->pid >= 0; }
/* Useable (only) in the child to once more make the ctx useable for
@@ -834,13 +907,13 @@ _hidden void libxl__event_disaster(libxl__egc*, const char *msg, int errnoval,
/* Fills in, or disposes of, the resources held by, a poller whose
* space the caller has allocated. ctx must be locked. */
-_hidden int libxl__poller_init(libxl_ctx *ctx, libxl__poller *p);
+_hidden int libxl__poller_init(libxl__gc *gc, libxl__poller *p);
_hidden void libxl__poller_dispose(libxl__poller *p);
/* Obtain a fresh poller from malloc or the idle list, and put it
* away again afterwards. _get can fail, returning NULL.
* ctx must be locked. */
-_hidden libxl__poller *libxl__poller_get(libxl_ctx *ctx);
+_hidden libxl__poller *libxl__poller_get(libxl__gc *gc);
_hidden void libxl__poller_put(libxl_ctx*, libxl__poller *p /* may be NULL */);
/* Notifies whoever is polling using p that they should wake up.
@@ -880,6 +953,8 @@ _hidden int libxl__domain_cpupool(libxl__gc *gc, uint32_t domid);
_hidden libxl_scheduler libxl__domain_scheduler(libxl__gc *gc, uint32_t domid);
_hidden int libxl__sched_set_params(libxl__gc *gc, uint32_t domid,
libxl_domain_sched_params *scparams);
+_hidden int libxl__grant_vga_iomem_permission(libxl__gc *gc, const uint32_t domid,
+ libxl_domain_config *const d_config);
typedef struct {
uint32_t store_port;
@@ -890,8 +965,6 @@ typedef struct {
uint32_t console_domid;
unsigned long console_mfn;
- unsigned long vm_generationid_addr;
-
char *saved_state;
libxl__file_reference pv_kernel;
@@ -923,7 +996,20 @@ _hidden int libxl__toolstack_restore(uint32_t domid, const uint8_t *buf,
uint32_t size, void *data);
_hidden int libxl__domain_resume_device_model(libxl__gc *gc, uint32_t domid);
+_hidden const char *libxl__userdata_path(libxl__gc *gc, uint32_t domid,
+ const char *userdata_userid,
+ const char *wh);
_hidden void libxl__userdata_destroyall(libxl__gc *gc, uint32_t domid);
+/* Caller must hold userdata store lock before calling
+ * libxl__userdata_{retrieve,store}
+ * See libxl__{un,}lock_domain_userdata.
+ */
+_hidden int libxl__userdata_retrieve(libxl__gc *gc, uint32_t domid,
+ const char *userdata_userid,
+ uint8_t **data_r, int *datalen_r);
+_hidden int libxl__userdata_store(libxl__gc *gc, uint32_t domid,
+ const char *userdata_userid,
+ const uint8_t *data, int datalen);
_hidden int libxl__domain_resume(libxl__gc *gc, uint32_t domid,
int suspend_cancel);
@@ -931,6 +1017,7 @@ _hidden int libxl__domain_resume(libxl__gc *gc, uint32_t domid,
/* returns 0 or 1, or a libxl error code */
_hidden int libxl__domain_pvcontrol_available(libxl__gc *gc, uint32_t domid);
+_hidden const char *libxl__domain_pvcontrol_xspath(libxl__gc*, uint32_t domid);
_hidden char * libxl__domain_pvcontrol_read(libxl__gc *gc,
xs_transaction_t t, uint32_t domid);
_hidden int libxl__domain_pvcontrol_write(libxl__gc *gc, xs_transaction_t t,
@@ -947,8 +1034,12 @@ _hidden int libxl__device_disk_dev_number(const char *virtpath,
_hidden int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
libxl__device_console *console,
- libxl__domain_build_state *state);
+ libxl__domain_build_state *state,
+ libxl__device *device);
+/* Returns 1 if device exists, 0 if not, ERROR_* (<0) on error. */
+_hidden int libxl__device_exists(libxl__gc *gc, xs_transaction_t t,
+ libxl__device *device);
_hidden int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, char **bents, char **fents, char **ro_fents);
_hidden char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device);
@@ -960,6 +1051,10 @@ _hidden int libxl__wait_for_backend(libxl__gc *gc, const char *be_path,
const char *state);
_hidden int libxl__nic_type(libxl__gc *gc, libxl__device *dev,
libxl_nic_type *nictype);
+_hidden int libxl__init_console_from_channel(libxl__gc *gc,
+ libxl__device_console *console,
+ int dev_num,
+ libxl_device_channel *channel);
/*
* For each aggregate type which can be used as an input we provide:
@@ -1080,6 +1175,60 @@ _hidden int libxl__create_pci_backend(libxl__gc *gc, uint32_t domid,
libxl_device_pci *pcidev, int num);
_hidden int libxl__device_pci_destroy_all(libxl__gc *gc, uint32_t domid);
+/*----- xswait: wait for a xenstore node to be suitable -----*/
+
+typedef struct libxl__xswait_state libxl__xswait_state;
+
+/*
+ * rc describes the circumstances of this callback:
+ *
+ * rc==0
+ *
+ * The xenstore path (may have) changed. It has been read for
+ * you. The result is in data (allocated from the ao gc).
+ * data may be NULL, which means that the xenstore read gave
+ * ENOENT.
+ *
+ * If you are satisfied, you MUST call libxl__xswait_stop.
+ * Otherwise, xswait will continue waiting and watching and
+ * will call you back later.
+ *
+ * rc==ERROR_TIMEDOUT
+ *
+ * The specified timeout was reached.
+ * This has NOT been logged (except to the debug log).
+ * xswait will not continue (but calling libxl__xswait_stop is OK).
+ *
+ * rc!=0, !=ERROR_TIMEDOUT
+ *
+ * Some other error occurred.
+ * This HAS been logged.
+ * xswait will not continue (but calling libxl__xswait_stop is OK).
+ *
+ * xswait.path may start with with '@', in which case no read is done
+ * and the callback will always get data==0.
+ */
+typedef void libxl__xswait_callback(libxl__egc *egc,
+ libxl__xswait_state *xswa, int rc, const char *data);
+
+struct libxl__xswait_state {
+ /* caller must fill these in, and they must all remain valid */
+ libxl__ao *ao;
+ const char *what; /* for error msgs: noun phrase, what we're waiting for */
+ const char *path;
+ int timeout_ms; /* as for poll(2) */
+ libxl__xswait_callback *callback;
+ /* remaining fields are private to xswait */
+ libxl__ev_time time_ev;
+ libxl__ev_xswatch watch_ev;
+};
+
+void libxl__xswait_init(libxl__xswait_state*);
+void libxl__xswait_stop(libxl__gc*, libxl__xswait_state*); /*idempotent*/
+bool libxl__xswait_inuse(const libxl__xswait_state *ss);
+
+int libxl__xswait_start(libxl__gc*, libxl__xswait_state*);
+
/*
*----- spawn -----
*
@@ -1221,11 +1370,10 @@ struct libxl__spawn_state {
int detaching; /* we are in Detaching */
int failed; /* might be true whenever we are not Idle */
libxl__ev_child mid; /* always in use whenever we are not Idle */
- libxl__ev_time timeout;
- libxl__ev_xswatch xswatch;
+ libxl__xswait_state xswait;
};
-static inline int libxl__spawn_inuse(libxl__spawn_state *ss)
+static inline int libxl__spawn_inuse(const libxl__spawn_state *ss)
{ return libxl__ev_child_inuse(&ss->mid); }
/*
@@ -1296,6 +1444,11 @@ _hidden int libxl__xenstore_child_wait_deprecated(libxl__gc *gc,
*
* The last entry of the array always has to be NULL.
*
+ * stdinfd, stdoutfd, stderrfd will be dup2'd onto the corresponding
+ * fd in the child, if they are not -1. The original copy of the
+ * descriptor will be closed in the child (unless it's 0, 1 or 2
+ * ie the source descriptor is itself stdin, stdout or stderr).
+ *
* Logs errors, never returns.
*/
_hidden void libxl__exec(libxl__gc *gc, int stdinfd, int stdoutfd,
@@ -1321,7 +1474,8 @@ _hidden const char *libxl__domain_device_model(libxl__gc *gc,
_hidden int libxl__need_xenpv_qemu(libxl__gc *gc,
int nr_consoles, libxl__device_console *consoles,
int nr_vfbs, libxl_device_vfb *vfbs,
- int nr_disks, libxl_device_disk *disks);
+ int nr_disks, libxl_device_disk *disks,
+ int nr_channels, libxl_device_channel *channels);
/*
* This function will cause the whole libxl process to hang
@@ -1422,6 +1576,8 @@ struct libxl__xen_console_reader {
_hidden int libxl__parse_mac(const char *s, libxl_mac mac);
/* compare mac address @a and @b. 0 if the same, -ve if a<b and +ve if a>b */
_hidden int libxl__compare_macs(libxl_mac *a, libxl_mac *b);
+/* return true if mac address is all zero (the default value) */
+_hidden int libxl__mac_is_default(libxl_mac *mac);
/* init a recursive mutex */
_hidden int libxl__init_recursive_mutex(libxl_ctx *ctx, pthread_mutex_t *lock);
@@ -1484,16 +1640,16 @@ _hidden yajl_gen_status libxl__yajl_gen_asciiz(yajl_gen hand, const char *str);
_hidden yajl_gen_status libxl__yajl_gen_enum(yajl_gen hand, const char *str);
typedef enum {
- JSON_NULL,
- JSON_BOOL,
- JSON_INTEGER,
- JSON_DOUBLE,
+ JSON_NULL = (1 << 0),
+ JSON_BOOL = (1 << 1),
+ JSON_INTEGER = (1 << 2),
+ JSON_DOUBLE = (1 << 3),
/* number is store in string, it's too big to be a long long or a double */
- JSON_NUMBER,
- JSON_STRING,
- JSON_MAP,
- JSON_ARRAY,
- JSON_ANY
+ JSON_NUMBER = (1 << 4),
+ JSON_STRING = (1 << 5),
+ JSON_MAP = (1 << 6),
+ JSON_ARRAY = (1 << 7),
+ JSON_ANY = 255 /* this is a mask of all values above, adjust as needed */
} libxl__json_node_type;
typedef struct libxl__json_object {
@@ -1511,6 +1667,14 @@ typedef struct libxl__json_object {
struct libxl__json_object *parent;
} libxl__json_object;
+typedef int (*libxl__json_parse_callback)(libxl__gc *gc,
+ libxl__json_object *o,
+ void *p);
+_hidden int libxl__object_from_json(libxl_ctx *ctx, const char *type,
+ libxl__json_parse_callback parse,
+ void *p,
+ const char *s);
+
typedef struct {
char *map_key;
libxl__json_object *obj;
@@ -1518,6 +1682,10 @@ typedef struct {
typedef struct libxl__yajl_ctx libxl__yajl_ctx;
+static inline bool libxl__json_object_is_null(const libxl__json_object *o)
+{
+ return o != NULL && o->type == JSON_NULL;
+}
static inline bool libxl__json_object_is_bool(const libxl__json_object *o)
{
return o != NULL && o->type == JSON_BOOL;
@@ -1530,6 +1698,14 @@ static inline bool libxl__json_object_is_integer(const libxl__json_object *o)
{
return o != NULL && o->type == JSON_INTEGER;
}
+static inline bool libxl__json_object_is_double(const libxl__json_object *o)
+{
+ return o != NULL && o->type == JSON_DOUBLE;
+}
+static inline bool libxl__json_object_is_number(const libxl__json_object *o)
+{
+ return o != NULL && o->type == JSON_NUMBER;
+}
static inline bool libxl__json_object_is_map(const libxl__json_object *o)
{
return o != NULL && o->type == JSON_MAP;
@@ -1555,6 +1731,14 @@ const char *libxl__json_object_get_string(const libxl__json_object *o)
return NULL;
}
static inline
+const char *libxl__json_object_get_number(const libxl__json_object *o)
+{
+ if (libxl__json_object_is_number(o))
+ return o->u.string;
+ else
+ return NULL;
+}
+static inline
flexarray_t *libxl__json_object_get_map(const libxl__json_object *o)
{
if (libxl__json_object_is_map(o))
@@ -1586,7 +1770,7 @@ _hidden libxl__json_object *libxl__json_object_alloc(libxl__gc *gc_opt,
libxl__json_node_type type);
_hidden int libxl__json_object_append_to(libxl__gc *gc_opt,
libxl__json_object *obj,
- libxl__json_object *dst);
+ libxl__yajl_ctx *ctx);
_hidden libxl__json_object *libxl__json_array_get(const libxl__json_object *o,
int i);
_hidden
@@ -1893,7 +2077,6 @@ _hidden int libxl__carefd_close(libxl__carefd*);
_hidden int libxl__carefd_fd(const libxl__carefd*);
/* common paths */
-_hidden const char *libxl__libexec_path(void);
_hidden const char *libxl__private_bindir_path(void);
_hidden const char *libxl__xenfirmwaredir_path(void);
_hidden const char *libxl__xen_config_dir_path(void);
@@ -1901,6 +2084,33 @@ _hidden const char *libxl__xen_script_dir_path(void);
_hidden const char *libxl__lock_dir_path(void);
_hidden const char *libxl__run_dir_path(void);
+/*----- subprocess execution with timeout -----*/
+
+typedef struct libxl__async_exec_state libxl__async_exec_state;
+
+typedef void libxl__async_exec_callback(libxl__egc *egc,
+ libxl__async_exec_state *aes, int status);
+
+struct libxl__async_exec_state {
+ /* caller must fill these in */
+ libxl__ao *ao;
+ const char *what; /* for error msgs, what we're executing */
+ int timeout_ms;
+ libxl__async_exec_callback *callback;
+ /* caller must fill in; as for libxl__exec */
+ int stdfds[3];
+ char **args; /* execution arguments */
+ char **env; /* execution environment */
+
+ /* private */
+ libxl__ev_time time;
+ libxl__ev_child child;
+};
+
+void libxl__async_exec_init(libxl__async_exec_state *aes);
+int libxl__async_exec_start(libxl__gc *gc, libxl__async_exec_state *aes);
+bool libxl__async_exec_inuse(const libxl__async_exec_state *aes);
+
/*----- device addition/removal -----*/
typedef struct libxl__ao_device libxl__ao_device;
@@ -1937,13 +2147,16 @@ struct libxl__ao_device {
libxl__multidev *multidev; /* reference to the containing multidev */
/* private for add/remove implementation */
libxl__ev_devstate backend_ds;
- /* Bodge for Qemu devices, also used for timeout of hotplug execution */
+ /* Bodge for Qemu devices */
libxl__ev_time timeout;
/* xenstore watch for backend path of driver domains */
libxl__ev_xswatch xs_watch;
- /* device hotplug execution */
- const char *what;
int num_exec;
+ /* for calling hotplug scripts */
+ libxl__async_exec_state aes;
+ /* If we need to update JSON config */
+ bool update_json;
+ /* for asynchronous execution of synchronous-only syscalls etc. */
libxl__ev_child child;
};
@@ -1955,20 +2168,42 @@ struct libxl__ao_device {
* multidev->callback = ...
* Then zero or more times
* libxl__multidev_prepare
- * libal__initiate_device_{remove/addition}.
+ * libxl__initiate_device_{remove/addition}
+ * (or some other thing which will eventually call
+ * aodev->callback or libxl__multidev_one_callback)
* Finally, once
* libxl__multidev_prepared
- * which will result (perhaps reentrantly) in one call to callback().
+ * which will result (perhaps reentrantly) in one call to
+ * multidev->callback().
*/
/* Starts preparing to add/remove a bunch of devices. */
_hidden void libxl__multidev_begin(libxl__ao *ao, libxl__multidev*);
-/* Prepares to add/remove one of many devices. Returns a libxl__ao_device
- * which has had libxl__prepare_ao_device called, and which has also
- * had ->callback set. The user should not mess with aodev->callback. */
+/* Prepares to add/remove one of many devices.
+ * Calls libxl__prepare_ao_device on libxl__ao_device argument provided and
+ * also sets the aodev->callback (to libxl__multidev_one_callback)
+ * The user should not mess with aodev->callback.
+ */
+_hidden void libxl__multidev_prepare_with_aodev(libxl__multidev*,
+ libxl__ao_device*);
+
+/* A wrapper function around libxl__multidev_prepare_with_aodev.
+ * Allocates a libxl__ao_device and prepares it for addition/removal.
+ * Returns the newly allocated libxl__ao_dev.
+ */
_hidden libxl__ao_device *libxl__multidev_prepare(libxl__multidev*);
+/* Indicates to multidev that this one device has been processed.
+ * Normally the multidev user does not need to touch this function, as
+ * multidev_prepare will name it in aodev->callback. However, if you
+ * want to do something more complicated you can set aodev->callback
+ * yourself to something else, so long as you eventually call
+ * libxl__multidev_one_callback.
+ */
+_hidden void libxl__multidev_one_callback(libxl__egc *egc,
+ libxl__ao_device *aodev);
+
/* Notifies the multidev machinery that we have now finished preparing
* and initiating devices. multidev->callback may then be called as
* soon as there are no prepared but not completed operations
@@ -2069,6 +2304,77 @@ struct libxl__multidev {
*
* Once finished, aodev->callback will be executed.
*/
+/*
+ * As of Xen 4.5 we maintain various infomation, including hotplug
+ * device information, in JSON files, so that we can use this JSON
+ * file as a template to reconstruct domain configuration.
+ *
+ * In essense there are now two views of device state, one is xenstore,
+ * the other is JSON file. We use xenstore as primary reference.
+ *
+ * Here we maintain one invariant: every device in xenstore must have
+ * an entry in JSON file.
+ *
+ * All device hotplug routines should comply to following pattern:
+ * lock json config (json_lock)
+ * read json config
+ * update in-memory json config with new entry, replacing
+ * any stale entry
+ * for loop -- xs transaction
+ * open xs transaction
+ * check device existence, abort if it exists
+ * write in-memory json config to disk
+ * commit xs transaction
+ * end for loop
+ * unlock json config
+ *
+ * Device removal routines are not touched.
+ *
+ * Here is the proof that we always maintain that invariant and we
+ * don't leak files during interaction of hotplug thread and other
+ * threads / processes.
+ *
+ * # Safe against parallel add
+ *
+ * When another thread / process tries to add same device, it's
+ * blocked by json_lock. The loser of two threads will bail at
+ * existence check, so that we don't overwrite anything.
+ *
+ * # Safe against domain destruction
+ *
+ * If the thread / process trying to destroy domain loses the race, it's
+ * blocked by json_lock. If the hotplug thread is loser, it bails at
+ * acquiring lock because lock acquisition function checks existence of
+ * the domain.
+ *
+ * # Safe against parallel removal
+ *
+ * When another thread / process tries to remove a device, it's _NOT_
+ * blocked by json_lock, but xenstore transaction can help maintain
+ * invariant. The removal threads either a) sees that device in
+ * xenstore, b) doesn't see that device in xenstore.
+ *
+ * In a), it sees that device in xenstore. At that point hotplug is
+ * already finished (both JSON and xenstore changes committed). So that
+ * device can be safely removed. JSON entry is left untouched and
+ * becomes stale, but this is a valid state -- next time when a
+ * device with same identifier gets added, the stale entry gets
+ * overwritten.
+ *
+ * In b), it doesn't see that device in xenstore, but it will commence
+ * anyway. Eventually a forcibly removal is initiated, which will forcely
+ * remove xenstore entry.
+ *
+ * If hotplug threads creates xenstore entry (therefore JSON entry as
+ * well) before force removal, that xenstore entry is removed. We're
+ * left with JSON stale entry but not xenstore entry, which is a valid
+ * state.
+ *
+ * If hotplug thread has not created xenstore entry when the removal
+ * is committed, we're obviously safe. Hotplug thread will add in
+ * xenstore entry afterwards. We have both JSON and xenstore entry,
+ * it's a valid state.
+ */
_hidden void libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
libxl_device_disk *disk,
libxl__ao_device *aodev);
@@ -2286,6 +2592,182 @@ typedef struct libxl__save_helper_state {
* marshalling and xc callback functions */
} libxl__save_helper_state;
+/*----- remus device related state structure -----*/
+/*
+ * The abstract Remus device layer exposes a common
+ * set of API to [external] libxl for manipulating devices attached to
+ * a guest protected by Remus. The device layer also exposes a set of
+ * [internal] interfaces that every device type must implement.
+ *
+ * The following API are exposed to libxl:
+ *
+ * One-time configuration operations:
+ * +libxl__remus_devices_setup
+ * > Enable output buffering for NICs, setup disk replication, etc.
+ * +libxl__remus_devices_teardown
+ * > Disable output buffering and disk replication; teardown any
+ * associated external setups like qdiscs for NICs.
+ *
+ * Operations executed every checkpoint (in order of invocation):
+ * +libxl__remus_devices_postsuspend
+ * +libxl__remus_devices_preresume
+ * +libxl__remus_devices_commit
+ *
+ * Each device type needs to implement the interfaces specified in
+ * the libxl__remus_device_instance_ops if it wishes to support Remus.
+ *
+ * The high-level control flow through the Remus device layer is shown below:
+ *
+ * xl remus
+ * |-> libxl_domain_remus_start
+ * |-> libxl__remus_devices_setup
+ * |-> Per-checkpoint libxl__remus_devices_[postsuspend,preresume,commit]
+ * ...
+ * |-> On backup failure, network error or other internal errors:
+ * libxl__remus_devices_teardown
+ */
+
+typedef struct libxl__remus_device libxl__remus_device;
+typedef struct libxl__remus_devices_state libxl__remus_devices_state;
+typedef struct libxl__remus_device_instance_ops libxl__remus_device_instance_ops;
+
+/*
+ * Interfaces to be implemented by every device subkind that wishes to
+ * support Remus. Functions must be implemented unless otherwise
+ * stated. Many of these functions are asynchronous. They call
+ * dev->aodev.callback when done. The actual implementations may be
+ * synchronous and call dev->aodev.callback directly (as the last
+ * thing they do).
+ */
+struct libxl__remus_device_instance_ops {
+ /* the device kind this ops belongs to... */
+ libxl__device_kind kind;
+
+ /*
+ * Checkpoint operations. May be NULL, meaning the op is not
+ * implemented and the caller should treat them as a no-op (and do
+ * nothing when checkpointing).
+ * Asynchronous.
+ */
+
+ void (*postsuspend)(libxl__egc *egc, libxl__remus_device *dev);
+ void (*preresume)(libxl__egc *egc, libxl__remus_device *dev);
+ void (*commit)(libxl__egc *egc, libxl__remus_device *dev);
+
+ /*
+ * setup() and teardown() are refer to the actual remus device.
+ * Asynchronous.
+ * teardown is called even if setup fails.
+ */
+ /*
+ * setup() should first determines whether the subkind matches the specific
+ * device. If matched, the device will then be managed with this set of
+ * subkind operations.
+ * Yields 0 if the device successfully set up.
+ * REMUS_DEVOPS_DOES_NOT_MATCH if the ops does not match the device.
+ * any other rc indicates failure.
+ */
+ void (*setup)(libxl__egc *egc, libxl__remus_device *dev);
+ void (*teardown)(libxl__egc *egc, libxl__remus_device *dev);
+};
+
+int init_subkind_nic(libxl__remus_devices_state *rds);
+void cleanup_subkind_nic(libxl__remus_devices_state *rds);
+int init_subkind_drbd_disk(libxl__remus_devices_state *rds);
+void cleanup_subkind_drbd_disk(libxl__remus_devices_state *rds);
+
+typedef void libxl__remus_callback(libxl__egc *,
+ libxl__remus_devices_state *, int rc);
+
+/*
+ * State associated with a remus invocation, including parameters
+ * passed to the remus abstract device layer by the remus
+ * save/restore machinery.
+ */
+struct libxl__remus_devices_state {
+ /*---- must be set by caller of libxl__remus_device_(setup|teardown) ----*/
+
+ libxl__ao *ao;
+ uint32_t domid;
+ libxl__remus_callback *callback;
+ int device_kind_flags;
+
+ /*----- private for abstract layer only -----*/
+
+ int num_devices;
+ /*
+ * this array is allocated before setup the remus devices by the
+ * remus abstract layer.
+ * devs may be NULL, means there's no remus devices that has been set up.
+ * the size of this array is 'num_devices', which is the total number
+ * of libxl nic devices and disk devices(num_nics + num_disks).
+ */
+ libxl__remus_device **devs;
+
+ libxl_device_nic *nics;
+ int num_nics;
+ libxl_device_disk *disks;
+ int num_disks;
+
+ libxl__multidev multidev;
+
+ /*----- private for concrete (device-specific) layer only -----*/
+
+ /* private for nic device subkind ops */
+ char *netbufscript;
+ struct nl_sock *nlsock;
+ struct nl_cache *qdisc_cache;
+
+ /* private for drbd disk subkind ops */
+ char *drbd_probe_script;
+};
+
+/*
+ * Information about a single device being handled by remus.
+ * Allocated by the remus abstract layer.
+ */
+struct libxl__remus_device {
+ /*----- shared between abstract and concrete layers -----*/
+ /*
+ * if this is true, that means the subkind ops match the device
+ */
+ bool matched;
+
+ /*----- set by remus device abstruct layer -----*/
+ /* libxl__device_* which this remus device related to */
+ const void *backend_dev;
+ libxl__device_kind kind;
+ libxl__remus_devices_state *rds;
+ libxl__ao_device aodev;
+
+ /*----- private for abstract layer only -----*/
+
+ /*
+ * Control and state variables for the asynchronous callback
+ * based loops which iterate over device subkinds, and over
+ * individual devices.
+ */
+ int ops_index;
+ const libxl__remus_device_instance_ops *ops;
+
+ /*----- private for concrete (device-specific) layer -----*/
+
+ /* concrete device's private data */
+ void *concrete_data;
+};
+
+/* the following 5 APIs are async ops, call rds->callback when done */
+_hidden void libxl__remus_devices_setup(libxl__egc *egc,
+ libxl__remus_devices_state *rds);
+_hidden void libxl__remus_devices_teardown(libxl__egc *egc,
+ libxl__remus_devices_state *rds);
+_hidden void libxl__remus_devices_postsuspend(libxl__egc *egc,
+ libxl__remus_devices_state *rds);
+_hidden void libxl__remus_devices_preresume(libxl__egc *egc,
+ libxl__remus_devices_state *rds);
+_hidden void libxl__remus_devices_commit(libxl__egc *egc,
+ libxl__remus_devices_state *rds);
+_hidden int libxl__netbuffer_enabled(libxl__gc *gc);
/*----- Domain suspend (save) state structure -----*/
@@ -2316,15 +2798,22 @@ struct libxl__domain_suspend_state {
int debug;
const libxl_domain_remus_info *remus;
/* private */
- xc_evtchn *xce; /* event channel handle */
- int suspend_eventchn;
+ libxl__ev_evtchn guest_evtchn;
+ int guest_evtchn_lockfd;
int hvm;
int xcflags;
int guest_responded;
+ libxl__xswait_state pvcontrol;
+ libxl__ev_xswatch guest_watch;
+ libxl__ev_time guest_timeout;
const char *dm_savefile;
+ libxl__remus_devices_state rds;
+ libxl__ev_time checkpoint_timeout; /* used for Remus checkpoint */
int interval; /* checkpoint interval (for Remus) */
libxl__save_helper_state shs;
libxl__logdirty_switch logdirty;
+ void (*callback_common_done)(libxl__egc*,
+ struct libxl__domain_suspend_state*, int ok);
/* private for libxl__domain_save_device_model */
libxl__save_device_model_cb *save_dm_callback;
libxl__datacopier_state save_dm_datacopier;
@@ -2577,6 +3066,7 @@ struct libxl__domain_create_state {
/* filled in by user */
libxl__ao *ao;
libxl_domain_config *guest_config;
+ libxl_domain_config guest_config_saved; /* vanilla config */
int restore_fd;
libxl__domain_create_cb *callback;
libxl_asyncprogress_how aop_console_how;
@@ -2602,8 +3092,7 @@ _hidden void libxl__domain_suspend(libxl__egc *egc,
/* calls libxl__xc_domain_suspend_done when done */
-_hidden void libxl__xc_domain_save(libxl__egc*, libxl__domain_suspend_state*,
- unsigned long vm_generationid_addr);
+_hidden void libxl__xc_domain_save(libxl__egc*, libxl__domain_suspend_state*);
/* If rc==0 then retval is the return value from xc_domain_save
* and errnoval is the errno value it provided.
* If rc!=0, retval and errnoval are undefined. */
@@ -2617,7 +3106,7 @@ _hidden void libxl__xc_domain_save_done(libxl__egc*, void *dss_void,
void libxl__xc_domain_saverestore_async_callback_done(libxl__egc *egc,
libxl__save_helper_state *shs, int return_value);
-_hidden int libxl__domain_suspend_common_callback(void *data);
+
_hidden void libxl__domain_suspend_common_switch_qemu_logdirty
(int domid, unsigned int enable, void *data);
_hidden int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
@@ -2627,8 +3116,7 @@ _hidden int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
/* calls libxl__xc_domain_restore_done when done */
_hidden void libxl__xc_domain_restore(libxl__egc *egc,
libxl__domain_create_state *dcs,
- int hvm, int pae, int superpages,
- int no_incr_generationid);
+ int hvm, int pae, int superpages);
/* If rc==0 then retval is the return value from xc_domain_save
* and errnoval is the errno value it provided.
* If rc!=0, retval and errnoval are undefined. */
@@ -2901,6 +3389,22 @@ void libxl__numa_candidate_put_nodemap(libxl__gc *gc,
libxl_bitmap_copy(CTX, &cndt->nodemap, nodemap);
}
+_hidden int libxl__ms_vm_genid_set(libxl__gc *gc, uint32_t domid,
+ const libxl_ms_vm_genid *id);
+
+
+/* Som handy macros for defbool type. */
+#define LIBXL__DEFBOOL_DEFAULT (0)
+#define LIBXL__DEFBOOL_FALSE (-1)
+#define LIBXL__DEFBOOL_TRUE (1)
+#define LIBXL__DEFBOOL_STR_DEFAULT "<default>"
+#define LIBXL__DEFBOOL_STR_FALSE "False"
+#define LIBXL__DEFBOOL_STR_TRUE "True"
+static inline int libxl__defbool_is_default(libxl_defbool *db)
+{
+ return !db->val;
+}
+
/*
* Inserts "elm_new" into the sorted list "head".
*
@@ -2950,7 +3454,180 @@ void libxl__numa_candidate_put_nodemap(libxl__gc *gc,
*/
#define CTYPE(isfoo,c) (isfoo((unsigned char)(c)))
+int libxl__defbool_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ libxl_defbool *p);
+int libxl__bool_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ bool *p);
+int libxl__mac_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ libxl_mac *p);
+int libxl__bitmap_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ libxl_bitmap *p);
+int libxl__uuid_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ libxl_uuid *p);
+int libxl__cpuid_policy_list_parse_json(libxl__gc *gc,
+ const libxl__json_object *o,
+ libxl_cpuid_policy_list *p);
+int libxl__string_list_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ libxl_string_list *p);
+int libxl__key_value_list_parse_json(libxl__gc *gc,
+ const libxl__json_object *o,
+ libxl_key_value_list *p);
+int libxl__hwcap_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ libxl_hwcap *p);
+int libxl__ms_vm_genid_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ libxl_ms_vm_genid *p);
+int libxl__int_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ void *p);
+int libxl__uint8_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ void *p);
+int libxl__uint16_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ void *p);
+int libxl__uint32_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ void *p);
+int libxl__uint64_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ void *p);
+int libxl__string_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ char **p);
+
+int libxl__random_bytes(libxl__gc *gc, uint8_t *buf, size_t len);
+
+/*
+ * Compile time assertion
+ */
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+#define BUILD_BUG_ON(p) ({ _Static_assert(!(p), "!(" #p ")"); })
+#else
+#define BUILD_BUG_ON(p) ((void)sizeof(char[1 - 2 * !!(p)]))
+#endif
+#include "_libxl_types_private.h"
+#include "_libxl_types_internal_private.h"
+
+/* This always return false, there's no "default value" for hw cap */
+static inline int libxl__hwcap_is_default(libxl_hwcap *hwcap)
+{
+ return 0;
+}
+static inline int libxl__string_list_is_empty(libxl_string_list *psl)
+{
+ return !libxl_string_list_length(psl);
+}
+
+static inline int libxl__key_value_list_is_empty(libxl_key_value_list *pkvl)
+{
+ return !libxl_key_value_list_length(pkvl);
+}
+
+int libxl__cpuid_policy_is_empty(libxl_cpuid_policy_list *pl);
+
+/* Portability note: a proper flock(2) implementation is required */
+typedef struct {
+ libxl__carefd *lock_carefd;
+ char *path; /* path of the lock file itself */
+} libxl__domain_userdata_lock;
+libxl__domain_userdata_lock *libxl__lock_domain_userdata(libxl__gc *gc,
+ uint32_t domid);
+void libxl__unlock_domain_userdata(libxl__domain_userdata_lock *lock);
+
+/*
+ * Retrieve / store domain configuration from / to libxl private
+ * data store. The registry entry in libxl private data store
+ * is "libxl-json".
+ * Caller must hold user data lock.
+ */
+int libxl__get_domain_configuration(libxl__gc *gc, uint32_t domid,
+ libxl_domain_config *d_config);
+int libxl__set_domain_configuration(libxl__gc *gc, uint32_t domid,
+ libxl_domain_config *d_config);
+
+/* ------ Things related to updating domain configurations ----- */
+void libxl__update_domain_configuration(libxl__gc *gc,
+ libxl_domain_config *dst,
+ const libxl_domain_config *src);
+static inline void libxl__update_config_nic(libxl__gc *gc,
+ libxl_device_nic *dst,
+ libxl_device_nic *src)
+{
+ dst->devid = src->devid;
+ libxl_mac_copy(CTX, &dst->mac, &src->mac);
+}
+
+static inline void libxl__update_config_vtpm(libxl__gc *gc,
+ libxl_device_vtpm *dst,
+ libxl_device_vtpm *src)
+{
+ dst->devid = src->devid;
+ libxl_uuid_copy(CTX, &dst->uuid, &src->uuid);
+}
+
+/* Macros used to compare device identifier. Returns true if the two
+ * devices have same identifier. */
+#define COMPARE_DEVID(a, b) ((a)->devid == (b)->devid)
+#define COMPARE_DISK(a, b) (!strcmp((a)->vdev, (b)->vdev))
+#define COMPARE_PCI(a, b) ((a)->func == (b)->func && \
+ (a)->bus == (b)->bus && \
+ (a)->dev == (b)->dev)
+
+/* DEVICE_ADD
+ *
+ * Add a device in libxl_domain_config structure
+ *
+ * It takes 6 parameters:
+ * type: the type of the device, say nic, vtpm, disk, pci etc
+ * ptr: pointer to the start of the array, the array must be
+ * of type libxl_device_#type
+ * domid: domain id of target domain
+ * dev: the device that is to be added / removed / updated
+ * compare: the COMPARE_* macro used to compare @dev's identifier to
+ * those in the array pointed to by @ptr
+ * d_config: pointer to template domain config
+ *
+ * For most device types (nic, vtpm), the array pointer @ptr can be
+ * derived from @type, pci device being the exception, hence we need
+ * to have @ptr.
+ *
+ * If there is already a device with the same identifier in d_config,
+ * that entry is updated.
+ */
+#define DEVICE_ADD(type, ptr, domid, dev, compare, d_config) \
+ ({ \
+ int DA_x; \
+ libxl_device_##type *DA_p = NULL; \
+ \
+ /* Check for existing device */ \
+ for (DA_x = 0; DA_x < (d_config)->num_##ptr; DA_x++) { \
+ if (compare(&(d_config)->ptr[DA_x], (dev))) { \
+ DA_p = &(d_config)->ptr[DA_x]; \
+ break; \
+ } \
+ } \
+ \
+ if (!DA_p) { \
+ (d_config)->ptr = \
+ libxl__realloc(NOGC, (d_config)->ptr, \
+ ((d_config)->num_##ptr + 1) * \
+ sizeof(libxl_device_##type)); \
+ DA_p = &(d_config)->ptr[(d_config)->num_##ptr]; \
+ (d_config)->num_##ptr++; \
+ } else { \
+ libxl_device_##type##_dispose(DA_p); \
+ } \
+ \
+ libxl_device_##type##_init(DA_p); \
+ libxl_device_##type##_copy(CTX, DA_p, (dev)); \
+ })
+
+/* This function copies X bytes from source to destination bitmap,
+ * where X is the smaller of the two sizes.
+ *
+ * If destination's size is larger than source, the extra bytes are
+ * untouched.
+ *
+ * XXX This is introduced to fix a regression for 4.5. It shall
+ * be revisited in 4.6 time frame.
+ */
+void libxl__bitmap_copy_best_effort(libxl__gc *gc, libxl_bitmap *dptr,
+ const libxl_bitmap *sptr);
#endif
/*
diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c
index 989ac3f..ceb014a 100644
--- a/tools/libxl/libxl_json.c
+++ b/tools/libxl/libxl_json.c
@@ -34,11 +34,20 @@ struct libxl__yajl_ctx {
};
#ifdef DEBUG_ANSWER
-# define DEBUG_GEN_ALLOC(ctx) \
- if ((ctx)->g == NULL) { \
- yajl_gen_config conf = { 1, " " }; \
+#if YAJL_VERSION < 20000
+# define DEBUG_GEN_ALLOC(ctx) \
+ if ((ctx)->g == NULL) { \
+ yajl_gen_config conf = { 1, " " }; \
(ctx)->g = yajl_gen_alloc(&conf, NULL); \
}
+#else /* YAJL2 */
+# define DEBUG_GEN_ALLOC(ctx) \
+ if ((ctx)->g == NULL) { \
+ (ctx)->g = yajl_gen_alloc(NULL); \
+ yajl_gen_config((ctx)->g, yajl_gen_beautify, 1); \
+ yajl_gen_config((ctx)->g, yajl_gen_indent_string, " "); \
+ }
+#endif
# define DEBUG_GEN_FREE(ctx) \
if ((ctx)->g) yajl_gen_free((ctx)->g)
# define DEBUG_GEN(ctx, type) yajl_gen_##type(ctx->g)
@@ -48,7 +57,7 @@ struct libxl__yajl_ctx {
# define DEBUG_GEN_REPORT(yajl_ctx) \
do { \
const unsigned char *buf = NULL; \
- unsigned int len = 0; \
+ size_t len = 0; \
yajl_gen_get_buf((yajl_ctx)->g, &buf, &len); \
LIBXL__LOG(libxl__gc_owner((yajl_ctx)->gc), \
LIBXL__LOG_DEBUG, "response:\n%s", buf); \
@@ -91,6 +100,42 @@ yajl_gen_status libxl_defbool_gen_json(yajl_gen hand,
return libxl__yajl_gen_asciiz(hand, libxl_defbool_to_string(*db));
}
+int libxl__defbool_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ libxl_defbool *p)
+{
+ const char *s;
+
+ if (!libxl__json_object_is_string(o))
+ return ERROR_FAIL;
+
+ s = libxl__json_object_get_string(o);
+
+ if (!strncmp(s, LIBXL__DEFBOOL_STR_DEFAULT,
+ strlen(LIBXL__DEFBOOL_STR_DEFAULT)))
+ p->val = LIBXL__DEFBOOL_DEFAULT;
+ else if (!strncmp(s, LIBXL__DEFBOOL_STR_TRUE,
+ strlen(LIBXL__DEFBOOL_STR_TRUE)))
+ p->val = LIBXL__DEFBOOL_TRUE;
+ else if (!strncmp(s, LIBXL__DEFBOOL_STR_FALSE,
+ strlen(LIBXL__DEFBOOL_STR_FALSE)))
+ p->val = LIBXL__DEFBOOL_FALSE;
+ else
+ return ERROR_FAIL;
+
+ return 0;
+}
+
+int libxl__bool_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ bool *p)
+{
+ if (!libxl__json_object_is_bool(o))
+ return ERROR_FAIL;
+
+ *p = libxl__json_object_get_bool(o);
+
+ return 0;
+}
+
yajl_gen_status libxl_uuid_gen_json(yajl_gen hand,
libxl_uuid *uuid)
{
@@ -99,6 +144,15 @@ yajl_gen_status libxl_uuid_gen_json(yajl_gen hand,
return yajl_gen_string(hand, (const unsigned char *)buf, LIBXL_UUID_FMTLEN);
}
+int libxl__uuid_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ libxl_uuid *p)
+{
+ if (!libxl__json_object_is_string(o))
+ return ERROR_FAIL;
+
+ return libxl_uuid_from_string(p, o->u.string);
+}
+
yajl_gen_status libxl_bitmap_gen_json(yajl_gen hand,
libxl_bitmap *bitmap)
{
@@ -119,6 +173,40 @@ out:
return s;
}
+int libxl__bitmap_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ libxl_bitmap *p)
+{
+ int i;
+ int size;
+ const libxl__json_object *t;
+ flexarray_t *array;
+
+ if (!libxl__json_object_is_array(o))
+ return ERROR_FAIL;
+
+ array = libxl__json_object_get_array(o);
+ if (!array->count) {
+ libxl_bitmap_init(p);
+ return 0;
+ }
+
+ t = libxl__json_array_get(o, array->count - 1);
+ if (!libxl__json_object_is_integer(t))
+ return ERROR_FAIL;
+ size = libxl__json_object_get_integer(t) + 1;
+
+ libxl_bitmap_alloc(CTX, p, size);
+
+ for (i = 0; (t = libxl__json_array_get(o, i)); i++) {
+ if (!libxl__json_object_is_integer(t))
+ return ERROR_FAIL;
+
+ libxl_bitmap_set(p, libxl__json_object_get_integer(t));
+ }
+
+ return 0;
+}
+
yajl_gen_status libxl_key_value_list_gen_json(yajl_gen hand,
libxl_key_value_list *pkvl)
{
@@ -146,6 +234,41 @@ out:
return s;
}
+int libxl__key_value_list_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ libxl_key_value_list *p)
+{
+ libxl__json_map_node *node = NULL;
+ flexarray_t *maps = NULL;
+ int i, size;
+ libxl_key_value_list kvl;
+
+ if (!libxl__json_object_is_map(o))
+ return ERROR_FAIL;
+
+ maps = libxl__json_object_get_map(o);
+ size = maps->count * 2;
+ kvl = *p = libxl__calloc(NOGC, size, sizeof(char *));
+
+ for (i = 0; i < maps->count; i++) {
+ int idx = i * 2;
+ if (flexarray_get(maps, i, (void**)&node) != 0)
+ return ERROR_FAIL;
+
+ if (!libxl__json_object_is_string(node->obj) &&
+ !libxl__json_object_is_null(node->obj))
+ return ERROR_FAIL;
+
+ kvl[idx] = libxl__strdup(NOGC, node->map_key);
+ if (libxl__json_object_is_string(node->obj))
+ kvl[idx+1] =
+ libxl__strdup(NOGC, libxl__json_object_get_string(node->obj));
+ else
+ kvl[idx+1] = NULL;
+ }
+
+ return 0;
+}
+
yajl_gen_status libxl_string_list_gen_json(yajl_gen hand, libxl_string_list *pl)
{
libxl_string_list l = *pl;
@@ -167,6 +290,38 @@ out:
return s;
}
+int libxl__string_list_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ libxl_string_list *p)
+{
+ const libxl__json_object *t;
+ libxl_string_list l;
+ flexarray_t *array = NULL;
+ int i, size;
+
+ if (!libxl__json_object_is_array(o))
+ return ERROR_FAIL;
+
+ array = libxl__json_object_get_array(o);
+ size = array->count;
+
+ if (size == 0) {
+ *p = NULL;
+ return 0;
+ }
+
+ /* need one extra slot as sentinel */
+ l = *p = libxl__calloc(NOGC, size + 1, sizeof(char *));
+
+ for (i = 0; (t = libxl__json_array_get(o, i)); i++) {
+ if (!libxl__json_object_is_string(t))
+ return ERROR_FAIL;
+
+ l[i] = libxl__strdup(NOGC, libxl__json_object_get_string(t));
+ }
+
+ return 0;
+}
+
yajl_gen_status libxl_mac_gen_json(yajl_gen hand, libxl_mac *mac)
{
char buf[LIBXL_MAC_FMTLEN+1];
@@ -174,6 +329,15 @@ yajl_gen_status libxl_mac_gen_json(yajl_gen hand, libxl_mac *mac)
return yajl_gen_string(hand, (const unsigned char *)buf, LIBXL_MAC_FMTLEN);
}
+int libxl__mac_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ libxl_mac *p)
+{
+ if (!libxl__json_object_is_string(o))
+ return ERROR_FAIL;
+
+ return libxl__parse_mac(libxl__json_object_get_string(o), *p);
+}
+
yajl_gen_status libxl_hwcap_gen_json(yajl_gen hand,
libxl_hwcap *p)
{
@@ -192,6 +356,66 @@ out:
return s;
}
+int libxl__hwcap_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ libxl_hwcap *p)
+{
+ int i;
+
+ if (!libxl__json_object_is_array(o))
+ return ERROR_FAIL;
+
+ for (i = 0; i<4; i++) {
+ const libxl__json_object *t;
+
+ t = libxl__json_array_get(o, i);
+ if (!t || !libxl__json_object_is_integer(t))
+ return ERROR_FAIL;
+
+ (*p)[i] = libxl__json_object_get_integer(t);
+ }
+
+ return 0;
+}
+
+yajl_gen_status libxl_ms_vm_genid_gen_json(yajl_gen hand, libxl_ms_vm_genid *p)
+{
+ yajl_gen_status s;
+ int i;
+
+ s = yajl_gen_array_open(hand);
+ if (s != yajl_gen_status_ok)
+ return s;
+
+ for (i = 0; i < LIBXL_MS_VM_GENID_LEN; i++) {
+ s = yajl_gen_integer(hand, p->bytes[i]);
+ if (s != yajl_gen_status_ok)
+ return s;
+ }
+
+ return yajl_gen_array_close(hand);
+}
+
+int libxl__ms_vm_genid_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ libxl_ms_vm_genid *p)
+{
+ unsigned int i;
+
+ if (!libxl__json_object_is_array(o))
+ return ERROR_FAIL;
+
+ for (i = 0; i < LIBXL_MS_VM_GENID_LEN; i++) {
+ const libxl__json_object *t;
+
+ t = libxl__json_array_get(o, i);
+ if (!t || !libxl__json_object_is_integer(t))
+ return ERROR_FAIL;
+
+ p->bytes[i] = libxl__json_object_get_integer(t);
+ }
+
+ return 0;
+}
+
yajl_gen_status libxl__string_gen_json(yajl_gen hand,
const char *p)
{
@@ -201,6 +425,20 @@ yajl_gen_status libxl__string_gen_json(yajl_gen hand,
return yajl_gen_null(hand);
}
+int libxl__string_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ char **p)
+{
+ if (!libxl__json_object_is_string(o) && !libxl__json_object_is_null(o))
+ return ERROR_FAIL;
+
+ if (libxl__json_object_is_null(o))
+ *p = NULL;
+ else
+ *p = libxl__strdup(NOGC, libxl__json_object_get_string(o));
+
+ return 0;
+}
+
/*
* libxl__json_object helper functions
*/
@@ -225,36 +463,43 @@ libxl__json_object *libxl__json_object_alloc(libxl__gc *gc,
return obj;
}
-int libxl__json_object_append_to(libxl__gc *gc,
- libxl__json_object *obj,
- libxl__json_object *dst)
+int libxl__json_object_append_to(libxl__gc *gc, libxl__json_object *obj,
+ libxl__yajl_ctx *ctx)
{
- assert(dst != NULL);
+ libxl__json_object *dst = ctx->current;
- switch (dst->type) {
- case JSON_MAP: {
- libxl__json_map_node *last;
+ if (dst) {
+ switch (dst->type) {
+ case JSON_MAP: {
+ libxl__json_map_node *last;
- if (dst->u.map->count == 0) {
+ if (dst->u.map->count == 0) {
+ LIBXL__LOG(libxl__gc_owner(gc), LIBXL__LOG_ERROR,
+ "Try to add a value to an empty map (with no key)");
+ return ERROR_FAIL;
+ }
+ flexarray_get(dst->u.map, dst->u.map->count - 1, (void**)&last);
+ last->obj = obj;
+ break;
+ }
+ case JSON_ARRAY:
+ flexarray_append(dst->u.array, obj);
+ break;
+ default:
LIBXL__LOG(libxl__gc_owner(gc), LIBXL__LOG_ERROR,
- "Try to add a value to an empty map (with no key)");
- return -1;
+ "Try append an object is not a map/array (%i)\n",
+ dst->type);
+ return ERROR_FAIL;
}
- flexarray_get(dst->u.map, dst->u.map->count - 1, (void**)&last);
- last->obj = obj;
- break;
- }
- case JSON_ARRAY:
- flexarray_append(dst->u.array, obj);
- break;
- default:
- LIBXL__LOG(libxl__gc_owner(gc), LIBXL__LOG_ERROR,
- "Try append an object is not a map/array (%i)\n",
- dst->type);
- return -1;
}
obj->parent = dst;
+
+ if (libxl__json_object_is_map(obj) || libxl__json_object_is_array(obj))
+ ctx->current = obj;
+ if (ctx->head == NULL)
+ ctx->head = obj;
+
return 0;
}
@@ -354,7 +599,7 @@ const libxl__json_object *libxl__json_map_get(const char *key,
return NULL;
if (strcmp(key, node->map_key) == 0) {
if (expected_type == JSON_ANY
- || (node->obj && node->obj->type == expected_type)) {
+ || (node->obj && (node->obj->type & expected_type))) {
return node->obj;
} else {
return NULL;
@@ -440,9 +685,8 @@ static int json_callback_null(void *opaque)
obj = libxl__json_object_alloc(ctx->gc, JSON_NULL);
- if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) {
+ if (libxl__json_object_append_to(ctx->gc, obj, ctx))
return 0;
- }
return 1;
}
@@ -457,9 +701,8 @@ static int json_callback_boolean(void *opaque, int boolean)
obj = libxl__json_object_alloc(ctx->gc, JSON_BOOL);
obj->u.b = boolean;
- if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) {
+ if (libxl__json_object_append_to(ctx->gc, obj, ctx))
return 0;
- }
return 1;
}
@@ -514,9 +757,8 @@ error:
obj->u.string = t;
out:
- if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) {
+ if (libxl__json_object_append_to(ctx->gc, obj, ctx))
return 0;
- }
return 1;
}
@@ -538,9 +780,8 @@ static int json_callback_string(void *opaque, const unsigned char *str,
obj = libxl__json_object_alloc(ctx->gc, JSON_STRING);
obj->u.string = t;
- if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) {
+ if (libxl__json_object_append_to(ctx->gc, obj, ctx))
return 0;
- }
return 1;
}
@@ -586,16 +827,8 @@ static int json_callback_start_map(void *opaque)
obj = libxl__json_object_alloc(ctx->gc, JSON_MAP);
- if (ctx->current) {
- if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) {
- return 0;
- }
- }
-
- ctx->current = obj;
- if (ctx->head == NULL) {
- ctx->head = obj;
- }
+ if (libxl__json_object_append_to(ctx->gc, obj, ctx))
+ return 0;
return 1;
}
@@ -626,16 +859,8 @@ static int json_callback_start_array(void *opaque)
obj = libxl__json_object_alloc(ctx->gc, JSON_ARRAY);
- if (ctx->current) {
- if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) {
- return 0;
- }
- }
-
- ctx->current = obj;
- if (ctx->head == NULL) {
- ctx->head = obj;
- }
+ if (libxl__json_object_append_to(ctx->gc, obj, ctx))
+ return 0;
return 1;
}
@@ -785,6 +1010,138 @@ out:
return ret;
}
+yajl_gen_status libxl__uint64_gen_json(yajl_gen hand, uint64_t val)
+{
+ char *num;
+ unsigned int len;
+ yajl_gen_status s;
+
+
+ len = asprintf(&num, "%"PRIu64, val);
+ if (len == -1) {
+ s = yajl_gen_in_error_state;
+ goto out;
+ }
+
+ s = yajl_gen_number(hand, num, len);
+
+ free(num);
+
+out:
+ return s;
+}
+
+int libxl__object_from_json(libxl_ctx *ctx, const char *type,
+ libxl__json_parse_callback parse,
+ void *p, const char *s)
+{
+ GC_INIT(ctx);
+ libxl__json_object *o;
+ int rc;
+
+ o = libxl__json_parse(gc, s);
+ if (!o) {
+ LOG(ERROR,
+ "unable to generate libxl__json_object from JSON representation of %s.",
+ type);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = parse(gc, o, p);
+ if (rc) {
+ LOG(ERROR, "unable to convert libxl__json_object to %s. (rc=%d)", type, rc);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = 0;
+out:
+ GC_FREE;
+ return rc;
+}
+
+int libxl__int_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ void *p)
+{
+ long long i;
+
+ if (!libxl__json_object_is_integer(o))
+ return ERROR_FAIL;
+
+ i = libxl__json_object_get_integer(o);
+
+ if (i > INT_MAX || i < INT_MIN)
+ return ERROR_FAIL;
+
+ *((int *)p) = i;
+
+ return 0;
+}
+
+/* Macro to generate:
+ * libxl__uint8_parse_json
+ * libxl__uint16_parse_json
+ * libxl__uint32_parse_json
+ */
+#define PARSE_UINT(width) \
+ int libxl__uint ## width ## _parse_json(libxl__gc *gc, \
+ const libxl__json_object *o,\
+ void *p) \
+ { \
+ long long i; \
+ \
+ if (!libxl__json_object_is_integer(o)) \
+ return ERROR_FAIL; \
+ \
+ i = libxl__json_object_get_integer(o); \
+ \
+ if (i < 0 || i > UINT ## width ## _MAX) \
+ return ERROR_FAIL; \
+ \
+ *((uint ## width ## _t *)p) = i; \
+ \
+ return 0; \
+ }
+
+PARSE_UINT(8);
+PARSE_UINT(16);
+PARSE_UINT(32);
+
+int libxl__uint64_parse_json(libxl__gc *gc, const libxl__json_object *o,
+ void *p)
+{
+ if (!libxl__json_object_is_integer(o) &&
+ !libxl__json_object_is_number(o))
+ return ERROR_FAIL;
+
+ if (libxl__json_object_is_integer(o)) {
+ long long i = libxl__json_object_get_integer(o);
+
+ if (i < 0)
+ return ERROR_FAIL;
+
+ *((uint64_t *)p) = i;
+ } else {
+ const char *s;
+ unsigned long long i;
+ int saved_errno = errno;
+
+ s = libxl__json_object_get_number(o);
+
+ errno = 0;
+ i = strtoull(s, NULL, 10);
+
+ if (i == ULLONG_MAX && errno == ERANGE)
+ return ERROR_FAIL;
+
+ errno = saved_errno;
+ *((uint64_t *)p) = i;
+ }
+
+ return 0;
+}
+
/*
* Local variables:
* mode: C
diff --git a/tools/libxl/libxl_json.h b/tools/libxl/libxl_json.h
index a4dd8fc..af26e78 100644
--- a/tools/libxl/libxl_json.h
+++ b/tools/libxl/libxl_json.h
@@ -22,8 +22,8 @@
# include <yajl/yajl_version.h>
#endif
+yajl_gen_status libxl__uint64_gen_json(yajl_gen hand, uint64_t val);
yajl_gen_status libxl_defbool_gen_json(yajl_gen hand, libxl_defbool *p);
-yajl_gen_status libxl_domid_gen_json(yajl_gen hand, libxl_domid *p);
yajl_gen_status libxl_uuid_gen_json(yajl_gen hand, libxl_uuid *p);
yajl_gen_status libxl_mac_gen_json(yajl_gen hand, libxl_mac *p);
yajl_gen_status libxl_bitmap_gen_json(yajl_gen hand, libxl_bitmap *p);
@@ -33,6 +33,7 @@ yajl_gen_status libxl_string_list_gen_json(yajl_gen hand, libxl_string_list *p);
yajl_gen_status libxl_key_value_list_gen_json(yajl_gen hand,
libxl_key_value_list *p);
yajl_gen_status libxl_hwcap_gen_json(yajl_gen hand, libxl_hwcap *p);
+yajl_gen_status libxl_ms_vm_genid_gen_json(yajl_gen hand, libxl_ms_vm_genid *p);
#include <_libxl_types_json.h>
diff --git a/tools/libxl/libxl_netbuffer.c b/tools/libxl/libxl_netbuffer.c
new file mode 100644
index 0000000..edc6843
--- /dev/null
+++ b/tools/libxl/libxl_netbuffer.c
@@ -0,0 +1,517 @@
+/*
+ * Copyright (C) 2014
+ * Author Shriram Rajagopalan <rshriram at cs.ubc.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+
+#include <netlink/cache.h>
+#include <netlink/socket.h>
+#include <netlink/attr.h>
+#include <netlink/route/link.h>
+#include <netlink/route/route.h>
+#include <netlink/route/qdisc.h>
+#include <netlink/route/qdisc/plug.h>
+
+typedef struct libxl__remus_device_nic {
+ int devid;
+
+ const char *vif;
+ const char *ifb;
+ struct rtnl_qdisc *qdisc;
+} libxl__remus_device_nic;
+
+int libxl__netbuffer_enabled(libxl__gc *gc)
+{
+ return 1;
+}
+
+int init_subkind_nic(libxl__remus_devices_state *rds)
+{
+ int rc, ret;
+ libxl__domain_suspend_state *dss = CONTAINER_OF(rds, *dss, rds);
+
+ STATE_AO_GC(rds->ao);
+
+ rds->nlsock = nl_socket_alloc();
+ if (!rds->nlsock) {
+ LOG(ERROR, "cannot allocate nl socket");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ ret = nl_connect(rds->nlsock, NETLINK_ROUTE);
+ if (ret) {
+ LOG(ERROR, "failed to open netlink socket: %s",
+ nl_geterror(ret));
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ /* get list of all qdiscs installed on network devs. */
+ ret = rtnl_qdisc_alloc_cache(rds->nlsock, &rds->qdisc_cache);
+ if (ret) {
+ LOG(ERROR, "failed to allocate qdisc cache: %s",
+ nl_geterror(ret));
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ if (dss->remus->netbufscript) {
+ rds->netbufscript = libxl__strdup(gc, dss->remus->netbufscript);
+ } else {
+ rds->netbufscript = GCSPRINTF("%s/remus-netbuf-setup",
+ libxl__xen_script_dir_path());
+ }
+
+ rc = 0;
+
+out:
+ return rc;
+}
+
+void cleanup_subkind_nic(libxl__remus_devices_state *rds)
+{
+ STATE_AO_GC(rds->ao);
+
+ /* free qdisc cache */
+ if (rds->qdisc_cache) {
+ nl_cache_clear(rds->qdisc_cache);
+ nl_cache_free(rds->qdisc_cache);
+ rds->qdisc_cache = NULL;
+ }
+
+ /* close & free nlsock */
+ if (rds->nlsock) {
+ nl_close(rds->nlsock);
+ nl_socket_free(rds->nlsock);
+ rds->nlsock = NULL;
+ }
+}
+
+/*----- setup() and teardown() -----*/
+
+/* helper functions */
+
+/*
+ * If the device has a vifname, then use that instead of
+ * the vifX.Y format.
+ * it must ONLY be used for remus because if driver domains
+ * were in use it would constitute a security vulnerability.
+ */
+static const char *get_vifname(libxl__remus_device *dev,
+ const libxl_device_nic *nic)
+{
+ const char *vifname = NULL;
+ const char *path;
+ int rc;
+
+ STATE_AO_GC(dev->rds->ao);
+
+ /* Convenience aliases */
+ const uint32_t domid = dev->rds->domid;
+
+ path = GCSPRINTF("%s/backend/vif/%d/%d/vifname",
+ libxl__xs_get_dompath(gc, 0), domid, nic->devid);
+ rc = libxl__xs_read_checked(gc, XBT_NULL, path, &vifname);
+ if (!rc && !vifname) {
+ vifname = libxl__device_nic_devname(gc, domid,
+ nic->devid,
+ nic->nictype);
+ }
+
+ return vifname;
+}
+
+static void free_qdisc(libxl__remus_device_nic *remus_nic)
+{
+ if (remus_nic->qdisc == NULL)
+ return;
+
+ nl_object_put((struct nl_object *)(remus_nic->qdisc));
+ remus_nic->qdisc = NULL;
+}
+
+static int init_qdisc(libxl__remus_devices_state *rds,
+ libxl__remus_device_nic *remus_nic)
+{
+ int rc, ret, ifindex;
+ struct rtnl_link *ifb = NULL;
+ struct rtnl_qdisc *qdisc = NULL;
+
+ STATE_AO_GC(rds->ao);
+
+ /* Now that we have brought up REMUS_IFB device with plug qdisc for
+ * this vif, so we need to refill the qdisc cache.
+ */
+ ret = nl_cache_refill(rds->nlsock, rds->qdisc_cache);
+ if (ret) {
+ LOG(ERROR, "cannot refill qdisc cache: %s", nl_geterror(ret));
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ /* get a handle to the REMUS_IFB interface */
+ ret = rtnl_link_get_kernel(rds->nlsock, 0, remus_nic->ifb, &ifb);
+ if (ret) {
+ LOG(ERROR, "cannot obtain handle for %s: %s", remus_nic->ifb,
+ nl_geterror(ret));
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ ifindex = rtnl_link_get_ifindex(ifb);
+ if (!ifindex) {
+ LOG(ERROR, "interface %s has no index", remus_nic->ifb);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ /* Get a reference to the root qdisc installed on the REMUS_IFB, by
+ * querying the qdisc list we obtained earlier. The netbufscript
+ * sets up the plug qdisc as the root qdisc, so we don't have to
+ * search the entire qdisc tree on the REMUS_IFB dev.
+
+ * There is no need to explicitly free this qdisc as its just a
+ * reference from the qdisc cache we allocated earlier.
+ */
+ qdisc = rtnl_qdisc_get_by_parent(rds->qdisc_cache, ifindex, TC_H_ROOT);
+ if (qdisc) {
+ const char *tc_kind = rtnl_tc_get_kind(TC_CAST(qdisc));
+ /* Sanity check: Ensure that the root qdisc is a plug qdisc. */
+ if (!tc_kind || strcmp(tc_kind, "plug")) {
+ LOG(ERROR, "plug qdisc is not installed on %s", remus_nic->ifb);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ remus_nic->qdisc = qdisc;
+ } else {
+ LOG(ERROR, "Cannot get qdisc handle from ifb %s", remus_nic->ifb);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = 0;
+
+out:
+ if (ifb)
+ rtnl_link_put(ifb);
+
+ if (rc && qdisc)
+ nl_object_put((struct nl_object *)qdisc);
+
+ return rc;
+}
+
+/* callbacks */
+
+static void netbuf_setup_script_cb(libxl__egc *egc,
+ libxl__async_exec_state *aes,
+ int status);
+static void netbuf_teardown_script_cb(libxl__egc *egc,
+ libxl__async_exec_state *aes,
+ int status);
+
+/*
+ * the script needs the following env & args
+ * $vifname
+ * $XENBUS_PATH (/libxl/<domid>/remus/netbuf/<devid>/)
+ * $REMUS_IFB (for teardown)
+ * setup/teardown as command line arg.
+ */
+static void setup_async_exec(libxl__remus_device *dev, char *op)
+{
+ int arraysize, nr = 0;
+ char **env = NULL, **args = NULL;
+ libxl__remus_device_nic *remus_nic = dev->concrete_data;
+ libxl__remus_devices_state *rds = dev->rds;
+ libxl__async_exec_state *aes = &dev->aodev.aes;
+
+ STATE_AO_GC(rds->ao);
+
+ /* Convenience aliases */
+ char *const script = libxl__strdup(gc, rds->netbufscript);
+ const uint32_t domid = rds->domid;
+ const int dev_id = remus_nic->devid;
+ const char *const vif = remus_nic->vif;
+ const char *const ifb = remus_nic->ifb;
+
+ arraysize = 7;
+ GCNEW_ARRAY(env, arraysize);
+ env[nr++] = "vifname";
+ env[nr++] = libxl__strdup(gc, vif);
+ env[nr++] = "XENBUS_PATH";
+ env[nr++] = GCSPRINTF("%s/remus/netbuf/%d",
+ libxl__xs_libxl_path(gc, domid), dev_id);
+ if (!strcmp(op, "teardown") && ifb) {
+ env[nr++] = "REMUS_IFB";
+ env[nr++] = libxl__strdup(gc, ifb);
+ }
+ env[nr++] = NULL;
+ assert(nr <= arraysize);
+
+ arraysize = 3; nr = 0;
+ GCNEW_ARRAY(args, arraysize);
+ args[nr++] = script;
+ args[nr++] = op;
+ args[nr++] = NULL;
+ assert(nr == arraysize);
+
+ aes->ao = dev->rds->ao;
+ aes->what = GCSPRINTF("%s %s", args[0], args[1]);
+ aes->env = env;
+ aes->args = args;
+ aes->timeout_ms = LIBXL_HOTPLUG_TIMEOUT * 1000;
+ aes->stdfds[0] = -1;
+ aes->stdfds[1] = -1;
+ aes->stdfds[2] = -1;
+
+ if (!strcmp(op, "teardown"))
+ aes->callback = netbuf_teardown_script_cb;
+ else
+ aes->callback = netbuf_setup_script_cb;
+}
+
+/* setup() and teardown() */
+
+static void nic_setup(libxl__egc *egc, libxl__remus_device *dev)
+{
+ int rc;
+ libxl__remus_device_nic *remus_nic;
+ const libxl_device_nic *nic = dev->backend_dev;
+
+ STATE_AO_GC(dev->rds->ao);
+
+ /*
+ * thers's no subkind of nic devices, so nic ops is always matched
+ * with nic devices
+ */
+ dev->matched = true;
+
+ GCNEW(remus_nic);
+ dev->concrete_data = remus_nic;
+ remus_nic->devid = nic->devid;
+ remus_nic->vif = get_vifname(dev, nic);
+ if (!remus_nic->vif) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ setup_async_exec(dev, "setup");
+ rc = libxl__async_exec_start(gc, &dev->aodev.aes);
+ if (rc)
+ goto out;
+
+ return;
+
+out:
+ dev->aodev.rc = rc;
+ dev->aodev.callback(egc, &dev->aodev);
+}
+
+/*
+ * In return, the script writes the name of REMUS_IFB device (during setup)
+ * to be used for output buffering into XENBUS_PATH/ifb
+ */
+static void netbuf_setup_script_cb(libxl__egc *egc,
+ libxl__async_exec_state *aes,
+ int status)
+{
+ libxl__ao_device *aodev = CONTAINER_OF(aes, *aodev, aes);
+ libxl__remus_device *dev = CONTAINER_OF(aodev, *dev, aodev);
+ libxl__remus_device_nic *remus_nic = dev->concrete_data;
+ libxl__remus_devices_state *rds = dev->rds;
+ const char *out_path_base, *hotplug_error = NULL;
+ int rc;
+
+ STATE_AO_GC(rds->ao);
+
+ /* Convenience aliases */
+ const uint32_t domid = rds->domid;
+ const int devid = remus_nic->devid;
+ const char *const vif = remus_nic->vif;
+ const char **const ifb = &remus_nic->ifb;
+
+ /*
+ * we need to get ifb first because it's needed for teardown
+ */
+ rc = libxl__xs_read_checked(gc, XBT_NULL,
+ GCSPRINTF("%s/remus/netbuf/%d/ifb",
+ libxl__xs_libxl_path(gc, domid),
+ devid),
+ ifb);
+ if (rc)
+ goto out;
+
+ if (!(*ifb)) {
+ LOG(ERROR, "Cannot get ifb dev name for domain %u dev %s",
+ domid, vif);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ out_path_base = GCSPRINTF("%s/remus/netbuf/%d",
+ libxl__xs_libxl_path(gc, domid), devid);
+
+ rc = libxl__xs_read_checked(gc, XBT_NULL,
+ GCSPRINTF("%s/hotplug-error", out_path_base),
+ &hotplug_error);
+ if (rc)
+ goto out;
+
+ if (hotplug_error) {
+ LOG(ERROR, "netbuf script %s setup failed for vif %s: %s",
+ rds->netbufscript, vif, hotplug_error);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ if (status) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ LOG(DEBUG, "%s will buffer packets from vif %s", *ifb, vif);
+ rc = init_qdisc(rds, remus_nic);
+
+out:
+ aodev->rc = rc;
+ aodev->callback(egc, aodev);
+}
+
+static void nic_teardown(libxl__egc *egc, libxl__remus_device *dev)
+{
+ int rc;
+ STATE_AO_GC(dev->rds->ao);
+
+ setup_async_exec(dev, "teardown");
+
+ rc = libxl__async_exec_start(gc, &dev->aodev.aes);
+ if (rc)
+ goto out;
+
+ return;
+
+out:
+ dev->aodev.rc = rc;
+ dev->aodev.callback(egc, &dev->aodev);
+}
+
+static void netbuf_teardown_script_cb(libxl__egc *egc,
+ libxl__async_exec_state *aes,
+ int status)
+{
+ int rc;
+ libxl__ao_device *aodev = CONTAINER_OF(aes, *aodev, aes);
+ libxl__remus_device *dev = CONTAINER_OF(aodev, *dev, aodev);
+ libxl__remus_device_nic *remus_nic = dev->concrete_data;
+
+ if (status)
+ rc = ERROR_FAIL;
+ else
+ rc = 0;
+
+ free_qdisc(remus_nic);
+
+ aodev->rc = rc;
+ aodev->callback(egc, aodev);
+}
+
+/*----- checkpointing APIs -----*/
+
+/* The value of buffer_op, not the value passed to kernel */
+enum {
+ tc_buffer_start,
+ tc_buffer_release
+};
+
+/* API implementations */
+
+static int remus_netbuf_op(libxl__remus_device_nic *remus_nic,
+ libxl__remus_devices_state *rds,
+ int buffer_op)
+{
+ int rc, ret;
+
+ STATE_AO_GC(rds->ao);
+
+ if (buffer_op == tc_buffer_start)
+ ret = rtnl_qdisc_plug_buffer(remus_nic->qdisc);
+ else
+ ret = rtnl_qdisc_plug_release_one(remus_nic->qdisc);
+
+ if (ret) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ ret = rtnl_qdisc_add(rds->nlsock, remus_nic->qdisc, NLM_F_REQUEST);
+ if (ret) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = 0;
+
+out:
+ if (rc)
+ LOG(ERROR, "Remus: cannot do netbuf op %s on %s:%s",
+ ((buffer_op == tc_buffer_start) ?
+ "start_new_epoch" : "release_prev_epoch"),
+ remus_nic->ifb, nl_geterror(ret));
+ return rc;
+}
+
+static void nic_postsuspend(libxl__egc *egc, libxl__remus_device *dev)
+{
+ int rc;
+ libxl__remus_device_nic *remus_nic = dev->concrete_data;
+
+ STATE_AO_GC(dev->rds->ao);
+
+ rc = remus_netbuf_op(remus_nic, dev->rds, tc_buffer_start);
+
+ dev->aodev.rc = rc;
+ dev->aodev.callback(egc, &dev->aodev);
+}
+
+static void nic_commit(libxl__egc *egc, libxl__remus_device *dev)
+{
+ int rc;
+ libxl__remus_device_nic *remus_nic = dev->concrete_data;
+
+ STATE_AO_GC(dev->rds->ao);
+
+ rc = remus_netbuf_op(remus_nic, dev->rds, tc_buffer_release);
+
+ dev->aodev.rc = rc;
+ dev->aodev.callback(egc, &dev->aodev);
+}
+
+const libxl__remus_device_instance_ops remus_device_nic = {
+ .kind = LIBXL__DEVICE_KIND_VIF,
+ .setup = nic_setup,
+ .teardown = nic_teardown,
+ .postsuspend = nic_postsuspend,
+ .commit = nic_commit,
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxl/libxl_nocpuid.c b/tools/libxl/libxl_nocpuid.c
index 5f7cb6a..3dcaef2 100644
--- a/tools/libxl/libxl_nocpuid.c
+++ b/tools/libxl/libxl_nocpuid.c
@@ -14,6 +14,11 @@
#include "libxl_internal.h"
+int libxl__cpuid_policy_is_empty(libxl_cpuid_policy_list *pl)
+{
+ return 1;
+}
+
void libxl_cpuid_dispose(libxl_cpuid_policy_list *p_cpuid_list)
{
}
@@ -44,6 +49,19 @@ yajl_gen_status libxl_cpuid_policy_list_gen_json(yajl_gen hand,
return 0;
}
+int libxl__cpuid_policy_list_parse_json(libxl__gc *gc,
+ const libxl__json_object *o,
+ libxl_cpuid_policy_list *p)
+{
+ return 0;
+}
+
+void libxl_cpuid_policy_list_copy(libxl_ctx *ctx,
+ libxl_cpuid_policy_list *dst,
+ libxl_cpuid_policy_list *src)
+{
+}
+
/*
* Local variables:
* mode: C
diff --git a/tools/libxl/libxl_nonetbuffer.c b/tools/libxl/libxl_nonetbuffer.c
new file mode 100644
index 0000000..3c659c2
--- /dev/null
+++ b/tools/libxl/libxl_nonetbuffer.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014
+ * Author Shriram Rajagopalan <rshriram at cs.ubc.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+
+int libxl__netbuffer_enabled(libxl__gc *gc)
+{
+ return 0;
+}
+
+int init_subkind_nic(libxl__remus_devices_state *rds)
+{
+ return 0;
+}
+
+void cleanup_subkind_nic(libxl__remus_devices_state *rds)
+{
+ return;
+}
+
+static void nic_setup(libxl__egc *egc, libxl__remus_device *dev)
+{
+ STATE_AO_GC(dev->rds->ao);
+
+ dev->aodev.rc = ERROR_FAIL;
+ dev->aodev.callback(egc, &dev->aodev);
+}
+
+const libxl__remus_device_instance_ops remus_device_nic = {
+ .kind = LIBXL__DEVICE_KIND_VIF,
+ .setup = nic_setup,
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxl/libxl_numa.c b/tools/libxl/libxl_numa.c
index 4fac664..94ca4fe 100644
--- a/tools/libxl/libxl_numa.c
+++ b/tools/libxl/libxl_numa.c
@@ -308,6 +308,11 @@ int libxl__get_numa_candidate(libxl__gc *gc,
if (ninfo == NULL)
return ERROR_FAIL;
+ if (nr_nodes <= 1) {
+ *cndt_found = 0;
+ goto out;
+ }
+
GCNEW_ARRAY(vcpus_on_node, nr_nodes);
/*
diff --git a/tools/libxl/libxl_osdeps.h b/tools/libxl/libxl_osdeps.h
index f91bc79..08eaf0c 100644
--- a/tools/libxl/libxl_osdeps.h
+++ b/tools/libxl/libxl_osdeps.h
@@ -26,15 +26,22 @@
#if defined(__NetBSD__)
#define SYSFS_PCI_DEV "/sys/bus/pci/devices"
#define SYSFS_PCIBACK_DRIVER "/kern/xen/pci"
+#define NETBACK_NIC_NAME "xvif%ui%d"
#include <util.h>
#elif defined(__OpenBSD__)
#include <util.h>
#elif defined(__linux__)
#define SYSFS_PCI_DEV "/sys/bus/pci/devices"
#define SYSFS_PCIBACK_DRIVER "/sys/bus/pci/drivers/pciback"
+#define NETBACK_NIC_NAME "vif%u.%d"
#include <pty.h>
#elif defined(__sun__)
#include <stropts.h>
+#elif defined(__FreeBSD__)
+#define SYSFS_PCI_DEV "/dev/null"
+#define SYSFS_PCIBACK_DRIVER "/dev/null"
+#define NETBACK_NIC_NAME "xnb%u.%d"
+#include <libutil.h>
#endif
#ifndef SYSFS_PCIBACK_DRIVER
diff --git a/tools/libxl/libxl_paths.c b/tools/libxl/libxl_paths.c
index 14b28d1..9b7b0d5 100644
--- a/tools/libxl/libxl_paths.c
+++ b/tools/libxl/libxl_paths.c
@@ -15,14 +15,9 @@
#include "libxl_osdeps.h" /* must come before any other headers */
#include "libxl_internal.h"
-const char *libxl__libexec_path(void)
-{
- return LIBEXEC;
-}
-
const char *libxl__private_bindir_path(void)
{
- return PRIVATE_BINDIR;
+ return LIBEXEC_BIN;
}
const char *libxl__xenfirmwaredir_path(void)
diff --git a/tools/libxl/libxl_pci.c b/tools/libxl/libxl_pci.c
index 2e52470..316643c 100644
--- a/tools/libxl/libxl_pci.c
+++ b/tools/libxl/libxl_pci.c
@@ -64,6 +64,20 @@ static void libxl_create_pci_backend_device(libxl__gc *gc, flexarray_t *back, in
flexarray_append_pair(back, libxl__sprintf(gc, "state-%d", num), libxl__sprintf(gc, "%d", 1));
}
+static int libxl__device_from_pcidev(libxl__gc *gc, uint32_t domid,
+ libxl_device_pci *pcidev,
+ libxl__device *device)
+{
+ device->backend_devid = 0;
+ device->backend_domid = 0;
+ device->backend_kind = LIBXL__DEVICE_KIND_PCI;
+ device->devid = 0;
+ device->domid = domid;
+ device->kind = LIBXL__DEVICE_KIND_PCI;
+
+ return 0;
+}
+
int libxl__create_pci_backend(libxl__gc *gc, uint32_t domid,
libxl_device_pci *pcidev, int num)
{
@@ -81,12 +95,7 @@ int libxl__create_pci_backend(libxl__gc *gc, uint32_t domid,
LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Creating pci backend");
/* add pci device */
- device.backend_devid = 0;
- device.backend_domid = 0;
- device.backend_kind = LIBXL__DEVICE_KIND_PCI;
- device.devid = 0;
- device.domid = domid;
- device.kind = LIBXL__DEVICE_KIND_PCI;
+ libxl__device_from_pcidev(gc, domid, pcidev, &device);
flexarray_append_pair(back, "frontend-id", libxl__sprintf(gc, "%d", domid));
flexarray_append_pair(back, "online", "1");
@@ -115,6 +124,15 @@ static int libxl__device_pci_add_xenstore(libxl__gc *gc, uint32_t domid, libxl_d
char *num_devs, *be_path;
int num = 0;
xs_transaction_t t;
+ libxl__device *device;
+ int rc;
+ libxl_domain_config d_config;
+ libxl_device_pci pcidev_saved;
+ libxl__domain_userdata_lock *lock = NULL;
+
+ libxl_domain_config_init(&d_config);
+ libxl_device_pci_init(&pcidev_saved);
+ libxl_device_pci_copy(CTX, &pcidev_saved, pcidev);
be_path = libxl__sprintf(gc, "%s/backend/pci/%d/0", libxl__xs_get_dompath(gc, 0), domid);
num_devs = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/num_devs", be_path));
@@ -139,15 +157,41 @@ static int libxl__device_pci_add_xenstore(libxl__gc *gc, uint32_t domid, libxl_d
if (!starting)
flexarray_append_pair(back, "state", libxl__sprintf(gc, "%d", 7));
-retry_transaction:
- t = xs_transaction_start(ctx->xsh);
- libxl__xs_writev(gc, t, be_path,
- libxl__xs_kvs_of_flexarray(gc, back, back->count));
- if (!xs_transaction_end(ctx->xsh, t, 0))
- if (errno == EAGAIN)
- goto retry_transaction;
+ GCNEW(device);
+ libxl__device_from_pcidev(gc, domid, pcidev, device);
- return 0;
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
+
+ rc = libxl__get_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+
+ DEVICE_ADD(pci, pcidevs, domid, &pcidev_saved, COMPARE_PCI, &d_config);
+
+ for (;;) {
+ rc = libxl__xs_transaction_start(gc, &t);
+ if (rc) goto out;
+
+ rc = libxl__set_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+
+ libxl__xs_writev(gc, t, be_path,
+ libxl__xs_kvs_of_flexarray(gc, back, back->count));
+
+ rc = libxl__xs_transaction_commit(gc, &t);
+ if (!rc) break;
+ if (rc < 0) goto out;
+ }
+
+out:
+ libxl__xs_transaction_abort(gc, &t);
+ if (lock) libxl__unlock_domain_userdata(lock);
+ libxl_device_pci_dispose(&pcidev_saved);
+ libxl_domain_config_dispose(&d_config);
+ return rc;
}
static int libxl__device_pci_remove_xenstore(libxl__gc *gc, uint32_t domid, libxl_device_pci *pcidev)
@@ -846,10 +890,16 @@ static int qemu_pci_add_xenstore(libxl__gc *gc, uint32_t domid,
static int do_pci_add(libxl__gc *gc, uint32_t domid, libxl_device_pci *pcidev, int starting)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
- int rc, hvm = 0;
+ libxl_domain_type type = libxl__domain_type(gc, domid);
+ char *sysfs_path;
+ FILE *f;
+ unsigned long long start, end, flags, size;
+ int irq, i, rc, hvm = 0;
+
+ if (type == LIBXL_DOMAIN_TYPE_INVALID)
+ return ERROR_FAIL;
- switch (libxl__domain_type(gc, domid)) {
- case LIBXL_DOMAIN_TYPE_HVM:
+ if (type == LIBXL_DOMAIN_TYPE_HVM) {
hvm = 1;
if (libxl__wait_for_device_model_deprecated(gc, domid, "running",
NULL, NULL, NULL) < 0) {
@@ -867,81 +917,75 @@ static int do_pci_add(libxl__gc *gc, uint32_t domid, libxl_device_pci *pcidev, i
}
if ( rc )
return ERROR_FAIL;
- break;
- case LIBXL_DOMAIN_TYPE_PV:
- {
- char *sysfs_path = libxl__sprintf(gc, SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
- pcidev->bus, pcidev->dev, pcidev->func);
- FILE *f = fopen(sysfs_path, "r");
- unsigned long long start = 0, end = 0, flags = 0, size = 0;
- int irq = 0;
- int i;
+ }
- if (f == NULL) {
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Couldn't open %s", sysfs_path);
- return ERROR_FAIL;
- }
- for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
- if (fscanf(f, "0x%llx 0x%llx 0x%llx\n", &start, &end, &flags) != 3)
- continue;
- size = end - start + 1;
- if (start) {
- if (flags & PCI_BAR_IO) {
- rc = xc_domain_ioport_permission(ctx->xch, domid, start, size, 1);
- if (rc < 0) {
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Error: xc_domain_ioport_permission error 0x%llx/0x%llx", start, size);
- fclose(f);
- return ERROR_FAIL;
- }
- } else {
- rc = xc_domain_iomem_permission(ctx->xch, domid, start>>XC_PAGE_SHIFT,
- (size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 1);
- if (rc < 0) {
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Error: xc_domain_iomem_permission error 0x%llx/0x%llx", start, size);
- fclose(f);
- return ERROR_FAIL;
- }
+ sysfs_path = libxl__sprintf(gc, SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
+ pcidev->bus, pcidev->dev, pcidev->func);
+ f = fopen(sysfs_path, "r");
+ start = end = flags = size = 0;
+ irq = 0;
+
+ if (f == NULL) {
+ LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Couldn't open %s", sysfs_path);
+ return ERROR_FAIL;
+ }
+ for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
+ if (fscanf(f, "0x%llx 0x%llx 0x%llx\n", &start, &end, &flags) != 3)
+ continue;
+ size = end - start + 1;
+ if (start) {
+ if (flags & PCI_BAR_IO) {
+ rc = xc_domain_ioport_permission(ctx->xch, domid, start, size, 1);
+ if (rc < 0) {
+ LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Error: xc_domain_ioport_permission error 0x%llx/0x%llx", start, size);
+ fclose(f);
+ return ERROR_FAIL;
+ }
+ } else {
+ rc = xc_domain_iomem_permission(ctx->xch, domid, start>>XC_PAGE_SHIFT,
+ (size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 1);
+ if (rc < 0) {
+ LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Error: xc_domain_iomem_permission error 0x%llx/0x%llx", start, size);
+ fclose(f);
+ return ERROR_FAIL;
}
}
}
- fclose(f);
- sysfs_path = libxl__sprintf(gc, SYSFS_PCI_DEV"/"PCI_BDF"/irq", pcidev->domain,
- pcidev->bus, pcidev->dev, pcidev->func);
- f = fopen(sysfs_path, "r");
- if (f == NULL) {
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Couldn't open %s", sysfs_path);
- goto out;
+ }
+ fclose(f);
+ sysfs_path = libxl__sprintf(gc, SYSFS_PCI_DEV"/"PCI_BDF"/irq", pcidev->domain,
+ pcidev->bus, pcidev->dev, pcidev->func);
+ f = fopen(sysfs_path, "r");
+ if (f == NULL) {
+ LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Couldn't open %s", sysfs_path);
+ goto out;
+ }
+ if ((fscanf(f, "%u", &irq) == 1) && irq) {
+ rc = xc_physdev_map_pirq(ctx->xch, domid, irq, &irq);
+ if (rc < 0) {
+ LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Error: xc_physdev_map_pirq irq=%d", irq);
+ fclose(f);
+ return ERROR_FAIL;
}
- if ((fscanf(f, "%u", &irq) == 1) && irq) {
- rc = xc_physdev_map_pirq(ctx->xch, domid, irq, &irq);
- if (rc < 0) {
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Error: xc_physdev_map_pirq irq=%d", irq);
- fclose(f);
- return ERROR_FAIL;
- }
- rc = xc_domain_irq_permission(ctx->xch, domid, irq, 1);
- if (rc < 0) {
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Error: xc_domain_irq_permission irq=%d", irq);
- fclose(f);
- return ERROR_FAIL;
- }
+ rc = xc_domain_irq_permission(ctx->xch, domid, irq, 1);
+ if (rc < 0) {
+ LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Error: xc_domain_irq_permission irq=%d", irq);
+ fclose(f);
+ return ERROR_FAIL;
}
- fclose(f);
+ }
+ fclose(f);
- /* Don't restrict writes to the PCI config space from this VM */
- if (pcidev->permissive) {
- if ( sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER"/permissive",
- pcidev) < 0 ) {
- LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
- "Setting permissive for device");
- return ERROR_FAIL;
- }
+ /* Don't restrict writes to the PCI config space from this VM */
+ if (pcidev->permissive) {
+ if ( sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER"/permissive",
+ pcidev) < 0 ) {
+ LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+ "Setting permissive for device");
+ return ERROR_FAIL;
}
- break;
- }
- case LIBXL_DOMAIN_TYPE_INVALID:
- return ERROR_FAIL;
}
+
out:
if (!libxl_is_stubdom(ctx, domid, NULL)) {
rc = xc_assign_device(ctx->xch, domid, pcidev_encode_bdf(pcidev));
@@ -965,7 +1009,7 @@ static int libxl__device_pci_reset(libxl__gc *gc, unsigned int domain, unsigned
char *reset;
int fd, rc;
- reset = libxl__sprintf(gc, "%s/pciback/do_flr", SYSFS_PCI_DEV);
+ reset = libxl__sprintf(gc, "%s/do_flr", SYSFS_PCIBACK_DRIVER);
fd = open(reset, O_WRONLY);
if (fd >= 0) {
char *buf = libxl__sprintf(gc, PCI_BDF, domain, bus, dev, func);
@@ -1050,6 +1094,12 @@ int libxl__device_pci_add(libxl__gc *gc, uint32_t domid, libxl_device_pci *pcide
rc = libxl__device_pci_setdefault(gc, pcidev);
if (rc) goto out;
+ if (pcidev->seize && !pciback_dev_is_assigned(gc, pcidev)) {
+ rc = libxl__device_pci_assignable_add(gc, pcidev, 1);
+ if ( rc )
+ goto out;
+ }
+
if (!libxl_pcidev_assignable(ctx, pcidev)) {
LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "PCI device %x:%x:%x.%x is not assignable",
pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func);
@@ -1160,6 +1210,7 @@ static int do_pci_remove(libxl__gc *gc, uint32_t domid,
{
libxl_ctx *ctx = libxl__gc_owner(gc);
libxl_device_pci *assigned;
+ libxl_domain_type type = libxl__domain_type(gc, domid);
int hvm = 0, rc, num;
int stubdomid = 0;
@@ -1175,8 +1226,7 @@ static int do_pci_remove(libxl__gc *gc, uint32_t domid,
}
rc = ERROR_FAIL;
- switch (libxl__domain_type(gc, domid)) {
- case LIBXL_DOMAIN_TYPE_HVM:
+ if (type == LIBXL_DOMAIN_TYPE_HVM) {
hvm = 1;
if (libxl__wait_for_device_model_deprecated(gc, domid, "running",
NULL, NULL, NULL) < 0)
@@ -1197,8 +1247,8 @@ static int do_pci_remove(libxl__gc *gc, uint32_t domid,
rc = ERROR_FAIL;
goto out_fail;
}
- break;
- case LIBXL_DOMAIN_TYPE_PV:
+ } else if (type != LIBXL_DOMAIN_TYPE_PV)
+ abort();
{
char *sysfs_path = libxl__sprintf(gc, SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
pcidev->bus, pcidev->dev, pcidev->func);
@@ -1248,10 +1298,6 @@ skip1:
}
}
fclose(f);
- break;
- }
- default:
- abort();
}
out:
/* don't do multiple resets while some functions are still passed through */
@@ -1429,6 +1475,69 @@ int libxl__device_pci_destroy_all(libxl__gc *gc, uint32_t domid)
return 0;
}
+int libxl__grant_vga_iomem_permission(libxl__gc *gc, const uint32_t domid,
+ libxl_domain_config *const d_config)
+{
+ int i, ret;
+
+ if (!libxl_defbool_val(d_config->b_info.u.hvm.gfx_passthru))
+ return 0;
+
+ for (i = 0 ; i < d_config->num_pcidevs ; i++) {
+ uint64_t vga_iomem_start = 0xa0000 >> XC_PAGE_SHIFT;
+ uint32_t stubdom_domid;
+ libxl_device_pci *pcidev = &d_config->pcidevs[i];
+ char *pci_device_class_path =
+ libxl__sprintf(gc, SYSFS_PCI_DEV"/"PCI_BDF"/class",
+ pcidev->domain, pcidev->bus, pcidev->dev,
+ pcidev->func);
+ int read_items;
+ unsigned long pci_device_class;
+
+ FILE *f = fopen(pci_device_class_path, "r");
+ if (!f) {
+ LOGE(ERROR,
+ "pci device "PCI_BDF" does not have class attribute",
+ pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func);
+ continue;
+ }
+ read_items = fscanf(f, "0x%lx\n", &pci_device_class);
+ fclose(f);
+ if (read_items != 1) {
+ LOGE(ERROR,
+ "cannot read class of pci device "PCI_BDF,
+ pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func);
+ continue;
+ }
+ if (pci_device_class != 0x030000) /* VGA class */
+ continue;
+
+ stubdom_domid = libxl_get_stubdom_id(CTX, domid);
+ ret = xc_domain_iomem_permission(CTX->xch, stubdom_domid,
+ vga_iomem_start, 0x20, 1);
+ if (ret < 0) {
+ LOGE(ERROR,
+ "failed to give stubdom%d access to iomem range "
+ "%"PRIx64"-%"PRIx64" for VGA passthru",
+ stubdom_domid,
+ vga_iomem_start, (vga_iomem_start + 0x20 - 1));
+ return ret;
+ }
+ ret = xc_domain_iomem_permission(CTX->xch, domid,
+ vga_iomem_start, 0x20, 1);
+ if (ret < 0) {
+ LOGE(ERROR,
+ "failed to give dom%d access to iomem range "
+ "%"PRIx64"-%"PRIx64" for VGA passthru",
+ domid, vga_iomem_start, (vga_iomem_start + 0x20 - 1));
+ return ret;
+ }
+ break;
+ }
+
+ return 0;
+}
+
/*
* Local variables:
* mode: C
diff --git a/tools/libxl/libxl_psr.c b/tools/libxl/libxl_psr.c
new file mode 100644
index 0000000..0437465
--- /dev/null
+++ b/tools/libxl/libxl_psr.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2014 Intel Corporation
+ * Author Dongxiao Xu <dongxiao.xu at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+#include "libxl_internal.h"
+
+
+#define IA32_QM_CTR_ERROR_MASK (0x3ul << 62)
+
+static void libxl__psr_cmt_log_err_msg(libxl__gc *gc, int err)
+{
+ char *msg;
+
+ switch (err) {
+ case ENOSYS:
+ msg = "unsupported operation";
+ break;
+ case ENODEV:
+ msg = "CMT is not supported in this system";
+ break;
+ case EEXIST:
+ msg = "CMT is already attached to this domain";
+ break;
+ case ENOENT:
+ msg = "CMT is not attached to this domain";
+ break;
+ case EUSERS:
+ msg = "no free RMID available";
+ break;
+ case ESRCH:
+ msg = "invalid domain ID";
+ break;
+ case EFAULT:
+ msg = "failed to exchange data with Xen";
+ break;
+ default:
+ msg = "unknown error";
+ break;
+ }
+
+ LOGE(ERROR, "%s", msg);
+}
+
+static int libxl__pick_socket_cpu(libxl__gc *gc, uint32_t socketid)
+{
+ int i, nr_cpus;
+ libxl_cputopology *topology;
+ int cpu = ERROR_FAIL;
+
+ topology = libxl_get_cpu_topology(CTX, &nr_cpus);
+ if (!topology)
+ return ERROR_FAIL;
+
+ for (i = 0; i < nr_cpus; i++)
+ if (topology[i].socket == socketid) {
+ cpu = i;
+ break;
+ }
+
+ libxl_cputopology_list_free(topology, nr_cpus);
+ return cpu;
+}
+
+int libxl_psr_cmt_attach(libxl_ctx *ctx, uint32_t domid)
+{
+ GC_INIT(ctx);
+ int rc;
+
+ rc = xc_psr_cmt_attach(ctx->xch, domid);
+ if (rc < 0) {
+ libxl__psr_cmt_log_err_msg(gc, errno);
+ rc = ERROR_FAIL;
+ }
+
+ GC_FREE;
+ return rc;
+}
+
+int libxl_psr_cmt_detach(libxl_ctx *ctx, uint32_t domid)
+{
+ GC_INIT(ctx);
+ int rc;
+
+ rc = xc_psr_cmt_detach(ctx->xch, domid);
+ if (rc < 0) {
+ libxl__psr_cmt_log_err_msg(gc, errno);
+ rc = ERROR_FAIL;
+ }
+
+ GC_FREE;
+ return rc;
+}
+
+int libxl_psr_cmt_domain_attached(libxl_ctx *ctx, uint32_t domid)
+{
+ int rc;
+ uint32_t rmid;
+
+ rc = xc_psr_cmt_get_domain_rmid(ctx->xch, domid, &rmid);
+ if (rc < 0)
+ return 0;
+
+ return !!rmid;
+}
+
+int libxl_psr_cmt_enabled(libxl_ctx *ctx)
+{
+ return xc_psr_cmt_enabled(ctx->xch);
+}
+
+int libxl_psr_cmt_get_total_rmid(libxl_ctx *ctx, uint32_t *total_rmid)
+{
+ GC_INIT(ctx);
+ int rc;
+
+ rc = xc_psr_cmt_get_total_rmid(ctx->xch, total_rmid);
+ if (rc < 0) {
+ libxl__psr_cmt_log_err_msg(gc, errno);
+ rc = ERROR_FAIL;
+ }
+
+ GC_FREE;
+ return rc;
+}
+
+int libxl_psr_cmt_get_l3_cache_size(libxl_ctx *ctx, uint32_t socketid,
+ uint32_t *l3_cache_size)
+{
+ GC_INIT(ctx);
+
+ int rc;
+ int cpu = libxl__pick_socket_cpu(gc, socketid);
+
+ if (cpu < 0) {
+ LOGE(ERROR, "failed to get socket cpu");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = xc_psr_cmt_get_l3_cache_size(ctx->xch, cpu, l3_cache_size);
+ if (rc < 0) {
+ libxl__psr_cmt_log_err_msg(gc, errno);
+ rc = ERROR_FAIL;
+ }
+
+out:
+ GC_FREE;
+ return rc;
+}
+
+int libxl_psr_cmt_get_cache_occupancy(libxl_ctx *ctx, uint32_t domid,
+ uint32_t socketid, uint32_t *l3_cache_occupancy)
+{
+ GC_INIT(ctx);
+
+ unsigned int rmid;
+ uint32_t upscaling_factor;
+ uint64_t monitor_data;
+ int cpu, rc;
+ xc_psr_cmt_type type;
+
+ rc = xc_psr_cmt_get_domain_rmid(ctx->xch, domid, &rmid);
+ if (rc < 0 || rmid == 0) {
+ LOGE(ERROR, "fail to get the domain rmid, "
+ "or domain is not attached with platform QoS monitoring service");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ cpu = libxl__pick_socket_cpu(gc, socketid);
+ if (cpu < 0) {
+ LOGE(ERROR, "failed to get socket cpu");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ type = XC_PSR_CMT_L3_OCCUPANCY;
+ rc = xc_psr_cmt_get_data(ctx->xch, rmid, cpu, type, &monitor_data);
+ if (rc < 0) {
+ LOGE(ERROR, "failed to get monitoring data");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = xc_psr_cmt_get_l3_upscaling_factor(ctx->xch, &upscaling_factor);
+ if (rc < 0) {
+ LOGE(ERROR, "failed to get L3 upscaling factor");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ *l3_cache_occupancy = upscaling_factor * monitor_data / 1024;
+ rc = 0;
+out:
+ GC_FREE;
+ return rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 8433e42..c7324e6 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -358,19 +358,14 @@ static int qmp_open(libxl__qmp_handler *qmp, const char *qmp_socket_path,
int timeout)
{
int ret;
- int flags = 0;
int i = 0;
qmp->qmp_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (qmp->qmp_fd < 0) {
return -1;
}
- if ((flags = fcntl(qmp->qmp_fd, F_GETFL)) == -1) {
- flags = 0;
- }
- if (fcntl(qmp->qmp_fd, F_SETFL, flags | O_NONBLOCK) == -1) {
- return -1;
- }
+ ret = libxl_fd_set_nonblock(qmp->ctx, qmp->qmp_fd, 1);
+ if (ret) return -1;
ret = libxl_fd_set_cloexec(qmp->ctx, qmp->qmp_fd, 1);
if (ret) return -1;
@@ -456,7 +451,7 @@ static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp)
if (incomplete) {
size_t current_pos = s - incomplete;
incomplete = libxl__realloc(gc, incomplete,
- incomplete_size + rd);
+ incomplete_size + rd + 1);
strncat(incomplete + incomplete_size, qmp->buffer, rd);
s = incomplete + current_pos;
incomplete_size += rd;
diff --git a/tools/libxl/libxl_remus_device.c b/tools/libxl/libxl_remus_device.c
new file mode 100644
index 0000000..a6cb7f6
--- /dev/null
+++ b/tools/libxl/libxl_remus_device.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2014 FUJITSU LIMITED
+ * Author: Yang Hongyang <yanghy at cn.fujitsu.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+
+extern const libxl__remus_device_instance_ops remus_device_nic;
+extern const libxl__remus_device_instance_ops remus_device_drbd_disk;
+static const libxl__remus_device_instance_ops *remus_ops[] = {
+ &remus_device_nic,
+ &remus_device_drbd_disk,
+ NULL,
+};
+
+/*----- helper functions -----*/
+
+static int init_device_subkind(libxl__remus_devices_state *rds)
+{
+ /* init device subkind-specific state in the libxl ctx */
+ int rc;
+ STATE_AO_GC(rds->ao);
+
+ if (libxl__netbuffer_enabled(gc)) {
+ rc = init_subkind_nic(rds);
+ if (rc) goto out;
+ }
+
+ rc = init_subkind_drbd_disk(rds);
+ if (rc) goto out;
+
+ rc = 0;
+out:
+ return rc;
+}
+
+static void cleanup_device_subkind(libxl__remus_devices_state *rds)
+{
+ /* cleanup device subkind-specific state in the libxl ctx */
+ STATE_AO_GC(rds->ao);
+
+ if (libxl__netbuffer_enabled(gc))
+ cleanup_subkind_nic(rds);
+
+ cleanup_subkind_drbd_disk(rds);
+}
+
+/*----- setup() and teardown() -----*/
+
+/* callbacks */
+
+static void all_devices_setup_cb(libxl__egc *egc,
+ libxl__multidev *multidev,
+ int rc);
+static void device_setup_iterate(libxl__egc *egc,
+ libxl__ao_device *aodev);
+static void devices_teardown_cb(libxl__egc *egc,
+ libxl__multidev *multidev,
+ int rc);
+
+/* remus device setup and teardown */
+
+static libxl__remus_device* remus_device_init(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ libxl__device_kind kind,
+ void *libxl_dev)
+{
+ libxl__remus_device *dev = NULL;
+
+ STATE_AO_GC(rds->ao);
+ GCNEW(dev);
+ dev->backend_dev = libxl_dev;
+ dev->kind = kind;
+ dev->rds = rds;
+
+ return dev;
+}
+
+static void remus_devices_setup(libxl__egc *egc,
+ libxl__remus_devices_state *rds);
+
+void libxl__remus_devices_setup(libxl__egc *egc, libxl__remus_devices_state *rds)
+{
+ int i, rc;
+
+ STATE_AO_GC(rds->ao);
+
+ rc = init_device_subkind(rds);
+ if (rc)
+ goto out;
+
+ rds->num_devices = 0;
+ rds->num_nics = 0;
+ rds->num_disks = 0;
+
+ if (rds->device_kind_flags & (1 << LIBXL__DEVICE_KIND_VIF))
+ rds->nics = libxl_device_nic_list(CTX, rds->domid, &rds->num_nics);
+
+ if (rds->device_kind_flags & (1 << LIBXL__DEVICE_KIND_VBD))
+ rds->disks = libxl_device_disk_list(CTX, rds->domid, &rds->num_disks);
+
+ if (rds->num_nics == 0 && rds->num_disks == 0)
+ goto out;
+
+ GCNEW_ARRAY(rds->devs, rds->num_nics + rds->num_disks);
+
+ for (i = 0; i < rds->num_nics; i++) {
+ rds->devs[rds->num_devices++] = remus_device_init(egc, rds,
+ LIBXL__DEVICE_KIND_VIF,
+ &rds->nics[i]);
+ }
+
+ for (i = 0; i < rds->num_disks; i++) {
+ rds->devs[rds->num_devices++] = remus_device_init(egc, rds,
+ LIBXL__DEVICE_KIND_VBD,
+ &rds->disks[i]);
+ }
+
+ remus_devices_setup(egc, rds);
+
+ return;
+
+out:
+ rds->callback(egc, rds, rc);
+}
+
+static void remus_devices_setup(libxl__egc *egc,
+ libxl__remus_devices_state *rds)
+{
+ int i, rc;
+
+ STATE_AO_GC(rds->ao);
+
+ libxl__multidev_begin(ao, &rds->multidev);
+ rds->multidev.callback = all_devices_setup_cb;
+ for (i = 0; i < rds->num_devices; i++) {
+ libxl__remus_device *dev = rds->devs[i];
+ dev->ops_index = -1;
+ libxl__multidev_prepare_with_aodev(&rds->multidev, &dev->aodev);
+
+ dev->aodev.rc = ERROR_REMUS_DEVICE_NOT_SUPPORTED;
+ dev->aodev.callback = device_setup_iterate;
+ device_setup_iterate(egc,&dev->aodev);
+ }
+
+ rc = 0;
+ libxl__multidev_prepared(egc, &rds->multidev, rc);
+}
+
+
+static void device_setup_iterate(libxl__egc *egc, libxl__ao_device *aodev)
+{
+ libxl__remus_device *dev = CONTAINER_OF(aodev, *dev, aodev);
+ EGC_GC;
+
+ if (aodev->rc != ERROR_REMUS_DEVICE_NOT_SUPPORTED &&
+ aodev->rc != ERROR_REMUS_DEVOPS_DOES_NOT_MATCH)
+ /* might be success or disaster */
+ goto out;
+
+ do {
+ dev->ops = remus_ops[++dev->ops_index];
+ if (!dev->ops) {
+ libxl_device_nic * nic = NULL;
+ libxl_device_disk * disk = NULL;
+ uint32_t domid;
+ int devid;
+ if (dev->kind == LIBXL__DEVICE_KIND_VIF) {
+ nic = (libxl_device_nic *)dev->backend_dev;
+ domid = nic->backend_domid;
+ devid = nic->devid;
+ } else if (dev->kind == LIBXL__DEVICE_KIND_VBD) {
+ disk = (libxl_device_disk *)dev->backend_dev;
+ domid = disk->backend_domid;
+ devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
+ } else {
+ LOG(ERROR,"device kind not handled by remus: %s",
+ libxl__device_kind_to_string(dev->kind));
+ aodev->rc = ERROR_FAIL;
+ goto out;
+ }
+ LOG(ERROR,"device not handled by remus"
+ " (device=%s:%"PRId32"/%"PRId32")",
+ libxl__device_kind_to_string(dev->kind),
+ domid, devid);
+ aodev->rc = ERROR_REMUS_DEVICE_NOT_SUPPORTED;
+ goto out;
+ }
+ } while (dev->ops->kind != dev->kind);
+
+ /* found the next ops_index to try */
+ assert(dev->aodev.callback == device_setup_iterate);
+ dev->ops->setup(egc,dev);
+ return;
+
+ out:
+ libxl__multidev_one_callback(egc,aodev);
+}
+
+static void all_devices_setup_cb(libxl__egc *egc,
+ libxl__multidev *multidev,
+ int rc)
+{
+ STATE_AO_GC(multidev->ao);
+
+ /* Convenience aliases */
+ libxl__remus_devices_state *const rds =
+ CONTAINER_OF(multidev, *rds, multidev);
+
+ rds->callback(egc, rds, rc);
+}
+
+void libxl__remus_devices_teardown(libxl__egc *egc,
+ libxl__remus_devices_state *rds)
+{
+ int i;
+ libxl__remus_device *dev;
+
+ STATE_AO_GC(rds->ao);
+
+ libxl__multidev_begin(ao, &rds->multidev);
+ rds->multidev.callback = devices_teardown_cb;
+ for (i = 0; i < rds->num_devices; i++) {
+ dev = rds->devs[i];
+ if (!dev->ops || !dev->matched)
+ continue;
+
+ libxl__multidev_prepare_with_aodev(&rds->multidev, &dev->aodev);
+ dev->ops->teardown(egc,dev);
+ }
+
+ libxl__multidev_prepared(egc, &rds->multidev, 0);
+}
+
+static void devices_teardown_cb(libxl__egc *egc,
+ libxl__multidev *multidev,
+ int rc)
+{
+ int i;
+
+ STATE_AO_GC(multidev->ao);
+
+ /* Convenience aliases */
+ libxl__remus_devices_state *const rds =
+ CONTAINER_OF(multidev, *rds, multidev);
+
+ /* clean nic */
+ for (i = 0; i < rds->num_nics; i++)
+ libxl_device_nic_dispose(&rds->nics[i]);
+ free(rds->nics);
+ rds->nics = NULL;
+ rds->num_nics = 0;
+
+ /* clean disk */
+ for (i = 0; i < rds->num_disks; i++)
+ libxl_device_disk_dispose(&rds->disks[i]);
+ free(rds->disks);
+ rds->disks = NULL;
+ rds->num_disks = 0;
+
+ cleanup_device_subkind(rds);
+
+ rds->callback(egc, rds, rc);
+}
+
+/*----- checkpointing APIs -----*/
+
+/* callbacks */
+
+static void devices_checkpoint_cb(libxl__egc *egc,
+ libxl__multidev *multidev,
+ int rc);
+
+/* API implementations */
+
+#define define_remus_checkpoint_api(api) \
+void libxl__remus_devices_##api(libxl__egc *egc, \
+ libxl__remus_devices_state *rds) \
+{ \
+ int i; \
+ libxl__remus_device *dev; \
+ \
+ STATE_AO_GC(rds->ao); \
+ \
+ libxl__multidev_begin(ao, &rds->multidev); \
+ rds->multidev.callback = devices_checkpoint_cb; \
+ for (i = 0; i < rds->num_devices; i++) { \
+ dev = rds->devs[i]; \
+ if (!dev->matched || !dev->ops->api) \
+ continue; \
+ libxl__multidev_prepare_with_aodev(&rds->multidev, &dev->aodev);\
+ dev->ops->api(egc,dev); \
+ } \
+ \
+ libxl__multidev_prepared(egc, &rds->multidev, 0); \
+}
+
+define_remus_checkpoint_api(postsuspend);
+
+define_remus_checkpoint_api(preresume);
+
+define_remus_checkpoint_api(commit);
+
+static void devices_checkpoint_cb(libxl__egc *egc,
+ libxl__multidev *multidev,
+ int rc)
+{
+ STATE_AO_GC(multidev->ao);
+
+ /* Convenience aliases */
+ libxl__remus_devices_state *const rds =
+ CONTAINER_OF(multidev, *rds, multidev);
+
+ rds->callback(egc, rds, rc);
+}
diff --git a/tools/libxl/libxl_remus_disk_drbd.c b/tools/libxl/libxl_remus_disk_drbd.c
new file mode 100644
index 0000000..3215f93
--- /dev/null
+++ b/tools/libxl/libxl_remus_disk_drbd.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2014 FUJITSU LIMITED
+ * Author Lai Jiangshan <laijs at cn.fujitsu.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+
+/*** drbd implementation ***/
+const int DRBD_SEND_CHECKPOINT = 20;
+const int DRBD_WAIT_CHECKPOINT_ACK = 30;
+
+typedef struct libxl__remus_drbd_disk {
+ int ctl_fd;
+ int ackwait;
+} libxl__remus_drbd_disk;
+
+int init_subkind_drbd_disk(libxl__remus_devices_state *rds)
+{
+ STATE_AO_GC(rds->ao);
+
+ rds->drbd_probe_script = GCSPRINTF("%s/block-drbd-probe",
+ libxl__xen_script_dir_path());
+
+ return 0;
+}
+
+void cleanup_subkind_drbd_disk(libxl__remus_devices_state *rds)
+{
+ return;
+}
+
+/*----- helper functions, for async calls -----*/
+static void drbd_async_call(libxl__egc *egc,
+ libxl__remus_device *dev,
+ void func(libxl__remus_device *),
+ libxl__ev_child_callback callback)
+{
+ int pid = -1, rc;
+ libxl__ao_device *aodev = &dev->aodev;
+ STATE_AO_GC(dev->rds->ao);
+
+ /* Fork and call */
+ pid = libxl__ev_child_fork(gc, &aodev->child, callback);
+ if (pid == -1) {
+ LOG(ERROR, "unable to fork");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ if (!pid) {
+ /* child */
+ func(dev);
+ /* notreached */
+ abort();
+ }
+
+ return;
+
+out:
+ aodev->rc = rc;
+ aodev->callback(egc, aodev);
+}
+
+/*----- match(), setup() and teardown() -----*/
+
+/* callbacks */
+static void match_async_exec_cb(libxl__egc *egc,
+ libxl__async_exec_state *aes,
+ int status);
+
+/* implementations */
+
+static void match_async_exec(libxl__egc *egc, libxl__remus_device *dev);
+
+static void drbd_setup(libxl__egc *egc, libxl__remus_device *dev)
+{
+ STATE_AO_GC(dev->rds->ao);
+
+ match_async_exec(egc, dev);
+}
+
+static void match_async_exec(libxl__egc *egc, libxl__remus_device *dev)
+{
+ int arraysize, nr = 0, rc;
+ const libxl_device_disk *disk = dev->backend_dev;
+ libxl__async_exec_state *aes = &dev->aodev.aes;
+ STATE_AO_GC(dev->rds->ao);
+
+ /* setup env & args */
+ arraysize = 1;
+ GCNEW_ARRAY(aes->env, arraysize);
+ aes->env[nr++] = NULL;
+ assert(nr <= arraysize);
+
+ arraysize = 3;
+ nr = 0;
+ GCNEW_ARRAY(aes->args, arraysize);
+ aes->args[nr++] = dev->rds->drbd_probe_script;
+ aes->args[nr++] = disk->pdev_path;
+ aes->args[nr++] = NULL;
+ assert(nr <= arraysize);
+
+ aes->ao = dev->rds->ao;
+ aes->what = GCSPRINTF("%s %s", aes->args[0], aes->args[1]);
+ aes->timeout_ms = LIBXL_HOTPLUG_TIMEOUT * 1000;
+ aes->callback = match_async_exec_cb;
+ aes->stdfds[0] = -1;
+ aes->stdfds[1] = -1;
+ aes->stdfds[2] = -1;
+
+ rc = libxl__async_exec_start(gc, aes);
+ if (rc)
+ goto out;
+
+ return;
+
+out:
+ dev->aodev.rc = rc;
+ dev->aodev.callback(egc, &dev->aodev);
+}
+
+static void match_async_exec_cb(libxl__egc *egc,
+ libxl__async_exec_state *aes,
+ int status)
+{
+ int rc;
+ libxl__ao_device *aodev = CONTAINER_OF(aes, *aodev, aes);
+ libxl__remus_device *dev = CONTAINER_OF(aodev, *dev, aodev);
+ libxl__remus_drbd_disk *drbd_disk;
+ const libxl_device_disk *disk = dev->backend_dev;
+
+ STATE_AO_GC(aodev->ao);
+
+ if (status) {
+ rc = ERROR_REMUS_DEVOPS_DOES_NOT_MATCH;
+ goto out;
+ }
+
+ /* ops matched */
+ dev->matched = true;
+
+ GCNEW(drbd_disk);
+ dev->concrete_data = drbd_disk;
+ drbd_disk->ackwait = 0;
+ drbd_disk->ctl_fd = open(disk->pdev_path, O_RDONLY);
+ if (drbd_disk->ctl_fd < 0) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = 0;
+
+out:
+ aodev->rc = rc;
+ aodev->callback(egc, aodev);
+}
+
+static void drbd_teardown(libxl__egc *egc, libxl__remus_device *dev)
+{
+ libxl__remus_drbd_disk *drbd_disk = dev->concrete_data;
+ STATE_AO_GC(dev->rds->ao);
+
+ close(drbd_disk->ctl_fd);
+ dev->aodev.rc = 0;
+ dev->aodev.callback(egc, &dev->aodev);
+}
+
+/*----- checkpointing APIs -----*/
+
+/* callbacks */
+static void checkpoint_async_call_done(libxl__egc *egc,
+ libxl__ev_child *child,
+ pid_t pid, int status);
+
+/* API implementations */
+
+/* this op will not wait and block, so implement as sync op */
+static void drbd_postsuspend(libxl__egc *egc, libxl__remus_device *dev)
+{
+ STATE_AO_GC(dev->rds->ao);
+
+ libxl__remus_drbd_disk *rdd = dev->concrete_data;
+
+ if (!rdd->ackwait) {
+ if (ioctl(rdd->ctl_fd, DRBD_SEND_CHECKPOINT, 0) <= 0)
+ rdd->ackwait = 1;
+ }
+
+ dev->aodev.rc = 0;
+ dev->aodev.callback(egc, &dev->aodev);
+}
+
+
+static void drbd_preresume_async(libxl__remus_device *dev);
+
+static void drbd_preresume(libxl__egc *egc, libxl__remus_device *dev)
+{
+ STATE_AO_GC(dev->rds->ao);
+
+ drbd_async_call(egc, dev, drbd_preresume_async, checkpoint_async_call_done);
+}
+
+static void drbd_preresume_async(libxl__remus_device *dev)
+{
+ libxl__remus_drbd_disk *rdd = dev->concrete_data;
+ int ackwait = rdd->ackwait;
+
+ if (ackwait) {
+ ioctl(rdd->ctl_fd, DRBD_WAIT_CHECKPOINT_ACK, 0);
+ ackwait = 0;
+ }
+
+ _exit(ackwait);
+}
+
+static void checkpoint_async_call_done(libxl__egc *egc,
+ libxl__ev_child *child,
+ pid_t pid, int status)
+{
+ int rc;
+ libxl__ao_device *aodev = CONTAINER_OF(child, *aodev, child);
+ libxl__remus_device *dev = CONTAINER_OF(aodev, *dev, aodev);
+ libxl__remus_drbd_disk *rdd = dev->concrete_data;
+
+ STATE_AO_GC(aodev->ao);
+
+ if (!WIFEXITED(status)) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rdd->ackwait = WEXITSTATUS(status);
+ rc = 0;
+
+out:
+ aodev->rc = rc;
+ aodev->callback(egc, aodev);
+}
+
+const libxl__remus_device_instance_ops remus_device_drbd_disk = {
+ .kind = LIBXL__DEVICE_KIND_VBD,
+ .setup = drbd_setup,
+ .teardown = drbd_teardown,
+ .postsuspend = drbd_postsuspend,
+ .preresume = drbd_preresume,
+};
diff --git a/tools/libxl/libxl_save_callout.c b/tools/libxl/libxl_save_callout.c
index e3bda8f..40b25e4 100644
--- a/tools/libxl/libxl_save_callout.c
+++ b/tools/libxl/libxl_save_callout.c
@@ -41,8 +41,7 @@ static void helper_done(libxl__egc *egc, libxl__save_helper_state *shs);
/*----- entrypoints -----*/
void libxl__xc_domain_restore(libxl__egc *egc, libxl__domain_create_state *dcs,
- int hvm, int pae, int superpages,
- int no_incr_generationid)
+ int hvm, int pae, int superpages)
{
STATE_AO_GC(dcs->ao);
@@ -59,7 +58,7 @@ void libxl__xc_domain_restore(libxl__egc *egc, libxl__domain_create_state *dcs,
state->store_port,
state->store_domid, state->console_port,
state->console_domid,
- hvm, pae, superpages, no_incr_generationid,
+ hvm, pae, superpages,
cbflags, dcs->checkpointed_stream,
};
@@ -75,8 +74,7 @@ void libxl__xc_domain_restore(libxl__egc *egc, libxl__domain_create_state *dcs,
argnums, ARRAY_SIZE(argnums));
}
-void libxl__xc_domain_save(libxl__egc *egc, libxl__domain_suspend_state *dss,
- unsigned long vm_generationid_addr)
+void libxl__xc_domain_save(libxl__egc *egc, libxl__domain_suspend_state *dss)
{
STATE_AO_GC(dss->ao);
int r, rc, toolstack_data_fd = -1;
@@ -105,10 +103,14 @@ void libxl__xc_domain_save(libxl__egc *egc, libxl__domain_suspend_state *dss,
toolstack_data_buf, toolstack_data_len,
"toolstack data tmpfile", 0);
if (r) { rc = ERROR_FAIL; goto out; }
+
+ /* file position must be reset before passing to libxl-save-helper. */
+ r = lseek(toolstack_data_fd, 0, SEEK_SET);
+ if (r) { rc = ERROR_FAIL; goto out; }
}
const unsigned long argnums[] = {
- dss->domid, 0, 0, dss->xcflags, dss->hvm, vm_generationid_addr,
+ dss->domid, 0, 0, dss->xcflags, dss->hvm,
toolstack_data_fd, toolstack_data_len,
cbflags,
};
@@ -172,7 +174,7 @@ static void run_helper(libxl__egc *egc, libxl__save_helper_state *shs,
shs->stdout_what = GCSPRINTF("domain %"PRIu32" save/restore helper"
" stdout pipe", domid);
- *arg++ = getenv("LIBXL_SAVE_HELPER") ?: PRIVATE_BINDIR "/" "libxl-save-helper";
+ *arg++ = getenv("LIBXL_SAVE_HELPER") ?: LIBEXEC_BIN "/" "libxl-save-helper";
*arg++ = mode_arg;
const char **stream_fd_arg = arg++;
for (i=0; i<num_argnums; i++)
diff --git a/tools/libxl/libxl_save_helper.c b/tools/libxl/libxl_save_helper.c
index 880565e..74826a1 100644
--- a/tools/libxl/libxl_save_helper.c
+++ b/tools/libxl/libxl_save_helper.c
@@ -47,10 +47,43 @@
#include "xenguest.h"
#include "_libxl_save_msgs_helper.h"
+/*----- logger -----*/
+
+static void tellparent_vmessage(xentoollog_logger *logger_in,
+ xentoollog_level level,
+ int errnoval,
+ const char *context,
+ const char *format,
+ va_list al)
+{
+ char *formatted;
+ int r = vasprintf(&formatted, format, al);
+ if (r < 0) { perror("memory allocation failed during logging"); exit(-1); }
+ helper_stub_log(level, errnoval, context, formatted, 0);
+ free(formatted);
+}
+
+static void tellparent_progress(struct xentoollog_logger *logger_in,
+ const char *context,
+ const char *doing_what, int percent,
+ unsigned long done, unsigned long total)
+{
+ helper_stub_progress(context, doing_what, done, total, 0);
+}
+
+static void tellparent_destroy(struct xentoollog_logger *logger_in)
+{
+ abort();
+}
+
/*----- globals -----*/
static const char *program = "libxl-save-helper";
-static xentoollog_logger *logger;
+static xentoollog_logger logger = {
+ tellparent_vmessage,
+ tellparent_progress,
+ tellparent_destroy,
+};
static xc_interface *xch;
/*----- error handling -----*/
@@ -61,7 +94,7 @@ static void fail(int errnoval, const char *fmt, ...)
{
va_list al;
va_start(al,fmt);
- xtl_logv(logger,XTL_ERROR,errnoval,program,fmt,al);
+ xtl_logv(&logger,XTL_ERROR,errnoval,program,fmt,al);
exit(-1);
}
@@ -86,45 +119,6 @@ static void *xmalloc(size_t sz)
return r;
}
-/*----- logger -----*/
-
-typedef struct {
- xentoollog_logger vtable;
-} xentoollog_logger_tellparent;
-
-static void tellparent_vmessage(xentoollog_logger *logger_in,
- xentoollog_level level,
- int errnoval,
- const char *context,
- const char *format,
- va_list al)
-{
- char *formatted;
- int r = vasprintf(&formatted, format, al);
- if (r < 0) { perror("memory allocation failed during logging"); exit(-1); }
- helper_stub_log(level, errnoval, context, formatted, 0);
- free(formatted);
-}
-
-static void tellparent_progress(struct xentoollog_logger *logger_in,
- const char *context,
- const char *doing_what, int percent,
- unsigned long done, unsigned long total)
-{
- helper_stub_progress(context, doing_what, done, total, 0);
-}
-
-static void tellparent_destroy(struct xentoollog_logger *logger_in)
-{
- abort();
-}
-
-static xentoollog_logger_tellparent *createlogger_tellparent(void)
-{
- xentoollog_logger_tellparent newlogger;
- return XTL_NEW_LOGGER(tellparent, newlogger);
-}
-
/*----- helper functions called by autogenerated stubs -----*/
unsigned char * helper_allocbuf(int len, void *user)
@@ -165,14 +159,20 @@ int helper_getreply(void *user)
static int toolstack_save_fd;
static uint32_t toolstack_save_len;
+static struct save_callbacks helper_save_callbacks;
static int toolstack_save_cb(uint32_t domid, uint8_t **buf,
uint32_t *len, void *data)
{
+ int r;
+
assert(toolstack_save_fd > 0);
- int r = lseek(toolstack_save_fd, 0, SEEK_SET);
- if (r) fail(errno,"rewind toolstack data tmpfile");
+ /* This is a hack for remus */
+ if (helper_save_callbacks.checkpoint) {
+ r = lseek(toolstack_save_fd, 0, SEEK_SET);
+ if (r) fail(errno,"rewind toolstack data tmpfile");
+ }
*buf = xmalloc(toolstack_save_len);
r = read_exactly(toolstack_save_fd, *buf, toolstack_save_len);
@@ -184,26 +184,20 @@ static int toolstack_save_cb(uint32_t domid, uint8_t **buf,
}
static void startup(const char *op) {
- logger = (xentoollog_logger*)createlogger_tellparent();
- if (!logger) {
- fprintf(stderr, "%s: cannot initialise logger\n", program);
- exit(-1);
- }
+ xtl_log(&logger,XTL_DEBUG,0,program,"starting %s",op);
- xtl_log(logger,XTL_DEBUG,0,program,"starting %s",op);
-
- xch = xc_interface_open(logger,logger,0);
+ xch = xc_interface_open(&logger,&logger,0);
if (!xch) fail(errno,"xc_interface_open failed");
}
static void complete(int retval) {
int errnoval = retval ? errno : 0; /* suppress irrelevant errnos */
- xtl_log(logger,XTL_DEBUG,errnoval,program,"complete r=%d",retval);
+ xtl_log(&logger,XTL_DEBUG,errnoval,program,"complete r=%d",retval);
helper_stub_complete(retval,errnoval,0);
+ xc_interface_close(xch);
exit(0);
}
-static struct save_callbacks helper_save_callbacks;
static struct restore_callbacks helper_restore_callbacks;
int main(int argc, char **argv)
@@ -223,7 +217,6 @@ int main(int argc, char **argv)
uint32_t max_factor = strtoul(NEXTARG,0,10);
uint32_t flags = strtoul(NEXTARG,0,10);
int hvm = atoi(NEXTARG);
- unsigned long genidad = strtoul(NEXTARG,0,10);
toolstack_save_fd = atoi(NEXTARG);
toolstack_save_len = strtoul(NEXTARG,0,10);
unsigned cbflags = strtoul(NEXTARG,0,10);
@@ -236,7 +229,7 @@ int main(int argc, char **argv)
startup("save");
r = xc_domain_save(xch, io_fd, dom, max_iters, max_factor, flags,
- &helper_save_callbacks, hvm, genidad);
+ &helper_save_callbacks, hvm);
complete(r);
} else if (!strcmp(mode,"--restore-domain")) {
@@ -250,7 +243,6 @@ int main(int argc, char **argv)
unsigned int hvm = strtoul(NEXTARG,0,10);
unsigned int pae = strtoul(NEXTARG,0,10);
int superpages = strtoul(NEXTARG,0,10);
- int no_incr_genidad = strtoul(NEXTARG,0,10);
unsigned cbflags = strtoul(NEXTARG,0,10);
int checkpointed = strtoul(NEXTARG,0,10);
assert(!*++argv);
@@ -259,15 +251,14 @@ int main(int argc, char **argv)
unsigned long store_mfn = 0;
unsigned long console_mfn = 0;
- unsigned long genidad = 0;
startup("restore");
r = xc_domain_restore(xch, io_fd, dom, store_evtchn, &store_mfn,
store_domid, console_evtchn, &console_mfn,
console_domid, hvm, pae, superpages,
- no_incr_genidad, checkpointed, &genidad,
+ checkpointed,
&helper_restore_callbacks);
- helper_stub_restore_results(store_mfn,console_mfn,genidad,0);
+ helper_stub_restore_results(store_mfn,console_mfn,0);
complete(r);
} else {
diff --git a/tools/libxl/libxl_save_msgs_gen.pl b/tools/libxl/libxl_save_msgs_gen.pl
index ee126c7..6b4b65e 100755
--- a/tools/libxl/libxl_save_msgs_gen.pl
+++ b/tools/libxl/libxl_save_msgs_gen.pl
@@ -23,17 +23,16 @@ our @msgs = (
STRING doing_what),
'unsigned long', 'done',
'unsigned long', 'total'] ],
- [ 3, 'scxW', "suspend", [] ],
- [ 4, 'scxW', "postcopy", [] ],
- [ 5, 'scxA', "checkpoint", [] ],
+ [ 3, 'scxA', "suspend", [] ],
+ [ 4, 'scxA', "postcopy", [] ],
+ [ 5, 'scxA', "checkpoint", [] ],
[ 6, 'scxA', "switch_qemu_logdirty", [qw(int domid
unsigned enable)] ],
# toolstack_save done entirely `by hand'
[ 7, 'rcxW', "toolstack_restore", [qw(uint32_t domid
BLOCK tsdata)] ],
[ 8, 'r', "restore_results", ['unsigned long', 'store_mfn',
- 'unsigned long', 'console_mfn',
- 'unsigned long', 'genidad'] ],
+ 'unsigned long', 'console_mfn'] ],
[ 9, 'srW', "complete", [qw(int retval
int errnoval)] ],
);
@@ -199,7 +198,7 @@ static void BLOCK_put(unsigned char *const buf,
uint32_t_put(buf, len, size);
bytes_put(buf, len, bytes, size);
}
-
+
static void STRING_put(unsigned char *const buf,
int *len,
const char *string)
@@ -209,7 +208,7 @@ static void STRING_put(unsigned char *const buf,
assert(slen < (uint32_t)0x40000000);
BLOCK_put(buf, len, (const void*)string, slen+1);
}
-
+
END
foreach my $sr (qw(save restore)) {
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 649ce50..f7fc695 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -5,24 +5,39 @@
namespace("libxl_")
-libxl_defbool = Builtin("defbool", passby=PASS_BY_REFERENCE)
-
-libxl_domid = Builtin("domid", json_fn = "yajl_gen_integer", autogenerate_json = False)
-libxl_devid = Builtin("devid", json_fn = "yajl_gen_integer", autogenerate_json = False, signed = True, init_val="-1")
-libxl_uuid = Builtin("uuid", passby=PASS_BY_REFERENCE)
-libxl_mac = Builtin("mac", passby=PASS_BY_REFERENCE)
-libxl_bitmap = Builtin("bitmap", dispose_fn="libxl_bitmap_dispose", passby=PASS_BY_REFERENCE)
-libxl_cpuid_policy_list = Builtin("cpuid_policy_list", dispose_fn="libxl_cpuid_dispose", passby=PASS_BY_REFERENCE)
-
-libxl_string_list = Builtin("string_list", dispose_fn="libxl_string_list_dispose", passby=PASS_BY_REFERENCE)
-libxl_key_value_list = Builtin("key_value_list", dispose_fn="libxl_key_value_list_dispose", passby=PASS_BY_REFERENCE)
-libxl_hwcap = Builtin("hwcap", passby=PASS_BY_REFERENCE)
+libxl_defbool = Builtin("defbool", json_parse_type="JSON_STRING", passby=PASS_BY_REFERENCE, copy_fn=None,
+ check_default_fn="libxl__defbool_is_default")
+libxl_domid = Builtin("domid", json_gen_fn = "yajl_gen_integer", json_parse_fn = "libxl__uint32_parse_json",
+ json_parse_type = "JSON_INTEGER", autogenerate_json = False, copy_fn=None)
+libxl_devid = Builtin("devid", json_gen_fn = "yajl_gen_integer", json_parse_fn = "libxl__int_parse_json",
+ json_parse_type = "JSON_INTEGER", autogenerate_json = False, signed = True, init_val="-1",
+ copy_fn=None)
+libxl_uuid = Builtin("uuid", json_parse_type="JSON_STRING", passby=PASS_BY_REFERENCE, check_default_fn="libxl_uuid_is_nil",
+ copy_fn="libxl_uuid_copy")
+libxl_mac = Builtin("mac", json_parse_type="JSON_STRING", passby=PASS_BY_REFERENCE, check_default_fn="libxl__mac_is_default",
+ copy_fn="libxl_mac_copy")
+libxl_bitmap = Builtin("bitmap", json_parse_type="JSON_ARRAY", dispose_fn="libxl_bitmap_dispose", passby=PASS_BY_REFERENCE,
+ check_default_fn="libxl_bitmap_is_empty", copy_fn="libxl_bitmap_copy_alloc")
+libxl_cpuid_policy_list = Builtin("cpuid_policy_list", dispose_fn="libxl_cpuid_dispose", passby=PASS_BY_REFERENCE,
+ json_parse_type="JSON_ARRAY", check_default_fn="libxl__cpuid_policy_is_empty",
+ copy_fn="libxl_cpuid_policy_list_copy")
+
+libxl_string_list = Builtin("string_list", dispose_fn="libxl_string_list_dispose", passby=PASS_BY_REFERENCE,
+ json_parse_type="JSON_ARRAY", check_default_fn="libxl__string_list_is_empty",
+ copy_fn="libxl_string_list_copy")
+libxl_key_value_list = Builtin("key_value_list", dispose_fn="libxl_key_value_list_dispose", passby=PASS_BY_REFERENCE,
+ json_parse_type="JSON_MAP", check_default_fn="libxl__key_value_list_is_empty",
+ copy_fn="libxl_key_value_list_copy")
+libxl_hwcap = Builtin("hwcap", passby=PASS_BY_REFERENCE, json_parse_type="JSON_ARRAY",
+ check_default_fn="libxl__hwcap_is_default", copy_fn="libxl_hwcap_copy")
+libxl_ms_vm_genid = Builtin("ms_vm_genid", passby=PASS_BY_REFERENCE, check_default_fn="libxl_ms_vm_genid_is_zero",
+ copy_fn="libxl_ms_vm_genid_copy")
#
# Specific integer types
#
-MemKB = UInt(64, init_val = "LIBXL_MEMKB_DEFAULT")
+MemKB = UInt(64, init_val = "LIBXL_MEMKB_DEFAULT", json_gen_fn = "libxl__uint64_gen_json")
#
# Constants / Enumerations
@@ -43,13 +58,24 @@ libxl_error = Enumeration("error", [
(-12, "OSEVENT_REG_FAIL"),
(-13, "BUFFERFULL"),
(-14, "UNKNOWN_CHILD"),
+ (-15, "LOCK_FAIL"),
+ (-16, "JSON_CONFIG_EMPTY"),
+ (-17, "DEVICE_EXISTS"),
+ (-18, "REMUS_DEVOPS_DOES_NOT_MATCH"),
+ (-19, "REMUS_DEVICE_NOT_SUPPORTED"),
], value_namespace = "")
libxl_domain_type = Enumeration("domain_type", [
(-1, "INVALID"),
(1, "HVM"),
(2, "PV"),
- ], init_val = -1)
+ ], init_val = "LIBXL_DOMAIN_TYPE_INVALID")
+
+libxl_channel_connection = Enumeration("channel_connection", [
+ (0, "UNKNOWN"),
+ (1, "PTY"),
+ (2, "SOCKET"), # a listening Unix domain socket
+ ])
libxl_device_model_version = Enumeration("device_model_version", [
(0, "UNKNOWN"),
@@ -95,7 +121,7 @@ libxl_action_on_shutdown = Enumeration("action_on_shutdown", [
(5, "COREDUMP_DESTROY"),
(6, "COREDUMP_RESTART"),
- ], init_val = 1)
+ ], init_val = "LIBXL_ACTION_ON_SHUTDOWN_DESTROY")
libxl_trigger = Enumeration("trigger", [
(0, "UNKNOWN"),
@@ -138,6 +164,7 @@ libxl_scheduler = Enumeration("scheduler", [
(5, "credit"),
(6, "credit2"),
(7, "arinc653"),
+ (8, "rtds"),
])
# Consistent with SHUTDOWN_* in sched.h (apart from UNKNOWN)
@@ -153,12 +180,20 @@ libxl_shutdown_reason = Enumeration("shutdown_reason", [
libxl_vga_interface_type = Enumeration("vga_interface_type", [
(1, "CIRRUS"),
(2, "STD"),
- ], init_val = 1)
+ (3, "NONE"),
+ ], init_val = "LIBXL_VGA_INTERFACE_TYPE_CIRRUS")
libxl_vendor_device = Enumeration("vendor_device", [
(0, "NONE"),
(1, "XENSERVER"),
])
+
+libxl_viridian_enlightenment = Enumeration("viridian_enlightenment", [
+ (0, "base"),
+ (1, "freq"),
+ (2, "time_ref_count"),
+ ])
+
#
# Complex libxl types
#
@@ -169,8 +204,12 @@ libxl_ioport_range = Struct("ioport_range", [
])
libxl_iomem_range = Struct("iomem_range", [
+ # start host frame number to be mapped to the guest
("start", uint64),
+ # number of frames to be mapped
("number", uint64),
+ # guest frame number used as a start for the mapping
+ ("gfn", uint64, {'init_val': "LIBXL_INVALID_GFN"}),
])
libxl_vga_interface_info = Struct("vga_interface_info", [
@@ -214,13 +253,14 @@ libxl_dominfo = Struct("dominfo",[
("uuid", libxl_uuid),
("domid", libxl_domid),
("ssidref", uint32),
+ ("ssid_label", string),
("running", bool),
("blocked", bool),
("paused", bool),
("shutdown", bool),
("dying", bool),
- # Valid iff (shutdown||dying).
+ # Valid iff ->shutdown is true.
#
# Otherwise set to a value guaranteed not to clash with any valid
# LIBXL_SHUTDOWN_REASON_* constant.
@@ -239,11 +279,28 @@ libxl_dominfo = Struct("dominfo",[
libxl_cpupoolinfo = Struct("cpupoolinfo", [
("poolid", uint32),
+ ("pool_name", string),
("sched", libxl_scheduler),
("n_dom", uint32),
("cpumap", libxl_bitmap)
], dir=DIR_OUT)
+libxl_channelinfo = Struct("channelinfo", [
+ ("backend", string),
+ ("backend_id", uint32),
+ ("frontend", string),
+ ("frontend_id", uint32),
+ ("devid", libxl_devid),
+ ("state", integer),
+ ("evtch", integer),
+ ("rref", integer),
+ ("u", KeyedUnion(None, libxl_channel_connection, "connection",
+ [("unknown", None),
+ ("pty", Struct(None, [("path", string),])),
+ ("socket", None),
+ ])),
+ ], dir=DIR_OUT)
+
libxl_vminfo = Struct("vminfo", [
("uuid", libxl_uuid),
("domid", libxl_domid),
@@ -269,11 +326,13 @@ libxl_domain_create_info = Struct("domain_create_info",[
("hap", libxl_defbool),
("oos", libxl_defbool),
("ssidref", uint32),
+ ("ssid_label", string),
("name", string),
("uuid", libxl_uuid),
("xsdata", libxl_key_value_list),
("platformdata", libxl_key_value_list),
("poolid", uint32),
+ ("pool_name", string),
("run_hotplug_scripts",libxl_defbool),
("pvh", libxl_defbool),
("driver_domain",libxl_defbool),
@@ -283,8 +342,6 @@ libxl_domain_restore_params = Struct("domain_restore_params", [
("checkpointed_stream", integer),
])
-MemKB = UInt(64, init_val = "LIBXL_MEMKB_DEFAULT")
-
libxl_domain_sched_params = Struct("domain_sched_params",[
("sched", libxl_scheduler),
("weight", integer, {'init_val': 'LIBXL_DOMAIN_SCHED_PARAM_WEIGHT_DEFAULT'}),
@@ -293,6 +350,7 @@ libxl_domain_sched_params = Struct("domain_sched_params",[
("slice", integer, {'init_val': 'LIBXL_DOMAIN_SCHED_PARAM_SLICE_DEFAULT'}),
("latency", integer, {'init_val': 'LIBXL_DOMAIN_SCHED_PARAM_LATENCY_DEFAULT'}),
("extratime", integer, {'init_val': 'LIBXL_DOMAIN_SCHED_PARAM_EXTRATIME_DEFAULT'}),
+ ("budget", integer, {'init_val': 'LIBXL_DOMAIN_SCHED_PARAM_BUDGET_DEFAULT'}),
])
libxl_domain_build_info = Struct("domain_build_info",[
@@ -300,6 +358,8 @@ libxl_domain_build_info = Struct("domain_build_info",[
("avail_vcpus", libxl_bitmap),
("cpumap", libxl_bitmap),
("nodemap", libxl_bitmap),
+ ("vcpu_hard_affinity", Array(libxl_bitmap, "num_vcpu_hard_affinity")),
+ ("vcpu_soft_affinity", Array(libxl_bitmap, "num_vcpu_soft_affinity")),
("numa_placement", libxl_defbool),
("tsc_mode", libxl_tsc_mode),
("max_memkb", MemKB),
@@ -308,6 +368,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
("shadow_memkb", MemKB),
("rtc_timeoffset", uint32),
("exec_ssidref", uint32),
+ ("exec_ssid_label", string),
("localtime", libxl_defbool),
("disable_migrate", libxl_defbool),
("cpuid", libxl_cpuid_policy_list),
@@ -318,6 +379,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
# if you set device_model you must set device_model_version too
("device_model", string),
("device_model_ssidref", uint32),
+ ("device_model_ssid_label", string),
# extra parameters pass directly to qemu, NULL terminated
("extra", libxl_string_list),
@@ -333,6 +395,9 @@ libxl_domain_build_info = Struct("domain_build_info",[
("iomem", Array(libxl_iomem_range, "num_iomem")),
("claim_mode", libxl_defbool),
("event_channels", uint32),
+ ("kernel", string),
+ ("cmdline", string),
+ ("ramdisk", string),
("u", KeyedUnion(None, libxl_domain_type, "type",
[("hvm", Struct(None, [("firmware", string),
("bios", libxl_bios_type),
@@ -343,9 +408,12 @@ libxl_domain_build_info = Struct("domain_build_info",[
("acpi_s4", libxl_defbool),
("nx", libxl_defbool),
("viridian", libxl_defbool),
+ ("viridian_enable", libxl_bitmap),
+ ("viridian_disable", libxl_bitmap),
("timeoffset", string),
("hpet", libxl_defbool),
("vpt_align", libxl_defbool),
+ ("mmio_hole_memkb", MemKB),
("timer_mode", libxl_timer_mode),
("nested_hvm", libxl_defbool),
("smbios_firmware", string),
@@ -372,6 +440,9 @@ libxl_domain_build_info = Struct("domain_build_info",[
("xen_platform_pci", libxl_defbool),
("usbdevice_list", libxl_string_list),
("vendor_device", libxl_vendor_device),
+ # See libxl_ms_vm_genid_generate()
+ ("ms_vm_genid", libxl_ms_vm_genid),
+ ("serial_list", libxl_string_list),
])),
("pv", Struct(None, [("kernel", string),
("slack_memkb", MemKB),
@@ -415,6 +486,8 @@ libxl_device_disk = Struct("device_disk", [
("removable", integer),
("readwrite", integer),
("is_cdrom", integer),
+ ("direct_io_safe", bool),
+ ("discard_enable", libxl_defbool),
])
libxl_device_nic = Struct("device_nic", [
@@ -444,6 +517,7 @@ libxl_device_pci = Struct("device_pci", [
("msitranslate", bool),
("power_mgmt", bool),
("permissive", bool),
+ ("seize", bool),
])
libxl_device_vtpm = Struct("device_vtpm", [
@@ -453,6 +527,18 @@ libxl_device_vtpm = Struct("device_vtpm", [
("uuid", libxl_uuid),
])
+libxl_device_channel = Struct("device_channel", [
+ ("backend_domid", libxl_domid),
+ ("backend_domname", string),
+ ("devid", libxl_devid),
+ ("name", string),
+ ("u", KeyedUnion(None, libxl_channel_connection, "connection",
+ [("unknown", None),
+ ("pty", None),
+ ("socket", Struct(None, [("path", string)])),
+ ])),
+])
+
libxl_domain_config = Struct("domain_config", [
("c_info", libxl_domain_create_info),
("b_info", libxl_domain_build_info),
@@ -463,6 +549,9 @@ libxl_domain_config = Struct("domain_config", [
("vfbs", Array(libxl_device_vfb, "num_vfbs")),
("vkbs", Array(libxl_device_vkb, "num_vkbs")),
("vtpms", Array(libxl_device_vtpm, "num_vtpms")),
+ # a channel manifests as a console with a name,
+ # see docs/misc/channels.txt
+ ("channels", Array(libxl_device_channel, "num_channels")),
("on_poweroff", libxl_action_on_shutdown),
("on_reboot", libxl_action_on_shutdown),
@@ -512,7 +601,8 @@ libxl_vcpuinfo = Struct("vcpuinfo", [
("blocked", bool),
("running", bool),
("vcpu_time", uint64), # total vcpu time ran (ns)
- ("cpumap", libxl_bitmap), # current cpu's affinities
+ ("cpumap", libxl_bitmap), # current hard cpu affinity
+ ("cpumap_soft", libxl_bitmap), # current soft cpu affinity
], dir=DIR_OUT)
libxl_physinfo = Struct("physinfo", [
@@ -559,8 +649,12 @@ libxl_sched_credit_params = Struct("sched_credit_params", [
libxl_domain_remus_info = Struct("domain_remus_info",[
("interval", integer),
- ("blackhole", bool),
- ("compression", bool),
+ ("allow_unsafe", libxl_defbool),
+ ("blackhole", libxl_defbool),
+ ("compression", libxl_defbool),
+ ("netbuf", libxl_defbool),
+ ("netbufscript", string),
+ ("diskbuf", libxl_defbool),
])
libxl_event_type = Enumeration("event_type", [
@@ -573,7 +667,7 @@ libxl_event_type = Enumeration("event_type", [
libxl_ev_user = UInt(64)
-libxl_ev_link = Builtin("ev_link", passby=PASS_BY_REFERENCE, private=True)
+libxl_ev_link = Builtin("ev_link", json_parse_type="JSON_STRING", passby=PASS_BY_REFERENCE, private=True)
libxl_event = Struct("event",[
("link", libxl_ev_link),
@@ -586,7 +680,7 @@ libxl_event = Struct("event",[
[("domain_shutdown", Struct(None, [
("shutdown_reason", uint8),
])),
- ("domain_death", Struct(None, [])),
+ ("domain_death", None),
("disk_eject", Struct(None, [
("vdev", string),
("disk", libxl_device_disk),
@@ -594,5 +688,9 @@ libxl_event = Struct("event",[
("operation_complete", Struct(None, [
("rc", integer),
])),
- ("domain_create_console_available", Struct(None, [])),
+ ("domain_create_console_available", None),
]))])
+
+libxl_psr_cmt_type = Enumeration("psr_cmt_type", [
+ (1, "CACHE_OCCUPANCY"),
+ ])
diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl
index cb9444f..5e55685 100644
--- a/tools/libxl/libxl_types_internal.idl
+++ b/tools/libxl/libxl_types_internal.idl
@@ -1,7 +1,9 @@
namespace("libxl__")
hidden(True)
-libxl_domid = Builtin("domid", namespace="libxl_", json_fn = "yajl_gen_integer")
+libxl_domid = Builtin("domid", namespace="libxl_", json_gen_fn = "yajl_gen_integer",
+ json_parse_fn = "libxl__uint32_parse_json", json_parse_type = "JSON_INTEGER",
+ autogenerate_json = False, copy_fn = None)
libxl__qmp_message_type = Enumeration("qmp_message_type", [
(1, "QMP"),
@@ -32,6 +34,11 @@ libxl__device_console = Struct("device_console", [
("devid", integer),
("consback", libxl__console_backend),
("output", string),
+ # A regular console has no name.
+ # A console with a name is called a 'channel', see docs/misc/channels.txt
+ ("name", string),
+ ("connection", string),
+ ("path", string),
])
libxl__device_action = Enumeration("device_action", [
diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c
index 1f334f2..3e1ba17 100644
--- a/tools/libxl/libxl_utils.c
+++ b/tools/libxl/libxl_utils.c
@@ -108,6 +108,37 @@ int libxl_domain_qualifier_to_domid(libxl_ctx *ctx, const char *name,
return rv;
}
+static int qualifier_to_id(const char *p, uint32_t *id_r)
+{
+ int i, alldigit;
+
+ alldigit = 1;
+ for (i = 0; p[i]; i++) {
+ if (!isdigit((uint8_t)p[i])) {
+ alldigit = 0;
+ break;
+ }
+ }
+
+ if (i > 0 && alldigit) {
+ *id_r = strtoul(p, NULL, 10);
+ return 0;
+ } else {
+ /* check here if it's a uuid and do proper conversion */
+ }
+ return 1;
+}
+
+int libxl_cpupool_qualifier_to_cpupoolid(libxl_ctx *ctx, const char *p,
+ uint32_t *poolid_r,
+ int *was_name_r)
+{
+ int was_name;
+
+ was_name = qualifier_to_id(p, poolid_r);
+ if (was_name_r) *was_name_r = was_name;
+ return was_name ? libxl_name_to_cpupoolid(ctx, p, poolid_r) : 0;
+}
char *libxl_cpupoolid_to_name(libxl_ctx *ctx, uint32_t poolid)
{
@@ -505,7 +536,7 @@ int libxl_uuid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
if(!libxl_uuid_compare(uuid, &vtpms[i].uuid)) {
vtpm->backend_domid = vtpms[i].backend_domid;
vtpm->devid = vtpms[i].devid;
- libxl_uuid_copy(&vtpm->uuid, &vtpms[i].uuid);
+ libxl_uuid_copy(ctx, &vtpm->uuid, &vtpms[i].uuid);
rc = 0;
break;
}
@@ -583,6 +614,34 @@ void libxl_bitmap_copy(libxl_ctx *ctx, libxl_bitmap *dptr,
memcpy(dptr->map, sptr->map, sz * sizeof(*dptr->map));
}
+/* This function copies X bytes from source to destination bitmap,
+ * where X is the smaller of the two sizes.
+ *
+ * If destination's size is larger than source, the extra bytes are
+ * untouched.
+ */
+void libxl__bitmap_copy_best_effort(libxl__gc *gc, libxl_bitmap *dptr,
+ const libxl_bitmap *sptr)
+{
+ int sz;
+
+ sz = dptr->size < sptr->size ? dptr->size : sptr->size;
+ memcpy(dptr->map, sptr->map, sz * sizeof(*dptr->map));
+}
+
+void libxl_bitmap_copy_alloc(libxl_ctx *ctx,
+ libxl_bitmap *dptr,
+ const libxl_bitmap *sptr)
+{
+ GC_INIT(ctx);
+
+ dptr->map = libxl__calloc(NOGC, sptr->size, sizeof(*sptr->map));
+ dptr->size = sptr->size;
+ memcpy(dptr->map, sptr->map, sptr->size * sizeof(*sptr->map));
+
+ GC_FREE;
+}
+
int libxl_bitmap_is_full(const libxl_bitmap *bitmap)
{
int i;
@@ -982,6 +1041,45 @@ int libxl_domid_valid_guest(uint32_t domid)
return domid > 0 && domid < DOMID_FIRST_RESERVED;
}
+void libxl_string_copy(libxl_ctx *ctx, char **dst, char **src)
+{
+ GC_INIT(ctx);
+
+ if (*src)
+ *dst = libxl__strdup(NOGC, *src);
+ else
+ *dst = NULL;
+
+ GC_FREE;
+}
+
+/*
+ * Fill @buf with @len random bytes.
+ */
+int libxl__random_bytes(libxl__gc *gc, uint8_t *buf, size_t len)
+{
+ static const char *dev = "/dev/urandom";
+ int fd;
+ int ret;
+
+ fd = open(dev, O_RDONLY);
+ if (fd < 0) {
+ LOGE(ERROR, "failed to open \"%s\"", dev);
+ return ERROR_FAIL;
+ }
+ ret = libxl_fd_set_cloexec(CTX, fd, 1);
+ if (ret) {
+ close(fd);
+ return ERROR_FAIL;
+ }
+
+ ret = libxl_read_exactly(CTX, fd, buf, len, dev, NULL);
+
+ close(fd);
+
+ return ret;
+}
+
/*
* Local variables:
* mode: C
diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h
index e37fb89..117b229 100644
--- a/tools/libxl/libxl_utils.h
+++ b/tools/libxl/libxl_utils.h
@@ -23,6 +23,9 @@ unsigned long libxl_get_required_shadow_memory(unsigned long maxmem_kb, unsigned
int libxl_name_to_domid(libxl_ctx *ctx, const char *name, uint32_t *domid);
int libxl_domain_qualifier_to_domid(libxl_ctx *ctx, const char *name, uint32_t *domid);
char *libxl_domid_to_name(libxl_ctx *ctx, uint32_t domid);
+int libxl_cpupool_qualifier_to_cpupoolid(libxl_ctx *ctx, const char *p,
+ uint32_t *poolid_r,
+ int *was_name_r);
int libxl_name_to_cpupoolid(libxl_ctx *ctx, const char *name, uint32_t *poolid);
char *libxl_cpupoolid_to_name(libxl_ctx *ctx, uint32_t poolid);
int libxl_cpupoolid_is_valid(libxl_ctx *ctx, uint32_t poolid);
@@ -73,6 +76,8 @@ int libxl_devid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
int libxl_bitmap_alloc(libxl_ctx *ctx, libxl_bitmap *bitmap, int n_bits);
/* Allocated bimap is from malloc, libxl_bitmap_dispose() to be
* called by the application when done. */
+void libxl_bitmap_copy_alloc(libxl_ctx *ctx, libxl_bitmap *dptr,
+ const libxl_bitmap *sptr);
void libxl_bitmap_copy(libxl_ctx *ctx, libxl_bitmap *dptr,
const libxl_bitmap *sptr);
int libxl_bitmap_is_full(const libxl_bitmap *bitmap);
@@ -98,6 +103,31 @@ static inline int libxl_bitmap_cpu_valid(libxl_bitmap *bitmap, int bit)
#define libxl_for_each_set_bit(v, m) for (v = 0; v < (m).size * 8; v++) \
if (libxl_bitmap_test(&(m), v))
+/*
+ * Compares two bitmaps bit by bit, up to nr_bits or, if nr_bits is 0, up
+ * to the size of the largest bitmap. If sizes does not match, bits past the
+ * of a bitmap are considered as being 0, which matches with the semantic and
+ * implementation of libxl_bitmap_test I think().
+ *
+ * So, basically, [0,1,0] and [0,1] are considered equal, while [0,1,1] and
+ * [0,1] are different.
+ */
+static inline int libxl_bitmap_equal(const libxl_bitmap *ba,
+ const libxl_bitmap *bb,
+ int nr_bits)
+{
+ int i;
+
+ if (nr_bits == 0)
+ nr_bits = ba->size > bb->size ? ba->size * 8 : bb->size * 8;
+
+ for (i = 0; i < nr_bits; i++) {
+ if (libxl_bitmap_test(ba, i) != libxl_bitmap_test(bb, i))
+ return 0;
+ }
+ return 1;
+}
+
int libxl_cpu_bitmap_alloc(libxl_ctx *ctx, libxl_bitmap *cpumap, int max_cpus);
int libxl_node_bitmap_alloc(libxl_ctx *ctx, libxl_bitmap *nodemap,
int max_nodes);
@@ -118,6 +148,8 @@ int libxl_cpumap_to_nodemap(libxl_ctx *ctx,
return (s + 1023) / 1024;
}
+void libxl_string_copy(libxl_ctx *ctx, char **dst, char **src);
+
#endif
/*
diff --git a/tools/libxl/libxl_uuid.c b/tools/libxl/libxl_uuid.c
index ecc29c7..7d4a032 100644
--- a/tools/libxl/libxl_uuid.c
+++ b/tools/libxl/libxl_uuid.c
@@ -14,13 +14,11 @@
#include "libxl_osdeps.h" /* must come before any other headers */
-#include <libxl_uuid.h>
-
#include "libxl_internal.h"
#if defined(__linux__)
-int libxl_uuid_is_nil(libxl_uuid *uuid)
+int libxl_uuid_is_nil(const libxl_uuid *uuid)
{
return uuid_is_null(uuid->uuid);
}
@@ -35,7 +33,8 @@ int libxl_uuid_from_string(libxl_uuid *uuid, const char *in)
return uuid_parse(in, uuid->uuid);
}
-void libxl_uuid_copy(libxl_uuid *dst, const libxl_uuid *src)
+void libxl_uuid_copy(libxl_ctx *ctx_opt, libxl_uuid *dst,
+ const libxl_uuid *src)
{
uuid_copy(dst->uuid, src->uuid);
}
@@ -45,31 +44,50 @@ void libxl_uuid_clear(libxl_uuid *uuid)
uuid_clear(uuid->uuid);
}
-int libxl_uuid_compare(libxl_uuid *uuid1, libxl_uuid *uuid2)
+int libxl_uuid_compare(const libxl_uuid *uuid1, const libxl_uuid *uuid2)
{
return uuid_compare(uuid1->uuid, uuid2->uuid);
}
+const uint8_t *libxl_uuid_bytearray_const(const libxl_uuid *uuid)
+{
+ return uuid->uuid;
+}
+
uint8_t *libxl_uuid_bytearray(libxl_uuid *uuid)
{
return uuid->uuid;
}
-#elif defined(__NetBSD__)
+#elif defined(__FreeBSD__) || defined(__NetBSD__)
-int libxl_uuid_is_nil(libxl_uuid *uuid)
+int libxl_uuid_is_nil(const libxl_uuid *uuid)
{
uint32_t status;
- return uuid_is_nil((uuid_t *)uuid->uuid, &status);
+
+ return uuid_is_nil(&uuid->uuid, &status);
}
void libxl_uuid_generate(libxl_uuid *uuid)
{
uint32_t status;
- uuid_create((uuid_t *)uuid->uuid, &status);
+
+ BUILD_BUG_ON(sizeof(libxl_uuid) != sizeof(uuid_t));
+ uuid_create(&uuid->uuid, &status);
assert(status == uuid_s_ok);
}
+#ifdef __FreeBSD__
+int libxl_uuid_from_string(libxl_uuid *uuid, const char *in)
+{
+ uint32_t status;
+
+ uuid_from_string(in, &uuid->uuid, &status);
+ if (status != uuid_s_ok)
+ return -1;
+ return 0;
+}
+#else
#define LIBXL__UUID_PTRS(uuid) &uuid[0], &uuid[1], &uuid[2], &uuid[3], \
&uuid[4], &uuid[5], &uuid[6], &uuid[7], \
&uuid[8], &uuid[9], &uuid[10],&uuid[11], \
@@ -81,27 +99,43 @@ int libxl_uuid_from_string(libxl_uuid *uuid, const char *in)
return 0;
}
#undef LIBXL__UUID_PTRS
+#endif
-void libxl_uuid_copy(libxl_uuid *dst, const libxl_uuid *src)
+void libxl_uuid_copy(libxl_ctx *ctx_opt, libxl_uuid *dst,
+ const libxl_uuid *src)
{
- memcpy(dst->uuid, src->uuid, sizeof(dst->uuid));
+ memcpy(&dst->uuid, &src->uuid, sizeof(dst->uuid));
}
void libxl_uuid_clear(libxl_uuid *uuid)
{
- memset(uuid->uuid, 0, sizeof(uuid->uuid));
+ memset(&uuid->uuid, 0, sizeof(uuid->uuid));
}
-int libxl_uuid_compare(libxl_uuid *uuid1, libxl_uuid *uuid2)
+#ifdef __FreeBSD__
+int libxl_uuid_compare(const libxl_uuid *uuid1, const libxl_uuid *uuid2)
+{
+
+ return uuid_compare(&uuid1->uuid, &uuid2->uuid, NULL);
+}
+#else
+int libxl_uuid_compare(const libxl_uuid *uuid1, const libxl_uuid *uuid2)
{
return memcmp(uuid1->uuid, uuid2->uuid, sizeof(uuid1->uuid));
}
+#endif
+
+const uint8_t *libxl_uuid_bytearray_const(const libxl_uuid *uuid)
+{
+
+ return uuid->uuid_raw;
+}
uint8_t *libxl_uuid_bytearray(libxl_uuid *uuid)
{
- return uuid->uuid;
-}
+ return uuid->uuid_raw;
+}
#else
#error "Please update libxl_uuid.c for your OS"
diff --git a/tools/libxl/libxl_uuid.h b/tools/libxl/libxl_uuid.h
index 93c65a7..c5041c7 100644
--- a/tools/libxl/libxl_uuid.h
+++ b/tools/libxl/libxl_uuid.h
@@ -33,32 +33,45 @@ typedef struct {
#define LIBXL_UUID_BYTES(arg) LIBXL__UUID_BYTES(((uint8_t *)arg.uuid))
-#elif defined(__NetBSD__)
+#elif defined(__FreeBSD__) || defined(__NetBSD__)
#include <uuid.h>
+#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
-#define LIBXL_UUID_BYTES(arg) LIBXL__UUID_BYTES(arg.uuid)
-
-typedef struct {
- uint8_t uuid[16];
+typedef union {
+ uuid_t uuid;
+ uint8_t uuid_raw[16];
} libxl_uuid;
+#define LIBXL_UUID_BYTES(arg) LIBXL__UUID_BYTES(arg.uuid_raw)
+
#else
#error "Please update libxl_uuid.h for your OS"
#endif
-int libxl_uuid_is_nil(libxl_uuid *uuid);
+int libxl_uuid_is_nil(const libxl_uuid *uuid);
void libxl_uuid_generate(libxl_uuid *uuid);
int libxl_uuid_from_string(libxl_uuid *uuid, const char *in);
-void libxl_uuid_copy(libxl_uuid *dst, const libxl_uuid *src);
+void libxl_uuid_copy(libxl_ctx *ctx_opt, libxl_uuid *dst,
+ const libxl_uuid *src);
+#if defined(LIBXL_API_VERSION) && LIBXL_API_VERSION < 0x040500
+void static inline libxl_uuid_copy_0x040400(libxl_uuid *dst,
+ const libxl_uuid *src)
+{
+ libxl_uuid_copy(NULL, dst, src);
+}
+#define libxl_uuid_copy libxl_uuid_copy_0x040400
+#endif
+
void libxl_uuid_clear(libxl_uuid *uuid);
-int libxl_uuid_compare(libxl_uuid *uuid1, libxl_uuid *uuid2);
+int libxl_uuid_compare(const libxl_uuid *uuid1, const libxl_uuid *uuid2);
+const uint8_t *libxl_uuid_bytearray_const(const libxl_uuid *uuid);
uint8_t *libxl_uuid_bytearray(libxl_uuid *uuid);
#endif /* __LIBXL_UUID_H__ */
diff --git a/tools/libxl/libxlu_cfg_y.c b/tools/libxl/libxlu_cfg_y.c
index 218933e..4437e05 100644
--- a/tools/libxl/libxlu_cfg_y.c
+++ b/tools/libxl/libxlu_cfg_y.c
@@ -1,10 +1,8 @@
+/* A Bison parser, made by GNU Bison 2.5. */
-/* A Bison parser, made by GNU Bison 2.4.1. */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
+/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -46,7 +44,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.4.1"
+#define YYBISON_VERSION "2.5"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -75,7 +73,7 @@
/* Copy the first part of user declarations. */
-/* Line 189 of yacc.c */
+/* Line 268 of yacc.c */
#line 19 "libxlu_cfg_y.y"
#define YYLEX_PARAM ctx->scanner
@@ -83,8 +81,8 @@
#include "libxlu_cfg_l.h"
-/* Line 189 of yacc.c */
-#line 88 "libxlu_cfg_y.c"
+/* Line 268 of yacc.c */
+#line 86 "libxlu_cfg_y.c"
/* Enabling traces. */
#ifndef YYDEBUG
@@ -124,7 +122,7 @@
typedef union YYSTYPE
{
-/* Line 214 of yacc.c */
+/* Line 293 of yacc.c */
#line 25 "libxlu_cfg_y.y"
char *string;
@@ -132,8 +130,8 @@ typedef union YYSTYPE
-/* Line 214 of yacc.c */
-#line 137 "libxlu_cfg_y.c"
+/* Line 293 of yacc.c */
+#line 135 "libxlu_cfg_y.c"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -157,8 +155,8 @@ typedef struct YYLTYPE
/* Copy the second part of user declarations. */
-/* Line 264 of yacc.c */
-#line 162 "libxlu_cfg_y.c"
+/* Line 343 of yacc.c */
+#line 160 "libxlu_cfg_y.c"
#ifdef short
# undef short
@@ -208,7 +206,7 @@ typedef short int yytype_int16;
#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
#ifndef YY_
-# if YYENABLE_NLS
+# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
# define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -261,11 +259,11 @@ YYID (yyi)
# define alloca _alloca
# else
# define YYSTACK_ALLOC alloca
-# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef _STDLIB_H
-# define _STDLIB_H 1
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
# endif
# endif
# endif
@@ -288,24 +286,24 @@ YYID (yyi)
# ifndef YYSTACK_ALLOC_MAXIMUM
# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
# endif
-# if (defined __cplusplus && ! defined _STDLIB_H \
+# if (defined __cplusplus && ! defined EXIT_SUCCESS \
&& ! ((defined YYMALLOC || defined malloc) \
&& (defined YYFREE || defined free)))
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef _STDLIB_H
-# define _STDLIB_H 1
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
# endif
# endif
# ifndef YYMALLOC
# define YYMALLOC malloc
-# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# ifndef YYFREE
# define YYFREE free
-# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
@@ -336,23 +334,7 @@ union yyalloc
((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+ 2 * YYSTACK_GAP_MAXIMUM)
-/* Copy COUNT objects from FROM to TO. The source and destination do
- not overlap. */
-# ifndef YYCOPY
-# if defined __GNUC__ && 1 < __GNUC__
-# define YYCOPY(To, From, Count) \
- __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-# else
-# define YYCOPY(To, From, Count) \
- do \
- { \
- YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (To)[yyi] = (From)[yyi]; \
- } \
- while (YYID (0))
-# endif
-# endif
+# define YYCOPY_NEEDED 1
/* Relocate STACK from its old location to the new one. The
local variables YYSIZE and YYSTACKSIZE give the old and new number of
@@ -372,6 +354,26 @@ union yyalloc
#endif
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 3
/* YYLAST -- Last index in YYTABLE. */
@@ -492,8 +494,8 @@ static const yytype_uint8 yyr2[] =
5, 0, 2
};
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
- STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE doesn't specify something else to do. Zero
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
@@ -528,8 +530,7 @@ static const yytype_int8 yypgoto[] =
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
- number is the opposite. If zero, do what YYDEFACT says.
- If YYTABLE_NINF, syntax error. */
+ number is the opposite. If YYTABLE_NINF, syntax error. */
#define YYTABLE_NINF -3
static const yytype_int8 yytable[] =
{
@@ -538,6 +539,12 @@ static const yytype_int8 yytable[] =
16, 26, 25, 20, 13
};
+#define yypact_value_is_default(yystate) \
+ ((yystate) == (-18))
+
+#define yytable_value_is_error(yytable_value) \
+ YYID (0)
+
static const yytype_uint8 yycheck[] =
{
0, 1, 19, 3, 0, 6, 6, 21, 8, 6,
@@ -566,9 +573,18 @@ static const yytype_uint8 yystos[] =
/* Like YYERROR except do call yyerror. This remains here temporarily
to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. */
+ Once GCC version 2 has supplanted version 1, this can go. However,
+ YYFAIL appears to be in use. Nevertheless, it is formally deprecated
+ in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+ discussed. */
#define YYFAIL goto yyerrlab
+#if defined YYFAIL
+ /* This is here to suppress warnings from the GCC cpp's
+ -Wunused-macros. Normally we don't worry about that warning, but
+ some users do, and we want to make it easy for users to remove
+ YYFAIL uses, which will produce warnings from Bison 2.5. */
+#endif
#define YYRECOVERING() (!!yyerrstatus)
@@ -578,7 +594,6 @@ do \
{ \
yychar = (Token); \
yylval = (Value); \
- yytoken = YYTRANSLATE (yychar); \
YYPOPSTACK (1); \
goto yybackup; \
} \
@@ -625,7 +640,7 @@ while (YYID (0))
we won't break user code: when these are the locations we know. */
#ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
# define YY_LOCATION_PRINT(File, Loc) \
fprintf (File, "%d.%d-%d.%d", \
(Loc).first_line, (Loc).first_column, \
@@ -834,7 +849,6 @@ int yydebug;
# define YYMAXDEPTH 10000
#endif
-
#if YYERROR_VERBOSE
@@ -937,115 +951,142 @@ yytnamerr (char *yyres, const char *yystr)
}
# endif
-/* Copy into YYRESULT an error message about the unexpected token
- YYCHAR while in state YYSTATE. Return the number of bytes copied,
- including the terminating null byte. If YYRESULT is null, do not
- copy anything; just return the number of bytes that would be
- copied. As a special case, return 0 if an ordinary "syntax error"
- message will do. Return YYSIZE_MAXIMUM if overflow occurs during
- size calculation. */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
- int yyn = yypact[yystate];
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
- if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
- return 0;
- else
+ Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return 2 if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+ yytype_int16 *yyssp, int yytoken)
+{
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = 0;
+ /* Arguments of yyformat. */
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ /* Number of reported tokens (one for the "unexpected", one per
+ "expected"). */
+ int yycount = 0;
+
+ /* There are many possibilities here to consider:
+ - Assume YYFAIL is not used. It's too flawed to consider. See
+ <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
+ for details. YYERROR is fine as it does not invoke this
+ function.
+ - If this state is a consistent state with a default action, then
+ the only way this function was invoked is if the default action
+ is an error action. In that case, don't check for expected
+ tokens because there are none.
+ - The only way there can be no lookahead present (in yychar) is if
+ this state is a consistent state with a default action. Thus,
+ detecting the absence of a lookahead is sufficient to determine
+ that there is no unexpected or expected token to report. In that
+ case, just report a simple "syntax error".
+ - Don't assume there isn't a lookahead just because this state is a
+ consistent state with a default action. There might have been a
+ previous inconsistent state, consistent state with a non-default
+ action, or user semantic action that manipulated yychar.
+ - Of course, the expected token list depends on states to have
+ correct lookahead information, and it depends on the parser not
+ to perform extra reductions after fetching a lookahead from the
+ scanner and before detecting a syntax error. Thus, state merging
+ (from LALR or IELR) and default reductions corrupt the expected
+ token list. However, the list is correct for canonical LR with
+ one exception: it will still contain any token that will not be
+ accepted due to an error action in a later state.
+ */
+ if (yytoken != YYEMPTY)
{
- int yytype = YYTRANSLATE (yychar);
- YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
- YYSIZE_T yysize = yysize0;
- YYSIZE_T yysize1;
- int yysize_overflow = 0;
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- int yyx;
-
-# if 0
- /* This is so xgettext sees the translatable formats that are
- constructed on the fly. */
- YY_("syntax error, unexpected %s");
- YY_("syntax error, unexpected %s, expecting %s");
- YY_("syntax error, unexpected %s, expecting %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
- char *yyfmt;
- char const *yyf;
- static char const yyunexpected[] = "syntax error, unexpected %s";
- static char const yyexpecting[] = ", expecting %s";
- static char const yyor[] = " or %s";
- char yyformat[sizeof yyunexpected
- + sizeof yyexpecting - 1
- + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
- * (sizeof yyor - 1))];
- char const *yyprefix = yyexpecting;
-
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
-
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn + 1;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yycount = 1;
-
- yyarg[0] = yytname[yytype];
- yyfmt = yystpcpy (yyformat, yyunexpected);
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
- {
- yycount = 1;
- yysize = yysize0;
- yyformat[sizeof yyunexpected - 1] = '\0';
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (0, yytname[yyx]);
- yysize_overflow |= (yysize1 < yysize);
- yysize = yysize1;
- yyfmt = yystpcpy (yyfmt, yyprefix);
- yyprefix = yyor;
- }
+ int yyn = yypact[*yyssp];
+ yyarg[yycount++] = yytname[yytoken];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+ }
+ }
- yyf = YY_(yyformat);
- yysize1 = yysize + yystrlen (yyf);
- yysize_overflow |= (yysize1 < yysize);
- yysize = yysize1;
+ switch (yycount)
+ {
+# define YYCASE_(N, S) \
+ case N: \
+ yyformat = S; \
+ break
+ YYCASE_(0, YY_("syntax error"));
+ YYCASE_(1, YY_("syntax error, unexpected %s"));
+ YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+ YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+ YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+ YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+ }
- if (yysize_overflow)
- return YYSIZE_MAXIMUM;
+ yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
- if (yyresult)
- {
- /* Avoid sprintf, as that infringes on the user's name space.
- Don't have undefined behavior even if the translation
- produced a string with the wrong number of "%s"s. */
- char *yyp = yyresult;
- int yyi = 0;
- while ((*yyp = *yyf) != '\0')
- {
- if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
- {
- yyp += yytnamerr (yyp, yyarg[yyi++]);
- yyf += 2;
- }
- else
- {
- yyp++;
- yyf++;
- }
- }
- }
- return yysize;
+ if (*yymsg_alloc < yysize)
+ {
+ *yymsg_alloc = 2 * yysize;
+ if (! (yysize <= *yymsg_alloc
+ && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+ *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+ return 1;
}
+
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ {
+ char *yyp = *yymsg;
+ int yyi = 0;
+ while ((*yyp = *yyformat) != '\0')
+ if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyformat += 2;
+ }
+ else
+ {
+ yyp++;
+ yyformat++;
+ }
+ }
+ return 0;
}
#endif /* YYERROR_VERBOSE */
-
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
@@ -1078,66 +1119,66 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, ctx)
{
case 3: /* "IDENT" */
-/* Line 1000 of yacc.c */
+/* Line 1391 of yacc.c */
#line 40 "libxlu_cfg_y.y"
{ free((yyvaluep->string)); };
-/* Line 1000 of yacc.c */
-#line 1087 "libxlu_cfg_y.c"
+/* Line 1391 of yacc.c */
+#line 1128 "libxlu_cfg_y.c"
break;
case 4: /* "STRING" */
-/* Line 1000 of yacc.c */
+/* Line 1391 of yacc.c */
#line 40 "libxlu_cfg_y.y"
{ free((yyvaluep->string)); };
-/* Line 1000 of yacc.c */
-#line 1096 "libxlu_cfg_y.c"
+/* Line 1391 of yacc.c */
+#line 1137 "libxlu_cfg_y.c"
break;
case 5: /* "NUMBER" */
-/* Line 1000 of yacc.c */
+/* Line 1391 of yacc.c */
#line 40 "libxlu_cfg_y.y"
{ free((yyvaluep->string)); };
-/* Line 1000 of yacc.c */
-#line 1105 "libxlu_cfg_y.c"
+/* Line 1391 of yacc.c */
+#line 1146 "libxlu_cfg_y.c"
break;
case 18: /* "value" */
-/* Line 1000 of yacc.c */
+/* Line 1391 of yacc.c */
#line 43 "libxlu_cfg_y.y"
{ xlu__cfg_set_free((yyvaluep->setting)); };
-/* Line 1000 of yacc.c */
-#line 1114 "libxlu_cfg_y.c"
+/* Line 1391 of yacc.c */
+#line 1155 "libxlu_cfg_y.c"
break;
case 19: /* "atom" */
-/* Line 1000 of yacc.c */
+/* Line 1391 of yacc.c */
#line 40 "libxlu_cfg_y.y"
{ free((yyvaluep->string)); };
-/* Line 1000 of yacc.c */
-#line 1123 "libxlu_cfg_y.c"
+/* Line 1391 of yacc.c */
+#line 1164 "libxlu_cfg_y.c"
break;
case 20: /* "valuelist" */
-/* Line 1000 of yacc.c */
+/* Line 1391 of yacc.c */
#line 43 "libxlu_cfg_y.y"
{ xlu__cfg_set_free((yyvaluep->setting)); };
-/* Line 1000 of yacc.c */
-#line 1132 "libxlu_cfg_y.c"
+/* Line 1391 of yacc.c */
+#line 1173 "libxlu_cfg_y.c"
break;
case 21: /* "values" */
-/* Line 1000 of yacc.c */
+/* Line 1391 of yacc.c */
#line 43 "libxlu_cfg_y.y"
{ xlu__cfg_set_free((yyvaluep->setting)); };
-/* Line 1000 of yacc.c */
-#line 1141 "libxlu_cfg_y.c"
+/* Line 1391 of yacc.c */
+#line 1182 "libxlu_cfg_y.c"
break;
default:
@@ -1145,6 +1186,7 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, ctx)
}
}
+
/* Prevent warnings from -Wmissing-prototypes. */
#ifdef YYPARSE_PARAM
#if defined __STDC__ || defined __cplusplus
@@ -1161,12 +1203,9 @@ int yyparse ();
#endif /* ! YYPARSE_PARAM */
-
-
-
-/*-------------------------.
-| yyparse or yypush_parse. |
-`-------------------------*/
+/*----------.
+| yyparse. |
+`----------*/
#ifdef YYPARSE_PARAM
#if (defined __STDC__ || defined __C99__FUNC__ \
@@ -1230,7 +1269,7 @@ YYLTYPE yylloc;
YYLTYPE *yylsp;
/* The locations where the error started and ended. */
- YYLTYPE yyerror_range[2];
+ YYLTYPE yyerror_range[3];
YYSIZE_T yystacksize;
@@ -1277,7 +1316,7 @@ YYLTYPE yylloc;
yyvsp = yyvs;
yylsp = yyls;
-#if YYLTYPE_IS_TRIVIAL
+#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
/* Initialize the default location before parsing starts. */
yylloc.first_line = yylloc.last_line = 1;
yylloc.first_column = yylloc.last_column = 1;
@@ -1379,7 +1418,7 @@ yybackup:
/* First try to decide what to do without reference to lookahead token. */
yyn = yypact[yystate];
- if (yyn == YYPACT_NINF)
+ if (yypact_value_is_default (yyn))
goto yydefault;
/* Not known => get a lookahead token if don't already have one. */
@@ -1410,8 +1449,8 @@ yybackup:
yyn = yytable[yyn];
if (yyn <= 0)
{
- if (yyn == 0 || yyn == YYTABLE_NINF)
- goto yyerrlab;
+ if (yytable_value_is_error (yyn))
+ goto yyerrlab;
yyn = -yyn;
goto yyreduce;
}
@@ -1467,80 +1506,91 @@ yyreduce:
{
case 9:
-/* Line 1455 of yacc.c */
+/* Line 1806 of yacc.c */
#line 57 "libxlu_cfg_y.y"
- { xlu__cfg_set_store(ctx,(yyvsp[(1) - (3)].string),(yyvsp[(3) - (3)].setting),(yylsp[(3) - (3)]).first_line); ;}
+ { xlu__cfg_set_store(ctx,(yyvsp[(1) - (3)].string),(yyvsp[(3) - (3)].setting),(yylsp[(3) - (3)]).first_line); }
break;
case 12:
-/* Line 1455 of yacc.c */
+/* Line 1806 of yacc.c */
#line 62 "libxlu_cfg_y.y"
- { (yyval.setting)= xlu__cfg_set_mk(ctx,1,(yyvsp[(1) - (1)].string)); ;}
+ { (yyval.setting)= xlu__cfg_set_mk(ctx,1,(yyvsp[(1) - (1)].string)); }
break;
case 13:
-/* Line 1455 of yacc.c */
+/* Line 1806 of yacc.c */
#line 63 "libxlu_cfg_y.y"
- { (yyval.setting)= (yyvsp[(3) - (4)].setting); ;}
+ { (yyval.setting)= (yyvsp[(3) - (4)].setting); }
break;
case 14:
-/* Line 1455 of yacc.c */
+/* Line 1806 of yacc.c */
#line 65 "libxlu_cfg_y.y"
- { (yyval.string)= (yyvsp[(1) - (1)].string); ;}
+ { (yyval.string)= (yyvsp[(1) - (1)].string); }
break;
case 15:
-/* Line 1455 of yacc.c */
+/* Line 1806 of yacc.c */
#line 66 "libxlu_cfg_y.y"
- { (yyval.string)= (yyvsp[(1) - (1)].string); ;}
+ { (yyval.string)= (yyvsp[(1) - (1)].string); }
break;
case 16:
-/* Line 1455 of yacc.c */
+/* Line 1806 of yacc.c */
#line 68 "libxlu_cfg_y.y"
- { (yyval.setting)= xlu__cfg_set_mk(ctx,0,0); ;}
+ { (yyval.setting)= xlu__cfg_set_mk(ctx,0,0); }
break;
case 17:
-/* Line 1455 of yacc.c */
+/* Line 1806 of yacc.c */
#line 69 "libxlu_cfg_y.y"
- { (yyval.setting)= (yyvsp[(1) - (1)].setting); ;}
+ { (yyval.setting)= (yyvsp[(1) - (1)].setting); }
break;
case 18:
-/* Line 1455 of yacc.c */
+/* Line 1806 of yacc.c */
#line 70 "libxlu_cfg_y.y"
- { (yyval.setting)= (yyvsp[(1) - (3)].setting); ;}
+ { (yyval.setting)= (yyvsp[(1) - (3)].setting); }
break;
case 19:
-/* Line 1455 of yacc.c */
+/* Line 1806 of yacc.c */
#line 72 "libxlu_cfg_y.y"
- { (yyval.setting)= xlu__cfg_set_mk(ctx,2,(yyvsp[(1) - (2)].string)); ;}
+ { (yyval.setting)= xlu__cfg_set_mk(ctx,2,(yyvsp[(1) - (2)].string)); }
break;
case 20:
-/* Line 1455 of yacc.c */
+/* Line 1806 of yacc.c */
#line 73 "libxlu_cfg_y.y"
- { xlu__cfg_set_add(ctx,(yyvsp[(1) - (5)].setting),(yyvsp[(4) - (5)].string)); (yyval.setting)= (yyvsp[(1) - (5)].setting); ;}
+ { xlu__cfg_set_add(ctx,(yyvsp[(1) - (5)].setting),(yyvsp[(4) - (5)].string)); (yyval.setting)= (yyvsp[(1) - (5)].setting); }
break;
-/* Line 1455 of yacc.c */
-#line 1542 "libxlu_cfg_y.c"
+/* Line 1806 of yacc.c */
+#line 1581 "libxlu_cfg_y.c"
default: break;
}
+ /* User semantic actions sometimes alter yychar, and that requires
+ that yytoken be updated with the new translation. We take the
+ approach of translating immediately before every use of yytoken.
+ One alternative is translating here after every semantic action,
+ but that translation would be missed if the semantic action invokes
+ YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+ if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
+ incorrect destructor might then be invoked immediately. In the
+ case of YYERROR or YYBACKUP, subsequent parser actions might lead
+ to an incorrect destructor call or verbose syntax error message
+ before the lookahead is translated. */
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
YYPOPSTACK (yylen);
@@ -1569,6 +1619,10 @@ yyreduce:
| yyerrlab -- here on detecting error |
`------------------------------------*/
yyerrlab:
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
@@ -1576,41 +1630,40 @@ yyerrlab:
#if ! YYERROR_VERBOSE
yyerror (&yylloc, ctx, YY_("syntax error"));
#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+ yyssp, yytoken)
{
- YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
- if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
- {
- YYSIZE_T yyalloc = 2 * yysize;
- if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
- yyalloc = YYSTACK_ALLOC_MAXIMUM;
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
- yymsg = (char *) YYSTACK_ALLOC (yyalloc);
- if (yymsg)
- yymsg_alloc = yyalloc;
- else
- {
- yymsg = yymsgbuf;
- yymsg_alloc = sizeof yymsgbuf;
- }
- }
-
- if (0 < yysize && yysize <= yymsg_alloc)
- {
- (void) yysyntax_error (yymsg, yystate, yychar);
- yyerror (&yylloc, ctx, yymsg);
- }
- else
- {
- yyerror (&yylloc, ctx, YY_("syntax error"));
- if (yysize != 0)
- goto yyexhaustedlab;
- }
+ char const *yymsgp = YY_("syntax error");
+ int yysyntax_error_status;
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ if (yysyntax_error_status == 0)
+ yymsgp = yymsg;
+ else if (yysyntax_error_status == 1)
+ {
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+ if (!yymsg)
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = 2;
+ }
+ else
+ {
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ yymsgp = yymsg;
+ }
+ }
+ yyerror (&yylloc, ctx, yymsgp);
+ if (yysyntax_error_status == 2)
+ goto yyexhaustedlab;
}
+# undef YYSYNTAX_ERROR
#endif
}
- yyerror_range[0] = yylloc;
+ yyerror_range[1] = yylloc;
if (yyerrstatus == 3)
{
@@ -1647,7 +1700,7 @@ yyerrorlab:
if (/*CONSTCOND*/ 0)
goto yyerrorlab;
- yyerror_range[0] = yylsp[1-yylen];
+ yyerror_range[1] = yylsp[1-yylen];
/* Do not reclaim the symbols of the rule which action triggered
this YYERROR. */
YYPOPSTACK (yylen);
@@ -1666,7 +1719,7 @@ yyerrlab1:
for (;;)
{
yyn = yypact[yystate];
- if (yyn != YYPACT_NINF)
+ if (!yypact_value_is_default (yyn))
{
yyn += YYTERROR;
if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
@@ -1681,7 +1734,7 @@ yyerrlab1:
if (yyssp == yyss)
YYABORT;
- yyerror_range[0] = *yylsp;
+ yyerror_range[1] = *yylsp;
yydestruct ("Error: popping",
yystos[yystate], yyvsp, yylsp, ctx);
YYPOPSTACK (1);
@@ -1691,10 +1744,10 @@ yyerrlab1:
*++yyvsp = yylval;
- yyerror_range[1] = yylloc;
+ yyerror_range[2] = yylloc;
/* Using YYLLOC is tempting, but would change the location of
the lookahead. YYLOC is available though. */
- YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
+ YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
*++yylsp = yyloc;
/* Shift the error token. */
@@ -1730,8 +1783,13 @@ yyexhaustedlab:
yyreturn:
if (yychar != YYEMPTY)
- yydestruct ("Cleanup: discarding lookahead",
- yytoken, &yylval, &yylloc, ctx);
+ {
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = YYTRANSLATE (yychar);
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, &yylloc, ctx);
+ }
/* Do not reclaim the symbols of the rule which action triggered
this YYABORT or YYACCEPT. */
YYPOPSTACK (yylen);
diff --git a/tools/libxl/libxlu_cfg_y.h b/tools/libxl/libxlu_cfg_y.h
index e7b3d12..d7dfaf2 100644
--- a/tools/libxl/libxlu_cfg_y.h
+++ b/tools/libxl/libxlu_cfg_y.h
@@ -1,10 +1,8 @@
+/* A Bison parser, made by GNU Bison 2.5. */
-/* A Bison parser, made by GNU Bison 2.4.1. */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
+/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -52,7 +50,7 @@
typedef union YYSTYPE
{
-/* Line 1676 of yacc.c */
+/* Line 2068 of yacc.c */
#line 25 "libxlu_cfg_y.y"
char *string;
@@ -60,8 +58,8 @@ typedef union YYSTYPE
-/* Line 1676 of yacc.c */
-#line 65 "libxlu_cfg_y.h"
+/* Line 2068 of yacc.c */
+#line 63 "libxlu_cfg_y.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
diff --git a/tools/libxl/libxlu_disk_l.c b/tools/libxl/libxlu_disk_l.c
index 03adfef..2c6e8e3 100644
--- a/tools/libxl/libxlu_disk_l.c
+++ b/tools/libxl/libxlu_disk_l.c
@@ -361,8 +361,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
-#define YY_NUM_RULES 26
-#define YY_END_OF_BUFFER 27
+#define YY_NUM_RULES 29
+#define YY_END_OF_BUFFER 30
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -370,90 +370,96 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_acclist[454] =
+static yyconst flex_int16_t yy_acclist[490] =
{ 0,
- 25, 25, 27, 23, 24, 26, 8193, 23, 24, 26,
- 16385, 8193, 23, 26,16385, 23, 24, 26, 24, 26,
- 23, 24, 26, 23, 24, 26, 23, 24, 26, 23,
- 24, 26, 23, 24, 26, 23, 24, 26, 23, 24,
- 26, 23, 24, 26, 23, 24, 26, 23, 24, 26,
- 23, 24, 26, 23, 24, 26, 23, 24, 26, 23,
- 24, 26, 23, 24, 26, 25, 26, 26, 23, 23,
- 8193, 23, 8193, 23,16385, 8193, 23, 8193, 23, 23,
- 8214, 23,16406, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
-
- 23, 23, 25, 8193, 23, 8193, 23, 8193, 8214, 23,
- 8214, 23, 8214, 13, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 8214, 23, 8214, 23, 8214, 13, 23, 18,
- 8214, 23,16406, 23, 23, 23, 23, 23, 23, 23,
- 8207, 8214, 23,16399,16406, 21, 8214, 23,16406, 23,
- 8206, 8214, 23,16398,16406, 23, 23, 8209, 8214, 23,
- 16401,16406, 23, 23, 23, 23, 18, 8214, 23, 18,
- 8214, 23, 18, 23, 18, 8214, 23, 3, 23, 23,
- 20, 8214, 23,16406, 23, 23, 8207, 8214, 23, 8207,
-
- 8214, 23, 8207, 23, 8207, 8214, 21, 8214, 23, 21,
- 8214, 23, 21, 23, 21, 8214, 8206, 8214, 23, 8206,
- 8214, 23, 8206, 23, 8206, 8214, 23, 8209, 8214, 23,
- 8209, 8214, 23, 8209, 23, 8209, 8214, 23, 23, 10,
- 23, 18, 8214, 23, 18, 8214, 23, 18, 8214, 18,
- 23, 18, 23, 3, 23, 23, 20, 8214, 23, 20,
- 8214, 23, 20, 23, 20, 8214, 23, 19, 8214, 23,
- 16406, 8207, 8214, 23, 8207, 8214, 23, 8207, 8214, 8207,
- 23, 8207, 21, 8214, 23, 21, 8214, 23, 21, 8214,
- 21, 23, 21, 8206, 8214, 23, 8206, 8214, 23, 8206,
-
- 8214, 8206, 23, 8206, 23, 8209, 8214, 23, 8209, 8214,
- 23, 8209, 8214, 8209, 23, 8209, 23, 23, 10, 13,
- 10, 7, 23, 23, 20, 8214, 23, 20, 8214, 23,
- 20, 8214, 20, 23, 20, 2, 19, 8214, 23, 19,
- 8214, 23, 19, 23, 19, 8214, 11, 23, 12, 10,
- 10, 13, 7, 13, 7, 8, 23, 6, 2, 13,
- 2, 19, 8214, 23, 19, 8214, 23, 19, 8214, 19,
- 23, 19, 11, 13, 11, 16, 8214, 23,16406, 12,
- 13, 12, 7, 7, 13, 8, 13, 8, 23, 6,
- 13, 6, 6, 13, 6, 13, 2, 2, 13, 11,
-
- 11, 13, 16, 8214, 23, 16, 8214, 23, 16, 23,
- 16, 8214, 12, 13, 8, 8, 13, 23, 6, 6,
- 13, 6, 6, 16, 8214, 23, 16, 8214, 23, 16,
- 8214, 16, 23, 16, 23, 6, 6, 9, 6, 5,
- 6, 9, 13, 9, 4, 6, 5, 6, 9, 9,
- 13, 4, 6
+ 28, 28, 30, 26, 27, 29, 8193, 26, 27, 29,
+ 16385, 8193, 26, 29,16385, 26, 27, 29, 27, 29,
+ 26, 27, 29, 26, 27, 29, 26, 27, 29, 26,
+ 27, 29, 26, 27, 29, 26, 27, 29, 26, 27,
+ 29, 26, 27, 29, 26, 27, 29, 26, 27, 29,
+ 26, 27, 29, 26, 27, 29, 26, 27, 29, 26,
+ 27, 29, 26, 27, 29, 28, 29, 29, 26, 26,
+ 8193, 26, 8193, 26,16385, 8193, 26, 8193, 26, 26,
+ 8217, 26,16409, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+
+ 26, 26, 26, 26, 28, 8193, 26, 8193, 26, 8193,
+ 8217, 26, 8217, 26, 8217, 16, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 8217, 26, 8217,
+ 26, 8217, 16, 26, 21, 8217, 26,16409, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 8210, 8217, 26,
+ 16402,16409, 26, 24, 8217, 26,16409, 26, 8209, 8217,
+ 26,16401,16409, 26, 26, 8212, 8217, 26,16404,16409,
+ 26, 26, 26, 26, 21, 8217, 26, 21, 8217, 26,
+ 21, 26, 21, 8217, 26, 3, 26, 26, 26, 26,
+
+ 23, 8217, 26,16409, 26, 26, 8210, 8217, 26, 8210,
+ 8217, 26, 8210, 26, 8210, 8217, 26, 24, 8217, 26,
+ 24, 8217, 26, 24, 26, 24, 8217, 8209, 8217, 26,
+ 8209, 8217, 26, 8209, 26, 8209, 8217, 26, 8212, 8217,
+ 26, 8212, 8217, 26, 8212, 26, 8212, 8217, 26, 26,
+ 10, 26, 21, 8217, 26, 21, 8217, 26, 21, 8217,
+ 21, 26, 21, 26, 3, 26, 26, 26, 26, 23,
+ 8217, 26, 23, 8217, 26, 23, 26, 23, 8217, 26,
+ 22, 8217, 26,16409, 8210, 8217, 26, 8210, 8217, 26,
+ 8210, 8217, 8210, 26, 8210, 26, 24, 8217, 26, 24,
+
+ 8217, 26, 24, 8217, 24, 26, 24, 8209, 8217, 26,
+ 8209, 8217, 26, 8209, 8217, 8209, 26, 8209, 26, 8212,
+ 8217, 26, 8212, 8217, 26, 8212, 8217, 8212, 26, 8212,
+ 26, 26, 10, 16, 10, 7, 26, 26, 26, 13,
+ 26, 23, 8217, 26, 23, 8217, 26, 23, 8217, 23,
+ 26, 23, 2, 22, 8217, 26, 22, 8217, 26, 22,
+ 26, 22, 8217, 26, 11, 26, 15, 10, 10, 16,
+ 7, 16, 7, 8, 26, 6, 26, 13, 26, 2,
+ 16, 2, 22, 8217, 26, 22, 8217, 26, 22, 8217,
+ 22, 26, 22, 26, 11, 16, 11, 19, 8217, 26,
+
+ 16409, 15, 16, 15, 7, 7, 16, 8, 16, 8,
+ 26, 6, 16, 6, 6, 16, 6, 16, 26, 2,
+ 2, 16, 26, 11, 11, 16, 19, 8217, 26, 19,
+ 8217, 26, 19, 26, 19, 8217, 15, 16, 8, 8,
+ 16, 26, 6, 6, 16, 6, 6, 26, 14, 26,
+ 19, 8217, 26, 19, 8217, 26, 19, 8217, 19, 26,
+ 19, 26, 6, 6, 26, 14, 26, 9, 6, 5,
+ 6, 26, 9, 16, 9, 4, 6, 5, 6, 26,
+ 9, 9, 16, 4, 6, 12, 26, 12, 26
} ;
-static yyconst flex_int16_t yy_accept[257] =
+static yyconst flex_int16_t yy_accept[287] =
{ 0,
1, 1, 1, 2, 3, 4, 7, 12, 16, 19,
21, 24, 27, 30, 33, 36, 39, 42, 45, 48,
51, 54, 57, 60, 63, 66, 68, 69, 70, 71,
73, 76, 78, 79, 80, 81, 84, 84, 85, 86,
87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
- 97, 98, 99, 100, 101, 102, 103, 104, 106, 108,
- 109, 111, 113, 114, 115, 116, 117, 118, 119, 120,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 108, 110, 111, 113, 115, 116, 117, 118, 119, 120,
121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
- 131, 132, 133, 135, 137, 138, 139, 140, 144, 145,
- 146, 147, 148, 149, 150, 151, 156, 160, 161, 166,
-
- 167, 168, 173, 174, 175, 176, 177, 180, 183, 185,
- 187, 188, 190, 191, 195, 196, 197, 200, 203, 205,
- 207, 210, 213, 215, 217, 220, 223, 225, 227, 228,
- 231, 234, 236, 238, 239, 240, 241, 242, 245, 248,
- 250, 252, 253, 254, 256, 257, 260, 263, 265, 267,
- 268, 272, 275, 278, 280, 282, 283, 286, 289, 291,
- 293, 294, 297, 300, 302, 304, 305, 306, 309, 312,
- 314, 316, 317, 318, 319, 321, 322, 323, 324, 325,
- 328, 331, 333, 335, 336, 337, 340, 343, 345, 347,
- 348, 349, 350, 351, 353, 355, 356, 357, 358, 359,
-
- 361, 362, 365, 368, 370, 372, 373, 375, 376, 380,
- 382, 383, 384, 386, 388, 389, 390, 392, 393, 395,
- 397, 398, 400, 401, 403, 406, 409, 411, 413, 415,
- 416, 418, 419, 420, 422, 423, 424, 427, 430, 432,
- 434, 435, 436, 437, 438, 439, 440, 442, 444, 445,
- 447, 449, 450, 452, 454, 454
+ 131, 132, 133, 134, 135, 136, 137, 138, 140, 142,
+ 143, 144, 145, 149, 150, 151, 152, 153, 154, 155,
+
+ 156, 157, 158, 163, 164, 168, 169, 174, 175, 176,
+ 181, 182, 183, 184, 185, 188, 191, 193, 195, 196,
+ 198, 199, 200, 201, 205, 206, 207, 210, 213, 215,
+ 217, 218, 221, 224, 226, 228, 231, 234, 236, 238,
+ 239, 242, 245, 247, 249, 250, 251, 252, 253, 256,
+ 259, 261, 263, 264, 265, 267, 268, 269, 270, 273,
+ 276, 278, 280, 281, 285, 288, 291, 293, 295, 296,
+ 297, 300, 303, 305, 307, 308, 311, 314, 316, 318,
+ 319, 320, 323, 326, 328, 330, 331, 332, 333, 335,
+ 336, 337, 338, 339, 340, 342, 345, 348, 350, 352,
+
+ 353, 354, 357, 360, 362, 364, 365, 366, 367, 368,
+ 369, 371, 373, 374, 375, 376, 377, 378, 380, 382,
+ 383, 386, 389, 391, 393, 394, 395, 397, 398, 402,
+ 404, 405, 406, 408, 410, 411, 412, 414, 415, 417,
+ 419, 420, 421, 423, 424, 425, 427, 430, 433, 435,
+ 437, 439, 440, 442, 443, 444, 446, 447, 448, 449,
+ 451, 454, 457, 459, 461, 462, 463, 464, 465, 466,
+ 468, 469, 470, 472, 473, 475, 476, 478, 480, 481,
+ 482, 484, 486, 488, 490, 490
} ;
static yyconst flex_int32_t yy_ec[256] =
@@ -496,244 +502,262 @@ static yyconst flex_int32_t yy_meta[34] =
1, 1, 1
} ;
-static yyconst flex_int16_t yy_base[315] =
+static yyconst flex_int16_t yy_base[345] =
{ 0,
- 0, 0, 563, 559, 558, 546, 32, 35, 665, 665,
- 44, 62, 30, 41, 50, 51, 532, 64, 47, 66,
- 67, 524, 68, 516, 72, 0, 665, 514, 665, 87,
- 91, 0, 0, 100, 500, 109, 0, 74, 95, 87,
- 32, 96, 105, 110, 77, 97, 40, 113, 116, 112,
- 118, 120, 121, 122, 123, 125, 0, 137, 0, 0,
- 147, 0, 0, 494, 129, 126, 134, 143, 145, 147,
- 148, 149, 151, 153, 156, 160, 155, 167, 162, 175,
- 168, 159, 188, 0, 0, 665, 166, 197, 179, 185,
- 176, 200, 460, 186, 193, 216, 225, 205, 234, 221,
-
- 237, 247, 204, 230, 244, 213, 254, 0, 256, 0,
- 251, 258, 254, 279, 256, 259, 267, 0, 269, 0,
- 286, 0, 288, 0, 290, 0, 297, 0, 267, 299,
- 0, 301, 0, 288, 297, 459, 302, 310, 0, 0,
- 0, 0, 305, 665, 307, 319, 0, 321, 0, 322,
- 332, 335, 0, 0, 0, 0, 339, 0, 0, 0,
- 0, 342, 0, 0, 0, 0, 340, 349, 0, 0,
- 0, 0, 337, 345, 450, 665, 442, 350, 352, 360,
- 0, 0, 0, 0, 424, 362, 0, 364, 0, 420,
- 319, 371, 419, 665, 418, 665, 417, 276, 368, 416,
-
- 665, 373, 0, 0, 0, 0, 415, 665, 382, 414,
- 0, 413, 665, 412, 665, 368, 411, 665, 384, 352,
- 410, 665, 409, 665, 391, 0, 395, 0, 0, 405,
- 665, 382, 316, 665, 385, 397, 399, 0, 0, 0,
- 0, 396, 403, 406, 271, 407, 228, 200, 665, 175,
- 665, 77, 665, 665, 665, 429, 433, 436, 440, 444,
- 448, 452, 456, 460, 464, 468, 472, 476, 480, 484,
- 488, 492, 496, 500, 504, 508, 512, 516, 520, 524,
- 528, 532, 536, 540, 544, 548, 552, 556, 560, 564,
- 568, 572, 576, 580, 584, 588, 592, 596, 600, 604,
-
- 608, 612, 616, 620, 624, 628, 632, 636, 640, 644,
- 648, 652, 656, 660
+ 0, 0, 714, 713, 715, 700, 32, 35, 718, 718,
+ 44, 62, 30, 41, 50, 51, 690, 64, 66, 40,
+ 68, 674, 69, 662, 72, 0, 718, 640, 718, 90,
+ 93, 0, 0, 102, 622, 111, 0, 74, 77, 88,
+ 81, 97, 99, 107, 111, 113, 114, 44, 119, 120,
+ 127, 115, 125, 126, 128, 129, 130, 132, 0, 143,
+ 0, 0, 156, 0, 0, 616, 143, 153, 152, 140,
+ 141, 157, 156, 163, 164, 159, 165, 167, 172, 195,
+ 175, 169, 176, 182, 181, 195, 183, 203, 0, 0,
+ 718, 192, 220, 199, 205, 200, 206, 606, 209, 602,
+
+ 216, 220, 246, 218, 255, 227, 264, 251, 231, 276,
+ 222, 260, 233, 234, 279, 0, 283, 0, 279, 286,
+ 281, 242, 283, 310, 265, 287, 295, 0, 313, 0,
+ 292, 320, 0, 322, 0, 324, 0, 331, 0, 320,
+ 333, 0, 335, 0, 293, 322, 604, 291, 343, 0,
+ 0, 0, 0, 335, 718, 340, 348, 346, 357, 0,
+ 359, 0, 298, 368, 371, 0, 0, 0, 0, 352,
+ 375, 0, 0, 0, 0, 378, 0, 0, 0, 0,
+ 376, 385, 0, 0, 0, 0, 347, 381, 596, 718,
+ 588, 383, 386, 384, 394, 396, 0, 0, 0, 0,
+
+ 580, 404, 0, 406, 0, 393, 572, 333, 413, 564,
+ 718, 556, 718, 544, 391, 407, 401, 718, 516, 718,
+ 418, 0, 0, 0, 0, 405, 509, 718, 432, 500,
+ 0, 492, 718, 474, 718, 413, 473, 718, 426, 424,
+ 240, 472, 718, 461, 425, 718, 440, 0, 442, 0,
+ 0, 379, 718, 438, 351, 718, 427, 422, 434, 451,
+ 454, 0, 0, 0, 0, 450, 449, 452, 455, 718,
+ 305, 457, 186, 454, 139, 718, 79, 718, 457, 38,
+ 718, 718, 462, 718, 718, 479, 483, 486, 490, 494,
+ 498, 502, 506, 510, 514, 518, 522, 526, 530, 534,
+
+ 538, 542, 546, 550, 554, 558, 562, 566, 570, 574,
+ 578, 582, 586, 590, 594, 598, 602, 606, 610, 614,
+ 618, 622, 626, 630, 634, 638, 642, 646, 650, 654,
+ 658, 662, 666, 670, 674, 678, 682, 686, 690, 694,
+ 698, 702, 706, 710
} ;
-static yyconst flex_int16_t yy_def[315] =
+static yyconst flex_int16_t yy_def[345] =
{ 0,
- 255, 1, 256, 256, 255, 257, 258, 258, 255, 255,
- 259, 259, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 260, 255, 257, 255, 261,
- 258, 262, 262, 263, 12, 257, 264, 12, 12, 12,
+ 285, 1, 286, 286, 285, 287, 288, 288, 285, 285,
+ 289, 289, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 290, 285, 287, 285, 291,
+ 288, 292, 292, 293, 12, 287, 294, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 260, 261, 262, 262,
- 265, 266, 266, 255, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 265, 266, 266, 255, 12, 267, 12, 12,
- 12, 12, 12, 12, 12, 268, 269, 12, 270, 12,
-
- 12, 271, 12, 12, 12, 12, 272, 273, 267, 273,
- 12, 12, 12, 274, 12, 12, 275, 276, 268, 276,
- 277, 278, 269, 278, 279, 280, 270, 280, 12, 281,
- 282, 271, 282, 12, 12, 283, 12, 272, 273, 273,
- 284, 284, 12, 255, 12, 285, 286, 274, 286, 12,
- 287, 275, 276, 276, 288, 288, 277, 278, 278, 289,
- 289, 279, 280, 280, 290, 290, 12, 281, 282, 282,
- 291, 291, 12, 12, 292, 255, 293, 12, 12, 285,
- 286, 286, 294, 294, 295, 296, 297, 287, 297, 298,
- 12, 299, 292, 255, 300, 255, 301, 12, 302, 303,
-
- 255, 296, 297, 297, 304, 304, 305, 255, 306, 307,
- 307, 300, 255, 308, 255, 12, 309, 255, 309, 309,
- 303, 255, 305, 255, 310, 311, 306, 311, 307, 308,
- 255, 12, 309, 255, 309, 309, 310, 311, 311, 312,
- 312, 12, 309, 309, 313, 309, 309, 314, 255, 309,
- 255, 314, 255, 255, 0, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255
+ 12, 12, 12, 12, 12, 12, 12, 12, 290, 291,
+ 292, 292, 295, 296, 296, 285, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 293,
+ 12, 12, 12, 12, 12, 12, 12, 295, 296, 296,
+ 285, 12, 297, 12, 12, 12, 12, 12, 12, 12,
+
+ 12, 12, 298, 80, 299, 12, 300, 12, 12, 301,
+ 12, 12, 12, 12, 302, 303, 297, 303, 12, 12,
+ 12, 12, 12, 304, 12, 12, 305, 306, 298, 306,
+ 80, 307, 308, 299, 308, 309, 310, 300, 310, 12,
+ 311, 312, 301, 312, 12, 12, 313, 12, 302, 303,
+ 303, 314, 314, 12, 285, 12, 12, 12, 315, 316,
+ 304, 316, 12, 317, 305, 306, 306, 318, 318, 80,
+ 307, 308, 308, 319, 319, 309, 310, 310, 320, 320,
+ 12, 311, 312, 312, 321, 321, 12, 12, 322, 285,
+ 323, 12, 12, 80, 12, 315, 316, 316, 324, 324,
+
+ 325, 326, 327, 317, 327, 80, 328, 12, 329, 322,
+ 285, 330, 285, 331, 12, 332, 80, 285, 333, 285,
+ 326, 327, 327, 334, 334, 80, 335, 285, 336, 337,
+ 337, 330, 285, 338, 285, 12, 339, 285, 339, 339,
+ 80, 333, 285, 80, 335, 285, 340, 341, 336, 341,
+ 337, 338, 285, 12, 339, 285, 339, 339, 80, 80,
+ 340, 341, 341, 342, 342, 12, 339, 339, 80, 285,
+ 343, 339, 339, 80, 344, 285, 339, 285, 80, 344,
+ 285, 285, 80, 285, 0, 285, 285, 285, 285, 285,
+ 285, 285, 285, 285, 285, 285, 285, 285, 285, 285,
+
+ 285, 285, 285, 285, 285, 285, 285, 285, 285, 285,
+ 285, 285, 285, 285, 285, 285, 285, 285, 285, 285,
+ 285, 285, 285, 285, 285, 285, 285, 285, 285, 285,
+ 285, 285, 285, 285, 285, 285, 285, 285, 285, 285,
+ 285, 285, 285, 285
} ;
-static yyconst flex_int16_t yy_nxt[699] =
+static yyconst flex_int16_t yy_nxt[752] =
{ 0,
6, 7, 8, 9, 6, 6, 6, 6, 10, 11,
12, 13, 14, 15, 16, 17, 17, 18, 17, 17,
17, 17, 19, 17, 20, 21, 22, 23, 24, 17,
25, 17, 17, 31, 31, 32, 31, 31, 32, 35,
- 33, 35, 41, 33, 28, 28, 28, 29, 34, 35,
- 35, 36, 37, 73, 42, 38, 35, 49, 68, 35,
- 35, 39, 28, 28, 28, 29, 34, 43, 45, 36,
- 37, 40, 44, 35, 46, 35, 35, 35, 51, 53,
- 249, 35, 50, 35, 55, 65, 35, 47, 56, 28,
- 59, 48, 31, 31, 32, 60, 35, 71, 67, 33,
-
- 28, 28, 28, 29, 35, 35, 35, 28, 37, 61,
- 61, 61, 62, 61, 35, 70, 61, 63, 66, 35,
- 49, 35, 35, 72, 74, 35, 69, 35, 75, 35,
- 35, 35, 35, 88, 35, 35, 82, 78, 35, 28,
- 59, 77, 87, 35, 76, 60, 80, 79, 81, 28,
- 84, 78, 35, 89, 35, 85, 35, 35, 35, 75,
- 35, 92, 35, 96, 35, 35, 90, 97, 35, 35,
- 93, 35, 94, 91, 99, 35, 35, 35, 254, 100,
- 95, 101, 102, 104, 35, 35, 98, 103, 35, 105,
- 28, 84, 111, 106, 35, 35, 85, 107, 107, 61,
-
- 108, 107, 35, 253, 107, 110, 112, 114, 113, 35,
- 75, 78, 99, 35, 35, 116, 117, 117, 61, 118,
- 117, 134, 35, 117, 120, 121, 121, 61, 122, 121,
- 35, 251, 121, 124, 125, 125, 61, 126, 125, 35,
- 137, 125, 128, 135, 102, 129, 35, 130, 130, 61,
- 131, 130, 136, 35, 130, 133, 28, 139, 28, 141,
- 35, 144, 140, 35, 142, 35, 151, 35, 35, 28,
- 153, 28, 155, 143, 249, 154, 35, 156, 145, 146,
- 146, 61, 147, 146, 150, 35, 146, 149, 28, 158,
- 28, 160, 28, 163, 159, 167, 161, 35, 164, 28,
-
- 165, 28, 169, 28, 171, 166, 35, 170, 216, 172,
- 177, 35, 28, 139, 35, 173, 35, 178, 140, 218,
- 179, 28, 181, 28, 183, 174, 209, 182, 35, 184,
- 185, 35, 186, 186, 61, 187, 186, 28, 153, 186,
- 189, 28, 158, 154, 28, 163, 35, 159, 190, 35,
- 164, 28, 169, 192, 35, 234, 191, 170, 197, 35,
- 199, 35, 28, 181, 28, 203, 28, 205, 182, 236,
- 204, 218, 206, 64, 211, 28, 203, 35, 198, 219,
- 220, 204, 225, 225, 61, 226, 225, 234, 218, 225,
- 228, 35, 232, 28, 238, 242, 235, 28, 240, 239,
-
- 218, 28, 238, 241, 245, 35, 218, 239, 215, 218,
- 218, 243, 208, 201, 234, 231, 196, 229, 224, 222,
- 215, 213, 176, 208, 244, 247, 246, 201, 250, 26,
+ 33, 276, 41, 33, 28, 28, 28, 29, 34, 35,
+ 35, 36, 37, 35, 42, 38, 52, 77, 43, 35,
+ 35, 39, 28, 28, 28, 29, 34, 44, 46, 36,
+ 37, 40, 45, 35, 47, 35, 50, 35, 35, 53,
+ 55, 35, 282, 35, 57, 67, 35, 48, 58, 51,
+ 35, 49, 28, 61, 31, 31, 32, 35, 62, 69,
+
+ 68, 33, 28, 28, 28, 29, 35, 70, 35, 28,
+ 37, 63, 63, 63, 64, 63, 35, 74, 63, 65,
+ 35, 50, 35, 35, 35, 72, 73, 71, 35, 35,
+ 78, 80, 79, 75, 35, 35, 35, 35, 35, 35,
+ 76, 35, 281, 87, 83, 28, 61, 81, 82, 35,
+ 35, 62, 35, 85, 84, 86, 92, 83, 28, 89,
+ 93, 35, 35, 95, 90, 35, 35, 98, 35, 96,
+ 97, 94, 35, 35, 35, 79, 35, 99, 35, 103,
+ 100, 35, 105, 107, 35, 35, 101, 109, 110, 278,
+ 35, 35, 35, 111, 102, 28, 28, 28, 29, 108,
+
+ 106, 35, 28, 37, 35, 28, 89, 104, 35, 35,
+ 112, 90, 119, 113, 35, 35, 124, 122, 35, 114,
+ 115, 115, 63, 116, 115, 35, 120, 115, 118, 35,
+ 34, 35, 121, 83, 107, 131, 35, 79, 110, 145,
+ 35, 147, 35, 35, 259, 126, 127, 127, 63, 128,
+ 127, 35, 34, 127, 130, 132, 132, 63, 133, 132,
+ 35, 148, 132, 135, 136, 136, 63, 137, 136, 35,
+ 157, 136, 139, 146, 35, 140, 141, 141, 63, 142,
+ 141, 28, 150, 141, 144, 28, 152, 151, 35, 155,
+ 35, 153, 35, 163, 164, 35, 35, 28, 166, 191,
+
+ 35, 154, 35, 167, 34, 156, 201, 35, 276, 158,
+ 159, 159, 63, 160, 159, 28, 168, 159, 162, 170,
+ 187, 169, 28, 172, 28, 174, 28, 177, 173, 35,
+ 175, 35, 178, 28, 179, 28, 183, 28, 185, 180,
+ 229, 184, 35, 186, 35, 28, 150, 192, 181, 35,
+ 188, 151, 194, 193, 238, 35, 35, 35, 195, 28,
+ 197, 28, 199, 206, 34, 198, 208, 200, 202, 202,
+ 63, 203, 202, 28, 166, 202, 205, 28, 172, 167,
+ 28, 177, 235, 173, 207, 35, 178, 28, 183, 209,
+ 35, 214, 35, 184, 216, 35, 34, 218, 28, 197,
+
+ 35, 217, 226, 35, 198, 34, 28, 222, 28, 224,
+ 238, 215, 223, 34, 225, 66, 231, 34, 239, 240,
+ 28, 222, 35, 236, 241, 238, 223, 256, 228, 256,
+ 238, 244, 247, 247, 63, 248, 247, 254, 257, 247,
+ 250, 258, 28, 262, 28, 264, 34, 35, 263, 268,
+ 265, 266, 238, 267, 270, 238, 28, 262, 271, 35,
+ 238, 269, 263, 34, 274, 284, 34, 34, 279, 34,
+ 283, 273, 272, 260, 34, 220, 256, 253, 277, 26,
26, 26, 26, 28, 28, 28, 30, 30, 30, 30,
- 35, 35, 35, 35, 57, 196, 57, 57, 58, 58,
- 58, 58, 60, 194, 60, 60, 34, 34, 34, 34,
- 64, 64, 176, 64, 83, 83, 83, 83, 85, 115,
- 85, 85, 109, 109, 109, 109, 119, 119, 119, 119,
- 123, 123, 123, 123, 127, 127, 127, 127, 132, 132,
- 132, 132, 138, 138, 138, 138, 140, 86, 140, 140,
-
- 148, 148, 148, 148, 152, 152, 152, 152, 154, 35,
- 154, 154, 157, 157, 157, 157, 159, 29, 159, 159,
- 162, 162, 162, 162, 164, 54, 164, 164, 168, 168,
- 168, 168, 170, 52, 170, 170, 175, 175, 175, 175,
- 142, 35, 142, 142, 180, 180, 180, 180, 182, 29,
- 182, 182, 188, 188, 188, 188, 156, 255, 156, 156,
- 161, 27, 161, 161, 166, 27, 166, 166, 172, 255,
- 172, 172, 193, 193, 193, 193, 195, 195, 195, 195,
- 184, 255, 184, 184, 200, 200, 200, 200, 202, 202,
- 202, 202, 204, 255, 204, 204, 207, 207, 207, 207,
-
- 210, 210, 210, 210, 212, 212, 212, 212, 214, 214,
- 214, 214, 217, 217, 217, 217, 221, 221, 221, 221,
- 206, 255, 206, 206, 223, 223, 223, 223, 227, 227,
- 227, 227, 211, 255, 211, 211, 230, 230, 230, 230,
- 233, 233, 233, 233, 237, 237, 237, 237, 239, 255,
- 239, 239, 241, 255, 241, 241, 248, 248, 248, 248,
- 252, 252, 252, 252, 5, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255
-
+ 35, 35, 35, 35, 59, 213, 59, 59, 60, 60,
+
+ 60, 60, 62, 251, 62, 62, 34, 34, 34, 34,
+ 66, 66, 246, 66, 88, 88, 88, 88, 90, 243,
+ 90, 90, 117, 117, 117, 117, 129, 129, 129, 129,
+ 134, 134, 134, 134, 138, 138, 138, 138, 143, 143,
+ 143, 143, 149, 149, 149, 149, 151, 235, 151, 151,
+ 161, 161, 161, 161, 165, 165, 165, 165, 167, 233,
+ 167, 167, 171, 171, 171, 171, 173, 190, 173, 173,
+ 176, 176, 176, 176, 178, 228, 178, 178, 182, 182,
+ 182, 182, 184, 220, 184, 184, 189, 189, 189, 189,
+ 153, 213, 153, 153, 196, 196, 196, 196, 198, 211,
+
+ 198, 198, 204, 204, 204, 204, 169, 190, 169, 169,
+ 175, 125, 175, 175, 180, 123, 180, 180, 186, 91,
+ 186, 186, 210, 210, 210, 210, 212, 212, 212, 212,
+ 200, 35, 200, 200, 219, 219, 219, 219, 221, 221,
+ 221, 221, 223, 29, 223, 223, 227, 227, 227, 227,
+ 230, 230, 230, 230, 232, 232, 232, 232, 234, 234,
+ 234, 234, 237, 237, 237, 237, 242, 242, 242, 242,
+ 225, 56, 225, 225, 245, 245, 245, 245, 249, 249,
+ 249, 249, 231, 54, 231, 231, 252, 252, 252, 252,
+ 255, 255, 255, 255, 261, 261, 261, 261, 263, 35,
+
+ 263, 263, 265, 29, 265, 265, 275, 275, 275, 275,
+ 280, 280, 280, 280, 285, 27, 27, 5, 285, 285,
+ 285, 285, 285, 285, 285, 285, 285, 285, 285, 285,
+ 285, 285, 285, 285, 285, 285, 285, 285, 285, 285,
+ 285, 285, 285, 285, 285, 285, 285, 285, 285, 285,
+ 285
} ;
-static yyconst flex_int16_t yy_chk[699] =
+static yyconst flex_int16_t yy_chk[752] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 7, 7, 7, 8, 8, 8, 13,
- 7, 41, 13, 8, 11, 11, 11, 11, 11, 47,
- 14, 11, 11, 47, 14, 11, 19, 19, 41, 15,
+ 7, 280, 13, 8, 11, 11, 11, 11, 11, 20,
+ 14, 11, 11, 48, 14, 11, 20, 48, 14, 15,
16, 11, 12, 12, 12, 12, 12, 14, 16, 12,
- 12, 12, 15, 18, 16, 20, 21, 23, 21, 23,
- 252, 25, 20, 38, 25, 38, 45, 18, 25, 30,
- 30, 18, 31, 31, 31, 30, 40, 45, 40, 31,
-
- 34, 34, 34, 34, 39, 42, 46, 34, 34, 36,
- 36, 36, 36, 36, 43, 43, 36, 36, 39, 44,
- 44, 50, 48, 46, 48, 49, 42, 51, 49, 52,
- 53, 54, 55, 66, 56, 66, 55, 56, 65, 58,
- 58, 51, 65, 67, 50, 58, 54, 53, 54, 61,
- 61, 52, 68, 67, 69, 61, 70, 71, 72, 70,
- 73, 71, 74, 75, 77, 75, 68, 76, 82, 76,
- 72, 79, 73, 69, 78, 87, 78, 81, 250, 79,
- 74, 80, 80, 81, 80, 91, 77, 80, 89, 82,
- 83, 83, 89, 87, 90, 94, 83, 88, 88, 88,
-
- 88, 88, 95, 248, 88, 88, 90, 92, 91, 92,
- 95, 98, 98, 103, 98, 94, 96, 96, 96, 96,
- 96, 103, 106, 96, 96, 97, 97, 97, 97, 97,
- 100, 247, 97, 97, 99, 99, 99, 99, 99, 104,
- 106, 99, 99, 104, 101, 100, 101, 102, 102, 102,
- 102, 102, 105, 105, 102, 102, 107, 107, 109, 109,
- 111, 112, 107, 113, 109, 115, 116, 112, 116, 117,
- 117, 119, 119, 111, 245, 117, 129, 119, 113, 114,
- 114, 114, 114, 114, 115, 198, 114, 114, 121, 121,
- 123, 123, 125, 125, 121, 129, 123, 134, 125, 127,
-
- 127, 130, 130, 132, 132, 127, 135, 130, 198, 132,
- 137, 137, 138, 138, 143, 134, 145, 143, 138, 233,
- 145, 146, 146, 148, 148, 135, 191, 146, 191, 148,
- 150, 150, 151, 151, 151, 151, 151, 152, 152, 151,
- 151, 157, 157, 152, 162, 162, 173, 157, 167, 167,
- 162, 168, 168, 174, 174, 220, 173, 168, 178, 178,
- 179, 179, 180, 180, 186, 186, 188, 188, 180, 220,
- 186, 199, 188, 192, 192, 202, 202, 216, 178, 199,
- 199, 202, 209, 209, 209, 209, 209, 219, 235, 209,
- 209, 232, 216, 225, 225, 232, 219, 227, 227, 225,
-
- 236, 237, 237, 227, 242, 242, 243, 237, 230, 244,
- 246, 235, 223, 221, 217, 214, 212, 210, 207, 200,
- 197, 195, 193, 190, 236, 244, 243, 185, 246, 256,
- 256, 256, 256, 257, 257, 257, 258, 258, 258, 258,
- 259, 259, 259, 259, 260, 177, 260, 260, 261, 261,
- 261, 261, 262, 175, 262, 262, 263, 263, 263, 263,
- 264, 264, 136, 264, 265, 265, 265, 265, 266, 93,
- 266, 266, 267, 267, 267, 267, 268, 268, 268, 268,
- 269, 269, 269, 269, 270, 270, 270, 270, 271, 271,
- 271, 271, 272, 272, 272, 272, 273, 64, 273, 273,
-
- 274, 274, 274, 274, 275, 275, 275, 275, 276, 35,
- 276, 276, 277, 277, 277, 277, 278, 28, 278, 278,
- 279, 279, 279, 279, 280, 24, 280, 280, 281, 281,
- 281, 281, 282, 22, 282, 282, 283, 283, 283, 283,
- 284, 17, 284, 284, 285, 285, 285, 285, 286, 6,
- 286, 286, 287, 287, 287, 287, 288, 5, 288, 288,
- 289, 4, 289, 289, 290, 3, 290, 290, 291, 0,
- 291, 291, 292, 292, 292, 292, 293, 293, 293, 293,
- 294, 0, 294, 294, 295, 295, 295, 295, 296, 296,
- 296, 296, 297, 0, 297, 297, 298, 298, 298, 298,
-
+ 12, 12, 15, 18, 16, 19, 19, 21, 23, 21,
+ 23, 25, 277, 38, 25, 38, 39, 18, 25, 19,
+ 41, 18, 30, 30, 31, 31, 31, 40, 30, 40,
+
+ 39, 31, 34, 34, 34, 34, 42, 41, 43, 34,
+ 34, 36, 36, 36, 36, 36, 44, 44, 36, 36,
+ 45, 45, 46, 47, 52, 43, 43, 42, 49, 50,
+ 49, 51, 50, 46, 53, 54, 51, 55, 56, 57,
+ 47, 58, 275, 57, 58, 60, 60, 52, 53, 70,
+ 71, 60, 67, 56, 55, 56, 67, 54, 63, 63,
+ 68, 69, 68, 70, 63, 73, 72, 73, 76, 71,
+ 72, 69, 74, 75, 77, 74, 78, 75, 82, 79,
+ 76, 79, 81, 83, 81, 83, 77, 85, 85, 273,
+ 85, 84, 87, 85, 78, 80, 80, 80, 80, 84,
+
+ 82, 92, 80, 80, 86, 88, 88, 80, 94, 96,
+ 86, 88, 94, 87, 95, 97, 99, 97, 99, 92,
+ 93, 93, 93, 93, 93, 101, 95, 93, 93, 102,
+ 104, 111, 96, 106, 106, 104, 106, 102, 109, 111,
+ 109, 113, 113, 114, 241, 101, 103, 103, 103, 103,
+ 103, 122, 241, 103, 103, 105, 105, 105, 105, 105,
+ 108, 114, 105, 105, 107, 107, 107, 107, 107, 112,
+ 122, 107, 107, 112, 125, 108, 110, 110, 110, 110,
+ 110, 115, 115, 110, 110, 117, 117, 115, 119, 120,
+ 121, 117, 123, 125, 126, 120, 126, 127, 127, 148,
+
+ 148, 119, 145, 127, 131, 121, 163, 163, 271, 123,
+ 124, 124, 124, 124, 124, 129, 129, 124, 124, 131,
+ 145, 129, 132, 132, 134, 134, 136, 136, 132, 140,
+ 134, 146, 136, 138, 138, 141, 141, 143, 143, 138,
+ 208, 141, 208, 143, 154, 149, 149, 154, 140, 156,
+ 146, 149, 157, 156, 255, 158, 187, 157, 158, 159,
+ 159, 161, 161, 170, 170, 159, 187, 161, 164, 164,
+ 164, 164, 164, 165, 165, 164, 164, 171, 171, 165,
+ 176, 176, 252, 171, 181, 181, 176, 182, 182, 188,
+ 188, 192, 192, 182, 193, 193, 194, 195, 196, 196,
+
+ 215, 194, 206, 195, 196, 206, 202, 202, 204, 204,
+ 216, 192, 202, 217, 204, 209, 209, 226, 216, 216,
+ 221, 221, 236, 215, 217, 258, 221, 240, 245, 239,
+ 257, 226, 229, 229, 229, 229, 229, 236, 239, 229,
+ 229, 240, 247, 247, 249, 249, 259, 254, 247, 258,
+ 249, 254, 267, 257, 260, 268, 261, 261, 266, 266,
+ 272, 259, 261, 260, 269, 283, 274, 269, 274, 279,
+ 279, 268, 267, 244, 283, 242, 237, 234, 272, 286,
+ 286, 286, 286, 287, 287, 287, 288, 288, 288, 288,
+ 289, 289, 289, 289, 290, 232, 290, 290, 291, 291,
+
+ 291, 291, 292, 230, 292, 292, 293, 293, 293, 293,
+ 294, 294, 227, 294, 295, 295, 295, 295, 296, 219,
+ 296, 296, 297, 297, 297, 297, 298, 298, 298, 298,
299, 299, 299, 299, 300, 300, 300, 300, 301, 301,
- 301, 301, 302, 302, 302, 302, 303, 303, 303, 303,
- 304, 0, 304, 304, 305, 305, 305, 305, 306, 306,
- 306, 306, 307, 0, 307, 307, 308, 308, 308, 308,
- 309, 309, 309, 309, 310, 310, 310, 310, 311, 0,
- 311, 311, 312, 0, 312, 312, 313, 313, 313, 313,
- 314, 314, 314, 314, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255
-
+ 301, 301, 302, 302, 302, 302, 303, 214, 303, 303,
+ 304, 304, 304, 304, 305, 305, 305, 305, 306, 212,
+ 306, 306, 307, 307, 307, 307, 308, 210, 308, 308,
+ 309, 309, 309, 309, 310, 207, 310, 310, 311, 311,
+ 311, 311, 312, 201, 312, 312, 313, 313, 313, 313,
+ 314, 191, 314, 314, 315, 315, 315, 315, 316, 189,
+
+ 316, 316, 317, 317, 317, 317, 318, 147, 318, 318,
+ 319, 100, 319, 319, 320, 98, 320, 320, 321, 66,
+ 321, 321, 322, 322, 322, 322, 323, 323, 323, 323,
+ 324, 35, 324, 324, 325, 325, 325, 325, 326, 326,
+ 326, 326, 327, 28, 327, 327, 328, 328, 328, 328,
+ 329, 329, 329, 329, 330, 330, 330, 330, 331, 331,
+ 331, 331, 332, 332, 332, 332, 333, 333, 333, 333,
+ 334, 24, 334, 334, 335, 335, 335, 335, 336, 336,
+ 336, 336, 337, 22, 337, 337, 338, 338, 338, 338,
+ 339, 339, 339, 339, 340, 340, 340, 340, 341, 17,
+
+ 341, 341, 342, 6, 342, 342, 343, 343, 343, 343,
+ 344, 344, 344, 344, 5, 4, 3, 285, 285, 285,
+ 285, 285, 285, 285, 285, 285, 285, 285, 285, 285,
+ 285, 285, 285, 285, 285, 285, 285, 285, 285, 285,
+ 285, 285, 285, 285, 285, 285, 285, 285, 285, 285,
+ 285
} ;
#define YY_TRAILING_MASK 0x2000
@@ -890,7 +914,7 @@ static int vdev_and_devtype(DiskParseContext *dpc, char *str) {
#define DPC ((DiskParseContext*)yyextra)
-#line 894 "libxlu_disk_l.c"
+#line 918 "libxlu_disk_l.c"
#define INITIAL 0
#define LEXERR 1
@@ -1131,7 +1155,7 @@ YY_DECL
/*----- the scanner rules which do the parsing -----*/
-#line 1135 "libxlu_disk_l.c"
+#line 1159 "libxlu_disk_l.c"
if ( !yyg->yy_init )
{
@@ -1195,14 +1219,14 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 256 )
+ if ( yy_current_state >= 286 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
*yyg->yy_state_ptr++ = yy_current_state;
++yy_cp;
}
- while ( yy_current_state != 255 );
+ while ( yy_current_state != 285 );
yy_find_action:
yy_current_state = *--yyg->yy_state_ptr;
@@ -1313,34 +1337,49 @@ YY_RULE_SETUP
#line 175 "libxlu_disk_l.l"
{ STRIP(','); SAVESTRING("script", script, FROMEQUALS); }
YY_BREAK
-/* the target magic parameter, eats the rest of the string */
case 12:
YY_RULE_SETUP
-#line 179 "libxlu_disk_l.l"
+#line 176 "libxlu_disk_l.l"
+{ DPC->disk->direct_io_safe = 1; }
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 177 "libxlu_disk_l.l"
+{ libxl_defbool_set(&DPC->disk->discard_enable, true); }
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 178 "libxlu_disk_l.l"
+{ libxl_defbool_set(&DPC->disk->discard_enable, false); }
+ YY_BREAK
+/* the target magic parameter, eats the rest of the string */
+case 15:
+YY_RULE_SETUP
+#line 182 "libxlu_disk_l.l"
{ STRIP(','); SAVESTRING("target", pdev_path, FROMEQUALS); }
YY_BREAK
/* unknown parameters */
-case 13:
-/* rule 13 can match eol */
+case 16:
+/* rule 16 can match eol */
YY_RULE_SETUP
-#line 183 "libxlu_disk_l.l"
+#line 186 "libxlu_disk_l.l"
{ xlu__disk_err(DPC,yytext,"unknown parameter"); }
YY_BREAK
/* deprecated prefixes */
/* the "/.*" in these patterns ensures that they count as if they
* matched the whole string, so these patterns take precedence */
-case 14:
+case 17:
YY_RULE_SETUP
-#line 190 "libxlu_disk_l.l"
+#line 193 "libxlu_disk_l.l"
{
STRIP(':');
DPC->had_depr_prefix=1; DEPRECATE("use `[format=]...,'");
setformat(DPC, yytext);
}
YY_BREAK
-case 15:
+case 18:
YY_RULE_SETUP
-#line 196 "libxlu_disk_l.l"
+#line 199 "libxlu_disk_l.l"
{
char *newscript;
STRIP(':');
@@ -1354,65 +1393,65 @@ YY_RULE_SETUP
free(newscript);
}
YY_BREAK
-case 16:
+case 19:
*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
yyg->yy_c_buf_p = yy_cp = yy_bp + 8;
YY_DO_BEFORE_ACTION; /* set up yytext again */
YY_RULE_SETUP
-#line 209 "libxlu_disk_l.l"
+#line 212 "libxlu_disk_l.l"
{ DPC->had_depr_prefix=1; DEPRECATE(0); }
YY_BREAK
-case 17:
+case 20:
YY_RULE_SETUP
-#line 210 "libxlu_disk_l.l"
+#line 213 "libxlu_disk_l.l"
{ DPC->had_depr_prefix=1; DEPRECATE(0); }
YY_BREAK
-case 18:
+case 21:
*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
yyg->yy_c_buf_p = yy_cp = yy_bp + 4;
YY_DO_BEFORE_ACTION; /* set up yytext again */
YY_RULE_SETUP
-#line 211 "libxlu_disk_l.l"
+#line 214 "libxlu_disk_l.l"
{ DPC->had_depr_prefix=1; DEPRECATE(0); }
YY_BREAK
-case 19:
+case 22:
*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
yyg->yy_c_buf_p = yy_cp = yy_bp + 6;
YY_DO_BEFORE_ACTION; /* set up yytext again */
YY_RULE_SETUP
-#line 212 "libxlu_disk_l.l"
+#line 215 "libxlu_disk_l.l"
{ DPC->had_depr_prefix=1; DEPRECATE(0); }
YY_BREAK
-case 20:
+case 23:
*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
yyg->yy_c_buf_p = yy_cp = yy_bp + 5;
YY_DO_BEFORE_ACTION; /* set up yytext again */
YY_RULE_SETUP
-#line 213 "libxlu_disk_l.l"
+#line 216 "libxlu_disk_l.l"
{ DPC->had_depr_prefix=1; DEPRECATE(0); }
YY_BREAK
-case 21:
+case 24:
*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
yyg->yy_c_buf_p = yy_cp = yy_bp + 4;
YY_DO_BEFORE_ACTION; /* set up yytext again */
YY_RULE_SETUP
-#line 214 "libxlu_disk_l.l"
+#line 217 "libxlu_disk_l.l"
{ DPC->had_depr_prefix=1; DEPRECATE(0); }
YY_BREAK
-case 22:
-/* rule 22 can match eol */
+case 25:
+/* rule 25 can match eol */
YY_RULE_SETUP
-#line 216 "libxlu_disk_l.l"
+#line 219 "libxlu_disk_l.l"
{
xlu__disk_err(DPC,yytext,"unknown deprecated disk prefix");
return 0;
}
YY_BREAK
/* positional parameters */
-case 23:
-/* rule 23 can match eol */
+case 26:
+/* rule 26 can match eol */
YY_RULE_SETUP
-#line 223 "libxlu_disk_l.l"
+#line 226 "libxlu_disk_l.l"
{
STRIP(',');
@@ -1439,27 +1478,27 @@ YY_RULE_SETUP
}
}
YY_BREAK
-case 24:
+case 27:
YY_RULE_SETUP
-#line 249 "libxlu_disk_l.l"
+#line 252 "libxlu_disk_l.l"
{
BEGIN(LEXERR);
yymore();
}
YY_BREAK
-case 25:
+case 28:
YY_RULE_SETUP
-#line 253 "libxlu_disk_l.l"
+#line 256 "libxlu_disk_l.l"
{
xlu__disk_err(DPC,yytext,"bad disk syntax"); return 0;
}
YY_BREAK
-case 26:
+case 29:
YY_RULE_SETUP
-#line 256 "libxlu_disk_l.l"
+#line 259 "libxlu_disk_l.l"
YY_FATAL_ERROR( "flex scanner jammed" );
YY_BREAK
-#line 1463 "libxlu_disk_l.c"
+#line 1502 "libxlu_disk_l.c"
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(LEXERR):
yyterminate();
@@ -1723,7 +1762,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 256 )
+ if ( yy_current_state >= 286 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1747,11 +1786,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 256 )
+ if ( yy_current_state >= 286 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 255);
+ yy_is_jam = (yy_current_state == 285);
if ( ! yy_is_jam )
*yyg->yy_state_ptr++ = yy_current_state;
@@ -2551,4 +2590,4 @@ void xlu__disk_yyfree (void * ptr , yyscan_t yyscanner)
#define YYTABLES_NAME "yytables"
-#line 256 "libxlu_disk_l.l"
+#line 259 "libxlu_disk_l.l"
diff --git a/tools/libxl/libxlu_disk_l.h b/tools/libxl/libxlu_disk_l.h
index 0176249..08f60e5 100644
--- a/tools/libxl/libxlu_disk_l.h
+++ b/tools/libxl/libxlu_disk_l.h
@@ -344,7 +344,7 @@ extern int xlu__disk_yylex (yyscan_t yyscanner);
#undef YY_DECL
#endif
-#line 256 "libxlu_disk_l.l"
+#line 259 "libxlu_disk_l.l"
#line 350 "libxlu_disk_l.h"
#undef xlu__disk_yyIN_HEADER
diff --git a/tools/libxl/libxlu_disk_l.l b/tools/libxl/libxlu_disk_l.l
index 7c4e7f1..1a5deb5 100644
--- a/tools/libxl/libxlu_disk_l.l
+++ b/tools/libxl/libxlu_disk_l.l
@@ -173,6 +173,9 @@ backendtype=[^,]*,? { STRIP(','); setbackendtype(DPC,FROMEQUALS); }
vdev=[^,]*,? { STRIP(','); SAVESTRING("vdev", vdev, FROMEQUALS); }
script=[^,]*,? { STRIP(','); SAVESTRING("script", script, FROMEQUALS); }
+direct-io-safe,? { DPC->disk->direct_io_safe = 1; }
+discard,? { libxl_defbool_set(&DPC->disk->discard_enable, true); }
+no-discard,? { libxl_defbool_set(&DPC->disk->discard_enable, false); }
/* the target magic parameter, eats the rest of the string */
diff --git a/tools/libxl/libxlu_pci.c b/tools/libxl/libxlu_pci.c
index f5dee93..26fb143 100644
--- a/tools/libxl/libxlu_pci.c
+++ b/tools/libxl/libxlu_pci.c
@@ -141,6 +141,8 @@ int xlu_pci_parse_bdf(XLU_Config *cfg, libxl_device_pci *pcidev, const char *str
pcidev->power_mgmt = atoi(tok);
}else if ( !strcmp(optkey, "permissive") ) {
pcidev->permissive = atoi(tok);
+ }else if ( !strcmp(optkey, "seize") ) {
+ pcidev->seize = atoi(tok);
}else{
XLU__PCI_ERR(cfg, "Unknown PCI BDF option: %s", optkey);
}
diff --git a/tools/libxl/xen-init-dom0.c b/tools/libxl/xen-init-dom0.c
new file mode 100644
index 0000000..7925d64
--- /dev/null
+++ b/tools/libxl/xen-init-dom0.c
@@ -0,0 +1,120 @@
+#include <err.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <xenctrl.h>
+#include <xenstore.h>
+#include <libxl.h>
+
+#define DOMNAME_PATH "/local/domain/0/name"
+#define DOMID_PATH "/local/domain/0/domid"
+
+static libxl_ctx *ctx;
+static xentoollog_logger_stdiostream *logger;
+static struct xs_handle *xsh;
+
+static void ctx_alloc(void)
+{
+ if (libxl_ctx_alloc(&ctx, LIBXL_VERSION, 0,
+ (xentoollog_logger *)logger)) {
+ fprintf(stderr, "cannot init libxl context\n");
+ exit(1);
+ }
+ xsh = xs_open(0);
+ if (!xsh) {
+ fprintf(stderr, "cannot open xenstore connection\n");
+ exit(1);
+ }
+}
+
+static void ctx_free(void)
+{
+ if (ctx) {
+ libxl_ctx_free(ctx);
+ ctx = NULL;
+ }
+ if (logger) {
+ xtl_logger_destroy((xentoollog_logger *)logger);
+ logger = NULL;
+ }
+ if (xsh) {
+ xs_close(xsh);
+ xsh = NULL;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int rc;
+ libxl_domain_config dom0_config;
+ char *domname_string = NULL, *domid_string = NULL;
+ char *json = NULL;;
+
+ logger = xtl_createlogger_stdiostream(stderr, XTL_ERROR, 0);
+ if (!logger) exit(1);
+
+ atexit(ctx_free);
+
+ ctx_alloc();
+
+ libxl_domain_config_init(&dom0_config);
+
+ /* Sanity check: this program can only be run once. */
+ domid_string = xs_read(xsh, XBT_NULL, DOMID_PATH, NULL);
+ domname_string = xs_read(xsh, XBT_NULL, DOMNAME_PATH, NULL);
+ if (domid_string && domname_string) {
+ fprintf(stderr, "Dom0 is already set up\n");
+ rc = 0;
+ goto out;
+ }
+
+ /* Generate stub JSON config. */
+ dom0_config.c_info.type = LIBXL_DOMAIN_TYPE_PV;
+ libxl_domain_build_info_init_type(&dom0_config.b_info,
+ LIBXL_DOMAIN_TYPE_PV);
+
+ json = libxl_domain_config_to_json(ctx, &dom0_config);
+ /* libxl-json format requires the string ends with '\0'. Code
+ * snippet taken from libxl.
+ */
+ rc = libxl_userdata_store(ctx, 0, "libxl-json",
+ (const uint8_t *)json,
+ strlen(json) + 1 /* include '\0' */);
+ if (rc) {
+ fprintf(stderr, "cannot store stub json config for Dom0\n");
+ goto out;
+ }
+
+ /* Write xenstore entries. */
+ if (!xs_write(xsh, XBT_NULL, DOMID_PATH, "0", strlen("0"))) {
+ fprintf(stderr, "cannot set domid for Dom0\n");
+ rc = 1;
+ goto out;
+ }
+
+ if (!xs_write(xsh, XBT_NULL, DOMNAME_PATH, "Domain-0",
+ strlen("Domain-0"))) {
+ fprintf(stderr, "cannot set domain name for Dom0\n");
+ rc = 1;
+ goto out;
+ }
+
+ printf("Done setting up Dom0\n");
+
+out:
+ libxl_domain_config_dispose(&dom0_config);
+ free(domid_string);
+ free(domname_string);
+ free(json);
+ return rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxl/xl.c b/tools/libxl/xl.c
index 657610b..f014306 100644
--- a/tools/libxl/xl.c
+++ b/tools/libxl/xl.c
@@ -33,8 +33,6 @@
#include "libxlutil.h"
#include "xl.h"
-#define XEND_LOCK { "/var/lock/subsys/xend", "/var/lock/xend" }
-
xentoollog_logger_stdiostream *logger;
int dryrun_only;
int force_execution;
@@ -46,10 +44,12 @@ char *default_vifscript = NULL;
char *default_bridge = NULL;
char *default_gatewaydev = NULL;
char *default_vifbackend = NULL;
+char *default_remus_netbufscript = NULL;
enum output_format default_output_format = OUTPUT_FORMAT_JSON;
int claim_mode = 1;
+bool progress_use_cr = 0;
-static xentoollog_level minmsglevel = XTL_PROGRESS;
+xentoollog_level minmsglevel = minmsglevel_default;
/* Get autoballoon option based on presence of dom0_mem Xen command
line option. */
@@ -177,6 +177,9 @@ static void parse_global_config(const char *configfile,
if (!xlu_cfg_get_long (config, "claim_mode", &l, 0))
claim_mode = l;
+ xlu_cfg_replace_string (config, "remus.default.netbufscript",
+ &default_remus_netbufscript, 0);
+
xlu_cfg_destroy(config);
}
@@ -188,12 +191,13 @@ void postfork(void)
xl_ctx_alloc();
}
-pid_t xl_fork(xlchildnum child) {
+pid_t xl_fork(xlchildnum child, const char *description) {
xlchild *ch = &children[child];
int i;
assert(!ch->pid);
ch->reaped = 0;
+ ch->description = description;
ch->pid = fork();
if (ch->pid == -1) {
@@ -237,6 +241,13 @@ int xl_child_pid(xlchildnum child)
return ch->pid;
}
+void xl_report_child_exitstatus(xentoollog_level level,
+ xlchildnum child, pid_t pid, int status)
+{
+ libxl_report_child_exitstatus(ctx, level, children[child].description,
+ pid, status);
+}
+
static int xl_reaped_callback(pid_t got, int status, void *user)
{
int i;
@@ -290,9 +301,8 @@ int main(int argc, char **argv)
int ret;
void *config_data = 0;
int config_len = 0;
- const char *locks[] = XEND_LOCK;
- while ((opt = getopt(argc, argv, "+vfN")) >= 0) {
+ while ((opt = getopt(argc, argv, "+vftN")) >= 0) {
switch (opt) {
case 'v':
if (minmsglevel > 0) minmsglevel--;
@@ -303,6 +313,9 @@ int main(int argc, char **argv)
case 'f':
force_execution = 1;
break;
+ case 't':
+ progress_use_cr = 1;
+ break;
default:
fprintf(stderr, "unknown global option\n");
exit(2);
@@ -317,7 +330,8 @@ int main(int argc, char **argv)
}
opterr = 0;
- logger = xtl_createlogger_stdiostream(stderr, minmsglevel, 0);
+ logger = xtl_createlogger_stdiostream(stderr, minmsglevel,
+ (progress_use_cr ? XTL_STDIOSTREAM_PROGRESS_USE_CR : 0));
if (!logger) exit(1);
atexit(xl_ctx_free);
@@ -344,19 +358,6 @@ int main(int argc, char **argv)
ret = 1;
goto xit;
}
- if (cspec->modifies && !dryrun_only) {
- for (int i = 0; i < sizeof(locks)/sizeof(locks[0]); i++) {
- if (!access(locks[i], F_OK) && !force_execution) {
- fprintf(stderr,
-"xend is running, which may cause unpredictable results when using\n"
-"this xl command. Please shut down xend before continuing.\n\n"
-"(This check can be overridden with the -f option.)\n"
- );
- ret = 1;
- goto xit;
- }
- }
- }
ret = cspec->cmd_impl(argc, argv);
} else if (!strcmp(cmd, "help")) {
help(argv[1]);
diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index f188708..c91de4f 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -67,6 +67,7 @@ int main_memset(int argc, char **argv);
int main_sched_credit(int argc, char **argv);
int main_sched_credit2(int argc, char **argv);
int main_sched_sedf(int argc, char **argv);
+int main_sched_rtds(int argc, char **argv);
int main_domid(int argc, char **argv);
int main_domname(int argc, char **argv);
int main_rename(int argc, char **argv);
@@ -78,6 +79,7 @@ int main_top(int argc, char **argv);
int main_networkattach(int argc, char **argv);
int main_networklist(int argc, char **argv);
int main_networkdetach(int argc, char **argv);
+int main_channellist(int argc, char **argv);
int main_blockattach(int argc, char **argv);
int main_blocklist(int argc, char **argv);
int main_blockdetach(int argc, char **argv);
@@ -110,6 +112,11 @@ int main_loadpolicy(int argc, char **argv);
int main_remus(int argc, char **argv);
#endif
int main_devd(int argc, char **argv);
+#ifdef LIBXL_HAVE_PSR_CMT
+int main_psr_cmt_attach(int argc, char **argv);
+int main_psr_cmt_detach(int argc, char **argv);
+int main_psr_cmt_show(int argc, char **argv);
+#endif
void help(const char *command);
@@ -130,6 +137,7 @@ typedef struct {
pid_t pid; /* 0: not in use */
int reaped; /* valid iff pid!=0 */
int status; /* valid iff reaped */
+ const char *description; /* valid iff pid!=0 */
} xlchild;
typedef enum {
@@ -139,7 +147,8 @@ typedef enum {
extern xlchild children[child_max];
-pid_t xl_fork(xlchildnum); /* like fork, but prints and dies if it fails */
+pid_t xl_fork(xlchildnum, const char *description);
+ /* like fork, but prints and dies if it fails */
void postfork(void); /* needed only if we aren't going to exec right away */
/* Handles EINTR. Clears out the xlchild so it can be reused. */
@@ -147,16 +156,28 @@ pid_t xl_waitpid(xlchildnum, int *status, int flags);
int xl_child_pid(xlchildnum); /* returns 0 if child struct is not in use */
+void xl_report_child_exitstatus(xentoollog_level level,
+ xlchildnum child, pid_t pid, int status);
+ /* like libxl_report_child_exitstatus, but uses children[].description */
+
+int child_report(xlchildnum child);
+ /* waits and expects child to exit status 0.
+ * otherwise, logs and returns ERROR_FAIL */
+
/* global options */
extern int autoballoon;
extern int run_hotplug_scripts;
extern int dryrun_only;
extern int claim_mode;
+extern bool progress_use_cr;
+extern xentoollog_level minmsglevel;
+#define minmsglevel_default XTL_PROGRESS
extern char *lockfile;
extern char *default_vifscript;
extern char *default_bridge;
extern char *default_gatewaydev;
extern char *default_vifbackend;
+extern char *default_remus_netbufscript;
extern char *blkdev_start;
enum output_format {
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 4fc46eb..0e754e7 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -34,6 +34,7 @@
#include <ctype.h>
#include <inttypes.h>
#include <limits.h>
+#include <xen/hvm/e820.h>
#include "libxl.h"
#include "libxl_utils.h"
@@ -88,9 +89,6 @@ xlchild children[child_max];
static const char *common_domname;
static int fd_lock = -1;
-/* Stash for specific vcpu to pcpu mappping */
-static int *vcpu_to_pcpu;
-
static const char savefileheader_magic[32]=
"Xen saved domain, xl format\n \0 \r";
@@ -110,6 +108,8 @@ static const char migrate_report[]=
* from target to source
*/
+#define XL_MANDATORY_FLAG_JSON (1U << 0) /* config data is in JSON format */
+#define XL_MANDATORY_FLAG_ALL (XL_MANDATORY_FLAG_JSON)
struct save_file_header {
char magic[32]; /* savefileheader_magic */
/* All uint32_ts are in domain's byte order. */
@@ -158,38 +158,6 @@ struct domain_create {
};
-
-static int qualifier_to_id(const char *p, uint32_t *id_r)
-{
- int i, alldigit;
-
- alldigit = 1;
- for (i = 0; p[i]; i++) {
- if (!isdigit((uint8_t)p[i])) {
- alldigit = 0;
- break;
- }
- }
-
- if (i > 0 && alldigit) {
- *id_r = strtoul(p, NULL, 10);
- return 0;
- } else {
- /* check here if it's a uuid and do proper conversion */
- }
- return 1;
-}
-
-static int cpupool_qualifier_to_cpupoolid(const char *p, uint32_t *poolid_r,
- int *was_name_r)
-{
- int was_name;
-
- was_name = qualifier_to_id(p, poolid_r);
- if (was_name_r) *was_name_r = was_name;
- return was_name ? libxl_name_to_cpupoolid(ctx, p, poolid_r) : 0;
-}
-
static uint32_t find_domain(const char *p) __attribute__((warn_unused_result));
static uint32_t find_domain(const char *p)
{
@@ -205,6 +173,28 @@ static uint32_t find_domain(const char *p)
return domid;
}
+int child_report(xlchildnum child)
+{
+ int status;
+ pid_t got = xl_waitpid(child, &status, 0);
+ if (got < 0) {
+ fprintf(stderr, "xl: warning, failed to waitpid for %s: %s\n",
+ children[child].description, strerror(errno));
+ return ERROR_FAIL;
+ } else if (status) {
+ xl_report_child_exitstatus(XTL_ERROR, child, got, status);
+ return ERROR_FAIL;
+ } else {
+ return 0;
+ }
+}
+
+static void console_child_report(xlchildnum child)
+{
+ if (xl_child_pid(child))
+ child_report(child);
+}
+
static int vncviewer(uint32_t domid, int autopass)
{
libxl_vncviewer_exec(ctx, domid, autopass);
@@ -212,28 +202,12 @@ static int vncviewer(uint32_t domid, int autopass)
return 1;
}
-static void vncviewer_child_report(void)
-{
- if (xl_child_pid(child_vncviewer)) {
- int status;
- pid_t got = xl_waitpid(child_vncviewer, &status, 0);
- if (got < 0)
- perror("xl: warning, failed to waitpid for vncviewer child");
- else if (status)
- libxl_report_child_exitstatus(ctx, XTL_ERROR, "vncviewer child",
- xl_child_pid(child_vncviewer), status);
- }
-}
-
static void autoconnect_vncviewer(uint32_t domid, int autopass)
{
- vncviewer_child_report();
+ console_child_report(child_vncviewer);
- pid_t pid = xl_fork(child_vncviewer);
- if (pid < 0) {
- perror("unable to fork vncviewer");
- return;
- } else if (pid > 0)
+ pid_t pid = xl_fork(child_vncviewer, "vncviewer child");
+ if (pid)
return;
postfork();
@@ -327,6 +301,18 @@ static void *xrealloc(void *ptr, size_t sz) {
return r;
}
+static char *xstrdup(const char *x)
+{
+ char *r;
+ r = strdup(x);
+ if (!r) {
+ fprintf(stderr, "xl: Unable to strdup a string of length %zu.\n",
+ strlen(x));
+ exit(-ERROR_FAIL);
+ }
+ return r;
+}
+
#define ARRAY_EXTEND_INIT(array,count,initfn) \
({ \
typeof((count)) array_extend_old_count = (count); \
@@ -352,6 +338,8 @@ static void dolog(const char *file, int line, const char *func, char *fmt, ...)
rc = vasprintf(&s, fmt, ap);
va_end(ap);
if (rc >= 0)
+ /* we ignore write errors since we have no way to report them;
+ * the alternative would be to abort the whole program */
libxl_write_exactly(NULL, logfile, s, rc, NULL, NULL);
free(s);
}
@@ -432,26 +420,13 @@ out:
static int do_daemonize(char *name)
{
char *fullname;
- pid_t child1, got_child;
+ pid_t child1;
int nullfd, ret = 0;
- int status = 0;
- child1 = xl_fork(child_waitdaemon);
+ child1 = xl_fork(child_waitdaemon, "domain monitoring daemonizing child");
if (child1) {
- got_child = xl_waitpid(child_waitdaemon, &status, 0);
- if (got_child != child1) {
- assert(got_child == -1);
- LOG("failed to wait for daemonizing child: %s", strerror(errno));
- ret = ERROR_FAIL;
- goto out;
- }
-
- if (status) {
- libxl_report_child_exitstatus(ctx, XTL_ERROR,
- "daemonizing child", child1, status);
- ret = ERROR_FAIL;
- goto out;
- }
+ ret = child_report(child_waitdaemon);
+ if (ret) goto out;
ret = 1;
goto out;
}
@@ -544,6 +519,30 @@ static void parse_vif_rate(XLU_Config **config, const char *rate,
}
}
+static void set_default_nic_values(libxl_device_nic *nic)
+{
+
+ if (default_vifscript) {
+ free(nic->script);
+ nic->script = strdup(default_vifscript);
+ }
+
+ if (default_bridge) {
+ free(nic->bridge);
+ nic->bridge = strdup(default_bridge);
+ }
+
+ if (default_gatewaydev) {
+ free(nic->gatewaydev);
+ nic->gatewaydev = strdup(default_gatewaydev);
+ }
+
+ if (default_vifbackend) {
+ free(nic->backend_domname);
+ nic->backend_domname = strdup(default_vifbackend);
+ }
+}
+
static void split_string_into_string_list(const char *str,
const char *delim,
libxl_string_list *psl)
@@ -556,7 +555,7 @@ static void split_string_into_string_list(const char *str,
s = strdup(str);
if (s == NULL) {
- fprintf(stderr, "unable to allocate memory to parse bootloader args\n");
+ fprintf(stderr, "unable to allocate memory to split string\n");
exit(-1);
}
@@ -572,7 +571,7 @@ static void split_string_into_string_list(const char *str,
sl = malloc((nr+1) * sizeof (char *));
if (sl == NULL) {
- fprintf(stderr, "unable to allocate memory for bootloader args\n");
+ fprintf(stderr, "unable to allocate memory to split string\n");
exit(-1);
}
@@ -589,6 +588,68 @@ static void split_string_into_string_list(const char *str,
free(s);
}
+/* NB: this follows the interface used by <ctype.h>. See 'man 3 ctype'
+ and look for CTYPE in libxl_internal.h */
+typedef int (*char_predicate_t)(const int c);
+
+static void trim(char_predicate_t predicate, const char *input, char **output)
+{
+ char *p, *q, *tmp;
+
+ *output = NULL;
+ if (*input == '\000')
+ return;
+ /* Input has length >= 1 */
+
+ p = tmp = xstrdup(input);
+ /* Skip past the characters for which predicate is true */
+ while ((*p != '\000') && (predicate((unsigned char)*p)))
+ p ++;
+ q = p + strlen(p) - 1;
+ /* q points to the last non-NULL character */
+ while ((q > p) && (predicate((unsigned char)*q)))
+ q --;
+ /* q points to the last character we want */
+ q ++;
+ *q = '\000';
+ *output = xstrdup(p);
+ free(tmp);
+}
+
+static int split_string_into_pair(const char *str,
+ const char *delim,
+ char **a,
+ char **b)
+{
+ char *s, *p, *saveptr, *aa = NULL, *bb = NULL;
+ int rc = 0;
+
+ s = xstrdup(str);
+
+ p = strtok_r(s, delim, &saveptr);
+ if (p == NULL) {
+ rc = ERROR_INVAL;
+ goto out;
+ }
+ aa = xstrdup(p);
+ p = strtok_r(NULL, delim, &saveptr);
+ if (p == NULL) {
+ rc = ERROR_INVAL;
+ goto out;
+ }
+ bb = xstrdup(p);
+
+ *a = aa;
+ aa = NULL;
+ *b = bb;
+ bb = NULL;
+out:
+ free(s);
+ free(aa);
+ free(bb);
+ return rc;
+}
+
static int parse_range(const char *str, unsigned long *a, unsigned long *b)
{
const char *nstr;
@@ -693,17 +754,18 @@ static int update_cpumap_range(const char *str, libxl_bitmap *cpumap)
* single cpus or as eintire NUMA nodes) and turns it into the
* corresponding libxl_bitmap (in cpumap).
*/
-static int vcpupin_parse(char *cpu, libxl_bitmap *cpumap)
+static int vcpupin_parse(const char *cpu, libxl_bitmap *cpumap)
{
- char *ptr, *saveptr = NULL;
+ char *ptr, *saveptr = NULL, *buf = strdup(cpu);
int rc = 0;
- for (ptr = strtok_r(cpu, ",", &saveptr); ptr;
+ for (ptr = strtok_r(buf, ",", &saveptr); ptr;
ptr = strtok_r(NULL, ",", &saveptr)) {
rc = update_cpumap_range(ptr, cpumap);
if (rc)
break;
}
+ free(buf);
return rc;
}
@@ -721,22 +783,142 @@ static void parse_top_level_vnc_options(XLU_Config *config,
xlu_cfg_get_defbool(config, "vncunused", &vnc->findunused, 0);
}
+static void parse_top_level_sdl_options(XLU_Config *config,
+ libxl_sdl_info *sdl)
+{
+ xlu_cfg_get_defbool(config, "sdl", &sdl->enable, 0);
+ xlu_cfg_get_defbool(config, "opengl", &sdl->opengl, 0);
+ xlu_cfg_replace_string (config, "display", &sdl->display, 0);
+ xlu_cfg_replace_string (config, "xauthority", &sdl->xauthority, 0);
+}
+
+static char *parse_cmdline(XLU_Config *config)
+{
+ char *cmdline = NULL;
+ const char *root = NULL, *extra = NULL, *buf = NULL;
+
+ xlu_cfg_get_string (config, "cmdline", &buf, 0);
+ xlu_cfg_get_string (config, "root", &root, 0);
+ xlu_cfg_get_string (config, "extra", &extra, 0);
+
+ if (buf) {
+ cmdline = strdup(buf);
+ if (root || extra)
+ fprintf(stderr, "Warning: ignoring root= and extra= "
+ "in favour of cmdline=\n");
+ } else {
+ if (root) {
+ if (asprintf(&cmdline, "root=%s %s", root, extra) == -1)
+ cmdline = NULL;
+ } else if (extra) {
+ cmdline = strdup(extra);
+ }
+ }
+
+ if ((buf || root || extra) && !cmdline) {
+ fprintf(stderr, "Failed to allocate memory for cmdline\n");
+ exit(1);
+ }
+
+ return cmdline;
+}
+
+static void parse_vcpu_affinity(libxl_domain_build_info *b_info,
+ XLU_ConfigList *cpus, const char *buf,
+ int num_cpus, bool is_hard)
+{
+ libxl_bitmap *vcpu_affinity_array;
+
+ /*
+ * If we are here, and buf is !NULL, we're dealing with a string. What
+ * we do in this case is parse it, and copy the result in _all_ (up to
+ * b_info->max_vcpus) the elements of the vcpu affinity array.
+ *
+ * If buf is NULL, we have a list, and what we do is putting in the
+ * i-eth element of the vcpu affinity array the result of the parsing
+ * of the i-eth entry of the list. If there are more vcpus than
+ * entries, it is fine to just not touch the last array elements.
+ */
+
+ /* Silently ignore values corresponding to non existing vcpus */
+ if (buf || num_cpus > b_info->max_vcpus)
+ num_cpus = b_info->max_vcpus;
+
+ if (is_hard) {
+ b_info->num_vcpu_hard_affinity = num_cpus;
+ b_info->vcpu_hard_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
+ vcpu_affinity_array = b_info->vcpu_hard_affinity;
+ } else {
+ b_info->num_vcpu_soft_affinity = num_cpus;
+ b_info->vcpu_soft_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
+ vcpu_affinity_array = b_info->vcpu_soft_affinity;
+ }
+
+ if (!buf) {
+ int j = 0;
+
+ while ((buf = xlu_cfg_get_listitem(cpus, j)) != NULL && j < num_cpus) {
+ libxl_bitmap_init(&vcpu_affinity_array[j]);
+ if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[j], 0)) {
+ fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", j);
+ exit(1);
+ }
+
+ if (vcpupin_parse(buf, &vcpu_affinity_array[j]))
+ exit(1);
+
+ j++;
+ }
+
+ /* We have a list of cpumaps, disable automatic placement */
+ libxl_defbool_set(&b_info->numa_placement, false);
+ } else {
+ int i;
+
+ libxl_bitmap_init(&vcpu_affinity_array[0]);
+ if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[0], 0)) {
+ fprintf(stderr, "Unable to allocate cpumap for vcpu 0\n");
+ exit(1);
+ }
+
+ if (vcpupin_parse(buf, &vcpu_affinity_array[0]))
+ exit(1);
+
+ for (i = 1; i < b_info->max_vcpus; i++) {
+ libxl_bitmap_init(&vcpu_affinity_array[i]);
+ if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[i], 0)) {
+ fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", i);
+ exit(1);
+ }
+ libxl_bitmap_copy(ctx, &vcpu_affinity_array[i],
+ &vcpu_affinity_array[0]);
+ }
+
+ libxl_defbool_set(&b_info->numa_placement, false);
+ }
+}
+
+static void replace_string(char **str, const char *val)
+{
+ free(*str);
+ *str = xstrdup(val);
+}
+
static void parse_config_data(const char *config_source,
const char *config_data,
int config_len,
- libxl_domain_config *d_config,
- struct domain_create *dom_info)
-
+ libxl_domain_config *d_config)
{
const char *buf;
long l;
XLU_Config *config;
XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms;
- XLU_ConfigList *ioports, *irqs, *iomem;
- int num_ioports, num_irqs, num_iomem;
+ XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian;
+ int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
int pci_power_mgmt = 0;
int pci_msitranslate = 0;
int pci_permissive = 0;
+ int pci_seize = 0;
int i, e;
libxl_domain_create_info *c_info = &d_config->c_info;
@@ -754,35 +936,17 @@ static void parse_config_data(const char *config_source,
exit(1);
}
- if (!xlu_cfg_get_string (config, "init_seclabel", &buf, 0)) {
- e = libxl_flask_context_to_sid(ctx, (char *)buf, strlen(buf),
- &c_info->ssidref);
- if (e) {
- if (errno == ENOSYS) {
- fprintf(stderr, "XSM Disabled: init_seclabel not supported\n");
- } else {
- fprintf(stderr, "Invalid init_seclabel: %s\n", buf);
- exit(1);
- }
- }
- }
+ if (!xlu_cfg_get_string (config, "init_seclabel", &buf, 0))
+ xlu_cfg_replace_string(config, "init_seclabel",
+ &c_info->ssid_label, 0);
if (!xlu_cfg_get_string (config, "seclabel", &buf, 0)) {
- uint32_t ssidref;
- e = libxl_flask_context_to_sid(ctx, (char *)buf, strlen(buf),
- &ssidref);
- if (e) {
- if (errno == ENOSYS) {
- fprintf(stderr, "XSM Disabled: seclabel not supported\n");
- } else {
- fprintf(stderr, "Invalid seclabel: %s\n", buf);
- exit(1);
- }
- } else if (c_info->ssidref) {
- b_info->exec_ssidref = ssidref;
- } else {
- c_info->ssidref = ssidref;
- }
+ if (c_info->ssid_label)
+ xlu_cfg_replace_string(config, "seclabel",
+ &b_info->exec_ssid_label, 0);
+ else
+ xlu_cfg_replace_string(config, "seclabel",
+ &c_info->ssid_label, 0);
}
libxl_defbool_set(&c_info->run_hotplug_scripts, run_hotplug_scripts);
@@ -810,14 +974,8 @@ static void parse_config_data(const char *config_source,
xlu_cfg_get_defbool(config, "oos", &c_info->oos, 0);
- if (!xlu_cfg_get_string (config, "pool", &buf, 0)) {
- c_info->poolid = -1;
- cpupool_qualifier_to_cpupoolid(buf, &c_info->poolid, NULL);
- }
- if (!libxl_cpupoolid_is_valid(ctx, c_info->poolid)) {
- fprintf(stderr, "Illegal pool specified\n");
- exit(1);
- }
+ if (!xlu_cfg_get_string (config, "pool", &buf, 0))
+ xlu_cfg_replace_string(config, "pool", &c_info->pool_name, 0);
libxl_domain_build_info_init_type(b_info, c_info->type);
if (blkdev_start)
@@ -853,60 +1011,15 @@ static void parse_config_data(const char *config_source,
if (!xlu_cfg_get_long (config, "maxvcpus", &l, 0))
b_info->max_vcpus = l;
- if (!xlu_cfg_get_list (config, "cpus", &cpus, 0, 1)) {
- int n_cpus = 0;
-
- if (libxl_cpu_bitmap_alloc(ctx, &b_info->cpumap, 0)) {
- fprintf(stderr, "Unable to allocate cpumap\n");
- exit(1);
- }
-
- /* Prepare the array for single vcpu to pcpu mappings */
- vcpu_to_pcpu = xmalloc(sizeof(int) * b_info->max_vcpus);
- memset(vcpu_to_pcpu, -1, sizeof(int) * b_info->max_vcpus);
-
- /*
- * Idea here is to let libxl think all the domain's vcpus
- * have cpu affinity with all the pcpus on the list.
- * It is then us, here in xl, that matches each single vcpu
- * to its pcpu (and that's why we need to stash such info in
- * the vcpu_to_pcpu array now) after the domain has been created.
- * Doing it like this saves the burden of passing to libxl
- * some big array hosting the single mappings. Also, using
- * the cpumap derived from the list ensures memory is being
- * allocated on the proper nodes anyway.
- */
- libxl_bitmap_set_none(&b_info->cpumap);
- while ((buf = xlu_cfg_get_listitem(cpus, n_cpus)) != NULL) {
- i = atoi(buf);
- if (!libxl_bitmap_cpu_valid(&b_info->cpumap, i)) {
- fprintf(stderr, "cpu %d illegal\n", i);
- exit(1);
- }
- libxl_bitmap_set(&b_info->cpumap, i);
- if (n_cpus < b_info->max_vcpus)
- vcpu_to_pcpu[n_cpus] = i;
- n_cpus++;
- }
+ buf = NULL;
+ if (!xlu_cfg_get_list (config, "cpus", &cpus, &num_cpus, 1) ||
+ !xlu_cfg_get_string (config, "cpus", &buf, 0))
+ parse_vcpu_affinity(b_info, cpus, buf, num_cpus, /* is_hard */ true);
- /* We have a cpumap, disable automatic placement */
- libxl_defbool_set(&b_info->numa_placement, false);
- }
- else if (!xlu_cfg_get_string (config, "cpus", &buf, 0)) {
- char *buf2 = strdup(buf);
-
- if (libxl_cpu_bitmap_alloc(ctx, &b_info->cpumap, 0)) {
- fprintf(stderr, "Unable to allocate cpumap\n");
- exit(1);
- }
-
- libxl_bitmap_set_none(&b_info->cpumap);
- if (vcpupin_parse(buf2, &b_info->cpumap))
- exit(1);
- free(buf2);
-
- libxl_defbool_set(&b_info->numa_placement, false);
- }
+ buf = NULL;
+ if (!xlu_cfg_get_list (config, "cpus_soft", &cpus, &num_cpus, 1) ||
+ !xlu_cfg_get_string (config, "cpus_soft", &buf, 0))
+ parse_vcpu_affinity(b_info, cpus, buf, num_cpus, false);
if (!xlu_cfg_get_long (config, "memory", &l, 0)) {
b_info->max_memkb = l * 1024;
@@ -983,12 +1096,9 @@ static void parse_config_data(const char *config_source,
if (!xlu_cfg_get_long(config, "rtc_timeoffset", &l, 0))
b_info->rtc_timeoffset = l;
- if (dom_info && !xlu_cfg_get_long(config, "vncviewer", &l, 0)) {
- /* Command line arguments must take precedence over what's
- * specified in the configuration file. */
- if (!dom_info->vnc)
- dom_info->vnc = l;
- }
+ if (!xlu_cfg_get_long(config, "vncviewer", &l, 0))
+ fprintf(stderr, "WARNING: ignoring \"vncviewer\" option. "
+ "Use \"-V\" option of \"xl create\" to automatically spawn vncviewer.\n");
xlu_cfg_get_defbool(config, "localtime", &b_info->localtime, 0);
@@ -998,13 +1108,21 @@ static void parse_config_data(const char *config_source,
if (!xlu_cfg_get_long(config, "max_event_channels", &l, 0))
b_info->event_channels = l;
+ xlu_cfg_replace_string (config, "kernel", &b_info->kernel, 0);
+ xlu_cfg_replace_string (config, "ramdisk", &b_info->ramdisk, 0);
+ b_info->cmdline = parse_cmdline(config);
+
xlu_cfg_get_defbool(config, "driver_domain", &c_info->driver_domain, 0);
switch(b_info->type) {
case LIBXL_DOMAIN_TYPE_HVM:
- if (!xlu_cfg_get_string (config, "kernel", &buf, 0))
- fprintf(stderr, "WARNING: ignoring \"kernel\" directive for HVM guest. "
- "Use \"firmware_override\" instead if you really want a non-default firmware\n");
+ if (!strcmp(libxl_basename(b_info->kernel), "hvmloader")) {
+ fprintf(stderr, "WARNING: you seem to be using \"kernel\" "
+ "directive to override HVM guest firmware. Ignore "
+ "that. Use \"firmware_override\" instead if you "
+ "really want a non-default firmware\n");
+ b_info->kernel = NULL;
+ }
xlu_cfg_replace_string (config, "firmware_override",
&b_info->u.hvm.firmware, 0);
@@ -1021,10 +1139,71 @@ static void parse_config_data(const char *config_source,
xlu_cfg_get_defbool(config, "acpi_s3", &b_info->u.hvm.acpi_s3, 0);
xlu_cfg_get_defbool(config, "acpi_s4", &b_info->u.hvm.acpi_s4, 0);
xlu_cfg_get_defbool(config, "nx", &b_info->u.hvm.nx, 0);
- xlu_cfg_get_defbool(config, "viridian", &b_info->u.hvm.viridian, 0);
xlu_cfg_get_defbool(config, "hpet", &b_info->u.hvm.hpet, 0);
xlu_cfg_get_defbool(config, "vpt_align", &b_info->u.hvm.vpt_align, 0);
+ switch (xlu_cfg_get_list(config, "viridian",
+ &viridian, &num_viridian, 1))
+ {
+ case 0: /* Success */
+ if (num_viridian) {
+ libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_enable,
+ LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
+ libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_disable,
+ LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
+ }
+ for (i = 0; i < num_viridian; i++) {
+ libxl_viridian_enlightenment v;
+
+ buf = xlu_cfg_get_listitem(viridian, i);
+ if (strcmp(buf, "all") == 0)
+ libxl_bitmap_set_any(&b_info->u.hvm.viridian_enable);
+ else if (strcmp(buf, "defaults") == 0)
+ libxl_defbool_set(&b_info->u.hvm.viridian, true);
+ else {
+ libxl_bitmap *s = &b_info->u.hvm.viridian_enable;
+ libxl_bitmap *r = &b_info->u.hvm.viridian_disable;
+
+ if (*buf == '!') {
+ s = &b_info->u.hvm.viridian_disable;
+ r = &b_info->u.hvm.viridian_enable;
+ buf++;
+ }
+
+ e = libxl_viridian_enlightenment_from_string(buf, &v);
+ if (e) {
+ fprintf(stderr,
+ "xl: unknown viridian enlightenment '%s'\n",
+ buf);
+ exit(-ERROR_FAIL);
+ }
+
+ libxl_bitmap_set(s, v);
+ libxl_bitmap_reset(r, v);
+ }
+ }
+ break;
+ case ESRCH: break; /* Option not present */
+ case EINVAL:
+ xlu_cfg_get_defbool(config, "viridian", &b_info->u.hvm.viridian, 1);
+ break;
+ default:
+ fprintf(stderr,"xl: Unable to parse viridian enlightenments.\n");
+ exit(-ERROR_FAIL);
+ }
+
+ if (!xlu_cfg_get_long(config, "mmio_hole", &l, 0)) {
+ uint64_t mmio_hole_size;
+
+ b_info->u.hvm.mmio_hole_memkb = l * 1024;
+ mmio_hole_size = b_info->u.hvm.mmio_hole_memkb * 1024;
+ if (mmio_hole_size < HVM_BELOW_4G_MMIO_LENGTH ||
+ mmio_hole_size > HVM_BELOW_4G_MMIO_START) {
+ fprintf(stderr,
+ "ERROR: invalid value %ld for \"mmio_hole\"\n", l);
+ exit (1);
+ }
+ }
if (!xlu_cfg_get_long(config, "timer_mode", &l, 1)) {
const char *s = libxl_timer_mode_to_string(l);
fprintf(stderr, "WARNING: specifying \"timer_mode\" as an integer is deprecated. "
@@ -1053,29 +1232,24 @@ static void parse_config_data(const char *config_source,
&b_info->u.hvm.smbios_firmware, 0);
xlu_cfg_replace_string(config, "acpi_firmware",
&b_info->u.hvm.acpi_firmware, 0);
+
+ if (!xlu_cfg_get_string(config, "ms_vm_genid", &buf, 0)) {
+ if (!strcmp(buf, "generate")) {
+ e = libxl_ms_vm_genid_generate(ctx, &b_info->u.hvm.ms_vm_genid);
+ if (e) {
+ fprintf(stderr, "ERROR: failed to generate a VM Generation ID\n");
+ exit(1);
+ }
+ } else if (!strcmp(buf, "none")) {
+ ;
+ } else {
+ fprintf(stderr, "ERROR: \"ms_vm_genid\" option must be \"generate\" or \"none\"\n");
+ exit(1);
+ }
+ }
break;
case LIBXL_DOMAIN_TYPE_PV:
{
- char *cmdline = NULL;
- const char *root = NULL, *extra = "";
-
- xlu_cfg_replace_string (config, "kernel", &b_info->u.pv.kernel, 0);
-
- xlu_cfg_get_string (config, "root", &root, 0);
- xlu_cfg_get_string (config, "extra", &extra, 0);
-
- if (root) {
- if (asprintf(&cmdline, "root=%s %s", root, extra) == -1)
- cmdline = NULL;
- } else {
- cmdline = strdup(extra);
- }
-
- if ((root || extra) && !cmdline) {
- fprintf(stderr, "Failed to allocate memory for cmdline\n");
- exit(1);
- }
-
xlu_cfg_replace_string (config, "bootloader", &b_info->u.pv.bootloader, 0);
switch (xlu_cfg_get_list_as_string_list(config, "bootloader_args",
&b_info->u.pv.bootloader_args, 1))
@@ -1098,13 +1272,11 @@ static void parse_config_data(const char *config_source,
exit(-ERROR_FAIL);
}
- if (!b_info->u.pv.bootloader && !b_info->u.pv.kernel) {
+ if (!b_info->u.pv.bootloader && !b_info->kernel) {
fprintf(stderr, "Neither kernel nor bootloader specified\n");
exit(1);
}
- b_info->u.pv.cmdline = cmdline;
- xlu_cfg_replace_string (config, "ramdisk", &b_info->u.pv.ramdisk, 0);
break;
}
default:
@@ -1195,6 +1367,7 @@ static void parse_config_data(const char *config_source,
}
if (!xlu_cfg_get_list(config, "iomem", &iomem, &num_iomem, 0)) {
+ int ret;
b_info->num_iomem = num_iomem;
b_info->iomem = calloc(num_iomem, sizeof(*b_info->iomem));
if (b_info->iomem == NULL) {
@@ -1208,13 +1381,15 @@ static void parse_config_data(const char *config_source,
"xl: Unable to get element %d in iomem list\n", i);
exit(1);
}
- if(sscanf(buf, "%" SCNx64",%" SCNx64,
- &b_info->iomem[i].start,
- &b_info->iomem[i].number)
- != 2) {
- fprintf(stderr,
- "xl: Invalid argument parsing iomem: %s\n", buf);
- exit(1);
+ libxl_iomem_range_init(&b_info->iomem[i]);
+ ret = sscanf(buf, "%" SCNx64",%" SCNx64"@%" SCNx64,
+ &b_info->iomem[i].start,
+ &b_info->iomem[i].number,
+ &b_info->iomem[i].gfn);
+ if (ret < 2) {
+ fprintf(stderr,
+ "xl: Invalid argument parsing iomem: %s\n", buf);
+ exit(1);
}
}
}
@@ -1284,6 +1459,84 @@ static void parse_config_data(const char *config_source,
}
}
+ if (!xlu_cfg_get_list (config, "channel", &channels, 0, 0)) {
+ d_config->num_channels = 0;
+ d_config->channels = NULL;
+ while ((buf = xlu_cfg_get_listitem (channels,
+ d_config->num_channels)) != NULL) {
+ libxl_device_channel *chn;
+ libxl_string_list pairs;
+ char *path = NULL;
+ int len;
+
+ chn = ARRAY_EXTEND_INIT(d_config->channels, d_config->num_channels,
+ libxl_device_channel_init);
+
+ split_string_into_string_list(buf, ",", &pairs);
+ len = libxl_string_list_length(&pairs);
+ for (i = 0; i < len; i++) {
+ char *key, *key_untrimmed, *value, *value_untrimmed;
+ int rc;
+ rc = split_string_into_pair(pairs[i], "=",
+ &key_untrimmed,
+ &value_untrimmed);
+ if (rc != 0) {
+ fprintf(stderr, "failed to parse channel configuration: %s",
+ pairs[i]);
+ exit(1);
+ }
+ trim(isspace, key_untrimmed, &key);
+ trim(isspace, value_untrimmed, &value);
+
+ if (!strcmp(key, "backend")) {
+ replace_string(&chn->backend_domname, value);
+ } else if (!strcmp(key, "name")) {
+ replace_string(&chn->name, value);
+ } else if (!strcmp(key, "path")) {
+ replace_string(&path, value);
+ } else if (!strcmp(key, "connection")) {
+ if (!strcmp(value, "pty")) {
+ chn->connection = LIBXL_CHANNEL_CONNECTION_PTY;
+ } else if (!strcmp(value, "socket")) {
+ chn->connection = LIBXL_CHANNEL_CONNECTION_SOCKET;
+ } else {
+ fprintf(stderr, "unknown channel connection '%s'\n",
+ value);
+ exit(1);
+ }
+ } else {
+ fprintf(stderr, "unknown channel parameter '%s',"
+ " ignoring\n", key);
+ }
+ free(key);
+ free(key_untrimmed);
+ free(value);
+ free(value_untrimmed);
+ }
+ switch (chn->connection) {
+ case LIBXL_CHANNEL_CONNECTION_UNKNOWN:
+ fprintf(stderr, "channel has unknown 'connection'\n");
+ exit(1);
+ case LIBXL_CHANNEL_CONNECTION_SOCKET:
+ if (!path) {
+ fprintf(stderr, "channel connection 'socket' requires path=..\n");
+ exit(1);
+ }
+ chn->u.socket.path = xstrdup(path);
+ break;
+ case LIBXL_CHANNEL_CONNECTION_PTY:
+ /* Nothing to do since PTY has no arguments */
+ break;
+ default:
+ fprintf(stderr, "unknown channel connection: %d",
+ chn->connection);
+ exit(1);
+ }
+ libxl_string_list_dispose(&pairs);
+ free(path);
+ }
+ }
+
if (!xlu_cfg_get_list (config, "vif", &nics, 0, 0)) {
d_config->num_nics = 0;
d_config->nics = NULL;
@@ -1296,26 +1549,7 @@ static void parse_config_data(const char *config_source,
nic = d_config->nics + d_config->num_nics;
libxl_device_nic_init(nic);
nic->devid = d_config->num_nics;
-
- if (default_vifscript) {
- free(nic->script);
- nic->script = strdup(default_vifscript);
- }
-
- if (default_bridge) {
- free(nic->bridge);
- nic->bridge = strdup(default_bridge);
- }
-
- if (default_gatewaydev) {
- free(nic->gatewaydev);
- nic->gatewaydev = strdup(default_gatewaydev);
- }
-
- if (default_vifbackend) {
- free(nic->backend_domname);
- nic->backend_domname = strdup(default_vifbackend);
- }
+ set_default_nic_values(nic);
p = strtok(buf2, ",");
if (!p)
@@ -1462,6 +1696,9 @@ skip_vfb:
if (!xlu_cfg_get_long (config, "pci_permissive", &l, 0))
pci_permissive = l;
+ if (!xlu_cfg_get_long (config, "pci_seize", &l, 0))
+ pci_seize = l;
+
/* To be reworked (automatically enabled) once the auto ballooning
* after guest starts is done (with PCI devices passed in). */
if (c_info->type == LIBXL_DOMAIN_TYPE_PV) {
@@ -1481,6 +1718,7 @@ skip_vfb:
pcidev->msitranslate = pci_msitranslate;
pcidev->power_mgmt = pci_power_mgmt;
pcidev->permissive = pci_permissive;
+ pcidev->seize = pci_seize;
if (!xlu_pci_parse_bdf(config, pcidev, buf))
d_config->num_pcidevs++;
}
@@ -1605,20 +1843,10 @@ skip_vfb:
&b_info->device_model_stubdomain, 0);
if (!xlu_cfg_get_string (config, "device_model_stubdomain_seclabel",
- &buf, 0)) {
- e = libxl_flask_context_to_sid(ctx, (char *)buf, strlen(buf),
- &b_info->device_model_ssidref);
- if (e) {
- if (errno == ENOSYS) {
- fprintf(stderr, "XSM Disabled:"
- " device_model_stubdomain_seclabel not supported\n");
- } else {
- fprintf(stderr, "Invalid device_model_stubdomain_seclabel:"
- " %s\n", buf);
- exit(1);
- }
- }
- }
+ &buf, 0))
+ xlu_cfg_replace_string(config, "device_model_stubdomain_seclabel",
+ &b_info->device_model_ssid_label, 0);
+
#define parse_extra_args(type) \
e = xlu_cfg_get_list_as_string_list(config, "device_model_args"#type, \
&b_info->extra##type, 0); \
@@ -1657,9 +1885,13 @@ skip_vfb:
libxl_device_vkb_init);
parse_top_level_vnc_options(config, &vfb->vnc);
+ parse_top_level_sdl_options(config, &vfb->sdl);
+ xlu_cfg_replace_string (config, "keymap", &vfb->keymap, 0);
}
- } else
+ } else {
parse_top_level_vnc_options(config, &b_info->u.hvm.vnc);
+ parse_top_level_sdl_options(config, &b_info->u.hvm.sdl);
+ }
if (c_info->type == LIBXL_DOMAIN_TYPE_HVM) {
if (!xlu_cfg_get_string (config, "vga", &buf, 0)) {
@@ -1667,6 +1899,8 @@ skip_vfb:
b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_STD;
} else if (!strcmp(buf, "cirrus")) {
b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
+ } else if (!strcmp(buf, "none")) {
+ b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_NONE;
} else {
fprintf(stderr, "Unknown vga \"%s\" specified\n", buf);
exit(1);
@@ -1676,8 +1910,6 @@ skip_vfb:
LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
xlu_cfg_replace_string (config, "keymap", &b_info->u.hvm.keymap, 0);
- xlu_cfg_get_defbool(config, "sdl", &b_info->u.hvm.sdl.enable, 0);
- xlu_cfg_get_defbool(config, "opengl", &b_info->u.hvm.sdl.opengl, 0);
xlu_cfg_get_defbool (config, "spice", &b_info->u.hvm.spice.enable, 0);
if (!xlu_cfg_get_long (config, "spiceport", &l, 0))
b_info->u.hvm.spice.port = l;
@@ -1698,9 +1930,26 @@ skip_vfb:
if (!xlu_cfg_get_long (config, "spiceusbredirection", &l, 0))
b_info->u.hvm.spice.usbredirection = l;
xlu_cfg_get_defbool(config, "nographic", &b_info->u.hvm.nographic, 0);
- xlu_cfg_get_defbool(config, "gfx_passthru",
+ xlu_cfg_get_defbool(config, "gfx_passthru",
&b_info->u.hvm.gfx_passthru, 0);
- xlu_cfg_replace_string (config, "serial", &b_info->u.hvm.serial, 0);
+ switch (xlu_cfg_get_list_as_string_list(config, "serial",
+ &b_info->u.hvm.serial_list,
+ 1))
+ {
+
+ case 0: break; /* Success */
+ case ESRCH: break; /* Option not present */
+ case EINVAL:
+ /* If it's not a valid list, try reading it as an atom,
+ * falling through to an error if it fails */
+ if (!xlu_cfg_replace_string(config, "serial",
+ &b_info->u.hvm.serial, 0))
+ break;
+ /* FALLTHRU */
+ default:
+ fprintf(stderr,"xl: Unable to parse serial.\n");
+ exit(-ERROR_FAIL);
+ }
xlu_cfg_replace_string (config, "boot", &b_info->u.hvm.boot, 0);
xlu_cfg_get_defbool(config, "usb", &b_info->u.hvm.usb, 0);
if (!xlu_cfg_get_long (config, "usbversion", &l, 0))
@@ -1756,21 +2005,41 @@ skip_vfb:
}
static void reload_domain_config(uint32_t domid,
- uint8_t **config_data, int *config_len)
+ libxl_domain_config *d_config)
{
+ int rc;
uint8_t *t_data;
int ret, t_len;
+ libxl_domain_config d_config_new;
+ /* In case user has used "config-update" to store a new config
+ * file.
+ */
ret = libxl_userdata_retrieve(ctx, domid, "xl", &t_data, &t_len);
- if (ret) {
- LOG("failed to retrieve guest configuration (rc=%d). "
- "reusing old configuration", ret);
+ if (ret && errno != ENOENT) {
+ LOG("\"xl\" configuration found but failed to load\n");
+ }
+ if (t_len > 0) {
+ LOG("\"xl\" configuration found, using it\n");
+ libxl_domain_config_dispose(d_config);
+ parse_config_data("<updated>", (const char *)t_data,
+ t_len, d_config);
+ free(t_data);
+ libxl_userdata_unlink(ctx, domid, "xl");
return;
}
- free(*config_data);
- *config_data = t_data;
- *config_len = t_len;
+ libxl_domain_config_init(&d_config_new);
+ rc = libxl_retrieve_domain_configuration(ctx, domid, &d_config_new);
+ if (rc) {
+ LOG("failed to retrieve guest configuration (rc=%d). "
+ "reusing old configuration", rc);
+ libxl_domain_config_dispose(&d_config_new);
+ } else {
+ libxl_domain_config_dispose(d_config);
+ /* Steal allocations */
+ memcpy(d_config, &d_config_new, sizeof(libxl_domain_config));
+ }
}
/* Returns 1 if domain should be restarted,
@@ -1778,7 +2047,6 @@ static void reload_domain_config(uint32_t domid,
* Can update r_domid if domain is destroyed etc */
static int handle_domain_death(uint32_t *r_domid,
libxl_event *event,
- uint8_t **config_data, int *config_len,
libxl_domain_config *d_config)
{
@@ -1836,13 +2104,12 @@ static int handle_domain_death(uint32_t *r_domid,
break;
case LIBXL_ACTION_ON_SHUTDOWN_RESTART_RENAME:
- reload_domain_config(*r_domid, config_data, config_len);
+ reload_domain_config(*r_domid, d_config);
restart = 2;
break;
case LIBXL_ACTION_ON_SHUTDOWN_RESTART:
- reload_domain_config(*r_domid, config_data, config_len);
-
+ reload_domain_config(*r_domid, d_config);
restart = 1;
/* fall-through */
case LIBXL_ACTION_ON_SHUTDOWN_DESTROY:
@@ -1872,13 +2139,6 @@ static int match_option_size(const char *prefix, size_t len,
#define MATCH_OPTION(prefix, arg, oparg) \
match_option_size((prefix "="), sizeof((prefix)), (arg), &(oparg))
-static void replace_string(char **str, const char *val)
-{
- free(*str);
- *str = strdup(val);
-}
-
-
/* Preserve a copy of a domain under a new name. Updates *r_domid */
static int preserve_domain(uint32_t *r_domid, libxl_event *event,
libxl_domain_config *d_config)
@@ -1966,19 +2226,6 @@ static int freemem(uint32_t domid, libxl_domain_build_info *b_info)
return ERROR_NOMEM;
}
-static void console_child_report(void)
-{
- if (xl_child_pid(child_console)) {
- int status;
- pid_t got = xl_waitpid(child_console, &status, 0);
- if (got < 0)
- perror("xl: warning, failed to waitpid for console child");
- else if (status)
- libxl_report_child_exitstatus(ctx, XTL_ERROR, "console child",
- xl_child_pid(child_console), status);
- }
-}
-
static void autoconnect_console(libxl_ctx *ctx_ignored,
libxl_event *ev, void *priv)
{
@@ -1986,13 +2233,10 @@ static void autoconnect_console(libxl_ctx *ctx_ignored,
libxl_event_free(ctx, ev);
- console_child_report();
+ console_child_report(child_console);
- pid_t pid = xl_fork(child_console);
- if (pid < 0) {
- perror("unable to fork xenconsole");
- return;
- } else if (pid > 0)
+ pid_t pid = xl_fork(child_console, "console child");
+ if (pid)
return;
postfork();
@@ -2000,7 +2244,7 @@ static void autoconnect_console(libxl_ctx *ctx_ignored,
sleep(1);
libxl_primary_console_exec(ctx, bldomid);
/* Do not return. xl continued in child process */
- fprintf(stderr, "Unable to attach console\n");
+ perror("xl: unable to exec console client");
_exit(1);
}
@@ -2055,6 +2299,7 @@ static uint32_t create_domain(struct domain_create *dom_info)
const char *config_source = NULL;
const char *restore_source = NULL;
int migrate_fd = dom_info->migrate_fd;
+ bool config_in_json;
int i;
int need_daemon = daemonize;
@@ -2109,7 +2354,7 @@ static uint32_t create_domain(struct domain_create *dom_info)
restore_source, hdr.mandatory_flags, hdr.optional_flags,
hdr.optional_data_len);
- badflags = hdr.mandatory_flags & ~( 0 /* none understood yet */ );
+ badflags = hdr.mandatory_flags & ~XL_MANDATORY_FLAG_ALL;
if (badflags) {
fprintf(stderr, "Savefile has mandatory flag(s) 0x%"PRIx32" "
"which are not supported; need newer xl\n",
@@ -2137,7 +2382,9 @@ static uint32_t create_domain(struct domain_create *dom_info)
optdata_here = optdata_begin;
if (OPTDATA_LEFT) {
- fprintf(stderr, " Savefile contains xl domain config\n");
+ fprintf(stderr, " Savefile contains xl domain config%s\n",
+ !!(hdr.mandatory_flags & XL_MANDATORY_FLAG_JSON)
+ ? " in JSON format" : "");
WITH_OPTDATA(4, {
memcpy(u32buf.b, optdata_here, 4);
config_len = u32buf.u32;
@@ -2177,6 +2424,7 @@ static uint32_t create_domain(struct domain_create *dom_info)
extra_config);
}
config_source=config_file;
+ config_in_json = false;
} else {
if (!config_data) {
fprintf(stderr, "Config file not specified and"
@@ -2184,12 +2432,18 @@ static uint32_t create_domain(struct domain_create *dom_info)
return ERROR_INVAL;
}
config_source = "<saved>";
+ config_in_json = !!(hdr.mandatory_flags & XL_MANDATORY_FLAG_JSON);
}
if (!dom_info->quiet)
printf("Parsing config from %s\n", config_source);
- parse_config_data(config_source, config_data, config_len, &d_config, dom_info);
+ if (config_in_json) {
+ libxl_domain_config_from_json(ctx, &d_config,
+ (const char *)config_data);
+ } else {
+ parse_config_data(config_source, config_data, config_len, &d_config);
+ }
if (migrate_fd >= 0) {
if (d_config.c_info.name) {
@@ -2240,11 +2494,17 @@ start:
if ( restoring ) {
libxl_domain_restore_params params;
+
+ libxl_domain_restore_params_init(¶ms);
+
params.checkpointed_stream = dom_info->checkpointed_stream;
ret = libxl_domain_create_restore(ctx, &d_config,
&domid, restore_fd,
¶ms,
0, autoconnect_console_how);
+
+ libxl_domain_restore_params_dispose(¶ms);
+
/*
* On subsequent reboot etc we should create the domain, not
* restore/migrate-receive it again.
@@ -2257,41 +2517,6 @@ start:
if ( ret )
goto error_out;
- /* If single vcpu to pcpu mapping was requested, honour it */
- if (vcpu_to_pcpu) {
- libxl_bitmap vcpu_cpumap;
-
- ret = libxl_cpu_bitmap_alloc(ctx, &vcpu_cpumap, 0);
- if (ret)
- goto error_out;
- for (i = 0; i < d_config.b_info.max_vcpus; i++) {
-
- if (vcpu_to_pcpu[i] != -1) {
- libxl_bitmap_set_none(&vcpu_cpumap);
- libxl_bitmap_set(&vcpu_cpumap, vcpu_to_pcpu[i]);
- } else {
- libxl_bitmap_set_any(&vcpu_cpumap);
- }
- if (libxl_set_vcpuaffinity(ctx, domid, i, &vcpu_cpumap)) {
- fprintf(stderr, "setting affinity failed on vcpu `%d'.\n", i);
- libxl_bitmap_dispose(&vcpu_cpumap);
- free(vcpu_to_pcpu);
- ret = ERROR_FAIL;
- goto error_out;
- }
- }
- libxl_bitmap_dispose(&vcpu_cpumap);
- free(vcpu_to_pcpu); vcpu_to_pcpu = NULL;
- }
-
- ret = libxl_userdata_store(ctx, domid, "xl",
- config_data, config_len);
- if (ret) {
- perror("cannot save config file");
- ret = ERROR_FAIL;
- goto error_out;
- }
-
release_lock();
if (!paused)
@@ -2348,9 +2573,7 @@ start:
LOG("Domain %d has shut down, reason code %d 0x%x", domid,
event->u.domain_shutdown.shutdown_reason,
event->u.domain_shutdown.shutdown_reason);
- switch (handle_domain_death(&domid, event,
- (uint8_t **)&config_data, &config_len,
- &d_config)) {
+ switch (handle_domain_death(&domid, event, &d_config)) {
case 2:
if (!preserve_domain(&domid, event, &d_config)) {
/* If we fail then exit leaving the old domain in place. */
@@ -2387,12 +2610,6 @@ start:
d_config.c_info.name = strdup(common_domname);
}
- /* Reparse the configuration in case it has changed */
- libxl_domain_config_dispose(&d_config);
- libxl_domain_config_init(&d_config);
- parse_config_data(config_source, config_data, config_len,
- &d_config, dom_info);
-
/*
* XXX FIXME: If this sleep is not there then domain
* re-creation fails sometimes.
@@ -2447,7 +2664,7 @@ out:
free(config_data);
- console_child_report();
+ console_child_report(child_console);
if (deathw)
libxl_evdisable_domain_death(ctx, deathw);
@@ -3056,12 +3273,14 @@ static void unpause_domain(uint32_t domid)
libxl_domain_unpause(ctx, domid);
}
-static void destroy_domain(uint32_t domid)
+static void destroy_domain(uint32_t domid, int force)
{
int rc;
- if (domid == 0) {
- fprintf(stderr, "Cannot destroy privileged domain 0.\n\n");
+ if (domid == 0 && !force) {
+ fprintf(stderr, "Not destroying domain 0; use -f to force.\n"
+ "This can only be done when using a disaggregated "
+ "hardware domain and toolstack.\n\n");
exit(-1);
}
rc = libxl_domain_destroy(ctx, domid, 0);
@@ -3169,9 +3388,7 @@ static void list_domains_details(const libxl_dominfo *info, int nb_domain)
{
libxl_domain_config d_config;
- char *config_source;
- uint8_t *data;
- int i, len, rc;
+ int i, rc;
yajl_gen hand = NULL;
yajl_gen_status s;
@@ -3192,22 +3409,15 @@ static void list_domains_details(const libxl_dominfo *info, int nb_domain)
s = yajl_gen_status_ok;
for (i = 0; i < nb_domain; i++) {
- /* no detailed info available on dom0 */
- if (info[i].domid == 0)
- continue;
- rc = libxl_userdata_retrieve(ctx, info[i].domid, "xl", &data, &len);
+ libxl_domain_config_init(&d_config);
+ rc = libxl_retrieve_domain_configuration(ctx, info[i].domid, &d_config);
if (rc)
continue;
- CHK_SYSCALL(asprintf(&config_source, "<domid %d data>", info[i].domid));
- libxl_domain_config_init(&d_config);
- parse_config_data(config_source, (char *)data, len, &d_config, NULL);
if (default_output_format == OUTPUT_FORMAT_JSON)
s = printf_info_one_json(hand, info[i].domid, &d_config);
else
printf_info_sexp(info[i].domid, &d_config);
libxl_domain_config_dispose(&d_config);
- free(data);
- free(config_source);
if (s != yajl_gen_status_ok)
goto out;
}
@@ -3340,15 +3550,8 @@ static void list_domains(int verbose, int context, int claim, int numa,
}
if (claim)
printf(" %5lu", (unsigned long)info[i].outstanding_memkb / 1024);
- if (verbose || context) {
- int rc;
- size_t size;
- char *buf = NULL;
- rc = libxl_flask_sid_to_context(ctx, info[i].ssidref, &buf,
- &size);
- printf(" %16s", rc < 0 ? "-" : buf);
- free(buf);
- }
+ if (verbose || context)
+ printf(" %16s", info[i].ssid_label ? : "-");
if (numa) {
libxl_domain_get_nodeaffinity(ctx, info[i].domid, &nodemap);
@@ -3399,22 +3602,41 @@ static void save_domain_core_begin(uint32_t domid,
int *config_len_r)
{
int rc;
+ libxl_domain_config d_config;
+ char *config_c = 0;
/* configuration file in optional data: */
+ libxl_domain_config_init(&d_config);
+
if (override_config_file) {
void *config_v = 0;
rc = libxl_read_file_contents(ctx, override_config_file,
&config_v, config_len_r);
- *config_data_r = config_v;
+ if (rc) {
+ fprintf(stderr, "unable to read overridden config file\n");
+ exit(2);
+ }
+ parse_config_data(override_config_file, config_v, *config_len_r,
+ &d_config);
+ free(config_v);
} else {
- rc = libxl_userdata_retrieve(ctx, domid, "xl",
- config_data_r, config_len_r);
+ rc = libxl_retrieve_domain_configuration(ctx, domid, &d_config);
+ if (rc) {
+ fprintf(stderr, "unable to retrieve domain configuration\n");
+ exit(2);
+ }
}
- if (rc) {
- fputs("Unable to get config file\n",stderr);
+
+ config_c = libxl_domain_config_to_json(ctx, &d_config);
+ if (!config_c) {
+ fprintf(stderr, "unable to convert config file to JSON\n");
exit(2);
}
+ *config_data_r = (uint8_t *)config_c;
+ *config_len_r = strlen(config_c) + 1; /* including trailing '\0' */
+
+ libxl_domain_config_dispose(&d_config);
}
static void save_domain_core_writeconfig(int fd, const char *source,
@@ -3442,6 +3664,8 @@ static void save_domain_core_writeconfig(int fd, const char *source,
u32buf.u32 = config_len;
ADD_OPTDATA(u32buf.b, 4);
ADD_OPTDATA(config_data, config_len);
+ if (config_len)
+ hdr.mandatory_flags |= XL_MANDATORY_FLAG_JSON;
/* that's the optional data */
@@ -3511,7 +3735,7 @@ static pid_t create_migration_child(const char *rune, int *send_fd,
MUST( libxl_pipe(ctx, sendpipe) );
MUST( libxl_pipe(ctx, recvpipe) );
- child = xl_fork(child_migration);
+ child = xl_fork(child_migration, "migration transport process");
if (!child) {
dup2(sendpipe[0], 0);
@@ -3572,9 +3796,8 @@ static void migration_child_report(int recv_fd) {
if (child == migration_child) {
if (status)
- libxl_report_child_exitstatus(ctx, XTL_INFO,
- "migration target process",
- migration_child, status);
+ xl_report_child_exitstatus(XTL_INFO, child_migration,
+ migration_child, status);
break;
}
if (child == -1) {
@@ -4090,11 +4313,26 @@ int main_migrate(int argc, char **argv)
domid = find_domain(argv[optind]);
host = argv[optind + 1];
+ bool pass_tty_arg = progress_use_cr || (isatty(2) > 0);
+
if (!ssh_command[0]) {
rune= host;
} else {
- if (asprintf(&rune, "exec %s %s xl migrate-receive%s%s",
+ char verbose_buf[minmsglevel_default+3];
+ int verbose_len;
+ verbose_buf[0] = ' ';
+ verbose_buf[1] = '-';
+ memset(verbose_buf+2, 'v', minmsglevel_default);
+ verbose_buf[sizeof(verbose_buf)-1] = 0;
+ if (minmsglevel == minmsglevel_default) {
+ verbose_len = 0;
+ } else {
+ verbose_len = (minmsglevel_default - minmsglevel) + 2;
+ }
+ if (asprintf(&rune, "exec %s %s xl%s%.*s migrate-receive%s%s",
ssh_command, host,
+ pass_tty_arg ? " -t" : "",
+ verbose_len, verbose_buf,
daemonize ? "" : " -e",
debug ? " -d" : "") < 0)
return 1;
@@ -4146,12 +4384,15 @@ int main_unpause(int argc, char **argv)
int main_destroy(int argc, char **argv)
{
int opt;
+ int force = 0;
- SWITCH_FOREACH_OPT(opt, "", NULL, "destroy", 1) {
- /* No options */
+ SWITCH_FOREACH_OPT(opt, "f", NULL, "destroy", 1) {
+ case 'f':
+ force = 1;
+ break;
}
- destroy_domain(find_domain(argv[optind]));
+ destroy_domain(find_domain(argv[optind]), force);
return 0;
}
@@ -4434,6 +4675,9 @@ int main_config_update(int argc, char **argv)
exit(1);
}
+ fprintf(stderr, "WARNING: xl now has better capability to manage domain configuration, "
+ "avoid using this command when possible\n");
+
domid = find_domain(argv[1]);
argc--; argv++;
@@ -4491,7 +4735,7 @@ int main_config_update(int argc, char **argv)
libxl_domain_config_init(&d_config);
- parse_config_data(filename, config_data, config_len, &d_config, NULL);
+ parse_config_data(filename, config_data, config_len, &d_config);
if (debug || dryrun_only)
printf_info(default_output_format, -1, &d_config);
@@ -4568,8 +4812,10 @@ static void print_vcpuinfo(uint32_t tdomid,
}
/* TIM */
printf("%9.1f ", ((float)vcpuinfo->vcpu_time / 1e9));
- /* CPU AFFINITY */
+ /* CPU HARD AND SOFT AFFINITY */
print_bitmap(vcpuinfo->cpumap.map, nr_cpus, stdout);
+ printf(" / ");
+ print_bitmap(vcpuinfo->cpumap_soft.map, nr_cpus, stdout);
printf("\n");
}
@@ -4580,10 +4826,8 @@ static void print_domain_vcpuinfo(uint32_t domid, uint32_t nr_cpus)
vcpuinfo = libxl_list_vcpu(ctx, domid, &nb_vcpu, &nrcpus);
- if (!vcpuinfo) {
- fprintf(stderr, "libxl_list_vcpu failed.\n");
+ if (!vcpuinfo)
return;
- }
for (i = 0; i < nb_vcpu; i++) {
print_vcpuinfo(domid, &vcpuinfo[i], nr_cpus);
@@ -4604,7 +4848,8 @@ static void vcpulist(int argc, char **argv)
}
printf("%-32s %5s %5s %5s %5s %9s %s\n",
- "Name", "ID", "VCPU", "CPU", "State", "Time(s)", "CPU Affinity");
+ "Name", "ID", "VCPU", "CPU", "State", "Time(s)",
+ "Affinity (Hard / Soft)");
if (!argc) {
if (!(dominfo = libxl_list_domain(ctx, &nb_domain))) {
fprintf(stderr, "libxl_list_domain failed.\n");
@@ -4637,30 +4882,72 @@ int main_vcpulist(int argc, char **argv)
return 0;
}
-static int vcpupin(uint32_t domid, const char *vcpu, char *cpu)
+int main_vcpupin(int argc, char **argv)
{
libxl_vcpuinfo *vcpuinfo;
- libxl_bitmap cpumap;
-
- uint32_t vcpuid;
+ libxl_bitmap cpumap_hard, cpumap_soft;;
+ libxl_bitmap *soft = &cpumap_soft, *hard = &cpumap_hard;
+ uint32_t domid;
+ /*
+ * int would be enough for vcpuid, but we don't want to
+ * mess aroung range checking the return value of strtol().
+ */
+ long vcpuid;
+ const char *vcpu, *hard_str, *soft_str;
char *endptr;
- int i, nb_cpu, nb_vcpu, rc = -1;
+ int opt, nb_cpu, nb_vcpu, rc = -1;
+
+ libxl_bitmap_init(&cpumap_hard);
+ libxl_bitmap_init(&cpumap_soft);
+
+ SWITCH_FOREACH_OPT(opt, "", NULL, "vcpu-pin", 3) {
+ /* No options */
+ }
- libxl_bitmap_init(&cpumap);
+ domid = find_domain(argv[optind]);
+ vcpu = argv[optind+1];
+ hard_str = argv[optind+2];
+ soft_str = (argc > optind+3) ? argv[optind+3] : NULL;
- vcpuid = strtoul(vcpu, &endptr, 10);
- if (vcpu == endptr) {
+ /* Figure out with which vCPU we are dealing with */
+ vcpuid = strtol(vcpu, &endptr, 10);
+ if (vcpu == endptr || vcpuid < 0) {
if (strcmp(vcpu, "all")) {
- fprintf(stderr, "Error: Invalid argument.\n");
+ fprintf(stderr, "Error: Invalid argument %s as VCPU.\n", vcpu);
goto out;
}
vcpuid = -1;
}
- if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0))
+ if (libxl_cpu_bitmap_alloc(ctx, &cpumap_hard, 0) ||
+ libxl_cpu_bitmap_alloc(ctx, &cpumap_soft, 0))
goto out;
- if (vcpupin_parse(cpu, &cpumap))
+ /*
+ * Syntax is: xl vcpu-pin <domid> <vcpu> <hard> <soft>
+ * We want to handle all the following cases ('-' means
+ * "leave it alone"):
+ * xl vcpu-pin 0 3 3,4
+ * xl vcpu-pin 0 3 3,4 -
+ * xl vcpu-pin 0 3 - 6-9
+ * xl vcpu-pin 0 3 3,4 6-9
+ */
+
+ /*
+ * Hard affinity is always present. However, if it's "-", all we need
+ * is passing a NULL pointer to the libxl_set_vcpuaffinity() call below.
+ */
+ if (!strcmp(hard_str, "-"))
+ hard = NULL;
+ else if (vcpupin_parse(hard_str, hard))
+ goto out;
+ /*
+ * Soft affinity is handled similarly. Only difference: we also want
+ * to pass NULL to libxl_set_vcpuaffinity() if it is not specified.
+ */
+ if (argc <= optind+3 || !strcmp(soft_str, "-"))
+ soft = NULL;
+ else if (vcpupin_parse(soft_str, soft))
goto out;
if (dryrun_only) {
@@ -4671,7 +4958,14 @@ static int vcpupin(uint32_t domid, const char *vcpu, char *cpu)
}
fprintf(stdout, "cpumap: ");
- print_bitmap(cpumap.map, nb_cpu, stdout);
+ if (hard)
+ print_bitmap(hard->map, nb_cpu, stdout);
+ else
+ fprintf(stdout, "-");
+ if (soft) {
+ fprintf(stdout, " ");
+ print_bitmap(soft->map, nb_cpu, stdout);
+ }
fprintf(stdout, "\n");
if (ferror(stdout) || fflush(stdout)) {
@@ -4684,43 +4978,28 @@ static int vcpupin(uint32_t domid, const char *vcpu, char *cpu)
}
if (vcpuid != -1) {
- if (libxl_set_vcpuaffinity(ctx, domid, vcpuid, &cpumap) == -1) {
- fprintf(stderr, "Could not set affinity for vcpu `%u'.\n", vcpuid);
+ if (libxl_set_vcpuaffinity(ctx, domid, vcpuid, hard, soft)) {
+ fprintf(stderr, "Could not set affinity for vcpu `%ld'.\n",
+ vcpuid);
goto out;
}
- }
- else {
- if (!(vcpuinfo = libxl_list_vcpu(ctx, domid, &nb_vcpu, &i))) {
+ } else {
+ if (!(vcpuinfo = libxl_list_vcpu(ctx, domid, &nb_vcpu, &nb_cpu))) {
fprintf(stderr, "libxl_list_vcpu failed.\n");
goto out;
}
- for (i = 0; i < nb_vcpu; i++) {
- if (libxl_set_vcpuaffinity(ctx, domid, vcpuinfo[i].vcpuid,
- &cpumap) == -1) {
- fprintf(stderr, "libxl_set_vcpuaffinity failed"
- " on vcpu `%u'.\n", vcpuinfo[i].vcpuid);
- }
- }
+ if (libxl_set_vcpuaffinity_all(ctx, domid, nb_vcpu, hard, soft))
+ fprintf(stderr, "Could not set affinity.\n");
libxl_vcpuinfo_list_free(vcpuinfo, nb_vcpu);
}
rc = 0;
out:
- libxl_bitmap_dispose(&cpumap);
+ libxl_bitmap_dispose(&cpumap_soft);
+ libxl_bitmap_dispose(&cpumap_hard);
return rc;
}
-int main_vcpupin(int argc, char **argv)
-{
- int opt;
-
- SWITCH_FOREACH_OPT(opt, "", NULL, "vcpu-pin", 3) {
- /* No options */
- }
-
- return vcpupin(find_domain(argv[optind]), argv[optind+1] , argv[optind+2]);
-}
-
static void vcpuset(uint32_t domid, const char* nr_vcpus, int check_host)
{
char *endptr;
@@ -5186,6 +5465,47 @@ static int sched_sedf_domain_output(
return 0;
}
+static int sched_rtds_domain_output(
+ int domid)
+{
+ char *domname;
+ libxl_domain_sched_params scinfo;
+ int rc = 0;
+
+ if (domid < 0) {
+ printf("%-33s %4s %9s %9s\n", "Name", "ID", "Period", "Budget");
+ return 0;
+ }
+
+ libxl_domain_sched_params_init(&scinfo);
+ rc = sched_domain_get(LIBXL_SCHEDULER_RTDS, domid, &scinfo);
+ if (rc)
+ goto out;
+
+ domname = libxl_domid_to_name(ctx, domid);
+ printf("%-33s %4d %9d %9d\n",
+ domname,
+ domid,
+ scinfo.period,
+ scinfo.budget);
+ free(domname);
+
+out:
+ libxl_domain_sched_params_dispose(&scinfo);
+ return rc;
+}
+
+static int sched_rtds_pool_output(uint32_t poolid)
+{
+ char *poolname;
+
+ poolname = libxl_cpupoolid_to_name(ctx, poolid);
+ printf("Cpupool %s: sched=RTDS\n", poolname);
+
+ free(poolname);
+ return 0;
+}
+
static int sched_default_pool_output(uint32_t poolid)
{
char *poolname;
@@ -5207,7 +5527,7 @@ static int sched_domain_output(libxl_scheduler sched, int (*output)(int),
int rc = 0;
if (cpupool) {
- if (cpupool_qualifier_to_cpupoolid(cpupool, &poolid, NULL) ||
+ if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL) ||
!libxl_cpupoolid_is_valid(ctx, poolid)) {
fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
return -ERROR_FAIL;
@@ -5327,7 +5647,8 @@ int main_sched_credit(int argc, char **argv)
uint32_t poolid = 0;
if (cpupool) {
- if (cpupool_qualifier_to_cpupoolid(cpupool, &poolid, NULL) ||
+ if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
+ &poolid, NULL) ||
!libxl_cpupoolid_is_valid(ctx, poolid)) {
fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
return -ERROR_FAIL;
@@ -5552,6 +5873,87 @@ int main_sched_sedf(int argc, char **argv)
return 0;
}
+/*
+ * <nothing> : List all domain paramters and sched params
+ * -d [domid] : List domain params for domain
+ * -d [domid] [params] : Set domain params for domain
+ */
+int main_sched_rtds(int argc, char **argv)
+{
+ const char *dom = NULL;
+ const char *cpupool = NULL;
+ int period = 0; /* period is in microsecond */
+ int budget = 0; /* budget is in microsecond */
+ bool opt_p = false;
+ bool opt_b = false;
+ int opt, rc;
+ static struct option opts[] = {
+ {"domain", 1, 0, 'd'},
+ {"period", 1, 0, 'p'},
+ {"budget", 1, 0, 'b'},
+ {"cpupool", 1, 0, 'c'},
+ COMMON_LONG_OPTS,
+ {0, 0, 0, 0}
+ };
+
+ SWITCH_FOREACH_OPT(opt, "d:p:b:c:h", opts, "sched-rtds", 0) {
+ case 'd':
+ dom = optarg;
+ break;
+ case 'p':
+ period = strtol(optarg, NULL, 10);
+ opt_p = 1;
+ break;
+ case 'b':
+ budget = strtol(optarg, NULL, 10);
+ opt_b = 1;
+ break;
+ case 'c':
+ cpupool = optarg;
+ break;
+ }
+
+ if (cpupool && (dom || opt_p || opt_b)) {
+ fprintf(stderr, "Specifying a cpupool is not allowed with "
+ "other options.\n");
+ return 1;
+ }
+ if (!dom && (opt_p || opt_b)) {
+ fprintf(stderr, "Must specify a domain.\n");
+ return 1;
+ }
+ if (opt_p != opt_b) {
+ fprintf(stderr, "Must specify period and budget\n");
+ return 1;
+ }
+
+ if (!dom) { /* list all domain's rt scheduler info */
+ return -sched_domain_output(LIBXL_SCHEDULER_RTDS,
+ sched_rtds_domain_output,
+ sched_rtds_pool_output,
+ cpupool);
+ } else {
+ uint32_t domid = find_domain(dom);
+ if (!opt_p && !opt_b) { /* output rt scheduler info */
+ sched_rtds_domain_output(-1);
+ return -sched_rtds_domain_output(domid);
+ } else { /* set rt scheduler paramaters */
+ libxl_domain_sched_params scinfo;
+ libxl_domain_sched_params_init(&scinfo);
+ scinfo.sched = LIBXL_SCHEDULER_RTDS;
+ scinfo.period = period;
+ scinfo.budget = budget;
+
+ rc = sched_domain_set(domid, &scinfo);
+ libxl_domain_sched_params_dispose(&scinfo);
+ if (rc)
+ return -rc;
+ }
+ }
+
+ return 0;
+}
+
int main_domid(int argc, char **argv)
{
uint32_t domid;
@@ -5770,6 +6172,8 @@ int main_networkattach(int argc, char **argv)
}
libxl_device_nic_init(&nic);
+ set_default_nic_values(&nic);
+
for (argv += optind+1, argc -= optind+1; argc > 0; ++argv, --argc) {
if (MATCH_OPTION("type", *argv, oparg)) {
if (!strcmp("vif", oparg)) {
@@ -5905,6 +6309,50 @@ int main_networkdetach(int argc, char **argv)
return 0;
}
+int main_channellist(int argc, char **argv)
+{
+ int opt;
+ libxl_device_channel *channels;
+ libxl_channelinfo channelinfo;
+ int nb, i;
+
+ SWITCH_FOREACH_OPT(opt, "", NULL, "channel-list", 1) {
+ /* No options */
+ }
+
+ /* Idx BE state evt-ch ring-ref connection params*/
+ printf("%-3s %-2s %-5s %-6s %8s %-10s %-30s\n",
+ "Idx", "BE", "state", "evt-ch", "ring-ref", "connection", "");
+ for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+ uint32_t domid = find_domain(*argv);
+ channels = libxl_device_channel_list(ctx, domid, &nb);
+ if (!channels)
+ continue;
+ for (i = 0; i < nb; ++i) {
+ if (!libxl_device_channel_getinfo(ctx, domid, &channels[i],
+ &channelinfo)) {
+ printf("%-3d %-2d ", channels[i].devid, channelinfo.backend_id);
+ printf("%-5d ", channelinfo.state);
+ printf("%-6d %-8d ", channelinfo.evtch, channelinfo.rref);
+ printf("%-10s ", libxl_channel_connection_to_string(
+ channels[i].connection));
+ switch (channels[i].connection) {
+ case LIBXL_CHANNEL_CONNECTION_PTY:
+ printf("%-30s ", channelinfo.u.pty.path);
+ break;
+ default:
+ break;
+ }
+ printf("\n");
+ libxl_channelinfo_dispose(&channelinfo);
+ }
+ libxl_device_channel_dispose(&channels[i]);
+ }
+ free(channels);
+ }
+ return 0;
+}
+
int main_blockattach(int argc, char **argv)
{
int opt;
@@ -5935,6 +6383,7 @@ int main_blockattach(int argc, char **argv)
if (libxl_device_disk_add(ctx, fe_domid, &disk, 0)) {
fprintf(stderr, "libxl_device_disk_add failed.\n");
+ return 1;
}
return 0;
}
@@ -5996,6 +6445,7 @@ int main_blockdetach(int argc, char **argv)
rc = libxl_device_disk_remove(ctx, domid, &disk, 0);
if (rc) {
fprintf(stderr, "libxl_device_disk_remove failed.\n");
+ return 1;
}
libxl_device_disk_dispose(&disk);
return rc;
@@ -6544,7 +6994,7 @@ int main_tmem_freeable(int argc, char **argv)
int opt;
int mb;
- SWITCH_FOREACH_OPT(opt, "", NULL, "tmem-freeale", 0) {
+ SWITCH_FOREACH_OPT(opt, "", NULL, "tmem-freeable", 0) {
/* No options */
}
@@ -6795,27 +7245,21 @@ int main_cpupoollist(int argc, char **argv)
for (p = 0; p < n_pools; p++) {
if (!ret && (!pool || (poolinfo[p].poolid == poolid))) {
- name = libxl_cpupoolid_to_name(ctx, poolinfo[p].poolid);
- if (!name) {
- fprintf(stderr, "error getting cpupool info\n");
- ret = -ERROR_NOMEM;
- } else {
- printf("%-19s", name);
- free(name);
- n = 0;
- libxl_for_each_bit(c, poolinfo[p].cpumap)
- if (libxl_bitmap_test(&poolinfo[p].cpumap, c)) {
- if (n && opt_cpus) printf(",");
- if (opt_cpus) printf("%d", c);
- n++;
- }
- if (!opt_cpus) {
- printf("%3d %9s y %4d", n,
- libxl_scheduler_to_string(poolinfo[p].sched),
- poolinfo[p].n_dom);
+ name = poolinfo[p].pool_name;
+ printf("%-19s", name);
+ n = 0;
+ libxl_for_each_bit(c, poolinfo[p].cpumap)
+ if (libxl_bitmap_test(&poolinfo[p].cpumap, c)) {
+ if (n && opt_cpus) printf(",");
+ if (opt_cpus) printf("%d", c);
+ n++;
}
- printf("\n");
+ if (!opt_cpus) {
+ printf("%3d %9s y %4d", n,
+ libxl_scheduler_to_string(poolinfo[p].sched),
+ poolinfo[p].n_dom);
}
+ printf("\n");
}
}
@@ -6836,7 +7280,7 @@ int main_cpupooldestroy(int argc, char **argv)
pool = argv[optind];
- if (cpupool_qualifier_to_cpupoolid(pool, &poolid, NULL) ||
+ if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
!libxl_cpupoolid_is_valid(ctx, poolid)) {
fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
return -ERROR_FAIL;
@@ -6858,7 +7302,7 @@ int main_cpupoolrename(int argc, char **argv)
pool = argv[optind++];
- if (cpupool_qualifier_to_cpupoolid(pool, &poolid, NULL) ||
+ if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
!libxl_cpupoolid_is_valid(ctx, poolid)) {
fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
return -ERROR_FAIL;
@@ -6896,7 +7340,7 @@ int main_cpupoolcpuadd(int argc, char **argv)
cpu = atoi(argv[optind]);
}
- if (cpupool_qualifier_to_cpupoolid(pool, &poolid, NULL) ||
+ if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
!libxl_cpupoolid_is_valid(ctx, poolid)) {
fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
return -ERROR_FAIL;
@@ -6941,7 +7385,7 @@ int main_cpupoolcpuremove(int argc, char **argv)
cpu = atoi(argv[optind]);
}
- if (cpupool_qualifier_to_cpupoolid(pool, &poolid, NULL) ||
+ if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
!libxl_cpupoolid_is_valid(ctx, poolid)) {
fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
return -ERROR_FAIL;
@@ -6985,7 +7429,7 @@ int main_cpupoolmigrate(int argc, char **argv)
return -ERROR_FAIL;
}
- if (cpupool_qualifier_to_cpupoolid(pool, &poolid, NULL) ||
+ if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
!libxl_cpupoolid_is_valid(ctx, poolid)) {
fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
return -ERROR_FAIL;
@@ -7266,18 +7710,29 @@ int main_remus(int argc, char **argv)
memset(&r_info, 0, sizeof(libxl_domain_remus_info));
/* Defaults */
r_info.interval = 200;
- r_info.blackhole = 0;
- r_info.compression = 1;
+ libxl_defbool_setdefault(&r_info.blackhole, false);
- SWITCH_FOREACH_OPT(opt, "bui:s:e", NULL, "remus", 2) {
+ SWITCH_FOREACH_OPT(opt, "Fbundi:s:N:e", NULL, "remus", 2) {
case 'i':
r_info.interval = atoi(optarg);
break;
+ case 'F':
+ libxl_defbool_set(&r_info.allow_unsafe, true);
+ break;
case 'b':
- r_info.blackhole = 1;
+ libxl_defbool_set(&r_info.blackhole, true);
break;
case 'u':
- r_info.compression = 0;
+ libxl_defbool_set(&r_info.compression, false);
+ break;
+ case 'n':
+ libxl_defbool_set(&r_info.netbuf, false);
+ break;
+ case 'N':
+ r_info.netbufscript = optarg;
+ break;
+ case 'd':
+ libxl_defbool_set(&r_info.diskbuf, false);
break;
case 's':
ssh_command = optarg;
@@ -7290,7 +7745,10 @@ int main_remus(int argc, char **argv)
domid = find_domain(argv[optind]);
host = argv[optind + 1];
- if (r_info.blackhole) {
+ if (!r_info.netbufscript)
+ r_info.netbufscript = default_remus_netbufscript;
+
+ if (libxl_defbool_val(r_info.blackhole)) {
send_fd = open("/dev/null", O_RDWR, 0644);
if (send_fd < 0) {
perror("failed to open /dev/null");
@@ -7327,13 +7785,19 @@ int main_remus(int argc, char **argv)
/* Point of no return */
rc = libxl_domain_remus_start(ctx, &r_info, domid, send_fd, recv_fd, 0);
- /* If we are here, it means backup has failed/domain suspend failed.
- * Try to resume the domain and exit gracefully.
- * TODO: Split-Brain check.
+ /* check if the domain exists. User may have xl destroyed the
+ * domain to force failover
*/
- fprintf(stderr, "remus sender: libxl_domain_suspend failed"
- " (rc=%d)\n", rc);
+ if (libxl_domain_info(ctx, 0, domid)) {
+ fprintf(stderr, "Remus: Primary domain has been destroyed.\n");
+ close(send_fd);
+ return 0;
+ }
+ /* If we are here, it means remus setup/domain suspend/backup has
+ * failed. Try to resume the domain and exit gracefully.
+ * TODO: Split-Brain check.
+ */
if (rc == ERROR_GUEST_TIMEDOUT)
fprintf(stderr, "Failed to suspend domain at primary.\n");
else {
@@ -7370,6 +7834,166 @@ out:
return ret;
}
+#ifdef LIBXL_HAVE_PSR_CMT
+static void psr_cmt_print_domain_cache_occupancy(libxl_dominfo *dominfo,
+ uint32_t nr_sockets)
+{
+ char *domain_name;
+ uint32_t socketid;
+ uint32_t l3_cache_occupancy;
+
+ if (!libxl_psr_cmt_domain_attached(ctx, dominfo->domid))
+ return;
+
+ domain_name = libxl_domid_to_name(ctx, dominfo->domid);
+ printf("%-40s %5d", domain_name, dominfo->domid);
+ free(domain_name);
+
+ for (socketid = 0; socketid < nr_sockets; socketid++) {
+ if ( !libxl_psr_cmt_get_cache_occupancy(ctx, dominfo->domid,
+ socketid, &l3_cache_occupancy) )
+ printf("%13u KB", l3_cache_occupancy);
+ }
+
+ printf("\n");
+}
+
+static int psr_cmt_show_cache_occupancy(uint32_t domid)
+{
+ uint32_t i, socketid, nr_sockets, total_rmid;
+ uint32_t l3_cache_size;
+ libxl_physinfo info;
+ int rc, nr_domains;
+
+ if (!libxl_psr_cmt_enabled(ctx)) {
+ fprintf(stderr, "CMT is disabled in the system\n");
+ return -1;
+ }
+
+ libxl_physinfo_init(&info);
+ rc = libxl_get_physinfo(ctx, &info);
+ if (rc < 0) {
+ fprintf(stderr, "Failed getting physinfo, rc: %d\n", rc);
+ libxl_physinfo_dispose(&info);
+ return -1;
+ }
+ nr_sockets = info.nr_cpus / info.threads_per_core / info.cores_per_socket;
+ libxl_physinfo_dispose(&info);
+
+ rc = libxl_psr_cmt_get_total_rmid(ctx, &total_rmid);
+ if (rc < 0) {
+ fprintf(stderr, "Failed to get max RMID value\n");
+ return -1;
+ }
+
+ printf("Total RMID: %d\n", total_rmid);
+
+ /* Header */
+ printf("%-40s %5s", "Name", "ID");
+ for (socketid = 0; socketid < nr_sockets; socketid++)
+ printf("%14s %d", "Socket", socketid);
+ printf("\n");
+
+ /* Total L3 cache size */
+ printf("%-46s", "Total L3 Cache Size");
+ for (socketid = 0; socketid < nr_sockets; socketid++) {
+ rc = libxl_psr_cmt_get_l3_cache_size(ctx, socketid, &l3_cache_size);
+ if (rc < 0) {
+ fprintf(stderr, "Failed to get system l3 cache size for socket:%d\n",
+ socketid);
+ return -1;
+ }
+ printf("%13u KB", l3_cache_size);
+ }
+ printf("\n");
+
+ /* Each domain */
+ if (domid != INVALID_DOMID) {
+ libxl_dominfo dominfo;
+ if (libxl_domain_info(ctx, &dominfo, domid)) {
+ fprintf(stderr, "Failed to get domain info for %d\n", domid);
+ return -1;
+ }
+ psr_cmt_print_domain_cache_occupancy(&dominfo, nr_sockets);
+ }
+ else
+ {
+ libxl_dominfo *list;
+ if (!(list = libxl_list_domain(ctx, &nr_domains))) {
+ fprintf(stderr, "Failed to get domain info for domain list.\n");
+ return -1;
+ }
+ for (i = 0; i < nr_domains; i++)
+ psr_cmt_print_domain_cache_occupancy(list + i, nr_sockets);
+ libxl_dominfo_list_free(list, nr_domains);
+ }
+ return 0;
+}
+
+int main_psr_cmt_attach(int argc, char **argv)
+{
+ uint32_t domid;
+ int opt, ret = 0;
+
+ SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-attach", 1) {
+ /* No options */
+ }
+
+ domid = find_domain(argv[optind]);
+ ret = libxl_psr_cmt_attach(ctx, domid);
+
+ return ret;
+}
+
+int main_psr_cmt_detach(int argc, char **argv)
+{
+ uint32_t domid;
+ int opt, ret = 0;
+
+ SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-detach", 1) {
+ /* No options */
+ }
+
+ domid = find_domain(argv[optind]);
+ ret = libxl_psr_cmt_detach(ctx, domid);
+
+ return ret;
+}
+
+int main_psr_cmt_show(int argc, char **argv)
+{
+ int opt, ret = 0;
+ uint32_t domid;
+ libxl_psr_cmt_type type;
+
+ SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-show", 1) {
+ /* No options */
+ }
+
+ libxl_psr_cmt_type_from_string(argv[optind], &type);
+
+ if (optind + 1 >= argc)
+ domid = INVALID_DOMID;
+ else if (optind + 1 == argc - 1)
+ domid = find_domain(argv[optind + 1]);
+ else {
+ help("psr-cmt-show");
+ return 2;
+ }
+
+ switch (type) {
+ case LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY:
+ ret = psr_cmt_show_cache_occupancy(domid);
+ break;
+ default:
+ help("psr-cmt-show");
+ return 2;
+ }
+
+ return ret;
+}
+#endif
+
/*
* Local variables:
* mode: C
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
index e8ab93a..4b30d3d 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -38,7 +38,9 @@ struct cmd_spec cmd_table[] = {
{ "config-update",
&main_config_update, 1, 1,
"Update a running domain's saved configuration, used when rebuilding "
- "the domain after reboot",
+ "the domain after reboot.\n"
+ "WARNING: xl now has better capability to manage domain configuration, "
+ "avoid using this command when possible",
"<Domain> <ConfigFile> [options] [vars]",
"-h Print this help.\n"
"-f FILE, --defconfig=FILE\n Use the given configuration file.\n"
@@ -56,7 +58,10 @@ struct cmd_spec cmd_table[] = {
{ "destroy",
&main_destroy, 0, 1,
"Terminate a domain immediately",
- "<Domain>",
+ "[options] <Domain>\n",
+ "-f Permit destroying domain 0, which will only succeed\n"
+ " when run from disaggregated toolstack domain with a\n"
+ " hardware domain distinct from domain 0."
},
{ "shutdown",
&main_shutdown, 0, 1,
@@ -215,7 +220,7 @@ struct cmd_spec cmd_table[] = {
{ "vcpu-pin",
&main_vcpupin, 1, 1,
"Set which CPUs a VCPU can use",
- "<Domain> <VCPU|all> <CPUs|all>",
+ "<Domain> <VCPU|all> <Hard affinity|-|all> <Soft affinity|-|all>",
},
{ "vcpu-set",
&main_vcpuset, 0, 1,
@@ -274,6 +279,14 @@ struct cmd_spec cmd_table[] = {
" --period/--slice)\n"
"-c CPUPOOL, --cpupool=CPUPOOL Restrict output to CPUPOOL"
},
+ { "sched-rtds",
+ &main_sched_rtds, 0, 1,
+ "Get/set rtds scheduler parameters",
+ "[-d <Domain> [-p[=PERIOD]] [-b[=BUDGET]]]",
+ "-d DOMAIN, --domain=DOMAIN Domain to modify\n"
+ "-p PERIOD, --period=PERIOD Period (us)\n"
+ "-b BUDGET, --budget=BUDGET Budget (us)\n"
+ },
{ "domid",
&main_domid, 0, 0,
"Convert a domain name to domain id",
@@ -332,6 +345,11 @@ struct cmd_spec cmd_table[] = {
"Destroy a domain's virtual network device",
"<Domain> <DevId|mac>",
},
+ { "channel-list",
+ &main_channellist, 0, 0,
+ "List virtual channel devices for a domain",
+ "<Domain(s)>",
+ },
{ "block-attach",
&main_blockattach, 1, 1,
"Create a new virtual block device",
@@ -482,13 +500,20 @@ struct cmd_spec cmd_table[] = {
"Enable Remus HA for domain",
"[options] <Domain> [<host>]",
"-i MS Checkpoint domain memory every MS milliseconds (def. 200ms).\n"
- "-b Replicate memory checkpoints to /dev/null (blackhole)\n"
"-u Disable memory checkpoint compression.\n"
"-s <sshcommand> Use <sshcommand> instead of ssh. String will be passed\n"
" to sh. If empty, run <host> instead of \n"
" ssh <host> xl migrate-receive -r [-e]\n"
"-e Do not wait in the background (on <host>) for the death\n"
- " of the domain."
+ " of the domain.\n"
+ "-N <netbufscript> Use netbufscript to setup network buffering instead of the\n"
+ " default script (/etc/xen/scripts/remus-netbuf-setup).\n"
+ "-F Enable unsafe configurations [-b|-n|-d flags]. Use this option\n"
+ " with caution as failover may not work as intended.\n"
+ "-b Replicate memory checkpoints to /dev/null (blackhole).\n"
+ " Works only in unsafe mode.\n"
+ "-n Disable network output buffering. Works only in unsafe mode.\n"
+ "-d Disable disk replication. Works only in unsafe mode."
},
#endif
{ "devd",
@@ -497,6 +522,25 @@ struct cmd_spec cmd_table[] = {
"[options]",
"-F Run in the foreground",
},
+#ifdef LIBXL_HAVE_PSR_CMT
+ { "psr-cmt-attach",
+ &main_psr_cmt_attach, 0, 1,
+ "Attach Cache Monitoring Technology service to a domain",
+ "<Domain>",
+ },
+ { "psr-cmt-detach",
+ &main_psr_cmt_detach, 0, 1,
+ "Detach Cache Monitoring Technology service from a domain",
+ "<Domain>",
+ },
+ { "psr-cmt-show",
+ &main_psr_cmt_show, 0, 1,
+ "Show Cache Monitoring Technology information",
+ "<PSR-CMT-Type> <Domain>",
+ "Available monitor types:\n"
+ "\"cache_occupancy\": Show L3 cache occupancy\n",
+ },
+#endif
};
int cmdtable_len = sizeof(cmd_table)/sizeof(struct cmd_spec);
diff --git a/tools/libxl/xl_sxp.c b/tools/libxl/xl_sxp.c
index a16a025..1c98352 100644
--- a/tools/libxl/xl_sxp.c
+++ b/tools/libxl/xl_sxp.c
@@ -37,7 +37,6 @@ void printf_info_sexp(int domid, libxl_domain_config *d_config)
libxl_domain_create_info *c_info = &d_config->c_info;
libxl_domain_build_info *b_info = &d_config->b_info;
- char *pool;
printf("(domain\n\t(domid %d)\n", domid);
printf("\t(create_info)\n");
@@ -55,10 +54,8 @@ void printf_info_sexp(int domid, libxl_domain_config *d_config)
} else {
printf("\t(uuid <unknown>)\n");
}
- pool = libxl_cpupoolid_to_name(ctx, c_info->poolid);
- if (pool)
- printf("\t(cpupool %s)\n", pool);
- free(pool);
+ if (c_info->pool_name)
+ printf("\t(cpupool %s)\n", c_info->pool_name);
if (c_info->xsdata)
printf("\t(xsdata contains data)\n");
else
@@ -147,9 +144,9 @@ void printf_info_sexp(int domid, libxl_domain_config *d_config)
break;
case LIBXL_DOMAIN_TYPE_PV:
printf("\t\t(linux %d)\n", 0);
- printf("\t\t\t(kernel %s)\n", b_info->u.pv.kernel);
- printf("\t\t\t(cmdline %s)\n", b_info->u.pv.cmdline);
- printf("\t\t\t(ramdisk %s)\n", b_info->u.pv.ramdisk);
+ printf("\t\t\t(kernel %s)\n", b_info->kernel);
+ printf("\t\t\t(cmdline %s)\n", b_info->cmdline);
+ printf("\t\t\t(ramdisk %s)\n", b_info->ramdisk);
printf("\t\t\t(e820_host %s)\n",
libxl_defbool_to_string(b_info->u.pv.e820_host));
printf("\t\t)\n");
diff --git a/tools/memshr/Makefile b/tools/memshr/Makefile
index a2d6b00..2c34f96 100644
--- a/tools/memshr/Makefile
+++ b/tools/memshr/Makefile
@@ -9,7 +9,6 @@ CFLAGS += $(CFLAGS_xeninclude)
CFLAGS += $(CFLAGS_libxenctrl)
CFLAGS += -D_GNU_SOURCE
CFLAGS += -fPIC
-CFLAGS += -g
LIB-SRCS := interface.c
LIB-SRCS += shm.c
diff --git a/tools/misc/Makefile b/tools/misc/Makefile
index 17aeda5..7a2bfd2 100644
--- a/tools/misc/Makefile
+++ b/tools/misc/Makefile
@@ -6,6 +6,8 @@ CFLAGS += -Werror
CFLAGS += $(CFLAGS_libxenctrl)
CFLAGS += $(CFLAGS_xeninclude)
CFLAGS += $(CFLAGS_libxenstore)
+# xen-hptool.c and xen-mfndump.c incorrectly use libxc internals
+CFLAGS += -I$(XEN_ROOT)/tools/libxc
HDRS = $(wildcard *.h)
@@ -14,13 +16,11 @@ TARGETS-$(CONFIG_X86) += xen-detect xen-hvmctx xen-hvmcrash xen-lowmemd xen-mfnd
TARGETS-$(CONFIG_MIGRATE) += xen-hptool
TARGETS := $(TARGETS-y)
-SUBDIRS := $(SUBDIRS-y)
-
INSTALL_BIN-y := xencons xencov_split
INSTALL_BIN-$(CONFIG_X86) += xen-detect
INSTALL_BIN := $(INSTALL_BIN-y)
-INSTALL_SBIN-y := xen-bugtool xen-python-path xenperf xenpm xen-tmem-list-parse gtraceview \
+INSTALL_SBIN-y := xen-bugtool xenperf xenpm xen-tmem-list-parse gtraceview \
gtracestat xenlockprof xenwatchdogd xen-ringwatch xencov
INSTALL_SBIN-$(CONFIG_X86) += xen-hvmctx xen-hvmcrash xen-lowmemd xen-mfndump
INSTALL_SBIN-$(CONFIG_MIGRATE) += xen-hptool
@@ -37,22 +37,19 @@ all: build
.PHONY: build
build: $(TARGETS)
- set -e; for d in $(SUBDIRS); do $(MAKE) -C $$d; done
.PHONY: install
install: build
$(INSTALL_DIR) $(DESTDIR)$(BINDIR)
$(INSTALL_DIR) $(DESTDIR)$(SBINDIR)
- $(INSTALL_DIR) $(DESTDIR)$(PRIVATE_BINDIR)
+ $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN)
$(INSTALL_PYTHON_PROG) $(INSTALL_BIN) $(DESTDIR)$(BINDIR)
$(INSTALL_PYTHON_PROG) $(INSTALL_SBIN) $(DESTDIR)$(SBINDIR)
- $(INSTALL_PYTHON_PROG) $(INSTALL_PRIVBIN) $(DESTDIR)$(PRIVATE_BINDIR)
- set -e; for d in $(SUBDIRS); do $(MAKE) -C $$d install-recurse; done
+ $(INSTALL_PYTHON_PROG) $(INSTALL_PRIVBIN) $(DESTDIR)$(LIBEXEC_BIN)
.PHONY: clean
clean:
$(RM) *.o $(TARGETS) *~ $(DEPS)
- set -e; for d in $(SUBDIRS); do $(MAKE) -C $$d clean; done
xen-hvmctx: xen-hvmctx.o
$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
@@ -76,7 +73,7 @@ xen-hptool: xen-hptool.o
$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS)
xen-mfndump: xen-mfndump.o
- $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS)
+ $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(APPEND_LDFLAGS)
xenwatchdogd: xenwatchdogd.o
$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
diff --git a/tools/misc/mkdeb b/tools/misc/mkdeb
index 2e40747..67b91cc 100644
--- a/tools/misc/mkdeb
+++ b/tools/misc/mkdeb
@@ -13,11 +13,17 @@ fi
cd $1
version=$2
-if test "$XEN_TARGET_ARCH" = "x86_32"; then
- arch=i386
-else
- arch=amd64
-fi
+
+# map the architecture, if necessary
+case "$XEN_TARGET_ARCH" in
+ x86_32|x86_32p) arch=i386 ;;
+ x86_64) arch=amd64 ;;
+ arm32) arch=armhf ;;
+ arm64) arch=$XEN_TARGET_ARCH;;
+ *) echo "Unknown XEN_TARGET_ARCH $XEN_TARGET_ARCH" >&2
+ exit 1
+ ;;
+esac
# Prepare the directory to package
cd dist
@@ -33,7 +39,7 @@ fi
# Fill in the debian boilerplate
mkdir -p deb/DEBIAN
cat >deb/DEBIAN/control <<EOF
-Package: xen-upstream-$version
+Package: xen-upstream
Source: xen-upstream
Version: $version
Architecture: $arch
@@ -41,12 +47,15 @@ Maintainer: Unmaintained snapshot
Section: admin
Priority: optional
Installed-Size: $(du -ks deb | cut -f1)
-Description: Xen hypervisor and tools, version $version
- This package contains the Xen hypervisor and associated tools, built
- from a source tree. It is not a fully packaged and supported Xen, just
- the output of a xen "make dist" wrapped in a .deb to make it easy to
- uninstall.
+Description: Xen upstream testing build snapshot
+ Warning: This is a custom testing build of Xen; it is not an
+ officially supported Debian package. Please not distribute.
+ It is just the output of a xen "make dist" wrapped in a .deb
+ to make it easy to update and uninstall.
EOF
+# Find all /etc files and add them to conffiles
+find deb/etc -type f -printf /etc/%P\\n >deb/DEBIAN/conffiles
+
# Package it up
chown -R root:root deb
diff --git a/tools/misc/mkrpm b/tools/misc/mkrpm
new file mode 100644
index 0000000..9b8c6d9
--- /dev/null
+++ b/tools/misc/mkrpm
@@ -0,0 +1,76 @@
+#!/bin/bash
+#
+# mkrpm: package the dist/install output of a Xen build in an .rpm
+#
+# Takes 2 arguments, the path to the dist directory and the version
+
+set -e
+
+if [[ -z "$1" || -z "$2" ]] ; then
+ echo "usage: $0 path-to-XEN_ROOT xen-version"
+ exit 1
+fi
+
+xenroot="$1"
+
+# rpmbuild doesn't like dashes in the version; break it down into
+# version and release. Default to "0" if there isn't a release.
+v=(${2/-/ })
+version=${v[0]}
+release=${v[1]}
+
+[[ -n "$release" ]] || release="0"
+
+cd $xenroot
+
+# Prepare the directory to package
+cd dist
+rm -rf rpm
+
+# Fill in the rpm boilerplate
+mkdir -p rpm/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
+cat >rpm/SPECS/xen.spec <<EOF
+Summary: Xen development build, version $version
+Name: xen$PKG_SUFFIX
+Version: $version
+Release: $release
+License: GPL
+Group: System/Hypervisor
+URL: http://xenbits.xenproject.org/xen.git
+
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
+%define __spec_install_post /usr/lib/rpm/brp-compress || :
+%define debug_package %{nil}
+
+%description
+This package contains the Xen hypervisor and associated tools, built
+from a source tree. It is not a fully packaged and supported Xen, just
+the output of a xen "make dist" wrapped in an .rpm to make it easy to
+uninstall.
+
+%build
+
+%install
+rm -rf \$RPM_BUILD_ROOT
+mkdir -p \$RPM_BUILD_ROOT
+cd %{_xenroot}
+dist/install.sh \$RPM_BUILD_ROOT/
+
+cd \$RPM_BUILD_ROOT
+
+%clean
+rm -rf \$RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root,-)
+/*
+
+%post
+EOF
+
+# Package it up
+rpmbuild --define "_xenroot $xenroot" --define "_topdir $PWD/rpm" -bb rpm/SPECS/xen.spec
+
+# Tidy up after ourselves
+mv rpm/RPMS/*/*.rpm .
+rm -rf rpm
diff --git a/tools/misc/mktarball b/tools/misc/mktarball
new file mode 100755
index 0000000..aad1096
--- /dev/null
+++ b/tools/misc/mktarball
@@ -0,0 +1,38 @@
+#!/bin/bash
+#
+# mktarball: Make a release tarball (including xen, qemu, and qemu-traditional)
+#
+# Takes 2 arguments, the path to the dist directory and the version
+set -ex
+
+function git_archive_into {
+ mkdir "$2"
+
+ git --git-dir="$1"/.git \
+ archive --format=tar HEAD | \
+ tar Cxf "$2" -
+}
+
+if [[ -z "$1" || -z "$2" ]] ; then
+ echo "usage: $0 path-to-XEN_ROOT xen-version"
+ exit 1
+fi
+
+xen_root="$1"
+desc="$2"
+
+tdir="$xen_root/dist/tmp.src-tarball"
+
+rm -rf $tdir
+
+mkdir -p $tdir
+
+git_archive_into $xen_root $tdir/xen-$desc
+
+git_archive_into $xen_root/tools/qemu-xen-dir-remote $tdir/xen-$desc/tools/qemu-xen
+
+git_archive_into $xen_root/tools/qemu-xen-traditional-dir-remote $tdir/xen-$desc/tools/qemu-xen-traditional
+
+GZIP=-9v tar cz -f $xen_root/dist/xen-$desc.tar.gz -C $tdir xen-$desc
+
+echo "Source tarball in $xen_root/dist/xen-$desc.tar.gz"
diff --git a/tools/misc/nsplitd/Makefile b/tools/misc/nsplitd/Makefile
deleted file mode 100644
index 91ccf4d..0000000
--- a/tools/misc/nsplitd/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-XEN_ROOT := $(CURDIR)/../../..
-include $(XEN_ROOT)/tools/Rules.mk
-
-CFILES = $(wildcard *.c)
-
-HDRS = $(wildcard *.h)
-OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
-
-TARGET = nsplitd
-
-.PHONY: all
-all: $(TARGET)
-
-.PHONY: install
-install: all
-
-.PHONY: clean
-clean:
- $(RM) *.o $(TARGET) *~
-
-$(TARGET): $(OBJS)
- $(HOSTCC) $(HOSTCFLAGS) -o $@ $^
-
-%.o: %.c $(HDRS) Makefile
- $(HOSTCC) $(HOSTCFLAGS) -c -o $@ $<
diff --git a/tools/misc/nsplitd/nsplitd.c b/tools/misc/nsplitd/nsplitd.c
deleted file mode 100644
index 32f0b56..0000000
--- a/tools/misc/nsplitd/nsplitd.c
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
- * nsplitd.c
- * ---------
- *
- * $Id: nsplitd.c,v 2.6 1998/09/17 14:28:37 sde1000 Exp $
- *
- * Copyright (c) 1995, University of Cambridge Computer Laboratory,
- * Copyright (c) 1995, Richard Black, All Rights Reserved.
- *
- *
- * A complete re-implementation of DME's nsplitd for use from inetd
- *
- */
-
-/* The basic stream comes in (via inetd) and we then conenct to
- * somewhere else providing a loop-through service, except we offer
- * two other ports for connection - one of which gets a second channel
- * using the top bit to distinguish, and the other is a master control
- * port (normally used for gdb) which gets complete exclusive access
- * for its duration.
- *
- * Originally designed for multiplexing a xwcons/telnet with a gdb
- * post-mortem debugging session.
- *
- * Here is a picture:
- *
- * port0 (from inetd)
- * 8-bit connection /
- * made by us <----> nsplitd <-----gdbport (default port0+2)
- * to host:port/tcp |\
- * | port1 (default port0+1)
- * \
- * control (default port0+3)
- *
- * If port1 is explicitly disabled (through a command-line option) then
- * port0 becomes 8-bit clean.
- */
-
-/*
- * N.B.: We do NOT support 8 bit stdin/stdout usage on a
- * /dev/... because to do that right involves much messing with ioctl
- * and TIOC... etc. If you want to do that sort of thing then the
- * right way to do it is to chain this onto wconsd (which does know
- * about and understand all the ioctl and TIOC grief).
- */
-
-#include <sys/types.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <netdb.h>
-#include <string.h>
-
-#include <sys/time.h>
-#include <sys/signal.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <sys/ioctl.h>
-#include <syslog.h>
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef LOG_DAEMON
-#define LOG_DAEMON 0
-#endif
-
-#define DB(x) /* ((x), fflush(stderr)) */
-
-extern char *optarg;
-
-extern int optind, opterr, optopt;
-
-static char *prog_name;
-
-static void usage(void)
-{
- fprintf(stderr, "This program (%s) should be run via inetd (tcp)\n\n",
- prog_name);
- fprintf(stderr, "usage: %s [-h<highport>][-g<gdbport>]"
- "[-c<ctlport>][-8] host:service\n",
- prog_name);
- exit(1);
-}
-
-static void fault(char *format, ...)
-{
- va_list ap;
- char logbuf[1024];
-
- va_start(ap, format);
- fprintf(stderr, "%s: ", prog_name);
- vfprintf(stderr, format, ap);
- fflush(stderr);
- va_end(ap);
-
- /* XXX This is a bit dubious, but there is no vsyslog */
- va_start(ap, format);
- vsnprintf(logbuf, sizeof(logbuf), format, ap);
- syslog(LOG_ERR, logbuf);
- va_end(ap);
- exit(1);
-}
-
-static int getservice(char *name, unsigned short *port)
-{
- struct servent *se;
-
- if (!name) return -1;
-
- if (isdigit(name[0]))
- *port = atoi(name);
- else
- {
- if (!(se = getservbyname(name, "tcp")))
- return -1;
- *port = ntohs(se->s_port);
- }
- return 0;
-}
-
-/*
- * connect_host: connect to ("name", "port")
- */
-static int connect_host (char *name, unsigned int port)
-{
- int fd;
- struct hostent *hostent;
- struct sockaddr_in sin;
- int on;
-
- if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
- fault("socket");
-
- if (!(hostent = gethostbyname(name)))
- fault("gethostbyname: %s: %s\n", name, strerror(errno));
-
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_port = htons (port);
- memcpy(&sin.sin_addr.s_addr, hostent->h_addr, sizeof(struct in_addr));
-
- if (connect(fd, (struct sockaddr *) &sin, sizeof (sin)) < 0)
- fault("connect: %s:%u: %s\n", name, port, strerror(errno));
-
- on = 1;
- if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)
- syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m");
-
- on = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0)
- syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
-
- return fd;
-}
-
-/*
- * open a tcp socket and start listening for connections on it
- */
-static int startlistening(unsigned short port)
-{
- int fd, on;
- struct sockaddr_in sin;
-
- if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
- fault("socket");
-
- on = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0)
- syslog(LOG_WARNING, "setsockopt (SO_REUSEADDR): %m");
-
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_port = htons (port);
- sin.sin_addr.s_addr = INADDR_ANY;
- if (bind(fd, &sin, sizeof(sin)) < 0)
- fault("bind: %u: %s\n", port, strerror(errno));
-
- if (listen(fd, 1) < 0)
- fault("listen: %s\n", strerror(errno));
-
- return fd;
-}
-
-static void noblock(int fd)
-{
- int on=1;
-
- if (ioctl(fd, FIONBIO, &on) < 0)
- fault("ioctl: FIONBIO: %s\n", strerror(errno));
-}
-
-
-/* You might not believe this, but fd_sets don't have to be a 32-bit
- * integer. In particular, in glibc2 it is an array of unsigned
- * longs. Hence, this hacked up FD_SET_rjb() that works out if it
- * would have been a nop. */
-#define FD_SET_rjb(fd, setp) \
-do { \
- if ((fd) != 32) \
- FD_SET((fd), (setp)); \
-} while(0)
-
-#define FD_ISSET_rjb(fd, setp) (((fd) != 32)? FD_ISSET((fd), (setp)) : 0)
-
-#define MAXSIZE 256
-
-/* -----------------------------------------------------------------
- * The main bit of the algorithm. Note we use 32 to mean not connected
- * because this gives us 1<<32 == 0. We could have done this one
- * character at a time, but that would have been very inefficient and
- * not the unix way. */
-static int debug;
-
-static void doit(int actl, int acto, int lish, int lisg, int lisc)
-{
- int acth, actg, actc;
- int gdbmode = FALSE;
- char gibuf[MAXSIZE], oibuf[MAXSIZE];
- char libuf[MAXSIZE], lobuf[MAXSIZE];
- char hibuf[MAXSIZE], hobuf[MAXSIZE];
- char ctlbuf[MAXSIZE];
- fd_set rdfs, wrfs, exfs;
- int gicc, oicc, licc, locc, hicc, hocc, ctlcc;
- char *giptr, *oiptr, *liptr, *loptr, *hiptr, *hoptr;
- int rc, fromlen;
- struct sockaddr_in from;
-
- gicc = oicc = licc = locc = hicc = hocc = ctlcc = 0;
- acth = actg = actc = 32; /* XXX yummy */
-
- noblock(actl);
- noblock(acto);
-
- for(;;)
- {
- FD_ZERO(&rdfs);
- FD_ZERO(&wrfs);
- FD_ZERO(&exfs);
-
- /* always take input from the control port (if it's connected) */
- FD_SET_rjb(actc, &rdfs);
-
- if (gdbmode)
- {
- if (oicc)
- FD_SET_rjb(actg, &wrfs);
- else
- FD_SET_rjb(acto, &rdfs);
-
- if (gicc)
- FD_SET_rjb(acto, &wrfs);
- else
- FD_SET_rjb(actg, &rdfs);
- }
- else
- {
- /* There is no such thing as oibuf because its been split into
- * lobuf and hobuf
- */
- if (locc || hocc)
- {
- if (locc)
- FD_SET_rjb(actl, &wrfs);
- if (hocc)
- FD_SET_rjb(acth, &wrfs);
- }
- else
- FD_SET_rjb(acto, &rdfs);
-
- if (licc)
- FD_SET_rjb(acto, &wrfs);
- else
- FD_SET_rjb(actl, &rdfs);
-
- if (hicc)
- FD_SET_rjb(acto, &wrfs);
- else
- FD_SET_rjb(acth, &rdfs);
- }
-
- if (acth == 32 && lish>=0) FD_SET_rjb(lish, &rdfs);
- if (actg == 32) FD_SET_rjb(lisg, &rdfs);
- if (actc == 32) FD_SET_rjb(lisc, &rdfs);
-
- /* now make exfs the union of the read and write fd sets, plus
- * "actl" */
- {
- int i;
- exfs = rdfs;
- for(i=0; i<32; i++) /* XXX we only copy fd numbers up to 31 */
- if (FD_ISSET(i, &wrfs))
- FD_SET_rjb(i, &exfs);
- FD_SET_rjb(actl, &exfs);
- }
-
- /* XXX AND: can't print something of type fd_set as %x - it
- * might be an array */
- DB(fprintf(stderr, "%s: before select: %08x %08x %08x\n",
- prog_name, rdfs, wrfs, exfs));
-
- if (select(32, &rdfs, &wrfs, &exfs, NULL) < 0)
- fault("select: %s\n", strerror(errno));
-
- DB(fprintf(stderr, "%s: after select: %08x %08x %08x\n",
- prog_name, rdfs, wrfs, exfs));
-
- /* XXX it appears that a non-blocking socket may not show up
- * correctly in exfs but instead goes readable with no data in
- * it. Thus we check for zero and goto the appropriate close
- * method. */
-
- /* Deal with exceptions */
- if (FD_ISSET_rjb(actg, &exfs))
- {
- exfs_actg:
- close(actg);
- gdbmode = FALSE;
- oicc = 0;
- oiptr = oibuf;
- actg = 32;
- continue; /* because assumptions changed */
- }
- if (FD_ISSET_rjb(acth, &exfs))
- {
- exfs_acth:
- close(acth);
- hicc = hocc = 0;
- hiptr = hibuf;
- hoptr = hibuf;
- acth = 32;
- continue; /* because assumptions changed */
- }
- if (FD_ISSET_rjb(actl, &exfs) ||
- FD_ISSET_rjb(acto, &exfs))
- {
- exfs_actl:
- exfs_acto:
- /* Thats all folks ... */
- break;
- }
- if (FD_ISSET_rjb(actc, &exfs))
- {
- exfs_ctl:
- close(actc);
- actc = 32;
- ctlcc = 0;
- continue;
- }
-
- /* Deal with reading */
- if (FD_ISSET_rjb(acto, &rdfs))
- {
- if ((oicc = read(acto, oiptr = oibuf, MAXSIZE)) < 0)
- fault("read acto: %d: %s\n", oicc, strerror(errno));
- if (!oicc) goto exfs_acto;
-
- if (!gdbmode)
- {
- int t;
-
- assert((locc == 0) && (hocc == 0));
- loptr = lobuf;
- hoptr = hobuf;
-
- if (lish>=0) {
- for(t=0; t<oicc; t++)
- if (oibuf[t] & 0x80)
- hobuf[hocc++] = oibuf[t] & 0x7f;
- else
- lobuf[locc++] = oibuf[t];
- } else {
- for (t=0; t<oicc; t++)
- lobuf[locc++] = oibuf[t];
- }
- /* If no high connection scratch that */
- if (acth == 32)
- hocc=0;
- }
- }
- if (FD_ISSET_rjb(actl, &rdfs))
- {
- if ((licc = read(actl, liptr = libuf, MAXSIZE)) < 0)
- fault("read actl: %d: %s\n", licc, strerror(errno));
- if (!licc) goto exfs_actl;
- }
- if (FD_ISSET_rjb(acth, &rdfs))
- {
- int t;
-
- if ((hicc = read(acth, hiptr = hibuf, MAXSIZE)) < 0)
- fault("read acth: %d: %s\n", hicc, strerror(errno));
- if (!hicc) goto exfs_acth;
- for(t=0; t<hicc; t++)
- hibuf[t] |= 0x80;
- }
- if (FD_ISSET_rjb(actg, &rdfs))
- {
- if ((gicc = read(actg, giptr = gibuf, MAXSIZE)) < 0)
- fault("read actg: %d: %s\n", gicc, strerror(errno));
- if (debug) write(1, giptr, gicc); /* XXX */
- if (!gicc) goto exfs_actg;
- }
- if (FD_ISSET_rjb(actc, &rdfs))
- {
- if ((ctlcc = read(actc, ctlbuf, MAXSIZE)) < 0)
- fault("read actc: %d: %s\n", ctlcc, strerror(errno));
- if (debug) write(1, ctlbuf, gicc);
- if (!ctlcc) goto exfs_ctl;
- if (ctlbuf[0] == 'r') /* reset command */
- {
- syslog(LOG_INFO, "reset command read, exiting");
- if (debug) write(1, "reseting\n", sizeof("reseting\n"));
- break;
- }
- }
-
- /* Deal with writing */
- if (FD_ISSET_rjb(actg, &wrfs))
- {
- /* We must be in gdb mode so send oi buffer data */
- assert(gdbmode);
- if (debug) write(2, oiptr, oicc); /* XXX */
- if ((rc = write(actg, oiptr, oicc)) <= 0)
- fault("write actg: %d: %s\n", rc, strerror(errno));
- oiptr += rc;
- oicc -= rc;
- }
- if (FD_ISSET_rjb(actl, &wrfs))
- {
- if ((rc = write(actl, loptr, locc)) <= 0)
- fault("write actl: %d: %s\n", rc, strerror(errno));
- loptr += rc;
- locc -= rc;
- }
- if (FD_ISSET_rjb(acth, &wrfs))
- {
- if ((rc = write(acth, hoptr, hocc)) <= 0)
- fault("write acth: %d: %s\n", rc, strerror(errno));
- hoptr += rc;
- hocc -= rc;
- }
- if (FD_ISSET_rjb(acto, &wrfs))
- {
- /* If in gdb mode send gdb input, otherwise send low data
- preferentially */
- if (gdbmode)
- {
- assert(gicc);
- if ((rc = write(acto, giptr, gicc)) <= 0)
- fault("write acto: %d: %s\n", rc, strerror(errno));
- giptr += rc;
- gicc -= rc;
- }
- else
- {
- if (licc)
- {
- if ((rc = write(acto, liptr, licc)) <= 0)
- fault("write acto: %d: %s\n", rc, strerror(errno));
- liptr += rc;
- licc -= rc;
- }
- else
- {
- assert(hicc);
- if ((rc = write(acto, hiptr, hicc)) <= 0)
- fault("write acto: %d: %s\n", rc, strerror(errno));
- hiptr += rc;
- hicc -= rc;
- }
- }
- }
-
- /* Deals with new connections */
- if ((acth == 32) && lish>=0 && (FD_ISSET_rjb(lish, &rdfs)))
- {
- fromlen = sizeof(from);
- if ((acth = accept(lish, &from, &fromlen)) < 0)
- {
- syslog(LOG_WARNING, "accept: %m");
- acth = 32;
- }
- else
- {
- noblock(acth);
- hicc = hocc = 0;
- syslog(LOG_INFO, "highbit client peer is %s:%u\n",
- inet_ntoa(from.sin_addr), ntohs(from.sin_port));
- }
- }
-
- if ((actg == 32) && (FD_ISSET_rjb(lisg, &rdfs)))
- {
- fromlen = sizeof(from);
- if ((actg = accept(lisg, &from, &fromlen)) < 0)
- {
- syslog(LOG_WARNING, "accept: %m");
- actg = 32;
- }
- else
- {
- noblock(actg);
- gicc = 0;
- gdbmode = TRUE;
- syslog(LOG_INFO, "gdb client peer is %s:%u\n",
- inet_ntoa(from.sin_addr), ntohs(from.sin_port));
- }
- }
-
- if ((actc == 32) && (FD_ISSET_rjb(lisc, &rdfs)))
- {
- fromlen = sizeof(from);
- if ((actc = accept(lisc, &from, &fromlen)) < 0)
- {
- syslog(LOG_WARNING, "accept (ctl): %m");
- actc = 32;
- }
- else
- {
- noblock(actc);
- syslog(LOG_INFO, "ctl client peer is %s:%u\n",
- inet_ntoa(from.sin_addr), ntohs(from.sin_port));
- }
- }
-
- /* Back to top of loop */
- }
-
- /* We are bailing because one of the primary connections has gone
- * away. We close these all explicitly here because that way the
- * timeout on reusing the port numbers is smnaller. */
-
- close(acth);
- close(actg);
- /* XXX AND: why are we closing all these "character counts" ?? */
- close(gicc);
- close(oicc);
- close(licc);
- close(locc);
- close(hicc);
- close(hocc);
-}
-
-/*
- * ------------------------------------------------------------
- */
-int main(int argc, char **argv)
-{
- /* In general, suffix "l" is low channel, "h" is high channel, "g"
- * is gdb channel, "c" is control channel and "o" is output channel.
- */
- struct sockaddr_in from;
- int infd = 0, outfd;
- unsigned short portl, porth, portg, portc, porto;
- int on = 1, c;
- char *outname, *outservice;
- int fromlen;
- int lish, lisg, lisc;
-#if 0
- FILE *newerr;
-#endif /* 0 */
-
- prog_name = argv[0];
-
- if (isatty(infd))
- usage();
-
- /* Here, then not just a simple idiot. */
-
- signal(SIGPIPE, SIG_IGN);
-
- openlog(prog_name, LOG_PID, LOG_DAEMON);
-
- fromlen = sizeof(from);
- if (getsockname(infd, &from, &fromlen) < 0)
- fault("getsockname: %s", strerror(errno));
- if ((fromlen != sizeof(from)) || (from.sin_family != AF_INET))
- fault("not an inet socket (family=%d)\n", from.sin_family);
-
- portl = ntohs(from.sin_port);
- porth = portl+1;
- portg = porth+1;
- portc = portg+1;
-
- fromlen = sizeof(from);
- if (getpeername(infd, &from, &fromlen) < 0)
- fault("getpeername: %s", strerror(errno));
- if ((fromlen != sizeof(from)) || (from.sin_family != AF_INET))
- fault("not an inet socket (family=%d)\n", from.sin_family);
-
- syslog(LOG_INFO, "on port %u peer is %s:%u\n", portl,
- inet_ntoa(from.sin_addr), ntohs(from.sin_port));
-
- if (setsockopt(infd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0)
- syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
-
- /* from here on, we map stderr to output on the connection so we can
- * report errors to the remote user.
- */
-#if 0
- if (!(newerr = fdopen(infd, "w")))
- syslog(LOG_WARNING, "fdopen: %m");
- else
- *stderr = *newerr;
-#endif
-
- while((c = getopt(argc, argv, "d8h:g:c:")) != EOF)
- {
- switch(c)
- {
- case 'd':
- debug++;
- break;
-
- case 'h':
- /* high bit port */
- if (getservice(optarg, &porth) < 0)
- fault("getservice failed (high port '%s')\n", optarg);
- break;
-
- case 'g':
- /* gdb port */
- if (getservice(optarg, &portg) < 0)
- fault("getservice failed (gdb port '%s')\n", optarg);
- break;
-
- case 'c':
- /* control port */
- if (getservice(optarg, &portc) < 0)
- fault("getservice failed (control port '%s')\n", optarg);
- break;
-
- case '8':
- /* 8-bit clean; no high port */
- porth=0;
- break;
-
- default:
- fault("bad argument list!\n");
- }
- }
-
- if (argc != optind + 1)
- fault("unparsed arguments (%d!=%d)\n", argc, optind+1);
-
- outname = argv[optind];
- if (!(outservice = strchr(outname, ':')))
- fault("output arg '%s' doesn't contain ':'\n", outname);
- *outservice++ = 0;
- if (getservice(outservice, &porto) < 0)
- fault("getservice failed (output port '%s')\n", outservice);
-
- /* Time to start the sockets */
-
- if (porth) {
- lish = startlistening(porth);
- } else {
- lish = -1;
- }
- lisg = startlistening(portg);
- lisc = startlistening(portc);
-
- outfd = connect_host(outname, porto);
-
- doit(infd, outfd, lish, lisg, lisc);
-
- syslog(LOG_INFO, "terminating normally\n");
-
- fclose(stderr);
-
- closelog();
- exit(0);
-}
-
-/* End $Id: nsplitd.c,v 2.6 1998/09/17 14:28:37 sde1000 Exp $ */
diff --git a/tools/misc/sxp-pretty b/tools/misc/sxp-pretty
deleted file mode 100644
index dd642b0..0000000
--- a/tools/misc/sxp-pretty
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python
-# -*- mode: python; -*-
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (c) 2007 XenSource Inc.
-#============================================================================
-
-
-import commands
-import os.path
-import pprint
-import sys
-
-import xen.xend.sxp as sxp
-
-def main():
- if len(sys.argv) == 1 or sys.argv[1] in ['', '-']:
- s = sxp.parse(sys.stdin)
- else:
- s = sxp.parse(open(sys.argv[1]))
-
- pprint.pprint(s)
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/tools/misc/xen-hptool.c b/tools/misc/xen-hptool.c
index 24c3e95..1134603 100644
--- a/tools/misc/xen-hptool.c
+++ b/tools/misc/xen-hptool.c
@@ -1,9 +1,10 @@
#include <xenctrl.h>
#include <xc_private.h>
#include <xc_core.h>
-#include <errno.h>
+#include <xenstore.h>
#include <unistd.h>
+#undef ARRAY_SIZE /* We shouldn't be including xc_private.h */
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
static xc_interface *xch;
@@ -97,12 +98,13 @@ static int hp_mem_query_func(int argc, char *argv[])
return ret;
}
-extern int xs_suspend_evtchn_port(int domid);
-
-static int suspend_guest(xc_interface *xch, xc_evtchn *xce, int domid, int *evtchn)
+static int suspend_guest(xc_interface *xch, xc_evtchn *xce, int domid,
+ int *evtchn, int *lockfd)
{
int port, rc, suspend_evtchn = -1;
+ *lockfd = -1;
+
if (!evtchn)
return -1;
@@ -112,7 +114,8 @@ static int suspend_guest(xc_interface *xch, xc_evtchn *xce, int domid, int *evtc
fprintf(stderr, "DOM%d: No suspend port, try live migration\n", domid);
goto failed;
}
- suspend_evtchn = xc_suspend_evtchn_init(xch, xce, domid, port);
+ suspend_evtchn = xc_suspend_evtchn_init_exclusive(xch, xce, domid,
+ port, lockfd);
if (suspend_evtchn < 0)
{
fprintf(stderr, "Suspend evtchn initialization failed\n");
@@ -135,7 +138,8 @@ static int suspend_guest(xc_interface *xch, xc_evtchn *xce, int domid, int *evtc
failed:
if (suspend_evtchn != -1)
- xc_suspend_evtchn_release(xch, xce, domid, suspend_evtchn);
+ xc_suspend_evtchn_release(xch, xce, domid,
+ suspend_evtchn, lockfd);
return -1;
}
@@ -193,7 +197,7 @@ static int hp_mem_offline_func(int argc, char *argv[])
}
else if (status & PG_OFFLINE_OWNED)
{
- int result, suspend_evtchn = -1;
+ int result, suspend_evtchn = -1, suspend_lockfd = -1;
xc_evtchn *xce;
xce = xc_evtchn_open(NULL, 0);
@@ -205,7 +209,8 @@ static int hp_mem_offline_func(int argc, char *argv[])
}
domid = status >> PG_OFFLINE_OWNER_SHIFT;
- if (suspend_guest(xch, xce, domid, &suspend_evtchn))
+ if (suspend_guest(xch, xce, domid,
+ &suspend_evtchn, &suspend_lockfd))
{
fprintf(stderr, "Failed to suspend guest %d for"
" mfn %lx\n", domid, mfn);
@@ -231,7 +236,8 @@ static int hp_mem_offline_func(int argc, char *argv[])
mfn, domid);
}
xc_domain_resume(xch, domid, 1);
- xc_suspend_evtchn_release(xch, xce, domid, suspend_evtchn);
+ xc_suspend_evtchn_release(xch, xce, domid,
+ suspend_evtchn, &suspend_lockfd);
xc_evtchn_close(xce);
}
break;
diff --git a/tools/misc/xen-mfndump.c b/tools/misc/xen-mfndump.c
index dea9fa9..0761f6e 100644
--- a/tools/misc/xen-mfndump.c
+++ b/tools/misc/xen-mfndump.c
@@ -1,12 +1,12 @@
#include <xenctrl.h>
#include <xc_private.h>
#include <xc_core.h>
-#include <errno.h>
#include <unistd.h>
#include <inttypes.h>
#include "xg_save_restore.h"
+#undef ARRAY_SIZE /* We shouldn't be including xc_private.h */
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
static xc_interface *xch;
@@ -102,43 +102,47 @@ int dump_p2m_func(int argc, char *argv[])
{
unsigned long pagetype = minfo.pfn_type[i] &
XEN_DOMCTL_PFINFO_LTAB_MASK;
+ xen_pfn_t mfn;
- printf(" pfn=0x%lx ==> mfn=0x%lx (type 0x%lx)", i, minfo.p2m_table[i],
- pagetype >> XEN_DOMCTL_PFINFO_LTAB_SHIFT);
-
- if ( is_mapped(minfo.p2m_table[i]) )
- printf(" [mapped]");
-
- if ( pagetype & XEN_DOMCTL_PFINFO_LPINTAB )
- printf (" [pinned]");
-
- if ( pagetype == XEN_DOMCTL_PFINFO_XTAB )
- printf(" [xtab]");
- if ( pagetype == XEN_DOMCTL_PFINFO_BROKEN )
- printf(" [broken]");
- if ( pagetype == XEN_DOMCTL_PFINFO_XALLOC )
- printf( " [xalloc]");
-
- switch ( pagetype & XEN_DOMCTL_PFINFO_LTABTYPE_MASK )
+ if ( minfo.guest_width == sizeof(uint64_t) )
+ mfn = ((uint64_t*)minfo.p2m_table)[i];
+ else
{
- case XEN_DOMCTL_PFINFO_L1TAB:
- printf(" L1 table");
- break;
-
- case XEN_DOMCTL_PFINFO_L2TAB:
- printf(" L2 table");
- break;
+ mfn = ((uint32_t*)minfo.p2m_table)[i];
+#ifdef __x86_64__
+ if ( mfn == ~0U ) /* Expand a 32bit guest's idea of INVALID_MFN */
+ mfn = ~0UL;
+#endif
+ }
- case XEN_DOMCTL_PFINFO_L3TAB:
- printf(" L3 table");
- break;
+ printf(" pfn=0x%lx ==> mfn=0x%lx (type 0x%lx)", i, mfn,
+ pagetype >> XEN_DOMCTL_PFINFO_LTAB_SHIFT);
- case XEN_DOMCTL_PFINFO_L4TAB:
- printf(" L4 table");
- break;
+ switch ( pagetype >> XEN_DOMCTL_PFINFO_LTAB_SHIFT )
+ {
+ case 0x0: /* NOTAB */
+ printf("\n");
+ break;
+ case 0x1 ... 0x4: /* L1 -> L4 */
+ printf(" L%lu\n", pagetype >> XEN_DOMCTL_PFINFO_LTAB_SHIFT);
+ break;
+ case 0x9 ... 0xc: /* Pinned L1 -> L4 */
+ printf(" pinned L%lu\n",
+ (pagetype >> XEN_DOMCTL_PFINFO_LTAB_SHIFT) & 7);
+ break;
+ case 0xd: /* BROKEN */
+ printf(" broken\n");
+ break;
+ case 0xe: /* XALLOC */
+ printf(" xalloc\n");
+ break;
+ case 0xf: /* XTAB */
+ printf(" invalid\n");
+ break;
+ default:
+ printf(" <invalid type>\n");
+ break;
}
-
- printf("\n");
}
printf(" --- End of P2M for domain %d ---\n", domid);
@@ -401,7 +405,7 @@ int main(int argc, char *argv[])
xch = xc_interface_open(0, 0, 0);
if ( !xch )
{
- ERROR("Failed to open an xc handler");
+ fprintf(stderr, "Failed to open an xc handler");
return 1;
}
diff --git a/tools/misc/xen-python-path b/tools/misc/xen-python-path
deleted file mode 100644
index 073abae..0000000
--- a/tools/misc/xen-python-path
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env python
-# -*- mode: python; -*-
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2007 XenSource Inc.
-#============================================================================
-
-# Nowadays we install xen in the standard python site-packages
-# directories. This script is still provided for the benefit of old
-# out-of-xen-tree callers. It is deprecated and will be removed.
-
-print '/dev/enoent/xen/python-path'
diff --git a/tools/misc/xenpm.c b/tools/misc/xenpm.c
index 2e57f1f..e43924c 100644
--- a/tools/misc/xenpm.c
+++ b/tools/misc/xenpm.c
@@ -29,6 +29,9 @@
#include <inttypes.h>
#include <sys/time.h>
+#define MAX_PKG_RESIDENCIES 12
+#define MAX_CORE_RESIDENCIES 8
+
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
static xc_interface *xc_handle;
@@ -102,7 +105,7 @@ static void parse_cpuid_and_int(int argc, char *argv[],
static void print_cxstat(int cpuid, struct xc_cx_stat *cxstat)
{
- int i;
+ unsigned int i;
printf("cpu id : %d\n", cpuid);
printf("total C-states : %d\n", cxstat->nr);
@@ -115,17 +118,14 @@ static void print_cxstat(int cpuid, struct xc_cx_stat *cxstat)
printf(" residency [%20"PRIu64" ms]\n",
cxstat->residencies[i]/1000000UL);
}
- printf("pc2 : [%20"PRIu64" ms]\n"
- "pc3 : [%20"PRIu64" ms]\n"
- "pc6 : [%20"PRIu64" ms]\n"
- "pc7 : [%20"PRIu64" ms]\n",
- cxstat->pc2/1000000UL, cxstat->pc3/1000000UL,
- cxstat->pc6/1000000UL, cxstat->pc7/1000000UL);
- printf("cc3 : [%20"PRIu64" ms]\n"
- "cc6 : [%20"PRIu64" ms]\n"
- "cc7 : [%20"PRIu64" ms]\n",
- cxstat->cc3/1000000UL, cxstat->cc6/1000000UL,
- cxstat->cc7/1000000UL);
+ for ( i = 0; i < MAX_PKG_RESIDENCIES && i < cxstat->nr_pc; ++i )
+ if ( cxstat->pc[i] )
+ printf("pc%d : [%20"PRIu64" ms]\n", i + 1,
+ cxstat->pc[i] / 1000000UL);
+ for ( i = 0; i < MAX_CORE_RESIDENCIES && i < cxstat->nr_cc; ++i )
+ if ( cxstat->cc[i] )
+ printf("cc%d : [%20"PRIu64" ms]\n", i + 1,
+ cxstat->cc[i] / 1000000UL);
printf("\n");
}
@@ -145,24 +145,36 @@ static int get_cxstat_by_cpuid(xc_interface *xc_handle, int cpuid, struct xc_cx_
if ( !max_cx_num )
return -ENODEV;
- cxstat->triggers = malloc(max_cx_num * sizeof(uint64_t));
- if ( !cxstat->triggers )
- return -ENOMEM;
- cxstat->residencies = malloc(max_cx_num * sizeof(uint64_t));
- if ( !cxstat->residencies )
+ cxstat->triggers = calloc(max_cx_num, sizeof(*cxstat->triggers));
+ cxstat->residencies = calloc(max_cx_num, sizeof(*cxstat->residencies));
+ cxstat->pc = calloc(MAX_PKG_RESIDENCIES, sizeof(*cxstat->pc));
+ cxstat->cc = calloc(MAX_CORE_RESIDENCIES, sizeof(*cxstat->cc));
+ if ( !cxstat->triggers || !cxstat->residencies ||
+ !cxstat->pc || !cxstat->cc )
{
+ free(cxstat->cc);
+ free(cxstat->pc);
+ free(cxstat->residencies);
free(cxstat->triggers);
return -ENOMEM;
}
+ cxstat->nr = max_cx_num;
+ cxstat->nr_pc = MAX_PKG_RESIDENCIES;
+ cxstat->nr_cc = MAX_CORE_RESIDENCIES;
+
ret = xc_pm_get_cxstat(xc_handle, cpuid, cxstat);
if( ret )
{
ret = -errno;
free(cxstat->triggers);
free(cxstat->residencies);
+ free(cxstat->pc);
+ free(cxstat->cc);
cxstat->triggers = NULL;
cxstat->residencies = NULL;
+ cxstat->pc = NULL;
+ cxstat->cc = NULL;
}
return ret;
@@ -198,6 +210,8 @@ static int show_cxstat_by_cpuid(xc_interface *xc_handle, int cpuid)
free(cxstatinfo.triggers);
free(cxstatinfo.residencies);
+ free(cxstatinfo.pc);
+ free(cxstatinfo.cc);
return 0;
}
@@ -482,25 +496,26 @@ static void signal_int_handler(int signo)
/* print out CC? and PC? */
for ( i = 0; i < socket_nr; i++ )
{
+ unsigned int n;
uint64_t res;
+
for ( j = 0; j <= info.max_cpu_index; j++ )
{
if ( cpu_to_socket[j] == socket_ids[i] )
break;
}
printf("\nSocket %d\n", socket_ids[i]);
- res = cxstat_end[j].pc2 - cxstat_start[j].pc2;
- printf("\tPC2\t%"PRIu64" ms\t%.2f%%\n", res / 1000000UL,
- 100UL * res / (double)sum_cx[j]);
- res = cxstat_end[j].pc3 - cxstat_start[j].pc3;
- printf("\tPC3\t%"PRIu64" ms\t%.2f%%\n", res / 1000000UL,
- 100UL * res / (double)sum_cx[j]);
- res = cxstat_end[j].pc6 - cxstat_start[j].pc6;
- printf("\tPC6\t%"PRIu64" ms\t%.2f%%\n", res / 1000000UL,
- 100UL * res / (double)sum_cx[j]);
- res = cxstat_end[j].pc7 - cxstat_start[j].pc7;
- printf("\tPC7\t%"PRIu64" ms\t%.2f%%\n", res / 1000000UL,
- 100UL * res / (double)sum_cx[j]);
+ for ( n = 0; n < MAX_PKG_RESIDENCIES; ++n )
+ {
+ if ( n >= cxstat_end[j].nr_pc )
+ continue;
+ res = cxstat_end[j].pc[n];
+ if ( n < cxstat_start[j].nr_pc )
+ res -= cxstat_start[j].pc[n];
+ printf("\tPC%u\t%"PRIu64" ms\t%.2f%%\n",
+ n + 1, res / 1000000UL,
+ 100UL * res / (double)sum_cx[j]);
+ }
for ( k = 0; k < core_nr; k++ )
{
for ( j = 0; j <= info.max_cpu_index; j++ )
@@ -510,15 +525,17 @@ static void signal_int_handler(int signo)
break;
}
printf("\t Core %d CPU %d\n", core_ids[k], j);
- res = cxstat_end[j].cc3 - cxstat_start[j].cc3;
- printf("\t\tCC3\t%"PRIu64" ms\t%.2f%%\n", res / 1000000UL,
- 100UL * res / (double)sum_cx[j]);
- res = cxstat_end[j].cc6 - cxstat_start[j].cc6;
- printf("\t\tCC6\t%"PRIu64" ms\t%.2f%%\n", res / 1000000UL,
- 100UL * res / (double)sum_cx[j]);
- res = cxstat_end[j].cc7 - cxstat_start[j].cc7;
- printf("\t\tCC7\t%"PRIu64" ms\t%.2f%%\n", res / 1000000UL,
- 100UL * res / (double)sum_cx[j]);
+ for ( n = 0; n < MAX_CORE_RESIDENCIES; ++n )
+ {
+ if ( n >= cxstat_end[j].nr_cc )
+ continue;
+ res = cxstat_end[j].cc[n];
+ if ( n < cxstat_start[j].nr_cc )
+ res -= cxstat_start[j].cc[n];
+ printf("\t\tCC%u\t%"PRIu64" ms\t%.2f%%\n",
+ n + 1, res / 1000000UL,
+ 100UL * res / (double)sum_cx[j]);
+ }
}
}
}
@@ -529,6 +546,8 @@ static void signal_int_handler(int signo)
{
free(cxstat[i].triggers);
free(cxstat[i].residencies);
+ free(cxstat[i].pc);
+ free(cxstat[i].cc);
free(pxstat[i].trans_pt);
free(pxstat[i].pt);
}
diff --git a/tools/ocaml/Makefile b/tools/ocaml/Makefile
index 8e4ca36..5710a5f 100644
--- a/tools/ocaml/Makefile
+++ b/tools/ocaml/Makefile
@@ -1,9 +1,12 @@
XEN_ROOT = $(CURDIR)/../..
include $(XEN_ROOT)/tools/Rules.mk
-SUBDIRS_PROGRAMS = xenstored test
+SUBDIRS := libs
+SUBDIRS += xenstored
-SUBDIRS = libs $(SUBDIRS_PROGRAMS)
+ifeq ($(CONFIG_TESTS),y)
+SUBDIRS += test
+endif
.NOTPARALLEL:
# targets here must be run in order, otherwise we can try
diff --git a/tools/ocaml/libs/eventchn/xeneventchn.mli b/tools/ocaml/libs/eventchn/xeneventchn.mli
index e4e02a4..e180145 100644
--- a/tools/ocaml/libs/eventchn/xeneventchn.mli
+++ b/tools/ocaml/libs/eventchn/xeneventchn.mli
@@ -14,7 +14,7 @@
* GNU Lesser General Public License for more details.
*)
-(** Event channel bindings: see tools/libxc/xenctrl.h *)
+(** Event channel bindings: see tools/libxc/include/xenctrl.h *)
type handle
(** An initialised event channel interface. *)
diff --git a/tools/ocaml/libs/xb/Makefile b/tools/ocaml/libs/xb/Makefile
index 62ffefb..09d1bc8 100644
--- a/tools/ocaml/libs/xb/Makefile
+++ b/tools/ocaml/libs/xb/Makefile
@@ -5,6 +5,7 @@ include $(TOPLEVEL)/common.make
CFLAGS += -I../mmap
CFLAGS += $(CFLAGS_libxenctrl) # For xen_mb()
CFLAGS += $(CFLAGS_xeninclude)
+CFLAGS += $(APPEND_CFLAGS)
OCAMLINCLUDE += -I ../mmap
OCAMLOPTFLAGS += -for-pack Xenbus
diff --git a/tools/ocaml/libs/xb/xb.ml b/tools/ocaml/libs/xb/xb.ml
index 29d354d..50944b5 100644
--- a/tools/ocaml/libs/xb/xb.ml
+++ b/tools/ocaml/libs/xb/xb.ml
@@ -21,6 +21,10 @@ exception End_of_file
exception Eagain
exception Noent
exception Invalid
+exception Reconnect
+
+let _ =
+ Callback.register_exception "Xb.Reconnect" Reconnect
type backend_mmap =
{
@@ -50,6 +54,19 @@ type t =
let init_partial_in () = NoHdr
(Partial.header_size (), String.make (Partial.header_size()) '\000')
+let reconnect t = match t.backend with
+ | Fd _ ->
+ (* should never happen, so close the connection *)
+ raise End_of_file
+ | Xenmmap backend ->
+ Xs_ring.close backend.mmap;
+ backend.eventchn_notify ();
+ (* Clear our old connection state *)
+ Queue.clear t.pkt_in;
+ Queue.clear t.pkt_out;
+ t.partial_in <- init_partial_in ();
+ t.partial_out <- ""
+
let queue con pkt = Queue.push pkt con.pkt_out
let read_fd back con s len =
@@ -84,6 +101,7 @@ let write con s len =
| Fd backfd -> write_fd backfd con s len
| Xenmmap backmmap -> write_mmap backmmap con s len
+(* NB: can throw Reconnect *)
let output con =
(* get the output string from a string_of(packet) or partial_out *)
let s = if String.length con.partial_out > 0 then
@@ -102,6 +120,7 @@ let output con =
(* after sending one packet, partial is empty *)
con.partial_out = ""
+(* NB: can throw Reconnect *)
let input con =
let newpacket = ref false in
let to_read =
@@ -145,6 +164,8 @@ let newcon backend = {
let open_fd fd = newcon (Fd { fd = fd; })
let open_mmap mmap notifyfct =
+ (* Advertise XENSTORE_SERVER_FEATURE_RECONNECTION *)
+ Xs_ring.set_server_features mmap (Xs_ring.Server_features.singleton Xs_ring.Server_feature.Reconnection);
newcon (Xenmmap {
mmap = mmap;
eventchn_notify = notifyfct;
diff --git a/tools/ocaml/libs/xb/xb.mli b/tools/ocaml/libs/xb/xb.mli
index 58234ae..4e1f833 100644
--- a/tools/ocaml/libs/xb/xb.mli
+++ b/tools/ocaml/libs/xb/xb.mli
@@ -23,7 +23,7 @@ module Op :
| Resume
| Set_target
| Restrict
- | Invalid (* Not a valid wire operation *)
+ | Invalid
val operation_c_mapping : operation array
val size : int
val array_search : 'a -> 'a array -> int
@@ -57,6 +57,7 @@ exception End_of_file
exception Eagain
exception Noent
exception Invalid
+exception Reconnect
type backend_mmap = {
mmap : Xenmmap.mmap_interface;
eventchn_notify : unit -> unit;
@@ -73,6 +74,7 @@ type t = {
mutable partial_out : string;
}
val init_partial_in : unit -> partial_buf
+val reconnect : t -> unit
val queue : t -> Packet.t -> unit
val read_fd : backend_fd -> 'a -> string -> int -> int
val read_mmap : backend_mmap -> 'a -> string -> int -> int
diff --git a/tools/ocaml/libs/xb/xs_ring.ml b/tools/ocaml/libs/xb/xs_ring.ml
index 9469609..48e06f4 100644
--- a/tools/ocaml/libs/xb/xs_ring.ml
+++ b/tools/ocaml/libs/xb/xs_ring.ml
@@ -14,5 +14,33 @@
* GNU Lesser General Public License for more details.
*)
+module Server_feature = struct
+ type t =
+ | Reconnection
+end
+
+module Server_features = Set.Make(struct
+ type t = Server_feature.t
+ let compare = compare
+end)
+
external read: Xenmmap.mmap_interface -> string -> int -> int = "ml_interface_read"
external write: Xenmmap.mmap_interface -> string -> int -> int = "ml_interface_write"
+
+external _internal_set_server_features: Xenmmap.mmap_interface -> int -> unit = "ml_interface_set_server_features" "noalloc"
+external _internal_get_server_features: Xenmmap.mmap_interface -> int = "ml_interface_get_server_features" "noalloc"
+
+
+let get_server_features mmap =
+ (* NB only one feature currently defined above *)
+ let x = _internal_get_server_features mmap in
+ if x = 0
+ then Server_features.empty
+ else Server_features.singleton Server_feature.Reconnection
+
+let set_server_features mmap set =
+ (* NB only one feature currently defined above *)
+ let x = if set = Server_features.empty then 0 else 1 in
+ _internal_set_server_features mmap x
+
+external close: Xenmmap.mmap_interface -> unit = "ml_interface_close" "noalloc"
diff --git a/tools/ocaml/libs/xb/xs_ring_stubs.c b/tools/ocaml/libs/xb/xs_ring_stubs.c
index 8bd1047..fc9b0c5 100644
--- a/tools/ocaml/libs/xb/xs_ring_stubs.c
+++ b/tools/ocaml/libs/xb/xs_ring_stubs.c
@@ -20,6 +20,7 @@
#include <unistd.h>
#include <errno.h>
#include <string.h>
+#include <stdint.h>
#include <xenctrl.h>
#include <xen/io/xs_wire.h>
@@ -35,22 +36,39 @@
#define GET_C_STRUCT(a) ((struct mmap_interface *) a)
-static int xs_ring_read(struct mmap_interface *interface,
- char *buffer, int len)
+CAMLprim value ml_interface_read(value ml_interface,
+ value ml_buffer,
+ value ml_len)
{
+ CAMLparam3(ml_interface, ml_buffer, ml_len);
+ CAMLlocal1(ml_result);
+
+ struct mmap_interface *interface = GET_C_STRUCT(ml_interface);
+ char *buffer = String_val(ml_buffer);
+ int len = Int_val(ml_len);
+ int result;
+
struct xenstore_domain_interface *intf = interface->addr;
XENSTORE_RING_IDX cons, prod; /* offsets only */
int to_read;
+ uint32_t connection;
+
+ cons = *(volatile uint32_t*)&intf->req_cons;
+ prod = *(volatile uint32_t*)&intf->req_prod;
+ connection = *(volatile uint32*)&intf->connection;
+
+ if (connection != XENSTORE_CONNECTED)
+ caml_raise_constant(*caml_named_value("Xb.Reconnect"));
- cons = *(volatile uint32*)&intf->req_cons;
- prod = *(volatile uint32*)&intf->req_prod;
xen_mb();
if ((prod - cons) > XENSTORE_RING_SIZE)
- return -1;
+ caml_failwith("bad connection");
- if (prod == cons)
- return 0;
+ if (prod == cons) {
+ result = 0;
+ goto exit;
+ }
cons = MASK_XENSTORE_IDX(cons);
prod = MASK_XENSTORE_IDX(prod);
if (prod > cons)
@@ -62,21 +80,41 @@ static int xs_ring_read(struct mmap_interface *interface,
memcpy(buffer, intf->req + cons, len);
xen_mb();
intf->req_cons += len;
- return len;
+ result = len;
+exit:
+ ml_result = Val_int(result);
+ CAMLreturn(ml_result);
}
-static int xs_ring_write(struct mmap_interface *interface,
- char *buffer, int len)
+CAMLprim value ml_interface_write(value ml_interface,
+ value ml_buffer,
+ value ml_len)
{
+ CAMLparam3(ml_interface, ml_buffer, ml_len);
+ CAMLlocal1(ml_result);
+
+ struct mmap_interface *interface = GET_C_STRUCT(ml_interface);
+ char *buffer = String_val(ml_buffer);
+ int len = Int_val(ml_len);
+ int result;
+
struct xenstore_domain_interface *intf = interface->addr;
XENSTORE_RING_IDX cons, prod;
int can_write;
+ uint32_t connection;
+
+ cons = *(volatile uint32_t*)&intf->rsp_cons;
+ prod = *(volatile uint32_t*)&intf->rsp_prod;
+ connection = *(volatile uint32*)&intf->connection;
+
+ if (connection != XENSTORE_CONNECTED)
+ caml_raise_constant(*caml_named_value("Xb.Reconnect"));
- cons = *(volatile uint32*)&intf->rsp_cons;
- prod = *(volatile uint32*)&intf->rsp_prod;
xen_mb();
- if ( (prod - cons) >= XENSTORE_RING_SIZE )
- return 0;
+ if ( (prod - cons) >= XENSTORE_RING_SIZE ) {
+ result = 0;
+ goto exit;
+ }
if (MASK_XENSTORE_IDX(prod) >= MASK_XENSTORE_IDX(cons))
can_write = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
else
@@ -86,31 +124,43 @@ static int xs_ring_write(struct mmap_interface *interface,
memcpy(intf->rsp + MASK_XENSTORE_IDX(prod), buffer, len);
xen_mb();
intf->rsp_prod += len;
- return len;
+ result = len;
+exit:
+ ml_result = Val_int(result);
+ CAMLreturn(ml_result);
}
-CAMLprim value ml_interface_read(value interface, value buffer, value len)
+CAMLprim value ml_interface_set_server_features(value interface, value v)
{
- CAMLparam3(interface, buffer, len);
- CAMLlocal1(result);
- int res;
+ CAMLparam2(interface, v);
+ struct xenstore_domain_interface *intf = GET_C_STRUCT(interface)->addr;
- res = xs_ring_read(GET_C_STRUCT(interface),
- String_val(buffer), Int_val(len));
- if (res == -1)
- caml_failwith("bad connection");
- result = Val_int(res);
- CAMLreturn(result);
+ intf->server_features = Int_val(v);
+
+ CAMLreturn(Val_unit);
+}
+
+CAMLprim value ml_interface_get_server_features(value interface)
+{
+ CAMLparam1(interface);
+ struct xenstore_domain_interface *intf = GET_C_STRUCT(interface)->addr;
+
+ CAMLreturn(Val_int (intf->server_features));
}
-CAMLprim value ml_interface_write(value interface, value buffer, value len)
+CAMLprim value ml_interface_close(value interface)
{
- CAMLparam3(interface, buffer, len);
- CAMLlocal1(result);
- int res;
-
- res = xs_ring_write(GET_C_STRUCT(interface),
- String_val(buffer), Int_val(len));
- result = Val_int(res);
- CAMLreturn(result);
+ CAMLparam1(interface);
+ struct xenstore_domain_interface *intf = GET_C_STRUCT(interface)->addr;
+ int i;
+
+ intf->req_cons = intf->req_prod = intf->rsp_cons = intf->rsp_prod = 0;
+ /* Ensure the unused space is full of invalid xenstore packets. */
+ for (i = 0; i < XENSTORE_RING_SIZE; i++) {
+ intf->req[i] = 0xff; /* XS_INVALID = 0xffff */
+ intf->rsp[i] = 0xff;
+ }
+ xen_mb ();
+ intf->connection = XENSTORE_CONNECTED;
+ CAMLreturn(Val_unit);
}
diff --git a/tools/ocaml/libs/xc/Makefile b/tools/ocaml/libs/xc/Makefile
index 239c187..d24b014 100644
--- a/tools/ocaml/libs/xc/Makefile
+++ b/tools/ocaml/libs/xc/Makefile
@@ -3,6 +3,7 @@ XEN_ROOT=$(TOPLEVEL)/../..
include $(TOPLEVEL)/common.make
CFLAGS += -I../mmap $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest)
+CFLAGS += $(APPEND_CFLAGS)
OCAMLINCLUDE += -I ../mmap
OBJS = xenctrl
diff --git a/tools/ocaml/libs/xc/xenctrl_stubs.c b/tools/ocaml/libs/xc/xenctrl_stubs.c
index ff29b47..f0810eb 100644
--- a/tools/ocaml/libs/xc/xenctrl_stubs.c
+++ b/tools/ocaml/libs/xc/xenctrl_stubs.c
@@ -438,7 +438,9 @@ CAMLprim value stub_xc_vcpu_setaffinity(value xch, value domid,
c_cpumap[i/8] |= 1 << (i&7);
}
retval = xc_vcpu_setaffinity(_H(xch), _D(domid),
- Int_val(vcpu), c_cpumap);
+ Int_val(vcpu),
+ c_cpumap, NULL,
+ XEN_VCPUAFFINITY_HARD);
free(c_cpumap);
if (retval < 0)
@@ -460,7 +462,9 @@ CAMLprim value stub_xc_vcpu_getaffinity(value xch, value domid,
failwith_xc(_H(xch));
retval = xc_vcpu_getaffinity(_H(xch), _D(domid),
- Int_val(vcpu), c_cpumap);
+ Int_val(vcpu),
+ c_cpumap, NULL,
+ XEN_VCPUAFFINITY_HARD);
if (retval < 0) {
free(c_cpumap);
failwith_xc(_H(xch));
diff --git a/tools/ocaml/libs/xentoollog/Makefile b/tools/ocaml/libs/xentoollog/Makefile
index 471b428..666eb66 100644
--- a/tools/ocaml/libs/xentoollog/Makefile
+++ b/tools/ocaml/libs/xentoollog/Makefile
@@ -6,6 +6,7 @@ include $(TOPLEVEL)/common.make
CFLAGS += -Wno-declaration-after-statement
CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest)
+CFLAGS += $(APPEND_CFLAGS)
OCAMLINCLUDE +=
OBJS = xentoollog
@@ -48,7 +49,7 @@ xentoollog.mli: xentoollog.mli.in _xtl_levels.mli.in
libs: $(LIBS)
-_xtl_levels.ml.in _xtl_levels.mli.in _xtl_levels.inc: genlevels.py $(XEN_ROOT)/tools/libxc/xentoollog.h
+_xtl_levels.ml.in _xtl_levels.mli.in _xtl_levels.inc: genlevels.py $(XEN_ROOT)/tools/libxc/include/xentoollog.h
$(PYTHON) genlevels.py _xtl_levels.mli.in _xtl_levels.ml.in _xtl_levels.inc
.PHONY: install
diff --git a/tools/ocaml/libs/xentoollog/genlevels.py b/tools/ocaml/libs/xentoollog/genlevels.py
index 6b42f21..65d334f 100755
--- a/tools/ocaml/libs/xentoollog/genlevels.py
+++ b/tools/ocaml/libs/xentoollog/genlevels.py
@@ -3,7 +3,7 @@
import sys
def read_levels():
- f = open('../../../libxc/xentoollog.h', 'r')
+ f = open('../../../libxc/include/xentoollog.h', 'r')
levels = []
record = False
diff --git a/tools/ocaml/libs/xl/Makefile b/tools/ocaml/libs/xl/Makefile
index 61eb44c..0d1549d 100644
--- a/tools/ocaml/libs/xl/Makefile
+++ b/tools/ocaml/libs/xl/Makefile
@@ -7,6 +7,7 @@ CFLAGS += -Wno-unused -Wno-declaration-after-statement
CFLAGS += $(CFLAGS_libxenlight)
CFLAGS += -I ../xentoollog
+CFLAGS += $(APPEND_CFLAGS)
OBJS = xenlight
INTF = xenlight.cmi
diff --git a/tools/ocaml/libs/xl/genwrap.py b/tools/ocaml/libs/xl/genwrap.py
index 5e43831..402e489 100644
--- a/tools/ocaml/libs/xl/genwrap.py
+++ b/tools/ocaml/libs/xl/genwrap.py
@@ -18,6 +18,7 @@ builtins = {
"libxl_string_list": ("string list", "libxl_string_list_val(&%(c)s, %(o)s)", "Val_string_list(&%(c)s)"),
"libxl_mac": ("int array", "Mac_val(&%(c)s, %(o)s)", "Val_mac(&%(c)s)"),
"libxl_hwcap": ("int32 array", None, "Val_hwcap(&%(c)s)"),
+ "libxl_ms_vm_genid": ("int array", "Ms_vm_genid_val(&%(c)s, %(o)s)", "Val_ms_vm_genid(&%(c)s)"),
# The following needs to be sorted out later
"libxl_cpuid_policy_list": ("unit", "%(c)s = 0", "Val_unit"),
}
diff --git a/tools/ocaml/libs/xl/xenlight_stubs.c b/tools/ocaml/libs/xl/xenlight_stubs.c
index 8e825ae..4133527 100644
--- a/tools/ocaml/libs/xl/xenlight_stubs.c
+++ b/tools/ocaml/libs/xl/xenlight_stubs.c
@@ -370,6 +370,31 @@ static value Val_hwcap(libxl_hwcap *c_val)
CAMLreturn(hwcap);
}
+static value Val_ms_vm_genid (libxl_ms_vm_genid *c_val)
+{
+ CAMLparam0();
+ CAMLlocal1(v);
+ int i;
+
+ v = caml_alloc_tuple(LIBXL_MS_VM_GENID_LEN);
+
+ for(i=0; i<LIBXL_MS_VM_GENID_LEN; i++)
+ Store_field(v, i, Val_int(c_val->bytes[i]));
+
+ CAMLreturn(v);
+}
+
+static int Ms_vm_genid_val(libxl_ms_vm_genid *c_val, value v)
+{
+ CAMLparam1(v);
+ int i;
+
+ for(i=0; i<LIBXL_MS_VM_GENID_LEN; i++)
+ c_val->bytes[i] = Int_val(Field(v, i));
+
+ CAMLreturn(0);
+}
+
static value Val_string_option(const char *c_val)
{
CAMLparam0();
diff --git a/tools/ocaml/test/Makefile b/tools/ocaml/test/Makefile
index 8033089..b75726f 100644
--- a/tools/ocaml/test/Makefile
+++ b/tools/ocaml/test/Makefile
@@ -3,6 +3,7 @@ OCAML_TOPLEVEL = $(CURDIR)/..
include $(OCAML_TOPLEVEL)/common.make
CFLAGS += $(CFLAGS_libxenlight)
+CFLAGS += $(APPEND_CFLAGS)
LIBS_xenlight = $(LDLIBS_libxenlight)
OCAMLINCLUDE += \
diff --git a/tools/ocaml/xenstored/Makefile b/tools/ocaml/xenstored/Makefile
index b18f190..48f1079 100644
--- a/tools/ocaml/xenstored/Makefile
+++ b/tools/ocaml/xenstored/Makefile
@@ -2,16 +2,32 @@ XEN_ROOT = $(CURDIR)/../../..
OCAML_TOPLEVEL = $(CURDIR)/..
include $(OCAML_TOPLEVEL)/common.make
+CFLAGS += -I$(XEN_ROOT)/tools/
+CFLAGS-$(CONFIG_SYSTEMD) += $(SYSTEMD_CFLAGS)
+LDFLAGS-$(CONFIG_SYSTEMD) += $(SYSTEMD_LIBS)
+
+CFLAGS += $(CFLAGS-y)
+CFLAGS += $(APPEND_CFLAGS)
+LDFLAGS += $(LDFLAGS-y)
+LDFLAGS += $(APPEND_LDFLAGS)
+
OCAMLINCLUDE += \
-I $(OCAML_TOPLEVEL)/libs/xb \
-I $(OCAML_TOPLEVEL)/libs/mmap \
-I $(OCAML_TOPLEVEL)/libs/xc \
-I $(OCAML_TOPLEVEL)/libs/eventchn
-LIBS = syslog.cma syslog.cmxa
+LIBS = syslog.cma syslog.cmxa select.cma select.cmxa
syslog_OBJS = syslog
syslog_C_OBJS = syslog_stubs
-OCAML_LIBRARY = syslog
+select_OBJS = select
+select_C_OBJS = select_stubs
+OCAML_LIBRARY = syslog select
+
+LIBS += systemd.cma systemd.cmxa
+systemd_OBJS = systemd
+systemd_C_OBJS = systemd_stubs
+OCAML_LIBRARY += systemd
OBJS = define \
stdext \
@@ -34,11 +50,13 @@ OBJS = define \
process \
xenstored
-INTF = symbol.cmi trie.cmi syslog.cmi
+INTF = symbol.cmi trie.cmi syslog.cmi systemd.cmi select.cmi
XENSTOREDLIBS = \
unix.cmxa \
-ccopt -L -ccopt . syslog.cmxa \
+ -ccopt -L -ccopt . systemd.cmxa \
+ -ccopt -L -ccopt . select.cmxa \
-ccopt -L -ccopt $(OCAML_TOPLEVEL)/libs/mmap $(OCAML_TOPLEVEL)/libs/mmap/xenmmap.cmxa \
-ccopt -L -ccopt $(OCAML_TOPLEVEL)/libs/eventchn $(OCAML_TOPLEVEL)/libs/eventchn/xeneventchn.cmxa \
-ccopt -L -ccopt $(OCAML_TOPLEVEL)/libs/xc $(OCAML_TOPLEVEL)/libs/xc/xenctrl.cmxa \
diff --git a/tools/ocaml/xenstored/connection.ml b/tools/ocaml/xenstored/connection.ml
index 47695f8..b4dc9cb 100644
--- a/tools/ocaml/xenstored/connection.ml
+++ b/tools/ocaml/xenstored/connection.ml
@@ -45,6 +45,20 @@ let mark_as_bad con =
|None -> ()
| Some domain -> Domain.mark_as_bad domain
+let initial_next_tid = 1
+
+let reconnect con =
+ Xenbus.Xb.reconnect con.xb;
+ (* dom is the same *)
+ Hashtbl.clear con.transactions;
+ con.next_tid <- initial_next_tid;
+ Hashtbl.clear con.watches;
+ (* anonid is the same *)
+ con.nb_watches <- 0;
+ con.stat_nb_ops <- 0;
+ (* perm is the same *)
+ ()
+
let get_path con =
Printf.sprintf "/local/domain/%i/" (match con.dom with None -> 0 | Some d -> Domain.get_id d)
@@ -89,7 +103,7 @@ let create xbcon dom =
xb = xbcon;
dom = dom;
transactions = Hashtbl.create 5;
- next_tid = 1;
+ next_tid = initial_next_tid;
watches = Hashtbl.create 8;
nb_watches = 0;
anonid = id;
@@ -223,10 +237,14 @@ let pop_in con = Xenbus.Xb.get_in_packet con.xb
let has_more_input con = Xenbus.Xb.has_more_input con.xb
let has_output con = Xenbus.Xb.has_output con.xb
+let has_old_output con = Xenbus.Xb.has_old_output con.xb
let has_new_output con = Xenbus.Xb.has_new_output con.xb
let peek_output con = Xenbus.Xb.peek_output con.xb
let do_output con = Xenbus.Xb.output con.xb
+let has_more_work con =
+ has_more_input con || not (has_old_output con) && has_new_output con
+
let incr_ops con = con.stat_nb_ops <- con.stat_nb_ops + 1
let mark_symbols con =
diff --git a/tools/ocaml/xenstored/connections.ml b/tools/ocaml/xenstored/connections.ml
index f4550f9..f9bc225 100644
--- a/tools/ocaml/xenstored/connections.ml
+++ b/tools/ocaml/xenstored/connections.ml
@@ -18,35 +18,47 @@
let debug fmt = Logging.debug "connections" fmt
type t = {
- mutable anonymous: Connection.t list;
+ anonymous: (Unix.file_descr, Connection.t) Hashtbl.t;
domains: (int, Connection.t) Hashtbl.t;
+ ports: (Xeneventchn.t, Connection.t) Hashtbl.t;
mutable watches: (string, Connection.watch list) Trie.t;
}
-let create () = { anonymous = []; domains = Hashtbl.create 8; watches = Trie.create () }
+let create () = {
+ anonymous = Hashtbl.create 37;
+ domains = Hashtbl.create 37;
+ ports = Hashtbl.create 37;
+ watches = Trie.create ()
+}
let add_anonymous cons fd can_write =
let xbcon = Xenbus.Xb.open_fd fd in
let con = Connection.create xbcon None in
- cons.anonymous <- con :: cons.anonymous
+ Hashtbl.add cons.anonymous (Xenbus.Xb.get_fd xbcon) con
let add_domain cons dom =
let xbcon = Xenbus.Xb.open_mmap (Domain.get_interface dom) (fun () -> Domain.notify dom) in
let con = Connection.create xbcon (Some dom) in
- Hashtbl.add cons.domains (Domain.get_id dom) con
+ Hashtbl.add cons.domains (Domain.get_id dom) con;
+ match Domain.get_port dom with
+ | Some p -> Hashtbl.add cons.ports p con;
+ | None -> ()
let select cons =
- let inset = List.map (fun c -> Connection.get_fd c) cons.anonymous
- and outset = List.fold_left (fun l c -> if Connection.has_output c
- then Connection.get_fd c :: l
- else l) [] cons.anonymous in
- inset, outset
+ Hashtbl.fold
+ (fun _ con (ins, outs) ->
+ let fd = Connection.get_fd con in
+ (fd :: ins, if Connection.has_output con then fd :: outs else outs))
+ cons.anonymous ([], [])
+
+let find cons =
+ Hashtbl.find cons.anonymous
-let find cons fd =
- List.find (fun c -> Connection.get_fd c = fd) cons.anonymous
+let find_domain cons =
+ Hashtbl.find cons.domains
-let find_domain cons id =
- Hashtbl.find cons.domains id
+let find_domain_by_port cons port =
+ Hashtbl.find cons.ports port
let del_watches_of_con con watches =
match List.filter (fun w -> Connection.get_con w != con) watches with
@@ -55,7 +67,7 @@ let del_watches_of_con con watches =
let del_anonymous cons con =
try
- cons.anonymous <- Utils.list_remove con cons.anonymous;
+ Hashtbl.remove cons.anonymous (Connection.get_fd con);
cons.watches <- Trie.map (del_watches_of_con con) cons.watches;
Connection.close con
with exn ->
@@ -65,6 +77,12 @@ let del_domain cons id =
try
let con = find_domain cons id in
Hashtbl.remove cons.domains id;
+ (match Connection.get_domain con with
+ | Some d ->
+ (match Domain.get_port d with
+ | Some p -> Hashtbl.remove cons.ports p
+ | None -> ())
+ | None -> ());
cons.watches <- Trie.map (del_watches_of_con con) cons.watches;
Connection.close con
with exn ->
@@ -74,17 +92,16 @@ let iter_domains cons fct =
Hashtbl.iter (fun k c -> fct c) cons.domains
let iter_anonymous cons fct =
- List.iter (fun c -> fct c) (List.rev cons.anonymous)
+ Hashtbl.iter (fun _ c -> fct c) cons.anonymous
let iter cons fct =
iter_domains cons fct; iter_anonymous cons fct
let has_more_work cons =
- Hashtbl.fold (fun id con acc ->
- if Connection.has_more_input con then
- con :: acc
- else
- acc) cons.domains []
+ Hashtbl.fold
+ (fun id con acc ->
+ if Connection.has_more_work con then con :: acc else acc)
+ cons.domains []
let key_of_str path =
if path.[0] = '@'
@@ -163,10 +180,10 @@ let stats cons =
nb_ops_dom := !nb_ops_dom + con_ops;
nb_watchs_dom := !nb_watchs_dom + con_watchs;
);
- (List.length cons.anonymous, !nb_ops_anon, !nb_watchs_anon,
+ (Hashtbl.length cons.anonymous, !nb_ops_anon, !nb_watchs_anon,
Hashtbl.length cons.domains, !nb_ops_dom, !nb_watchs_dom)
let debug cons =
- let anonymous = List.map Connection.debug cons.anonymous in
+ let anonymous = Hashtbl.fold (fun _ con accu -> Connection.debug con :: accu) cons.anonymous [] in
let domains = Hashtbl.fold (fun _ con accu -> Connection.debug con :: accu) cons.domains [] in
String.concat "" (domains @ anonymous)
diff --git a/tools/ocaml/xenstored/domain.ml b/tools/ocaml/xenstored/domain.ml
index 444069d..ab34314 100644
--- a/tools/ocaml/xenstored/domain.ml
+++ b/tools/ocaml/xenstored/domain.ml
@@ -28,6 +28,9 @@ type t =
eventchn: Event.t;
mutable port: Xeneventchn.t option;
mutable bad_client: bool;
+ mutable io_credit: int; (* the rounds of ring process left to do, default is 0,
+ usually set to 1 when there is work detected, could
+ also set to n to give "lazy" clients extra credit *)
}
let get_path dom = "/local/domain/" ^ (sprintf "%u" dom.id)
@@ -35,10 +38,16 @@ let get_id domain = domain.id
let get_interface d = d.interface
let get_mfn d = d.mfn
let get_remote_port d = d.remote_port
+let get_port d = d.port
let is_bad_domain domain = domain.bad_client
let mark_as_bad domain = domain.bad_client <- true
+let get_io_credit domain = domain.io_credit
+let set_io_credit ?(n=1) domain = domain.io_credit <- max 0 n
+let incr_io_credit domain = domain.io_credit <- domain.io_credit + 1
+let decr_io_credit domain = domain.io_credit <- max 0 (domain.io_credit - 1)
+
let string_of_port = function
| None -> "None"
| Some x -> string_of_int (Xeneventchn.to_int x)
@@ -73,7 +82,8 @@ let make id mfn remote_port interface eventchn = {
interface = interface;
eventchn = eventchn;
port = None;
- bad_client = false
+ bad_client = false;
+ io_credit = 0;
}
let is_dom0 d = d.id = 0
diff --git a/tools/ocaml/xenstored/logging.ml b/tools/ocaml/xenstored/logging.ml
index 3d4a329..665b922 100644
--- a/tools/ocaml/xenstored/logging.ml
+++ b/tools/ocaml/xenstored/logging.ml
@@ -130,8 +130,17 @@ let string_of_date () =
tm.Unix.tm_hour tm.Unix.tm_min tm.Unix.tm_sec
(int_of_float (1000.0 *. msec))
+(* We can defer to syslog for log management *)
let make_syslog_logger facility =
- (* We defer to syslog for log management *)
+ (* When TZ is unset in the environment, each syslog call will stat the
+ /etc/localtime file at least three times during the process. We'd like to
+ avoid this cost given that we are not a mobile environment and we log
+ almost every xenstore entry update/watch. *)
+ let () =
+ let tz_is_set =
+ try String.length (Unix.getenv "TZ") > 0
+ with Not_found -> false in
+ if not tz_is_set then Unix.putenv "TZ" "/etc/localtime" in
let nothing () = () in
let write ?level s =
let level = match level with
diff --git a/tools/ocaml/xenstored/oxenstored.conf b/tools/ocaml/xenstored/oxenstored.conf
index 13ee770..dd20eda 100644
--- a/tools/ocaml/xenstored/oxenstored.conf
+++ b/tools/ocaml/xenstored/oxenstored.conf
@@ -33,3 +33,6 @@ persistent = false
# acesss-log-nb-chars = 180
# access-log-special-ops = false
+# Perodically scanning all the rings as a safenet for lazy clients.
+# Define the interval in seconds, set to negative to disable.
+# ring-scan-interval = 20
diff --git a/tools/ocaml/xenstored/parse_arg.ml b/tools/ocaml/xenstored/parse_arg.ml
index 5d21601..6e22c16 100644
--- a/tools/ocaml/xenstored/parse_arg.ml
+++ b/tools/ocaml/xenstored/parse_arg.ml
@@ -25,6 +25,7 @@ type config =
tracefile: string option; (* old xenstored compatibility *)
restart: bool;
disable_socket: bool;
+ use_select: bool;
}
let do_argv =
@@ -35,7 +36,8 @@ let do_argv =
and reraise_top_level = ref false
and config_file = ref ""
and restart = ref false
- and disable_socket = ref false in
+ and disable_socket = ref false
+ and use_select = ref false in
let speclist =
[ ("--no-domain-init", Arg.Unit (fun () -> domain_init := false),
@@ -52,8 +54,9 @@ let do_argv =
("-T", Arg.Set_string tracefile, ""); (* for compatibility *)
("--restart", Arg.Set restart, "Read database on starting");
("--disable-socket", Arg.Unit (fun () -> disable_socket := true), "Disable socket");
+ ("--use-select", Arg.Unit (fun () -> use_select := true), "Use select instead of poll"); (* for backward compatibility and testing *)
] in
- let usage_msg = "usage : xenstored [--config-file <filename>] [--no-domain-init] [--help] [--no-fork] [--reraise-top-level] [--restart] [--disable-socket]" in
+ let usage_msg = "usage : xenstored [--config-file <filename>] [--no-domain-init] [--help] [--no-fork] [--reraise-top-level] [--restart] [--disable-socket] [--use-select]" in
Arg.parse speclist (fun s -> ()) usage_msg;
{
domain_init = !domain_init;
@@ -65,4 +68,5 @@ let do_argv =
tracefile = if !tracefile <> "" then Some !tracefile else None;
restart = !restart;
disable_socket = !disable_socket;
+ use_select = !use_select;
}
diff --git a/tools/ocaml/xenstored/process.ml b/tools/ocaml/xenstored/process.ml
index 89db56c..0620585 100644
--- a/tools/ocaml/xenstored/process.ml
+++ b/tools/ocaml/xenstored/process.ml
@@ -377,7 +377,12 @@ let do_input store cons doms con =
let newpacket =
try
Connection.do_input con
- with Failure exp ->
+ with Xenbus.Xb.Reconnect ->
+ info "%s requests a reconnect" (Connection.get_domstr con);
+ Connection.reconnect con;
+ info "%s reconnection complete" (Connection.get_domstr con);
+ false
+ | Failure exp ->
error "caught exception %s" exp;
error "got a bad client %s" (sprintf "%-8s" (Connection.get_domstr con));
Connection.mark_as_bad con;
@@ -407,6 +412,11 @@ let do_output store cons doms con =
(Xenbus.Xb.Op.to_string ty) (sanitize_data data);*)
write_answer_log ~ty ~tid ~con ~data;
);
- ignore (Connection.do_output con)
+ try
+ ignore (Connection.do_output con)
+ with Xenbus.Xb.Reconnect ->
+ info "%s requests a reconnect" (Connection.get_domstr con);
+ Connection.reconnect con;
+ info "%s reconnection complete" (Connection.get_domstr con)
)
diff --git a/tools/ocaml/xenstored/quota.ml b/tools/ocaml/xenstored/quota.ml
index c668302..e6953c6 100644
--- a/tools/ocaml/xenstored/quota.ml
+++ b/tools/ocaml/xenstored/quota.ml
@@ -81,3 +81,8 @@ let add_entry quota id =
let add quota diff =
Hashtbl.iter (fun id nb -> set_entry quota id (get_entry quota id + nb)) diff.cur
+
+let merge orig_quota mod_quota dest_quota =
+ Hashtbl.iter (fun id nb -> let diff = nb - (get_entry orig_quota id) in
+ if diff <> 0 then
+ set_entry dest_quota id ((get_entry dest_quota id) + diff)) mod_quota.cur
diff --git a/tools/ocaml/xenstored/select.ml b/tools/ocaml/xenstored/select.ml
new file mode 100644
index 0000000..0455e16
--- /dev/null
+++ b/tools/ocaml/xenstored/select.ml
@@ -0,0 +1,77 @@
+(*
+ * Copyright (C) 2014 Zheng Li <dev at zheng.li>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *)
+
+
+(* The [read], [write], [except] are fields mapped to the POLLIN/OUT/PRI
+ subscription flags used by poll, which have a correspondence to the
+ readfds, writefds, exceptfds concept as in select. *)
+type event = {
+ mutable read: bool;
+ mutable write: bool;
+ mutable except: bool;
+}
+
+external select_on_poll: (Unix.file_descr * event) array -> int -> int = "stub_select_on_poll"
+external set_fd_limit: int -> unit = "stub_set_fd_limit"
+
+(* The rlim_max given to setrlimit must not go above the system level nr_open,
+ which we can read from /proc/sys. *)
+let get_sys_fs_nr_open () =
+ try
+ let ch = open_in "/proc/sys/fs/nr_open" in
+ let v = int_of_string (input_line ch) in
+ close_in_noerr ch; v
+ with _ -> 1024 * 1024
+
+let init_event () = {read = false; write = false; except = false}
+
+let poll_select in_fds out_fds exc_fds timeout =
+ let h = Hashtbl.create 57 in
+ let add_event event_set fd =
+ let e =
+ try Hashtbl.find h fd
+ with Not_found ->
+ let e = init_event () in
+ Hashtbl.add h fd e; e in
+ event_set e in
+ List.iter (add_event (fun x -> x.read <- true)) in_fds;
+ List.iter (add_event (fun x -> x.write <- true)) out_fds;
+ List.iter (add_event (fun x -> x.except <- true)) exc_fds;
+ (* Unix.stdin and init_event are dummy input as stubs, which will
+ always be overwritten later on. *)
+ let a = Array.make (Hashtbl.length h) (Unix.stdin, init_event ()) in
+ let i = ref (-1) in
+ Hashtbl.iter (fun fd event -> incr i; Array.set a !i (fd, event)) h;
+ let n = select_on_poll a (int_of_float (timeout *. 1000.)) in
+ let r = [], [], [] in
+ if n = 0 then r else
+ Array.fold_right
+ (fun (fd, event) (r, w, x) ->
+ (if event.read then fd :: r else r),
+ (if event.write then fd :: w else w),
+ (if event.except then fd :: x else x))
+ a r
+
+(* If the use_poll function is not called at all, we default to the original Unix.select behavior *)
+let select_fun = ref Unix.select
+
+let use_poll yes =
+ let sel_fun, max_fd =
+ if yes then poll_select, get_sys_fs_nr_open ()
+ else Unix.select, 1024 in
+ select_fun := sel_fun;
+ set_fd_limit max_fd
+
+let select in_fds out_fds exc_fds timeout =
+ (!select_fun) in_fds out_fds exc_fds timeout
diff --git a/tools/ocaml/xenstored/select.mli b/tools/ocaml/xenstored/select.mli
new file mode 100644
index 0000000..3912779
--- /dev/null
+++ b/tools/ocaml/xenstored/select.mli
@@ -0,0 +1,27 @@
+(*
+ * Copyright (C) 2014 Zheng Li <dev at zheng.li>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *)
+
+
+(** Same interface and semantics as [Unix.select] but with an extra alternative
+ implementation based on poll. Switching implementations is done by calling
+ the [use_poll] function. *)
+val select:
+ Unix.file_descr list -> Unix.file_descr list -> Unix.file_descr list -> float
+ -> Unix.file_descr list * Unix.file_descr list * Unix.file_descr list
+
+(** [use_poll true] will use poll based select with max fds number limitation
+ eliminated; [use_poll false] will use standard [Unix.select] with max fd
+ number set to 1024; not calling this function at all equals to use the
+ standard [Unix.select] with max fd number setting untouched. *)
+val use_poll: bool -> unit
diff --git a/tools/ocaml/xenstored/select_stubs.c b/tools/ocaml/xenstored/select_stubs.c
new file mode 100644
index 0000000..af72b84
--- /dev/null
+++ b/tools/ocaml/xenstored/select_stubs.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2014 Zheng Li <dev at zheng.li>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <poll.h>
+#include <errno.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <caml/mlvalues.h>
+#include <caml/memory.h>
+#include <caml/fail.h>
+#include <caml/alloc.h>
+#include <caml/signals.h>
+#include <caml/unixsupport.h>
+
+CAMLprim value stub_select_on_poll(value fd_events, value timeo) {
+
+ CAMLparam2(fd_events, timeo);
+ CAMLlocal1(events);
+ int i, rc, c_len = Wosize_val(fd_events), c_timeo = Int_val(timeo);
+ struct pollfd c_fds[c_len];
+
+
+ for (i = 0; i < c_len; i++) {
+
+ events = Field(Field(fd_events, i), 1);
+
+ c_fds[i].fd = Int_val(Field(Field(fd_events, i), 0));
+ c_fds[i].events = c_fds[i].revents = 0;
+ c_fds[i].events |= Bool_val(Field(events, 0)) ? POLLIN : 0;
+ c_fds[i].events |= Bool_val(Field(events, 1)) ? POLLOUT: 0;
+ c_fds[i].events |= Bool_val(Field(events, 2)) ? POLLPRI: 0;
+
+ };
+
+ caml_enter_blocking_section();
+ rc = poll(c_fds, c_len, c_timeo);
+ caml_leave_blocking_section();
+
+ if (rc < 0) uerror("poll", Nothing);
+
+ if (rc > 0) {
+
+ for (i = 0; i < c_len; i++) {
+
+ events = Field(Field(fd_events, i), 1);
+
+ if (c_fds[i].revents & POLLNVAL) unix_error(EBADF, "select", Nothing);
+ Field(events, 0) = Val_bool(c_fds[i].events & POLLIN && c_fds[i].revents & (POLLIN |POLLHUP|POLLERR));
+ Field(events, 1) = Val_bool(c_fds[i].events & POLLOUT && c_fds[i].revents & (POLLOUT|POLLHUP|POLLERR));
+ Field(events, 2) = Val_bool(c_fds[i].revents & POLLPRI);
+
+ }
+
+ }
+
+ CAMLreturn(Val_int(rc));
+}
+
+
+CAMLprim value stub_set_fd_limit(value limit) {
+
+ CAMLparam1(limit);
+ struct rlimit rl;
+
+ rl.rlim_cur = rl.rlim_max = Int_val(limit);
+ if (setrlimit(RLIMIT_NOFILE, &rl) != 0) uerror("setrlimit", Nothing);
+ CAMLreturn(Val_unit);
+
+}
diff --git a/tools/ocaml/xenstored/store.ml b/tools/ocaml/xenstored/store.ml
index cac0b44..223ee21 100644
--- a/tools/ocaml/xenstored/store.ml
+++ b/tools/ocaml/xenstored/store.ml
@@ -188,20 +188,17 @@ let rec get_deepest_existing_node node = function
with Not_found -> node, false
let set_node rnode path nnode =
- let quota = Quota.create () in
- if !Quota.activate then Node.recurse (fun node -> Quota.add_entry quota (Node.get_owner node)) nnode;
if path = [] then
- nnode, quota
+ nnode
else
let set_node node name =
try
let ent = Node.find node name in
- if !Quota.activate then Node.recurse (fun node -> Quota.del_entry quota (Node.get_owner node)) ent;
Node.replace_child node ent nnode
with Not_found ->
Node.add_child node nnode
in
- apply_modify rnode path set_node, quota
+ apply_modify rnode path set_node
(* read | ls | getperms use this *)
let rec lookup node path fct =
@@ -375,15 +372,15 @@ let dump_buffer store = dump_store_buf store.root
(* modifying functions with quota udpate *)
-let set_node store path node =
- let root, quota_diff = Path.set_node store.root path node in
+let set_node store path node orig_quota mod_quota =
+ let root = Path.set_node store.root path node in
store.root <- root;
- Quota.add store.quota quota_diff
+ Quota.merge orig_quota mod_quota store.quota
let write store perm path value =
let node, existing = get_deepest_existing_node store path in
let owner = Node.get_owner node in
- if existing then
+ if existing || (Perms.Connection.is_dom0 perm) then
(* Only check the string length limit *)
Quota.check store.quota (-1) (String.length value)
else
@@ -398,7 +395,7 @@ let mkdir store perm path =
let node, existing = get_deepest_existing_node store path in
let owner = Node.get_owner node in
(* It's upt to the mkdir logic to decide what to do with existing path *)
- if not existing then Quota.check store.quota owner 0;
+ if not (existing || (Perms.Connection.is_dom0 perm)) then Quota.check store.quota owner 0;
store.root <- path_mkdir store perm path;
Quota.add_entry store.quota owner
@@ -416,7 +413,7 @@ let setperms store perm path nperms =
| Some node ->
let old_owner = Node.get_owner node in
let new_owner = Perms.Node.get_owner nperms in
- if old_owner <> new_owner then Quota.check store.quota new_owner 0;
+ if not ((old_owner = new_owner) || (Perms.Connection.is_dom0 perm)) then Quota.check store.quota new_owner 0;
store.root <- path_setperms store perm path nperms;
Quota.del_entry store.quota old_owner;
Quota.add_entry store.quota new_owner
diff --git a/tools/ocaml/xenstored/systemd.ml b/tools/ocaml/xenstored/systemd.ml
new file mode 100644
index 0000000..2aa39ea
--- /dev/null
+++ b/tools/ocaml/xenstored/systemd.ml
@@ -0,0 +1,17 @@
+(*
+ * Copyright (C) 2014 Luis R. Rodriguez <mcgrof at suse.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *)
+
+external sd_listen_fds: string -> Unix.file_descr = "ocaml_sd_listen_fds"
+external sd_booted: unit -> bool = "ocaml_sd_booted"
+external sd_notify_ready: unit -> unit = "ocaml_sd_notify_ready"
diff --git a/tools/ocaml/xenstored/systemd.mli b/tools/ocaml/xenstored/systemd.mli
new file mode 100644
index 0000000..85c9f2e
--- /dev/null
+++ b/tools/ocaml/xenstored/systemd.mli
@@ -0,0 +1,24 @@
+(*
+ * Copyright (C) 2014 Luis R. Rodriguez <mcgrof at suse.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *)
+
+(** Calls the C library sd_listen_fds() function for us. Although
+ * the library doesn't accept argument we send one over to help
+ * us do sanity checks on the expected sockets *)
+val sd_listen_fds: string -> Unix.file_descr
+
+(** Tells us whether or not systemd support was compiled in *)
+val sd_booted: unit -> bool
+
+(** Tells systemd we're ready *)
+external sd_notify_ready: unit -> unit = "ocaml_sd_notify_ready"
diff --git a/tools/ocaml/xenstored/systemd_stubs.c b/tools/ocaml/xenstored/systemd_stubs.c
new file mode 100644
index 0000000..623592c
--- /dev/null
+++ b/tools/ocaml/xenstored/systemd_stubs.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2014 Luis R. Rodriguez <mcgrof at suse.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <caml/mlvalues.h>
+#include <caml/memory.h>
+#include <caml/alloc.h>
+#include <caml/custom.h>
+#include <caml/signals.h>
+#include <caml/fail.h>
+#include <config.h>
+
+#if defined(HAVE_SYSTEMD)
+
+#include <sys/socket.h>
+#include <systemd/sd-daemon.h>
+
+/* Will work regardless of the order systemd gives them to us */
+static int oxen_get_sd_fd(const char *connect_to)
+{
+ int fd = SD_LISTEN_FDS_START;
+ int r;
+
+ while (fd <= SD_LISTEN_FDS_START + 1) {
+ r = sd_is_socket_unix(fd, SOCK_STREAM, 1, connect_to, 0);
+ if (r > 0)
+ return fd;
+ fd++;
+ }
+
+ return -EBADR;
+}
+
+static int oxen_verify_socket_socket(const char *connect_to)
+{
+ if ((strcmp("/var/run/xenstored/socket_ro", connect_to) != 0) &&
+ (strcmp("/var/run/xenstored/socket", connect_to) != 0)) {
+ sd_notifyf(0, "STATUS=unexpected socket: %s\n"
+ "ERRNO=%i",
+ connect_to,
+ EBADR);
+ return -EBADR;
+ }
+
+ return oxen_get_sd_fd(connect_to);
+}
+
+CAMLprim value ocaml_sd_listen_fds(value connect_to)
+{
+ CAMLparam1(connect_to);
+ CAMLlocal1(sock_ret);
+ int sock = -EBADR, n;
+
+ n = sd_listen_fds(0);
+ if (n <= 0) {
+ sd_notifyf(0, "STATUS=Failed to get any active sockets: %s\n"
+ "ERRNO=%i",
+ strerror(errno),
+ errno);
+ caml_failwith("ocaml_sd_listen_fds() failed to get any sockets");
+ } else if (n != 2) {
+ fprintf(stderr, SD_ERR "Expected 2 fds but given %d\n", n);
+ sd_notifyf(0, "STATUS=Mismatch on number (2): %s\n"
+ "ERRNO=%d",
+ strerror(EBADR),
+ EBADR);
+ caml_failwith("ocaml_sd_listen_fds() mismatch");
+ }
+
+ sock = oxen_verify_socket_socket(String_val(connect_to));
+ if (sock <= 0) {
+ fprintf(stderr, "failed to verify sock %s\n",
+ String_val(connect_to));
+ caml_failwith("ocaml_sd_listen_fds_init() invalid socket");
+ }
+
+ sock_ret = Val_int(sock);
+
+ CAMLreturn(sock_ret);
+}
+
+CAMLprim value ocaml_sd_booted(value ignore)
+{
+ CAMLparam1(ignore);
+ CAMLlocal1(ret);
+
+ ret = Val_false;
+
+ if (sd_booted())
+ ret = Val_true;
+
+ CAMLreturn(ret);
+}
+
+CAMLprim value ocaml_sd_notify_ready(value ignore)
+{
+ CAMLparam1(ignore);
+ CAMLlocal1(ret);
+
+ ret = Val_int(0);
+
+ sd_notify(1, "READY=1");
+
+ CAMLreturn(ret);
+}
+
+#else
+
+CAMLprim value ocaml_sd_listen_fds(value connect_to)
+{
+ CAMLparam1(connect_to);
+ CAMLlocal1(sock_ret);
+
+ sock_ret = Val_int(-1);
+
+ CAMLreturn(sock_ret);
+}
+
+CAMLprim value ocaml_sd_booted(value ignore)
+{
+ CAMLparam1(ignore);
+ CAMLlocal1(ret);
+
+ ret = Val_false;
+
+ CAMLreturn(ret);
+}
+
+CAMLprim value ocaml_sd_notify_ready(value ignore)
+{
+ CAMLparam1(ignore);
+ CAMLlocal1(ret);
+
+ ret = Val_int(-1);
+
+ CAMLreturn(ret);
+}
+#endif
diff --git a/tools/ocaml/xenstored/transaction.ml b/tools/ocaml/xenstored/transaction.ml
index e59d681..77de4e8 100644
--- a/tools/ocaml/xenstored/transaction.ml
+++ b/tools/ocaml/xenstored/transaction.ml
@@ -74,6 +74,7 @@ type ty = No | Full of (int * Store.Node.t * Store.t)
type t = {
ty: ty;
store: Store.t;
+ quota: Quota.t;
mutable ops: (Xenbus.Xb.Op.operation * Store.Path.t) list;
mutable read_lowpath: Store.Path.t option;
mutable write_lowpath: Store.Path.t option;
@@ -84,6 +85,7 @@ let make id store =
{
ty = ty;
store = if id = none then store else Store.copy store;
+ quota = Quota.copy store.Store.quota;
ops = [];
read_lowpath = None;
write_lowpath = None;
@@ -155,7 +157,7 @@ let commit ~con t =
(* it has to be in the store, otherwise it means bugs
in the lowpath registration. we don't need to handle none. *)
- maybe (fun n -> Store.set_node cstore p n) n;
+ maybe (fun n -> Store.set_node cstore p n t.quota store.Store.quota) n;
Logging.write_coalesce ~tid:(get_id t) ~con (Store.Path.to_string p);
) t.write_lowpath;
maybe (fun p ->
diff --git a/tools/ocaml/xenstored/utils.ml b/tools/ocaml/xenstored/utils.ml
index 68b70c5..61321c6 100644
--- a/tools/ocaml/xenstored/utils.ml
+++ b/tools/ocaml/xenstored/utils.ml
@@ -73,14 +73,21 @@ let trim_path path =
let join_by_null ls = String.concat "\000" ls
(* unix utils *)
+let create_regular_unix_socket name =
+ Unixext.unlink_safe name;
+ Unixext.mkdir_rec (Filename.dirname name) 0o700;
+ let sockaddr = Unix.ADDR_UNIX(name) in
+ let sock = Unix.socket Unix.PF_UNIX Unix.SOCK_STREAM 0 in
+ Unix.set_close_on_exec sock;
+ Unix.bind sock sockaddr;
+ Unix.listen sock 1;
+ sock
+
let create_unix_socket name =
- Unixext.unlink_safe name;
- Unixext.mkdir_rec (Filename.dirname name) 0o700;
- let sockaddr = Unix.ADDR_UNIX(name) in
- let sock = Unix.socket Unix.PF_UNIX Unix.SOCK_STREAM 0 in
- Unix.bind sock sockaddr;
- Unix.listen sock 1;
- sock
+ if Systemd.sd_booted() then
+ Systemd.sd_listen_fds name
+ else
+ create_regular_unix_socket name
let read_file_single_integer filename =
let fd = Unix.openfile filename [ Unix.O_RDONLY ] 0o640 in
diff --git a/tools/ocaml/xenstored/xenstored.ml b/tools/ocaml/xenstored/xenstored.ml
index 438ecb9..bfe689b 100644
--- a/tools/ocaml/xenstored/xenstored.ml
+++ b/tools/ocaml/xenstored/xenstored.ml
@@ -43,17 +43,24 @@ let process_connection_fds store cons domains rset wset =
debug "closing socket connection"
in
let process_fdset_with fds fct =
- List.iter (fun fd -> try_fct fct (Connections.find cons fd)) fds
- in
+ List.iter
+ (fun fd ->
+ try try_fct fct (Connections.find cons fd)
+ with Not_found -> ()
+ ) fds in
process_fdset_with rset Process.do_input;
process_fdset_with wset Process.do_output
let process_domains store cons domains =
let do_io_domain domain =
if not (Domain.is_bad_domain domain) then
- let con = Connections.find_domain cons (Domain.get_id domain) in
+ let io_credit = Domain.get_io_credit domain in
+ if io_credit > 0 then (
+ let con = Connections.find_domain cons (Domain.get_id domain) in
Process.do_input store cons domains con;
- Process.do_output store cons domains con in
+ Process.do_output store cons domains con;
+ Domain.decr_io_credit domain;
+ ) in
Domains.iter domains do_io_domain
let sigusr1_handler store =
@@ -76,6 +83,8 @@ let config_filename cf =
let default_pidfile = "/var/run/xenstored.pid"
+let ring_scan_interval = ref 20
+
let parse_config filename =
let pidfile = ref default_pidfile in
let options = [
@@ -102,6 +111,7 @@ let parse_config filename =
("access-log-transactions-ops", Config.Set_bool Logging.access_log_transaction_ops);
("access-log-special-ops", Config.Set_bool Logging.access_log_special_ops);
("allow-debug", Config.Set_bool Process.allow_debug);
+ ("ring-scan-interval", Config.Set_int ring_scan_interval);
("pid-file", Config.Set_string pidfile); ] in
begin try Config.read filename options (fun _ _ -> raise Not_found)
with
@@ -274,6 +284,8 @@ let _ =
);
);
+ Select.use_poll (not cf.use_select);
+
Sys.set_signal Sys.sighup (Sys.Signal_handle sighup_handler);
Sys.set_signal Sys.sigterm (Sys.Signal_handle (fun i -> quit := true));
Sys.set_signal Sys.sigusr1 (Sys.Signal_handle (fun i -> sigusr1_handler store));
@@ -300,6 +312,7 @@ let _ =
Connections.add_anonymous cons cfd can_write
and handle_eventchn fd =
let port = Event.pending eventchn in
+ debug "pending port %d" (Xeneventchn.to_int port);
finally (fun () ->
if Some port = eventchn.Event.virq_port then (
let (notify, deaddom) = Domains.cleanup xc domains in
@@ -307,7 +320,11 @@ let _ =
if deaddom <> [] || notify then
Connections.fire_spec_watches cons "@releaseDomain"
)
- ) (fun () -> Event.unmask eventchn port);
+ else
+ let c = Connections.find_domain_by_port cons port in
+ match Connection.get_domain c with
+ | Some dom -> Domain.incr_io_credit dom | None -> ()
+ ) (fun () -> Event.unmask eventchn port)
and do_if_set fd set fct =
if List.mem fd set then
fct fd in
@@ -315,11 +332,30 @@ let _ =
maybe (fun fd -> do_if_set fd rset (accept_connection true)) rw_sock;
maybe (fun fd -> do_if_set fd rset (accept_connection false)) ro_sock;
do_if_set (Event.fd eventchn) rset (handle_eventchn)
- in
+ in
+
+ let ring_scan_checker dom =
+ (* no need to scan domains already marked as for processing *)
+ if not (Domain.get_io_credit dom > 0) then
+ let con = Connections.find_domain cons (Domain.get_id dom) in
+ if not (Connection.has_more_work con) then (
+ Process.do_output store cons domains con;
+ Process.do_input store cons domains con;
+ if Connection.has_more_work con then
+ (* Previously thought as no work, but detect some after scan (as
+ processing a new message involves multiple steps.) It's very
+ likely to be a "lazy" client, bump its credit. It could be false
+ positive though (due to time window), but it's no harm to give a
+ domain extra credit. *)
+ let n = 32 + 2 * (Domains.number domains) in
+ info "found lazy domain %d, credit %d" (Domain.get_id dom) n;
+ Domain.set_io_credit ~n dom
+ ) in
let last_stat_time = ref 0. in
- let periodic_ops_counter = ref 0 in
- let periodic_ops () =
+ let last_scan_time = ref 0. in
+
+ let periodic_ops now =
(* we garbage collect the string->int dictionary after a sizeable amount of operations,
* there's no need to be really fast even if we got loose
* objects since names are often reuse.
@@ -332,10 +368,13 @@ let _ =
Symbol.garbage ()
end;
+ (* scan all the xs rings as a safenet for ill-behaved clients *)
+ if !ring_scan_interval >= 0 && now > (!last_scan_time +. float !ring_scan_interval) then
+ (last_scan_time := now; Domains.iter domains ring_scan_checker);
+
(* make sure we don't print general stats faster than 2 min *)
- let ntime = Unix.gettimeofday () in
- if ntime > (!last_stat_time +. 120.) then (
- last_stat_time := ntime;
+ if now > (!last_stat_time +. 120.) then (
+ last_stat_time := now;
let gc = Gc.stat () in
let (lanon, lanon_ops, lanon_watchs,
@@ -356,19 +395,23 @@ let _ =
)
in
+ let period_ops_interval = 15. in
+ let period_start = ref 0. in
+
let main_loop () =
- incr periodic_ops_counter;
- if !periodic_ops_counter > 20 then (
- periodic_ops_counter := 0;
- periodic_ops ();
- );
let mw = Connections.has_more_work cons in
+ List.iter
+ (fun c ->
+ match Connection.get_domain c with
+ | None -> () | Some d -> Domain.incr_io_credit d)
+ mw;
+ let timeout =
+ if List.length mw > 0 then 0. else period_ops_interval in
let inset, outset = Connections.select cons in
- let timeout = if List.length mw > 0 then 0. else -1. in
let rset, wset, _ =
try
- Unix.select (spec_fds @ inset) outset [] timeout
+ Select.select (spec_fds @ inset) outset [] timeout
with Unix.Unix_error(Unix.EINTR, _, _) ->
[], [], [] in
let sfds, cfds =
@@ -377,12 +420,19 @@ let _ =
process_special_fds sfds;
if List.length cfds > 0 || List.length wset > 0 then
process_connection_fds store cons domains cfds wset;
+ if timeout <> 0. then (
+ let now = Unix.gettimeofday () in
+ if now > !period_start +. period_ops_interval then
+ (period_start := now; periodic_ops now)
+ );
process_domains store cons domains
in
while not !quit
do
try
+ if Systemd.sd_booted() then
+ Systemd.sd_notify_ready ();
main_loop ()
with exc ->
error "caught exception %s" (Printexc.to_string exc);
diff --git a/tools/pygrub/Makefile b/tools/pygrub/Makefile
index 0191638..3dff608 100644
--- a/tools/pygrub/Makefile
+++ b/tools/pygrub/Makefile
@@ -6,18 +6,17 @@ include $(XEN_ROOT)/tools/Rules.mk
all: build
.PHONY: build
build:
- CC="$(CC)" CFLAGS="$(CFLAGS)" $(PYTHON) setup.py build
+ CC="$(CC)" CFLAGS="$(CFLAGS) $(APPEND_LDFLAGS)" $(PYTHON) setup.py build
.PHONY: install
install: all
- CC="$(CC)" CFLAGS="$(CFLAGS)" $(PYTHON) setup.py install \
+ CC="$(CC)" CFLAGS="$(CFLAGS) $(APPEND_LDFLAGS)" $(PYTHON) setup.py install \
$(PYTHON_PREFIX_ARG) --root="$(DESTDIR)" \
- --install-scripts=$(PRIVATE_BINDIR) --force
- $(INSTALL_DIR) $(DESTDIR)/var/run/xend/boot
- set -e; if [ $(BINDIR) != $(PRIVATE_BINDIR) -a \
+ --install-scripts=$(LIBEXEC_BIN) --force
+ set -e; if [ $(BINDIR) != $(LIBEXEC_BIN) -a \
"`readlink -f $(DESTDIR)/$(BINDIR)`" != \
- "`readlink -f $(PRIVATE_BINDIR)`" ]; then \
- ln -sf $(PRIVATE_BINDIR)/pygrub $(DESTDIR)/$(BINDIR); \
+ "`readlink -f $(LIBEXEC_BIN)`" ]; then \
+ ln -sf $(LIBEXEC_BIN)/pygrub $(DESTDIR)/$(BINDIR); \
fi
.PHONY: clean
diff --git a/tools/pygrub/src/GrubConf.py b/tools/pygrub/src/GrubConf.py
index 974cded..dea7044 100644
--- a/tools/pygrub/src/GrubConf.py
+++ b/tools/pygrub/src/GrubConf.py
@@ -231,7 +231,7 @@ class _GrubConfigFile(object):
if val == "saved":
self._default = 0
else:
- self._default = int(val)
+ self._default = val
if self._default < 0:
raise ValueError, "default must be positive number"
@@ -431,11 +431,11 @@ class Grub2ConfigFile(_GrubConfigFile):
if self.commands.has_key(com):
if self.commands[com] is not None:
- if arg.strip() == "${saved_entry}":
+ arg_strip = arg.strip()
+ if arg_strip == "${saved_entry}" or arg_strip == "${next_entry}":
+ logging.warning("grub2's saved_entry/next_entry not supported")
arg = "0"
- elif arg.strip() == "${next_entry}":
- arg = "0"
- setattr(self, self.commands[com], arg.strip())
+ setattr(self, self.commands[com], arg_strip)
else:
logging.info("Ignored directive %s" %(com,))
elif com.startswith('set:'):
diff --git a/tools/pygrub/src/pygrub b/tools/pygrub/src/pygrub
index 45a7290..aa7e562 100644
--- a/tools/pygrub/src/pygrub
+++ b/tools/pygrub/src/pygrub
@@ -13,7 +13,7 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
-import os, sys, string, struct, tempfile, re, traceback
+import os, sys, string, struct, tempfile, re, traceback, stat, errno
import copy
import logging
import platform
@@ -29,6 +29,16 @@ import grub.ExtLinuxConf
PYGRUB_VER = 0.6
FS_READ_MAX = 1024 * 1024
+SECTOR_SIZE = 512
+
+def read_size_roundup(fd, size):
+ if platform.system() != 'FreeBSD':
+ return size
+ st = os.fstat(fd)
+ if (not stat.S_ISCHR(st.st_mode)):
+ return size
+ # Round up to sector size if it's a raw character device
+ return (((size)+((SECTOR_SIZE)-1))&(~((SECTOR_SIZE)-1)))
def enable_cursor(ison):
if ison:
@@ -45,7 +55,7 @@ DISK_TYPE_RAW, DISK_TYPE_HYBRIDISO, DISK_TYPE_DOS = range(3)
def identify_disk_image(file):
"""Detect DOS partition table or HybridISO format."""
fd = os.open(file, os.O_RDONLY)
- buf = os.read(fd, 0x8006)
+ buf = os.read(fd, read_size_roundup(fd, 0x8006))
os.close(fd)
if len(buf) >= 512 and \
@@ -56,7 +66,6 @@ def identify_disk_image(file):
return DISK_TYPE_DOS
return DISK_TYPE_RAW
-SECTOR_SIZE=512
DK_LABEL_LOC=1
DKL_MAGIC=0xdabe
V_ROOT=0x2
@@ -91,7 +100,7 @@ def get_fs_offset_gpt(file):
i = partcount
offsets = []
while i>0:
- buf = os.read(fd, partsize)
+ buf = os.read(fd, read_size_roundup(fd, partsize))
offsets.append(struct.unpack("<Q", buf[32:40])[0] * SECTOR_SIZE)
i -= 1
os.close(fd)
@@ -360,11 +369,7 @@ class Grub:
curline = len(img.lines) - 1
if self.isdone:
- # Fix to allow pygrub command-line editing in Lilo bootloader (used by IA64)
- if platform.machine() == 'ia64':
- origimg.reset(img.lines, img.path)
- else:
- origimg.reset(img.lines)
+ origimg.reset(img.lines)
def edit_line(self, line):
self.screen.erase()
@@ -416,25 +421,18 @@ class Grub:
if not os.access(fn, os.R_OK):
raise RuntimeError, "Unable to access %s" %(fn,)
- if platform.machine() == 'ia64':
- cfg_list = map(lambda x: (x,grub.LiloConf.LiloConfigFile),
- # common distributions
- ["/efi/debian/elilo.conf", "/efi/gentoo/elilo.conf",
- "/efi/redflag/elilo.conf", "/efi/redhat/elilo.conf",
- "/efi/SuSE/elilo.conf",] +
- # fallbacks
- ["/efi/boot/elilo.conf", "/elilo.conf",])
- else:
- cfg_list = map(lambda x: (x,grub.GrubConf.Grub2ConfigFile),
- ["/boot/grub/grub.cfg", "/grub/grub.cfg",
- "/boot/grub2/grub.cfg", "/grub2/grub.cfg"]) + \
- map(lambda x: (x,grub.ExtLinuxConf.ExtLinuxConfigFile),
- ["/boot/isolinux/isolinux.cfg",
- "/boot/extlinux/extlinux.conf",
- "/boot/extlinux.conf"]) + \
- map(lambda x: (x,grub.GrubConf.GrubConfigFile),
- ["/boot/grub/menu.lst", "/boot/grub/grub.conf",
- "/grub/menu.lst", "/grub/grub.conf"])
+ cfg_list = map(lambda x: (x,grub.GrubConf.Grub2ConfigFile),
+ ["/boot/grub/grub.cfg", "/grub/grub.cfg",
+ "/boot/grub2/grub.cfg", "/grub2/grub.cfg"]) + \
+ map(lambda x: (x,grub.ExtLinuxConf.ExtLinuxConfigFile),
+ ["/boot/isolinux/isolinux.cfg",
+ "/boot/extlinux/extlinux.conf",
+ "/boot/extlinux.conf",
+ "/extlinux/extlinux.conf",
+ "/extlinux.conf"]) + \
+ map(lambda x: (x,grub.GrubConf.GrubConfigFile),
+ ["/boot/grub/menu.lst", "/boot/grub/grub.conf",
+ "/grub/menu.lst", "/grub/grub.conf"])
if not fs:
# set the config file and parse it
@@ -458,13 +456,37 @@ class Grub:
del f
self.cf.parse(buf)
+ def image_index(self):
+ if self.cf.default.isdigit():
+ sel = int(self.cf.default)
+ else:
+ # We don't fully support submenus. Look for the leaf value in
+ # "submenu0>submenu1>...>menuentry" and hope that it's unique.
+ title = self.cf.default
+ while 1:
+ try:
+ title = re.search('(\S)>(\S.+$)',title).group(2)
+ except AttributeError:
+ break
+
+ # Map string to index in images array
+ sel = 0
+ for i in range(len(self.cf.images)):
+ if self.cf.images[i].title == title:
+ sel = i
+ break
+
+ # If the selected (default) image doesn't exist we select the first entry
+ if sel > len(self.cf.images):
+ logging.warning("Default image not found")
+ sel = 0
+
+ return sel
+
def run(self):
timeout = int(self.cf.timeout)
+ self.selected_image = self.image_index()
- self.selected_image = self.cf.default
- # If the selected (default) image doesn't exist we select the first entry
- if self.selected_image > len(self.cf.images):
- self.selected_image = 0
self.isdone = False
while not self.isdone:
self.run_main(timeout)
@@ -609,7 +631,7 @@ def run_grub(file, entry, fs, cfg_args):
if interactive and not list_entries:
curses.wrapper(run_main)
else:
- sel = g.cf.default
+ sel = g.image_index()
# set the entry to boot as requested
if entry is not None:
@@ -770,7 +792,7 @@ if __name__ == "__main__":
debug = False
not_really = False
output_format = "sxp"
- output_directory = "/var/run/xend/boot"
+ output_directory = "/var/run/xen/pygrub"
# what was passed in
incfg = { "kernel": None, "ramdisk": None, "args": "" }
@@ -821,11 +843,23 @@ if __name__ == "__main__":
sys.exit(1)
output_format = a
elif o in ("--output-directory",):
+ if not os.path.isdir(a):
+ print "%s is not an existing directory" % a
+ sys.exit(1)
output_directory = a
if debug:
logging.basicConfig(level=logging.DEBUG)
+
+ try:
+ os.makedirs(output_directory, 0700)
+ except OSError,e:
+ if (e.errno == errno.EEXIST) and os.path.isdir(output_directory):
+ pass
+ else:
+ raise
+
if output is None or output == "-":
fd = sys.stdout.fileno()
else:
diff --git a/tools/python/Makefile b/tools/python/Makefile
index 3d0f8f0..533d3de 100644
--- a/tools/python/Makefile
+++ b/tools/python/Makefile
@@ -4,38 +4,19 @@ include $(XEN_ROOT)/tools/Rules.mk
.PHONY: all
all: build
-XENPATH = "xen/util/path.py"
-
-genpath-target = $(call buildmakevars2file,$(XENPATH))
-$(eval $(genpath-target))
-
.PHONY: build
-build: genpath genwrap.py $(XEN_ROOT)/tools/libxl/libxl_types.idl \
+build: genwrap.py $(XEN_ROOT)/tools/libxl/libxl_types.idl \
$(XEN_ROOT)/tools/libxl/idl.py
PYTHONPATH=$(XEN_ROOT)/tools/libxl $(PYTHON) genwrap.py \
$(XEN_ROOT)/tools/libxl/libxl_types.idl \
xen/lowlevel/xl/_pyxl_types.h \
xen/lowlevel/xl/_pyxl_types.c
- CC="$(CC)" CFLAGS="$(CFLAGS)" $(PYTHON) setup.py build --xend=$(CONFIG_XEND)
+ CC="$(CC)" CFLAGS="$(CFLAGS) $(LDFLAGS) $(APPEND_LDFLAGS)" $(PYTHON) setup.py build
.PHONY: install
-install: install-dtd
- CC="$(CC)" CFLAGS="$(CFLAGS)" $(PYTHON) setup.py install \
- $(PYTHON_PREFIX_ARG) --root="$(DESTDIR)" --force --xend=$(CONFIG_XEND)
-
- $(INSTALL_DIR) $(DESTDIR)$(SBINDIR)
-ifeq ($(CONFIG_XEND),y)
- $(INSTALL_PYTHON_PROG) xen/xm/xm $(DESTDIR)$(SBINDIR)/xm
- $(INSTALL_PYTHON_PROG) xen/xend/xend $(DESTDIR)$(SBINDIR)/xend
-endif
-
-install-dtd: all
-ifeq ($(CONFIG_XEND),y)
- $(INSTALL_DIR) $(DESTDIR)$(SHAREDIR)/xen
- $(INSTALL_DATA) xen/xm/create.dtd $(DESTDIR)$(SHAREDIR)/xen
-else
- :
-endif
+install:
+ CC="$(CC)" CFLAGS="$(CFLAGS) $(LDFLAGS) $(APPEND_LDFLAGS)" $(PYTHON) setup.py install \
+ $(PYTHON_PREFIX_ARG) --root="$(DESTDIR)" --force
.PHONY: test
test:
@@ -43,10 +24,8 @@ test:
.PHONY: clean
clean:
- rm -f $(XENPATH)
- rm -rf build/ *.pyc *.pyo *.o *.a *~ xen/util/auxbin.pyc
- rm -f xen/lowlevel/xl/_pyxl_types.h
- rm -f xen/lowlevel/xl/_pyxl_types.c
+ find . \( -name "*.py[ocd]" -o -name "*~" -o -name "_*.[hc]" \) -delete
+ rm -rf build/
rm -f $(DEPS)
-include $(DEPS)
diff --git a/tools/python/README.XendConfig b/tools/python/README.XendConfig
deleted file mode 100644
index 338715b..0000000
--- a/tools/python/README.XendConfig
+++ /dev/null
@@ -1,160 +0,0 @@
-XendConfig parameters
-=====================
-
-Things that are empty means there is no direct mapping.
-
-In order to make the XendConfig fully backwards compatible, it needs a
-representation of all the below parameters. Where both columns have
-values, it means we can have a direct translation.
-
-Where the Legacy Config value does not exist, it means we have to make
-up the value on whether we supported it or not.
-
-Where the Legacy config value is prefixed with an '!', it means it is
-not a direct mapping and needs a translation function.
-
-Where the Xen API config value does not exist, it means we have to add
-a parameter outside of the Xen API Configuration to support it.
-
-
-Xen API Config Legacy Config
--------------- -------------
-uuid uuid
-power_state !state (and xc_getinfo)
-name_label name
-name_description
-user_version
-is_a_template
-auto_power_on
-resident_on
-memory_static_min memory
-memory_static_max maxmem
-memory_actual
-memory_dynamic_min
-memory_dynamic_max
-vcpus_policy !set_credit/set_sedf
-vcpus_params !set_credit/set_sedf
-vcpus_number vcpus
-vcpus_utilisation
-vcpus_features_required
-vcpus_features_can_use
-vcpus_features_force_on
-vcpus_features_force_off
-actions_after_shutdown on_poweroff
-actions_after_reboot on_reboot
-actions_after_suspend
-actions_after_crash on_crash
-
-vifs !(devices.vifs)
- - uuid dev.uuid
- - name
- - type vif.type
- - device
- - network
- - vm
- - MAC vif.mac
- - MTU
- - io_read_kbs !vif.rate
- - io_write_kbs !vif.rate
- vif.bridge
- vif.script
- vif.ip
- vif.vifname (backend name)
-
-vbds !(devices.vbds)
- - uuid
- - vm
- - vdi
- - device vbd.uname
- - mode !vbd.mode
- - driver vbd.driver
- - io_read_kbs
- - io_write_kbs
-
-bios_boot image.boot?
-platform_std_VGA image.stdvga
-platform_serial image.serial
-platform_localtime !localtime (bool)
-platform_clock_offset
-platform_enable_audio !image.soundhw (bool)
-builder (sxp root name)
-boot_method
-kernel_kernel kernel.kernel
-kernel_initrd kernel.ramdisk
-kernel_args !kernel.args
-grub_cmdline bootloader_args
-PCI_bus
-tools_version
-
-otherConfig
- - image image (see image.*)
- - shadow_memory shadow_memory
- - security security
- - vcpu_avail vcpu_avail
- - features features
- - on_xend_stop on_xend_stop
- - on_xend_start on_xend_start
- - start_time start_time
- - cpus cpus (?)
- max_vcpu_id
-
- >> only from xc
- - online_vcpus xc.online_vcpus
- - status xc.status
- - cpu_time xc.cpu_time
- - shutdown_reason xc.shutdown_reason
- - up_time xc.uptime
- - crashed xc.crashed
- - dying xc.dying
- - shutdown xc.shutdown
-
- image.type (linux or hvm)
- image.root
- image.ip
- image.nographic
- image.vnc
- image.sdl
- image.monitor
- image.vncdisplay
- image.vncunused
- image.hvm.device_model
- image.hvm.display
- image.hvm.xauthority
- image.hvm.vncconsole
- image.hvm.pae
- image.hvm.acpi (also in image.devices)
- image.hvm.apic
- image.hvm.devices.boot
- image.hvm.devices.fda
- image.hvm.devices.fdb
- image.hvm.devices.soundhw
- image.hvm.devices.isa
- image.hvm.devices.vcpus?
- image.hvm.devices.acpi
- image.hvm.devices.usb
- image.hvm.devices.usbdevice
-
-
- dev.backend
- dev.dom
- dev.id
-
- pci.domain
- pci.bus
- pci.slot
- pci.func
-
- pciquirk.pci_ids
- pciquirk.pci_config_space_fields
- pciquirk.unconstrained_dev_ids
-
- irq.irq
-
-- vcpu (probably not needed, only in XM and generated dynamically)
- vcpu.number
- vcpu.online
- vcpu.blocked
- vcpu.running
- vcpu.cpu_time
- vcpu.cpu
- vcpu.cpumap
diff --git a/tools/python/README.sxpcfg b/tools/python/README.sxpcfg
deleted file mode 100644
index a4762fe..0000000
--- a/tools/python/README.sxpcfg
+++ /dev/null
@@ -1,114 +0,0 @@
-Map of all supported SXP configuration options
-----------------------------------------------
-
-uuid
-vcpus
-maxmem
-memory
-name
-on_poweroff
-on_reboot
-on_crash
-bootloader
-kernel_kernel
-kernel_initrd
-kernel_args
-localtime
-
-shadow_memory
-security
-ssidref (deprecated)
-vcpu_avail
-cpu_weight (deprecated)
-bootloader_args
-features
-on_xend_stop
-on_xend_start
-start_time
-cpu (deprecated)
-cpus
-
-(xc getinfo)
-domid
-online_vcpus
-status
-cpu_time
-shutdown_reason
-(xm list --long)
-up_time
-
-image
- - kernel
- - ramdisk
- - args
- - ip
- - root
- (configVNC)
- - nographic
- - vnc
- - sdl
- - vncdisplay
- - vncunused
- (HVM)
- - device_model
- - display
- - xauthority
- - vncconsole
- - pae
- - acpi
- - apic
- (parseDeviceModel)
- - boot
- - fda
- - fdb
- - soundhw
- - localtime
- - monitor
- - serial
- - stdvga
- - isa
- - vcpus
- - acpi
- - usb
- - usbdevice
-
-(all devices)
- - backend
- - dom
- - id
- - uuid
-
-vbd
- - uname
- - dev (ioemu:, .. etc)
- - mode (r, w. w!)
-
-vif
- - type
- - mac
- - bridge
- - model
- - rate
- - vifname
- - script
- - ip
-
-pci
- - domain
- - bus
- - slot
- - func
- (Xen 2.0)
- - dev
-
-io
- - from
- - to
-
-pciquirk
- - pci_ids
- - pci_config_space_fields
- - unconstrained_dev_ids
-
-irq
- - irq
diff --git a/tools/python/logging/logging-0.4.9.2/PKG-INFO b/tools/python/logging/logging-0.4.9.2/PKG-INFO
deleted file mode 100644
index 6f7ee38..0000000
--- a/tools/python/logging/logging-0.4.9.2/PKG-INFO
+++ /dev/null
@@ -1,25 +0,0 @@
-Metadata-Version: 1.0
-Name: logging
-Version: 0.4.9.2
-Summary: A logging module for Python
-Home-page: http://www.red-dove.com/python_logging.html
-Author: Vinay Sajip
-Author-email: vinay_sajip at red-dove.com
-License: Copyright (C) 2001-2004 by Vinay Sajip. All Rights Reserved.
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Vinay Sajip
-not be used in advertising or publicity pertaining to distribution
-of the software without specific, written prior permission.
-
-VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
-AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-Description: This module is intended to provide a standard error logging mechanism in Python as per PEP 282.
-Platform: UNKNOWN
diff --git a/tools/python/logging/logging-0.4.9.2/README.txt b/tools/python/logging/logging-0.4.9.2/README.txt
deleted file mode 100644
index 3d38889..0000000
--- a/tools/python/logging/logging-0.4.9.2/README.txt
+++ /dev/null
@@ -1,311 +0,0 @@
-This module is intended to provide error logging functionality for Python
-programs. It aims to be aligned with Python Enhancement Proposal (PEP) 282.
-
-For more information on the package itself, see python_logging.html. In it,
-there is a description of each file in the distribution.
-You can also use pydoc to browse the interfaces.
-
-Change History
---------------
-
-Version Date Description
-=============================================================================
-0.4.9.2 28 Feb 2004 Traceback text is now cached.
- Tracebacks can be propagated across sockets as text.
- Added makeLogRecord() to allow a LogRecord to be
- created from a dictionary.
- Closing a handler now removes it from the internal list
- used by shutdown().
- Made close() call flush() for handlers where this makes
- sense (thanks to Jim Jewett).
- The exc_info keyword parameter can be used to pass an
- exception tuple as well as a flag indicating that the
- current exception should be logged.
- A shutdown hook is registered to call shutdown() on
- application (Python) exit (thanks to Jim Jewett).
- Removed redundant error check in setLoggerClass().
- Added RESET_ERROR to logging.config.
- SocketHandler now uses an exponential backoff strategy
- (thanks to Robert Olson).
- Minor documentation corrections.
------------------------------------------------------------------------------
-0.4.8 22 Apr 2003 Made _listener global in stopListening().
- Made listen() correctly pass the specified port.
- Removed some redundant imports in __init__.py.
- Added the record being processed as a parameter to
- handleError (thanks to Gordon den Otter for the idea).
- Handler.handle returns the result of applying the
- filter to the record (thanks to Gordon den Otter for
- the idea).
- Added a seek(0, 2) in RotatingFileHandler before the
- tell() call. This is because under Windows, tell()
- returns 0 until the first actual write (thanks to
- Gordon den Otter for the patch).
- Altered findCaller to not use inspect (thanks to
- Jeremy Hylton for the patch).
- Renamed warn and WARN to warning and WARNING. This may
- break existing code, but the standard Python module
- will use warning/WARNING rather than warn/WARN. The
- fatal and FATAL synonyms for critical and CRITICAL
- have also been removed.
- Added defaultEncoding and some support for encoding
- Unicode messages (thanks to St�phane Bidoul for the
- suggestion).
- Added process ID to the list of LogRecord attributes.
- Modified Logger.removeHandler so that it does not
- close the handler on removal.
- Modified SMTPHandler to treat a single "to address"
- correctly (thanks to Anthony Baxter).
- Modified SMTPHandler to add a date header to the SMTP
- message (thanks to David Driver for the suggestion).
- Modified HTTPHandler to factor out the mapping of
- a LogRecord to a dictionary (thanks to Franz Glasner
- for the patch).
------------------------------------------------------------------------------
-0.4.7 15 Nov 2002 Made into a package with three modules: __init__ (the
- core code), handlers (all handlers other than
- FileHandler and its bases) and config (all the config
- stuff). Before doing this:
- Updated docstrings to include a short line, then a
- blank line, then more descriptive text.
- Renamed 'lvl' to 'level' in various functions.
- Changed FileHandler to use "a" and "w" instead of "a+"
- and "w+".
- Moved log file rotation functionality from FileHandler
- to a new class RotatingFileHandler.
- Improved docstring describing rollover.
- Updated makePickle to use 4-byte length and struct
- module, likewise logrecv.py. Also updated on-the-fly
- config reader to use 4-byte length/struct module.
- Altered ConfigParser test to look at 'readline' rather
- than 'read'.
- Added optional "defaults" argument to fileConfig, to
- be passed to ConfigParser.
- Renamed ALL to NOTSET to avoid confusion.
- Commented out getRootLogger(), as obsolete.
- To do regression testing, run log_test.py and compare
- the created files stdout.log and stderr.log against
- the files stdout.exp and stderr.exp. They should match
- except fir a couple of exception messages which give
- absolute file paths.
- Updated python_logging.html to remove links to
- logging_pydoc.html, which has been removed from the
- distribution.
- Changed default for raiseExceptions to 1.
------------------------------------------------------------------------------
-0.4.6 08 Jul 2002 Added raiseExceptions to allow conditional propagation
- of exceptions which occur during handling.
- Added converter to Formatter to allow use of any
- function to convert time from seconds to a tuple. It
- still defaults to time.localtime but now you can also
- use time.gmtime.
- Added log_test22.py to test the conversion feature.
- Changed rootlogger default level to WARN - was DEBUG.
- Updated some docstrings.
- Moved import of threading to where thread is imported.
- If either is unavailable, threading support is off.
- Updated minor defects in python_logging.html.
- Check to see if ConfigParser has readfp method; if it
- does and an object with a 'read' method is passed in,
- assumes a file-like object and uses readfp to read it
- in.
------------------------------------------------------------------------------
-0.4.5 04 Jun 2002 Fixed bug which caused problem if no args to message
- (suggested by Hye-Shik Chang).
- Fixed bug in _fixupParents (thanks to Nicholas Veeser)
- and added log_test19.py as a test case for this bug.
- Added getMessage to LogRecord (code was moved here from
- Formatter.format)
- Applied str() to record.msg to allow arbitrary classes
- to determine the formatting (as msg can now be a class
- instance).
- Table of Contents added to python_logging.html, the
- section on Loggers updated, and the logconf.ini file
- section annotated.
- Added log_test20.py which demonstrates how to use
- class instances to provide alternatives to numeric
- severities as mechanisms for control of logging.
- Added log_test21.py which builds on log_test20.py to
- show how you can use a regular expression-based Filter
- for flexible matching similar to e.g. Protomatter
- Syslog, where you can filter on e.g. "a.*" or "*.b" or
- "a.*.c".
- _levelNames changed to contain reverse mappings as well
- as forward mappings (leveltext->level as well as level
- -> leveltext). The reverse mappings are used by
- fileConfig().
- fileConfig() now more forgiving of missing options in
- .ini file - sensible defaults now used when some
- options are absent. Also, eval() is used less when
- interpreting .ini file contents - int() and dict lookup
- are used in more places.
------------------------------------------------------------------------------
-0.4.4 02 May 2002 getEffectiveLevel() returns ALL instead of None when
- nothing found. Modified references to level=0 to
- level=ALL in a couple of places.
- SocketHandler now inherits from Handler (it used to
- inherit from StreamHandler, for no good reason).
- getLock() renamed to createLock().
- Docstring tidy-ups, and some tidying up of
- DatagramHandler.
- Factored out unpickling in logrecv.py.
- Added log_test18.py to illustrate MatchFilter, which is
- a general matching filter.
- Improved FileHandler.doRollover() so that the base
- file name is always the most recent, then .1, then .2
- etc. up to the maximum backup count. Renamed formal
- args and attributes used in rollover.
- Changed LogRecord attributes lvl -> levelno, level ->
- levelname (less ambiguity)
- Formatter.format searches for "%(asctime)" rather than
- "(asctime)"
- Renamed _start_time to _startTime
- Formatter.formatTime now returns the time
- Altered logrecv.py to support stopping servers
- programmatically
- Added log_test.py as overall test harness
- basicConfig() can now be safely called more than once
- Modified test scripts to make it easier to call them
- from log_test.py
- Moved SOAPHandler from core to log_test13.py. It's not
- general enough to be in the core; most production use
- will have differing RPC signatures.
------------------------------------------------------------------------------
-0.4.3 14 Apr 2002 Bug fix one-off error message to go to sys.stderr
- rather than sys.stdout.
- logrecv.py fix TCP for busy network.
- Thread safety - added locking to Handler and for shared
- data in module, and log_test16.py to test it.
- Added socket listener to allow on-the-fly configuration
- and added log_test17.py to test it.
------------------------------------------------------------------------------
-0.4.2 11 Apr 2002 Bug fix fileConfig() - setup of MemoryHandler target
- and errors when loggers have no handlers set or
- handlers have no formatters set
- logconf.py - seems to hang if window closed when combo
- dropdown is showing - added code to close popup on exit
- Some tweaks to _srcfile computation (normpath added)
- findCaller() optimized, now a lot faster!
- Logger.removeHandler now closes the handler before
- removing it
- fileConfig() removes existing handlers before adding
- the new set, to avoid memory leakage when repeated
- calls are made
- Fixed logrecv.py bug which hogged CPU time when TCP
- connection was closed from the client
- Added log_test14.py to demonstrate/test a DBHandler
- which writes logging records into an RDBMS using the
- Python Database API 2.0 (to run, you need something
- which supports this already installed - I tested with
- mxODBC)
- Made getLogger name argument optional - returns root
- logger if omitted
- Altered Filter to take a string initializer, filtering
- a sub-hierarchy rooted at a particular point (idea from
- Denis S. Otkidach).
- Added log_test15.py to test Filter initializer
- Minor docstring changes
------------------------------------------------------------------------------
-0.4.1 03 Apr 2002 Bug fix SMTPHandler - extra \r\n needed (Oleg Orlov)
- Added BufferingHandler, BufferingFormatter
- Renamed getChainedPriority to getEffectiveLevel
- Removed Logger.getRoot as it is redundant
- Added log_test9.py to test Buffering classes and
- to show an XMLFormatter example.
- Added setLoggerClass.
- Added log_test10.py to test setLoggerClass, using an
- example Logger-derived class which outputs exception
- info even for DEBUG level logging calls
- Added log_test11.py to test a buffering implementation
- of SMTPHandler
- Changed logging call implementation to allow keyword
- arguments (Kevin Butler and others)
- Changed default SysLogHandler implementation.
- Renamed "additive" to "propagate" as it better
- describes the attribute.
- Added HTTPHandler.
- Modified logrecv.py to remove "both" option and to add
- "HTTP" and "SOAP" options (SOAP option needs you to
- have PyXML-0.6.6 and ZSI installed - for logrecv.py
- only, and not for the core logging module itself).
- Added log_test12.py to test HTTPHandler.
- Added log_test13.py to test SOAPHandler.
- Formatted to Python source guidelines (spaces, indent
- of 4, within 80 columns).
- More method renamings (result of feedback) - _handle()
- renamed to emit(), _logRecord() renamed to handle().
- Renamed FATAL to CRITICAL (David Goodger), but left
- fatal() and FATAL in (until PEP is changed)
- Changed configuration file format to ConfigParser
- format.
- Factored filter application functionality out to a new
- Filterer class. The isLoggable() method is renamed to
- filter() in both Filter and Filterer classes.
- Altered SMTPHandler __init__ to accept (host, port)
- for the mail internet address.
- Added GUI configurator which uses Tkinter and the new
- configuration file format. (See logconf.py and an
- example configuration file in logconf.ini)
- Altered log_test3.py to test with the new file format.
------------------------------------------------------------------------------
-0.4 21 Mar 2002 Incorporated comments/patches from Ollie Rutherfurd:
- -Added level filtering for handlers.
- -Return root logger if no name specified in getLogger.
- Incorporated comments from Greg Ward:
- -Added distutils setup.py script.
- Added formatter initialization in Handler.__init__.
- Tidied up docstrings.
- Added removeHandler to Logger.
- Added removeFilter to Logger and Handler.
- logrecv.py modified to keep connection alive until
- client closes it.
- SocketHandler modified to not reset connection after
- each logging event.
- Added shutdown function which closes open sockets
- Renamed DEFAULT_LOGGING_PORT->DEFAULT_TCP_LOGGING_PORT
- Added DEFAULT_UDP_LOGGING_PORT
- Added log_test4.py (example of arbitrary levels)
- Added addLevelName, changed behaviour of getLevelName
- Fixed bugs in DatagramHandler
- Added SMTPHandler implementation
- Added log_test5.py to test SMTPHandler
- Added SysLogHandler (contribution from Nicolas Untz
- based on Sam Rushing's syslog.py)
- Modified log_test1.py to add a SysLogHandler
- Added rollover functionality to FileHandler
- Added NTEventLogHandler (based on Win32 extensions)
- Added MemoryHandler implementation
- Added log_test7.py to test MemoryHandler
- Added log_test8.py to test FileHandler rollover
- Added logException method to Logger
- Added formatException method to Formatter
- Added log_test6.py to test NTEventHandler and
- logException
- Numerous internal method renamings (sorry - but better
- to do this now, rather than when we enter beta status).
------------------------------------------------------------------------------
-0.3 14 Mar 2002 First public release, for early feedback
------------------------------------------------------------------------------
-0.2 Consolidated into single file (for internal use only)
------------------------------------------------------------------------------
-0.1 Initial implementation (for internal use only)
------------------------------------------------------------------------------
-
------------------------------------------------------------------------------
-COPYRIGHT
------------------------------------------------------------------------------
-Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Vinay Sajip
-not be used in advertising or publicity pertaining to distribution
-of the software without specific, written prior permission.
-VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
-AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/tools/python/logging/logging-0.4.9.2/default.css b/tools/python/logging/logging-0.4.9.2/default.css
deleted file mode 100644
index 0c7ce5b..0000000
--- a/tools/python/logging/logging-0.4.9.2/default.css
+++ /dev/null
@@ -1,32 +0,0 @@
-BODY, P, UL, OL {font-family: Verdana, Arial, Helvetica, Geneva, sans-serif ; background: white; color: black; font-size: 10pt; }
-CODE {font-family: "Courier New", Courier, Monaco, monospace ; }
-PRE {font-family: "Courier New", Courier, Monaco, monospace ; }
-.program { color: navy; font-family: "Courier New", Courier, Monaco, monospace }
-.output { color: maroon }
-HR {color: gray ; }
-.navbar { font-family: Verdana, Arial, Helvetica, Geneva, sans-serif; background: #FFFF66 ; border-style: none none solid none; border-width: thin; padding: 2px;}
-.navarea { background: #FFFF66 ; }
-TR { font-size: 10pt }
-.red { color: #FF0000 }
-.maroon { color: #800000 }
-.comment { color: green }
-.optional { color: silver }
-.strong { font-weight: bold }
-TR.tblheading { background: silver ; }
-.notrecommended {color: #666666 ; }
-.deemphasized {color: #666666 ; }
-TABLE.densetable {font-size: 80% ; }
-TH { text-align: left; background: silver }
-TR.summaryrow { font-size: 90%; background: #00FFFF ; }
-CAPTION {font-size: 100% ; }
-.embeddedfloat {float: right; margin-left: 3em}
-.bigtd { font-size: 18pt }
-TD, .normaltd { vertical-align: top; background: #EEEEEE; font-family: Verdana, Arial, Helvetica, Geneva, sans-serif; font-size: 10pt }
-H1, H2, H3, H4, H5, H6 {font-family: Verdana, Arial, Helvetica, Geneva, sans-serif ; }
-H4 {margin-bottom: 0.5em }
-H5, H6 {margin-bottom: 0.1em }
-A:link {color: blue ; }
-A:visited {color: purple ; }
-A:active {color: red ; }
-A { font-family: Verdana, Arial, Helvetica, Geneva, sans-serif; font-size: 10pt }
-.warning { color: red }
\ No newline at end of file
diff --git a/tools/python/logging/logging-0.4.9.2/liblogging.tex b/tools/python/logging/logging-0.4.9.2/liblogging.tex
deleted file mode 100644
index bc39ab2..0000000
--- a/tools/python/logging/logging-0.4.9.2/liblogging.tex
+++ /dev/null
@@ -1,1281 +0,0 @@
-\section{\module{logging} ---
- Logging facility for Python}
-
-\declaremodule{standard}{logging}
-
-% These apply to all modules, and may be given more than once:
-
-\moduleauthor{Vinay Sajip}{vinay_sajip at red-dove.com}
-\sectionauthor{Vinay Sajip}{vinay_sajip at red-dove.com}
-
-\modulesynopsis{Logging module for Python based on \pep{282}.}
-
-\indexii{Errors}{logging}
-
-\versionadded{2.3}
-This module defines functions and classes which implement a flexible
-error logging system for applications.
-
-Logging is performed by calling methods on instances of the
-\class{Logger} class (hereafter called \dfn{loggers}). Each instance has a
-name, and they are conceptually arranged in a name space hierarchy
-using dots (periods) as separators. For example, a logger named
-"scan" is the parent of loggers "scan.text", "scan.html" and "scan.pdf".
-Logger names can be anything you want, and indicate the area of an
-application in which a logged message originates.
-
-Logged messages also have levels of importance associated with them.
-The default levels provided are \constant{DEBUG}, \constant{INFO},
-\constant{WARNING}, \constant{ERROR} and \constant{CRITICAL}. As a
-convenience, you indicate the importance of a logged message by calling
-an appropriate method of \class{Logger}. The methods are
-\method{debug()}, \method{info()}, \method{warning()}, \method{error()} and
-\method{critical()}, which mirror the default levels. You are not
-constrained to use these levels: you can specify your own and use a
-more general \class{Logger} method, \method{log()}, which takes an
-explicit level argument.
-
-Levels can also be associated with loggers, being set either by the
-developer or through loading a saved logging configuration. When a
-logging method is called on a logger, the logger compares its own
-level with the level associated with the method call. If the logger's
-level is higher than the method call's, no logging message is actually
-generated. This is the basic mechanism controlling the verbosity of
-logging output.
-
-Logging messages are encoded as instances of the \class{LogRecord} class.
-When a logger decides to actually log an event, an \class{LogRecord}
-instance is created from the logging message.
-
-Logging messages are subjected to a dispatch mechanism through the
-use of \dfn{handlers}, which are instances of subclasses of the
-\class{Handler} class. Handlers are responsible for ensuring that a logged
-message (in the form of a \class{LogRecord}) ends up in a particular
-location (or set of locations) which is useful for the target audience for
-that message (such as end users, support desk staff, system administrators,
-developers). Handlers are passed \class{LogRecord} instances intended for
-particular destinations. Each logger can have zero, one or more handlers
-associated with it (via the \method{addHandler} method of \class{Logger}).
-In addition to any handlers directly associated with a logger,
-\emph{all handlers associated with all ancestors of the logger} are
-called to dispatch the message.
-
-Just as for loggers, handlers can have levels associated with them.
-A handler's level acts as a filter in the same way as a logger's level does.
-If a handler decides to actually dispatch an event, the \method{emit()} method
-is used to send the message to its destination. Most user-defined subclasses
-of \class{Handler} will need to override this \method{emit()}.
-
-In addition to the base \class{Handler} class, many useful subclasses
-are provided:
-
-\begin{enumerate}
-
-\item \class{StreamHandler} instances send error messages to
-streams (file-like objects).
-
-\item \class{FileHandler} instances send error messages to disk
-files.
-
-\item \class{RotatingFileHandler} instances send error messages to disk
-files, with support for maximum log file sizes and log file rotation.
-
-\item \class{SocketHandler} instances send error messages to
-TCP/IP sockets.
-
-\item \class{DatagramHandler} instances send error messages to UDP
-sockets.
-
-\item \class{SMTPHandler} instances send error messages to a
-designated email address.
-
-\item \class{SysLogHandler} instances send error messages to a
-\UNIX{} syslog daemon, possibly on a remote machine.
-
-\item \class{NTEventLogHandler} instances send error messages to a
-Windows NT/2000/XP event log.
-
-\item \class{MemoryHandler} instances send error messages to a
-buffer in memory, which is flushed whenever specific criteria are
-met.
-
-\item \class{HTTPHandler} instances send error messages to an
-HTTP server using either \samp{GET} or \samp{POST} semantics.
-
-\end{enumerate}
-
-The \class{StreamHandler} and \class{FileHandler} classes are defined
-in the core logging package. The other handlers are defined in a sub-
-module, \module{logging.handlers}. (There is also another sub-module,
-\module{logging.config}, for configuration functionality.)
-
-Logged messages are formatted for presentation through instances of the
-\class{Formatter} class. They are initialized with a format string
-suitable for use with the \% operator and a dictionary.
-
-For formatting multiple messages in a batch, instances of
-\class{BufferingFormatter} can be used. In addition to the format string
-(which is applied to each message in the batch), there is provision for
-header and trailer format strings.
-
-When filtering based on logger level and/or handler level is not enough,
-instances of \class{Filter} can be added to both \class{Logger} and
-\class{Handler} instances (through their \method{addFilter()} method).
-Before deciding to process a message further, both loggers and handlers
-consult all their filters for permission. If any filter returns a false
-value, the message is not processed further.
-
-The basic \class{Filter} functionality allows filtering by specific logger
-name. If this feature is used, messages sent to the named logger and its
-children are allowed through the filter, and all others dropped.
-
-In addition to the classes described above, there are a number of module-
-level functions.
-
-\begin{funcdesc}{getLogger}{\optional{name}}
-Return a logger with the specified name or, if no name is specified, return
-a logger which is the root logger of the hierarchy.
-
-All calls to this function with a given name return the same logger instance.
-This means that logger instances never need to be passed between different
-parts of an application.
-\end{funcdesc}
-
-\begin{funcdesc}{debug}{msg\optional{, *args\optional{, **kwargs}}}
-Logs a message with level \constant{DEBUG} on the root logger.
-The \var{msg} is the message format string, and the \var{args} are the
-arguments which are merged into \var{msg}. The only keyword argument in
-\var{kwargs} which is inspected is \var{exc_info} which, if it does not
-evaluate as false, causes exception information (via a call to
-\function{sys.exc_info()}) to be added to the logging message.
-\end{funcdesc}
-
-\begin{funcdesc}{info}{msg\optional{, *args\optional{, **kwargs}}}
-Logs a message with level \constant{INFO} on the root logger.
-The arguments are interpreted as for \function{debug()}.
-\end{funcdesc}
-
-\begin{funcdesc}{warning}{msg\optional{, *args\optional{, **kwargs}}}
-Logs a message with level \constant{WARNING} on the root logger.
-The arguments are interpreted as for \function{debug()}.
-\end{funcdesc}
-
-\begin{funcdesc}{error}{msg\optional{, *args\optional{, **kwargs}}}
-Logs a message with level \constant{ERROR} on the root logger.
-The arguments are interpreted as for \function{debug()}.
-\end{funcdesc}
-
-\begin{funcdesc}{critical}{msg\optional{, *args\optional{, **kwargs}}}
-Logs a message with level \constant{CRITICAL} on the root logger.
-The arguments are interpreted as for \function{debug()}.
-\end{funcdesc}
-
-\begin{funcdesc}{exception}{msg\optional{, *args}}
-Logs a message with level \constant{ERROR} on the root logger.
-The arguments are interpreted as for \function{debug()}. Exception info
-is added to the logging message. This function should only be called
-from an exception handler.
-\end{funcdesc}
-
-\begin{funcdesc}{disable}{lvl}
-Provides an overriding level \var{lvl} for all loggers which takes
-precedence over the logger's own level. When the need arises to
-temporarily throttle logging output down across the whole application,
-this function can be useful.
-\end{funcdesc}
-
-\begin{funcdesc}{addLevelName}{lvl, levelName}
-Associates level \var{lvl} with text \var{levelName} in an internal
-dictionary, which is used to map numeric levels to a textual
-representation, for example when a \class{Formatter} formats a message.
-This function can also be used to define your own levels. The only
-constraints are that all levels used must be registered using this
-function, levels should be positive integers and they should increase
-in increasing order of severity.
-\end{funcdesc}
-
-\begin{funcdesc}{getLevelName}{lvl}
-Returns the textual representation of logging level \var{lvl}. If the
-level is one of the predefined levels \constant{CRITICAL},
-\constant{ERROR}, \constant{WARNING}, \constant{INFO} or \constant{DEBUG}
-then you get the corresponding string. If you have associated levels
-with names using \function{addLevelName()} then the name you have associated
-with \var{lvl} is returned. Otherwise, the string "Level \%s" \% lvl is
-returned.
-\end{funcdesc}
-
-\begin{funcdesc}{makeLogRecord}{attrdict}
-Creates and returns a new \class{LogRecord} instance whose attributes are
-defined by \var{attrdict}. This function is useful for taking a pickled
-\class{LogRecord} attribute dictionary, sent over a socket, and reconstituting
-it as a \class{LogRecord} instance at the receiving end.
-\end{funcdesc}
-
-\begin{funcdesc}{basicConfig}{}
-Does basic configuration for the logging system by creating a
-\class{StreamHandler} with a default \class{Formatter} and adding it to
-the root logger. The functions \function{debug()}, \function{info()},
-\function{warning()}, \function{error()} and \function{critical()} will call
-\function{basicConfig()} automatically if no handlers are defined for the
-root logger.
-\end{funcdesc}
-
-\begin{funcdesc}{shutdown}{}
-Informs the logging system to perform an orderly shutdown by flushing and
-closing all handlers.
-\end{funcdesc}
-
-\begin{funcdesc}{setLoggerClass}{klass}
-Tells the logging system to use the class \var{klass} when instantiating a
-logger. The class should define \method{__init__()} such that only a name
-argument is required, and the \method{__init__()} should call
-\method{Logger.__init__()}. This function is typically called before any
-loggers are instantiated by applications which need to use custom logger
-behavior.
-\end{funcdesc}
-
-
-\begin{seealso}
- \seepep{282}{A Logging System}
- {The proposal which described this feature for inclusion in
- the Python standard library.}
- \seelink{http://www.red-dove.com/python_logging.html}
- {Original Python \module{logging} package}
- {This is the original source for the \module{logging}
- package. The version of the package available from this
- site is suitable for use with Python 1.5.2, 2.1.x and 2.2.x, which
- do not include the \module{logging} package in the standard
- library.}
-\end{seealso}
-
-
-\subsection{Logger Objects}
-
-Loggers have the following attributes and methods. Note that Loggers are
-never instantiated directly, but always through the module-level function
-\function{logging.getLogger(name)}.
-
-\begin{datadesc}{propagate}
-If this evaluates to false, logging messages are not passed by this
-logger or by child loggers to higher level (ancestor) loggers. The
-constructor sets this attribute to 1.
-\end{datadesc}
-
-\begin{methoddesc}{setLevel}{lvl}
-Sets the threshold for this logger to \var{lvl}. Logging messages
-which are less severe than \var{lvl} will be ignored. When a logger is
-created, the level is set to \constant{NOTSET} (which causes all messages
-to be processed in the root logger, or delegation to the parent in non-root
-loggers).
-\end{methoddesc}
-
-\begin{methoddesc}{isEnabledFor}{lvl}
-Indicates if a message of severity \var{lvl} would be processed by
-this logger. This method checks first the module-level level set by
-\function{logging.disable(lvl)} and then the logger's effective level as
-determined by \method{getEffectiveLevel()}.
-\end{methoddesc}
-
-\begin{methoddesc}{getEffectiveLevel}{}
-Indicates the effective level for this logger. If a value other than
-\constant{NOTSET} has been set using \method{setLevel()}, it is returned.
-Otherwise, the hierarchy is traversed towards the root until a value
-other than \constant{NOTSET} is found, and that value is returned.
-\end{methoddesc}
-
-\begin{methoddesc}{debug}{msg\optional{, *args\optional{, **kwargs}}}
-Logs a message with level \constant{DEBUG} on this logger.
-The \var{msg} is the message format string, and the \var{args} are the
-arguments which are merged into \var{msg}. The only keyword argument in
-\var{kwargs} which is inspected is \var{exc_info} which, if it does not
-evaluate as false, causes exception information (via a call to
-\function{sys.exc_info()}) to be added to the logging message.
-\end{methoddesc}
-
-\begin{methoddesc}{info}{msg\optional{, *args\optional{, **kwargs}}}
-Logs a message with level \constant{INFO} on this logger.
-The arguments are interpreted as for \method{debug()}.
-\end{methoddesc}
-
-\begin{methoddesc}{warning}{msg\optional{, *args\optional{, **kwargs}}}
-Logs a message with level \constant{WARNING} on this logger.
-The arguments are interpreted as for \method{debug()}.
-\end{methoddesc}
-
-\begin{methoddesc}{error}{msg\optional{, *args\optional{, **kwargs}}}
-Logs a message with level \constant{ERROR} on this logger.
-The arguments are interpreted as for \method{debug()}.
-\end{methoddesc}
-
-\begin{methoddesc}{critical}{msg\optional{, *args\optional{, **kwargs}}}
-Logs a message with level \constant{CRITICAL} on this logger.
-The arguments are interpreted as for \method{debug()}.
-\end{methoddesc}
-
-\begin{methoddesc}{log}{lvl, msg\optional{, *args\optional{, **kwargs}}}
-Logs a message with level \var{lvl} on this logger.
-The other arguments are interpreted as for \method{debug()}.
-\end{methoddesc}
-
-\begin{methoddesc}{exception}{msg\optional{, *args}}
-Logs a message with level \constant{ERROR} on this logger.
-The arguments are interpreted as for \method{debug()}. Exception info
-is added to the logging message. This method should only be called
-from an exception handler.
-\end{methoddesc}
-
-\begin{methoddesc}{addFilter}{filt}
-Adds the specified filter \var{filt} to this logger.
-\end{methoddesc}
-
-\begin{methoddesc}{removeFilter}{filt}
-Removes the specified filter \var{filt} from this logger.
-\end{methoddesc}
-
-\begin{methoddesc}{filter}{record}
-Applies this logger's filters to the record and returns a true value if
-the record is to be processed.
-\end{methoddesc}
-
-\begin{methoddesc}{addHandler}{hdlr}
-Adds the specified handler \var{hdlr} to this logger.
-\end{methoddesc}
-
-\begin{methoddesc}{removeHandler}{hdlr}
-Removes the specified handler \var{hdlr} from this logger.
-\end{methoddesc}
-
-\begin{methoddesc}{findCaller}{}
-Finds the caller's source filename and line number. Returns the filename
-and line number as a 2-element tuple.
-\end{methoddesc}
-
-\begin{methoddesc}{handle}{record}
-Handles a record by passing it to all handlers associated with this logger
-and its ancestors (until a false value of \var{propagate} is found).
-This method is used for unpickled records received from a socket, as well
-as those created locally. Logger-level filtering is applied using
-\method{filter()}.
-\end{methoddesc}
-
-\begin{methoddesc}{makeRecord}{name, lvl, fn, lno, msg, args, exc_info}
-This is a factory method which can be overridden in subclasses to create
-specialized \class{LogRecord} instances.
-\end{methoddesc}
-
-\subsection{Handler Objects}
-
-Handlers have the following attributes and methods. Note that
-\class{Handler} is never instantiated directly; this class acts as a
-base for more useful subclasses. However, the \method{__init__()}
-method in subclasses needs to call \method{Handler.__init__()}.
-
-\begin{methoddesc}{__init__}{level=\constant{NOTSET}}
-Initializes the \class{Handler} instance by setting its level, setting
-the list of filters to the empty list and creating a lock (using
-\method{createLock()}) for serializing access to an I/O mechanism.
-\end{methoddesc}
-
-\begin{methoddesc}{createLock}{}
-Initializes a thread lock which can be used to serialize access to
-underlying I/O functionality which may not be threadsafe.
-\end{methoddesc}
-
-\begin{methoddesc}{acquire}{}
-Acquires the thread lock created with \method{createLock()}.
-\end{methoddesc}
-
-\begin{methoddesc}{release}{}
-Releases the thread lock acquired with \method{acquire()}.
-\end{methoddesc}
-
-\begin{methoddesc}{setLevel}{lvl}
-Sets the threshold for this handler to \var{lvl}. Logging messages which are
-less severe than \var{lvl} will be ignored. When a handler is created, the
-level is set to \constant{NOTSET} (which causes all messages to be processed).
-\end{methoddesc}
-
-\begin{methoddesc}{setFormatter}{form}
-Sets the \class{Formatter} for this handler to \var{form}.
-\end{methoddesc}
-
-\begin{methoddesc}{addFilter}{filt}
-Adds the specified filter \var{filt} to this handler.
-\end{methoddesc}
-
-\begin{methoddesc}{removeFilter}{filt}
-Removes the specified filter \var{filt} from this handler.
-\end{methoddesc}
-
-\begin{methoddesc}{filter}{record}
-Applies this handler's filters to the record and returns a true value if
-the record is to be processed.
-\end{methoddesc}
-
-\begin{methoddesc}{flush}{}
-Ensure all logging output has been flushed. This version does
-nothing and is intended to be implemented by subclasses.
-\end{methoddesc}
-
-\begin{methoddesc}{close}{}
-Tidy up any resources used by the handler. This version does
-nothing and is intended to be implemented by subclasses.
-\end{methoddesc}
-
-\begin{methoddesc}{handle}{record}
-Conditionally emits the specified logging record, depending on
-filters which may have been added to the handler. Wraps the actual
-emission of the record with acquisition/release of the I/O thread
-lock.
-\end{methoddesc}
-
-\begin{methoddesc}{handleError}{record}
-This method should be called from handlers when an exception is
-encountered during an \method{emit()} call. By default it does nothing,
-which means that exceptions get silently ignored. This is what is
-mostly wanted for a logging system - most users will not care
-about errors in the logging system, they are more interested in
-application errors. You could, however, replace this with a custom
-handler if you wish. The specified record is the one which was being
-processed when the exception occurred.
-\end{methoddesc}
-
-\begin{methoddesc}{format}{record}
-Do formatting for a record - if a formatter is set, use it.
-Otherwise, use the default formatter for the module.
-\end{methoddesc}
-
-\begin{methoddesc}{emit}{record}
-Do whatever it takes to actually log the specified logging record.
-This version is intended to be implemented by subclasses and so
-raises a \exception{NotImplementedError}.
-\end{methoddesc}
-
-\subsubsection{StreamHandler}
-
-The \class{StreamHandler} class sends logging output to streams such as
-\var{sys.stdout}, \var{sys.stderr} or any file-like object (or, more
-precisely, any object which supports \method{write()} and \method{flush()}
-methods).
-
-\begin{classdesc}{StreamHandler}{\optional{strm}}
-Returns a new instance of the \class{StreamHandler} class. If \var{strm} is
-specified, the instance will use it for logging output; otherwise,
-\var{sys.stderr} will be used.
-\end{classdesc}
-
-\begin{methoddesc}{emit}{record}
-If a formatter is specified, it is used to format the record.
-The record is then written to the stream with a trailing newline.
-If exception information is present, it is formatted using
-\function{traceback.print_exception()} and appended to the stream.
-\end{methoddesc}
-
-\begin{methoddesc}{flush}{}
-Flushes the stream by calling its \method{flush()} method. Note that
-the \method{close()} method is inherited from \class{Handler} and
-so does nothing, so an explicit \method{flush()} call may be needed
-at times.
-\end{methoddesc}
-
-\subsubsection{FileHandler}
-
-The \class{FileHandler} class sends logging output to a disk file.
-It inherits the output functionality from \class{StreamHandler}.
-
-\begin{classdesc}{FileHandler}{filename\optional{, mode}}
-Returns a new instance of the \class{FileHandler} class. The specified
-file is opened and used as the stream for logging. If \var{mode} is
-not specified, \constant{'a'} is used. By default, the file grows
-indefinitely.
-\end{classdesc}
-
-\begin{methoddesc}{close}{}
-Closes the file.
-\end{methoddesc}
-
-\begin{methoddesc}{emit}{record}
-Outputs the record to the file.
-\end{methoddesc}
-
-\subsubsection{RotatingFileHandler}
-
-The \class{RotatingFileHandler} class supports rotation of disk log files.
-
-\begin{classdesc}{RotatingFileHandler}{filename\optional{, mode\optional{,
- maxBytes\optional{, backupCount}}}}
-Returns a new instance of the \class{RotatingFileHandler} class. The
-specified file is opened and used as the stream for logging. If
-\var{mode} is not specified, \code{'a'} is used. By default, the
-file grows indefinitely.
-
-You can use the \var{maxBytes} and
-\var{backupCount} values to allow the file to \dfn{rollover} at a
-predetermined size. When the size is about to be exceeded, the file is
-closed and a new file is silently opened for output. Rollover occurs
-whenever the current log file is nearly \var{maxBytes} in length; if
-\var{maxBytes} is zero, rollover never occurs. If \var{backupCount}
-is non-zero, the system will save old log files by appending the
-extensions ".1", ".2" etc., to the filename. For example, with
-a \var{backupCount} of 5 and a base file name of
-\file{app.log}, you would get \file{app.log},
-\file{app.log.1}, \file{app.log.2}, up to \file{app.log.5}. The file being
-written to is always \file{app.log}. When this file is filled, it is
-closed and renamed to \file{app.log.1}, and if files \file{app.log.1},
-\file{app.log.2}, etc. exist, then they are renamed to \file{app.log.2},
-\file{app.log.3} etc. respectively.
-\end{classdesc}
-
-\begin{methoddesc}{doRollover}{}
-Does a rollover, as described above.
-\end{methoddesc}
-
-\begin{methoddesc}{emit}{record}
-Outputs the record to the file, catering for rollover as described
-in \method{setRollover()}.
-\end{methoddesc}
-
-\subsubsection{SocketHandler}
-
-The \class{SocketHandler} class sends logging output to a network
-socket. The base class uses a TCP socket.
-
-\begin{classdesc}{SocketHandler}{host, port}
-Returns a new instance of the \class{SocketHandler} class intended to
-communicate with a remote machine whose address is given by \var{host}
-and \var{port}.
-\end{classdesc}
-
-\begin{methoddesc}{close}{}
-Closes the socket.
-\end{methoddesc}
-
-\begin{methoddesc}{handleError}{}
-\end{methoddesc}
-
-\begin{methoddesc}{emit}{}
-Pickles the record's attribute dictionary and writes it to the socket in
-binary format. If there is an error with the socket, silently drops the
-packet. If the connection was previously lost, re-establishes the connection.
-To unpickle the record at the receiving end into a LogRecord, use the
-\function{makeLogRecord} function.
-\end{methoddesc}
-
-\begin{methoddesc}{handleError}{}
-Handles an error which has occurred during \method{emit()}. The
-most likely cause is a lost connection. Closes the socket so that
-we can retry on the next event.
-\end{methoddesc}
-
-\begin{methoddesc}{makeSocket}{}
-This is a factory method which allows subclasses to define the precise
-type of socket they want. The default implementation creates a TCP
-socket (\constant{socket.SOCK_STREAM}).
-\end{methoddesc}
-
-\begin{methoddesc}{makePickle}{record}
-Pickles the record's attribute dictionary in binary format with a length
-prefix, and returns it ready for transmission across the socket.
-\end{methoddesc}
-
-\begin{methoddesc}{send}{packet}
-Send a pickled string \var{packet} to the socket. This function allows
-for partial sends which can happen when the network is busy.
-\end{methoddesc}
-
-\subsubsection{DatagramHandler}
-
-The \class{DatagramHandler} class inherits from \class{SocketHandler}
-to support sending logging messages over UDP sockets.
-
-\begin{classdesc}{DatagramHandler}{host, port}
-Returns a new instance of the \class{DatagramHandler} class intended to
-communicate with a remote machine whose address is given by \var{host}
-and \var{port}.
-\end{classdesc}
-
-\begin{methoddesc}{emit}{}
-Pickles the record's attribute dictionary and writes it to the socket in
-binary format. If there is an error with the socket, silently drops the
-packet.
-To unpickle the record at the receiving end into a LogRecord, use the
-\function{makeLogRecord} function.
-\end{methoddesc}
-
-\begin{methoddesc}{makeSocket}{}
-The factory method of \class{SocketHandler} is here overridden to create
-a UDP socket (\constant{socket.SOCK_DGRAM}).
-\end{methoddesc}
-
-\begin{methoddesc}{send}{s}
-Send a pickled string to a socket.
-\end{methoddesc}
-
-\subsubsection{SysLogHandler}
-
-The \class{SysLogHandler} class supports sending logging messages to a
-remote or local \UNIX{} syslog.
-
-\begin{classdesc}{SysLogHandler}{\optional{address\optional{, facility}}}
-Returns a new instance of the \class{SysLogHandler} class intended to
-communicate with a remote \UNIX{} machine whose address is given by
-\var{address} in the form of a \code{(\var{host}, \var{port})}
-tuple. If \var{address} is not specified, \code{('localhost', 514)} is
-used. The address is used to open a UDP socket. If \var{facility} is
-not specified, \constant{LOG_USER} is used.
-\end{classdesc}
-
-\begin{methoddesc}{close}{}
-Closes the socket to the remote host.
-\end{methoddesc}
-
-\begin{methoddesc}{emit}{record}
-The record is formatted, and then sent to the syslog server. If
-exception information is present, it is \emph{not} sent to the server.
-\end{methoddesc}
-
-\begin{methoddesc}{encodePriority}{facility, priority}
-Encodes the facility and priority into an integer. You can pass in strings
-or integers - if strings are passed, internal mapping dictionaries are used
-to convert them to integers.
-\end{methoddesc}
-
-\subsubsection{NTEventLogHandler}
-
-The \class{NTEventLogHandler} class supports sending logging messages
-to a local Windows NT, Windows 2000 or Windows XP event log. Before
-you can use it, you need Mark Hammond's Win32 extensions for Python
-installed.
-
-\begin{classdesc}{NTEventLogHandler}{appname\optional{,
- dllname\optional{, logtype}}}
-Returns a new instance of the \class{NTEventLogHandler} class. The
-\var{appname} is used to define the application name as it appears in the
-event log. An appropriate registry entry is created using this name.
-The \var{dllname} should give the fully qualified pathname of a .dll or .exe
-which contains message definitions to hold in the log (if not specified,
-\code{'win32service.pyd'} is used - this is installed with the Win32
-extensions and contains some basic placeholder message definitions.
-Note that use of these placeholders will make your event logs big, as the
-entire message source is held in the log. If you want slimmer logs, you have
-to pass in the name of your own .dll or .exe which contains the message
-definitions you want to use in the event log). The \var{logtype} is one of
-\code{'Application'}, \code{'System'} or \code{'Security'}, and
-defaults to \code{'Application'}.
-\end{classdesc}
-
-\begin{methoddesc}{close}{}
-At this point, you can remove the application name from the registry as a
-source of event log entries. However, if you do this, you will not be able
-to see the events as you intended in the Event Log Viewer - it needs to be
-able to access the registry to get the .dll name. The current version does
-not do this (in fact it doesn't do anything).
-\end{methoddesc}
-
-\begin{methoddesc}{emit}{record}
-Determines the message ID, event category and event type, and then logs the
-message in the NT event log.
-\end{methoddesc}
-
-\begin{methoddesc}{getEventCategory}{record}
-Returns the event category for the record. Override this if you
-want to specify your own categories. This version returns 0.
-\end{methoddesc}
-
-\begin{methoddesc}{getEventType}{record}
-Returns the event type for the record. Override this if you want
-to specify your own types. This version does a mapping using the
-handler's typemap attribute, which is set up in \method{__init__()}
-to a dictionary which contains mappings for \constant{DEBUG},
-\constant{INFO}, \constant{WARNING}, \constant{ERROR} and
-\constant{CRITICAL}. If you are using your own levels, you will either need
-to override this method or place a suitable dictionary in the
-handler's \var{typemap} attribute.
-\end{methoddesc}
-
-\begin{methoddesc}{getMessageID}{record}
-Returns the message ID for the record. If you are using your
-own messages, you could do this by having the \var{msg} passed to the
-logger being an ID rather than a format string. Then, in here,
-you could use a dictionary lookup to get the message ID. This
-version returns 1, which is the base message ID in
-\file{win32service.pyd}.
-\end{methoddesc}
-
-\subsubsection{SMTPHandler}
-
-The \class{SMTPHandler} class supports sending logging messages to an email
-address via SMTP.
-
-\begin{classdesc}{SMTPHandler}{mailhost, fromaddr, toaddrs, subject}
-Returns a new instance of the \class{SMTPHandler} class. The
-instance is initialized with the from and to addresses and subject
-line of the email. The \var{toaddrs} should be a list of strings without
-domain names (That's what the \var{mailhost} is for). To specify a
-non-standard SMTP port, use the (host, port) tuple format for the
-\var{mailhost} argument. If you use a string, the standard SMTP port
-is used.
-\end{classdesc}
-
-\begin{methoddesc}{emit}{record}
-Formats the record and sends it to the specified addressees.
-\end{methoddesc}
-
-\begin{methoddesc}{getSubject}{record}
-If you want to specify a subject line which is record-dependent,
-override this method.
-\end{methoddesc}
-
-\subsubsection{MemoryHandler}
-
-The \class{MemoryHandler} supports buffering of logging records in memory,
-periodically flushing them to a \dfn{target} handler. Flushing occurs
-whenever the buffer is full, or when an event of a certain severity or
-greater is seen.
-
-\class{MemoryHandler} is a subclass of the more general
-\class{BufferingHandler}, which is an abstract class. This buffers logging
-records in memory. Whenever each record is added to the buffer, a
-check is made by calling \method{shouldFlush()} to see if the buffer
-should be flushed. If it should, then \method{flush()} is expected to
-do the needful.
-
-\begin{classdesc}{BufferingHandler}{capacity}
-Initializes the handler with a buffer of the specified capacity.
-\end{classdesc}
-
-\begin{methoddesc}{emit}{record}
-Appends the record to the buffer. If \method{shouldFlush()} returns true,
-calls \method{flush()} to process the buffer.
-\end{methoddesc}
-
-\begin{methoddesc}{flush}{}
-You can override this to implement custom flushing behavior. This version
-just zaps the buffer to empty.
-\end{methoddesc}
-
-\begin{methoddesc}{shouldFlush}{record}
-Returns true if the buffer is up to capacity. This method can be
-overridden to implement custom flushing strategies.
-\end{methoddesc}
-
-\begin{classdesc}{MemoryHandler}{capacity\optional{, flushLevel
-\optional{, target}}}
-Returns a new instance of the \class{MemoryHandler} class. The
-instance is initialized with a buffer size of \var{capacity}. If
-\var{flushLevel} is not specified, \constant{ERROR} is used. If no
-\var{target} is specified, the target will need to be set using
-\method{setTarget()} before this handler does anything useful.
-\end{classdesc}
-
-\begin{methoddesc}{close}{}
-Calls \method{flush()}, sets the target to \constant{None} and
-clears the buffer.
-\end{methoddesc}
-
-\begin{methoddesc}{flush}{}
-For a \class{MemoryHandler}, flushing means just sending the buffered
-records to the target, if there is one. Override if you want
-different behavior.
-\end{methoddesc}
-
-\begin{methoddesc}{setTarget}{target}
-Sets the target handler for this handler.
-\end{methoddesc}
-
-\begin{methoddesc}{shouldFlush}{record}
-Checks for buffer full or a record at the \var{flushLevel} or higher.
-\end{methoddesc}
-
-\subsubsection{HTTPHandler}
-
-The \class{HTTPHandler} class supports sending logging messages to a
-Web server, using either \samp{GET} or \samp{POST} semantics.
-
-\begin{classdesc}{HTTPHandler}{host, url\optional{, method}}
-Returns a new instance of the \class{HTTPHandler} class. The
-instance is initialized with a host address, url and HTTP method.
-If no \var{method} is specified, \samp{GET} is used.
-\end{classdesc}
-
-\begin{methoddesc}{emit}{record}
-Sends the record to the Web server as an URL-encoded dictionary.
-\end{methoddesc}
-
-\subsection{Formatter Objects}
-
-\class{Formatter}s have the following attributes and methods. They are
-responsible for converting a \class{LogRecord} to (usually) a string
-which can be interpreted by either a human or an external system. The
-base
-\class{Formatter} allows a formatting string to be specified. If none is
-supplied, the default value of \code{'\%(message)s\e'} is used.
-
-A Formatter can be initialized with a format string which makes use of
-knowledge of the \class{LogRecord} attributes - such as the default value
-mentioned above making use of the fact that the user's message and
-arguments are pre-formatted into a LogRecord's \var{message}
-attribute. This format string contains standard python \%-style
-mapping keys. See section \ref{typesseq-strings}, ``String Formatting
-Operations,'' for more information on string formatting.
-
-Currently, the useful mapping keys in a LogRecord are:
-
-\begin{tableii}{l|l}{code}{Format}{Description}
-\lineii{\%(name)s} {Name of the logger (logging channel).}
-\lineii{\%(levelno)s} {Numeric logging level for the message
- (\constant{DEBUG}, \constant{INFO},
- \constant{WARNING}, \constant{ERROR},
- \constant{CRITICAL}).}
-\lineii{\%(levelname)s}{Text logging level for the message
- (\code{'DEBUG'}, \code{'INFO'},
- \code{'WARNING'}, \code{'ERROR'},
- \code{'CRITICAL'}).}
-\lineii{\%(pathname)s} {Full pathname of the source file where the logging
- call was issued (if available).}
-\lineii{\%(filename)s} {Filename portion of pathname.}
-\lineii{\%(module)s} {Module (name portion of filename).}
-\lineii{\%(lineno)d} {Source line number where the logging call was issued
- (if available).}
-\lineii{\%(created)f} {Time when the LogRecord was created (as
- returned by \function{time.time()}).}
-\lineii{\%(asctime)s} {Human-readable time when the LogRecord was created.
- By default this is of the form
- ``2003-07-08 16:49:45,896'' (the numbers after the
- comma are millisecond portion of the time).}
-\lineii{\%(msecs)d} {Millisecond portion of the time when the
- \class{LogRecord} was created.}
-\lineii{\%(thread)d} {Thread ID (if available).}
-\lineii{\%(process)d} {Process ID (if available).}
-\lineii{\%(message)s} {The logged message, computed as \code{msg \% args}.}
-\end{tableii}
-
-\begin{classdesc}{Formatter}{\optional{fmt\optional{, datefmt}}}
-Returns a new instance of the \class{Formatter} class. The
-instance is initialized with a format string for the message as a whole,
-as well as a format string for the date/time portion of a message. If
-no \var{fmt} is specified, \code{'\%(message)s'} is used. If no \var{datefmt}
-is specified, the ISO8601 date format is used.
-\end{classdesc}
-
-\begin{methoddesc}{format}{record}
-The record's attribute dictionary is used as the operand to a
-string formatting operation. Returns the resulting string.
-Before formatting the dictionary, a couple of preparatory steps
-are carried out. The \var{message} attribute of the record is computed
-using \var{msg} \% \var{args}. If the formatting string contains
-\code{'(asctime)'}, \method{formatTime()} is called to format the
-event time. If there is exception information, it is formatted using
-\method{formatException()} and appended to the message.
-\end{methoddesc}
-
-\begin{methoddesc}{formatTime}{record\optional{, datefmt}}
-This method should be called from \method{format()} by a formatter which
-wants to make use of a formatted time. This method can be overridden
-in formatters to provide for any specific requirement, but the
-basic behavior is as follows: if \var{datefmt} (a string) is specified,
-it is used with \function{time.strftime()} to format the creation time of the
-record. Otherwise, the ISO8601 format is used. The resulting
-string is returned.
-\end{methoddesc}
-
-\begin{methoddesc}{formatException}{exc_info}
-Formats the specified exception information (a standard exception tuple
-as returned by \function{sys.exc_info()}) as a string. This default
-implementation just uses \function{traceback.print_exception()}.
-The resulting string is returned.
-\end{methoddesc}
-
-\subsection{Filter Objects}
-
-\class{Filter}s can be used by \class{Handler}s and \class{Logger}s for
-more sophisticated filtering than is provided by levels. The base filter
-class only allows events which are below a certain point in the logger
-hierarchy. For example, a filter initialized with "A.B" will allow events
-logged by loggers "A.B", "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB",
-"B.A.B" etc. If initialized with the empty string, all events are passed.
-
-\begin{classdesc}{Filter}{\optional{name}}
-Returns an instance of the \class{Filter} class. If \var{name} is specified,
-it names a logger which, together with its children, will have its events
-allowed through the filter. If no name is specified, allows every event.
-\end{classdesc}
-
-\begin{methoddesc}{filter}{record}
-Is the specified record to be logged? Returns zero for no, nonzero for
-yes. If deemed appropriate, the record may be modified in-place by this
-method.
-\end{methoddesc}
-
-\subsection{LogRecord Objects}
-
-LogRecord instances are created every time something is logged. They
-contain all the information pertinent to the event being logged. The
-main information passed in is in msg and args, which are combined
-using msg \% args to create the message field of the record. The record
-also includes information such as when the record was created, the
-source line where the logging call was made, and any exception
-information to be logged.
-
-LogRecord has no methods; it's just a repository for information about the
-logging event. The only reason it's a class rather than a dictionary is to
-facilitate extension.
-
-\begin{classdesc}{LogRecord}{name, lvl, pathname, lineno, msg, args,
- exc_info}
-Returns an instance of \class{LogRecord} initialized with interesting
-information. The \var{name} is the logger name; \var{lvl} is the
-numeric level; \var{pathname} is the absolute pathname of the source
-file in which the logging call was made; \var{lineno} is the line
-number in that file where the logging call is found; \var{msg} is the
-user-supplied message (a format string); \var{args} is the tuple
-which, together with \var{msg}, makes up the user message; and
-\var{exc_info} is the exception tuple obtained by calling
-\function{sys.exc_info() }(or \constant{None}, if no exception information
-is available).
-\end{classdesc}
-
-\subsection{Thread Safety}
-
-The logging module is intended to be thread-safe without any special work
-needing to be done by its clients. It achieves this though using threading
-locks; there is one lock to serialize access to the module's shared data,
-and each handler also creates a lock to serialize access to its underlying
-I/O.
-
-\subsection{Configuration}
-
-
-\subsubsection{Configuration functions}
-
-The following functions allow the logging module to be
-configured. Before they can be used, you must import
-\module{logging.config}. Their use is optional --- you can configure
-the logging module entirely by making calls to the main API (defined
-in \module{logging} itself) and defining handlers which are declared
-either in \module{logging} or \module{logging.handlers}.
-
-\begin{funcdesc}{fileConfig}{fname\optional{, defaults}}
-Reads the logging configuration from a ConfigParser-format file named
-\var{fname}. This function can be called several times from an application,
-allowing an end user the ability to select from various pre-canned
-configurations (if the developer provides a mechanism to present the
-choices and load the chosen configuration). Defaults to be passed to
-ConfigParser can be specified in the \var{defaults} argument.
-\end{funcdesc}
-
-\begin{funcdesc}{listen}{\optional{port}}
-Starts up a socket server on the specified port, and listens for new
-configurations. If no port is specified, the module's default
-\constant{DEFAULT_LOGGING_CONFIG_PORT} is used. Logging configurations
-will be sent as a file suitable for processing by \function{fileConfig()}.
-Returns a \class{Thread} instance on which you can call \method{start()}
-to start the server, and which you can \method{join()} when appropriate.
-To stop the server, call \function{stopListening()}.
-\end{funcdesc}
-
-\begin{funcdesc}{stopListening}{}
-Stops the listening server which was created with a call to
-\function{listen()}. This is typically called before calling \method{join()}
-on the return value from \function{listen()}.
-\end{funcdesc}
-
-\subsubsection{Configuration file format}
-
-The configuration file format understood by \function{fileConfig} is
-based on ConfigParser functionality. The file must contain sections
-called \code{[loggers]}, \code{[handlers]} and \code{[formatters]}
-which identify by name the entities of each type which are defined in
-the file. For each such entity, there is a separate section which
-identified how that entity is configured. Thus, for a logger named
-\code{log01} in the \code{[loggers]} section, the relevant
-configuration details are held in a section
-\code{[logger_log01]}. Similarly, a handler called \code{hand01} in
-the \code{[handlers]} section will have its configuration held in a
-section called \code{[handler_hand01]}, while a formatter called
-\code{form01} in the \code{[formatters]} section will have its
-configuration specified in a section called
-\code{[formatter_form01]}. The root logger configuration must be
-specified in a section called \code{[logger_root]}.
-
-Examples of these sections in the file are given below.
-
-\begin{verbatim}
-[loggers]
-keys=root,log02,log03,log04,log05,log06,log07
-
-[handlers]
-keys=hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09
-
-[formatters]
-keys=form01,form02,form03,form04,form05,form06,form07,form08,form09
-\end{verbatim}
-
-The root logger must specify a level and a list of handlers. An
-example of a root logger section is given below.
-
-\begin{verbatim}
-[logger_root]
-level=NOTSET
-handlers=hand01
-\end{verbatim}
-
-The \code{level} entry can be one of \code{DEBUG, INFO, WARNING,
-ERROR, CRITICAL} or \code{NOTSET}. For the root logger only,
-\code{NOTSET} means that all messages will be logged. Level values are
-\function{eval()}uated in the context of the \code{logging} package's
-namespace.
-
-The \code{handlers} entry is a comma-separated list of handler names,
-which must appear in the \code{[handlers]} section. These names must
-appear in the \code{[handlers]} section and have corresponding
-sections in the configuration file.
-
-For loggers other than the root logger, some additional information is
-required. This is illustrated by the following example.
-
-\begin{verbatim}
-[logger_parser]
-level=DEBUG
-handlers=hand01
-propagate=1
-qualname=compiler.parser
-\end{verbatim}
-
-The \code{level} and \code{handlers} entries are interpreted as for
-the root logger, except that if a non-root logger's level is specified
-as \code{NOTSET}, the system consults loggers higher up the hierarchy
-to determine the effective level of the logger. The \code{propagate}
-entry is set to 1 to indicate that messages must propagate to handlers
-higher up the logger hierarchy from this logger, or 0 to indicate that
-messages are \strong{not} propagated to handlers up the hierarchy. The
-\code{qualname} entry is the hierarchical channel name of the logger,
-that is to say the name used by the application to get the logger.
-
-Sections which specify handler configuration are exemplified by the
-following.
-
-\begin{verbatim}
-[handler_hand01]
-class=StreamHandler
-level=NOTSET
-formatter=form01
-args=(sys.stdout,)
-\end{verbatim}
-
-The \code{class} entry indicates the handler's class (as determined by
-\function{eval()} in the \code{logging} package's namespace). The
-\code{level} is interpreted as for loggers, and \code{NOTSET} is taken
-to mean "log everything".
-
-The \code{formatter} entry indicates the key name of the formatter for
-this handler. If blank, a default formatter
-(\code{logging._defaultFormatter}) is used. If a name is specified, it
-must appear in the \code{[formatters]} section and have a
-corresponding section in the configuration file.
-
-The \code{args} entry, when \function{eval()}uated in the context of
-the \code{logging} package's namespace, is the list of arguments to
-the constructor for the handler class. Refer to the constructors for
-the relevant handlers, or to the examples below, to see how typical
-entries are constructed.
-
-\begin{verbatim}
-[handler_hand02]
-class=FileHandler
-level=DEBUG
-formatter=form02
-args=('python.log', 'w')
-
-[handler_hand03]
-class=handlers.SocketHandler
-level=INFO
-formatter=form03
-args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)
-
-[handler_hand04]
-class=handlers.DatagramHandler
-level=WARN
-formatter=form04
-args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)
-
-[handler_hand05]
-class=handlers.SysLogHandler
-level=ERROR
-formatter=form05
-args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)
-
-[handler_hand06]
-class=NTEventLogHandler
-level=CRITICAL
-formatter=form06
-args=('Python Application', '', 'Application')
-
-[handler_hand07]
-class=SMTPHandler
-level=WARN
-formatter=form07
-args=('localhost', 'from at abc', ['user1 at abc', 'user2 at xyz'], 'Logger Subject')
-
-[handler_hand08]
-class=MemoryHandler
-level=NOTSET
-formatter=form08
-target=
-args=(10, ERROR)
-
-[handler_hand09]
-class=HTTPHandler
-level=NOTSET
-formatter=form09
-args=('localhost:9022', '/log', 'GET')
-\end{verbatim}
-
-Sections which specify formatter configuration are typified by the following.
-
-\begin{verbatim}
-[formatter_form01]
-format=F1 %(asctime)s %(levelname)s %(message)s
-datefmt=
-\end{verbatim}
-
-The \code{format} entry is the overall format string, and the
-\code{datefmt} entry is the \function{strftime()}-compatible date/time format
-string. If empty, the package substitutes ISO8601 format date/times, which
-is almost equivalent to specifying the date format string "%Y-%m-%d %H:%M:%S".
-The ISO8601 format also specifies milliseconds, which are appended to the
-result of using the above format string, with a comma separator. An example
-time in ISO8601 format is \code{2003-01-23 00:29:50,411}.
-
-\subsection{Using the logging package}
-
-\subsubsection{Simplest usage}
-
-Here's a simple example which shows the most casual usage of the logging
-package.
-
-\begin{verbatim}
-import logging
-logging.debug("Houston, we have a %s", "thorny problem")
-logging.info("Houston, we have a %s", "interesting problem")
-logging.warning("Houston, we have a %s", "bit of a problem")
-logging.error("Houston, we have a %s", "major problem")
-logging.critical("Houston, we have a %s", "major disaster")
-try:
- infinity = 1 / 0
-except:
- logging.exception("Houston, we have an %s", "unexpected problem")
-\end{verbatim}
-
-If you run the above example, this will produce:
-
-\begin{verbatim}
-WARNING:root:Houston, we have a bit of a problem
-ERROR:root:Houston, we have a major problem
-CRITICAL:root:Houston, we have a major disaster
-ERROR:root:Houston, we have an unexpected problem
-Traceback (most recent call last):
- File "C:\Projects\RDC\Python\packages\logging\test\tmp.py", line 8, in ?
- infinity = 1 / 0
-ZeroDivisionError: integer division or modulo by zero
-\end{verbatim}
-
-The reason you get this output is that the default format is
-
-\begin{verbatim}
-"%(levelname)s:%(name)s:%(message)s".
-\end{verbatim}
-
-When you invoke functions \function{info()}, \function{warning()} etc. in the
-logging package itself, these calls are delegated to the correspondingly
-named methods in the root logger. This is why the logger name shown in the above
-logging output is "root". If the root logger has no handlers configured, the
-logging package creates a console handler and adds it to the root logger
-automatically. (It does this by calling the \function{basicConfig()}, which you
-can also call directly from your own code.)
-
-By default, events with a severity below WARNING are suppressed. Notice
-that the \function{exception()} function acts like \function{error()}, except
-that a traceback is appended to the log entry.
-
-\subsubsection{Logging to the console}
-
-Here's a simple example which logs all messages to the console. We use a named
-logger:
-
-\begin{verbatim}
-import logging
-logging.basicConfig()
-logger = logging.getLogger('myapp')
-logger.setLevel(logging.DEBUG)
-logger.debug("Houston, we have a %s", "thorny problem")
-logger.info("Houston, we have a %s", "interesting problem")
-logger.warning("Houston, we have a %s", "bit of a problem")
-logger.error("Houston, we have a %s", "major problem")
-logger.critical("Houston, we have a %s", "major disaster")
-try:
- infinity = 1 / 0
-except:
- logger.exception("Houston, we have an %s", "unexpected problem")
-\end{verbatim}
-
-Here's the corresponding output:
-
-\begin{verbatim}
-DEBUG:myapp:Houston, we have a thorny problem
-INFO:myapp:Houston, we have a interesting problem
-WARNING:myapp:Houston, we have a bit of a problem
-ERROR:myapp:Houston, we have a major problem
-CRITICAL:myapp:Houston, we have a major disaster
-ERROR:myapp:Houston, we have an unexpected problem
-Traceback (most recent call last):
- File "C:\Projects\RDC\Python\packages\logging\test\tmp.py", line 11, in ?
- infinity = 1 / 0
-ZeroDivisionError: integer division or modulo by zero
-\end{verbatim}
-
-As you can see, the specified logger name now appears in the output, and
-DEBUG and INFO messages are included in the output because we explicitly
-asked for them via the call to \method{setLevel()}.
-
-\subsubsection{Logging to a file}
-
-Here's a simple logging example that just logs to a file. In order,
-it creates a \class{Logger} instance, then a \class{FileHandler}
-and a \class{Formatter}. It attaches the \class{Formatter} to the
-\class{FileHandler}, then the \class{FileHandler} to the \class{Logger}.
-Finally, it sets a debug level for the logger.
-
-\begin{verbatim}
-import logging
-logger = logging.getLogger('myapp')
-hdlr = logging.FileHandler('/var/tmp/myapp.log')
-formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
-hdlr.setFormatter(formatter)
-logger.addHandler(hdlr)
-logger.setLevel(logging.WARNING)
-\end{verbatim}
-
-We can use this logger object now to write entries to the log file:
-
-\begin{verbatim}
-logger.error('We have a problem')
-logger.info('While this is just chatty')
-\end{verbatim}
-
-If we look in the file that was created, we'll see something like this:
-\begin{verbatim}
-2003-07-08 16:49:45,896 ERROR We have a problem
-\end{verbatim}
-
-The info message was not written to the file - we called the \method{setLevel}
-method to say we only wanted \code{WARNING} or worse, so the info message is
-discarded.
-
-The timestamp is of the form
-``year-month-day hour:minutes:seconds,milliseconds.''
-Note that despite the three digits of precision in the milliseconds field,
-not all systems provide time with this much precision.
-
-\subsubsection{Logging to a rotating set of files}
-
diff --git a/tools/python/logging/logging-0.4.9.2/logging/__init__.py b/tools/python/logging/logging-0.4.9.2/logging/__init__.py
deleted file mode 100644
index 75946e0..0000000
--- a/tools/python/logging/logging-0.4.9.2/logging/__init__.py
+++ /dev/null
@@ -1,1225 +0,0 @@
-# Copyright 2001-2004 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-"""
-Logging package for Python. Based on PEP 282 and comments thereto in
-comp.lang.python, and influenced by Apache's log4j system.
-
-Should work under Python versions >= 1.5.2, except that source line
-information is not available unless 'sys._getframe()' is.
-
-Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved.
-
-To use, simply 'import logging' and log away!
-"""
-
-import sys, os, types, time, string, cStringIO
-
-try:
- import thread
- import threading
-except ImportError:
- thread = None
-
-__author__ = "Vinay Sajip <vinay_sajip at red-dove.com>"
-__status__ = "beta"
-__version__ = "0.4.9.2"
-__date__ = "28 February 2004"
-
-#---------------------------------------------------------------------------
-# Miscellaneous module data
-#---------------------------------------------------------------------------
-
-#
-#_srcfile is used when walking the stack to check when we've got the first
-# caller stack frame.
-#
-if string.lower(__file__[-4:]) in ['.pyc', '.pyo']:
- _srcfile = __file__[:-4] + '.py'
-else:
- _srcfile = __file__
-_srcfile = os.path.normcase(_srcfile)
-
-# _srcfile is only used in conjunction with sys._getframe().
-# To provide compatibility with older versions of Python, set _srcfile
-# to None if _getframe() is not available; this value will prevent
-# findCaller() from being called.
-if not hasattr(sys, "_getframe"):
- _srcfile = None
-
-#
-#_startTime is used as the base when calculating the relative time of events
-#
-_startTime = time.time()
-
-#
-#raiseExceptions is used to see if exceptions during handling should be
-#propagated
-#
-raiseExceptions = 1
-
-#---------------------------------------------------------------------------
-# Level related stuff
-#---------------------------------------------------------------------------
-#
-# Default levels and level names, these can be replaced with any positive set
-# of values having corresponding names. There is a pseudo-level, NOTSET, which
-# is only really there as a lower limit for user-defined levels. Handlers and
-# loggers are initialized with NOTSET so that they will log all messages, even
-# at user-defined levels.
-#
-CRITICAL = 50
-FATAL = CRITICAL
-ERROR = 40
-WARNING = 30
-WARN = WARNING
-INFO = 20
-DEBUG = 10
-NOTSET = 0
-
-_levelNames = {
- CRITICAL : 'CRITICAL',
- ERROR : 'ERROR',
- WARNING : 'WARNING',
- INFO : 'INFO',
- DEBUG : 'DEBUG',
- NOTSET : 'NOTSET',
- 'CRITICAL' : CRITICAL,
- 'ERROR' : ERROR,
- 'WARN' : WARNING,
- 'WARNING' : WARNING,
- 'INFO' : INFO,
- 'DEBUG' : DEBUG,
- 'NOTSET' : NOTSET,
-}
-
-def getLevelName(level):
- """
- Return the textual representation of logging level 'level'.
-
- If the level is one of the predefined levels (CRITICAL, ERROR, WARNING,
- INFO, DEBUG) then you get the corresponding string. If you have
- associated levels with names using addLevelName then the name you have
- associated with 'level' is returned. Otherwise, the string
- "Level %s" % level is returned.
- """
- return _levelNames.get(level, ("Level %s" % level))
-
-def addLevelName(level, levelName):
- """
- Associate 'levelName' with 'level'.
-
- This is used when converting levels to text during message formatting.
- """
- _acquireLock()
- try: #unlikely to cause an exception, but you never know...
- _levelNames[level] = levelName
- _levelNames[levelName] = level
- finally:
- _releaseLock()
-
-#---------------------------------------------------------------------------
-# Thread-related stuff
-#---------------------------------------------------------------------------
-
-#
-#_lock is used to serialize access to shared data structures in this module.
-#This needs to be an RLock because fileConfig() creates Handlers and so
-#might arbitrary user threads. Since Handler.__init__() updates the shared
-#dictionary _handlers, it needs to acquire the lock. But if configuring,
-#the lock would already have been acquired - so we need an RLock.
-#The same argument applies to Loggers and Manager.loggerDict.
-#
-_lock = None
-
-def _acquireLock():
- """
- Acquire the module-level lock for serializing access to shared data.
-
- This should be released with _releaseLock().
- """
- global _lock
- if (not _lock) and thread:
- _lock = threading.RLock()
- if _lock:
- _lock.acquire()
-
-def _releaseLock():
- """
- Release the module-level lock acquired by calling _acquireLock().
- """
- if _lock:
- _lock.release()
-
-#---------------------------------------------------------------------------
-# The logging record
-#---------------------------------------------------------------------------
-
-class LogRecord:
- """
- A LogRecord instance represents an event being logged.
-
- LogRecord instances are created every time something is logged. They
- contain all the information pertinent to the event being logged. The
- main information passed in is in msg and args, which are combined
- using str(msg) % args to create the message field of the record. The
- record also includes information such as when the record was created,
- the source line where the logging call was made, and any exception
- information to be logged.
- """
- def __init__(self, name, level, pathname, lineno, msg, args, exc_info):
- """
- Initialize a logging record with interesting information.
- """
- ct = time.time()
- self.name = name
- self.msg = msg
- self.args = args
- self.levelname = getLevelName(level)
- self.levelno = level
- self.pathname = pathname
- try:
- self.filename = os.path.basename(pathname)
- self.module = os.path.splitext(self.filename)[0]
- except:
- self.filename = pathname
- self.module = "Unknown module"
- self.exc_info = exc_info
- self.exc_text = None # used to cache the traceback text
- self.lineno = lineno
- self.created = ct
- self.msecs = (ct - long(ct)) * 1000
- self.relativeCreated = (self.created - _startTime) * 1000
- if thread:
- self.thread = thread.get_ident()
- else:
- self.thread = None
- if hasattr(os, 'getpid'):
- self.process = os.getpid()
- else:
- self.process = None
-
- def __str__(self):
- return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
- self.pathname, self.lineno, self.msg)
-
- def getMessage(self):
- """
- Return the message for this LogRecord.
-
- Return the message for this LogRecord after merging any user-supplied
- arguments with the message.
- """
- if not hasattr(types, "UnicodeType"): #if no unicode support...
- msg = str(self.msg)
- else:
- try:
- msg = str(self.msg)
- except UnicodeError:
- msg = self.msg #Defer encoding till later
- if self.args:
- msg = msg % self.args
- return msg
-
-def makeLogRecord(dict):
- """
- Make a LogRecord whose attributes are defined by the specified dictionary,
- This function is useful for converting a logging event received over
- a socket connection (which is sent as a dictionary) into a LogRecord
- instance.
- """
- rv = LogRecord(None, None, "", 0, "", (), None)
- rv.__dict__.update(dict)
- return rv
-
-#---------------------------------------------------------------------------
-# Formatter classes and functions
-#---------------------------------------------------------------------------
-
-class Formatter:
- """
- Formatter instances are used to convert a LogRecord to text.
-
- Formatters need to know how a LogRecord is constructed. They are
- responsible for converting a LogRecord to (usually) a string which can
- be interpreted by either a human or an external system. The base Formatter
- allows a formatting string to be specified. If none is supplied, the
- default value of "%s(message)\\n" is used.
-
- The Formatter can be initialized with a format string which makes use of
- knowledge of the LogRecord attributes - e.g. the default value mentioned
- above makes use of the fact that the user's message and arguments are pre-
- formatted into a LogRecord's message attribute. Currently, the useful
- attributes in a LogRecord are described by:
-
- %(name)s Name of the logger (logging channel)
- %(levelno)s Numeric logging level for the message (DEBUG, INFO,
- WARNING, ERROR, CRITICAL)
- %(levelname)s Text logging level for the message ("DEBUG", "INFO",
- "WARNING", "ERROR", "CRITICAL")
- %(pathname)s Full pathname of the source file where the logging
- call was issued (if available)
- %(filename)s Filename portion of pathname
- %(module)s Module (name portion of filename)
- %(lineno)d Source line number where the logging call was issued
- (if available)
- %(created)f Time when the LogRecord was created (time.time()
- return value)
- %(asctime)s Textual time when the LogRecord was created
- %(msecs)d Millisecond portion of the creation time
- %(relativeCreated)d Time in milliseconds when the LogRecord was created,
- relative to the time the logging module was loaded
- (typically at application startup time)
- %(thread)d Thread ID (if available)
- %(process)d Process ID (if available)
- %(message)s The result of record.getMessage(), computed just as
- the record is emitted
- """
-
- converter = time.localtime
-
- def __init__(self, fmt=None, datefmt=None):
- """
- Initialize the formatter with specified format strings.
-
- Initialize the formatter either with the specified format string, or a
- default as described above. Allow for specialized date formatting with
- the optional datefmt argument (if omitted, you get the ISO8601 format).
- """
- if fmt:
- self._fmt = fmt
- else:
- self._fmt = "%(message)s"
- self.datefmt = datefmt
-
- def formatTime(self, record, datefmt=None):
- """
- Return the creation time of the specified LogRecord as formatted text.
-
- This method should be called from format() by a formatter which
- wants to make use of a formatted time. This method can be overridden
- in formatters to provide for any specific requirement, but the
- basic behaviour is as follows: if datefmt (a string) is specified,
- it is used with time.strftime() to format the creation time of the
- record. Otherwise, the ISO8601 format is used. The resulting
- string is returned. This function uses a user-configurable function
- to convert the creation time to a tuple. By default, time.localtime()
- is used; to change this for a particular formatter instance, set the
- 'converter' attribute to a function with the same signature as
- time.localtime() or time.gmtime(). To change it for all formatters,
- for example if you want all logging times to be shown in GMT,
- set the 'converter' attribute in the Formatter class.
- """
- ct = self.converter(record.created)
- if datefmt:
- s = time.strftime(datefmt, ct)
- else:
- t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
- s = "%s,%03d" % (t, record.msecs)
- return s
-
- def formatException(self, ei):
- """
- Format and return the specified exception information as a string.
-
- This default implementation just uses
- traceback.print_exception()
- """
- import traceback
- sio = cStringIO.StringIO()
- traceback.print_exception(ei[0], ei[1], ei[2], None, sio)
- s = sio.getvalue()
- sio.close()
- if s[-1] == "\n":
- s = s[:-1]
- return s
-
- def format(self, record):
- """
- Format the specified record as text.
-
- The record's attribute dictionary is used as the operand to a
- string formatting operation which yields the returned string.
- Before formatting the dictionary, a couple of preparatory steps
- are carried out. The message attribute of the record is computed
- using LogRecord.getMessage(). If the formatting string contains
- "%(asctime)", formatTime() is called to format the event time.
- If there is exception information, it is formatted using
- formatException() and appended to the message.
- """
- record.message = record.getMessage()
- if string.find(self._fmt,"%(asctime)") >= 0:
- record.asctime = self.formatTime(record, self.datefmt)
- s = self._fmt % record.__dict__
- if record.exc_info:
- # Cache the traceback text to avoid converting it multiple times
- # (it's constant anyway)
- if not record.exc_text:
- record.exc_text = self.formatException(record.exc_info)
- if record.exc_text:
- if s[-1] != "\n":
- s = s + "\n"
- s = s + record.exc_text
- return s
-
-#
-# The default formatter to use when no other is specified
-#
-_defaultFormatter = Formatter()
-
-class BufferingFormatter:
- """
- A formatter suitable for formatting a number of records.
- """
- def __init__(self, linefmt=None):
- """
- Optionally specify a formatter which will be used to format each
- individual record.
- """
- if linefmt:
- self.linefmt = linefmt
- else:
- self.linefmt = _defaultFormatter
-
- def formatHeader(self, records):
- """
- Return the header string for the specified records.
- """
- return ""
-
- def formatFooter(self, records):
- """
- Return the footer string for the specified records.
- """
- return ""
-
- def format(self, records):
- """
- Format the specified records and return the result as a string.
- """
- rv = ""
- if len(records) > 0:
- rv = rv + self.formatHeader(records)
- for record in records:
- rv = rv + self.linefmt.format(record)
- rv = rv + self.formatFooter(records)
- return rv
-
-#---------------------------------------------------------------------------
-# Filter classes and functions
-#---------------------------------------------------------------------------
-
-class Filter:
- """
- Filter instances are used to perform arbitrary filtering of LogRecords.
-
- Loggers and Handlers can optionally use Filter instances to filter
- records as desired. The base filter class only allows events which are
- below a certain point in the logger hierarchy. For example, a filter
- initialized with "A.B" will allow events logged by loggers "A.B",
- "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
- initialized with the empty string, all events are passed.
- """
- def __init__(self, name=''):
- """
- Initialize a filter.
-
- Initialize with the name of the logger which, together with its
- children, will have its events allowed through the filter. If no
- name is specified, allow every event.
- """
- self.name = name
- self.nlen = len(name)
-
- def filter(self, record):
- """
- Determine if the specified record is to be logged.
-
- Is the specified record to be logged? Returns 0 for no, nonzero for
- yes. If deemed appropriate, the record may be modified in-place.
- """
- if self.nlen == 0:
- return 1
- elif self.name == record.name:
- return 1
- elif string.find(record.name, self.name, 0, self.nlen) != 0:
- return 0
- return (record.name[self.nlen] == ".")
-
-class Filterer:
- """
- A base class for loggers and handlers which allows them to share
- common code.
- """
- def __init__(self):
- """
- Initialize the list of filters to be an empty list.
- """
- self.filters = []
-
- def addFilter(self, filter):
- """
- Add the specified filter to this handler.
- """
- if not (filter in self.filters):
- self.filters.append(filter)
-
- def removeFilter(self, filter):
- """
- Remove the specified filter from this handler.
- """
- if filter in self.filters:
- self.filters.remove(filter)
-
- def filter(self, record):
- """
- Determine if a record is loggable by consulting all the filters.
-
- The default is to allow the record to be logged; any filter can veto
- this and the record is then dropped. Returns a zero value if a record
- is to be dropped, else non-zero.
- """
- rv = 1
- for f in self.filters:
- if not f.filter(record):
- rv = 0
- break
- return rv
-
-#---------------------------------------------------------------------------
-# Handler classes and functions
-#---------------------------------------------------------------------------
-
-_handlers = {} #repository of handlers (for flushing when shutdown called)
-
-class Handler(Filterer):
- """
- Handler instances dispatch logging events to specific destinations.
-
- The base handler class. Acts as a placeholder which defines the Handler
- interface. Handlers can optionally use Formatter instances to format
- records as desired. By default, no formatter is specified; in this case,
- the 'raw' message as determined by record.message is logged.
- """
- def __init__(self, level=NOTSET):
- """
- Initializes the instance - basically setting the formatter to None
- and the filter list to empty.
- """
- Filterer.__init__(self)
- self.level = level
- self.formatter = None
- #get the module data lock, as we're updating a shared structure.
- _acquireLock()
- try: #unlikely to raise an exception, but you never know...
- _handlers[self] = 1
- finally:
- _releaseLock()
- self.createLock()
-
- def createLock(self):
- """
- Acquire a thread lock for serializing access to the underlying I/O.
- """
- if thread:
- self.lock = thread.allocate_lock()
- else:
- self.lock = None
-
- def acquire(self):
- """
- Acquire the I/O thread lock.
- """
- if self.lock:
- self.lock.acquire()
-
- def release(self):
- """
- Release the I/O thread lock.
- """
- if self.lock:
- self.lock.release()
-
- def setLevel(self, level):
- """
- Set the logging level of this handler.
- """
- self.level = level
-
- def format(self, record):
- """
- Format the specified record.
-
- If a formatter is set, use it. Otherwise, use the default formatter
- for the module.
- """
- if self.formatter:
- fmt = self.formatter
- else:
- fmt = _defaultFormatter
- return fmt.format(record)
-
- def emit(self, record):
- """
- Do whatever it takes to actually log the specified logging record.
-
- This version is intended to be implemented by subclasses and so
- raises a NotImplementedError.
- """
- raise NotImplementedError, 'emit must be implemented '\
- 'by Handler subclasses'
-
- def handle(self, record):
- """
- Conditionally emit the specified logging record.
-
- Emission depends on filters which may have been added to the handler.
- Wrap the actual emission of the record with acquisition/release of
- the I/O thread lock. Returns whether the filter passed the record for
- emission.
- """
- rv = self.filter(record)
- if rv:
- self.acquire()
- try:
- self.emit(record)
- finally:
- self.release()
- return rv
-
- def setFormatter(self, fmt):
- """
- Set the formatter for this handler.
- """
- self.formatter = fmt
-
- def flush(self):
- """
- Ensure all logging output has been flushed.
-
- This version does nothing and is intended to be implemented by
- subclasses.
- """
- pass
-
- def close(self):
- """
- Tidy up any resources used by the handler.
-
- This version does removes the handler from an internal list
- of handlers which is closed when shutdown() is called. Subclasses
- should ensure that this gets called from overridden close()
- methods.
- """
- #get the module data lock, as we're updating a shared structure.
- _acquireLock()
- try: #unlikely to raise an exception, but you never know...
- del _handlers[self]
- finally:
- _releaseLock()
-
- def handleError(self, record):
- """
- Handle errors which occur during an emit() call.
-
- This method should be called from handlers when an exception is
- encountered during an emit() call. If raiseExceptions is false,
- exceptions get silently ignored. This is what is mostly wanted
- for a logging system - most users will not care about errors in
- the logging system, they are more interested in application errors.
- You could, however, replace this with a custom handler if you wish.
- The record which was being processed is passed in to this method.
- """
- if raiseExceptions:
- import traceback
- ei = sys.exc_info()
- traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
- del ei
-
-class StreamHandler(Handler):
- """
- A handler class which writes logging records, appropriately formatted,
- to a stream. Note that this class does not close the stream, as
- sys.stdout or sys.stderr may be used.
- """
- def __init__(self, strm=None):
- """
- Initialize the handler.
-
- If strm is not specified, sys.stderr is used.
- """
- Handler.__init__(self)
- if not strm:
- strm = sys.stderr
- self.stream = strm
- self.formatter = None
-
- def flush(self):
- """
- Flushes the stream.
- """
- self.stream.flush()
-
- def emit(self, record):
- """
- Emit a record.
-
- If a formatter is specified, it is used to format the record.
- The record is then written to the stream with a trailing newline
- [N.B. this may be removed depending on feedback]. If exception
- information is present, it is formatted using
- traceback.print_exception and appended to the stream.
- """
- try:
- msg = self.format(record)
- if not hasattr(types, "UnicodeType"): #if no unicode support...
- self.stream.write("%s\n" % msg)
- else:
- try:
- self.stream.write("%s\n" % msg)
- except UnicodeError:
- self.stream.write("%s\n" % msg.encode("UTF-8"))
- self.flush()
- except:
- self.handleError(record)
-
-class FileHandler(StreamHandler):
- """
- A handler class which writes formatted logging records to disk files.
- """
- def __init__(self, filename, mode="a"):
- """
- Open the specified file and use it as the stream for logging.
- """
- StreamHandler.__init__(self, open(filename, mode))
- self.baseFilename = filename
- self.mode = mode
-
- def close(self):
- """
- Closes the stream.
- """
- self.flush()
- self.stream.close()
- StreamHandler.close(self)
-
-#---------------------------------------------------------------------------
-# Manager classes and functions
-#---------------------------------------------------------------------------
-
-class PlaceHolder:
- """
- PlaceHolder instances are used in the Manager logger hierarchy to take
- the place of nodes for which no loggers have been defined. This class is
- intended for internal use only and not as part of the public API.
- """
- def __init__(self, alogger):
- """
- Initialize with the specified logger being a child of this placeholder.
- """
- self.loggers = [alogger]
-
- def append(self, alogger):
- """
- Add the specified logger as a child of this placeholder.
- """
- if alogger not in self.loggers:
- self.loggers.append(alogger)
-
-#
-# Determine which class to use when instantiating loggers.
-#
-_loggerClass = None
-
-def setLoggerClass(klass):
- """
- Set the class to be used when instantiating a logger. The class should
- define __init__() such that only a name argument is required, and the
- __init__() should call Logger.__init__()
- """
- if klass != Logger:
- if not issubclass(klass, Logger):
- raise TypeError, "logger not derived from logging.Logger: " + \
- klass.__name__
- global _loggerClass
- _loggerClass = klass
-
-class Manager:
- """
- There is [under normal circumstances] just one Manager instance, which
- holds the hierarchy of loggers.
- """
- def __init__(self, rootnode):
- """
- Initialize the manager with the root node of the logger hierarchy.
- """
- self.root = rootnode
- self.disable = 0
- self.emittedNoHandlerWarning = 0
- self.loggerDict = {}
-
- def getLogger(self, name):
- """
- Get a logger with the specified name (channel name), creating it
- if it doesn't yet exist.
-
- If a PlaceHolder existed for the specified name [i.e. the logger
- didn't exist but a child of it did], replace it with the created
- logger and fix up the parent/child references which pointed to the
- placeholder to now point to the logger.
- """
- rv = None
- _acquireLock()
- try:
- if self.loggerDict.has_key(name):
- rv = self.loggerDict[name]
- if isinstance(rv, PlaceHolder):
- ph = rv
- rv = _loggerClass(name)
- rv.manager = self
- self.loggerDict[name] = rv
- self._fixupChildren(ph, rv)
- self._fixupParents(rv)
- else:
- rv = _loggerClass(name)
- rv.manager = self
- self.loggerDict[name] = rv
- self._fixupParents(rv)
- finally:
- _releaseLock()
- return rv
-
- def _fixupParents(self, alogger):
- """
- Ensure that there are either loggers or placeholders all the way
- from the specified logger to the root of the logger hierarchy.
- """
- name = alogger.name
- i = string.rfind(name, ".")
- rv = None
- while (i > 0) and not rv:
- substr = name[:i]
- if not self.loggerDict.has_key(substr):
- self.loggerDict[substr] = PlaceHolder(alogger)
- else:
- obj = self.loggerDict[substr]
- if isinstance(obj, Logger):
- rv = obj
- else:
- assert isinstance(obj, PlaceHolder)
- obj.append(alogger)
- i = string.rfind(name, ".", 0, i - 1)
- if not rv:
- rv = self.root
- alogger.parent = rv
-
- def _fixupChildren(self, ph, alogger):
- """
- Ensure that children of the placeholder ph are connected to the
- specified logger.
- """
- for c in ph.loggers:
- if string.find(c.parent.name, alogger.name) <> 0:
- alogger.parent = c.parent
- c.parent = alogger
-
-#---------------------------------------------------------------------------
-# Logger classes and functions
-#---------------------------------------------------------------------------
-
-class Logger(Filterer):
- """
- Instances of the Logger class represent a single logging channel. A
- "logging channel" indicates an area of an application. Exactly how an
- "area" is defined is up to the application developer. Since an
- application can have any number of areas, logging channels are identified
- by a unique string. Application areas can be nested (e.g. an area
- of "input processing" might include sub-areas "read CSV files", "read
- XLS files" and "read Gnumeric files"). To cater for this natural nesting,
- channel names are organized into a namespace hierarchy where levels are
- separated by periods, much like the Java or Python package namespace. So
- in the instance given above, channel names might be "input" for the upper
- level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
- There is no arbitrary limit to the depth of nesting.
- """
- def __init__(self, name, level=NOTSET):
- """
- Initialize the logger with a name and an optional level.
- """
- Filterer.__init__(self)
- self.name = name
- self.level = level
- self.parent = None
- self.propagate = 1
- self.handlers = []
- self.disabled = 0
-
- def setLevel(self, level):
- """
- Set the logging level of this logger.
- """
- self.level = level
-
-# def getRoot(self):
-# """
-# Get the root of the logger hierarchy.
-# """
-# return Logger.root
-
- def debug(self, msg, *args, **kwargs):
- """
- Log 'msg % args' with severity 'DEBUG'.
-
- To pass exception information, use the keyword argument exc_info with
- a true value, e.g.
-
- logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
- """
- if self.manager.disable >= DEBUG:
- return
- if DEBUG >= self.getEffectiveLevel():
- apply(self._log, (DEBUG, msg, args), kwargs)
-
- def info(self, msg, *args, **kwargs):
- """
- Log 'msg % args' with severity 'INFO'.
-
- To pass exception information, use the keyword argument exc_info with
- a true value, e.g.
-
- logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
- """
- if self.manager.disable >= INFO:
- return
- if INFO >= self.getEffectiveLevel():
- apply(self._log, (INFO, msg, args), kwargs)
-
- def warning(self, msg, *args, **kwargs):
- """
- Log 'msg % args' with severity 'WARNING'.
-
- To pass exception information, use the keyword argument exc_info with
- a true value, e.g.
-
- logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
- """
- if self.manager.disable >= WARNING:
- return
- if self.isEnabledFor(WARNING):
- apply(self._log, (WARNING, msg, args), kwargs)
-
- warn = warning
-
- def error(self, msg, *args, **kwargs):
- """
- Log 'msg % args' with severity 'ERROR'.
-
- To pass exception information, use the keyword argument exc_info with
- a true value, e.g.
-
- logger.error("Houston, we have a %s", "major problem", exc_info=1)
- """
- if self.manager.disable >= ERROR:
- return
- if self.isEnabledFor(ERROR):
- apply(self._log, (ERROR, msg, args), kwargs)
-
- def exception(self, msg, *args):
- """
- Convenience method for logging an ERROR with exception information.
- """
- apply(self.error, (msg,) + args, {'exc_info': 1})
-
- def critical(self, msg, *args, **kwargs):
- """
- Log 'msg % args' with severity 'CRITICAL'.
-
- To pass exception information, use the keyword argument exc_info with
- a true value, e.g.
-
- logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
- """
- if self.manager.disable >= CRITICAL:
- return
- if CRITICAL >= self.getEffectiveLevel():
- apply(self._log, (CRITICAL, msg, args), kwargs)
-
- fatal = critical
-
- def log(self, level, msg, *args, **kwargs):
- """
- Log 'msg % args' with the severity 'level'.
-
- To pass exception information, use the keyword argument exc_info with
- a true value, e.g.
-
- logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
- """
- if self.manager.disable >= level:
- return
- if self.isEnabledFor(level):
- apply(self._log, (level, msg, args), kwargs)
-
- def findCaller(self):
- """
- Find the stack frame of the caller so that we can note the source
- file name and line number.
- """
- f = sys._getframe(1)
- while 1:
- co = f.f_code
- filename = os.path.normcase(co.co_filename)
- if filename == _srcfile:
- f = f.f_back
- continue
- return filename, f.f_lineno
-
- def makeRecord(self, name, level, fn, lno, msg, args, exc_info):
- """
- A factory method which can be overridden in subclasses to create
- specialized LogRecords.
- """
- return LogRecord(name, level, fn, lno, msg, args, exc_info)
-
- def _log(self, level, msg, args, exc_info=None):
- """
- Low-level logging routine which creates a LogRecord and then calls
- all the handlers of this logger to handle the record.
- """
- if _srcfile:
- fn, lno = self.findCaller()
- else:
- fn, lno = "<unknown file>", 0
- if exc_info:
- if type(exc_info) != types.TupleType:
- exc_info = sys.exc_info()
- record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info)
- self.handle(record)
-
- def handle(self, record):
- """
- Call the handlers for the specified record.
-
- This method is used for unpickled records received from a socket, as
- well as those created locally. Logger-level filtering is applied.
- """
- if (not self.disabled) and self.filter(record):
- self.callHandlers(record)
-
- def addHandler(self, hdlr):
- """
- Add the specified handler to this logger.
- """
- if not (hdlr in self.handlers):
- self.handlers.append(hdlr)
-
- def removeHandler(self, hdlr):
- """
- Remove the specified handler from this logger.
- """
- if hdlr in self.handlers:
- #hdlr.close()
- self.handlers.remove(hdlr)
-
- def callHandlers(self, record):
- """
- Pass a record to all relevant handlers.
-
- Loop through all handlers for this logger and its parents in the
- logger hierarchy. If no handler was found, output a one-off error
- message to sys.stderr. Stop searching up the hierarchy whenever a
- logger with the "propagate" attribute set to zero is found - that
- will be the last logger whose handlers are called.
- """
- c = self
- found = 0
- while c:
- for hdlr in c.handlers:
- found = found + 1
- if record.levelno >= hdlr.level:
- hdlr.handle(record)
- if not c.propagate:
- c = None #break out
- else:
- c = c.parent
- if (found == 0) and not self.manager.emittedNoHandlerWarning:
- sys.stderr.write("No handlers could be found for logger"
- " \"%s\"\n" % self.name)
- self.manager.emittedNoHandlerWarning = 1
-
- def getEffectiveLevel(self):
- """
- Get the effective level for this logger.
-
- Loop through this logger and its parents in the logger hierarchy,
- looking for a non-zero logging level. Return the first one found.
- """
- logger = self
- while logger:
- if logger.level:
- return logger.level
- logger = logger.parent
- return NOTSET
-
- def isEnabledFor(self, level):
- """
- Is this logger enabled for level 'level'?
- """
- if self.manager.disable >= level:
- return 0
- return level >= self.getEffectiveLevel()
-
-class RootLogger(Logger):
- """
- A root logger is not that different to any other logger, except that
- it must have a logging level and there is only one instance of it in
- the hierarchy.
- """
- def __init__(self, level):
- """
- Initialize the logger with the name "root".
- """
- Logger.__init__(self, "root", level)
-
-_loggerClass = Logger
-
-root = RootLogger(WARNING)
-Logger.root = root
-Logger.manager = Manager(Logger.root)
-
-#---------------------------------------------------------------------------
-# Configuration classes and functions
-#---------------------------------------------------------------------------
-
-BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
-
-def basicConfig():
- """
- Do basic configuration for the logging system by creating a
- StreamHandler with a default Formatter and adding it to the
- root logger.
- """
- if len(root.handlers) == 0:
- hdlr = StreamHandler()
- fmt = Formatter(BASIC_FORMAT)
- hdlr.setFormatter(fmt)
- root.addHandler(hdlr)
-
-#---------------------------------------------------------------------------
-# Utility functions at module level.
-# Basically delegate everything to the root logger.
-#---------------------------------------------------------------------------
-
-def getLogger(name=None):
- """
- Return a logger with the specified name, creating it if necessary.
-
- If no name is specified, return the root logger.
- """
- if name:
- return Logger.manager.getLogger(name)
- else:
- return root
-
-#def getRootLogger():
-# """
-# Return the root logger.
-#
-# Note that getLogger('') now does the same thing, so this function is
-# deprecated and may disappear in the future.
-# """
-# return root
-
-def critical(msg, *args, **kwargs):
- """
- Log a message with severity 'CRITICAL' on the root logger.
- """
- if len(root.handlers) == 0:
- basicConfig()
- apply(root.critical, (msg,)+args, kwargs)
-
-fatal = critical
-
-def error(msg, *args, **kwargs):
- """
- Log a message with severity 'ERROR' on the root logger.
- """
- if len(root.handlers) == 0:
- basicConfig()
- apply(root.error, (msg,)+args, kwargs)
-
-def exception(msg, *args):
- """
- Log a message with severity 'ERROR' on the root logger,
- with exception information.
- """
- apply(error, (msg,)+args, {'exc_info': 1})
-
-def warning(msg, *args, **kwargs):
- """
- Log a message with severity 'WARNING' on the root logger.
- """
- if len(root.handlers) == 0:
- basicConfig()
- apply(root.warning, (msg,)+args, kwargs)
-
-warn = warning
-
-def info(msg, *args, **kwargs):
- """
- Log a message with severity 'INFO' on the root logger.
- """
- if len(root.handlers) == 0:
- basicConfig()
- apply(root.info, (msg,)+args, kwargs)
-
-def debug(msg, *args, **kwargs):
- """
- Log a message with severity 'DEBUG' on the root logger.
- """
- if len(root.handlers) == 0:
- basicConfig()
- apply(root.debug, (msg,)+args, kwargs)
-
-def disable(level):
- """
- Disable all logging calls less severe than 'level'.
- """
- root.manager.disable = level
-
-def shutdown():
- """
- Perform any cleanup actions in the logging system (e.g. flushing
- buffers).
-
- Should be called at application exit.
- """
- for h in _handlers.keys():
- h.flush()
- h.close()
-
-#Let's try and shutdown automatically on application exit...
-try:
- import atexit
- atexit.register(shutdown)
-except ImportError: # for Python versions < 2.0
- def exithook(status, old_exit=sys.exit):
- try:
- shutdown()
- finally:
- old_exit(status)
-
- sys.exit = exithook
diff --git a/tools/python/logging/logging-0.4.9.2/logging/config.py b/tools/python/logging/logging-0.4.9.2/logging/config.py
deleted file mode 100644
index c9ffab0..0000000
--- a/tools/python/logging/logging-0.4.9.2/logging/config.py
+++ /dev/null
@@ -1,301 +0,0 @@
-# Copyright 2001-2004 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-"""
-Configuration functions for the logging package for Python. The core package
-is based on PEP 282 and comments thereto in comp.lang.python, and influenced
-by Apache's log4j system.
-
-Should work under Python versions >= 1.5.2, except that source line
-information is not available unless 'sys._getframe()' is.
-
-Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved.
-
-To use, simply 'import logging' and log away!
-"""
-
-import sys, logging, logging.handlers, string, thread, threading, socket, struct, os
-
-from SocketServer import ThreadingTCPServer, StreamRequestHandler
-
-
-DEFAULT_LOGGING_CONFIG_PORT = 9030
-
-if sys.platform == "win32":
- RESET_ERROR = 10054 #WSAECONNRESET
-else:
- RESET_ERROR = 104 #ECONNRESET
-
-#
-# The following code implements a socket listener for on-the-fly
-# reconfiguration of logging.
-#
-# _listener holds the server object doing the listening
-_listener = None
-
-def fileConfig(fname, defaults=None):
- """
- Read the logging configuration from a ConfigParser-format file.
-
- This can be called several times from an application, allowing an end user
- the ability to select from various pre-canned configurations (if the
- developer provides a mechanism to present the choices and load the chosen
- configuration).
- In versions of ConfigParser which have the readfp method [typically
- shipped in 2.x versions of Python], you can pass in a file-like object
- rather than a filename, in which case the file-like object will be read
- using readfp.
- """
- import ConfigParser
-
- cp = ConfigParser.ConfigParser(defaults)
- if hasattr(cp, 'readfp') and hasattr(fname, 'readline'):
- cp.readfp(fname)
- else:
- cp.read(fname)
- #first, do the formatters...
- flist = cp.get("formatters", "keys")
- if len(flist):
- flist = string.split(flist, ",")
- formatters = {}
- for form in flist:
- sectname = "formatter_%s" % form
- opts = cp.options(sectname)
- if "format" in opts:
- fs = cp.get(sectname, "format", 1)
- else:
- fs = None
- if "datefmt" in opts:
- dfs = cp.get(sectname, "datefmt", 1)
- else:
- dfs = None
- f = logging.Formatter(fs, dfs)
- formatters[form] = f
- #next, do the handlers...
- #critical section...
- logging._acquireLock()
- try:
- try:
- #first, lose the existing handlers...
- logging._handlers.clear()
- #now set up the new ones...
- hlist = cp.get("handlers", "keys")
- if len(hlist):
- hlist = string.split(hlist, ",")
- handlers = {}
- fixups = [] #for inter-handler references
- for hand in hlist:
- sectname = "handler_%s" % hand
- klass = cp.get(sectname, "class")
- opts = cp.options(sectname)
- if "formatter" in opts:
- fmt = cp.get(sectname, "formatter")
- else:
- fmt = ""
- klass = eval(klass, vars(logging))
- args = cp.get(sectname, "args")
- args = eval(args, vars(logging))
- h = apply(klass, args)
- if "level" in opts:
- level = cp.get(sectname, "level")
- h.setLevel(logging._levelNames[level])
- if len(fmt):
- h.setFormatter(formatters[fmt])
- #temporary hack for FileHandler and MemoryHandler.
- if klass == logging.handlers.MemoryHandler:
- if "target" in opts:
- target = cp.get(sectname,"target")
- else:
- target = ""
- if len(target): #the target handler may not be loaded yet, so keep for later...
- fixups.append((h, target))
- handlers[hand] = h
- #now all handlers are loaded, fixup inter-handler references...
- for fixup in fixups:
- h = fixup[0]
- t = fixup[1]
- h.setTarget(handlers[t])
- #at last, the loggers...first the root...
- llist = cp.get("loggers", "keys")
- llist = string.split(llist, ",")
- llist.remove("root")
- sectname = "logger_root"
- root = logging.root
- log = root
- opts = cp.options(sectname)
- if "level" in opts:
- level = cp.get(sectname, "level")
- log.setLevel(logging._levelNames[level])
- for h in root.handlers[:]:
- root.removeHandler(h)
- hlist = cp.get(sectname, "handlers")
- if len(hlist):
- hlist = string.split(hlist, ",")
- for hand in hlist:
- log.addHandler(handlers[hand])
- #and now the others...
- #we don't want to lose the existing loggers,
- #since other threads may have pointers to them.
- #existing is set to contain all existing loggers,
- #and as we go through the new configuration we
- #remove any which are configured. At the end,
- #what's left in existing is the set of loggers
- #which were in the previous configuration but
- #which are not in the new configuration.
- existing = root.manager.loggerDict.keys()
- #now set up the new ones...
- for log in llist:
- sectname = "logger_%s" % log
- qn = cp.get(sectname, "qualname")
- opts = cp.options(sectname)
- if "propagate" in opts:
- propagate = cp.getint(sectname, "propagate")
- else:
- propagate = 1
- logger = logging.getLogger(qn)
- if qn in existing:
- existing.remove(qn)
- if "level" in opts:
- level = cp.get(sectname, "level")
- logger.setLevel(logging._levelNames[level])
- for h in logger.handlers[:]:
- logger.removeHandler(h)
- logger.propagate = propagate
- logger.disabled = 0
- hlist = cp.get(sectname, "handlers")
- if len(hlist):
- hlist = string.split(hlist, ",")
- for hand in hlist:
- logger.addHandler(handlers[hand])
- #Disable any old loggers. There's no point deleting
- #them as other threads may continue to hold references
- #and by disabling them, you stop them doing any logging.
- for log in existing:
- root.manager.loggerDict[log].disabled = 1
- except:
- import traceback
- ei = sys.exc_info()
- traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
- del ei
- finally:
- logging._releaseLock()
-
-def listen(port=DEFAULT_LOGGING_CONFIG_PORT):
- """
- Start up a socket server on the specified port, and listen for new
- configurations.
-
- These will be sent as a file suitable for processing by fileConfig().
- Returns a Thread object on which you can call start() to start the server,
- and which you can join() when appropriate. To stop the server, call
- stopListening().
- """
- if not thread:
- raise NotImplementedError, "listen() needs threading to work"
-
- class ConfigStreamHandler(StreamRequestHandler):
- """
- Handler for a logging configuration request.
-
- It expects a completely new logging configuration and uses fileConfig
- to install it.
- """
- def handle(self):
- """
- Handle a request.
-
- Each request is expected to be a 4-byte length,
- followed by the config file. Uses fileConfig() to do the
- grunt work.
- """
- import tempfile
- try:
- conn = self.connection
- chunk = conn.recv(4)
- if len(chunk) == 4:
- slen = struct.unpack(">L", chunk)[0]
- chunk = self.connection.recv(slen)
- while len(chunk) < slen:
- chunk = chunk + conn.recv(slen - len(chunk))
- #Apply new configuration. We'd like to be able to
- #create a StringIO and pass that in, but unfortunately
- #1.5.2 ConfigParser does not support reading file
- #objects, only actual files. So we create a temporary
- #file and remove it later.
- file = tempfile.mktemp(".ini")
- f = open(file, "w")
- f.write(chunk)
- f.close()
- fileConfig(file)
- os.remove(file)
- except socket.error, e:
- if type(e.args) != types.TupleType:
- raise
- else:
- errcode = e.args[0]
- if errcode != RESET_ERROR:
- raise
-
- class ConfigSocketReceiver(ThreadingTCPServer):
- """
- A simple TCP socket-based logging config receiver.
- """
-
- allow_reuse_address = 1
-
- def __init__(self, host='localhost', port=DEFAULT_LOGGING_CONFIG_PORT,
- handler=None):
- ThreadingTCPServer.__init__(self, (host, port), handler)
- logging._acquireLock()
- self.abort = 0
- logging._releaseLock()
- self.timeout = 1
-
- def serve_until_stopped(self):
- import select
- abort = 0
- while not abort:
- rd, wr, ex = select.select([self.socket.fileno()],
- [], [],
- self.timeout)
- if rd:
- self.handle_request()
- logging._acquireLock()
- abort = self.abort
- logging._releaseLock()
-
- def serve(rcvr, hdlr, port):
- server = rcvr(port=port, handler=hdlr)
- global _listener
- logging._acquireLock()
- _listener = server
- logging._releaseLock()
- server.serve_until_stopped()
-
- return threading.Thread(target=serve,
- args=(ConfigSocketReceiver,
- ConfigStreamHandler, port))
-
-def stopListening():
- """
- Stop the listening server which was created with a call to listen().
- """
- global _listener
- if _listener:
- logging._acquireLock()
- _listener.abort = 1
- _listener = None
- logging._releaseLock()
diff --git a/tools/python/logging/logging-0.4.9.2/logging/handlers.py b/tools/python/logging/logging-0.4.9.2/logging/handlers.py
deleted file mode 100644
index 99a543e..0000000
--- a/tools/python/logging/logging-0.4.9.2/logging/handlers.py
+++ /dev/null
@@ -1,787 +0,0 @@
-# Copyright 2001-2004 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-"""
-Additional handlers for the logging package for Python. The core package is
-based on PEP 282 and comments thereto in comp.lang.python, and influenced by
-Apache's log4j system.
-
-Should work under Python versions >= 1.5.2, except that source line
-information is not available unless 'sys._getframe()' is.
-
-Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved.
-
-To use, simply 'import logging' and log away!
-"""
-
-import sys, logging, socket, types, os, string, cPickle, struct, time
-
-from SocketServer import ThreadingTCPServer, StreamRequestHandler
-
-#
-# Some constants...
-#
-
-DEFAULT_TCP_LOGGING_PORT = 9020
-DEFAULT_UDP_LOGGING_PORT = 9021
-DEFAULT_HTTP_LOGGING_PORT = 9022
-DEFAULT_SOAP_LOGGING_PORT = 9023
-SYSLOG_UDP_PORT = 514
-
-
-class RotatingFileHandler(logging.FileHandler):
- def __init__(self, filename, mode="a", maxBytes=0, backupCount=0):
- """
- Open the specified file and use it as the stream for logging.
-
- By default, the file grows indefinitely. You can specify particular
- values of maxBytes and backupCount to allow the file to rollover at
- a predetermined size.
-
- Rollover occurs whenever the current log file is nearly maxBytes in
- length. If backupCount is >= 1, the system will successively create
- new files with the same pathname as the base file, but with extensions
- ".1", ".2" etc. appended to it. For example, with a backupCount of 5
- and a base file name of "app.log", you would get "app.log",
- "app.log.1", "app.log.2", ... through to "app.log.5". The file being
- written to is always "app.log" - when it gets filled up, it is closed
- and renamed to "app.log.1", and if files "app.log.1", "app.log.2" etc.
- exist, then they are renamed to "app.log.2", "app.log.3" etc.
- respectively.
-
- If maxBytes is zero, rollover never occurs.
- """
- logging.FileHandler.__init__(self, filename, mode)
- self.maxBytes = maxBytes
- self.backupCount = backupCount
- if maxBytes > 0:
- self.mode = "a"
-
- def doRollover(self):
- """
- Do a rollover, as described in __init__().
- """
-
- self.stream.close()
- if self.backupCount > 0:
- for i in range(self.backupCount - 1, 0, -1):
- sfn = "%s.%d" % (self.baseFilename, i)
- dfn = "%s.%d" % (self.baseFilename, i + 1)
- if os.path.exists(sfn):
- #print "%s -> %s" % (sfn, dfn)
- if os.path.exists(dfn):
- os.remove(dfn)
- os.rename(sfn, dfn)
- dfn = self.baseFilename + ".1"
- if os.path.exists(dfn):
- os.remove(dfn)
- os.rename(self.baseFilename, dfn)
- #print "%s -> %s" % (self.baseFilename, dfn)
- self.stream = open(self.baseFilename, "w")
-
- def emit(self, record):
- """
- Emit a record.
-
- Output the record to the file, catering for rollover as described
- in doRollover().
- """
- if self.maxBytes > 0: # are we rolling over?
- msg = "%s\n" % self.format(record)
- self.stream.seek(0, 2) #due to non-posix-compliant Windows feature
- if self.stream.tell() + len(msg) >= self.maxBytes:
- self.doRollover()
- logging.FileHandler.emit(self, record)
-
-
-class SocketHandler(logging.Handler):
- """
- A handler class which writes logging records, in pickle format, to
- a streaming socket. The socket is kept open across logging calls.
- If the peer resets it, an attempt is made to reconnect on the next call.
- The pickle which is sent is that of the LogRecord's attribute dictionary
- (__dict__), so that the receiver does not need to have the logging module
- installed in order to process the logging event.
-
- To unpickle the record at the receiving end into a LogRecord, use the
- makeLogRecord function.
- """
-
- def __init__(self, host, port):
- """
- Initializes the handler with a specific host address and port.
-
- The attribute 'closeOnError' is set to 1 - which means that if
- a socket error occurs, the socket is silently closed and then
- reopened on the next logging call.
- """
- logging.Handler.__init__(self)
- self.host = host
- self.port = port
- self.sock = None
- self.closeOnError = 0
- self.retryTime = None
- #
- # Exponential backoff parameters.
- #
- self.retryStart = 1.0
- self.retryMax = 30.0
- self.retryFactor = 2.0
-
- def makeSocket(self):
- """
- A factory method which allows subclasses to define the precise
- type of socket they want.
- """
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.connect((self.host, self.port))
- return s
-
- def createSocket(self):
- """
- Try to create a socket, using an exponential backoff with
- a max retry time. Thanks to Robert Olson for the original patch
- (SF #815911) which has been slightly refactored.
- """
- now = time.time()
- # Either retryTime is None, in which case this
- # is the first time back after a disconnect, or
- # we've waited long enough.
- if self.retryTime is None:
- attempt = 1
- else:
- attempt = (now >= self.retryTime)
- if attempt:
- try:
- self.sock = self.makeSocket()
- self.retryTime = None # next time, no delay before trying
- except:
- #Creation failed, so set the retry time and return.
- if self.retryTime is None:
- self.retryPeriod = self.retryStart
- else:
- self.retryPeriod = self.retryPeriod * self.retryFactor
- if self.retryPeriod > self.retryMax:
- self.retryPeriod = self.retryMax
- self.retryTime = now + self.retryPeriod
-
- def send(self, s):
- """
- Send a pickled string to the socket.
-
- This function allows for partial sends which can happen when the
- network is busy.
- """
- if self.sock is None:
- self.createSocket()
- #self.sock can be None either because we haven't reached the retry
- #time yet, or because we have reached the retry time and retried,
- #but are still unable to connect.
- if self.sock:
- try:
- if hasattr(self.sock, "sendall"):
- self.sock.sendall(s)
- else:
- sentsofar = 0
- left = len(s)
- while left > 0:
- sent = self.sock.send(s[sentsofar:])
- sentsofar = sentsofar + sent
- left = left - sent
- except socket.error:
- self.sock.close()
- self.sock = None # so we can call createSocket next time
-
- def makePickle(self, record):
- """
- Pickles the record in binary format with a length prefix, and
- returns it ready for transmission across the socket.
- """
- ei = record.exc_info
- if ei:
- dummy = self.format(record) # just to get traceback text into record.exc_text
- record.exc_info = None # to avoid Unpickleable error
- s = cPickle.dumps(record.__dict__, 1)
- if ei:
- record.exc_info = ei # for next handler
- slen = struct.pack(">L", len(s))
- return slen + s
-
- def handleError(self, record):
- """
- Handle an error during logging.
-
- An error has occurred during logging. Most likely cause -
- connection lost. Close the socket so that we can retry on the
- next event.
- """
- if self.closeOnError and self.sock:
- self.sock.close()
- self.sock = None #try to reconnect next time
- else:
- logging.Handler.handleError(self, record)
-
- def emit(self, record):
- """
- Emit a record.
-
- Pickles the record and writes it to the socket in binary format.
- If there is an error with the socket, silently drop the packet.
- If there was a problem with the socket, re-establishes the
- socket.
- """
- try:
- s = self.makePickle(record)
- self.send(s)
- except:
- self.handleError(record)
-
- def close(self):
- """
- Closes the socket.
- """
- if self.sock:
- self.sock.close()
- self.sock = None
- logging.Handler.close(self)
-
-class DatagramHandler(SocketHandler):
- """
- A handler class which writes logging records, in pickle format, to
- a datagram socket. The pickle which is sent is that of the LogRecord's
- attribute dictionary (__dict__), so that the receiver does not need to
- have the logging module installed in order to process the logging event.
-
- To unpickle the record at the receiving end into a LogRecord, use the
- makeLogRecord function.
-
- """
- def __init__(self, host, port):
- """
- Initializes the handler with a specific host address and port.
- """
- SocketHandler.__init__(self, host, port)
- self.closeOnError = 0
-
- def makeSocket(self):
- """
- The factory method of SocketHandler is here overridden to create
- a UDP socket (SOCK_DGRAM).
- """
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- return s
-
- def send(self, s):
- """
- Send a pickled string to a socket.
-
- This function no longer allows for partial sends which can happen
- when the network is busy - UDP does not guarantee delivery and
- can deliver packets out of sequence.
- """
- self.sock.sendto(s, (self.host, self.port))
-
-class SysLogHandler(logging.Handler):
- """
- A handler class which sends formatted logging records to a syslog
- server. Based on Sam Rushing's syslog module:
- http://www.nightmare.com/squirl/python-ext/misc/syslog.py
- Contributed by Nicolas Untz (after which minor refactoring changes
- have been made).
- """
-
- # from <linux/sys/syslog.h>:
- # ======================================================================
- # priorities/facilities are encoded into a single 32-bit quantity, where
- # the bottom 3 bits are the priority (0-7) and the top 28 bits are the
- # facility (0-big number). Both the priorities and the facilities map
- # roughly one-to-one to strings in the syslogd(8) source code. This
- # mapping is included in this file.
- #
- # priorities (these are ordered)
-
- LOG_EMERG = 0 # system is unusable
- LOG_ALERT = 1 # action must be taken immediately
- LOG_CRIT = 2 # critical conditions
- LOG_ERR = 3 # error conditions
- LOG_WARNING = 4 # warning conditions
- LOG_NOTICE = 5 # normal but significant condition
- LOG_INFO = 6 # informational
- LOG_DEBUG = 7 # debug-level messages
-
- # facility codes
- LOG_KERN = 0 # kernel messages
- LOG_USER = 1 # random user-level messages
- LOG_MAIL = 2 # mail system
- LOG_DAEMON = 3 # system daemons
- LOG_AUTH = 4 # security/authorization messages
- LOG_SYSLOG = 5 # messages generated internally by syslogd
- LOG_LPR = 6 # line printer subsystem
- LOG_NEWS = 7 # network news subsystem
- LOG_UUCP = 8 # UUCP subsystem
- LOG_CRON = 9 # clock daemon
- LOG_AUTHPRIV = 10 # security/authorization messages (private)
-
- # other codes through 15 reserved for system use
- LOG_LOCAL0 = 16 # reserved for local use
- LOG_LOCAL1 = 17 # reserved for local use
- LOG_LOCAL2 = 18 # reserved for local use
- LOG_LOCAL3 = 19 # reserved for local use
- LOG_LOCAL4 = 20 # reserved for local use
- LOG_LOCAL5 = 21 # reserved for local use
- LOG_LOCAL6 = 22 # reserved for local use
- LOG_LOCAL7 = 23 # reserved for local use
-
- priority_names = {
- "alert": LOG_ALERT,
- "crit": LOG_CRIT,
- "critical": LOG_CRIT,
- "debug": LOG_DEBUG,
- "emerg": LOG_EMERG,
- "err": LOG_ERR,
- "error": LOG_ERR, # DEPRECATED
- "info": LOG_INFO,
- "notice": LOG_NOTICE,
- "panic": LOG_EMERG, # DEPRECATED
- "warn": LOG_WARNING, # DEPRECATED
- "warning": LOG_WARNING,
- }
-
- facility_names = {
- "auth": LOG_AUTH,
- "authpriv": LOG_AUTHPRIV,
- "cron": LOG_CRON,
- "daemon": LOG_DAEMON,
- "kern": LOG_KERN,
- "lpr": LOG_LPR,
- "mail": LOG_MAIL,
- "news": LOG_NEWS,
- "security": LOG_AUTH, # DEPRECATED
- "syslog": LOG_SYSLOG,
- "user": LOG_USER,
- "uucp": LOG_UUCP,
- "local0": LOG_LOCAL0,
- "local1": LOG_LOCAL1,
- "local2": LOG_LOCAL2,
- "local3": LOG_LOCAL3,
- "local4": LOG_LOCAL4,
- "local5": LOG_LOCAL5,
- "local6": LOG_LOCAL6,
- "local7": LOG_LOCAL7,
- }
-
- def __init__(self, address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER):
- """
- Initialize a handler.
-
- If address is specified as a string, UNIX socket is used.
- If facility is not specified, LOG_USER is used.
- """
- logging.Handler.__init__(self)
-
- self.address = address
- self.facility = facility
- if type(address) == types.StringType:
- self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
- # syslog may require either DGRAM or STREAM sockets
- try:
- self.socket.connect(address)
- except socket.error:
- self.socket.close()
- self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- self.socket.connect(address)
- self.unixsocket = 1
- else:
- self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- self.unixsocket = 0
-
- self.formatter = None
-
- # curious: when talking to the unix-domain '/dev/log' socket, a
- # zero-terminator seems to be required. this string is placed
- # into a class variable so that it can be overridden if
- # necessary.
- log_format_string = '<%d>%s\000'
-
- def encodePriority (self, facility, priority):
- """
- Encode the facility and priority. You can pass in strings or
- integers - if strings are passed, the facility_names and
- priority_names mapping dictionaries are used to convert them to
- integers.
- """
- if type(facility) == types.StringType:
- facility = self.facility_names[facility]
- if type(priority) == types.StringType:
- priority = self.priority_names[priority]
- return (facility << 3) | priority
-
- def close (self):
- """
- Closes the socket.
- """
- if self.unixsocket:
- self.socket.close()
- logging.Handler.close(self)
-
- def emit(self, record):
- """
- Emit a record.
-
- The record is formatted, and then sent to the syslog server. If
- exception information is present, it is NOT sent to the server.
- """
- msg = self.format(record)
- """
- We need to convert record level to lowercase, maybe this will
- change in the future.
- """
- msg = self.log_format_string % (
- self.encodePriority(self.facility,
- string.lower(record.levelname)),
- msg)
- try:
- if self.unixsocket:
- self.socket.send(msg)
- else:
- self.socket.sendto(msg, self.address)
- except:
- self.handleError(record)
-
-class SMTPHandler(logging.Handler):
- """
- A handler class which sends an SMTP email for each logging event.
- """
- def __init__(self, mailhost, fromaddr, toaddrs, subject):
- """
- Initialize the handler.
-
- Initialize the instance with the from and to addresses and subject
- line of the email. To specify a non-standard SMTP port, use the
- (host, port) tuple format for the mailhost argument.
- """
- logging.Handler.__init__(self)
- if type(mailhost) == types.TupleType:
- host, port = mailhost
- self.mailhost = host
- self.mailport = port
- else:
- self.mailhost = mailhost
- self.mailport = None
- self.fromaddr = fromaddr
- if type(toaddrs) == types.StringType:
- toaddrs = [toaddrs]
- self.toaddrs = toaddrs
- self.subject = subject
-
- def getSubject(self, record):
- """
- Determine the subject for the email.
-
- If you want to specify a subject line which is record-dependent,
- override this method.
- """
- return self.subject
-
- weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
-
- monthname = [None,
- 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
- 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
-
- def date_time(self):
- """Return the current date and time formatted for a MIME header."""
- year, month, day, hh, mm, ss, wd, y, z = time.gmtime(time.time())
- s = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (
- self.weekdayname[wd],
- day, self.monthname[month], year,
- hh, mm, ss)
- return s
-
- def emit(self, record):
- """
- Emit a record.
-
- Format the record and send it to the specified addressees.
- """
- try:
- import smtplib
- port = self.mailport
- if not port:
- port = smtplib.SMTP_PORT
- smtp = smtplib.SMTP(self.mailhost, port)
- msg = self.format(record)
- msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\nDate: %s\r\n\r\n%s" % (
- self.fromaddr,
- string.join(self.toaddrs, ","),
- self.getSubject(record),
- self.date_time(), msg)
- smtp.sendmail(self.fromaddr, self.toaddrs, msg)
- smtp.quit()
- except:
- self.handleError(record)
-
-class NTEventLogHandler(logging.Handler):
- """
- A handler class which sends events to the NT Event Log. Adds a
- registry entry for the specified application name. If no dllname is
- provided, win32service.pyd (which contains some basic message
- placeholders) is used. Note that use of these placeholders will make
- your event logs big, as the entire message source is held in the log.
- If you want slimmer logs, you have to pass in the name of your own DLL
- which contains the message definitions you want to use in the event log.
- """
- def __init__(self, appname, dllname=None, logtype="Application"):
- logging.Handler.__init__(self)
- try:
- import win32evtlogutil, win32evtlog
- self.appname = appname
- self._welu = win32evtlogutil
- if not dllname:
- dllname = os.path.split(self._welu.__file__)
- dllname = os.path.split(dllname[0])
- dllname = os.path.join(dllname[0], r'win32service.pyd')
- self.dllname = dllname
- self.logtype = logtype
- self._welu.AddSourceToRegistry(appname, dllname, logtype)
- self.deftype = win32evtlog.EVENTLOG_ERROR_TYPE
- self.typemap = {
- logging.DEBUG : win32evtlog.EVENTLOG_INFORMATION_TYPE,
- logging.INFO : win32evtlog.EVENTLOG_INFORMATION_TYPE,
- logging.WARNING : win32evtlog.EVENTLOG_WARNING_TYPE,
- logging.ERROR : win32evtlog.EVENTLOG_ERROR_TYPE,
- logging.CRITICAL: win32evtlog.EVENTLOG_ERROR_TYPE,
- }
- except ImportError:
- print "The Python Win32 extensions for NT (service, event "\
- "logging) appear not to be available."
- self._welu = None
-
- def getMessageID(self, record):
- """
- Return the message ID for the event record. If you are using your
- own messages, you could do this by having the msg passed to the
- logger being an ID rather than a formatting string. Then, in here,
- you could use a dictionary lookup to get the message ID. This
- version returns 1, which is the base message ID in win32service.pyd.
- """
- return 1
-
- def getEventCategory(self, record):
- """
- Return the event category for the record.
-
- Override this if you want to specify your own categories. This version
- returns 0.
- """
- return 0
-
- def getEventType(self, record):
- """
- Return the event type for the record.
-
- Override this if you want to specify your own types. This version does
- a mapping using the handler's typemap attribute, which is set up in
- __init__() to a dictionary which contains mappings for DEBUG, INFO,
- WARNING, ERROR and CRITICAL. If you are using your own levels you will
- either need to override this method or place a suitable dictionary in
- the handler's typemap attribute.
- """
- return self.typemap.get(record.levelno, self.deftype)
-
- def emit(self, record):
- """
- Emit a record.
-
- Determine the message ID, event category and event type. Then
- log the message in the NT event log.
- """
- if self._welu:
- try:
- id = self.getMessageID(record)
- cat = self.getEventCategory(record)
- type = self.getEventType(record)
- msg = self.format(record)
- self._welu.ReportEvent(self.appname, id, cat, type, [msg])
- except:
- self.handleError(record)
-
- def close(self):
- """
- Clean up this handler.
-
- You can remove the application name from the registry as a
- source of event log entries. However, if you do this, you will
- not be able to see the events as you intended in the Event Log
- Viewer - it needs to be able to access the registry to get the
- DLL name.
- """
- #self._welu.RemoveSourceFromRegistry(self.appname, self.logtype)
- logging.Handler.close(self)
-
-class HTTPHandler(logging.Handler):
- """
- A class which sends records to a Web server, using either GET or
- POST semantics.
- """
- def __init__(self, host, url, method="GET"):
- """
- Initialize the instance with the host, the request URL, and the method
- ("GET" or "POST")
- """
- logging.Handler.__init__(self)
- method = string.upper(method)
- if method not in ["GET", "POST"]:
- raise ValueError, "method must be GET or POST"
- self.host = host
- self.url = url
- self.method = method
-
- def mapLogRecord(self, record):
- """
- Default implementation of mapping the log record into a dict
- that is sent as the CGI data. Overwrite in your class.
- Contributed by Franz Glasner.
- """
- return record.__dict__
-
- def emit(self, record):
- """
- Emit a record.
-
- Send the record to the Web server as an URL-encoded dictionary
- """
- try:
- import httplib, urllib
- h = httplib.HTTP(self.host)
- url = self.url
- data = urllib.urlencode(self.mapLogRecord(record))
- if self.method == "GET":
- if (string.find(url, '?') >= 0):
- sep = '&'
- else:
- sep = '?'
- url = url + "%c%s" % (sep, data)
- h.putrequest(self.method, url)
- if self.method == "POST":
- h.putheader("Content-length", str(len(data)))
- h.endheaders()
- if self.method == "POST":
- h.send(data)
- h.getreply() #can't do anything with the result
- except:
- self.handleError(record)
-
-class BufferingHandler(logging.Handler):
- """
- A handler class which buffers logging records in memory. Whenever each
- record is added to the buffer, a check is made to see if the buffer should
- be flushed. If it should, then flush() is expected to do what's needed.
- """
- def __init__(self, capacity):
- """
- Initialize the handler with the buffer size.
- """
- logging.Handler.__init__(self)
- self.capacity = capacity
- self.buffer = []
-
- def shouldFlush(self, record):
- """
- Should the handler flush its buffer?
-
- Returns true if the buffer is up to capacity. This method can be
- overridden to implement custom flushing strategies.
- """
- return (len(self.buffer) >= self.capacity)
-
- def emit(self, record):
- """
- Emit a record.
-
- Append the record. If shouldFlush() tells us to, call flush() to process
- the buffer.
- """
- self.buffer.append(record)
- if self.shouldFlush(record):
- self.flush()
-
- def flush(self):
- """
- Override to implement custom flushing behaviour.
-
- This version just zaps the buffer to empty.
- """
- self.buffer = []
-
- def close(self):
- """
- Close the handler.
-
- This version just flushes and chains to the parent class' close().
- """
- self.flush()
- logging.Handler.close(self)
-
-class MemoryHandler(BufferingHandler):
- """
- A handler class which buffers logging records in memory, periodically
- flushing them to a target handler. Flushing occurs whenever the buffer
- is full, or when an event of a certain severity or greater is seen.
- """
- def __init__(self, capacity, flushLevel=logging.ERROR, target=None):
- """
- Initialize the handler with the buffer size, the level at which
- flushing should occur and an optional target.
-
- Note that without a target being set either here or via setTarget(),
- a MemoryHandler is no use to anyone!
- """
- BufferingHandler.__init__(self, capacity)
- self.flushLevel = flushLevel
- self.target = target
-
- def shouldFlush(self, record):
- """
- Check for buffer full or a record at the flushLevel or higher.
- """
- return (len(self.buffer) >= self.capacity) or \
- (record.levelno >= self.flushLevel)
-
- def setTarget(self, target):
- """
- Set the target handler for this handler.
- """
- self.target = target
-
- def flush(self):
- """
- For a MemoryHandler, flushing means just sending the buffered
- records to the target, if there is one. Override if you want
- different behaviour.
- """
- if self.target:
- for record in self.buffer:
- self.target.handle(record)
- self.buffer = []
-
- def close(self):
- """
- Flush, set the target to None and lose the buffer.
- """
- self.flush()
- self.target = None
- BufferingHandler.close(self)
diff --git a/tools/python/logging/logging-0.4.9.2/python_logging.html b/tools/python/logging/logging-0.4.9.2/python_logging.html
deleted file mode 100644
index b759ef9..0000000
--- a/tools/python/logging/logging-0.4.9.2/python_logging.html
+++ /dev/null
@@ -1,1183 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
-"http://www.w3.org/TR/REC-html40/loose.dtd">
-<html>
-
-<head>
-<meta name="AUTHOR" content="Vinay Sajip">
-<meta name="COPYRIGHT" content="� 2002 Red Dove Consultants Limited">
-<meta name="KEYWORDS" content="Red Dove Consultants, Python, logging, PEP 282">
-<meta name="DESCRIPTION" content="A logging system for Python">
-<meta name="summary" content="A logging system for Python">
-<meta name="publisher" content="Red Dove Consultants Limited">
-<meta name="identifier" content="http://www.red-dove.com">
-<title>A Logging System for Python</title>
-<link title="Default Style" rel="stylesheet" href="default.css" type="text/css">
-</head>
-
-<body style="margin: 5px" marginheight="0">
-<table border="0" width="100%" cellspacing="0" cellpadding="0">
- <tr>
- <td class="bigtd">A Logging System for Python</td>
- <td rowspan="2" align="right" style="text-align: right; vertical-align: top"><a href="/index.html">Home</a><br>
- <a href="#download">Download</a><br>
- <a href="#license">Copyright & License</a><br>
- <a href="#changes">Recent Changes</a><br>
- <!-- a href="logging_manual.html">Online Manual</a --></td>
- </tr>
- <tr>
- <td>"Oh, I'm a lumberjack and I'm okay..." <small>(Monty Python, <a href="http://www.montypython.net/scripts/lumberj.php">The Lumberjack Song</a>)</small></td>
- </tr>
-</table>
-
-<h4>Table of Contents</h4>
-<a href="#abstract">Abstract</a><br>
-<a href="#motivation">Motivation</a><br>
-<a href="#influences">Influences</a><br>
-<a href="#simplest">A Simple Example</a><br>
-<a href="#ctrlflow">Control Flow</a><br>
-<a href="#levels">Levels</a><br>
-<a href="#loggers">Loggers</a><br>
-<a href="#handlers">Handlers</a><br>
-<a href="#formatters">Formatters</a><br>
-<a href="#filters">Filters</a><br>
-<a href="#config">Configuration</a><br>
-<a href="#guiconf">The GUI Configurator</a><br>
-<a href="#scenarios">Case Scenarios</a><br>
-<a href="#threadsafe">Thread Safety</a><br>
-<a href="#onthefly">On-The-Fly Reconfiguration</a><br>
-<a href="#mlcf">Module-Level Convenience Functions</a><br>
-<a href="#perf">Performance</a><br>
-<a href="#impstatus">Implementation Status</a><br>
-<a href="#acks">Acknowledgements</a><br>
-<a href="#todo">Still To Do</a><br>
-<a href="#download">Download and Installation</a><br>
-<a href="#changes">Change History</a><br>
-<a href="#license">Copyright and License</a><br>
-
-<a name="abstract"></a><h4>Abstract</h4>
-
-<p>There is a need for a standard logging system in Python, as comprehensively documented
-in <a href="http://www.python.org/peps/pep-0282.html">PEP 282</a> and
-enthusiastically endorsed by the BDFL in the <a
-href="http://www.python.org/doc/essays/pepparade.html">Parade of the PEPs</a>. By a happy
-coincidence, the package described here was already in development and fairly close in
-intent and design to the description in the aforementioned PEP, borrowing as it did
-heavily from JSR-47 (now JDK 1.4's java.util.logging package) and <a
-href="http://jakarta.apache.org/log4j/">log4j</a>. This page describes it in more detail.
-As I have tweaked the package to meet comments on PEP 282, I have structured this page in
-the same way as the original PEP. </p>
-
-<a name="motivation"></a><h4>Motivation</h4>
-
-<p>The Python community has been incredibly helpful to me, a relative newcomer to the
-language. Python and its community has certainly saved me much time and effort, and it
-seems appropriate to give something back to the community by offering up this package for
-people to try. Any <a href="mailto:vinay_sajip at red-dove.com">feedback</a> will be gratefully accepted. </p>
-
-<a name="influences"></a><h4>Influences</h4>
-
-<p>This package owes its greatest debt to Apache <a
-href="http://jakarta.apache.org/log4j/">log4j</a>. Due notice was also taken of log4j's
-comprehensive <a href="http://jakarta.apache.org/log4j/docs/critique.html">critique</a> of
-JSR47. This package bears a close resemblance to log4j, but is not a close translation
-(as, for example, <a href="http://log4p.sourceforge.net/">log4p</a> appears to be). I have
-attempted to be more minimalist (and hopefully more Pythonic) in my approach. You be the
-judge! </p>
-
-<a name="simplest"></a><h4>A Simple Example</h4>
-
-<p>Using the package doesn't get much simpler. It is packaged as a standard Python package called (unsurprisingly) <code>logging</code>. You just need to <code>import logging</code> and you're ready to go. Minimal example: </p>
-
-<pre class="program">
-# --- app.py --------------------------------------------------------------------
-import logging
-
-logging.warn("Hello")
-logging.error("Still here...")
-logging.warn("Goodbye")
-</pre>
-
-<p>When you run <code>app.py</code>, the results are: </p>
-
-<pre class="output">
-WARN:root:Hello
-ERROR:root:Still here...
-WARN:root:Goodbye
-</pre>
-
-<p>Don't worry about the format of the output - it's all configurable. Here's a slightly
-more involved example; if you've just looked at PEP 282 you will probably get a feeling of
-dej� vu. (This is intentional.)</p>
-
-<a name="nextsimplest"></a><pre class="program">
-# --- mymodule.py --------------------------------------------------------------------
-import logging
-log = logging.getLogger("MyModule")
-
-def doIt():
- log.debug("doin' stuff")
- <span class="comment">#do stuff...but suppose an error occurs?</span>
- raise TypeError, "bogus type error for testing"
-
-# --- myapp.py -----------------------------------------------------------------------
-import logging, mymodule
-
-logging.basicConfig()
-
-log = logging.getLogger("MyApp")
-log.setLevel(logging.DEBUG) <span class="comment">#set verbosity to show all messages of severity >= DEBUG</span>
-log.info("Starting my app")
-try:
- mymodule.doIt()
-except Exception, e:
- log.exception("There was a problem.")
-log.info("Ending my app")
-</pre>
-
-<p>When you run <code>myapp.py</code>, the results are: </p>
-
-<pre class="output">
-INFO:MyApp:Starting my app
-ERROR:MyApp:There was a problem.
-Traceback (most recent call last):
- File "myapp.py", line 9, in ?
- mymodule.doIt()
- File "mymodule.py", line 7, in doIt
- raise TypeError, "Bogus type error for testing"
-TypeError: Bogus type error for testing
-INFO:MyApp:Ending my app
-</pre>
-
-<p>But don't worry - the above output is not hardcoded into the package. It's just an
-example of what you can do with very little work. As you can see, exceptions are handled
-as one would expect. </p>
-
-<a name="ctrlflow"></a><h4>Control Flow</h4>
-
-<p>The package pretty much matches the PEP regarding control flow. The user of the package
-makes logging calls on instances of <code>Logger</code>, which are organized into a
-hierarchy based on a "dotted name" namespace. This hierarchy is embodied in an
-encapsulated singleton <code>Manager</code> instance (which can be ignored by users of the
-package, for most purposes). Based on the type of logging call and the logging
-configuration (see below), the call may be passed through a set of <code>Filter</code>
-instances to decide whether it should be dropped. If not, then the logger consults a set
-of <code>Handler</code> instances which are associated with it, and asks each handler
-instance to "handle" the logging event. By default, the system moves up the
-namespace hierarchy and invokes handlers on all loggers at or above the level of the
-logger on which the logging call was made. (You can override this by setting a logger's
-"propagate" attribute to 0 - no traversal up the hierarchy is made from such a
-logger. But I'm getting ahead of myself...) </p>
-
-<p>Handlers are passed <code>LogRecord</code> instances which (should) contain all the
-information we're interested in logging. Handlers, too, can invoke filters to determine
-whether a record should be dropped. If not, then the handler takes a handler-specific
-action to actually log the record to a file, the console or whatever.</p>
-
-<a name="levels"></a><h4>Levels</h4>
-
-<p>The following levels are implemented by default: </p>
-
-<pre>
-DEBUG
-INFO
-WARN
-ERROR
-CRITICAL
-</pre>
-
-<p>The <code>CRITICAL</code> level replaces the earlier <code>FATAL</code> level. You can use either (for now), but <code>CRITICAL</code> is preferred since <code>FATAL</code> implies that the application is about to terminate. This is not true for many systems which use logging - for example, a Web server application which encounters a <code>CRITICAL</code> condition (e.g. running out of resources) will still try to keep going as best it can.</p>
-<p><code>FATAL</code> (and the corresponding <code>fatal()</code> methods) may be removed in future versions of the package. Currently, <code>CRITICAL</code> is synonymous with <code>FATAL</code> and <code>critical()</code> methods are synonymous with <code>fatal()</code>.</p>
-<p>Exceptions logged via <code>exception()</code> use the <code>ERROR</code> level for logging. If it is desired to log exception information with arbitrary logging levels, this can be done by passing a keyword argument <code>exc_info</code> with a true value to the logging methods (see the pydoc for more details).</p>
-<p>The levels are not deeply hardcoded into the package - the number of levels, their numeric values and their textual representation are all configurable. The above levels represent the experience of the log4j community and so are provided as the default levels for users who do not have very specific requirements in this area.</p>
-<p>The example script <code>log_test4.py</code> shows the use of bespoke logging levels (as well as filtering by level at logger and handler, as well as use of filter classes).</p>
-
-<a name="loggers"></a><h4>Loggers</h4>
-
-<p>The package implements loggers pretty much as mentioned in the PEP, except that the manager class is called <code>Manager</code> rather than <code>LogManager</code>.</p>
-<p>Each Logger instance represents "an area" of the application. This somewhat nebulous definition is needed because it's entirely up to each application developer to define an application's "areas".</p><p>For example, an application which reads and processes spreadsheet-type data in different formats might have an overall area "input", concerned with reading input files; and areas "input.csv", "input.xls" and "input.gnu", related to processing comma-separated-value, Excel and Gnumeric i [...]
-
-<a name="handlers"></a><h4>Handlers</h4>
-
-<p>The following handlers are implemented. I guess they could use more testing ;-)
-
-<ul>
- <li>StreamHandler - logging to a stream, defaulting to sys.stderr.</li>
- <li>FileHandler - logging to disk files.</li>
- <li>RotatingFileHandler - logging to disk files with support for rollover, rotating files.</li>
- <li>SocketHandler - logging to a streaming socket.</li>
- <li>DatagramHandler - logging to a UDP socket.</li>
- <li>SMTPHandler - logging to an email address.</li>
- <li>SysLogHandler - logging to Unix syslog. Contributed by Nicolas Untz, based on <a href="http://www.nightmare.com/squirl/python-ext/misc/syslog.py
-">Sam Rushing's syslog module</a>.</li>
- <li>MemoryHandler - buffering records in memory until a specific trigger occurs (or until the buffer gets full).</li>
- <li>NTEventLogHandler - writes events to the NT event log. For this to work, you need to have Mark Hammond's Win32 extensions installed. (Though of course you can still log to NT from other platforms - just use SocketHandler to redirect to an NT machine).</li>
- <li>HTTPHandler - sends events to a Web server using either GET or POST semantics.</li>
-</ul>
-<p>All of these except the first two are defined in a sub-module, handlers.py. (To use these handlers, you'll need to <code>import logging.handlers</code>. In addition to the above list, there are example implementations of <code>XMLHandler</code> (see <code>log_test9.py</code>), <code>BufferingSMTPHandler</code> (see <code>log_test11.py</code>) and <code>DBHandler</code> (see <code>log_test14.py</code>) in the test harnesses, on which you can base more specific classes. There is also a [...]
-<p>SOAPHandler, which sends events to a SOAP server, has moved (as of release 0.4.4) from the core to an example script (log_test13.py). The SOAP message is packaged as a function call to a single <code>log()</code> function on the remote server, which takes each relevant member of the LogRecord as a positional parameter. This is perhaps not ideal - but then this SOAPHandler is just a proof-of-concept example to get you started ;-)</p>
-<p>Note that the handlers are specifically intended <I>not</I> to raise exceptions when errors occur at runtime. This is to avoid error messages from the logging infrastructure polluting logging messages from the application being logged. If, for example, a SocketHandler sees a connection reset by the remote endpoint, it will silently drop all records passed to it (but it will try to connect each time). It may be that due to bugs there are some exceptions incorrectly raised by the loggin [...]
-
-<a name="formatters"></a><h4>Formatters</h4>
-
-<p>A basic Formatter has been implemented, which should cater for most immediate
-requirements. You basically initialize the Formatter with a format string which knows how the attribute dictionary of a LogRecord looks. For example, the output in the example above was produced
-with a format string of <code>"%(asctime)s %(name)-19s %(levelname)-5s -
-%(message)s"</code>. Note that the "message" attribute of the <code>LogRecord</code>
-is derived from <code>"msg % args"</code> where <code>msg</code> and <code>args</code>
-are passed by the the user in a logging call.</p>
-
-<a name="filters"></a><h4>Filters</h4>
-
-<p>Filters are used to refine logging output at either logger or handler level with a finer control than is available by just using logging levels. The basic Filter class takes an optional name argument and passes all logging records from loggers which are at or below the specified name.</p>
-<p>For example, a <code>Filter</code> initialized with "A.B" will allow events logged by loggers "A.B", "A.B.C", "A.B.C.D", "A.B.D" but not "A.BB", "B.A.B". If no name is specified, all events are passed by the filter.</p>
-
-<a name="config"></a><h4>Configuration</h4>
-
-<p>A basic configuration is provided via a module-level function, <code>basicConfig()</code>.
-If you want to use very simple logging, you can just call the <a href="#mlcf">module-level
-convenience functions</a> and they will call <code>basicConfig()</code> for you if
-necessary. It (basically) adds a <code>StreamHandler</code> (which writes to <code>sys.stderr</code>)to the root <code>Logger</code>.</p>
-
-<p>There are numerous examples of configuration in the test/example scripts included in the distribution. For example, <code>log_test8.py</code> has an example of using a file-based logger.</p>
-<p>An alternative using ConfigParser-based configuration files is also available (the older, dict-based function is no more). To use this functionality, you'll need to <code>import logging.config</code>. Here is an example of such a config file - it's a bit long, but a full working example so bear with me. I've annotated it as best I can :-): </p>
-<p>
-In the listing below, some values are used by both the logging configuration API
-and the GUI configurator, while others are used only by the GUI configurator. To
-make it clearer which values you absolutely need to have in the .ini file for it to be useful even if you hand-code it, the values used by the configuration API are shown
-<span class="program"><span class="strong">like this</span></span>. (The other ones are used by the GUI configurator, but ignored by the configuration API.)
-</p>
-<pre class="program">
-# --- logconf.ini -----------------------------------------------------------
-#The "loggers" section contains the key names for all the loggers in this
-#configuration. These are not the actual channel names, but values used to
-#identify where the parameters for each logger are found in this file.
-#The section for an individual logger is named "logger_xxx" where the "key"
-#for a logger is "xxx". So ... "logger_root", "logger_log02", etc. further
-#down the file, indicate how the root logger is set up, logger "log_02" is set
-#up, and so on.
-#Logger key names can be any identifier, except "root" which is reserved for
-#the root logger. (The names "lognn" are generated by the GUI configurator.)
-
-<span class="strong">[loggers]
-keys=root,log02,log03,log04,log05,log06,log07</span>
-
-#The "handlers" section contains the key names for all the handlers in this
-#configuration. Just as for loggers above, the key names are values used to
-#identify where the parameters for each handler are found in this file.
-#The section for an individual handler is named "handler_xxx" where the "key"
-#for a handler is "xxx". So sections "handler_hand01", "handler_hand02", etc.
-#further down the file, indicate how the handlers "hand01", "hand02" etc.
-#are set up.
-#Handler key names can be any identifier. (The names "handnn" are generated
-#by the GUI configurator.)
-
-<span class="strong">[handlers]
-keys=hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09</span>
-
-#The "formatters" section contains the key names for all the formatters in
-#this configuration. Just as for loggers and handlers above, the key names
-#are values used to identify where the parameters for each formatter are found
-#in this file.
-#The section for an individual formatter is named "formatter_xxx" where the
-#"key" for a formatter is "xxx". So sections "formatter_form01",
-#"formatter_form02", etc. further down the file indicate how the formatters
-#"form01", "form02" etc. are set up.
-#Formatter key names can be any identifier. (The names "formnn" are generated
-#by the GUI configurator.)
-
-<span class="strong">[formatters]
-keys=form01,form02,form03,form04,form05,form06,form07,form08,form09</span>
-
-#The section below indicates the information relating to the root logger.
-#
-#The level value needs to be one of DEBUG, INFO, WARN, ERROR, CRITICAL or NOTSET.
-#In the root logger, NOTSET indicates that all messages will be logged.
-#Level values are eval()'d in the context of the logging package's namespace.
-#
-#The propagate value indicates whether or not parents of this loggers will
-#be traversed when looking for handlers. It doesn't really make sense in the
-#root logger - it's just there because a root logger is almost like any other
-#logger.
-#
-#The channel value indicates the lowest portion of the channel name of the
-#logger. For a logger called "a.b.c", this value would be "c".
-#
-#The parent value indicates the key name of the parent logger, except that
-#root is shown as "(root)" rather than "root".
-#
-#The qualname value is the fully qualified channel name of the logger. For a
-#logger called "a.b.c", this value would be "a.b.c".
-#
-#The handlers value is a comma-separated list of the key names of the handlers
-#attached to this logger.
-#
-<span class="strong">[logger_root]
-level=NOTSET
-handlers=hand01</span>
-qualname=(root) <span class="comment"># note - this is used in non-root loggers</span>
-propagate=1 <span class="comment"># note - this is used in non-root loggers</span>
-channel=
-parent=
-
-#
-#The explanation for the values in this section is analogous to the above. The
-#logger is named "log02" and coincidentally has a key name of "log02". It has
-#a level of DEBUG and handler with key name "hand02". (See section
-#"handler_hand02" for handler details.) If the level value were NOTSET, this tells
-#the logging package to consult the parent (as long as propagate is 1) for the
-#effective level of this logger. If propagate is 0, this level is treated as for
-#the root logger - a value of NOTSET means "pass everything", and other values are
-#interpreted at face value.
-#
-<span class="strong">[logger_log02]
-level=DEBUG
-propagate=1
-qualname=log02
-handlers=hand02</span>
-channel=log02
-parent=(root)
-
-#
-#The explanation for the values in this section is analogous to the above. The
-#logger is named "log02.log03" and has a key name of "log03".
-#It has a level of INFO and handler with key name "hand03".
-#
-<span class="strong">[logger_log03]
-level=INFO
-propagate=1
-qualname=log02.log03
-handlers=hand03</span>
-channel=log03
-parent=log02
-
-#
-#The explanations for the values in this section and subsequent logger sections
-#are analogous to the above.
-#
-<span class="strong">[logger_log04]
-level=WARN
-propagate=0
-qualname=log02.log03.log04
-handlers=hand04</span>
-channel=log04
-parent=log03
-
-<span class="strong">[logger_log05]
-level=ERROR
-propagate=1
-qualname=log02.log03.log04.log05
-handlers=hand05</span>
-channel=log05
-parent=log04
-
-<span class="strong">[logger_log06]
-level=CRITICAL
-propagate=1
-qualname=log02.log03.log04.log05.log06
-handlers=hand06</span>
-channel=log06
-parent=log05
-
-<span class="strong">[logger_log07]
-level=WARN
-propagate=1
-qualname=log02.log03.log04.log05.log06.log07
-handlers=hand07</span>
-channel=log07
-parent=log06
-
-#The section below indicates the information relating to handler "hand01".
-#The first three keys (class, level and formatter) are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The class value indicates the handler's class (as determined by eval() in
-#the logging package's namespace).
-#
-#The level value needs to be one of DEBUG, INFO, WARN, ERROR, CRITICAL or NOTSET.
-#NOTSET means "use the parent's level".
-#
-#The formatter value indicates the key name of the formatter for this handler.
-#If blank, a default formatter (logging._defaultFormatter) is used.
-#
-#The stream value indicates the stream for this StreamHandler. It is computed
-#by doing eval() on the string value in the context of the logging package's
-#namespace.
-#
-#The args value is a tuple of arguments which is passed to the constructor for
-#this handler's class in addition to the "self" argument.
-#
-<span class="strong">[handler_hand01]
-class=StreamHandler
-level=NOTSET
-formatter=form01
-args=(sys.stdout,)</span>
-stream=sys.stdout
-
-#The section below indicates the information relating to handler "hand02".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The filename value is the name of the file to write logging information to.
-#The mode value is the mode used to open() the file. The maxsize and backcount
-#values control rollover as described in the package's pydoc.
-#
-<span class="strong">[handler_hand02]
-class=FileHandler
-level=DEBUG
-formatter=form02
-args=('python.log', 'w')</span>
-filename=python.log
-mode=w
-
-#The section below indicates the information relating to handler "hand03".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The host value is the name of the host to send logging information to.
-#The port value is the port number to use for the socket connection.
-#
-<span class="strong">[handler_hand03]
-class=handlers.SocketHandler
-level=INFO
-formatter=form03
-args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)</span>
-host=localhost
-port=DEFAULT_TCP_LOGGING_PORT
-
-#The section below indicates the information relating to handler "hand04".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The host value is the name of the host to send logging information to.
-#The port value is the port number to use for the socket connection.
-#
-<span class="strong">[handler_hand04]
-class=handlers.DatagramHandler
-level=WARN
-formatter=form04
-args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)</span>
-host=localhost
-port=DEFAULT_UDP_LOGGING_PORT
-
-#The section below indicates the information relating to handler "hand05".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The host value is the name of the host to send logging information to.
-#The port value is the port number to use for the socket connection.
-#The facility is the syslog facility to use for logging.
-#
-<span class="strong">[handler_hand05]
-class=handlers.SysLogHandler
-level=ERROR
-formatter=form05
-args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)</span>
-host=localhost
-port=SYSLOG_UDP_PORT
-facility=LOG_USER
-
-#The section below indicates the information relating to handler "hand06".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The appname value is the name of the application which appears in the
-#NT event log.
-#The dllname value is the pathname of a DLL to use for message definitions.
-#The logtype is the type of NT event log to write to - Application, Security
-#or System.
-#
-<span class="strong">[handler_hand06]
-class=NTEventLogHandler
-level=CRITICAL
-formatter=form06
-args=('Python Application', '', 'Application')</span>
-appname=Python Application
-dllname=
-logtype=Application
-
-#The section below indicates the information relating to handler "hand07".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The host value is the name of the SMTP server to connect to.
-#The port value is the port number to use for the SMTP connection.
-#The from value is the "From" value in emails.
-#The to value is a comma-separated list of email addresses.
-#The subject value is the subject of the email.
-#
-<span class="strong">[handler_hand07]
-class=SMTPHandler
-level=WARN
-formatter=form07
-args=('localhost', 'from at abc', ['user1 at abc', 'user2 at xyz'], 'Logger Subject')</span>
-host=localhost
-port=25
-from=from at abc
-to=user1 at abc,user2 at xyz
-subject=Logger Subject
-
-#The section below indicates the information relating to handler "hand08".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The capacity value is the size of this handler's buffer.
-#The flushlevel value is the logging level at which the buffer is flushed.
-#The from value is the "From" value in emails.
-#The target value is the key name of the handler which messages are flushed
-#to (i.e. sent to when flushing).
-#
-<span class="strong">[handler_hand08]
-class=MemoryHandler
-level=NOTSET
-formatter=form08
-target=
-args=(10, ERROR)</span>
-capacity=10
-flushlevel=ERROR
-
-#The section below indicates the information relating to handler "hand09".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The host value is the name of the HTTP server to connect to.
-#The port value is the port number to use for the HTTP connection.
-#The url value is the url to request from the server.
-#The method value is the HTTP request type (GET or POST).
-#
-<span class="strong">[handler_hand09]
-class=HTTPHandler
-level=NOTSET
-formatter=form09
-args=('localhost:9022', '/log', 'GET')</span>
-host=localhost
-port=9022
-url=/log
-method=GET
-
-#The sections below indicate the information relating to the various
-#formatters. The format value is the overall format string, and the
-#datefmt value is the strftime-compatible date/time format string. If
-#empty, the logging package substitutes ISO8601 format date/times where
-#needed. See the package pydoc for more details of the format string
-#structure.
-#
-<span class="strong">[formatter_form01]
-format=F1 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form02]
-format=F2 %(asctime)s %(pathname)s(%(lineno)d): %(levelname)s %(message)s
-datefmt=
-
-[formatter_form03]
-format=F3 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form04]
-format=%(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form05]
-format=F5 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form06]
-format=F6 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form07]
-format=F7 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form08]
-format=F8 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form09]
-format=F9 %(asctime)s %(levelname)s %(message)s
-datefmt=</span>
-
-# --- end of logconf.ini ----------------------------------------------------
-</pre>
-
-<p>To use a file like this, you would call <code>logging.config.fileConfig("logconf.ini")</code>
-whereupon the file is read in and processed. Note that evaluation happens in the context of the logging package (hence the unqualified class names).
-
-
-<a name="guiconf"></a><h4>The GUI Configurator</h4>
-
-To create a file like the above, you can use the new GUI configurator, <code>logconf.py</code>, which is invoked either with no arguments or with a single argument giving the name of a configuration file to read. (Or, if you're a masochist/don't have Tk, you can do it by hand. The configurator is a quick hack, which I hope is reasonably intuitive - have a play with it and see what you think. I've used it with 1.5.2 and 2.1.2 on Windows and 1.5.2 on Linux/x86. There's no validation, rudim [...]
-
-<p>Here's a screenshot of the configurator:</p>
-<img src="logconf.png" border="0"/>
-<p>Here's a quick guide on how to use it:
-<ul>
-<li>The screen is laid out in three panels - for loggers, handlers and formatters (see the yellow rectangles in the screenshot).</li>
-<li>Each panel consists of a listbox, New and Delete buttons and a "property editor" to set properties for each of the objects.</li>
-<li>To create loggers, you need to first select the parent logger before clicking the New button. To create handlers and formatters, just click the appropriate New button.</li>
-<li>To delete an item, just select it in the listbox and click the Delete button.</li>
-<li>Whenever an item is selected in the listbox, its properties are displayed in the property editor section.</li>
-<li>Whenever an item is deleted, the property editor section is cleared.</li>
-<li>To edit a property, just click on the name or value. If the property is read-only, nothing happens. If it's a user-editable value, an entry field appears and you can type into it. If it's a user-selectable value (I mean selectable from a list), a button with ... appears. Clicking on it causes a pseudo-combobox to appear. All such boxes are single-selection, except for the "Handlers" property of loggers, for which several handlers can be selected.</li>
-<li>To commit the changes, just click elsewhere in the property editor section, e.g. below the last property or on some other property.</li>
-<li>Formatters are referred to by handlers, and handlers are referred to by loggers. Hence formatters and handlers have names generated for them automatically, for use in cross-referencing. The names of these cannot be changed. The name for loggers is, however, editable (except for the root logger), as it represents the position of the logger in the hierarchy.</li>
-<li>The Load, Save, Save As and Reset buttons should be reasonably self-explanatory (except perhaps Reset, which just deletes all non-root loggers, handlers and formatters and starts with a clean slate).</li>
-<li>Filters are not supported in this release, but will be as soon as time permits and if there is enough demand.</li>
-</ul></p>
-<a name="scenarios"></a><h4>Case Scenarios</h4>
-
-<p>With reference to the <a href="http://www.python.org/peps/pep-0282.html">PEP</a>,
-here are my comments on the current state of play.
-
-<ol>
- <li>A short simple script. See the example <a href="#simplest"><code>app.py</code></a>
- above.</li>
- <li>Medium sized app with C extension module. I have not specifically considered C extension
- modules but I assume they can just use the standard Python C API to make logging calls.</li>
- <li>Distutils. I would welcome more specific comments on what kind of configuration people
- think would be useful. To a certain extent, controlling verbosity levels through setup.py
- options is, I think, the domain of the app developer rather than the logging package.</li>
- <li>Large applications. If users can restart a system after changing the logging settings
- (via some user-friendly or support-desk-friendly interface) then present functionality
- should cater for this. In the case where the logging behaviour of a (long-)running system needs
- to be changed, then the functionality (new in 0.4.3) described <a href="#onthefly">below</a> can be used.</li>
-</ol>
-
-<a name="threadsafe"></a><h4>Thread Safety</h4>
-
-<p>The package is intended to be threadsafe. Although it makes no use of threads to provide its functionality (except for <a href="#onthefly">on-the-fly reconfiguration</a>), shared data in the package is protected by a thread lock which is acquired before, and released after, modifications to shared data. In addition, the Handler class creates a per-handler instance I/O lock which is acquired before, and released after, calling emit(). If you define your own handlers, in most situations [...]
-
-<a name="onthefly"></a><h4>On-The-Fly Reconfiguration</h4>
-
-<p>The package also allows a program to permit changing of the logging configuration on the fly, i.e. <em>while the program is still running</em>. This should be a help for developers of long-running programs such as servers (e.g. Zope, Webware). At this stage, the on-the-fly configurability is fairly basic - to use it, two new module-level functions are provided (in the <code>logging.config</code> module).
-<ul>
- <li><code>listen([port])</code> is used to create a thread which, when started, opens a socket server which listens on the specified port for configuration requests. The socket protocol is very basic - a two-byte length followed by a string of that length is sent to the listener. The string should be in the same format as logging configuration files, i.e. ConfigParser files conforming to the scheme described <a href="#config">above</a>.</li>
- <li><code>stopListening()</code> tells the thread created by listening to terminate.</li>
-</ul>
-Currently, you can't just change part of the logging configuration - the sent configuration completely replaces the existing configuration, and if previously existing loggers are not in the new configurations, they will be disabled after the new configuration takes effect. The script <code>log_test17.py</code> in the distribution illustrates the on-the-fly configuration feature.
-</p>
-
-<a name="mlcf"></a><h4>Module-Level Convenience Functions</h4>
-
-<p>For the casual user, there are module-level convenience functions which operate on the
-root logger. <a href="logging_pydoc.html#functions">Here</a> is the pydoc for them. </p>
-
-<a name="perf"></a><h4>Performance</h4>
-
-<p>The implementation has not been optimized for performance. This is planned to be done in a later phase, following feature stabilization and benchmarking.</p>
-
-<a name="impstatus"></a><h4>Implementation Status</h4>
-
-<p>The implementation is what I have termed alpha - mainly because it has not had very wide exposure or extensive testing in many environments. Please try to use it/break it and give me
-any <a href="mailto:vinay_sajip at red-dove.com">feedback</a> you can! There is no reason I can see why this package should not be ready in time for the Python 2.3 release :-)</p>
-
-
-<a name="#acks"></a><h4>Acknowledgements</h4>
-<p>The biggest thank you goes to the <a href="http://jakarta.apache.org/log4j/">log4j</a> developers, whom I am attempting to flatter sincerely by imitation ;-) Thanks also to Trent Mick for <a href="http://www.python.org/peps/pep-0282.html">PEP 282</a>, which prompted me to offer this implementation.</p>
-<p>I'd also like to thank all of the people who have given me feedback, patches and encouragement. In particular (but in no particular order):</p>
-<ul>
-<li>Ollie Rutherfurd - patches and suggestions.</li>
-<li>Greg Ward - for nudging me in the direction of distutils.</li>
-<li>Hunter Matthews - questions about user-defined logging levels.</li>
-<li>Nicolas Untz - SysLogHandler implementation.</li>
-<li>Jeremy Hylton - discussions about logging exceptions.</li>
-<li>Kevin Butler - discussions about logging exceptions.</li>
-<li>Richard Jones - lots of positive feedback and ideas.</li>
-<li>David Goodger - suggestion about using CRITICAL rather than FATAL.</li>
-<li>Denis S. Otkidach - suggestions on filters and feedback on performance.</li>
-</ul>
-<a name="todo"></a><h4>Still To Do</h4>
-<p>No rest for the wicked...</p>
-<ul>
-<li>Improvements to the GUI configurator. Feedback, anyone?</li>
-<li>Overview-type documentation? The pydoc is reasonably comprehensive (I like to think). Perhaps a slightly formalized version of the information on this page?</li>
-<li>Testing, and more testing (you could help with this, too ...)</li>
-</ul>
-<p>If you can help with any of this, please <a href="mailto:vinay_sajip at red-dove.com">email me</a>.</p>
-<a name="download"></a><h4>Download and Installation</h4>
-<p>The current version is 0.4.7. <a href="logging-0.4.7.tar.gz">Here</a> is the latest tarball (also in <a href="logging-0.4.7.zip">zip</a> format or <a href="logging-0.4.7.win32.exe">Windows executable</a> - the latter includes the logging package only). The distribution contains the following files:
-<hr>
-<table border="0" cellpadding="0" cellspacing="0" width="100%">
-<tr><th>Filename</th><th> </th><th>Contents</th></tr>
-<tr><td colspan="3"> </td></tr>
-<tr>
-<td><code>README.txt</code></td><td> </td>
-<td>Brief description and change history.</td>
-</tr>
-<tr>
-<td><code>__init__.py</code></td><td> </td>
-<td>The core logging package itself, including StreamHandler and FileHandler.</td>
-</tr>
-<tr>
-<td><code>handlers.py</code></td><td> </td>
-<td>The other handlers provided as part of the package.</td>
-</tr>
-<tr>
-<td><code>config.py</code></td><td> </td>
-<td>The code for configuring the package.</td>
-</tr>
-<tr>
-<td><code>setup.py</code></td><td> </td>
-<td>The distutils setup script.</td>
-</tr>
-<tr>
-<td><code>logrecv.py</code></td><td> </td>
-<td>A test server used for testing SocketHandler, DatagramHandler, HTTPHandler and SOAPHandler. Run it with an argument of one of "TCP", "UDP", "HTTP" or "SOAP" before running a test harness which logs to one of these handlers. Note that to use the SOAP handler, you need to have installed <a href="http://sourceforge.net/projects/pyxml">PyXML-0.6.6</a> and the <a href="http://www.zolera.com/opensrc/zsi/zsi.html">Zolera Soap Infrastructure</a>. This is needed for <code>logrecv.py</code> on [...]
-</tr>
-<tr>
-<td><code>app.py</code></td><td> </td>
-<td>The minimal example described <a href="#simplest">above</a>.</td>
-</tr>
-<tr>
-<td><code>mymodule.py</code></td><td> </td>
-<td>Another example described <a href="#nextsimplest">above</a>.</td>
-</tr>
-<tr>
-<td><code>myapp.py</code></td><td> </td>
-<td>From the second example described <a href="#nextsimplest">above</a>.</td>
-</tr>
-<tr>
-<td><code>log_test.py</code></td><td> </td>
-<td>A test script intended to work as a regression test harness. Runs a number of the other scripts and generates output to stdout.log and stderr.log.</td>
-</tr>
-<tr>
-<td><code>log_test0.py</code></td><td> </td>
-<td>A simple test script using <code>basicConfig()</code> only.</td>
-</tr>
-<tr>
-<td><code>log_test1.py</code></td><td> </td>
-<td>An example showing slightly more involved configuration and
- exception handling, as well as a Unix syslog handler which uses the standard library's syslog module.</td>
-</tr>
-<tr>
-<td><code>log_test2.py</code></td><td> </td>
-<td>A version of <code>log_test0.py</code> which only logs to
- a <code>SocketHandler</code>.</td>
-</tr>
-<tr>
-<td><code>log_test3.py</code></td><td> </td>
-<td>An example showing use of <code>fileConfig()</code> and
- logging to various loggers.</td>
-</tr>
-<tr>
-<td><code>log_test4.py</code></td><td> </td>
-<td>An example showing use of bespoke levels, filtering by level at logger and handler, and use of filter classes (descendants of <code>Filter</code>).</td>
-</tr>
-<tr>
-<td><code>log_test5.py</code></td><td> </td>
-<td>An example showing use of <code>SMTPHandler</code>. Before running this script, be sure to change the bogus addresses it contains to real ones which you have access to.</td>
-</tr>
-<tr>
-<td><code>log_test6.py</code></td><td> </td>
-<td>An example showing use of <code>NTEventLogHandler</code>. This script needs to be run on an NT system.</td>
-</tr>
-<tr>
-<td><code>log_test7.py</code></td><td> </td>
-<td>An example showing use of <code>MemoryHandler</code>.</td>
-</tr>
-<tr>
-<td><code>log_test8.py</code></td><td> </td>
-<td>An example showing use of <code>FileHandler</code> with rollover across multiple files.</td>
-</tr>
-<tr>
-<td><code>log_test9.py</code></td><td> </td>
-<td>An example showing use of <code>BufferingHandler</code> and <code>BufferingFormatter</code> through implementing simple <code>XMLFormatter</code> and <code>XMLHandler</code> classes.</td>
-</tr>
-<tr>
-<td><code>log_test10.py</code></td><td> </td>
-<td>An example showing how to get the logging module to create loggers of your own class (though it needs to be a subclass of <code>Logger</code>).</td>
-</tr>
-<tr>
-<td><code>log_test11.py</code></td><td> </td>
-<td>An example SMTP handler, called <code>BufferingSMTPHandler</code>, which buffers events and sends them via email in batches.</td>
-</tr>
-<tr>
-<td><code>log_test12.py</code></td><td> </td>
-<td>An example showing the use of <code>HTTPHandler</code>, for use with <code>logrecv.py</code>.</td>
-</tr>
-<tr>
-<td><code>log_test13.py</code></td><td> </td>
-<td>An example showing the use of <code>SOAPHandler</code>, for use with <code>logrecv.py</code>.</td>
-</tr>
-<tr>
-<td><code>log_test14.py</code></td><td> </td>
-<td>An example showing an implementation of <code>DBHandler</code>, showing how to log requests to RDBMS tables using the Python Database API 2.0.</td>
-</tr>
-<tr>
-<td><code>log_test15.py</code></td><td> </td>
-<td>An example showing the use of the <code>Filter</code> class with a string initializer.</td>
-</tr>
-<tr>
-<td><code>log_test16.py</code></td><td> </td>
-<td>An example showing the use of logging in a multi-threaded program.</td>
-</tr>
-<tr>
-<td><code>log_test17.py</code></td><td> </td>
-<td>An example showing the use of logging in a multi-threaded program, together with reconfiguring logging on the fly through the use of <code>listen()</code> and <code>stopListening()</code>. This script serves as both server and client, depending on the arguments it's called with.</td>
-</tr>
-<tr>
-<td><code>log_test18.py</code></td><td> </td>
-<td>An example showing the use of an example filter, MatchFilter, which offers flexible match-based
-filtering of LogRecords.</td>
-</tr>
-<tr>
-<td><code>log_test19.py</code></td><td> </td>
-<td>A basic test of logger parents.</td>
-</tr>
-<tr>
-<td><code>log_test20.py</code></td><td> </td>
-<td>Demonstrates the use of custom class instances for messages and filtering based on classes.</td>
-</tr>
-<tr>
-<td><code>log_test21.py</code></td><td> </td>
-<td>Demonstrates the use of a wildcard name-space filter with and without custom message classes.</td>
-</tr>
-<tr>
-<td><code>log_test22.py</code></td><td> </td>
-<td>Demonstrates the use of either localtime or gmtime to do date/time formatting.</td>
-</tr>
-<tr>
-<td><code>debug.ini</code></td><td> </td>
-<td>An example configuration for use with log_test17.py.</td>
-</tr>
-<tr>
-<td><code>warn.ini</code></td><td> </td>
-<td>An example configuration for use with log_test17.py.</td>
-</tr>
-<tr>
-<td><code>error.ini</code></td><td> </td>
-<td>An example configuration for use with log_test17.py.</td>
-</tr>
-<tr>
-<td><code>critical.ini</code></td><td> </td>
-<td>An example configuration for use with log_test17.py.</td>
-</tr>
-<tr>
-<td><code>log_test3.ini</code></td><td> </td>
-<td>An example configuration for use with log_test3.py.</td>
-</tr>
-<tr>
-<td><code>stdout.exp</code></td><td> </td>
-<td>The expected results of stdout.log after running log_test.py.</td>
-</tr>
-<tr>
-<td><code>stderr.exp</code></td><td> </td>
-<td>The expected results of stderr.log after running log_test.py.</td>
-</tr>
-<tr>
-<td><code>logconf.py</code></td><td> </td>
-<td>A Tkinter-based GUI configurator.</td>
-</tr>
-<tr>
-<td><code>logconf.ini</code></td><td> </td>
-<td>Example configuration file, in ConfigParser format, for use with <code>logconf.py</code> and <code>log_test3.py</code>.</td>
-</tr>
-<tr>
-<td><code>logging.dtd</code></td><td> </td>
-<td>A simple example DTD for use with <code>log_test9.py</code>.</td>
-</tr>
-<tr>
-<td><code>logging.xml</code></td><td> </td>
-<td>An example XML file for use with <code>log_test9.py</code>. It references <code>events.xml</code> as external data.</td>
-</tr>
-<tr>
-<td><code>events.xml</code></td><td> </td>
-<td>An example XML file for use with <code>log_test9.py</code>. It holds the actual events in XML format.</td>
-</tr>
-<tr>
-<td><code>python_logging.html</code></td><td> </td>
-<td>The page you're reading now.</td>
-</tr>
-<td><code>default.css</code></td><td> </td>
-<td>Stylesheet for use with the HTML pages.</td>
-</tr>
-<tr><td colspan="3"> </td></tr>
-</table>
-<hr>
-<p>To install, unpack the archive into any directory, and in that directory invoke the script <code>"setup.py install"</code> to install the module in the default location used by distutils.</p>
-<p>To use, just put <code>logging.py</code> in your Python path, "<code>import logging</code>" and go. (The installation procedure described above will normally put the logging module in your Python path. If you want to use file-based configuration API, you'll also need to <code>import logging.config</code>. To use the more esoteric handlers, you'll also need to <code>import logging.handlers</code>.)</p>
-
-<a name="changes"></a><h4>Change History</h4>
-
-<p>The change history is as follows.</p>
-
-<pre>
-Version Date Description
-=============================================================================
-0.4.7 15 Nov 2002 Made into a package with three modules: __init__ (the
- core code), handlers (all handlers other than
- FileHandler and its bases) and config (all the config
- stuff). Before doing this:
- Updated docstrings to include a short line, then a
- blank line, then more descriptive text.
- Renamed 'lvl' to 'level' in various functions.
- Changed FileHandler to use "a" and "w" instead of "a+"
- and "w+".
- Moved log file rotation functionality from FileHandler
- to a new class RotatingFileHandler.
- Improved docstring describing rollover.
- Updated makePickle to use 4-byte length and struct
- module, likewise logrecv.py. Also updated on-the-fly
- config reader to use 4-byte length/struct module.
- Altered ConfigParser test to look at 'readline' rather
- than 'read'.
- Added optional "defaults" argument to fileConfig, to
- be passed to ConfigParser.
- Renamed ALL to NOTSET to avoid confusion.
- Commented out getRootLogger(), as obsolete.
- To do regression testing, run log_test.py and compare
- the created files stdout.log and stderr.log against
- the files stdout.exp and stderr.exp. They should match
- except fir a couple of exception messages which give
- absolute file paths.
- Updated python_logging.html to remove links to
- logging_pydoc.html, which has been removed from the
- distribution.
- Changed default for raiseExceptions to 1.
------------------------------------------------------------------------------
-0.4.6 08 Jul 2002 Added raiseExceptions to allow conditional propagation
- of exceptions which occur during handling.
- Added converter to Formatter to allow use of any
- function to convert time from seconds to a tuple. It
- still defaults to time.localtime but now you can also
- use time.gmtime.
- Added log_test22.py to test the conversion feature.
- Changed rootlogger default level to WARN - was DEBUG.
- Updated some docstrings.
- Moved import of threading to where thread is imported.
- If either is unavailable, threading support is off.
- Updated minor defects in python_logging.html.
- Check to see if ConfigParser has readfp method; if it
- does and an object with a 'read' method is passed in,
- assumes a file-like object and uses readfp to read it
- in.
------------------------------------------------------------------------------
-0.4.5 04 Jun 2002 Fixed bug which caused problem if no args to message
- (suggested by Hye-Shik Chang).
- Fixed bug in _fixupParents (thanks to Nicholas Veeser)
- and added log_test19.py as a test case for this bug.
- Added getMessage to LogRecord (code was moved here from
- Formatter.format)
- Applied str() to record.msg to allow arbitrary classes
- to determine the formatting (as msg can now be a class
- instance).
- Table of Contents added to python_logging.html, the
- section on Loggers updated, and the logconf.ini file
- section annotated.
- Added log_test20.py which demonstrates how to use
- class instances to provide alternatives to numeric
- severities as mechanisms for control of logging.
- Added log_test21.py which builds on log_test20.py to
- show how you can use a regular expression-based Filter
- for flexible matching similar to e.g. Protomatter
- Syslog, where you can filter on e.g. "a.*" or "*.b" or
- "a.*.c".
- _levelNames changed to contain reverse mappings as well
- as forward mappings (leveltext->level as well as level
- -> leveltext). The reverse mappings are used by
- fileConfig().
- fileConfig() now more forgiving of missing options in
- .ini file - sensible defaults now used when some
- options are absent. Also, eval() is used less when
- interpreting .ini file contents - int() and dict lookup
- are used in more places. Altered log_test3.py and added
- log_test3.ini to show a hand-coded configuration file.
------------------------------------------------------------------------------
-0.4.4 02 May 2002 getEffectiveLevel() returns ALL instead of None when
- nothing found. Modified references to level=0 to
- level=ALL in a couple of places.
- SocketHandler now inherits from Handler (it used to
- inherit from StreamHandler, for no good reason).
- getLock() renamed to createLock().
- Docstring tidy-ups, and some tidying up of
- DatagramHandler.
- Factored out unpickling in logrecv.py.
- Added log_test18.py to illustrate MatchFilter, which is
- a general matching filter.
- Improved FileHandler.doRollover() so that the base
- file name is always the most recent, then .1, then .2
- etc. up to the maximum backup count. Renamed formal
- args and attributes used in rollover.
- Changed LogRecord attributes lvl -> levelno, level ->
- levelname (less ambiguity)
- Formatter.format searches for "%(asctime)" rather than
- "(asctime)"
- Renamed _start_time to _startTime
- Formatter.formatTime now returns the time
- Altered logrecv.py to support stopping servers
- programmatically
- Added log_test.py as overall test harness
- basicConfig() can now be safely called more than once
- Modified test scripts to make it easier to call them
- from log_test.py
- Moved SOAPHandler from core to log_test13.py. It's not
- general enough to be in the core; most production use
- will have differing RPC signatures.
------------------------------------------------------------------------------
-0.4.3 14 Apr 2002 Bug fix one-off error message to go to sys.stderr
- rather than sys.stdout.
- logrecv.py fix TCP for busy network.
- Thread safety - added locking to Handler and for shared
- data in module, and log_test16.py to test it.
- Added socket listener to allow on-the-fly configuration
- and added log_test17.py to test it.
------------------------------------------------------------------------------
-0.4.2 11 Apr 2002 Bug fix fileConfig() - setup of MemoryHandler target
- and errors when loggers have no handlers set or
- handlers have no formatters set
- logconf.py - seems to hang if window closed when combo
- dropdown is showing - added code to close popup on exit
- Some tweaks to _srcfile computation (normpath added)
- findCaller() optimized, now a lot faster!
- Logger.removeHandler now closes the handler before
- removing it
- fileConfig() removes existing handlers before adding
- the new set, to avoid memory leakage when repeated
- calls are made
- Fixed logrecv.py bug which hogged CPU time when TCP
- connection was closed from the client
- Added log_test14.py to demonstrate/test a DBHandler
- which writes logging records into an RDBMS using the
- Python Database API 2.0 (to run, you need something
- which supports this already installed - I tested with
- mxODBC)
- Made getLogger name argument optional - returns root
- logger if omitted
- Altered Filter to take a string initializer, filtering
- a sub-hierarchy rooted at a particular point (idea from
- Denis S. Otkidach).
- Added log_test15.py to test Filter initializer
------------------------------------------------------------------------------
-0.4.1 03 Apr 2002 Bug fix SMTPHandler - extra \r\n needed (Oleg Orlov)
- Added BufferingHandler, BufferingFormatter
- Renamed getChainedPriority to getEffectiveLevel
- Removed Logger.getRoot as it is redundant
- Added log_test9.py to test Buffering classes and
- to show an XMLFormatter example.
- Added setLoggerClass.
- Added log_test10.py to test setLoggerClass, using an
- example Logger-derived class which outputs exception
- info even for DEBUG level logging calls
- Added log_test11.py to test a buffering implementation
- of SMTPHandler
- Changed logging call implementation to allow keyword
- arguments (Kevin Butler and others)
- Changed default SysLogHandler implementation.
- Renamed "additive" to "propagate" as it better
- describes the attribute.
- Added HTTPHandler.
- Modified logrecv.py to remove "both" option and to add
- "HTTP" and "SOAP" options (SOAP option needs you to
- have PyXML-0.6.6 and ZSI installed - for logrecv.py
- only, and not for the core logging module itself).
- Added log_test12.py to test HTTPHandler.
- Added log_test13.py to test SOAPHandler.
- Formatted to Python source guidelines (spaces, indent
- of 4, within 80 columns).
- More method renamings (result of feedback) - _handle()
- renamed to emit(), _logRecord() renamed to handle().
- Renamed FATAL to CRITICAL (David Goodger), but left
- fatal() and FATAL in (until PEP is changed)
- Changed configuration file format to ConfigParser
- format.
- Factored filter application functionality out to a new
- Filterer class. The isLoggable() method is renamed to
- filter() in both Filter and Filterer classes.
- Altered SMTPHandler __init__ to accept (host, port)
- for the mail internet address.
- Added GUI configurator which uses Tkinter and the new
- configuration file format. (See logconf.py and an
- example configuration file in logconf.ini)
- Altered log_test3.py to test with the new file format.
------------------------------------------------------------------------------
-0.4 21 Mar 2002 Incorporated comments/patches from Ollie Rutherfurd:
- -Added level filtering for handlers.
- -Return root logger if no name specified in getLogger.
- Incorporated comments from Greg Ward:
- -Added distutils setup.py script.
- Added formatter initialization in Handler.__init__.
- Tidied up docstrings.
- Added removeHandler to Logger.
- Added removeFilter to Logger and Handler.
- logrecv.py modified to keep connection alive until
- client closes it.
- SocketHandler modified to not reset connection after
- each logging event.
- Added shutdown function which closes open sockets
- Renamed DEFAULT_LOGGING_PORT->DEFAULT_TCP_LOGGING_PORT
- Added DEFAULT_UDP_LOGGING_PORT
- Added log_test4.py (example of arbitrary levels)
- Added addLevelName, changed behaviour of getLevelName
- Fixed bugs in DatagramHandler
- Added SMTPHandler implementation
- Added log_test5.py to test SMTPHandler
- Added SysLogHandler (contribution from Nicolas Untz
- based on Sam Rushing's syslog.py)
- Modified log_test1.py to add a SysLogHandler
- Added rollover functionality to FileHandler
- Added NTEventLogHandler (based on Win32 extensions)
- Added MemoryHandler implementation
- Added log_test7.py to test MemoryHandler
- Added log_test8.py to test FileHandler rollover
- Added logException method to Logger
- Added formatException method to Formatter
- Added log_test6.py to test NTEventHandler and
- logException
- Numerous internal method renamings (sorry - but better
- to do this now, rather than when we enter beta status).
------------------------------------------------------------------------------
-0.3 14 Mar 2002 First public release, for early feedback
------------------------------------------------------------------------------
-0.2 Consolidated into single file (for internal use only)
------------------------------------------------------------------------------
-0.1 Initial implementation (for internal use only)
------------------------------------------------------------------------------
-</pre>
-
-<a name="license"></a><h4>Copyright and License</h4>
-
-<p>The copyright statement follows. </p>
-
-<pre>
-Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Vinay Sajip
-not be used in advertising or publicity pertaining to distribution
-of the software without specific, written prior permission.
-VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
-AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-</pre>
-</body>
-</html>
diff --git a/tools/python/logging/logging-0.4.9.2/setup.py b/tools/python/logging/logging-0.4.9.2/setup.py
deleted file mode 100644
index 5bca563..0000000
--- a/tools/python/logging/logging-0.4.9.2/setup.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from distutils.core import setup
-
-setup(name = "logging",
- description="A logging module for Python",
- long_description = """This module is intended to provide a standard error logging mechanism in Python as per PEP 282.""",
- license="""Copyright (C) 2001-2004 by Vinay Sajip. All Rights Reserved.
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Vinay Sajip
-not be used in advertising or publicity pertaining to distribution
-of the software without specific, written prior permission.
-
-VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
-AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.""",
- version = "0.4.9.2",
- author = "Vinay Sajip",
- author_email = "vinay_sajip at red-dove.com",
- maintainer = "Vinay Sajip",
- maintainer_email = "vinay_sajip at red-dove.com",
- url = "http://www.red-dove.com/python_logging.html",
- packages = ["logging"],
- )
diff --git a/tools/python/logging/logging-0.4.9.2/test/app.py b/tools/python/logging/logging-0.4.9.2/test/app.py
deleted file mode 100644
index e550a19..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/app.py
+++ /dev/null
@@ -1,5 +0,0 @@
-import logging
-
-logging.warning("Hello")
-logging.error("Still here...")
-logging.warning("Goodbye")
\ No newline at end of file
diff --git a/tools/python/logging/logging-0.4.9.2/test/critical.ini b/tools/python/logging/logging-0.4.9.2/test/critical.ini
deleted file mode 100644
index 8cbaa8a..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/critical.ini
+++ /dev/null
@@ -1,60 +0,0 @@
-[loggers]
-keys=root,log02,log03,log04,log05
-
-[handlers]
-keys=hand01
-
-[formatters]
-keys=form01
-
-[logger_root]
-level=WARN
-propagate=1
-channel=
-parent=
-qualname=(root)
-handlers=hand01
-
-[logger_log02]
-level=CRITICAL
-propagate=1
-channel=A
-parent=(root)
-qualname=A
-handlers=
-
-[logger_log03]
-level=CRITICAL
-propagate=1
-channel=B
-parent=log02
-qualname=A.B
-handlers=
-
-[logger_log04]
-level=CRITICAL
-propagate=1
-channel=C
-parent=log03
-qualname=A.B.C
-handlers=
-
-[logger_log05]
-level=CRITICAL
-propagate=1
-channel=D
-parent=log04
-qualname=A.B.C.D
-handlers=
-
-[handler_hand01]
-class=StreamHandler
-level=NOTSET
-formatter=form01
-stream=sys.stderr
-args=(sys.stderr,)
-
-[formatter_form01]
-format=critical.ini %(name)s %(levelname)s %(message)s
-datefmt=
-
diff --git a/tools/python/logging/logging-0.4.9.2/test/debug.ini b/tools/python/logging/logging-0.4.9.2/test/debug.ini
deleted file mode 100644
index 6c8622f..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/debug.ini
+++ /dev/null
@@ -1,60 +0,0 @@
-[loggers]
-keys=root,log02,log03,log04,log05
-
-[handlers]
-keys=hand01
-
-[formatters]
-keys=form01
-
-[logger_root]
-level=WARN
-propagate=1
-channel=
-parent=
-qualname=(root)
-handlers=hand01
-
-[logger_log02]
-level=DEBUG
-propagate=1
-channel=A
-parent=(root)
-qualname=A
-handlers=
-
-[logger_log03]
-level=DEBUG
-propagate=1
-channel=B
-parent=log02
-qualname=A.B
-handlers=
-
-[logger_log04]
-level=DEBUG
-propagate=1
-channel=C
-parent=log03
-qualname=A.B.C
-handlers=
-
-[logger_log05]
-level=DEBUG
-propagate=1
-channel=D
-parent=log04
-qualname=A.B.C.D
-handlers=
-
-[handler_hand01]
-class=StreamHandler
-level=NOTSET
-formatter=form01
-stream=sys.stderr
-args=(sys.stderr,)
-
-[formatter_form01]
-format=debug.ini %(name)s %(levelname)s %(message)s
-datefmt=
-
diff --git a/tools/python/logging/logging-0.4.9.2/test/error.ini b/tools/python/logging/logging-0.4.9.2/test/error.ini
deleted file mode 100644
index 49beea7..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/error.ini
+++ /dev/null
@@ -1,60 +0,0 @@
-[loggers]
-keys=root,log02,log03,log04,log05
-
-[handlers]
-keys=hand01
-
-[formatters]
-keys=form01
-
-[logger_root]
-level=WARN
-propagate=1
-channel=
-parent=
-qualname=(root)
-handlers=hand01
-
-[logger_log02]
-level=ERROR
-propagate=1
-channel=A
-parent=(root)
-qualname=A
-handlers=
-
-[logger_log03]
-level=ERROR
-propagate=1
-channel=B
-parent=log02
-qualname=A.B
-handlers=
-
-[logger_log04]
-level=ERROR
-propagate=1
-channel=C
-parent=log03
-qualname=A.B.C
-handlers=
-
-[logger_log05]
-level=ERROR
-propagate=1
-channel=D
-parent=log04
-qualname=A.B.C.D
-handlers=
-
-[handler_hand01]
-class=StreamHandler
-level=NOTSET
-formatter=form01
-stream=sys.stderr
-args=(sys.stderr,)
-
-[formatter_form01]
-format=error.ini %(name)s %(levelname)s %(message)s
-datefmt=
-
diff --git a/tools/python/logging/logging-0.4.9.2/test/events.xml b/tools/python/logging/logging-0.4.9.2/test/events.xml
deleted file mode 100644
index f7f1092..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/events.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
- <event name="root" level="20" filename="log_test9.py" lineno="66">
- <message>Info index = 90</message>
- </event>
- <event name="root" level="20" filename="log_test9.py" lineno="66">
- <message>Info index = 91</message>
- </event>
- <event name="root" level="20" filename="log_test9.py" lineno="66">
- <message>Info index = 92</message>
- </event>
- <event name="root" level="20" filename="log_test9.py" lineno="66">
- <message>Info index = 93</message>
- </event>
- <event name="root" level="20" filename="log_test9.py" lineno="66">
- <message>Info index = 94</message>
- </event>
- <event name="root" level="20" filename="log_test9.py" lineno="66">
- <message>Info index = 95</message>
- </event>
- <event name="root" level="20" filename="log_test9.py" lineno="66">
- <message>Info index = 96</message>
- </event>
- <event name="root" level="20" filename="log_test9.py" lineno="66">
- <message>Info index = 97</message>
- </event>
- <event name="root" level="20" filename="log_test9.py" lineno="66">
- <message>Info index = 98</message>
- </event>
- <event name="root" level="20" filename="log_test9.py" lineno="66">
- <message>Info index = 99</message>
- </event>
\ No newline at end of file
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test.py b/tools/python/logging/logging-0.4.9.2/test/log_test.py
deleted file mode 100755
index 5d54b9b..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test.py
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""Test harness for the logging module. Run all tests.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-
-import os, sys, logging, threading, time
-
-BANNER = "-- %-10s %-6s --------------------------------------------------------\n"
-
-def banner(nm, typ):
- sep = BANNER % (nm, typ)
- sys.stdout.write(sep)
- sys.stdout.flush()
- sys.stderr.write(sep)
- sys.stderr.flush()
-
-def main():
- oldout = sys.stdout
- olderr = sys.stderr
- sys.stdout = open("stdout.log", "w")
- sys.stderr = open("stderr.log", "w")
- logging.basicConfig()
- root = logging.getLogger("")
- hdlr0 = root.handlers[0]
- #Set up servers
- import logrecv
- threads = []
- tcpserver = logrecv.LogRecordSocketReceiver()
- tcpserver.logname = ""
- threads.append(threading.Thread(target=logrecv.runTCP, args=(tcpserver,)))
- udpserver = logrecv.LogRecordDatagramReceiver()
- udpserver.logname = ""
- threads.append(threading.Thread(target=logrecv.runUDP, args=(udpserver,)))
- httpserver = logrecv.LogRecordHTTPReceiver()
- httpserver.logname = ""
- threads.append(threading.Thread(target=logrecv.runHTTP, args=(httpserver,)))
- soapserver = None
- if logrecv.SOAPServer:
- soapserver = logrecv.SOAPServer()
- soapserver.modules = (sys.modules["logrecv"],)
- soapserver.logname = ""
- threads.append(threading.Thread(target=logrecv.runSOAP, args=(soapserver,)))
-
- for thread in threads:
- thread.start()
- try:
- import log_test0
- banner("log_test0", "begin")
- log_test0.main()
- banner("log_test0", "end")
- try:
- import log_test1
- banner("log_test1", "begin")
- log_test1.main()
- banner("log_test1", "end")
- except ImportError:
- pass
-
- import log_test2
- banner("log_test2", "begin")
- log_test2.main()
- banner("log_test2", "end")
- time.sleep(3)
-
- #Skip 3 as it tests fileConfig
-
- banner("log_test4", "begin")
- import log_test4
- banner("log_test4", "end")
-
- #Skip 5 as it tests SMTPHandler, can't easily check results automatically
-
- #Skip 6 as it tests NTEventLogHandler, can't easily check results automatically
-
- banner("log_test7", "begin")
- root.removeHandler(hdlr0)
- import log_test7
- root.addHandler(hdlr0)
- banner("log_test7", "end")
-
- banner("log_test8", "begin")
- import log_test8
- root.removeHandler(hdlr0)
- log_test8.main()
- root.addHandler(hdlr0)
- banner("log_test8", "end")
-
- banner("log_test9", "begin")
- import log_test9
- root.removeHandler(hdlr0)
- log_test9.main()
- root.addHandler(hdlr0)
- banner("log_test9", "end")
-
- banner("log_test10", "begin")
- import log_test10
- log_test10.main()
- banner("log_test10", "end")
-
- #Skip 11 as it tests SMTPHandler, can't easily check results automatically
-
- import log_test12
- banner("log_test12", "begin")
- log_test12.main()
- banner("log_test12", "end")
-
- import log_test13
- banner("log_test13", "begin")
- log_test13.main()
- banner("log_test13", "end")
-
- import log_test15
- banner("log_test15", "begin")
- log_test15.test(log_test15.FILTER)
- banner("log_test15", "end")
-
- time.sleep(3)
-
- finally:
- #shut down servers
- olderr.write("Tidying up...")
- tcpserver.abort = 1
- udpserver.abort = 1
- httpserver.abort = 1
- if soapserver:
- soapserver.abort = 1
- for thread in threads:
- thread.join()
- sys.stdout.close()
- sys.stdout = oldout
- #don't close this, as hdlr0 references it. hdlr0 will be closed at application exit
- #sys.stderr.close()
- sys.stderr = olderr
- print "Test run completed."
-
-if __name__ == "__main__":
- main()
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test0.py b/tools/python/logging/logging-0.4.9.2/test/log_test0.py
deleted file mode 100755
index 3799841..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test0.py
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""Test harness for the logging module. A basic test of levels.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-
-import logging
-msgcount = 0
-
-def nextmessage():
- global msgcount
- rv = "Message %d" % msgcount
- msgcount = msgcount + 1
- return rv
-
-def main():
- logging.basicConfig()
- logging.getLogger("").setLevel(logging.DEBUG)
- ERR = logging.getLogger("ERR")
- ERR.setLevel(logging.ERROR)
- INF = logging.getLogger("INF")
- INF.setLevel(logging.INFO)
- INF_ERR = logging.getLogger("INF.ERR")
- INF_ERR.setLevel(logging.ERROR)
- DEB = logging.getLogger("DEB")
- DEB.setLevel(logging.DEBUG)
-
- INF_UNDEF = logging.getLogger("INF.UNDEF")
- INF_ERR_UNDEF = logging.getLogger("INF.ERR.UNDEF")
- UNDEF = logging.getLogger("UNDEF")
-
- GRANDCHILD = logging.getLogger("INF.BADPARENT.UNDEF")
- CHILD = logging.getLogger("INF.BADPARENT")
-
- #These should log
- ERR.log(logging.CRITICAL, nextmessage())
- ERR.error(nextmessage())
-
- INF.log(logging.CRITICAL, nextmessage())
- INF.error(nextmessage())
- INF.warning(nextmessage())
- INF.info(nextmessage())
-
- INF_UNDEF.log(logging.CRITICAL, nextmessage())
- INF_UNDEF.error(nextmessage())
- INF_UNDEF.warning(nextmessage())
- INF_UNDEF.info(nextmessage())
-
- INF_ERR.log(logging.CRITICAL, nextmessage())
- INF_ERR.error(nextmessage())
-
- INF_ERR_UNDEF.log(logging.CRITICAL, nextmessage())
- INF_ERR_UNDEF.error(nextmessage())
-
- DEB.log(logging.CRITICAL, nextmessage())
- DEB.error(nextmessage())
- DEB.warning(nextmessage())
- DEB.info(nextmessage())
- DEB.debug(nextmessage())
-
- UNDEF.log(logging.CRITICAL, nextmessage())
- UNDEF.error(nextmessage())
- UNDEF.warning(nextmessage())
- UNDEF.info(nextmessage())
-
- GRANDCHILD.log(logging.CRITICAL, nextmessage())
- CHILD.log(logging.CRITICAL, nextmessage())
-
- #These should not log
- ERR.warning(nextmessage())
- ERR.info(nextmessage())
- ERR.debug(nextmessage())
-
- INF.debug(nextmessage())
- INF_UNDEF.debug(nextmessage())
-
- INF_ERR.warning(nextmessage())
- INF_ERR.info(nextmessage())
- INF_ERR.debug(nextmessage())
- INF_ERR_UNDEF.warning(nextmessage())
- INF_ERR_UNDEF.info(nextmessage())
- INF_ERR_UNDEF.debug(nextmessage())
-
- INF.info("Messages should bear numbers 0 through 24.")
-
-if __name__ == "__main__":
- import sys
- #print sys.argv[0]
- args = sys.argv[1:]
- if "-profile" in args:
- import profile, pstats
- args.remove("-profile")
- statf = "log_test0.pro"
- profile.run("main()", statf)
- stats = pstats.Stats(statf)
- stats.strip_dirs().sort_stats('time').print_stats()
- else:
- main()
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test1.py b/tools/python/logging/logging-0.4.9.2/test/log_test1.py
deleted file mode 100755
index 98b9874..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test1.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""Test harness for the logging module. A test showing exception handling and use of SysLogHandler.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-import sys, logging
-import syslog
-
-class SLHandler(logging.Handler):
- def __init__(self, ident, logopt=0, facility=syslog.LOG_USER):
- logging.Handler.__init__(self)
- self.ident = ident
- self.logopt = logopt
- self.facility = facility
- self.mappings = {
- logging.DEBUG: syslog.LOG_DEBUG,
- logging.INFO: syslog.LOG_INFO,
- logging.WARNING: syslog.LOG_WARNING,
- logging.ERROR: syslog.LOG_ERR,
- logging.CRITICAL: syslog.LOG_CRIT,
- }
-
- def encodeLevel(self, level):
- return self.mappings.get(level, syslog.LOG_INFO)
-
- def emit(self, record):
- syslog.openlog(self.ident, self.logopt, self.facility)
- msg = self.format(record)
- prio = self.encodeLevel(record.levelno)
- syslog.syslog(prio, msg)
- syslog.closelog()
-
-def config():
- logging.basicConfig()
- logging.getLogger("").setLevel(logging.DEBUG)
- if __name__ == "__main__":
- fmt = logging.Formatter("%(asctime)s %(filename)s:%(lineno)d %(levelname)-5s - %(message)s")
- hdlr = logging.FileHandler("tmp.tmp")
- hdlr.setFormatter(fmt)
- logging.getLogger("").addHandler(hdlr)
- else:
- fmt = None
- hdlr = SLHandler("log_test1")
- if fmt:
- hdlr.setFormatter(fmt)
- logging.getLogger("").addHandler(hdlr)
- return hdlr
-
-def run():
- logging.info("Starting...")
- try:
- print "7" + 4
- except Exception, e:
- logging.error("Problem %s (%d)", "ERROR", logging.ERROR, exc_info=1)
- logging.debug("Problem %s (%d)", "DEBUG", logging.DEBUG, exc_info=1)
- logging.info("Done.")
-
-
-def main():
- hdlr = config()
- run()
- logging.getLogger("").removeHandler(hdlr)
-
-if __name__ == "__main__":
- main()
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test10.py b/tools/python/logging/logging-0.4.9.2/test/log_test10.py
deleted file mode 100755
index 839c08c..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test10.py
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""Test harness for the logging module. Shows use of a user-defined Logger subclass.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-import sys
-import locale
-
-locale.setlocale(locale.LC_ALL, '')
-
-from logging import *
-
-LOG_FORMAT = "%(asctime)s %(levelname)-5s %(message)s"
-DATE_FORMAT = "%x %X"
-
-class MyLogger(Logger):
- """
- A simple example of a logger extension.
- """
- def debug(self, msg, *args, **kwargs):
- """
- This overridden method passes exception information for DEBUG level calls
- """
- if self.manager.disable >= DEBUG:
- return
- if DEBUG >= self.getEffectiveLevel():
- exc_info = kwargs.get("exc_info", 0)
- ei = None
- if exc_info:
- ei = sys.exc_info()
- if not ei[1]:
- ei = None
- self._log(DEBUG, msg, args, ei)
- del ei
-
-class NotALogger:
- pass
-
-def config():
- try:
- setLoggerClass(NotALogger)
- except Exception, e:
- sys.stderr.write("%s\n" % e)
- setLoggerClass(MyLogger)
- if __name__ == "__main__":
- basicConfig()
- if __name__ == "__main__":
- getLogger("").handlers[0].setFormatter(Formatter(LOG_FORMAT, DATE_FORMAT))
-
-def run():
- getLogger("").setLevel(DEBUG)
- logger = getLogger("mylogger")
- logger.info("Starting...")
- logger.debug("Debug message not in exception handler (no traceback)")
- logger.info("About to throw exception...")
- try:
- print "7" + 4
- except Exception, e:
- logger.debug("Debug message inside exception handler (traceback)",exc_info=1)
- logger.info("Done.")
-
-def main():
- config()
- run()
-
-if __name__ == "__main__":
- main()
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test11.py b/tools/python/logging/logging-0.4.9.2/test/log_test11.py
deleted file mode 100755
index 0aae955..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test11.py
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""Test harness for the logging module. Tests BufferingSMTPHandler, an alternative implementation
-of SMTPHandler.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-import string, logging, logging.handlers
-
-MAILHOST = 'beta'
-FROM = 'log_test11 at red-dove.com'
-TO = ['arkadi_renko']
-SUBJECT = 'Test Logging email from Python logging module (buffering)'
-
-class BufferingSMTPHandler(logging.handlers.BufferingHandler):
- def __init__(self, mailhost, fromaddr, toaddrs, subject, capacity):
- logging.handlers.BufferingHandler.__init__(self, capacity)
- self.mailhost = mailhost
- self.mailport = None
- self.fromaddr = fromaddr
- self.toaddrs = toaddrs
- self.subject = subject
- self.setFormatter(logging.Formatter("%(asctime)s %(levelname)-5s %(message)s"))
-
- def flush(self):
- if len(self.buffer) > 0:
- try:
- import smtplib
- port = self.mailport
- if not port:
- port = smtplib.SMTP_PORT
- smtp = smtplib.SMTP(self.mailhost, port)
- msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" % (self.fromaddr, string.join(self.toaddrs, ","), self.subject)
- for record in self.buffer:
- s = self.format(record)
- print s
- msg = msg + s + "\r\n"
- smtp.sendmail(self.fromaddr, self.toaddrs, msg)
- smtp.quit()
- except:
- self.handleError(None) # no particular record
- self.buffer = []
-
-def test():
- logger = logging.getLogger("")
- logger.setLevel(logging.DEBUG)
- logger.addHandler(BufferingSMTPHandler(MAILHOST, FROM, TO, SUBJECT, 10))
- for i in xrange(102):
- logger.info("Info index = %d", i)
- logging.shutdown()
-
-if __name__ == "__main__":
- test()
\ No newline at end of file
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test12.py b/tools/python/logging/logging-0.4.9.2/test/log_test12.py
deleted file mode 100755
index e5e9be3..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test12.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""
-A test harness for the logging module. Tests HTTPHandler.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-import sys, string, logging, logging.handlers
-
-def main():
- import pdb
- host = "localhost:%d" % logging.handlers.DEFAULT_HTTP_LOGGING_PORT
- gh = logging.handlers.HTTPHandler(host, '/log', 'GET')
- ph = logging.handlers.HTTPHandler(host, '/log', 'POST')
- logger = logging.getLogger("log_test12")
- logger.propagate = 0
- logger.addHandler(gh)
- logger.addHandler(ph)
- logging.getLogger("").setLevel(logging.DEBUG)
- logger.info("Jackdaws love my big %s of %s", "sphinx", "quartz")
- logger.debug("Pack my %s with twelve dozen %s", "box", "liquor jugs")
- gh.close()
- ph.close()
- logger.removeHandler(gh)
- logger.removeHandler(ph)
-
-if __name__ == "__main__":
- main()
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test13.py b/tools/python/logging/logging-0.4.9.2/test/log_test13.py
deleted file mode 100755
index c054f29..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test13.py
+++ /dev/null
@@ -1,106 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""
-A test harness for the logging module. Implements a SOAPHandler class which
-can be used to form the basis of extended SOAP functionality.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-import string, logging, logging.handlers, types
-
-SOAP_MESSAGE = """<SOAP-ENV:Envelope
- xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:logging="http://www.red-dove.com/logging"
- SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
->
- <SOAP-ENV:Body>
- <logging:log>
-%s
- </logging:log>
- </SOAP-ENV:Body>
-</SOAP-ENV:Envelope>
-"""
-
-class SOAPHandler(logging.Handler):
- """
- A class which sends records to a SOAP server.
- """
- def __init__(self, host, url):
- """
- Initialize the instance with the host and the request URL
- """
- logging.Handler.__init__(self)
- self.host = host
- self.url = url
-
- def emit(self, record):
- """
- Send the record to the Web server as a SOAP message
- """
- try:
- import httplib
- h = httplib.HTTP(self.host)
- h.putrequest("POST", self.url)
- keys = record.__dict__.keys()
- keys.sort()
- args = ""
- for key in keys:
- v = record.__dict__[key]
- if type(v) == types.StringType:
- t = "string"
- elif (type(v) == types.IntType) or (type(v) == types.LongType):
- t = "integer"
- elif type(v) == types.FloatType:
- t = "float"
- else:
- t = "string"
- args = args + "%12s<logging:%s xsi:type=\"xsd:%s\">%s</logging:%s>\n" % ("",
- key, t, str(v), key)
- data = SOAP_MESSAGE % args[:-1]
- h.putheader("Content-type", "text/plain; charset=\"utf-8\"")
- h.putheader("Content-length", str(len(data)))
- h.endheaders()
- #print data
- h.send(data)
- r = h.getreply() #can't do anything with the result
- f = h.getfile()
- if f:
- #print f.read()
- f.close()
- except:
- self.handleError(record)
-
-def main():
- sh = SOAPHandler('localhost:%d' % logging.handlers.DEFAULT_SOAP_LOGGING_PORT, '/log')
- logger = logging.getLogger("log_test13")
- logging.getLogger("").setLevel(logging.DEBUG)
- logger.propagate = 0
- logger.addHandler(sh)
- logger.info("Jackdaws love my big %s of %s", "sphinx", "quartz")
- logger.debug("Pack my %s with five dozen %s", "box", "liquor jugs")
- logger.removeHandler(sh)
-
-if __name__ == "__main__":
- main()
-
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test14.py b/tools/python/logging/logging-0.4.9.2/test/log_test14.py
deleted file mode 100755
index c00121b..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test14.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""
-A test harness for the logging module. An example handler - DBHandler -
-which writes to an Python DB API 2.0 data source. You'll need to set this
-source up before you run the test.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-import sys, string, time, logging
-
-class DBHandler(logging.Handler):
- def __init__(self, dsn, uid='', pwd=''):
- logging.Handler.__init__(self)
- import mx.ODBC.Windows
- self.dsn = dsn
- self.uid = uid
- self.pwd = pwd
- self.conn = mx.ODBC.Windows.connect(self.dsn, self.uid, self.pwd)
- self.SQL = """INSERT INTO Events (
- Created,
- RelativeCreated,
- Name,
- LogLevel,
- LevelText,
- Message,
- Filename,
- Pathname,
- Lineno,
- Milliseconds,
- Exception,
- Thread
- )
- VALUES (
- %(dbtime)s,
- %(relativeCreated)d,
- '%(name)s',
- %(levelno)d,
- '%(levelname)s',
- '%(message)s',
- '%(filename)s',
- '%(pathname)s',
- %(lineno)d,
- %(msecs)d,
- '%(exc_text)s',
- '%(thread)s'
- );
- """
- self.cursor = self.conn.cursor()
-
- def formatDBTime(self, record):
- record.dbtime = time.strftime("#%m/%d/%Y#", time.localtime(record.created))
-
- def emit(self, record):
- try:
- #use default formatting
- self.format(record)
- #now set the database time up
- self.formatDBTime(record)
- if record.exc_info:
- record.exc_text = logging._defaultFormatter.formatException(record.exc_info)
- else:
- record.exc_text = ""
- sql = self.SQL % record.__dict__
- self.cursor.execute(sql)
- self.conn.commit()
- except:
- import traceback
- ei = sys.exc_info()
- traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
- del ei
-
- def close(self):
- self.cursor.close()
- self.conn.close()
- logging.Handler.close(self)
-
-dh = DBHandler('Logging')
-logger = logging.getLogger("")
-logger.setLevel(logging.DEBUG)
-logger.addHandler(dh)
-logger.info("Jackdaws love my big %s of %s", "sphinx", "quartz")
-logger.debug("Pack my %s with five dozen %s", "box", "liquor jugs")
-try:
- import math
- math.exp(1000)
-except:
- logger.exception("Problem with %s", "math.exp")
-logging.shutdown()
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test15.py b/tools/python/logging/logging-0.4.9.2/test/log_test15.py
deleted file mode 100755
index cebb9d8..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test15.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""
-A test harness for the logging module. Tests Filter.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-
-import sys, logging
-
-FILTER = "a.b"
-
-def message(s):
- sys.stderr.write("%s\n" % s)
-
-def doLog():
- logging.getLogger("a").info("Info 1")
- logging.getLogger("a.b").info("Info 2")
- logging.getLogger("a.c").info("Info 3")
- logging.getLogger("a.b.c").info("Info 4")
- logging.getLogger("a.b.c.d").info("Info 5")
- logging.getLogger("a.bb.c").info("Info 6")
- logging.getLogger("b").info("Info 7")
- logging.getLogger("b.a").info("Info 8")
- logging.getLogger("c.a.b").info("Info 9")
- logging.getLogger("a.bb").info("Info 10")
-
-def test(fs):
- root = logging.getLogger()
- root.setLevel(logging.DEBUG)
- if __name__ == "__main__":
- hand = logging.StreamHandler()
- hand.setFormatter(logging.Formatter("%(name)-10s %(message)s"))
- root.addHandler(hand)
- else:
- hand = root.handlers[0]
- message("Unfiltered...")
- doLog()
- message("Filtered with '%s'..." % fs)
- filt = logging.Filter(fs)
- hand.addFilter(filt)
- doLog()
- hand.removeFilter(filt)
-
-if __name__ == "__main__":
- import sys
- if len(sys.argv) > 1:
- fs = sys.argv[1]
- else:
- fs = FILTER
- test(fs)
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test16.py b/tools/python/logging/logging-0.4.9.2/test/log_test16.py
deleted file mode 100755
index f98b627..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test16.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""
-A test harness for the logging module. Tests thread safety.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-
-import logging, logging.handlers, thread, threading, random
-
-logging.raiseExceptions = 1
-
-NUM_THREADS = 10
-LOOP_COUNT = 10000
-
-LOG_MESSAGES = [
- (logging.DEBUG, "%3d This is a %s message", "debug"),
- (logging.INFO, "%3d This is an %s message", "informational"),
- (logging.WARNING, "%3d This is a %s message", "warning"),
- (logging.ERROR, "%3d This is an %s message", "error"),
- (logging.CRITICAL, "%3d This is a %s message", "critical"),
-]
-
-LOG_NAMES = ["A", "A.B", "A.B.C", "A.B.C.D"]
-
-def doLog(num):
- logger = logging.getLogger('')
- logger.info("*** thread %s started (%d)", thread.get_ident(), num)
- for i in xrange(LOOP_COUNT):
- logger = logging.getLogger(random.choice(LOG_NAMES))
- a = random.choice(LOG_MESSAGES)
- args = a[0:2] + (num,) + a[2:]
- apply(logger.log, args)
-
-def test():
- f = logging.Formatter("%(asctime)s %(levelname)-9s %(name)-8s %(thread)5s %(message)s")
- root = logging.getLogger('')
- root.setLevel(logging.DEBUG)
- h = logging.FileHandler('thread.log', 'w')
- root.addHandler(h)
- h.setFormatter(f)
- h = logging.handlers.SocketHandler('localhost', logging.handlers.DEFAULT_TCP_LOGGING_PORT)
- #h = logging.handlers.DatagramHandler('localhost', logging.handlers.DEFAULT_UDP_LOGGING_PORT)
- root.addHandler(h)
- threads = []
- for i in xrange(NUM_THREADS):
- threads.append(threading.Thread(target=doLog, args=(len(threads),)))
- for t in threads:
- t.start()
- for t in threads:
- t.join()
-
-if __name__ == "__main__":
- test()
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test17.py b/tools/python/logging/logging-0.4.9.2/test/log_test17.py
deleted file mode 100755
index 3a72d5e..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test17.py
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""
-A test harness for the logging module. Tests thread safety.
-
-To use as a server, run with no arguments in one process.
-To use as a client, run with arguments "-client <filename>" where <filename>
-is the name of a file containing a logging configuration.
-The example files debug.ini, warn.ini, error.ini and critical.ini are
-provided to use in the test. They each have a customized message format
-(prefixed with their name) and the loggers have their levels set to the
-value implied by their name.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-
-import sys, logging, logging.config, thread, threading, random, time, struct
-
-NUM_THREADS = 10
-LOOP_COUNT = 10
-
-CONFIG_PORT = 9077
-
-logging.raiseExceptions = 1
-
-LOG_MESSAGES = [
- (logging.DEBUG, "%3d This is a %s message", "debug"),
- (logging.INFO, "%3d This is an %s message", "informational"),
- (logging.WARNING, "%3d This is a %s message", "warning"),
- (logging.ERROR, "%3d This is an %s message", "error"),
- (logging.CRITICAL, "%3d This is a %s message", "critical"),
-]
-
-LOG_NAMES = ["A", "A.B", "A.B.C", "A.B.C.D"]
-
-def doLog(num):
- logger = logging.getLogger('')
- logger.setLevel(logging.DEBUG)
- logger.info("*** thread %s started (%d)", thread.get_ident(), num)
- for i in xrange(LOOP_COUNT):
- logger = logging.getLogger(random.choice(LOG_NAMES))
- a = random.choice(LOG_MESSAGES)
- args = a[0:2] + (num,) + a[2:]
- time.sleep(random.random() * 3)
- apply(logger.log, args)
-
-def runserver():
- f = logging.Formatter("%(asctime)s %(levelname)-9s %(name)-8s %(thread)5s %(message)s")
- root = logging.getLogger('')
- h = logging.StreamHandler()
- root.addHandler(h)
- h.setFormatter(f)
- threads = []
- for i in xrange(NUM_THREADS):
- threads.append(threading.Thread(target=doLog, args=(len(threads),)))
- threads.append(logging.config.listen(CONFIG_PORT)) #don't use default port
- for t in threads:
- t.start()
- for t in threads[:-1]:
- t.join()
- logging.config.stopListening()
- threads[-1].join()
-
-def runclient(fname):
- import socket
-
- print "configuring with '%s'" % fname
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.connect(('localhost', CONFIG_PORT))
- f = open(fname, "r")
- s = f.read()
- f.close()
- slen = struct.pack(">L", len(s))
- s = slen + s
- sentsofar = 0
- left = len(s)
- while left > 0:
- sent = sock.send(s[sentsofar:])
- sentsofar = sentsofar + sent
- left = left - sent
- sock.close()
-
-if __name__ == "__main__":
- if "-client" not in sys.argv:
- runserver()
- else:
- sys.argv.remove("-client")
- if len(sys.argv) > 1:
- fname = sys.argv[1]
- else:
- fname = "warn.ini"
- runclient(fname)
\ No newline at end of file
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test18.py b/tools/python/logging/logging-0.4.9.2/test/log_test18.py
deleted file mode 100755
index 071ff8c..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test18.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""
-A test harness for the logging module. Tests MatchFilter.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-
-import logging, types, string
-
-class MatchFilter(logging.Filter):
- def __init__(self, **kwargs):
- self.dict = kwargs
-
- def matchOne(self, key, value, record):
- rv = getattr(record, key)
- if key != "name":
- if key not in ["message", "msg"]:
- return rv == value
- else:
- return string.find(str(rv), value) >= 0
- else:
- if rv == value:
- return 1
- nlen = len(value)
- if string.find(rv, value, 0, nlen) != 0:
- return 0
- if rv[nlen] == ".":
- return 1
-
- def matchValue(self, key, record):
- vl = self.dict [key]
- if type(vl) != types.ListType:
- rv = self.matchOne(key, vl, record)
- else:
- for v in vl:
- rv = self.matchOne(key, v, record)
- if rv:
- break
- return rv
-
- def filter(self, record):
- rv = 1
- for k in self.dict.keys():
- if self.matchValue(k, record):
- rv = 0
- break
- return rv
-
-def doLog(logger, n):
- logger.debug("Debug %d" % n)
- logger.info("Info %d" % n)
- logger.warning("Warning %d" % n)
- logger.error("Error %d" % n)
- logger.critical("Critical %d" % n)
-
-def test():
- fmt = logging.Formatter("%(name)-10s %(levelname)-9s %(message)s")
- hand = logging.StreamHandler()
- hand.setFormatter(fmt)
- root = logging.getLogger("")
- root.setLevel(logging.DEBUG)
- root.addHandler(hand)
- loggers = ['A',
- 'A.B',
- 'A.BB',
- 'A.C',
- 'AA.B',
- 'A.B.C',
- 'A.B.C.D',
- 'A.B.C.D.E',
- 'Z.A.B',
- ]
- filt = MatchFilter(name = ['A.C', 'A.B.C'], #reject these loggers and their children
- levelno = [logging.WARNING, logging.CRITICAL], #reject these levels,
- msg = 'bug 2' #reject if this in message
- )
- hand.addFilter(filt)
- for log in loggers:
- doLog(logging.getLogger(log), loggers.index(log))
-
-if __name__ == "__main__":
- test()
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test19.py b/tools/python/logging/logging-0.4.9.2/test/log_test19.py
deleted file mode 100755
index cdfa1a0..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test19.py
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""Test harness for the logging module. A basic test of parents.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-
-import logging
-
-def main():
- logging.basicConfig()
- root = logging.getLogger("")
- ab = logging.getLogger("a.b")
- abc = logging.getLogger("a.b.c")
- root.setLevel(logging.ERROR)
- ab.setLevel(logging.INFO)
- abc.info("Info")
- abc.warning("Warning")
- abc.error("Error")
- print "abc = %s" % abc
- print "abc.parent = %s" % abc.parent
- print "ab = %s" % ab
- print "ab.parent = %s" % ab.parent
- print "root = %s" % root
-
-if __name__ == "__main__":
- import sys
- print sys.argv[0]
- args = sys.argv[1:]
- if "-profile" in args:
- import profile, pstats
- args.remove("-profile")
- statf = "log_test19.pro"
- profile.run("main()", statf)
- stats = pstats.Stats(statf)
- stats.strip_dirs().sort_stats('time').print_stats()
- else:
- main()
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test2.py b/tools/python/logging/logging-0.4.9.2/test/log_test2.py
deleted file mode 100755
index 2ba0ee1..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test2.py
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""
-A test harness for the logging module. Tests logger levels and basic Formatter, and logging to
-sockets.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-
-import logging, logging.handlers, socket
-
-msgcount = 0
-
-def nextmessage():
- global msgcount
- rv = "Message %d" % msgcount
- msgcount = msgcount + 1
- return rv
-
-def main():
- logging.basicConfig()
- logging.getLogger("").setLevel(logging.DEBUG)
- hdlr = logging.handlers.SocketHandler('localhost', logging.handlers.DEFAULT_TCP_LOGGING_PORT)
- if __name__ == "__main__":
- hdlr.setFormatter(logging.Formatter("%(asctime)s %(name)-19s %(levelname)-5s - %(message)s"))
- logging.getLogger("").addHandler(hdlr)
- ERR = logging.getLogger("ERR")
- ERR.setLevel(logging.ERROR)
- INF = logging.getLogger("INF")
- INF.setLevel(logging.INFO)
- INF_ERR = logging.getLogger("INF.ERR")
- INF_ERR.setLevel(logging.ERROR)
- DEB = logging.getLogger("DEB")
- DEB.setLevel(logging.DEBUG)
-
- INF_UNDEF = logging.getLogger("INF.UNDEF")
- INF_ERR_UNDEF = logging.getLogger("INF.ERR.UNDEF")
- UNDEF = logging.getLogger("UNDEF")
-
- GRANDCHILD = logging.getLogger("INF.BADPARENT.UNDEF")
- CHILD = logging.getLogger("INF.BADPARENT")
-
- #These should log
- ERR.log(logging.CRITICAL, nextmessage())
- ERR.error(nextmessage())
-
- INF.log(logging.CRITICAL, nextmessage())
- INF.error(nextmessage())
- INF.warning(nextmessage())
- INF.info(nextmessage())
-
- INF_UNDEF.log(logging.CRITICAL, nextmessage())
- INF_UNDEF.error(nextmessage())
- INF_UNDEF.warning(nextmessage())
- INF_UNDEF.info(nextmessage())
-
- INF_ERR.log(logging.CRITICAL, nextmessage())
- INF_ERR.error(nextmessage())
-
- INF_ERR_UNDEF.log(logging.CRITICAL, nextmessage())
- INF_ERR_UNDEF.error(nextmessage())
-
- DEB.log(logging.CRITICAL, nextmessage())
- DEB.error(nextmessage())
- DEB.warning(nextmessage())
- DEB.info(nextmessage())
- DEB.debug(nextmessage())
-
- UNDEF.log(logging.CRITICAL, nextmessage())
- UNDEF.error(nextmessage())
- UNDEF.warning(nextmessage())
- UNDEF.info(nextmessage())
-
- GRANDCHILD.log(logging.CRITICAL, nextmessage())
- CHILD.log(logging.CRITICAL, nextmessage())
-
- #These should not log
- ERR.warning(nextmessage())
- ERR.info(nextmessage())
- ERR.debug(nextmessage())
-
- INF.debug(nextmessage())
- INF_UNDEF.debug(nextmessage())
-
- INF_ERR.warning(nextmessage())
- INF_ERR.info(nextmessage())
- INF_ERR.debug(nextmessage())
- INF_ERR_UNDEF.warning(nextmessage())
- INF_ERR_UNDEF.info(nextmessage())
- INF_ERR_UNDEF.debug(nextmessage())
-
- INF.info("Messages should bear numbers 0 through 24.")
- hdlr.close()
- logging.getLogger("").removeHandler(hdlr)
-
-if __name__ == "__main__":
- try:
- main()
- except socket.error:
- print "\nA socket error occurred. Ensure that logrecv.py is running to receive logging requests from this script."
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test20.py b/tools/python/logging/logging-0.4.9.2/test/log_test20.py
deleted file mode 100755
index d3701f3..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test20.py
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""Test harness for the logging module. Demonstrates the use of custom class
-instances for messages and filtering based on classes.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-
-import logging
-
-class MyClass:
- def __init__(self, arg1, arg2):
- self.arg1 = arg1
- self.arg2 = arg2
-
- def __str__(self):
- return "%s, %s" % (self.arg1, self.arg2)
-
-class MyChildClass(MyClass):
- pass
-
-class ClassFilter(logging.Filter):
- def __init__(self, klass):
- self.klass = klass
-
- def filter(self, record):
- return isinstance(record.msg, self.klass)
-
-class MyClassFilter(ClassFilter):
- def __init__(self, arg):
- ClassFilter.__init__(self, MyClass)
- self.arg = arg
-
- def filter(self, record):
- return ClassFilter.filter(self, record) and (record.msg.arg2 == self.arg)
-
-def main():
- handler = logging.StreamHandler()
- root = logging.getLogger("")
- root.setLevel(logging.DEBUG)
- root.addHandler(handler)
- root.addFilter(MyClassFilter("world"))
- #Not logged, as it's not a MyClass instance
- root.info("%s, %s", "Hello", "world")
- #Logged, as it's an appropriate instance which matches the filter criteria
- root.info(MyClass("Hello", "world"))
- #Not logged, as it's an appropriate class but doesn't match the filter criteria
- root.info(MyClass("Hello", "world!"))
- #Logged, as it's an appropriate instance which matches the filter criteria
- root.info(MyClass("Goodbye", "world"))
- #Logged, as it's an appropriate class which matches the filter criteria
- root.info(MyChildClass("Hello again", "world"))
-
-if __name__ == "__main__":
- import sys
- args = sys.argv[1:]
- if "-profile" in args:
- import profile, pstats
- args.remove("-profile")
- statf = "log_test20.pro"
- profile.run("main()", statf)
- stats = pstats.Stats(statf)
- stats.strip_dirs().sort_stats('time').print_stats()
- else:
- main()
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test21.py b/tools/python/logging/logging-0.4.9.2/test/log_test21.py
deleted file mode 100755
index 1626beb..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test21.py
+++ /dev/null
@@ -1,141 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""Test harness for the logging module. Demonstrates the use of a wildcard
-name-space filter with and without custom message classes.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-
-import logging, re, string, types
-
-class TaggedEvent:
- def __init__(self, tag, msg):
- self.tag = tag
- self.msg = msg
-
- def __str__(self):
- return "%s: %s" % (self.tag, self.msg)
-
-class WildcardFilter(logging.Filter):
- def __init__(self, wildcards):
- self.setWildcards(wildcards)
-
- def setWildcard(self, wildcard):
- arr = string.split(wildcard, ".")
- for i in xrange(len(arr)):
- s = arr[i]
- if s == "*":
- arr[i] = r'[\w.]*'
- elif string.find(s, "*") > 0:
- arr[i] = string.replace(s, "*", r'[\w]*')
- s = "^%s$" % string.join(arr, r'\.')
- self.patterns.append(re.compile(s))
-
- def setWildcards(self, wildcards):
- if type(wildcards) != types.ListType:
- wildcards = [wildcards]
- self.patterns = []
- for wildcard in wildcards:
- self.setWildcard(wildcard)
-
- def filter(self, record):
- rv = 0
- for pat in self.patterns:
- m = pat.match(record.name)
- if m is not None:
- rv = 1
- break
- return rv
-
-class TagFilter(WildcardFilter):
- def filter(self, record):
- rv = 0
- if isinstance(record.msg, TaggedEvent):
- tag = record.msg.tag
- else:
- tag = record.name
- for pat in self.patterns:
- m = pat.match(tag)
- if m is not None:
- rv = 1
- break
- return rv
-
-def main():
- handler = logging.StreamHandler()
- root = logging.getLogger("")
- root.setLevel(logging.DEBUG)
- ab = logging.getLogger("a.b")
- abc = logging.getLogger("a.b.c")
-
- root.addHandler(handler)
- filter = WildcardFilter("*.b")
- handler.addFilter(filter)
-
- ab.info("#1 from a.b") #logged
- abc.info("#1 from a.b.c") #not logged
- filter.setWildcards("*.b.c")
- ab.info("#2 from a.b") #not logged
- abc.info("#2 from a.b.c") #logged
- filter.setWildcards("*.b*")
- ab.info("#3 from a.b") #logged
- abc.info("#3 from a.b.c") #not logged
- filter.setWildcards("*")
- ab.info("#4 from a.b") #logged
- abc.info("#4 from a.b.c") #logged
- filter.setWildcards("a*")
- ab.info("#5 from a.b") #not logged
- abc.info("#5 from a.b.c") #not logged
- filter.setWildcards("a.*")
- ab.info("#6 from a.b") #logged
- abc.info("#6 from a.b.c") #logged
- filter.setWildcards("*.b.*")
- ab.info("#7 from a.b") #not logged
- abc.info("#7 from a.b.c") #logged
- filter.setWildcards(["*.b", "*.b.*"])
- ab.info("#8 from a.b") #logged
- abc.info("#8 from a.b.c") #logged
- filter.setWildcards(["a.*.c"])
- ab.info("#9 from a.b") #not logged
- abc.info("#9 from a.b.c") #logged
-
- #Now test filtering with a tagged class
- handler.removeFilter(filter)
- tagfilter = TagFilter(["*.b", "*.b.*"])
- root.addFilter(tagfilter)
- root.info(TaggedEvent("a.b", "#10")) #logged
- root.info(TaggedEvent("a.c", "#10")) #not logged
- root.info(TaggedEvent("a.b.c", "#10")) #logged
- root.info(TaggedEvent("a.b.d", "#10")) #logged
-
-if __name__ == "__main__":
- import sys
- args = sys.argv[1:]
- if "-profile" in args:
- import profile, pstats
- args.remove("-profile")
- statf = "log_test21.pro"
- profile.run("main()", statf)
- stats = pstats.Stats(statf)
- stats.strip_dirs().sort_stats('time').print_stats()
- else:
- main()
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test22.py b/tools/python/logging/logging-0.4.9.2/test/log_test22.py
deleted file mode 100755
index 427ae40..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test22.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""Test harness for the logging module. Demonstrates the use of different
-converters for time(secs) -> time(tuple).
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-
-import logging, time
-
-def main():
- handler = logging.StreamHandler()
- f1 = logging.Formatter("%(asctime)s %(message)s", "%m/%d %H:%M:%S")
- f2 = logging.Formatter("%(asctime)s %(message)s", "%m/%d %H:%M:%S")
- f2.converter = time.gmtime
- handler.setFormatter(f1)
- root = logging.getLogger("")
- root.setLevel(logging.DEBUG)
- root.addHandler(handler)
- root.info("Something happened! [should be in local time]")
- handler.setFormatter(f2)
- root.info("Something else happened! [should be in GMT]")
- handler.setFormatter(f1)
- root.info("Something happened again! [should be in local time]")
- logging.Formatter.converter = time.gmtime
- root.info("Something else happened again! [should be in GMT]")
- logging.Formatter.converter = time.localtime
- root.info("Something else happened yet again! [should be in local time]")
-
-if __name__ == "__main__":
- main()
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test3.ini b/tools/python/logging/logging-0.4.9.2/test/log_test3.ini
deleted file mode 100644
index 15b7518..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test3.ini
+++ /dev/null
@@ -1,95 +0,0 @@
-[loggers]
-keys=root,area1,area11,area111,area1111,area11111,area111111
-
-[handlers]
-keys=console,file,socket,datagram,syslog,NT,SMTP
-
-[formatters]
-keys=short,medium,long
-
-[logger_root]
-handlers=console
-level=DEBUG
-
-[logger_area1]
-level=DEBUG
-qualname=log02
-handlers=file
-
-[logger_area11]
-level=INFO
-qualname=log02.log03
-handlers=socket
-
-[logger_area111]
-level=WARN
-propagate=0
-qualname=log02.log03.log04
-handlers=datagram
-
-[logger_area1111]
-level=ERROR
-qualname=log02.log03.log04.log05
-handlers=syslog
-
-[logger_area11111]
-level=CRITICAL
-qualname=log02.log03.log04.log05.log06
-handlers=NT
-
-[logger_area111111]
-level=WARN
-qualname=log02.log03.log04.log05.log06.log07
-handlers=SMTP
-
-[handler_console]
-class=StreamHandler
-formatter=medium
-stream=sys.stdout
-args=(sys.stdout,)
-
-[handler_file]
-class=FileHandler
-level=DEBUG
-formatter=long
-args=('python.log', 'w')
-
-[handler_socket]
-class=handlers.SocketHandler
-level=INFO
-formatter=medium
-args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)
-
-[handler_datagram]
-class=handlers.DatagramHandler
-level=WARN
-formatter=medium
-args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)
-
-[handler_syslog]
-class=handlers.SysLogHandler
-level=ERROR
-formatter=short
-args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)
-
-[handler_NT]
-class=handlers.NTEventLogHandler
-level=CRITICAL
-formatter=medium
-args=('Python Application', '', 'Application')
-
-[handler_SMTP]
-class=handlers.SMTPHandler
-level=WARN
-formatter=long
-args=('localhost', 'from at abc', ['user1 at abc', 'user2 at xyz'], 'Logger Subject')
-
-[formatter_short]
-format=%(message)s
-
-[formatter_long]
-format=%(asctime)s %(pathname)s(%(lineno)d): %(levelname)s %(message)s
-
-[formatter_medium]
-format=%(asctime)s %(levelname)s %(message)s
-datefmt=%m-%d-%Y
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test3.py b/tools/python/logging/logging-0.4.9.2/test/log_test3.py
deleted file mode 100755
index 09ba9ac..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test3.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""
-A test harness for the logging module. Tests new fileConfig (not yet a complete test).
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-import logging, logging.config
-
-def doLog(logger):
- logger.debug("Debug")
- logger.info("Info")
- logger.warning("Warning")
- logger.error("Error")
- logger.critical("Critical")
-
-def main():
- logging.config.fileConfig("log_test3.ini")
- logger = logging.getLogger(None)
- print "---------------------------------------------------"
- print "-- Logging to root; messages appear on console only"
- print "---------------------------------------------------"
- doLog(logger)
- print "----------------------------------------------------------------------"
- print "-- Logging to log02; messages appear on console and in file python.log"
- print "----------------------------------------------------------------------"
- logger = logging.getLogger("log02")
- doLog(logger)
- print "--------------------------------------------------------------------------"
- print "-- Logging to log02.log03; messages appear on console, in file python.log,"
- print "-- and at logrecv.py tcp (if running. <= DEBUG messages will not appear)."
- print "--------------------------------------------------------------------------"
- logger = logging.getLogger("log02.log03")
- doLog(logger)
- print "-----------------------------------------------------------------------"
- print "-- Logging to log02.log03.log04; messages appear only at logrecv.py udp"
- print "-- (if running. <= INFO messages will not appear)."
- print "-----------------------------------------------------------------------"
- logger = logging.getLogger("log02.log03.log04")
- doLog(logger)
- print "--------------------------------------------------------------------"
- print "-- Logging to log02.log03.log04.log05.log06; messages appear at"
- print "-- logrecv.py udp (if running. < CRITICAL messages will not appear)."
- print "--------------------------------------------------------------------"
- logger = logging.getLogger("log02.log03.log04.log05.log06")
- doLog(logger)
- print "-- All done."
- logging.shutdown()
-
-if __name__ == "__main__":
- main()
\ No newline at end of file
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test4.py b/tools/python/logging/logging-0.4.9.2/test/log_test4.py
deleted file mode 100755
index 5b59777..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test4.py
+++ /dev/null
@@ -1,168 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""
-A test harness for the logging module. Tests arbitrary logging levels, filtering, and
-use of strftime formatting.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-
-import logging
-import locale, sys
-
-locale.setlocale(locale.LC_ALL, '')
-
-def message(s):
- sys.stderr.write("%s\n" % s)
-
-#
-# First, we define our levels. There can be as many as you want - the only limitations are that
-# they should be integers, the lowest should be > 0 and larger values mean less information being
-# logged. If you need specific level values which do not fit into these limitations, you can use
-# a mapping dictionary to convert between your application levels and the logging system.
-#
-SILENT = 10
-TACITURN = 9
-TERSE = 8
-EFFUSIVE = 7
-SOCIABLE = 6
-VERBOSE = 5
-TALKATIVE = 4
-GARRULOUS = 3
-CHATTERBOX = 2
-BORING = 1
-
-LEVEL_RANGE = range(BORING, SILENT + 1)
-
-#
-# Next, we define names for our levels. You don't need to do this - in which case the system will
-# use "Level n" to denote the text for the level.
-#
-my_logging_levels = {
- SILENT : 'Silent',
- TACITURN : 'Taciturn',
- TERSE : 'Terse',
- EFFUSIVE : 'Effusive',
- SOCIABLE : 'Sociable',
- VERBOSE : 'Verbose',
- TALKATIVE : 'Talkative',
- GARRULOUS : 'Garrulous',
- CHATTERBOX: 'Chatterbox',
- BORING : 'Boring',
-}
-
-#
-# Now, tell the logging system to associate names with our levels.
-#
-for lvl in my_logging_levels.keys():
- logging.addLevelName(lvl, my_logging_levels[lvl])
-
-#
-# Now, define a test function which logs an event at each of our levels.
-#
-def doLog(log):
- for lvl in LEVEL_RANGE:
- log.log(lvl, "This should only be seen at the '%s' logging level (or lower)", logging.getLevelName(lvl))
-
-#
-# Get the root logger and add a console hander to it, when run as a script.
-#
-log = logging.getLogger("")
-
-if __name__ == "__main__":
- hdlr = logging.StreamHandler()
- hdlr.setFormatter(logging.Formatter("%(asctime)s %(message)s", "%X")) #date format is as per the locale
- log.addHandler(hdlr)
-else:
- hdlr = log.handlers[0]
-#
-# Set the logging level to each different value and call the utility function to log events.
-# In the output, you should see that each time round the loop, the logging events actually output
-# decreases.
-#
-for lvl in LEVEL_RANGE:
- message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl))
- log.setLevel(lvl)
- doLog(log)
-#
-# Now, we demonstrate level filtering at the handler level. Tell the handler defined above
-# to filter at level 'SOCIABLE', and repeat the above loop. Compare the output from the two runs.
-#
-hdlr.setLevel(SOCIABLE)
-message("-- Filtering at handler level to SOCIABLE --")
-for lvl in LEVEL_RANGE:
- message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl))
- log.setLevel(lvl)
- doLog(log)
-
-hdlr.setLevel(0) #turn off level filtering at the handler
-
-#
-# Now, let's demonstrate filtering. Suppose for some perverse reason we only want to print out
-# all except GARRULOUS messages. Let's create a filter for this purpose...
-#
-class SpecificLevelFilter(logging.Filter):
- def __init__(self, lvl):
- self.level = lvl
-
- def filter(self, record):
- return self.level != record.levelno
-
-class GarrulousFilter(SpecificLevelFilter):
- def __init__(self):
- SpecificLevelFilter.__init__(self, GARRULOUS)
-
-garr = GarrulousFilter()
-hdlr.addFilter(garr)
-message("-- Filtering using GARRULOUS filter --")
-for lvl in LEVEL_RANGE:
- message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl))
- log.setLevel(lvl)
- doLog(log)
-#
-# Now, let's demonstrate filtering at the logger. This time, use a filter which excludes SOCIABLE
-# and TACITURN messages. Note that GARRULOUS events are still excluded.
-#
-class VerySpecificFilter(logging.Filter):
- def filter(self, record):
- return record.levelno not in [SOCIABLE, TACITURN]
-
-spec = VerySpecificFilter()
-log.addFilter(spec)
-message("-- Filtering using specific filter for SOCIABLE, TACITURN --")
-for lvl in LEVEL_RANGE:
- message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl))
- log.setLevel(lvl)
- doLog(log)
-
-log.removeFilter(spec)
-hdlr.removeFilter(garr)
-#Undo the one level which clashes...for regression tests
-logging.addLevelName(logging.DEBUG, "DEBUG")
-
-#
-# Er...that's it for now
-#
-if __name__ == "__main__":
- print "All done."
- logging.shutdown()
-
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test5.py b/tools/python/logging/logging-0.4.9.2/test/log_test5.py
deleted file mode 100755
index fd8d246..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test5.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""
-A test harness for the logging module. Tests SMTPHandler.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-import logging, logging.handlers
-
-MAILHOST = 'beta'
-FROM = 'log_test5 at yourdomain.com'
-TO = ['arkadi_renko']
-SUBJECT = 'Test Logging email from Python logging module (non-buffering)'
-
-def main():
- log = logging.getLogger("")
- log.setLevel(logging.DEBUG)
- hdlr = logging.handlers.SMTPHandler(MAILHOST, FROM, TO, SUBJECT)
- hdlr.setFormatter(logging.Formatter("%(asctime)s %(levelname)-5s %(message)s"))
- log.addHandler(hdlr)
- log.info("Test email contents")
- log.removeHandler(hdlr)
-
-if __name__ == "__main__":
- main()
\ No newline at end of file
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test6.py b/tools/python/logging/logging-0.4.9.2/test/log_test6.py
deleted file mode 100755
index 53ad805..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test6.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""
-A test harness for the logging module. Tests NTEventLogHandler.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-import logging, logging.handlers
-
-def main():
- ntl = logging.handlers.NTEventLogHandler("Python Logging Test")
- logger = logging.getLogger("")
- logger.setLevel(logging.DEBUG)
- logger.addHandler(ntl)
- logger.debug("This is a '%s' message", "Debug")
- logger.info("This is a '%s' message", "Info")
- logger.warning("This is a '%s' message", "Warning")
- logger.error("This is a '%s' message", "Error")
- logger.critical("This is a '%s' message", "Critical")
- try:
- x = 4 / 0
- except:
- logger.info("This is an %s (or should that be %s?)", "informational exception", "exceptional information", exc_info=1)
- logger.exception("This is the same stuff, via a %s", "exception() call")
- logger.removeHandler(ntl)
-
-if __name__ == "__main__":
- main()
\ No newline at end of file
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test7.py b/tools/python/logging/logging-0.4.9.2/test/log_test7.py
deleted file mode 100755
index 82845ba..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test7.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""
-A test harness for the logging module. Tests MemoryHandler.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-import sys, logging, logging.handlers
-
-def message(s):
- sys.stderr.write("%s\n" % s)
-
-sh = logging.StreamHandler()
-mh = logging.handlers.MemoryHandler(10,logging.WARNING, sh)
-logger = logging.getLogger("")
-logger.setLevel(logging.DEBUG)
-logger.addHandler(mh)
-message("-- logging at DEBUG, nothing should be seen yet --")
-logger.debug("Debug message")
-message("-- logging at INFO, nothing should be seen yet --")
-logger.info("Info message")
-message("-- logging at WARNING, 3 messages should be seen --")
-logger.warning("Warning message")
-for i in xrange(102):
- message("-- logging %d at level INFO, messages should be seen every 10 events --" % i)
- logger.info("Info index = %d", i)
-sh.close()
-mh.close()
-logger.removeHandler(mh)
\ No newline at end of file
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test8.py b/tools/python/logging/logging-0.4.9.2/test/log_test8.py
deleted file mode 100755
index 774b0dd..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test8.py
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""
-A test harness for the logging module. Tests FileHandler rollover.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-import logging, logging.handlers
-import locale
-
-locale.setlocale(locale.LC_ALL, '')
-
-sequence = 0
-
-def doLog(logger):
- global sequence
- sequence = sequence + 1
- logger.debug("%6d This message should be at level %d - %s", sequence,\
- logging.DEBUG, logging.getLevelName(logging.DEBUG))
- sequence = sequence + 1
- logger.info("%6d This message should be at level %d - %s", sequence,
- logging.INFO, logging.getLevelName(logging.INFO))
- sequence = sequence + 1
- logger.warning("%6d This message should be at level %d - %s", sequence,\
- logging.WARNING, logging.getLevelName(logging.WARNING))
- sequence = sequence + 1
- logger.error("%6d This message should be at level %d - %s", sequence,\
- logging.ERROR, logging.getLevelName(logging.ERROR))
- sequence = sequence + 1
- logger.critical("%6d This message should be at level %d - %s", sequence,\
- logging.CRITICAL, logging.getLevelName(logging.CRITICAL))
-
-def main():
- logger = logging.getLogger("") #root logger
- logger.setLevel(logging.DEBUG)
- if __name__ == "__main__":
- logname = "rollover.log"
- else:
- logname = "log_test_rollover.log"
- hdlr = logging.handlers.RotatingFileHandler(logname, "a", 5000, 3)
- if __name__ == "__main__":
- fmt = logging.Formatter("%(asctime)s %(levelname)-5s %(message)s", "%x %X")
- hdlr.setFormatter(fmt)
- logger.addHandler(hdlr)
- for i in xrange(100):
- doLog(logger)
- logger.removeHandler(hdlr)
-
-if __name__ == "__main__":
- main()
\ No newline at end of file
diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test9.py b/tools/python/logging/logging-0.4.9.2/test/log_test9.py
deleted file mode 100755
index 75653af..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/log_test9.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-"""
-A test harness for the logging module. Tests BufferingHandler, BufferingFormatter.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-import logging, logging.handlers
-
-class XMLFormatter(logging.BufferingFormatter):
- """
- A formatter which formats a set of records using XML, using an example DTD called "logging.dtd".
- """
- def __init__(self):
- fmtstr = """
- <event name="%(name)s" level="%(levelno)d" filename="%(filename)s" lineno="%(lineno)d">
- <message>%(message)s</message>
- </event>"""
- logging.BufferingFormatter.__init__(self, logging.Formatter(fmtstr))
-
-# def formatHeader(self, records):
-# return """
-#<?xml version="1.0" ?><!DOCTYPE eventSet SYSTEM "logging.dtd">
-#<eventSet xmlns="http://www.red-dove.com/logging">"""
-#
-# def formatFooter(self, records):
-# return "</eventSet>"
-
-class XMLHandler(logging.handlers.BufferingHandler):
- def __init__(self, capacity):
- logging.handlers.BufferingHandler.__init__(self, capacity)
- self.setFormatter(XMLFormatter())
-
- def flush(self):
- if len(self.buffer) > 0:
- file = open("events.xml","w")
- file.write(self.formatter.format(self.buffer))
- file.close()
- self.buffer = []
-
-def main():
- logger = logging.getLogger("")
- logger.setLevel(logging.DEBUG)
- xh = XMLHandler(10)
- logger.addHandler(xh)
- for i in xrange(100):
- logger.info("Info index = %d", i)
- xh.close()
- logger.removeHandler(xh)
-
-if __name__ == "__main__":
- main()
diff --git a/tools/python/logging/logging-0.4.9.2/test/logconf.ini b/tools/python/logging/logging-0.4.9.2/test/logconf.ini
deleted file mode 100644
index b74e10c..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/logconf.ini
+++ /dev/null
@@ -1,180 +0,0 @@
-[loggers]
-keys=root,log02,log03,log04,log05,log06,log07
-
-[handlers]
-keys=hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09
-
-[formatters]
-keys=form01,form02,form03,form04,form05,form06,form07,form08,form09
-
-[logger_root]
-level=NOTSET
-propagate=1
-channel=
-parent=
-qualname=(root)
-handlers=hand01
-
-[logger_log02]
-level=DEBUG
-propagate=1
-channel=log02
-parent=(root)
-qualname=log02
-handlers=hand02
-
-[logger_log03]
-level=INFO
-propagate=1
-channel=log03
-parent=log02
-qualname=log02.log03
-handlers=hand03
-
-[logger_log04]
-level=WARN
-propagate=0
-channel=log04
-parent=log03
-qualname=log02.log03.log04
-handlers=hand04
-
-[logger_log05]
-level=ERROR
-propagate=1
-channel=log05
-parent=log04
-qualname=log02.log03.log04.log05
-handlers=hand05
-
-[logger_log06]
-level=CRITICAL
-propagate=1
-channel=log06
-parent=log05
-qualname=log02.log03.log04.log05.log06
-handlers=hand06
-
-[logger_log07]
-level=WARN
-propagate=1
-channel=log07
-parent=log06
-qualname=log02.log03.log04.log05.log06.log07
-handlers=hand07
-
-[handler_hand01]
-class=StreamHandler
-level=NOTSET
-formatter=form01
-stream=sys.stdout
-args=(sys.stdout,)
-
-[handler_hand02]
-class=FileHandler
-level=DEBUG
-formatter=form02
-filename=python.log
-mode=w
-args=('python.log', 'w')
-
-[handler_hand03]
-class=handlers.SocketHandler
-level=INFO
-formatter=form03
-host=localhost
-port=handlers.DEFAULT_TCP_LOGGING_PORT
-args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)
-
-[handler_hand04]
-class=handlers.DatagramHandler
-level=WARN
-formatter=form04
-host=localhost
-port=handlers.DEFAULT_UDP_LOGGING_PORT
-args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)
-
-[handler_hand05]
-class=handlers.SysLogHandler
-level=ERROR
-formatter=form05
-host=localhost
-port=handlers.SYSLOG_UDP_PORT
-facility=LOG_USER
-args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)
-
-[handler_hand06]
-class=handlers.NTEventLogHandler
-level=CRITICAL
-formatter=form06
-appname=Python Application
-dllname=
-logtype=Application
-args=('Python Application', '', 'Application')
-
-[handler_hand07]
-class=handlers.SMTPHandler
-level=WARN
-formatter=form07
-host=localhost
-port=25
-from=from at abc
-to=user1 at abc,user2 at xyz
-subject=Logger Subject
-args=('localhost', 'from at abc', ['user1 at abc', 'user2 at xyz'], 'Logger Subject')
-
-[handler_hand08]
-class=handlers.MemoryHandler
-level=NOTSET
-formatter=form08
-capacity=10
-flushlevel=ERROR
-target=
-args=(10, ERROR)
-
-[handler_hand09]
-class=handlers.HTTPHandler
-level=NOTSET
-formatter=form09
-host=localhost
-port=9022
-url=/log
-method=GET
-args=('localhost:9022', '/log', 'GET')
-
-[formatter_form01]
-format=F1 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form02]
-format=F2 %(asctime)s %(pathname)s(%(lineno)d): %(levelname)s %(message)s
-datefmt=
-
-[formatter_form03]
-format=F3 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form04]
-format=%(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form05]
-format=F5 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form06]
-format=F6 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form07]
-format=F7 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form08]
-format=F8 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form09]
-format=F9 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
diff --git a/tools/python/logging/logging-0.4.9.2/test/logconf.py b/tools/python/logging/logging-0.4.9.2/test/logconf.py
deleted file mode 100755
index f54792f..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/logconf.py
+++ /dev/null
@@ -1,1738 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# This file is part of the Python logging distribution. See
-# http://www.red-dove.com/python_logging.html
-#
-
-"""
-A simple-minded GUI configurator for the logging module, using Tkinter.
-
-Should work under Python versions >= 1.5.2.
-
-Copyright (C) 2002 Vinay Sajip. All Rights Reserved.
-
-Configuration files are read/written using ConfigParser.
-"""
-"""
-
-(C) 2002 Vinay Sajip. All rights reserved.
-"""
-from Tkinter import *
-from tkFileDialog import *
-from tkMessageBox import *
-
-import os, sys, string, types
-import ConfigParser
-
-active = None
-
-__version__ = "0.4.1"
-
-DEFAULT_FILENAME = "logconf.ini"
-
-LOGGING_LEVELS = (
- ("NOTSET", "NOTSET"),
- ("DEBUG", "DEBUG"),
- ("INFO", "INFO"),
- ("WARNING", "WARNING"),
- ("ERROR", "ERROR"),
- ("CRITICAL", "CRITICAL")
-)
-
-HANDLER_TYPES = (
- ("StreamHandlerProxy", "StreamHandler"),
- ("FileHandlerProxy", "FileHandler"),
- ("RotatingFileHandlerProxy", "RotatingFileHandler"),
- ("SocketHandlerProxy", "SocketHandler"),
- ("DatagramHandlerProxy", "DatagramHandler"),
- ("SysLogHandlerProxy", "SysLogHandler"),
- ("NTEventLogHandlerProxy", "NTEventLogHandler"),
- ("SMTPHandlerProxy", "SMTPHandler"),
- ("MemoryHandlerProxy", "MemoryHandler"),
- ("HTTPHandlerProxy", "HTTPHandler"),
-# ("SOAPHandlerProxy", "SOAPHandler"),
-)
-
-OUTPUT_STREAMS = (
- ("sys.stdout", "sys.stdout"),
- ("sys.stderr", "sys.stderr")
-)
-
-FILE_MODES = (
- ("a", "a"),
- ("w", "w")
- )
-
-HTTP_METHODS = (
- ("GET", "GET"),
- ("POST", "POST")
-)
-
-SYSLOG_FACILITIES = (
- ("LOG_AUTH", "auth"),
- ("LOG_AUTHPRIV", "authpriv"),
- ("LOG_CRON", "cron"),
- ("LOG_DAEMON", "daemon"),
- ("LOG_KERN", "kern"),
- ("LOG_LPR", "lpr"),
- ("LOG_MAIL", "mail"),
- ("LOG_NEWS", "news"),
- ("LOG_AUTH", "security"),
- ("LOG_SYSLOG", "syslog"),
- ("LOG_USER", "user"),
- ("LOG_UUCP", "uucp"),
- ("LOG_LOCAL0", "local0"),
- ("LOG_LOCAL1", "local1"),
- ("LOG_LOCAL2", "local2"),
- ("LOG_LOCAL3", "local3"),
- ("LOG_LOCAL4", "local4"),
- ("LOG_LOCAL5", "local5"),
- ("LOG_LOCAL6", "local6"),
- ("LOG_LOCAL7", "local7"),
-)
-
-LOG_TYPES = (
- ("Application", "Application"),
- ("System", "System"),
- ("Security", "Security")
-)
-
-BOOLEAN_VALUES = (
- ("0", "False"),
- ("1", "True")
-)
-
-class Property:
- def __init__(self, name, caption, value=None, choices=None):
- self.name = name
- self.caption = caption
- self.value = value
- self.choices = choices
-
- def getChoices(self):
- return self.choices
-
- def isvalid(self, s):
- return 0
-
- def getCaption(self):
- return self.caption
-
- def getValue(self):
- return self.value
-
- def getChoiceText(self, val):
- rv = ""
- choices = self.getChoices()
- if choices:
- for choice in choices:
- if choice[0] == val:
- rv = choice[1]
- break
- return rv
-
- def setValue(self, val):
- self.value = val
-
- def getValueText(self):
- if type(self.value) in [types.ListType, types.TupleType]:
- v = list(self.value)
- else:
- v = [self.value]
- choices = self.getChoices()
- if choices:
- v = map(self.getChoiceText, v)
- return string.join(v, ',')
-
-class PropertyHolder:
- def __init__(self, dict):
- self.dict = dict
- self.propnames = []
- self.onPropListChanged = None
-
- def getPropNames(self):
- """
- Return the property names in the order in which they are to
- be listed.
- """
- return self.propnames
-
- def getProp(self, name):
- return self.dict[name]
-
- def isReadonly(self, name):
- return 0
-
- #convenience methods
- def getPropValue(self, name):
- return self.dict[name].value
-
- def setPropValue(self, name, value):
- self.dict[name].setValue(value)
-
-LINE_COLOUR = '#999999'
-
-class ScrollingList(Frame):
- def __init__(self, parent, *args, **kwargs):
- Frame.__init__(self, parent)
- self.parent = parent
- self.listener = self.parent
- self.sb = Scrollbar(self, orient=VERTICAL)
- kwargs["yscrollcommand"] = self.sb.set
- self.list = apply(Listbox, (self,) + args, kwargs)
- self.sb.config(command=self.list.yview)
- self.sb.pack(side=RIGHT, fill=Y)
- self.list.pack(side=LEFT, fill=BOTH,expand=1)
- self.list.bind('<ButtonRelease-1>', self.onListChange)
- self.choices = None
-
- def setContents(self, choices, value):
- self.choices = choices
- self.value = value
- self.list.delete(0, END)
- if type(value) == types.ListType:
- sm = EXTENDED
- else:
- sm = BROWSE
- self.list.configure(selectmode=sm)
- i = 0
- for choice in choices:
- self.list.insert(END, choice[1])
- if sm == EXTENDED:
- if choice[0] in value:
- self.list.select_set(i)
- else:
- if choice[0] == value:
- self.list.select_set(i)
- i = i + 1
-
- def getValue(self):
- if type(self.value) == types.ListType:
- multi = 1
- rv = []
- else:
- multi = 0
- for i in xrange(len(self.choices)):
- if self.list.select_includes(i):
- if not multi:
- rv = self.choices[i][0]
- break
- else:
- rv.append(self.choices[i][0])
- return rv
-
- def onListChange(self, event):
- self.value = self.getValue()
- self.listener.onListChange(self.value)
-
-class PropertyHeader(Canvas):
- def __init__(self, parent, *args, **kwargs):
- self.namewidth = 120
- if kwargs.has_key("namewidth"):
- self.namewidth = kwargs["namewidth"]
- del kwargs["namewidth"]
- self.rowheight = 16
- if kwargs.has_key("rowheight"):
- self.rowheight = kwargs["rowheight"]
- del kwargs["rowheight"]
- apply(Canvas.__init__, (self, parent)+args, kwargs)
- self.bind('<Configure>', self.onConfigure)
- x = 5
- y = 0
- wid = int(self.cget('width'))
- self.create_text(x, y, text='Property', anchor='nw')
- self.create_text(x + self.namewidth, y, text='Value', anchor='nw')
- self.create_line(self.namewidth, 0, self.namewidth, self.rowheight, fill=LINE_COLOUR)
- self.tline = self.create_line(0, 0, wid, 0, fill=LINE_COLOUR)
- #self.create_line(0, 0, 0, self.rowheight, fill=LINE_COLOUR)
- #self.create_line(wid - 1, 0, wid - 1, self.rowheight, fill=LINE_COLOUR)
-
- def onConfigure(self, event):
- self.delete(self.tline)
- self.tline = self.create_line(0, 0, event.width, 0, fill=LINE_COLOUR)
-
-_popup = None
-
-class PropertyCanvas(Canvas):
- def __init__(self, parent, *args, **kwargs):
- self.namewidth = 120
- if kwargs.has_key("namewidth"):
- self.namewidth = kwargs["namewidth"]
- del kwargs["namewidth"]
- self.rowheight = 16
- if kwargs.has_key("rowheight"):
- self.rowheight = kwargs["rowheight"]
- del kwargs["rowheight"]
- apply(Canvas.__init__, (self, parent)+args, kwargs)
- self.namitems = []
- self.valitems = []
- self.lines = []
- self.pnames = []
- #Event bindings...
- self.bind('<Enter>', self.onEnter)
- self.bind('<Button-1>', self.onClick)
- self.bind('<Configure>', self.onConfigure)
- self.button = Button(height=self.rowheight, width=self.rowheight, text='...', command=self.onEdit)
- self.btnitem = None
- self.editor = Entry()
- self.edititem = None
- self.popup = Toplevel()
- self.popup.withdraw()
- self.popup.overrideredirect(1)
- self.list = ScrollingList(self.popup, background='white', relief=FLAT, borderwidth=0)
- self.list.pack(fill=BOTH, expand=1)
- self.list.listener = self
- self.listvisible = 0
-
- def clear(self):
- for itm in self.namitems:
- self.delete(itm)
- self.namitems = []
- for itm in self.valitems:
- self.delete(itm)
- self.valitems = []
- for lin in self.lines:
- self.delete(lin)
- self.lines = []
-
- def setPropertyHolder(self, ph):
- self.ph = ph
- self.pnames = ph.getPropNames()
- wid = int(self.cget('width'))
- hei = int(self.cget('height'))
- self.clear()
- x = 5
- y = 0
- i = 0
- self.props = []
- for n in self.pnames:
- prop = self.ph.getProp(n)
- self.props.append(prop)
- tn = "n%d" % i
- tv = "v%d" % i
- self.namitems.append(self.create_text(x, y + 2, text=prop.getCaption(), anchor='nw', tags=tn))
- self.valitems.append(self.create_text(x + self.namewidth, y + 2, text=prop.getValueText(), anchor='nw', tags=tv))
- y = y + self.rowheight
- i = i + 1
- self.drawLines(wid, hei)
- #self.config(height=y)
-
- def drawLines(self, wid, hei):
- for lin in self.lines:
- self.delete(lin)
- self.lines = []
- y = 0
- for i in xrange(len(self.pnames)):
- self.lines.append(self.create_line(0, y, wid, y, fill=LINE_COLOUR))
- y = y + self.rowheight
- self.lines.append(self.create_line(0, y, wid, y, fill=LINE_COLOUR))
- self.create_line(self.namewidth, 0, self.namewidth, hei, fill=LINE_COLOUR)
-
- def onEnter(self, event):
- if not self.edititem and not self.listvisible:
- self.focus_set()
-
- def hideControls(self):
- if self.listvisible:
- self.popup.withdraw()
- global _popup
- _popup = None
- self.listvisible = 0
- if self.edititem:
- self.ph.setPropValue(self.editprop.name, self.editor.get())
- self.itemconfig(self.valitems[self.editrow], text=self.editprop.getValueText())
- self.delete(self.edititem)
- self.edititem = None
- if self.btnitem:
- self.delete(self.btnitem)
- self.btnitem = None
-
- def onClick(self, event):
- row = event.y / self.rowheight
- self.hideControls()
- if row < len(self.pnames):
- wid = int(self.cget('width'))
- hei = self.rowheight
- prop = self.props[row]
- if not self.ph.isReadonly(self.pnames[row]):
- self.editrow = row
- self.editprop = prop
- choices = prop.getChoices()
- if choices != None:
- val = prop.getValue()
- self.list.setContents(choices, val)
- self.listy = row * hei + self.rowheight
- self.btnitem = self.create_window(wid - hei, row * hei, width=hei, height=hei, window=self.button, anchor='nw', tags='button')
- else:
- self.editor.delete(0, END)
- self.editor.insert(0, prop.getValueText())
- self.editor.select_range(0, END)
- self.edititem = self.create_window(self.namewidth + 1, row * hei, width=wid - self.namewidth, height = hei + 1, window=self.editor, anchor='nw', tags='editor')
- self.editor.focus_set()
-
- def onConfigure(self, event):
- self.hideControls()
- self.drawLines(event.width, event.height)
- self.configure(width=event.width, height=event.height)
-
- def onEdit(self):
- wid = int(self.cget('width'))
- #self.listitem = self.create_window(self.namewidth + 1, self.listy, width=wid - self.namewidth - 1, height = self.rowheight * 3, window=self.list, anchor='nw', tags='list')
- w = wid - self.namewidth - 1
- h = self.rowheight * 5
- x = self.winfo_rootx() + self.namewidth + 1
- y = self.winfo_rooty() + self.listy
- s = "%dx%d+%d+%d" % (w, h, x, y)
- self.popup.deiconify()
- self.popup.lift()
- self.popup.focus_set()
- self.listvisible = 1
- self.list.focus_set()
- #For some reason with 1.5.2 (Windows), making the geometry call
- #immediately following the assignment to s doesn't work. So we
- #do it here
- self.popup.geometry(s)
- global _popup
- _popup = self.popup
-
- def onListChange(self, val):
- self.ph.setPropValue(self.editprop.name, val)
- self.itemconfig(self.valitems[self.editrow], text=self.editprop.getValueText())
- if type(val) != types.ListType:
- self.hideControls()
-
-class PropertyEditor(Frame):
- def __init__(self, parent, *args, **kwargs):
- Frame.__init__(self, parent)
- self.parent = parent
- nw = kwargs.get("namewidth", 120)
- rh = kwargs.get("rowheight", 16)
- wid = kwargs.get("width", 300)
- hei = kwargs.get("height", 60)
- self.header = PropertyHeader(self, namewidth=nw, rowheight=rh, height=14, highlightthickness=0)
- self.body = PropertyCanvas(self, namewidth=nw, rowheight=rh, width=wid, height=hei, background='white', highlightthickness=0)
- self.header.pack(side=TOP, fill=X)
- self.body.pack(side=BOTTOM, fill=BOTH, expand=1)
-
- def setPropertyHolder(self, ph):
- self.body.setPropertyHolder(ph)
-
-class ADUPanel(Frame):
- def __init__(self, parent):
- Frame.__init__(self, parent)
- self.parent = parent
- self.add = Button(self, text="New", command=parent.onAdd)
- self.add.pack(side=LEFT) #, fill=X, expand=1)
- self.rmv = Button(self, text="Delete", command=parent.onDelete)
- self.rmv.pack(side=LEFT) #, fill=X, expand=1)
- #self.upd = Button(self, text="Update", command=parent.onUpdate)
- #self.upd.pack(side=RIGHT, fill=X, expand=1)
-
-class ScrollList(Frame):
- def __init__(self, parent, *args, **kwargs):
- Frame.__init__(self, parent)
- self.parent = parent
- self.sb = Scrollbar(self, orient=VERTICAL)
- kwargs["yscrollcommand"] = self.sb.set
- self.list = apply(Listbox, (self,) + args, kwargs)
- self.sb.config(command=self.list.yview)
- self.sb.pack(side=RIGHT, fill=Y)
- self.list.pack(side=LEFT, fill=BOTH,expand=1)
-
-def sortqn(log1, log2):
- qn1 = log1.getQualifiedName()
- qn2 = log2.getQualifiedName()
- if qn1 == "(root)":
- rv = -1
- elif qn2 == "(root)":
- rv = 1
- else:
- rv = cmp(qn1, qn2)
- return rv
-
-def sortn(obj1, obj2):
- return cmp(obj1.getPropValue("name"), obj2.getPropValue("name"))
-
-class LoggerPanel(Frame):
- def __init__(self, parent):
- Frame.__init__(self, parent)
- self.parent = parent
- label = Label(self, text="Loggers:")
- label.grid(row=0, column=0, sticky='w')
- self.slist = ScrollList(self, height=15, background='white')
- self.slist.list.bind('<ButtonRelease-1>', self.onListChange)
- self.slist.grid(row=1, column=0, sticky="nsew")
- self.adu = ADUPanel(self)
- self.adu.grid(row=2, column=0, sticky="we")
- label = Label(self, text="Properties of selected logger:")
- label.grid(row=3, column=0, sticky='w')
- self.pe = PropertyEditor(self, height=120, borderwidth=1)
- self.pe.grid(row=4, column=0, sticky='nsew')
- self.columnconfigure(0, weight=1)
- self.rowconfigure(1, weight=3)
- self.rowconfigure(4, weight=1)
-
- def setConfig(self, config):
- self.config = config
- #populate list of loggers
- llist = config.getLoggers()
- llist.sort(sortqn)
- self.slist.list.delete(0, END)
- self.pe.body.clear()
- self.names = []
- for logger in llist:
- self.names.append(logger.getPropValue("name"))
- self.slist.list.insert(END, logger.getQualifiedName())
-
- def onAdd(self):
- items = self.slist.list.curselection()
- if not len(items):
- showerror("No Parent Selected", "You haven't selected a parent logger.")
- else:
- idx = int(items[0])
- parent = self.config.getLogger(self.names[idx])
- log = self.config.getLogger(None)
- log.onChannelChanged = self.onChannelChanged
- log.setPropValue("parent", parent.getPropValue("name"))
- self.names.insert(1 + idx, log.getPropValue("name"))
- self.slist.list.insert(1 + idx, log.getQualifiedName())
- self.slist.list.select_clear(0, END)
- self.slist.list.select_set(1 + idx)
- self.pe.setPropertyHolder(log)
-
- def onDelete(self):
- items = self.slist.list.curselection()
- if not len(items):
- showerror("No Item Selected", "You haven't selected anything to delete.")
- else:
- idx = int(items[0])
- name = self.slist.list.get(idx)
- if name == "(root)":
- showerror("Root Item Selected", "You cannot delete the root logger.")
- else:
- resp = askyesno("Logger Deletion", "Are you sure you want to delete logger '%s'?" % name)
- if resp:
- #self.config.removeLogger(self.names[idx])
- log = self.config.getLogger(self.names[idx])
- log.deleted = 1
- self.slist.list.delete(idx)
- del self.names[idx]
- self.pe.body.clear()
-
- def onChannelChanged(self, nm, chname):
- i = self.names.index(nm)
- sel = i
- while i < len(self.names):
- log = self.config.getLogger(self.names[i])
- self.slist.list.delete(i)
- self.slist.list.insert(i, log.getQualifiedName())
- i = i + 1
- self.slist.list.select_clear(0, END)
- self.slist.list.select_set(sel)
-
- def onListChange(self, event):
- self.pe.body.hideControls()
- items = self.slist.list.curselection()
- idx = int(items[0])
- name = self.names[idx]
- log = self.config.getLogger(name)
- self.pe.setPropertyHolder(log)
-
-class HandlerPanel(Frame):
- def __init__(self, parent):
- Frame.__init__(self, parent)
- self.parent = parent
- label = Label(self, text="Handlers:")
- label.grid(row=0, column=0, sticky='w')
- self.slist = ScrollList(self, height=6, background='white')
- self.slist.list.bind('<ButtonRelease-1>', self.onListChange)
- self.slist.grid(row=1, column=0, sticky="nsew")
- self.adu = ADUPanel(self)
- self.adu.grid(row=2, column=0, sticky="we")
- label = Label(self, text="Properties of selected handler:")
- label.grid(row=3, column=0, sticky='w')
- self.pe = PropertyEditor(self, height=90, borderwidth=1)
- self.pe.grid(row=4, column=0, sticky='nsew')
- self.columnconfigure(0, weight=1)
- self.rowconfigure(1, weight=1)
- self.rowconfigure(4, weight=1)
-
- def setConfig(self, config):
- self.config = config
- #populate list of handlers
- hlist = config.getHandlers()
- hlist.sort(sortn)
- self.slist.list.delete(0, END)
- self.pe.body.clear()
- for hand in hlist:
- hand.onPropListChanged = self.onPropListChanged
- self.slist.list.insert(END, hand.getPropValue("name"))
-
- def onAdd(self):
- self.pe.body.hideControls()
- hand = self.config.getHandler(None)
- self.slist.list.insert(END, hand.getProp("name").getValueText())
- self.slist.list.select_clear(0, END)
- self.slist.list.select_set(END)
- hand.onPropListChanged = self.onPropListChanged
- self.pe.setPropertyHolder(hand)
-
- def onDelete(self):
- items = self.slist.list.curselection()
- if not len(items):
- showerror("No Item Selected", "You haven't selected anything to delete")
- else:
- name = self.slist.list.get(int(items[0]))
- log = self.config.handlerIsUsed(name)
- if log:
- showerror("Handler in use",
- "The handler '%s' is being used by logger '%s'"\
- ", so it cannot be deleted." % (
- name, log))
- else:
- self.config.removeHandler(name)
- self.slist.list.delete(items)
- self.pe.body.clear()
-
- def onUpdate(self):
- print "handler update"
-
- def onListChange(self, event):
- self.pe.body.hideControls()
- items = self.slist.list.curselection()
- name = self.slist.list.get(int(items[0]))
- hand = self.config.getHandler(name)
- self.pe.setPropertyHolder(hand)
-
- def onPropListChanged(self, newhand):
- newhand.onPropListChanged = self.onPropListChanged
- self.pe.setPropertyHolder(newhand)
-
-class FormatterPanel(Frame):
- def __init__(self, parent):
- Frame.__init__(self, parent)
- self.parent = parent
- label = Label(self, text="Formatters:")
- label.grid(row=0, column=0, sticky='w')
- self.slist = ScrollList(self, height=4, background='white')
- self.slist.list.bind('<ButtonRelease-1>', self.onListChange)
- self.slist.grid(row=1, column=0, sticky="nsew")
- self.adu = ADUPanel(self)
- self.adu.grid(row=2, column=0, sticky="ew")
- label = Label(self, text="Properties of selected formatter:")
- label.grid(row=3, column=0, sticky='w')
- self.pe = PropertyEditor(self, height=60, borderwidth=1)
- self.pe.grid(row=4, column=0, sticky='nsew')
- self.columnconfigure(0, weight=1)
- self.rowconfigure(1, weight=1)
- self.rowconfigure(4, weight=1)
-
- def setConfig(self, config):
- self.config = config
- #populate list of formatters
- flist = config.getFormatters()
- flist.sort(sortn)
- self.slist.list.delete(0, END)
- self.pe.body.clear()
- for form in flist:
- self.slist.list.insert(END, form.getPropValue("name"))
-
- def onAdd(self):
- self.pe.body.hideControls()
- fmt = self.config.getFormatter(None)
- self.slist.list.insert(END, fmt.getProp("name").getValueText())
- self.slist.list.select_clear(0, END)
- i = self.slist.list.size()
- self.slist.list.select_set(i - 1)
- self.pe.setPropertyHolder(fmt)
-
- def onDelete(self):
- self.pe.body.hideControls()
- items = self.slist.list.curselection()
- if not len(items):
- showerror("No Item Selected", "You haven't selected anything to delete")
- else:
- name = self.slist.list.get(int(items[0]))
- h = self.config.formatterIsUsed(name)
- if h:
- showerror("Formatter in use",
- "The formatter '%s' is being used by handler '%s'"\
- ", so it cannot be deleted." % (
- name, h))
- else:
- self.config.removeFormatter(name)
- self.slist.list.delete(items)
- self.pe.body.clear()
-
- def onUpdate(self):
- self.pe.body.hideControls()
-
- def onListChange(self, event):
- self.pe.body.hideControls()
- items = self.slist.list.curselection()
- name = self.slist.list.get(int(items[0]))
- fmt = self.config.getFormatter(name)
- self.pe.setPropertyHolder(fmt)
-
-class FilterPanel(Frame):
- def __init__(self, parent):
- Frame.__init__(self, parent)
- self.parent = parent
- label = Label(self, text="Filters:")
- label.grid(row=0, column=0, sticky='w')
- self.slist = ScrollList(self, height=4, background='white')
- self.slist.list.bind('<ButtonRelease-1>', self.onListChange)
- self.slist.grid(row=1, column=0, sticky="nsew")
- self.adu = ADUPanel(self)
- self.adu.grid(row=2, column=0, sticky="ew")
- label = Label(self, text="Properties of selected filter:")
- label.grid(row=3, column=0, sticky='w')
- self.pe = PropertyEditor(self, height=60, borderwidth=1)
- self.pe.grid(row=4, column=0, sticky='nsew')
- self.columnconfigure(0, weight=1)
- self.rowconfigure(1, weight=1)
- self.rowconfigure(4, weight=1)
-
- def setConfig(self, config):
- self.config = config
- #populate list of filters
- flist = config.getFilters()
- flist.sort(sortn)
- self.slist.list.delete(0, END)
- self.pe.body.clear()
- for filt in flist:
- self.slist.list.insert(END, filt.getPropValue("name"))
-
- def onAdd(self):
- self.pe.body.hideControls()
- filt = self.config.getFilter(None)
- self.slist.list.insert(END, filt.getProp("name").getValueText())
- self.slist.list.select_clear(0, END)
- i = self.slist.list.size()
- self.slist.list.select_set(i - 1)
- self.pe.setPropertyHolder(filt)
-
- def onDelete(self):
- self.pe.body.hideControls()
- items = self.slist.list.curselection()
- if not len(items):
- showerror("No Item Selected", "You haven't selected anything to delete")
- else:
- name = self.slist.list.get(int(items[0]))
- h = self.config.filterIsUsed(name)
- if h:
- showerror("Filter in use",
- "The filter '%s' is being used by '%s'"\
- ", so it cannot be deleted." % (
- name, h))
- else:
- self.config.removeFilter(name)
- self.slist.list.delete(items)
- self.pe.body.clear()
-
- def onUpdate(self):
- self.pe.body.hideControls()
-
- def onListChange(self, event):
- self.pe.body.hideControls()
- items = self.slist.list.curselection()
- name = self.slist.list.get(int(items[0]))
- filt = self.config.getFilter(name)
- self.pe.setPropertyHolder(filt)
-
-class ConfigPanel(Frame):
- def __init__(self, parent):
- Frame.__init__(self, parent)
- self.parent = parent
- self.load = Button(self, text="Load...", command=parent.onLoad)
- self.load.pack(side=LEFT)
- self.save = Button(self, text="Save", command=parent.onSave)
- self.save.pack(side=LEFT)
- self.save = Button(self, text="Save as...", command=parent.onSaveAs)
- self.save.pack(side=LEFT)
- self.reset = Button(self, text="Reset", command=parent.onReset)
- self.reset.pack(side=RIGHT)
-
-class Configurator(Frame):
- def __init__(self, parent):
- Frame.__init__(self, parent)
- self.parent = parent
- self.llist = LoggerPanel(self)
- self.llist.grid(row=0, column=0, rowspan=2, sticky='nsew')
- spacer = Canvas(self, width=2, highlightthickness=0)
- spacer.grid(row=0, column=1, rowspan=2, sticky='ns')
- self.hlist = HandlerPanel(self)
- self.hlist.grid(row=0, column=2, sticky='nsew')
- self.flist = FormatterPanel(self)
- self.flist.grid(row=1, column=2, sticky='nsew')
- self.cfg = ConfigPanel(self)
- self.cfg.grid(row=2, column=0, columnspan=2, sticky='w')
- self.filename = None
-
- self.rowconfigure(0, weight=1)
- self.columnconfigure(0, weight=1)
- self.columnconfigure(2, weight=1)
-
- label = Label(self, text="Copyright (C) 2002 Vinay Sajip. All rights reserved.", foreground='brown')
- label.grid(row=3, column=0, columnspan=2, sticky='w')
-
- if len(sys.argv) > 1:
- fn = sys.argv[1]
- try:
- self.loadFile(fn)
- except Exception, e:
- print e
- raise
- else:
- self.onReset(0)
- self.setTitle()
- self.focus_set()
-
- def setTitle(self):
- if self.filename:
- s = os.path.split(self.filename)[1]
- else:
- s = "untitled"
- self.winfo_toplevel().title("%s - Python Logging Configurator V%s" % (s, __version__))
-
- def loadFile(self, fn):
- self.config = LoggingConfig()
- self.config.read(fn)
- self.filename = fn
- self.llist.setConfig(self.config)
- self.hlist.setConfig(self.config)
- self.flist.setConfig(self.config)
- self.setTitle()
-
- def onLoad(self):
- fn = askopenfilename(title="Choose configuration file", filetypes=[("Logging configurations", "*.ini"), ("All files", "*.*")])
- if fn:
- self.loadFile(fn)
-
- def onSaveAs(self):
- if self.filename:
- fn = os.path.split(self.filename)[1]
- else:
- fn = DEFAULT_FILENAME
- fn = asksaveasfilename(title="Save configuration as", initialfile=fn, filetypes=[("Logging configurations", "*.ini"), ("All files", "*.*")])
- if fn:
- self.config.save(fn)
- self.filename = fn
- self.setTitle()
-
- def onSave(self):
- if not self.filename:
- self.onSaveAs()
- else:
- self.config.save(self.filename)
-
- def onReset(self, confirm=1):
- if not confirm:
- doit = 1
- else:
- doit = askyesno("Reset", "Are you sure you want to reset?")
- if doit:
- self.config = LoggingConfig()
- self.llist.setConfig(self.config)
- self.hlist.setConfig(self.config)
- self.flist.setConfig(self.config)
- self.setTitle()
-
-# -- general properties
-
-class NameProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "name", "Name", value)
-
-class LevelProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "level", "Level", value)
-
- def getChoices(self):
- return LOGGING_LEVELS
-
-# -- formatter properties
-
-class FormatProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "format", "Format", value)
-
-class DateFormatProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "datefmt", "Date Format", value)
-
-class FormatterProxy(PropertyHolder):
- def __init__(self, config, dict):
- self.config = config
- PropertyHolder.__init__(self, dict)
- prop = NameProperty(dict.get("name", ""))
- self.dict["name"] = prop
- prop = FormatProperty(dict.get("format", "%(asctime)s %(levelname)s %(message)s"))
- self.dict["format"] = prop
- prop = DateFormatProperty(dict.get("datefmt", ""))
- self.dict["datefmt"] = prop
- self.propnames = ["name", "format", "datefmt"]
-
- def isReadonly(self, name):
- return name == "name"
-
- def writeConfig(self, file):
- file.write("[formatter_%s]\n" % self.getPropValue("name"))
- file.write("format=%s\n" % self.getPropValue("format"))
- file.write("datefmt=%s\n\n" % self.getPropValue("datefmt"))
-
-# -- filter properties
-
-class LoggerNameProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "lname", "Name", value)
-
-class FilterProxy(PropertyHolder):
- def __init__(self, config, dict):
- self.config = config
- PropertyHolder.__init__(self, dict)
- prop = NameProperty(dict.get("name", ""))
- self.dict["name"] = prop
- prop = LoggerNameProperty(dict.get("lname", ""))
- self.dict["lname"] = prop
- self.propnames = ["name", "lname"]
-
- def isReadonly(self, name):
- return name == "name"
-
- def writeConfig(self, file):
- file.write("[filter_%s]\n" % self.getPropValue("name"))
- file.write("lname=%s\n" % self.getPropValue("lname"))
-
-# -- handler properties and proxies
-
-class HandlerTypeProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "class", "Type", value)
-
- def getChoices(self):
- return HANDLER_TYPES
-
-class FormatterProperty(Property):
- def __init__(self, config, value=None):
- self.config = config
- Property.__init__(self, "formatter", "Formatter", value)
-
- def getChoices(self):
- return self.config.getFormatterChoice()
-
-class HandlerProxy(PropertyHolder):
- def __init__(self, config, dict):
- self.config = config
- PropertyHolder.__init__(self, dict)
- prop = NameProperty(dict.get("name", ""))
- self.dict["name"] = prop
- prop = HandlerTypeProperty(dict.get("class", "StreamHandlerProxy"))
- self.dict["class"] = prop
- prop = FormatterProperty(self.config, dict.get("formatter", ""))
- self.dict["formatter"] = prop
- prop = LevelProperty(dict.get("level", "NOTSET"))
- self.dict["level"] = prop
- self.propnames = ["name", "class", "level", "formatter"]
-
- def isReadonly(self, name):
- return (name == "name")
-
- def setPropValue(self, name, value):
- PropertyHolder.setPropValue(self, name, value)
- if (name == "class"): #morph type of handler
- #print "try morph -> %s" % value
- try:
- klass = eval(value)
- except Exception, e:
- print e
- klass = None
- if klass:
- n = self.getPropValue("name")
- d = {
- "name": n,
- "class": value,
- "formatter": self.getPropValue("formatter"),
- "level": self.getPropValue("level"),
- }
- newhand = klass(self.config, d)
- self.config.handlers[n] = newhand #FIXME encapsulation
- if self.onPropListChanged:
- self.onPropListChanged(newhand)
-
- def writeConfig(self, file):
- file.write("[handler_%s]\n" % self.getPropValue("name"))
- s = self.getProp("class").getValueText()
- if not s in ["StreamHandler", "FileHandler"]:
- s = "handlers." + s
- file.write("class=%s\n" % s)
- file.write("level=%s\n" % self.getPropValue("level"))
- file.write("formatter=%s\n" % self.getPropValue("formatter"))
-
-class StreamProperty(Property):
- def __init__(self, config, value=None):
- self.config = config
- Property.__init__(self, "stream", "Stream", value)
-
- def getChoices(self):
- return OUTPUT_STREAMS
-
-class StreamHandlerProxy(HandlerProxy):
- def __init__(self, config, dict):
- HandlerProxy.__init__(self, config, dict)
- prop = StreamProperty(self.config, dict.get("stream", "sys.stderr"))
- self.dict["stream"] = prop
- self.propnames.append("stream")
-
- def writeConfig(self, file):
- HandlerProxy.writeConfig(self, file)
- file.write("stream=%s\n" % self.getPropValue("stream"))
- file.write("args=(%s,)\n\n" % self.getPropValue("stream"))
-
- def readConfig(self, sectname):
- prop = StreamProperty(self.config, self.config.get(sectname, "stream"))
- self.dict["stream"] = prop
- self.propnames.append("stream")
-
-class FilenameProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "filename", "File name", value)
-
-class ModeProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "mode", "Mode", value)
-
- def getChoices(self):
- return FILE_MODES
-
-class MaxSizeProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "maxsize", "Maximum Size (bytes)", value)
-
-class BackupCountProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "backcount", "Backup Count", value)
-
-class FileHandlerProxy(HandlerProxy):
- def __init__(self, config, dict):
- HandlerProxy.__init__(self, config, dict)
- prop = FilenameProperty(dict.get("filename", "python.log"))
- self.dict["filename"] = prop
- prop = ModeProperty(dict.get("mode", "a"))
- self.dict["mode"] = prop
- self.propnames.extend(["filename", "mode"])
-
- def writeConfig(self, file):
- HandlerProxy.writeConfig(self, file)
- fn = self.getPropValue("filename")
- file.write("filename=%s\n" % fn)
- mode = self.getPropValue("mode")
- file.write("mode=%s\n" % mode)
- file.write("args=('%s', '%s')\n\n" % (fn, mode))
-
- def readConfig(self, sectname):
- prop = FilenameProperty(self.config.get(sectname, "filename"))
- self.dict["filename"] = prop
- prop = ModeProperty(self.config.get(sectname, "mode"))
- self.dict["mode"] = prop
- self.propnames.extend(["filename", "mode"])
-
-class RotatingFileHandlerProxy(FileHandlerProxy):
- def __init__(self, config, dict):
- FileHandlerProxy.__init__(self, config, dict)
- prop = MaxSizeProperty(dict.get("maxsize", "0"))
- self.dict["maxsize"] = prop
- prop = BackupCountProperty(dict.get("backcount", "1"))
- self.dict["backcount"] = prop
- self.propnames.extend(["maxsize", "backcount"])
-
- def writeConfig(self, file):
- HandlerProxy.writeConfig(self, file)
- fn = self.getPropValue("filename")
- file.write("filename=%s\n" % fn)
- mode = self.getPropValue("mode")
- file.write("mode=%s\n" % mode)
- ms = self.getPropValue("maxsize")
- file.write("maxsize=%s\n" % ms)
- bc = self.getPropValue("backcount")
- file.write("backcount=%s\n" % bc)
- file.write("args=('%s', '%s', %s, %s)\n\n" % (fn, mode, ms, bc))
-
- def readConfig(self, sectname):
- FileHandlerProxy.readConfig(self, sectname)
- prop = MaxSizeProperty(self.config.get(sectname, "maxsize"))
- self.dict["maxsize"] = prop
- prop = BackupCountProperty(self.config.get(sectname, "backcount"))
- self.dict["backcount"] = prop
- self.propnames.extend(["maxsize", "backcount"])
-
-
-class HostProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "host", "Host", value)
-
-class PortProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "port", "Port", value)
-
-class SocketHandlerProxy(HandlerProxy):
- def __init__(self, config, dict):
- HandlerProxy.__init__(self, config, dict)
- prop = HostProperty(dict.get("host", "localhost"))
- self.dict["host"] = prop
- prop = PortProperty(dict.get("port", "handlers.DEFAULT_TCP_LOGGING_PORT"))
- self.dict["port"] = prop
- self.propnames.extend(["host", "port"])
-
- def writeConfig(self, file):
- HandlerProxy.writeConfig(self, file)
- host = self.getPropValue("host")
- file.write("host=%s\n" % host)
- port = self.getPropValue("port")
- file.write("port=%s\n" % port)
- file.write("args=('%s', %s)\n\n" % (host, port))
-
- def readConfig(self, sectname):
- prop = HostProperty(self.config.get(sectname, "host"))
- self.dict["host"] = prop
- prop = PortProperty(self.config.get(sectname, "port"))
- self.dict["port"] = prop
- self.propnames.extend(["host", "port"])
-
-class DatagramHandlerProxy(HandlerProxy):
- def __init__(self, config, dict):
- HandlerProxy.__init__(self, config, dict)
- prop = HostProperty(dict.get("host", "localhost"))
- self.dict["host"] = prop
- prop = PortProperty(dict.get("port", "handlers.DEFAULT_UDP_LOGGING_PORT"))
- self.dict["port"] = prop
- self.propnames.extend(["host", "port"])
-
- def writeConfig(self, file):
- HandlerProxy.writeConfig(self, file)
- host = self.getPropValue("host")
- file.write("host=%s\n" % host)
- port = self.getPropValue("port")
- file.write("port=%s\n" % port)
- file.write("args=('%s', %s)\n\n" % (host, port))
-
- def readConfig(self, sectname):
- prop = HostProperty(self.config.get(sectname, "host"))
- self.dict["host"] = prop
- prop = PortProperty(self.config.get(sectname, "port"))
- self.dict["port"] = prop
- self.propnames.extend(["host", "port"])
-
-class URLProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "url", "URL", value)
-
-class MethodProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "method", "HTTP Method", value)
-
- def getChoices(self):
- return HTTP_METHODS
-
-class HTTPHandlerProxy(HandlerProxy):
- def __init__(self, config, dict):
- HandlerProxy.__init__(self, config, dict)
- prop = HostProperty(dict.get("host", "localhost"))
- self.dict["host"] = prop
- prop = PortProperty(dict.get("port", "80"))
- self.dict["port"] = prop
- prop = URLProperty(dict.get("url", ""))
- self.dict["url"] = prop
- prop = MethodProperty(dict.get("method", "GET"))
- self.dict["method"] = prop
- self.propnames.extend(["host", "port", "url", "method"])
-
- def writeConfig(self, file):
- HandlerProxy.writeConfig(self, file)
- host = self.getPropValue("host")
- file.write("host=%s\n" % host)
- port = self.getPropValue("port")
- file.write("port=%s\n" % port)
- url = self.getPropValue("url")
- file.write("url=%s\n" % url)
- meth = self.getPropValue("method")
- file.write("method=%s\n" % meth)
- file.write("args=('%s:%s', '%s', '%s')\n\n" % (host, port, url, meth))
-
- def readConfig(self, sectname):
- prop = HostProperty(self.config.get(sectname, "host"))
- self.dict["host"] = prop
- prop = PortProperty(self.config.get(sectname, "port"))
- self.dict["port"] = prop
- prop = URLProperty(self.config.get(sectname, "url"))
- self.dict["url"] = prop
- prop = MethodProperty(self.config.get(sectname, "method"))
- self.dict["method"] = prop
- self.propnames.extend(["host", "port", "url", "method"])
-
-class SOAPHandlerProxy(HandlerProxy):
- def __init__(self, config, dict):
- HandlerProxy.__init__(self, config, dict)
- prop = HostProperty(dict.get("host", "localhost"))
- self.dict["host"] = prop
- prop = PortProperty(dict.get("port", "80"))
- self.dict["port"] = prop
- prop = URLProperty(dict.get("url", ""))
- self.dict["url"] = prop
- self.propnames.extend(["host", "port", "url"])
-
- def writeConfig(self, file):
- HandlerProxy.writeConfig(self, file)
- host = self.getPropValue("host")
- file.write("host=%s\n" % host)
- port = self.getPropValue("port")
- file.write("port=%s\n" % port)
- url = self.getPropValue("url")
- file.write("url=%s\n" % url)
- file.write("args=('%s:%s', '%s')\n\n" % (host, port, url))
-
- def readConfig(self, sectname):
- prop = HostProperty(self.config.get(sectname, "host"))
- self.dict["host"] = prop
- prop = PortProperty(self.config.get(sectname, "port"))
- self.dict["port"] = prop
- prop = URLProperty(self.config.get(sectname, "url"))
- self.dict["url"] = prop
- self.propnames.extend(["host", "port", "url"])
-
-class FacilityProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "facility", "Facility", value)
-
- def getChoices(self):
- return SYSLOG_FACILITIES
-
-class SysLogHandlerProxy(HandlerProxy):
- def __init__(self, config, dict):
- HandlerProxy.__init__(self, config, dict)
- prop = HostProperty(dict.get("host", "localhost"))
- self.dict["host"] = prop
- prop = PortProperty(dict.get("port", "handlers.SYSLOG_UDP_PORT"))
- self.dict["port"] = prop
- prop = FacilityProperty(dict.get("facility", "handlers.SysLogHandler.LOG_USER"))
- self.dict["facility"] = prop
- self.propnames.extend(["host", "port", "facility"])
-
- def writeConfig(self, file):
- HandlerProxy.writeConfig(self, file)
- host = self.getPropValue("host")
- file.write("host=%s\n" % host)
- port = self.getPropValue("port")
- file.write("port=%s\n" % port)
- fac = self.getPropValue("facility")
- file.write("facility=%s\n" % fac)
- file.write("args=(('%s', %s), handlers.SysLogHandler.%s)\n\n" % (host, port, fac))
-
- def readConfig(self, sectname):
- prop = HostProperty(self.config.get(sectname, "host"))
- self.dict["host"] = prop
- prop = PortProperty(self.config.get(sectname, "port"))
- self.dict["port"] = prop
- prop = FacilityProperty(self.config.get(sectname, "facility"))
- self.dict["facility"] = prop
- self.propnames.extend(["host", "port", "facility"])
-
-class FromProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "from", "From", value)
-
-class ToProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "to", "To", value)
-
-class SubjectProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "subject", "Subject", value)
-
-class SMTPHandlerProxy(HandlerProxy):
- def __init__(self, config, dict):
- HandlerProxy.__init__(self, config, dict)
- prop = HostProperty(dict.get("host", "localhost"))
- self.dict["host"] = prop
- prop = PortProperty(dict.get("port", "25"))
- self.dict["port"] = prop
- prop = FromProperty(dict.get("from", ""))
- self.dict["from"] = prop
- prop = ToProperty(dict.get("to", ""))
- self.dict["to"] = prop
- prop = SubjectProperty(dict.get("subject", ""))
- self.dict["subject"] = prop
- self.propnames.extend(["host", "port", "from", "to", "subject"])
-
- def writeConfig(self, file):
- HandlerProxy.writeConfig(self, file)
- host = self.getPropValue("host")
- file.write("host=%s\n" % host)
- port = self.getPropValue("port")
- file.write("port=%s\n" % port)
- frm = self.getPropValue("from")
- file.write("from=%s\n" % frm)
- to = self.getPropValue("to")
- file.write("to=%s\n" % to)
- subj = self.getPropValue("subject")
- file.write("subject=%s\n" % subj)
- to = string.split(to, ",")
- file.write("args=('%s', '%s', %s, '%s')\n\n" % (host, frm, repr(to), subj))
-
- def readConfig(self, sectname):
- prop = HostProperty(self.config.get(sectname, "host"))
- self.dict["host"] = prop
- prop = PortProperty(self.config.get(sectname, "port"))
- self.dict["port"] = prop
- prop = FromProperty(self.config.get(sectname, "from"))
- self.dict["from"] = prop
- prop = ToProperty(self.config.get(sectname, "to"))
- self.dict["to"] = prop
- prop = SubjectProperty(self.config.get(sectname, "subject"))
- self.dict["subject"] = prop
- self.propnames.extend(["host", "port", "from", "to", "subject"])
-
-class CapacityProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "capacity", "Capacity", value)
-
-class FlushLevelProperty(LevelProperty):
- def __init__(self, value=None):
- Property.__init__(self, "flushlevel", "Flush Level", value)
-
-class TargetProperty(Property):
- def __init__(self, config, value=None):
- self.config = config
- Property.__init__(self, "target", "Target", value)
-
- def getChoices(self):
- handlers = self.config.getHandlerChoice()
- nm = self.dict["name"].getValueText()
- #can't be own target...
- return filter(lambda x,nm=nm: x[0] != nm, handlers)
-
-class MemoryHandlerProxy(HandlerProxy):
- def __init__(self, config, dict):
- HandlerProxy.__init__(self, config, dict)
- prop = CapacityProperty(dict.get("capacity", "10"))
- self.dict["capacity"] = prop
- prop = FlushLevelProperty(dict.get("flushlevel", "ERROR"))
- self.dict["flushlevel"] = prop
- prop = TargetProperty(config, dict.get("target", ""))
- prop.dict = self.dict
- self.dict["target"] = prop
- self.propnames.extend(["capacity", "flushlevel", "target"])
-
- def writeConfig(self, file):
- HandlerProxy.writeConfig(self, file)
- cap = self.getPropValue("capacity")
- file.write("capacity=%s\n" % cap)
- flvl = self.getPropValue("flushlevel")
- file.write("flushlevel=%s\n" % flvl)
- file.write("target=%s\n" % self.getPropValue("target"))
- file.write("args=(%s, %s)\n\n" % (cap, flvl))
-
- def readConfig(self, sectname):
- prop = CapacityProperty(self.config.get(sectname, "capacity"))
- self.dict["capacity"] = prop
- prop = FlushLevelProperty(self.config.get(sectname, "flushlevel"))
- self.dict["flushlevel"] = prop
- prop = TargetProperty(self.config, self.config.get(sectname, "target"))
- prop.dict = self.dict
- self.dict["target"] = prop
- self.propnames.extend(["capacity", "flushlevel", "target"])
-
-class AppNameProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "appname", "Application Name", value)
-
-class DLLNameProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "dllname", "Message DLL name", value)
-
-class LogTypeProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "logtype", "Log Type", value)
-
- def getChoices(self):
- return LOG_TYPES
-
-class NTEventLogHandlerProxy(HandlerProxy):
- def __init__(self, config, dict):
- HandlerProxy.__init__(self, config, dict)
- prop = AppNameProperty(dict.get("appname", "Python Application"))
- self.dict["appname"] = prop
- prop = DLLNameProperty(dict.get("dllname", ""))
- self.dict["dllname"] = prop
- prop = LogTypeProperty(dict.get("logtype", "Application"))
- self.dict["logtype"] = prop
- self.propnames.extend(["appname", "dllname", "logtype"])
-
- def writeConfig(self, file):
- HandlerProxy.writeConfig(self, file)
- app = self.getPropValue("appname")
- file.write("appname=%s\n" % app)
- dll = self.getPropValue("dllname")
- file.write("dllname=%s\n" % dll)
- ltype = self.getPropValue("logtype")
- file.write("logtype=%s\n" % ltype)
- file.write("args=('%s', '%s', '%s')\n\n" % (app, dll, ltype))
-
- def readConfig(self, sectname):
- prop = AppNameProperty(self.config.get(sectname, "appname"))
- self.dict["appname"] = prop
- prop = DLLNameProperty(self.config.get(sectname, "dllname"))
- self.dict["dllname"] = prop
- prop = LogTypeProperty(self.config.get(sectname, "logtype"))
- self.dict["logtype"] = prop
- self.propnames.extend(["appname", "dllname", "logtype"])
-
-# -- logger properties and proxies
-
-class ChannelProperty(Property):
- def __init__(self, value=None):
- Property.__init__(self, "channel", "Name", value)
-
-class HandlerProperty(Property):
- def __init__(self, config, value=None):
- self.config = config
- Property.__init__(self, "handler", "Handlers", value)
-
- def getChoices(self):
- return self.config.getHandlerChoice()
-
-class FilterProperty(Property):
- def __init__(self, config, value=None):
- self.config = config
- Property.__init__(self, "filter", "Filters", value)
-
- def getChoices(self):
- return self.config.getFilterChoice()
-
-class ParentProperty(Property):
- def __init__(self, config, value=None):
- self.config = config
- Property.__init__(self, "parent", "Parent", value)
-
- def getChoices(self):
- loggers = self.config.getLoggerChoice()
- nm = self.dict["name"].getValueText()
- #can't be own parent...
- return filter(lambda x,nm=nm: x[0] != nm, loggers)
-
- def getValueText(self):
- if self.dict.has_key("root"):
- return ""
- pn = Property.getValueText(self)
- rv = ""
- while pn != "(root)":
- parent = self.config.getLogger(pn)
- rv = parent.getPropValue("channel") + "." + rv
- pn = parent.getProp("parent").value
- return rv[:-1]
-
-class PropagateProperty(Property):
- def __init__(self, config, value=None):
- self.config = config
- Property.__init__(self, "propagate", "Propagate", value)
-
- def getChoices(self):
- return BOOLEAN_VALUES
-
-class LoggerProxy(PropertyHolder):
- def __init__(self, config, dict):
- self.config = config
- PropertyHolder.__init__(self, dict)
- prop = ChannelProperty(dict.get("channel", ""))
- self.dict["channel"] = prop
- prop = NameProperty(dict.get("name", ""))
- self.dict["name"] = prop
- prop = HandlerProperty(config, dict.get("handler", []))
- self.dict["handler"] = prop
- prop = LevelProperty(dict.get("level", "NOTSET"))
- self.dict["level"] = prop
- prop = PropagateProperty(self.config, dict.get("propagate", "1"))
- self.dict["propagate"] = prop
- prop = ParentProperty(config, dict.get("parent", "(root)"))
- prop.dict = self.dict
- self.dict["parent"] = prop
- self.propnames = ["parent", "channel", "level", "propagate", "handler"]
- self.onChannelChanged = None
- self.deleted = 0
-
- def isReadonly(self, name):
- return (name in ["channel", "parent", "propagate"]) and self.dict.has_key("root")
-
- def getQualifiedName(self):
- pt = self.getProp("parent").getValueText()
- nm = self.getPropValue("channel")
- if pt:
- pn = pt + "." + nm
- else:
- pn = nm
- if pn == "":
- pn = "(root)"
- return pn
-
- def setPropValue(self, name, value):
- PropertyHolder.setPropValue(self, name, value)
- if (name == "channel"):
- nm = self.getPropValue("name")
- if self.onChannelChanged:
- self.onChannelChanged(nm, value)
-
- def writeConfig(self, file):
- if self.dict.has_key("root"):
- name = "root"
- else:
- name = self.getPropValue("name")
- file.write("[logger_%s]\n" % name)
- file.write("level=%s\n" % self.getPropValue("level"))
- file.write("propagate=%s\n" % self.getPropValue("propagate"))
- file.write("channel=%s\n" % self.getPropValue("channel"))
- file.write("parent=%s\n" % self.getPropValue("parent"))
- file.write("qualname=%s\n" % self.getQualifiedName())
- file.write("handlers=%s\n\n" % string.join(self.getPropValue("handler"), ","))
-
-# -- logging configuration
-
-class LoggingConfig(ConfigParser.ConfigParser):
- def __init__(self, defaults=None):
- ConfigParser.ConfigParser.__init__(self, defaults)
- self.formatters = {}
- self.handlers = {}
- self.loggers = {}
-# self.filters = {}
- #create root logger
- d = { "name": "(root)", "root": 1, "parent": "" }
- self.loggers["(root)"] = LoggerProxy(self, d)
-
- def read(self, fn):
- ConfigParser.ConfigParser.read(self, fn)
- llist = self.get("loggers", "keys")
- llist = string.split(llist, ",")
- llist.remove("root")
- sectname = "logger_root"
- log = self.loggers["(root)"]
- log.setPropValue("level", self.get(sectname, "level"))
- hlist = self.get(sectname, "handlers")
- hlist = string.split(hlist, ",")
- log.setPropValue("handler", hlist)
- for log in llist:
- sectname = "logger_%s" % log
- hlist = self.get(sectname, "handlers")
- hlist = string.split(hlist, ",")
- d = {
- "name" : log,
- "level" : self.get(sectname, "level"),
- "channel" : self.get(sectname, "channel"),
- "parent" : self.get(sectname, "parent"),
- "propagate" : self.get(sectname, "propagate"),
- "handler" : hlist,
- }
- self.loggers[log] = LoggerProxy(self, d)
- hlist = self.get("handlers", "keys")
- if len(hlist):
- hlist = string.split(hlist, ",")
- for hand in hlist:
- sectname = "handler_%s" % hand
- klass = self.get(sectname, "class")
- if klass[:9] == "handlers.":
- klass = klass[9:]
- d = {
- "name" : hand,
- "class" : "%sProxy" % klass,
- "level" : self.get(sectname, "level"),
- "formatter" : self.get(sectname, "formatter"),
- }
- hobj = HandlerProxy(self, d)
- hobj.__class__ = eval("%sProxy" % klass)
- hobj.readConfig(sectname)
- self.handlers[hand] = hobj
-
- flist = self.get("formatters", "keys")
- if len(flist):
- flist = string.split(flist, ",")
- for form in flist:
- sectname = "formatter_%s" % form
- d = {
- "name" : form,
- "format" : self.get(sectname, "format", 1),
- "datefmt" : self.get(sectname, "datefmt", 1),
- }
- self.formatters[form] = FormatterProxy(self, d)
-
-# flist = self.get("filters", "keys")
-# if len(flist):
-# flist = string.split(flist, ",")
-# for filt in flist:
-# sectname = "filter_%s" % filt
-# d = {
-# "name" : filt,
-# "lname" : self.get(sectname, "lname", 1),
-# }
-# self.filters[filt] = FilterProxy(self, d)
-
- def getFormatter(self, name):
- if name:
- fmt = self.formatters[name]
- else:
- n = len(self.formatters.keys()) + 1
- name = "form%02d" % n
- fmt = FormatterProxy(self, {"name": name})
- self.formatters[name] = fmt
- return fmt
-
- def getHandler(self, name):
- if name:
- hand = self.handlers[name]
- else:
- n = len(self.handlers.keys()) + 1
- name = "hand%02d" % n
- hand = StreamHandlerProxy(self, {"name": name})
- self.handlers[name] = hand
- return hand
-
- def getLogger(self, name):
- if name:
- log = self.loggers[name]
- else:
- n = len(self.loggers.keys()) + 1
- name = "log%02d" % n
- log = LoggerProxy(self, {"name": name, "channel": name})
- self.loggers[name] = log
- return log
-
- def getFormatterChoice(self):
- values = []
- keys = self.formatters.keys()
- keys.sort()
- for f in keys:
- values.append((f, f))
- return tuple(values)
-
- def getHandlerChoice(self):
- values = []
- keys = self.handlers.keys()
- keys.sort()
- for f in keys:
- values.append((f, f))
- return tuple(values)
-
- def getFilterChoice(self):
- values = []
- keys = self.filters.keys()
- keys.sort()
- for f in keys:
- values.append((f, f))
- return tuple(values)
-
- def getLoggerChoice(self):
- values = []
- keys = self.loggers.keys()
- keys.sort()
- for f in keys:
- values.append((f, f))
- return tuple(values)
-
- def getLoggers(self):
- return self.loggers.values()
-
- def getHandlers(self):
- return self.handlers.values()
-
- def getFormatters(self):
- return self.formatters.values()
-
- def formatterIsUsed(self, name):
- rv = None
- for h in self.handlers.keys():
- if self.handlers[h].getPropValue("formatter") == name:
- rv = h
- break
- return rv
-
- def handlerIsUsed(self, name):
- rv = None
- for log in self.loggers.keys():
- if name in self.loggers[log].getPropValue("handler"):
- rv = log
- break
- return rv
-
- def removeFormatter(self, name):
- del self.formatters[name]
-
- def removeHandler(self, name):
- del self.handlers[name]
-
- def removeLogger(self, name):
- del self.loggers[name]
-
- def save(self, fn):
- #needed because 1.5.2 ConfigParser should be supported
- file = open(fn, "w")
- #Write out the keys
- loggers = self.loggers.keys()
- loggers.remove("(root)")
- loggers = filter(lambda x, d=self.loggers: not d[x].deleted, loggers)
- loggers.sort()
- list = ["root"]
- list.extend(loggers)
- file.write("[loggers]\nkeys=%s\n\n" % string.join(list, ","))
- handlers = self.handlers.keys()
- handlers.sort()
- file.write("[handlers]\nkeys=%s\n\n" % string.join(handlers, ","))
- formatters = self.formatters.keys()
- formatters.sort()
- file.write("[formatters]\nkeys=%s\n\n" % string.join(formatters, ","))
- #write out the root logger properties
- log = self.loggers["(root)"]
- log.writeConfig(file)
- #write out other logger properties
- for log in loggers:
- log = self.loggers[log]
- log.writeConfig(file)
- #write out handler properties
- for hand in handlers:
- hand = self.handlers[hand]
- hand.writeConfig(file)
- #write out formatter properties
- for form in formatters:
- form = self.formatters[form]
- form.writeConfig(file)
- file.close()
-
-root = None
-
-def onClose():
- if _popup:
- _popup.withdraw()
- root.destroy()
-
-def main():
- global root
- root=Tk()
- cfg = Configurator(root)
- cfg.pack(side=LEFT, fill=BOTH, expand=1)
- root.protocol("WM_DELETE_WINDOW", onClose)
- root.mainloop()
-
-if __name__ == "__main__":
- main()
\ No newline at end of file
diff --git a/tools/python/logging/logging-0.4.9.2/test/logging.dtd b/tools/python/logging/logging-0.4.9.2/test/logging.dtd
deleted file mode 100644
index b2275ab..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/logging.dtd
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<!-- Author: Vinay Sajip, Red Dove Consultants Ltd. http://www.red-dove.com/ -->
-
-<!-- THIS IS ONLY A VERY SIMPLE EXAMPLE -->
-
-<!ELEMENT logging:events (logging:event*)>
-
-<!ELEMENT logging:event (logging:message)>
-
-<!ATTLIST logging:event
- name CDATA #REQUIRED
- level CDATA #REQUIRED
- created CDATA #IMPLIED
- filename CDATA #IMPLIED
- lineno CDATA #IMPLIED
->
-
-<!ELEMENT logging:message (#PCDATA)>
\ No newline at end of file
diff --git a/tools/python/logging/logging-0.4.9.2/test/logging.xml b/tools/python/logging/logging-0.4.9.2/test/logging.xml
deleted file mode 100644
index 6dabaff..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/logging.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE events SYSTEM "logging.dtd" [<!ENTITY data SYSTEM "events.xml">]>
-<events xmlns="http://www.red-dove.com/logging">
-&data;
-</events>
\ No newline at end of file
diff --git a/tools/python/logging/logging-0.4.9.2/test/logrecv.ini b/tools/python/logging/logging-0.4.9.2/test/logrecv.ini
deleted file mode 100644
index eede0d3..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/logrecv.ini
+++ /dev/null
@@ -1,36 +0,0 @@
-[loggers]
-keys=root
-
-[handlers]
-keys=hand01,hand02
-
-[formatters]
-keys=form01
-
-[logger_root]
-level=NOTSET
-propagate=1
-channel=
-parent=
-qualname=(root)
-handlers=hand01,hand02
-
-[handler_hand01]
-class=FileHandler
-level=NOTSET
-formatter=form01
-filename=logrecv.log
-mode=w
-args=('logrecv.log', 'w')
-
-[handler_hand02]
-class=StreamHandler
-level=NOTSET
-formatter=form01
-stream=sys.stderr
-args=(sys.stderr,)
-
-[formatter_form01]
-format=%(asctime)s %(levelname)-9s %(name)-8s %(thread)5s %(message)s
-datefmt=
-
diff --git a/tools/python/logging/logging-0.4.9.2/test/logrecv.py b/tools/python/logging/logging-0.4.9.2/test/logrecv.py
deleted file mode 100755
index 4c8007e..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/logrecv.py
+++ /dev/null
@@ -1,443 +0,0 @@
-#! /usr/bin/env python
-#
-# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Vinay Sajip
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-"""
-Simple socket-based logging event receiver for use with "logging.py" logging
-module.
-
-Should work under Python versions >= 1.5.2, except that source line information
-is not available unless 'inspect' is.
-
-Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
-"""
-
-from select import select
-import sys, string, struct, types, cPickle, socket
-import logging, logging.handlers, logging.config
-
-TIMEOUT = 10
-if sys.platform == "win32":
- RESET_ERROR = 10054
-else:
- RESET_ERROR = 0 #FIXME get correct value for Unix...
-
-logging.raiseExceptions = 1
-
-#
-# TCP receiver
-#
-
-from SocketServer import ThreadingTCPServer, StreamRequestHandler
-
-class LogRecordStreamHandler(StreamRequestHandler):
- """
- Handler for a streaming logging request. It basically logs the record
- using whatever logging policy is configured locally.
- """
-
- def handle(self):
- """
- Handle multiple requests - each expected to be a 4-byte length,
- followed by the LogRecord in pickle format. Logs the record
- according to whatever policy is configured locally.
- """
- while 1:
- try:
- chunk = self.connection.recv(4)
- if len(chunk) < 4:
- break
- slen = struct.unpack(">L", chunk)[0]
- chunk = self.connection.recv(slen)
- while len(chunk) < slen:
- chunk = chunk + self.connection.recv(slen - len(chunk))
- obj = self.unPickle(chunk)
- record = logging.makeLogRecord(obj)
- self.handleLogRecord(record)
- except socket.error, e:
- if type(e.args) != types.TupleType:
- raise
- else:
- errcode = e.args[0]
- if errcode != RESET_ERROR:
- raise
- break
-
- def unPickle(self, data):
- return cPickle.loads(data)
-
- def handleLogRecord(self, record):
- #if a name is specified, we use the named logger rather than the one
- #implied by the record. This is so test harnesses don't get into
- #endless loops (particularly log_test.py, which has this code and the
- #client code in the same Python instance)
- if self.server.logname is not None:
- name = self.server.logname
- else:
- name = record.name
- logger = logging.getLogger(name)
- logger.handle(record)
-
-class LogRecordSocketReceiver(ThreadingTCPServer):
- """
- A simple-minded TCP socket-based logging receiver suitable for test
- purposes.
- """
-
- allow_reuse_address = 1
-
- def __init__(self, host='localhost', port=logging.handlers.DEFAULT_TCP_LOGGING_PORT,
- handler=LogRecordStreamHandler):
- ThreadingTCPServer.__init__(self, (host, port), handler)
- self.abort = 0
- self.timeout = 1
- self.logname = None
-
- def serve_until_stopped(self):
- import select
- abort = 0
- while not abort:
- rd, wr, ex = select.select([self.socket.fileno()],
- [], [],
- self.timeout)
- if rd:
- self.handle_request()
- abort = self.abort
-
-#
-# UDP receiver
-#
-
-from SocketServer import ThreadingUDPServer, DatagramRequestHandler
-
-class LogRecordDatagramHandler(DatagramRequestHandler):
- """
- Handler for a datagram logging request. It basically logs the record using
- whatever logging policy is configured locally.
- """
- def handle(self):
- chunk = self.packet
- slen = struct.unpack(">L", chunk[:4])[0]
- chunk = chunk[4:]
- assert len(chunk) == slen
- obj = self.unPickle(chunk)
- record = logging.LogRecord(None, None, "", 0, "", (), None)
- record.__dict__.update(obj)
- self.handleLogRecord(record)
-
- def unPickle(self, data):
- return cPickle.loads(data)
-
- def handleLogRecord(self, record):
- #if a name is specified, we use the named logger rather than the one
- #implied by the record. This is so test harnesses don't get into
- #endless loops (particularly log_test.py, which has this code and the
- #client code in the same Python instance)
- if self.server.logname is not None:
- name = self.server.logname
- else:
- name = record.name
- logger = logging.getLogger(name)
- logger.handle(record)
-
- def finish(self):
- pass
-
-class LogRecordDatagramReceiver(ThreadingUDPServer):
- """
- A simple-minded UDP datagram-based logging receiver suitable for test
- purposes.
- """
-
- allow_reuse_address = 1
-
- def __init__(self, host='localhost', port=logging.handlers.DEFAULT_UDP_LOGGING_PORT,
- handler=LogRecordDatagramHandler):
- ThreadingUDPServer.__init__(self, (host, port), handler)
- self.abort = 0
- self.timeout = 1
- self.logname = None
-
- def serve_until_stopped(self):
- import select
- abort = 0
- while not abort:
- rd, wr, ex = select.select([self.socket.fileno()],
- [], [],
- self.timeout)
- if rd:
- self.handle_request()
- abort = self.abort
-
-#
-# HTTP receiver
-#
-
-from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
-
-import cgi
-
-class LogRecordHTTPHandler(BaseHTTPRequestHandler):
- def makeDict(self, fs):
- dict = {}
- for mfs in fs.list:
- dict[mfs.name] = mfs.value
- for key in ["args", "exc_info", "exc_text", "lineno", "msecs", "created",
- "thread", "levelno", "relativeCreated"]:
- if dict.has_key(key):
- dict[key] = eval(dict[key])
- return dict
-
- def do_GET(self):
- """Serve a GET request."""
- sts = "OK"
- env = { 'REQUEST_METHOD' : 'GET'}
- try:
- i = string.find(self.path, '?')
- if i >= 0:
- env['QUERY_STRING'] = self.path[i + 1:]
- fs = cgi.FieldStorage(environ=env)
- dict = self.makeDict(fs)
- record = logging.LogRecord(None, None, "", 0, "", (), None)
- record.__dict__.update(dict)
- self.handleLogRecord(record)
- except Exception, e:
- sts = "ERROR"
- raise
- self.send_head()
- self.wfile.write("GET %s" % sts)
-
- def handleLogRecord(self, record):
- #if a name is specified, we use the named logger rather than the one
- #implied by the record. This is so test harnesses don't get into
- #endless loops (particularly log_test.py, which has this code and the
- #client code in the same Python instance)
- if self.server.logname is not None:
- name = self.server.logname
- else:
- name = record.name
- logger = logging.getLogger(name)
- logger.handle(record)
-
- def do_HEAD(self):
- """Serve a HEAD request."""
- self.send_head()
-
- def do_POST(self):
- """Serve a POST request."""
- sts = "OK"
- env = { 'REQUEST_METHOD' : 'POST'}
- try:
- length = self.headers.getheader('content-length')
- if length:
- env['CONTENT_LENGTH'] = length
- #print self.headers
- i = string.find(self.path, '?')
- if i >= 0:
- env['QUERY_STRING'] = self.path[i + 1:]
- fs = cgi.FieldStorage(fp=self.rfile, environ=env)
- dict = self.makeDict(fs)
- record = logging.LogRecord(None, None, "", 0, "", (), None)
- record.__dict__.update(dict)
- self.handleLogRecord(record)
- except Exception, e:
- print e
- sys.stdout.flush()
- sts = "ERROR"
- raise
- self.send_head()
- self.wfile.write("POST %s" % sts)
-
- def send_head(self):
- """Common code for GET and HEAD commands.
-
- This sends the response code and MIME headers.
-
- Return value is either a file object (which has to be copied
- to the outputfile by the caller unless the command was HEAD,
- and must be closed by the caller under all circumstances), or
- None, in which case the caller has nothing further to do.
-
- """
- self.send_response(200)
- self.send_header("Content-type", "text/plain")
- self.end_headers()
-
- def log_message(self, *args):
- #comment out the following line if you don't want to show requests
- #apply(BaseHTTPRequestHandler.log_message, (self,) + args)
- pass
-
-class LogRecordHTTPReceiver(HTTPServer):
- def __init__(self, host='localhost', port=logging.handlers.DEFAULT_HTTP_LOGGING_PORT,
- handler=LogRecordHTTPHandler):
- HTTPServer.__init__(self, (host, port), handler)
- self.abort = 0
- self.timeout = 1
- self.logname = None
-
- def serve_until_stopped(self):
- import select
- abort = 0
- while not abort:
- rd, wr, ex = select.select([self.socket.fileno()],
- [], [],
- self.timeout)
- if rd:
- self.handle_request()
- abort = self.abort
-
-
-#
-# SOAP receiver
-#
-
-try:
- from ZSI import dispatch
-
- logname = None
-
- def log(args, created, exc_info, exc_text, filename, levelname, levelno, lineno, module, msecs, msg, name, pathname, process, relativeCreated, thread):
- record = logging.LogRecord(None, None, "", 0, "", (), None)
- record.args = eval(args)
- record.exc_info = eval(exc_info)
- record.exc_text = eval(exc_text)
- record.created = created
- record.filename = filename
- record.module = module
- record.levelname = levelname
- record.lineno = lineno
- record.levelno = levelno
- record.msecs = msecs
- record.msg = msg
- record.name = name
- record.pathname = pathname
- record.process = process
- record.relativeCreated = relativeCreated
- record.thread = thread
- #if a name is specified, we use the named logger rather than the one
- #implied by the record. This is so test harnesses don't get into
- #endless loops (particularly log_test.py, which has this code and the
- #client code in the same Python instance)
- if logname is not None:
- lname = logname
- else:
- lname = name
- logger = logging.getLogger(lname)
- logger.handle(record)
-
- class MySOAPRequestHandler(dispatch.SOAPRequestHandler):
- def log_message(self, *args):
- #comment out the following line if you don't want to show requests
- #apply(BaseHTTPRequestHandler.log_message, (self,) + args)
- pass
-
- class SOAPServer(HTTPServer):
- def __init__(self, port=logging.handlers.DEFAULT_SOAP_LOGGING_PORT):
- address = ('', port)
- HTTPServer.__init__(self, address, MySOAPRequestHandler)
- self.abort = 0
- self.timeout = 1
- self.logname = None
- self.docstyle = 0
- self.nsdict = {}
- self.typesmodule = None
- self.rpc = 1
- self.modules = (sys.modules["__main__"],)
-
- def serve_until_stopped(self):
- import select
- abort = 0
- while not abort:
- rd, wr, ex = select.select([self.socket.fileno()],
- [], [],
- self.timeout)
- if rd:
- global logname
- logname = self.logname
- self.handle_request()
- abort = self.abort
-
-except ImportError:
- "Import failed"
- SOAPServer = None
-
-def runTCP(tcpserver=None):
- if not tcpserver:
- tcpserver = LogRecordSocketReceiver()
- print "About to start TCP server..."
- tcpserver.serve_until_stopped()
-
-def runUDP(udpserver=None):
- if not udpserver:
- udpserver = LogRecordDatagramReceiver()
- print "About to start UDP server..."
- udpserver.serve_until_stopped()
-
-def runHTTP(httpserver=None):
- if not httpserver:
- httpserver = LogRecordHTTPReceiver()
- print "About to start HTTP server..."
- httpserver.serve_until_stopped()
-
-def runSOAP(soapserver=None):
- if not SOAPServer:
- print "Sorry, ZSI is not available. Install PyXML-0.6.6 and ZSI first."
- print "See README.txt and python_logging.html for more information."
- else:
- if not soapserver:
- soapserver = SOAPServer()
- print "About to start SOAP server..."
- soapserver.serve_until_stopped()
-
-FORMAT_STR = "%(asctime)s %(name)-19s %(levelname)-5s - %(message)s"
-
-if __name__ == "__main__":
- if (len(sys.argv) < 2) or not (string.lower(sys.argv[1]) in \
- ["udp", "tcp", "http", "soap"]):
- print "usage: logrecv.py [UDP|TCP|HTTP|SOAP]"
- else:
- #logging.basicConfig()
- logging.config.fileConfig("logrecv.ini")
-# both = string.lower(sys.argv[1]) == "both"
-# hdlr = logging.FileHandler("test.log")
-# hdlr.setFormatter(logging.Formatter(FORMAT_STR))
-# logging.getLogger("").addHandler(hdlr)
-# if both:
-# import threading
-# tcpthread = threading.Thread(target=runTCP)
-# udpthread = threading.Thread(target=runUDP)
-# tcpthread.start()
-# udpthread.start()
-# tcpthread.join()
-# udpthread.join()
-# else:
-# tcp = string.lower(sys.argv[1]) == "tcp"
-# if tcp:
-# runTCP()
-# else:
-# runUDP()
- arg = string.lower(sys.argv[1])
- if arg == "tcp":
- runTCP()
- elif arg == "udp":
- runUDP()
- elif arg == "http":
- runHTTP()
- elif arg == "soap":
- runSOAP()
diff --git a/tools/python/logging/logging-0.4.9.2/test/myapp.py b/tools/python/logging/logging-0.4.9.2/test/myapp.py
deleted file mode 100644
index d1da1c2..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/myapp.py
+++ /dev/null
@@ -1,13 +0,0 @@
-import logging, mymodule
-
-logging.basicConfig()
-
-log = logging.getLogger("MyApp")
-log.setLevel(logging.DEBUG) #set verbosity to show all messages of severity >= DEBUG
-log.info("Starting my app")
-try:
- mymodule.doIt()
-except Exception, e:
- log.exception("There was a problem.")
-log.info("Ending my app")
-
diff --git a/tools/python/logging/logging-0.4.9.2/test/mymodule.py b/tools/python/logging/logging-0.4.9.2/test/mymodule.py
deleted file mode 100644
index ac824df..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/mymodule.py
+++ /dev/null
@@ -1,8 +0,0 @@
-import logging
-log = logging.getLogger("MyModule")
-
-def doIt():
- log.debug("Doin' stuff...")
- #do stuff...
- raise TypeError, "Bogus type error for testing"
-
diff --git a/tools/python/logging/logging-0.4.9.2/test/stderr.exp b/tools/python/logging/logging-0.4.9.2/test/stderr.exp
deleted file mode 100644
index 7426e86..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/stderr.exp
+++ /dev/null
@@ -1,566 +0,0 @@
--- log_test0 begin --------------------------------------------------------
-CRITICAL:ERR:Message 0
-ERROR:ERR:Message 1
-CRITICAL:INF:Message 2
-ERROR:INF:Message 3
-WARNING:INF:Message 4
-INFO:INF:Message 5
-CRITICAL:INF.UNDEF:Message 6
-ERROR:INF.UNDEF:Message 7
-WARNING:INF.UNDEF:Message 8
-INFO:INF.UNDEF:Message 9
-CRITICAL:INF.ERR:Message 10
-ERROR:INF.ERR:Message 11
-CRITICAL:INF.ERR.UNDEF:Message 12
-ERROR:INF.ERR.UNDEF:Message 13
-CRITICAL:DEB:Message 14
-ERROR:DEB:Message 15
-WARNING:DEB:Message 16
-INFO:DEB:Message 17
-DEBUG:DEB:Message 18
-CRITICAL:UNDEF:Message 19
-ERROR:UNDEF:Message 20
-WARNING:UNDEF:Message 21
-INFO:UNDEF:Message 22
-CRITICAL:INF.BADPARENT.UNDEF:Message 23
-CRITICAL:INF.BADPARENT:Message 24
-INFO:INF:Messages should bear numbers 0 through 24.
--- log_test0 end --------------------------------------------------------
--- log_test2 begin --------------------------------------------------------
-CRITICAL:ERR:Message 0
-ERROR:ERR:Message 1
-CRITICAL:INF:Message 2
-ERROR:INF:Message 3
-WARNING:INF:Message 4
-INFO:INF:Message 5
-CRITICAL:INF.UNDEF:Message 6
-ERROR:INF.UNDEF:Message 7
-WARNING:INF.UNDEF:Message 8
-INFO:INF.UNDEF:Message 9
-CRITICAL:INF.ERR:Message 10
-ERROR:INF.ERR:Message 11
-CRITICAL:INF.ERR.UNDEF:Message 12
-ERROR:INF.ERR.UNDEF:Message 13
-CRITICAL:DEB:Message 14
-ERROR:DEB:Message 15
-WARNING:DEB:Message 16
-INFO:DEB:Message 17
-DEBUG:DEB:Message 18
-CRITICAL:UNDEF:Message 19
-ERROR:UNDEF:Message 20
-WARNING:UNDEF:Message 21
-INFO:UNDEF:Message 22
-CRITICAL:INF.BADPARENT.UNDEF:Message 23
-CRITICAL:INF.BADPARENT:Message 24
-INFO:INF:Messages should bear numbers 0 through 24.
--- log_test2 end --------------------------------------------------------
-CRITICAL:ERR:Message 0
-ERROR:ERR:Message 1
-CRITICAL:INF:Message 2
-ERROR:INF:Message 3
-WARNING:INF:Message 4
-INFO:INF:Message 5
-CRITICAL:INF.UNDEF:Message 6
-ERROR:INF.UNDEF:Message 7
-WARNING:INF.UNDEF:Message 8
-INFO:INF.UNDEF:Message 9
-CRITICAL:INF.ERR:Message 10
-ERROR:INF.ERR:Message 11
-CRITICAL:INF.ERR.UNDEF:Message 12
-ERROR:INF.ERR.UNDEF:Message 13
-CRITICAL:DEB:Message 14
-ERROR:DEB:Message 15
-WARNING:DEB:Message 16
-INFO:DEB:Message 17
-DEBUG:DEB:Message 18
-CRITICAL:UNDEF:Message 19
-ERROR:UNDEF:Message 20
-WARNING:UNDEF:Message 21
-INFO:UNDEF:Message 22
-CRITICAL:INF.BADPARENT.UNDEF:Message 23
-CRITICAL:INF.BADPARENT:Message 24
-INFO:INF:Messages should bear numbers 0 through 24.
--- log_test4 begin --------------------------------------------------------
--- setting logging level to 'Boring' -----
-Boring:root:This should only be seen at the 'Boring' logging level (or lower)
-Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
-Garrulous:root:This should only be seen at the 'Garrulous' logging level (or lower)
-Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
-Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Chatterbox' -----
-Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
-Garrulous:root:This should only be seen at the 'Garrulous' logging level (or lower)
-Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
-Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Garrulous' -----
-Garrulous:root:This should only be seen at the 'Garrulous' logging level (or lower)
-Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
-Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Talkative' -----
-Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
-Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Verbose' -----
-Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Sociable' -----
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Effusive' -----
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Terse' -----
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Taciturn' -----
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Silent' -----
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- Filtering at handler level to SOCIABLE --
--- setting logging level to 'Boring' -----
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Chatterbox' -----
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Garrulous' -----
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Talkative' -----
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Verbose' -----
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Sociable' -----
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Effusive' -----
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Terse' -----
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Taciturn' -----
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Silent' -----
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- Filtering using GARRULOUS filter --
--- setting logging level to 'Boring' -----
-Boring:root:This should only be seen at the 'Boring' logging level (or lower)
-Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
-Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
-Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Chatterbox' -----
-Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
-Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
-Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Garrulous' -----
-Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
-Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Talkative' -----
-Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
-Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Verbose' -----
-Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Sociable' -----
-Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Effusive' -----
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Terse' -----
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Taciturn' -----
-Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Silent' -----
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- Filtering using specific filter for SOCIABLE, TACITURN --
--- setting logging level to 'Boring' -----
-Boring:root:This should only be seen at the 'Boring' logging level (or lower)
-Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
-Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
-Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Chatterbox' -----
-Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
-Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
-Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Garrulous' -----
-Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
-Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Talkative' -----
-Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
-Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Verbose' -----
-Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Sociable' -----
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Effusive' -----
-Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Terse' -----
-Terse:root:This should only be seen at the 'Terse' logging level (or lower)
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Taciturn' -----
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- setting logging level to 'Silent' -----
-Silent:root:This should only be seen at the 'Silent' logging level (or lower)
--- log_test4 end --------------------------------------------------------
--- log_test7 begin --------------------------------------------------------
--- logging at DEBUG, nothing should be seen yet --
--- logging at INFO, nothing should be seen yet --
--- logging at WARNING, 3 messages should be seen --
-Debug message
-Info message
-Warning message
--- logging 0 at level INFO, messages should be seen every 10 events --
--- logging 1 at level INFO, messages should be seen every 10 events --
--- logging 2 at level INFO, messages should be seen every 10 events --
--- logging 3 at level INFO, messages should be seen every 10 events --
--- logging 4 at level INFO, messages should be seen every 10 events --
--- logging 5 at level INFO, messages should be seen every 10 events --
--- logging 6 at level INFO, messages should be seen every 10 events --
--- logging 7 at level INFO, messages should be seen every 10 events --
--- logging 8 at level INFO, messages should be seen every 10 events --
--- logging 9 at level INFO, messages should be seen every 10 events --
-Info index = 0
-Info index = 1
-Info index = 2
-Info index = 3
-Info index = 4
-Info index = 5
-Info index = 6
-Info index = 7
-Info index = 8
-Info index = 9
--- logging 10 at level INFO, messages should be seen every 10 events --
--- logging 11 at level INFO, messages should be seen every 10 events --
--- logging 12 at level INFO, messages should be seen every 10 events --
--- logging 13 at level INFO, messages should be seen every 10 events --
--- logging 14 at level INFO, messages should be seen every 10 events --
--- logging 15 at level INFO, messages should be seen every 10 events --
--- logging 16 at level INFO, messages should be seen every 10 events --
--- logging 17 at level INFO, messages should be seen every 10 events --
--- logging 18 at level INFO, messages should be seen every 10 events --
--- logging 19 at level INFO, messages should be seen every 10 events --
-Info index = 10
-Info index = 11
-Info index = 12
-Info index = 13
-Info index = 14
-Info index = 15
-Info index = 16
-Info index = 17
-Info index = 18
-Info index = 19
--- logging 20 at level INFO, messages should be seen every 10 events --
--- logging 21 at level INFO, messages should be seen every 10 events --
--- logging 22 at level INFO, messages should be seen every 10 events --
--- logging 23 at level INFO, messages should be seen every 10 events --
--- logging 24 at level INFO, messages should be seen every 10 events --
--- logging 25 at level INFO, messages should be seen every 10 events --
--- logging 26 at level INFO, messages should be seen every 10 events --
--- logging 27 at level INFO, messages should be seen every 10 events --
--- logging 28 at level INFO, messages should be seen every 10 events --
--- logging 29 at level INFO, messages should be seen every 10 events --
-Info index = 20
-Info index = 21
-Info index = 22
-Info index = 23
-Info index = 24
-Info index = 25
-Info index = 26
-Info index = 27
-Info index = 28
-Info index = 29
--- logging 30 at level INFO, messages should be seen every 10 events --
--- logging 31 at level INFO, messages should be seen every 10 events --
--- logging 32 at level INFO, messages should be seen every 10 events --
--- logging 33 at level INFO, messages should be seen every 10 events --
--- logging 34 at level INFO, messages should be seen every 10 events --
--- logging 35 at level INFO, messages should be seen every 10 events --
--- logging 36 at level INFO, messages should be seen every 10 events --
--- logging 37 at level INFO, messages should be seen every 10 events --
--- logging 38 at level INFO, messages should be seen every 10 events --
--- logging 39 at level INFO, messages should be seen every 10 events --
-Info index = 30
-Info index = 31
-Info index = 32
-Info index = 33
-Info index = 34
-Info index = 35
-Info index = 36
-Info index = 37
-Info index = 38
-Info index = 39
--- logging 40 at level INFO, messages should be seen every 10 events --
--- logging 41 at level INFO, messages should be seen every 10 events --
--- logging 42 at level INFO, messages should be seen every 10 events --
--- logging 43 at level INFO, messages should be seen every 10 events --
--- logging 44 at level INFO, messages should be seen every 10 events --
--- logging 45 at level INFO, messages should be seen every 10 events --
--- logging 46 at level INFO, messages should be seen every 10 events --
--- logging 47 at level INFO, messages should be seen every 10 events --
--- logging 48 at level INFO, messages should be seen every 10 events --
--- logging 49 at level INFO, messages should be seen every 10 events --
-Info index = 40
-Info index = 41
-Info index = 42
-Info index = 43
-Info index = 44
-Info index = 45
-Info index = 46
-Info index = 47
-Info index = 48
-Info index = 49
--- logging 50 at level INFO, messages should be seen every 10 events --
--- logging 51 at level INFO, messages should be seen every 10 events --
--- logging 52 at level INFO, messages should be seen every 10 events --
--- logging 53 at level INFO, messages should be seen every 10 events --
--- logging 54 at level INFO, messages should be seen every 10 events --
--- logging 55 at level INFO, messages should be seen every 10 events --
--- logging 56 at level INFO, messages should be seen every 10 events --
--- logging 57 at level INFO, messages should be seen every 10 events --
--- logging 58 at level INFO, messages should be seen every 10 events --
--- logging 59 at level INFO, messages should be seen every 10 events --
-Info index = 50
-Info index = 51
-Info index = 52
-Info index = 53
-Info index = 54
-Info index = 55
-Info index = 56
-Info index = 57
-Info index = 58
-Info index = 59
--- logging 60 at level INFO, messages should be seen every 10 events --
--- logging 61 at level INFO, messages should be seen every 10 events --
--- logging 62 at level INFO, messages should be seen every 10 events --
--- logging 63 at level INFO, messages should be seen every 10 events --
--- logging 64 at level INFO, messages should be seen every 10 events --
--- logging 65 at level INFO, messages should be seen every 10 events --
--- logging 66 at level INFO, messages should be seen every 10 events --
--- logging 67 at level INFO, messages should be seen every 10 events --
--- logging 68 at level INFO, messages should be seen every 10 events --
--- logging 69 at level INFO, messages should be seen every 10 events --
-Info index = 60
-Info index = 61
-Info index = 62
-Info index = 63
-Info index = 64
-Info index = 65
-Info index = 66
-Info index = 67
-Info index = 68
-Info index = 69
--- logging 70 at level INFO, messages should be seen every 10 events --
--- logging 71 at level INFO, messages should be seen every 10 events --
--- logging 72 at level INFO, messages should be seen every 10 events --
--- logging 73 at level INFO, messages should be seen every 10 events --
--- logging 74 at level INFO, messages should be seen every 10 events --
--- logging 75 at level INFO, messages should be seen every 10 events --
--- logging 76 at level INFO, messages should be seen every 10 events --
--- logging 77 at level INFO, messages should be seen every 10 events --
--- logging 78 at level INFO, messages should be seen every 10 events --
--- logging 79 at level INFO, messages should be seen every 10 events --
-Info index = 70
-Info index = 71
-Info index = 72
-Info index = 73
-Info index = 74
-Info index = 75
-Info index = 76
-Info index = 77
-Info index = 78
-Info index = 79
--- logging 80 at level INFO, messages should be seen every 10 events --
--- logging 81 at level INFO, messages should be seen every 10 events --
--- logging 82 at level INFO, messages should be seen every 10 events --
--- logging 83 at level INFO, messages should be seen every 10 events --
--- logging 84 at level INFO, messages should be seen every 10 events --
--- logging 85 at level INFO, messages should be seen every 10 events --
--- logging 86 at level INFO, messages should be seen every 10 events --
--- logging 87 at level INFO, messages should be seen every 10 events --
--- logging 88 at level INFO, messages should be seen every 10 events --
--- logging 89 at level INFO, messages should be seen every 10 events --
-Info index = 80
-Info index = 81
-Info index = 82
-Info index = 83
-Info index = 84
-Info index = 85
-Info index = 86
-Info index = 87
-Info index = 88
-Info index = 89
--- logging 90 at level INFO, messages should be seen every 10 events --
--- logging 91 at level INFO, messages should be seen every 10 events --
--- logging 92 at level INFO, messages should be seen every 10 events --
--- logging 93 at level INFO, messages should be seen every 10 events --
--- logging 94 at level INFO, messages should be seen every 10 events --
--- logging 95 at level INFO, messages should be seen every 10 events --
--- logging 96 at level INFO, messages should be seen every 10 events --
--- logging 97 at level INFO, messages should be seen every 10 events --
--- logging 98 at level INFO, messages should be seen every 10 events --
--- logging 99 at level INFO, messages should be seen every 10 events --
-Info index = 90
-Info index = 91
-Info index = 92
-Info index = 93
-Info index = 94
-Info index = 95
-Info index = 96
-Info index = 97
-Info index = 98
-Info index = 99
--- logging 100 at level INFO, messages should be seen every 10 events --
--- logging 101 at level INFO, messages should be seen every 10 events --
-Info index = 100
-Info index = 101
--- log_test7 end --------------------------------------------------------
--- log_test8 begin --------------------------------------------------------
--- log_test8 end --------------------------------------------------------
--- log_test9 begin --------------------------------------------------------
--- log_test9 end --------------------------------------------------------
--- log_test10 begin --------------------------------------------------------
-logger not derived from logging.Logger: NotALogger
-INFO:mylogger:Starting...
-DEBUG:mylogger:Debug message not in exception handler (no traceback)
-INFO:mylogger:About to throw exception...
-DEBUG:mylogger:Debug message inside exception handler (traceback)
-Traceback (most recent call last):
- File "C:\Projects\RDC\Python\packages\logging\test\log_test10.py", line 77, in run
- print "7" + 4
-TypeError: cannot concatenate 'str' and 'int' objects
-INFO:mylogger:Done.
--- log_test10 end --------------------------------------------------------
--- log_test12 begin --------------------------------------------------------
-INFO:log_test12:Jackdaws love my big sphinx of quartz
-INFO:log_test12:Jackdaws love my big sphinx of quartz
-DEBUG:log_test12:Pack my box with twelve dozen liquor jugs
-DEBUG:log_test12:Pack my box with twelve dozen liquor jugs
--- log_test12 end --------------------------------------------------------
--- log_test13 begin --------------------------------------------------------
-INFO:log_test13:Jackdaws love my big sphinx of quartz
-DEBUG:log_test13:Pack my box with five dozen liquor jugs
--- log_test13 end --------------------------------------------------------
--- log_test15 begin --------------------------------------------------------
-Unfiltered...
-INFO:a:Info 1
-INFO:a.b:Info 2
-INFO:a.c:Info 3
-INFO:a.b.c:Info 4
-INFO:a.b.c.d:Info 5
-INFO:a.bb.c:Info 6
-INFO:b:Info 7
-INFO:b.a:Info 8
-INFO:c.a.b:Info 9
-INFO:a.bb:Info 10
-Filtered with 'a.b'...
-INFO:a.b:Info 2
-INFO:a.b.c:Info 4
-INFO:a.b.c.d:Info 5
--- log_test15 end --------------------------------------------------------
diff --git a/tools/python/logging/logging-0.4.9.2/test/stdout.exp b/tools/python/logging/logging-0.4.9.2/test/stdout.exp
deleted file mode 100644
index bf3d150..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/stdout.exp
+++ /dev/null
@@ -1,24 +0,0 @@
-About to start TCP server...
-About to start UDP server...
-About to start HTTP server...
-About to start SOAP server...
--- log_test0 begin --------------------------------------------------------
--- log_test0 end --------------------------------------------------------
--- log_test2 begin --------------------------------------------------------
--- log_test2 end --------------------------------------------------------
--- log_test4 begin --------------------------------------------------------
--- log_test4 end --------------------------------------------------------
--- log_test7 begin --------------------------------------------------------
--- log_test7 end --------------------------------------------------------
--- log_test8 begin --------------------------------------------------------
--- log_test8 end --------------------------------------------------------
--- log_test9 begin --------------------------------------------------------
--- log_test9 end --------------------------------------------------------
--- log_test10 begin --------------------------------------------------------
--- log_test10 end --------------------------------------------------------
--- log_test12 begin --------------------------------------------------------
--- log_test12 end --------------------------------------------------------
--- log_test13 begin --------------------------------------------------------
--- log_test13 end --------------------------------------------------------
--- log_test15 begin --------------------------------------------------------
--- log_test15 end --------------------------------------------------------
diff --git a/tools/python/logging/logging-0.4.9.2/test/warn.ini b/tools/python/logging/logging-0.4.9.2/test/warn.ini
deleted file mode 100644
index 3a7b374..0000000
--- a/tools/python/logging/logging-0.4.9.2/test/warn.ini
+++ /dev/null
@@ -1,60 +0,0 @@
-[loggers]
-keys=root,log02,log03,log04,log05
-
-[handlers]
-keys=hand01
-
-[formatters]
-keys=form01
-
-[logger_root]
-level=WARN
-propagate=1
-channel=
-parent=
-qualname=(root)
-handlers=hand01
-
-[logger_log02]
-level=WARN
-propagate=1
-channel=A
-parent=(root)
-qualname=A
-handlers=
-
-[logger_log03]
-level=WARN
-propagate=1
-channel=B
-parent=log02
-qualname=A.B
-handlers=
-
-[logger_log04]
-level=WARN
-propagate=1
-channel=C
-parent=log03
-qualname=A.B.C
-handlers=
-
-[logger_log05]
-level=WARN
-propagate=1
-channel=D
-parent=log04
-qualname=A.B.C.D
-handlers=
-
-[handler_hand01]
-class=StreamHandler
-level=NOTSET
-formatter=form01
-stream=sys.stderr
-args=(sys.stderr,)
-
-[formatter_form01]
-format=warn.ini %(name)s %(levelname)s %(message)s
-datefmt=
-
diff --git a/tools/python/logging/setup.py b/tools/python/logging/setup.py
deleted file mode 100644
index 724e17e..0000000
--- a/tools/python/logging/setup.py
+++ /dev/null
@@ -1,11 +0,0 @@
-#============================================================================
-# Install the logging package from python 2.3 if not present.
-#============================================================================
-import os
-
-try:
- import logging
-except ImportError:
- print 'logging package not found: installing'
- os.chdir('logging-0.4.9.2')
- execfile('setup.py')
diff --git a/tools/python/ptsname/ptsname.c b/tools/python/ptsname/ptsname.c
deleted file mode 100644
index 3849bb8..0000000
--- a/tools/python/ptsname/ptsname.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/******************************************************************************
- * ptsname.c
- *
- * A python extension to expose the POSIX ptsname() function.
- *
- * Copyright (C) 2007 XenSource Ltd
- */
-
-#include <Python.h>
-#include <stdlib.h>
-
-/* Needed for Python versions earlier than 2.3. */
-#ifndef PyMODINIT_FUNC
-#define PyMODINIT_FUNC DL_EXPORT(void)
-#endif
-
-static PyObject *do_ptsname(PyObject *self, PyObject *args)
-{
- int fd;
- char *path;
-
- if (!PyArg_ParseTuple(args, "i", &fd))
- return NULL;
-
- path = ptsname(fd);
-
- if (!path)
- {
- PyErr_SetFromErrno(PyExc_IOError);
- return NULL;
- }
-
- return PyString_FromString(path);
-}
-
-static PyMethodDef ptsname_methods[] = {
- { "ptsname", do_ptsname, METH_VARARGS },
- { NULL }
-};
-
-PyMODINIT_FUNC initptsname(void)
-{
- Py_InitModule("ptsname", ptsname_methods);
-}
diff --git a/tools/python/scripts/README b/tools/python/scripts/README
deleted file mode 100644
index a5d8759..0000000
--- a/tools/python/scripts/README
+++ /dev/null
@@ -1,49 +0,0 @@
-Xen API Test
-============
-
-xapi.py is a simple command line tool to test the functionality of a
-domain lifecycle supporting, Xen API talking version of Xend.
-
-Creating a VM is slightly more work under the Xen API. The differences
-with this and xm is:
-
-1. None of the devices are created during vm-create. You must use
- vbd-create and vif-create to attach a new device to the VM.
-
-2. VM's that are created using vm-create will not start by
- default. You must use vm-start to "start" the domain.
-
-3. VM's that are created using vm-create will not be removed on
- shutdown. You must remove it using vm-delete.
-
-Example Configuration Files
----------------------------
-
-xapi.py uses a simple python configuration file similar to xm in the
-face of the lack of any other reasonable format.
-
-All the fields are directly mapped to the arguments that are in the
-Xen API constructore for the respective classes.
-
-xapi.domcfg.py: example configuration for a paravirtualised domain.
-xapi.vbdcfg.py: example configuration for a file based block device.
-xapi.vifcfg.py: example configuration for a simple bridged network
- device.
-
-Example Session
----------------
-
-xapi.py vm-list
-xapi.py vm-create xapi.domcfg.py
-xapi.py vbd-create <DomainName> xapi.vbdcfg.py
-xapi.py vif-create <DomainName> xapi.vifcfg.py
-
-Notes
------
-
-Currently lacking:
-
-1. Any real authentication. XendAuthSessions need to be filled in with
- a proper authentication implementation either using PAM or other
- means.
-
diff --git a/tools/python/scripts/README.lifecycle b/tools/python/scripts/README.lifecycle
deleted file mode 100644
index 1e24cc0..0000000
--- a/tools/python/scripts/README.lifecycle
+++ /dev/null
@@ -1,136 +0,0 @@
-Xend Lifecycle/XenAPI Implementation Changes
-============================================
-
-Summary of what has changed in this branch of Xend:
-
-Managed Domains
----------------
-
-The concept of managed domains is that Xend now has the ability to
-manage the lifecycle of a domain from when it is created to being
-shutdown.
-
-XendDomain
-~~~~~~~~~~
-
-In order to support managed domains, XendDomain has been modified to
-keep the configuration in /var/lib/xend/domains/.
-
-The configuration is stored in SXP format so that it can be easily
-loaded by the current Xend. In the future, we may switch to an XML
-format similar to how XenAPI defines a VM configuration.
-
-TODO: There are still places where the device configuration or VM
-configuration can be altered but the managed domain does not save it.
-
-XendDomainInfo
-~~~~~~~~~~~~~~
-
-XendDomainInfo has changed to support this mode of operation,
-especially with domain construction and assumptions about the domain
-when it shuts down.
-
-All configuration option parsing and validation has been moved from
-XendDomainInfo to XendConfig. The purpose is so that we can abstract
-away the knowledge of SXP in XendDomainInfo. The goal is to do away
-with the bulky way of accessing SXP in Xend and moving that all to a
-more pythonic interface.
-
-The DevController stuff at the end of XendDomainInfo has also been
-moved to XendDevices because now it is needed in both XendConfig and
-XendDomainInfo.
-
-Many of the constants are moved to XendConstants which reduces the
-amount of recursive or scoped imports that occur in the code.
-
-XendConfig
-~~~~~~~~~~
-
-XendConfig is the beginnings of an interface for configuration options
-so that other parts of Xend do not need to know what format the
-configuration in. It can accept configuration passed in as parsed SXP
-format, python filename or a Xen API struct.
-
-It is a subclass of a python dictionary, and hence access to its
-functions are via the __getitem__ accessor.
-
-TODO: Define a proper interface to the XendConfig which is based on
-either the Xen API or some other flexible format.
-
-XMLRPCServer
-~~~~~~~~~~~~
-
-Changes to the busy loop in here and SrvServer so that the daemon
-shuts down cleanly. This also allows us to catch the shutdown and
-perform maintanence tasks on the domains.
-
-Replacing xendomains init.d script
-==================================
-
-Some work has gone into catching Xend's shutdown so that we can do the
-same tasks that xendomains init.d script does but natively in Xend.
-
-For instance, a new configuration option, 'on_xend_start' and
-'on_xend_stop' will allow domains that are managed by Xend to start up
-when Xend starts, and correspondingly stop when Xend stops.
-
-Xen API
-=======
-
-The new Xen API gives a standard interface to creating, configuring,
-controlling and destroying VMs and the virtual devices that belong to
-it.
-
-It also introduces the concept of Storage Repositories (SR) which are
-factories for creating disk images.
-
-XendDomain
-~~~~~~~~~~
-
-XendDomain has now separated the section for the Legacy XM XMLRPC API
-and the new Xen API.
-
-Since many things have a UUID, these are stored and represented as
-close to the existing configuration.
-
-XendDomainInfo
-~~~~~~~~~~~~~~
-
-XendDomainInfo now supports UUIDs being assigned to devices and the
-domain itself. It will preserve the UUID for managed domains.
-
-A number of new functions are now in XendDomainInfo to provide an
-interface to devices.
-
-XendNode
-~~~~~~~~
-
-Represents the Host class in the Xen API and also contains an
-incomplete representation of the physical CPUs availabel for the host.
-
-XendAuthSessions
-~~~~~~~~~~~~~~~~
-
-An abstract authenticator for the Xen API. Currently it is an empty
-implementation with rudimentary support for users. The plan is the add
-PAM based authentication.
-
-XendAPI
-~~~~~~~
-
-The guts of the Xen API implementation. Implements all the supported
-functionality of the Xen API by placing calls to the relevent objects
-like XendDomain and XendDomanInfo.
-
-The initialisation of the XendAPI object will actually install a
-number of validation decorators in order to ensure the input is
-correct. It is using some features of introspection and
-metaprogramming in Python to reduce the amount of replication in the
-code.
-
-XMLRPCServer
-~~~~~~~~~~~~
-
-The XMLRPC Server will support both the new Xen API and the old XM
-XMLRPC API. The support is clearly marked in the code.
-
diff --git a/tools/python/scripts/test_hvm_create.py b/tools/python/scripts/test_hvm_create.py
deleted file mode 100644
index 5020363..0000000
--- a/tools/python/scripts/test_hvm_create.py
+++ /dev/null
@@ -1,178 +0,0 @@
-#!/usr/bin/python
-
-vm_cfg = {
- 'name_label': 'API_HVM',
- 'user_version': 1,
- 'is_a_template': False,
- 'auto_power_on': False, # TODO
-
- 'memory_static_min': 64,
- 'memory_static_max': 128,
- #'memory_dynamic_min': 64,
- #'memory_dynamic_max': 128,
-
-
- 'VCPUs_policy': 'credit',
- 'VCPUs_params': {},
- 'VCPUs_number': 2,
-
- 'actions_after_shutdown': 'destroy',
- 'actions_after_reboot': 'restart',
- 'actions_after_crash': 'destroy',
-
- 'PV_bootloader': '',
- 'PV_bootloader_args': '',
-
- 'PV_kernel': '',
- 'PV_ramdisk': '',
- 'PV_args': '',
-
- 'HVM_boot': 'cda',
- 'platform_std_VGA': False,
- 'platform_serial': '',
- 'platform_localtime': False,
- 'platform_clock_offset': False,
- 'platform_enable_audio': False,
- 'PCI_bus': ''
-}
-
-local_vdi_cfg = {
- 'name_label': 'gentoo.hvm',
- 'name_description': '',
- 'virtual_size': 0,
- 'type': 'system',
- 'parent': '',
- 'SR_name': 'Local',
- 'sharable': False,
- 'read_only': False,
- 'other_config': {'location': 'file:/root/gentoo.amd64.hvm.img'},
-}
-
-local_vbd_cfg = {
- 'VDI': '',
- 'VM': '',
- 'device': 'hda',
- 'mode': 'RW',
- 'type': 'disk',
- 'driver': 'ioemu',
-}
-
-vif_cfg = {
- 'name': 'API_VIF',
- 'type': 'ioemu',
- 'device': '',
- 'network': '',
- 'MAC': '',
- 'MTU': 1500,
-}
-
-console_cfg = {
- 'protocol': 'rfb',
- 'other_config': {'vncunused': 1, 'vncpasswd': 'testing'},
-}
-
-
-import sys
-import time
-
-from xapi import connect, execute
-
-def test_vm_create():
- server, session = connect()
- vm_uuid = None
- local_vdi_uuid = None
- local_vbd_uuid = None
- vif_uuid = None
-
- # List all VMs
- vm_list = execute(server, 'VM.get_all', (session,))
- vm_names = []
- for vm_uuid in vm_list:
- vm_record = execute(server, 'VM.get_record', (session, vm_uuid))
- vm_names.append(vm_record['name_label'])
-
- # Get default SR
- local_sr_list = execute(server, 'SR.get_by_name_label',
- (session, local_vdi_cfg['SR_name']))
- local_sr_uuid = local_sr_list[0]
-
- # Get default network
- net_list = execute(server, 'network.get_all', (session,))
- net_uuid = net_list[0]
-
- try:
- # Create a new VM
- print 'Create VM'
- vm_uuid = execute(server, 'VM.create', (session, vm_cfg))
-
- print 'Create VDI'
- # Create a new VDI (Local)
- local_vdi_cfg['SR'] = local_sr_uuid
- local_vdi_uuid = execute(server, 'VDI.create',
- (session, local_vdi_cfg))
-
- print 'Create VBD'
- # Create a new VBD (Local)
- local_vbd_cfg['VM'] = vm_uuid
- local_vbd_cfg['VDI'] = local_vdi_uuid
- local_vbd_uuid = execute(server, 'VBD.create',
- (session, local_vbd_cfg))
-
- print 'Craete VIF'
- # Create a new VIF
- vif_cfg['network'] = net_uuid
- vif_cfg['VM'] = vm_uuid
- vif_uuid = execute(server, 'VIF.create', (session, vif_cfg))
-
- # Create a console
- console_cfg['VM'] = vm_uuid
- console_uuid = execute(server, 'console.create',
- (session, console_cfg))
- print console_uuid
-
- # Start the VM
- execute(server, 'VM.start', (session, vm_uuid, False))
-
- time.sleep(30)
-
- test_suspend = False
- if test_suspend:
- print 'Suspending VM..'
- execute(server, 'VM.suspend', (session, vm_uuid))
- print 'Suspended VM.'
- time.sleep(5)
- print 'Resuming VM ...'
- execute(server, 'VM.resume', (session, vm_uuid, False))
- print 'Resumed VM.'
-
- # Wait for user to say we're good to shut it down
- while True:
- destroy = raw_input('destroy VM? ')
- if destroy[0] in ('y', 'Y'):
- break
-
- finally:
- # Clean up
- if vif_uuid:
- execute(server, 'VIF.destroy', (session, vif_uuid))
-
- if local_vbd_uuid:
- execute(server, 'VBD.destroy', (session, local_vbd_uuid))
- if local_vdi_uuid:
- execute(server, 'VDI.destroy', (session, local_vdi_uuid))
-
- if vm_uuid:
- try:
- execute(server, 'VM.hard_shutdown', (session, vm_uuid))
- time.sleep(2)
- except:
- pass
- try:
- execute(server, 'VM.destroy', (session, vm_uuid))
- except:
- pass
-
-
-if __name__ == "__main__":
- test_vm_create()
-
diff --git a/tools/python/scripts/test_vm_create.py b/tools/python/scripts/test_vm_create.py
deleted file mode 100644
index 9ac8a6e..0000000
--- a/tools/python/scripts/test_vm_create.py
+++ /dev/null
@@ -1,211 +0,0 @@
-#!/usr/bin/python
-
-vm_cfg = {
- 'name_label': 'APIVM',
- 'user_version': 1,
- 'is_a_template': False,
- 'auto_power_on': False, # TODO
-
- 'memory_static_min': 64,
- 'memory_static_max': 128,
- #'memory_dynamic_min': 64,
- #'memory_dynamic_max': 128,
-
-
- 'VCPUs_policy': 'credit',
- 'VCPUs_params': '',
- 'VCPUs_number': 2,
-
- 'actions_after_shutdown': 'destroy',
- 'actions_after_reboot': 'restart',
- 'actions_after_crash': 'destroy',
-
- 'PV_bootloader': '',
- 'PV_bootloader_args': '',
-
- 'PV_kernel': '/boot/vmlinuz-2.6.18-xenU',
- 'PV_ramdisk': '',
- 'PV_args': 'root=/dev/sda1 ro',
-
- #'HVM_boot': '',
- 'platform_std_VGA': False,
- 'platform_serial': '',
- 'platform_localtime': False,
- 'platform_clock_offset': False,
- 'platform_enable_audio': False,
- 'PCI_bus': ''
-}
-
-vdi_cfg = {
- 'name_label': 'API_VDI',
- 'name_description': '',
- 'virtual_size': 100 * 1024 * 1024 * 1024,
- 'type': 'system',
- 'parent': '',
- 'SR_name': 'QCoW',
- 'sharable': False,
- 'read_only': False,
-}
-
-vbd_cfg = {
- 'VDI': '',
- 'VM': '',
- 'device': 'sda2',
- 'mode': 'RW',
- 'type': 'disk',
- 'driver': 'paravirtualised',
-}
-
-local_vdi_cfg = {
- 'name_label': 'gentoo.amd64.img',
- 'name_description': '',
- 'virtual_size': 0,
- 'type': 'system',
- 'parent': '',
- 'SR_name': 'Local',
- 'sharable': False,
- 'read_only': False,
- 'other_config': {'location': 'file:/root/gentoo.amd64.img'},
-}
-
-local_vbd_cfg = {
- 'VDI': '',
- 'VM': '',
- 'device': 'sda1',
- 'mode': 'RW',
- 'type': 'disk',
- 'driver': 'paravirtualised',
-}
-
-vif_cfg = {
- 'name': 'API_VIF',
- 'type': 'paravirtualised',
- 'device': '',
- 'network': '',
- 'MAC': '',
- 'MTU': 1500,
-}
-
-console_cfg = {
- 'protocol': 'rfb',
- 'other_config': {'vncunused': 1, 'vncpasswd': 'testing'},
-}
-
-import sys
-import time
-
-from xapi import connect, execute
-
-def test_vm_create():
- server, session = connect()
- vm_uuid = None
- vdi_uuid = None
- local_vdi_uuid = None
- local_vbd_uuid = None
- vbd_uuid = None
- vif_uuid = None
-
- # List all VMs
- vm_list = execute(server, 'VM.get_all', (session,))
- vm_names = []
- for vm_uuid in vm_list:
- vm_record = execute(server, 'VM.get_record', (session, vm_uuid))
- vm_names.append(vm_record['name_label'])
-
- # Get default SR
- sr_list = execute(server, 'SR.get_by_name_label', (session,
- vdi_cfg['SR_name']))
- sr_uuid = sr_list[0]
-
- local_sr_list = execute(server, 'SR.get_by_name_label',
- (session, local_vdi_cfg['SR_name']))
- local_sr_uuid = local_sr_list[0]
-
- # Get default network
- net_list = execute(server, 'network.get_all', (session,))
- net_uuid = net_list[0]
-
- try:
- # Create a new VM
- vm_uuid = execute(server, 'VM.create', (session, vm_cfg))
-
- # Create a new VDI
- vdi_cfg['SR'] = sr_uuid
- vdi_uuid = execute(server, 'VDI.create', (session, vdi_cfg))
-
- # Create a VDI backed VBD
- vbd_cfg['VM'] = vm_uuid
- vbd_cfg['VDI'] = vdi_uuid
- vbd_uuid = execute(server, 'VBD.create', (session, vbd_cfg))
-
- # Create a new VDI (Local)
- local_vdi_cfg['SR'] = local_sr_uuid
- local_vdi_uuid = execute(server, 'VDI.create',
- (session, local_vdi_cfg))
-
- # Create a new VBD (Local)
- local_vbd_cfg['VM'] = vm_uuid
- local_vbd_cfg['VDI'] = local_vdi_uuid
- local_vbd_uuid = execute(server, 'VBD.create',
- (session, local_vbd_cfg))
-
- # Create a new VIF
- vif_cfg['network'] = net_uuid
- vif_cfg['VM'] = vm_uuid
- vif_uuid = execute(server, 'VIF.create', (session, vif_cfg))
-
- # Create a console
- console_cfg['VM'] = vm_uuid
- console_uuid = execute(server, 'console.create',
- (session, console_cfg))
- print console_uuid
-
- # Start the VM
- execute(server, 'VM.start', (session, vm_uuid, False))
-
- time.sleep(30)
-
- test_suspend = False
- if test_suspend:
- print 'Suspending VM..'
- execute(server, 'VM.suspend', (session, vm_uuid))
- print 'Suspended VM.'
- time.sleep(5)
- print 'Resuming VM ...'
- execute(server, 'VM.resume', (session, vm_uuid, False))
- print 'Resumed VM.'
-
- finally:
- # Wait for user to say we're good to shut it down
- while True:
- destroy = raw_input('destroy VM? ')
- if destroy[0] in ('y', 'Y'):
- break
-
- # Clean up
- if vif_uuid:
- execute(server, 'VIF.destroy', (session, vif_uuid))
-
- if local_vbd_uuid:
- execute(server, 'VBD.destroy', (session, local_vbd_uuid))
- if local_vdi_uuid:
- execute(server, 'VDI.destroy', (session, local_vdi_uuid))
-
- if vbd_uuid:
- execute(server, 'VBD.destroy', (session, vbd_uuid))
- if vdi_uuid:
- execute(server, 'VDI.destroy', (session, vdi_uuid))
-
- if vm_uuid:
- try:
- execute(server, 'VM.hard_shutdown', (session, vm_uuid))
- time.sleep(2)
- except:
- pass
-
- execute(server, 'VM.destroy', (session, vm_uuid))
-
-
-if __name__ == "__main__":
- test_vm_create()
-
diff --git a/tools/python/scripts/xapi.domcfg.py b/tools/python/scripts/xapi.domcfg.py
deleted file mode 100644
index d7b8ae5..0000000
--- a/tools/python/scripts/xapi.domcfg.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# VM Configuration for Xen API
-#
-
-name_label = 'GentooAPI'
-name_description = 'Gentoo VM via API'
-user_version = 1
-is_a_template = False
-memory_static_max = 32
-memory_dynamic_max = 32
-memory_dynamic_min = 32
-memory_static_min = 32
-VCPUs_policy = ''
-VCPUs_params = ''
-VCPUS_features_required = ''
-VCPUs_features_can_use = ''
-VCPUs_features_force_on = ''
-VCPUs_features_force_off = ''
-actions_after_shutdown = 'destroy'
-actions_after_reboot = 'restart'
-actions_after_suspend = 'destroy'
-actions_after_crash = 'restart'
-bios_boot = ''
-platform_std_VGA = False
-platform_serial = ''
-platform_localtime = False
-platform_clock_offset = False
-platform_enable_audio = False
-builder = 'linux'
-boot_method = '' # this will remove the kernel/initrd ??
-kernel_kernel = '/boot/vmlinuz-2.6.16.29-xen'
-kernel_initrd = '/root/initrd-2.6.16.29-xen.img'
-kernel_args = 'root=/dev/sda1 ro'
-grub_cmdline = ''
-PCI_bus = ''
-other_config = ''
-
diff --git a/tools/python/scripts/xapi.py b/tools/python/scripts/xapi.py
deleted file mode 100644
index 0997187..0000000
--- a/tools/python/scripts/xapi.py
+++ /dev/null
@@ -1,854 +0,0 @@
-#!/usr/bin/python
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 XenSource Ltd.
-#============================================================================
-
-import sys
-import time
-import re
-import os
-
-from xen.util.xmlrpclib2 import ServerProxy
-from optparse import *
-from pprint import pprint
-from types import DictType
-from getpass import getpass
-
-# Get default values from the environment
-SERVER_URI = os.environ.get('XAPI_SERVER_URI', 'http://localhost:9363/')
-SERVER_USER = os.environ.get('XAPI_SERVER_USER', '')
-SERVER_PASS = os.environ.get('XAPI_SERVER_PASS', '')
-
-MB = 1024 * 1024
-
-HOST_INFO_FORMAT = '%-20s: %-50s'
-VM_LIST_FORMAT = '%(name_label)-18s %(memory_actual)-5s %(VCPUs_number)-5s'\
- ' %(power_state)-10s %(uuid)-36s'
-SR_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(physical_size)-10s' \
- '%(type)-10s'
-VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s'
-VBD_LIST_FORMAT = '%(device)-6s %(uuid)-36s %(VDI)-8s'
-TASK_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(status)-8s %(progress)-4s'
-VIF_LIST_FORMAT = '%(name)-8s %(device)-7s %(uuid)-36s %(MAC)-10s'
-CONSOLE_LIST_FORMAT = '%(uuid)-36s %(protocol)-8s %(location)-32s'
-
-COMMANDS = {
- 'host-info': ('', 'Get Xen Host Info'),
- 'host-set-name': ('', 'Set host name'),
- 'pif-list': ('', 'List all PIFs'),
- 'sr-list': ('', 'List all SRs'),
- 'vbd-list': ('', 'List all VBDs'),
- 'vbd-create': ('<domname> <pycfg> [opts]',
- 'Create VBD attached to domname'),
- 'vdi-create': ('<pycfg> [opts]', 'Create a VDI'),
- 'vdi-list' : ('', 'List all VDI'),
- 'vdi-rename': ('<vdi_uuid> <new_name>', 'Rename VDI'),
- 'vdi-destroy': ('<vdi_uuid>', 'Delete VDI'),
- 'vif-create': ('<domname> <pycfg>', 'Create VIF attached to domname'),
-
- 'vm-create': ('<pycfg>', 'Create VM with python config'),
- 'vm-destroy': ('<domname>', 'Delete VM'),
-
- 'vm-list': ('[--long]', 'List all domains.'),
- 'vm-name': ('<uuid>', 'Name of UUID.'),
- 'vm-shutdown': ('<name> [opts]', 'Shutdown VM with name'),
- 'vm-start': ('<name>', 'Start VM with name'),
- 'vm-uuid': ('<name>', 'UUID of a domain by name.'),
- 'async-vm-start': ('<name>', 'Start VM asynchronously'),
-}
-
-OPTIONS = {
- 'sr-list': [(('-l', '--long'),
- {'action':'store_true',
- 'help':'List all properties of SR'})
- ],
-
- 'vdi-list': [(('-l', '--long'),
- {'action':'store_true',
- 'help':'List all properties of VDI'})
- ],
- 'vif-list': [(('-l', '--long'),
- {'action':'store_true',
- 'help':'List all properties of VIF'})
- ],
- 'vm-list': [(('-l', '--long'),
- {'action':'store_true',
- 'help':'List all properties of VMs'})
- ],
- 'vm-shutdown': [(('-f', '--force'), {'help': 'Shutdown Forcefully',
- 'action': 'store_true'})],
-
- 'vdi-create': [(('--name-label',), {'help': 'Name for VDI'}),
- (('--name-description',), {'help': 'Description for VDI'}),
- (('--virtual-size',), {'type': 'int',
- 'default': 0,
- 'help': 'Size of VDI in bytes'}),
- (('--type',), {'choices': ['system', 'user', 'ephemeral'],
- 'default': 'system',
- 'help': 'VDI type'}),
- (('--sharable',), {'action': 'store_true',
- 'help': 'VDI sharable'}),
- (('--read-only',), {'action': 'store_true',
- 'help': 'Read only'}),
- (('--sr',), {})],
-
- 'vbd-create': [(('--VDI',), {'help': 'UUID of VDI to attach to.'}),
- (('--mode',), {'choices': ['RO', 'RW'],
- 'help': 'device mount mode'}),
- (('--driver',), {'choices':['paravirtualised', 'ioemu'],
- 'help': 'Driver for VBD'}),
- (('--device',), {'help': 'Device name on guest domain'})]
-
-}
-
-class OptionError(Exception):
- pass
-
-class XenAPIError(Exception):
- pass
-
-#
-# Extra utility functions
-#
-
-class IterableValues(Values):
- """Better interface to the list of values from optparse."""
-
- def __iter__(self):
- for opt, val in self.__dict__.items():
- if opt[0] == '_' or callable(val):
- continue
- yield opt, val
-
-
-def parse_args(cmd_name, args, set_defaults = False):
- argstring, desc = COMMANDS[cmd_name]
- parser = OptionParser(usage = 'xapi %s %s' % (cmd_name, argstring),
- description = desc)
- if cmd_name in OPTIONS:
- for optargs, optkwds in OPTIONS[cmd_name]:
- parser.add_option(*optargs, **optkwds)
-
- if set_defaults:
- default_values = parser.get_default_values()
- defaults = IterableValues(default_values.__dict__)
- else:
- defaults = IterableValues()
- (opts, extraargs) = parser.parse_args(args = list(args),
- values = defaults)
- return opts, extraargs
-
-def execute(server, fn, args, async = False):
- if async:
- func = eval('server.Async.%s' % fn)
- else:
- func = eval('server.%s' % fn)
-
- result = func(*args)
- if type(result) != DictType:
- raise TypeError("Function returned object of type: %s" %
- str(type(result)))
- if 'Value' not in result:
- raise XenAPIError(*result['ErrorDescription'])
- return result['Value']
-
-_initialised = False
-_server = None
-_session = None
-def connect(*args):
- global _server, _session, _initialised
-
- if not _initialised:
- # try without password or default credentials
- try:
- _server = ServerProxy(SERVER_URI)
- _session = execute(_server.session, 'login_with_password',
- (SERVER_USER, SERVER_PASS))
- except:
- login = raw_input("Login: ")
- password = getpass()
- creds = (login, password)
- _server = ServerProxy(SERVER_URI)
- _session = execute(_server.session, 'login_with_password',
- creds)
-
- _initialised = True
- return (_server, _session)
-
-def _stringify(adict):
- return dict([(k, str(v)) for k, v in adict.items()])
-
-def _read_python_cfg(filename):
- cfg = {}
- execfile(filename, {}, cfg)
- return cfg
-
-def resolve_vm(server, session, vm_name):
- vm_uuid = execute(server, 'VM.get_by_name_label', (session, vm_name))
- if not vm_uuid:
- return None
- else:
- return vm_uuid[0]
-
-def resolve_vdi(server, session, vdi_name):
- vdi_uuid = execute(server, 'VDI.get_by_name_label', (session, vdi_name))
- if not vdi_uuid:
- return None
- else:
- return vdi_uuid[0]
-
-#
-# Actual commands
-#
-
-def xapi_host_info(args, async = False):
- server, session = connect()
- hosts = execute(server, 'host.get_all', (session,))
- for host in hosts: # there is only one, but ..
- hostinfo = execute(server, 'host.get_record', (session, host))
- print HOST_INFO_FORMAT % ('Name', hostinfo['name_label'])
- print HOST_INFO_FORMAT % ('Version', hostinfo['software_version'])
- print HOST_INFO_FORMAT % ('CPUs', len(hostinfo['host_CPUs']))
- print HOST_INFO_FORMAT % ('VMs', len(hostinfo['resident_VMs']))
- print HOST_INFO_FORMAT % ('UUID', host)
-
- for host_cpu_uuid in hostinfo['host_CPUs']:
- host_cpu = execute(server, 'host_cpu.get_record',
- (session, host_cpu_uuid))
- print 'CPU %s Util: %.2f' % (host_cpu['number'],
- float(host_cpu['utilisation']))
-
-def xapi_host_set_name(args, async = False):
- if len(args) < 1:
- raise OptionError("No hostname specified")
-
- server, session = connect()
- hosts = execute(server, 'host.get_all', (session,))
- if len(hosts) > 0:
- execute(server, 'host.set_name_label', (session, hosts[0], args[0]))
- print 'Hostname: %s' % execute(server, 'host.get_name_label',
- (session, hosts[0]))
-
-def xapi_vm_uuid(args, async = False):
- if len(args) < 1:
- raise OptionError("No domain name specified")
-
- server, session = connect()
- vm_uuid = resolve_vm(server, session, args[0])
- print vm_uuid
-
-def xapi_vm_name(args, async = False):
- if len(args) < 1:
- raise OptionError("No UUID specified")
-
- server, session = connect()
- vm_name = execute(server, 'VM.get_name_label', (session, args[0]))
- print vm_name
-
-def xapi_vm_list(args, async = False):
- opts, args = parse_args('vm-list', args, set_defaults = True)
- is_long = opts and opts.long
-
- list_only = args
-
- server, session = connect()
- vm_uuids = execute(server, 'VM.get_all', (session,))
- if not is_long:
- print VM_LIST_FORMAT % {'name_label':'Name',
- 'memory_actual':'Mem',
- 'VCPUs_number': 'VCPUs',
- 'power_state': 'State',
- 'uuid': 'UUID'}
-
- for uuid in vm_uuids:
- vm_info = execute(server, 'VM.get_record', (session, uuid))
-
- # skip domain if we don't want
- if list_only and vm_info['name_label'] not in list_only:
- continue
-
- if is_long:
- vbds = vm_info['VBDs']
- vifs = vm_info['VIFs']
- vif_infos = []
- vbd_infos = []
- for vbd in vbds:
- vbd_info = execute(server, 'VBD.get_record', (session, vbd))
- vbd_infos.append(vbd_info)
- for vif in vifs:
- vif_info = execute(server, 'VIF.get_record', (session, vif))
- vif_infos.append(vif_info)
- vm_info['VBDs'] = vbd_infos
- vm_info['VIFs'] = vif_infos
- pprint(vm_info)
- else:
- print VM_LIST_FORMAT % _stringify(vm_info)
-
-def xapi_vm_create(args, async = False):
- if len(args) < 1:
- raise OptionError("Configuration file not specified")
-
- filename = args[0]
- cfg = _read_python_cfg(filename)
-
- print 'Creating VM from %s ..' % filename
- server, session = connect()
- uuid = execute(server, 'VM.create', (session, cfg), async = async)
- print 'Done. (%s)' % uuid
- print uuid
-
-def xapi_vm_destroy(args, async = False):
- if len(args) < 1:
- raise OptionError("No domain name specified.")
-
- server, session = connect()
- vm_uuid = resolve_vm(server, session, args[0])
- print 'Destroying VM %s (%s)' % (args[0], vm_uuid)
- success = execute(server, 'VM.destroy', (session, vm_uuid), async = async)
- print 'Done.'
-
-
-def xapi_vm_start(args, async = False):
- if len(args) < 1:
- raise OptionError("No Domain name specified.")
-
- server, session = connect()
- vm_uuid = resolve_vm(server, session, args[0])
- print 'Starting VM %s (%s)' % (args[0], vm_uuid)
- success = execute(server, 'VM.start', (session, vm_uuid, False), async = async)
- if async:
- print 'Task started: %s' % success
- else:
- print 'Done.'
-
-def xapi_vm_suspend(args, async = False):
- if len(args) < 1:
- raise OptionError("No Domain name specified.")
-
- server, session = connect()
- vm_uuid = resolve_vm(server, session, args[0])
- print 'Suspending VM %s (%s)' % (args[0], vm_uuid)
- success = execute(server, 'VM.suspend', (session, vm_uuid), async = async)
- if async:
- print 'Task started: %s' % success
- else:
- print 'Done.'
-
-
-def xapi_vm_resume(args, async = False):
- if len(args) < 1:
- raise OptionError("No Domain name specified.")
-
- server, session = connect()
- vm_uuid = resolve_vm(server, session, args[0])
- print 'Resuming VM %s (%s)' % (args[0], vm_uuid)
- success = execute(server, 'VM.resume', (session, vm_uuid, False), async = async)
- if async:
- print 'Task started: %s' % success
- else:
- print 'Done.'
-
-def xapi_vm_pause(args, async = False):
- if len(args) < 1:
- raise OptionError("No Domain name specified.")
-
- server, session = connect()
- vm_uuid = resolve_vm(server, session, args[0])
- print 'Pausing VM %s (%s)' % (args[0], vm_uuid)
- success = execute(server, 'VM.pause', (session, vm_uuid), async = async)
- if async:
- print 'Task started: %s' % success
- else:
- print 'Done.'
-
-def xapi_vm_unpause(args, async = False):
- if len(args) < 1:
- raise OptionError("No Domain name specified.")
-
- server, session = connect()
- vm_uuid = resolve_vm(server, session, args[0])
- print 'Pausing VM %s (%s)' % (args[0], vm_uuid)
- success = execute(server, 'VM.unpause', (session, vm_uuid), async = async)
- if async:
- print 'Task started: %s' % success
- else:
- print 'Done.'
-
-def xapi_task_list(args, async = False):
- server, session = connect()
- all_tasks = execute(server, 'task.get_all', (session,))
-
- print TASK_LIST_FORMAT % {'name_label': 'Task Name',
- 'uuid': 'UUID',
- 'status': 'Status',
- 'progress': '%'}
-
- for task_uuid in all_tasks:
- task = execute(server, 'task.get_record', (session, task_uuid))
- print TASK_LIST_FORMAT % task
-
-def xapi_task_clear(args, async = False):
- server, session = connect()
- all_tasks = execute(server, 'task.get_all', (session,))
- for task_uuid in all_tasks:
- success = execute(server, 'task.destroy', (session, task_uuid))
- print 'Destroyed Task %s' % task_uuid
-
-def xapi_vm_shutdown(args, async = False):
- opts, args = parse_args("vm-shutdown", args, set_defaults = True)
-
- if len(args) < 1:
- raise OptionError("No Domain name specified.")
-
- server, session = connect()
- vm_uuid = resolve_vm(server, session, args[0])
- if opts.force:
- print 'Forcefully shutting down VM %s (%s)' % (args[0], vm_uuid)
- success = execute(server, 'VM.hard_shutdown', (session, vm_uuid), async = async)
- else:
- print 'Shutting down VM %s (%s)' % (args[0], vm_uuid)
- success = execute(server, 'VM.clean_shutdown', (session, vm_uuid), async = async)
-
- if async:
- print 'Task started: %s' % success
- else:
- print 'Done.'
-
-def xapi_vbd_create(args, async = False):
- opts, args = parse_args('vbd-create', args)
-
- if len(args) < 2:
- raise OptionError("Configuration file and domain not specified")
-
- domname = args[0]
-
- if len(args) > 1:
- filename = args[1]
- cfg = _read_python_cfg(filename)
- else:
- cfg = {}
-
- for opt, val in opts:
- cfg[opt] = val
-
- print 'Creating VBD ...',
- server, session = connect()
- vm_uuid = resolve_vm(server, session, domname)
- cfg['VM'] = vm_uuid
- vbd_uuid = execute(server, 'VBD.create', (session, cfg), async = async)
- if async:
- print 'Task started: %s' % vbd_uuid
- else:
- print 'Done. (%s)' % vbd_uuid
-
-def xapi_vif_create(args, async = False):
- if len(args) < 2:
- raise OptionError("Configuration file not specified")
-
- domname = args[0]
- filename = args[1]
- cfg = _read_python_cfg(filename)
-
- print 'Creating VIF from %s ..' % filename
- server, session = connect()
- vm_uuid = resolve_vm(server, session, domname)
- cfg['VM'] = vm_uuid
- vif_uuid = execute(server, 'VIF.create', (session, cfg), async = async)
- if async:
- print 'Task started: %s' % vif_uuid
- else:
- print 'Done. (%s)' % vif_uuid
-
-def xapi_vbd_list(args, async = False):
- server, session = connect()
- domname = args[0]
-
- dom_uuid = resolve_vm(server, session, domname)
- vbds = execute(server, 'VM.get_VBDs', (session, dom_uuid))
-
- print VBD_LIST_FORMAT % {'device': 'Device',
- 'uuid' : 'UUID',
- 'VDI': 'VDI'}
-
- for vbd in vbds:
- vbd_struct = execute(server, 'VBD.get_record', (session, vbd))
- print VBD_LIST_FORMAT % vbd_struct
-
-
-def xapi_vbd_stats(args, async = False):
- server, session = connect()
- domname = args[0]
- dom_uuid = resolve_vm(server, session, domname)
-
- vbds = execute(server, 'VM.get_VBDs', (session, dom_uuid))
- for vbd_uuid in vbds:
- print execute(server, 'VBD.get_io_read_kbs', (session, vbd_uuid))
-
-def xapi_vif_list(args, async = False):
- server, session = connect()
- opts, args = parse_args('vdi-list', args, set_defaults = True)
- is_long = opts and opts.long
-
- domname = args[0]
-
- dom_uuid = resolve_vm(server, session, domname)
- vifs = execute(server, 'VM.get_VIFs', (session, dom_uuid))
-
- if not is_long:
- print VIF_LIST_FORMAT % {'name': 'Name',
- 'device': 'Device',
- 'uuid' : 'UUID',
- 'MAC': 'MAC'}
-
- for vif in vifs:
- vif_struct = execute(server, 'VIF.get_record', (session, vif))
- print VIF_LIST_FORMAT % vif_struct
- else:
- for vif in vifs:
- vif_struct = execute(server, 'VIF.get_record', (session, vif))
- pprint(vif_struct)
-
-def xapi_console_list(args, async = False):
- server, session = connect()
- opts, args = parse_args('vdi-list', args, set_defaults = True)
- is_long = opts and opts.long
-
- domname = args[0]
-
- dom_uuid = resolve_vm(server, session, domname)
- consoles = execute(server, 'VM.get_consoles', (session, dom_uuid))
-
- if not is_long:
- print CONSOLE_LIST_FORMAT % {'protocol': 'Protocol',
- 'location': 'Location',
- 'uuid': 'UUID'}
-
- for console in consoles:
- console_struct = execute(server, 'console.get_record',
- (session, console))
- print CONSOLE_LIST_FORMAT % console_struct
- else:
- for console in consoles:
- console_struct = execute(server, 'console.get_record',
- (session, console))
- pprint(console_struct)
-
-
-def xapi_vdi_list(args, async = False):
- opts, args = parse_args('vdi-list', args, set_defaults = True)
- is_long = opts and opts.long
-
- server, session = connect()
- vdis = execute(server, 'VDI.get_all', (session,))
-
- if not is_long:
- print VDI_LIST_FORMAT % {'name_label': 'VDI Label',
- 'uuid' : 'UUID',
- 'virtual_size': 'Bytes'}
-
- for vdi in vdis:
- vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
- print VDI_LIST_FORMAT % vdi_struct
-
- else:
- for vdi in vdis:
- vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
- pprint(vdi_struct)
-
-def xapi_sr_list(args, async = False):
- opts, args = parse_args('sr-list', args, set_defaults = True)
- is_long = opts and opts.long
-
- server, session = connect()
- srs = execute(server, 'SR.get_all', (session,))
- if not is_long:
- print SR_LIST_FORMAT % {'name_label': 'SR Label',
- 'uuid' : 'UUID',
- 'physical_size': 'Size (MB)',
- 'type': 'Type'}
-
- for sr in srs:
- sr_struct = execute(server, 'SR.get_record', (session, sr))
- sr_struct['physical_size'] = int(sr_struct['physical_size'])/MB
- print SR_LIST_FORMAT % sr_struct
- else:
- for sr in srs:
- sr_struct = execute(server, 'SR.get_record', (session, sr))
- pprint(sr_struct)
-
-def xapi_sr_rename(args, async = False):
- server, session = connect()
- sr = execute(server, 'SR.get_by_name_label', (session, args[0]))
- execute(server, 'SR.set_name_label', (session, sr[0], args[1]))
-
-def xapi_vdi_create(args, async = False):
- opts, args = parse_args('vdi-create', args)
-
- if len(args) > 0:
- cfg = _read_python_cfg(args[0])
- else:
- cfg = {}
-
- for opt, val in opts:
- cfg[opt] = val
-
- server, session = connect()
- srs = []
- if cfg.get('SR'):
- srs = execute(server, 'SR.get_by_name_label', (session, cfg['SR']))
- else:
- srs = execute(server, 'SR.get_all', (session,))
-
- sr = srs[0]
- cfg['SR'] = sr
-
- size = cfg['virtual_size']/MB
- print 'Creating VDI of size: %dMB ..' % size,
- uuid = execute(server, 'VDI.create', (session, cfg), async = async)
- if async:
- print 'Task started: %s' % uuid
- else:
- print 'Done. (%s)' % uuid
-
-
-def xapi_vdi_destroy(args, async = False):
- server, session = connect()
- if len(args) < 1:
- raise OptionError('Not enough arguments')
-
- vdi_uuid = args[0]
- print 'Deleting VDI %s' % vdi_uuid
- result = execute(server, 'VDI.destroy', (session, vdi_uuid), async = async)
- if async:
- print 'Task started: %s' % result
- else:
- print 'Done.'
-
-def xapi_vdi_rename(args, async = False):
- server, session = connect()
- if len(args) < 2:
- raise OptionError('Not enough arguments')
-
- vdi_uuid = execute(server, 'VDI.get_by_name_label', session, args[0])
- vdi_name = args[1]
-
- print 'Renaming VDI %s to %s' % (vdi_uuid[0], vdi_name)
- result = execute(server, 'VDI.set_name_label',
- (session, vdi_uuid[0], vdi_name), async = async)
- if async:
- print 'Task started: %s' % result
- else:
- print 'Done.'
-
-
-def xapi_pif_list(args, async = False):
- server, session = connect()
- pif_uuids = execute(server, 'PIF.get_all', (session,))
- for pif_uuid in pif_uuids:
- pif = execute(server, 'PIF.get_record', (session, pif_uuid))
- print pif
-
-
-def xapi_debug_wait(args, async = False):
- secs = 10
- if len(args) > 0:
- secs = int(args[0])
- server, session = connect()
- task_uuid = execute(server, 'debug.wait', (session, secs), async=async)
- print 'Task UUID: %s' % task_uuid
-
-def xapi_vm_stat(args, async = False):
- domname = args[0]
-
- server, session = connect()
- vm_uuid = resolve_vm(server, session, domname)
- vif_uuids = execute(server, 'VM.get_VIFs', (session, vm_uuid))
- vbd_uuids = execute(server, 'VM.get_VBDs', (session, vm_uuid))
- vcpus_utils = execute(server, 'VM.get_VCPUs_utilisation',
- (session, vm_uuid))
-
- for vcpu_num in sorted(vcpus_utils.keys()):
- print 'CPU %s : %5.2f%%' % (vcpu_num, vcpus_utils[vcpu_num] * 100)
-
- for vif_uuid in vif_uuids:
- vif = execute(server, 'VIF.get_record', (session, vif_uuid))
- print '%(device)s: rx: %(io_read_kbs)10.2f tx: %(io_write_kbs)10.2f' \
- % vif
- for vbd_uuid in vbd_uuids:
- vbd = execute(server, 'VBD.get_record', (session, vbd_uuid))
- print '%(device)s: rd: %(io_read_kbs)10.2f wr: %(io_write_kbs)10.2f' \
- % vbd
-
-#
-# Command Line Utils
-#
-import cmd
-import shlex
-
-class XenAPICmd(cmd.Cmd):
- def __init__(self, server, session):
- cmd.Cmd.__init__(self)
- self.server = server
- self.session = session
- self.prompt = ">>> "
-
- def default(self, line):
- words = shlex.split(line)
- if len(words) > 0:
- cmd_name = words[0].replace('-', '_')
- is_async = 'async' in cmd_name
- if is_async:
- cmd_name = re.sub('async_', '', cmd_name)
-
- func_name = 'xapi_%s' % cmd_name
- func = globals().get(func_name)
-
- if func:
- try:
- args = tuple(words[1:])
- func(args, async = is_async)
- return True
- except SystemExit:
- return False
- except OptionError, e:
- print 'Error:', str(e)
- return False
- except Exception, e:
- import traceback
- traceback.print_exc()
- return False
- print '*** Unknown command: %s' % words[0]
- return False
-
- def do_EOF(self, line):
- print
- sys.exit(0)
-
- def do_help(self, line):
- usage(print_usage = False)
-
- def emptyline(self):
- pass
-
- def postcmd(self, stop, line):
- return False
-
- def precmd(self, line):
- words = shlex.split(line)
- if len(words) > 0:
- words0 = words[0].replace('-', '_')
- return ' '.join([words0] + words[1:])
- else:
- return line
-
-def shell():
- server, session = connect()
- x = XenAPICmd(server, session)
- x.cmdloop('Xen API Prompt. Type "help" for a list of functions')
-
-def usage(command = None, print_usage = True):
- if not command:
- if print_usage:
- print 'Usage: xapi <subcommand> [options] [args]'
- print
- print 'Subcommands:'
- print
-
- for func in sorted(globals().keys()):
- if func.startswith('xapi_'):
- command = func[5:].replace('_', '-')
- args, description = COMMANDS.get(command, ('', ''))
- print '%-16s %-40s' % (command, description)
- print
- else:
- parse_args(command, ['-h'])
-
-def main(args):
-
- # poor man's optparse that doesn't abort on unrecognised opts
-
- options = {}
- remaining = []
-
- arg_n = 0
- while args:
- arg = args.pop(0)
-
- if arg in ('--help', '-h'):
- options['help'] = True
- elif arg in ('--server', '-s') and args:
- options['server'] = args.pop(0)
- elif arg in ('--user', '-u') and args:
- options['user'] = args.pop(0)
- elif arg in ('--password', '-p') and args:
- options['password'] = args.pop(0)
- else:
- remaining.append(arg)
-
- # abort here if these conditions are true
-
- if options.get('help') and not remaining:
- usage()
- sys.exit(1)
-
- if options.get('help') and remaining:
- usage(remaining[0])
- sys.exit(1)
-
- if not remaining:
- usage()
- sys.exit(1)
-
- if options.get('server'):
- # it is ugly to use a global, but it is simple
- global SERVER_URI
- SERVER_URI = options['server']
-
- if options.get('user'):
- global SERVER_USER
- SERVER_USER = options['user']
-
- if options.get('password'):
- global SERVER_PASS
- SERVER_PASS = options['password']
-
- subcmd = remaining[0].replace('-', '_')
- is_async = 'async' in subcmd
- if is_async:
- subcmd = re.sub('async_', '', subcmd)
- subcmd_func_name = 'xapi_' + subcmd
- subcmd_func = globals().get(subcmd_func_name, None)
-
- if subcmd == 'shell':
- shell()
- elif not subcmd_func or not callable(subcmd_func):
- print 'Error: Unable to find subcommand \'%s\'' % subcmd
- usage()
- sys.exit(1)
-
- try:
- subcmd_func(remaining[1:], async = is_async)
- except XenAPIError, e:
- print 'Error: %s' % str(e.args[0])
- sys.exit(2)
- except OptionError, e:
- print 'Error: %s' % e
-
- sys.exit(0)
-
-if __name__ == "__main__":
- import sys
- main(sys.argv[1:])
diff --git a/tools/python/scripts/xapi.vbdcfg.py b/tools/python/scripts/xapi.vbdcfg.py
deleted file mode 100644
index 82dcaf8..0000000
--- a/tools/python/scripts/xapi.vbdcfg.py
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Virtual Block Device (VBD) Xen API Configuration
-#
-# Note: There is a non-API field here called "image" which is a backwards
-# compat addition so you can mount to old images.
-#
-
-VDI = ''
-device = 'sda1'
-mode = 'RW'
-driver = 'paravirtualised'
-image = 'file:/root/gentoo.amd64.img'
diff --git a/tools/python/scripts/xapi.vdicfg.py b/tools/python/scripts/xapi.vdicfg.py
deleted file mode 100644
index cb63653..0000000
--- a/tools/python/scripts/xapi.vdicfg.py
+++ /dev/null
@@ -1,6 +0,0 @@
-name_label = 'VDI 1'
-name_description = ''
-virtual_size = 10 * 1024 * 1024 * 1024
-type = 'system'
-sharable = False
-read_only = False
diff --git a/tools/python/scripts/xapi.vifcfg.py b/tools/python/scripts/xapi.vifcfg.py
deleted file mode 100644
index f421224..0000000
--- a/tools/python/scripts/xapi.vifcfg.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Virtual Network Interface Configuration for the Xen API
-#
-
-name = ''
-type = 'paravirtualised'
-#device = 'eth0' # this is the dom0 device, not domU!
-network = '' # ignored
-MAC = ''
-MTU = '1500'
diff --git a/tools/python/scripts/xapi.vtpmcfg.py b/tools/python/scripts/xapi.vtpmcfg.py
deleted file mode 100644
index 7c419ba..0000000
--- a/tools/python/scripts/xapi.vtpmcfg.py
+++ /dev/null
@@ -1,3 +0,0 @@
-type = 'paravirtualised'
-backend = 'Domain-0'
-instance = 1
diff --git a/tools/python/setup.py b/tools/python/setup.py
index 8127b21..439c429 100644
--- a/tools/python/setup.py
+++ b/tools/python/setup.py
@@ -13,7 +13,7 @@ PATH_XENSTORE = XEN_ROOT + "/tools/xenstore"
xc = Extension("xc",
extra_compile_args = extra_compile_args,
- include_dirs = [ PATH_XEN, PATH_LIBXC, "xen/lowlevel/xc" ],
+ include_dirs = [ PATH_XEN, PATH_LIBXC + "/include", "xen/lowlevel/xc" ],
library_dirs = [ PATH_LIBXC ],
libraries = [ "xenctrl", "xenguest" ],
depends = [ PATH_LIBXC + "/libxenctrl.so", PATH_LIBXC + "/libxenguest.so" ],
@@ -21,121 +21,30 @@ xc = Extension("xc",
xs = Extension("xs",
extra_compile_args = extra_compile_args,
- include_dirs = [ PATH_XEN, PATH_XENSTORE, "xen/lowlevel/xs" ],
+ include_dirs = [ PATH_XEN, PATH_XENSTORE + "/include", "xen/lowlevel/xs" ],
library_dirs = [ PATH_XENSTORE ],
libraries = [ "xenstore" ],
depends = [ PATH_XENSTORE + "/libxenstore.so" ],
sources = [ "xen/lowlevel/xs/xs.c" ])
-scf = Extension("scf",
- extra_compile_args = extra_compile_args,
- include_dirs = [ "xen/lowlevel/scf" ],
- library_dirs = [ ],
- libraries = [ ],
- depends = [ ],
- sources = [ "xen/lowlevel/scf/scf.c" ])
-
-process = Extension("process",
- extra_compile_args = extra_compile_args,
- include_dirs = [ "xen/lowlevel/process" ],
- library_dirs = [ ],
- libraries = [ "contract" ],
- depends = [ ],
- sources = [ "xen/lowlevel/process/process.c" ])
-
-flask = Extension("flask",
- extra_compile_args = extra_compile_args,
- include_dirs = [ PATH_XEN, PATH_LIBXC, "xen/lowlevel/flask" ],
- library_dirs = [ PATH_LIBXC ],
- libraries = [ "xenctrl" ],
- depends = [ PATH_LIBXC + "/libxenctrl.so" ],
- sources = [ "xen/lowlevel/flask/flask.c" ])
-
-ptsname = Extension("ptsname",
- extra_compile_args = extra_compile_args,
- include_dirs = [ "ptsname" ],
- library_dirs = [ ],
- libraries = [ ],
- depends = [ ],
- sources = [ "ptsname/ptsname.c" ])
-
-checkpoint = Extension("checkpoint",
- extra_compile_args = extra_compile_args,
- include_dirs = [ PATH_XEN, PATH_LIBXC, PATH_XENSTORE ],
- library_dirs = [ PATH_LIBXC, PATH_XENSTORE ],
- libraries = [ "xenctrl", "xenguest", "xenstore", "rt" ],
- depends = [ PATH_LIBXC + "/libxenctrl.so",
- PATH_LIBXC + "/libxenguest.so",
- PATH_XENSTORE + "/libxenstore.so" ],
- sources = [ "xen/lowlevel/checkpoint/checkpoint.c",
- "xen/lowlevel/checkpoint/libcheckpoint.c"])
-
-netlink = Extension("netlink",
- extra_compile_args = extra_compile_args,
- include_dirs = [ ],
- library_dirs = [ ],
- libraries = [ ],
- depends = [ ],
- sources = [ "xen/lowlevel/netlink/netlink.c",
- "xen/lowlevel/netlink/libnetlink.c"])
-
xl = Extension("xl",
extra_compile_args = extra_compile_args,
- include_dirs = [ PATH_XEN, PATH_LIBXL, PATH_LIBXC, "xen/lowlevel/xl" ],
+ include_dirs = [ PATH_XEN, PATH_LIBXL, PATH_LIBXC + "/include", "xen/lowlevel/xl" ],
library_dirs = [ PATH_LIBXL ],
libraries = [ "xenlight" ],
depends = [ PATH_LIBXL + "/libxenlight.so" ],
sources = [ "xen/lowlevel/xl/xl.c", "xen/lowlevel/xl/_pyxl_types.c" ])
plat = os.uname()[0]
-modules = [ xc, xs, ptsname, flask ]
+modules = [ xc, xs ]
#modules.extend([ xl ])
-if plat == 'SunOS':
- modules.extend([ scf, process ])
-if plat == 'Linux':
- modules.extend([ checkpoint, netlink ])
-
-enable_xend = True
-new_argv = []
-for arg in sys.argv:
- if arg == "--xend=y":
- enable_xend = True
- elif arg == "--xend=n":
- enable_xend = False
- else:
- new_argv.append(arg)
-sys.argv = new_argv
-
-if enable_xend:
- xend_packages = [
- 'xen.util',
- 'xen.util.xsm',
- 'xen.util.xsm.dummy',
- 'xen.util.xsm.flask',
- 'xen.util.xsm.acm',
- 'xen.xend',
- 'xen.xend.server',
- 'xen.xend.xenstore',
- 'xen.xm',
- 'xen.web',
- 'xen.remus',
- 'xen.xend.tests',
- 'xen.xend.server.tests',
- 'xen.xend.xenstore.tests',
- 'xen.xm.tests'
- ]
-else:
- xend_packages = []
setup(name = 'xen',
version = '3.0',
description = 'Xen',
packages = ['xen',
'xen.lowlevel',
- ] + xend_packages,
+ ],
ext_package = "xen.lowlevel",
ext_modules = modules
)
-
-os.chdir('logging')
-execfile('setup.py')
diff --git a/tools/python/xen/lowlevel/checkpoint/checkpoint.c b/tools/python/xen/lowlevel/checkpoint/checkpoint.c
deleted file mode 100644
index c5cdd83..0000000
--- a/tools/python/xen/lowlevel/checkpoint/checkpoint.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/* python bridge to checkpointing API */
-
-#include <Python.h>
-
-#include <xenstore.h>
-#include <xenctrl.h>
-
-#include "checkpoint.h"
-
-#define PKG "xen.lowlevel.checkpoint"
-
-static PyObject* CheckpointError;
-
-typedef struct {
- PyObject_HEAD
- checkpoint_state cps;
-
- /* milliseconds between checkpoints */
- unsigned int interval;
- int armed;
-
- PyObject* suspend_cb;
- PyObject* postcopy_cb;
- PyObject* checkpoint_cb;
-
- PyThreadState* threadstate;
-} CheckpointObject;
-
-static int suspend_trampoline(void* data);
-static int postcopy_trampoline(void* data);
-static int checkpoint_trampoline(void* data);
-
-static PyObject* Checkpoint_new(PyTypeObject* type, PyObject* args,
- PyObject* kwargs)
-{
- CheckpointObject* self = (CheckpointObject*)type->tp_alloc(type, 0);
-
- if (!self)
- return NULL;
-
- checkpoint_init(&self->cps);
- self->suspend_cb = NULL;
- self->armed = 0;
-
- return (PyObject*)self;
-}
-
-static int Checkpoint_init(PyObject* obj, PyObject* args, PyObject* kwargs)
-{
- return 0;
-}
-
-static void Checkpoint_dealloc(CheckpointObject* self)
-{
- checkpoint_close(&self->cps);
-
- self->ob_type->tp_free((PyObject*)self);
-}
-
-static PyObject* pycheckpoint_open(PyObject* obj, PyObject* args)
-{
- CheckpointObject* self = (CheckpointObject*)obj;
- checkpoint_state* cps = &self->cps;
- unsigned int domid;
-
- if (!PyArg_ParseTuple(args, "I", &domid))
- return NULL;
-
- if (checkpoint_open(cps, domid) < 0) {
- PyErr_SetString(CheckpointError, checkpoint_error(cps));
-
- return NULL;
- }
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject* pycheckpoint_close(PyObject* obj, PyObject* args)
-{
- CheckpointObject* self = (CheckpointObject*)obj;
-
- if (checkpoint_resume(&self->cps) < 0)
- fprintf(stderr, "%s\n", checkpoint_error(&self->cps));
-
- checkpoint_close(&self->cps);
-
- Py_XDECREF(self->suspend_cb);
- self->suspend_cb = NULL;
- Py_XDECREF(self->postcopy_cb);
- self->postcopy_cb = NULL;
- Py_XDECREF(self->checkpoint_cb);
- self->checkpoint_cb = NULL;
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject* pycheckpoint_start(PyObject* obj, PyObject* args) {
- CheckpointObject* self = (CheckpointObject*)obj;
-
- PyObject* iofile;
- PyObject* suspend_cb = NULL;
- PyObject* postcopy_cb = NULL;
- PyObject* checkpoint_cb = NULL;
- unsigned int interval = 0;
- unsigned int flags = 0;
-
- int fd;
- struct save_callbacks callbacks;
- int rc;
-
- if (!PyArg_ParseTuple(args, "O|OOOII", &iofile, &suspend_cb, &postcopy_cb,
- &checkpoint_cb, &interval, &flags))
- return NULL;
-
- self->interval = interval;
-
- Py_INCREF(iofile);
- Py_XINCREF(suspend_cb);
- Py_XINCREF(postcopy_cb);
- Py_XINCREF(checkpoint_cb);
-
- fd = PyObject_AsFileDescriptor(iofile);
- Py_DECREF(iofile);
- if (fd < 0) {
- PyErr_SetString(PyExc_TypeError, "invalid file handle");
- return NULL;
- }
-
- if (suspend_cb && suspend_cb != Py_None) {
- if (!PyCallable_Check(suspend_cb)) {
- PyErr_SetString(PyExc_TypeError, "suspend callback not callable");
- goto err;
- }
- self->suspend_cb = suspend_cb;
- } else
- self->suspend_cb = NULL;
-
- if (postcopy_cb && postcopy_cb != Py_None) {
- if (!PyCallable_Check(postcopy_cb)) {
- PyErr_SetString(PyExc_TypeError, "postcopy callback not callable");
- return NULL;
- }
- self->postcopy_cb = postcopy_cb;
- } else
- self->postcopy_cb = NULL;
-
- if (checkpoint_cb && checkpoint_cb != Py_None) {
- if (!PyCallable_Check(checkpoint_cb)) {
- PyErr_SetString(PyExc_TypeError, "checkpoint callback not callable");
- return NULL;
- }
- self->checkpoint_cb = checkpoint_cb;
- } else
- self->checkpoint_cb = NULL;
-
- memset(&callbacks, 0, sizeof(callbacks));
- callbacks.suspend = suspend_trampoline;
- callbacks.postcopy = postcopy_trampoline;
- callbacks.checkpoint = checkpoint_trampoline;
- callbacks.data = self;
-
- self->threadstate = PyEval_SaveThread();
- rc = checkpoint_start(&self->cps, fd, &callbacks, flags);
- PyEval_RestoreThread(self->threadstate);
-
- if (rc < 0) {
- PyErr_SetString(CheckpointError, checkpoint_error(&self->cps));
- goto err;
- }
-
- Py_INCREF(Py_None);
- return Py_None;
-
- err:
- self->suspend_cb = NULL;
- Py_XDECREF(suspend_cb);
- self->postcopy_cb = NULL;
- Py_XDECREF(postcopy_cb);
- self->checkpoint_cb = NULL;
- Py_XDECREF(checkpoint_cb);
-
- return NULL;
-}
-
-static PyMethodDef Checkpoint_methods[] = {
- { "open", pycheckpoint_open, METH_VARARGS,
- "open connection to xen" },
- { "close", pycheckpoint_close, METH_NOARGS,
- "close connection to xen" },
- { "start", pycheckpoint_start, METH_VARARGS | METH_KEYWORDS,
- "begin a checkpoint" },
- { NULL, NULL, 0, NULL }
-};
-
-static PyTypeObject CheckpointType = {
- PyObject_HEAD_INIT(NULL)
- 0, /* ob_size */
- PKG ".checkpointer", /* tp_name */
- sizeof(CheckpointObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)Checkpoint_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
- NULL, /* tp_getattr */
- NULL, /* tp_setattr */
- NULL, /* tp_compare */
- NULL, /* tp_repr */
- NULL, /* tp_as_number */
- NULL, /* tp_as_sequence */
- NULL, /* tp_as_mapping */
- NULL, /* tp_hash */
- NULL, /* tp_call */
- NULL, /* tp_str */
- NULL, /* tp_getattro */
- NULL, /* tp_setattro */
- NULL, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- "Checkpoint object", /* tp_doc */
- NULL, /* tp_traverse */
- NULL, /* tp_clear */
- NULL, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- NULL, /* tp_iter */
- NULL, /* tp_iternext */
- Checkpoint_methods, /* tp_methods */
- NULL, /* tp_members */
- NULL, /* tp_getset */
- NULL, /* tp_base */
- NULL, /* tp_dict */
- NULL, /* tp_descr_get */
- NULL, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)Checkpoint_init, /* tp_init */
- NULL, /* tp_alloc */
- Checkpoint_new, /* tp_new */
-};
-
-static PyMethodDef methods[] = {
- { NULL }
-};
-
-static char doc[] = "checkpoint API";
-
-PyMODINIT_FUNC initcheckpoint(void) {
- PyObject *m;
-
- if (PyType_Ready(&CheckpointType) < 0)
- return;
-
- m = Py_InitModule3(PKG, methods, doc);
-
- if (!m)
- return;
-
- Py_INCREF(&CheckpointType);
- PyModule_AddObject(m, "checkpointer", (PyObject*)&CheckpointType);
-
- CheckpointError = PyErr_NewException(PKG ".error", NULL, NULL);
- Py_INCREF(CheckpointError);
- PyModule_AddObject(m, "error", CheckpointError);
-
- block_timer();
-}
-
-/* private functions */
-
-/* bounce C suspend call into python equivalent.
- * returns 1 on success or 0 on failure */
-static int suspend_trampoline(void* data)
-{
- CheckpointObject* self = (CheckpointObject*)data;
-
- PyObject* result;
-
- /* call default suspend function, then python hook if available */
- if (self->armed) {
- if (checkpoint_wait(&self->cps) < 0) {
- fprintf(stderr, "%s\n", checkpoint_error(&self->cps));
- return 0;
- }
- } else {
- if (self->interval) {
- self->armed = 1;
- checkpoint_settimer(&self->cps, self->interval);
- }
-
- if (!checkpoint_suspend(&self->cps)) {
- fprintf(stderr, "%s\n", checkpoint_error(&self->cps));
- return 0;
- }
- }
-
- if (!self->suspend_cb)
- return 1;
-
- PyEval_RestoreThread(self->threadstate);
- result = PyObject_CallFunction(self->suspend_cb, NULL);
- self->threadstate = PyEval_SaveThread();
-
- if (!result)
- return 0;
-
- if (result == Py_None || PyObject_IsTrue(result)) {
- Py_DECREF(result);
- return 1;
- }
-
- Py_DECREF(result);
-
- return 0;
-}
-
-static int postcopy_trampoline(void* data)
-{
- CheckpointObject* self = (CheckpointObject*)data;
-
- PyObject* result;
- int rc = 0;
-
- if (!self->postcopy_cb)
- goto resume;
-
- PyEval_RestoreThread(self->threadstate);
- result = PyObject_CallFunction(self->postcopy_cb, NULL);
-
- if (result && (result == Py_None || PyObject_IsTrue(result)))
- rc = 1;
-
- Py_XDECREF(result);
- self->threadstate = PyEval_SaveThread();
-
- resume:
- if (checkpoint_resume(&self->cps) < 0) {
- fprintf(stderr, "%s\n", checkpoint_error(&self->cps));
- return 0;
- }
-
- return rc;
-}
-
-static int checkpoint_trampoline(void* data)
-{
- CheckpointObject* self = (CheckpointObject*)data;
-
- PyObject* result;
-
- if (checkpoint_postflush(&self->cps) < 0) {
- fprintf(stderr, "%s\n", checkpoint_error(&self->cps));
- return -1;
- }
-
- if (!self->checkpoint_cb)
- return 0;
-
- PyEval_RestoreThread(self->threadstate);
- result = PyObject_CallFunction(self->checkpoint_cb, NULL);
- self->threadstate = PyEval_SaveThread();
-
- if (!result)
- return 0;
-
- if (result == Py_None || PyObject_IsTrue(result)) {
- Py_DECREF(result);
- return 1;
- }
-
- Py_DECREF(result);
-
- return 0;
-}
diff --git a/tools/python/xen/lowlevel/checkpoint/checkpoint.h b/tools/python/xen/lowlevel/checkpoint/checkpoint.h
deleted file mode 100644
index 187d9d7..0000000
--- a/tools/python/xen/lowlevel/checkpoint/checkpoint.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* API for checkpointing */
-
-#ifndef _CHECKPOINT_H_
-#define _CHECKPOINT_H_ 1
-
-#include <pthread.h>
-#include <semaphore.h>
-#include <time.h>
-
-#include <xenguest.h>
-#include <xenstore.h>
-
-typedef enum {
- dt_unknown,
- dt_pv,
- dt_hvm,
- dt_pvhvm /* HVM with PV drivers */
-} checkpoint_domtype;
-
-typedef struct {
- xc_interface *xch;
- xc_evtchn *xce; /* event channel handle */
- struct xs_handle* xsh; /* xenstore handle */
- int watching_shutdown; /* state of watch on @releaseDomain */
-
- unsigned int domid;
- checkpoint_domtype domtype;
- int fd;
-
- int suspend_evtchn;
-
- char* errstr;
-
- /* suspend deadline thread support */
- volatile int suspended;
- volatile int done;
- pthread_t suspend_thr;
- sem_t suspended_sem;
- sem_t resumed_sem;
- timer_t timer;
-} checkpoint_state;
-
-#define CHECKPOINT_FLAGS_COMPRESSION 1
-char* checkpoint_error(checkpoint_state* s);
-
-void checkpoint_init(checkpoint_state* s);
-int checkpoint_open(checkpoint_state* s, unsigned int domid);
-void checkpoint_close(checkpoint_state* s);
-int checkpoint_start(checkpoint_state* s, int fd,
- struct save_callbacks* callbacks,
- unsigned int remus_flags);
-int checkpoint_suspend(checkpoint_state* s);
-int checkpoint_resume(checkpoint_state* s);
-int checkpoint_postflush(checkpoint_state* s);
-
-int checkpoint_settimer(checkpoint_state* s, int millis);
-int checkpoint_wait(checkpoint_state* s);
-void block_timer(void);
-void unblock_timer(void);
-
-#endif
diff --git a/tools/python/xen/lowlevel/checkpoint/libcheckpoint.c b/tools/python/xen/lowlevel/checkpoint/libcheckpoint.c
deleted file mode 100644
index 01c0d47..0000000
--- a/tools/python/xen/lowlevel/checkpoint/libcheckpoint.c
+++ /dev/null
@@ -1,847 +0,0 @@
-/* API for checkpointing */
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <xenctrl.h>
-#include <xenguest.h>
-#include <xenstore.h>
-
-#include "checkpoint.h"
-
-static char errbuf[256];
-
-static int setup_suspend_evtchn(checkpoint_state* s);
-static void release_suspend_evtchn(checkpoint_state *s);
-static int setup_shutdown_watch(checkpoint_state* s);
-static int check_shutdown(checkpoint_state* s);
-static void release_shutdown_watch(checkpoint_state* s);
-
-static int evtchn_suspend(checkpoint_state* s);
-static int compat_suspend(checkpoint_state* s);
-static int pollfd(checkpoint_state* s, int fd);
-
-static int switch_qemu_logdirty(checkpoint_state* s, int enable);
-static int suspend_hvm(checkpoint_state* s);
-static int suspend_qemu(checkpoint_state* s);
-static int resume_qemu(checkpoint_state* s);
-static int send_qemu(checkpoint_state* s);
-
-static int create_suspend_timer(checkpoint_state* s);
-static int delete_suspend_timer(checkpoint_state* s);
-static int create_suspend_thread(checkpoint_state* s);
-static void stop_suspend_thread(checkpoint_state* s);
-
-/* Returns a string describing the most recent error returned by
- * a checkpoint function. Static -- do not free. */
-char* checkpoint_error(checkpoint_state* s)
-{
- return s->errstr;
-}
-
-void checkpoint_init(checkpoint_state* s)
-{
- s->xch = NULL;
- s->xce = NULL;
- s->xsh = NULL;
- s->watching_shutdown = 0;
-
- s->domid = 0;
- s->domtype = dt_unknown;
- s->fd = -1;
-
- s->suspend_evtchn = -1;
-
- s->errstr = NULL;
-
- s->suspended = 0;
- s->done = 0;
- s->suspend_thr = 0;
- s->timer = 0;
-}
-
-/* open a checkpoint session to guest domid */
-int checkpoint_open(checkpoint_state* s, unsigned int domid)
-{
- xc_dominfo_t dominfo;
- unsigned long pvirq;
-
- s->domid = domid;
-
- s->xch = xc_interface_open(0,0,0);
- if (!s->xch) {
- s->errstr = "could not open control interface (are you root?)";
-
- return -1;
- }
-
- s->xsh = xs_daemon_open();
- if (!s->xsh) {
- checkpoint_close(s);
- s->errstr = "could not open xenstore handle";
-
- return -1;
- }
-
- s->xce = xc_evtchn_open(NULL, 0);
- if (s->xce == NULL) {
- checkpoint_close(s);
- s->errstr = "could not open event channel handle";
-
- return -1;
- }
-
- if (xc_domain_getinfo(s->xch, s->domid, 1, &dominfo) < 0) {
- checkpoint_close(s);
- s->errstr = "could not get domain info";
-
- return -1;
- }
- if (dominfo.hvm) {
- if (xc_get_hvm_param(s->xch, s->domid, HVM_PARAM_CALLBACK_IRQ, &pvirq)) {
- checkpoint_close(s);
- s->errstr = "could not get HVM callback IRQ";
-
- return -1;
- }
- s->domtype = pvirq ? dt_pvhvm : dt_hvm;
- } else
- s->domtype = dt_pv;
-
- if (setup_shutdown_watch(s) < 0) {
- checkpoint_close(s);
-
- return -1;
- }
-
- if (s->domtype == dt_pv) {
- if (setup_suspend_evtchn(s) < 0) {
- fprintf(stderr, "WARNING: suspend event channel unavailable, "
- "falling back to slow xenstore signalling\n");
- }
- } else if (s->domtype == dt_pvhvm) {
- checkpoint_close(s);
- s->errstr = "PV-on-HVM is unsupported";
-
- return -1;
- }
-
- return 0;
-}
-
-void checkpoint_close(checkpoint_state* s)
-{
- if (s->timer)
- delete_suspend_timer(s);
- if (s->suspend_thr)
- stop_suspend_thread(s);
-
- release_shutdown_watch(s);
- release_suspend_evtchn(s);
-
- if (s->xch) {
- xc_interface_close(s->xch);
- s->xch = NULL;
- }
- if (s->xce != NULL) {
- xc_evtchn_close(s->xce);
- s->xce = NULL;
- }
- if (s->xsh) {
- xs_daemon_close(s->xsh);
- s->xsh = NULL;
- }
-
- s->domid = 0;
- s->fd = -1;
-}
-
-/* we toggle logdirty ourselves around the xc_domain_save call --
- * it avoids having to pass around checkpoint_state */
-static int noop_switch_logdirty(int domid, unsigned enable, void *data)
-{
- return 0;
-}
-
-int checkpoint_start(checkpoint_state* s, int fd,
- struct save_callbacks* callbacks,
- unsigned int remus_flags)
-{
- int hvm, rc;
- int flags = XCFLAGS_LIVE;
- unsigned long vm_generationid_addr;
-
- if (!s->domid) {
- s->errstr = "checkpoint state not opened";
- return -1;
- }
-
- s->fd = fd;
-
- hvm = s->domtype > dt_pv;
- if (hvm) {
- char path[128];
- char *addr;
-
- sprintf(path, "/local/domain/%u/hvmloader/generation-id-address", s->domid);
- addr = xs_read(s->xsh, XBT_NULL, path, NULL);
-
- vm_generationid_addr = (addr) ? strtoul(addr, NULL, 0) : 0;
- free(addr);
-
- flags |= XCFLAGS_HVM;
- if (switch_qemu_logdirty(s, 1))
- return -1;
- } else {
- vm_generationid_addr = 0;
- }
- if (remus_flags & CHECKPOINT_FLAGS_COMPRESSION)
- flags |= XCFLAGS_CHECKPOINT_COMPRESS;
-
- callbacks->switch_qemu_logdirty = noop_switch_logdirty;
-
- rc = xc_domain_save(s->xch, fd, s->domid, 0, 0, flags, callbacks, hvm,
- vm_generationid_addr);
-
- if (hvm)
- switch_qemu_logdirty(s, 0);
-
- return rc;
-}
-
-/* suspend the domain. Returns 0 on failure, 1 on success */
-int checkpoint_suspend(checkpoint_state* s)
-{
- struct timeval tv;
- int rc;
-
- gettimeofday(&tv, NULL);
- fprintf(stderr, "PROF: suspending at %lu.%06lu\n", (unsigned long)tv.tv_sec,
- (unsigned long)tv.tv_usec);
-
- if (s->suspend_evtchn >= 0)
- rc = evtchn_suspend(s);
- else if (s->domtype == dt_hvm)
- rc = suspend_hvm(s);
- else
- rc = compat_suspend(s);
-
- return rc < 0 ? 0 : 1;
-}
-
-/* wait for a suspend to be triggered by another thread */
-int checkpoint_wait(checkpoint_state* s)
-{
- int rc;
-
- if (!s->suspend_thr) {
- s->errstr = "checkpoint timer is not active\n";
- return -1;
- }
-
- do {
- rc = sem_wait(&s->suspended_sem);
- if (rc < 0 && errno != EINTR) {
- snprintf(errbuf, sizeof(errbuf),
- "error waiting for suspend semaphore: %d %d\n", rc, errno);
- s->errstr = errbuf;
- return -1;
- }
- } while (rc < 0);
-
- if (!s->suspended) {
- snprintf(errbuf, sizeof(errbuf), "domain not suspended?\n");
- s->errstr = errbuf;
- return -1;
- }
-
- return 0;
-}
-
-/* let guest execution resume */
-int checkpoint_resume(checkpoint_state* s)
-{
- struct timeval tv;
- int rc;
-
- if (xc_domain_resume(s->xch, s->domid, 1)) {
- snprintf(errbuf, sizeof(errbuf), "error resuming domain: %d", errno);
- s->errstr = errbuf;
-
- return -1;
- }
-
- gettimeofday(&tv, NULL);
- fprintf(stderr, "PROF: resumed at %lu.%06lu\n", (unsigned long)tv.tv_sec,
- (unsigned long)tv.tv_usec);
-
- if (s->domtype > dt_pv && resume_qemu(s) < 0)
- return -1;
-
- /* restore watchability in xenstore */
- if (xs_resume_domain(s->xsh, s->domid) < 0)
- fprintf(stderr, "error resuming domain in xenstore\n");
-
- s->suspended = 0;
-
- if (s->suspend_thr) {
- if ((rc = sem_post(&s->resumed_sem)))
- fprintf(stderr, "error posting resume semaphore\n");
- }
-
- return 0;
-}
-
-/* called after xc_domain_save has flushed its buffer */
-int checkpoint_postflush(checkpoint_state *s)
-{
- if (s->domtype > dt_pv && send_qemu(s) < 0)
- return -1;
-
- return 0;
-}
-
-/* force suspend within millis ms if copy hasn't completed yet */
-int checkpoint_settimer(checkpoint_state* s, int millis)
-{
- struct itimerspec t;
- int err;
-
- if (!s->suspend_thr) {
- if (create_suspend_timer(s) < 0)
- return -1;
-
- if (create_suspend_thread(s) < 0) {
- delete_suspend_timer(s);
- return -1;
- }
- }
-
- t.it_value.tv_sec = millis / 1000;
- t.it_value.tv_nsec = (millis % 1000) * 1000000L;
- t.it_interval.tv_sec = t.it_value.tv_sec;
- t.it_interval.tv_nsec = t.it_value.tv_nsec;
-
- if ((err = timer_settime(s->timer, 0, &t, NULL))) {
- fprintf(stderr, "Error arming timer: %d\n", err);
- return -1;
- }
-
- return 0;
-}
-
-int delete_suspend_timer(checkpoint_state* s)
-{
- int rc = 0;
-
- if (s->timer) {
- if ((rc = timer_delete(s->timer)))
- fprintf(stderr, "Error deleting timer: %s\n", strerror(errno));
- s->timer = 0;
- }
-
- return rc;
-}
-
-/* Set up event channel used to signal a guest to suspend itself */
-static int setup_suspend_evtchn(checkpoint_state* s)
-{
- int port;
-
- port = xs_suspend_evtchn_port(s->domid);
- if (port < 0) {
- s->errstr = "failed to read suspend event channel";
- return -1;
- }
-
- s->suspend_evtchn = xc_suspend_evtchn_init(s->xch, s->xce, s->domid, port);
- if (s->suspend_evtchn < 0) {
- s->errstr = "failed to bind suspend event channel";
- return -1;
- }
-
- fprintf(stderr, "bound to suspend event channel %u:%d as %d\n", s->domid, port,
- s->suspend_evtchn);
-
- return 0;
-}
-
-/* release suspend event channels bound to guest */
-static void release_suspend_evtchn(checkpoint_state *s)
-{
- /* TODO: teach xen to clean up if port is unbound */
- if (s->xce != NULL && s->suspend_evtchn >= 0) {
- xc_suspend_evtchn_release(s->xch, s->xce, s->domid, s->suspend_evtchn);
- s->suspend_evtchn = -1;
- }
-}
-
-static int setup_shutdown_watch(checkpoint_state* s)
-{
- char buf[16];
-
- /* write domain ID to watch so we can ignore other domain shutdowns */
- snprintf(buf, sizeof(buf), "%u", s->domid);
- if ( !xs_watch(s->xsh, "@releaseDomain", buf) ) {
- fprintf(stderr, "Could not bind to shutdown watch\n");
- return -1;
- }
- /* watch fires once on registration */
- s->watching_shutdown = 1;
- check_shutdown(s);
-
- return 0;
-}
-
-/* returns -1 on error or death, 0 if domain is running, 1 if suspended */
-static int check_shutdown(checkpoint_state* s) {
- unsigned int count;
- int xsfd;
- char **vec;
- char buf[16];
- xc_dominfo_t info;
-
- xsfd = xs_fileno(s->xsh);
-
- /* loop on watch if it fires for another domain */
- while (1) {
- if (pollfd(s, xsfd) < 0)
- return -1;
-
- vec = xs_read_watch(s->xsh, &count);
- if (s->watching_shutdown == 1) {
- s->watching_shutdown = 2;
- return 0;
- }
- if (!vec) {
- fprintf(stderr, "empty watch fired\n");
- continue;
- }
- snprintf(buf, sizeof(buf), "%d", s->domid);
- if (!strcmp(vec[XS_WATCH_TOKEN], buf))
- break;
- }
-
- if (xc_domain_getinfo(s->xch, s->domid, 1, &info) != 1
- || info.domid != s->domid) {
- snprintf(errbuf, sizeof(errbuf),
- "error getting info for domain %u", s->domid);
- s->errstr = errbuf;
- return -1;
- }
- if (!info.shutdown) {
- snprintf(errbuf, sizeof(errbuf),
- "domain %u not shut down", s->domid);
- s->errstr = errbuf;
- return 0;
- }
-
- if (info.shutdown_reason != SHUTDOWN_suspend)
- return -1;
-
- return 1;
-}
-
-static void release_shutdown_watch(checkpoint_state* s) {
- char buf[16];
-
- if (!s->xsh)
- return;
- if (!s->watching_shutdown)
- return;
-
- snprintf(buf, sizeof(buf), "%u", s->domid);
- if (!xs_unwatch(s->xsh, "@releaseDomain", buf))
- fprintf(stderr, "Could not release shutdown watch\n");
-
- s->watching_shutdown = 0;
-}
-
-static int evtchn_suspend(checkpoint_state* s)
-{
- int rc;
-
- rc = xc_evtchn_notify(s->xce, s->suspend_evtchn);
- if (rc < 0) {
- snprintf(errbuf, sizeof(errbuf),
- "failed to notify suspend event channel: %d", rc);
- s->errstr = errbuf;
-
- return -1;
- }
-
- do
- if (!(rc = pollfd(s, xc_evtchn_fd(s->xce))))
- rc = xc_evtchn_pending(s->xce);
- while (rc >= 0 && rc != s->suspend_evtchn);
- if (rc <= 0)
- return -1;
-
- if (xc_evtchn_unmask(s->xce, s->suspend_evtchn) < 0) {
- snprintf(errbuf, sizeof(errbuf),
- "failed to unmask suspend notification channel: %d", rc);
- s->errstr = errbuf;
-
- return -1;
- }
-
- return 0;
-}
-
-/* suspend through xenstore if suspend event channel is unavailable */
-static int compat_suspend(checkpoint_state* s)
-{
- char path[128];
-
- sprintf(path, "/local/domain/%u/control/shutdown", s->domid);
-
- if (!xs_write(s->xsh, XBT_NULL, path, "suspend", 7)) {
- s->errstr = "error signalling qemu logdirty";
- return -1;
- }
-
- if (check_shutdown(s) != 1)
- return -1;
-
- return 0;
-}
-
-/* returns -1 if fd does not become readable within timeout */
-static int pollfd(checkpoint_state* s, int fd)
-{
- fd_set rfds;
- struct timeval tv;
- int rc;
-
- FD_ZERO(&rfds);
- FD_SET(fd, &rfds);
-
- tv.tv_sec = 0;
- tv.tv_usec = 500000;
-
- rc = select(fd + 1, &rfds, NULL, NULL, &tv);
-
- if (rc < 0) {
- snprintf(errbuf, sizeof(errbuf),
- "error polling fd: %s", strerror(errno));
- s->errstr = errbuf;
- } else if (!rc) {
- snprintf(errbuf, sizeof(errbuf), "timeout polling fd");
- s->errstr = errbuf;
- } else if (! FD_ISSET(fd, &rfds)) {
- snprintf(errbuf, sizeof(errbuf), "unknown error polling fd");
- s->errstr = errbuf;
- } else
- return 0;
-
- return -1;
-}
-
-/* adapted from the eponymous function in xc_save */
-static int switch_qemu_logdirty(checkpoint_state *s, int enable)
-{
- char path[128];
- char *tail, *cmd, *response;
- char **vec;
- unsigned int len;
-
- sprintf(path, "/local/domain/0/device-model/%u/logdirty/", s->domid);
- tail = path + strlen(path);
-
- strcpy(tail, "ret");
- if (!xs_watch(s->xsh, path, "qemu-logdirty-ret")) {
- s->errstr = "error watching qemu logdirty return";
- return 1;
- }
- /* null fire. XXX unify with shutdown watch! */
- vec = xs_read_watch(s->xsh, &len);
- free(vec);
-
- strcpy(tail, "cmd");
- cmd = enable ? "enable" : "disable";
- if (!xs_write(s->xsh, XBT_NULL, path, cmd, strlen(cmd))) {
- s->errstr = "error signalling qemu logdirty";
- return 1;
- }
-
- vec = xs_read_watch(s->xsh, &len);
- free(vec);
-
- strcpy(tail, "ret");
- xs_unwatch(s->xsh, path, "qemu-logdirty-ret");
-
- response = xs_read(s->xsh, XBT_NULL, path, &len);
- if (!len || strcmp(response, cmd)) {
- if (len)
- free(response);
- s->errstr = "qemu logdirty command failed";
- return 1;
- }
- free(response);
- fprintf(stderr, "qemu logdirty mode: %s\n", cmd);
-
- return 0;
-}
-
-static int suspend_hvm(checkpoint_state *s)
-{
- int rc = -1;
-
- fprintf(stderr, "issuing HVM suspend hypercall\n");
- rc = xc_domain_shutdown(s->xch, s->domid, SHUTDOWN_suspend);
- if (rc < 0) {
- s->errstr = "shutdown hypercall failed";
- return -1;
- }
- fprintf(stderr, "suspend hypercall returned %d\n", rc);
-
- if (check_shutdown(s) != 1)
- return -1;
-
- rc = suspend_qemu(s);
-
- return rc;
-}
-
-static int suspend_qemu(checkpoint_state *s)
-{
- char path[128];
-
- fprintf(stderr, "pausing QEMU\n");
-
- sprintf(path, "/local/domain/0/device-model/%d/command", s->domid);
- if (!xs_write(s->xsh, XBT_NULL, path, "save", 4)) {
- fprintf(stderr, "error signalling QEMU to save\n");
- return -1;
- }
-
- sprintf(path, "/local/domain/0/device-model/%d/state", s->domid);
-
- do {
- char* state;
- unsigned int len;
-
- state = xs_read(s->xsh, XBT_NULL, path, &len);
- if (!state) {
- s->errstr = "error reading QEMU state";
- return -1;
- }
-
- if (!strcmp(state, "paused")) {
- free(state);
- return 0;
- }
-
- free(state);
- usleep(1000);
- } while(1);
-
- return -1;
-}
-
-static int resume_qemu(checkpoint_state *s)
-{
- char path[128];
- fprintf(stderr, "resuming QEMU\n");
-
- sprintf(path, "/local/domain/0/device-model/%d/command", s->domid);
- if (!xs_write(s->xsh, XBT_NULL, path, "continue", 8)) {
- fprintf(stderr, "error signalling QEMU to resume\n");
- return -1;
- }
-
- return 0;
-}
-
-static int send_qemu(checkpoint_state *s)
-{
- char buf[8192];
- char path[128];
- struct stat sb;
- uint32_t qlen = 0;
- int qfd;
- int rc;
-
- if (s->fd < 0)
- return -1;
-
- sprintf(path, "/var/lib/xen/qemu-save.%d", s->domid);
-
- if (stat(path, &sb) < 0) {
- snprintf(errbuf, sizeof(errbuf),
- "error getting QEMU state file status: %s", strerror(errno));
- s->errstr = errbuf;
- return -1;
- }
-
- qlen = sb.st_size;
- qfd = open(path, O_RDONLY);
- if (qfd < 0) {
- snprintf(errbuf, sizeof(errbuf), "error opening QEMU state file: %s",
- strerror(errno));
- s->errstr = errbuf;
- return -1;
- }
-
- fprintf(stderr, "Sending %u bytes of QEMU state\n", qlen);
- if (write(s->fd, "RemusDeviceModelState", 21) != 21) {
- s->errstr = "error writing QEMU header";
- close(qfd);
- return -1;
- }
- if (write(s->fd, &qlen, sizeof(qlen)) != sizeof(qlen)) {
- s->errstr = "error writing QEMU size";
- close(qfd);
- return -1;
- }
-
- while ((rc = read(qfd, buf, qlen > sizeof(buf) ? sizeof(buf) : qlen)) > 0) {
- qlen -= rc;
- if (write(s->fd, buf, rc) != rc) {
- rc = -1;
- break;
- }
- }
- if (rc < 0) {
- snprintf(errbuf, sizeof(errbuf), "error writing QEMU state: %s",
- strerror(errno));
- s->errstr = errbuf;
- }
-
- close(qfd);
-
- return rc;
-}
-
-/*thread responsible to suspend the domain early if necessary*/
-static void *suspend_thread(void *arg)
-{
- checkpoint_state* s = (checkpoint_state*)arg;
- sigset_t tss;
- int rc;
- int sig;
-
- fprintf(stderr, "Suspend thread started\n");
-
- sigemptyset(&tss);
- sigaddset(&tss, SIGRTMIN);
-
- while (1) {
- /* wait for checkpoint thread to signal resume */
- if ((rc = sem_wait(&s->resumed_sem)))
- fprintf(stderr, "Error waiting on resume semaphore\n");
-
- if ((rc = sigwait(&tss, &sig))) {
- fprintf(stderr, "sigwait failed: %d %d\n", rc, errno);
- break;
- }
- if (sig != SIGRTMIN)
- fprintf(stderr, "received unexpected signal %d\n", sig);
-
- if (s->done)
- break;
-
- if (s->suspended) {
- fprintf(stderr, "domain already suspended?\n");
- } else {
- rc = checkpoint_suspend(s);
- if (rc)
- s->suspended = 1;
- else
- fprintf(stderr, "checkpoint_suspend failed\n");
- }
-
- if ((rc = sem_post(&s->suspended_sem)))
- fprintf(stderr, "Error posting suspend semaphore\n");
- }
-
- fprintf(stderr, "Suspend thread exiting\n");
-
- return NULL;
-}
-
-static int create_suspend_timer(checkpoint_state* s)
-{
- struct sigevent event;
- int err;
-
- event.sigev_notify = SIGEV_SIGNAL;
- event.sigev_signo = SIGRTMIN;
- event.sigev_value.sival_int = 0;
-
- if ((err = timer_create(CLOCK_REALTIME, &event, &s->timer))) {
- snprintf(errbuf, sizeof(errbuf), "Error creating timer: %d\n", err);
- s->errstr = errbuf;
- return -1;
- }
-
- return 0;
-}
-
-void block_timer(void)
-{
- sigset_t tss;
-
- sigemptyset(&tss);
- sigaddset(&tss, SIGRTMIN);
-
- pthread_sigmask(SIG_BLOCK, &tss, NULL);
-}
-
-void unblock_timer(void)
-{
- sigset_t tss;
-
- sigemptyset(&tss);
- sigaddset(&tss, SIGRTMIN);
-
- pthread_sigmask(SIG_UNBLOCK, &tss, NULL);
-}
-
-static int create_suspend_thread(checkpoint_state* s)
-{
- int err;
-
- if ((err = sem_init(&s->suspended_sem, 0, 0))) {
- snprintf(errbuf, sizeof(errbuf),
- "Error initializing suspend semaphore: %d\n", err);
- s->errstr = errbuf;
- return -1;
- }
-
- if ((err = sem_init(&s->resumed_sem, 0, 0))) {
- snprintf(errbuf, sizeof(errbuf),
- "Error initializing resume semaphore: %d\n", err);
- s->errstr = errbuf;
- return -1;
- }
-
- /* signal mask should be inherited */
- block_timer();
-
- if ((err = pthread_create(&s->suspend_thr, NULL, suspend_thread, s))) {
- snprintf(errbuf, sizeof(errbuf), "Error creating suspend thread: %d\n", err);
- s->errstr = errbuf;
- return -1;
- }
-
- return 0;
-}
-
-static void stop_suspend_thread(checkpoint_state* s)
-{
- int err;
-
- s->done = 1;
-
- err = sem_post(&s->resumed_sem);
-
- err = pthread_join(s->suspend_thr, NULL);
- s->suspend_thr = 0;
-}
diff --git a/tools/python/xen/lowlevel/flask/flask.c b/tools/python/xen/lowlevel/flask/flask.c
deleted file mode 100644
index c3fcf3b..0000000
--- a/tools/python/xen/lowlevel/flask/flask.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/******************************************************************************
- * flask.c
- *
- * Authors: George Coker, <gscoker at alpha.ncsc.mil>
- * Michael LeMay, <mdlemay at epoch.ncsc.mil>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- */
-
-#include <Python.h>
-#include <xenctrl.h>
-
-#define PKG "xen.lowlevel.flask"
-#define CLS "flask"
-
-#define CTX_LEN 1024
-
-static PyObject *xc_error_obj;
-
-typedef struct {
- PyObject_HEAD;
- xc_interface *xc_handle;
-} XcObject;
-
-static PyObject *pyflask_context_to_sid(PyObject *self, PyObject *args,
- PyObject *kwds)
-{
- xc_interface *xc_handle;
- char *ctx;
- char *buf;
- uint32_t len;
- uint32_t sid;
- int ret;
-
- static char *kwd_list[] = { "context", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s", kwd_list,
- &ctx) )
- return NULL;
-
- len = strlen(ctx);
-
- buf = malloc(len);
- if (!buf) {
- errno = -ENOMEM;
- PyErr_SetFromErrno(xc_error_obj);
- }
-
- memcpy(buf, ctx, len);
-
- xc_handle = xc_interface_open(0,0,0);
- if (!xc_handle) {
- free(buf);
- return PyErr_SetFromErrno(xc_error_obj);
- }
-
- ret = xc_flask_context_to_sid(xc_handle, buf, len, &sid);
-
- xc_interface_close(xc_handle);
-
- free(buf);
-
- if ( ret != 0 ) {
- errno = -ret;
- return PyErr_SetFromErrno(xc_error_obj);
- }
-
- return PyInt_FromLong(sid);
-}
-
-static PyObject *pyflask_sid_to_context(PyObject *self, PyObject *args,
- PyObject *kwds)
-{
- xc_interface *xc_handle;
- uint32_t sid;
- char ctx[CTX_LEN];
- uint32_t ctx_len = CTX_LEN;
- int ret;
-
- static char *kwd_list[] = { "sid", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
- &sid) )
- return NULL;
-
- xc_handle = xc_interface_open(0,0,0);
- if (!xc_handle) {
- return PyErr_SetFromErrno(xc_error_obj);
- }
-
- ret = xc_flask_sid_to_context(xc_handle, sid, ctx, ctx_len);
-
- xc_interface_close(xc_handle);
-
- if ( ret != 0 ) {
- errno = -ret;
- return PyErr_SetFromErrno(xc_error_obj);
- }
-
- return Py_BuildValue("s", ctx, ctx_len);
-}
-
-static PyObject *pyflask_load(PyObject *self, PyObject *args, PyObject *kwds)
-{
- xc_interface *xc_handle;
- char *policy;
- uint32_t len;
- int ret;
-
- static char *kwd_list[] = { "policy", NULL };
-
- if( !PyArg_ParseTupleAndKeywords(args, kwds, "s#", kwd_list, &policy, &len) )
- return NULL;
-
- xc_handle = xc_interface_open(0,0,0);
- if (!xc_handle) {
- return PyErr_SetFromErrno(xc_error_obj);
- }
-
- ret = xc_flask_load(xc_handle, policy, len);
-
- xc_interface_close(xc_handle);
-
- if ( ret != 0 ) {
- errno = -ret;
- return PyErr_SetFromErrno(xc_error_obj);
- }
-
- return Py_BuildValue("i", ret);
-}
-
-static PyObject *pyflask_getenforce(PyObject *self)
-{
- xc_interface *xc_handle;
- int ret;
-
- xc_handle = xc_interface_open(0,0,0);
- if (!xc_handle) {
- return PyErr_SetFromErrno(xc_error_obj);
- }
-
- ret = xc_flask_getenforce(xc_handle);
-
- xc_interface_close(xc_handle);
-
- if ( ret < 0 ) {
- errno = -ret;
- return PyErr_SetFromErrno(xc_error_obj);
- }
-
- return Py_BuildValue("i", ret);
-}
-
-static PyObject *pyflask_setenforce(PyObject *self, PyObject *args,
- PyObject *kwds)
-{
- xc_interface *xc_handle;
- int mode;
- int ret;
-
- static char *kwd_list[] = { "mode", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
- &mode) )
- return NULL;
-
- xc_handle = xc_interface_open(0,0,0);
- if (!xc_handle) {
- return PyErr_SetFromErrno(xc_error_obj);
- }
-
- ret = xc_flask_setenforce(xc_handle, mode);
-
- xc_interface_close(xc_handle);
-
- if ( ret != 0 ) {
- errno = -ret;
- return PyErr_SetFromErrno(xc_error_obj);
- }
-
- return Py_BuildValue("i", ret);
-}
-
-static PyObject *pyflask_access(PyObject *self, PyObject *args,
- PyObject *kwds)
-{
- xc_interface *xc_handle;
- char *tcon, *scon;
- uint16_t tclass;
- uint32_t req, allowed, decided, auditallow, auditdeny, seqno;
- int ret;
-
- static char *kwd_list[] = { "src_context", "tar_context",
- "tar_class", "req_permissions",
- "decided", "auditallow","auditdeny",
- "seqno", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ssil|llll", kwd_list,
- &scon, &tcon, &tclass, &req, &decided,
- &auditallow, &auditdeny, &seqno) )
- return NULL;
-
- xc_handle = xc_interface_open(0,0,0);
- if (!xc_handle) {
- return PyErr_SetFromErrno(xc_error_obj);
- }
-
- ret = xc_flask_access(xc_handle, scon, tcon, tclass, req, &allowed, &decided,
- &auditallow, &auditdeny, &seqno);
-
- xc_interface_close(xc_handle);
-
- if ( ret != 0 ) {
- errno = -ret;
- return PyErr_SetFromErrno(xc_error_obj);
- }
-
- return Py_BuildValue("i",ret);
-}
-
-static PyMethodDef pyflask_methods[] = {
- { "flask_context_to_sid",
- (PyCFunction)pyflask_context_to_sid,
- METH_KEYWORDS, "\n"
- "Convert a context string to a dynamic SID.\n"
- " context [str]: String specifying context to be converted\n"
- "Returns: [int]: Numeric SID on success; -1 on error.\n" },
-
- { "flask_sid_to_context",
- (PyCFunction)pyflask_sid_to_context,
- METH_KEYWORDS, "\n"
- "Convert a dynamic SID to context string.\n"
- " context [int]: SID to be converted\n"
- "Returns: [str]: Numeric SID on success; -1 on error.\n" },
-
- { "flask_load",
- (PyCFunction)pyflask_load,
- METH_KEYWORDS, "\n"
- "Loads a policy into the hypervisor.\n"
- " policy [str]: policy to be load\n"
- "Returns: [int]: 0 on success; -1 on failure.\n" },
-
- { "flask_getenforce",
- (PyCFunction)pyflask_getenforce,
- METH_NOARGS, "\n"
- "Returns the current mode of the Flask XSM module.\n"
- "Returns: [int]: 0 for permissive; 1 for enforcing; -1 on failure.\n" },
-
- { "flask_setenforce",
- (PyCFunction)pyflask_setenforce,
- METH_KEYWORDS, "\n"
- "Modifies the current mode for the Flask XSM module.\n"
- " mode [int]: mode to change to\n"
- "Returns: [int]: 0 on success; -1 on failure.\n" },
-
- { "flask_access",
- (PyCFunction)pyflask_access,
- METH_KEYWORDS, "\n"
- "Returns whether a source context has access to target context based on \
- class and permissions requested.\n"
- " scon [str]: source context\n"
- " tcon [str]: target context\n"
- " tclass [int]: target security class\n"
- " req [int] requested permissions\n"
- " allowed [int] permissions allow for the target class between the source \
- and target context\n"
- " decided [int] the permissions that were returned in the allowed \
- parameter\n"
- " auditallow [int] permissions set to audit on allow\n"
- " auditdeny [int] permissions set to audit on deny\n"
- " seqno [int] not used\n"
- "Returns: [int]: 0 on all permission granted; -1 if any permissions are \
- denied\n" },
- { NULL, NULL, 0, NULL }
-
-};
-
-PyMODINIT_FUNC initflask(void)
-{
- Py_InitModule("flask", pyflask_methods);
-}
-
-
-/*
- * Local variables:
- * c-indent-level: 4
- * c-basic-offset: 4
- * End:
- */
diff --git a/tools/python/xen/lowlevel/netlink/libnetlink.c b/tools/python/xen/lowlevel/netlink/libnetlink.c
deleted file mode 100644
index c5fc0bf..0000000
--- a/tools/python/xen/lowlevel/netlink/libnetlink.c
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
- * libnetlink.c RTnetlink service routines.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * Authors: Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <fcntl.h>
-#include <net/if_arp.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-#include <sys/uio.h>
-
-#include "libnetlink.h"
-
-void rtnl_close(struct rtnl_handle *rth)
-{
- close(rth->fd);
-}
-
-int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions,
- int protocol)
-{
- socklen_t addr_len;
- int sndbuf = 32768;
- int rcvbuf = 32768;
-
- memset(rth, 0, sizeof(*rth));
-
- rth->fd = socket(AF_NETLINK, SOCK_RAW, protocol);
- if (rth->fd < 0) {
- perror("Cannot open netlink socket");
- return -1;
- }
-
- if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) {
- perror("SO_SNDBUF");
- return -1;
- }
-
- if (setsockopt(rth->fd,SOL_SOCKET,SO_RCVBUF,&rcvbuf,sizeof(rcvbuf)) < 0) {
- perror("SO_RCVBUF");
- return -1;
- }
-
- memset(&rth->local, 0, sizeof(rth->local));
- rth->local.nl_family = AF_NETLINK;
- rth->local.nl_groups = subscriptions;
-
- if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) {
- perror("Cannot bind netlink socket");
- return -1;
- }
- addr_len = sizeof(rth->local);
- if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) {
- perror("Cannot getsockname");
- return -1;
- }
- if (addr_len != sizeof(rth->local)) {
- fprintf(stderr, "Wrong address length %d\n", addr_len);
- return -1;
- }
- if (rth->local.nl_family != AF_NETLINK) {
- fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family);
- return -1;
- }
- rth->seq = time(NULL);
- return 0;
-}
-
-int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions)
-{
- return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE);
-}
-
-int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
-{
- struct {
- struct nlmsghdr nlh;
- struct rtgenmsg g;
- } req;
- struct sockaddr_nl nladdr;
-
- memset(&nladdr, 0, sizeof(nladdr));
- nladdr.nl_family = AF_NETLINK;
-
- memset(&req, 0, sizeof(req));
- req.nlh.nlmsg_len = sizeof(req);
- req.nlh.nlmsg_type = type;
- req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
- req.nlh.nlmsg_pid = 0;
- req.nlh.nlmsg_seq = rth->dump = ++rth->seq;
- req.g.rtgen_family = family;
-
- return sendto(rth->fd, (void*)&req, sizeof(req), 0,
- (struct sockaddr*)&nladdr, sizeof(nladdr));
-}
-
-int rtnl_send(struct rtnl_handle *rth, const char *buf, int len)
-{
- struct sockaddr_nl nladdr;
-
- memset(&nladdr, 0, sizeof(nladdr));
- nladdr.nl_family = AF_NETLINK;
-
- return sendto(rth->fd, buf, len, 0, (struct sockaddr*)&nladdr, sizeof(nladdr));
-}
-
-int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len)
-{
- struct nlmsghdr nlh;
- struct sockaddr_nl nladdr;
- struct iovec iov[2] = {
- { .iov_base = &nlh, .iov_len = sizeof(nlh) },
- { .iov_base = req, .iov_len = len }
- };
- struct msghdr msg = {
- .msg_name = &nladdr,
- .msg_namelen = sizeof(nladdr),
- .msg_iov = iov,
- .msg_iovlen = 2,
- };
-
- memset(&nladdr, 0, sizeof(nladdr));
- nladdr.nl_family = AF_NETLINK;
-
- nlh.nlmsg_len = NLMSG_LENGTH(len);
- nlh.nlmsg_type = type;
- nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
- nlh.nlmsg_pid = 0;
- nlh.nlmsg_seq = rth->dump = ++rth->seq;
-
- return sendmsg(rth->fd, &msg, 0);
-}
-
-int rtnl_dump_filter(struct rtnl_handle *rth,
- rtnl_filter_t filter,
- void *arg1,
- rtnl_filter_t junk,
- void *arg2)
-{
- struct sockaddr_nl nladdr;
- struct iovec iov;
- struct msghdr msg = {
- .msg_name = &nladdr,
- .msg_namelen = sizeof(nladdr),
- .msg_iov = &iov,
- .msg_iovlen = 1,
- };
- char buf[16384];
-
- iov.iov_base = buf;
- while (1) {
- int status;
- struct nlmsghdr *h;
-
- iov.iov_len = sizeof(buf);
- status = recvmsg(rth->fd, &msg, 0);
-
- if (status < 0) {
- if (errno == EINTR)
- continue;
- perror("OVERRUN");
- continue;
- }
-
- if (status == 0) {
- fprintf(stderr, "EOF on netlink\n");
- return -1;
- }
-
- h = (struct nlmsghdr*)buf;
- while (NLMSG_OK(h, status)) {
- int err;
-
- if (nladdr.nl_pid != 0 ||
- h->nlmsg_pid != rth->local.nl_pid ||
- h->nlmsg_seq != rth->dump) {
- if (junk) {
- err = junk(&nladdr, h, arg2);
- if (err < 0)
- return err;
- }
- goto skip_it;
- }
-
- if (h->nlmsg_type == NLMSG_DONE)
- return 0;
- if (h->nlmsg_type == NLMSG_ERROR) {
- struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
- if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
- fprintf(stderr, "ERROR truncated\n");
- } else {
- errno = -err->error;
- perror("RTNETLINK answers");
- }
- return -1;
- }
- err = filter(&nladdr, h, arg1);
- if (err < 0)
- return err;
-
-skip_it:
- h = NLMSG_NEXT(h, status);
- }
- if (msg.msg_flags & MSG_TRUNC) {
- fprintf(stderr, "Message truncated\n");
- continue;
- }
- if (status) {
- fprintf(stderr, "!!!Remnant of size %d\n", status);
- exit(1);
- }
- }
-}
-
-int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
- unsigned groups, struct nlmsghdr *answer,
- rtnl_filter_t junk,
- void *jarg)
-{
- int status;
- unsigned seq;
- struct nlmsghdr *h;
- struct sockaddr_nl nladdr;
- struct iovec iov = {
- .iov_base = (void*) n,
- .iov_len = n->nlmsg_len
- };
- struct msghdr msg = {
- .msg_name = &nladdr,
- .msg_namelen = sizeof(nladdr),
- .msg_iov = &iov,
- .msg_iovlen = 1,
- };
- char buf[16384];
-
- memset(&nladdr, 0, sizeof(nladdr));
- nladdr.nl_family = AF_NETLINK;
- nladdr.nl_pid = peer;
- nladdr.nl_groups = groups;
-
- n->nlmsg_seq = seq = ++rtnl->seq;
-
- if (answer == NULL)
- n->nlmsg_flags |= NLM_F_ACK;
-
- status = sendmsg(rtnl->fd, &msg, 0);
-
- if (status < 0) {
- perror("Cannot talk to rtnetlink");
- return -1;
- }
-
- memset(buf,0,sizeof(buf));
-
- iov.iov_base = buf;
-
- while (1) {
- iov.iov_len = sizeof(buf);
- status = recvmsg(rtnl->fd, &msg, 0);
-
- if (status < 0) {
- if (errno == EINTR)
- continue;
- perror("OVERRUN");
- continue;
- }
- if (status == 0) {
- fprintf(stderr, "EOF on netlink\n");
- return -1;
- }
- if (msg.msg_namelen != sizeof(nladdr)) {
- fprintf(stderr, "sender address length == %d\n", msg.msg_namelen);
- exit(1);
- }
- for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
- int err;
- int len = h->nlmsg_len;
- int l = len - sizeof(*h);
-
- if (l<0 || len>status) {
- if (msg.msg_flags & MSG_TRUNC) {
- fprintf(stderr, "Truncated message\n");
- return -1;
- }
- fprintf(stderr, "!!!malformed message: len=%d\n", len);
- exit(1);
- }
-
- if (nladdr.nl_pid != peer ||
- h->nlmsg_pid != rtnl->local.nl_pid ||
- h->nlmsg_seq != seq) {
- if (junk) {
- err = junk(&nladdr, h, jarg);
- if (err < 0)
- return err;
- }
- continue;
- }
-
- if (h->nlmsg_type == NLMSG_ERROR) {
- struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
- if (l < sizeof(struct nlmsgerr)) {
- fprintf(stderr, "ERROR truncated\n");
- } else {
- errno = -err->error;
- if (errno == 0) {
- if (answer)
- memcpy(answer, h, h->nlmsg_len);
- return 0;
- }
- perror("RTNETLINK answers");
- }
- return -1;
- }
- if (answer) {
- memcpy(answer, h, h->nlmsg_len);
- return 0;
- }
-
- fprintf(stderr, "Unexpected reply!!!\n");
-
- status -= NLMSG_ALIGN(len);
- h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
- }
- if (msg.msg_flags & MSG_TRUNC) {
- fprintf(stderr, "Message truncated\n");
- continue;
- }
- if (status) {
- fprintf(stderr, "!!!Remnant of size %d\n", status);
- exit(1);
- }
- }
-}
-
-int rtnl_listen(struct rtnl_handle *rtnl,
- rtnl_filter_t handler,
- void *jarg)
-{
- int status;
- struct nlmsghdr *h;
- struct sockaddr_nl nladdr;
- struct iovec iov;
- struct msghdr msg = {
- .msg_name = &nladdr,
- .msg_namelen = sizeof(nladdr),
- .msg_iov = &iov,
- .msg_iovlen = 1,
- };
- char buf[8192];
-
- memset(&nladdr, 0, sizeof(nladdr));
- nladdr.nl_family = AF_NETLINK;
- nladdr.nl_pid = 0;
- nladdr.nl_groups = 0;
-
- iov.iov_base = buf;
- while (1) {
- iov.iov_len = sizeof(buf);
- status = recvmsg(rtnl->fd, &msg, 0);
-
- if (status < 0) {
- if (errno == EINTR)
- continue;
- perror("OVERRUN");
- continue;
- }
- if (status == 0) {
- fprintf(stderr, "EOF on netlink\n");
- return -1;
- }
- if (msg.msg_namelen != sizeof(nladdr)) {
- fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen);
- exit(1);
- }
- for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
- int err;
- int len = h->nlmsg_len;
- int l = len - sizeof(*h);
-
- if (l<0 || len>status) {
- if (msg.msg_flags & MSG_TRUNC) {
- fprintf(stderr, "Truncated message\n");
- return -1;
- }
- fprintf(stderr, "!!!malformed message: len=%d\n", len);
- exit(1);
- }
-
- err = handler(&nladdr, h, jarg);
- if (err < 0)
- return err;
-
- status -= NLMSG_ALIGN(len);
- h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
- }
- if (msg.msg_flags & MSG_TRUNC) {
- fprintf(stderr, "Message truncated\n");
- continue;
- }
- if (status) {
- fprintf(stderr, "!!!Remnant of size %d\n", status);
- exit(1);
- }
- }
-}
-
-int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler,
- void *jarg)
-{
- int status;
- struct sockaddr_nl nladdr;
- char buf[8192];
- struct nlmsghdr *h = (void*)buf;
-
- memset(&nladdr, 0, sizeof(nladdr));
- nladdr.nl_family = AF_NETLINK;
- nladdr.nl_pid = 0;
- nladdr.nl_groups = 0;
-
- while (1) {
- int err, len, type;
- int l;
-
- status = fread(&buf, 1, sizeof(*h), rtnl);
-
- if (status < 0) {
- if (errno == EINTR)
- continue;
- perror("rtnl_from_file: fread");
- return -1;
- }
- if (status == 0)
- return 0;
-
- len = h->nlmsg_len;
- type= h->nlmsg_type;
- l = len - sizeof(*h);
-
- if (l<0 || len>sizeof(buf)) {
- fprintf(stderr, "!!!malformed message: len=%d @%lu\n",
- len, ftell(rtnl));
- return -1;
- }
-
- status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl);
-
- if (status < 0) {
- perror("rtnl_from_file: fread");
- return -1;
- }
- if (status < l) {
- fprintf(stderr, "rtnl-from_file: truncated message\n");
- return -1;
- }
-
- err = handler(&nladdr, h, jarg);
- if (err < 0)
- return err;
- }
-}
-
-int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data)
-{
- int len = RTA_LENGTH(4);
- struct rtattr *rta;
- if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) {
- fprintf(stderr,"addattr32: Error! max allowed bound %d exceeded\n",maxlen);
- return -1;
- }
- rta = NLMSG_TAIL(n);
- rta->rta_type = type;
- rta->rta_len = len;
- memcpy(RTA_DATA(rta), &data, 4);
- n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
- return 0;
-}
-
-int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
- int alen)
-{
- int len = RTA_LENGTH(alen);
- struct rtattr *rta;
-
- if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
- fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",maxlen);
- return -1;
- }
- rta = NLMSG_TAIL(n);
- rta->rta_type = type;
- rta->rta_len = len;
- memcpy(RTA_DATA(rta), data, alen);
- n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
- return 0;
-}
-
-int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len)
-{
- if (NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) {
- fprintf(stderr, "addraw_l ERROR: message exceeded bound of %d\n",maxlen);
- return -1;
- }
-
- memcpy(NLMSG_TAIL(n), data, len);
- memset((void *) NLMSG_TAIL(n) + len, 0, NLMSG_ALIGN(len) - len);
- n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len);
- return 0;
-}
-
-int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data)
-{
- int len = RTA_LENGTH(4);
- struct rtattr *subrta;
-
- if (RTA_ALIGN(rta->rta_len) + len > maxlen) {
- fprintf(stderr,"rta_addattr32: Error! max allowed bound %d exceeded\n",maxlen);
- return -1;
- }
- subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
- subrta->rta_type = type;
- subrta->rta_len = len;
- memcpy(RTA_DATA(subrta), &data, 4);
- rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len;
- return 0;
-}
-
-int rta_addattr_l(struct rtattr *rta, int maxlen, int type,
- const void *data, int alen)
-{
- struct rtattr *subrta;
- int len = RTA_LENGTH(alen);
-
- if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) {
- fprintf(stderr,"rta_addattr_l: Error! max allowed bound %d exceeded\n",maxlen);
- return -1;
- }
- subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
- subrta->rta_type = type;
- subrta->rta_len = len;
- memcpy(RTA_DATA(subrta), data, alen);
- rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len);
- return 0;
-}
-
-int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
-{
- memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
- while (RTA_OK(rta, len)) {
- if (rta->rta_type <= max)
- tb[rta->rta_type] = rta;
- rta = RTA_NEXT(rta,len);
- }
- if (len)
- fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len);
- return 0;
-}
-
-int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len)
-{
- int i = 0;
-
- memset(tb, 0, sizeof(struct rtattr *) * max);
- while (RTA_OK(rta, len)) {
- if (rta->rta_type <= max && i < max)
- tb[i++] = rta;
- rta = RTA_NEXT(rta,len);
- }
- if (len)
- fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len);
- return i;
-}
diff --git a/tools/python/xen/lowlevel/netlink/libnetlink.h b/tools/python/xen/lowlevel/netlink/libnetlink.h
deleted file mode 100644
index 8a4e6c6..0000000
--- a/tools/python/xen/lowlevel/netlink/libnetlink.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef __LIBNETLINK_H__
-#define __LIBNETLINK_H__ 1
-
-#include <netinet/in.h>
-#include <asm/types.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-
-struct rtnl_handle
-{
- int fd;
- struct sockaddr_nl local;
- struct sockaddr_nl peer;
- __u32 seq;
- __u32 dump;
-};
-
-extern int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions);
-extern int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, int protocol);
-extern void rtnl_close(struct rtnl_handle *rth);
-extern int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type);
-extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len);
-
-typedef int (*rtnl_filter_t)(const struct sockaddr_nl *,
- struct nlmsghdr *n, void *);
-extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter,
- void *arg1,
- rtnl_filter_t junk,
- void *arg2);
-extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
- unsigned groups, struct nlmsghdr *answer,
- rtnl_filter_t junk,
- void *jarg);
-extern int rtnl_send(struct rtnl_handle *rth, const char *buf, int);
-
-
-extern int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data);
-extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int alen);
-extern int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len);
-extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data);
-extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, const void *data, int alen);
-
-extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len);
-extern int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len);
-
-#define parse_rtattr_nested(tb, max, rta) \
- (parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)))
-
-extern int rtnl_listen(struct rtnl_handle *, rtnl_filter_t handler,
- void *jarg);
-extern int rtnl_from_file(FILE *, rtnl_filter_t handler,
- void *jarg);
-
-#define NLMSG_TAIL(nmsg) \
- ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
-
-#endif /* __LIBNETLINK_H__ */
-
diff --git a/tools/python/xen/lowlevel/netlink/netlink.c b/tools/python/xen/lowlevel/netlink/netlink.c
deleted file mode 100644
index c48b8e4..0000000
--- a/tools/python/xen/lowlevel/netlink/netlink.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* python binding to libnetlink */
-
-#include <Python.h>
-#include "libnetlink.h"
-
-#define PKG "xen.lowlevel.netlink"
-
-typedef struct {
- PyObject_HEAD
- int opened;
- struct rtnl_handle rth;
-} PyRtnlObject;
-
-/* todo: subscriptions? */
-static PyObject* PyRtnl_new(PyTypeObject* type, PyObject* args,
- PyObject* kwargs)
-{
- return type->tp_alloc(type, 0);
-}
-
-static int PyRtnl_init(PyObject* obj, PyObject* args, PyObject* kwargs)
-{
- PyRtnlObject* self = (PyRtnlObject*)obj;
-
- if (rtnl_open(&self->rth, 0) < 0) {
- PyErr_SetString(PyExc_IOError, "could not open rtnl handle");
- return -1;
- }
-
- return 0;
-}
-
-static void PyRtnl_dealloc(PyRtnlObject* obj)
-{
- PyRtnlObject* self = (PyRtnlObject*)obj;
-
- rtnl_close(&self->rth);
-}
-
-static PyObject* pyrtnl_talk(PyObject* obj, PyObject* args)
-{
- PyRtnlObject* self = (PyRtnlObject*)obj;
- char* msg;
- int len;
- int peer = 0;
- int groups = 0;
-
- if (!PyArg_ParseTuple(args, "s#|ii", &msg, &len, &peer, &groups))
- return NULL;
-
- if (rtnl_talk(&self->rth, (struct nlmsghdr*)msg, peer, groups, NULL, NULL,
- NULL) < 0)
- {
- PyErr_SetString(PyExc_IOError, "error sending message");
- return NULL;
- }
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject* pyrtnl_wilddump_request(PyObject* obj, PyObject* args)
-{
- PyRtnlObject* self = (PyRtnlObject*)obj;
- int family, type;
-
- if (!PyArg_ParseTuple(args, "ii", &family, &type))
- return NULL;
-
- if (rtnl_wilddump_request(&self->rth, family, type) < 0) {
- PyErr_SetString(PyExc_IOError, "could not send dump request");
- return NULL;
- }
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject* pyrtnl_dump_request(PyObject* obj, PyObject* args)
-{
- PyRtnlObject* self = (PyRtnlObject*)obj;
- int type;
- char* req;
- int len;
-
- if (!PyArg_ParseTuple(args, "is#", &type, &req, &len))
- return NULL;
-
- if (rtnl_dump_request(&self->rth, type, req, len) < 0) {
- PyErr_SetString(PyExc_IOError, "could not send dump request");
- return NULL;
- }
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-/* translate args to python and call python callback */
-static int dump_filter_helper(const struct sockaddr_nl *who,
- struct nlmsghdr *n, void *arg)
-{
- PyObject* filter = arg;
- PyObject* args;
- PyObject* result;
-
- args = Py_BuildValue("s#s#", who, sizeof(*who), n, n->nlmsg_len);
- result = PyObject_CallObject(filter, args);
- Py_DECREF(args);
- if (!result)
- return -1;
-
- /* result is ignored as long as an exception isn't raised */
- Py_DECREF(result);
- return 0;
-}
-
-static PyObject* pyrtnl_dump_filter(PyObject* obj, PyObject* args)
-{
- PyRtnlObject* self = (PyRtnlObject*)obj;
- PyObject *filter;
-
- if (!PyArg_ParseTuple(args, "O:dump_filter", &filter))
- return NULL;
-
- if (!PyCallable_Check(filter)) {
- PyErr_SetString(PyExc_TypeError, "parameter must be callable");
- return NULL;
- }
-
- Py_INCREF(filter);
- if (rtnl_dump_filter(&self->rth, dump_filter_helper, filter, NULL,
- NULL) < 0)
- {
- Py_DECREF(filter);
- return NULL;
- }
- Py_DECREF(filter);
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyMethodDef PyRtnl_methods[] = {
- { "talk", pyrtnl_talk, METH_VARARGS,
- "send a message to rtnetlink and receive a response.\n" },
- { "wilddump_request", pyrtnl_wilddump_request, METH_VARARGS,
- "dump objects.\n" },
- { "dump_request", pyrtnl_dump_request, METH_VARARGS,
- "start a dump of a particular netlink type.\n" },
- { "dump_filter", pyrtnl_dump_filter, METH_VARARGS,
- "iterate over an rtnl dump.\n" },
- { NULL }
-};
-
-static PyTypeObject PyRtnlType = {
- PyObject_HEAD_INIT(NULL)
- 0, /* ob_size */
- PKG ".rtnl", /* tp_name */
- sizeof(PyRtnlObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)PyRtnl_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
- NULL, /* tp_getattr */
- NULL, /* tp_setattr */
- NULL, /* tp_compare */
- NULL, /* tp_repr */
- NULL, /* tp_as_number */
- NULL, /* tp_as_sequence */
- NULL, /* tp_as_mapping */
- NULL, /* tp_hash */
- NULL, /* tp_call */
- NULL, /* tp_str */
- NULL, /* tp_getattro */
- NULL, /* tp_setattro */
- NULL, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- "rtnetlink handle", /* tp_doc */
- NULL, /* tp_traverse */
- NULL, /* tp_clear */
- NULL, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- NULL, /* tp_iter */
- NULL, /* tp_iternext */
- PyRtnl_methods, /* tp_methods */
- NULL, /* tp_members */
- NULL, /* tp_getset */
- NULL, /* tp_base */
- NULL, /* tp_dict */
- NULL, /* tp_descr_get */
- NULL, /* tp_descr_set */
- 0, /* tp_dictoffset */
- PyRtnl_init, /* tp_init */
- NULL, /* tp_alloc */
- PyRtnl_new, /* tp_new */
-};
-
-static PyMethodDef methods[] = {
- { NULL }
-};
-
-static char doc[] = "libnetlink wrapper";
-
-PyMODINIT_FUNC initnetlink(void)
-{
- PyObject *mod;
-
- if (PyType_Ready(&PyRtnlType) == -1)
- return;
-
- if (!(mod = Py_InitModule3(PKG, methods, doc)))
- return;
-
- Py_INCREF(&PyRtnlType);
- PyModule_AddObject(mod, "rtnl", (PyObject *)&PyRtnlType);
-}
diff --git a/tools/python/xen/lowlevel/process/process.c b/tools/python/xen/lowlevel/process/process.c
deleted file mode 100644
index a1e71bc..0000000
--- a/tools/python/xen/lowlevel/process/process.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.
- *
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <Python.h>
-
-#include <libcontract.h>
-#include <sys/contract/process.h>
-#include <fcntl.h>
-#include <stdio.h>
-
-/*
- * On Solaris, xend runs under a contract as an smf(5) service. As a
- * result, when spawning long-running children such as a domain's
- * qemu-dm instantiation, we have to make sure it's in a separate
- * contract. Before we fork, we must activate a separate process
- * contract template to place the child processes in a new contract.
- */
-
-static PyObject *
-pyprocess_activate(PyObject *o, PyObject *args, PyObject *kwargs)
-{
- static char *kwlist[] = { "name", NULL };
- char *name = NULL;
- int flags;
- int cfd;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &name))
- return (NULL);
-
- cfd = open64("/system/contract/process/template", O_RDWR);
-
- if (cfd == -1)
- goto err;
-
- if ((flags = fcntl(cfd, F_GETFD, 0)) == -1)
- goto err;
-
- if (fcntl(cfd, F_SETFD, flags | FD_CLOEXEC) == -1)
- goto err;
-
- if (name != NULL)
- ct_pr_tmpl_set_svc_aux(cfd, name);
-
- if (ct_tmpl_activate(cfd))
- goto err;
-
- return (PyInt_FromLong((long)cfd));
-
-err:
- if (cfd != -1)
- close(cfd);
- PyErr_SetFromErrno(PyExc_OSError);
- return (NULL);
-}
-
-static PyObject *
-pyprocess_clear(PyObject *o, PyObject *args, PyObject *kwargs)
-{
- static char *kwlist[] = { "contract", NULL };
- int cfd;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &cfd))
- return (NULL);
-
- if (ct_tmpl_clear(cfd) != 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- return (NULL);
- }
-
- close(cfd);
-
- Py_INCREF(Py_None);
- return (Py_None);
-}
-
-static PyObject *
-pyprocess_abandon_latest(PyObject *o, PyObject *args, PyObject *kwargs)
-{
- static char *kwlist[] = { NULL };
- static char path[PATH_MAX];
- ct_stathdl_t st;
- ctid_t latest;
- int cfd;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
- return (NULL);
-
- cfd = open64("/system/contract/process/latest", O_RDONLY);
- if (cfd == -1)
- goto err;
-
- ct_status_read(cfd, CTD_COMMON, &st);
- latest = ct_status_get_id(st);
- ct_status_free(st);
- close(cfd);
-
- snprintf(path, PATH_MAX, "/system/contract/process/%ld/ctl",
- (long)latest);
-
- if ((cfd = open64(path, O_WRONLY)) < 0)
- goto err;
- if (ct_ctl_abandon(cfd))
- goto err;
- close(cfd);
-
- Py_INCREF(Py_None);
- return (Py_None);
-err:
- PyErr_SetFromErrno(PyExc_OSError);
- return (NULL);
-}
-
-PyDoc_STRVAR(pyprocess_activate__doc__,
- "activate(name)\n"
- "\n"
- "Activate a new process contract template. If name is given,\n"
- "it is used as the template's auxiliary value.\n"
- "Returns the new contract template.\n");
-
-PyDoc_STRVAR(pyprocess_clear__doc__,
- "clear(contract)\n"
- "\n"
- "Clear and close the given contract template.\n");
-
-PyDoc_STRVAR(pyprocess_abandon_latest__doc__,
- "abandon_latest()\n"
- "\n"
- "Abandon the latest contract created by this thread.\n");
-
-static struct PyMethodDef pyprocess_module_methods[] = {
- { "activate", (PyCFunction) pyprocess_activate,
- METH_VARARGS|METH_KEYWORDS, pyprocess_activate__doc__ },
- { "clear", (PyCFunction) pyprocess_clear,
- METH_VARARGS|METH_KEYWORDS, pyprocess_clear__doc__ },
- { "abandon_latest", (PyCFunction) pyprocess_abandon_latest,
- METH_VARARGS|METH_KEYWORDS, pyprocess_abandon_latest__doc__ },
- { NULL, NULL, 0, NULL }
-};
-
-PyMODINIT_FUNC
-initprocess(void)
-{
- Py_InitModule("process", pyprocess_module_methods);
-}
diff --git a/tools/python/xen/lowlevel/scf/scf.c b/tools/python/xen/lowlevel/scf/scf.c
deleted file mode 100644
index 22a7960..0000000
--- a/tools/python/xen/lowlevel/scf/scf.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * 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.
- *
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <Python.h>
-
-#include <libscf.h>
-#include <stdio.h>
-
-#define XEND_FMRI "svc:/system/xvm/xend:default"
-#define XEND_PG "config"
-
-static PyObject *scf_exc;
-
-static void *
-scf_exception(const char *err, const char *value)
-{
- int scferr = scf_error();
- const char *scfstrerr = scf_strerror(scferr);
- PyObject *obj = Py_BuildValue("(isss)", scferr, err, scfstrerr, value);
- PyErr_SetObject(scf_exc, obj);
- return (NULL);
-}
-
-static PyObject *
-pyscf_get_bool(PyObject *o, PyObject *args, PyObject *kwargs)
-{
- static char *kwlist[] = { "name", NULL };
- scf_simple_prop_t *prop;
- uint8_t *val;
- char *name;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
- return (NULL);
-
- prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
-
- if (prop == NULL)
- return (scf_exception("scf_simple_prop_get() failed", name));
-
- if ((val = scf_simple_prop_next_boolean(prop)) == NULL)
- return (scf_exception("scf_simple_prop_next_boolean() failed",
- name));
-
- if (*val) {
- scf_simple_prop_free(prop);
- Py_INCREF(Py_True);
- return (Py_True);
- }
-
- scf_simple_prop_free(prop);
- Py_INCREF(Py_False);
- return (Py_False);
-}
-
-static PyObject *
-pyscf_get_int(PyObject *o, PyObject *args, PyObject *kwargs)
-{
- static char *kwlist[] = { "name", NULL };
- scf_simple_prop_t *prop;
- PyObject *obj;
- int64_t *val;
- char *name;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
- return (NULL);
-
- prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
-
- if (prop == NULL)
- return (scf_exception("scf_simple_prop_get() failed", name));
-
- if ((val = scf_simple_prop_next_integer(prop)) == NULL)
- return (scf_exception("scf_simple_prop_next_integer() failed",
- name));
-
- obj = PyInt_FromLong((long)*val);
- scf_simple_prop_free(prop);
- return (obj);
-}
-
-static PyObject *
-pyscf_get_string(PyObject *o, PyObject *args, PyObject *kwargs)
-{
- static char *kwlist[] = { "name", NULL };
- scf_simple_prop_t *prop;
- PyObject *obj;
- char *name;
- char *str;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
- return (NULL);
-
- prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
-
- if (prop == NULL)
- return (scf_exception("scf_simple_prop_get() failed", name));
-
- if ((str = scf_simple_prop_next_astring(prop)) == NULL) {
- scf_simple_prop_free(prop);
- return (scf_exception("scf_simple_prop_next_astring() failed",
- name));
- }
-
- obj = PyString_FromString(str);
- scf_simple_prop_free(prop);
- return (obj);
-}
-
-PyDoc_STRVAR(pyscf_get_bool__doc__,
- "get_bool(name) - get the value of the named boolean property");
-PyDoc_STRVAR(pyscf_get_int__doc__,
- "get_int(name) - get the value of the named integer property");
-PyDoc_STRVAR(pyscf_get_string__doc__,
- "get_string(name) - get the value of the named string property");
-
-static struct PyMethodDef pyscf_module_methods[] = {
- { "get_bool", (PyCFunction) pyscf_get_bool,
- METH_VARARGS|METH_KEYWORDS, pyscf_get_bool__doc__ },
- { "get_int", (PyCFunction) pyscf_get_int,
- METH_VARARGS|METH_KEYWORDS, pyscf_get_int__doc__ },
- { "get_string", (PyCFunction) pyscf_get_string,
- METH_VARARGS|METH_KEYWORDS, pyscf_get_string__doc__ },
- { NULL, NULL, 0, NULL }
-};
-
-PyMODINIT_FUNC
-initscf(void)
-{
- PyObject *m;
- m = Py_InitModule("scf", pyscf_module_methods);
-
- scf_exc = PyErr_NewException("scf.error", NULL, NULL);
- Py_INCREF(scf_exc);
- PyModule_AddObject(m, "error", scf_exc);
- PyModule_AddIntConstant(m, "SCF_ERROR_NOT_FOUND", SCF_ERROR_NOT_FOUND);
-}
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index 737bdac..d95d459 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -256,7 +256,8 @@ static PyObject *pyxc_vcpu_setaffinity(XcObject *self,
}
}
- if ( xc_vcpu_setaffinity(self->xc_handle, dom, vcpu, cpumap) != 0 )
+ if ( xc_vcpu_setaffinity(self->xc_handle, dom, vcpu, cpumap,
+ NULL, XEN_VCPUAFFINITY_HARD) != 0 )
{
free(cpumap);
return pyxc_error_to_exception(self->xc_handle);
@@ -403,7 +404,8 @@ static PyObject *pyxc_vcpu_getinfo(XcObject *self,
if(cpumap == NULL)
return pyxc_error_to_exception(self->xc_handle);
- rc = xc_vcpu_getaffinity(self->xc_handle, dom, vcpu, cpumap);
+ rc = xc_vcpu_getaffinity(self->xc_handle, dom, vcpu, cpumap,
+ NULL, XEN_VCPUAFFINITY_HARD);
if ( rc < 0 )
{
free(cpumap);
@@ -544,27 +546,27 @@ static PyObject *pyxc_linux_build(XcObject *self,
return pyxc_error_to_exception(self->xc_handle);
}
-static PyObject *pyxc_get_hvm_param(XcObject *self,
+static PyObject *pyxc_hvm_param_get(XcObject *self,
PyObject *args,
PyObject *kwds)
{
uint32_t dom;
int param;
- unsigned long value;
+ uint64_t value;
static char *kwd_list[] = { "domid", "param", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
&dom, ¶m) )
return NULL;
- if ( xc_get_hvm_param(self->xc_handle, dom, param, &value) != 0 )
+ if ( xc_hvm_param_get(self->xc_handle, dom, param, &value) != 0 )
return pyxc_error_to_exception(self->xc_handle);
- return PyLong_FromUnsignedLong(value);
+ return PyLong_FromUnsignedLongLong(value);
}
-static PyObject *pyxc_set_hvm_param(XcObject *self,
+static PyObject *pyxc_hvm_param_set(XcObject *self,
PyObject *args,
PyObject *kwds)
{
@@ -577,7 +579,7 @@ static PyObject *pyxc_set_hvm_param(XcObject *self,
&dom, ¶m, &value) )
return NULL;
- if ( xc_set_hvm_param(self->xc_handle, dom, param, value) != 0 )
+ if ( xc_hvm_param_set(self->xc_handle, dom, param, value) != 0 )
return pyxc_error_to_exception(self->xc_handle);
Py_INCREF(zero);
@@ -1183,6 +1185,40 @@ static PyObject *pyxc_physinfo(XcObject *self)
"virt_caps", virt_caps);
}
+static PyObject *pyxc_getcpuinfo(XcObject *self, PyObject *args, PyObject *kwds)
+{
+ xc_cpuinfo_t *cpuinfo, *cpuinfo_ptr;
+ PyObject *cpuinfo_list_obj, *cpuinfo_obj;
+ int max_cpus, nr_cpus, ret, i;
+ static char *kwd_list[] = { "max_cpus", NULL };
+ static char kwd_type[] = "i";
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, kwd_type, kwd_list, &max_cpus))
+ return NULL;
+
+ cpuinfo = malloc(sizeof(xc_cpuinfo_t) * max_cpus);
+ if (!cpuinfo)
+ return NULL;
+
+ ret = xc_getcpuinfo(self->xc_handle, max_cpus, cpuinfo, &nr_cpus);
+ if (ret != 0) {
+ free(cpuinfo);
+ return pyxc_error_to_exception(self->xc_handle);
+ }
+
+ cpuinfo_list_obj = PyList_New(0);
+ cpuinfo_ptr = cpuinfo;
+ for (i = 0; i < nr_cpus; i++) {
+ cpuinfo_obj = Py_BuildValue("{s:k}", "idletime", cpuinfo_ptr->idletime);
+ PyList_Append(cpuinfo_list_obj, cpuinfo_obj);
+ cpuinfo_ptr++;
+ }
+
+ free(cpuinfo);
+
+ return cpuinfo_list_obj;
+}
+
static PyObject *pyxc_topologyinfo(XcObject *self)
{
#define MAX_CPU_INDEX 255
@@ -2446,7 +2482,7 @@ static PyMethodDef pyxc_methods[] = {
"Returns: None on sucess. Raises exception on error.\n" },
{ "hvm_get_param",
- (PyCFunction)pyxc_get_hvm_param,
+ (PyCFunction)pyxc_hvm_param_get,
METH_VARARGS | METH_KEYWORDS, "\n"
"get a parameter of HVM guest OS.\n"
" dom [int]: Identifier of domain to build into.\n"
@@ -2454,7 +2490,7 @@ static PyMethodDef pyxc_methods[] = {
"Returns: [long] value of the param.\n" },
{ "hvm_set_param",
- (PyCFunction)pyxc_set_hvm_param,
+ (PyCFunction)pyxc_hvm_param_set,
METH_VARARGS | METH_KEYWORDS, "\n"
"set a parameter of HVM guest OS.\n"
" dom [int]: Identifier of domain to build into.\n"
@@ -2611,6 +2647,13 @@ static PyMethodDef pyxc_methods[] = {
"Returns [dict]: information about the hardware"
" [None]: on failure.\n" },
+ { "getcpuinfo",
+ (PyCFunction)pyxc_getcpuinfo,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Get information about physical CPUs\n"
+ "Returns [list]: information about physical CPUs"
+ " [None]: on failure.\n" },
+
{ "topologyinfo",
(PyCFunction)pyxc_topologyinfo,
METH_NOARGS, "\n"
diff --git a/tools/python/xen/remus/__init__.py b/tools/python/xen/remus/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/tools/python/xen/remus/blkdev.py b/tools/python/xen/remus/blkdev.py
deleted file mode 100644
index 6cd1fa2..0000000
--- a/tools/python/xen/remus/blkdev.py
+++ /dev/null
@@ -1,31 +0,0 @@
-handlers = []
-
-class BlkDevException(Exception): pass
-
-class BlkDev(object):
- "Object representing a VM block device"
- def __init__(self, **props):
- self.uname = ''
- if 'dev' not in props:
- raise BlkDevException('no device')
- #if 'uname' not in props:
- #raise BlkDevException('no uname')
- if 'mode' not in props:
- raise BlkDevException('no mode')
- self.__dict__.update(props)
- self.dev = props['dev'].rstrip(':disk')
-
- def __str__(self):
- return '%s,%s,%s' % (self.uname, self.dev, self.mode)
-
-def register(handler):
- "register a block device class with parser"
- if handler not in handlers:
- handlers.insert(0, handler)
-
-def parse(props):
- "turn a vm device dictionary into a blkdev object"
- for handler in handlers:
- if handler.handles(**props):
- return handler(**props)
- return BlkDev(**props)
diff --git a/tools/python/xen/remus/device.py b/tools/python/xen/remus/device.py
deleted file mode 100644
index 970e1ea..0000000
--- a/tools/python/xen/remus/device.py
+++ /dev/null
@@ -1,397 +0,0 @@
-# Remus device interface
-#
-# Coordinates with devices at suspend, resume, and commit hooks
-
-import os, re, fcntl
-
-import netlink, qdisc, util
-
-class ReplicatedDiskException(Exception): pass
-class BufferedNICException(Exception): pass
-
-class CheckpointedDevice(object):
- 'Base class for buffered devices'
-
- def postsuspend(self):
- 'called after guest has suspended'
- pass
-
- def preresume(self):
- 'called before guest resumes'
- pass
-
- def commit(self):
- 'called when backup has acknowledged checkpoint reception'
- pass
-
-class ReplicatedDisk(CheckpointedDevice):
- """
- Send a checkpoint message to a replicated disk while the domain
- is paused between epochs.
- """
- FIFODIR = '/var/run/tap'
- SEND_CHECKPOINT = 20
- WAIT_CHECKPOINT_ACK = 30
-
- def __init__(self, disk):
- # look up disk, make sure it is tap:buffer, and set up socket
- # to request commits.
- self.ctlfd = None
- self.msgfd = None
- self.is_drbd = False
- self.ackwait = False
-
- if disk.uname.startswith('tap:remus:') or disk.uname.startswith('tap:tapdisk:remus:'):
- fifo = re.match("tap:.*(remus.*)\|", disk.uname).group(1).replace(':', '_')
- absfifo = os.path.join(self.FIFODIR, fifo)
- absmsgfifo = absfifo + '.msg'
-
- self.installed = False
- self.ctlfd = open(absfifo, 'w+b')
- self.msgfd = open(absmsgfifo, 'r+b')
- elif disk.uname.startswith('drbd:'):
- #get the drbd device associated with this resource
- drbdres = re.match("drbd:(.*)", disk.uname).group(1)
- drbddev = util.runcmd("drbdadm sh-dev %s" % drbdres).rstrip()
-
- #check for remus supported drbd installation
- rconf = util.runcmd("drbdsetup %s show" % drbddev)
- if rconf.find('protocol D;') == -1:
- raise ReplicatedDiskException('Remus support for DRBD disks requires the '
- 'resources to operate in protocol D. Please make '
- 'sure that you have installed the remus supported DRBD '
- 'version from git://aramis.nss.cs.ubc.ca/drbd-8.3-remus '
- 'and enabled protocol D in the resource config')
-
- #check if resource is in connected state
- cstate = util.runcmd("drbdadm cstate %s" % drbdres).rstrip()
- if cstate != 'Connected':
- raise ReplicatedDiskException('DRBD resource %s is not in connected state!'
- % drbdres)
-
- #open a handle to the resource so that we could issue chkpt ioctls
- self.ctlfd = open(drbddev, 'r')
- self.is_drbd = True
- else:
- raise ReplicatedDiskException('Disk is not replicated: %s' %
- str(disk))
-
- def __del__(self):
- self.uninstall()
-
- def uninstall(self):
- if self.ctlfd:
- self.ctlfd.close()
- self.ctlfd = None
-
- def postsuspend(self):
- if not self.is_drbd:
- os.write(self.ctlfd.fileno(), 'flush')
- elif not self.ackwait:
- if (fcntl.ioctl(self.ctlfd.fileno(), self.SEND_CHECKPOINT, 0) > 0):
- self.ackwait = False
- else:
- self.ackwait = True
-
- def preresume(self):
- if self.is_drbd and self.ackwait:
- fcntl.ioctl(self.ctlfd.fileno(), self.WAIT_CHECKPOINT_ACK, 0)
- self.ackwait = False
-
- def commit(self):
- if not self.is_drbd:
- msg = os.read(self.msgfd.fileno(), 4)
- if msg != 'done':
- print 'Unknown message: %s' % msg
-
-### Network
-
-# shared rtnl handle
-_rth = None
-def getrth():
- global _rth
-
- if not _rth:
- _rth = netlink.rtnl()
- return _rth
-
-class Netbuf(object):
- "Proxy for netdev with a queueing discipline"
-
- @staticmethod
- def devclass():
- "returns the name of this device class"
- return 'unknown'
-
- @classmethod
- def available(cls):
- "returns True if this module can proxy the device"
- return cls._hasdev(cls.devclass())
-
- def __init__(self, devname):
- self.devname = devname
- self.vif = None
-
- # override in subclasses
- def install(self, vif):
- "set up proxy on device"
- raise BufferedNICException('unimplemented')
-
- def uninstall(self):
- "remove proxy on device"
- raise BufferedNICException('unimplemented')
-
- # protected
- @staticmethod
- def _hasdev(devclass):
- """check for existence of device, attempting to load kernel
- module if not present"""
- devname = '%s0' % devclass
- rth = getrth()
-
- if rth.getlink(devname):
- return True
- if util.modprobe(devclass) and rth.getlink(devname):
- return True
-
- return False
-
-class IFBBuffer(Netbuf):
- """Capture packets arriving on a VIF using an ingress filter and tc
- mirred action to forward them to an IFB device.
- """
-
- @staticmethod
- def devclass():
- return 'ifb'
-
- def install(self, vif):
- self.vif = vif
- # voodoo from http://www.linuxfoundation.org/collaborate/workgroups/networking/ifb#Typical_Usage
- util.runcmd('ip link set %s up' % self.devname)
- try:
- util.runcmd('tc qdisc add dev %s ingress' % vif.dev)
- except util.PipeException, e:
- # check if error indicates that ingress qdisc
- # already exists on the vif. If so, ignore it.
- ignoreme = 'RTNETLINK answers: File exists'
- if ignoreme in str(e):
- pass
- else:
- raise e
- util.runcmd('tc filter add dev %s parent ffff: proto ip pref 10 '
- 'u32 match u32 0 0 action mirred egress redirect '
- 'dev %s' % (vif.dev, self.devname))
-
- def uninstall(self):
- try:
- util.runcmd('tc qdisc del dev %s ingress' % self.vif.dev)
- except util.PipeException, e:
- pass
- util.runcmd('ip link set %s down' % self.devname)
-
-class IMQBuffer(Netbuf):
- """Redirect packets coming in on vif to an IMQ device."""
-
- imqebt = '/usr/lib/xen/bin/imqebt'
-
- @staticmethod
- def devclass():
- return 'imq'
-
- def install(self, vif):
- # stopgap hack to set up IMQ for an interface. Wrong in many ways.
- self.vif = vif
-
- for mod in ['imq', 'ebt_imq']:
- util.runcmd(['modprobe', mod])
- util.runcmd("ip link set %s up" % self.devname)
- util.runcmd("%s -F FORWARD" % self.imqebt)
- util.runcmd("%s -A FORWARD -i %s -j imq --todev %s" % (self.imqebt, vif.dev, self.devname))
-
- def uninstall(self):
- util.runcmd("%s -F FORWARD" % self.imqebt)
- util.runcmd('ip link set %s down' % self.devname)
-
-# in order of desirability
-netbuftypes = [IFBBuffer, IMQBuffer]
-
-def selectnetbuf():
- "Find the best available buffer type"
- for driver in netbuftypes:
- if driver.available():
- return driver
-
- raise BufferedNICException('no net buffer available')
-
-class Netbufpool(object):
- """Allocates/releases proxy netdevs (IMQ/IFB)
-
- A file contains a list of entries of the form <pid>:<device>\n
- To allocate a device, lock the file, then claim a new device if
- one is free. If there are no free devices, check each PID for liveness
- and take a device if the PID is dead, otherwise return failure.
- Add an entry to the file before releasing the lock.
- """
- def __init__(self, netbufclass):
- "Create a pool of Device"
- self.netbufclass = netbufclass
- self.path = '/var/run/remus/' + self.netbufclass.devclass()
-
- self.devices = self.getdevs()
-
- pooldir = os.path.dirname(self.path)
- if not os.path.exists(pooldir):
- os.makedirs(pooldir, 0755)
-
- def get(self):
- "allocate a free device"
- def getfreedev(table):
- for dev in self.devices:
- if dev not in table or not util.checkpid(table[dev]):
- return dev
-
- return None
-
- lock = util.Lock(self.path)
- table = self.load()
-
- dev = getfreedev(table)
- if not dev:
- lock.unlock()
- raise BufferedNICException('no free devices')
- dev = self.netbufclass(dev)
-
- table[dev.devname] = os.getpid()
-
- self.save(table)
- lock.unlock()
-
- return dev
-
- def put(self, dev):
- "release claim on device"
- lock = util.Lock(self.path)
- table = self.load()
-
- del table[dev.devname]
-
- self.save(table)
- lock.unlock()
-
- # private
- def load(self):
- """load and parse allocation table"""
- table = {}
- if not os.path.exists(self.path):
- return table
-
- fd = open(self.path)
- for line in fd.readlines():
- iface, pid = line.strip().split()
- table[iface] = int(pid)
- fd.close()
- return table
-
- def save(self, table):
- """write table to disk"""
- lines = ['%s %d\n' % (iface, table[iface]) for iface in sorted(table)]
- fd = open(self.path, 'w')
- fd.writelines(lines)
- fd.close()
-
- def getdevs(self):
- """find all available devices of our device type"""
- ifaces = []
- for line in util.runcmd('ifconfig -a -s').splitlines():
- iface = line.split()[0]
- if iface.startswith(self.netbufclass.devclass()):
- ifaces.append(iface)
-
- return ifaces
-
-class BufferedNIC(CheckpointedDevice):
- """
- Buffer a protected domain's network output between rounds so that
- nothing is issued that a failover might not know about.
- """
-
- def __init__(self, vif):
- self.installed = False
- self.vif = vif
-
- self.pool = Netbufpool(selectnetbuf())
- self.rth = getrth()
-
- self.setup()
-
- def __del__(self):
- self.uninstall()
-
- def postsuspend(self):
- if not self.installed:
- self.install()
-
- self._sendqmsg(qdisc.TC_PLUG_BUFFER)
-
- def commit(self):
- '''Called when checkpoint has been acknowledged by
- the backup'''
- self._sendqmsg(qdisc.TC_PLUG_RELEASE_ONE)
-
- # private
- def _sendqmsg(self, action):
- self.q.action = action
- req = qdisc.changerequest(self.bufdevno, self.handle, self.q)
- self.rth.talk(req.pack())
- return True
-
- def setup(self):
- """install Remus plug on VIF outbound traffic"""
- self.bufdev = self.pool.get()
-
- devname = self.bufdev.devname
- bufdev = self.rth.getlink(devname)
- if not bufdev:
- raise BufferedNICException('could not find device %s' % devname)
-
- self.bufdev.install(self.vif)
-
- self.bufdevno = bufdev['index']
- self.handle = qdisc.TC_H_ROOT
- self.q = qdisc.PlugQdisc()
-
- if not util.modprobe('sch_plug'):
- raise BufferedNICException('could not load sch_plug module')
-
- def install(self):
- devname = self.bufdev.devname
- q = self.rth.getqdisc(self.bufdevno)
- if q:
- if q['kind'] == 'plug':
- self.installed = True
- return
- if q['kind'] not in ('ingress', 'pfifo_fast', 'mq'):
- raise BufferedNICException('there is already a queueing '
- 'discipline %s on %s' % (q['kind'], devname))
-
- print ('installing buffer on %s... ' % devname),
- req = qdisc.addrequest(self.bufdevno, self.handle, self.q)
- self.rth.talk(req.pack())
- self.installed = True
- print 'done.'
-
- def uninstall(self):
- if self.installed:
- try:
- req = qdisc.delrequest(self.bufdevno, self.handle)
- self.rth.talk(req.pack())
- except IOError, e:
- pass
- self.installed = False
-
- try:
- self.bufdev.uninstall()
- except util.PipeException, e:
- pass
- self.pool.put(self.bufdev)
diff --git a/tools/python/xen/remus/image.py b/tools/python/xen/remus/image.py
deleted file mode 100644
index b79d1e5..0000000
--- a/tools/python/xen/remus/image.py
+++ /dev/null
@@ -1,227 +0,0 @@
-# VM image file manipulation
-
-import logging, struct
-
-import vm
-
-SIGNATURE = 'LinuxGuestRecord'
-LONGLEN = struct.calcsize('L')
-INTLEN = struct.calcsize('i')
-PAGE_SIZE = 4096
-# ~0L
-P2M_EXT_SIG = 4294967295L
-# frames per page
-FPP = 1024
-LTAB_MASK = 0xf << 28
-BATCH_SIZE = 1024
-IDXLEN = INTLEN + BATCH_SIZE * LONGLEN
-
-logging.basicConfig(level=logging.DEBUG)
-log = logging.getLogger()
-
-class VMParseException(Exception): pass
-
-class VMImage(object):
- def __init__(self, img=None):
- """img may be a path or a file object.
- If compact is True, apply checkpoints to base image instead
- of simply concatenating them.
- """
- self.img = img
-
- self.dom = None
- self.fd = None
- self.header = None
- self.nr_pfns = 0
- # p2m extension header (unparsed)
- self.p2mext = None
-
- if self.img:
- self.open(self.img)
-
- def open(self, img):
- if isinstance(img, str):
- self.fd = file(img, 'rb')
- else:
- self.fd = img
-
- self.readheader()
-
- def readheader(self):
- sig = self.fd.read(len(SIGNATURE))
- if sig != SIGNATURE:
- raise VMParseException("Bad signature in image")
-
- hlen = self.fd.read(INTLEN)
- hlen, = struct.unpack('!i', hlen)
-
- self.header = self.fd.read(hlen)
- self.dom = parseheader(self.header)
-
- def readp2mfl(self):
- "read the P2M frame list"
- pfnlen = self.fd.read(LONGLEN)
- self.nr_pfns, = struct.unpack('L', pfnlen)
- p2m0 = self.fd.read(LONGLEN)
-
- p2mhdr = p2m0
- p2m0, = struct.unpack('L', p2m0)
- if p2m0 == P2M_EXT_SIG:
- elen = self.fd.read(INTLEN)
- elen, = struct.unpack('I', elen)
-
- self.p2mext = self.fd.read(elen)
-
- p2m0 = self.fd.read(LONGLEN)
- p2m0, = struct.unpack('L', p2m0)
- p2mfl = [p2m0]
-
- p2mfle = (self.nr_pfns + FPP - 1)/FPP - 1
- p2ms = self.fd.read(LONGLEN * p2mfle)
- p2mfl.extend(struct.unpack('%dL' % p2mfle, p2ms))
-
- self.p2mfl = p2mfl
-
- def flush(self):
- self.ofd.write(self.tail)
-
-class Writer(object):
- """compress a stream of checkpoints into a single image of the
- last checkpoint"""
- def __init__(self, fd, compact=False):
- self.fd = fd
- self.compact = compact
-
- self.vm = None
- self.tail = None
- # offset to first batch of pages
- self.imgstart = 0
- # PFN mappings
- self.pfns = []
-
- def __del__(self):
- self.close()
-
- def writeheader(self):
- hlen = struct.pack('!i', len(self.vm.header))
- header = ''.join([SIGNATURE, hlen, self.vm.header])
- self.fd.write(header)
-
- def writep2mfl(self):
- p2m = [struct.pack('L', self.vm.nr_pfns)]
- if self.vm.p2mext:
- p2m.extend([struct.pack('L', P2M_EXT_SIG), self.vm.p2mext])
- p2m.append(struct.pack('%dL' % len(self.vm.p2mfl), *self.vm.p2mfl))
- self.fd.write(''.join(p2m))
-
- def writebatch(self, batch):
- def offset(pfn):
- isz = (pfn / BATCH_SIZE + 1) * IDXLEN
- return self.imgstart + isz + pfn * PAGE_SIZE
-
- if not self.compact:
- return self.fd.write(batch)
-
- batch = parsebatch(batch)
- # sort pages for better disk seek behaviour
- batch.sort(lambda x, y: cmp(x[0] & ~LTAB_MASK, y[0] & ~LTAB_MASK))
-
- for pfndesc, page in batch:
- pfn = pfndesc & ~LTAB_MASK
- if pfn > self.vm.nr_pfns:
- log.error('INVALID PFN: %d' % pfn)
- if len(self.pfns) <= pfn:
- self.pfns.extend([0] * (pfn - len(self.pfns) + 1))
- self.pfns[pfn] = pfndesc
- self.fd.seek(offset(pfn))
- self.fd.write(page)
-
- #print "max offset: %d, %d" % (len(self.pfns), offset(self.pfns[-1]))
-
- def writeindex(self):
- "Write batch header in front of each page"
- hdrlen = INTLEN + BATCH_SIZE * LONGLEN
- batches = (len(self.pfns) + BATCH_SIZE - 1) / BATCH_SIZE
-
- for i in xrange(batches):
- offset = self.imgstart + i * (hdrlen + (PAGE_SIZE * BATCH_SIZE))
- pfnoff = i * BATCH_SIZE
- # python auto-clamps overreads
- pfns = self.pfns[pfnoff:pfnoff + BATCH_SIZE]
-
- self.fd.seek(offset)
- self.fd.write(struct.pack('i', len(pfns)))
- self.fd.write(struct.pack('%dL' % len(pfns), *pfns))
-
- def slurp(self, ifd):
- """Apply an incremental checkpoint to a loaded image.
- accepts a path or a file object."""
- if isinstance(ifd, str):
- ifd = file(ifd, 'rb')
-
- if not self.vm:
- self.vm = VMImage(ifd)
- self.writeheader()
-
- self.vm.readp2mfl()
- self.writep2mfl()
- self.imgstart = self.fd.tell()
-
- while True:
- l, batch = readbatch(ifd)
- if l <= 0:
- break
- self.writebatch(batch)
- self.tail = batch + ifd.read()
-
- def flush(self):
- if self.tail:
- self.fd.seek(0, 2)
- self.fd.write(self.tail)
- if self.compact:
- self.writeindex()
- self.tail = None
-
- def close(self):
- self.flush()
-
-def parseheader(header):
- "parses a header sexpression"
- return vm.parsedominfo(vm.strtosxpr(header))
-
-def makeheader(dominfo):
- "create an image header from a VM dominfo sxpr"
- items = [SIGNATURE]
- sxpr = vm.sxprtostr(dominfo)
- items.append(struct.pack('!i', len(sxpr)))
- items.append(sxpr)
- return ''.join(items)
-
-def readbatch(fd):
- batch = []
- batchlen = fd.read(INTLEN)
- batch.append(batchlen)
- batchlen, = struct.unpack('i', batchlen)
- log.info("batch length: %d" % batchlen)
- if batchlen <= 0:
- return (batchlen, batch[0])
-
- batchfns = fd.read(LONGLEN * batchlen)
- batch.append(batchfns)
- pages = fd.read(PAGE_SIZE * batchlen)
- if len(pages) != PAGE_SIZE * batchlen:
- log.error('SHORT READ: %d' % len(pages))
- batch.append(pages)
-
- return (batchlen, ''.join(batch))
-
-def parsebatch(batch):
- "parse a batch string into pages"
- batchlen, batch = batch[:INTLEN], batch[INTLEN:]
- batchlen, = struct.unpack('i', batchlen)
- #print 'batch length: %d' % batchlen
- pfnlen = batchlen * LONGLEN
- pfns = struct.unpack('%dL' % batchlen, batch[:pfnlen])
- pagebuf = batch[pfnlen:]
- pages = [pagebuf[i*PAGE_SIZE:(i+1)*PAGE_SIZE] for i in xrange(batchlen)]
- return zip(pfns, pages)
diff --git a/tools/python/xen/remus/netlink.py b/tools/python/xen/remus/netlink.py
deleted file mode 100644
index 56ea774..0000000
--- a/tools/python/xen/remus/netlink.py
+++ /dev/null
@@ -1,318 +0,0 @@
-# netlink wrappers
-
-# See include/linux/netlink.h and rtnetlink.h
-
-import socket, struct
-import xen.lowlevel.netlink
-
-NETLINK_ROUTE = 0
-
-NLM_F_REQUEST = 1 # It is request message.
-NLM_F_MULTI = 2 # Multipart message, terminated by NLMSG_DONE
-NLM_F_ACK = 4 # Reply with ack, with zero or error code
-NLM_F_ECHO = 8 # Echo this request
-
-# Modifiers to GET request
-NLM_F_ROOT = 0x100 # specify tree root
-NLM_F_MATCH = 0x200 # return all matching
-NLM_F_ATOMIC = 0x400 # atomic GET
-NLM_F_DUMP = NLM_F_ROOT|NLM_F_MATCH
-
-# Modifiers to NEW request
-NLM_F_REPLACE = 0x100 # Override existing
-NLM_F_EXCL = 0x200 # Do not touch, if it exists
-NLM_F_CREATE = 0x400 # Create, if it does not exist
-NLM_F_APPEND = 0x800 # Add to end of list
-
-RTM_NEWLINK = 16
-RTM_GETLINK = 18
-RTM_NEWQDISC = 36
-RTM_DELQDISC = 37
-RTM_GETQDISC = 38
-
-IFLA_UNSPEC = 0
-IFLA_ADDRESS = 1
-IFLA_BROADCAST = 2
-IFLA_IFNAME = 3
-IFLA_MTU = 4
-IFLA_LINK = 5
-IFLA_QDISC = 6
-IFLA_STATS = 7
-IFLA_COST = 8
-IFLA_PRIORITY = 9
-IFLA_MASTER = 10
-IFLA_WIRELESS = 11
-IFLA_PROTINFO = 12
-IFLA_TXQLEN = 13
-IFLA_MAP = 14
-IFLA_WEIGHT = 15
-
-TCA_UNSPEC = 0
-TCA_KIND = 1
-TCA_OPTIONS = 2
-TCA_STATS = 3
-TCA_XSTATS = 4
-TCA_RATE = 5
-TCA_FCNT = 6
-TCA_STATS2 = 7
-
-class RTNLException(Exception): pass
-
-def align(l, alignto=4):
- return (l + alignto - 1) & ~(alignto - 1)
-
-class rtattr(object):
- "rtattribute"
- fmt = "HH"
- fmtlen = struct.calcsize(fmt)
-
- def __init__(self, msg=None):
- if msg:
- self.unpack(msg)
- else:
- self.rta_len = 0
- self.rta_type = 0
-
- self.body = ''
-
- def __len__(self):
- return align(self.rta_len)
-
- def pack(self):
- self.rta_len = self.fmtlen + len(self.body)
- s = struct.pack(self.fmt, self.rta_len, self.rta_type) + self.body
- pad = align(self.rta_len) - len(s)
- if pad:
- s += '\0' * pad
- return s
-
- def unpack(self, msg):
- args = struct.unpack(self.fmt, msg[:self.fmtlen])
- self.rta_len, self.rta_type = args
-
- self.body = msg[self.fmtlen:self.rta_len]
-
-class rtattrlist(object):
- def __init__(self, msg):
- self.start = msg
-
- def __iter__(self):
- body = self.start
- while len(body) > rtattr.fmtlen:
- rta = rtattr(body)
- yield rta
- body = body[len(rta):]
-
-class nlmsg(object):
- "netlink message header"
- fmt = "IHHII"
- fmtlen = struct.calcsize(fmt)
-
- def __init__(self, msg=None):
- if msg:
- self.unpack(msg)
- else:
- self.nlmsg_len = 0
- self.nlmsg_type = 0
- self.nlmsg_flags = 0
- self.nlmsg_seq = 0
- self.nlmsg_pid = 0
-
- self.rta = ''
- self.body = ''
-
- def __len__(self):
- return align(self.fmtlen + len(self.body) + len(self.rta))
-
- def addattr(self, type, data):
- attr = rtattr()
- attr.rta_type = type
- attr.body = data
- self.rta += attr.pack()
- self.nlmsg_len = len(self)
-
- def settype(self, cmd):
- self.nlmsg_type = cmd
-
- def pack(self):
- s = struct.pack(self.fmt, len(self), self.nlmsg_type,
- self.nlmsg_flags, self.nlmsg_seq,
- self.nlmsg_pid) + self.body + self.rta
- return s
-
- def unpack(self, msg):
- args = struct.unpack(self.fmt, msg[:self.fmtlen])
- self.nlmsg_len, self.nlmsg_type, self.nlmsg_flags = args[:3]
- self.nlmsg_seq, self.nlmsg_pid = args[3:]
-
- self.body = msg[align(self.fmtlen):]
- self.rta = ''
-
- def __str__(self):
- return '<netlink message, len %d, type %d>' % \
- (self.nlmsg_len, self.nlmsg_type)
-
-class ifinfomsg(object):
- "interface info message"
- fmt = "BxHiII"
- fmtlen = struct.calcsize(fmt)
-
- def __init__(self, msg=None):
- if msg:
- self.unpack(msg)
- else:
- self.ifi_family = 0
- self.ifi_type = 0
- self.ifi_index = 0
- self.ifi_flags = 0
- self.ifi_change = 0
-
- self.body = ''
-
- def unpack(self, msg):
- args = struct.unpack(self.fmt, msg[:self.fmtlen])
- self.ifi_family, self.ifi_type, self.ifi_index= args[:3]
- self.ifi_flags, self.ifi_change = args[3:]
-
- self.body = msg[align(self.fmtlen):]
-
- def __str__(self):
- return '<ifinfo message, family %d, type %d, index %d>' % \
- (self.ifi_family, self.ifi_type, self.ifi_index)
-
-class tcmsg(object):
- "TC message"
- fmt = "BxxxiIII"
- fmtlen = struct.calcsize(fmt)
-
- def __init__(self, msg=None):
- if msg:
- self.unpack(msg)
- else:
- self.tcm_family = socket.AF_UNSPEC
- self.tcm_ifindex = 0
- self.tcm_handle = 0
- self.tcm_parent = 0
- self.tcm_info = 0
-
- self.rta = ''
-
- def unpack(self, msg):
- args = struct.unpack(self.fmt, msg[:self.fmtlen])
- self.tcm_family, self.tcm_ifindex, self.tcm_handle = args[:3]
- self.tcm_parent, self.tcm_info = args[3:]
-
- self.rta = msg[align(self.fmtlen):]
-
- def pack(self):
- return struct.pack(self.fmt, self.tcm_family, self.tcm_ifindex,
- self.tcm_handle, self.tcm_parent, self.tcm_info)
-
- def __str__(self):
- return '<tc message, family %d, index %d>' % \
- (self.tcm_family, self.tcm_ifindex)
-
-class newlinkmsg(object):
- def __init__(self, nlmsg):
- if nlmsg.nlmsg_type != RTM_NEWLINK:
- raise RTNLException("wrong message type")
- self.nlmsg = nlmsg
- self.ifi = ifinfomsg(self.nlmsg.body)
-
- self.rtattrs = {}
- for rta in rtattrlist(self.ifi.body):
- self.rtattrs[rta.rta_type] = rta.body
-
-class newqdiscmsg(object):
- def __init__(self, nlmsg):
- if nlmsg.nlmsg_type != RTM_NEWQDISC:
- raise RTNLException("wrong message type")
- self.nlmsg = nlmsg
- self.t = tcmsg(self.nlmsg.body)
-
- self.rtattrs = {}
- for rta in rtattrlist(self.t.rta):
- self.rtattrs[rta.rta_type] = rta.body
-
-class rtnl(object):
- def __init__(self):
- self._rth = xen.lowlevel.netlink.rtnl()
- self._linkcache = None
-
- def getlink(self, key, cached=False):
- """returns the interface object corresponding to the key, which
- may be an index number or device name."""
- if not cached:
- self._linkcache = None
- if self._linkcache is None:
- self._linkcache = self.getlinks()
-
- if isinstance(key, int):
- return self._linkcache.get(key)
-
- for k, v in self._linkcache.iteritems():
- if v['name'] == key:
- return v
-
- return None
-
- def getlinks(self):
- """returns a dictionary of interfaces keyed by kernel
- interface index"""
- links = {}
- def dumpfilter(addr, msgstr):
- msg = newlinkmsg(nlmsg(msgstr))
- idx = msg.ifi.ifi_index
- ifname = msg.rtattrs[IFLA_IFNAME].strip('\0')
- address = msg.rtattrs.get(IFLA_ADDRESS)
-
- link = {'index': idx,
- 'type': msg.ifi.ifi_type,
- 'name': ifname,
- 'address': address}
- links[idx] = link
-
- self._rth.wilddump_request(socket.AF_UNSPEC, RTM_GETLINK)
- self._rth.dump_filter(dumpfilter)
-
- return links
-
- def getqdisc(self, dev):
- """returns the queueing discipline on device dev, which may be
- specified by kernel index or device name"""
- qdiscs = self.getqdiscs(dev)
- if qdiscs:
- return qdiscs.values()[0]
- return None
-
- def getqdiscs(self, dev=None):
- """returns a dictionary of queueing disciplines keyed by kernel
- interface index"""
- qdiscs = {}
- def dumpfilter(addr, msgstr):
- msg = newqdiscmsg(nlmsg(msgstr))
- idx = msg.t.tcm_ifindex
- handle = msg.t.tcm_handle
- kind = msg.rtattrs[TCA_KIND].strip('\0')
- opts = msg.rtattrs.get(TCA_OPTIONS)
-
- qdisc = {'index': idx,
- 'handle': handle,
- 'kind': kind,
- 'options': opts}
- qdiscs[idx] = qdisc
-
- tcm = tcmsg()
- if dev:
- link = self.getlink(dev)
- if not link:
- raise QdiscException('device %s not found' % dev)
- tcm.tcm_ifindex = link['index']
-
- msg = tcm.pack()
- self._rth.dump_request(RTM_GETQDISC, msg)
- self._rth.dump_filter(dumpfilter)
- return qdiscs
-
- def talk(self, req):
- self._rth.talk(req)
diff --git a/tools/python/xen/remus/profile.py b/tools/python/xen/remus/profile.py
deleted file mode 100644
index fea8c28..0000000
--- a/tools/python/xen/remus/profile.py
+++ /dev/null
@@ -1,56 +0,0 @@
-"""Simple profiling module
-"""
-
-import time
-
-class ProfileBlock(object):
- """A section of code to be profiled"""
- def __init__(self, name):
- self.name = name
-
- def enter(self):
- print "PROF: entered %s at %f" % (self.name, time.time())
-
- def exit(self):
- print "PROF: exited %s at %f" % (self.name, time.time())
-
-class NullProfiler(object):
- def enter(self, name):
- pass
-
- def exit(self, name=None):
- pass
-
-class Profiler(object):
- def __init__(self):
- self.blocks = {}
- self.running = []
-
- def enter(self, name):
- try:
- block = self.blocks[name]
- except KeyError:
- block = ProfileBlock(name)
- self.blocks[name] = block
-
- block.enter()
- self.running.append(block)
-
- def exit(self, name=None):
- if name is not None:
- block = None
- while self.running:
- tmp = self.running.pop()
- if tmp.name == name:
- block = tmp
- break
- tmp.exit()
- if not block:
- raise KeyError('block %s not running' % name)
- else:
- try:
- block = self.running.pop()
- except IndexError:
- raise KeyError('no block running')
-
- block.exit()
diff --git a/tools/python/xen/remus/qdisc.py b/tools/python/xen/remus/qdisc.py
deleted file mode 100644
index 4d54e01..0000000
--- a/tools/python/xen/remus/qdisc.py
+++ /dev/null
@@ -1,189 +0,0 @@
-import socket, struct
-
-import netlink
-import platform
-
-kernelversion = platform.platform(terse=True).split("-")[1].split(".")
-
-qdisc_kinds = {}
-
-TC_H_ROOT = 0xFFFFFFFF
-
-class QdiscException(Exception): pass
-
-class request(object):
- "qdisc request message"
- def __init__(self, cmd, flags=0, dev=None, handle=0):
- self.n = netlink.nlmsg()
- self.t = netlink.tcmsg()
-
- self.n.nlmsg_flags = netlink.NLM_F_REQUEST|flags
- self.n.nlmsg_type = cmd
- self.t.tcm_family = socket.AF_UNSPEC
-
- if not handle:
- handle = TC_H_ROOT
- self.t.tcm_parent = handle
-
- if dev:
- self.t.tcm_ifindex = dev
-
- def pack(self):
- t = self.t.pack()
- self.n.body = t
- return self.n.pack()
-
-class addrequest(request):
- def __init__(self, dev, handle, qdisc):
- flags = netlink.NLM_F_EXCL|netlink.NLM_F_CREATE
- super(addrequest, self).__init__(netlink.RTM_NEWQDISC, flags=flags,
- dev=dev, handle=handle)
- self.n.addattr(netlink.TCA_KIND, qdisc.kind + '\0')
- opts = qdisc.pack()
- if opts:
- self.n.addattr(netlink.TCA_OPTIONS, opts)
-
-class delrequest(request):
- def __init__(self, dev, handle):
- super(delrequest, self).__init__(netlink.RTM_DELQDISC, dev=dev,
- handle=handle)
-
-class changerequest(request):
- def __init__(self, dev, handle, qdisc):
- super(changerequest, self).__init__(netlink.RTM_NEWQDISC,
- dev=dev, handle=handle)
- self.n.addattr(netlink.TCA_KIND, qdisc.kind + '\0')
- opts = qdisc.pack()
- if opts:
- self.n.addattr(netlink.TCA_OPTIONS, opts)
-
-class Qdisc(object):
- def __new__(cls, qdict=None, *args, **opts):
- if qdict:
- kind = qdict.get('kind')
- cls = qdisc_kinds.get(kind, cls)
- obj = super(Qdisc, cls).__new__(cls)
- return obj
-
- def __init__(self, qdict):
- self._qdict = qdict
- self.kind = qdict['kind']
- self.handle = qdict['handle'] >> 16
-
- def parse(self, opts):
- if opts:
- raise QdiscException('cannot parse qdisc parameters')
-
- def optstr(self):
- if self.qdict['options']:
- return '[cannot parse qdisc parameters]'
- else:
- return ''
-
- def pack(self):
- return ''
-
-TC_PRIO_MAX = 15
-class PrioQdisc(Qdisc):
- fmt = 'i%sB' % (TC_PRIO_MAX + 1)
-
- def __init__(self, qdict):
- super(PrioQdisc, self).__init__(qdict)
-
- if qdict.get('options'):
- self.unpack(qdict['options'])
- else:
- self.bands = 3
- self.priomap = [1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
-
- def pack(self):
- #return struct.pack(self.fmt, self.bands, *self.priomap)
- return ''
-
- def unpack(self, opts):
- args = struct.unpack(self.fmt, opts)
- self.bands = args[0]
- self.priomap = args[1:]
-
- def optstr(self):
- mapstr = ' '.join([str(p) for p in self.priomap])
- return 'bands %d priomap %s' % (self.bands, mapstr)
-
-qdisc_kinds['prio'] = PrioQdisc
-qdisc_kinds['pfifo_fast'] = PrioQdisc
-
-class CfifoQdisc(Qdisc):
- fmt = 'II'
-
- def __init__(self, qdict):
- super(CfifoQdisc, self).__init__(qdict)
-
- if qdict.get('options'):
- self.unpack(qdict['options'])
- else:
- self.epoch = 0
- self.vmid = 0
-
- def pack(self):
- return struct.pack(self.fmt, self.epoch, self.vmid)
-
- def unpack(self, opts):
- self.epoch, self.vmid = struct.unpack(self.fmt, opts)
-
- def parse(self, opts):
- args = list(opts)
- try:
- while args:
- arg = args.pop(0)
- if arg == 'epoch':
- self.epoch = int(args.pop(0))
- continue
- if arg.lower() == 'vmid':
- self.vmid = int(args.pop(0))
- continue
- except Exception, inst:
- raise QdiscException(str(inst))
-
- def optstr(self):
- return 'epoch %d vmID %d' % (self.epoch, self.vmid)
-
-qdisc_kinds['cfifo'] = CfifoQdisc
-
-TC_PLUG_BUFFER = 0
-TC_PLUG_RELEASE_ONE = 1
-
-class PlugQdisc(Qdisc):
-
- def __init__(self, qdict=None):
- if int(kernelversion[0]) >= 3 and int(kernelversion[1]) >= 4:
- self.fmt = 'iI'
- self.limit = 10000
- else:
- self.fmt = 'I'
-
- if not qdict:
- qdict = {'kind': 'plug',
- 'handle': TC_H_ROOT}
- super(PlugQdisc, self).__init__(qdict)
-
- self.action = 0
-
- def pack(self):
- if int(kernelversion[0]) >= 3 and int(kernelversion[1]) >= 4:
- return struct.pack(self.fmt, self.action, self.limit)
- else:
- return struct.pack(self.fmt, self.action)
-
- def parse(self, args):
- if not args:
- raise QdiscException('no action given')
- arg = args[0]
-
- if arg == 'checkpoint':
- self.action = TC_PLUG_BUFFER
- elif arg == 'release':
- self.action = TC_PLUG_RELEASE_ONE
- else:
- raise QdiscException('unknown action')
-
-qdisc_kinds['plug'] = PlugQdisc
diff --git a/tools/python/xen/remus/save.py b/tools/python/xen/remus/save.py
deleted file mode 100644
index 2193061..0000000
--- a/tools/python/xen/remus/save.py
+++ /dev/null
@@ -1,186 +0,0 @@
-#!/usr/bin/env python
-
-import os, select, socket, threading, time, signal, xmlrpclib
-
-from xen.xend.XendClient import server
-from xen.xend.xenstore.xswatch import xswatch
-
-import xen.lowlevel.xc
-from xen.xend.xenstore import xsutil
-xc = xen.lowlevel.xc.xc()
-
-import xen.lowlevel.checkpoint
-
-import vm, image
-
-XCFLAGS_LIVE = 1
-
-xcsave = '/usr/lib/xen/bin/xc_save'
-
-class _proxy(object):
- "proxy simulates an object without inheritance"
- def __init__(self, obj):
- self._obj = obj
-
- def __getattr__(self, name):
- return getattr(self._obj, name)
-
- def proxy(self, obj):
- self._obj = obj
-
-class CheckpointError(Exception): pass
-
-class CheckpointingFile(_proxy):
- """Tee writes into separate file objects for each round.
- This is necessary because xc_save gets a single file descriptor
- for the duration of checkpointing.
- """
- def __init__(self, path):
- self.path = path
-
- self.round = 0
- self.rfd, self.wfd = os.pipe()
- self.fd = file(path, 'wb')
-
- # this pipe is used to notify the writer thread of checkpoints
- self.cprfd, self.cpwfd = os.pipe()
-
- super(CheckpointingFile, self).__init__(self.fd)
-
- wt = threading.Thread(target=self._wrthread, name='disk-write-thread')
- wt.setDaemon(True)
- wt.start()
- self.wt = wt
-
- def fileno(self):
- return self.wfd
-
- def close(self):
- os.close(self.wfd)
- # closing wfd should signal writer to stop
- self.wt.join()
- os.close(self.rfd)
- os.close(self.cprfd)
- os.close(self.cpwfd)
- self.fd.close()
- self.wt = None
-
- def checkpoint(self):
- os.write(self.cpwfd, '1')
-
- def _wrthread(self):
- while True:
- r, o, e = select.select((self.rfd, self.cprfd), (), ())
- if self.rfd in r:
- data = os.read(self.rfd, 256 * 1024)
- if not data:
- break
- self.fd.write(data)
- if self.cprfd in r:
- junk = os.read(self.cprfd, 1)
- self.round += 1
- self.fd = file('%s.%d' % (self.path, self.round), 'wb')
- self.proxy(self.fd)
-
-class MigrationSocket(_proxy):
- def __init__(self, address):
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.connect(address)
-
- sock.send("receive\n")
- sock.recv(80)
-
- fd = os.fdopen(sock.fileno(), 'w+')
-
- self.sock = sock
- super(MigrationSocket, self).__init__(fd)
-
-class NullSocket(_proxy):
- def __init__(self, address):
- filedesc = os.open('/dev/null', 0666)
- fd = os.fdopen(filedesc, 'w+')
- super(NullSocket, self).__init__(fd)
-
-class Keepalive(object):
- "Call a keepalive method at intervals"
- def __init__(self, method, interval=0.1):
- self.keepalive = method
- self.interval = interval
-
- self.thread = None
- self.running = False
-
- def start(self):
- if not self.interval:
- return
- self.thread = threading.Thread(target=self.run, name='keepalive-thread')
- self.thread.setDaemon(True)
- self.running = True
- self.thread.start()
-
- def stop(self):
- if not self.thread:
- return
- self.running = False
- self.thread.join()
- self.thread = None
-
- def run(self):
- while self.running:
- self.keepalive()
- time.sleep(self.interval)
- self.keepalive(stop=True)
-
-class Saver(object):
- def __init__(self, domid, fd, suspendcb=None, resumecb=None,
- checkpointcb=None, interval=0, flags=0):
- """Create a Saver object for taking guest checkpoints.
- domid: name, number or UUID of a running domain
- fd: a stream to which checkpoint data will be written.
- suspendcb: callback invoked after guest is suspended
- resumecb: callback invoked before guest resumes
- checkpointcb: callback invoked when a checkpoint is complete. Return
- True to take another checkpoint, or False to stop.
- flags: Remus flags to be passed to xc_domain_save
- """
- self.fd = fd
- self.suspendcb = suspendcb
- self.resumecb = resumecb
- self.checkpointcb = checkpointcb
- self.interval = interval
- self.flags = flags
-
- self.vm = vm.VM(domid)
-
- self.checkpointer = None
-
- def start(self):
- vm.getshadowmem(self.vm)
-
- hdr = image.makeheader(self.vm.dominfo)
- self.fd.write(hdr)
- self.fd.flush()
-
- self.checkpointer = xen.lowlevel.checkpoint.checkpointer()
- try:
- try:
- self.checkpointer.open(self.vm.domid)
- self.checkpointer.start(self.fd, self.suspendcb, self.resumecb,
- self.checkpointcb, self.interval,
- self.flags)
- except xen.lowlevel.checkpoint.error, e:
- raise CheckpointError(e)
- finally:
- try: #errors in checkpoint close are not critical atm.
- self.checkpointer.close()
- except:
- pass
-
- def _resume(self):
- """low-overhead version of XendDomainInfo.resumeDomain"""
- # TODO: currently assumes SUSPEND_CANCEL is available
- if True:
- xc.domain_resume(self.vm.domid, 1)
- xsutil.ResumeDomain(self.vm.domid)
- else:
- server.xend.domain.resumeDomain(self.vm.domid)
diff --git a/tools/python/xen/remus/tapdisk.py b/tools/python/xen/remus/tapdisk.py
deleted file mode 100644
index 49a9bda..0000000
--- a/tools/python/xen/remus/tapdisk.py
+++ /dev/null
@@ -1,4 +0,0 @@
-import blkdev
-
-class TapDisk(BlkDev):
- pass
diff --git a/tools/python/xen/remus/util.py b/tools/python/xen/remus/util.py
deleted file mode 100644
index b75052c..0000000
--- a/tools/python/xen/remus/util.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# utility functions
-
-import fcntl, os, subprocess
-
-class PipeException(Exception):
- def __init__(self, message, errno):
- self.errno = errno
- message = '%s: %d, %s' % (message, errno, os.strerror(errno))
- Exception.__init__(self, message)
-
-class Lock(object):
- """advisory lock"""
-
- def __init__(self, filename):
- """lock using filename for synchronization"""
- self.filename = filename + '.lock'
-
- self.fd = None
-
- self.lock()
-
- def __del__(self):
- self.unlock()
-
- def lock(self):
- if self.fd:
- return
-
- self.fd = open(self.filename, 'w')
- fcntl.lockf(self.fd, fcntl.LOCK_EX)
-
- def unlock(self):
- if not self.fd:
- return
-
- fcntl.lockf(self.fd, fcntl.LOCK_UN)
- self.fd = None
- try:
- os.remove(self.filename)
- except OSError:
- # harmless race
- pass
-
-def canonifymac(mac):
- return ':'.join(['%02x' % int(field, 16) for field in mac.split(':')])
-
-def checkpid(pid):
- """return True if pid is live"""
- try:
- os.kill(pid, 0)
- return True
- except OSError:
- return False
-
-def runcmd(args, cwd=None):
- # TODO: stdin handling
- if type(args) == str:
- args = args.split(' ')
- try:
- proc = subprocess.Popen(args, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE, close_fds=True,
- cwd=cwd)
- stdout = proc.stdout.read()
- stderr = proc.stderr.read()
- proc.wait()
- if proc.returncode:
- print ' '.join(args)
- errmsg = stderr.strip()
- print errmsg
- raise PipeException('%s failed (errmsg: %s)' % (args[0], errmsg),
- proc.returncode)
- return stdout
- except (OSError, IOError), inst:
- raise PipeException('could not run %s' % args[0], inst.errno)
-
-def modprobe(modname):
- """attempt to load kernel module modname"""
- try:
- runcmd(['modprobe', '-q', modname])
- return True
- except PipeException:
- return False
diff --git a/tools/python/xen/remus/vbd.py b/tools/python/xen/remus/vbd.py
deleted file mode 100644
index 25ed8ea..0000000
--- a/tools/python/xen/remus/vbd.py
+++ /dev/null
@@ -1,9 +0,0 @@
-import blkdev
-
-class VBD(blkdev.BlkDev):
- def handles(self, **props):
- uname = props.get('uname', '')
- return uname.startswith('phy:')
- handles = classmethod(handles)
-
-blkdev.register(VBD)
diff --git a/tools/python/xen/remus/vdi.py b/tools/python/xen/remus/vdi.py
deleted file mode 100644
index 56fc3f8..0000000
--- a/tools/python/xen/remus/vdi.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#code to play with vdis and snapshots
-
-import os
-
-def run(cmd):
- fd = os.popen(cmd)
- res = [l for l in fd if l.rstrip()]
- return not fd.close(), res
-
-
-_blockstore = '/blockstore.dat'
-
-def set_blockstore(blockstore):
- global _blockstore
- __blockstore = blockstore
-
-
-class SnapShot:
- def __init__(self, vdi, block, index):
- self.__vdi = vdi
- self.__block = block
- self.__index = index
-
- #TODO add snapshot date and radix
-
- def __str__(self):
- return '%d %d %d' % (self.__vdi.id(), self.__block, self.__index)
-
- def vdi(self):
- return self.__vdi
-
- def block(self):
- return self.__block
-
- def index(self):
- return self.__index
-
- def match(self, block, index):
- return self.__block == block and self.__index == index
-
-
-class VDIException(Exception):
- pass
-
-
-class VDI:
- def __init__(self, id, name):
- self.__id = id
- self.__name = name
-
- def __str__(self):
- return 'vdi: %d %s' % (self.__id, self.__name)
-
- def id(self):
- return self.__id
-
- def name(self):
- return self.__name
-
- def list_snapshots(self):
- res, ls = run('vdi_snap_list %s %d' % (_blockstore, self.__id))
- if res:
- return [SnapShot(self, int(l[0]), int(l[1])) for l in [l.split() for l in ls[1:]]]
- else:
- raise VDIException("Error reading snapshot list")
-
- def snapshot(self):
- res, ls = run('vdi_checkpoint %s %d' % (_blockstore, self.__id))
- if res:
- _, block, idx = ls[0].split()
- return SnapShot(self, int(block), int(idx))
- else:
- raise VDIException("Error taking vdi snapshot")
-
-
-def create(name, snap):
- res, _ = run('vdi_create %s %s %d %d'
- % (_blockstore, name, snap.block(), snap.index()))
- if res:
- return lookup_by_name(name)
- else:
- raise VDIException('Unable to create vdi from snapshot')
-
-
-def fill(name, img_file):
- res, _ = run('vdi_create %s %s' % (_blockstore, name))
-
- if res:
- vdi = lookup_by_name(name)
- res, _ = run('vdi_fill %d %s' % (vdi.id(), img_file))
- if res:
- return vdi
- raise VDIException('Unable to create vdi from disk img file')
-
-
-def list_vdis():
- vdis = []
- res, lines = run('vdi_list %s' % _blockstore)
- if res:
- for l in lines:
- r = l.split()
- vdis.append(VDI(int(r[0]), r[1]))
- return vdis
- else:
- raise VDIException("Error doing vdi list")
-
-
-def lookup_by_id(id):
- vdis = list_vdis()
- for v in vdis:
- if v.id() == id:
- return v
- raise VDIException("No match from vdi id")
-
-
-def lookup_by_name(name):
- vdis = list_vdis()
- for v in vdis:
- if v.name() == name:
- return v
- raise VDIException("No match for vdi name")
diff --git a/tools/python/xen/remus/vif.py b/tools/python/xen/remus/vif.py
deleted file mode 100644
index d14d54b..0000000
--- a/tools/python/xen/remus/vif.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from xen.remus.util import canonifymac
-
-class VIF(object):
- def __init__(self, **props):
- self.dev = 'unknown'
- self.__dict__.update(props)
- if 'mac' in props:
- self.mac = canonifymac(props['mac'])
-
- def __str__(self):
- return self.mac
-
-def parse(props, domid, index):
- "turn a vm device dictionary into a vif object"
- vif = VIF(**props)
- vif.dev = 'vif%d.%d' % (domid, index)
-
- return vif
diff --git a/tools/python/xen/remus/vm.py b/tools/python/xen/remus/vm.py
deleted file mode 100644
index 90002e3..0000000
--- a/tools/python/xen/remus/vm.py
+++ /dev/null
@@ -1,168 +0,0 @@
-#!/usr/bin/env python
-
-import xmlrpclib
-
-from xen.xend.XendClient import server
-from xen.xend import sxp, osdep
-from xen.lowlevel.xc import xc
-
-import vif
-import blkdev
-# need a nicer way to load disk drivers
-import vbd
-
-class VMException(Exception): pass
-
-class VM(object):
- "Representation of a virtual machine"
- def __init__(self, domid=None, dominfo=None):
- self.dominfo = dominfo
-
- self.domid = -1
- self.name = 'unknown'
- self.dom = {}
- self.disks = []
- self.vifs = []
-
- if domid:
- try:
- self.dominfo = server.xend.domain(domid, 'all')
- except xmlrpclib.Fault:
- raise VMException('error looking up domain %s' % str(domid))
-
- if self.dominfo:
- self.loaddominfo()
-
- def loaddominfo(self):
- self.dom = parsedominfo(self.dominfo)
- self.domid = self.dom['domid']
- self.name = self.dom['name']
-
- self.disks = getdisks(self.dom)
- self.vifs = getvifs(self.dom)
-
- def __str__(self):
- return 'VM %d (%s), vifs: [%s], disks: [%s]' % \
- (self.domid, self.name,
- ', '.join([str(v) for v in self.vifs]),
- ', '.join([str(d) for d in self.disks]))
-
-def parsedominfo(dominfo):
- "parses a dominfo sexpression in the form of python lists of lists"
- def s2d(s):
- r = {}
- for elem in s:
- if len(elem) == 0:
- continue
- name = elem[0]
- if len(elem) == 1:
- val = None
- else:
- val = elem[1]
- if isinstance(val, list):
- val = s2d(elem[1:])
- if isinstance(name, list):
- # hack for ['cpus', [[1]]]
- return s2d(elem)
- if name in r:
- for k, v in val.iteritems():
- if k in r[name]:
- if not isinstance(r[name][k], list):
- r[name][k] = [r[name][k]]
- r[name][k].append(v)
- else:
- r[name][k] = v
- else:
- r[name] = val
- return r
-
- return s2d(dominfo[1:])
-
-def domtosxpr(dom):
- "convert a dominfo into a python sxpr"
- def d2s(d):
- r = []
- for k, v in d.iteritems():
- elem = [k]
- if isinstance(v, dict):
- elem.extend(d2s(v))
- else:
- if v is None:
- v = ''
- elem.append(v)
- r.append(elem)
- return r
-
- sxpr = ['domain']
- sxpr.extend(d2s(dom))
- return sxpr
-
-def strtosxpr(s):
- "convert a string to a python sxpr"
- p = sxp.Parser()
- p.input(s)
- return p.get_val()
-
-def sxprtostr(sxpr):
- "convert an sxpr to string"
- return sxp.to_string(sxpr)
-
-def getvifs(dom):
- "return vif objects for devices in dom"
- vifs = dom['device'].get('vif', [])
- if type(vifs) != list:
- vifs = [vifs]
-
- vifno = 0
- parsed = []
- for v in vifs:
- parsed.append(vif.parse(v, dom['domid'], vifno))
- vifno += 1
-
- return parsed
-
-def getdisks(dom):
- "return block device objects for devices in dom"
- disks = dom['device'].get('vbd', [])
- if type(disks) != list:
- disks = [disks]
-
- # tapdisk1 devices
- tap1s = dom['device'].get('tap', [])
- if type(tap1s) != list:
- disks.append(tap1s)
- else:
- disks.extend(tap1s)
-
- # tapdisk2 devices
- tap2s = dom['device'].get('tap2', [])
- if type(tap2s) != list:
- disks.append(tap2s)
- else:
- disks.extend(tap2s)
-
- return [blkdev.parse(disk) for disk in disks]
-
-def fromxend(domid):
- "create a VM object from xend information"
- return VM(domid)
-
-def getshadowmem(vm):
- "Balloon down domain0 to create free memory for shadow paging."
- maxmem = int(vm.dom['maxmem'])
- shadow = int(vm.dom['shadow_memory'])
- vcpus = int(vm.dom['vcpus'])
-
- # from XendDomainInfo.checkLiveMigrateMemory:
- # 1MB per vcpu plus 4Kib/Mib of RAM. This is higher than
- # the minimum that Xen would allocate if no value were given.
- shadowneeded = vcpus * 1024 + maxmem * 4 - shadow * 1024
- physinfo = xc().physinfo()
- freemem = int(physinfo['free_memory'])
- needed = shadowneeded - freemem
- if needed > 0:
- print "Freeing %d kB for shadow mode" % needed
- dom0cur = osdep.lookup_balloon_stat('current')
- # target is in MB, not KB
- target = (dom0cur - needed) / 1024
- server.xend.domain.setMemoryTarget(0, target)
diff --git a/tools/python/xen/util/Brctl.py b/tools/python/xen/util/Brctl.py
deleted file mode 100644
index 5dc9a7f..0000000
--- a/tools/python/xen/util/Brctl.py
+++ /dev/null
@@ -1,186 +0,0 @@
-"""Bridge control utilities.
-"""
-import os
-import os.path
-import re
-import sys
-
-CMD_IFCONFIG = 'ifconfig'
-CMD_ROUTE = 'route'
-CMD_BRCTL = 'brctl'
-CMD_IPTABLES = "iptables"
-
-opts = None
-
-class Opts:
-
- def __init__(self, defaults):
- for (k, v) in defaults.items():
- setattr(self, k, v)
- pass
-
-def cmd(p, s):
- """Print and execute command 'p' with args 's'.
- """
- global opts
- c = p + ' ' + s
- if opts.verbose: print c
- if not opts.dryrun:
- os.system(c)
-
-bridgeRE = re.compile(r'([^\t]*)\t*[^\t]*\t*[^\t]*\t*([^\t]*)')
-def get_state():
- fin = os.popen(CMD_BRCTL + ' show', 'r')
- try:
- bridges = {}
- brlist = None
- brname = None
- first = True
- for line in fin:
- if first:
- first = False
- elif line[0] == '\t':
- brlist.append(line.strip())
- else:
- if brname:
- bridges[brname] = brlist
- m = bridgeRE.match(line)
- brname = m.group(1)
- brlist = [m.group(2).strip()]
- if brname:
- bridges[brname] = brlist
- return bridges
- finally:
- fin.close()
-
-def vif_bridge_add(params):
- """Add the network interface for vif on dom to a bridge.
- """
- cmd(CMD_BRCTL, 'addif %(bridge)s %(vif)s' % params)
-
-def vif_bridge_rem(params):
- """Remove the network interface for vif on dom from a bridge.
- """
- cmd(CMD_BRCTL, 'delif %(bridge)s %(vif)s' % params)
-
-def vif_restrict_addr(vif, addr, delete=0):
- d = { 'vif': vif, 'addr': addr}
- if delete:
- d['flag'] = '-D'
- else:
- d['flag'] = '-A'
- cmd(CMD_IPTABLES, '-P FORWARD DROP')
- cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-in %(vif)s -s %(addr)s -j ACCEPT' % d)
- cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-out %(vif)s -d %(addr)s -j ACCEPT' % d)
-
-def bridge_create(bridge, **kwd):
- """Create a bridge.
- Defaults hello time to 0, forward delay to 0 and stp off.
- """
- cmd(CMD_BRCTL, 'addbr %s' % bridge)
- if kwd.get('hello', None) is None:
- kwd['hello'] = 0
- if kwd.get('fd', None) is None:
- kwd['fd'] = 0
- if kwd.get('stp', None) is None:
- kwd['stp'] = 'off'
- bridge_set(bridge, **kwd)
- cmd(CMD_IFCONFIG, "%s up" % bridge)
-
-def bridge_set(bridge, hello=None, fd=None, stp=None):
- """Set bridge parameters.
- """
- if hello is not None:
- cmd(CMD_BRCTL, 'sethello %s %d' % (bridge, hello))
- if fd is not None:
- cmd(CMD_BRCTL, 'setfd %s %d' % (bridge, fd))
- if stp is not None:
- cmd(CMD_BRCTL, 'stp %s %s' % (bridge, stp))
-
-def bridge_del(bridge):
- """Delete a bridge.
- """
- cmd(CMD_IFCONFIG, '%s down' % bridge)
- cmd(CMD_BRCTL, 'delbr %s' % bridge)
-
-def routes():
- """Return a list of the routes.
- """
- fin = os.popen(CMD_ROUTE + ' -n', 'r')
- routes = []
- for x in fin:
- if x.startswith('Kernel'): continue
- if x.startswith('Destination'): continue
- x = x.strip()
- y = x.split()
- z = { 'destination': y[0],
- 'gateway' : y[1],
- 'mask' : y[2],
- 'flags' : y[3],
- 'metric' : y[4],
- 'ref' : y[5],
- 'use' : y[6],
- 'interface' : y[7] }
- routes.append(z)
- return routes
-
-def ifconfig(interface):
- """Return the ip config for an interface,
- """
- fin = os.popen(CMD_IFCONFIG + ' %s' % interface, 'r')
- inetre = re.compile('\s*inet\s*addr:(?P<address>\S*)\s*Bcast:(?P<broadcast>\S*)\s*Mask:(?P<mask>\S*)')
- info = None
- for x in fin:
- m = inetre.match(x)
- if not m: continue
- info = m.groupdict()
- info['interface'] = interface
- break
- return info
-
-def reconfigure(interface, bridge):
- """Reconfigure an interface to be attached to a bridge, and give the bridge
- the IP address etc. from interface. Move the default route to the interface
- to the bridge.
-
- """
- global opts
- intf_info = ifconfig(interface)
- if not intf_info:
- print >>sys.stderr, 'Interface not found:', interface
- return
- #bridge_info = ifconfig(bridge)
- #if not bridge_info:
- # print >>sys.stderr, 'Bridge not found:', bridge
- # return
- route_info = routes()
- intf_info['bridge'] = bridge
- intf_info['gateway'] = None
- for r in route_info:
- if (r['destination'] == '0.0.0.0' and
- 'G' in r['flags'] and
- r['interface'] == interface):
- intf_info['gateway'] = r['gateway']
- if not intf_info['gateway']:
- print >>sys.stderr, 'Gateway not found: ', interface
- return
- cmd(CMD_IFCONFIG,
- '%(bridge)s %(address)s netmask %(mask)s broadcast %(broadcast)s up'
- % intf_info)
- cmd(CMD_ROUTE,
- 'add default gateway %(gateway)s dev %(bridge)s'
- % intf_info)
- cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info)
- cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info)
-
-defaults = {
- 'verbose' : 1,
- 'dryrun' : 0,
- }
-
-opts = Opts(defaults)
-
-def set_opts(val):
- global opts
- opts = val
- return opts
diff --git a/tools/python/xen/util/SSHTransport.py b/tools/python/xen/util/SSHTransport.py
deleted file mode 100644
index fa975f3..0000000
--- a/tools/python/xen/util/SSHTransport.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 Anthony Liguori <aliguori at us.ibm.com>
-# Copyright (C) 2006 XenSource Inc.
-#============================================================================
-
-"""
-XML-RPC SSH transport.
-"""
-
-from xmlrpclib import getparser, Fault
-from subprocess import Popen, PIPE
-from getpass import getuser
-from fcntl import ioctl
-import errno
-import os
-import termios
-
-
-def getHTTPURI(uri):
- (protocol, rest) = uri.split(':', 1)
- if not rest.startswith('//'):
- raise ValueError("Invalid ssh URL '%s'" % uri)
- rest = rest[2:]
- user = getuser()
- path = 'RPC2'
- if rest.find('@') != -1:
- (user, rest) = rest.split('@', 1)
- if rest.find('/') != -1:
- (host, rest) = rest.split('/', 1)
- if len(rest) > 0:
- path = rest
- else:
- host = rest
- transport = SSHTransport(host, user)
- uri = 'http://%s/%s' % (host, path)
- return transport, uri
-
-
-class SSHTransport(object):
- def __init__(self, host, user, askpass=None):
- self.host = host
- self.user = user
- self.askpass = askpass
- self.ssh = None
-
- def getssh(self):
- if self.ssh == None:
- if self.askpass:
- f = open('/dev/tty', 'w')
- try:
- os.environ['SSH_ASKPASS'] = self.askpass
- ioctl(f.fileno(), termios.TIOCNOTTY)
- finally:
- f.close()
-
- cmd = ['ssh', '%s@%s' % (self.user, self.host), 'xm serve']
- try:
- self.ssh = Popen(cmd, bufsize=0, stdin=PIPE, stdout=PIPE)
- except OSError, (err, msg):
- if err == errno.ENOENT:
- raise Fault(0, "ssh executable not found!")
- raise
- return self.ssh
-
- def request(self, host, handler, request_body, verbose=0):
- p, u = getparser()
- ssh = self.getssh()
- ssh.stdin.write("""POST /%s HTTP/1.1
-User-Agent: Xen
-Host: %s
-Content-Type: text/xml
-Content-Length: %d
-
-%s""" % (handler, host, len(request_body), request_body))
- ssh.stdin.flush()
-
- content_length = 0
- line = ssh.stdout.readline()
- if line.split()[1] != '200':
- raise Fault(0, 'Server returned %s' % (' '.join(line[1:])))
-
- while line not in ['', '\r\n', '\n']:
- if line.lower().startswith('content-length:'):
- content_length = int(line[15:].strip())
- line = ssh.stdout.readline()
- content = ssh.stdout.read(content_length)
- p.feed(content)
- p.close()
- return u.close()
diff --git a/tools/python/xen/util/__init__.py b/tools/python/xen/util/__init__.py
deleted file mode 100644
index 8d1c8b6..0000000
--- a/tools/python/xen/util/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tools/python/xen/util/acmpolicy.py b/tools/python/xen/util/acmpolicy.py
deleted file mode 100644
index 6752169..0000000
--- a/tools/python/xen/util/acmpolicy.py
+++ /dev/null
@@ -1,1622 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006,2007 International Business Machines Corp.
-# Author: Stefan Berger <stefanb at us.ibm.com>
-#============================================================================
-
-import os
-import stat
-import array
-import struct
-import shutil
-import commands
-
-# sha is deprecated as of python 2.6
-try:
- from hashlib import sha1
-except ImportError:
- # but hashlib was only added in python 2.5
- from sha import new as sha1
-
-from xml.dom import minidom, Node
-from xen.xend.XendLogging import log
-from xen.util import xsconstants, bootloader, mkdir
-from xen.util.xspolicy import XSPolicy
-from xen.xend.XendError import SecurityError
-import xen.util.xsm.acm.acm as security
-from xen.util.xsm.xsm import XSMError
-from xen.xend import XendOptions
-
-ACM_POLICIES_DIR = security.policy_dir_prefix + "/"
-
-# Constants needed for generating a binary policy from its XML
-# representation
-ACM_POLICY_VERSION = 4 # Latest one
-ACM_CHWALL_VERSION = 1
-
-ACM_STE_VERSION = 1
-
-ACM_MAGIC = 0x001debc;
-
-ACM_NULL_POLICY = 0
-ACM_CHINESE_WALL_POLICY = 1
-ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY = 2
-ACM_POLICY_UNDEFINED = 15
-
-
-ACM_LABEL_UNLABELED = "__UNLABELED__"
-ACM_LABEL_UNLABELED_DISPLAY = "unlabeled"
-
-"""
- Error codes reported in when trying to test for a new policy
- These error codes are reported in an array of tuples where
- each error code is followed by a parameter describing the error
- more closely, such as a domain id.
-"""
-ACM_EVTCHN_SHARING_VIOLATION = 0x100
-ACM_GNTTAB_SHARING_VIOLATION = 0x101
-ACM_DOMAIN_LOOKUP = 0x102
-ACM_CHWALL_CONFLICT = 0x103
-ACM_SSIDREF_IN_USE = 0x104
-
-
-DEFAULT_policy = \
-"<?xml version=\"1.0\" ?>\n" +\
-"<SecurityPolicyDefinition xmlns=\"http://www.ibm.com\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.ibm.com ../../security_policy.xsd\">\n" +\
-" <PolicyHeader>\n" +\
-" <PolicyName>DEFAULT</PolicyName>\n" +\
-" <Version>1.0</Version>\n" +\
-" </PolicyHeader>\n" +\
-" <SimpleTypeEnforcement>\n" +\
-" <SimpleTypeEnforcementTypes>\n" +\
-" <Type>SystemManagement</Type>\n" +\
-" <Type>__UNLABELED__</Type>\n" +\
-" </SimpleTypeEnforcementTypes>\n" +\
-" </SimpleTypeEnforcement>\n" +\
-" <ChineseWall>\n" +\
-" <ChineseWallTypes>\n" +\
-" <Type>SystemManagement</Type>\n" +\
-" </ChineseWallTypes>\n" +\
-" </ChineseWall>\n" +\
-" <SecurityLabelTemplate>\n" +\
-" <SubjectLabels bootstrap=\"SystemManagement\">\n" +\
-" <VirtualMachineLabel>\n" +\
-" <Name%s>SystemManagement</Name>\n" +\
-" <SimpleTypeEnforcementTypes>\n" +\
-" <Type>SystemManagement</Type>\n" +\
-" <Type>__UNLABELED__</Type>\n" +\
-" </SimpleTypeEnforcementTypes>\n" +\
-" <ChineseWallTypes>\n" +\
-" <Type/>\n" +\
-" </ChineseWallTypes>\n" +\
-" </VirtualMachineLabel>\n" +\
-" <VirtualMachineLabel>\n" +\
-" <Name>__UNLABELED__</Name>\n" +\
-" <SimpleTypeEnforcementTypes>\n" +\
-" <Type>__UNLABELED__</Type>\n" +\
-" </SimpleTypeEnforcementTypes>\n" +\
-" <ChineseWallTypes>\n" +\
-" <Type/>\n" +\
-" </ChineseWallTypes>\n" +\
-" </VirtualMachineLabel>\n" +\
-" </SubjectLabels>\n" +\
-" <ObjectLabels>\n" +\
-" <ResourceLabel>\n" +\
-" <Name>__UNLABELED__</Name>\n" +\
-" <SimpleTypeEnforcementTypes>\n" +\
-" <Type>__UNLABELED__</Type>\n" +\
-" </SimpleTypeEnforcementTypes>\n" +\
-" </ResourceLabel>\n" +\
-" </ObjectLabels>\n" +\
-" </SecurityLabelTemplate>\n" +\
-"</SecurityPolicyDefinition>\n"
-
-ACM_SCHEMA="""<?xml version="1.0" encoding="UTF-8"?>
-<!-- Author: Ray Valdez, Reiner Sailer {rvaldez,sailer}@us.ibm.com -->
-<!-- This file defines the schema, which is used to define -->
-<!-- the security policy and the security labels in Xen. -->
-
-<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.ibm.com" xmlns="http://www.ibm.com" elementFormDefault="qualified">
- <xsd:element name="SecurityPolicyDefinition">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="PolicyHeader" minOccurs="1" maxOccurs="1"></xsd:element>
- <xsd:element ref="SimpleTypeEnforcement" minOccurs="0" maxOccurs="1"></xsd:element>
- <xsd:element ref="ChineseWall" minOccurs="0" maxOccurs="1"></xsd:element>
- <xsd:element ref="SecurityLabelTemplate" minOccurs="1" maxOccurs="1"></xsd:element>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="PolicyHeader">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="PolicyName" minOccurs="1" maxOccurs="1" type="xsd:string"></xsd:element>
- <xsd:element name="PolicyUrl" minOccurs="0" maxOccurs="1" type="xsd:string"></xsd:element>
- <xsd:element name="Reference" type="xsd:string" minOccurs="0" maxOccurs="1" />
- <xsd:element name="Date" minOccurs="0" maxOccurs="1" type="xsd:string"></xsd:element>
- <xsd:element name="NameSpaceUrl" minOccurs="0" maxOccurs="1" type="xsd:string"></xsd:element>
- <xsd:element name="Version" minOccurs="1" maxOccurs="1" type="VersionFormat"/>
- <xsd:element ref="FromPolicy" minOccurs="0" maxOccurs="1"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ChineseWall">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="ChineseWallTypes" minOccurs="1" maxOccurs="1" />
- <xsd:element ref="ConflictSets" minOccurs="0" maxOccurs="1" />
- </xsd:sequence>
- <xsd:attribute name="priority" type="PolicyOrder" use="optional"></xsd:attribute>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="SimpleTypeEnforcement">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="SimpleTypeEnforcementTypes" />
- </xsd:sequence>
- <xsd:attribute name="priority" type="PolicyOrder" use="optional"></xsd:attribute>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="SecurityLabelTemplate">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="SubjectLabels" minOccurs="0" maxOccurs="1">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="VirtualMachineLabel" minOccurs="1" maxOccurs="unbounded"></xsd:element>
- </xsd:sequence>
- <xsd:attribute name="bootstrap" type="xsd:string" use="required"></xsd:attribute>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ObjectLabels" minOccurs="0" maxOccurs="1">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="ResourceLabel" minOccurs="1" maxOccurs="unbounded"></xsd:element>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ChineseWallTypes">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" minOccurs="1" ref="Type" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ConflictSets">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" minOccurs="1" ref="Conflict" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="SimpleTypeEnforcementTypes">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" minOccurs="1" ref="Type" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Conflict">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" minOccurs="1" ref="Type" />
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" use="required"></xsd:attribute>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="VirtualMachineLabel">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="Name" type="NameWithFrom"></xsd:element>
- <xsd:element ref="SimpleTypeEnforcementTypes" minOccurs="0" maxOccurs="1" />
- <xsd:element ref="ChineseWallTypes" minOccurs="0" maxOccurs="unbounded" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ResourceLabel">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="Name" type="NameWithFrom"></xsd:element>
- <xsd:element name="SimpleTypeEnforcementTypes" type="SingleSimpleTypeEnforcementType" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Name" type="xsd:string" />
- <xsd:element name="Type" type="xsd:string" />
- <xsd:simpleType name="PolicyOrder">
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="PrimaryPolicyComponent"></xsd:enumeration>
- </xsd:restriction>
- </xsd:simpleType>
- <xsd:element name="FromPolicy">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="PolicyName" minOccurs="1" maxOccurs="1" type="xsd:string"/>
- <xsd:element name="Version" minOccurs="1" maxOccurs="1" type="VersionFormat"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:simpleType name="VersionFormat">
- <xsd:restriction base="xsd:string">
- <xsd:pattern value="[0-9]{1,8}.[0-9]{1,8}"></xsd:pattern>
- </xsd:restriction>
- </xsd:simpleType>
- <xsd:complexType name="NameWithFrom">
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attribute name="from" type="xsd:string" use="optional"></xsd:attribute>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- <xsd:complexType name="SingleSimpleTypeEnforcementType">
- <xsd:sequence>
- <xsd:element maxOccurs="1" minOccurs="1" ref="Type" />
- </xsd:sequence>
- </xsd:complexType>
-</xsd:schema>"""
-
-
-def get_DEFAULT_policy(dom0label=""):
- fromnode = ""
- if dom0label != "":
- fromnode = " from=\"%s\"" % dom0label
- return DEFAULT_policy % fromnode
-
-def initialize():
- xoptions = XendOptions.instance()
- basedir = xoptions.get_xend_security_path()
- policiesdir = basedir + "/policies"
- mkdir.parents(policiesdir, stat.S_IRWXU)
-
- instdir = security.install_policy_dir_prefix
- DEF_policy_file = "DEFAULT-security_policy.xml"
-
- #Install default policy.
- f = open(policiesdir + "/" + DEF_policy_file, 'w')
- if f:
- f.write(get_DEFAULT_policy())
- f.close()
- else:
- log.error("Could not write the default policy's file.")
- defpol = ACMPolicy(xml=get_DEFAULT_policy())
- defpol.compile()
-
-
-class ACMPolicy(XSPolicy):
- """
- ACMPolicy class. Implements methods for getting information from
- the XML representation of the policy as well as compilation and
- loading of a policy into the HV.
- """
-
- def __init__(self, name=None, dom=None, ref=None, xml=None):
- if name:
- self.name = name
- try:
- self.dom = minidom.parse(self.path_from_policy_name(name))
- except Exception, e:
- raise SecurityError(-xsconstants.XSERR_XML_PROCESSING,
- str(e))
- elif dom:
- self.dom = dom
- self.name = self.get_name()
- elif xml:
- try:
- self.dom = minidom.parseString(xml)
- except Exception, e:
- raise SecurityError(-xsconstants.XSERR_XML_PROCESSING,
- str(e))
- self.name = self.get_name()
- rc = self.validate()
- if rc != xsconstants.XSERR_SUCCESS:
- raise SecurityError(rc)
- if ref:
- from xen.xend.XendXSPolicy import XendACMPolicy
- self.xendacmpolicy = XendACMPolicy(self, {}, ref)
- else:
- self.xendacmpolicy = None
- XSPolicy.__init__(self, name=self.name, ref=ref)
-
- def get_dom(self):
- return self.dom
-
- def get_name(self):
- return self.policy_dom_get_hdr_item("PolicyName")
-
- def get_type(self):
- return xsconstants.XS_POLICY_ACM
-
- def get_type_name(self):
- return xsconstants.ACM_POLICY_ID
-
- def __str__(self):
- return self.get_name()
-
-
- def validate(self):
- """
- validate against the policy's schema Does not fail if the
- libxml2 python lib is not installed
- """
- rc = xsconstants.XSERR_SUCCESS
- try:
- import libxml2
- except Exception, e:
- log.warn("Libxml2 python-wrapper is not installed on the system.")
- return xsconstants.XSERR_SUCCESS
- try:
- parserctxt = libxml2.schemaNewMemParserCtxt(ACM_SCHEMA,
- len(ACM_SCHEMA))
- schemaparser = parserctxt.schemaParse()
- valid = schemaparser.schemaNewValidCtxt()
- doc = libxml2.parseDoc(self.toxml())
- if doc.schemaValidateDoc(valid) != 0:
- rc = -xsconstants.XSERR_BAD_XML
- except Exception, e:
- log.warn("Problem with the schema: %s" % str(e))
- rc = -xsconstants.XSERR_GENERAL_FAILURE
- if rc != xsconstants.XSERR_SUCCESS:
- log.warn("XML did not validate against schema")
- if rc == xsconstants.XSERR_SUCCESS:
- rc = self.__validate_name_and_labels()
- return rc
-
- def __validate_name_and_labels(self):
- """ no ':' allowed in the policy name and the labels """
- if ':' in self.get_name():
- return -xsconstants.XSERR_BAD_POLICY_NAME
- for s in self.policy_get_resourcelabel_names():
- if ':' in s:
- return -xsconstants.XSERR_BAD_LABEL
- for s in self.policy_get_virtualmachinelabel_names():
- if ':' in s:
- return -xsconstants.XSERR_BAD_LABEL
- return xsconstants.XSERR_SUCCESS
-
-
- def is_default_policy(self):
- """
- Determine whether this is the default policy
- """
- default = ['SystemManagement', ACM_LABEL_UNLABELED ]
- if self.policy_get_virtualmachinelabel_names() == default and \
- self.policy_get_bootstrap_vmlabel() == default[0] and \
- self.policy_get_stetypes_types() == default and \
- self.policy_get_stes_of_vmlabel(default[0]) == default and \
- self.policy_get_stes_of_vmlabel(default[1]) == [default[1]] and \
- self.policy_get_resourcelabel_names() == [default[1]] and \
- self.policy_get_chwall_types() == [ default[0] ] and \
- self.get_name() == "DEFAULT":
- return True
- return False
-
- def update(self, xml_new):
- """
- Update the policy with the new XML. The hypervisor decides
- whether the new policy can be applied.
- """
- rc = -xsconstants.XSERR_XML_PROCESSING
- errors = ""
- acmpol_old = self
- try:
- acmpol_new = ACMPolicy(xml=xml_new)
- except Exception:
- return -xsconstants.XSERR_XML_PROCESSING, errors
-
- vmlabel_map = acmpol_new.policy_get_vmlabel_translation_map()
-
- # An update requires version information in the current
- # and new policy. The version number of the current policy
- # must be the same as what is in the FromPolicy/Version node
- # in the new one and the current policy's name must be the
- # same as in FromPolicy/PolicyName
- # The default policy when it is set skips this step.
- if not acmpol_new.is_default_policy() and \
- not acmpol_old.is_default_policy():
- irc = self.__do_update_version_check(acmpol_new)
- if irc != xsconstants.XSERR_SUCCESS:
- return irc, errors
-
- if self.isloaded():
- newvmnames = \
- acmpol_new.policy_get_virtualmachinelabel_names_sorted()
- oldvmnames = \
- acmpol_old.policy_get_virtualmachinelabel_names_sorted()
- del_array = ""
- chg_array = ""
-
- for o in oldvmnames:
- if o not in newvmnames:
- old_idx = oldvmnames.index(o)
- if vmlabel_map.has_key(o):
- #not a deletion, but a renaming
- new = vmlabel_map[o]
- new_idx = newvmnames.index(new)
- chg_array += struct.pack("ii", old_idx, new_idx)
- else:
- del_array += struct.pack("i", old_idx)
- for v in newvmnames:
- if v in oldvmnames:
- old_idx = oldvmnames.index(v)
- new_idx = newvmnames.index(v)
- if old_idx != new_idx:
- chg_array += struct.pack("ii", old_idx, new_idx)
-
- # VM labels indicated in the 'from' attribute of a VM or
- # resource node but that did not exist in the old policy
- # are considered bad labels.
- bad_renamings = set(vmlabel_map.keys()) - set(oldvmnames)
- if len(bad_renamings) > 0:
- log.error("Bad VM label renamings: %s" %
- list(bad_renamings))
- return -xsconstants.XSERR_BAD_LABEL, errors
-
- reslabel_map = acmpol_new.policy_get_reslabel_translation_map()
- oldresnames = acmpol_old.policy_get_resourcelabel_names()
- bad_renamings = set(reslabel_map.keys()) - set(oldresnames)
- if len(bad_renamings) > 0:
- log.error("Bad resource label renamings: %s" %
- list(bad_renamings))
- return -xsconstants.XSERR_BAD_LABEL, errors
-
- #Get binary and map from the new policy
- rc, pol_map, bin_pol = acmpol_new.policy_create_map_and_bin()
- if rc != xsconstants.XSERR_SUCCESS:
- log.error("Could not build the map and binary policy.")
- return rc, errors
-
- #Need to do / check the following:
- # - relabel all resources where there is a 'from' field in
- # the policy and mark those as unlabeled where the label
- # does not appear in the new policy anymore
- # - relabel all VMs where there is a 'from' field in the
- # policy and mark those as unlabeled where the label
- # does not appear in the new policy anymore; no running
- # or paused VM may be unlabeled through this
- # - check that under the new labeling conditions the VMs
- # still have access to their resources as before. Unlabeled
- # resources are inaccessible. If this check fails, the
- # update failed.
- # - Attempt changes in the hypervisor; if this step fails,
- # roll back the relabeling of resources and VMs
- # - Commit the relabeling of resources
-
-
- rc, errors = security.change_acm_policy(bin_pol,
- del_array, chg_array,
- vmlabel_map, reslabel_map,
- self, acmpol_new,
- acmpol_new.is_default_policy())
-
- if rc == 0:
- # Replace the old DOM with the new one and save it
- self.dom = acmpol_new.dom
- self.compile()
- log.info("ACM policy update was successful")
- else:
- #Not loaded in HV
- self.dom = acmpol_new.dom
- rc = self.compile()
- return rc, errors
-
- def force_default_policy(klass, policy_ref):
- """
- Force the installation of the DEFAULT policy if for
- example no XML of the current policy is available and
- the update path with comparisons of old and new policy
- cannot be taken.
- This only succeeds if only Domain-0 is running or
- all guest have the same ssidref as Domain-0.
- """
- errors = ""
-
- acmpol_new = ACMPolicy(xml = get_DEFAULT_policy(), ref=policy_ref)
-
- from xen.lowlevel import acm
- dom0_ssidref = acm.getssid(0)
- del_array = ""
- chg_array = struct.pack("ii",
- dom0_ssidref['ssidref'] & 0xffff,
- 0x1)
-
- rc, pol_map, bin_pol = acmpol_new.policy_create_map_and_bin()
- if rc != xsconstants.XSERR_SUCCESS:
- return rc, errors, acmpol_new
- rc, errors = security.hv_chg_policy(bin_pol, del_array, chg_array)
- return rc, errors, acmpol_new
-
- force_default_policy = classmethod(force_default_policy)
-
- def get_reset_policy_xml(klass):
- dom0_label = security.get_ssid(0)[1]
- return get_DEFAULT_policy(dom0_label)
-
- get_reset_policy_xml = classmethod(get_reset_policy_xml)
-
- def __do_update_version_check(self, acmpol_new):
- acmpol_old = self
-
- now_vers = acmpol_old.policy_dom_get_hdr_item("Version")
- now_name = acmpol_old.policy_dom_get_hdr_item("PolicyName")
- req_oldvers = acmpol_new.policy_dom_get_frompol_item("Version")
- req_oldname = acmpol_new.policy_dom_get_frompol_item("PolicyName")
-
- if now_vers == "" or \
- now_vers != req_oldvers or \
- now_name != req_oldname:
- log.info("Policy rejected: %s != %s or %s != %s" % \
- (now_vers,req_oldvers,now_name,req_oldname))
- return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE
-
- if not self.isVersionUpdate(acmpol_new):
- log.info("Policy rejected since new version is not an update.")
- return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE
-
- return xsconstants.XSERR_SUCCESS
-
-
- def compareVersions(self, v1, v2):
- """
- Compare two policy versions given their tuples of major and
- minor.
- Return '0' if versions are equal, '>0' if v1 > v2 and
- '<' if v1 < v2
- """
- rc = v1[0] - v2[0]
- if rc == 0:
- rc = v1[1] - v2[1]
- return rc
-
- def getVersionTuple(self, item="Version"):
- v_str = self.policy_dom_get_hdr_item(item)
- return self.__convVersionToTuple(v_str)
-
- def get_version(self):
- return self.policy_dom_get_hdr_item("Version")
-
- def isVersionUpdate(self, polnew):
- if self.compareVersions(polnew.getVersionTuple(),
- self.getVersionTuple()) > 0:
- return True
- return False
-
- def __convVersionToTuple(self, v_str):
- """ Convert a version string, formatted according to the scheme
- "%d.%d" into a tuple of (major, minor). Return (0,0) if the
- string is empty.
- """
- major = 0
- minor = 0
- if v_str != "":
- tmp = v_str.split(".")
- major = int(tmp[0])
- if len(tmp) > 1:
- minor = int(tmp[1])
- return (major, minor)
-
- def get_policies_path(self):
- xoptions = XendOptions.instance()
- basedir = xoptions.get_xend_security_path()
- return basedir + "/policies/"
-
- def policy_path(self, name):
- prefix = self.get_policies_path()
- path = prefix + name.replace('.','/')
- _path = path.split("/")
- del _path[-1]
- mkdir.parents("/".join(_path), stat.S_IRWXU)
- return path
-
- def path_from_policy_name(self, name):
- return self.policy_path(name) + "-security_policy.xml"
-
- #
- # Functions interacting with the bootloader
- #
- def vmlabel_to_ssidref(self, vm_label):
- """ Convert a VMlabel into an ssidref given the current
- policy
- Return xsconstants.INVALID_SSIDREF if conversion failed.
- """
- ssidref = xsconstants.INVALID_SSIDREF
- names = self.policy_get_virtualmachinelabel_names_sorted()
- try:
- vmidx = names.index(vm_label)
- ssidref = (vmidx << 16) | vmidx
- except:
- pass
- return ssidref
-
- def set_vm_bootlabel(self, vm_label, remove=False):
- parms="<>"
- if vm_label != "":
- ssidref = self.vmlabel_to_ssidref(vm_label)
- if ssidref == xsconstants.INVALID_SSIDREF:
- return -xsconstants.XSERR_BAD_LABEL
- parms = "0x%08x:%s:%s:%s" % \
- (ssidref, xsconstants.ACM_POLICY_ID, \
- self.get_name(),vm_label)
- else:
- ssidref = 0 #Identifier for removal
-
- if remove == True:
- parms = "<>"
-
- try:
- def_title = bootloader.get_default_title()
- bootloader.set_kernel_attval(def_title, "ssidref", parms)
- except:
- return -xsconstants.XSERR_GENERAL_FAILURE
- return ssidref
-
- #
- # Utility functions related to the policy's files
- #
- def get_filename(self, postfix, prefix=None, dotted=False):
- """
- Create the filename for the policy. The prefix is prepended
- to the path. If dotted is True, then a policy name like
- 'a.b.c' will remain as is, otherwise it will become 'a/b/c'
- """
- if prefix == None:
- prefix = self.get_policies_path()
- name = self.get_name()
- if name:
- p = name.split(".")
- path = ""
- if dotted:
- sep = "."
- else:
- sep = "/"
- if len(p) > 1:
- path = sep.join(p[0:len(p)-1])
- if prefix != "" or path != "":
- allpath = prefix + path + sep + p[-1] + postfix
- else:
- allpath = p[-1] + postfix
- return allpath
- return None
-
- def __readfile(self, name):
- cont = ""
- filename = self.get_filename(name)
- f = open(filename, "r")
- if f:
- cont = f.read()
- f.close()
- return cont
-
- def get_map(self):
- return self.__readfile(".map")
-
- def get_bin(self):
- return self.__readfile(".bin")
-
- def copy_policy_file(self, suffix, destdir):
- spolfile = self.get_filename(suffix)
- dpolfile = destdir + "/" + self.get_filename(suffix,"",dotted=True)
- try:
- shutil.copyfile(spolfile, dpolfile)
- except Exception, e:
- log.error("Could not copy policy file %s to %s: %s" %
- (spolfile, dpolfile, str(e)))
- return -xsconstants.XSERR_FILE_ERROR
- return xsconstants.XSERR_SUCCESS
-
- #
- # DOM-related functions
- #
-
- def policy_dom_get(self, parent, key, createit=False):
- for node in parent.childNodes:
- if node.nodeType == Node.ELEMENT_NODE:
- if node.nodeName == key:
- return node
- if createit:
- self.dom_create_node(parent, key)
- return self.policy_dom_get(parent, key)
-
- def dom_create_node(self, parent, newname, value=" "):
- xml = "<a><"+newname+">"+ value +"</"+newname+"></a>"
- frag = minidom.parseString(xml)
- frag.childNodes[0].nodeType = Node.DOCUMENT_FRAGMENT_NODE
- parent.appendChild(frag.childNodes[0])
- return frag.childNodes[0]
-
- def dom_get_node(self, path, createit=False):
- node = None
- parts = path.split("/")
- doc = self.get_dom()
- if len(parts) > 0:
- node = self.policy_dom_get(doc.documentElement, parts[0])
- if node:
- i = 1
- while i < len(parts):
- _node = self.policy_dom_get(node, parts[i], createit)
- if not _node:
- if not createit:
- break
- else:
- self.dom_create_node(node, parts[i])
- _node = self.policy_dom_get(node, parts[i])
- node = _node
- i += 1
- return node
-
- #
- # Header-related functions
- #
- def policy_dom_get_header_subnode(self, nodename):
- node = self.dom_get_node("PolicyHeader/%s" % nodename)
- return node
-
- def policy_dom_get_hdr_item(self, name, default=""):
- node = self.policy_dom_get_header_subnode(name)
- if node and len(node.childNodes) > 0:
- return node.childNodes[0].nodeValue
- return default
-
- def policy_dom_get_frompol_item(self, name, default="", createit=False):
- node = self.dom_get_node("PolicyHeader/FromPolicy",createit)
- if node:
- node = self.policy_dom_get(node, name, createit)
- if node and len(node.childNodes) > 0:
- return node.childNodes[0].nodeValue
- return default
-
- def get_header_fields_map(self):
- header = {
- 'policyname' : self.policy_dom_get_hdr_item("PolicyName"),
- 'policyurl' : self.policy_dom_get_hdr_item("PolicyUrl"),
- 'reference' : self.policy_dom_get_hdr_item("Reference"),
- 'date' : self.policy_dom_get_hdr_item("Date"),
- 'namespaceurl' : self.policy_dom_get_hdr_item("NameSpaceUrl"),
- 'version' : self.policy_dom_get_hdr_item("Version")
- }
- return header
-
- def set_frompolicy_name(self, name):
- """ For tools to adapt the header of the policy """
- node = self.dom_get_node("PolicyHeader/FromPolicy/PolicyName",
- createit=True)
- node.childNodes[0].nodeValue = name
-
- def set_frompolicy_version(self, version):
- """ For tools to adapt the header of the policy """
- node = self.dom_get_node("PolicyHeader/FromPolicy/Version",
- createit=True)
- node.childNodes[0].nodeValue = version
-
- def set_policy_name(self, name):
- """ For tools to adapt the header of the policy """
- node = self.dom_get_node("PolicyHeader/PolicyName")
- node.childNodes[0].nodeValue = name
-
- def set_policy_version(self, version):
- """ For tools to adapt the header of the policy """
- node = self.dom_get_node("PolicyHeader/Version")
- node.childNodes[0].nodeValue = version
-
- def update_frompolicy(self, curpol):
- self.set_frompolicy_name(curpol.policy_dom_get_hdr_item("PolicyName"))
- version = curpol.policy_dom_get_hdr_item("Version")
- self.set_frompolicy_version(version)
- (maj, minor) = self.__convVersionToTuple(version)
- self.set_policy_version("%s.%s" % (maj, minor+1))
-
- #
- # Get all types that are part of a node
- #
-
- def policy_get_types(self, node):
- strings = []
- i = 0
- while i < len(node.childNodes):
- if node.childNodes[i].nodeName == "Type" and \
- len(node.childNodes[i].childNodes) > 0:
- strings.append(node.childNodes[i].childNodes[0].nodeValue)
- i += 1
- return strings
-
- #
- # Simple Type Enforcement-related functions
- #
-
- def policy_get_stetypes_node(self):
- node = self.dom_get_node("SimpleTypeEnforcement/SimpleTypeEnforcementTypes")
- return node
-
- def policy_get_stetypes_types(self):
- strings = []
- node = self.policy_get_stetypes_node()
- if node:
- strings = self.policy_get_types(node)
- return strings
-
- #
- # Chinese Wall Type-related functions
- #
-
- def policy_get_chwall_types(self):
- strings = []
- node = self.dom_get_node("ChineseWall/ChineseWallTypes")
- if node:
- strings = self.policy_get_types(node)
- return strings
-
- def policy_get_chwall_cfses(self):
- cfs = []
- node = self.dom_get_node("ChineseWall/ConflictSets")
- if node:
- i = 0
- while i < len(node.childNodes):
- _cfs = {}
- if node.childNodes[i].nodeName == "Conflict":
- _cfs['name'] = node.childNodes[i].getAttribute('name')
- _cfs['chws'] = self.policy_get_types(node.childNodes[i])
- cfs.append(_cfs)
- i += 1
- return cfs
-
- def policy_get_chwall_cfses_names_sorted(self):
- """
- Return the list of all conflict set names in alphabetical
- order.
- """
- cfs_names = []
- node = self.dom_get_node("ChineseWall/ConflictSets")
- if node:
- i = 0
- while i < len(node.childNodes):
- if node.childNodes[i].nodeName == "Conflict":
- n = node.childNodes[i].getAttribute('name')
- #it better have a name!
- if n:
- cfs_names.append(n)
- i += 1
- cfs_names.sort()
- return cfs_names
-
- #
- # Subject Label-related functions
- #
-
- def policy_get_bootstrap_vmlabel(self):
- node = self.dom_get_node("SecurityLabelTemplate/SubjectLabels")
- if node:
- vmlabel = node.getAttribute("bootstrap")
- return vmlabel
-
- # Get the names of all virtual machine labels; returns an array
- def policy_get_virtualmachinelabel_names(self):
- strings = []
- node = self.dom_get_node("SecurityLabelTemplate/SubjectLabels")
- if node:
- i = 0
- while i < len(node.childNodes):
- if node.childNodes[i].nodeName == "VirtualMachineLabel":
- name = self.policy_dom_get(node.childNodes[i], "Name")
- if len(name.childNodes) > 0:
- strings.append(name.childNodes[0].nodeValue)
- i += 1
- return strings
-
- def policy_sort_virtualmachinelabel_names(self, vmnames):
- bootstrap = self.policy_get_bootstrap_vmlabel()
- if bootstrap not in vmnames:
- raise SecurityError(-xsconstants.XSERR_POLICY_INCONSISTENT)
- vmnames.remove(bootstrap)
- vmnames.sort()
- vmnames.insert(0, bootstrap)
- if ACM_LABEL_UNLABELED in vmnames:
- vmnames.remove(ACM_LABEL_UNLABELED)
- vmnames.insert(0, ACM_LABEL_UNLABELED)
- return vmnames
-
- def policy_get_virtualmachinelabel_names_sorted(self):
- """ Get a sorted list of VMlabel names. The bootstrap VM's
- label will be the first one in that list, followed
- by an alphabetically sorted list of VM label names """
- vmnames = self.policy_get_virtualmachinelabel_names()
- res = self.policy_sort_virtualmachinelabel_names(vmnames)
- if res[0] != ACM_LABEL_UNLABELED:
- res.insert(0, ACM_LABEL_UNLABELED)
- return res
-
- def policy_get_virtualmachinelabels(self):
- """ Get a list of all virtual machine labels in this policy """
- res = []
- node = self.dom_get_node("SecurityLabelTemplate/SubjectLabels")
- if node:
- i = 0
- while i < len(node.childNodes):
- if node.childNodes[i].nodeName == "VirtualMachineLabel":
- name = self.policy_dom_get(node.childNodes[i], "Name")
- if len(name.childNodes) > 0:
- _res = {}
- _res['type'] = xsconstants.ACM_LABEL_VM
- _res['name'] = name.childNodes[0].nodeValue
- stes = self.policy_dom_get(node.childNodes[i],
- "SimpleTypeEnforcementTypes")
- if stes:
- _res['stes'] = self.policy_get_types(stes)
- else:
- _res['stes'] = []
- chws = self.policy_dom_get(node.childNodes[i],
- "ChineseWallTypes")
- if chws:
- _res['chws'] = self.policy_get_types(chws)
- else:
- _res['chws'] = []
- res.append(_res)
- i += 1
- return res
-
- def policy_get_stes_of_vmlabel(self, vmlabel):
- """ Get a list of all STEs of a given VMlabel """
- return self.__policy_get_stes_of_labeltype(vmlabel,
- "/SubjectLabels", "VirtualMachineLabel")
-
- def policy_get_stes_of_resource(self, reslabel):
- """ Get a list of all resources of a given VMlabel """
- return self.__policy_get_stes_of_labeltype(reslabel,
- "/ObjectLabels", "ResourceLabel")
-
- def __policy_get_stes_of_labeltype(self, label, path, labeltype):
- node = self.dom_get_node("SecurityLabelTemplate" + path)
- if node:
- i = 0
- while i < len(node.childNodes):
- if node.childNodes[i].nodeName == labeltype:
- name = self.policy_dom_get(node.childNodes[i], "Name")
- if len(name.childNodes) > 0 and \
- name.childNodes[0].nodeValue == label:
- stes = self.policy_dom_get(node.childNodes[i],
- "SimpleTypeEnforcementTypes")
- if not stes:
- return []
- return self.policy_get_types(stes)
- i += 1
- return []
-
- def policy_check_vmlabel_against_reslabels(self, vmlabel, resources):
- """
- Check whether the given vmlabel is compatible with the given
- resource labels. Do this by getting all the STEs of the
- vmlabel and the STEs of the resources. Any STE type of the
- VM label must match an STE type of the resource.
- """
- vm_stes = self.policy_get_stes_of_vmlabel(vmlabel)
- if len(vm_stes) == 0:
- return False
- for res in resources:
- res_stes = self.policy_get_stes_of_resource(res)
- if len(res_stes) == 0 or \
- len( set(res_stes).intersection( set(vm_stes) ) ) == 0:
- return False
- return True
-
- def __policy_get_label_translation_map(self, path, labeltype):
- res = {}
- node = self.dom_get_node("SecurityLabelTemplate/" + path)
- if node:
- i = 0
- while i < len(node.childNodes):
- if node.childNodes[i].nodeName == labeltype:
- name = self.policy_dom_get(node.childNodes[i], "Name")
- from_name = name.getAttribute("from")
- if from_name and len(name.childNodes) > 0:
- res.update({from_name : name.childNodes[0].nodeValue})
- i += 1
- return res
-
- def policy_get_vmlabel_translation_map(self):
- """
- Get a dictionary of virtual machine mappings from their
- old VMlabel name to the new VMlabel name.
- """
- return self.__policy_get_label_translation_map("SubjectLabels",
- "VirtualMachineLabel")
-
- def policy_get_reslabel_translation_map(self):
- """
- Get a dictionary of resource mappings from their
- old resource label name to the new resource label name.
- """
- return self.__policy_get_label_translation_map("ObjectLabels",
- "ResourceLabel")
-
- #
- # Object Label-related functions
- #
- def policy_get_resourcelabel_names(self):
- """
- Get the names of all resource labels in an array but
- only those that actually have types
- """
- strings = []
- node = self.dom_get_node("SecurityLabelTemplate/ObjectLabels")
- if node:
- i = 0
- while i < len(node.childNodes):
- if node.childNodes[i].nodeName == "ResourceLabel":
- name = self.policy_dom_get(node.childNodes[i], "Name")
- stes = self.policy_dom_get(node.childNodes[i],
- "SimpleTypeEnforcementTypes")
- if stes and len(name.childNodes) > 0:
- strings.append(name.childNodes[0].nodeValue)
- i += 1
- return strings
-
- def policy_get_resourcelabels(self):
- """
- Get all information about all resource labels of this policy.
- """
- res = []
- node = self.dom_get_node("SecurityLabelTemplate/ObjectLabels")
- if node:
- i = 0
- while i < len(node.childNodes):
- if node.childNodes[i].nodeName == "ResourceLabel":
- name = self.policy_dom_get(node.childNodes[i], "Name")
- if len(name.childNodes) > 0:
- _res = {}
- _res['type'] = xsconstants.ACM_LABEL_RES
- _res['name'] = name.childNodes[0].nodeValue
- stes = self.policy_dom_get(node.childNodes[i],
- "SimpleTypeEnforcementTypes")
- if stes:
- _res['stes'] = self.policy_get_types(stes)
- else:
- _res['stes'] = []
- _res['chws'] = []
- res.append(_res)
- i += 1
- return res
-
-
- def policy_find_reslabels_with_stetype(self, stetype):
- """
- Find those resource labels that hold a given STE type.
- """
- res = []
- reslabels = self.policy_get_resourcelabels()
- for resl in reslabels:
- if stetype in resl['stes']:
- res.append(resl['name'])
- return res
-
-
- def toxml(self):
- dom = self.get_dom()
- if dom:
- return dom.toxml()
- return None
-
- def hash(self):
- """ Calculate a SHA1 hash of the XML policy """
- return sha1(self.toxml())
-
- def save(self):
- ### Save the XML policy into a file ###
- rc = -xsconstants.XSERR_FILE_ERROR
- name = self.get_name()
- if name:
- path = self.path_from_policy_name(name)
- if path:
- f = open(path, 'w')
- if f:
- try:
- try:
- f.write(self.toxml())
- rc = 0
- except:
- pass
- finally:
- f.close()
- return rc
-
- def __write_to_file(self, suffix, data):
- #write the data into a file with the given suffix
- f = open(self.get_filename(suffix),"w")
- if f:
- try:
- try:
- f.write(data)
- except Exception, e:
- log.error("Error writing file: %s" % str(e))
- return -xsconstants.XSERR_FILE_ERROR
- finally:
- f.close()
- else:
- return -xsconstants.XSERR_FILE_ERROR
- return xsconstants.XSERR_SUCCESS
-
-
- def compile(self):
- rc = self.save()
- if rc == 0:
- rc, mapfile, bin_pol = self.policy_create_map_and_bin()
-
- if rc == 0:
- try:
- security.mapfile_lock()
-
- rc = self.__write_to_file(".map", mapfile)
- if rc != 0:
- log.error("Error writing map file")
-
- finally:
- security.mapfile_unlock()
-
- if rc == 0:
- rc = self.__write_to_file(".bin", bin_pol)
- if rc != 0:
- log.error("Error writing binary policy file")
- return rc
-
- def loadintohv(self):
- """
- load this policy into the hypervisor
- if successful,the policy's flags will indicate that the
- policy is the one loaded into the hypervisor
- """
- if not self.isloaded():
- (ret, output) = commands.getstatusoutput(
- security.xensec_tool +
- " loadpolicy " +
- self.get_filename(".bin"))
- if ret != 0:
- return -xsconstants.XSERR_POLICY_LOAD_FAILED
- return xsconstants.XSERR_SUCCESS
-
- def isloaded(self):
- """
- Determine whether this policy is the active one.
- """
- if self.get_name() == security.get_active_policy_name():
- return True
- return False
-
- def destroy(self):
- """
- Destroy the policy including its binary, mapping and
- XML files.
- This only works if the policy is not the one that's loaded
- """
- if self.isloaded():
- return -xsconstants.XSERR_POLICY_LOADED
- files = [ self.get_filename(".map",""),
- self.get_filename(".bin","") ]
- for f in files:
- try:
- os.unlink(f)
- except:
- pass
- if self.xendacmpolicy:
- self.xendacmpolicy.destroy()
- XSPolicy.destroy(self)
- return xsconstants.XSERR_SUCCESS
-
- def policy_get_domain_label(self, domid):
- """
- Given a domain's ID, retrieve the label it has using
- its ssidref for reverse calculation.
- """
- try:
- mgmt_dom = security.get_ssid(domid)
- except:
- return ""
- return self.policy_get_domain_label_by_ssidref(int(mgmt_dom[3]))
-
- def policy_get_domain_label_by_ssidref(self, ssidref):
- """ Given an ssidref, find the corresponding VM label """
- chwall_ref = ssidref & 0xffff
- try:
- allvmtypes = self.policy_get_virtualmachinelabel_names_sorted()
- except:
- return None
- return allvmtypes[chwall_ref]
-
- def policy_get_domain_label_formatted(self, domid):
- label = self.policy_get_domain_label(domid)
- if label == "":
- label = ACM_LABEL_UNLABELED
- return "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, self.get_name(), label)
-
- def policy_get_domain_label_by_ssidref_formatted(self, ssidref):
- label = self.policy_get_domain_label_by_ssidref(ssidref)
- if label == "":
- return ""
- return "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, self.get_name(), label)
-
- def policy_create_map_and_bin(self):
- """
- Create the policy's map and binary files -- compile the policy.
- """
- def roundup8(len):
- return ((len + 7) & ~7)
-
- rc = xsconstants.XSERR_SUCCESS
- mapfile = ""
- primpolcode = ACM_POLICY_UNDEFINED
- secpolcode = ACM_POLICY_UNDEFINED
- unknown_ste = set()
- unknown_chw = set()
- unlabeled_ste = "__NULL_LABEL__"
- unlabeled_chw = "__NULL_LABEL__"
-
- rc = self.validate()
- if rc:
- return rc, "", ""
-
- stes = self.policy_get_stetypes_types()
- if stes:
- stes.sort()
-
- chws = self.policy_get_chwall_types()
- if chws:
- chws.sort()
-
- vms = self.policy_get_virtualmachinelabels()
- bootstrap = self.policy_get_bootstrap_vmlabel()
-
- vmlabels = self.policy_get_virtualmachinelabel_names_sorted()
- if bootstrap not in vmlabels:
- log.error("Bootstrap label '%s' not found among VM labels '%s'." \
- % (bootstrap, vmlabels))
- return -xsconstants.XSERR_POLICY_INCONSISTENT, "", ""
-
- vms_with_chws = []
- chws_by_vm = { ACM_LABEL_UNLABELED : [] }
- for v in vms:
- if v.has_key("chws"):
- vms_with_chws.append(v["name"])
- chws_by_vm[v["name"]] = v["chws"]
-
-
- if bootstrap in vms_with_chws:
- vms_with_chws.remove(bootstrap)
- vms_with_chws.sort()
- vms_with_chws.insert(0, bootstrap)
- else:
- vms_with_chws.sort()
-
- if ACM_LABEL_UNLABELED in vms_with_chws:
- unlabeled_chw = ACM_LABEL_UNLABELED
- vms_with_chws.remove(ACM_LABEL_UNLABELED) ; # @1
-
- vms_with_stes = []
- stes_by_vm = { ACM_LABEL_UNLABELED : [] }
- for v in vms:
- if v.has_key("stes"):
- vms_with_stes.append(v["name"])
- stes_by_vm[v["name"]] = v["stes"]
-
- if bootstrap in vms_with_stes:
- vms_with_stes.remove(bootstrap)
- vms_with_stes.sort()
- vms_with_stes.insert(0, bootstrap)
- else:
- vms_with_stes.sort()
-
- if ACM_LABEL_UNLABELED in vms_with_stes:
- unlabeled_ste = ACM_LABEL_UNLABELED
- vms_with_stes.remove(ACM_LABEL_UNLABELED) ; # @2
-
- resnames = self.policy_get_resourcelabel_names()
- resnames.sort()
- stes_by_res = {}
- res = self.policy_get_resourcelabels()
- for r in res:
- if r.has_key("stes"):
- stes_by_res[r["name"]] = r["stes"]
-
- if ACM_LABEL_UNLABELED in resnames:
- resnames.remove(ACM_LABEL_UNLABELED)
-
- # check for duplicate labels
- if len(vmlabels) != len(set(vmlabels)) or \
- len(resnames) != len(set(resnames)) or \
- len(stes) != len(set(stes)) or \
- len(chws) != len(set(chws)):
- return -xsconstants.XSERR_POLICY_HAS_DUPLICATES, "", ""
-
- max_chw_ssids = 1 + len(vms_with_chws)
- max_chw_types = 1 + len(vms_with_chws)
- max_ste_ssids = 1 + len(vms_with_stes) + len(resnames)
- max_ste_types = 1 + len(vms_with_stes) + len(resnames)
-
- mapfile = "POLICYREFERENCENAME %s\n" % self.get_name()
- mapfile += "MAGIC %08x\n" % ACM_MAGIC
- mapfile += "POLICFILE %s\n" % \
- self.path_from_policy_name(self.get_name())
- mapfile += "BINARYFILE %s\n" % self.get_filename(".bin")
- mapfile += "MAX-CHWALL-TYPES %08x\n" % len(chws)
- mapfile += "MAX-CHWALL-SSIDS %08x\n" % max_chw_ssids
- mapfile += "MAX-CHWALL-LABELS %08x\n" % max_chw_ssids
- mapfile += "MAX-STE-TYPES %08x\n" % len(stes)
- mapfile += "MAX-STE-SSIDS %08x\n" % max_ste_ssids
- mapfile += "MAX-STE-LABELS %08x\n" % max_ste_ssids
- mapfile += "\n"
-
- if chws:
- mapfile += \
- "PRIMARY CHWALL\n"
- primpolcode = ACM_CHINESE_WALL_POLICY
- if stes:
- mapfile += \
- "SECONDARY STE\n"
- else:
- mapfile += \
- "SECONDARY NULL\n"
- secpolcode = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY
- else:
- if stes:
- mapfile += \
- "PRIMARY STE\n"
- primpolcode = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY
- mapfile += \
- "SECONDARY NULL\n"
-
- mapfile += "\n"
-
- if len(vms_with_chws) > 0:
- mapfile += \
- "LABEL->SSID ANY CHWALL %-20s %x\n" % \
- (unlabeled_chw, 0)
- i = 0
- for v in vms_with_chws:
- mapfile += \
- "LABEL->SSID VM CHWALL %-20s %x\n" % \
- (v, i+1)
- i += 1
- mapfile += "\n"
-
- if len(vms_with_stes) > 0 or len(resnames) > 0:
- mapfile += \
- "LABEL->SSID ANY STE %-20s %08x\n" % \
- (unlabeled_ste, 0)
- i = 0
- for v in vms_with_stes:
- mapfile += \
- "LABEL->SSID VM STE %-20s %x\n" % (v, i+1)
- i += 1
- j = 0
- for r in resnames:
- mapfile += \
- "LABEL->SSID RES STE %-20s %x\n" % (r, j+i+1)
- j += 1
- mapfile += "\n"
-
- if vms_with_chws:
- mapfile += \
- "SSID->TYPE CHWALL %08x\n" % 0
- i = 1
- for v in vms_with_chws:
- mapfile += \
- "SSID->TYPE CHWALL %08x" % i
- for c in chws_by_vm[v]:
- mapfile += " %s" % c
- mapfile += "\n"
- i += 1
- mapfile += "\n"
-
- if len(vms_with_stes) > 0 or len(resnames) > 0:
- mapfile += \
- "SSID->TYPE STE %08x\n" % 0
- i = 1
- for v in vms_with_stes:
- mapfile += \
- "SSID->TYPE STE %08x" % i
- for s in stes_by_vm[v]:
- mapfile += " %s" % s
- mapfile += "\n"
- i += 1
-
- for r in resnames:
- mapfile += \
- "SSID->TYPE STE %08x" % i
- for s in stes_by_res[r]:
- mapfile += " %s" % s
- mapfile += "\n"
- i += 1
- mapfile += "\n"
-
- if chws:
- i = 0
- while i < len(chws):
- mapfile += \
- "TYPE CHWALL %-20s %d\n" % (chws[i], i)
- i += 1
- mapfile += "\n"
- if stes:
- i = 0
- while i < len(stes):
- mapfile += \
- "TYPE STE %-20s %d\n" % (stes[i], i)
- i += 1
- mapfile += "\n"
-
- mapfile += "\n"
-
- # Build header with policy name
- length = roundup8(4 + len(self.get_name()) + 1)
- polname = self.get_name();
- pr_bin = struct.pack("!i", len(polname)+1)
- pr_bin += polname;
- while len(pr_bin) < length:
- pr_bin += "\x00"
-
- # Build chinese wall part
- vms_with_chws.insert(0, ACM_LABEL_UNLABELED)
-
- cfses_names = self.policy_get_chwall_cfses_names_sorted()
- cfses = self.policy_get_chwall_cfses()
-
- chwformat = "!iiiiiiiii"
- max_chw_cfs = len(cfses)
- chw_ssid_offset = struct.calcsize(chwformat)
- chw_confset_offset = chw_ssid_offset + \
- 2 * len(chws) * max_chw_types
- chw_running_types_offset = 0
- chw_conf_agg_offset = 0
-
- chw_bin = struct.pack(chwformat,
- ACM_CHWALL_VERSION,
- ACM_CHINESE_WALL_POLICY,
- len(chws),
- max_chw_ssids,
- max_chw_cfs,
- chw_ssid_offset,
- chw_confset_offset,
- chw_running_types_offset,
- chw_conf_agg_offset)
- chw_bin_body = ""
-
- # VMs that are listed and their chinese walls
- for v in vms_with_chws:
- for c in chws:
- unknown_chw |= (set(chws_by_vm[v]) - set(chws))
- if c in chws_by_vm[v]:
- chw_bin_body += struct.pack("!h",1)
- else:
- chw_bin_body += struct.pack("!h",0)
-
- # Conflict sets -- they need to be processed in alphabetical order
- for cn in cfses_names:
- if cn == "" or cn is None:
- return -xsconstants.XSERR_BAD_CONFLICTSET, "", ""
- i = 0
- while i < len(cfses):
- if cfses[i]['name'] == cn:
- conf = cfses[i]['chws']
- break
- i += 1
- for c in chws:
- if c in conf:
- chw_bin_body += struct.pack("!h",1)
- else:
- chw_bin_body += struct.pack("!h",0)
- del cfses[i]
-
- if len(cfses) != 0:
- return -xsconstants.XSERR_BAD_CONFLICTSET, "", ""
-
- chw_bin += chw_bin_body
-
- while len(chw_bin) < roundup8(len(chw_bin)):
- chw_bin += "\x00"
-
- # Build STE part
- vms_with_stes.insert(0, ACM_LABEL_UNLABELED) # Took out in @2
-
- steformat="!iiiii"
- ste_bin = struct.pack(steformat,
- ACM_STE_VERSION,
- ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- len(stes),
- max_ste_types,
- struct.calcsize(steformat))
- ste_bin_body = ""
- if stes:
- # VMs that are listed and their STE types
- for v in vms_with_stes:
- unknown_ste |= (set(stes_by_vm[v]) - set(stes))
- for s in stes:
- if s in stes_by_vm[v]:
- ste_bin_body += struct.pack("!h",1)
- else:
- ste_bin_body += struct.pack("!h",0)
- for r in resnames:
- unknown_ste |= (set(stes_by_res[r]) - set(stes))
- for s in stes:
- if s in stes_by_res[r]:
- ste_bin_body += struct.pack("!h",1)
- else:
- ste_bin_body += struct.pack("!h",0)
-
- ste_bin += ste_bin_body;
-
- while len(ste_bin) < roundup8(len(ste_bin)):
- ste_bin += "\x00"
-
- #Write binary header:
- headerformat="!iiiiiiiiii20s"
- totallen_bin = struct.calcsize(headerformat) + \
- len(pr_bin) + len(chw_bin) + len(ste_bin)
- polref_offset = struct.calcsize(headerformat)
- primpoloffset = polref_offset + len(pr_bin)
- if primpolcode == ACM_CHINESE_WALL_POLICY:
- secpoloffset = primpoloffset + len(chw_bin)
- elif primpolcode == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
- secpoloffset = primpoloffset + len(ste_bin)
- else:
- secpoloffset = primpoloffset
-
- (major, minor) = self.getVersionTuple()
- hdr_bin = struct.pack(headerformat,
- ACM_MAGIC,
- ACM_POLICY_VERSION,
- totallen_bin,
- polref_offset,
- primpolcode,
- primpoloffset,
- secpolcode,
- secpoloffset,
- major, minor,
- self.hash().digest())
-
- all_bin = array.array('B')
- for s in [ hdr_bin, pr_bin, chw_bin, ste_bin ]:
- for c in s:
- all_bin.append(ord(c))
-
- log.info("Compiled policy: rc = %s" % hex(rc))
- if len(unknown_ste) > 0:
- log.info("The following STEs in VM/res labels were unknown:" \
- " %s" % list(unknown_ste))
- rc = -xsconstants.XSERR_BAD_LABEL
- if len(unknown_chw) > 0:
- log.info("The following Ch. Wall types in labels were unknown:" \
- " %s" % list(unknown_chw))
- rc = -xsconstants.XSERR_BAD_LABEL
- return rc, mapfile, all_bin.tostring()
-
- def validate_enforced_policy_hash(self):
- """ verify that the policy hash embedded in the binary policy
- that is currently enforce matches the one of the XML policy.
- """
- if self.hash().digest() != self.get_enforced_policy_hash():
- raise Exception('Policy hashes do not match')
-
- def get_enforced_policy_hash(self):
- binpol = self.get_enforced_binary()
- headerformat="!iiiiiiiiii20s"
- res = struct.unpack(headerformat, binpol[:60])
- if len(res) >= 11:
- return res[10]
- return None
-
- def get_enforced_binary(self):
- rc, binpol = security.hv_get_policy()
- if rc != 0:
- raise SecurityError(-xsconstants.XSERR_HV_OP_FAILED)
- return binpol
-
- get_enforced_binary = classmethod(get_enforced_binary)
diff --git a/tools/python/xen/util/asserts.py b/tools/python/xen/util/asserts.py
deleted file mode 100644
index dd3cb7f..0000000
--- a/tools/python/xen/util/asserts.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#===========================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-
-def isCharConvertible(c):
- """Assert that the given value is convertible to a character using the %c
- conversion. This implies that c is either an integer, or a character
- (i.e. a string of length 1).
- """
-
- assert (isinstance(c, int) or
- (isinstance(c, str) and
- len(c) == 1)), "%s is not convertible to a character" % c
diff --git a/tools/python/xen/util/auxbin.py b/tools/python/xen/util/auxbin.py
deleted file mode 100644
index a690ad9..0000000
--- a/tools/python/xen/util/auxbin.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005-2006 XenSource Inc.
-#============================================================================
-
-
-import os
-import os.path
-import sys
-from xen.util.path import *
-
-def execute(exe, args = None):
- exepath = pathTo(exe)
- a = [ exepath ]
- if args:
- a.extend(args)
- try:
- os.execv(exepath, a)
- except (OSError, TypeError), exn:
- print exepath, ": ", exn
- sys.exit(1)
-
-SEARCHDIRS = [ BINDIR, SBINDIR, LIBEXEC, PRIVATE_BINDIR, XENFIRMWAREDIR ]
-def pathTo(exebin):
- for dir in SEARCHDIRS:
- exe = os.path.join(dir, exebin)
- if os.path.exists(exe):
- return exe
- return None
-
-def xen_configdir():
- return XEN_CONFIG_DIR
-
-def scripts_dir():
- return XEN_SCRIPT_DIR
diff --git a/tools/python/xen/util/blkif.py b/tools/python/xen/util/blkif.py
deleted file mode 100644
index 4bbae30..0000000
--- a/tools/python/xen/util/blkif.py
+++ /dev/null
@@ -1,107 +0,0 @@
-import os
-import re
-import string
-
-def expand_dev_name(name):
- if not name:
- return name
- if re.match( '^/', name ):
- return name
- else:
- return '/dev/' + name
-
-def blkdev_name_to_number(name):
- """Take the given textual block-device name (e.g., '/dev/sda1',
- 'hda') and return the device number used by the OS. """
-
- n = expand_dev_name(name)
-
- devname = 'virtual-device'
- devnum = None
-
- scsi_major = [ 8, 65, 66, 67, 68, 69, 70, 71, 128, 129, 130, 131, 132, 133, 134, 135 ]
- if re.match( '/dev/sd[a-z]([1-9]|1[0-5])?$', n):
- major = scsi_major[(ord(n[7:8]) - ord('a')) / 16]
- minor = ((ord(n[7:8]) - ord('a')) % 16) * 16 + int(n[8:] or 0)
- devnum = major * 256 + minor
- elif re.match( '/dev/sd[a-i][a-z]([1-9]|1[0-5])?$', n):
- major = scsi_major[((ord(n[7:8]) - ord('a') + 1) * 26 + (ord(n[8:9]) - ord('a'))) / 16 ]
- minor = (((ord(n[7:8]) - ord('a') + 1 ) * 26 + (ord(n[8:9]) - ord('a'))) % 16) * 16 + int(n[9:] or 0)
- devnum = major * 256 + minor
- elif re.match( '/dev/hd[a-t]([1-9]|[1-5][0-9]|6[0-3])?$', n):
- ide_majors = [ 3, 22, 33, 34, 56, 57, 88, 89, 90, 91 ]
- major = ide_majors[(ord(n[7:8]) - ord('a')) / 2]
- minor = ((ord(n[7:8]) - ord('a')) % 2) * 64 + int(n[8:] or 0)
- devnum = major * 256 + minor
- elif re.match( '/dev/xvd[a-p]([1-9]|1[0-5])?$', n):
- devnum = (202 << 8) + ((ord(n[8:9]) - ord('a')) << 4) + int(n[9:] or 0)
- elif re.match('/dev/xvd[q-z]([1-9]|1[0-5])?$', n):
- devname = 'virtual-device-ext'
- devnum = (1 << 28) + ((ord(n[8:9]) - ord('a')) << 8) + int(n[9:] or 0)
- elif re.match('/dev/xvd[a-i][a-z]([1-9]|1[0-5])?$', n):
- devname = 'virtual-device-ext'
- devnum = (1 << 28) + (((ord(n[8:9]) - ord('a') + 1) * 26 + (ord(n[9:10]) - ord('a'))) << 8) + int(n[10:] or 0)
- elif re.match( '^(0x)[0-9a-fA-F]+$', name ):
- devnum = string.atoi(name, 16)
- elif re.match('^[0-9]+$', name):
- devnum = string.atoi(name, 10)
-
- return (devname, devnum)
-
-def blkdev_segment(name):
- """Take the given block-device name (e.g. '/dev/sda1', 'hda')
- and return a dictionary { device, start_sector,
- nr_sectors, type }
- device: Device number of the given partition
- start_sector: Index of first sector of the partition
- nr_sectors: Number of sectors comprising this partition
- type: 'Disk' or identifying name for partition type
- """
- val = None
- (name, n) = blkdev_name_to_number(name)
- if not n is None:
- val = { 'device' : n,
- 'start_sector' : long(0),
- 'nr_sectors' : long(1L<<63),
- 'type' : 'Disk' }
- return val
-
-def parse_uname(uname):
- fn = typ = taptype = None
- if uname.find(":") != -1:
- (typ, fn) = uname.split(":", 1)
-
- if typ in ("phy") and not fn.startswith("/"):
- fn = "/dev/%s" %(fn,)
-
- if typ in ("tap", "tap2"):
- (taptype, fn) = fn.split(":", 1)
- if taptype in ("tapdisk", "ioemu"):
- (taptype, fn) = fn.split(":", 1)
- return (fn, (typ,taptype))
-
-
-def blkdev_uname_to_file(uname):
- """Take a blkdev uname and return the corresponding filename."""
- return parse_uname(uname)[0]
-
-def blkdev_uname_to_taptype(uname):
- """Take a blkdev uname and return the blktap type."""
- return parse_uname(uname)[1]
-
-def mount_mode(name):
- mode = None
- name = expand_dev_name(name)
- lines = os.popen('mount 2>/dev/null').readlines()
- exp = re.compile('^' + name + ' .*[\(,]r(?P<mode>[ow])[,\)]')
- for line in lines:
- pm = exp.match(line)
- if not pm: continue
- mode = pm.group('mode')
- break
- if mode == 'w':
- return mode
- if mode == 'o':
- mode = 'r'
- return mode
-
diff --git a/tools/python/xen/util/bootloader.py b/tools/python/xen/util/bootloader.py
deleted file mode 100644
index d3b2de7..0000000
--- a/tools/python/xen/util/bootloader.py
+++ /dev/null
@@ -1,626 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006,2007 International Business Machines Corp.
-# Author: Stefan Berger <stefanb at us.ibm.com>
-#============================================================================
-
-import re
-import os, stat
-import tempfile
-import shutil
-import threading
-
-from xen.xend.XendLogging import log
-from xen.util import mkdir
-import xen.util.xsm.xsm as security
-
-#
-# Functions for modifying entries in the bootloader, i.e. adding
-# a module to boot the system with a policy.
-#
-
-def get_default_title():
- """ See description in Bootloader class below """
- return __bootloader.get_default_title()
-
-
-def get_boot_policies():
- """ See description in Bootloader class below """
- return __bootloader.get_boot_policies()
-
-
-def add_boot_policy(index, binpolname):
- """ See description in Bootloader class below """
- return __bootloader.add_boot_policy(index, binpolname)
-
-
-def rm_policy_from_boottitle(index, unamelist):
- """ See description in Bootloader class below """
- return __bootloader.rm_policy_from_boottitle(index, unamelist)
-
-
-def set_kernel_attval(index, att, val):
- """ See description in Bootloader class below """
- return __bootloader.set_kernel_attval(index, att, val)
-
-
-def get_kernel_val(index, att):
- """ See description in Bootloader class below """
- return __bootloader.get_kernel_val(index, att)
-
-
-def set_boot_policy(title_idx, filename):
- boottitles = get_boot_policies()
- for key in boottitles.iterkeys():
- boottitles[key] += ".bin"
- if boottitles.has_key(title_idx):
- rm_policy_from_boottitle(title_idx, [ boottitles[title_idx] ])
- rc = add_boot_policy(title_idx, filename)
- return rc
-
-
-def loads_default_policy(filename):
- """ Determine whether the given policy is loaded by the default boot title """
- policy = get_default_policy()
- if policy:
- polfile = policy + ".bin"
- if polfile == filename or \
- "/"+polfile == filename:
- return True
- return False
-
-
-def get_default_policy():
- """ Get the name of the policy loaded by the default boot title """
- title = get_default_title()
- policies = get_boot_policies()
- return policies.get(title)
-
-
-def set_default_boot_policy(filename):
- """ Set the boot policy in the default title to the given name. """
- title = get_default_title()
- return set_boot_policy(title, filename)
-
-
-def __is_bootdir_mounted():
- """
- Determine whether the boot partition /boot is mounted or not
- """
- rc = False
- file = open("/proc/mounts")
- for line in file:
- tmp = line.split(" ")
- if tmp[1] == "/boot":
- rc = True
- break
- return rc
-
-def get_prefix():
- if __is_bootdir_mounted():
- return "/"
- else:
- return "/boot/"
-
-
-
-class Bootloader:
- """ Bootloader class that real bootloader implementations must overwrite """
- def __init__(self):
- pass
-
- def probe(self):
- """ Test whether this implementation of a bootloader is supported on the
- local system """
- return True
-
- def get_default_title(self):
- """ Get the index (starting with 0) of the default boot title
- This number is read from the grub configuration file.
- In case of an error '-1' is returned
- @rtype: int
- @return: the index of the default boot title
- """
- return None
-
- def get_boot_policies(self):
- """ Get a dictionary of policies that the system is booting with.
- @rtype: dict
- @return: dictionary of boot titles where the keys are the
- indices of the boot titles
- """
- return {}
-
- def add_boot_policy(self, index, binpolname):
- """ Add the binary policy for automatic loading when
- booting the system. Add it to the boot title at index
- 'index'.
- """
- return False
-
- def rm_policy_from_boottitle(self, index, unamelist):
- """ Remove a policy from the given title. A list of possible policies
- must be given to detect what module to remove
- """
- return False
-
- def set_kernel_attval(self, index, att, val):
- """
- Append an attribut/value pair to the kernel line.
- @param index : The index of the title to modify
- @param att : The attribute to add
- @param val : The value to add. If no value or the special value
- '<>' is given, then the attribute will be removed.
- If an empty value is given, then only the attribute
- is added in the format "att", otherwise "att=val"
- is added.
- """
- return False
-
- def get_kernel_val(self, index, att):
- """
- Get an attribute's value from the kernel line.
- @param index : The index of the title to get the attribute/value from
- @param att : The attribute to read the value of
- """
- return None
-
-
-class Grub(Bootloader):
- """ Implementation for manipulating bootloader entries in grub according
- to the 'Bootloader' class interface """
-
- def __init__(self):
- self.__bootfile_lock = threading.RLock()
- self.title_re = re.compile("\s*title\s", re.IGNORECASE)
- self.module_re = re.compile("\s+module\s", re.IGNORECASE)
- self.policy_re = re.compile(".*\.bin", re.IGNORECASE)
- self.kernel_re = re.compile("\s*kernel\s", re.IGNORECASE)
- Bootloader.__init__(self)
-
- def probe(self):
- try:
- boot_file = self.__get_bootfile()
- except:
- return False
- return True
-
-
- def __get_bootfile(self):
- """ Get the name of the bootfile """
- boot_file = "/boot/grub/grub.conf"
- alt_boot_file = "/boot/grub/menu.lst"
-
- if not os.path.isfile(boot_file):
- #take alternate boot file instead
- boot_file = alt_boot_file
-
- #follow symlink since menue.lst might be linked to grub.conf
- if not os.path.exists(boot_file):
- raise IOError("Boot file \'%s\' not found." % boot_file)
-
- if stat.S_ISLNK(os.lstat(boot_file)[stat.ST_MODE]):
- new_name = os.readlink(boot_file)
- if new_name[0] == "/":
- boot_file = new_name
- else:
- path = boot_file.split('/')
- path[len(path)-1] = new_name
- boot_file = '/'.join(path)
- if not os.path.exists(boot_file):
- raise IOError("Boot file \'%s\' not found." % boot_file)
- return boot_file
-
-
- def get_default_title(self):
- """ Get the index (starting with 0) of the default boot title
- This number is read from the grub configuration file.
- In case of an error '-1' is returned
- @rtype: int
- @return: the index of the default boot title
- """
- def_re = re.compile("default", re.IGNORECASE)
- default = None
- try:
- boot_file = self.__get_bootfile()
- except:
- return default
- try:
- self.__bootfile_lock.acquire()
- grub_fd = open(boot_file)
- for line in grub_fd:
- line = line.rstrip()
- if def_re.match(line):
- #remove 'default='
- line = line.lstrip()[8:]
- default = int(line)
- break
- finally:
- self.__bootfile_lock.release()
- return default
-
-
- def get_boot_policies(self):
- """ Get a dictionary of policies that the system is booting with.
- @rtype: dict
- @return: dictionary of boot titles where the keys are the
- indices of the boot titles
- """
- policies = {}
- within_title = 0
- idx = -1
- try:
- boot_file = self.__get_bootfile()
- except:
- return policies
- try:
- self.__bootfile_lock.acquire()
-
- grub_fd = open(boot_file)
- for line in grub_fd:
- if self.title_re.match(line):
- within_title = 1
- idx = idx + 1
- if within_title and self.module_re.match(line):
- if self.policy_re.match(line):
- start = line.find("module")
- pol = line[start+6:]
- pol = pol.strip()
- if pol[0] == '/':
- pol = pol[1:]
- if pol[0:5] == "boot/":
- pol = pol[5:]
- if pol.endswith(".bin"):
- pol = pol[:-4]
- policies[idx] = pol
- finally:
- self.__bootfile_lock.release()
- return policies
-
-
- def add_boot_policy(self, index, binpolname):
- """ Add the binary policy for automatic loading when
- booting the system. Add it to the boot title at index
- 'index'.
- """
- ctr = 0
- module_line = ""
- within_title = 0
- found = False
- try:
- boot_file = self.__get_bootfile()
- except:
- return False
- try:
- self.__bootfile_lock.acquire()
- grub_fd = open(boot_file)
- (tmp_fd, tmp_grub) = tempfile.mkstemp()
- for line in grub_fd:
- if self.title_re.match(line):
- if module_line != "" and not found:
- os.write(tmp_fd, module_line)
- found = True
-
- if ctr == index:
- within_title = 1
- else:
- within_title = 0
- ctr = ctr + 1
- elif within_title and self.module_re.match(line):
- start = line.find("module")
- l = line[start+6:len(line)]
- l = l.lstrip()
- if l[0] == '/':
- prefix = "/"
- else:
- prefix = ""
- prefix = get_prefix()
- module_line = "\tmodule %s%s\n" % (prefix,binpolname)
- else:
- if module_line != "" and not found:
- os.write(tmp_fd, module_line)
- found = True
-
- os.write(tmp_fd, line)
-
- if module_line != "" and not found:
- if ord(line[-1]) not in [ 10 ]:
- os.write(tmp_fd, '\n')
- os.write(tmp_fd, module_line)
- found = True
-
- shutil.move(boot_file, boot_file+"_save")
- shutil.copyfile(tmp_grub, boot_file)
- os.close(tmp_fd)
- try:
- os.remove(tmp_grub)
- except:
- pass
- finally:
- self.__bootfile_lock.release()
- return found
-
-
- def rm_policy_from_boottitle(self, index, unamelist):
- """ Remove a policy from the given title. A list of possible policies
- must be given to detect what module to remove
- """
- found = False
- ctr = 0
- within_title = 0
-
- prefix = get_prefix()
- namelist = [prefix+name for name in unamelist]
-
- try:
- boot_file = self.__get_bootfile()
- except:
- return False
- try:
- self.__bootfile_lock.acquire()
-
- grub_fd = open(boot_file)
- (tmp_fd, tmp_grub) = tempfile.mkstemp()
- for line in grub_fd:
- omit_line = False
- if self.title_re.match(line):
- if ctr == index:
- within_title = 1
- else:
- within_title = 0
- ctr = ctr + 1
- if within_title and self.module_re.match(line):
- if self.policy_re.match(line):
- start = line.find("module")
- pol = line[start+6:len(line)]
- pol = pol.strip()
- if pol in namelist:
- omit_line = True
- found = True
- if not omit_line:
- os.write(tmp_fd, line)
- if found:
- shutil.move(boot_file, boot_file+"_save")
- shutil.copyfile(tmp_grub, boot_file)
- os.close(tmp_fd)
- try:
- os.remove(tmp_grub)
- except:
- pass
- finally:
- self.__bootfile_lock.release()
- return found
-
-
- def set_kernel_attval(self, index, att, val):
- """
- Append an attribut/value pair to the kernel line.
- @param index : The index of the title to modify
- @param att : The attribute to add
- @param val : The value to add. If no value or the special value
- '<>' is given, then the attribute will be removed.
- If an empty value is given, then only the attribute
- is added in the format "att", otherwise "att=val"
- is added.
- """
- found = False
- ctr = 0
- within_title = 0
- try:
- boot_file = self.__get_bootfile()
- except:
- False
- try:
- self.__bootfile_lock.acquire()
-
- grub_fd = open(boot_file)
- (tmp_fd, tmp_grub) = tempfile.mkstemp()
- for line in grub_fd:
- if self.title_re.match(line):
- if ctr == index:
- within_title = 1
- else:
- within_title = 0
- ctr = ctr + 1
- if within_title and self.kernel_re.match(line):
- nitems = []
- items = line.split(" ")
- i = 0
- while i < len(items):
- el = items[i].split("=",1)
- if el[0] != att:
- nitems.append(items[i].rstrip("\n"))
- i += 1
- if val == "":
- nitems.append("%s" % (att))
- elif val != None and val != "<>":
- nitems.append("%s=%s" % (att,val))
- line = " ".join(nitems) + "\n"
- os.write(tmp_fd, line)
- shutil.move(boot_file, boot_file+"_save")
- shutil.copyfile(tmp_grub, boot_file)
- os.close(tmp_fd)
- try:
- os.remove(tmp_grub)
- except:
- pass
- finally:
- self.__bootfile_lock.release()
- return found
-
-
- def get_kernel_val(self, index, att):
- """
- Get an attribute's value from the kernel line.
- @param index : The index of the title to get the attribute/value from
- @param att : The attribute to read the value of
- """
- ctr = 0
- within_title = 0
- try:
- boot_file = self.__get_bootfile()
- except:
- return None
- try:
- self.__bootfile_lock.acquire()
-
- grub_fd = open(boot_file)
- for line in grub_fd:
- if self.title_re.match(line):
- if ctr == index:
- within_title = 1
- else:
- within_title = 0
- ctr = ctr + 1
- if within_title and self.kernel_re.match(line):
- line = line.strip()
- items = line.split(" ")
- i = 0
- while i < len(items):
- el = items[i].split("=",1)
- if el[0] == att:
- if len(el) == 1:
- return "<>"
- return el[1]
- i += 1
- finally:
- self.__bootfile_lock.release()
- return None # Not found
-
-class LatePolicyLoader(Bootloader):
- """ A fake bootloader file that holds the policy to load automatically
- once xend has started up and the Domain-0 label to set. """
- def __init__(self):
- self.__bootfile_lock = threading.RLock()
- self.PATH = security.security_dir_prefix
- self.FILENAME = self.PATH + "/xen_boot_policy"
- self.DEFAULT_TITLE = "ANY"
- self.POLICY_ATTR = "POLICY"
- Bootloader.__init__(self)
-
- def probe(self):
- try:
- _dir=os.path.dirname(self.FILENAME)
- mkdir.parents(_dir, stat.S_IRWXU)
- except:
- return False
- return True
-
- def get_default_title(self):
- return self.DEFAULT_TITLE
-
- def get_boot_policies(self):
- policies = {}
- try:
- self.__bootfile_lock.acquire()
-
- res = self.__loadcontent()
-
- pol = res.get( self.POLICY_ATTR )
- if pol:
- policies.update({ self.DEFAULT_TITLE : pol })
-
- finally:
- self.__bootfile_lock.release()
-
- return policies
-
- def add_boot_policy(self, index, binpolname):
- try:
- self.__bootfile_lock.acquire()
-
- res = self.__loadcontent()
- if binpolname.endswith(".bin"):
- binpolname = binpolname[0:-4]
- res[ self.POLICY_ATTR ] = binpolname
- self.__writecontent(res)
- finally:
- self.__bootfile_lock.release()
-
- return True
-
- def rm_policy_from_boottitle(self, index, unamelist):
- try:
- self.__bootfile_lock.acquire()
-
- res = self.__loadcontent()
- if self.POLICY_ATTR in res:
- del(res[self.POLICY_ATTR])
- self.__writecontent(res)
- finally:
- self.__bootfile_lock.release()
-
- return True
-
- def set_kernel_attval(self, index, att, val):
- try:
- self.__bootfile_lock.acquire()
-
- res = self.__loadcontent()
- res[att] = val
- self.__writecontent(res)
- finally:
- self.__bootfile_lock.release()
-
- return True
-
- def get_kernel_val(self, index, att):
- try:
- self.__bootfile_lock.acquire()
-
- res = self.__loadcontent()
- return res.get(att)
- finally:
- self.__bootfile_lock.release()
-
- def __loadcontent(self):
- res={}
- try:
- file = open(self.FILENAME)
- for line in file:
- tmp = line.split("=",1)
- if len(tmp) == 2:
- res[tmp[0]] = tmp[1].strip()
- file.close()
- except:
- pass
-
- return res
-
- def __writecontent(self, items):
- rc = True
- try:
- file = open(self.FILENAME,"w")
- if file:
- for key, value in items.items():
- file.write("%s=%s\n" % (str(key),str(value)))
- file.close()
- except:
- rc = False
-
- return rc
-
-
-__bootloader = Bootloader()
-
-def init():
- global __bootloader
- grub = Grub()
- if grub.probe() == True:
- __bootloader = grub
- else:
- late = LatePolicyLoader()
- if late.probe() == True:
- __bootloader = late
diff --git a/tools/python/xen/util/bugtool.py b/tools/python/xen/util/bugtool.py
deleted file mode 100644
index 2abcc86..0000000
--- a/tools/python/xen/util/bugtool.py
+++ /dev/null
@@ -1,234 +0,0 @@
-#!/usr/bin/env python
-
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-# Copyright (c) 2005, XenSource Ltd.
-
-
-import errno
-import getpass
-import httplib
-import re
-import os
-import os.path
-import StringIO
-import sys
-import tarfile
-import tempfile
-import time
-import urllib
-
-import xen.lowlevel.xc
-
-from xen.xend import encode
-
-
-SERVER = 'bugzilla.xen.org'
-SHOW_BUG_PATTERN = 'http://%s/bugzilla/show_bug.cgi?id=%%d' % SERVER
-ATTACH_PATTERN = \
- 'http://%s/bugzilla/attachment.cgi?bugid=%%d&action=enter' % SERVER
-
-TITLE_RE = re.compile(r'<title>(.*)</title>')
-
-FILES_TO_SEND = [ '/var/log/' + x for x in
- [ 'syslog', 'messages', 'debug',
- 'xen/xend-debug.log', 'xen/xenstored-trace.log',
- 'xen/xen-hotplug.log', 'xen/xend.log' ] +
- [ 'xen/xend.log.%d' % z for z in range(1,6) ] ]
-#FILES_TO_SEND = [ ]
-
-
-def main(argv = None):
- if argv is None:
- argv = sys.argv
-
- print '''
-This application will collate the Xen dmesg output, details of the hardware
-configuration of your machine, information about the build of Xen that you are
-using, plus, if you allow it, various logs.
-
-The information collated can either be posted to a Xen Bugzilla bug (this bug
-must already exist in the system, and you must be a registered user there), or
-it can be saved as a .tar.bz2 for sending or archiving.
-
-The collated logs may contain private information, and if you are at all
-worried about that, you should exit now, or you should explicitly exclude
-those logs from the archive.
-
-'''
-
- bugball = []
-
- xc = xen.lowlevel.xc.xc()
-
- def do(n, f):
- try:
- s = f()
- except Exception, exn:
- s = str(exn)
- bugball.append(string_iterator(n, s))
-
- do('xen-dmesg', lambda: xc.readconsolering())
- do('physinfo', lambda: prettyDict(xc.physinfo()))
- do('xeninfo', lambda: prettyDict(xc.xeninfo()))
-
- for filename in FILES_TO_SEND:
- if not os.path.exists(filename):
- continue
-
- if yes('Include %s? [Y/n] ' % filename):
- bugball.append(file(filename))
-
- maybeAttach(bugball)
-
- if (yes('''
-Do you wish to save these details as a tarball (.tar.bz2)? [Y/n] ''')):
- tar(bugball)
-
- return 0
-
-
-def maybeAttach(bugball):
- if not yes('''
-Do you wish to attach these details to a Bugzilla bug? [Y/n] '''):
- return
-
- bug = int(raw_input('Bug number? '))
-
- bug_title = getBugTitle(bug)
-
- if bug_title == 'Search by bug number' or bug_title == 'Invalid Bug ID':
- print >>sys.stderr, 'Bug %d does not exist!' % bug
- maybeAttach(bugball)
- elif yes('Are you sure that you want to attach to %s? [Y/n] ' %
- bug_title):
- attach(bug, bugball)
- else:
- maybeAttach(bugball)
-
-
-def attach(bug, bugball):
- username = raw_input('Bugzilla username: ')
- password = getpass.getpass('Bugzilla password: ')
-
- conn = httplib.HTTPConnection(SERVER)
- try:
- for f in bugball:
- send(bug, conn, f, f.name, username, password)
- finally:
- conn.close()
-
-
-def getBugTitle(bug):
- f = urllib.urlopen(SHOW_BUG_PATTERN % bug)
-
- try:
- for line in f:
- m = TITLE_RE.search(line)
- if m:
- return m.group(1)
- finally:
- f.close()
-
- raise ValueError("Could not find title of bug %d!" % bug)
-
-
-def send(bug, conn, fd, filename, username, password):
-
- print "Attaching %s to bug %d." % (filename, bug)
-
- headers, data = encode.encode_data(
- { 'bugid' : str(bug),
- 'action' : 'insert',
- 'data' : fd,
- 'description' : '%s from %s' % (filename, username),
- 'contenttypeselection' : 'text/plain',
- 'contenttypemethod' : 'list',
- 'ispatch' : '0',
- 'GoAheadAndLogIn' : '1',
- 'Bugzilla_login' : username,
- 'Bugzilla_password' : password,
- })
-
- conn.request('POST',ATTACH_PATTERN % bug, data, headers)
- response = conn.getresponse()
- try:
- body = response.read()
- m = TITLE_RE.search(body)
-
- if response.status != 200:
- print >>sys.stderr, (
- 'Attach failed: %s %s.' % (response.status, response.reason))
- elif not m or m.group(1) != 'Changes Submitted':
- print >>sys.stderr, (
- 'Attach failed: got a page titled %s.' % m.group(1))
- else:
- print "Attaching %s to bug %d succeeded." % (filename, bug)
- finally:
- response.close()
-
-
-def tar(bugball):
- filename = raw_input('Tarball destination filename? ')
-
- now = time.time()
-
- tf = tarfile.open(filename, 'w:bz2')
-
- try:
- for f in bugball:
- ti = tarfile.TarInfo(f.name.split('/')[-1])
- if hasattr(f, 'size'):
- ti.size = f.size()
- else:
- ti.size = os.stat(f.name).st_size
-
- ti.mtime = now
- ti.type = tarfile.REGTYPE
- ti.uid = 0
- ti.gid = 0
- ti.uname = 'root'
- ti.gname = 'root'
-
- f.seek(0) # If we've added this file to a bug, it will have been
- # read once already, so reset it.
- tf.addfile(ti, f)
- finally:
- tf.close()
-
- print 'Writing tarball %s successful.' % filename
-
-
-def prettyDict(d):
- format = '%%-%ds: %%s' % max(map(len, [k for k, _ in d.items()]))
- return '\n'.join([format % i for i in d.items()]) + '\n'
-
-
-class string_iterator(StringIO.StringIO):
- def __init__(self, name, val):
- StringIO.StringIO.__init__(self, val)
- self.name = name
-
- def size(self):
- return len(self.getvalue())
-
-
-def yes(prompt):
- yn = raw_input(prompt)
-
- return len(yn) == 0 or yn.lower()[0] == 'y'
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/tools/python/xen/util/diagnose.py b/tools/python/xen/util/diagnose.py
deleted file mode 100644
index e31f396..0000000
--- a/tools/python/xen/util/diagnose.py
+++ /dev/null
@@ -1,185 +0,0 @@
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-# Copyright (c) 2005-2006 XenSource Inc
-
-
-import re
-import socket
-import sys
-
-from xen.xend import sxp
-
-from xen.xend.XendClient import server
-from xen.xend.XendError import XendError
-from xen.xend.xenstore.xstransact import xstransact
-from xen.xend.server import DevConstants
-
-import xen.xend.XendProtocol
-
-
-domain = None
-domid = None
-deviceClass = None
-device = None
-frontendPath = None
-backendPath = None
-
-
-def diagnose(dom):
- global domain
- global domid
- global dompath
-
- try:
- domain = server.xend.domain(dom)
- state = sxp.child_value(domain, 'state')
- domid = int(sxp.child_value(domain, 'domid'))
- name = sxp.child_value(domain, 'name')
-
- print "Domain ID is %d." % domid
- print "Domain name is %s." % name
-
- if not state:
- raise XendError("Cannot find state")
-
- if state.find('c') != -1:
- print "Domain has crashed."
- except socket.error, exn:
- print "Cannot contact Xend."
-
- try:
- domid = int(dom)
- name = dom
- except ValueError:
- print \
-"Without Xend, you will have to specify the domain ID, not the domain name."
- sys.exit(1)
- except xen.xend.XendProtocol.XendError, exn:
- print exn
- sys.exit(1)
-
- dompath = '/local/domain/%d' % domid
- diagnose_console()
- diagnose_devices()
-
-
-def diagnose_console():
- port = xstransact.Read(dompath + '/console/port')
- ringref = xstransact.Read(dompath + '/console/ring-ref')
- tty = xstransact.Read(dompath + '/console/tty')
-
- if not port:
- print "Console port is missing; Xend has failed."
- if not ringref:
- print "Console ring-ref is missing; Xend has failed."
- if not tty:
- print "Console tty is missing; Xenconsoled has failed."
-
-
-def diagnose_devices():
- global deviceClass
- global device
- global frontendPath
- global backendPath
-
- device_path = dompath + '/device'
-
- device_classes = xstransact.List(device_path)
-
- print "Found %d device classes in use." % len(device_classes)
-
- for dc in device_classes:
- deviceClass = dc
- device_class_path = device_path + '/' + deviceClass
-
- devices = xstransact.List(device_class_path)
-
- print "Found %d %s devices." % (len(devices), deviceClass)
-
- for d in devices:
- device = d
-
- print "Found device %s, %s." % (deviceClass, device)
-
- frontendPath = device_class_path + '/' + device
- backendPath = xstransact.Read(frontendPath, 'backend')
-
- if not backendPath:
- print ("Cannot find backend path for device %s, %s." %
- (deviceClass, device))
- else:
- frontend_state = xstransact.Read(frontendPath, 'state')
- backend_state = xstransact.Read(backendPath, 'state')
-
- print "Backend is in state %s." % stateString(backend_state)
- print "Frontend is in state %s." % stateString(frontend_state)
-
- check_for_error(True)
- check_for_error(False)
-
- diagnose_hotplugging()
-
-
-def check_for_error(backend):
- if backend:
- path = backendPath.replace('backend/', 'error/backend/')
- else:
- path = frontendPath.replace('device/', 'error/device/')
-
- err = xstransact.Read(path, 'error')
-
- if err:
- print ("%s for device %s, %s shows error %s." %
- (backend and 'Backend' or 'Frontend', deviceClass, device,
- err))
-
-
-def diagnose_hotplugging():
- if deviceClass == 'vbd':
- phy = xstransact.Read(backendPath, 'physical-device')
-
- if phy:
- print ('Device %s, %s hotplugging has completed successfully, '
- 'and is connected to physical device %s.' %
- (deviceClass, device, phy))
- else:
- print ('Device %s, %s hotplugging failed.' %
- (deviceClass, device))
- elif deviceClass == 'vif':
- handle = xstransact.Read(backendPath, 'handle')
-
- if handle:
- print ('Device %s, %s hotplugging has completed successfully, '
- 'and is using handle %s.' %
- (deviceClass, device, handle))
- else:
- print ('Device %s, %s hotplugging failed.' %
- (deviceClass, device))
-
-
-def stateString(state):
- return state and DevConstants.xenbusState[int(state)] or '<None>'
-
-
-def main(argv = None):
- if argv is None:
- argv = sys.argv
-
- diagnose(argv[1])
-
- return 0
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/tools/python/xen/util/dictio.py b/tools/python/xen/util/dictio.py
deleted file mode 100644
index 4fcebdb..0000000
--- a/tools/python/xen/util/dictio.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#===========================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 International Business Machines Corp.
-# Author: Bryan D. Payne <bdpayne at us.ibm.com>
-#============================================================================
-
-
-def dict_read(dictname, filename):
- """Loads <filename> and returns the dictionary named <dictname> from
- the file.
- """
- dict = {}
-
- # read in the config file
- globs = {}
- locs = {}
- execfile(filename, globs, locs)
-
- for (k, v) in locs.items():
- if k == dictname:
- dict = v
- break
-
- return dict
-
-def dict_write(dict, dictname, filename):
- """Writes <dict> to <filename> using the name <dictname>. If the file
- contains any other data, it will be overwritten.
- """
- prefix = dictname + " = {\n"
- suffix = "}\n"
- fd = open(filename, "wb")
- fd.write(prefix)
- for key in dict:
- line = " '" + str(key) + "': " + str(dict[key]) + ",\n"
- fd.write(line)
- fd.write(suffix)
- fd.close()
diff --git a/tools/python/xen/util/fileuri.py b/tools/python/xen/util/fileuri.py
deleted file mode 100644
index b4a7923..0000000
--- a/tools/python/xen/util/fileuri.py
+++ /dev/null
@@ -1,156 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2009 flonatel GmbH & Co. KG
-#============================================================================
-
-import logging
-import os
-import base64
-import tempfile
-import stat
-from xen.xend.XendLogging import log
-from xen.util import mkdir
-
-#
-# This functions and classes can be used where a filename is expected -
-# especially in the xenapi.VM.create() for PV_kernel and PV_ramdisk.
-#
-# The functions have a backward compatibility mode, i.e. when there is
-# no appropriate scheme detected, the data is seens as a path to a
-# (local) file.
-#
-
-class scheme_error(Exception):
- def __init__(self, value):
- self.value = value
- def __str__(self):
- return repr(self.value)
-
-# Data scheme (as defined in RFC 2397):
-# data:application/octet-stream;base64,<base64 encoded data>
-# It looks that there is currently no general purpose implementation
-# available (in python) for this URL scheme - so the very basic is
-# done here.
-#
-# Limitations
-# o Only base64 is currently supported
-class scheme_data:
-
- def encode(data, mediatype = 'application/octet-stream',
- encoding = 'base64'):
- # XXX Limit this to base64 for current implementation
- if encoding!='base64':
- raise scheme_error("invalid encoding")
- return 'data:' + mediatype + ";" + encoding \
- + "," + base64.b64encode(data)
- encode = staticmethod(encode)
-
- # Private method: parse encoded data
- def parse(encoded_data):
- if not isinstance(encoded_data, str):
- raise scheme_error("encoded data has wrong type")
- if not encoded_data.startswith('data:'):
- raise scheme_error("'data:' scheme declaration missing")
- comma = encoded_data.find(',', 5)
- if comma == -1:
- raise scheme_error("data separator (comma) is missing")
- # Cut off the media type and encoding
- mtenc = encoded_data[5:comma]
- if len(mtenc)==0:
- raise scheme_error("encoding is empty")
- # XXX Limit to base64 encoding
- if not mtenc.endswith(';base64'):
- raise scheme_error("encoding is not base64")
- mediatype = mtenc[:-7]
- return (mediatype, 'base64', comma+1)
- parse = staticmethod(parse)
-
- # Stores the data in a local file and returns the filename
- # and a flag if this file in temporary only and must be deleted
- # after starting the VM.
- def decode(encoded_data):
- mkdir.parents("/var/run/xend/boot/", stat.S_IRWXU)
- mediatype, encoding, data_start = scheme_data.parse(encoded_data)
- fd, filename = tempfile.mkstemp(
- prefix="data_uri_file.", dir="/var/run/xend/boot")
- # Because of python 2.3 support, there is a need to nest these
- # (see http://www.python.org/doc/2.3/ref/try.html)
- try:
- try:
- os.write(fd, base64.b64decode(encoded_data[data_start:]))
- except TypeError, se:
- raise scheme_error("failed to decode as base64")
- finally:
- os.close(fd)
- return filename, True
- decode = staticmethod(decode)
-
- # Utility function which reads in the given (local) file and
- # creates a data scheme from this.
- def create_from_file(filename):
- try:
- f = open(filename, "r")
- d = f.read()
- f.close()
- return scheme_data.encode(d)
- except IOError:
- raise scheme_error("file does not exists")
- create_from_file = staticmethod(create_from_file)
-
-
-# File Scheme
-# This class supports absolut paths only.
-class scheme_file:
-
- def encode(filename):
- if len(filename) == 0:
- raise scheme_error("filename is empty")
- if filename[0] != '/':
- raise scheme_error("filename is not absolut")
- return 'file://' + filename
- encode = staticmethod(encode)
-
- def decode(encoded_data):
- if not encoded_data.startswith("file://"):
- raise scheme_error("no file:// scheme found")
- path = encoded_data[7:]
- if len(path)==0:
- raise scheme_error("path is empty")
- if path[0]!='/':
- raise scheme_error("path is not absolute")
- return path, False
- decode = staticmethod(decode)
-
-
-class scheme_set:
-
- def __init__(self):
- self.schemes = [scheme_data, scheme_file]
-
- # log_decode_exception flags whether a specific uri schema
- # decoding exception should be logged or not (default: False - do
- # not log).
- def decode(self, uri, log_decode_exception=False):
- for scheme in self.schemes:
- try:
- # If this passes, it is the correct scheme
- return scheme.decode(uri)
- except scheme_error, se:
- if log_decode_exception:
- log.debug("Decode throws an error: '%s'" % se)
- return uri, False
-
-schemes = scheme_set()
-
diff --git a/tools/python/xen/util/ip.py b/tools/python/xen/util/ip.py
deleted file mode 100644
index 9133e88..0000000
--- a/tools/python/xen/util/ip.py
+++ /dev/null
@@ -1,121 +0,0 @@
-import os
-import re
-import socket
-import struct
-import errno
-
-##### Networking-related functions
-
-def get_defaultroute():
- fd = os.popen('/sbin/ip route list 2>/dev/null')
- for line in fd.readlines():
- m = re.search('^default via ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) dev ([^ ]*)',
- line)
- if m:
- return [m.group(1), m.group(2)]
- return [None, None]
-
-def get_current_ipaddr(dev='defaultroute'):
- """Get the primary IP address for the given network interface.
-
- dev network interface (default: default route device)
-
- returns interface address as a string
- """
- if dev == 'defaultroute':
- dev = get_defaultroute()[1]
- if not dev:
- return
- fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
- for line in fd.readlines():
- m = re.search( '^\s+inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
- line )
- if m:
- return m.group(1)
- return None
-
-def get_current_ipmask(dev='defaultroute'):
- """Get the primary IP netmask for a network interface.
-
- dev network interface (default: default route device)
-
- returns interface netmask as a string
- """
- if dev == 'defaultroute':
- dev = get_defaultroute()[1]
- if not dev:
- return
- fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
- for line in fd.readlines():
- m = re.search( '^.+Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
- line )
- if m:
- return m.group(1)
- return None
-
-def get_current_ipgw(dev='defaultroute'):
- """Get the IP gateway for a network interface.
-
- dev network interface (default: default route device)
-
- returns gateway address as a string
- """
- if dev == 'defaultroute':
- return get_defaultroute()[0]
- if not dev:
- return
- fd = os.popen( '/sbin/route -n' )
- for line in fd.readlines():
- m = re.search( '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' +
- '\s+\S+\s+\S*G.*' + dev + '.*', line )
- if m:
- return m.group(1)
- return None
-
-def inet_aton(addr):
- """Convert an IP addr in IPv4 dot notation into an int.
-
- addr IP address as a string
-
- returns integer
- """
- b = socket.inet_aton(addr)
- return struct.unpack('!I', b)[0]
-
-def inet_ntoa(n):
- """Convert an int into an IP addr in IPv4 dot notation.
-
- n IP address
-
- returns string
- """
- b = struct.pack('!I', n)
- return socket.inet_ntoa(b)
-
-def add_offset_to_ip(addr, offset):
- """Add a numerical offset to an IP addr in IPv4 dot notation.
-
- addr IP address
- offset offset to add
-
- returns new address
- """
- n = inet_aton(addr)
- n += offset
- return inet_ntoa(n)
-
-def check_subnet( ip, network, netmask ):
- """Check if an IP address is in the subnet defined by
- a network address and mask'.
-
- ip IP adress
- network network address
- netmask network mask
-
- returns 1 if it is in the subnet, 0 if not
- """
- n_ip = inet_aton(ip)
- n_net = inet_aton(network)
- n_mask = inet_aton(netmask)
- return (n_ip & n_mask) == (n_net & n_mask)
-
diff --git a/tools/python/xen/util/mac.py b/tools/python/xen/util/mac.py
deleted file mode 100644
index 47dffd8..0000000
--- a/tools/python/xen/util/mac.py
+++ /dev/null
@@ -1,11 +0,0 @@
-
-from string import join, split
-
-def macToString(mac):
- return ':'.join(map(lambda x: "%02x" % x, mac))
-
-def macFromString(str):
- mac = [ int(x, 16) for x in str.split(':') ]
- if len(mac) != 6:
- raise ValueError("invalid mac: %s" % str)
- return mac
diff --git a/tools/python/xen/util/mkdir.py b/tools/python/xen/util/mkdir.py
deleted file mode 100644
index 121e498..0000000
--- a/tools/python/xen/util/mkdir.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (c) 2006 XenSource Inc.
-#============================================================================
-
-import errno
-import os
-import os.path
-import stat
-
-
-def parents(dir, perms, enforcePermissions = False):
- """
- Ensure that the given directory exists, creating it if necessary, but not
- complaining if it's already there.
-
- @param dir The directory name.
- @param perms One of the stat.S_ constants.
- @param enforcePermissions Enforce our ownership and the given permissions,
- even if the directory pre-existed with different ones.
- """
- # Catch the exception here, rather than checking for the directory's
- # existence first, to avoid races.
- try:
- os.makedirs(dir, perms)
- except OSError, exn:
- if exn.args[0] != errno.EEXIST or not os.path.isdir(dir):
- raise
- if enforcePermissions:
- os.chown(dir, os.geteuid(), os.getegid())
- os.chmod(dir, stat.S_IRWXU)
diff --git a/tools/python/xen/util/oshelp.py b/tools/python/xen/util/oshelp.py
deleted file mode 100644
index c2c0282..0000000
--- a/tools/python/xen/util/oshelp.py
+++ /dev/null
@@ -1,33 +0,0 @@
-import fcntl
-import os
-
-def close_fds(pass_fds=()):
- try:
- MAXFD = os.sysconf('SC_OPEN_MAX')
- except:
- MAXFD = 256
- for i in range(3, MAXFD):
- if i in pass_fds:
- continue
- try:
- os.close(i)
- except OSError:
- pass
-
-def fcntl_setfd_cloexec(file, bool):
- f = fcntl.fcntl(file, fcntl.F_GETFD)
- if bool: f |= fcntl.FD_CLOEXEC
- else: f &= ~fcntl.FD_CLOEXEC
- fcntl.fcntl(file, fcntl.F_SETFD, f)
-
-def waitstatus_description(st):
- if os.WIFEXITED(st):
- es = os.WEXITSTATUS(st)
- if es: return "exited with nonzero status %i" % es
- else: return "exited"
- elif os.WIFSIGNALED(st):
- s = "died due to signal %i" % os.WTERMSIG(st)
- if os.WCOREDUMP(st): s += " (core dumped)"
- return s
- else:
- return "failed with unexpected wait status %i" % st
diff --git a/tools/python/xen/util/pci.py b/tools/python/xen/util/pci.py
deleted file mode 100644
index adeca4b..0000000
--- a/tools/python/xen/util/pci.py
+++ /dev/null
@@ -1,1416 +0,0 @@
-#!/usr/bin/env python
-#
-# PCI Device Information Class
-# - Helps obtain information about which I/O resources a PCI device needs
-#
-# Author: Ryan Wilson <hap9 at epoch.ncsc.mil>
-
-import sys
-import os, os.path
-import errno
-import resource
-import re
-import types
-import struct
-import time
-import threading
-from xen.util import utils
-from xen.xend import uuid
-from xen.xend import sxp
-from xen.xend.XendConstants import AUTO_PHP_SLOT
-from xen.xend.XendSXPDev import dev_dict_to_sxp
-from xen.xend.XendLogging import log
-
-# for 2.3 compatibility
-try:
- set()
-except NameError:
- from sets import Set as set
-
-PROC_PCI_PATH = '/proc/bus/pci/devices'
-PROC_PCI_NUM_RESOURCES = 7
-
-SYSFS_PCI_DEVS_PATH = '/bus/pci/devices'
-SYSFS_PCI_DEV_RESOURCE_PATH = '/resource'
-SYSFS_PCI_DEV_CONFIG_PATH = '/config'
-SYSFS_PCI_DEV_IRQ_PATH = '/irq'
-SYSFS_PCI_DEV_DRIVER_DIR_PATH = '/driver'
-SYSFS_PCI_DEV_VENDOR_PATH = '/vendor'
-SYSFS_PCI_DEV_DEVICE_PATH = '/device'
-SYSFS_PCI_DEV_SUBVENDOR_PATH = '/subsystem_vendor'
-SYSFS_PCI_DEV_SUBDEVICE_PATH = '/subsystem_device'
-SYSFS_PCI_DEV_CLASS_PATH = '/class'
-SYSFS_PCIBACK_PATH = '/bus/pci/drivers/pciback/'
-SYSFS_PCISTUB_PATH = '/bus/pci/drivers/pci-stub/'
-
-LSPCI_CMD = 'lspci'
-
-PCI_DEV_REG_EXPRESS_STR = r"[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}."+ \
- r"[0-9a-fA-F]{1}"
-
-DEV_TYPE_PCIe_ENDPOINT = 0
-DEV_TYPE_PCIe_BRIDGE = 1
-DEV_TYPE_PCI_BRIDGE = 2
-DEV_TYPE_PCI = 3
-
-PCI_VENDOR_ID = 0x0
-PCI_STATUS = 0x6
-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
-
-PCI_CAP_ID_EXP = 0x10
-PCI_EXP_FLAGS = 0x2
-PCI_EXP_FLAGS_TYPE = 0x00f0
-PCI_EXP_TYPE_DOWNSTREAM = 0x6
-PCI_EXP_TYPE_PCI_BRIDGE = 0x7
-PCI_EXP_DEVCAP = 0x4
-PCI_EXP_DEVCAP_FLR = (0x1 << 28)
-PCI_EXP_DEVCTL = 0x8
-PCI_EXP_DEVCTL_FLR = (0x1 << 15)
-
-PCI_EXT_CAP_ID_ACS = 0x000d
-PCI_EXT_CAP_ACS_ENABLED = 0x1d # The bits V, R, C, U.
-PCI_EXT_ACS_CTRL = 0x06
-
-
-PCI_CAP_ID_PM = 0x01
-PCI_PM_CTRL = 4
-PCI_PM_CTRL_NO_SOFT_RESET = 0x0008
-PCI_PM_CTRL_STATE_MASK = 0x0003
-PCI_D3hot = 3
-PCI_D0hot = 0
-
-VENDOR_INTEL = 0x8086
-PCI_CAP_ID_VENDOR_SPECIFIC_CAP = 0x09
-PCI_CLASS_ID_USB = 0x0c03
-PCI_USB_FLRCTRL = 0x4
-
-PCI_DEVICE_ID = 0x02
-PCI_COMMAND = 0x04
-PCI_CLASS_ID_VGA = 0x0300
-
-PCI_DEVICE_ID_IGFX_GM45 = 0x2a42
-PCI_DEVICE_ID_IGFX_EAGLELAKE = 0x2e02
-PCI_DEVICE_ID_IGFX_Q45 = 0x2e12
-PCI_DEVICE_ID_IGFX_G45 = 0x2e22
-PCI_DEVICE_ID_IGFX_G41 = 0x2e32
-
-PCI_CAP_IGFX_CAP09_OFFSET = 0xa4
-PCI_CAP_IGFX_CAP13_OFFSET = 0xa4
-PCI_CAP_IGFX_GDRST = 0X0d
-PCI_CAP_IGFX_GDRST_OFFSET = 0xc0
-
-# The VF of Intel 82599 10GbE Controller
-# See http://download.intel.com/design/network/datashts/82599_datasheet.pdf
-# For 'VF PCIe Configuration Space', see its Table 9.7.
-DEVICE_ID_82599 = 0x10ed
-
-PCI_CAP_ID_AF = 0x13
-PCI_AF_CAPs = 0x3
-PCI_AF_CAPs_TP_FLR = 0x3
-PCI_AF_CTL = 0x4
-PCI_AF_CTL_FLR = 0x1
-
-PCI_BAR_0 = 0x10
-PCI_BAR_5 = 0x24
-PCI_BAR_SPACE = 0x01
-PCI_BAR_IO = 0x01
-PCI_BAR_IO_MASK = ~0x03
-PCI_BAR_MEM = 0x00
-PCI_BAR_MEM_MASK = ~0x0f
-PCI_STATUS_CAP_MASK = 0x10
-PCI_STATUS_OFFSET = 0x6
-PCI_CAP_OFFSET = 0x34
-MSIX_BIR_MASK = 0x7
-MSIX_SIZE_MASK = 0x7ff
-
-# Global variable to store information from lspci
-lspci_info = None
-lspci_info_lock = threading.RLock()
-
-#Calculate PAGE_SHIFT: number of bits to shift an address to get the page number
-PAGE_SIZE = resource.getpagesize()
-PAGE_SHIFT = 0
-t = PAGE_SIZE
-while not (t&1):
- t>>=1
- PAGE_SHIFT+=1
-
-PAGE_MASK=~(PAGE_SIZE - 1)
-# Definitions from Linux: include/linux/pci.h
-def PCI_DEVFN(slot, func):
- return ((((slot) & 0x1f) << 3) | ((func) & 0x07))
-def PCI_SLOT(devfn):
- return (devfn >> 3) & 0x1f
-def PCI_FUNC(devfn):
- return devfn & 0x7
-
-def PCI_BDF(domain, bus, slot, func):
- return (((domain & 0xffff) << 16) | ((bus & 0xff) << 8) |
- PCI_DEVFN(slot, func))
-
-def check_pci_opts(opts):
- def f((k, v)):
- if k not in ['msitranslate', 'power_mgmt'] or \
- not v.lower() in ['0', '1', 'yes', 'no']:
- raise PciDeviceParseError('Invalid pci option %s=%s: ' % (k, v))
-
- map(f, opts)
-
-def serialise_pci_opts(opts):
- return ','.join(map(lambda x: '='.join(x), opts))
-
-def split_pci_opts(opts):
- return map(lambda x: x.split('='),
- filter(lambda x: x != '', opts.split(',')))
-
-def append_default_pci_opts(opts, defopts):
- optsdict = dict(opts)
- return opts + filter(lambda (k, v): not optsdict.has_key(k), defopts)
-
-def pci_opts_list_to_sxp(list):
- return dev_dict_to_sxp({'opts': list})
-
-def pci_opts_list_from_sxp(dev):
- return map(lambda x: sxp.children(x)[0], sxp.children(dev, 'opts'))
-
-def pci_convert_dict_to_sxp(dev, state, sub_state = None):
- pci_sxp = ['pci', dev_dict_to_sxp(dev), ['state', state]]
- if sub_state != None:
- pci_sxp.append(['sub_state', sub_state])
- return pci_sxp
-
-def pci_convert_sxp_to_dict(dev_sxp):
- """Convert pci device sxp to dict
- @param dev_sxp: device configuration
- @type dev_sxp: SXP object (parsed config)
- @return: dev_config
- @rtype: dictionary
- """
- # Parsing the device SXP's. In most cases, the SXP looks
- # like this:
- #
- # [device, [vif, [mac, xx:xx:xx:xx:xx:xx], [ip 1.3.4.5]]]
- #
- # However, for PCI devices it looks like this:
- #
- # [device, [pci, [dev, [domain, 0], [bus, 0], [slot, 1], [func, 2]]]
- #
- # It seems the reasoning for this difference is because
- # pciif.py needs all the PCI device configurations at
- # the same time when creating the devices.
- #
- # To further complicate matters, Xen 2.0 configuration format
- # uses the following for pci device configuration:
- #
- # [device, [pci, [domain, 0], [bus, 0], [dev, 1], [func, 2]]]
-
- # For PCI device hotplug support, the SXP of PCI devices is
- # extendend like this:
- #
- # [device, [pci, [dev, [domain, 0], [bus, 0], [slot, 1], [func, 2],
- # [vdevfn, 0]],
- # [state, 'Initialising']]]
- #
- # 'vdevfn' shows the virtual hotplug slot number which the PCI device
- # is inserted in. This is only effective for HVM domains.
- #
- # state 'Initialising' indicates that the device is being attached,
- # while state 'Closing' indicates that the device is being detached.
- #
- # The Dict looks like this:
- #
- # { devs: [{domain: 0, bus: 0, slot: 1, func: 2, vdevfn: 0}],
- # states: ['Initialising'] }
-
- dev_config = {}
-
- pci_devs = []
- for pci_dev in sxp.children(dev_sxp, 'dev'):
- pci_dev_info = dict(pci_dev[1:])
- if 'opts' in pci_dev_info:
- pci_dev_info['opts'] = pci_opts_list_from_sxp(pci_dev)
- # If necessary, initialize uuid, key, and vdevfn for each pci device
- if not pci_dev_info.has_key('uuid'):
- pci_dev_info['uuid'] = uuid.createString()
- if not pci_dev_info.has_key('key'):
- pci_dev_info['key'] = "%02x:%02x.%x" % \
- (int(pci_dev_info['bus'], 16),
- int(pci_dev_info['slot'], 16),
- int(pci_dev_info['func'], 16))
- if not pci_dev_info.has_key('vdevfn'):
- pci_dev_info['vdevfn'] = "0x%02x" % AUTO_PHP_SLOT
- pci_devs.append(pci_dev_info)
- dev_config['devs'] = pci_devs
-
- pci_states = []
- for pci_state in sxp.children(dev_sxp, 'state'):
- try:
- pci_states.append(pci_state[1])
- except IndexError:
- raise XendError("Error reading state while parsing pci sxp")
- dev_config['states'] = pci_states
-
- return dev_config
-
-def parse_hex(val):
- try:
- if isinstance(val, types.StringTypes):
- return int(val, 16)
- else:
- return val
- except ValueError:
- return None
-
-AUTO_PHP_FUNC = 1
-MANUAL_PHP_FUNC = 2
-
-def parse_pci_pfunc_vfunc(func_str):
- list = func_str.split('=')
- l = len(list)
- if l == 0 or l > 2:
- raise PciDeviceParseError('Invalid function: ' + func_str)
- p = int(list[0], 16)
- if p < 0 or p > 7:
- raise PciDeviceParseError('Invalid physical function in: ' + func_str)
- if l == 1:
- # This defaults to linear mapping of physical to virtual functions
- return (p, p, AUTO_PHP_FUNC)
- else:
- v = int(list[1], 16)
- if v < 0 or v > 7:
- raise PciDeviceParseError('Invalid virtual function in: ' +
- func_str)
- return (p, v, MANUAL_PHP_FUNC)
-
-def pci_func_range(start, end):
- if end < start:
- x = pci_func_range(end, start)
- x.reverse()
- return x
- return range(start, end + 1)
-
-def pci_pfunc_vfunc_range(orig, a, b):
- phys = pci_func_range(a[0], b[0])
- virt = pci_func_range(a[1], b[1])
- if len(phys) != len(virt):
- raise PciDeviceParseError('Invalid range in: ' + orig)
- return map(lambda x: x + (MANUAL_PHP_FUNC,), zip(phys, virt))
-
-def pci_func_list_map_fn(key, func_str):
- if func_str == "*":
- return map(lambda x: parse_pci_pfunc_vfunc(x['func']),
- filter(lambda x:
- pci_dict_cmp(x, key, ['domain', 'bus', 'slot']),
- get_all_pci_dict()))
- l = map(parse_pci_pfunc_vfunc, func_str.split("-"))
- if len(l) == 1:
- return l
- if len(l) == 2:
- return pci_pfunc_vfunc_range(func_str, l[0], l[1])
- return []
-
-def pci_func_list_process(pci_dev_str, template, func_str):
- l = reduce(lambda x, y: x + y,
- (map(lambda x: pci_func_list_map_fn(template, x),
- func_str.split(","))))
-
- phys = map(lambda x: x[0], l)
- virt = map(lambda x: x[1], l)
- if len(phys) != len(set(phys)) or len(virt) != len(set(virt)):
- raise PciDeviceParseError("Duplicate functions: %s" % pci_dev_str)
-
- return l
-
-def parse_pci_name_extended(pci_dev_str):
- 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]([,-=][0-7])*))" +
- r"(@(?P<vdevfn>[01]?[0-9a-fA-F]))?" +
- r"(,(?P<opts>.*))?$", pci_dev_str)
-
- if pci_match == None:
- raise PciDeviceParseError("Failed to parse pci device: %s" %
- pci_dev_str)
-
- pci_dev_info = pci_match.groupdict('')
-
- template = {}
- if pci_dev_info['domain'] != '':
- domain = int(pci_dev_info['domain'], 16)
- else:
- domain = 0
- template['domain'] = "0x%04x" % domain
- template['bus'] = "0x%02x" % int(pci_dev_info['bus'], 16)
- template['slot'] = "0x%02x" % int(pci_dev_info['slot'], 16)
- template['key'] = pci_dev_str.split(',')[0]
- if pci_dev_info['opts'] != '':
- template['opts'] = split_pci_opts(pci_dev_info['opts'])
- check_pci_opts(template['opts'])
-
- # This is where virtual function assignment takes place
- func_list = pci_func_list_process(pci_dev_str, template,
- pci_dev_info['func'])
- if len(func_list) == 0:
- return []
-
- # Set the virtual function of the numerically lowest physical function
- # to zero if it has not been manually set
- if not filter(lambda x: x[1] == 0, func_list):
- auto = filter(lambda x: x[2] == AUTO_PHP_FUNC, func_list)
- manual = filter(lambda x: x[2] == MANUAL_PHP_FUNC, func_list)
- if not auto:
- raise PciDeviceParseError('Virtual device does not include '
- 'virtual function 0: ' + pci_dev_str)
- auto.sort(lambda x,y: cmp(x[1], y[1]))
- auto[0] = (auto[0][0], 0, AUTO_PHP_FUNC)
- func_list = auto + manual
-
- # For pci attachment and detachment is it important that virtual
- # function 0 is done last. This is because is virtual function 0 that
- # is used to singnal changes to the guest using ACPI
- func_list.sort(lambda x,y: cmp(PCI_FUNC(y[1]), PCI_FUNC(x[1])))
-
- # Virtual slot assignment takes place here if specified in the bdf,
- # else it is done inside qemu-xen, as it knows which slots are free
- pci = []
- for (pfunc, vfunc, auto) in func_list:
- pci_dev = template.copy()
- pci_dev['func'] = "0x%x" % pfunc
-
- if pci_dev_info['vdevfn'] == '':
- vdevfn = AUTO_PHP_SLOT | vfunc
- else:
- vdevfn = PCI_DEVFN(int(pci_dev_info['vdevfn'], 16), vfunc)
- pci_dev['vdevfn'] = "0x%02x" % vdevfn
-
- pci.append(pci_dev)
-
- return pci
-
-def parse_pci_name(pci_name_string):
- dev = parse_pci_name_extended(pci_name_string)
-
- if len(dev) != 1:
- raise PciDeviceParseError(("Failed to parse pci device: %s: "
- "multiple functions specified prohibited") %
- pci_name_string)
-
- pci = dev[0]
- if not int(pci['vdevfn'], 16) & AUTO_PHP_SLOT:
- raise PciDeviceParseError(("Failed to parse pci device: %s: " +
- "vdevfn provided where prohibited: 0x%02x") %
- (pci_name_string,
- PCI_SLOT(int(pci['vdevfn'], 16))))
- if 'opts' in pci:
- raise PciDeviceParseError(("Failed to parse pci device: %s: " +
- "options provided where prohibited: %s") %
- (pci_name_string, pci['opts']))
-
- return pci
-
-def __pci_dict_to_fmt_str(fmt, dev):
- return fmt % (int(dev['domain'], 16), int(dev['bus'], 16),
- int(dev['slot'], 16), int(dev['func'], 16))
-
-def pci_dict_to_bdf_str(dev):
- return __pci_dict_to_fmt_str('%04x:%02x:%02x.%01x', dev)
-
-def pci_dict_to_xc_str(dev):
- return __pci_dict_to_fmt_str('0x%x, 0x%x, 0x%x, 0x%x', dev)
-
-def pci_dict_cmp(a, b, keys=['domain', 'bus', 'slot', 'func']):
- return reduce(lambda x, y: x and y,
- map(lambda k: int(a[k], 16) == int(b[k], 16), keys))
-
-def extract_the_exact_pci_names(pci_names):
- result = []
-
- if isinstance(pci_names, types.StringTypes):
- pci_names = pci_names.split()
- elif isinstance(pci_names, types.ListType):
- pci_names = re.findall(PCI_DEV_REG_EXPRESS_STR, '%s' % pci_names)
- else:
- raise PciDeviceParseError('Invalid argument: %s' % pci_names)
-
- for pci in pci_names:
- # The length of DDDD:bb:dd.f is 12.
- if len(pci) != 12:
- continue
- if re.match(PCI_DEV_REG_EXPRESS_STR, pci) is None:
- continue
- result = result + [pci]
- return result
-
-def find_sysfs_mnt():
- try:
- return utils.find_sysfs_mount()
- except IOError, (errno, strerr):
- raise PciDeviceParseError(('Failed to locate sysfs mount: %s: %s (%d)'%
- (PROC_PCI_PATH, strerr, errno)))
- return None
-
-def get_all_pci_names():
- if not sys.platform.startswith('linux'): return []
- sysfs_mnt = find_sysfs_mnt()
- if sysfs_mnt is None:
- return None
- pci_names = os.popen('ls ' + sysfs_mnt + SYSFS_PCI_DEVS_PATH).read().split()
- return pci_names
-
-def get_all_pci_dict():
- return map(parse_pci_name, get_all_pci_names())
-
-def get_all_pci_devices():
- return map(PciDevice, get_all_pci_dict())
-
-def _create_lspci_info():
- """Execute 'lspci' command and parse the result.
- If the command does not exist, lspci_info will be kept blank ({}).
-
- Expects to be protected by lspci_info_lock.
- """
- global lspci_info
-
- lspci_info = {}
-
- for paragraph in os.popen(LSPCI_CMD + ' -vmm').read().split('\n\n'):
- device_name = None
- device_info = {}
- # FIXME: workaround for pciutils without the -mm option.
- # see: git://git.kernel.org/pub/scm/utils/pciutils/pciutils.git
- # commit: 3fd6b4d2e2fda814047664ffc67448ac782a8089
- first_device = True
- for line in paragraph.split('\n'):
- try:
- (opt, value) = line.split(':\t')
- if opt == 'Slot' or (opt == 'Device' and first_device):
- device_name = pci_dict_to_bdf_str(parse_pci_name(value))
- first_device = False
- else:
- device_info[opt] = value
- except:
- pass
- if device_name is not None:
- lspci_info[device_name] = device_info
-
-def create_lspci_info():
- global lspci_info_lock
- lspci_info_lock.acquire()
- try:
- _create_lspci_info()
- finally:
- lspci_info_lock.release()
-
-def save_pci_conf_space(devs_string):
- pci_list = []
- cfg_list = []
- sysfs_mnt = find_sysfs_mnt()
- for pci_str in devs_string:
- pci_path = sysfs_mnt + SYSFS_PCI_DEVS_PATH + '/' + pci_str + \
- SYSFS_PCI_DEV_CONFIG_PATH
- fd = os.open(pci_path, os.O_RDONLY)
- size = os.fstat(fd).st_size
- configs = []
- for i in range(0, size, 4):
- configs = configs + [os.read(fd,4)]
- os.close(fd)
- pci_list = pci_list + [pci_path]
- cfg_list = cfg_list + [configs]
- return (pci_list, cfg_list)
-
-def restore_pci_conf_space(pci_cfg_list):
- time.sleep(1.0)
- pci_list = pci_cfg_list[0]
- cfg_list = pci_cfg_list[1]
- for i in range(0, len(pci_list)):
- pci_path = pci_list[i]
- configs = cfg_list[i]
- fd = os.open(pci_path, os.O_WRONLY)
- for dw in configs:
- os.write(fd, dw)
- os.close(fd)
-
-def find_all_assignable_devices():
- ''' devices owned by pcibak or pci-stub can be directly assigned to
- guest with IOMMU (VT-d or AMD IOMMU), find all these devices.
- '''
- sysfs_mnt = find_sysfs_mnt()
- pciback_path = sysfs_mnt + SYSFS_PCIBACK_PATH
- pcistub_path = sysfs_mnt + SYSFS_PCISTUB_PATH
- pci_names1 = os.popen('ls %s 2>/dev/null' % pciback_path).read()
- pci_names2 = os.popen('ls %s 2>/dev/null' % pcistub_path).read()
- if len(pci_names1) + len(pci_names2) == 0 :
- return None
- pci_list = extract_the_exact_pci_names(pci_names1)
- pci_list = pci_list + extract_the_exact_pci_names(pci_names2)
- dev_list = []
- for pci in pci_list:
- dev = PciDevice(parse_pci_name(pci))
- dev_list = dev_list + [dev]
- return dev_list
-
-def transform_list(target, src):
- ''' src: its element is pci string (Format: xxxx:xx:xx.x).
- target: its element is pci string, or a list of pci string.
-
- If all the elements in src are in target, we remove them from target
- and add src into target; otherwise, we remove from target all the
- elements that also appear in src.
- '''
- result = []
- target_contains_src = True
- for e in src:
- if not e in target:
- target_contains_src = False
- break
-
- if target_contains_src:
- result = result + [src]
- for e in target:
- if not e in src:
- result = result + [e]
- return result
-
-def check_FLR_capability(dev_list):
- if len(dev_list) == 0:
- return []
-
- pci_list = []
- pci_dev_dict = {}
- for dev in dev_list:
- pci_list = pci_list + [dev.name]
- pci_dev_dict[dev.name] = dev
-
- while True:
- need_transform = False
- 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
- elif dev.dev_type == DEV_TYPE_PCI and not dev.pci_af_flr:
- coassigned_pci_list = dev.find_coassigned_pci_devices(True)
- del coassigned_pci_list[0]
- need_transform = True
-
- if need_transform:
- pci_list = transform_list(pci_list, coassigned_pci_list)
- if not need_transform:
- break
-
- if len(pci_list) == 0:
- return []
-
- for i in range(0, len(pci_list)):
- if isinstance(pci_list[i], types.StringTypes):
- pci_list[i] = [pci_list[i]]
-
- # Now every element in pci_list is a list of pci string.
-
- result = []
- for pci_names in pci_list:
- devs = []
- for pci in pci_names:
- devs = devs + [pci_dev_dict[pci]]
- result = result + [devs]
- return result
-
-def check_mmio_bar(devs_list):
- result = []
-
- for dev_list in devs_list:
- non_aligned_bar_found = False
- for dev in dev_list:
- if dev.has_non_page_aligned_bar:
- non_aligned_bar_found = True
- break
- if not non_aligned_bar_found:
- result = result + [dev_list]
-
- return result
-
-class PciDeviceParseError(Exception):
- def __init__(self,msg):
- self.message = msg
- def __str__(self):
- return self.message
-
-class PciDeviceAssignmentError(Exception):
- def __init__(self,msg):
- self.message = msg
- def __str__(self):
- return 'pci: improper device assignment specified: ' + \
- self.message
-
-class PciDeviceVslotMissing(Exception):
- def __init__(self,msg):
- self.message = msg
- def __str__(self):
- return 'pci: no vslot: ' + self.message
-
-class PciDevice:
- def __init__(self, dev):
- self.domain = int(dev['domain'], 16)
- self.bus = int(dev['bus'], 16)
- self.slot = int(dev['slot'], 16)
- self.func = int(dev['func'], 16)
- self.name = pci_dict_to_bdf_str(dev)
- self.cfg_space_path = find_sysfs_mnt()+SYSFS_PCI_DEVS_PATH+'/'+ \
- self.name + SYSFS_PCI_DEV_CONFIG_PATH
- self.irq = 0
- self.iomem = []
- self.ioports = []
- self.driver = None
- self.vendor = None
- self.device = None
- self.subvendor = None
- self.subdevice = None
- self.msix = 0
- self.msix_iomem = []
- self.revision = 0
- self.classcode = None
- self.vendorname = ""
- self.devicename = ""
- self.classname = ""
- self.subvendorname = ""
- self.subdevicename = ""
- self.dev_type = None
- self.is_downstream_port = False
- self.acs_enabled = False
- self.has_non_page_aligned_bar = False
- self.pcie_flr = False
- self.pci_af_flr = False
- self.detect_dev_info()
- if (self.dev_type == DEV_TYPE_PCI_BRIDGE) or \
- (self.dev_type == DEV_TYPE_PCIe_BRIDGE):
- return
- self.get_info_from_sysfs()
- self.get_info_from_lspci()
-
- def find_parent(self):
- # i.e., /sys/bus/pci/devices/0000:00:19.0 or
- # /sys/bus/pci/devices/0000:03:04.0
- path = find_sysfs_mnt()+SYSFS_PCI_DEVS_PATH+'/'+ self.name
- # i.e., ../../../devices/pci0000:00/0000:00:19.0
- # ../../../devices/pci0000:00/0000:00:02.0/0000:01:00.2/0000:03:04.0
- try:
- target = os.readlink(path)
- lst = target.split('/')
- parent = lst[len(lst)-2]
- if parent[0:3] == 'pci':
- # We have reached the upmost one.
- return None
- return parse_pci_name(parent)
- except OSError, (errno, strerr):
- raise PciDeviceParseError('Can not locate the parent of %s',
- self.name)
-
- def find_the_uppermost_pci_bridge(self):
- # Find the uppermost PCI/PCI-X bridge
- dev = self.find_parent()
- if dev is None:
- return None
- dev = dev_parent = PciDevice(dev)
- while dev_parent.dev_type != DEV_TYPE_PCIe_BRIDGE:
- parent = dev_parent.find_parent()
- if parent is None:
- break
- dev = dev_parent
- dev_parent = PciDevice(parent)
- return dev
-
- def find_all_devices_behind_the_bridge(self, ignore_bridge):
- sysfs_mnt = find_sysfs_mnt()
- self_path = sysfs_mnt + SYSFS_PCI_DEVS_PATH + '/' + self.name
- pci_names = os.popen('ls ' + self_path).read()
- dev_list = extract_the_exact_pci_names(pci_names)
-
- list = [self.name]
- for pci_str in dev_list:
- dev = PciDevice(parse_pci_name(pci_str))
- if dev.dev_type == DEV_TYPE_PCI_BRIDGE or \
- dev.dev_type == DEV_TYPE_PCIe_BRIDGE:
- sub_list_including_self = \
- dev.find_all_devices_behind_the_bridge(ignore_bridge)
- if ignore_bridge:
- del sub_list_including_self[0]
- list = list + [sub_list_including_self]
- else:
- list = list + [dev.name]
- return list
-
- def find_coassigned_pci_devices(self, ignore_bridge = True):
- ''' Here'self' is a PCI device, we need find the uppermost PCI/PCI-X
- bridge, and all devices behind it must be co-assigned to the same
- guest.
-
- Parameter:
- [ignore_bridge]: if set, the returned result doesn't include
- any bridge behind the uppermost PCI/PCI-X bridge.
-
- Note: The first element of the return value is the uppermost
- PCI/PCI-X bridge. If the caller doesn't need the first
- element, the caller itself can remove it explicitly.
- '''
- dev = self.find_the_uppermost_pci_bridge()
-
- # The 'self' device is on bus0.
- if dev is None:
- return [self.name]
-
- dev_list = dev.find_all_devices_behind_the_bridge(ignore_bridge)
- dev_list = extract_the_exact_pci_names(dev_list)
- return dev_list
-
- def do_secondary_bus_reset(self, target_bus, devs):
- # Save the config spaces of all the devices behind the bus.
- (pci_list, cfg_list) = save_pci_conf_space(devs)
-
- #Do the Secondary Bus Reset
- sysfs_mnt = find_sysfs_mnt()
- parent_path = sysfs_mnt + SYSFS_PCI_DEVS_PATH + '/' + \
- target_bus + SYSFS_PCI_DEV_CONFIG_PATH
- fd = os.open(parent_path, os.O_RDWR)
- os.lseek(fd, PCI_CB_BRIDGE_CONTROL, 0)
- br_cntl = (struct.unpack('H', os.read(fd, 2)))[0]
- # Assert Secondary Bus Reset
- os.lseek(fd, PCI_CB_BRIDGE_CONTROL, 0)
- br_cntl |= PCI_BRIDGE_CTL_BUS_RESET
- os.write(fd, struct.pack('H', br_cntl))
- time.sleep(0.100)
- # De-assert Secondary Bus Reset
- os.lseek(fd, PCI_CB_BRIDGE_CONTROL, 0)
- br_cntl &= ~PCI_BRIDGE_CTL_BUS_RESET
- os.write(fd, struct.pack('H', br_cntl))
- time.sleep(0.100)
- os.close(fd)
-
- # 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 False
-
- # No_Soft_Reset - When set 1, this bit indicates that
- # devices transitioning from D3hot to D0 because of
- # PowerState commands do not perform an internal reset.
- pm_ctl = self.pci_conf_read32(pos + PCI_PM_CTRL)
- if (pm_ctl & PCI_PM_CTRL_NO_SOFT_RESET) == PCI_PM_CTRL_NO_SOFT_RESET:
- return False
-
- (pci_list, cfg_list) = save_pci_conf_space([self.name])
-
- # Enter D3hot
- 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
- pm_ctl &= ~PCI_PM_CTRL_STATE_MASK
- pm_ctl |= PCI_D0hot
- self.pci_conf_write32(pos + PCI_PM_CTRL, pm_ctl)
- time.sleep(0.010)
-
- restore_pci_conf_space((pci_list, cfg_list))
- return True
-
- def do_vendor_specific_FLR_method(self):
- pos = self.find_cap_offset(PCI_CAP_ID_VENDOR_SPECIFIC_CAP)
- if pos == 0:
- return
-
- vendor_id = self.pci_conf_read16(PCI_VENDOR_ID)
- if vendor_id != VENDOR_INTEL:
- return
-
- class_id = self.pci_conf_read16(PCI_CLASS_DEVICE)
- if class_id != PCI_CLASS_ID_USB:
- return
-
- (pci_list, cfg_list) = save_pci_conf_space([self.name])
-
- self.pci_conf_write8(pos + PCI_USB_FLRCTRL, 1)
- time.sleep(0.100)
-
- restore_pci_conf_space((pci_list, cfg_list))
-
- def do_FLR_for_integrated_device(self):
- if not self.do_Dstate_transition():
- self.do_vendor_specific_FLR_method()
-
- def do_AF_FLR(self, af_pos):
- ''' use PCI Advanced Capability to do FLR
- '''
- (pci_list, cfg_list) = save_pci_conf_space([self.name])
- self.pci_conf_write8(af_pos + PCI_AF_CTL, PCI_AF_CTL_FLR)
- time.sleep(0.100)
- restore_pci_conf_space((pci_list, cfg_list))
-
- def do_FLR_for_intel_4Series_iGFX(self):
- af_pos = PCI_CAP_IGFX_CAP13_OFFSET
- self.do_AF_FLR(af_pos)
- log.debug("Intel 4 Series iGFX FLR done")
-
- def do_FLR_for_GM45_iGFX(self):
- reg32 = self.pci_conf_read32(PCI_CAP_IGFX_CAP09_OFFSET)
- if ((reg32 >> 16) & 0x000000FF) != 0x06 or \
- ((reg32 >> 24) & 0x000000F0) != 0x20:
- return
-
- self.pci_conf_write8(PCI_CAP_IGFX_GDRST_OFFSET, PCI_CAP_IGFX_GDRST)
- for i in range(0, 10):
- time.sleep(0.100)
- reg8 = self.pci_conf_read8(PCI_CAP_IGFX_GDRST_OFFSET)
- if (reg8 & 0x01) == 0:
- break
- if i == 10:
- log.debug("Intel iGFX FLR fail on GM45")
- return
-
- # This specific reset will hang if the command register does not have
- # memory space access enabled
- cmd = self.pci_conf_read16(PCI_COMMAND)
- self.pci_conf_write16(PCI_COMMAND, (cmd | 0x02))
- af_pos = PCI_CAP_IGFX_CAP09_OFFSET
- self.do_AF_FLR(af_pos)
- self.pci_conf_write16(PCI_COMMAND, cmd)
-
- log.debug("Intel iGFX FLR on GM45 done")
-
- def find_all_the_multi_functions(self):
- sysfs_mnt = find_sysfs_mnt()
- parentdict = self.find_parent()
- if parentdict is None :
- return [ self.name ]
- parent = pci_dict_to_bdf_str(parentdict)
- pci_names = os.popen('ls ' + sysfs_mnt + SYSFS_PCI_DEVS_PATH + '/' + \
- parent + '/').read()
- funcs = extract_the_exact_pci_names(pci_names)
- return funcs
-
- def find_coassigned_devices(self):
- if self.dev_type == DEV_TYPE_PCIe_ENDPOINT and not self.pcie_flr:
- return self.find_all_the_multi_functions()
- elif self.dev_type == DEV_TYPE_PCI and not self.pci_af_flr:
- coassigned_pci_list = self.find_coassigned_pci_devices(True)
- if len(coassigned_pci_list) > 1:
- del coassigned_pci_list[0]
- return coassigned_pci_list
- else:
- return [self.name]
-
- def find_cap_offset(self, cap):
- path = find_sysfs_mnt()+SYSFS_PCI_DEVS_PATH+'/'+ \
- self.name+SYSFS_PCI_DEV_CONFIG_PATH
-
- pos = PCI_CAPABILITY_LIST
-
- try:
- fd = None
- fd = os.open(path, os.O_RDONLY)
- os.lseek(fd, PCI_STATUS, 0)
- status = struct.unpack('H', os.read(fd, 2))[0]
- if (status & 0x10) == 0:
- os.close(fd)
- # The device doesn't support PCI_STATUS_CAP_LIST
- return 0
-
- max_cap = 48
- while max_cap > 0:
- os.lseek(fd, pos, 0)
- pos = ord(os.read(fd, 1))
- if pos < 0x40:
- pos = 0
- break;
- os.lseek(fd, pos + 0, 0)
- id = ord(os.read(fd, 1))
- if id == 0xff:
- pos = 0
- break;
-
- # Found the capability
- if id == cap:
- break;
-
- # Test the next one
- pos = pos + 1
- max_cap = max_cap - 1;
-
- os.close(fd)
- except OSError, (errno, strerr):
- if fd is not None:
- os.close(fd)
- raise PciDeviceParseError(('Error when accessing sysfs: %s (%d)' %
- (strerr, errno)))
- return pos
-
- def find_ext_cap(self, cap):
- path = find_sysfs_mnt()+SYSFS_PCI_DEVS_PATH+'/'+ \
- self.name+SYSFS_PCI_DEV_CONFIG_PATH
-
- ttl = 480; # 3840 bytes, minimum 8 bytes per capability
- pos = 0x100
-
- fd = None
- try:
- fd = os.open(path, os.O_RDONLY)
- os.lseek(fd, pos, 0)
- h = os.read(fd, 4)
- if len(h) == 0: # MMCONF is not enabled?
- os.close(fd)
- return 0
- header = struct.unpack('I', h)[0]
- if header == 0 or header == -1:
- os.close(fd)
- return 0
-
- while ttl > 0:
- if (header & 0x0000ffff) == cap:
- os.close(fd)
- return pos
- pos = (header >> 20) & 0xffc
- if pos < 0x100:
- break
- os.lseek(fd, pos, 0)
- header = struct.unpack('I', os.read(fd, 4))[0]
- ttl = ttl - 1
- os.close(fd)
- except OSError, (errno, strerr):
- if fd is not None:
- os.close(fd)
- raise PciDeviceParseError(('Error when accessing sysfs: %s (%d)' %
- (strerr, errno)))
- return 0
-
- def is_behind_switch_lacking_acs(self):
- # If there is intermediate PCIe switch, which doesn't support ACS or
- # doesn't enable ACS, between Root Complex and the function, we return
- # True, meaning the function is not allowed to be assigned to guest due
- # to potential security issue.
- parent = self.find_parent()
- while parent is not None:
- dev_parent = PciDevice(parent)
- if dev_parent.is_downstream_port and not dev_parent.acs_enabled:
- return True
- parent = dev_parent.find_parent()
- return False
-
- def pci_conf_read8(self, pos):
- fd = os.open(self.cfg_space_path, os.O_RDONLY)
- os.lseek(fd, pos, 0)
- str = os.read(fd, 1)
- os.close(fd)
- val = struct.unpack('B', str)[0]
- return val
-
- def pci_conf_read16(self, pos):
- fd = os.open(self.cfg_space_path, os.O_RDONLY)
- os.lseek(fd, pos, 0)
- str = os.read(fd, 2)
- os.close(fd)
- val = struct.unpack('H', str)[0]
- return val
-
- def pci_conf_read32(self, pos):
- fd = os.open(self.cfg_space_path, os.O_RDONLY)
- os.lseek(fd, pos, 0)
- str = os.read(fd, 4)
- os.close(fd)
- val = struct.unpack('I', str)[0]
- return val
-
- def pci_conf_write8(self, pos, val):
- str = struct.pack('B', val)
- fd = os.open(self.cfg_space_path, os.O_WRONLY)
- os.lseek(fd, pos, 0)
- os.write(fd, str)
- os.close(fd)
-
- def pci_conf_write16(self, pos, val):
- str = struct.pack('H', val)
- fd = os.open(self.cfg_space_path, os.O_WRONLY)
- os.lseek(fd, pos, 0)
- os.write(fd, str)
- os.close(fd)
-
- def pci_conf_write32(self, pos, val):
- str = struct.pack('I', val)
- fd = os.open(self.cfg_space_path, os.O_WRONLY)
- os.lseek(fd, pos, 0)
- os.write(fd, str)
- os.close(fd)
-
- def detect_dev_info(self):
- try:
- class_dev = self.pci_conf_read16(PCI_CLASS_DEVICE)
- except OSError, (err, strerr):
- if err == errno.ENOENT:
- strerr = "the device doesn't exist?"
- raise PciDeviceParseError('%s: %s' %\
- (self.name, strerr))
- pos = self.find_cap_offset(PCI_CAP_ID_EXP)
- if class_dev == PCI_CLASS_BRIDGE_PCI:
- if pos == 0:
- self.dev_type = DEV_TYPE_PCI_BRIDGE
- else:
- creg = self.pci_conf_read16(pos + PCI_EXP_FLAGS)
- type = (creg & PCI_EXP_FLAGS_TYPE) >> 4
- if type == PCI_EXP_TYPE_PCI_BRIDGE:
- self.dev_type = DEV_TYPE_PCI_BRIDGE
- else:
- self.dev_type = DEV_TYPE_PCIe_BRIDGE
- if type == PCI_EXP_TYPE_DOWNSTREAM:
- self.is_downstream_port = True
- pos = self.find_ext_cap(PCI_EXT_CAP_ID_ACS)
- if pos != 0:
- ctrl = self.pci_conf_read16(pos + PCI_EXT_ACS_CTRL)
- if (ctrl & PCI_EXT_CAP_ACS_ENABLED) == \
- (PCI_EXT_CAP_ACS_ENABLED):
- self.acs_enabled = True
- else:
- if pos != 0:
- self.dev_type = DEV_TYPE_PCIe_ENDPOINT
- else:
- self.dev_type = DEV_TYPE_PCI
-
- # Force 0000:00:00.0 to be DEV_TYPE_PCIe_BRIDGE
- if self.name == '0000:00:00.0':
- self.dev_type = DEV_TYPE_PCIe_BRIDGE
-
- if (self.dev_type == DEV_TYPE_PCI_BRIDGE) or \
- (self.dev_type == DEV_TYPE_PCIe_BRIDGE):
- return
-
- # Try to findthe PCIe FLR capability
- if self.dev_type == DEV_TYPE_PCIe_ENDPOINT:
- dev_cap = self.pci_conf_read32(pos + PCI_EXP_DEVCAP)
- if dev_cap & PCI_EXP_DEVCAP_FLR:
- self.pcie_flr = True
- else:
- # Quirk for the VF of Intel 82599 10GbE Controller.
- # We know it does have PCIe FLR capability even if it doesn't
- # report that (dev_cap.PCI_EXP_DEVCAP_FLR is 0).
- # See the 82599 datasheet.
- dev_path = find_sysfs_mnt()+SYSFS_PCI_DEVS_PATH+'/'+self.name
- vendor_id = parse_hex(os.popen('cat %s/vendor' % dev_path).read())
- device_id = parse_hex(os.popen('cat %s/device' % dev_path).read())
- if (vendor_id == VENDOR_INTEL) and \
- (device_id == DEVICE_ID_82599):
- self.pcie_flr = True
- elif self.dev_type == DEV_TYPE_PCI:
- # Try to find the "PCI Advanced Capabilities"
- pos = self.find_cap_offset(PCI_CAP_ID_AF)
- if pos != 0:
- af_cap = self.pci_conf_read8(pos + PCI_AF_CAPs)
- if (af_cap & PCI_AF_CAPs_TP_FLR) == PCI_AF_CAPs_TP_FLR:
- self.pci_af_flr = True
-
- bar_addr = PCI_BAR_0
- while bar_addr <= PCI_BAR_5:
- bar = self.pci_conf_read32(bar_addr)
- if (bar & PCI_BAR_SPACE) == PCI_BAR_MEM:
- bar = bar & PCI_BAR_MEM_MASK
- bar = bar & ~PAGE_MASK
- if bar != 0:
- self.has_non_page_aligned_bar = True
- break
- bar_addr = bar_addr + 4
-
- def devs_check_driver(self, devs):
- if len(devs) == 0:
- return
- for pci_dev in devs:
- dev = PciDevice(parse_pci_name(pci_dev))
- if dev.driver == 'pciback' or dev.driver == 'pci-stub':
- continue
- err_msg = 'pci: %s must be co-assigned to the same guest with %s' + \
- ', but it is not owned by pciback or pci-stub.'
- raise PciDeviceAssignmentError(err_msg % (pci_dev, self.name))
-
- def do_FLR(self, is_hvm, strict_check):
- """ Perform FLR (Functional Level Reset) for the device.
- """
- if self.dev_type == DEV_TYPE_PCIe_ENDPOINT:
- # If PCIe device supports FLR, we use it.
- if self.pcie_flr:
- (pci_list, cfg_list) = save_pci_conf_space([self.name])
- pos = self.find_cap_offset(PCI_CAP_ID_EXP)
- self.pci_conf_write32(pos + PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_FLR)
- # We must sleep at least 100ms for the completion of FLR
- time.sleep(0.100)
- restore_pci_conf_space((pci_list, cfg_list))
- else:
- if self.bus == 0:
- self.do_FLR_for_integrated_device()
- else:
- funcs = self.find_all_the_multi_functions()
-
- if not is_hvm and (len(funcs) > 1):
- return
- if is_hvm and not strict_check:
- return
-
- self.devs_check_driver(funcs)
-
- parent = pci_dict_to_bdf_str(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".
- if self.bus == 0 and self.pci_af_flr:
- af_pos = self.find_cap_offset(PCI_CAP_ID_AF)
- self.do_AF_FLR(af_pos)
- else:
- if self.bus == 0:
- if self.slot == 0x02 and self.func == 0x0:
- vendor_id = self.pci_conf_read16(PCI_VENDOR_ID)
- if vendor_id != VENDOR_INTEL:
- return
- class_id = self.pci_conf_read16(PCI_CLASS_DEVICE)
- if class_id != PCI_CLASS_ID_VGA:
- return
- device_id = self.pci_conf_read16(PCI_DEVICE_ID)
- if device_id == PCI_DEVICE_ID_IGFX_GM45:
- self.do_FLR_for_GM45_iGFX()
- elif device_id == PCI_DEVICE_ID_IGFX_EAGLELAKE or \
- device_id == PCI_DEVICE_ID_IGFX_Q45 or \
- device_id == PCI_DEVICE_ID_IGFX_G45 or \
- device_id == PCI_DEVICE_ID_IGFX_G41:
- self.do_FLR_for_intel_4Series_iGFX()
- else:
- log.debug("Unknown iGFX device_id:%x", device_id)
- else:
- self.do_FLR_for_integrated_device()
- else:
- devs = self.find_coassigned_pci_devices(False)
- # Remove the element 0 which is a bridge
- target_bus = devs[0]
- del devs[0]
-
- if not is_hvm and (len(devs) > 1):
- return
- if is_hvm and not strict_check:
- return
-
- self.devs_check_driver(devs)
-
- # Do Secondary Bus Reset.
- self.do_secondary_bus_reset(target_bus, devs)
-
- def find_capability(self, type):
- sysfs_mnt = find_sysfs_mnt()
- if sysfs_mnt == None:
- return False
- path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
- 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))
- if capa_id == type:
- # get the type
- message_cont_lo = ord(conf_file.read(1))
- message_cont_hi = ord(conf_file.read(1))
- self.msix=1
- self.msix_entries = (message_cont_lo + \
- (message_cont_hi << 8)) \
- & MSIX_SIZE_MASK
- t_off=conf_file.read(4)
- p_off=conf_file.read(4)
- self.table_offset=ord(t_off[0]) | (ord(t_off[1])<<8) | \
- (ord(t_off[2])<<16)| \
- (ord(t_off[3])<<24)
- self.pba_offset=ord(p_off[0]) | (ord(p_off[1]) << 8)| \
- (ord(p_off[2])<<16) | \
- (ord(p_off[3])<<24)
- self.table_index = self.table_offset & MSIX_BIR_MASK
- self.table_offset = self.table_offset & ~MSIX_BIR_MASK
- self.pba_index = self.pba_offset & MSIX_BIR_MASK
- self.pba_offset = self.pba_offset & ~MSIX_BIR_MASK
- break
- except IOError, (errno, strerr):
- raise PciDeviceParseError(('Failed to locate sysfs mount: %s: %s (%d)' %
- (PROC_PCI_PATH, strerr, errno)))
- except TypeError, err:
- log.debug("Caught TypeError '%s'" % err)
- pass
-
- def get_info_from_sysfs(self):
- self.find_capability(0x11)
- sysfs_mnt = find_sysfs_mnt()
- if sysfs_mnt == None:
- return False
-
- path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
- self.name+SYSFS_PCI_DEV_RESOURCE_PATH
- try:
- resource_file = open(path,'r')
-
- for i in range(PROC_PCI_NUM_RESOURCES):
- line = resource_file.readline()
- sline = line.split()
- if len(sline)<3:
- continue
-
- start = int(sline[0],16)
- end = int(sline[1],16)
- flags = int(sline[2],16)
- size = end-start+1
-
- if start!=0:
- if flags&PCI_BAR_IO:
- self.ioports.append( (start,size) )
- else:
- self.iomem.append( (start,size) )
-
- except IOError, (errno, strerr):
- raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
- (path, strerr, errno)))
-
- path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
- self.name+SYSFS_PCI_DEV_IRQ_PATH
- try:
- self.irq = int(open(path,'r').readline())
- except IOError, (errno, strerr):
- raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
- (path, strerr, errno)))
-
- path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
- self.name+SYSFS_PCI_DEV_DRIVER_DIR_PATH
- try:
- self.driver = os.path.basename(os.readlink(path))
- except OSError, (errno, strerr):
- self.driver = ""
-
- path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
- self.name+SYSFS_PCI_DEV_VENDOR_PATH
- try:
- self.vendor = int(open(path,'r').readline(), 16)
- except IOError, (errno, strerr):
- raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
- (path, strerr, errno)))
-
- path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
- self.name+SYSFS_PCI_DEV_DEVICE_PATH
- try:
- self.device = int(open(path,'r').readline(), 16)
- except IOError, (errno, strerr):
- raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
- (path, strerr, errno)))
-
- path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
- self.name+SYSFS_PCI_DEV_SUBVENDOR_PATH
- try:
- self.subvendor = int(open(path,'r').readline(), 16)
- except IOError, (errno, strerr):
- raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
- (path, strerr, errno)))
-
- path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
- self.name+SYSFS_PCI_DEV_SUBDEVICE_PATH
- try:
- self.subdevice = int(open(path,'r').readline(), 16)
- except IOError, (errno, strerr):
- raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
- (path, strerr, errno)))
-
- path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
- self.name+SYSFS_PCI_DEV_CLASS_PATH
- try:
- self.classcode = int(open(path,'r').readline(), 16)
- except IOError, (errno, strerr):
- raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
- (path, strerr, errno)))
-
- return True
-
- def get_info_from_lspci(self):
- """ Get information such as vendor name, device name, class name, etc.
- Since we cannot obtain these data from sysfs, use 'lspci' command.
- """
- global lspci_info
- global lspci_info_lock
-
- lspci_info_lock.acquire()
- try:
- if lspci_info is None:
- _create_lspci_info()
-
- device_info = lspci_info.get(self.name)
- if device_info:
- try:
- self.revision = int(device_info.get('Rev', '0'), 16)
- except ValueError:
- pass
- self.vendorname = device_info.get('Vendor', '')
- self.devicename = device_info.get('Device', '')
- self.classname = device_info.get('Class', '')
- self.subvendorname = device_info.get('SVendor', '')
- self.subdevicename = device_info.get('SDevice', '')
- return True
- finally:
- lspci_info_lock.release()
-
- def __str__(self):
- str = "PCI Device %s\n" % (self.name)
- for (start,size) in self.ioports:
- str = str + "IO Port 0x%02x [size=%d]\n"%(start,size)
- for (start,size) in self.iomem:
- str = str + "IO Mem 0x%02x [size=%d]\n"%(start,size)
- str = str + "IRQ %d\n"%(self.irq)
- str = str + "Vendor ID 0x%04x\n"%(self.vendor)
- str = str + "Device ID 0x%04x\n"%(self.device)
- str = str + "Sybsystem Vendor ID 0x%04x\n"%(self.subvendor)
- str = str + "Subsystem Device ID 0x%04x"%(self.subdevice)
- return str
-
-def main():
- if len(sys.argv)<5:
- print "Usage: %s <domain> <bus> <slot> <func>\n" % sys.argv[0]
- sys.exit(2)
-
- dev = PciDevice(int(sys.argv[1],16), int(sys.argv[2],16),
- int(sys.argv[3],16), int(sys.argv[4],16))
- print str(dev)
-
-if __name__=='__main__':
- main()
diff --git a/tools/python/xen/util/rwlock.py b/tools/python/xen/util/rwlock.py
deleted file mode 100644
index e79a82f..0000000
--- a/tools/python/xen/util/rwlock.py
+++ /dev/null
@@ -1,137 +0,0 @@
-""" Reader-writer lock implementation based on a condition variable """
-
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2008 International Business Machines Corp.
-# Author: Stefan Berger <stefanb at us.ibm.com>
-#============================================================================
-
-from threading import Condition
-
-class RWLock:
-
- RWLOCK_STATE_WRITER = -1
- RWLOCK_STATE_UNUSED = 0
-
- def __init__(self):
- self.__condition = Condition()
- self.__state = RWLock.RWLOCK_STATE_UNUSED
- self.__blocked_writers = 0
-
- def acquire_reader(self):
- self.__condition.acquire()
- while True:
- if self.__state == RWLock.RWLOCK_STATE_WRITER:
- self.__condition.wait()
- else:
- break
- self.__state += 1
- self.__condition.release()
-
- def acquire_writer(self):
- self.__condition.acquire()
- self.__acquire_writer(RWLock.RWLOCK_STATE_UNUSED)
- self.__condition.release()
-
- def __acquire_writer(self, wait_for_state):
- while True:
- if self.__state == wait_for_state:
- self.__state = RWLock.RWLOCK_STATE_WRITER
- break
- else:
- self.__blocked_writers += 1
- self.__condition.wait()
- self.__blocked_writers -= 1
-
- def release(self):
- self.__condition.acquire()
- if self.__state == RWLock.RWLOCK_STATE_WRITER:
- self.__state = RWLock.RWLOCK_STATE_UNUSED
- elif self.__state == RWLock.RWLOCK_STATE_UNUSED:
- assert False, 'Lock not in use.'
- else:
- self.__state -= 1
- self.__condition.notifyAll()
- self.__condition.release()
-
-
-if __name__ == '__main__':
- from threading import Thread
- from time import sleep
-
- rwlock = RWLock()
-
- class Base(Thread):
- def __init__(self, name, timeout):
- self.name = name
- self.timeout = timeout
- Thread.__init__(self)
-
- class Reader(Base):
- def __init__(self, name = 'Reader', timeout = 10):
- Base.__init__(self, name, timeout)
-
- def run(self):
- print '%s begin' % self.name
- rwlock.acquire_reader()
- print '%s acquired' % self.name
- sleep(self.timeout)
- rwlock.release()
- print '%s end' % self.name
-
- class ReaderTwice(Base):
- def __init__(self, name = 'Reader', timeout = 10):
- Base.__init__(self, name, timeout)
-
- def run(self):
- print '%s begin' % self.name
- rwlock.acquire_reader()
- print '%s acquired once' % self.name
- sleep(self.timeout)
- rwlock.acquire_reader()
- print '%s acquired twice' % self.name
- sleep(self.timeout)
- rwlock.release()
- rwlock.release()
- print '%s end' % self.name
-
- class Writer(Base):
- def __init__(self, name = 'Writer', timeout = 10):
- Base.__init__(self, name, timeout)
-
- def run(self):
- print '%s begin' % self.name
- rwlock.acquire_writer()
- print '%s acquired' % self.name
- sleep(self.timeout)
- rwlock.release()
- print '%s end' % self.name
-
- def run_test(threadlist, msg):
- print msg
- for t in threadlist:
- t.start()
- sleep(1)
- for t in threads:
- t.join()
- print 'Done\n\n'
-
- threads = []
- threads.append( Reader('R1', 4) )
- threads.append( Reader('R2', 4) )
- threads.append( Writer('W1', 4) )
- threads.append( Reader('R3', 4) )
- run_test(threads,
- 'Test: readers may bypass blocked writers')
diff --git a/tools/python/xen/util/sxputils.py b/tools/python/xen/util/sxputils.py
deleted file mode 100644
index ff5678b..0000000
--- a/tools/python/xen/util/sxputils.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (c) 2009 Fujitsu Technology Solutions
-#============================================================================
-
-""" convert sxp to map / map to sxp.
-"""
-
-import types
-from xen.xend import sxp
-
-def map2sxp(map_val):
- """ conversion of all key-value pairs of a map (recursively) to sxp.
- @param map_val: map; if a value contains a list or dict it is also
- converted to sxp
- @type map_val: dict
- @return sxp expr
- @rtype: list
- """
- sxp_vals = []
- for (k, v) in map_val.items():
- if isinstance(v, types.DictionaryType):
- sxp_vals += [[k] + map2sxp(v)]
- elif isinstance(v, types.ListType):
- sxp_vals += [[k] + v]
- else:
- sxp_vals += [[k, v]]
- return sxp_vals
-
-def sxp2map( s ):
- """ conversion of sxp to map.
- @param s: sxp expr
- @type s: list
- @return: map
- @rtype: dict
- """
- sxphash = {}
-
- for child in sxp.children( s ):
- if isinstance( child, types.ListType ) and len( child ) > 1:
- if isinstance( child[1], types.ListType ) and len( child[1] ) > 1:
- sxphash[ child[0] ] = sxp2map( child )
- else:
- childs = sxp.children(child)
- if len(childs) > 1:
- sxphash[ child[0] ] = childs
- else:
- sxphash[ child[0] ] = childs[0]
-
- return sxphash
-
-
diff --git a/tools/python/xen/util/utils.py b/tools/python/xen/util/utils.py
deleted file mode 100644
index 6be3e8e..0000000
--- a/tools/python/xen/util/utils.py
+++ /dev/null
@@ -1,78 +0,0 @@
-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
-
-# Global variable to store the sysfs mount point
-sysfs_mount_point = None
-
-PROC_MOUNTS_PATH = '/proc/mounts'
-
-def find_sysfs_mount():
- global sysfs_mount_point
-
- if not sysfs_mount_point is None:
- return sysfs_mount_point
-
- try:
- mounts_file = open(PROC_MOUNTS_PATH, 'r')
-
- for line in mounts_file:
- sline = line.split()
- if len(sline) < 3:
- continue
- if sline[2] == 'sysfs':
- sysfs_mount_point= sline[1]
- break
- mounts_file.close()
- return sysfs_mount_point
- except IOError, (errno, strerr):
- raise
-
- return None
-
diff --git a/tools/python/xen/util/vscsi_util.py b/tools/python/xen/util/vscsi_util.py
deleted file mode 100644
index 5872e65..0000000
--- a/tools/python/xen/util/vscsi_util.py
+++ /dev/null
@@ -1,304 +0,0 @@
-#!/usr/bin/env python
-# -*- mode: python; -*-
-
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2008 FUJITSU Limited
-# Based on the blkif.py
-#============================================================================
-
-
-"""Support for VSCSI Devices.
-"""
-import os
-import os.path
-import sys
-import re
-import string
-from xen.util import utils
-
-SYSFS_SCSI_PATH = "/bus/scsi/devices"
-SYSFS_SCSI_DEV_VENDOR_PATH = '/vendor'
-SYSFS_SCSI_DEV_MODEL_PATH = '/model'
-SYSFS_SCSI_DEV_TYPEID_PATH = '/type'
-SYSFS_SCSI_DEV_REVISION_PATH = '/rev'
-SYSFS_SCSI_DEV_SCSILEVEL_PATH = '/scsi_level'
-
-SCSI_ID_COMMANDS = [
- "/lib/udev/scsi_id -gu --sg-version 3 -d /dev/%s 2>/dev/null",
- "/sbin/scsi_id -gu -s /class/scsi_generic/%s 2>/dev/null"
-]
-
-def _vscsi_get_devname_by(name, scsi_devices):
- """A device name is gotten by the HCTL.
- (e.g., '0:0:0:0' to '/dev/sda')
- """
-
- try:
- search = re.compile(r'' + name + '$', re.DOTALL)
- except Exception, e:
- raise VmError("vscsi: invalid expression. " + str(e))
-
- for hctl, devname, sg, scsi_id in scsi_devices:
- if search.match(hctl):
- return (hctl, devname)
-
- return (None, None)
-
-
-def _vscsi_get_hctl_by(phyname, scsi_devices):
- """An HCTL is gotten by the device name or the scsi_id.
- (e.g., '/dev/sda' to '0:0:0:0')
- """
-
- if re.match('/dev/sd[a-z]+([1-9]|1[0-5])?$', phyname):
- # sd driver
- name = re.sub('(^/dev/)|([1-9]|1[0-5])?$', '', phyname)
- elif re.match('/dev/sg[0-9]+$', phyname):
- # sg driver
- name = re.sub('^/dev/', '', phyname)
- elif re.match('/dev/st[0-9]+$', phyname):
- # st driver
- name = re.sub('^/dev/', '', phyname)
- else:
- # scsi_id -gu
- name = phyname
-
- for hctl, devname, sg, scsi_id in scsi_devices:
- if name in [devname, sg, scsi_id]:
- return (hctl, devname)
-
- return (None, None)
-
-
-def _vscsi_get_scsiid(sg):
- for scsi_id_command in SCSI_ID_COMMANDS:
- scsi_id = os.popen(scsi_id_command % sg).read().split()
- if len(scsi_id):
- return scsi_id[0]
- return None
-
-
-def _vscsi_get_scsidevices_by_lsscsi(option = ""):
- """ get all scsi devices information by lsscsi """
-
- devices = []
-
- for scsiinfo in os.popen('{ lsscsi -g %s; } 2>/dev/null' % option).readlines():
- s = scsiinfo.replace(']', '] ').split()
- hctl = s[0][1:-1]
- try:
- devname = s[-2].split('/dev/')[1]
- except IndexError:
- devname = None
- try:
- sg = s[-1].split('/dev/')[1]
- if devname is None:
- devname = sg
- scsi_id = _vscsi_get_scsiid(sg)
- except IndexError:
- sg = None
- scsi_id = None
- devices.append([hctl, devname, sg, scsi_id])
-
- return devices
-
-
-def _vscsi_get_scsidevices_by_sysfs():
- """ get all scsi devices information by sysfs """
-
- devices = []
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- except:
- return devices
-
- if sysfs_mnt is None:
- return devices
-
- for dirpath, dirnames, files in os.walk(sysfs_mnt + SYSFS_SCSI_PATH):
- for hctl in dirnames:
- if len(hctl.split(':')) != 4:
- continue
- paths = os.path.join(dirpath, hctl)
- devname = None
- sg = None
- scsi_id = None
- for f in os.listdir(paths):
- realpath = os.path.realpath(os.path.join(paths, f))
- if re.match('^block:', f) or \
- re.match('^tape:', f) or \
- re.match('^scsi_changer:', f) or \
- re.match('^onstream_tape:', f):
- devname = os.path.basename(realpath)
- elif f == "block" or \
- f == "tape" or \
- f == "scsi_changer" or \
- f == "onstream_tape":
- for dir in os.listdir(os.path.join(paths, f)):
- if os.path.exists(os.path.join(paths, f, dir, "dev")):
- devname = os.path.basename(dir)
-
- if re.match('^scsi_generic:', f):
- sg = os.path.basename(realpath)
- elif f == "scsi_generic":
- for dir in os.listdir(os.path.join(paths, f)):
- if os.path.exists(os.path.join(paths, f, dir, "dev")):
- sg = os.path.basename(dir)
- if sg:
- if devname is None:
- devname = sg
- scsi_id = _vscsi_get_scsiid(sg)
- devices.append([hctl, devname, sg, scsi_id])
-
- return devices
-
-
-def vscsi_get_scsidevices(mask="*"):
- """ get all scsi devices information """
-
- devices = _vscsi_get_scsidevices_by_lsscsi("[%s]" % mask)
- if devices or (len(mask) and mask[0] != "*"):
- # devices found or partial device scan
- return devices
- return _vscsi_get_scsidevices_by_sysfs()
-
-
-def vscsi_get_hctl_and_devname_by(target, scsi_devices = None):
- if target.startswith('/dev/'):
- target = os.path.realpath(target)
- if scsi_devices is None:
- if len(target.split(':')) == 4:
- scsi_devices = _vscsi_get_scsidevices_by_lsscsi(target)
- elif target.startswith('/dev/'):
- scsi_devices = _vscsi_get_scsidevices_by_lsscsi("| grep %s" % target)
- else:
- scsi_devices = _vscsi_get_scsidevices_by_lsscsi("")
- if not scsi_devices:
- scsi_devices = _vscsi_get_scsidevices_by_sysfs()
-
- if len(target.split(':')) == 4:
- return _vscsi_get_devname_by(target, scsi_devices)
- else:
- return _vscsi_get_hctl_by(target, scsi_devices)
-
-
-def get_scsi_vendor(pHCTL):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- sysfs_scsi_dev_path = \
- os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL)
- scsi_vendor = \
- os.popen('cat ' + sysfs_scsi_dev_path + \
- SYSFS_SCSI_DEV_VENDOR_PATH).read()
- return scsi_vendor.splitlines()[0]
- except:
- return None
-
-def get_scsi_model(pHCTL):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- sysfs_scsi_dev_path = \
- os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL)
- scsi_model = \
- os.popen('cat ' + sysfs_scsi_dev_path + \
- SYSFS_SCSI_DEV_MODEL_PATH).read()
- return scsi_model.splitlines()[0]
- except:
- return None
-
-def get_scsi_typeid(pHCTL):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- sysfs_scsi_dev_path = \
- os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL)
- scsi_typeid = \
- os.popen('cat ' + sysfs_scsi_dev_path + \
- SYSFS_SCSI_DEV_TYPEID_PATH).read()
- return int(scsi_typeid.splitlines()[0])
- except:
- return None
-
-def get_scsi_revision(pHCTL):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- sysfs_scsi_dev_path = \
- os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL)
- scsi_revision = \
- os.popen('cat ' + sysfs_scsi_dev_path + \
- SYSFS_SCSI_DEV_REVISION_PATH).read()
- return scsi_revision.splitlines()[0]
- except:
- return None
-
-def get_scsi_scsilevel(pHCTL):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- sysfs_scsi_dev_path = \
- os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL)
- scsi_scsilevel = \
- os.popen('cat ' + sysfs_scsi_dev_path + \
- SYSFS_SCSI_DEV_SCSILEVEL_PATH).read()
- return int(scsi_scsilevel.splitlines()[0])
- except:
- return None
-
-def _make_scsi_record(scsi_info):
- scsi_rec = {
- 'physical_HCTL': scsi_info[0],
- 'dev_name': None,
- 'sg_name': scsi_info[2],
- 'scsi_id': None
- }
- if scsi_info[1] is not None:
- scsi_rec['dev_name'] = scsi_info[1]
- if scsi_info[3] is not None:
- scsi_rec['scsi_id'] = scsi_info[3]
-
- scsi_rec['vendor_name'] = \
- get_scsi_vendor(scsi_rec['physical_HCTL'])
- scsi_rec['model'] = \
- get_scsi_model(scsi_rec['physical_HCTL'])
- scsi_rec['type_id'] = \
- get_scsi_typeid(scsi_rec['physical_HCTL'])
- scsi_rec['revision'] = \
- get_scsi_revision(scsi_rec['physical_HCTL'])
- scsi_rec['scsi_level'] = \
- get_scsi_scsilevel(scsi_rec['physical_HCTL'])
-
- try:
- lsscsi_info = os.popen('lsscsi %s 2>/dev/null' % scsi_rec['physical_HCTL']).read().split()
- scsi_rec['type'] = lsscsi_info[1]
- except:
- scsi_rec['type'] = None
-
- return scsi_rec
-
-def get_scsi_device(pHCTL):
- scsis_info = _vscsi_get_scsidevices_by_lsscsi(pHCTL)
- if not scsis_info:
- scsis_info = _vscsi_get_scsidevices_by_sysfs()
- for scsi_info in scsis_info:
- if scsi_info[0] == pHCTL:
- return _make_scsi_record(scsi_info)
- return None
-
-def get_all_scsi_devices(mask="*"):
- scsi_records = []
- for scsi_info in vscsi_get_scsidevices(mask):
- scsi_record = _make_scsi_record(scsi_info)
- scsi_records.append(scsi_record)
- return scsi_records
-
diff --git a/tools/python/xen/util/vusb_util.py b/tools/python/xen/util/vusb_util.py
deleted file mode 100644
index 9ca498c..0000000
--- a/tools/python/xen/util/vusb_util.py
+++ /dev/null
@@ -1,338 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2009, FUJITSU LABORATORIES LTD.
-# Author: Noboru Iwamatsu <n_iwamatsu at jp.fujitsu.com>
-#============================================================================
-
-
-"""Support for VUSB Devices.
-"""
-import os
-import os.path
-import sys
-import re
-import string
-from xen.util import utils
-
-SYSFS_USB_DEVS_PATH = '/bus/usb/devices'
-SYSFS_USB_DEV_BDEVICECLASS_PATH = '/bDeviceClass'
-SYSFS_USB_DEV_BDEVICESUBCLASS_PATH = '/bDeviceSubClass'
-SYSFS_USB_DEV_DEVNUM_PATH = '/devnum'
-SYSFS_USB_DEV_IDVENDOR_PATH = '/idVendor'
-SYSFS_USB_DEV_IDPRODUCT_PATH = '/idProduct'
-SYSFS_USB_DEV_MANUFACTURER_PATH = '/manufacturer'
-SYSFS_USB_DEV_PRODUCT_PATH = '/product'
-SYSFS_USB_DEV_SERIAL_PATH = '/serial'
-SYSFS_USB_DEV_DRIVER_PATH = '/driver'
-SYSFS_USB_DRIVER_BIND_PATH = '/bind'
-SYSFS_USB_DRIVER_UNBIND_PATH = '/unbind'
-SYSFS_USBBACK_PATH = '/bus/usb/drivers/usbback'
-SYSFS_PORTIDS_PATH = '/port_ids'
-USBHUB_CLASS_CODE = '09'
-
-def get_usb_bDeviceClass(dev):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- sysfs_usb_dev_path = \
- os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
- if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_BDEVICECLASS_PATH):
- usb_deviceclass = \
- os.popen('cat ' + sysfs_usb_dev_path + \
- SYSFS_USB_DEV_BDEVICECLASS_PATH).readline()
- return usb_deviceclass.splitlines()[0]
- else:
- return ""
- except:
- return None
-
-def get_usb_bDeviceSubClass(dev):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- sysfs_usb_dev_path = \
- os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
- if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_BDEVICESUBCLASS_PATH):
- usb_devicesubclass = \
- os.popen('cat ' + sysfs_usb_dev_path + \
- SYSFS_USB_DEV_BDEVICESUBCLASS_PATH).readline()
- return usb_devicesubclass.splitlines()[0]
- else:
- return ""
- except:
- return None
-
-def get_usb_devnum(dev):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- sysfs_usb_dev_path = \
- os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
- if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_DEVNUM_PATH):
- usb_devicesubclass = \
- os.popen('cat ' + sysfs_usb_dev_path + \
- SYSFS_USB_DEV_DEVNUM_PATH).readline()
- return usb_devicesubclass.splitlines()[0]
- else:
- return ""
- except:
- return None
-
-def get_usb_idvendor(dev):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- sysfs_usb_dev_path = \
- os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
- if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_IDVENDOR_PATH):
- usb_idvendor = \
- os.popen('cat ' + sysfs_usb_dev_path + \
- SYSFS_USB_DEV_IDVENDOR_PATH).readline()
- return usb_idvendor.splitlines()[0]
- else:
- return ""
- except:
- return None
-
-def get_usb_idproduct(dev):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- sysfs_usb_dev_path = \
- os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
- if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_IDPRODUCT_PATH):
- usb_idproduct = \
- os.popen('cat ' + sysfs_usb_dev_path + \
- SYSFS_USB_DEV_IDPRODUCT_PATH).readline()
- return usb_idproduct.splitlines()[0]
- else:
- return ""
- except:
- return None
-
-def get_usb_manufacturer(dev):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- sysfs_usb_dev_path = \
- os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
-
- if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_MANUFACTURER_PATH):
- usb_manufacturer = \
- os.popen('cat ' + sysfs_usb_dev_path + \
- SYSFS_USB_DEV_MANUFACTURER_PATH).readline()
- return usb_manufacturer.splitlines()[0]
- else:
- return ""
- except:
- return None
-
-def get_usb_product(dev):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- sysfs_usb_dev_path = \
- os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
- if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_PRODUCT_PATH):
- usb_product = \
- os.popen('cat ' + sysfs_usb_dev_path + \
- SYSFS_USB_DEV_PRODUCT_PATH).readline()
- return usb_product.splitlines()[0]
- else:
- return ""
- except:
- return None
-
-def get_usb_serial(dev):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- sysfs_usb_dev_path = \
- os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
- if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_SERIAL_PATH):
- usb_serial = \
- os.popen('cat ' + sysfs_usb_dev_path + \
- SYSFS_USB_DEV_SERIAL_PATH).readline()
- return usb_serial.splitlines()[0]
- else:
- return ""
- except:
- return None
-
-def get_usbdevice_info_by_lsusb(dev):
- try:
- vend = get_usb_idvendor(dev)
- prod = get_usb_idproduct(dev)
- output = os.popen('lsusb -d ' + vend + ':' + prod).readline().split()
- text = ""
- if len(output) > 6:
- for str in output[6:]:
- if text != "":
- text= text + ' '
- text = text + str
- return text
- else:
- return ""
- except:
- return None
-
-def get_usbdevice_info(dev):
- try:
- manuf = get_usb_manufacturer(dev)
- prod = get_usb_product(dev)
- if manuf == "" or prod == "":
- return get_usbdevice_info_by_lsusb(dev)
- else:
- return manuf + ' ' + prod
- except:
- return None
-
-def usb_device_is_hub(dev):
- usb_classcode = get_usb_bDeviceClass(dev)
- if (usb_classcode == USBHUB_CLASS_CODE):
- return True
- else:
- return False
-
-def get_all_usb_names():
- usb_names = []
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- usb_names = os.popen('ls ' + sysfs_mnt + SYSFS_USB_DEVS_PATH).read().split()
- except:
- pass
- return usb_names
-
-def get_usb_devices():
- devs = []
- for name in get_all_usb_names():
- dev_match = re.match(r"(^(?P<bus>[0-9]{1,2})[-,])" + \
- r"(?P<root_port>[0-9]{1,2})" + \
- r"(?P<port>([\.,]{1}[0-9]{1,2}){0,5})$", name)
- if dev_match is not None:
- dev = dev_match.group('bus') + '-' \
- + dev_match.group('root_port') \
- + dev_match.group('port')
- if (usb_device_is_hub(dev)):
- continue
- else:
- devs.append(dev)
- return devs
-
-def get_usb_intfs(dev):
- intfs = []
- try:
- search = re.compile(r'^' + dev + ':')
- except:
- raise UsbDeviceParseError("Invalid expression.")
- for name in get_all_usb_names():
- if search.match(name):
- intfs.append(name)
- return intfs
-
-def get_assigned_buses():
- buses = []
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- if os.path.exists(sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH):
- portids = \
- os.popen('cat ' + sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH).read().splitlines()
- for portid in portids:
- buses.append(portid.split(':')[0])
- except:
- raise UsbDeviceParseError("Can't get assigned buses from port_ids.")
- return buses
-
-def get_assigned_bus(domid, dev, port):
- bus = ""
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- if os.path.exists(sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH):
- portids = \
- os.popen('cat ' + sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH).read().splitlines()
- for portid in portids:
- if portid.split(':')[1] == str(domid) and portid.split(':')[2] == str(dev) and portid.split(':')[3] == str(port):
- bus = portid.split(':')[0]
- except:
- raise UsbDeviceParseError("Can't get assigned bus (%d:%d:%d)." % (domid, dev, port))
- return bus
-
-def bus_is_assigned(bus):
- assigned = False
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- if os.path.exists(sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH):
- portids = \
- os.popen('cat ' + sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH).read().splitlines()
- for portid in portids:
- if portid.split(':')[0] == bus:
- assigned = True
- except:
- raise UsbDeviceParseError("Can't get assignment status: (%s)." % bus)
- return assigned
-
-def usb_intf_is_binded(intf):
- if os.path.exists(SYSFS_USBBACK_PATH + '/' + intf):
- return True
- else:
- return False
-
-def usb_device_is_connected(dev):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- sysfs_dev_path = \
- os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
- if os.path.exists(sysfs_dev_path):
- return True
- else:
- return False
- except:
- raise UsbDeviceParseError("Can't get connection status (%s)." % dev)
-
-def unbind_usb_device(dev):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- for intf in get_usb_intfs(dev):
- sysfs_usb_intf_path = \
- os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, intf)
- if os.path.exists(sysfs_usb_intf_path + SYSFS_USB_DEV_DRIVER_PATH):
- fd = os.open(sysfs_usb_intf_path + \
- SYSFS_USB_DEV_DRIVER_PATH + \
- SYSFS_USB_DRIVER_UNBIND_PATH, os.O_WRONLY)
- os.write(fd, intf)
- os.close(fd)
- except:
- raise UsbDeviceBindingError("can't unbind intf (%s). " % intf)
-
-def bind_usb_device(dev):
- try:
- sysfs_mnt = utils.find_sysfs_mount()
- for intf in get_usb_intfs(dev):
- sysfs_usb_intf_path = \
- os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, intf)
- if os.path.exists(sysfs_usb_intf_path + SYSFS_USB_DEV_DRIVER_PATH):
- unbind_usb_device(dev)
-
- fd = os.open(sysfs_mnt + SYSFS_USBBACK_PATH + \
- SYSFS_USB_DRIVER_BIND_PATH, os.O_WRONLY)
- os.write(fd, intf)
- os.close(fd)
- except:
- raise UsbDeviceBindingError("can't bind intf (%s). " % intf)
-
-class UsbDeviceParseError(Exception):
- def __init__(self,msg):
- self.message = msg
- def __str__(self):
- return 'vusb: Error parsing USB device info: '+self.message
-
-class UsbDeviceBindingError(Exception):
- def __init__(self,msg):
- self.message = msg
- def __str__(self):
- return 'vusb: Failed to bind/unbind USB device: ' + \
- self.message
diff --git a/tools/python/xen/util/xmlrpcclient.py b/tools/python/xen/util/xmlrpcclient.py
deleted file mode 100644
index d4191b7..0000000
--- a/tools/python/xen/util/xmlrpcclient.py
+++ /dev/null
@@ -1,129 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 Anthony Liguori <aliguori at us.ibm.com>
-# Copyright (C) 2007 XenSource Inc.
-#============================================================================
-
-
-from httplib import FakeSocket, HTTPConnection, HTTP
-import socket
-import string
-import xmlrpclib
-from types import StringTypes
-from sys import hexversion
-
-
-try:
- import SSHTransport
- ssh_enabled = True
-except ImportError:
- # SSHTransport is disabled on Python <2.4, because it uses the subprocess
- # package.
- ssh_enabled = False
-
-
-# A new ServerProxy that also supports httpu urls. An http URL comes in the
-# form:
-#
-# httpu:///absolute/path/to/socket.sock
-#
-# It assumes that the RPC handler is /RPC2. This probably needs to be improved
-
-class HTTPUnixConnection(HTTPConnection):
- def connect(self):
- self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- self.sock.connect(self.host)
-
-class HTTPUnix(HTTP):
- _connection_class = HTTPUnixConnection
-
-class UnixTransport(xmlrpclib.Transport):
- def request(self, host, handler, request_body, verbose=0):
- self.__handler = handler
- return xmlrpclib.Transport.request(self, host, '/RPC2',
- request_body, verbose)
- def make_connection(self, host):
- if hexversion < 0x02070000:
- # python 2.6 or earlier
- return HTTPUnix(self.__handler)
- else:
- # xmlrpclib.Transport changed in python 2.7
- return HTTPUnixConnection(self.__handler)
-
-
-# We need our own transport for HTTPS, because xmlrpclib.SafeTransport is
-# broken -- it does not handle ERROR_ZERO_RETURN properly.
-class HTTPSTransport(xmlrpclib.SafeTransport):
- def _parse_response(self, file, sock):
- p, u = self.getparser()
- while 1:
- try:
- if sock:
- response = sock.recv(1024)
- else:
- response = file.read(1024)
- except socket.sslerror, exn:
- if exn[0] == socket.SSL_ERROR_ZERO_RETURN:
- break
- raise
-
- if not response:
- break
- if self.verbose:
- print 'body:', repr(response)
- p.feed(response)
-
- file.close()
- p.close()
- return u.close()
-
-
-# See xmlrpclib2.TCPXMLRPCServer._marshalled_dispatch.
-def conv_string(x):
- if isinstance(x, StringTypes):
- s = string.replace(x, "'", r"\047")
- exec "s = '" + s + "'"
- return s
- else:
- return x
-
-
-class ServerProxy(xmlrpclib.ServerProxy):
- def __init__(self, uri, transport=None, encoding=None, verbose=0,
- allow_none=1):
- if transport == None:
- (protocol, rest) = uri.split(':', 1)
- if protocol == 'httpu':
- uri = 'http:' + rest
- transport = UnixTransport()
- elif protocol == 'https':
- transport = HTTPSTransport()
- elif protocol == 'ssh':
- global ssh_enabled
- if ssh_enabled:
- (transport, uri) = SSHTransport.getHTTPURI(uri)
- else:
- raise ValueError(
- "SSH transport not supported on Python <2.4.")
- xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding,
- verbose, allow_none)
-
- def __request(self, methodname, params):
- response = xmlrpclib.ServerProxy.__request(self, methodname, params)
-
- if isinstance(response, tuple):
- return tuple([conv_string(x) for x in response])
- else:
- return conv_string(response)
diff --git a/tools/python/xen/util/xmlrpclib2.py b/tools/python/xen/util/xmlrpclib2.py
deleted file mode 100644
index 065a0a3..0000000
--- a/tools/python/xen/util/xmlrpclib2.py
+++ /dev/null
@@ -1,220 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 Anthony Liguori <aliguori at us.ibm.com>
-# Copyright (C) 2006 XenSource Inc.
-#============================================================================
-
-"""
-An enhanced XML-RPC client/server interface for Python.
-"""
-
-import re
-import fcntl
-from types import *
-
-
-from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
-import SocketServer
-import xmlrpclib, socket, os, stat
-
-import mkdir
-
-from xen.web import connection
-from xen.xend.XendLogging import log
-
-#
-# Convert all integers to strings as described in the Xen API
-#
-
-
-def stringify(value):
- if isinstance(value, long) or \
- (isinstance(value, int) and not isinstance(value, bool)):
- return str(value)
- elif isinstance(value, dict):
- new_value = {}
- for k, v in value.items():
- new_value[stringify(k)] = stringify(v)
- return new_value
- elif isinstance(value, (tuple, list)):
- return [stringify(v) for v in value]
- else:
- return value
-
-
-# We're forced to subclass the RequestHandler class so that we can work around
-# some bugs in Keep-Alive handling and also enabled it by default
-class XMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
- protocol_version = "HTTP/1.1"
- # xend crashes in python 2.7 unless disable_nagle_algorithm = False
- # it isn't used in earlier versions so it is harmless to set it generally
- disable_nagle_algorithm = False
-
- def __init__(self, hosts_allowed, request, client_address, server):
- self.hosts_allowed = hosts_allowed
- SimpleXMLRPCRequestHandler.__init__(self, request, client_address,
- server)
-
- # this is inspired by SimpleXMLRPCRequestHandler's do_POST but differs
- # in a few non-trivial ways
- # 1) we never generate internal server errors. We let the exception
- # propagate so that it shows up in the Xend debug logs
- # 2) we don't bother checking for a _dispatch function since we don't
- # use one
- def do_POST(self):
- addrport = self.client_address
- if not connection.hostAllowed(addrport, self.hosts_allowed):
- self.connection.shutdown(1)
- return
-
- data = self.rfile.read(int(self.headers["content-length"]))
- rsp = self.server._marshaled_dispatch(data)
-
- self.send_response(200)
- self.send_header("Content-Type", "text/xml")
- self.send_header("Content-Length", str(len(rsp)))
- self.end_headers()
-
- self.wfile.write(rsp)
- self.wfile.flush()
- if self.close_connection == 1:
- self.connection.shutdown(1)
-
-# This is a base XML-RPC server for TCP. It sets allow_reuse_address to
-# true, and has an improved marshaller that logs and serializes exceptions.
-
-class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer):
- allow_reuse_address = True
-
- def __init__(self, addr, allowed, xenapi, requestHandler=None,
- logRequests = 1):
- self.xenapi = xenapi
-
- if requestHandler is None:
- requestHandler = XMLRPCRequestHandler
- SimpleXMLRPCServer.__init__(self, addr,
- (lambda x, y, z:
- requestHandler(allowed, x, y, z)),
- logRequests)
-
- flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
- flags |= fcntl.FD_CLOEXEC
- fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)
-
- def get_request(self):
- (client, addr) = SimpleXMLRPCServer.get_request(self)
- flags = fcntl.fcntl(client.fileno(), fcntl.F_GETFD)
- flags |= fcntl.FD_CLOEXEC
- fcntl.fcntl(client.fileno(), fcntl.F_SETFD, flags)
- return (client, addr)
-
- def _marshaled_dispatch(self, data, dispatch_method = None):
- params, method = xmlrpclib.loads(data)
- if False:
- # Enable this block of code to exit immediately without sending
- # a response. This allows you to test client-side crash handling.
- import sys
- sys.exit(1)
- try:
- if dispatch_method is not None:
- response = dispatch_method(method, params)
- else:
- response = self._dispatch(method, params)
-
- if self.xenapi and \
- (response is None or
- not isinstance(response, dict) or
- 'Status' not in response):
- log.exception('Internal error handling %s: Invalid result %s',
- method, response)
- response = { "Status": "Failure",
- "ErrorDescription":
- ['INTERNAL_ERROR',
- 'Invalid result %s handling %s' %
- (response, method)]}
-
- # With either Unicode or normal strings, we can only transmit
- # \t, \n, \r, \u0020-\ud7ff, \ue000-\ufffd, and \u10000-\u10ffff
- # in an XML document. xmlrpclib does not escape these values
- # properly, and then breaks when it comes to parse the document.
- # To hack around this problem, we use repr here and exec above
- # to transmit the string using Python encoding.
- # Thanks to David Mertz <mertz at gnosis.cx> for the trick (buried
- # in xml_pickle.py).
- if isinstance(response, StringTypes):
- response = repr(response)[1:-1]
-
- response = (response,)
- response = xmlrpclib.dumps(response,
- methodresponse=1,
- allow_none=1)
- except Exception, exn:
- try:
- if self.xenapi:
- if _is_not_supported(exn):
- errdesc = ['MESSAGE_METHOD_UNKNOWN', method]
- else:
- log.exception('Internal error handling %s', method)
- errdesc = ['INTERNAL_ERROR', str(exn)]
-
- response = xmlrpclib.dumps(
- ({ "Status": "Failure",
- "ErrorDescription": errdesc },),
- methodresponse = 1)
- else:
- import xen.xend.XendClient
- if isinstance(exn, xmlrpclib.Fault):
- response = xmlrpclib.dumps(exn)
- else:
- log.exception('Internal error handling %s', method)
- response = xmlrpclib.dumps(
- xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn)))
- except:
- log.exception('Internal error handling error')
-
- return response
-
-
-notSupportedRE = re.compile(r'method "(.*)" is not supported')
-def _is_not_supported(exn):
- try:
- m = notSupportedRE.search(exn[0])
- return m is not None
- except:
- return False
-
-
-# This is a XML-RPC server that sits on a Unix domain socket.
-# It implements proper support for allow_reuse_address by
-# unlink()'ing an existing socket.
-
-class UnixXMLRPCRequestHandler(XMLRPCRequestHandler):
- def address_string(self):
- try:
- return XMLRPCRequestHandler.address_string(self)
- except ValueError, e:
- return self.client_address[:2]
-
-class UnixXMLRPCServer(TCPXMLRPCServer):
- address_family = socket.AF_UNIX
- allow_address_reuse = True
-
- def __init__(self, addr, allowed, xenapi, logRequests = 1):
- mkdir.parents(os.path.dirname(addr), stat.S_IRWXU, True)
- if self.allow_reuse_address and os.path.exists(addr):
- os.unlink(addr)
-
- TCPXMLRPCServer.__init__(self, addr, allowed, xenapi,
- UnixXMLRPCRequestHandler, logRequests)
diff --git a/tools/python/xen/util/xpopen.py b/tools/python/xen/util/xpopen.py
deleted file mode 100644
index 75aa08e..0000000
--- a/tools/python/xen/util/xpopen.py
+++ /dev/null
@@ -1,182 +0,0 @@
-#
-# Copyright (c) 2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved
-#
-# PSF LICENSE AGREEMENT FOR PYTHON 2.3
-# ------------------------------------
-#
-# 1. This LICENSE AGREEMENT is between the Python Software Foundation
-# ("PSF"), and the Individual or Organization ("Licensee") accessing and
-# otherwise using Python 2.3 software in source or binary form and its
-# associated documentation.
-#
-# 2. Subject to the terms and conditions of this License Agreement, PSF
-# hereby grants Licensee a nonexclusive, royalty-free, world-wide
-# license to reproduce, analyze, test, perform and/or display publicly,
-# prepare derivative works, distribute, and otherwise use Python 2.3
-# alone or in any derivative version, provided, however, that PSF's
-# License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
-# 2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved" are
-# retained in Python 2.3 alone or in any derivative version prepared by
-# Licensee.
-#
-# 3. In the event Licensee prepares a derivative work that is based on
-# or incorporates Python 2.3 or any part thereof, and wants to make
-# the derivative work available to others as provided herein, then
-# Licensee hereby agrees to include in any such work a brief summary of
-# the changes made to Python 2.3.
-#
-# 4. PSF is making Python 2.3 available to Licensee on an "AS IS"
-# basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
-# IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
-# DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
-# FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.3 WILL NOT
-# INFRINGE ANY THIRD PARTY RIGHTS.
-#
-# 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
-# 2.3 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
-# A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.3,
-# OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
-#
-# 6. This License Agreement will automatically terminate upon a material
-# breach of its terms and conditions.
-#
-# 7. Nothing in this License Agreement shall be deemed to create any
-# relationship of agency, partnership, or joint venture between PSF and
-# Licensee. This License Agreement does not grant permission to use PSF
-# trademarks or trade name in a trademark sense to endorse or promote
-# products or services of Licensee, or any third party.
-#
-# 8. By copying, installing or otherwise using Python 2.3, Licensee
-# agrees to be bound by the terms and conditions of this License
-# Agreement.
-#
-# Modifications: Copyright (c) 2005 Christian Limpach <Christian.Limpach at cl.cam.ac.uk>
-# - add support for excluding a list of file descriptors from being
-# closed, allowing access to those file descriptors from the command.
-#
-
-"""Spawn a command with pipes to its stdin, stdout, and optionally stderr.
-
-The normal os.popen(cmd, mode) call spawns a shell command and provides a
-file interface to just the input or output of the process depending on
-whether mode is 'r' or 'w'. This module provides the functions xpopen2(cmd)
-and xpopen3(cmd) which return two or three pipes to the spawned command.
-Optionally exclude a list of file descriptors from being closed, allowing
-access to those file descriptors from the command.
-"""
-
-import os
-import sys
-
-try:
- MAXFD = os.sysconf('SC_OPEN_MAX')
-except (AttributeError, ValueError):
- MAXFD = 256
-
-_active = []
-
-def _cleanup():
- for inst in _active[:]:
- inst.poll()
-
-class xPopen3:
- """Class representing a child process. Normally instances are created
- by the factory functions popen2() and popen3()."""
-
- sts = -1 # Child not completed yet
-
- def __init__(self, cmd, capturestderr=False, bufsize=-1, passfd=(), env=None):
- """The parameter 'cmd' is the shell command to execute in a
- sub-process. The 'capturestderr' flag, if true, specifies that
- the object should capture standard error output of the child process.
- The default is false. If the 'bufsize' parameter is specified, it
- specifies the size of the I/O buffers to/from the child process."""
- _cleanup()
- self.passfd = passfd
- p2cread, p2cwrite = os.pipe()
- c2pread, c2pwrite = os.pipe()
- if capturestderr:
- errout, errin = os.pipe()
- self.pid = os.fork()
- if self.pid == 0:
- # Child
- os.dup2(p2cread, 0)
- os.dup2(c2pwrite, 1)
- if capturestderr:
- os.dup2(errin, 2)
- self._run_child(cmd, env)
- os.close(p2cread)
- self.tochild = os.fdopen(p2cwrite, 'w', bufsize)
- os.close(c2pwrite)
- self.fromchild = os.fdopen(c2pread, 'r', bufsize)
- if capturestderr:
- os.close(errin)
- self.childerr = os.fdopen(errout, 'r', bufsize)
- else:
- self.childerr = None
- _active.append(self)
-
- def _run_child(self, cmd, env):
- if isinstance(cmd, basestring):
- cmd = ['/bin/sh', '-c', cmd]
- for i in range(3, MAXFD):
- if i in self.passfd:
- continue
- try:
- os.close(i)
- except OSError:
- pass
- try:
- if env is None:
- os.execvp(cmd[0], cmd)
- else:
- os.execvpe(cmd[0], cmd, env)
- finally:
- os._exit(127)
-
- def poll(self):
- """Return the exit status of the child process if it has finished,
- or -1 if it hasn't finished yet."""
- if self.sts < 0:
- try:
- pid, sts = os.waitpid(self.pid, os.WNOHANG)
- if pid == self.pid:
- self.sts = sts
- _active.remove(self)
- except os.error:
- pass
- return self.sts
-
- def wait(self):
- """Wait for and return the exit status of the child process."""
- if self.sts < 0:
- pid, sts = os.waitpid(self.pid, 0)
- if pid == self.pid:
- self.sts = sts
- _active.remove(self)
- return self.sts
-
-
-def xpopen2(cmd, bufsize=-1, mode='t', passfd=[], env=None):
- """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is
- specified, it sets the buffer size for the I/O pipes. The file objects
- (child_stdout, child_stdin) are returned."""
- inst = xPopen3(cmd, False, bufsize, passfd, env)
- return inst.fromchild, inst.tochild
-
-def xpopen3(cmd, bufsize=-1, mode='t', passfd=[], env=None):
- """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is
- specified, it sets the buffer size for the I/O pipes. The file objects
- (child_stdout, child_stdin, child_stderr) are returned."""
- inst = xPopen3(cmd, True, bufsize, passfd, env)
- return inst.fromchild, inst.tochild, inst.childerr
-
-def call(*popenargs, **kwargs):
- """Run command with arguments. Wait for command to complete, then
- return the status.
-
- The arguments are the same as for the xPopen3 constructor. Example:
-
- status = call("ls -l")
- """
- return xPopen3(*popenargs, **kwargs).wait()
diff --git a/tools/python/xen/util/xsconstants.py b/tools/python/xen/util/xsconstants.py
deleted file mode 100644
index 8d2e9ec..0000000
--- a/tools/python/xen/util/xsconstants.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2007 International Business Machines Corp.
-# Author: Stefan Berger <stefanb at us.ibm.com>
-#============================================================================
-
-XS_INST_NONE = 0
-XS_INST_BOOT = (1 << 0)
-XS_INST_LOAD = (1 << 1)
-
-XS_POLICY_ACM = (1 << 0)
-XS_POLICY_FLASK = (1 << 1)
-XS_POLICY_DUMMY = (1 << 2)
-XS_POLICY_USE = 0
-
-# Some internal variables used by the Xen-API
-ACM_LABEL_VM = (1 << 0)
-ACM_LABEL_RES = (1 << 1)
-
-# Base for XS error codes for collision avoidance with other error codes
-XSERR_BASE = 0x1000
-
-# XS error codes as used by the Xen-API
-XSERR_SUCCESS = 0
-XSERR_GENERAL_FAILURE = 1 + XSERR_BASE
-XSERR_BAD_XML = 2 + XSERR_BASE # XML is wrong (not according to schema)
-XSERR_XML_PROCESSING = 3 + XSERR_BASE
-XSERR_POLICY_INCONSISTENT = 4 + XSERR_BASE # i.e., bootstrap name not a VM label
-XSERR_FILE_ERROR = 5 + XSERR_BASE
-XSERR_BAD_RESOURCE_FORMAT = 6 + XSERR_BASE # badly formatted resource
-XSERR_BAD_LABEL_FORMAT = 7 + XSERR_BASE
-XSERR_RESOURCE_NOT_LABELED = 8 + XSERR_BASE
-XSERR_RESOURCE_ALREADY_LABELED = 9 + XSERR_BASE
-XSERR_WRONG_POLICY_TYPE = 10 + XSERR_BASE
-XSERR_BOOTPOLICY_INSTALLED = 11 + XSERR_BASE
-XSERR_NO_DEFAULT_BOOT_TITLE = 12 + XSERR_BASE
-XSERR_POLICY_LOAD_FAILED = 13 + XSERR_BASE
-XSERR_POLICY_LOADED = 14 + XSERR_BASE
-XSERR_POLICY_TYPE_UNSUPPORTED = 15 + XSERR_BASE
-XSERR_BAD_CONFLICTSET = 16 + XSERR_BASE
-XSERR_RESOURCE_IN_USE = 17 + XSERR_BASE
-XSERR_BAD_POLICY_NAME = 18 + XSERR_BASE
-XSERR_VERSION_PREVENTS_UPDATE = 19 + XSERR_BASE
-XSERR_BAD_LABEL = 20 + XSERR_BASE
-XSERR_VM_WRONG_STATE = 21 + XSERR_BASE
-XSERR_POLICY_NOT_LOADED = 22 + XSERR_BASE
-XSERR_RESOURCE_ACCESS = 23 + XSERR_BASE
-XSERR_HV_OP_FAILED = 24 + XSERR_BASE
-XSERR_BOOTPOLICY_INSTALL_ERROR = 25 + XSERR_BASE
-XSERR_VM_NOT_AUTHORIZED = 26 + XSERR_BASE
-XSERR_VM_IN_CONFLICT = 27 + XSERR_BASE
-XSERR_POLICY_HAS_DUPLICATES = 28 + XSERR_BASE
-XSERR_LAST = 28 + XSERR_BASE ## KEEP LAST
-
-XSERR_MESSAGES = [
- '',
- 'General Failure',
- 'XML is malformed',
- 'Error while processing XML',
- 'Policy has inconsistencies',
- 'A file access error occurred',
- 'The resource format is not valid',
- 'The label format is not valid',
- 'The resource is not labeld',
- 'The resource is already labeld',
- 'The policy type is wrong',
- 'The system boot policy is installed',
- 'Could not find the default boot title',
- 'Loading of the policy failed',
- 'The policy is loaded',
- 'The policy type is unsupported',
- 'There is a bad conflict set',
- 'The resource is in use',
- 'The policy has an invalid name',
- 'The version of the policy prevents an update',
- 'The label is bad',
- 'Operation not premittend - the VM is in the wrong state',
- 'The policy is not loaded',
- 'Error accessing resource',
- 'Operation failed in hypervisor',
- 'Boot policy installation error',
- 'VM is not authorized to run',
- 'VM label conflicts with another VM',
- 'Duplicate labels or types in policy'
-]
-
-def xserr2string(err):
- if err == XSERR_SUCCESS:
- return "Success"
- if err >= XSERR_GENERAL_FAILURE and \
- err <= XSERR_LAST:
- return XSERR_MESSAGES[err - XSERR_BASE]
- return "Unknown XSERR code '%s'." % (hex(err))
-
-# Policy identifiers used in labels
-ACM_POLICY_ID = 'ACM'
-FLASK_POLICY_ID = 'FLASK'
-
-INVALID_POLICY_PREFIX = 'INV_'
-
-INVALID_SSIDREF = 0xFFFFFFFFL
-
-XS_INACCESSIBLE_LABEL = '__INACCESSIBLE__'
diff --git a/tools/python/xen/util/xsm/__init__.py b/tools/python/xen/util/xsm/__init__.py
deleted file mode 100644
index 139597f..0000000
--- a/tools/python/xen/util/xsm/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/tools/python/xen/util/xsm/acm/__init__.py b/tools/python/xen/util/xsm/acm/__init__.py
deleted file mode 100644
index 8d1c8b6..0000000
--- a/tools/python/xen/util/xsm/acm/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tools/python/xen/util/xsm/acm/acm.py b/tools/python/xen/util/xsm/acm/acm.py
deleted file mode 100644
index 20ff88f..0000000
--- a/tools/python/xen/util/xsm/acm/acm.py
+++ /dev/null
@@ -1,1627 +0,0 @@
-#===========================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 International Business Machines Corp.
-# Author: Reiner Sailer
-# Author: Bryan D. Payne <bdpayne at us.ibm.com>
-# Author: Stefan Berger <stefanb at us.ibm.com>
-#============================================================================
-
-import commands
-import logging
-import os, string, re
-import threading
-import struct
-import stat
-import base64
-from xen.xend import sxp
-from xen.xend import XendConstants
-from xen.xend import XendOptions
-from xen.xend.XendLogging import log
-from xen.xend.XendError import VmError
-from xen.util import dictio, xsconstants, auxbin, xpopen
-from xen.xend.XendConstants import *
-
-#global directories and tools for security management
-install_policy_dir_prefix = auxbin.xen_configdir() + "/acm-security/policies"
-security_dir_prefix = XendOptions.instance().get_xend_security_path()
-policy_dir_prefix = security_dir_prefix + "/policies"
-res_label_filename = policy_dir_prefix + "/resource_labels"
-boot_filename = "/boot/grub/menu.lst"
-altboot_filename = "/boot/grub/grub.conf"
-xensec_tool = "/usr/sbin/xensec_tool"
-
-#global patterns for map file
-#police_reference_tagname = "POLICYREFERENCENAME"
-primary_entry_re = re.compile("\s*PRIMARY\s+.*", re.IGNORECASE)
-secondary_entry_re = re.compile("\s*SECONDARY\s+.*", re.IGNORECASE)
-label_template_re = re.compile(".*security_label_template.xml", re.IGNORECASE)
-mapping_filename_re = re.compile(".*\.map", re.IGNORECASE)
-policy_reference_entry_re = re.compile("\s*POLICYREFERENCENAME\s+.*", re.IGNORECASE)
-vm_label_re = re.compile("\s*LABEL->SSID\s.+[VM|ANY]\s+.*", re.IGNORECASE)
-res_label_re = re.compile("\s*LABEL->SSID\s+RES\s+.*", re.IGNORECASE)
-all_label_re = re.compile("\s*LABEL->SSID\s+.*", re.IGNORECASE)
-access_control_re = re.compile("\s*access_control\s*=", re.IGNORECASE)
-
-#global patterns for boot configuration file
-xen_title_re = re.compile("\s*title\s+XEN", re.IGNORECASE)
-any_title_re = re.compile("\s*title\s", re.IGNORECASE)
-xen_kernel_re = re.compile("\s*kernel.*xen.*\.gz", re.IGNORECASE)
-kernel_ver_re = re.compile("\s*module.*vmlinuz", re.IGNORECASE)
-any_module_re = re.compile("\s*module\s", re.IGNORECASE)
-empty_line_re = re.compile("^\s*$")
-binary_name_re = re.compile(".*[chwall|ste|chwall_ste].*\.bin", re.IGNORECASE)
-policy_name_re = re.compile(".*[chwall|ste|chwall_ste].*", re.IGNORECASE)
-
-#decision hooks known to the hypervisor
-ACMHOOK_sharing = 1
-ACMHOOK_authorization = 2
-ACMHOOK_conflictset = 3
-
-#other global variables
-NULL_SSIDREF = 0
-
-#general Rlock for map files; only one lock for all mapfiles
-__mapfile_lock = threading.RLock()
-__resfile_lock = threading.RLock()
-
-log = logging.getLogger("xend.util.security")
-
-
-#Functions exported through XML-RPC
-xmlrpc_exports = [
- 'on',
- 'set_resource_label',
- 'get_resource_label',
- 'list_labels',
- 'get_labeled_resources',
- 'set_policy',
- 'reset_policy',
- 'get_policy',
- 'activate_policy',
- 'rm_bootpolicy',
- 'get_xstype',
- 'get_domain_label',
- 'set_domain_label'
-]
-
-# Our own exception definition. It is masked (pass) if raised and
-# whoever raises this exception must provide error information.
-class XSMError(Exception):
- def __init__(self,value):
- self.value = value
- def __str__(self):
- return repr(self.value)
-
-
-
-def err(msg):
- """Raise ACM exception.
- """
- raise XSMError(msg)
-
-
-
-active_policy = None
-
-
-def mapfile_lock():
- __mapfile_lock.acquire()
-
-def mapfile_unlock():
- __mapfile_lock.release()
-
-
-def resfile_lock():
- __resfile_lock.acquire()
-
-def resfile_unlock():
- __resfile_lock.release()
-
-
-def refresh_security_policy():
- """
- retrieves security policy
- """
- global active_policy
-
- active_policy = 'INACCESSIBLE'
-
- if os.access("/proc/xen/privcmd", os.R_OK|os.W_OK):
- active_policy = "INACTIVE"
-
-def get_active_policy_name():
- refresh_security_policy()
- return active_policy
-
-# now set active_policy
-refresh_security_policy()
-
-def on():
- """
- returns none if security policy is off (not compiled),
- any string otherwise, use it: if not security.on() ...
- """
- if get_active_policy_name() not in ['INACTIVE', 'NULL', '']:
- return xsconstants.XS_POLICY_ACM
- return 0
-
-
-def calc_dom_ssidref_from_info(info):
- """
- Calculate a domain's ssidref from the security_label in its
- info.
- This function is called before the domain is started and
- makes sure that:
- - the type of the policy is the same as indicated in the label
- - the name of the policy is the same as indicated in the label
- - calculates an up-to-date ssidref for the domain
- The latter is necessary since the domain's ssidref could have
- changed due to changes to the policy.
- """
- import xen.xend.XendConfig
- if isinstance(info, xen.xend.XendConfig.XendConfig):
- if info.has_key('security_label'):
- seclab = info['security_label']
- tmp = seclab.split(":")
- if len(tmp) != 3:
- raise VmError("VM label '%s' in wrong format." % seclab)
- typ, policyname, vmlabel = seclab.split(":")
- if typ != xsconstants.ACM_POLICY_ID:
- raise VmError("Policy type '%s' must be changed." % typ)
- if get_active_policy_name() != policyname:
- raise VmError("Active policy '%s' different than "
- "what in VM's label ('%s')." %
- (get_active_policy_name(), policyname))
- ssidref = label2ssidref(vmlabel, policyname, "dom")
- return ssidref
- else:
- return 0x0
- raise VmError("security.calc_dom_ssidref_from_info: info of type '%s'"
- "not supported." % type(info))
-
-
-def getmapfile(policyname):
- """
- in: if policyname is None then the currently
- active hypervisor policy is used
- out: 1. primary policy, 2. secondary policy,
- 3. open file descriptor for mapping file, and
- 4. True if policy file is available, False otherwise
- """
- if not policyname:
- policyname = get_active_policy_name()
- map_file_ok = False
- primary = None
- secondary = None
- #strip last part of policy as file name part
- policy_dir_list = string.split(policyname, ".")
- policy_file = policy_dir_list.pop()
- if len(policy_dir_list) > 0:
- policy_dir = string.join(policy_dir_list, "/") + "/"
- else:
- policy_dir = ""
-
- map_filename = policy_dir_prefix + "/" + policy_dir + policy_file + ".map"
- # check if it is there, if not check if policy file is there
- if not os.path.isfile(map_filename):
- policy_filename = policy_dir_prefix + "/" + policy_dir + policy_file + "-security_policy.xml"
- if not os.path.isfile(policy_filename):
- err("Policy file \'" + policy_filename + "\' not found.")
- else:
- err("Mapping file \'" + map_filename + "\' not found.")
-
- f = open(map_filename)
- for line in f:
- if policy_reference_entry_re.match(line):
- l = line.split()
- if (len(l) == 2) and (l[1] == policyname):
- map_file_ok = True
- elif primary_entry_re.match(line):
- l = line.split()
- if len(l) == 2:
- primary = l[1]
- elif secondary_entry_re.match(line):
- l = line.split()
- if len(l) == 2:
- secondary = l[1]
- f.close()
- f = open(map_filename)
- if map_file_ok and primary and secondary:
- return (primary, secondary, f, True)
- else:
- err("Mapping file inconsistencies found.")
-
-
-
-def ssidref2label(ssidref_var):
- """
- returns labelname corresponding to ssidref;
- maps current policy to default directory
- to find mapping file
- """
- #1. translated permitted input formats
- if isinstance(ssidref_var, str):
- ssidref_var.strip()
- if ssidref_var[0:2] == "0x":
- ssidref = int(ssidref_var[2:], 16)
- else:
- ssidref = int(ssidref_var)
- elif isinstance(ssidref_var, int):
- ssidref = ssidref_var
- else:
- err("Instance type of ssidref not supported (must be of type 'str' or 'int')")
-
- if ssidref == 0:
- from xen.util.acmpolicy import ACM_LABEL_UNLABELED
- return ACM_LABEL_UNLABELED
-
- try:
- mapfile_lock()
-
- (primary, secondary, f, pol_exists) = getmapfile(None)
- if not f:
- if (pol_exists):
- err("Mapping file for policy not found.")
- else:
- err("Policy file for \'" + get_active_policy_name() +
- "\' not found.")
-
- #2. get labelnames for both ssidref parts
- pri_ssid = ssidref & 0xffff
- sec_ssid = ssidref >> 16
- pri_null_ssid = NULL_SSIDREF & 0xffff
- sec_null_ssid = NULL_SSIDREF >> 16
- pri_labels = []
- sec_labels = []
- labels = []
-
- for line in f:
- l = line.split()
- if (len(l) < 5) or (l[0] != "LABEL->SSID"):
- continue
- if primary and (l[2] == primary) and (int(l[4], 16) == pri_ssid):
- pri_labels.append(l[3])
- if secondary and (l[2] == secondary) and (int(l[4], 16) == sec_ssid):
- sec_labels.append(l[3])
- f.close()
- finally:
- mapfile_unlock()
-
- #3. get the label that is in both lists (combination must be a single label)
- if (primary == "CHWALL") and (pri_ssid == pri_null_ssid) and (sec_ssid != sec_null_ssid):
- labels = sec_labels
- elif (secondary == "CHWALL") and (pri_ssid != pri_null_ssid) and (sec_ssid == sec_null_ssid):
- labels = pri_labels
- elif secondary == "NULL":
- labels = pri_labels
- else:
- for i in pri_labels:
- for j in sec_labels:
- if (i==j):
- labels.append(i)
- if len(labels) != 1:
- err("Label for ssidref \'" + str(ssidref) +
- "\' unknown or not unique in policy \'" + active_policy + "\'")
-
- return labels[0]
-
-
-
-def label2ssidref(labelname, policyname, typ):
- """
- returns ssidref corresponding to labelname;
- maps current policy to default directory
- to find mapping file """
-
- if policyname in ['NULL', 'INACTIVE', 'INACCESSIBLE' ]:
- err("Cannot translate labels for \'" + policyname + "\' policy.")
-
- allowed_types = ['ANY']
- if typ == 'dom':
- allowed_types.append('VM')
- elif typ == 'res':
- allowed_types.append('RES')
- else:
- err("Invalid type. Must specify 'dom' or 'res'.")
-
- try:
- mapfile_lock()
- (primary, secondary, f, pol_exists) = getmapfile(policyname)
-
- #2. get labelnames for ssidref parts and find a common label
- pri_ssid = []
- sec_ssid = []
- for line in f:
- l = line.split()
- if (len(l) < 5) or (l[0] != "LABEL->SSID"):
- continue
- if primary and (l[1] in allowed_types) and \
- (l[2] == primary) and \
- (l[3] == labelname):
- pri_ssid.append(int(l[4], 16))
- if secondary and (l[1] in allowed_types) and \
- (l[2] == secondary) and \
- (l[3] == labelname):
- sec_ssid.append(int(l[4], 16))
- f.close()
- if (typ == 'res') and (primary == "CHWALL") and (len(pri_ssid) == 0):
- pri_ssid.append(NULL_SSIDREF)
- elif (typ == 'res') and (secondary == "CHWALL") and \
- (len(sec_ssid) == 0):
- sec_ssid.append(NULL_SSIDREF)
-
- #3. sanity check and composition of ssidref
- if (len(pri_ssid) == 0) or ((len(sec_ssid) == 0) and \
- (secondary != "NULL")):
- err("Label \'" + labelname + "\' not found.")
- elif (len(pri_ssid) > 1) or (len(sec_ssid) > 1):
- err("Label \'" + labelname + "\' not unique in policy (policy error)")
- if secondary == "NULL":
- return pri_ssid[0]
- else:
- return (sec_ssid[0] << 16) | pri_ssid[0]
- finally:
- mapfile_unlock()
-
-
-def refresh_ssidref(config):
- """
- looks up ssidref from security field
- and refreshes the value if label exists
- """
- #called by dom0, policy could have changed after xen.utils.security was initialized
- refresh_security_policy()
-
- security = None
- if isinstance(config, dict):
- security = config['security']
- elif isinstance(config, list):
- security = sxp.child_value(config, 'security')
- else:
- err("Instance type of config parameter not supported.")
- if not security:
- #nothing to do (no security label attached)
- return config
-
- policyname = None
- labelname = None
- # compose new security field
- for idx in range(0, len(security)):
- if security[idx][0] == 'ssidref':
- security.pop(idx)
- break
- elif security[idx][0] == 'access_control':
- for jdx in [1, 2]:
- if security[idx][jdx][0] == 'label':
- labelname = security[idx][jdx][1]
- elif security[idx][jdx][0] == 'policy':
- policyname = security[idx][jdx][1]
- else:
- err("Illegal field in access_control")
- #verify policy is correct
- if active_policy != policyname:
- err("Policy \'" + str(policyname) +
- "\' in label does not match active policy \'"
- + str(active_policy) +"\'!")
-
- new_ssidref = label2ssidref(labelname, policyname, 'dom')
- if not new_ssidref:
- err("SSIDREF refresh failed!")
-
- security.append([ 'ssidref',str(new_ssidref)])
- security = ['security', security ]
-
- for idx in range(0,len(config)):
- if config[idx][0] == 'security':
- config.pop(idx)
- break
- config.append(security)
-
-
-
-def get_ssid(domain):
- """
- enables domains to retrieve the label / ssidref of a running domain
- """
- err("No policy active.")
-
-
-
-def get_decision(arg1, arg2):
- """
- enables domains to retrieve access control decisions from
- the hypervisor Access Control Module.
- IN: args format = ['domid', id] or ['ssidref', ssidref]
- or ['access_control', ['policy', policy], ['label', label], ['type', type]]
- """
- err("No policy active.")
-
-
-def has_authorization(ssidref):
- """ Check if the domain with the given ssidref has authorization to
- run on this system. To have authoriztion dom0's STE types must
- be a superset of that of the domain's given through its ssidref.
- """
- return True
-
-
-def hv_chg_policy(bin_pol, del_array, chg_array):
- """
- Change the binary policy in the hypervisor
- The 'del_array' and 'chg_array' give hints about deleted ssidrefs
- and changed ssidrefs which can be due to deleted VM labels
- or reordered VM labels
- """
- err("No policy active.")
-
-def hv_get_policy():
- """
- Gte the binary policy enforced in the hypervisor
- """
- err("No policy active.")
-
-
-def is_in_conflict(ssidref):
- """ Check whether the given ssidref is in conflict with any running
- domain.
- """
- return False
-
-
-def set_policy(xs_type, xml, flags, overwrite):
- """
- Xend exports this function via XML-RPC
- """
- from xen.xend import XendXSPolicyAdmin
- xspoladmin = XendXSPolicyAdmin.XSPolicyAdminInstance()
- try:
- acmpol, rc, errors = \
- xspoladmin.add_acmpolicy_to_system(xml,
- int(flags),
- True)
- return rc, base64.b64encode(errors)
- except Exception, e:
- err(str(e))
-
-
-def reset_policy():
- """
- Xend exports this function via XML-RPC
- """
- from xen.xend import XendXSPolicyAdmin
- xspoladmin = XendXSPolicyAdmin.XSPolicyAdminInstance()
- try:
- acmpol, rc, errors = \
- xspoladmin.reset_acmpolicy()
- return rc, base64.b64encode(errors)
- except Exception, e:
- err(str(e))
-
-
-def get_policy():
- """
- Xend exports this function via XML-RPC
- """
- from xen.xend import XendXSPolicyAdmin
- poladmin = XendXSPolicyAdmin.XSPolicyAdminInstance()
- try:
- policy = poladmin.get_loaded_policy()
- if policy != None:
- return policy.toxml(), poladmin.get_policy_flags(policy)
- except Exception, e:
- err(str(e))
- return "", 0
-
-def activate_policy(flags):
- """
- Xend exports this function via XML-RPC
- """
- from xen.xend import XendXSPolicyAdmin
- poladmin = XendXSPolicyAdmin.XSPolicyAdminInstance()
- try:
- policies = poladmin.get_policies()
- if len(policies) > 0:
- flags = int(flags)
- irc = poladmin.activate_xspolicy(policies[0], flags)
- return irc
- except Exception, e:
- err("Error while activating the policy: " % str(e))
- return 0
-
-
-def rm_bootpolicy():
- """
- Xend exports this function via XML-RPC
- """
- from xen.xend import XendXSPolicyAdmin
- rc = XendXSPolicyAdmin.XSPolicyAdminInstance().rm_bootpolicy()
- if rc != xsconstants.XSERR_SUCCESS:
- err("Error while removing boot policy: %s" % \
- str(xsconstants.xserr2string(-rc)))
- return rc
-
-
-def get_xstype():
- """
- Xend exports this function via XML-RPC
- """
- from xen.xend import XendXSPolicyAdmin
- return XendXSPolicyAdmin.XSPolicyAdminInstance().isXSEnabled()
-
-
-def get_domain_label(domain):
- """
- Xend exports this function via XML-RPC
- """
- from xen.xend import XendDomain
- dom = XendDomain.instance().domain_lookup_nr(domain)
- if dom:
- seclab = dom.get_security_label()
- return seclab
- else:
- err("Domain not found.")
-
-
-def set_domain_label(domain, seclab, old_seclab):
- """
- Xend exports this function via XML-RPC
- """
- from xen.xend import XendDomain
- dom = XendDomain.instance().domain_lookup_nr(domain)
- if dom:
- results = dom.set_security_label(seclab, old_seclab)
- rc, errors, old_label, new_ssidref = results
- return rc, new_ssidref
- else:
- err("Domain not found.")
-
-
-def dump_policy():
- if active_policy in ['NULL', 'INACTIVE', 'INACCESSIBLE' ]:
- err("\'" + active_policy + "\' policy. Nothing to dump.")
-
- (ret, output) = commands.getstatusoutput(xensec_tool + " getpolicy")
- if ret:
- err("Dumping hypervisor policy failed:\n" + output)
-
- print output
-
-
-def dump_policy_file(filename, ssidref=None):
- ssid = ""
- if ssidref:
- ssid = " " + str(ssidref)
- (ret, output) = commands.getstatusoutput(xensec_tool + " dumppolicy " +
- filename + ssid)
- if ret:
- err("Dumping policy failed:\n" + output)
-
- print output
-
-
-def list_labels(policy_name, ltype):
- """
- Xend exports this function via XML-RPC
-
- List the VM,resource or any kind of labels contained in the
- given policy. If no policy name is given, the currently
- active policy's label will be returned if they exist.
- """
- if not policy_name:
- if active_policy in [ 'NULL', 'INACTIVE', "" ]:
- err("Current policy \'" + active_policy + "\' "
- "has no labels defined.\n")
-
- if not ltype or ltype == 'dom':
- condition = vm_label_re
- elif ltype == 'res':
- condition = res_label_re
- elif ltype == 'any':
- condition = all_label_re
- else:
- err("Unknown label type \'" + ltype + "\'")
-
- try:
- mapfile_lock()
-
- (primary, secondary, f, pol_exists) = getmapfile(policy_name)
- if not f:
- if pol_exists:
- err("Cannot find mapfile for policy \'" + policy_name + "\'.\n")
- else:
- err("Unknown policy \'" + policy_name + "\'")
-
- labels = []
- for line in f:
- if condition.match(line):
- label = line.split()[3]
- if label not in labels:
- labels.append(label)
- finally:
- mapfile_unlock()
-
- if '__NULL_LABEL__' in labels:
- labels.remove('__NULL_LABEL__')
-
- return labels
-
-
-def get_res_label(resource):
- """Returns resource label information (policytype, label, policy) if
- it exists. Otherwise returns null label and policy.
- """
- def default_res_label():
- ssidref = NULL_SSIDREF
- if on():
- label = ssidref2label(ssidref)
- else:
- label = None
- return (xsconstants.ACM_POLICY_ID, 'NULL', label)
-
-
- tmp = get_resource_label(resource)
- if len(tmp) == 2:
- policytype = xsconstants.ACM_POLICY_ID
- policy, label = tmp
- elif len(tmp) == 3:
- policytype, policy, label = tmp
- else:
- policytype, policy, label = default_res_label()
-
- return (policytype, label, policy)
-
-
-def get_res_security_details(resource):
- """Returns the (label, ssidref, policy) associated with a given
- resource from the global resource label file.
- """
- def default_security_details():
- ssidref = NULL_SSIDREF
- if on():
- label = ssidref2label(ssidref)
- else:
- label = None
- policy = active_policy
- return (label, ssidref, policy)
-
- # find the entry associated with this resource
- (policytype, label, policy) = get_res_label(resource)
- if policy == 'NULL':
- log.info("Resource label for "+resource+" not in file, using DEFAULT.")
- return default_security_details()
-
- if policytype != xsconstants.ACM_POLICY_ID:
- raise VmError("Unknown policy type '%s in label for resource '%s'" %
- (policytype, resource))
-
- # is this resource label for the running policy?
- if policy == active_policy:
- ssidref = label2ssidref(label, policy, 'res')
- elif label == xsconstants.XS_INACCESSIBLE_LABEL:
- ssidref = NULL_SSIDREF
- else:
- log.info("Resource label not for active policy, using DEFAULT.")
- return default_security_details()
-
- return (label, ssidref, policy)
-
-def security_label_to_details(seclab):
- """ Convert a Xen-API type of security label into details """
- def default_security_details():
- ssidref = NULL_SSIDREF
- if on():
- label = ssidref2label(ssidref)
- else:
- label = None
- policy = active_policy
- return (label, ssidref, policy)
-
- (policytype, policy, label) = seclab.split(":")
-
- # is this resource label for the running policy?
- if policy == active_policy:
- ssidref = label2ssidref(label, policy, 'res')
- else:
- log.info("Resource label not for active policy, using DEFAULT.")
- return default_security_details()
-
- return (label, ssidref, policy)
-
-def unify_resname(resource, mustexist=True):
- """Makes all resource locations absolute. In case of physical
- resources, '/dev/' is added to local file names"""
-
- if not resource:
- return resource
-
- # sanity check on resource name
- try:
- (typ, resfile) = resource.split(":", 1)
- except:
- err("Resource spec '%s' contains no ':' delimiter" % resource)
-
- if typ == "tap":
- try:
- (subtype, resfile) = resfile.split(":")
- except:
- err("Resource spec '%s' contains no tap subtype" % resource)
-
- if typ in ["phy"]:
- if not resfile.startswith("/"):
- resfile = "/dev/" + resfile
- if mustexist:
- resfile = os.path.realpath(resfile)
- try:
- stats = os.lstat(resfile)
- if not (stat.S_ISBLK(stats[stat.ST_MODE])):
- err("Invalid resource")
- except:
- err("Invalid resource")
-
- if typ in [ "file", "tap" ]:
- resfile = os.path.realpath(resfile)
- if mustexist and not os.path.isfile(resfile):
- err("Invalid resource")
-
- if typ == "vlan":
- try:
- vlan = int(resfile)
- if vlan < 1 or vlan > 4095:
- err("VLAN ID %d out of range." % vlan)
- except Exception, e:
- err("Invalid VLAN : %s" % resfile)
-
-
- #file: resources must be specified with absolute path
- #vlan resources don't start with '/'
- if typ != "vlan":
- if (not resfile.startswith("/")) or \
- (mustexist and not os.path.exists(resfile)):
- err("Invalid resource.")
-
- # from here on absolute file names with resources
- if typ == "tap":
- typ = typ + ":" + subtype
- resource = typ + ":" + resfile
- return resource
-
-
-def res_security_check(resource, domain_label):
- """Checks if the given resource can be used by the given domain
- label. Returns 1 if the resource can be used, otherwise 0.
- """
- rtnval = 1
-
- # if security is on, ask the hypervisor for a decision
- if on():
- #build canonical resource name
- resource = unify_resname(resource)
-
- (label, ssidref, policy) = get_res_security_details(resource)
- domac = ['access_control']
- domac.append(['policy', active_policy])
- domac.append(['label', domain_label])
- domac.append(['type', 'dom'])
- decision = get_decision(domac, ['ssidref', str(ssidref)])
-
- # provide descriptive error messages
- if decision == 'DENIED':
- if label == ssidref2label(NULL_SSIDREF):
- raise XSMError("Resource '"+resource+"' is not labeled")
- rtnval = 0
- else:
- raise XSMError("Permission denied for resource '"+resource+"' because label '"+label+"' is not allowed")
- rtnval = 0
-
- # security is off, make sure resource isn't labeled
- else:
- # Note, we can't canonicalise the resource here, because people using
- # xm without ACM are free to use relative paths.
- (policytype, label, policy) = get_res_label(resource)
- if policy != 'NULL':
- raise XSMError("Security is off, but '"+resource+"' is labeled")
- rtnval = 0
-
- return rtnval
-
-def res_security_check_xapi(rlabel, rssidref, rpolicy, xapi_dom_label):
- """Checks if the given resource can be used by the given domain
- label. Returns 1 if the resource can be used, otherwise 0.
- """
- rtnval = 1
- # if security is on, ask the hypervisor for a decision
- if on():
- if rlabel == xsconstants.XS_INACCESSIBLE_LABEL:
- return 0
- typ, dpolicy, domain_label = xapi_dom_label.split(":")
- if not dpolicy or not domain_label:
- raise VmError("VM security label in wrong format.")
- if active_policy != rpolicy:
- raise VmError("Resource's policy '%s' != active policy '%s'" %
- (rpolicy, active_policy))
- domac = ['access_control']
- domac.append(['policy', active_policy])
- domac.append(['label', domain_label])
- domac.append(['type', 'dom'])
- decision = get_decision(domac, ['ssidref', str(rssidref)])
-
- log.info("Access Control Decision : %s" % decision)
- # provide descriptive error messages
- if decision == 'DENIED':
- if rlabel == ssidref2label(NULL_SSIDREF):
- #raise XSMError("Resource is not labeled")
- rtnval = 0
- else:
- #raise XSMError("Permission denied for resource because label '"+rlabel+"' is not allowed")
- rtnval = 0
-
- # security is off, make sure resource isn't labeled
- else:
- # Note, we can't canonicalise the resource here, because people using
- # xm without ACM are free to use relative paths.
- if rpolicy != 'NULL':
- #raise XSMError("Security is off, but resource is labeled")
- rtnval = 0
-
- return rtnval
-
-
-def validate_label_xapi(xapi_label, dom_or_res):
- """
- Make sure that this label is part of the currently enforced policy
- and that it references the current policy.
- dom_or_res defines whether this is a VM ('res') or resource label
- ('res')
- """
- tmp = xapi_label.split(":")
- if len(tmp) != 3:
- return -xsconstants.XSERR_BAD_LABEL_FORMAT
- policytyp, policyref, label = tmp
- return validate_label(policytyp, policyref, label, dom_or_res)
-
-
-def validate_label(policytype, policyref, label, dom_or_res):
- """
- Make sure that this label is part of the currently enforced policy
- and that it reference the current policy.
- """
- if policytype != xsconstants.ACM_POLICY_ID:
- return -xsconstants.XSERR_WRONG_POLICY_TYPE
- if not policytype or not label:
- return -xsconstants.XSERR_BAD_LABEL_FORMAT
- rc = xsconstants.XSERR_SUCCESS
- if label == xsconstants.XS_INACCESSIBLE_LABEL:
- return rc
- from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
- curpol = XSPolicyAdminInstance().get_loaded_policy()
- if not curpol or curpol.get_name() != policyref:
- rc = -xsconstants.XSERR_BAD_LABEL
- else:
- try:
- label2ssidref(label, curpol.get_name() , dom_or_res)
- except:
- rc = -xsconstants.XSERR_BAD_LABEL
- return rc
-
-
-def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi):
- """Assign a resource label to a resource
- @param resource: The name of a resource, i.e., "phy:/dev/hda", or
- "tap:qcow:/path/to/file.qcow"
-
- @param reslabel_xapi: A resource label foramtted as in all other parts of
- the Xen-API, i.e., ACM:xm-test:blue"
- @rtype: int
- @return Success (0) or failure value (< 0)
- """
- olabel = ""
- if reslabel_xapi == "":
- return rm_resource_label(resource, oldlabel_xapi)
-
- rc = validate_label_xapi(reslabel_xapi, 'res')
- if rc != xsconstants.XSERR_SUCCESS:
- return rc
-
- if oldlabel_xapi not in [ "" ]:
- tmp = oldlabel_xapi.split(":")
- if len(tmp) != 3:
- return -xsconstants.XSERR_BAD_LABEL_FORMAT
- otyp, opolicyref, olabel = tmp
- # Only ACM is supported
- if otyp != xsconstants.ACM_POLICY_ID and \
- otyp != xsconstants.INVALID_POLICY_PREFIX + \
- xsconstants.ACM_POLICY_ID:
- return -xsconstants.XSERR_WRONG_POLICY_TYPE
- typ, policyref, label = reslabel_xapi.split(":")
- return set_resource_label(resource, typ, policyref, label, olabel)
-
-
-def is_resource_in_use(resource):
- """
- Domain-0 'owns' resources of type 'VLAN', the rest are owned by
- the guests.
- """
- from xen.xend import XendDomain
- lst = []
- if resource.startswith('vlan'):
- from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
- curpol = XSPolicyAdminInstance().get_loaded_policy()
- policytype, label, policy = get_res_label(resource)
- if curpol and \
- policytype == xsconstants.ACM_POLICY_ID and \
- policy == curpol.get_name() and \
- label in curpol.policy_get_resourcelabel_names():
- # VLAN is in use.
- lst.append(XendDomain.instance().
- get_vm_by_uuid(XendDomain.DOM0_UUID))
- else:
- dominfos = XendDomain.instance().list('all')
- for dominfo in dominfos:
- if is_resource_in_use_by_dom(dominfo, resource):
- lst.append(dominfo)
- return lst
-
-def devices_equal(res1, res2, mustexist=True):
- """ Determine whether two devices are equal """
- return (unify_resname(res1, mustexist) ==
- unify_resname(res2, mustexist))
-
-def is_resource_in_use_by_dom(dominfo, resource):
- """ Determine whether a resources is in use by a given domain
- @return True or False
- """
- if not dominfo.domid:
- return False
- if dominfo._stateGet() not in [ DOM_STATE_RUNNING ]:
- return False
- devs = dominfo.info['devices']
- uuids = devs.keys()
- for uuid in uuids:
- dev = devs[uuid]
- if len(dev) >= 2 and dev[1].has_key('uname'):
- # dev[0] is type, i.e. 'vbd'
- if devices_equal(dev[1]['uname'], resource, mustexist=False):
- log.info("RESOURCE IN USE: Domain %d uses %s." %
- (dominfo.domid, resource))
- return True
- return False
-
-
-def get_domain_resources(dominfo):
- """ Collect all resources of a domain in a map where each entry of
- the map is a list.
- Entries are strored in the following formats:
- tap:qcow:/path/xyz.qcow
- """
- resources = { 'vbd' : [], 'tap' : [], 'vif' : []}
- devs = dominfo.info['devices']
- uuids = devs.keys()
- for uuid in uuids:
- dev = devs[uuid]
- typ = dev[0]
- if typ in [ 'vbd', 'tap' ]:
- resources[typ].append(dev[1]['uname'])
- if typ in [ 'vif' ]:
- sec_lab = dev[1].get('security_label')
- if sec_lab:
- resources[typ].append(sec_lab)
- else:
- # !!! This should really get the label of the domain
- # or at least a resource label that has the same STE type
- # as the domain has
- from xen.util.acmpolicy import ACM_LABEL_UNLABELED
- resources[typ].append("%s:%s:%s" %
- (xsconstants.ACM_POLICY_ID,
- active_policy,
- ACM_LABEL_UNLABELED))
-
- return resources
-
-
-def resources_compatible_with_vmlabel(xspol, dominfo, vmlabel):
- """
- Check whether the resources' labels are compatible with the
- given VM label. This is a function to be used when for example
- a running domain is to get the new label 'vmlabel'
- """
- if not xspol:
- return False
-
- try:
- resfile_lock()
- try:
- access_control = dictio.dict_read("resources",
- res_label_filename)
- except:
- # No labeled resources -> must be compatible
- return True
- return __resources_compatible_with_vmlabel(xspol, dominfo, vmlabel,
- access_control)
- finally:
- resfile_unlock()
- return False
-
-
-def __resources_compatible_with_vmlabel(xspol, dominfo, vmlabel,
- access_control,
- is_policy_update=False):
- """
- Check whether the resources' labels are compatible with the
- given VM label. The access_control parameter provides a
- dictionary of the resource name to resource label mappings
- under which the evaluation should be done.
- Call this only for a paused or running domain.
- """
- def collect_labels(reslabels, s_label, polname):
- if len(s_label) != 3 or polname != s_label[1]:
- return False
- label = s_label[2]
- if not label in reslabels:
- reslabels.append(label)
- return True
-
- resources = get_domain_resources(dominfo)
- reslabels = [] # all resource labels
-
- polname = xspol.get_name()
- for key, value in resources.items():
- if key in [ 'vbd', 'tap' ]:
- for res in resources[key]:
- if not res in access_control:
- label = [xsconstants.ACM_POLICY_ID,
- xspol.get_name(),
- ACM_LABEL_UNLABELED]
- else:
- label = access_control[res]
- if not collect_labels(reslabels, label, polname):
- return False
- elif key in [ 'vif' ]:
- for xapi_label in value:
- label = xapi_label.split(":")
- from xen.util.acmpolicy import ACM_LABEL_UNLABELED
- if not (is_policy_update and \
- label[2] == ACM_LABEL_UNLABELED):
- if not collect_labels(reslabels, label, polname):
- return False
- else:
- log.error("Unhandled device type: %s" % key)
- return False
-
- # Check that all resource labes have a common STE type with the
- # vmlabel
- if len(reslabels) > 0:
- rc = xspol.policy_check_vmlabel_against_reslabels(vmlabel, reslabels)
- else:
- rc = True
- log.info("vmlabel=%s, reslabels=%s, rc=%s" %
- (vmlabel, reslabels, str(rc)))
- return rc;
-
-def set_resource_label(resource, policytype, policyref, reslabel, \
- oreslabel = None):
- """
- Xend exports this function via XML-RPC.
-
- Assign a label to a resource
- If the old label (oreslabel) is given, then the resource must have
- that old label.
- A resource label may be changed if
- - the resource is not in use
- @param resource : The name of a resource, i.e., "phy:/dev/hda"
- @param policyref : The name of the policy
- @param reslabel : the resource label within the policy
- @param oreslabel : optional current resource label
-
- @rtype: int
- @return Success (0) or failure value (< 0)
- """
-
-
- try:
- resource = unify_resname(resource, mustexist=False)
- except Exception:
- return -xsconstants.XSERR_BAD_RESOURCE_FORMAT
-
- try:
- resfile_lock()
- mapfile_lock()
-
- if reslabel not in [ '', xsconstants.XS_INACCESSIBLE_LABEL ]:
- ssidref = label2ssidref(reslabel, policyref, 'res')
-
- domains = is_resource_in_use(resource)
- if len(domains) > 0:
- return -xsconstants.XSERR_RESOURCE_IN_USE
-
- access_control = {}
- try:
- access_control = dictio.dict_read("resources", res_label_filename)
- except:
- pass
- if oreslabel:
- if not access_control.has_key(resource):
- return -xsconstants.XSERR_BAD_LABEL
- tmp = access_control[resource]
- if len(tmp) != 3:
- return -xsconstants.XSERR_BAD_LABEL
- if tmp[2] != oreslabel:
- return -xsconstants.XSERR_BAD_LABEL
- if resource.startswith('vlan:'):
- for key, value in access_control.items():
- if value == tuple([policytype, policyref, reslabel]) and \
- key.startswith('vlan:'):
- return -xsconstants.XSERR_BAD_LABEL
-
- if reslabel == xsconstants.XS_INACCESSIBLE_LABEL:
- policytype = xsconstants.ACM_POLICY_ID
- policyref = '*'
-
- if reslabel != "":
- new_entry = { resource : tuple([policytype, policyref, reslabel])}
- access_control.update(new_entry)
- command = "add"
- reslbl = ":".join([policytype, policyref, reslabel])
- else:
- if access_control.has_key(resource):
- del access_control[resource]
- command = "remove"
- reslbl = ""
- run_resource_label_change_script(resource, reslbl, command)
- dictio.dict_write(access_control, "resources", res_label_filename)
- finally:
- resfile_unlock()
- mapfile_unlock()
- return xsconstants.XSERR_SUCCESS
-
-def rm_resource_label(resource, oldlabel_xapi):
- """Remove a resource label from a physical resource
- @param resource: The name of a resource, i.e., "phy:/dev/hda"
-
- @rtype: int
- @return Success (0) or failure value (< 0)
- """
- tmp = oldlabel_xapi.split(":")
- if len(tmp) != 3:
- return -xsconstants.XSERR_BAD_LABEL_FORMAT
- otyp, opolicyref, olabel = tmp
- # Only ACM is supported
- if otyp != xsconstants.ACM_POLICY_ID and \
- otyp != xsconstants.INVALID_POLICY_PREFIX + xsconstants.ACM_POLICY_ID:
- return -xsconstants.XSERR_WRONG_POLICY_TYPE
- return set_resource_label(resource, "", "", "", olabel)
-
-def get_resource_label_xapi(resource):
- """Get the assigned resource label of a physical resource
- in the format used by then Xen-API, i.e., "ACM:xm-test:blue"
-
- @rtype: string
- @return the string representing policy type, policy name and label of
- the resource
- """
- res = get_resource_label(resource)
- return format_resource_label(res)
-
-def format_resource_label(res):
- if res:
- if len(res) == 2:
- return xsconstants.ACM_POLICY_ID + ":" + res[0] + ":" + res[1]
- if len(res) == 3:
- return ":".join(res)
- return ""
-
-def get_resource_label(resource):
- """
- Xend exports this function via XML-RPC.
-
- Get the assigned resource label of a given resource
- @param resource: The name of a resource, i.e., "phy:/dev/hda"
-
- @rtype: list
- @return tuple of (policy name, resource label), i.e., (xm-test, blue)
- """
- try:
- resource = unify_resname(resource, mustexist=False)
- except Exception:
- return []
-
- reslabel_map = get_labeled_resources()
-
- if reslabel_map.has_key(resource):
- return list(reslabel_map[resource])
- else:
- #Try to resolve each label entry
- for key, value in reslabel_map.items():
- try:
- if resource == unify_resname(key):
- return list(value)
- except:
- pass
-
- return []
-
-
-def get_labeled_resources_xapi():
- """ Get a map of all labeled resource with the labels formatted in the
- xen-api resource label format.
- """
- reslabel_map = get_labeled_resources()
- for key, labeldata in reslabel_map.items():
- reslabel_map[key] = format_resource_label(labeldata)
- return reslabel_map
-
-
-def get_labeled_resources():
- """
- Xend exports this function via XML-RPC
-
- Get a map of all labeled resources.
- @rtype: list
- @return list of labeled resources
- """
- try:
- resfile_lock()
- try:
- access_control = dictio.dict_read("resources", res_label_filename)
- except:
- return {}
- finally:
- resfile_unlock()
- return access_control
-
-
-def relabel_domains(relabel_list):
- """
- Relabel the given domains to have a new ssidref.
- @param relabel_list: a list containing tuples of domid, ssidref
- example: [ [0, 0x00020002] ]
- """
- rc = -xsconstants.XSERR_GENERAL_FAILURE
- errors = ""
- return rc, errors
-
-
-def __update_label_policy_change(sec_lab,
- cur_poltype,
- cur_polname,
- new_poltype,
- new_polname,
- polnew_labels,
- label_map):
- """
- Determine a new resource label given the new policy's type
- and name and the new policy's (resource/VM) labels and the
- (resource/VM) label map that indicates renaming rules for
- labels.
- """
- is_deleted = False
- policytype, policy, label = sec_lab
-
- if cur_poltype != policytype or \
- cur_polname != policy:
- return sec_lab, is_deleted
-
- if policytype != xsconstants.ACM_POLICY_ID:
- return sec_lab, is_deleted
- elif label_map.has_key(label) and policy == cur_polname:
- # renaming of an active label; policy may have been renamed
- label = label_map[label]
- polname = new_polname
- elif label not in polnew_labels:
- # label been removed
- policytype = xsconstants.INVALID_POLICY_PREFIX + policytype
- polname = policy
- is_deleted = True
- else:
- # no change to label
- policytype = xsconstants.ACM_POLICY_ID
- polname = new_polname
-
- return tuple( [ policytype, polname, label ] ), is_deleted
-
-
-def change_acm_policy(bin_pol, del_array, chg_array,
- vmlabel_map, reslabel_map, cur_acmpol, new_acmpol,
- is_reset):
- """
- Change the ACM policy of the system by relabeling
- domains and resources first and doing some access checks.
- Then update the policy in the hypervisor. If this is all successful,
- relabel the domains permanently and commit the relabed resources.
-
- Need to do / check the following:
- - relabel all resources where there is a 'from' field in
- the policy. [ NOT DOING THIS: and mark those as unlabeled where the label
- does not appear in the new policy anymore (deletion) ]
- - relabel all VMs where there is a 'from' field in the
- policy and mark those as unlabeled where the label
- does not appear in the new policy anymore; no running
- or paused VM may be unlabeled through this
- - check that under the new labeling conditions the VMs
- still have access to their resources as before. Unlabeled
- resources are inaccessible. If this check fails, the
- update failed.
- - Attempt changes in the hypervisor; if this step fails,
- roll back the relabeling of resources and VMs
- - Make the relabeling of resources and VMs permanent
-
- This function should be called with the lock to the domains
- held (XendDomain.instance().domains_lock)
- """
- from xen.util.acmpolicy import ACM_LABEL_UNLABELED
- rc = xsconstants.XSERR_SUCCESS
-
- domain_label_map = {}
- new_policyname = new_acmpol.get_name()
- new_policytype = new_acmpol.get_type_name()
- cur_policyname = cur_acmpol.get_name()
- cur_policytype = cur_acmpol.get_type_name()
- polnew_reslabels = new_acmpol.policy_get_resourcelabel_names()
- errors=""
-
- try:
- resfile_lock()
- mapfile_lock()
-
- # Get all domains' dominfo.
- from xen.xend import XendDomain
- dominfos = XendDomain.instance().list('all')
-
- log.info("----------------------------------------------")
-
- label_changes = []
- # relabel resources
-
- access_control = {}
- try:
- access_control = dictio.dict_read("resources", res_label_filename)
- except:
- pass
-
- for key, labeldata in access_control.items():
- if len(labeldata) == 2:
- policy, label = labeldata
- policytype = xsconstants.ACM_POLICY_ID
- elif len(labeldata) == 3:
- policytype, policy, label = labeldata
- else:
- return -xsconstants.XSERR_BAD_LABEL_FORMAT, ""
-
- new_sec_lab, is_deleted = \
- __update_label_policy_change( tuple([policytype,
- policy,
- label]),
- cur_policytype,
- cur_policyname,
- new_policytype,
- new_policyname,
- polnew_reslabels,
- reslabel_map)
-
- if is_deleted:
- label_changes.append(key)
- # Update entry
- access_control[key] = new_sec_lab
-
- # All resources have new labels in the access_control map
- # There may still be labels in there that are invalid now.
-
- # Do this in memory without writing to disk:
- # - Relabel all domains independent of whether they are running
- # or not
- # - later write back to config files
- polnew_vmlabels = new_acmpol.policy_get_virtualmachinelabel_names()
-
- for dominfo in dominfos:
- sec_lab = dominfo.get_security_label()
- if not sec_lab:
- continue
- policytype, policy, vmlabel = sec_lab.split(":")
- name = dominfo.getName()
-
- if policytype != cur_policytype or \
- policy != cur_policyname:
- continue
-
- new_vmlabel = vmlabel
- if vmlabel_map.has_key(vmlabel) and \
- (not is_reset or name == "Domain-0") :
- # renaming of the label; this is only allowed if it's
- # not a reset of the policy or if it is a reset, then
- # only for Domain-0
- new_vmlabel = vmlabel_map[vmlabel]
- polname = new_policyname
- elif new_vmlabel not in polnew_vmlabels and \
- vmlabel != ACM_LABEL_UNLABELED:
- # removal of VM label and not the 'unlabeled' label
- policytype = xsconstants.INVALID_POLICY_PREFIX + policytype
- polname = policy
- else:
- polname = new_policyname
-
- new_seclab = "%s:%s:%s" % \
- (policytype, polname, new_vmlabel)
-
- domain_label_map[dominfo] = [ sec_lab, new_seclab ]
-
- if dominfo._stateGet() in (DOM_STATE_PAUSED, DOM_STATE_RUNNING):
- compatible = __resources_compatible_with_vmlabel(new_acmpol,
- dominfo,
- new_vmlabel,
- access_control,
- is_policy_update=True)
- log.info("Domain %s with new label '%s' can access its "
- "resources? : %s" %
- (name, new_vmlabel, str(compatible)))
- log.info("VM labels in new policy: %s" %
- new_acmpol.policy_get_virtualmachinelabel_names())
- if not compatible:
- return (-xsconstants.XSERR_RESOURCE_ACCESS, "")
-
- for dominfo in dominfos:
- # relabel the VIF interfaces
- changed = False
- for vif_uuid in dominfo.get_vifs():
- sec_lab = dominfo.info['devices'][vif_uuid][1]\
- .get('security_label')
- if sec_lab:
- result, _ = \
- __update_label_policy_change(tuple(sec_lab.split(':')),
- cur_policytype,
- cur_policyname,
- new_policytype,
- new_policyname,
- polnew_reslabels,
- reslabel_map)
- new_sec_lab = ':'.join(list(result))
- if new_sec_lab != sec_lab:
- changed = True
- dominfo.info['devices'][vif_uuid][1]\
- ['security_label'] = new_sec_lab
- if changed:
- XendDomain.instance().managed_config_save(dominfo)
-
- rc, errors = hv_chg_policy(bin_pol, del_array, chg_array)
- if rc == 0:
- for key in label_changes:
- run_resource_label_change_script(key, "", "remove")
- # Write the relabeled resources back into the file
- dictio.dict_write(access_control, "resources", res_label_filename)
- # Properly update all VMs to their new labels
- for dominfo, labels in domain_label_map.items():
- sec_lab, new_seclab = labels
- if sec_lab != new_seclab:
- log.info("Updating domain %s to new label '%s'." % \
- (dominfo.getName(), new_seclab))
- # This better be working!
- res = dominfo.set_security_label(new_seclab,
- sec_lab,
- new_acmpol,
- cur_acmpol)
- if res[0] != xsconstants.XSERR_SUCCESS:
- log.info("ERROR: Could not chg label on domain %s: %s" %
- (dominfo.getName(),
- xsconstants.xserr2string(-int(res[0]))))
- finally:
- log.info("----------------------------------------------")
- mapfile_unlock()
- resfile_unlock()
-
- return rc, errors
-
-def parse_security_label(security_label):
- tmp = security_label.split(":")
- if len(tmp) != 3:
- return ""
- else:
- return security_label
-
-def set_security_label(policy, label):
- if label and policy and label != "" and policy != "":
- return "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, policy, label)
- else:
- return ""
-
-def ssidref2security_label(ssidref):
- from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
- return XSPolicyAdminInstance().ssidref_to_vmlabel(ssidref)
-
-def get_security_label(self, xspol=None):
- """
- Get the security label of a domain
- @param xspol The policy to use when converting the ssid into
- a label; only to be passed during the updating
- of the policy
- """
- domid = self.getDomid()
-
- if not xspol:
- from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
- xspol = XSPolicyAdminInstance().get_loaded_policy()
-
- label = ""
- if xspol:
- label = xspol.policy_get_domain_label_formatted(domid)
- if domid != 0:
- label = self.info.get('security_label', label)
- return label
-
-
-def check_can_run(sec_label):
- """ Check whether a VM could run, given its vm label. A VM can run if
- - it is authorized
- - is not in conflict with any running domain
- """
- try:
- mapfile_lock()
-
- if sec_label == None or sec_label == "":
- vm_label = ACM_LABEL_UNLABELED
- else:
- poltype, policy, vm_label = sec_label.split(':')
- if policy != get_active_policy_name():
- return -xsconstants.XSERR_BAD_POLICY_NAME
- ssidref = label2ssidref(vm_label, policy, 'dom')
- if ssidref != xsconstants.INVALID_SSIDREF:
- if not has_authorization(ssidref):
- return -xsconstants.XSERR_VM_NOT_AUTHORIZED
- if is_in_conflict(ssidref):
- return -xsconstants.XSERR_VM_IN_CONFLICT
- return -xsconstants.XSERR_SUCCESS
- else:
- return -xsconstants.XSERR_BAD_LABEL
- finally:
- mapfile_unlock()
-
-
-__cond = threading.Condition()
-__script_runner = None
-__orders = []
-
-def run_resource_label_change_script(resource, label, command):
- global __cond, __orders, __script_runner
-
- def __run_resource_label_change_script():
- global __cond, __orders
- script = XendOptions.instance().get_resource_label_change_script()
- if script:
- parms = {}
- while True:
- __cond.acquire()
- if len(__orders) == 0:
- __cond.wait()
-
- parms['label'], \
- parms['command'], \
- parms['resource'] = __orders[0]
-
- __orders = __orders[1:]
- __cond.release()
-
- log.info("Running resource label change script %s: %s" %
- (script, parms))
- parms.update(os.environ)
- xpopen.call(" ".join(script, params))
- else:
- log.info("No script given for relabeling of resources.")
- if not __script_runner:
- __script_runner = \
- threading.Thread(target=__run_resource_label_change_script,
- args=())
- __script_runner.start()
-
- __cond.acquire()
- __orders.append((label,command,resource))
- __cond.notify()
- __cond.release()
diff --git a/tools/python/xen/util/xsm/dummy/__init__.py b/tools/python/xen/util/xsm/dummy/__init__.py
deleted file mode 100644
index 8d1c8b6..0000000
--- a/tools/python/xen/util/xsm/dummy/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tools/python/xen/util/xsm/dummy/dummy.py b/tools/python/xen/util/xsm/dummy/dummy.py
deleted file mode 100644
index 795d637..0000000
--- a/tools/python/xen/util/xsm/dummy/dummy.py
+++ /dev/null
@@ -1,136 +0,0 @@
-import sys
-from xen.util import xsconstants
-from xen.xend.XendLogging import log
-
-class XSMError(Exception):
- def __init__(self,value):
- self.value = value
- def __str__(self):
- return repr(self.value)
-
-
-security_dir_prefix = "";
-policy_dir_prefix = "";
-active_policy = "";
-NULL_SSIDREF = 0;
-
-#Functions exported through XML-RPC
-xmlrpc_exports = [
- 'set_resource_label',
- 'get_resource_label',
- 'list_labels',
- 'get_labeled_resources',
- 'set_policy',
- 'reset_policy',
- 'get_policy',
- 'activate_policy',
- 'rm_bootpolicy',
- 'get_xstype',
- 'get_domain_label',
- 'set_domain_label'
-]
-
-def err(msg):
- """Raise XSM-dummy exception.
- """
- raise XSMError(msg)
-
-def on():
- return 0
-
-def ssidref2label(ssidref):
- return 0
-
-def label2ssidref(label, policy, type):
- return 0
-
-def res_security_check(resource, domain_label):
- return 1
-
-def get_res_security_details(resource):
- return ("","","")
-
-def get_res_label(resource):
- return ("","")
-
-def res_security_check_xapi(rlabel, rssidref, rpolicy, xapi_dom_label):
- return 1
-
-def parse_security_label(security_label):
- return ""
-
-def calc_dom_ssidref_from_info(info):
- return ""
-
-def set_security_label(policy, label):
- return ""
-
-def ssidref2security_label(ssidref):
- return ""
-
-def has_authorization(ssidref):
- return True
-
-def get_security_label(self, xspol=None):
- return ""
-
-def get_resource_label_xapi(resource):
- return ""
-
-def get_labeled_resources_xapi():
- return {}
-
-def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi):
- err("Command not supported under XSM 'dummy' module.")
-
-def format_resource_label(res):
- return ""
-
-def set_resource_label(resource, policytype, policyref, reslabel,
- oreslabel = None):
- err("Command not supported under XSM 'dummy' module.")
-
-def get_resource_label(resource):
- return ""
-
-def list_labels(policy_name, ltype):
- return []
-
-def get_labeled_resources():
- return {}
-
-def set_policy(xs_type, xml, flags, overwrite):
- err("Command not supported under xsm 'dummy' module.")
-
-def reset_policy():
- err("Command not supported under xsm 'dummy' module.")
-
-def get_policy():
- return "", 0
-
-def activate_policy():
- err("Command not supported under xsm 'dummy' module.")
-
-def rm_bootpolicy():
- err("Command not supported under xsm 'dummy' module.")
-
-def get_xstype():
- return 0
-
-def get_domain_label(domain):
- return ""
-
-def set_domain_label():
- err("Command not supported under xsm 'dummy' module.")
-
-def dump_policy():
- pass
-
-def dump_policy_file():
- pass
-
-def get_ssid(domain):
- err("No ssid has been assigned to any domain under xsm dummy module.")
-
-def security_label_to_details(res_label):
- return ("","","")
diff --git a/tools/python/xen/util/xsm/flask/__init__.py b/tools/python/xen/util/xsm/flask/__init__.py
deleted file mode 100644
index 8d1c8b6..0000000
--- a/tools/python/xen/util/xsm/flask/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tools/python/xen/util/xsm/flask/flask.py b/tools/python/xen/util/xsm/flask/flask.py
deleted file mode 100644
index 83d662d..0000000
--- a/tools/python/xen/util/xsm/flask/flask.py
+++ /dev/null
@@ -1,65 +0,0 @@
-import sys
-import base64
-from xen.lowlevel import flask
-from xen.util import xsconstants
-from xen.xend import sxp
-
-#Functions exported through XML-RPC
-xmlrpc_exports = [
- 'on',
- 'set_policy',
- 'getenforce',
- 'setenforce'
-]
-
-def err(msg):
- """Raise XSM-Flask exception.
- """
- sys.stderr.write("XSM-FlaskError: " + msg + "\n")
- raise XSMError(msg)
-
-def on():
- return xsconstants.XS_POLICY_FLASK
-
-def ssidref2label(ssidref):
- try:
- return flask.flask_sid_to_context(ssidref)
- except:
- return ""
-
-def label2ssidref(label, policy, type):
- try:
- return flask.flask_context_to_sid(label)
- except:
- raise XSMError('Invalid context %s' % label)
-
-def parse_security_label(security_label):
- return security_label
-
-def calc_dom_ssidref_from_info(info):
- ssidref = label2ssidref(info['security_label'], "", "")
- return ssidref
-
-def set_security_label(policy, label):
- if label:
- return label
- else:
- return ""
-
-def ssidref2security_label(ssidref):
- label = ssidref2label(ssidref)
- return label
-
-def get_security_label(self, xspol=None):
- label = self.info['security_label']
- return label
-
-def set_policy(xs_type, policy_b64, flags=None, overwrite=None):
- policy = base64.b64decode(policy_b64);
- return flask.flask_load(policy), ""
-
-def getenforce():
- return flask.flask_getenforce()
-
-def setenforce(mode):
- return flask.flask_setenforce(mode)
diff --git a/tools/python/xen/util/xsm/xsm.py b/tools/python/xen/util/xsm/xsm.py
deleted file mode 100644
index 1c093c6..0000000
--- a/tools/python/xen/util/xsm/xsm.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import sys
-import string
-from xen.xend import XendOptions
-from xen.util import xsconstants
-from xsm_core import xsm_init
-
-xoptions = XendOptions.instance()
-xsm_module_name = xoptions.get_xsm_module_name()
-
-xsconstants.XS_POLICY_USE = eval("xsconstants.XS_POLICY_" +
- string.upper(xsm_module_name))
-
-xsm_module_path = "xen.util.xsm." + xsm_module_name + "." + xsm_module_name
-xsm_module = __import__(xsm_module_path, globals(), locals(), ['*'])
-
-xsm_init(xsm_module)
-
-for op in dir(xsm_module):
- if not hasattr(sys.modules[__name__], op):
- setattr(sys.modules[__name__], op, getattr(xsm_module, op, None))
diff --git a/tools/python/xen/util/xsm/xsm_core.py b/tools/python/xen/util/xsm/xsm_core.py
deleted file mode 100644
index f40af12..0000000
--- a/tools/python/xen/util/xsm/xsm_core.py
+++ /dev/null
@@ -1,7 +0,0 @@
-import sys
-import xen.util.xsm.dummy.dummy as dummy
-
-def xsm_init(self):
- for op in dir(dummy):
- if not hasattr(self, op):
- setattr(self, op, getattr(dummy, op, None))
diff --git a/tools/python/xen/util/xspolicy.py b/tools/python/xen/util/xspolicy.py
deleted file mode 100644
index 7cd5656..0000000
--- a/tools/python/xen/util/xspolicy.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006,2007 International Business Machines Corp.
-# Author: Stefan Berger <stefanb at us.ibm.com>
-#============================================================================
-
-import threading
-import xsconstants
-
-class XSPolicy:
- """
- The base policy class for all policies administered through
- XSPolicyAdmin.
- """
-
- def __init__(self, name=None, ref=None):
- self.lock = threading.Lock()
- self.ref = ref
- self.name = name
- if ref:
- from xen.xend.XendXSPolicy import XendXSPolicy
- self.xendxspolicy = XendXSPolicy(self, {}, ref)
- else:
- self.xendxspolicy = None
-
- def grab_lock(self):
- self.lock.acquire()
-
- def unlock(self):
- self.lock.release()
-
- def get_ref(self):
- return self.ref
-
- def destroy(self):
- if self.xendxspolicy:
- self.xendxspolicy.destroy()
-
- # All methods below should be overwritten by the inheriting class
-
- def isloaded(self):
- return False
-
- def loadintohv(self):
- return xsconstants.XSERR_POLICY_LOAD_FAILED
-
- def get_type(self):
- return xsconstants.XS_POLICY_NONE
-
- def get_type_name(self):
- return ""
-
- def update(self, repr_new):
- return -xsconstants.XSERR_GENERAL_FAILURE, ""
diff --git a/tools/python/xen/web/SrvBase.py b/tools/python/xen/web/SrvBase.py
deleted file mode 100644
index cabb7b1..0000000
--- a/tools/python/xen/web/SrvBase.py
+++ /dev/null
@@ -1,98 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
-
-import types
-
-
-from xen.xend import sxp
-from xen.xend import PrettyPrint
-from xen.xend.Args import ArgError
-from xen.xend.XendError import XendError
-from xen.xend.XendLogging import log
-
-import resource
-import http
-import httpserver
-
-def uri_pathlist(p):
- """Split a path into a list.
- p path
- return list of path elements
- """
- l = []
- for x in p.split('/'):
- if x == '': continue
- l.append(x)
- return l
-
-class SrvBase(resource.Resource):
- """Base class for services.
- """
-
-
- def use_sxp(self, req):
- return req.useSxp()
-
- def get_op_method(self, op):
- """Get the method for an operation.
- For operation 'foo' looks for 'op_foo'.
-
- op operation name
- returns method or None
- """
- op_method_name = 'op_' + op
- return getattr(self, op_method_name, None)
-
- def perform(self, req):
- """General operation handler for posted operations.
- For operation 'foo' looks for a method op_foo and calls
- it with op_foo(op, req). Replies with code 500 if op_foo
- is not found.
-
- The method must return a list when req.use_sxp is true
- and an HTML string otherwise (or list).
- Methods may also return a ThreadRequest (for incomplete processing).
-
- req request
- """
- op = req.args.get('op')
- if op is None or len(op) != 1:
- req.setResponseCode(http.NOT_ACCEPTABLE, "Invalid request")
- return ''
- op = op[0]
- op_method = self.get_op_method(op)
- if op_method is None:
- req.setResponseCode(http.NOT_IMPLEMENTED, "Operation not implemented: " + op)
- req.setHeader("Content-Type", "text/plain")
- req.write("Operation not implemented: " + op)
- return ''
- else:
- try:
- return op_method(op, req)
- except Exception, exn:
- req.setResponseCode(http.INTERNAL_SERVER_ERROR, "Request failed: " + op)
- log.exception("Request %s failed.", op)
- if req.useSxp():
- return ['xend.err', str(exn)]
- else:
- return "<p>%s</p>" % str(exn)
-
- def print_path(self, req):
- """Print the path with hyperlinks.
- """
- req.printPath()
-
diff --git a/tools/python/xen/web/SrvDir.py b/tools/python/xen/web/SrvDir.py
deleted file mode 100644
index 006975e..0000000
--- a/tools/python/xen/web/SrvDir.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
-
-import types
-
-from xen.xend import sxp
-from xen.xend import PrettyPrint
-from xen.xend.Args import ArgError
-from xen.xend.XendError import XendError, XendInvalidDomain
-#from xen.xend.XendLogging import log
-
-import resource
-import http
-
-from xen.web.SrvBase import SrvBase
-
-class SrvConstructor:
- """Delayed constructor for sub-servers.
- Does not import the sub-server class or create the object until needed.
- """
-
- def __init__(self, klass):
- """Create a constructor. It is assumed that the class
- should be imported as 'from xen.xend.server.klass import klass'.
-
- klass name of its class
- """
- self.klass = klass
- self.obj = None
-
- def getobj(self):
- """Get the sub-server object, importing its class and instantiating it if
- necessary.
- """
- if not self.obj:
- exec 'from xen.xend.server.%s import %s' % (self.klass, self.klass)
- klassobj = eval(self.klass)
- self.obj = klassobj()
- return self.obj
-
-class SrvDir(SrvBase):
- """Base class for directory servlets.
- """
- isLeaf = False
-
- def __init__(self):
- SrvBase.__init__(self)
- self.table = {}
- self.order = []
-
- def noChild(self, msg):
- return resource.ErrorPage(http.NOT_FOUND, msg=msg)
-
- def getChild(self, x, req):
- if x == '': return self
- try:
- val = self.get(x)
- except XendError, ex:
- return self.noChild(str(ex))
- except XendInvalidDomain, ex:
- return self.noChild(str(ex))
- if val is None:
- return self.noChild('Not found: ' + str(x))
- else:
- return val
-
- def get(self, x):
- val = self.table.get(x)
- if isinstance(val, SrvConstructor):
- val = val.getobj()
- return val
-
- def add(self, x, v=None):
- if v is None:
- v = 'SrvDir'
- if isinstance(v, types.StringType):
- v = SrvConstructor(v)
- self.table[x] = v
- self.order.append(x)
- return v
-
- def render_GET(self, req):
- if self.use_sxp(req):
- req.setHeader("Content-type", sxp.mime_type)
- self.ls(req, 1)
- else:
- req.write('<html><head></head><body>')
- self.print_path(req)
- self.ls(req)
- self.form(req)
- req.write('</body></html>')
- return ''
-
- def ls(self, req, use_sxp=0):
- url = req.prePathURL()
- if not url.endswith('/'):
- url += '/'
- if use_sxp:
- req.write('(ls ')
- for k in self.order:
- req.write(' ' + k)
- req.write(')')
- else:
- req.write('<ul>')
- for k in self.order:
- v = self.get(k)
- req.write('<li><a href="%s%s">%s</a></li>'
- % (url, k, k))
- req.write('</ul>')
-
- def form(self, req):
- pass
diff --git a/tools/python/xen/web/__init__.py b/tools/python/xen/web/__init__.py
deleted file mode 100644
index 718ac55..0000000
--- a/tools/python/xen/web/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
-
diff --git a/tools/python/xen/web/connection.py b/tools/python/xen/web/connection.py
deleted file mode 100644
index 17e1762..0000000
--- a/tools/python/xen/web/connection.py
+++ /dev/null
@@ -1,333 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd.
-#============================================================================
-
-import sys
-import os
-import threading
-import socket
-import fcntl
-
-from errno import EAGAIN, EINTR, EWOULDBLOCK
-
-try:
- from OpenSSL import SSL
-except ImportError:
- pass
-
-from xen.xend.XendLogging import log
-
-"""General classes to support server and client sockets, without
-specifying what kind of socket they are. There are subclasses
-for TCP and unix-domain sockets (see tcp.py and unix.py).
-"""
-
-BUFFER_SIZE = 16384
-BACKLOG = 5
-
-
-class SocketServerConnection:
- """An accepted connection to a server.
- """
-
- def __init__(self, sock, protocol_class):
- self.sock = sock
- self.protocol = protocol_class()
- self.protocol.setTransport(self)
- threading.Thread(target=self.main).start()
-
-
- def main(self):
- try:
- while True:
- try:
- data = self.sock.recv(BUFFER_SIZE)
- if data == '':
- break
- if self.protocol.dataReceived(data):
- break
- except socket.error, ex:
- if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR):
- break
- finally:
- try:
- self.sock.close()
- except:
- pass
-
-
- def close(self):
- self.sock.close()
-
-
- def write(self, data):
- self.sock.send(data)
-
-
-class SocketListener:
- """A server socket, running listen in a thread.
- Accepts connections and runs a thread for each one.
- """
-
- def __init__(self, protocol_class):
- self.protocol_class = protocol_class
- self.sock = self.createSocket()
- threading.Thread(target=self.main).start()
-
-
- def close(self):
- try:
- self.sock.close()
- except:
- pass
-
-
- def createSocket(self):
- raise NotImplementedError()
-
-
- def acceptConnection(self, sock, protocol, addr):
- raise NotImplementedError()
-
-
- def main(self):
- try:
- fcntl.fcntl(self.sock.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC)
- self.sock.listen(BACKLOG)
-
- while True:
- try:
- (sock, addr) = self.sock.accept()
- self.acceptConnection(sock, addr)
- except socket.error, ex:
- if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR):
- break
- finally:
- self.close()
-
-
-class SSLSocketServerConnection(SocketServerConnection):
- """An SSL aware accepted connection to a server.
-
- As pyOpenSSL SSL.Connection fileno() method just retrieve the file
- descriptor number for the underlying socket, direct read/write to the file
- descriptor will result no data encrypted.
-
- recv2fd() and fd2send() are simple wrappers for functions who need direct
- read/write to a file descriptor rather than a socket like object.
-
- To use recv2fd(), you can create a pipe and start a thread to transfer all
- received data to one end of the pipe, then read from the other end:
-
- p2cread, p2cwrite = os.pipe()
- threading.Thread(target=connection.SSLSocketServerConnection.recv2fd,
- args=(sock, p2cwrite)).start()
- os.read(p2cread, 1024)
-
- To use fd2send():
-
- p2cread, p2cwrite = os.pipe()
- threading.Thread(target=connection.SSLSocketServerConnection.fd2send,
- args=(sock, p2cread)).start()
- os.write(p2cwrite, "data")
- """
-
- def __init__(self, sock, protocol_class):
- SocketServerConnection.__init__(self, sock, protocol_class)
-
-
- def main(self):
- try:
- while True:
- try:
- data = self.sock.recv(BUFFER_SIZE)
- if data == "":
- break
- if self.protocol.dataReceived(data):
- break
- except socket.error, ex:
- if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR):
- break
- except (SSL.WantReadError, SSL.WantWriteError, \
- SSL.WantX509LookupError):
- # The operation did not complete; the same I/O method
- # should be called again.
- continue
- except SSL.ZeroReturnError:
- # The SSL Connection has been closed.
- break
- except SSL.SysCallError, (retval, desc):
- if ((retval == -1 and desc == "Unexpected EOF")
- or retval > 0):
- # The SSL Connection is lost.
- break
- log.debug("SSL SysCallError:%d:%s" % (retval, desc))
- break
- except SSL.Error, e:
- # other SSL errors
- log.debug("SSL Error:%s" % e)
- break
- finally:
- try:
- self.sock.close()
- except:
- pass
-
-
- def recv2fd(sock, fd):
- try:
- while True:
- try:
- data = sock.recv(BUFFER_SIZE)
- if data == "":
- break
- count = 0
- while count < len(data):
- try:
- nbytes = os.write(fd, data[count:])
- count += nbytes
- except os.error, ex:
- if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR):
- raise
- except socket.error, ex:
- if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR):
- break
- except (SSL.WantReadError, SSL.WantWriteError, \
- SSL.WantX509LookupError):
- # The operation did not complete; the same I/O method
- # should be called again.
- continue
- except SSL.ZeroReturnError:
- # The SSL Connection has been closed.
- break
- except SSL.SysCallError, (retval, desc):
- if ((retval == -1 and desc == "Unexpected EOF")
- or retval > 0):
- # The SSL Connection is lost.
- break
- log.debug("SSL SysCallError:%d:%s" % (retval, desc))
- break
- except SSL.Error, e:
- # other SSL errors
- log.debug("SSL Error:%s" % e)
- break
- finally:
- try:
- sock.close()
- os.close(fd)
- except:
- pass
-
- recv2fd = staticmethod(recv2fd)
-
-
- def fd2send(sock, fd):
- try:
- while True:
- try:
- data = os.read(fd, BUFFER_SIZE)
- if data == "":
- break
- count = 0
- while count < len(data):
- try:
- nbytes = sock.send(data[count:])
- count += nbytes
- except socket.error, ex:
- if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR):
- raise
- except (SSL.WantReadError, SSL.WantWriteError, \
- SSL.WantX509LookupError):
- # The operation did not complete; the same I/O method
- # should be called again.
- continue
- except SSL.ZeroReturnError:
- # The SSL Connection has been closed.
- raise
- except SSL.SysCallError, (retval, desc):
- if not (retval == -1 and data == ""):
- # errors when writing empty strings are expected
- # and can be ignored
- log.debug("SSL SysCallError:%d:%s" % (retval, desc))
- raise
- except SSL.Error, e:
- # other SSL errors
- log.debug("SSL Error:%s" % e)
- raise
- except os.error, ex:
- if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR):
- break
- finally:
- try:
- sock.close()
- os.close(fd)
- except:
- pass
-
- fd2send = staticmethod(fd2send)
-
-
-def hostAllowed(addrport, hosts_allowed):
- if hosts_allowed is None:
- return True
- else:
- fqdn = socket.getfqdn(addrport[0])
- for h in hosts_allowed:
- if h.match(fqdn) or h.match(addrport[0]):
- return True
- log.warn("Rejected connection from %s (%s).", addrport[0], fqdn)
- return False
-
-
-class SocketDgramListener:
- """A connectionless server socket, running listen in a thread.
- """
-
- def __init__(self, protocol_class):
- self.protocol = protocol_class()
- self.sock = self.createSocket()
- threading.Thread(target=self.main).start()
-
-
- def close(self):
- try:
- self.sock.close()
- except:
- pass
-
-
- def createSocket(self):
- raise NotImplementedError()
-
-
- def main(self):
- try:
- fcntl.fcntl(self.sock.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC)
-
- while True:
- try:
- data = self.sock.recv(BUFFER_SIZE)
- self.protocol.dataReceived(data)
- except socket.error, ex:
- if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR):
- break
- finally:
- try:
- self.close()
- except:
- pass
diff --git a/tools/python/xen/web/http.py b/tools/python/xen/web/http.py
deleted file mode 100644
index e11d8d2..0000000
--- a/tools/python/xen/web/http.py
+++ /dev/null
@@ -1,518 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-#============================================================================
-# Parts of this library are derived from Twisted:
-# Copyright (C) 2001 Matthew W. Lefkowitz
-#
-# Copyright (C) 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
-
-from mimetools import Message
-from cStringIO import StringIO
-import math
-import socket
-import time
-import cgi
-
-CONTINUE = 100
-SWITCHING_PROTOCOLS = 101
-
-OK = 200
-CREATED = 201
-ACCEPTED = 202
-NON_AUTHORITATIVE_INFORMATION = 203
-NO_CONTENT = 204
-RESET_CONTENT = 205
-PARTIAL_CONTENT = 206
-MULTI_STATUS = 207
-
-MULTIPLE_CHOICE = 300
-MOVED_PERMANENTLY = 301
-FOUND = 302
-SEE_OTHER = 303
-NOT_MODIFIED = 304
-USE_PROXY = 305
-TEMPORARY_REDIRECT = 307
-
-BAD_REQUEST = 400
-UNAUTHORIZED = 401
-PAYMENT_REQUIRED = 402
-FORBIDDEN = 403
-NOT_FOUND = 404
-NOT_ALLOWED = 405
-NOT_ACCEPTABLE = 406
-PROXY_AUTH_REQUIRED = 407
-REQUEST_TIMEOUT = 408
-CONFLICT = 409
-GONE = 410
-LENGTH_REQUIRED = 411
-PRECONDITION_FAILED = 412
-REQUEST_ENTITY_TOO_LARGE = 413
-REQUEST_URI_TOO_LONG = 414
-UNSUPPORTED_MEDIA_TYPE = 415
-REQUESTED_RANGE_NOT_SATISFIABLE = 416
-EXPECTATION_FAILED = 417
-
-INTERNAL_SERVER_ERROR = 500
-NOT_IMPLEMENTED = 501
-BAD_GATEWAY = 502
-SERVICE_UNAVAILABLE = 503
-GATEWAY_TIMEOUT = 504
-VERSION_NOT_SUPPORTED = 505
-INSUFFICIENT_STORAGE_SPACE = 507
-NOT_EXTENDED = 510
-
-NO_BODY_CODES = [ NO_CONTENT, NOT_MODIFIED ]
-
-
-STATUS = {
- CONTINUE : "Continue",
- SWITCHING_PROTOCOLS : "Switching protocols",
-
- OK : "OK",
- CREATED : "Created",
- ACCEPTED : "Accepted",
- NON_AUTHORITATIVE_INFORMATION : "Non-authoritative information",
- NO_CONTENT : "No content",
- RESET_CONTENT : "Reset content",
- PARTIAL_CONTENT : "Partial content",
- MULTI_STATUS : "Multi-status",
-
- MULTIPLE_CHOICE : "Multiple choice",
- MOVED_PERMANENTLY : "Moved permanently",
- FOUND : "Found",
- SEE_OTHER : "See other",
- NOT_MODIFIED : "Not modified",
- USE_PROXY : "Use proxy",
- TEMPORARY_REDIRECT : "Temporary redirect",
-
- BAD_REQUEST : "Bad request",
- UNAUTHORIZED : "Unauthorized",
- PAYMENT_REQUIRED : "Payment required",
- FORBIDDEN : "Forbidden",
- NOT_FOUND : "Not found",
- NOT_ALLOWED : "Not allowed",
- NOT_ACCEPTABLE : "Not acceptable",
- PROXY_AUTH_REQUIRED : "Proxy authentication required",
- REQUEST_TIMEOUT : "Request timeout",
- CONFLICT : "Conflict",
- GONE : "Gone",
- LENGTH_REQUIRED : "Length required",
- PRECONDITION_FAILED : "Precondition failed",
- REQUEST_ENTITY_TOO_LARGE : "Request entity too large",
- REQUEST_URI_TOO_LONG : "Request URI too long",
- UNSUPPORTED_MEDIA_TYPE : "Unsupported media type",
- REQUESTED_RANGE_NOT_SATISFIABLE : "Requested range not satisfiable",
- EXPECTATION_FAILED : "Expectation failed",
-
- INTERNAL_SERVER_ERROR : "Internal server error",
- NOT_IMPLEMENTED : "Not implemented",
- BAD_GATEWAY : "Bad gateway",
- SERVICE_UNAVAILABLE : "Service unavailable",
- GATEWAY_TIMEOUT : "Gateway timeout",
- VERSION_NOT_SUPPORTED : "HTTP version not supported",
- INSUFFICIENT_STORAGE_SPACE : "Insufficient storage space",
- NOT_EXTENDED : "Not extended",
- }
-
-def getStatus(code):
- return STATUS.get(code, "unknown")
-
-MULTIPART_FORM_DATA = 'multipart/form-data'
-URLENCODED = 'application/x-www-form-urlencoded'
-
-parseQueryArgs = cgi.parse_qs
-
-def timegm(year, month, day, hour, minute, second):
- """Convert time tuple in GMT to seconds since epoch, GMT"""
- EPOCH = 1970
- assert year >= EPOCH
- assert 1 <= month <= 12
- days = 365*(year-EPOCH) + calendar.leapdays(EPOCH, year)
- for i in range(1, month):
- days = days + calendar.mdays[i]
- if month > 2 and calendar.isleap(year):
- days = days + 1
- days = days + day - 1
- hours = days*24 + hour
- minutes = hours*60 + minute
- seconds = minutes*60 + second
- return seconds
-
-def stringToDatetime(dateString):
- """Convert an HTTP date string to seconds since epoch."""
- parts = dateString.split(' ')
- day = int(parts[1])
- month = int(monthname.index(parts[2]))
- year = int(parts[3])
- hour, min, sec = map(int, parts[4].split(':'))
- return int(timegm(year, month, day, hour, min, sec))
-
-class HttpRequest:
-
- http_version = (1, 1)
-
- http_version_string = ("HTTP/%d.%d" % http_version)
-
- max_content_length = 10000
- max_headers = 500
-
- request_line = None
- request_method = None
- request_uri = None
- request_path = None
- request_query = None
- request_version = None
- content_length = 0
- content = None
- etag = None
- close_connection = True
- response_code = 200
- response_status = "OK"
- response_sent = False
- cached = False
- last_modified = None
-
- forceSSL = False
-
- def __init__(self, host, rin, out):
- self.host = host
- self.rin = rin
- self.out = out
- self.request_args = {}
- self.args = self.request_args
- self.request_headers = {}
- self.request_cookies = {}
- self.response_headers = {}
- self.response_cookies = {}
- self.output = StringIO()
- self.parseRequest()
-
- def isSecure(self):
- return self.forceSSL
-
- def getRequestMethod(self):
- return self.request_method
-
- def trim(self, str, ends):
- for end in ends:
- if str.endswith(end):
- str = str[ : -len(end) ]
- break
- return str
-
- def requestError(self, code, msg=None):
- self.sendError(code, msg)
- raise ValueError(self.response_status)
-
- def sendError(self, code, msg=None):
- self.setResponseCode(code, msg=msg)
- self.sendResponse()
-
- def parseRequestVersion(self, version):
- try:
- if not version.startswith('HTTP/'):
- raise ValueError
- version_string = version.split('/', 1)[1]
- version_codes = version_string.split('.')
- if len(version_codes) != 2:
- raise ValueError
- request_version = (int(version_codes[0]), int(version_codes[1]))
- except (ValueError, IndexError):
- self.requestError(400, "Bad request version (%s)" % `version`)
-
- def parseRequestLine(self):
- line = self.trim(self.request_line, ['\r\n', '\n'])
- line_fields = line.split()
- n = len(line_fields)
- if n == 3:
- [method, uri, version] = line_fields
- elif n == 2:
- [method, uri] = line_fields
- version = 'HTTP/0.9'
- else:
- self.requestError(BAD_REQUEST,
- "Bad request (%s)" % `line`)
-
- request_version = self.parseRequestVersion(version)
-
- if request_version > (2, 0):
- self.requestError(VERSION_NOT_SUPPORTED,
- "HTTP version not supported (%s)" % `version`)
- #if request_version >= (1, 1) and self.http_version >= (1, 1):
- # self.close_connection = False
- #else:
- # self.close_connection = True
-
- self.request_method = method
- self.method = method
- self.request_uri = uri
- self.request_version = version
-
- uri_query = uri.split('?')
- if len(uri_query) == 1:
- self.request_path = uri
- else:
- self.request_path = uri_query[0]
- self.request_query = uri_query[1]
- self.request_args = parseQueryArgs(self.request_query)
- self.args = self.request_args
-
-
- def parseRequestHeaders(self):
- header_bytes = ""
- header_count = 0
- while True:
- if header_count >= self.max_headers:
- self.requestError(BAD_REQUEST,
- "Bad request (too many headers)")
- line = self.rin.readline()
- header_bytes += line
- header_count += 1
- if line == '\r\n' or line == '\n' or line == '':
- break
- header_input = StringIO(header_bytes)
- self.request_headers = Message(header_input)
-
- def parseRequestCookies(self):
- cookie_hdr = self.getHeader("cookie")
- if not cookie_hdr: return
- for cookie in cookie_hdr.split(';'):
- try:
- cookie = cookie.lstrip()
- (k, v) = cookie.split('=', 1)
- self.request_cookies[k] = v
- except ValueError:
- pass
-
- def parseRequestArgs(self):
- if ((self.content is None) or
- (self.request_method != "POST")):
- return
- content_type = self.getHeader('content-type')
- if not content_type:
- return
- (encoding, params) = cgi.parse_header(content_type)
- if encoding == URLENCODED:
- xargs = cgi.parse_qs(self.content.getvalue(),
- keep_blank_values=True)
- elif encoding == MULTIPART_FORM_DATA:
- xargs = cgi.parse_multipart(self.content, params)
- else:
- xargs = {}
- self.request_args.update(xargs)
-
- def getCookie(self, k):
- return self.request_cookies[k]
-
- def readContent(self):
- try:
- self.content_length = int(self.getHeader("Content-Length"))
- except:
- return
- if self.content_length > self.max_content_length:
- self.requestError(REQUEST_ENTITY_TOO_LARGE)
- self.content = self.rin.read(self.content_length)
- self.content = StringIO(self.content)
- self.content.seek(0,0)
-
- def parseRequest(self):
- self.request_line = self.rin.readline()
- self.parseRequestLine()
- self.parseRequestHeaders()
- self.parseRequestCookies()
- connection_mode = self.getHeader('Connection')
- self.setCloseConnection(connection_mode)
- self.readContent()
- self.parseRequestArgs()
-
- def setCloseConnection(self, mode):
- if not mode: return
- mode = mode.lower()
- if mode == 'close':
- self.close_connection = True
- elif (mode == 'keep-alive') and (self.http_version >= (1, 1)):
- self.close_connection = False
-
- def getCloseConnection(self):
- return self.close_connection
-
- def getHeader(self, k, v=None):
- return self.request_headers.get(k, v)
-
- def getRequestMethod(self):
- return self.request_method
-
- def getRequestPath(self):
- return self.request_path
-
- def setResponseCode(self, code, status=None, msg=None):
- self.response_code = code
- if not status:
- status = getStatus(code)
- self.response_status = status
-
- def setResponseHeader(self, k, v):
- k = k.lower()
- self.response_headers[k] = v
- if k == 'connection':
- self.setCloseConnection(v)
-
- setHeader = setResponseHeader
-
- def setLastModified(self, when):
- # time.time() may be a float, but the HTTP-date strings are
- # only good for whole seconds.
- when = long(math.ceil(when))
- if (not self.last_modified) or (self.last_modified < when):
- self.lastModified = when
-
- modified_since = self.getHeader('if-modified-since')
- if modified_since:
- modified_since = stringToDatetime(modified_since)
- if modified_since >= when:
- self.setResponseCode(NOT_MODIFIED)
- self.cached = True
-
- def setContentType(self, ty):
- self.setResponseHeader("Content-Type", ty)
-
- def setEtag(self, etag):
- if etag:
- self.etag = etag
-
- tags = self.getHeader("if-none-match")
- if tags:
- tags = tags.split()
- if (etag in tags) or ('*' in tags):
- if self.request_method in ("HEAD", "GET"):
- code = NOT_MODIFIED
- else:
- code = PRECONDITION_FAILED
- self.setResponseCode(code)
- self.cached = True
-
- def addCookie(self, k, v, expires=None, domain=None, path=None,
- max_age=None, comment=None, secure=None):
- cookie = v
- if expires != None:
- cookie += "; Expires=%s" % expires
- if domain != None:
- cookie += "; Domain=%s" % domain
- if path != None:
- cookie += "; Path=%s" % path
- if max_age != None:
- cookie += "; Max-Age=%s" % max_age
- if comment != None:
- cookie += "; Comment=%s" % comment
- if secure:
- cookie += "; Secure"
- self.response_cookies[k] = cookie
-
- def sendResponseHeaders(self):
- if self.etag:
- self.setResponseHeader("ETag", self.etag)
- for (k, v) in self.response_headers.items():
- self.send("%s: %s\r\n" % (k.capitalize(), v))
- for (k, v) in self.response_cookies.items():
- self.send("Set-Cookie: %s=%s\r\n" % (k, v))
- self.send("\r\n")
-
- def sendResponse(self):
- if self.response_sent:
- return
- self.response_sent = True
- send_body = self.hasBody()
- if not self.close_connection:
- self.setResponseHeader("Connection", "keep-alive")
- self.setResponseHeader("Pragma", "no-cache")
- self.setResponseHeader("Cache-Control", "no-cache")
- self.setResponseHeader("Expires", "-1")
- if send_body:
- self.output.seek(0, 0)
- body = self.output.getvalue()
- body_length = len(body)
- self.setResponseHeader("Content-Length", body_length)
- if self.http_version > (0, 9):
- self.send("%s %d %s\r\n" % (self.http_version_string,
- self.response_code,
- self.response_status))
- self.sendResponseHeaders()
- if send_body:
- self.send(body)
- self.flush()
-
- def write(self, data):
- self.output.write(data)
-
- def send(self, data):
- #print 'send>', data
- self.out.write(data)
-
- def flush(self):
- self.out.flush()
-
- def hasNoBody(self):
- return ((self.request_method == "HEAD") or
- (self.response_code in NO_BODY_CODES) or
- self.cached)
-
- def hasBody(self):
- return not self.hasNoBody()
-
- def process(self):
- pass
- return self.close_connection
-
- def getRequestHostname(self):
- """Get the hostname that the user passed in to the request.
-
- Uses the 'Host:' header if it is available, and the
- host we are listening on otherwise.
- """
- return (self.getHeader('host') or
- socket.gethostbyaddr(self.getHostAddr())[0]
- ).split(':')[0]
-
- def getHost(self):
- return self.host
-
- def getHostAddr(self):
- return self.host[0]
-
- def getPort(self):
- return self.host[1]
-
- def setHost(self, host, port, ssl=0):
- """Change the host and port the request thinks it's using.
-
- This method is useful for working with reverse HTTP proxies (e.g.
- both Squid and Apache's mod_proxy can do this), when the address
- the HTTP client is using is different than the one we're listening on.
-
- For example, Apache may be listening on https://www.example.com, and then
- forwarding requests to http://localhost:8080, but we don't want HTML produced
- to say 'http://localhost:8080', they should say 'https://www.example.com',
- so we do::
-
- request.setHost('www.example.com', 443, ssl=1)
-
- """
- self.forceSSL = ssl
- self.received_headers["host"] = host
- self.host = (host, port)
-
-
-
diff --git a/tools/python/xen/web/httpserver.py b/tools/python/xen/web/httpserver.py
deleted file mode 100644
index d8a1f78..0000000
--- a/tools/python/xen/web/httpserver.py
+++ /dev/null
@@ -1,367 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2006 XenSource Ltd.
-#============================================================================
-
-import threading
-
-import string
-import socket
-import types
-from urllib import quote, unquote
-import os
-import os.path
-import fcntl
-
-from xen.xend import sxp
-from xen.xend.Args import ArgError
-from xen.xend.XendError import XendError
-
-import http
-import unix
-from resource import Resource, ErrorPage
-from SrvDir import SrvDir
-
-class ThreadRequest:
- """A request to complete processing using a thread.
- """
-
- def __init__(self, processor, req, fn, args, kwds):
- self.processor = processor
- self.req = req
- self.fn = fn
- self.args = args
- self.kwds = kwds
-
- def run(self):
- self.processor.setInThread()
- thread = threading.Thread(target=self.main)
- thread.setDaemon(True)
- thread.start()
-
- def call(self):
- try:
- self.fn(*self.args, **self.kwds)
- except SystemExit:
- raise
- except Exception, ex:
- self.req.resultErr(ex)
- self.req.finish()
-
- def main(self):
- self.call()
- self.processor.process()
-
-
-class RequestProcessor:
- """Processor for requests on a connection to an http server.
- Requests are executed synchonously unless they ask for a thread by returning
- a ThreadRequest.
- """
-
- done = False
-
- inThread = False
-
- def __init__(self, server, sock, addr):
- self.server = server
- self.sock = sock
- self.srd = sock.makefile('rb')
- self.srw = sock.makefile('wb')
- self.srvaddr = server.getServerAddr()
-
- def isInThread(self):
- return self.inThread
-
- def setInThread(self):
- self.inThread = True
-
- def getServer(self):
- return self.server
-
- def getRequest(self):
- return HttpServerRequest(self, self.srvaddr, self.srd, self.srw)
-
- def close(self):
- try:
- self.sock.close()
- except:
- pass
-
- def finish(self):
- self.done = True
- self.close()
-
- def process(self):
- while not self.done:
- req = self.getRequest()
- res = req.process()
- if isinstance(res, ThreadRequest):
- if self.isInThread():
- res.call()
- else:
- res.run()
- break
- else:
- req.finish()
-
-class HttpServerRequest(http.HttpRequest):
- """A single request to an http server.
- """
-
- def __init__(self, processor, addr, srd, srw):
- self.processor = processor
- self.prepath = ''
- http.HttpRequest.__init__(self, addr, srd, srw)
-
- def getServer(self):
- return self.processor.getServer()
-
- def process(self):
- """Process the request. If the return value is a ThreadRequest
- it is evaluated in a thread.
- """
- try:
- self.prepath = []
- self.postpath = map(unquote, string.split(self.request_path[1:], '/'))
- resource = self.getResource()
- return self.render(resource)
- except SystemExit:
- raise
- except Exception, ex:
- self.processError(ex)
-
- def processError(self, ex):
- import traceback; traceback.print_exc()
- self.sendError(http.INTERNAL_SERVER_ERROR, msg=str(ex))
- self.setCloseConnection('close')
-
- def finish(self):
- self.sendResponse()
- if self.close_connection:
- self.processor.finish()
-
- def prePathURL(self):
- url_host = self.getRequestHostname()
- port = self.getPort()
- if self.isSecure():
- url_proto = "https"
- default_port = 443
- else:
- url_proto = "http"
- default_port = 80
- if port != default_port:
- url_host += (':%d' % port)
- url_path = quote(string.join(self.prepath, '/'))
- return ('%s://%s/%s' % (url_proto, url_host, url_path))
-
- def getResource(self):
- return self.getServer().getResource(self)
-
- def render(self, resource):
- val = None
- if resource is None:
- self.sendError(http.NOT_FOUND)
- else:
- try:
- while True:
- val = resource.render(self)
- if not isinstance(val, Resource):
- break
- val = self.result(val)
- except SystemExit:
- raise
- except Exception, ex:
- self.resultErr(ex)
- return val
-
- def threadRequest(self, _fn, *_args, **_kwds):
- """Create a request to finish request processing in a thread.
- Use this to create a ThreadRequest to return from rendering a
- resource if you need a thread to complete processing.
- """
- return ThreadRequest(self.processor, self, _fn, _args, _kwds)
-
- def result(self, val):
- if isinstance(val, Exception):
- return self.resultErr(val)
- else:
- return self.resultVal(val)
-
- def resultVal(self, val):
- """Callback to complete the request.
-
- @param val: the value
- """
- if val is None:
- return val
- elif isinstance(val, ThreadRequest):
- return val
- elif self.useSxp():
- self.setHeader("Content-Type", sxp.mime_type)
- sxp.show(val, out=self)
- else:
- self.write('<html><head></head><body>')
- self.printPath()
- if isinstance(val, types.ListType):
- self.write('<code><pre>')
- PrettyPrint.prettyprint(val, out=self)
- self.write('</pre></code>')
- else:
- self.write(str(val))
- self.write('</body></html>')
- return None
-
- def resultErr(self, err):
- """Error callback to complete a request.
-
- @param err: the error
- """
- if not isinstance(err, (ArgError, sxp.ParseError, XendError)):
- raise
- #log.exception("op=%s: %s", op, str(err))
- if self.useSxp():
- self.setHeader("Content-Type", sxp.mime_type)
- sxp.show(['xend.err', str(err)], out=self)
- else:
- self.setHeader("Content-Type", "text/plain")
- self.write('Error ')
- self.write(': ')
- self.write(str(err))
- return None
-
- def useSxp(self):
- """Determine whether to send an SXP response to a request.
- Uses SXP if there is no User-Agent, no Accept, or application/sxp is in Accept.
-
- returns 1 for SXP, 0 otherwise
- """
- ok = 0
- user_agent = self.getHeader('User-Agent')
- accept = self.getHeader('Accept')
- if (not user_agent) or (not accept) or (accept.find(sxp.mime_type) >= 0):
- ok = 1
- return ok
-
- def printPath(self):
- pathlist = [x for x in self.prepath if x != '' ]
- s = "/"
- self.write('<h1><a href="/">/</a>')
- for x in pathlist:
- s += x + "/"
- self.write(' <a href="%s">%s</a>/' % (s, x))
- self.write("</h1>")
-
-class HttpServerClient:
-
- def __init__(self, server, sock, addr):
- self.server = server
- self.sock = sock
- self.addr = addr
-
- def process(self):
- thread = threading.Thread(target=self.doProcess)
- thread.setDaemon(True)
- thread.start()
-
- def doProcess(self):
- try:
- rp = RequestProcessor(self.server, self.sock, self.addr)
- rp.process()
- except SystemExit:
- raise
- except Exception, ex:
- print 'HttpServer>processRequest> exception: ', ex
- try:
- self.sock.close()
- except:
- pass
-
-class HttpServer:
-
- backlog = 5
-
- def __init__(self, root, interface, port=8080):
- self.root = root
- self.interface = interface
- self.port = port
- # ready indicates when we are ready to begin accept connections
- # it should be set after a successful bind
- self.ready = False
- self.closed = False
-
- def run(self):
- self.bind()
- self.listen()
- self.ready = True
-
- while not self.closed:
- (sock, addr) = self.accept()
- cl = HttpServerClient(self, sock, addr)
- cl.process()
-
- def stop(self):
- self.close()
-
- def bind(self):
- self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- flags = fcntl.fcntl(self.socket.fileno(), fcntl.F_GETFD)
- flags |= fcntl.FD_CLOEXEC
- fcntl.fcntl(self.socket.fileno(), fcntl.F_SETFD, flags)
- self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- self.socket.bind((self.interface, self.port))
-
- def listen(self):
- self.socket.listen(self.backlog)
-
- def accept(self):
- return self.socket.accept()
-
- def close(self):
- self.closed = True
- self.ready = False
- # shutdown socket explicitly to allow reuse
- try:
- self.socket.shutdown(2)
- except socket.error:
- pass
-
- try:
- self.socket.close()
- except socket.error:
- pass
-
- def getServerAddr(self):
- return (socket.gethostname(), self.port)
-
- def getResource(self, req):
- return self.root.getRequestResource(req)
-
- def shutdown(self):
- self.close()
-
-
-class UnixHttpServer(HttpServer):
-
- def __init__(self, root, path):
- HttpServer.__init__(self, root, 'localhost')
- self.path = path
-
- def bind(self):
- self.socket = unix.bind(self.path)
- flags = fcntl.fcntl(self.socket.fileno(), fcntl.F_GETFD)
- flags |= fcntl.FD_CLOEXEC
- fcntl.fcntl(self.socket.fileno(), fcntl.F_SETFD, flags)
diff --git a/tools/python/xen/web/protocol.py b/tools/python/xen/web/protocol.py
deleted file mode 100644
index 603973a..0000000
--- a/tools/python/xen/web/protocol.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd.
-#============================================================================
-
-class Protocol:
-
- def __init__(self):
- self.transport = None
-
- def setTransport(self, transport):
- self.transport = transport
-
- def dataReceived(self, data):
- raise NotImplementedError()
-
- def write(self, data):
- if self.transport:
- return self.transport.write(data)
- else:
- return 0
-
- def read(self):
- if self.transport:
- return self.transport.read()
- else:
- return None
diff --git a/tools/python/xen/web/resource.py b/tools/python/xen/web/resource.py
deleted file mode 100644
index 6c226bb..0000000
--- a/tools/python/xen/web/resource.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
-
-import http
-
-def findResource(resource, request):
- """Traverse resource tree to find who will handle the request."""
- while request.postpath and not resource.isLeaf:
- #print 'findResource:', resource, request.postpath
- pathElement = request.postpath.pop(0)
- request.prepath.append(pathElement)
- next = resource.getPathResource(pathElement, request)
- if not next: break
- resource = next
- return resource
-
-class Resource:
-
- isLeaf = False
-
- def __init__(self):
- self.children = {}
-
- def getRequestResource(self, req):
- return findResource(self, req)
-
- def getChild(self, path, request):
- return None
-
- def getPathResource(self, path, request):
- #print 'getPathResource>', self, path
- if self.children.has_key(path):
- val = self.children[path]
- else:
- val = self.getChild(path, request)
- #print 'getPathResource<', val
- return val
-
- def putChild(self, path, child):
- self.children[path] = child
- #child.server = self.server
-
- def render(self, req):
- meth = getattr(self, 'render_' + req.getRequestMethod(), self.unsupported)
- return meth(req)
-
- def supportedMethods(self):
- l = []
- s = 'render_'
- for x in dir(self):
- if x.startswith(s):
- l.append(x[len(s):])
- return l
-
- def render_HEAD(self, req):
- return self.render_GET(req)
-
- def render_GET(self, req):
- req.setContentType("text/plain")
- req.write("GET")
-
- def render_POST(self, req):
- req.setContentType("text/plain")
- req.write("POST")
-
- def unsupported(self, req):
- req.setHeader("Accept", ",".join(self.supportedMethods()))
- req.setResponseCode(http.NOT_IMPLEMENTED)
- req.setContentType("text/plain")
- req.write("Request method not supported (%s)" % req.getRequestMethod())
-
-class ErrorPage(Resource):
-
- isLeaf = True
-
- def __init__(self, code, status=None, msg=None):
- Resource.__init__(self)
- if status is None:
- status = http.getStatus(code)
- if msg is None:
- msg = status
- self.code = code
- self.status = status
- self.msg = msg
-
- def render(self, req):
- req.setResponseCode(self.code, self.status)
- req.setContentType("text/plain")
- req.write(self.msg)
-
-
-
-
-
diff --git a/tools/python/xen/web/static.py b/tools/python/xen/web/static.py
deleted file mode 100644
index 70cb7d6..0000000
--- a/tools/python/xen/web/static.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
-import os
-
-from resource import Resource
-
-class File(Resource):
-
- isLeaf = True
-
- def __init__(self, filename, defaultType=None):
- if defaultType is None:
- defaultType = "text/plain"
- self.filename = filename
- self.type = defaultType
- self.encoding = None
-
- def getFileSize(self):
- try:
- info = os.stat(self.filename)
- return info.st_size
- except:
- return 0
-
- def render(self, req):
- if self.type:
- req.setHeader('Content-Type', self.type)
- if self.encoding:
- req.setHeader('Content-Encoding', self.encoding)
- req.setHeader('Content-Length', self.getFileSize())
- try:
- io = file(self.filename, "r")
- while True:
- buf = io.read(1024)
- if not buf:
- break
- req.write(buf)
- except IOError:
- pass
- try:
- if io:
- io.close()
- except:
- pass
-
-
-
diff --git a/tools/python/xen/web/tcp.py b/tools/python/xen/web/tcp.py
deleted file mode 100644
index 2227375..0000000
--- a/tools/python/xen/web/tcp.py
+++ /dev/null
@@ -1,212 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd.
-#============================================================================
-
-
-import errno
-import re
-import socket
-import time
-import fcntl # For get_interface_addr
-import struct # For get_interface_addr
-
-import connection
-
-from xen.xend.XendLogging import log
-
-
-class TCPListener(connection.SocketListener):
-
- def __init__(self, protocol_class, port, interface, hosts_allow):
- self.port = port
- self.interface = interface
- self.hosts_allow = hosts_allow
- connection.SocketListener.__init__(self, protocol_class)
-
- def isValidHex(self, word):
- # If we have empty word we treat it as valid
- if len(word) == 0:
- return True
- try:
- int(word, 16)
- return True
- except ValueError:
- return False
-
- def isValidIP(self, ipaddr):
- # Check for IPv4 address
- numValid = 0
- tmp = ipaddr.split('.')
- for byte in tmp:
- if byte.isdigit():
- numValid += 1
-
- if numValid == len(tmp):
- return True
-
- # Check for IPv6 address
- numValid = 0
- tmp = ipaddr.split(':')
- for word in tmp:
- if self.isValidHex(word):
- numValid += 1
-
- return numValid == len(tmp)
-
- def getIfAddr(self, ifname):
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- try:
- x = socket.inet_ntoa(fcntl.ioctl(
- s.fileno(),
- 0x8915, # SIOCGIFADDR
- struct.pack('256s', ifname[:15])
- )[20:24])
- s.close()
- except Exception, e:
- x = ifname
-
- return x
-
- def createSocket(self):
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-
- # SO_REUSEADDR does not always ensure that we do not get an address
- # in use error when restarted quickly
- # we implement a timeout to try and avoid failing unnecessarily
- timeout = time.time() + 30
- while True:
- try:
- if not self.isValidIP(self.interface):
- self.interface = self.getIfAddr(self.interface)
- log.debug("Listening on %s:%s" % (self.interface, self.port))
- sock.bind((self.interface, self.port))
- return sock
- except socket.error, (_errno, strerrno):
- if _errno == errno.EADDRINUSE and time.time() < timeout:
- time.sleep(0.5)
- else:
- raise
-
-
- def acceptConnection(self, sock, addrport):
- addr = addrport[0]
- if connection.hostAllowed(addrport, self.hosts_allow):
- connection.SocketServerConnection(sock, self.protocol_class)
- else:
- try:
- sock.close()
- except:
- pass
-
-class SSLTCPListener(TCPListener):
-
- def __init__(self, protocol_class, port, interface, hosts_allow,
- ssl_key_file = None, ssl_cert_file = None):
- if not ssl_key_file or not ssl_cert_file:
- raise ValueError("SSLXMLRPCServer requires ssl_key_file "
- "and ssl_cert_file to be set.")
-
- self.ssl_key_file = ssl_key_file
- self.ssl_cert_file = ssl_cert_file
-
- TCPListener.__init__(self, protocol_class, port, interface, hosts_allow)
-
- def isValidHex(self, word):
- # If we have empty word we treat it as valid
- if len(word) == 0:
- return True
- try:
- int(word, 16)
- return True
- except ValueError:
- return False
-
- def isValidIP(self, ipaddr):
- # Check for IPv4 address
- numValid = 0
- tmp = ipaddr.split('.')
- for byte in tmp:
- if byte.isdigit():
- numValid += 1
-
- if numValid == len(tmp):
- return True
-
- # Check for IPv6 address
- numValid = 0
- tmp = ipaddr.split(':')
- for word in tmp:
- if self.isValidHex(word):
- numValid += 1
-
- return numValid == len(tmp)
-
- def getIfAddr(self, ifname):
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- try:
- x = socket.inet_ntoa(fcntl.ioctl(
- s.fileno(),
- 0x8915, # SIOCGIFADDR
- struct.pack('256s', ifname[:15])
- )[20:24])
- s.close()
- except Exception, e:
- x = ifname
-
- return x
-
- def createSocket(self):
- from OpenSSL import SSL
- # make a SSL socket
- ctx = SSL.Context(SSL.SSLv23_METHOD)
- ctx.set_options(SSL.OP_NO_SSLv2)
- ctx.use_privatekey_file (self.ssl_key_file)
- ctx.use_certificate_file(self.ssl_cert_file)
- sock = SSL.Connection(ctx,
- socket.socket(socket.AF_INET, socket.SOCK_STREAM))
- sock.set_accept_state()
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-
- # SO_REUSEADDR does not always ensure that we do not get an address
- # in use error when restarted quickly
- # we implement a timeout to try and avoid failing unnecessarily
- timeout = time.time() + 30
- while True:
- try:
- if not self.isValidIP(self.interface):
- self.interface = self.getIfAddr(self.interface)
- log.debug("Listening on %s:%s" % (self.interface, self.port))
- sock.bind((self.interface, self.port))
- return sock
- except socket.error, (_errno, strerrno):
- if _errno == errno.EADDRINUSE and time.time() < timeout:
- time.sleep(0.5)
- else:
- raise
-
-
- def acceptConnection(self, sock, addrport):
- addr = addrport[0]
- if connection.hostAllowed(addrport, self.hosts_allow):
- connection.SSLSocketServerConnection(sock, self.protocol_class)
- else:
- try:
- sock.close()
- except:
- pass
-
diff --git a/tools/python/xen/web/unix.py b/tools/python/xen/web/unix.py
deleted file mode 100644
index 180c085..0000000
--- a/tools/python/xen/web/unix.py
+++ /dev/null
@@ -1,69 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005-2006 XenSource Ltd.
-#============================================================================
-
-
-import os
-import os.path
-import socket
-import stat
-
-from xen.util import mkdir
-
-import connection
-
-
-def bind(path, type = socket.SOCK_STREAM):
- """Create a Unix socket, and bind it to the given path.
- The socket is created such that only the current user may access it."""
-
- if path[0] == '\0': # Abstract namespace is used for the path
- pass
- else:
- parent = os.path.dirname(path)
- mkdir.parents(parent, stat.S_IRWXU, True)
- if os.path.exists(path):
- os.unlink(path)
-
- sock = socket.socket(socket.AF_UNIX, type)
- sock.bind(path)
- return sock
-
-
-class UnixListener(connection.SocketListener):
- def __init__(self, path, protocol_class):
- self.path = path
- connection.SocketListener.__init__(self, protocol_class)
-
-
- def createSocket(self):
- return bind(self.path, socket.SOCK_STREAM)
-
-
- def acceptConnection(self, sock, _):
- connection.SocketServerConnection(sock, self.protocol_class)
-
-
-class UnixDgramListener(connection.SocketDgramListener):
- def __init__(self, path, protocol_class):
- self.path = path
- connection.SocketDgramListener.__init__(self, protocol_class)
-
-
- def createSocket(self):
- return bind(self.path, socket.SOCK_DGRAM)
-
diff --git a/tools/python/xen/xend/Args.py b/tools/python/xen/xend/Args.py
deleted file mode 100644
index e2193b6..0000000
--- a/tools/python/xen/xend/Args.py
+++ /dev/null
@@ -1,166 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
-
-import types
-import StringIO
-
-from xen.xend import sxp
-
-class ArgError(StandardError):
- pass
-
-class Args:
- """Argument encoding support for HTTP.
- """
-
- def __init__(self, paramspec, keyspec):
- self.arg_ord = []
- self.arg_dict = {}
- self.key_ord = []
- self.key_dict = {}
- for (name, typ) in paramspec:
- self.arg_ord.append(name)
- self.arg_dict[name] = typ
- for (name, typ) in keyspec:
- self.key_ord.append(name)
- self.key_dict[name] = typ
-
- def get_args(self, d, xargs=None):
- args = {}
- keys = {}
- params = []
- if xargs:
- self.split_args(xargs, args, keys)
- self.split_args(d, args, keys)
- for a in self.arg_ord:
- if a in args:
- params.append(args[a])
- else:
- raise ArgError('Missing parameter: %s' % a)
- return (params, keys)
-
- def split_args(self, d, args, keys):
- for (k, v) in d.items():
- if k in self.arg_dict:
- typ = self.arg_dict[k]
- val = self.coerce(typ, v)
- args[k] = val
- elif k in self.key_dict:
- typ = self.key_dict[k]
- val = self.coerce(typ, v)
- keys[k] = val
- else:
- raise ArgError('Invalid parameter: %s' % k)
-
- def get_form_args(self, f, xargs=None):
- d = {}
- for (k, v) in f.items():
- if ((k not in self.arg_dict) and
- (k not in self.key_dict)):
- continue
- if isinstance(v, types.ListType):
- n = len(v)
- if n == 0:
- continue
- elif n == 1:
- val = v[0]
- else:
- raise ArgError('Too many values for %s' % k)
- else:
- val = v
- d[k] = val
- return self.get_args(d, xargs=xargs)
-
- def coerce(self, typ, v):
- try:
- if typ == 'int':
- val = int(v)
- elif typ == 'long':
- val = long(v)
- elif typ == 'str':
- val = str(v)
- elif typ == 'sxpr':
- val = self.sxpr(v)
- elif typ == 'bool':
- val = self.bool(v)
- else:
- raise ArgError('invalid type:' + str(typ))
- return val
- except ArgError:
- raise
- except StandardError, ex:
- raise ArgError(str(ex))
-
- def bool(self, v):
- return (v.lower() in ['on', 'yes', '1', 'true'])
-
- def sxpr(self, v):
- if isinstance(v, types.ListType):
- val = v
- elif isinstance(v, types.FileType) or hasattr(v, 'readline'):
- val = self.sxpr_file(v)
- elif isinstance(v, types.StringType):
- val = self.sxpr_file(StringIO.StringIO(v))
- else:
- val = str(v)
- return val
-
- def sxpr_file(self, fin):
- try:
- vals = sxp.parse(fin)
- except:
- raise ArgError('Coercion to sxpr failed')
- if len(vals) == 1:
- return vals[0]
- else:
- raise ArgError('Too many sxprs')
-
- def call_with_args(self, fn, args, xargs=None):
- (params, keys) = self.get_args(args, xargs=xargs)
- return fn(*params, **keys)
-
- def call_with_form_args(self, fn, fargs, xargs=None):
- (params, keys) = self.get_form_args(fargs, xargs=xargs)
- return fn(*params, **keys)
-
-class ArgFn(Args):
- """Represent a remote HTTP operation as a function.
- Used on the client.
- """
-
- def __init__(self, fn, paramspec, keyspec = None):
- if keyspec == None:
- keyspec = {}
- Args.__init__(self, paramspec, keyspec)
- self.fn = fn
-
- def __call__(self, fargs, xargs=None):
- return self.call_with_args(self.fn, fargs, xargs=xargs)
-
-class FormFn(Args):
- """Represent an operation as a function over a form.
- Used in the HTTP server.
- """
-
- def __init__(self, fn, paramspec, keyspec = None):
- if keyspec == None:
- keyspec = {}
- Args.__init__(self, paramspec, keyspec)
- self.fn = fn
-
- def __call__(self, fargs, xargs=None):
- return self.call_with_form_args(self.fn, fargs, xargs=xargs)
diff --git a/tools/python/xen/xend/MemoryPool.py b/tools/python/xen/xend/MemoryPool.py
deleted file mode 100644
index 1a9add6..0000000
--- a/tools/python/xen/xend/MemoryPool.py
+++ /dev/null
@@ -1,118 +0,0 @@
-#===========================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2009 Novell, Inc.
-# Author: James (Song Wei) <jsong at novell.com>
-#============================================================================
-
-import xen.lowlevel.xc
-import XendDomain
-import XendOptions
-from XendLogging import log
-from XendError import VmError
-
-class MemoryPool:
-
- def init(self):
- xoptions = XendOptions.instance()
- self.default_reserved_memory = xoptions.get_reserved_memory() * 1024 * 1024 #KiB
- if self.default_reserved_memory <= 0:
- return
- self.enable_memory_pool = 1
- self.dom0_ballooning = xoptions.get_enable_dom0_ballooning()
- if not self.dom0_ballooning:
- return
- self.reserve_memory = 0
- self.untouched_memory = 0
- #init reserved memory
- #if not reserve_memory_size:
- xc = xen.lowlevel.xc.xc()
- physinfo = xc.physinfo()
- total_mem = physinfo['total_memory']
- if total_mem < self.reserve_memory:
- self.default_reserved_memory = total_mem
- self.reserve_memory = self.default_reserved_memory
- self.untouched_memory = self.default_reserved_memory
- log.debug("MemoryPool: init reserved_memory %d KiB" %self.reserve_memory)
-
- def __init__(self):
- self.reserve_memory = 0
- self.untouched_memory = 0
- self.default_reserved_memory = 0
- self.enable_memory_pool = 0
- self.dom0_ballooning = 0
- def available_memory_check(self, need_mem):
- return self.is_enabled() and self.reserved_memory > need_mem
-
- def decrease_memory(self, value):
- if not self.is_enabled() or value <= 4096: #4M for PV guest kernel and ramdisk unzip
- return
- elif self.reserve_memory < value:
- raise VMError(('I need %d KiB, but only have %d KiB in Memory Pool') %(value,self.reserve_memory))
- else:
- self.reserve_memory -= value
- log.debug("MemoryPool: decrease_memory: decrease: %d reserved_memory %d KiB" %(value,self.reserve_memory))
- return
-
- def decrease_untouched_memory(self, value):
- if not self.is_enabled():
- return
- elif self.untouched_memory < value:
- raise VmError(('I need %d KiB untouch mem, but only have %d KiB untouched mem in Memory Pool') %(value,self.reserve_memory))
- else:
- self.untouched_memory -= value
- log.debug("MemoryPool: decrease_untouched_memory: untouched_memory %d KiB" %self.untouched_memory)
- return
-
- def increase_memory(self, value):
- if not self.is_enabled():
- return
- else:
- self.reserve_memory += value
- if self.reserve_memory > self.default_reserved_memory:
- raise VmError(('the maxsize of memory pool is %d KiB, but current is %d KiB') %(value,self.reserve_memory))
- log.debug("MemoryPool: increase_memory:%d, reserved_memory %d KiB" %(value,self.reserve_memory))
- return
-
- def is_enabled(self):
- return self.enable_memory_pool and self.dom0_ballooning
-
- def get_pool_size(self):
- if self.is_enabled():
- return self.default_reserved_memory
- else:
- return 0
-
- def get_left_memory(self):
- if self.is_enabled():
- return self.reserve_memory
- else:
- return 0
-
- def get_untouched_memory(self):
- if self.is_enabled():
- return self.untouched_memory
- else:
- return 0
-
-def instance():
- """Singleton constructor. Use this instead of the class constructor.
- """
- global MP_inst
- try:
- MP_inst
- except:
- MP_inst = MemoryPool()
- MP_inst.init()
- return MP_inst
diff --git a/tools/python/xen/xend/PrettyPrint.py b/tools/python/xen/xend/PrettyPrint.py
deleted file mode 100644
index 22a78fb..0000000
--- a/tools/python/xen/xend/PrettyPrint.py
+++ /dev/null
@@ -1,323 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-"""General pretty-printer, including support for SXP.
-
-"""
-import sys
-import types
-import StringIO
-from xen.xend import sxp
-
-class PrettyItem:
-
- def __init__(self, width):
- self.width = width
-
- def insert(self, block):
- block.addtoline(self)
-
- def get_width(self):
- return self.width
-
- def output(self, _):
- print '***PrettyItem>output>', self
- pass
-
- def prettyprint(self, _):
- print '***PrettyItem>prettyprint>', self
- return self.width
-
-class PrettyString(PrettyItem):
-
- def __init__(self, x):
- PrettyItem.__init__(self, len(x))
- self.value = x
-
- def output(self, out):
- out.write(self.value)
-
- def prettyprint(self, line):
- line.output(self)
-
- def show(self, out):
- print >> out, ("(string (width %d) '%s')" % (self.width, self.value))
-
-class PrettySpace(PrettyItem):
-
- def output(self, out):
- out.write(' ' * self.width)
-
- def prettyprint(self, line):
- line.output(self)
-
- def show(self, out):
- print >> out, ("(space (width %d))" % self.width)
-
-class PrettyBreak(PrettyItem):
-
- def __init__(self, width, indent):
- PrettyItem.__init__(self, width)
- self.indent = indent
- self.space = 0
- self.active = 0
-
- def output(self, out):
- out.write(' ' * self.width)
-
- def prettyprint(self, line):
- if line.breaks(self.space):
- self.active = 1
- line.newline(self.indent)
- else:
- line.output(self)
-
- def show(self, out):
- print >> out, ("(break (width %d) (indent %d) (space %d) (active %d))"
- % (self.width, self.indent, self.space, self.active))
-
-class PrettyNewline(PrettySpace):
-
- def insert(self, block):
- block.newline()
- block.addtoline(self)
-
- def prettyprint(self, line):
- line.newline(0)
- line.output(self)
-
- def show(self, out):
- print >> out, ("(nl (width %d))" % self.width)
-
-class PrettyLine(PrettyItem):
- def __init__(self):
- PrettyItem.__init__(self, 0)
- self.content = []
-
- def write(self, x):
- self.content.append(x)
-
- def end(self):
- width = 0
- lastwidth = 0
- lastbreak = None
- for x in self.content:
- if isinstance(x, PrettyBreak):
- if lastbreak:
- lastbreak.space = (width - lastwidth)
- lastbreak = x
- lastwidth = width
- width += x.get_width()
- if lastbreak:
- lastbreak.space = (width - lastwidth)
- self.width = width
-
- def prettyprint(self, line):
- for x in self.content:
- x.prettyprint(line)
-
- def show(self, out):
- print >> out, '(LINE (width %d)' % self.width
- for x in self.content:
- x.show(out)
- print >> out, ')'
-
-class PrettyBlock(PrettyItem):
-
- def __init__(self, all=0, parent=None):
- PrettyItem.__init__(self, 0)
-
- self.lines = []
- self.parent = parent
- self.indent = 0
- self.all = all
- self.broken = 0
- self.newline()
-
- def add(self, item):
- item.insert(self)
-
- def end(self):
- self.width = 0
- for l in self.lines:
- l.end()
- if self.width < l.width:
- self.width = l.width
-
- def breaks(self, _):
- return self.all and self.broken
-
- def newline(self):
- self.lines.append(PrettyLine())
-
- def addtoline(self, x):
- self.lines[-1].write(x)
-
- def prettyprint(self, line):
- self.indent = line.used
- line.block = self
- if not line.fits(self.width):
- self.broken = 1
- for l in self.lines:
- l.prettyprint(line)
- line.block = self.parent
-
- def show(self, out):
- print >> out, ('(BLOCK (width %d) (indent %d) (all %d) (broken %d)' %
- (self.width, self.indent, self.all, self.broken))
- for l in self.lines:
- l.show(out)
- print >> out, ')'
-
-class Line:
-
- def __init__(self, out, width):
- self.block = None
- self.out = out
- self.width = width
- self.used = 0
- self.space = self.width
-
- def newline(self, indent):
- indent += self.block.indent
- self.out.write('\n')
- self.out.write(' ' * indent)
- self.used = indent
- self.space = self.width - self.used
-
- def fits(self, n):
- return self.space - n >= 0
-
- def breaks(self, n):
- return self.block.breaks(n) or not self.fits(n)
-
- def output(self, x):
- n = x.get_width()
- self.space -= n
- self.used += n
- if self.space < 0:
- self.space = 0
- x.output(self.out)
-
-class PrettyPrinter:
- """A prettyprinter based on what I remember of Derek Oppen's
- prettyprint algorithm from TOPLAS way back.
- """
-
- def __init__(self, width=40):
- self.width = width
- self.block = None
- self.top = None
-
- def write(self, x):
- self.block.add(PrettyString(x))
-
- def add(self, item):
- self.block.add(item)
-
- def addbreak(self, width=1, indent=4):
- self.add(PrettyBreak(width, indent))
-
- def addspace(self, width=1):
- self.add(PrettySpace(width))
-
- def addnl(self, indent=0):
- self.add(PrettyNewline(indent))
-
- def begin(self, all=0):
- block = PrettyBlock(all=all, parent=self.block)
- self.block = block
-
- def end(self):
- self.block.end()
- if self.block.parent:
- self.block.parent.add(self.block)
- else:
- self.top = self.block
- self.block = self.block.parent
-
- def prettyprint(self, out=sys.stdout):
- self.top.prettyprint(Line(out, self.width))
-
-class SXPPrettyPrinter(PrettyPrinter):
- """An SXP prettyprinter.
- """
-
- def pstring(self, x):
- io = StringIO.StringIO()
- sxp.show(x, out=io)
- io.seek(0)
- val = io.getvalue()
- io.close()
- return val
-
- def pprint(self, l):
- if isinstance(l, types.ListType):
- self.begin(all=1)
- self.write('(')
- i = 0
- for x in l:
- if(i): self.addbreak()
- self.pprint(x)
- i += 1
- self.addbreak(width=0, indent=0)
- self.write(')')
- self.end()
- else:
- self.write(self.pstring(l))
-
-def prettyprint(sxpr, out=sys.stdout, width=80):
- """Prettyprint an SXP form.
-
- sxpr s-expression
- out destination
- width maximum output width
- """
- if isinstance(sxpr, types.ListType):
- pp = SXPPrettyPrinter(width=width)
- pp.pprint(sxpr)
- pp.prettyprint(out=out)
- else:
- sxp.show(sxpr, out=out)
- print >> out
-
-def prettyprintstring(sxpr, width=80):
- """Prettyprint an SXP form to a string.
-
- sxpr s-expression
- width maximum output width
- """
- io = StringIO.StringIO()
- prettyprint(sxpr, out=io, width=width)
- io.seek(0)
- val = io.getvalue()
- io.close()
- return val
-
-def main():
- pin = sxp.Parser()
- while 1:
- buf = sys.stdin.read(100)
- pin.input(buf)
- if buf == '': break
- l = pin.get_val()
- prettyprint(l, width=80)
-
-if __name__ == "__main__":
- main()
-
diff --git a/tools/python/xen/xend/Vifctl.py b/tools/python/xen/xend/Vifctl.py
deleted file mode 100644
index 58d4ae7..0000000
--- a/tools/python/xen/xend/Vifctl.py
+++ /dev/null
@@ -1,35 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-"""Xend interface to networking control scripts.
-"""
-
-import XendOptions
-from xen.util import xpopen
-
-def network(op):
- """Call a network control script.
-
- @param op: operation (start, stop)
- """
- if op not in ['start', 'stop']:
- raise ValueError('Invalid operation: ' + op)
- script = XendOptions.instance().get_network_script()
- if script:
- script.insert(1, op)
- xpopen.call(script)
diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py
deleted file mode 100644
index 359a26b..0000000
--- a/tools/python/xen/xend/XendAPI.py
+++ /dev/null
@@ -1,2812 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006-2007 XenSource Ltd.
-#============================================================================
-
-import inspect
-import os
-import Queue
-import string
-import sys
-import traceback
-import threading
-import time
-import xmlrpclib
-
-# sets is deprecated as of python 2.6, but set is unavailable in 2.3
-try:
- set
-except NameError:
- from sets import Set as set
-
-import XendDomain, XendDomainInfo, XendNode, XendDmesg
-import XendLogging, XendTaskManager, XendAPIStore
-
-from xen.xend import uuid as genuuid
-from XendAPIVersion import *
-from XendAuthSessions import instance as auth_manager
-from XendError import *
-from XendClient import ERROR_INVALID_DOMAIN
-from XendLogging import log
-from XendNetwork import XendNetwork
-from XendTask import XendTask
-from XendPIFMetrics import XendPIFMetrics
-from XendVMMetrics import XendVMMetrics
-from XendPIF import XendPIF
-from XendPBD import XendPBD
-from XendPPCI import XendPPCI
-from XendDPCI import XendDPCI
-from XendPSCSI import XendPSCSI, XendPSCSI_HBA
-from XendDSCSI import XendDSCSI, XendDSCSI_HBA
-from XendXSPolicy import XendXSPolicy, XendACMPolicy
-from xen.xend.XendCPUPool import XendCPUPool
-
-from XendAPIConstants import *
-from xen.util.xmlrpclib2 import stringify
-
-from xen.util.blkif import blkdev_name_to_number
-from xen.util import xsconstants
-
-
-AUTH_NONE = 'none'
-AUTH_PAM = 'pam'
-
-argcounts = {}
-
-# ------------------------------------------
-# Utility Methods for Xen API Implementation
-# ------------------------------------------
-
-def xen_api_success(value):
- """Wraps a return value in XenAPI format."""
- if value is None:
- s = ''
- else:
- s = stringify(value)
- return {"Status": "Success", "Value": s}
-
-def xen_api_success_void():
- """Return success, but caller expects no return value."""
- return xen_api_success("")
-
-def xen_api_error(error):
- """Wraps an error value in XenAPI format."""
- if type(error) == tuple:
- error = list(error)
- if type(error) != list:
- error = [error]
- if len(error) == 0:
- error = ['INTERNAL_ERROR', 'Empty list given to xen_api_error']
-
- return { "Status": "Failure",
- "ErrorDescription": [str(x) for x in error] }
-
-
-def xen_api_todo():
- """Temporary method to make sure we track down all the TODOs"""
- return {"Status": "Error", "ErrorDescription": XEND_ERROR_TODO}
-
-
-def now():
- return datetime()
-
-
-def datetime(when = None):
- """Marshall the given time as a Xen-API DateTime.
-
- @param when The time in question, given as seconds since the epoch, UTC.
- May be None, in which case the current time is used.
- """
- if when is None:
- return xmlrpclib.DateTime(time.gmtime())
- else:
- return xmlrpclib.DateTime(time.gmtime(when))
-
-
-# ---------------------------------------------------
-# Event dispatch
-# ---------------------------------------------------
-
-EVENT_QUEUE_LENGTH = 50
-event_registrations = {}
-
-def event_register(session, reg_classes):
- if session not in event_registrations:
- event_registrations[session] = {
- 'classes' : set(),
- 'queue' : Queue.Queue(EVENT_QUEUE_LENGTH),
- 'next-id' : 1
- }
- if not reg_classes:
- reg_classes = classes
- sessionclasses = event_registrations[session]['classes']
- if hasattr(sessionclasses, 'union_update'):
- sessionclasses.union_update(reg_classes)
- else:
- sessionclasses.update(reg_classes)
-
-
-
-def event_unregister(session, unreg_classes):
- if session not in event_registrations:
- return
-
- if unreg_classes:
- event_registrations[session]['classes'].intersection_update(
- unreg_classes)
- if len(event_registrations[session]['classes']) == 0:
- del event_registrations[session]
- else:
- del event_registrations[session]
-
-
-def event_next(session):
- if session not in event_registrations:
- return xen_api_error(['SESSION_NOT_REGISTERED', session])
- queue = event_registrations[session]['queue']
- events = [queue.get()]
- try:
- while True:
- events.append(queue.get(False))
- except Queue.Empty:
- pass
-
- return xen_api_success(events)
-
-
-def _ctor_event_dispatch(xenapi, ctor, api_cls, session, args):
- result = ctor(xenapi, session, *args)
- if result['Status'] == 'Success':
- ref = result['Value']
- event_dispatch('add', api_cls, ref, '')
- return result
-
-
-def _dtor_event_dispatch(xenapi, dtor, api_cls, session, ref, args):
- result = dtor(xenapi, session, ref, *args)
- if result['Status'] == 'Success':
- event_dispatch('del', api_cls, ref, '')
- return result
-
-
-def _setter_event_dispatch(xenapi, setter, api_cls, attr_name, session, ref,
- args):
- result = setter(xenapi, session, ref, *args)
- if result['Status'] == 'Success':
- event_dispatch('mod', api_cls, ref, attr_name)
- return result
-
-
-def event_dispatch(operation, api_cls, ref, attr_name):
- assert operation in ['add', 'del', 'mod']
- event = {
- 'timestamp' : now(),
- 'class' : api_cls,
- 'operation' : operation,
- 'ref' : ref,
- 'obj_uuid' : ref,
- 'field' : attr_name,
- }
- for reg in event_registrations.values():
- if api_cls in reg['classes']:
- event['id'] = reg['next-id']
- reg['next-id'] += 1
- reg['queue'].put(event)
-
-
-# ---------------------------------------------------
-# Python Method Decorators for input value validation
-# ---------------------------------------------------
-
-def trace(func, api_name = ''):
- """Decorator to trace XMLRPC Xen API methods.
-
- @param func: function with any parameters
- @param api_name: name of the api call for debugging.
- """
- if hasattr(func, 'api'):
- api_name = func.api
- def trace_func(self, *args, **kwargs):
- log.debug('%s: %s' % (api_name, args))
- return func(self, *args, **kwargs)
- trace_func.api = api_name
- return trace_func
-
-
-def catch_typeerror(func):
- """Decorator to catch any TypeErrors and translate them into Xen-API
- errors.
-
- @param func: function with params: (self, ...)
- @rtype: callable object
- """
- def f(self, *args, **kwargs):
- try:
- return func(self, *args, **kwargs)
- except TypeError, exn:
- #log.exception('catch_typeerror')
- if hasattr(func, 'api') and func.api in argcounts:
- # Assume that if the argument count was wrong and if the
- # exception was thrown inside this file, then it is due to an
- # invalid call from the client, otherwise it's an internal
- # error (which will be handled further up).
- expected = argcounts[func.api]
- actual = len(args) + len(kwargs)
- if expected != actual:
- tb = sys.exc_info()[2]
- try:
- sourcefile = traceback.extract_tb(tb)[-1][0]
- if sourcefile == inspect.getsourcefile(XendAPI):
- return xen_api_error(
- ['MESSAGE_PARAMETER_COUNT_MISMATCH',
- func.api, expected, actual])
- finally:
- del tb
- raise
- except XendAPIError, exn:
- return xen_api_error(exn.get_api_error())
-
- return f
-
-
-def session_required(func):
- """Decorator to verify if session is valid before calling method.
-
- @param func: function with params: (self, session, ...)
- @rtype: callable object
- """
- def check_session(self, session, *args, **kwargs):
- if auth_manager().is_session_valid(session):
- return func(self, session, *args, **kwargs)
- else:
- return xen_api_error(['SESSION_INVALID', session])
-
- return check_session
-
-
-def _is_valid_ref(ref, validator):
- return type(ref) == str and validator(ref)
-
-def _check_ref(validator, clas, func, api, session, ref, *args, **kwargs):
- if _is_valid_ref(ref, validator):
- return func(api, session, ref, *args, **kwargs)
- else:
- return xen_api_error(['HANDLE_INVALID', clas, ref])
-
-
-def valid_host(func):
- """Decorator to verify if host_ref is valid before calling method.
-
- @param func: function with params: (self, session, host_ref, ...)
- @rtype: callable object
- """
- return lambda *args, **kwargs: \
- _check_ref(XendNode.instance().is_valid_host,
- 'host', func, *args, **kwargs)
-
-def valid_host_metrics(func):
- """Decorator to verify if host_metrics_ref is valid before calling
- method.
-
- @param func: function with params: (self, session, host_metrics_ref)
- @rtype: callable object
- """
- return lambda *args, **kwargs: \
- _check_ref(lambda r: r == XendNode.instance().host_metrics_uuid,
- 'host_metrics', func, *args, **kwargs)
-
-def valid_host_cpu(func):
- """Decorator to verify if host_cpu_ref is valid before calling method.
-
- @param func: function with params: (self, session, host_cpu_ref, ...)
- @rtype: callable object
- """
- return lambda *args, **kwargs: \
- _check_ref(XendNode.instance().is_valid_cpu,
- 'host_cpu', func, *args, **kwargs)
-
-def valid_vm(func):
- """Decorator to verify if vm_ref is valid before calling method.
-
- @param func: function with params: (self, session, vm_ref, ...)
- @rtype: callable object
- """
- return lambda *args, **kwargs: \
- _check_ref(XendDomain.instance().is_valid_vm,
- 'VM', func, *args, **kwargs)
-
-def valid_vbd(func):
- """Decorator to verify if vbd_ref is valid before calling method.
-
- @param func: function with params: (self, session, vbd_ref, ...)
- @rtype: callable object
- """
- return lambda *args, **kwargs: \
- _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
- 'VBD', func, *args, **kwargs)
-
-def valid_vbd_metrics(func):
- """Decorator to verify if ref is valid before calling method.
-
- @param func: function with params: (self, session, ref, ...)
- @rtype: callable object
- """
- return lambda *args, **kwargs: \
- _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
- 'VBD_metrics', func, *args, **kwargs)
-
-def valid_vif(func):
- """Decorator to verify if vif_ref is valid before calling method.
-
- @param func: function with params: (self, session, vif_ref, ...)
- @rtype: callable object
- """
- return lambda *args, **kwargs: \
- _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
- 'VIF', func, *args, **kwargs)
-
-def valid_vif_metrics(func):
- """Decorator to verify if ref is valid before calling method.
-
- @param func: function with params: (self, session, ref, ...)
- @rtype: callable object
- """
- return lambda *args, **kwargs: \
- _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
- 'VIF_metrics', func, *args, **kwargs)
-
-def valid_vdi(func):
- """Decorator to verify if vdi_ref is valid before calling method.
-
- @param func: function with params: (self, session, vdi_ref, ...)
- @rtype: callable object
- """
- return lambda *args, **kwargs: \
- _check_ref(XendNode.instance().is_valid_vdi,
- 'VDI', func, *args, **kwargs)
-
-def valid_console(func):
- """Decorator to verify if console_ref is valid before calling method.
-
- @param func: function with params: (self, session, console_ref, ...)
- @rtype: callable object
- """
- return lambda *args, **kwargs: \
- _check_ref(lambda r: XendDomain.instance().is_valid_dev('console',
- r),
- 'console', func, *args, **kwargs)
-
-def valid_sr(func):
- """Decorator to verify if sr_ref is valid before calling method.
-
- @param func: function with params: (self, session, sr_ref, ...)
- @rtype: callable object
- """
- return lambda *args, **kwargs: \
- _check_ref(lambda r: XendNode.instance().is_valid_sr,
- 'SR', func, *args, **kwargs)
-
-def valid_task(func):
- """Decorator to verify if task_ref is valid before calling
- method.
-
- @param func: function with params: (self, session, task_ref)
- @rtype: callable object
- """
- return lambda *args, **kwargs: \
- _check_ref(XendTaskManager.get_task,
- 'task', func, *args, **kwargs)
-
-def valid_debug(func):
- """Decorator to verify if task_ref is valid before calling
- method.
-
- @param func: function with params: (self, session, task_ref)
- @rtype: callable object
- """
- return lambda *args, **kwargs: \
- _check_ref(lambda r: r in XendAPI._debug,
- 'debug', func, *args, **kwargs)
-
-
-def valid_object(class_name):
- """Decorator to verify if object is valid before calling
- method.
-
- @param func: function with params: (self, session, pif_ref)
- @rtype: callable object
- """
- return lambda func: \
- lambda *args, **kwargs: \
- _check_ref(lambda r: \
- XendAPIStore.get(r, class_name) is not None,
- class_name, func, *args, **kwargs)
-
-# -----------------------------
-# Bridge to Legacy XM API calls
-# -----------------------------
-
-def do_vm_func(fn_name, vm_ref, *args, **kwargs):
- """Helper wrapper func to abstract away from repetitive code.
-
- @param fn_name: function name for XendDomain instance
- @type fn_name: string
- @param vm_ref: vm_ref
- @type vm_ref: string
- @param *args: more arguments
- @type *args: tuple
- """
- try:
- xendom = XendDomain.instance()
- fn = getattr(xendom, fn_name)
- xendom.do_legacy_api_with_uuid(fn, vm_ref, *args, **kwargs)
- return xen_api_success_void()
- except VMBadState, exn:
- return xen_api_error(['VM_BAD_POWER_STATE', vm_ref, exn.expected,
- exn.actual])
-
-
-classes = {
- 'session' : None,
- 'event' : None,
- 'host' : valid_host,
- 'host_cpu' : valid_host_cpu,
- 'host_metrics' : valid_host_metrics,
- 'VM' : valid_vm,
- 'VBD' : valid_vbd,
- 'VBD_metrics' : valid_vbd_metrics,
- 'VIF' : valid_vif,
- 'VIF_metrics' : valid_vif_metrics,
- 'VDI' : valid_vdi,
- 'console' : valid_console,
- 'SR' : valid_sr,
- 'task' : valid_task,
- 'XSPolicy' : valid_object("XSPolicy"),
- 'ACMPolicy' : valid_object("ACMPolicy"),
- 'debug' : valid_debug,
- 'network' : valid_object("network"),
- 'PIF' : valid_object("PIF"),
- 'VM_metrics' : valid_object("VM_metrics"),
- 'PBD' : valid_object("PBD"),
- 'PIF_metrics' : valid_object("PIF_metrics"),
- 'PPCI' : valid_object("PPCI"),
- 'DPCI' : valid_object("DPCI"),
- 'PSCSI' : valid_object("PSCSI"),
- 'PSCSI_HBA' : valid_object("PSCSI_HBA"),
- 'DSCSI' : valid_object("DSCSI"),
- 'DSCSI_HBA' : valid_object("DSCSI_HBA"),
- 'cpu_pool' : valid_object("cpu_pool"),
-}
-
-autoplug_classes = {
- 'network' : XendNetwork,
- 'PIF' : XendPIF,
- 'VM_metrics' : XendVMMetrics,
- 'PBD' : XendPBD,
- 'PIF_metrics' : XendPIFMetrics,
- 'PPCI' : XendPPCI,
- 'DPCI' : XendDPCI,
- 'PSCSI' : XendPSCSI,
- 'PSCSI_HBA' : XendPSCSI_HBA,
- 'DSCSI' : XendDSCSI,
- 'DSCSI_HBA' : XendDSCSI_HBA,
- 'XSPolicy' : XendXSPolicy,
- 'ACMPolicy' : XendACMPolicy,
- 'cpu_pool' : XendCPUPool,
-}
-
-class XendAPI(object):
- """Implementation of the Xen-API in Xend. Expects to be
- used via XMLRPCServer.
-
- All methods that need a valid session are marked with
- a L{session_required} decorator that will
- transparently perform the required session authentication.
-
- We need to support Python <2.4, so we use the old decorator syntax.
-
- All XMLRPC accessible methods require an 'api' attribute and
- is set to the XMLRPC function name which the method implements.
- """
-
- __decorated__ = False
- __init_lock__ = threading.Lock()
- _debug = {}
-
- def __new__(cls, *args, **kwds):
- """ Override __new__ to decorate the class only once.
-
- Lock to make sure the classes are not decorated twice.
- """
- cls.__init_lock__.acquire()
- try:
- if not cls.__decorated__:
- cls._decorate()
- cls.__decorated__ = True
-
- return object.__new__(cls, *args, **kwds)
- finally:
- cls.__init_lock__.release()
-
- def _decorate(cls):
- """ Decorate all the object methods to have validators
- and appropriate function attributes.
-
- This should only be executed once for the duration of the
- server.
- """
- global_validators = [session_required, catch_typeerror]
-
-
- # Cheat methods
- # -------------
- # Methods that have a trivial implementation for all classes.
- # 1. get_by_uuid == getting by ref, so just return uuid for
- # all get_by_uuid() methods.
-
- for api_cls in classes.keys():
- # We'll let the autoplug classes implement these functions
- # themselves - its much cleaner to do it in the base class
- if api_cls == 'session' or api_cls in autoplug_classes.keys():
- continue
-
- get_by_uuid = '%s_get_by_uuid' % api_cls
- get_uuid = '%s_get_uuid' % api_cls
- get_all_records = '%s_get_all_records' % api_cls
-
- def _get_by_uuid(_1, _2, ref):
- return xen_api_success(ref)
-
- def _get_uuid(_1, _2, ref):
- return xen_api_success(ref)
-
- def unpack(v):
- return v.get('Value')
-
- def _get_all_records(_api_cls):
- return lambda s, session: \
- xen_api_success(dict([(ref, unpack(getattr(cls, '%s_get_record' % _api_cls)(s, session, ref)))\
- for ref in unpack(getattr(cls, '%s_get_all' % _api_cls)(s, session))]))
-
- setattr(cls, get_by_uuid, _get_by_uuid)
- setattr(cls, get_uuid, _get_uuid)
- setattr(cls, get_all_records, _get_all_records(api_cls))
-
- # Autoplugging classes
- # --------------------
- # These have all of their methods grabbed out from the implementation
- # class, and wrapped up to be compatible with the Xen-API.
-
- def getter(ref, type):
- return XendAPIStore.get(ref, type)
-
- for api_cls, impl_cls in autoplug_classes.items():
- def doit(n):
- dot_n = '%s.%s' % (api_cls, n)
- full_n = '%s_%s' % (api_cls, n)
- if not hasattr(cls, full_n):
- f = getattr(impl_cls, n)
- argcounts[dot_n] = f.func_code.co_argcount + 1
- g = lambda api_cls: \
- setattr(cls, full_n, \
- lambda s, session, ref, *args: \
- xen_api_success( \
- f(getter(ref, api_cls), *args)))
- g(api_cls) # Force api_cls to be captured
-
- def doit_func(n):
- dot_n = '%s.%s' % (api_cls, n)
- full_n = '%s_%s' % (api_cls, n)
- if not hasattr(cls, full_n):
- f = getattr(impl_cls, n)
- argcounts[dot_n] = f.func_code.co_argcount
- setattr(cls, full_n, \
- lambda s, session, *args: \
- xen_api_success( \
- f(*args)))
-
- ro_attrs = impl_cls.getAttrRO()
- rw_attrs = impl_cls.getAttrRW()
- methods = impl_cls.getMethods()
- funcs = impl_cls.getFuncs()
-
- for attr_name in ro_attrs + rw_attrs:
- doit('get_%s' % attr_name)
- for attr_name in rw_attrs:
- doit('set_%s' % attr_name)
- for method in methods:
- doit('%s' % method)
- for func in funcs:
- doit_func('%s' % func)
-
- def wrap_method(name, new_f):
- try:
- f = getattr(cls, name)
- wrapped_f = (lambda *args: new_f(f, *args))
- wrapped_f.api = f.api
- wrapped_f.async = f.async
- setattr(cls, name, wrapped_f)
- except AttributeError:
- # Logged below (API call: %s not found)
- pass
-
-
- def setter_event_wrapper(api_cls, attr_name):
- setter_name = '%s_set_%s' % (api_cls, attr_name)
- wrap_method(
- setter_name,
- lambda setter, s, session, ref, *args:
- _setter_event_dispatch(s, setter, api_cls, attr_name,
- session, ref, args))
-
-
- def ctor_event_wrapper(api_cls):
- ctor_name = '%s_create' % api_cls
- wrap_method(
- ctor_name,
- lambda ctor, s, session, *args:
- _ctor_event_dispatch(s, ctor, api_cls, session, args))
-
-
- def dtor_event_wrapper(api_cls):
- dtor_name = '%s_destroy' % api_cls
- wrap_method(
- dtor_name,
- lambda dtor, s, session, ref, *args:
- _dtor_event_dispatch(s, dtor, api_cls, session, ref, args))
-
-
- # Wrapping validators around XMLRPC calls
- # ---------------------------------------
-
- for api_cls, validator in classes.items():
- def doit(n, takes_instance, async_support = False,
- return_type = None):
- n_ = n.replace('.', '_')
- try:
- f = getattr(cls, n_)
- if n not in argcounts:
- argcounts[n] = f.func_code.co_argcount - 1
-
- validators = takes_instance and validator and \
- [validator] or []
-
- validators += global_validators
- for v in validators:
- f = v(f)
- f.api = n
- f.async = async_support
- if return_type:
- f.return_type = return_type
-
- setattr(cls, n_, f)
- except AttributeError:
- log.warn("API call: %s not found" % n)
-
- if api_cls in autoplug_classes.keys():
- impl_cls = autoplug_classes[api_cls]
- ro_attrs = impl_cls.getAttrRO()
- rw_attrs = impl_cls.getAttrRW()
- methods = map(lambda x: (x, ""), impl_cls.getMethods())
- funcs = map(lambda x: (x, ""), impl_cls.getFuncs())
- else:
- ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, []) \
- + cls.Base_attr_ro
- rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, []) \
- + cls.Base_attr_rw
- methods = getattr(cls, '%s_methods' % api_cls, []) \
- + cls.Base_methods
- funcs = getattr(cls, '%s_funcs' % api_cls, []) \
- + cls.Base_funcs
-
- # wrap validators around readable class attributes
- for attr_name in ro_attrs + rw_attrs:
- doit('%s.get_%s' % (api_cls, attr_name), True,
- async_support = False)
-
- # wrap validators around writable class attrributes
- for attr_name in rw_attrs:
- doit('%s.set_%s' % (api_cls, attr_name), True,
- async_support = False)
- setter_event_wrapper(api_cls, attr_name)
-
- # wrap validators around methods
- for method_name, return_type in methods:
- doit('%s.%s' % (api_cls, method_name), True,
- async_support = True)
-
- # wrap validators around class functions
- for func_name, return_type in funcs:
- doit('%s.%s' % (api_cls, func_name), False,
- async_support = True,
- return_type = return_type)
-
- ctor_event_wrapper(api_cls)
- dtor_event_wrapper(api_cls)
-
-
- _decorate = classmethod(_decorate)
-
- def __init__(self, auth):
- self.auth = auth
-
- Base_attr_ro = ['uuid']
- Base_attr_rw = []
- Base_methods = [('get_record', 'Struct')]
- Base_funcs = [('get_all', 'Set'), ('get_by_uuid', None), ('get_all_records', 'Set')]
-
- # Xen API: Class Session
- # ----------------------------------------------------------------
- # NOTE: Left unwrapped by __init__
-
- session_attr_ro = ['this_host', 'this_user', 'last_active']
- session_methods = [('logout', None)]
-
- def session_get_all(self, session):
- return xen_api_success([session])
-
- def session_login_with_password(self, *args):
- if len(args) != 2:
- return xen_api_error(
- ['MESSAGE_PARAMETER_COUNT_MISMATCH',
- 'session.login_with_password', 2, len(args)])
- username = args[0]
- password = args[1]
- try:
- session = ((self.auth == AUTH_NONE and
- auth_manager().login_unconditionally(username)) or
- auth_manager().login_with_password(username, password))
- return xen_api_success(session)
- except XendError, e:
- return xen_api_error(['SESSION_AUTHENTICATION_FAILED'])
- session_login_with_password.api = 'session.login_with_password'
-
- # object methods
- def session_logout(self, session):
- auth_manager().logout(session)
- return xen_api_success_void()
-
- def session_get_record(self, session, self_session):
- if self_session != session:
- return xen_api_error(['PERMISSION_DENIED'])
- record = {'uuid' : session,
- 'this_host' : XendNode.instance().uuid,
- 'this_user' : auth_manager().get_user(session),
- 'last_active': now()}
- return xen_api_success(record)
-
- def session_get_uuid(self, session, self_session):
- return xen_api_success(self_session)
-
- def session_get_by_uuid(self, session, self_session):
- return xen_api_success(self_session)
-
- # attributes (ro)
- def session_get_this_host(self, session, self_session):
- if self_session != session:
- return xen_api_error(['PERMISSION_DENIED'])
- return xen_api_success(XendNode.instance().uuid)
-
- def session_get_this_user(self, session, self_session):
- if self_session != session:
- return xen_api_error(['PERMISSION_DENIED'])
- user = auth_manager().get_user(session)
- if user is not None:
- return xen_api_success(user)
- return xen_api_error(['SESSION_INVALID', session])
-
- def session_get_last_active(self, session, self_session):
- if self_session != session:
- return xen_api_error(['PERMISSION_DENIED'])
- return xen_api_success(now())
-
-
- # Xen API: Class User
- # ----------------------------------------------------------------
- # TODO: NOT IMPLEMENTED YET
-
- # Xen API: Class Tasks
- # ----------------------------------------------------------------
-
- task_attr_ro = ['name_label',
- 'name_description',
- 'status',
- 'progress',
- 'type',
- 'result',
- 'error_info',
- 'allowed_operations',
- 'session'
- ]
-
- task_attr_rw = []
-
- task_funcs = [('get_by_name_label', 'Set(task)'),
- ('cancel', None)]
-
- def task_get_name_label(self, session, task_ref):
- task = XendTaskManager.get_task(task_ref)
- return xen_api_success(task.name_label)
-
- def task_get_name_description(self, session, task_ref):
- task = XendTaskManager.get_task(task_ref)
- return xen_api_success(task.name_description)
-
- def task_get_status(self, session, task_ref):
- task = XendTaskManager.get_task(task_ref)
- return xen_api_success(task.get_status())
-
- def task_get_progress(self, session, task_ref):
- task = XendTaskManager.get_task(task_ref)
- return xen_api_success(task.progress)
-
- def task_get_type(self, session, task_ref):
- task = XendTaskManager.get_task(task_ref)
- return xen_api_success(task.type)
-
- def task_get_result(self, session, task_ref):
- task = XendTaskManager.get_task(task_ref)
- return xen_api_success(task.result)
-
- def task_get_error_info(self, session, task_ref):
- task = XendTaskManager.get_task(task_ref)
- return xen_api_success(task.error_info)
-
- def task_get_allowed_operations(self, session, task_ref):
- return xen_api_success({})
-
- def task_get_session(self, session, task_ref):
- task = XendTaskManager.get_task(task_ref)
- return xen_api_success(task.session)
-
- def task_get_all(self, session):
- tasks = XendTaskManager.get_all_tasks()
- return xen_api_success(tasks)
-
- def task_get_record(self, session, task_ref):
- task = XendTaskManager.get_task(task_ref)
- return xen_api_success(task.get_record())
-
- def task_cancel(self, session, task_ref):
- return xen_api_error('OPERATION_NOT_ALLOWED')
-
- def task_get_by_name_label(self, session, name):
- return xen_api_success(XendTaskManager.get_task_by_name(name))
-
- # Xen API: Class host
- # ----------------------------------------------------------------
-
- host_attr_ro = ['software_version',
- 'resident_VMs',
- 'PBDs',
- 'PIFs',
- 'PPCIs',
- 'PSCSIs',
- 'PSCSI_HBAs',
- 'host_CPUs',
- 'cpu_configuration',
- 'metrics',
- 'capabilities',
- 'supported_bootloaders',
- 'sched_policy',
- 'API_version_major',
- 'API_version_minor',
- 'API_version_vendor',
- 'API_version_vendor_implementation',
- 'enabled',
- 'resident_cpu_pools']
-
- host_attr_rw = ['name_label',
- 'name_description',
- 'other_config',
- 'logging']
-
- host_methods = [('disable', None),
- ('enable', None),
- ('reboot', None),
- ('shutdown', None),
- ('add_to_other_config', None),
- ('remove_from_other_config', None),
- ('dmesg', 'String'),
- ('dmesg_clear', 'String'),
- ('get_log', 'String'),
- ('send_debug_keys', None),
- ('tmem_thaw', None),
- ('tmem_freeze', None),
- ('tmem_flush', None),
- ('tmem_destroy', None),
- ('tmem_list', None),
- ('tmem_set_weight', None),
- ('tmem_set_cap', None),
- ('tmem_set_compress', None),
- ('tmem_query_freeable_mb', None),
- ('tmem_shared_auth', None)]
-
- host_funcs = [('get_by_name_label', None),
- ('list_methods', None)]
-
- # attributes
- def host_get_name_label(self, session, host_ref):
- return xen_api_success(XendNode.instance().name)
- def host_set_name_label(self, session, host_ref, new_name):
- XendNode.instance().set_name(new_name)
- return xen_api_success_void()
- def host_get_name_description(self, session, host_ref):
- return xen_api_success(XendNode.instance().get_description())
- def host_set_name_description(self, session, host_ref, new_desc):
- XendNode.instance().set_description(new_desc)
- return xen_api_success_void()
- def host_get_other_config(self, session, host_ref):
- return xen_api_success(XendNode.instance().other_config)
- def host_set_other_config(self, session, host_ref, other_config):
- node = XendNode.instance()
- node.other_config = dict(other_config)
- node.save()
- return xen_api_success_void()
- def host_add_to_other_config(self, session, host_ref, key, value):
- node = XendNode.instance()
- node.other_config[key] = value
- node.save()
- return xen_api_success_void()
- def host_remove_from_other_config(self, session, host_ref, key):
- node = XendNode.instance()
- if key in node.other_config:
- del node.other_config[key]
- node.save()
- return xen_api_success_void()
- def host_get_API_version_major(self, _, ref):
- return xen_api_success(XEN_API_VERSION_MAJOR)
- def host_get_API_version_minor(self, _, ref):
- return xen_api_success(XEN_API_VERSION_MINOR)
- def host_get_API_version_vendor(self, _, ref):
- return xen_api_success(XEN_API_VERSION_VENDOR)
- def host_get_API_version_vendor_implementation(self, _, ref):
- return xen_api_success(XEN_API_VERSION_VENDOR_IMPLEMENTATION)
- def host_get_software_version(self, session, host_ref):
- return xen_api_success(XendNode.instance().xen_version())
- def host_get_enabled(self, _1, _2):
- return xen_api_success(XendDomain.instance().allow_new_domains())
- def host_get_resident_VMs(self, session, host_ref):
- return xen_api_success(XendDomain.instance().get_domain_refs())
- def host_get_PBDs(self, _, ref):
- return xen_api_success(XendPBD.get_all())
- def host_get_PIFs(self, session, ref):
- return xen_api_success(XendNode.instance().get_PIF_refs())
- def host_get_PPCIs(self, session, ref):
- return xen_api_success(XendNode.instance().get_PPCI_refs())
- def host_get_PSCSIs(self, session, ref):
- return xen_api_success(XendNode.instance().get_PSCSI_refs())
- def host_get_PSCSI_HBAs(self, session, ref):
- return xen_api_success(XendNode.instance().get_PSCSI_HBA_refs())
- def host_get_host_CPUs(self, session, host_ref):
- return xen_api_success(XendNode.instance().get_host_cpu_refs())
- def host_get_metrics(self, _, ref):
- return xen_api_success(XendNode.instance().host_metrics_uuid)
- def host_get_capabilities(self, session, host_ref):
- return xen_api_success(XendNode.instance().get_capabilities())
- def host_get_supported_bootloaders(self, session, host_ref):
- return xen_api_success(['pygrub'])
- def host_get_sched_policy(self, _, host_ref):
- return xen_api_success(XendNode.instance().get_vcpus_policy())
- def host_get_cpu_configuration(self, _, host_ref):
- return xen_api_success(XendNode.instance().get_cpu_configuration())
- def host_set_logging(self, _, host_ref, logging):
- return xen_api_todo()
- def host_get_logging(self, _, host_ref):
- return xen_api_todo()
- def host_get_resident_cpu_pools(self, _, host_ref):
- return xen_api_success(XendCPUPool.get_all())
-
- # object methods
- def host_disable(self, session, host_ref):
- XendDomain.instance().set_allow_new_domains(False)
- return xen_api_success_void()
- def host_enable(self, session, host_ref):
- XendDomain.instance().set_allow_new_domains(True)
- return xen_api_success_void()
- def host_reboot(self, session, host_ref):
- if not XendDomain.instance().allow_new_domains():
- return xen_api_error(XEND_ERROR_HOST_RUNNING)
- return xen_api_error(XEND_ERROR_UNSUPPORTED)
- def host_shutdown(self, session, host_ref):
- if not XendDomain.instance().allow_new_domains():
- return xen_api_error(XEND_ERROR_HOST_RUNNING)
- return xen_api_error(XEND_ERROR_UNSUPPORTED)
-
- def host_dmesg(self, session, host_ref):
- return xen_api_success(XendDmesg.instance().info())
-
- def host_dmesg_clear(self, session, host_ref):
- return xen_api_success(XendDmesg.instance().clear())
-
- def host_get_log(self, session, host_ref):
- log_file = open(XendLogging.getLogFilename())
- log_buffer = log_file.read()
- log_buffer = log_buffer.replace('\b', ' ')
- log_buffer = log_buffer.replace('\f', '\n')
- log_file.close()
- return xen_api_success(log_buffer)
-
- def host_send_debug_keys(self, _, host_ref, keys):
- node = XendNode.instance()
- node.send_debug_keys(keys)
- return xen_api_success_void()
-
- def host_get_record(self, session, host_ref):
- node = XendNode.instance()
- dom = XendDomain.instance()
- record = {'uuid': node.uuid,
- 'name_label': node.name,
- 'name_description': '',
- 'API_version_major': XEN_API_VERSION_MAJOR,
- 'API_version_minor': XEN_API_VERSION_MINOR,
- 'API_version_vendor': XEN_API_VERSION_VENDOR,
- 'API_version_vendor_implementation':
- XEN_API_VERSION_VENDOR_IMPLEMENTATION,
- 'software_version': node.xen_version(),
- 'enabled': XendDomain.instance().allow_new_domains(),
- 'other_config': node.other_config,
- 'resident_VMs': dom.get_domain_refs(),
- 'host_CPUs': node.get_host_cpu_refs(),
- 'cpu_configuration': node.get_cpu_configuration(),
- 'metrics': node.host_metrics_uuid,
- 'capabilities': node.get_capabilities(),
- 'supported_bootloaders': ['pygrub'],
- 'sched_policy': node.get_vcpus_policy(),
- 'logging': {},
- 'PIFs': XendPIF.get_all(),
- 'PBDs': XendPBD.get_all(),
- 'PPCIs': XendPPCI.get_all(),
- 'PSCSIs': XendPSCSI.get_all(),
- 'PSCSI_HBAs': XendPSCSI_HBA.get_all(),
- 'resident_cpu_pools': XendCPUPool.get_all(),
- }
- return xen_api_success(record)
-
- def host_tmem_thaw(self, _, host_ref, cli_id):
- node = XendNode.instance()
- try:
- node.tmem_thaw(cli_id)
- except Exception, e:
- return xen_api_error(e)
- return xen_api_success_void()
-
- def host_tmem_freeze(self, _, host_ref, cli_id):
- node = XendNode.instance()
- try:
- node.tmem_freeze(cli_id)
- except Exception, e:
- return xen_api_error(e)
- return xen_api_success_void()
-
- def host_tmem_flush(self, _, host_ref, cli_id, pages):
- node = XendNode.instance()
- try:
- node.tmem_flush(cli_id, pages)
- except Exception, e:
- return xen_api_error(e)
- return xen_api_success_void()
-
- def host_tmem_destroy(self, _, host_ref, cli_id):
- node = XendNode.instance()
- try:
- node.tmem_destroy(cli_id)
- except Exception, e:
- return xen_api_error(e)
- return xen_api_success_void()
-
- def host_tmem_list(self, _, host_ref, cli_id, use_long):
- node = XendNode.instance()
- try:
- info = node.tmem_list(cli_id, use_long)
- except Exception, e:
- return xen_api_error(e)
- return xen_api_success(info)
-
- def host_tmem_set_weight(self, _, host_ref, cli_id, value):
- node = XendNode.instance()
- try:
- node.tmem_set_weight(cli_id, value)
- except Exception, e:
- return xen_api_error(e)
- return xen_api_success_void()
-
- def host_tmem_set_cap(self, _, host_ref, cli_id, value):
- node = XendNode.instance()
- try:
- node.tmem_set_cap(cli_id, value)
- except Exception, e:
- return xen_api_error(e)
- return xen_api_success_void()
-
- def host_tmem_set_compress(self, _, host_ref, cli_id, value):
- node = XendNode.instance()
- try:
- node.tmem_set_compress(cli_id, value)
- except Exception, e:
- return xen_api_error(e)
- return xen_api_success_void()
-
- def host_tmem_query_freeable_mb(self, _, host_ref):
- node = XendNode.instance()
- try:
- pages = node.tmem_query_freeable_mb()
- except Exception, e:
- return xen_api_error(e)
- return xen_api_success(pages is None and -1 or pages)
-
- def host_tmem_shared_auth(self, _, host_ref, cli_id, uuid_str, auth):
- node = XendNode.instance()
- try:
- node.tmem_shared_auth(cli_id, uuid_str, auth)
- except Exception, e:
- return xen_api_error(e)
- return xen_api_success_void()
-
- # class methods
- def host_get_all(self, session):
- return xen_api_success((XendNode.instance().uuid,))
- def host_get_by_name_label(self, session, name):
- if XendNode.instance().name == name:
- return xen_api_success((XendNode.instance().uuid,))
- return xen_api_success([])
-
- def host_list_methods(self, _):
- def _funcs():
- return [getattr(XendAPI, x) for x in XendAPI.__dict__]
-
- return xen_api_success([x.api for x in _funcs()
- if hasattr(x, 'api')])
-
- # Xen API: Class host_CPU
- # ----------------------------------------------------------------
-
- host_cpu_attr_ro = ['host',
- 'number',
- 'vendor',
- 'speed',
- 'modelname',
- 'stepping',
- 'flags',
- 'utilisation',
- 'features',
- 'cpu_pool']
-
- host_cpu_funcs = [('get_unassigned_cpus', 'Set(host_cpu)')]
-
- # attributes
- def _host_cpu_get(self, ref, field):
- return xen_api_success(
- XendNode.instance().get_host_cpu_field(ref, field))
-
- def host_cpu_get_host(self, _, ref):
- return xen_api_success(XendNode.instance().uuid)
- def host_cpu_get_features(self, _, ref):
- return self._host_cpu_get(ref, 'features')
- def host_cpu_get_number(self, _, ref):
- return self._host_cpu_get(ref, 'number')
- def host_cpu_get_vendor(self, _, ref):
- return self._host_cpu_get(ref, 'vendor')
- def host_cpu_get_speed(self, _, ref):
- return self._host_cpu_get(ref, 'speed')
- def host_cpu_get_modelname(self, _, ref):
- return self._host_cpu_get(ref, 'modelname')
- def host_cpu_get_stepping(self, _, ref):
- return self._host_cpu_get(ref, 'stepping')
- def host_cpu_get_flags(self, _, ref):
- return self._host_cpu_get(ref, 'flags')
- def host_cpu_get_utilisation(self, _, ref):
- return xen_api_success(XendNode.instance().get_host_cpu_load(ref))
- def host_cpu_get_cpu_pool(self, _, ref):
- return xen_api_success(XendCPUPool.get_cpu_pool_by_cpu_ref(ref))
-
- # object methods
- def host_cpu_get_record(self, _, ref):
- node = XendNode.instance()
- record = dict([(f, node.get_host_cpu_field(ref, f))
- for f in self.host_cpu_attr_ro
- if f not in ['uuid', 'host', 'utilisation', 'cpu_pool']])
- record['uuid'] = ref
- record['host'] = node.uuid
- record['utilisation'] = node.get_host_cpu_load(ref)
- record['cpu_pool'] = XendCPUPool.get_cpu_pool_by_cpu_ref(ref)
- return xen_api_success(record)
-
- # class methods
- def host_cpu_get_all(self, session):
- return xen_api_success(XendNode.instance().get_host_cpu_refs())
- def host_cpu_get_unassigned_cpus(self, session):
- return xen_api_success(
- [ref for ref in XendNode.instance().get_host_cpu_refs()
- if len(XendCPUPool.get_cpu_pool_by_cpu_ref(ref)) == 0])
-
-
- # Xen API: Class host_metrics
- # ----------------------------------------------------------------
-
- host_metrics_attr_ro = ['memory_total',
- 'memory_free',
- 'last_updated']
- host_metrics_attr_rw = []
- host_metrics_methods = []
-
- def host_metrics_get_all(self, _):
- return xen_api_success([XendNode.instance().host_metrics_uuid])
-
- def _host_metrics_get(self, ref, f):
- return xen_api_success(getattr(node, f)())
-
- def host_metrics_get_record(self, _, ref):
- return xen_api_success({
- 'uuid' : ref,
- 'memory_total' : self._host_metrics_get_memory_total(),
- 'memory_free' : self._host_metrics_get_memory_free(),
- 'last_updated' : now(),
- })
-
- def host_metrics_get_memory_total(self, _1, _2):
- return xen_api_success(self._host_metrics_get_memory_total())
-
- def host_metrics_get_memory_free(self, _1, _2):
- return xen_api_success(self._host_metrics_get_memory_free())
-
- def host_metrics_get_last_updated(self, _1, _2):
- return xen_api_success(now())
-
- def _host_metrics_get_memory_total(self):
- node = XendNode.instance()
- return node.xc.physinfo()['total_memory'] * 1024
-
- def _host_metrics_get_memory_free(self):
- node = XendNode.instance()
- return node.xc.physinfo()['free_memory'] * 1024
-
- # Xen API: Class VM
- # ----------------------------------------------------------------
-
- VM_attr_ro = ['power_state',
- 'resident_on',
- 'consoles',
- 'VIFs',
- 'VBDs',
- 'DPCIs',
- 'DSCSIs',
- 'DSCSI_HBAs',
- 'tools_version',
- 'domid',
- 'is_control_domain',
- 'metrics',
- 'crash_dumps',
- 'cpu_pool',
- ]
-
- VM_attr_rw = ['name_label',
- 'name_description',
- 'user_version',
- 'is_a_template',
- 'auto_power_on',
- 'memory_dynamic_max',
- 'memory_dynamic_min',
- 'memory_static_max',
- 'memory_static_min',
- 'VCPUs_max',
- 'VCPUs_at_startup',
- 'VCPUs_params',
- 'actions_after_shutdown',
- 'actions_after_reboot',
- 'actions_after_suspend',
- 'actions_after_crash',
- 'PV_bootloader',
- 'PV_kernel',
- 'PV_ramdisk',
- 'PV_args',
- 'PV_bootloader_args',
- 'HVM_boot_policy',
- 'HVM_boot_params',
- 'platform',
- 'PCI_bus',
- 'other_config',
- 'security_label',
- 'pool_name',
- ]
-
- VM_methods = [('clone', 'VM'),
- ('start', None),
- ('pause', None),
- ('unpause', None),
- ('clean_shutdown', None),
- ('clean_reboot', None),
- ('hard_shutdown', None),
- ('hard_reboot', None),
- ('suspend', None),
- ('resume', None),
- ('send_sysrq', None),
- ('set_VCPUs_number_live', None),
- ('add_to_HVM_boot_params', None),
- ('remove_from_HVM_boot_params', None),
- ('add_to_VCPUs_params', None),
- ('add_to_VCPUs_params_live', None),
- ('remove_from_VCPUs_params', None),
- ('add_to_platform', None),
- ('remove_from_platform', None),
- ('add_to_other_config', None),
- ('remove_from_other_config', None),
- ('save', None),
- ('set_memory_dynamic_max_live', None),
- ('set_memory_dynamic_min_live', None),
- ('send_trigger', None),
- ('migrate', None),
- ('destroy', None),
- ('cpu_pool_migrate', None),
- ]
-
- VM_funcs = [('create', 'VM'),
- ('restore', None),
- ('get_by_name_label', 'Set(VM)')]
-
- # parameters required for _create()
- VM_attr_inst = [
- 'name_label',
- 'name_description',
- 'user_version',
- 'is_a_template',
- 'memory_static_max',
- 'memory_dynamic_max',
- 'memory_dynamic_min',
- 'memory_static_min',
- 'VCPUs_max',
- 'VCPUs_at_startup',
- 'VCPUs_params',
- 'actions_after_shutdown',
- 'actions_after_reboot',
- 'actions_after_suspend',
- 'actions_after_crash',
- 'PV_bootloader',
- 'PV_kernel',
- 'PV_ramdisk',
- 'PV_args',
- 'PV_bootloader_args',
- 'HVM_boot_policy',
- 'HVM_boot_params',
- 'platform',
- 'PCI_bus',
- 'other_config',
- 'security_label']
-
- def VM_get(self, name, session, vm_ref):
- return xen_api_success(
- XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
-
- def VM_set(self, name, session, vm_ref, value):
- xd = XendDomain.instance()
- dominfo = xd.get_vm_by_uuid(vm_ref)
- dominfo.info[name] = value
- return self._VM_save(dominfo)
-
- def _VM_save(self, dominfo):
- XendDomain.instance().managed_config_save(dominfo)
- return xen_api_success_void()
-
- # attributes (ro)
- def VM_get_power_state(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_power_state())
-
- def VM_get_resident_on(self, session, vm_ref):
- return xen_api_success(XendNode.instance().uuid)
-
- def VM_get_memory_static_max(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_memory_static_max())
-
- def VM_get_memory_static_min(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_memory_static_min())
-
- def VM_get_VIFs(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_vifs())
-
- def VM_get_VBDs(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_vbds())
-
- def VM_get_consoles(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_consoles())
-
- def VM_get_DPCIs(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_dpcis())
-
- def VM_get_DSCSIs(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_dscsis())
-
- def VM_get_DSCSI_HBAs(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_dscsi_HBAs())
-
- def VM_get_tools_version(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return dom.get_tools_version()
-
- def VM_get_metrics(self, _, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_metrics())
-
- def VM_get_VCPUs_max(self, _, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_todo()
-
- def VM_get_VCPUs_at_startup(self, _, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_todo()
-
- # attributes (rw)
- def VM_get_name_label(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.getName())
-
- def VM_get_name_description(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_todo()
-
- def VM_get_user_version(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_todo()
-
- def VM_get_is_a_template(self, session, ref):
- return self.VM_get('is_a_template', session, ref)
-
- def VM_get_auto_power_on(self, session, vm_ref):
- return self.VM_get('auto_power_on', session, vm_ref)
-
- def VM_get_memory_dynamic_max(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_memory_dynamic_max())
-
- def VM_get_memory_dynamic_min(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_memory_dynamic_min())
-
- def VM_get_VCPUs_params(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_vcpus_params())
-
- def VM_get_actions_after_shutdown(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_on_shutdown())
-
- def VM_get_actions_after_reboot(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_on_reboot())
-
- def VM_get_actions_after_suspend(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_on_suspend())
-
- def VM_get_actions_after_crash(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_on_crash())
-
- def VM_get_PV_bootloader(self, session, vm_ref):
- return self.VM_get('PV_bootloader', session, vm_ref)
-
- def VM_get_PV_kernel(self, session, vm_ref):
- return self.VM_get('PV_kernel', session, vm_ref)
-
- def VM_get_PV_ramdisk(self, session, vm_ref):
- return self.VM_get('PV_ramdisk', session, vm_ref)
-
- def VM_get_PV_args(self, session, vm_ref):
- return self.VM_get('PV_args', session, vm_ref)
-
- def VM_get_PV_bootloader_args(self, session, vm_ref):
- return self.VM_get('PV_bootloader_args', session, vm_ref)
-
- def VM_get_HVM_boot_policy(self, session, vm_ref):
- return self.VM_get('HVM_boot_policy', session, vm_ref)
-
- def VM_get_HVM_boot_params(self, session, vm_ref):
- return self.VM_get('HVM_boot_params', session, vm_ref)
-
- def VM_get_platform(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_platform())
-
- def VM_get_PCI_bus(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return dom.get_pci_bus()
-
- def VM_set_PCI_bus(self, session, vm_ref, val):
- return self.VM_set('PCI_bus', session, vm_ref, val)
-
- def VM_get_other_config(self, session, vm_ref):
- return self.VM_get('other_config', session, vm_ref)
-
- def VM_get_domid(self, _, ref):
- domid = XendDomain.instance().get_vm_by_uuid(ref).getDomid()
- return xen_api_success(domid is None and -1 or domid)
-
- def VM_get_is_control_domain(self, session, vm_ref):
- xd = XendDomain.instance()
- return xen_api_success(
- xd.get_vm_by_uuid(vm_ref) == xd.privilegedDomain())
-
- def VM_get_cpu_pool(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- pool_ref = XendCPUPool.query_pool_ref(dom.get_cpu_pool())
- return xen_api_success(pool_ref)
-
- def VM_get_pool_name(self, session, vm_ref):
- return self.VM_get('pool_name', session, vm_ref)
-
- def VM_set_pool_name(self, session, vm_ref, value):
- return self.VM_set('pool_name', session, vm_ref, value)
-
- def VM_set_name_label(self, session, vm_ref, label):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- dom.setName(label)
- return self._VM_save(dom)
-
- def VM_set_name_description(self, session, vm_ref, desc):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_todo()
-
- def VM_set_user_version(self, session, vm_ref, ver):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_todo()
-
- def VM_set_is_a_template(self, session, vm_ref, is_template):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_todo()
-
- def VM_set_auto_power_on(self, session, vm_ref, val):
- return self.VM_set('auto_power_on', session, vm_ref, val)
-
- def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- dom.set_memory_dynamic_max(int(mem))
- return self._VM_save(dom)
-
- def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- dom.set_memory_dynamic_min(int(mem))
- return self._VM_save(dom)
-
- def VM_set_memory_static_max(self, session, vm_ref, mem):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- dom.set_memory_static_max(int(mem))
- return self._VM_save(dom)
-
- def VM_set_memory_static_min(self, session, vm_ref, mem):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- dom.set_memory_static_min(int(mem))
- return self._VM_save(dom)
-
- def VM_set_memory_dynamic_max_live(self, session, vm_ref, mem):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- dom.set_memory_dynamic_max(int(mem))
- # need to pass target as MiB
- dom.setMemoryTarget(int(mem)/1024/1024)
- return xen_api_success_void()
-
- def VM_set_memory_dynamic_min_live(self, session, vm_ref, mem):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- dom.set_memory_dynamic_min(int(mem))
- # need to pass target as MiB
- dom.setMemoryTarget(int(mem)/1024/1024)
- return xen_api_success_void()
-
- def VM_set_VCPUs_params(self, session, vm_ref, value):
- return self.VM_set('vcpus_params', session, vm_ref, value)
-
- def VM_add_to_VCPUs_params(self, session, vm_ref, key, value):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- if 'vcpus_params' not in dom.info:
- dom.info['vcpus_params'] = {}
- dom.info['vcpus_params'][key] = value
- return self._VM_save(dom)
-
- def VM_add_to_VCPUs_params_live(self, session, vm_ref, key, value):
- self.VM_add_to_VCPUs_params(session, vm_ref, key, value)
- self._VM_VCPUs_params_refresh(vm_ref)
- return xen_api_success_void()
-
- def _VM_VCPUs_params_refresh(self, vm_ref):
- xendom = XendDomain.instance()
- xeninfo = xendom.get_vm_by_uuid(vm_ref)
-
- #update the cpumaps
- for key, value in xeninfo.info['vcpus_params'].items():
- if key.startswith("cpumap"):
- vcpu = int(key[6:])
- try:
- cpus = map(int, value.split(","))
- xendom.domain_pincpu(xeninfo.getDomid(), vcpu, cpus)
- except Exception, ex:
- log.exception(ex)
-
- #need to update sched params aswell
- if 'weight' in xeninfo.info['vcpus_params'] \
- and 'cap' in xeninfo.info['vcpus_params']:
- weight = xeninfo.info['vcpus_params']['weight']
- xendom.domain_sched_credit2_set(xeninfo.getDomid(), weight)
-
- def VM_set_VCPUs_number_live(self, _, vm_ref, num):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- dom.setVCpuCount(int(num))
- return xen_api_success_void()
-
- def VM_remove_from_VCPUs_params(self, session, vm_ref, key):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- if 'vcpus_params' in dom.info \
- and key in dom.info['vcpus_params']:
- del dom.info['vcpus_params'][key]
- return self._VM_save(dom)
- else:
- return xen_api_success_void()
-
- def VM_set_VCPUs_at_startup(self, session, vm_ref, num):
- return self.VM_set('VCPUs_at_startup', session, vm_ref, num)
-
- def VM_set_VCPUs_max(self, session, vm_ref, num):
- return self.VM_set('VCPUs_max', session, vm_ref, num)
-
- def VM_set_actions_after_shutdown(self, session, vm_ref, action):
- if action not in XEN_API_ON_NORMAL_EXIT:
- return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
- return self.VM_set('actions_after_shutdown', session, vm_ref, action)
-
- def VM_set_actions_after_reboot(self, session, vm_ref, action):
- if action not in XEN_API_ON_NORMAL_EXIT:
- return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
- return self.VM_set('actions_after_reboot', session, vm_ref, action)
-
- def VM_set_actions_after_suspend(self, session, vm_ref, action):
- if action not in XEN_API_ON_NORMAL_EXIT:
- return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
- return self.VM_set('actions_after_suspend', session, vm_ref, action)
-
- def VM_set_actions_after_crash(self, session, vm_ref, action):
- if action not in XEN_API_ON_CRASH_BEHAVIOUR:
- return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref])
- return self.VM_set('actions_after_crash', session, vm_ref,
- XEN_API_ON_CRASH_BEHAVIOUR_LEGACY[action])
-
- def VM_set_HVM_boot_policy(self, session, vm_ref, value):
- if value != "" and value != "BIOS order":
- return xen_api_error(
- ['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value,
- 'Xend supports only the "BIOS order" boot policy.'])
- else:
- return self.VM_set('HVM_boot_policy', session, vm_ref, value)
-
- def VM_set_HVM_boot_params(self, session, vm_ref, value):
- return self.VM_set('HVM_boot_params', session, vm_ref, value)
-
- def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- if 'HVM_boot_params' not in dom.info:
- dom.info['HVM_boot_params'] = {}
- dom.info['HVM_boot_params'][key] = value
- return self._VM_save(dom)
-
- def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- if 'HVM_boot_params' in dom.info \
- and key in dom.info['HVM_boot_params']:
- del dom.info['HVM_boot_params'][key]
- return self._VM_save(dom)
- else:
- return xen_api_success_void()
-
- def VM_set_PV_bootloader(self, session, vm_ref, value):
- return self.VM_set('PV_bootloader', session, vm_ref, value)
-
- def VM_set_PV_kernel(self, session, vm_ref, value):
- return self.VM_set('PV_kernel', session, vm_ref, value)
-
- def VM_set_PV_ramdisk(self, session, vm_ref, value):
- return self.VM_set('PV_ramdisk', session, vm_ref, value)
-
- def VM_set_PV_args(self, session, vm_ref, value):
- return self.VM_set('PV_args', session, vm_ref, value)
-
- def VM_set_PV_bootloader_args(self, session, vm_ref, value):
- return self.VM_set('PV_bootloader_args', session, vm_ref, value)
-
- def VM_set_platform(self, session, vm_ref, value):
- return self.VM_set('platform', session, vm_ref, value)
-
- def VM_add_to_platform(self, session, vm_ref, key, value):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- plat = dom.get_platform()
- plat[key] = value
- return self.VM_set_platform(session, vm_ref, plat)
-
- def VM_remove_from_platform(self, session, vm_ref, key):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- plat = dom.get_platform()
- if key in plat:
- del plat[key]
- return self.VM_set_platform(session, vm_ref, plat)
- else:
- return xen_api_success_void()
-
- def VM_set_other_config(self, session, vm_ref, value):
- return self.VM_set('other_config', session, vm_ref, value)
-
- def VM_add_to_other_config(self, session, vm_ref, key, value):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- if dom and 'other_config' in dom.info:
- dom.info['other_config'][key] = value
- return self._VM_save(dom)
-
- def VM_remove_from_other_config(self, session, vm_ref, key):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- if dom and 'other_config' in dom.info \
- and key in dom.info['other_config']:
- del dom.info['other_config'][key]
- return self._VM_save(dom)
- else:
- return xen_api_success_void()
-
- def VM_get_crash_dumps(self, _, vm_ref):
- return xen_api_todo()
-
- # class methods
- def VM_get_all(self, session):
- refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
- return xen_api_success(refs)
-
- def VM_get_by_name_label(self, session, label):
- xendom = XendDomain.instance()
- dom = xendom.domain_lookup_nr(label)
- if dom:
- return xen_api_success([dom.get_uuid()])
- return xen_api_success([])
-
- def VM_get_security_label(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- label = dom.get_security_label()
- return xen_api_success(label)
-
- def VM_set_security_label(self, session, vm_ref, sec_label, old_label):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- (rc, errors, oldlabel, new_ssidref) = \
- dom.set_security_label(sec_label, old_label)
- if rc != xsconstants.XSERR_SUCCESS:
- return xen_api_error(['SECURITY_ERROR', rc,
- xsconstants.xserr2string(-rc)])
- if rc == 0:
- rc = new_ssidref
- return xen_api_success(rc)
-
- def VM_create(self, session, vm_struct):
- xendom = XendDomain.instance()
- domuuid = XendTask.log_progress(0, 100,
- xendom.create_domain, vm_struct)
- return xen_api_success(domuuid)
-
- # object methods
- def VM_get_record(self, session, vm_ref):
- xendom = XendDomain.instance()
- xeninfo = xendom.get_vm_by_uuid(vm_ref)
- if not xeninfo:
- return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref])
-
- domid = xeninfo.getDomid()
-
- record = {
- 'uuid': xeninfo.get_uuid(),
- 'power_state': xeninfo.get_power_state(),
- 'name_label': xeninfo.getName(),
- 'name_description': xeninfo.getName(),
- 'user_version': 1,
- 'is_a_template': xeninfo.info['is_a_template'],
- 'auto_power_on': xeninfo.info['auto_power_on'],
- 'resident_on': XendNode.instance().uuid,
- 'memory_static_min': xeninfo.get_memory_static_min(),
- 'memory_static_max': xeninfo.get_memory_static_max(),
- 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
- 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
- 'VCPUs_params': xeninfo.get_vcpus_params(),
- 'VCPUs_at_startup': xeninfo.getVCpuCount(),
- 'VCPUs_max': xeninfo.getVCpuCount(),
- 'actions_after_shutdown': xeninfo.get_on_shutdown(),
- 'actions_after_reboot': xeninfo.get_on_reboot(),
- 'actions_after_suspend': xeninfo.get_on_suspend(),
- 'actions_after_crash': xeninfo.get_on_crash(),
- 'consoles': xeninfo.get_consoles(),
- 'VIFs': xeninfo.get_vifs(),
- 'VBDs': xeninfo.get_vbds(),
- 'DPCIs': xeninfo.get_dpcis(),
- 'DSCSIs': xeninfo.get_dscsis(),
- 'DSCSI_HBAs': xeninfo.get_dscsi_HBAs(),
- 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
- 'PV_kernel': xeninfo.info.get('PV_kernel'),
- 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
- 'PV_args': xeninfo.info.get('PV_args'),
- 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
- 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
- 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
- 'platform': xeninfo.get_platform(),
- 'PCI_bus': xeninfo.get_pci_bus(),
- 'tools_version': xeninfo.get_tools_version(),
- 'other_config': xeninfo.info.get('other_config', {}),
- 'domid': domid is None and -1 or domid,
- 'is_control_domain': xeninfo.info['is_control_domain'],
- 'metrics': xeninfo.get_metrics(),
- 'security_label': xeninfo.get_security_label(),
- 'crash_dumps': [],
- 'pool_name': xeninfo.info.get('pool_name'),
- 'cpu_pool' : XendCPUPool.query_pool_ref(xeninfo.get_cpu_pool()),
- }
- return xen_api_success(record)
-
- def VM_clean_reboot(self, session, vm_ref):
- xendom = XendDomain.instance()
- xeninfo = xendom.get_vm_by_uuid(vm_ref)
- XendTask.log_progress(0, 100, xeninfo.shutdown, "reboot")
- return xen_api_success_void()
-
- def VM_clean_shutdown(self, session, vm_ref):
- xendom = XendDomain.instance()
- xeninfo = xendom.get_vm_by_uuid(vm_ref)
- XendTask.log_progress(0, 100, xeninfo.shutdown, "poweroff")
- return xen_api_success_void()
-
- def VM_clone(self, session, vm_ref):
- return xen_api_error(XEND_ERROR_UNSUPPORTED)
-
- def VM_destroy(self, session, vm_ref):
- return XendTask.log_progress(0, 100, do_vm_func,
- "domain_delete", vm_ref)
-
- def VM_hard_reboot(self, session, vm_ref):
- return XendTask.log_progress(0, 100, do_vm_func,
- "domain_reset", vm_ref)
-
- def VM_hard_shutdown(self, session, vm_ref):
- return XendTask.log_progress(0, 100, do_vm_func,
- "domain_destroy", vm_ref)
-
- def VM_pause(self, session, vm_ref):
- return XendTask.log_progress(0, 100, do_vm_func,
- "domain_pause", vm_ref)
-
- def VM_resume(self, session, vm_ref, start_paused):
- return XendTask.log_progress(0, 100, do_vm_func,
- "domain_resume", vm_ref,
- start_paused = start_paused)
-
- def VM_start(self, session, vm_ref, start_paused):
- try:
- return XendTask.log_progress(0, 100, do_vm_func,
- "domain_start", vm_ref,
- start_paused = start_paused)
- except HVMRequired, exn:
- return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
-
- def VM_suspend(self, session, vm_ref):
- return XendTask.log_progress(0, 100, do_vm_func,
- "domain_suspend", vm_ref)
-
- def VM_unpause(self, session, vm_ref):
- return XendTask.log_progress(0, 100, do_vm_func,
- "domain_unpause", vm_ref)
-
- def VM_send_sysrq(self, _, vm_ref, req):
- xeninfo = XendDomain.instance().get_vm_by_uuid(vm_ref)
- if xeninfo.state == XEN_API_VM_POWER_STATE_RUNNING \
- or xeninfo.state == XEN_API_VM_POWER_STATE_PAUSED:
- xeninfo.send_sysrq(req)
- return xen_api_success_void()
- else:
- return xen_api_error(
- ['VM_BAD_POWER_STATE', vm_ref,
- XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_RUNNING],
- XendDomain.POWER_STATE_NAMES[xeninfo.state]])
-
- def VM_send_trigger(self, _, vm_ref, trigger, vcpu):
- xendom = XendDomain.instance()
- xeninfo = xendom.get_vm_by_uuid(vm_ref)
- xendom.domain_send_trigger(xeninfo.getDomid(), trigger, vcpu)
- return xen_api_success_void()
-
- def VM_migrate(self, _, vm_ref, destination_url, live, other_config):
- xendom = XendDomain.instance()
- xeninfo = xendom.get_vm_by_uuid(vm_ref)
-
- port = other_config.get("port", 0)
- node = other_config.get("node", -1)
- ssl = other_config.get("ssl", None)
- chs = other_config.get("change_home_server", False)
-
- xendom.domain_migrate(xeninfo.getDomid(), destination_url,
- bool(live), port, node, ssl, bool(chs))
- return xen_api_success_void()
-
- def VM_save(self, _, vm_ref, dest, checkpoint):
- xendom = XendDomain.instance()
- xeninfo = xendom.get_vm_by_uuid(vm_ref)
- xendom.domain_save(xeninfo.getDomid(), dest, checkpoint)
- return xen_api_success_void()
-
- def VM_restore(self, _, src, paused):
- xendom = XendDomain.instance()
- xendom.domain_restore(src, bool(paused))
- return xen_api_success_void()
-
- def VM_cpu_pool_migrate(self, session, vm_ref, cpu_pool_ref):
- xendom = XendDomain.instance()
- xeninfo = xendom.get_vm_by_uuid(vm_ref)
- domid = xeninfo.getDomid()
- pool = XendAPIStore.get(cpu_pool_ref, XendCPUPool.getClass())
- if pool == None:
- return xen_api_error(['HANDLE_INVALID', 'cpu_pool', cpu_pool_ref])
- if domid is not None:
- if domid == 0:
- return xen_api_error(['OPERATION_NOT_ALLOWED',
- 'could not move Domain-0'])
- try:
- XendCPUPool.move_domain(cpu_pool_ref, domid)
- except Exception, ex:
- return xen_api_error(['INTERNAL_ERROR',
- 'could not move domain'])
- self.VM_set('pool_name', session, vm_ref, pool.get_name_label())
- return xen_api_success_void()
-
-
- # Xen API: Class VBD
- # ----------------------------------------------------------------
-
- VBD_attr_ro = ['VM',
- 'VDI',
- 'metrics',
- 'runtime_properties']
- VBD_attr_rw = ['device',
- 'bootable',
- 'mode',
- 'type']
-
- VBD_attr_inst = VBD_attr_rw
-
- VBD_methods = [('media_change', None), ('destroy', None)]
- VBD_funcs = [('create', 'VBD')]
-
- # object methods
- def VBD_get_record(self, session, vbd_ref):
- xendom = XendDomain.instance()
- vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
- if not vm:
- return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
- cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
- if not cfg:
- return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
-
- valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
- self.Base_attr_ro + self.Base_attr_rw
-
- return_cfg = {}
- for k in cfg.keys():
- if k in valid_vbd_keys:
- return_cfg[k] = cfg[k]
-
- return_cfg['metrics'] = vbd_ref
- return_cfg['runtime_properties'] = {} #todo
-
- return xen_api_success(return_cfg)
-
- def VBD_media_change(self, session, vbd_ref, new_vdi_ref):
- xendom = XendDomain.instance()
- xennode = XendNode.instance()
-
- vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
- if not vm:
- return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
- cur_vbd_struct = vm.get_dev_xenapi_config('vbd', vbd_ref)
- if not cur_vbd_struct:
- return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
- if cur_vbd_struct['type'] != XEN_API_VBD_TYPE[0]: # Not CD
- return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
- if cur_vbd_struct['mode'] != 'RO': # Not read only
- return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
-
- new_vdi = xennode.get_vdi_by_uuid(new_vdi_ref)
- if not new_vdi:
- return xen_api_error(['HANDLE_INVALID', 'VDI', new_vdi_ref])
- new_vdi_image = new_vdi.get_location()
-
- valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
- self.Base_attr_ro + self.Base_attr_rw
-
- new_vbd_struct = {}
- for k in cur_vbd_struct.keys():
- if k in valid_vbd_keys:
- new_vbd_struct[k] = cur_vbd_struct[k]
- new_vbd_struct['VDI'] = new_vdi_ref
-
- try:
- XendTask.log_progress(0, 100,
- vm.change_vdi_of_vbd,
- new_vbd_struct, new_vdi_image)
- except XendError, e:
- log.exception("Error in VBD_media_change")
- return xen_api_error(['INTERNAL_ERROR', str(e)])
-
- return xen_api_success_void()
-
- # class methods
- def VBD_create(self, session, vbd_struct):
- xendom = XendDomain.instance()
- xennode = XendNode.instance()
-
- if not xendom.is_valid_vm(vbd_struct['VM']):
- return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
-
- dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
- vdi = xennode.get_vdi_by_uuid(vbd_struct['VDI'])
- if not vdi:
- return xen_api_error(['HANDLE_INVALID', 'VDI', vbd_struct['VDI']])
-
- # new VBD via VDI/SR
- vdi_image = vdi.get_location()
-
- try:
- vbd_ref = XendTask.log_progress(0, 100,
- dom.create_vbd,
- vbd_struct, vdi_image)
- except XendError, e:
- log.exception("Error in VBD_create")
- return xen_api_error(['INTERNAL_ERROR', str(e)])
-
- xendom.managed_config_save(dom)
- return xen_api_success(vbd_ref)
-
-
- def VBD_destroy(self, session, vbd_ref):
- xendom = XendDomain.instance()
- vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
- if not vm:
- return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
-
- vdi_ref = XendDomain.instance()\
- .get_dev_property_by_uuid('vbd', vbd_ref, "VDI")
- vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
-
- XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
-
- xendom.managed_config_save(vm)
- return xen_api_success_void()
-
- def _VBD_get(self, vbd_ref, prop):
- return xen_api_success(
- XendDomain.instance().get_dev_property_by_uuid(
- 'vbd', vbd_ref, prop))
-
- # attributes (ro)
- def VBD_get_metrics(self, _, vbd_ref):
- return xen_api_success(vbd_ref)
-
- def VBD_get_runtime_properties(self, _, vbd_ref):
- xendom = XendDomain.instance()
- dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
- device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref)
-
- try:
- devid = int(device['id'])
- device_sxps = dominfo.getDeviceSxprs('vbd')
- device_dicts = [dict(device_sxp[1][0:]) for device_sxp in device_sxps]
- device_dict = [device_dict
- for device_dict in device_dicts
- if int(device_dict['virtual-device']) == devid][0]
-
- return xen_api_success(device_dict)
- except Exception, exn:
- log.exception(exn)
- return xen_api_success({})
-
- # attributes (rw)
- def VBD_get_VM(self, session, vbd_ref):
- return self._VBD_get(vbd_ref, 'VM')
-
- def VBD_get_VDI(self, session, vbd_ref):
- return self._VBD_get(vbd_ref, 'VDI')
-
- def VBD_get_device(self, session, vbd_ref):
- return self._VBD_get(vbd_ref, 'device')
-
- def VBD_get_bootable(self, session, vbd_ref):
- return self._VBD_get(vbd_ref, 'bootable')
-
- def VBD_get_mode(self, session, vbd_ref):
- return self._VBD_get(vbd_ref, 'mode')
-
- def VBD_get_type(self, session, vbd_ref):
- return self._VBD_get(vbd_ref, 'type')
-
- def VBD_set_bootable(self, session, vbd_ref, bootable):
- bootable = bool(bootable)
- xd = XendDomain.instance()
- vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
- vm.set_dev_property('vbd', vbd_ref, 'bootable', int(bootable))
- xd.managed_config_save(vm)
- return xen_api_success_void()
-
- def VBD_set_mode(self, session, vbd_ref, mode):
- if mode == 'RW':
- mode = 'w'
- else:
- mode = 'r'
- xd = XendDomain.instance()
- vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
- vm.set_dev_property('vbd', vbd_ref, 'mode', mode)
- xd.managed_config_save(vm)
- return xen_api_success_void()
-
- def VBD_get_all(self, session):
- xendom = XendDomain.instance()
- vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
- vbds = reduce(lambda x, y: x + y, vbds)
- return xen_api_success(vbds)
-
-
- # Xen API: Class VBD_metrics
- # ----------------------------------------------------------------
-
- VBD_metrics_attr_ro = ['io_read_kbs',
- 'io_write_kbs',
- 'last_updated']
- VBD_metrics_attr_rw = []
- VBD_metrics_methods = []
-
- def VBD_metrics_get_all(self, session):
- return self.VBD_get_all(session)
-
- def VBD_metrics_get_record(self, _, ref):
- vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref)
- if not vm:
- return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref])
- return xen_api_success(
- { 'io_read_kbs' : vm.get_dev_property('vbd', ref, 'io_read_kbs'),
- 'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs'),
- 'last_updated' : now()
- })
-
- def VBD_metrics_get_io_read_kbs(self, _, ref):
- return self._VBD_get(ref, 'io_read_kbs')
-
- def VBD_metrics_get_io_write_kbs(self, session, ref):
- return self._VBD_get(ref, 'io_write_kbs')
-
- def VBD_metrics_get_last_updated(self, _1, _2):
- return xen_api_success(now())
-
-
- # Xen API: Class VIF
- # ----------------------------------------------------------------
-
- VIF_attr_ro = ['network',
- 'VM',
- 'metrics',
- 'runtime_properties']
- VIF_attr_rw = ['device',
- 'MAC',
- 'MTU',
- 'security_label']
-
- VIF_attr_inst = VIF_attr_rw
-
- VIF_methods = [('destroy', None)]
- VIF_funcs = [('create', 'VIF')]
-
-
- # object methods
- def VIF_get_record(self, session, vif_ref):
- xendom = XendDomain.instance()
- vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
- if not vm:
- return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
- cfg = vm.get_dev_xenapi_config('vif', vif_ref)
- if not cfg:
- return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
-
- valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
- self.Base_attr_ro + self.Base_attr_rw
-
- return_cfg = {}
- for k in cfg.keys():
- if k in valid_vif_keys:
- return_cfg[k] = cfg[k]
-
- return_cfg['metrics'] = vif_ref
-
- return xen_api_success(return_cfg)
-
- # class methods
- def VIF_create(self, session, vif_struct):
- xendom = XendDomain.instance()
- if not xendom.is_valid_vm(vif_struct['VM']):
- return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
-
- dom = xendom.get_vm_by_uuid(vif_struct['VM'])
- try:
- vif_ref = dom.create_vif(vif_struct)
- xendom.managed_config_save(dom)
- return xen_api_success(vif_ref)
- except XendError, exn:
- return xen_api_error(['INTERNAL_ERROR', str(exn)])
-
- def VIF_destroy(self, session, vif_ref):
- xendom = XendDomain.instance()
- vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
- if not vm:
- return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
-
- vm.destroy_vif(vif_ref)
-
- xendom.managed_config_save(vm)
- return xen_api_success_void()
-
- def _VIF_get(self, ref, prop):
- return xen_api_success(
- XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop))
-
- # getters/setters
- def VIF_get_metrics(self, _, vif_ref):
- return xen_api_success(vif_ref)
-
- def VIF_get_VM(self, session, vif_ref):
- xendom = XendDomain.instance()
- vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
- return xen_api_success(vm.get_uuid())
-
- def VIF_get_MTU(self, session, vif_ref):
- return self._VIF_get(vif_ref, 'MTU')
-
- def VIF_get_MAC(self, session, vif_ref):
- return self._VIF_get(vif_ref, 'MAC')
-
- def VIF_get_device(self, session, vif_ref):
- return self._VIF_get(vif_ref, 'device')
-
- def VIF_get_network(self, session, vif_ref):
- return self._VIF_get(vif_ref, 'network')
-
- def VIF_get_all(self, session):
- xendom = XendDomain.instance()
- vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
- vifs = reduce(lambda x, y: x + y, vifs)
- return xen_api_success(vifs)
-
- def VIF_get_runtime_properties(self, _, vif_ref):
- xendom = XendDomain.instance()
- dominfo = xendom.get_vm_with_dev_uuid('vif', vif_ref)
- device = dominfo.get_dev_config_by_uuid('vif', vif_ref)
-
- try:
- devid = int(device['id'])
-
- device_sxps = dominfo.getDeviceSxprs('vif')
- device_dicts = [dict(device_sxp[1][1:])
- for device_sxp in device_sxps]
-
- device_dict = [device_dict
- for device_dict in device_dicts
- if int(device_dict['handle']) == devid][0]
-
- return xen_api_success(device_dict)
-
- except Exception, exn:
- log.exception(exn)
- return xen_api_success({})
-
- def VIF_get_security_label(self, session, vif_ref):
- return self._VIF_get(vif_ref, 'security_label')
-
- def _VIF_set(self, ref, prop, val, old_val):
- return XendDomain.instance().set_dev_property_by_uuid(
- 'vif', ref, prop, val, old_val)
-
- def VIF_set_security_label(self, session, vif_ref, sec_lab, old_lab):
- xendom = XendDomain.instance()
- dom = xendom.get_vm_with_dev_uuid('vif', vif_ref)
- if not dom:
- return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
-
- if dom._stateGet() == XEN_API_VM_POWER_STATE_RUNNING:
- raise SecurityError(-xsconstants.XSERR_RESOURCE_IN_USE)
-
- rc = self._VIF_set(vif_ref, 'security_label', sec_lab, old_lab)
- if rc == False:
- raise SecurityError(-xsconstants.XSERR_BAD_LABEL)
- return xen_api_success(xsconstants.XSERR_SUCCESS)
-
-
- # Xen API: Class VIF_metrics
- # ----------------------------------------------------------------
-
- VIF_metrics_attr_ro = ['io_read_kbs',
- 'io_write_kbs',
- 'io_total_read_kbs',
- 'io_total_write_kbs',
- 'last_updated']
- VIF_metrics_attr_rw = []
- VIF_metrics_methods = []
-
- def VIF_metrics_get_all(self, session):
- return self.VIF_get_all(session)
-
- def VIF_metrics_get_record(self, _, ref):
- vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref)
- if not vm:
- return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref])
- return xen_api_success(
- { 'io_read_kbs' : vm.get_dev_property('vif', ref, 'io_read_kbs'),
- 'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs'),
- 'io_total_read_kbs' : vm.get_dev_property('vif', ref, 'io_total_read_kbs'),
- 'io_total_write_kbs' : vm.get_dev_property('vif', ref, 'io_total_write_kbs'),
- 'last_updated' : now()
- })
-
- def VIF_metrics_get_io_read_kbs(self, _, ref):
- return self._VIF_get(ref, 'io_read_kbs')
-
- def VIF_metrics_get_io_write_kbs(self, session, ref):
- return self._VIF_get(ref, 'io_write_kbs')
-
- def VIF_metrics_get_io_total_read_kbs(self, _, ref):
- return self._VIF_get(ref, 'io_total_read_kbs')
-
- def VIF_metrics_get_io_total_write_kbs(self, session, ref):
- return self._VIF_get(ref, 'io_total_write_kbs')
-
- def VIF_metrics_get_last_updated(self, _1, _2):
- return xen_api_success(now())
-
-
- # Xen API: Class VDI
- # ----------------------------------------------------------------
- VDI_attr_ro = ['SR',
- 'VBDs',
- 'physical_utilisation',
- 'type']
- VDI_attr_rw = ['name_label',
- 'name_description',
- 'virtual_size',
- 'sharable',
- 'read_only',
- 'other_config',
- 'security_label']
- VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
-
- VDI_methods = [('destroy', None)]
- VDI_funcs = [('create', 'VDI'),
- ('get_by_name_label', 'Set(VDI)')]
-
- def _get_VDI(self, ref):
- return XendNode.instance().get_vdi_by_uuid(ref)
-
- def VDI_get_VBDs(self, session, vdi_ref):
- vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
- return xen_api_success(vdi.getVBDs())
-
- def VDI_get_physical_utilisation(self, session, vdi_ref):
- return xen_api_success(self._get_VDI(vdi_ref).
- get_physical_utilisation())
-
- def VDI_get_type(self, session, vdi_ref):
- return xen_api_success(self._get_VDI(vdi_ref).type)
-
- def VDI_get_name_label(self, session, vdi_ref):
- return xen_api_success(self._get_VDI(vdi_ref).name_label)
-
- def VDI_get_name_description(self, session, vdi_ref):
- return xen_api_success(self._get_VDI(vdi_ref).name_description)
-
- def VDI_get_SR(self, session, vdi_ref):
- return xen_api_success(self._get_VDI(vdi_ref).sr_uuid)
-
- def VDI_get_virtual_size(self, session, vdi_ref):
- return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
-
- def VDI_get_sharable(self, session, vdi_ref):
- return xen_api_success(self._get_VDI(vdi_ref).sharable)
-
- def VDI_get_read_only(self, session, vdi_ref):
- return xen_api_success(self._get_VDI(vdi_ref).read_only)
-
- def VDI_set_name_label(self, session, vdi_ref, value):
- self._get_VDI(vdi_ref).name_label = value
- return xen_api_success_void()
-
- def VDI_set_name_description(self, session, vdi_ref, value):
- self._get_VDI(vdi_ref).name_description = value
- return xen_api_success_void()
-
- def VDI_set_virtual_size(self, session, vdi_ref, value):
- return xen_api_error(XEND_ERROR_UNSUPPORTED)
-
- def VDI_set_sharable(self, session, vdi_ref, value):
- self._get_VDI(vdi_ref).sharable = bool(value)
- return xen_api_success_void()
-
- def VDI_set_read_only(self, session, vdi_ref, value):
- self._get_VDI(vdi_ref).read_only = bool(value)
- return xen_api_success_void()
-
- def VDI_get_other_config(self, session, vdi_ref):
- return xen_api_success(
- self._get_VDI(vdi_ref).other_config)
-
- def VDI_set_other_config(self, session, vdi_ref, other_config):
- self._get_VDI(vdi_ref).other_config = other_config
- return xen_api_success_void()
-
- # Object Methods
-
- def VDI_destroy(self, session, vdi_ref):
- # check no VBDs attached
- image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
- if image.getVBDs():
- raise VDIError("Cannot destroy VDI with VBDs attached",
- image.name_label)
-
- sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
- sr.destroy_vdi(vdi_ref)
- return xen_api_success_void()
-
- def VDI_get_record(self, session, vdi_ref):
- image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
- return xen_api_success({
- 'uuid': vdi_ref,
- 'name_label': image.name_label,
- 'name_description': image.name_description,
- 'SR': image.sr_uuid,
- 'VBDs': image.getVBDs(),
- 'virtual_size': image.virtual_size,
- 'physical_utilisation': image.physical_utilisation,
- 'type': image.type,
- 'sharable': image.sharable,
- 'read_only': image.read_only,
- 'other_config': image.other_config,
- 'security_label' : image.get_security_label()
- })
-
- # Class Functions
- def VDI_create(self, session, vdi_struct):
- sr_ref = vdi_struct.get('SR')
- xennode = XendNode.instance()
- if not xennode.is_valid_sr(sr_ref):
- return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
-
- vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
- return xen_api_success(vdi_uuid)
-
- def VDI_get_all(self, session):
- xennode = XendNode.instance()
- vdis = [sr.get_vdis() for sr in xennode.srs.values()]
- return xen_api_success(reduce(lambda x, y: x + y, vdis))
-
- def VDI_get_by_name_label(self, session, name):
- xennode = XendNode.instance()
- return xen_api_success(xennode.get_vdi_by_name_label(name))
-
- def VDI_set_security_label(self, session, vdi_ref, sec_lab, old_lab):
- vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
- rc = vdi.set_security_label(sec_lab, old_lab)
- if rc < 0:
- return xen_api_error(['SECURITY_ERROR', rc,
- xsconstants.xserr2string(-rc)])
- return xen_api_success(rc)
-
- def VDI_get_security_label(self, session, vdi_ref):
- vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
- return xen_api_success(vdi.get_security_label())
-
- # Xen API: Class console
- # ----------------------------------------------------------------
-
-
- console_attr_ro = ['location', 'protocol', 'VM']
- console_attr_rw = ['other_config']
- console_funcs = [('create', 'console')]
-
- def console_get_all(self, session):
- xendom = XendDomain.instance()
- cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
- cons = reduce(lambda x, y: x + y, cons)
- return xen_api_success(cons)
-
- def console_get_location(self, session, console_ref):
- xendom = XendDomain.instance()
- return xen_api_success(xendom.get_dev_property_by_uuid('console',
- console_ref,
- 'location'))
-
- def console_get_protocol(self, session, console_ref):
- xendom = XendDomain.instance()
- return xen_api_success(xendom.get_dev_property_by_uuid('console',
- console_ref,
- 'protocol'))
-
- def console_get_VM(self, session, console_ref):
- xendom = XendDomain.instance()
- vm = xendom.get_vm_with_dev_uuid('console', console_ref)
- return xen_api_success(vm.get_uuid())
-
- def console_get_other_config(self, session, console_ref):
- xendom = XendDomain.instance()
- return xen_api_success(xendom.get_dev_property_by_uuid('console',
- console_ref,
- 'other_config'))
-
- # object methods
- def console_get_record(self, session, console_ref):
- xendom = XendDomain.instance()
- vm = xendom.get_vm_with_dev_uuid('console', console_ref)
- if not vm:
- return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
- cfg = vm.get_dev_xenapi_config('console', console_ref)
- if not cfg:
- return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
-
- valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
- self.Base_attr_ro + self.Base_attr_rw
-
- return_cfg = {}
- for k in cfg.keys():
- if k in valid_console_keys:
- return_cfg[k] = cfg[k]
-
- return xen_api_success(return_cfg)
-
- def console_create(self, session, console_struct):
- xendom = XendDomain.instance()
- if not xendom.is_valid_vm(console_struct['VM']):
- return xen_api_error(['HANDLE_INVALID', 'VM',
- console_struct['VM']])
-
- dom = xendom.get_vm_by_uuid(console_struct['VM'])
- try:
- if 'protocol' not in console_struct:
- return xen_api_error(['CONSOLE_PROTOCOL_INVALID',
- 'No protocol specified'])
-
- console_ref = dom.create_console(console_struct)
- xendom.managed_config_save(dom)
- return xen_api_success(console_ref)
- except XendError, exn:
- return xen_api_error(['INTERNAL_ERROR', str(exn)])
-
- def console_set_other_config(self, session, console_ref, other_config):
- xd = XendDomain.instance()
- vm = xd.get_vm_with_dev_uuid('console', console_ref)
- vm.set_console_other_config(console_ref, other_config)
- xd.managed_config_save(vm)
- return xen_api_success_void()
-
- # Xen API: Class SR
- # ----------------------------------------------------------------
- SR_attr_ro = ['VDIs',
- 'PBDs',
- 'virtual_allocation',
- 'physical_utilisation',
- 'physical_size',
- 'type',
- 'content_type']
-
- SR_attr_rw = ['name_label',
- 'name_description']
-
- SR_attr_inst = ['physical_size',
- 'type',
- 'name_label',
- 'name_description']
-
- SR_methods = []
- SR_funcs = [('get_by_name_label', 'Set(SR)'),
- ('get_by_uuid', 'SR')]
-
- # Class Functions
- def SR_get_all(self, session):
- return xen_api_success(XendNode.instance().get_all_sr_uuid())
-
- def SR_get_by_name_label(self, session, label):
- return xen_api_success(XendNode.instance().get_sr_by_name(label))
-
- def SR_get_supported_types(self, _):
- return xen_api_success(['local', 'qcow_file'])
-
- # Class Methods
-
- def SR_get_record(self, session, sr_ref):
- sr = XendNode.instance().get_sr(sr_ref)
- if sr:
- return xen_api_success(sr.get_record())
- return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
-
- # Attribute acceess
-
- def _get_SR_func(self, sr_ref, func):
- return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
- func)())
-
- def _get_SR_attr(self, sr_ref, attr):
- return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
- attr))
-
- def SR_get_VDIs(self, _, ref):
- return self._get_SR_func(ref, 'list_images')
-
- def SR_get_PBDs(self, _, ref):
- return xen_api_success(XendPBD.get_by_SR(ref))
-
- def SR_get_virtual_allocation(self, _, ref):
- return self._get_SR_func(ref, 'virtual_allocation')
-
- def SR_get_physical_utilisation(self, _, ref):
- return self._get_SR_func(ref, 'physical_utilisation')
-
- def SR_get_physical_size(self, _, ref):
- return self._get_SR_attr(ref, 'physical_size')
-
- def SR_get_type(self, _, ref):
- return self._get_SR_attr(ref, 'type')
-
- def SR_get_content_type(self, _, ref):
- return self._get_SR_attr(ref, 'content_type')
-
- def SR_get_name_label(self, _, ref):
- return self._get_SR_attr(ref, 'name_label')
-
- def SR_get_name_description(self, _, ref):
- return self._get_SR_attr(ref, 'name_description')
-
- def SR_set_name_label(self, session, sr_ref, value):
- sr = XendNode.instance.get_sr(sr_ref)
- if sr:
- sr.name_label = value
- XendNode.instance().save()
- return xen_api_success_void()
-
- def SR_set_name_description(self, session, sr_ref, value):
- sr = XendNode.instance.get_sr(sr_ref)
- if sr:
- sr.name_description = value
- XendNode.instance().save()
- return xen_api_success_void()
-
-
- # Xen API: Class event
- # ----------------------------------------------------------------
-
- event_attr_ro = []
- event_attr_rw = []
- event_funcs = [('register', None),
- ('unregister', None),
- ('next', None)]
-
- def event_register(self, session, reg_classes):
- event_register(session, reg_classes)
- return xen_api_success_void()
-
- def event_unregister(self, session, unreg_classes):
- event_unregister(session, unreg_classes)
- return xen_api_success_void()
-
- def event_next(self, session):
- return event_next(session)
-
- # Xen API: Class debug
- # ----------------------------------------------------------------
-
- debug_methods = [('destroy', None),
- ('get_record', 'debug')]
- debug_funcs = [('wait', None),
- ('return_failure', None)]
-
- def debug_wait(self, session, wait_secs):
- import time
- prog_units = 100/float(wait_secs)
- for i in range(int(wait_secs)):
- XendTask.log_progress(prog_units * i, prog_units * (i + 1),
- time.sleep, 1)
- return xen_api_success_void()
-
-
- def debug_return_failure(self, session):
- return xen_api_error(['DEBUG_FAIL', session])
-
- def debug_create(self, session):
- debug_uuid = genuuid.createString()
- self._debug[debug_uuid] = None
- return xen_api_success(debug_uuid)
-
- def debug_destroy(self, session, debug_ref):
- del self._debug[debug_ref]
- return xen_api_success_void()
-
- def debug_get_record(self, session, debug_ref):
- return xen_api_success({'uuid': debug_ref})
-
-
-class XendAPIAsyncProxy:
- """ A redirector for Async.Class.function calls to XendAPI
- but wraps the call for use with the XendTaskManager.
-
- @ivar xenapi: Xen API instance
- @ivar method_map: Mapping from XMLRPC method name to callable objects.
- """
-
- method_prefix = 'Async.'
-
- def __init__(self, xenapi):
- """Initialises the Async Proxy by making a map of all
- implemented Xen API methods for use with XendTaskManager.
-
- @param xenapi: XendAPI instance
- """
- self.xenapi = xenapi
- self.method_map = {}
- for method_name in dir(self.xenapi):
- method = getattr(self.xenapi, method_name)
- if method_name[0] != '_' and hasattr(method, 'async') \
- and method.async == True:
- self.method_map[method.api] = method
-
- def _dispatch(self, method, args):
- """Overridden method so that SimpleXMLRPCServer will
- resolve methods through this method rather than through
- inspection.
-
- @param method: marshalled method name from XMLRPC.
- @param args: marshalled arguments from XMLRPC.
- """
-
- # Only deal with method names that start with "Async."
- if not method.startswith(self.method_prefix):
- return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
-
- # Lookup synchronous version of the method
- synchronous_method_name = method[len(self.method_prefix):]
- if synchronous_method_name not in self.method_map:
- return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
-
- method = self.method_map[synchronous_method_name]
-
- # Check that we've got enough arguments before issuing a task ID.
- needed = argcounts[method.api]
- if len(args) != needed:
- return xen_api_error(['MESSAGE_PARAMETER_COUNT_MISMATCH',
- self.method_prefix + method.api, needed,
- len(args)])
-
- # Validate the session before proceeding
- session = args[0]
- if not auth_manager().is_session_valid(session):
- return xen_api_error(['SESSION_INVALID', session])
-
- # create and execute the task, and return task_uuid
- return_type = getattr(method, 'return_type', None)
- task_uuid = XendTaskManager.create_task(method, args,
- synchronous_method_name,
- return_type,
- synchronous_method_name,
- session)
- return xen_api_success(task_uuid)
diff --git a/tools/python/xen/xend/XendAPIConstants.py b/tools/python/xen/xend/XendAPIConstants.py
deleted file mode 100644
index b3d2f9e..0000000
--- a/tools/python/xen/xend/XendAPIConstants.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006-2007 XenSource Ltd.
-#============================================================================
-
-#
-# Xen API Enums
-#
-
-XEN_API_VM_POWER_STATE = [
- 'Halted',
- 'Paused',
- 'Running',
- 'Suspended',
- 'Halted',
- 'Crashed',
- 'Unknown'
-]
-
-XEN_API_VM_POWER_STATE_HALTED = 0
-XEN_API_VM_POWER_STATE_PAUSED = 1
-XEN_API_VM_POWER_STATE_RUNNING = 2
-XEN_API_VM_POWER_STATE_SUSPENDED = 3
-XEN_API_VM_POWER_STATE_SHUTTINGDOWN = 4
-XEN_API_VM_POWER_STATE_CRASHED = 5
-XEN_API_VM_POWER_STATE_UNKNOWN = 6
-
-XEN_API_ON_NORMAL_EXIT = [
- 'destroy',
- 'restart',
-]
-
-XEN_API_ON_CRASH_BEHAVIOUR = [
- 'destroy',
- 'coredump_and_destroy',
- 'restart',
- 'coredump_and_restart',
- 'preserve',
- 'rename_restart'
-]
-
-XEN_API_ON_CRASH_BEHAVIOUR_FILTER = {
- 'destroy' : 'destroy',
- 'coredump-destroy' : 'coredump_and_destroy',
- 'coredump_and_destroy' : 'coredump_and_destroy',
- 'restart' : 'restart',
- 'coredump-restart' : 'coredump_and_restart',
- 'coredump_and_restart' : 'coredump_and_restart',
- 'preserve' : 'preserve',
- 'rename-restart' : 'rename_restart',
- 'rename_restart' : 'rename_restart',
-}
-
-XEN_API_ON_CRASH_BEHAVIOUR_LEGACY = {
- 'destroy' : 'destroy',
- 'coredump-destroy' : 'coredump-destroy',
- 'coredump_and_destroy' : 'coredump-destroy',
- 'restart' : 'restart',
- 'coredump-restart' : 'coredump-restart',
- 'coredump_and_restart' : 'coredump-restart',
- 'preserve' : 'preserve',
- 'rename-restart' : 'rename-restart',
- 'rename_restart' : 'rename-restart',
-}
-
-XEN_API_VBD_MODE = ['RO', 'RW']
-XEN_API_VDI_TYPE = ['system', 'user', 'ephemeral']
-XEN_API_VBD_TYPE = ['CD', 'Disk']
-XEN_API_TASK_STATUS_TYPE = ['pending', 'success', 'failure']
-XEN_API_CONSOLE_PROTOCOL = ['vt100', 'rfb', 'rdp']
diff --git a/tools/python/xen/xend/XendAPIStore.py b/tools/python/xen/xend/XendAPIStore.py
deleted file mode 100644
index 6876f2e..0000000
--- a/tools/python/xen/xend/XendAPIStore.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2007 Tom Wilkie <tom.wilkie at gmail.com>
-#============================================================================
-"""
-This is a place to put instances of XenAPI objects,
-instead of just holding them in arbitrary places.
-
-All objects which subclass XendBase should use this
-mechanism.
-
-You must register both the uuid and type, and get objects
-by type, to ensure safety
-"""
-
-import threading
-
-__classes = {}
-__classes_lock = threading.RLock()
-
-def register(uuid, type, inst):
- __classes_lock.acquire()
- try:
- __classes[(uuid, type)] = inst
- return inst
- finally:
- __classes_lock.release()
-
-def deregister(uuid, type):
- __classes_lock.acquire()
- try:
- old = get(uuid, type)
- if old is not None:
- del __classes[(uuid, type)]
- return old
- finally:
- __classes_lock.release()
-
-def get(uuid, type):
- """
- Get the instances by uuid and type
- """
- __classes_lock.acquire()
- try:
- return __classes.get((uuid, type), None)
- finally:
- __classes_lock.release()
-
-def get_all(all_type):
- """
- Get all instances by type
- """
- __classes_lock.acquire()
- try:
- return [inst
- for ((uuid, t), inst) in __classes.items()
- if t == all_type]
- finally:
- __classes_lock.release()
-
-def get_all_uuid(all_type):
- """
- Get all uuids by type
- """
- __classes_lock.acquire()
- try:
- return [uuid
- for (uuid, t) in __classes.keys()
- if t == all_type]
- finally:
- __classes_lock.release()
diff --git a/tools/python/xen/xend/XendAPIVersion.py b/tools/python/xen/xend/XendAPIVersion.py
deleted file mode 100644
index 2659108..0000000
--- a/tools/python/xen/xend/XendAPIVersion.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (c) 2007 XenSource Inc.
-#============================================================================
-
-
-XEN_API_VERSION_MAJOR = 1
-XEN_API_VERSION_MINOR = 0
-XEN_API_VERSION_VENDOR = 'xenbits'
-XEN_API_VERSION_VENDOR_IMPLEMENTATION = {}
diff --git a/tools/python/xen/xend/XendAuthSessions.py b/tools/python/xen/xend/XendAuthSessions.py
deleted file mode 100644
index fb28e3f..0000000
--- a/tools/python/xen/xend/XendAuthSessions.py
+++ /dev/null
@@ -1,131 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 XenSource Ltd.
-#============================================================================
-
-import time
-
-from xen.xend import uuid
-from xen.xend.XendError import *
-from xen.xend.XendLogging import log
-
-class XendAuthSessions:
- """Keeps track of Xen API Login Sessions using PAM.
-
- Note: Login sessions are not valid across instances of Xend.
- """
- def __init__(self):
- self.sessions = {}
-
- def init(self):
- pass
-
- def login_unconditionally(self, username):
- """Returns a session UUID if valid.
-
- @rtype: string
- @return: Session UUID
- """
- new_session = uuid.createString()
- self.sessions[new_session] = (username, time.time())
- return new_session
-
- def login_with_password(self, username, password):
- """Returns a session UUID if valid, otherwise raises an error.
-
- @raises XendError: If login fails.
- @rtype: string
- @return: Session UUID
- """
- if self.is_authorized(username, password):
- return self.login_unconditionally(username)
-
- raise XendError("Login failed")
-
- def logout(self, session):
- """Delete session of it exists."""
- if self.is_session_valid(session):
- del self.sessions[session]
-
- def is_session_valid(self, session):
- """Returns true is session is valid."""
- if type(session) == type(str()):
- return (session in self.sessions)
- return False
-
- def is_authorized(self, username, password):
- """Returns true is a user is authorised via PAM.
-
- Note: We use the 'login' PAM stack rather than inventing
- our own.
-
- @rtype: boolean
- """
- pam_auth = None
- try:
- import PAM
- pam_auth = PAM.pam()
- except ImportError:
- log.warn("python-pam is required for XenAPI support.")
- return False
- except NameError:
- # if PAM doesn't exist, let's ignore it
- return False
-
- pam_auth.start("login")
- pam_auth.set_item(PAM.PAM_USER, username)
-
- def _pam_conv(auth, query_list, user_data = None):
- resp = []
- for i in range(len(query_list)):
- query, qtype = query_list[i]
- if qtype == PAM.PAM_PROMPT_ECHO_ON:
- resp.append((username, 0))
- elif qtype == PAM.PAM_PROMPT_ECHO_OFF:
- resp.append((password, 0))
- else:
- return None
- return resp
-
- pam_auth.set_item(PAM.PAM_CONV, _pam_conv)
-
- try:
- pam_auth.authenticate()
- pam_auth.acct_mgmt()
- except PAM.error, resp:
- return False
- except Exception, e:
- log.warn("Error with PAM: %s" % str(e))
- return False
- else:
- return True
-
- def get_user(self, session):
- try:
- return self.sessions[session][0]
- except (KeyError, IndexError):
- return None
-
-
-def instance():
- """Singleton constructor. Use this instead of the class constructor.
- """
- global inst
- try:
- inst
- except:
- inst = XendAuthSessions()
- inst.init()
- return inst
diff --git a/tools/python/xen/xend/XendBase.py b/tools/python/xen/xend/XendBase.py
deleted file mode 100644
index 9244776..0000000
--- a/tools/python/xen/xend/XendBase.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/python
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2007 Tom Wilkie <tom.wilkie at gmail.com>
-#============================================================================
-"""
-Base class for all XenAPI classes
-"""
-
-from xen.xend.XendError import *
-from xen.xend import XendAPIStore
-
-class XendBase:
- #
- # These functions describe the object, and what is exposed via the API
- #
- def getClass(self):
- return "Base"
-
- def getAttrRO(self):
- return ['uuid']
-
- def getAttrRW(self):
- return []
-
- def getAttrInst(self):
- return []
-
- def getMethods(self):
- return ["get_record"]
-
- def getFuncs(self):
- return ["get_all", "get_by_uuid", "get_all_records"]
-
- getClass = classmethod(getClass)
- getAttrRO = classmethod(getAttrRO)
- getAttrRW = classmethod(getAttrRW)
- getAttrInst = classmethod(getAttrInst)
- getMethods = classmethod(getMethods)
- getFuncs = classmethod(getFuncs)
-
- def __init__(self, uuid, record):
- self.__uuid = uuid
-
- # First check this class implements all the correct methods:
- for attr_ro in self.getAttrRO() + self.getAttrRW():
- if not hasattr(self, "get_%s" % attr_ro):
- raise ImplementationError(self.getClass(),
- "get_%s" % attr_ro)
-
- for attr_rw in self.getAttrRW():
- if not hasattr(self, "set_%s" % attr_rw):
- raise ImplementationError(self.getClass(),
- "set_%s" % attr_rw)
-
- for method in self.getMethods():
- if not hasattr(self, method):
- raise ImplementationError(self.getClass(),
- method)
-
- for func in self.getFuncs():
- if not hasattr(self.__class__, func):
- raise ImplementationError(self.getClass(),
- func)
-
- # Next check that the class is being created with the correct
- # parameters
- if not isinstance(record, dict):
- raise CreateUnspecifiedAttributeError(
- "record" , self.getClass())
-
- for attr_inst in self.getAttrInst():
- if attr_inst not in record:
- raise CreateUnspecifiedAttributeError(
- attr_inst, self.getClass())
- setattr(self, attr_inst, record[attr_inst])
-
- # Finally register it
- XendAPIStore.register(uuid, self.getClass(), self)
-
- def destroy(self):
- XendAPIStore.deregister(self.get_uuid(), self.getClass())
-
- def get_uuid(self):
- return self.__uuid
-
- def get_record(self):
- keys = self.getAttrRO() + self.getAttrRW()
- return dict([(key, getattr(self, "get_%s" % key)())
- for key in keys])
-
- #
- # Class methods
- #
-
- def get_all(cls):
- return XendAPIStore.get_all_uuid(cls.getClass())
-
- def get_by_uuid(cls, uuid):
- # Sanity check the uuid is one of us
- me = XendAPIStore.get(uuid, cls.getClass())
- if me is not None and me.getClass() == cls.getClass():
- # In OSS, ref == uuid
- return uuid
- else:
- raise ValueError("Big Error.. TODO!")
-
- def get_all_records(cls):
- return dict([(inst.get_uuid(), inst.get_record())
- for inst in XendAPIStore.get_all(cls.getClass())])
-
- get_all = classmethod(get_all)
- get_by_uuid = classmethod(get_by_uuid)
- get_all_records = classmethod(get_all_records)
diff --git a/tools/python/xen/xend/XendBootloader.py b/tools/python/xen/xend/XendBootloader.py
deleted file mode 100644
index f17428e..0000000
--- a/tools/python/xen/xend/XendBootloader.py
+++ /dev/null
@@ -1,230 +0,0 @@
-#
-# XendBootloader.py - Framework to run a boot loader for picking the kernel
-#
-# Copyright 2005-2006 Red Hat, Inc.
-# Jeremy Katz <katzj at redhat.com>
-#
-# This software may be freely redistributed under the terms of the GNU
-# general public license.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-
-import os, select, errno, stat, signal, tty
-import random
-import shlex
-from xen.xend import sxp
-
-from xen.util import mkdir, oshelp
-from XendLogging import log
-from XendError import VmError
-
-import pty, termios, fcntl
-from xen.lowlevel import ptsname
-
-def bootloader(blexec, disk, dom, quiet = False, blargs = '', kernel = '',
- ramdisk = '', kernel_args = ''):
- """Run the boot loader executable on the given disk and return a
- config image.
- @param blexec Binary to use as the boot loader
- @param disk Disk to run the boot loader on.
- @param dom DomainInfo representing the domain being booted.
- @param quiet Run in non-interactive mode, just booting the default.
- @param blargs Arguments to pass to the bootloader."""
-
- if not os.access(blexec, os.X_OK):
- msg = "Bootloader isn't executable"
- log.error(msg)
- raise VmError(msg)
- if not os.access(disk, os.R_OK):
- msg = "Disk isn't accessible"
- log.error(msg)
- raise VmError(msg)
-
- if os.uname()[0] == "NetBSD" and disk.startswith('/dev/'):
- disk = "/r".join(disk.rsplit("/",1))
-
- mkdir.parents("/var/run/xend/boot/", stat.S_IRWXU)
-
- while True:
- fifo = "/var/run/xend/boot/xenbl.%s" %(random.randint(0, 32000),)
- try:
- os.mkfifo(fifo, 0600)
- except OSError, e:
- if (e.errno != errno.EEXIST):
- raise
- break
-
- # We need to present the bootloader's tty as a pty slave that xenconsole
- # can access. Since the bootloader itself needs a pty slave,
- # we end up with a connection like this:
- #
- # xenconsole -- (slave pty1 master) <-> (master pty2 slave) -- bootloader
- #
- # where we copy characters between the two master fds, as well as
- # listening on the bootloader's fifo for the results.
-
- (m1, s1) = pty.openpty()
-
- # On Solaris, the pty master side will get cranky if we try
- # to write to it while there is no slave. To work around this,
- # keep the slave descriptor open until we're done. Set it
- # to raw terminal parameters, otherwise it will echo back
- # characters, which will confuse the I/O loop below.
- # Furthermore, a raw master pty device has no terminal
- # semantics on Solaris, so don't try to set any attributes
- # for it.
- if os.uname()[0] != 'SunOS' and os.uname()[0] != 'NetBSD':
- tty.setraw(m1)
- os.close(s1)
- else:
- tty.setraw(s1)
-
- fcntl.fcntl(m1, fcntl.F_SETFL, os.O_NDELAY)
-
- slavename = ptsname.ptsname(m1)
- dom.storeDom("console/tty", slavename)
-
- # Release the domain lock here, because we definitely don't want
- # a stuck bootloader to deny service to other xend clients.
- from xen.xend import XendDomain
- domains = XendDomain.instance()
- domains.domains_lock.release()
-
- (child, m2) = pty.fork()
- if (not child):
- args = [ blexec ]
- if kernel:
- args.append("--kernel=%s" % kernel)
- if ramdisk:
- args.append("--ramdisk=%s" % ramdisk)
- if kernel_args:
- args.append("--args=%s" % kernel_args)
- if quiet:
- args.append("-q")
- args.append("--output=%s" % fifo)
- if blargs:
- args.extend(shlex.split(blargs))
- args.append(disk)
-
- try:
- log.debug("Launching bootloader as %s." % str(args))
- env = os.environ.copy()
- env['TERM'] = 'vt100'
- oshelp.close_fds()
- os.execvpe(args[0], args, env)
- except OSError, e:
- print e
- pass
- os._exit(1)
-
- # record that this domain is bootloading
- dom.bootloader_pid = child
-
- # On Solaris, the master pty side does not have terminal semantics,
- # so don't try to set any attributes, as it will fail.
- if os.uname()[0] != 'SunOS':
- tty.setraw(m2);
-
- fcntl.fcntl(m2, fcntl.F_SETFL, os.O_NDELAY);
- while True:
- try:
- r = os.open(fifo, os.O_RDONLY)
- except OSError, e:
- if e.errno == errno.EINTR:
- continue
- break
-
- fcntl.fcntl(r, fcntl.F_SETFL, os.O_NDELAY);
-
- ret = ""
- inbuf=""; outbuf="";
- # filedescriptors:
- # r - input from the bootloader (bootstring output)
- # m1 - input/output from/to xenconsole
- # m2 - input/output from/to pty that controls the bootloader
- # The filedescriptors are NDELAY, so it's ok to try to read
- # bigger chunks than may be available, to keep e.g. curses
- # screen redraws in the bootloader efficient. m1 is the side that
- # gets xenconsole input, which will be keystrokes, so a small number
- # is sufficient. m2 is pygrub output, which will be curses screen
- # updates, so a larger number (1024) is appropriate there.
- #
- # For writeable descriptors, only include them in the set for select
- # if there is actual data to write, otherwise this would loop too fast,
- # eating up CPU time.
-
- while True:
- wsel = []
- if len(outbuf) != 0:
- wsel = wsel + [m1]
- if len(inbuf) != 0:
- wsel = wsel + [m2]
- sel = select.select([r, m1, m2], wsel, [])
- try:
- if m1 in sel[0]:
- s = os.read(m1, 16)
- inbuf += s
- if m2 in sel[1]:
- n = os.write(m2, inbuf)
- inbuf = inbuf[n:]
- except OSError, e:
- if e.errno == errno.EIO:
- pass
- try:
- if m2 in sel[0]:
- s = os.read(m2, 1024)
- outbuf += s
- if m1 in sel[1]:
- n = os.write(m1, outbuf)
- outbuf = outbuf[n:]
- except OSError, e:
- if e.errno == errno.EIO:
- pass
- if r in sel[0]:
- s = os.read(r, 128)
- ret = ret + s
- if len(s) == 0:
- break
- del inbuf
- del outbuf
- os.waitpid(child, 0)
- os.close(r)
- os.close(m2)
- os.close(m1)
- if os.uname()[0] == 'SunOS' or os.uname()[0] == 'NetBSD':
- os.close(s1)
- os.unlink(fifo)
-
- # Re-acquire the lock to cover the changes we're about to make
- # when we return to domain creation.
- domains.domains_lock.acquire()
-
- if dom.bootloader_pid is None:
- msg = "Domain was died while the bootloader was running."
- log.error(msg)
- raise VmError, msg
-
- dom.bootloader_pid = None
-
- if len(ret) == 0:
- msg = "Boot loader didn't return any data!"
- log.error(msg)
- raise VmError, msg
-
- pin = sxp.Parser()
- pin.input(ret)
- pin.input_eof()
- blcfg = pin.val
- return blcfg
-
-
-def bootloader_tidy(dom):
- if hasattr(dom, "bootloader_pid") and dom.bootloader_pid is not None:
- pid = dom.bootloader_pid
- dom.bootloader_pid = None
- os.kill(pid, signal.SIGKILL)
-
-
diff --git a/tools/python/xen/xend/XendCPUPool.py b/tools/python/xen/xend/XendCPUPool.py
deleted file mode 100644
index d26cbd6..0000000
--- a/tools/python/xen/xend/XendCPUPool.py
+++ /dev/null
@@ -1,910 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (c) 2009 Fujitsu Technology Solutions.
-#============================================================================
-
-""" CPU Pool support including XEN-API and Legacy API.
-"""
-
-import types
-import threading
-import re
-import xen.lowlevel.xc
-import XendNode
-import XendDomain
-from xen.xend.XendLogging import log
-from xen.xend.XendBase import XendBase
-from xen.xend import XendAPIStore
-from xen.xend.XendConstants import XS_POOLROOT
-from xen.xend import uuid as genuuid
-from xen.xend.XendError import VmError, XendAPIError, PoolError
-from xen.xend.xenstore.xstransact import xstransact
-from xen.util.sxputils import sxp2map, map2sxp
-
-
-XEND_ERROR_INTERNAL = 'INTERNAL_ERROR'
-XEND_ERROR_UNKOWN_SCHED_POLICY = 'UNKOWN_SCHED_POLICY'
-XEND_ERROR_BAD_POOL_STATE = 'POOL_BAD_STATE'
-XEND_ERROR_POOL_PARAM = 'PARAMETER_ERROR'
-XEND_ERROR_INSUFFICIENT_CPUS = 'INSUFFICIENT_CPUS'
-XEND_ERROR_POOL_RECONF = 'POOL_RECONF'
-XEND_ERROR_INVALID_CPU = 'INVAILD_CPU'
-XEND_ERROR_LAST_CPU_NOT_REM = 'LAST_CPU_NOT_REMOVEABLE'
-
-
-XEN_SCHEDULER_TO_ID = {
- 'credit2': xen.lowlevel.xc.XEN_SCHEDULER_CREDIT2,
- 'credit' : xen.lowlevel.xc.XEN_SCHEDULER_CREDIT,
- 'sedf' : xen.lowlevel.xc.XEN_SCHEDULER_SEDF,
- }
-
-xc = xen.lowlevel.xc.xc()
-
-class XendCPUPool(XendBase):
- """ CPU Pool management.
- @ivar pool_lock: Lock to secure modification of pool data
- @type pool_lock: Rlock
- """
-
- pool_lock = threading.RLock()
-
- def getClass(cls):
- return "cpu_pool"
-
- def getAttrRO(cls):
- attrRO = ['resident_on',
- 'started_VMs',
- 'host_CPUs',
- 'activated',
- ]
- return XendBase.getAttrRO() + attrRO
-
- def getAttrRW(cls):
- attrRW = ['name_label',
- 'name_description',
- 'auto_power_on',
- 'ncpu',
- 'sched_policy',
- 'proposed_CPUs',
- 'other_config',
- ]
- return XendBase.getAttrRW() + attrRW
-
- def getMethods(cls):
- methods = ['destroy',
- 'activate',
- 'deactivate',
- 'add_host_CPU_live',
- 'remove_host_CPU_live',
- 'add_to_proposed_CPUs',
- 'remove_from_proposed_CPUs',
- 'add_to_other_config',
- 'remove_from_other_config',
- ]
- return XendBase.getMethods() + methods
-
- def getFuncs(cls):
- funcs = ['create',
- 'get_by_name_label',
- ]
- return XendBase.getFuncs() + funcs
-
- getClass = classmethod(getClass)
- getAttrRO = classmethod(getAttrRO)
- getAttrRW = classmethod(getAttrRW)
- getMethods = classmethod(getMethods)
- getFuncs = classmethod(getFuncs)
-
-
- #
- # XenAPI function calls
- #
-
- def create(cls, record):
- """ Create a new managed pool instance.
- @param record: attributes of pool
- @type record: dict
- @return: uuid of created pool
- @rtype: str
- """
- new_uuid = genuuid.createString()
- XendCPUPool(record, new_uuid)
- XendNode.instance().save_cpu_pools()
- return new_uuid
-
- create = classmethod(create)
-
-
- def get_by_name_label(cls, name_label):
- """ Query a Pool(ref) by its name.
- @return: ref of pool
- @rtype: str
- """
- cls.pool_lock.acquire()
- try:
- return [ inst.get_uuid()
- for inst in XendAPIStore.get_all(cls.getClass())
- if inst.name_label == name_label
- ]
- finally:
- cls.pool_lock.release()
-
- get_by_name_label = classmethod(get_by_name_label)
-
-
- def get_cpu_pool_by_cpu_ref(cls, host_cpu):
- """ Query cpu_pool ref the given cpu belongs to.
- @param host_cpu: ref of host_cpu to lookup
- @type host_cpu: str
- @return: list cpu_pool refs (list contains not more than one element)
- @rtype: list of str
- """
- node = XendNode.instance()
- cpu_nr = node.get_host_cpu_field(host_cpu, 'number')
- for pool_rec in xc.cpupool_getinfo():
- if cpu_nr in pool_rec['cpulist']:
- # pool found; return the ref
- return cls.query_pool_ref(pool_rec['cpupool'])
- return []
-
- get_cpu_pool_by_cpu_ref = classmethod(get_cpu_pool_by_cpu_ref)
-
-
- def get_all_managed(cls):
- """ Query all managed pools.
- @return: uuids of all managed pools
- @rtype: list of str
- """
- cls.pool_lock.acquire()
- try:
- managed_pools = [ inst.get_uuid()
- for inst in XendAPIStore.get_all(cls.getClass())
- if inst.is_managed() ]
- finally:
- cls.pool_lock.release()
- return managed_pools
-
- get_all_managed = classmethod(get_all_managed)
-
-
- #
- # XenAPI methods calls
- #
-
- def __init__(self, record, new_uuid, managed_pool=True):
- XendBase.__init__(self, new_uuid, record)
- try:
- self._managed = managed_pool
- self.name_label = None
-
- name = record.get('name_label', 'Pool-Unnamed')
- self._checkName(name)
- self.name_label = name
- self.name_description = record.get('name_description',
- self.name_label)
- self.proposed_cpus = [ int(cpu)
- for cpu in record.get('proposed_CPUs', []) ]
- self.auto_power_on = bool(record.get('auto_power_on', False))
- self.ncpu = int(record.get('ncpu', 1))
- self.sched_policy = record.get('sched_policy', '')
- self.other_config = record.get('other_config', {})
- except Exception, ex:
- XendBase.destroy(self)
- raise ex
-
-
- def get_resident_on(self):
- """ Always return uuid of own node.
- @return: uuid of this node
- @rytpe: str
- """
- return XendNode.instance().uuid
-
- def get_started_VMs(self):
- """ Query all VMs currently assigned to pool.
- @return: ref of all VMs assigned to pool; if pool is not active,
- an empty list will be returned
- @rtype: list of str
- """
- if self.get_activated():
- # search VMs related to this pool
- pool_id = self.query_pool_id()
- started_VMs = [ vm.get_uuid()
- for vm in XendDomain.instance().list('all')
- if vm.get_cpu_pool() == pool_id ]
- else:
- # pool not active, so it couldn't have any started VMs
- started_VMs = []
-
- return started_VMs
-
- def get_host_CPUs(self):
- """ Query all cpu refs of this pool currently asisgned .
- - Read pool id of this pool from xenstore
- - Read cpu configuration from hypervisor
- - lookup cpu number -> cpu ref
- @return: host_cpu refs
- @rtype: list of str
- """
- if self.get_activated():
- node = XendNode.instance()
- pool_id = self.query_pool_id()
- if pool_id == None:
- raise PoolError(XEND_ERROR_INTERNAL,
- [self.getClass(), 'get_host_CPUs'])
- cpus = []
- for pool_rec in xc.cpupool_getinfo():
- if pool_rec['cpupool'] == pool_id:
- cpus = pool_rec['cpulist']
-
- # query host_cpu ref for any cpu of the pool
- host_CPUs = [ cpu_ref
- for cpu_ref in node.get_host_cpu_refs()
- if node.get_host_cpu_field(cpu_ref, 'number')
- in cpus ]
- else:
- # pool not active, so it couldn't have any assigned cpus
- host_CPUs = []
-
- return host_CPUs
-
- def get_activated(self):
- """ Query if the pool is registered in XendStore.
- If pool uuid is not in XenStore, the pool is not activated.
- @return: True, if activated
- @rtype: bool
- """
- return self.query_pool_id() != None
-
- def get_name_label(self):
- return self.name_label
-
- def get_name_description(self):
- return self.name_description
-
- def get_auto_power_on(self):
- return self.auto_power_on
-
- def get_ncpu(self):
- return self.ncpu
-
- def get_sched_policy(self):
- if len(self.sched_policy) == 0:
- # default scheduler selected
- return XendNode.instance().get_vcpus_policy()
- else:
- return self.sched_policy
-
- def get_proposed_CPUs(self):
- return [ str(cpu) for cpu in self.proposed_cpus ]
-
- def get_other_config(self):
- return self.other_config
-
- def set_name_label(self, name_label):
- self._checkName(name_label)
- self.name_label = name_label
- if self._managed:
- XendNode.instance().save_cpu_pools()
-
- def set_name_description(self, name_descr):
- self.name_description = name_descr
- if self._managed:
- XendNode.instance().save_cpu_pools()
-
- def set_auto_power_on(self, auto_power_on):
- self.auto_power_on = bool(int(auto_power_on))
- if self._managed:
- XendNode.instance().save_cpu_pools()
-
- def set_ncpu(self, ncpu):
- _ncpu = int(ncpu)
- if _ncpu < 1:
- raise PoolError(XEND_ERROR_POOL_PARAM, 'ncpu')
- self.ncpu = _ncpu
- if self._managed:
- XendNode.instance().save_cpu_pools()
-
- def set_sched_policy(self, sched_policy):
- if self.get_activated():
- raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated')
- self.sched_policy = sched_policy
- if self._managed:
- XendNode.instance().save_cpu_pools()
-
- def set_proposed_CPUs(self, proposed_cpus):
- if self.get_activated():
- raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated')
- self.proposed_cpus = [ int(cpu) for cpu in proposed_cpus ]
- if self._managed:
- XendNode.instance().save_cpu_pools()
-
- def set_other_config(self, other_config):
- self.other_config = other_config
- if self._managed:
- XendNode.instance().save_cpu_pools()
-
- def destroy(self):
- """ In order to destroy a cpu pool, it must be deactivated """
- self.pool_lock.acquire()
- try:
- if self.get_activated():
- raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated')
- XendBase.destroy(self)
- finally:
- self.pool_lock.release()
- XendNode.instance().save_cpu_pools()
-
- def activate(self):
- """ Create pool in hypervisor and add cpus.
- Preconditions:
- - pool not already active
- - enough unbound cpus available
- Actions:
- - create pool in hypervisor
- - select free cpus (preferred from proposed_CPUs list) and bind it to
- the pool
- - create entries in Xenstore
- """
- self.pool_lock.acquire()
- try:
- if self.get_activated():
- raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated')
- sched_policy = self.get_sched_policy()
- if sched_policy not in XEN_SCHEDULER_TO_ID.keys():
- raise PoolError(XEND_ERROR_UNKOWN_SCHED_POLICY)
- unbound_cpus = set(self.unbound_cpus())
- if len(unbound_cpus) < self.ncpu:
- raise PoolError(XEND_ERROR_INSUFFICIENT_CPUS,
- [str(self.ncpu), str(len(unbound_cpus))])
-
- # build list of cpu numbers to bind to pool
- cpu_set = set(self.proposed_cpus).intersection(unbound_cpus)
- if len(cpu_set) < self.ncpu:
- pool_cpus = (list(cpu_set) +
- list(unbound_cpus.difference(cpu_set)))
- else:
- pool_cpus = list(cpu_set)
- pool_cpus = pool_cpus[0:self.ncpu]
-
- # create pool in hypervisor
- pool_id = xc.cpupool_create(
- sched = XEN_SCHEDULER_TO_ID.get(sched_policy, 0))
-
- self.update_XS(pool_id)
- # add cpus
- for cpu in pool_cpus:
- xc.cpupool_addcpu(pool_id, cpu)
-
- finally:
- self.pool_lock.release()
-
- def deactivate(self):
- """ Delete pool in hypervisor
- Preconditions:
- - pool is activated
- - no running VMs in pool
- Actions:
- - call hypervisor for deletion
- - remove path of pool in xenstore
- """
- self.pool_lock.acquire()
- try:
- if not self.get_activated():
- raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'deactivated')
- if len(self.get_started_VMs()) != 0:
- raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'in use')
-
- pool_id = self.query_pool_id()
- # remove cpus from pool
- cpus = []
- for pool_rec in xc.cpupool_getinfo():
- if pool_rec['cpupool'] == pool_id:
- cpus = pool_rec['cpulist']
- for cpu_number in cpus:
- xc.cpupool_removecpu(pool_id, cpu_number)
- xc.cpupool_destroy(pool_id)
-
- # update XenStore
- xs_path = XS_POOLROOT + "%s/" % pool_id
- xstransact.Remove(xs_path)
- finally:
- self.pool_lock.release()
-
- def add_host_CPU_live(self, cpu_ref):
- """ Add cpu to pool, if it is currently not assigned to a pool.
- @param cpu_ref: reference of host_cpu instance to add
- @type cpu_ref: str
- """
- if not self.get_activated():
- raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'deactivated')
- node = XendNode.instance()
- number = node.get_host_cpu_field(cpu_ref, 'number')
-
- self.pool_lock.acquire()
- try:
- pool_id = self.query_pool_id()
- other_pool_ref = self.get_cpu_pool_by_cpu_ref(cpu_ref)
- if len(other_pool_ref) != 0:
- raise PoolError(XEND_ERROR_INVALID_CPU,
- 'cpu already assigned to pool "%s"' % other_pool_ref[0])
- xc.cpupool_addcpu(pool_id, number)
- finally:
- self.pool_lock.release()
-
- if number not in self.proposed_cpus:
- self.proposed_cpus.append(number)
- self._update_ncpu(pool_id)
- if self._managed:
- XendNode.instance().save_cpu_pools()
-
- def remove_host_CPU_live(self, cpu_ref):
- """ Remove cpu from pool.
- After successfull call, the cpu is free.
- Remove of the last cpu of the pool is rejected.
- @param cpu_ref: reference of host_cpu instance to remove
- @type cpu_ref: str
- """
- if not self.get_activated():
- raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'deactivated')
- node = XendNode.instance()
- number = node.get_host_cpu_field(cpu_ref, 'number')
-
- self.pool_lock.acquire()
- try:
- pool_id = self.query_pool_id()
- pool_rec = {}
- for pool in xc.cpupool_getinfo():
- if pool['cpupool'] == pool_id:
- pool_rec = pool
- break
-
- if number in pool_rec['cpulist']:
- if len(pool_rec['cpulist']) < 2 and pool_rec['n_dom'] > 0:
- raise PoolError(XEND_ERROR_LAST_CPU_NOT_REM,
- 'could not remove last cpu')
- xc.cpupool_removecpu(pool_id, number)
- else:
- raise PoolError(XEND_ERROR_INVALID_CPU,
- 'CPU not assigned to pool')
- finally:
- self.pool_lock.release()
-
- if number in self.proposed_cpus:
- self.proposed_cpus.remove(number)
- self._update_ncpu(pool_id)
- if self._managed:
- XendNode.instance().save_cpu_pools()
-
- def add_to_proposed_CPUs(self, cpu):
- if self.get_activated():
- raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated')
-
- _cpu = int(cpu)
- if _cpu not in self.proposed_cpus:
- self.proposed_cpus.append(_cpu)
- self.proposed_cpus.sort()
- if self._managed:
- XendNode.instance().save_cpu_pools()
-
- def remove_from_proposed_CPUs(self, cpu):
- if self.get_activated():
- raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated')
- _cpu = int(cpu)
- if _cpu in self.proposed_cpus:
- self.proposed_cpus.remove(_cpu)
- if self._managed:
- XendNode.instance().save_cpu_pools()
-
- def add_to_other_config(self, key, value):
- self.other_config[key] = value
- if self._managed:
- XendNode.instance().save_cpu_pools()
-
- def remove_from_other_config(self, key):
- if key in self.other_config:
- del self.other_config[key]
- if self._managed:
- XendNode.instance().save_cpu_pools()
-
-
- #
- # Legacy RPC calls
- #
- def pool_new(cls, config):
- try:
- record = sxp2map(config)
- if record.has_key('proposed_CPUs') and \
- not isinstance(record['proposed_CPUs'], types.ListType):
- record['proposed_CPUs'] = [record['proposed_CPUs']]
- new_uuid = cls.create(record)
- except XendAPIError, ex:
- raise VmError(ex.get_api_error())
- return new_uuid
-
- def pool_create(cls, config):
- try:
- record = sxp2map(config)
- if record.has_key('proposed_CPUs') and \
- not isinstance(record['proposed_CPUs'], types.ListType):
- record['proposed_CPUs'] = [record['proposed_CPUs']]
- new_uuid = genuuid.createString()
- pool = XendCPUPool(record, new_uuid, False)
- pool.activate()
- except XendAPIError, ex:
- raise VmError(ex.get_api_error())
-
- def pool_start(cls, poolname):
- pool = cls.lookup_pool(poolname)
- if not pool:
- raise VmError('unknown pool %s' % poolname)
- try:
- pool.activate()
- except XendAPIError, ex:
- raise VmError(ex.get_api_error())
-
- def pool_list(cls, names):
- sxprs = []
- try:
- node = XendNode.instance()
- xd = XendDomain.instance()
- pools = cls.get_all_records()
- for (pool_uuid, pool_vals) in pools.items():
- if pool_vals['name_label'] in names or len(names) == 0:
- # conv host_cpu refs to cpu number
- cpus = [ node.get_host_cpu_field(cpu_ref, 'number')
- for cpu_ref in pool_vals['host_CPUs'] ]
- cpus.sort()
- pool_vals['host_CPU_numbers'] = cpus
- # query VMs names. Take in account, that a VM
- # returned by get_all_records could be destroy, now
- vm_names = [ vm.getName()
- for vm in map(xd.get_vm_by_uuid,
- pool_vals['started_VMs'])
- if vm ]
- pool_vals['started_VM_names'] = vm_names
- pool_vals['auto_power_on'] = int(pool_vals['auto_power_on'])
- sxprs += [[pool_uuid] + map2sxp(pool_vals)]
- except XendAPIError, ex:
- raise VmError(ex.get_api_error())
- return sxprs
-
- def pool_destroy(cls, poolname):
- pool = cls.lookup_pool(poolname)
- if not pool:
- raise VmError('unknown pool %s' % poolname)
- try:
- pool.deactivate()
- if not pool.is_managed():
- pool.destroy()
- except XendAPIError, ex:
- raise VmError(ex.get_api_error())
-
- def pool_delete(cls, poolname):
- pool = cls.lookup_pool(poolname)
- if not pool:
- raise VmError('unknown pool %s' % poolname)
- try:
- pool.destroy()
- except XendAPIError, ex:
- raise VmError(ex.get_api_error())
-
- def pool_cpu_add(cls, poolname, cpu):
- pool = cls.lookup_pool(poolname)
- if not pool:
- raise VmError('unknown pool %s' % poolname)
- try:
- cpu_ref = cls._cpu_number_to_ref(int(cpu))
- if cpu_ref:
- pool.add_host_CPU_live(cpu_ref)
- else:
- raise PoolError(XEND_ERROR_INVALID_CPU,
- 'CPU unknown')
- except XendAPIError, ex:
- raise VmError(ex.get_api_error())
-
- def pool_cpu_remove(cls, poolname, cpu):
- pool = cls.lookup_pool(poolname)
- if not pool:
- raise VmError('unknown pool %s' % poolname)
- try:
- cpu_ref = cls._cpu_number_to_ref(int(cpu))
- if cpu_ref:
- pool.remove_host_CPU_live(cpu_ref)
- else:
- raise PoolError(XEND_ERROR_INVALID_CPU,
- 'CPU unknown')
- except XendAPIError, ex:
- raise VmError(ex.get_api_error())
-
- def pool_migrate(cls, domname, poolname):
- dom = XendDomain.instance()
- pool = cls.lookup_pool(poolname)
- if not pool:
- raise VmError('unknown pool %s' % poolname)
- dominfo = dom.domain_lookup_nr(domname)
- if not dominfo:
- raise VmError('unknown domain %s' % domname)
- domid = dominfo.getDomid()
- if domid is not None:
- if domid == 0:
- raise VmError('could not move Domain-0')
- try:
- cls.move_domain(pool.get_uuid(), domid)
- except Exception, ex:
- raise VmError('could not move domain')
- dominfo.info['pool_name'] = poolname
- dom.managed_config_save(dominfo)
-
- pool_new = classmethod(pool_new)
- pool_create = classmethod(pool_create)
- pool_start = classmethod(pool_start)
- pool_list = classmethod(pool_list)
- pool_destroy = classmethod(pool_destroy)
- pool_delete = classmethod(pool_delete)
- pool_cpu_add = classmethod(pool_cpu_add)
- pool_cpu_remove = classmethod(pool_cpu_remove)
- pool_migrate = classmethod(pool_migrate)
-
-
- #
- # methods
- #
-
- def is_managed(self):
- """ Check, if pool is managed.
- @return: True, if managed
- @rtype: bool
- """
- return self._managed
-
- def query_pool_id(self):
- """ Get corresponding pool-id of pool instance from XenStore.
- @return: pool id or None
- @rytpe: int
- """
- self.pool_lock.acquire()
- try:
- for pool_id in xstransact.List(XS_POOLROOT):
- uuid = xstransact.Read(XS_POOLROOT + "%s/" % pool_id, 'uuid')
- if uuid == self.get_uuid():
- return int(pool_id)
- finally:
- self.pool_lock.release()
-
- return None
-
- def update_XS(self, pool_id):
- """ Write (or update) data in xenstore taken from instance.
- @param pool_id: Pool id to build path to pool data in xenstore
- @type pool_id: int
- """
- self.pool_lock.acquire()
- try:
- xs_path = XS_POOLROOT + "%s/" % pool_id
- xs_entries = { 'uuid' : self.get_uuid(),
- 'name' : self.name_label,
- 'description' : self.name_description
- }
- xstransact.Mkdir(xs_path)
- xstransact.Mkdir(xs_path, 'other_config')
- xstransact.Write(xs_path, xs_entries)
- xstransact.Write('%s%s' % (xs_path, 'other_config'),
- self.other_config)
- finally:
- self.pool_lock.release()
-
- def _update_ncpu(self, pool_id):
- for pool_rec in xc.cpupool_getinfo():
- if pool_rec['cpupool'] == pool_id:
- self.ncpu = len(pool_rec['cpulist'])
-
- def _checkName(self, name):
- """ Check if a pool name is valid. Valid names contain alphabetic
- characters, digits, or characters in '_-.:/+'.
- The same name cannot be used for more than one pool at the same
- time.
- @param name: name
- @type name: str
- @raise: PoolError if invalid
- """
- if name is None or name == '':
- raise PoolError(XEND_ERROR_POOL_PARAM, 'Missing Pool Name')
- if not re.search(r'^[A-Za-z0-9_\-\.\:\/\+]+$', name):
- raise PoolError(XEND_ERROR_POOL_PARAM, 'Invalid Pool Name')
-
- pool = self.lookup_pool(name)
- if pool and pool.get_uuid() != self.get_uuid():
- raise PoolError(XEND_ERROR_POOL_PARAM,
- 'Pool name "%s" already exists' % name)
-
-
- #
- # class methods
- #
-
- def recreate_active_pools(cls):
- """ Read active pool config from hypervisor and create pool instances.
- - Query pool ids and assigned CPUs from hypervisor.
- - Query additional information for any pool from xenstore.
- If an entry for a pool id is missing in xenstore, it will be
- recreated with a new uuid and generic name (this is an error case)
- - Create an XendCPUPool instance for any pool id
- Function have to be called after recreation of managed pools.
- """
- log.debug('recreate_active_pools')
-
- for pool_rec in xc.cpupool_getinfo():
- pool = pool_rec['cpupool']
-
- # read pool data from xenstore
- path = XS_POOLROOT + "%s/" % pool
- uuid = xstransact.Read(path, 'uuid')
- if not uuid:
- # xenstore entry missing / invaild; create entry with new uuid
- uuid = genuuid.createString()
- name = "Pool-%s" % pool
- try:
- inst = XendCPUPool( { 'name_label' : name }, uuid, False )
- inst.update_XS(pool)
- except PoolError, ex:
- # log error and skip domain
- log.error('cannot recreate pool %s; skipping (reason: %s)' \
- % (name, ex))
- else:
- (name, descr) = xstransact.Read(path, 'name', 'description')
- other_config = {}
- for key in xstransact.List(path + 'other_config'):
- other_config[key] = xstransact.Read(
- path + 'other_config/%s' % key)
-
- # check existance of pool instance
- inst = XendAPIStore.get(uuid, cls.getClass())
- if inst:
- # update attributes of existing instance
- inst.name_label = name
- inst.name_description = descr
- inst.other_config = other_config
- else:
- # recreate instance
- try:
- inst = XendCPUPool(
- { 'name_label' : name,
- 'name_description' : descr,
- 'other_config' : other_config,
- 'proposed_CPUs' : pool_rec['cpulist'],
- 'ncpu' : len(pool_rec['cpulist']),
- },
- uuid, False )
- except PoolError, ex:
- # log error and skip domain
- log.error(
- 'cannot recreate pool %s; skipping (reason: %s)' \
- % (name, ex))
-
- recreate_active_pools = classmethod(recreate_active_pools)
-
-
- def recreate(cls, record, current_uuid):
- """ Recreate a pool instance while xend restart.
- @param record: attributes of pool
- @type record: dict
- @param current_uuid: uuid of pool to create
- @type current_uuid: str
- """
- XendCPUPool(record, current_uuid)
-
- recreate = classmethod(recreate)
-
-
- def autostart_pools(cls):
- """ Start managed pools that are marked as autostart pools.
- Function is called after recreation of managed domains while
- xend restart.
- """
- cls.pool_lock.acquire()
- try:
- for inst in XendAPIStore.get_all(cls.getClass()):
- if inst.is_managed() and inst.auto_power_on and \
- inst.query_pool_id() == None:
- inst.activate()
- finally:
- cls.pool_lock.release()
-
- autostart_pools = classmethod(autostart_pools)
-
-
- def move_domain(cls, pool_ref, domid):
- cls.pool_lock.acquire()
- try:
- pool = XendAPIStore.get(pool_ref, cls.getClass())
- pool_id = pool.query_pool_id()
-
- xc.cpupool_movedomain(pool_id, domid)
- finally:
- cls.pool_lock.release()
-
- move_domain = classmethod(move_domain)
-
-
- def query_pool_ref(cls, pool_id):
- """ Get pool ref by pool id.
- Take the ref from xenstore.
- @param pool_id:
- @type pool_id: int
- @return: ref
- @rtype: str
- """
- uuid = xstransact.Read(XS_POOLROOT + "%s/" % pool_id, 'uuid')
- if uuid:
- return [uuid]
- else:
- return []
-
- query_pool_ref = classmethod(query_pool_ref)
-
-
- def lookup_pool(cls, id_or_name):
- """ Search XendCPUPool instance with given id_or_name.
- @param id_or_name: pool id or pool nameto search
- @type id_or_name: [int, str]
- @return: instane or None if not found
- @rtype: XendCPUPool
- """
- pool_uuid = None
- try:
- pool_id = int(id_or_name)
- # pool id given ?
- pool_uuid = cls.query_pool_ref(pool_id)
- if not pool_uuid:
- # not found -> search name
- pool_uuid = cls.get_by_name_label(id_or_name)
- except ValueError:
- # pool name given
- pool_uuid = cls.get_by_name_label(id_or_name)
-
- if len(pool_uuid) > 0:
- return XendAPIStore.get(pool_uuid[0], cls.getClass())
- else:
- return None
-
- lookup_pool = classmethod(lookup_pool)
-
-
- def number_of_pools(cls):
- return len(xc.cpupool_getinfo())
-
- number_of_pools = classmethod(number_of_pools)
-
- def _cpu_number_to_ref(cls, number):
- node = XendNode.instance()
- for cpu_ref in node.get_host_cpu_refs():
- if node.get_host_cpu_field(cpu_ref, 'number') == number:
- return cpu_ref
- return None
-
- _cpu_number_to_ref = classmethod(_cpu_number_to_ref)
-
-
- def unbound_cpus(cls):
- """ Build list containing the numbers of all cpus not bound to a pool.
- Info is taken from Hypervisor.
- @return: list of cpu numbers
- @rytpe: list of int
- """
- return xc.cpupool_freeinfo()
-
- unbound_cpus = classmethod(unbound_cpus)
-
diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py
deleted file mode 100644
index a433ffa..0000000
--- a/tools/python/xen/xend/XendCheckpoint.py
+++ /dev/null
@@ -1,425 +0,0 @@
-# Copyright (C) 2005 Christian Limpach <Christian.Limpach at cl.cam.ac.uk>
-# Copyright (C) 2005 XenSource Ltd
-
-# This file is subject to the terms and conditions of the GNU General
-# Public License. See the file "COPYING" in the main directory of
-# this archive for more details.
-
-import os
-import os.path
-import re
-import string
-import threading
-import fcntl
-from struct import pack, unpack, calcsize
-
-from xen.util.xpopen import xPopen3
-import xen.util.auxbin
-import xen.lowlevel.xc
-
-from xen.xend import balloon, sxp, image
-from xen.xend.XendError import XendError, VmError
-from xen.xend.XendLogging import log
-from xen.xend.XendConfig import XendConfig
-from xen.xend.XendConstants import *
-from xen.xend import XendNode
-
-SIGNATURE = "LinuxGuestRecord"
-QEMU_SIGNATURE = "QemuDeviceModelRecord"
-dm_batch = 512
-XC_SAVE = "xc_save"
-XC_RESTORE = "xc_restore"
-
-
-sizeof_int = calcsize("i")
-sizeof_unsigned_int = calcsize("I")
-sizeof_unsigned_long = calcsize("L")
-
-
-xc = xen.lowlevel.xc.xc()
-
-
-def write_exact(fd, buf, errmsg):
- if os.write(fd, buf) != len(buf):
- raise XendError(errmsg)
-
-
-def read_exact(fd, size, errmsg):
- buf = ''
- while size != 0:
- readstr = os.read(fd, size)
- if not len(readstr):
- log.error("read_exact: EOF trying to read %d (buf='%s')" % \
- (size, buf))
- raise XendError(errmsg)
- size = size - len(readstr)
- buf = buf + readstr
- return buf
-
-
-def insert_after(list, pred, value):
- for i,k in enumerate(list):
- if type(k) == type([]):
- if k[0] == pred:
- list.insert (i+1, value)
- return
-
-
-def save(fd, dominfo, network, live, dst, checkpoint=False, node=-1,sock=None):
- from xen.xend import XendDomain
-
- try:
- if not os.path.isdir("/var/lib/xen"):
- os.makedirs("/var/lib/xen")
- except Exception, exn:
- log.exception("Can't create directory '/var/lib/xen'")
- raise XendError("Can't create directory '/var/lib/xen'")
-
- write_exact(fd, SIGNATURE, "could not write guest state file: signature")
-
- sxprep = dominfo.sxpr()
-
- if node > -1:
- insert_after(sxprep,'vcpus',['node', str(node)])
-
- for device_sxp in sxp.children(sxprep, 'device'):
- backend = sxp.child(device_sxp[1], 'backend')
- if backend == None:
- continue
- bkdominfo = XendDomain.instance().domain_lookup_nr(backend[1])
- if bkdominfo == None:
- raise XendError("Could not find backend: %s" % backend[1])
- if bkdominfo.getDomid() == XendDomain.DOM0_ID:
- # Skip for compatibility of checkpoint data format
- continue
- backend[1] = bkdominfo.getName()
-
- config = sxp.to_string(sxprep)
-
- domain_name = dominfo.getName()
- # Rename the domain temporarily, so that we don't get a name clash if this
- # domain is migrating (live or non-live) to the local host. Doing such a
- # thing is useful for debugging.
- dominfo.setName('migrating-' + domain_name)
-
- try:
- dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP1, domain_name)
-
- write_exact(fd, pack("!i", len(config)),
- "could not write guest state file: config len")
- write_exact(fd, config, "could not write guest state file: config")
-
- image_cfg = dominfo.info.get('image', {})
- hvm = dominfo.info.is_hvm()
-
- # xc_save takes three customization parameters: maxit, max_f, and
- # flags the last controls whether or not save is 'live', while the
- # first two further customize behaviour when 'live' save is
- # enabled. Passing "0" simply uses the defaults compiled into
- # libxenguest; see the comments and/or code in xc_linux_save() for
- # more information.
- cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd),
- str(dominfo.getDomid()), "0", "0",
- str(int(live) | (int(hvm) << 2)) ]
- log.debug("[xc_save]: %s", string.join(cmd))
-
- def saveInputHandler(line, tochild):
- log.debug("In saveInputHandler %s", line)
- if line == "suspend":
- log.debug("Suspending %d ...", dominfo.getDomid())
- dominfo.shutdown('suspend')
- dominfo.waitForSuspend()
- if line in ('suspend', 'suspended'):
- dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP2,
- domain_name)
- log.info("Domain %d suspended.", dominfo.getDomid())
- dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP3,
- domain_name)
- if hvm:
- dominfo.image.saveDeviceModel()
-
- if line == "suspend":
- tochild.write("done\n")
- tochild.flush()
- log.debug('Written done')
-
- forkHelper(cmd, fd, saveInputHandler, False)
-
- # put qemu device model state
- if os.path.exists("/var/lib/xen/qemu-save.%d" % dominfo.getDomid()):
- write_exact(fd, QEMU_SIGNATURE, "could not write qemu signature")
- qemu_fd = os.open("/var/lib/xen/qemu-save.%d" % dominfo.getDomid(),
- os.O_RDONLY)
- while True:
- buf = os.read(qemu_fd, dm_batch)
- if len(buf):
- write_exact(fd, buf, "could not write device model state")
- else:
- break
- os.close(qemu_fd)
- os.remove("/var/lib/xen/qemu-save.%d" % dominfo.getDomid())
-
- if checkpoint:
- dominfo.resumeDomain()
- else:
- if live and sock != None:
- try:
- sock.shutdown(2)
- except:
- pass
- sock.close()
-
- dominfo.destroy()
- dominfo.testDeviceComplete()
- try:
- dominfo.setName(domain_name, False)
- except VmError:
- # Ignore this. The name conflict (hopefully) arises because we
- # are doing localhost migration; if we are doing a suspend of a
- # persistent VM, we need the rename, and don't expect the
- # conflict. This needs more thought.
- pass
-
- except Exception, exn:
- log.exception("Save failed on domain %s (%s) - resuming.", domain_name,
- dominfo.getDomid())
- dominfo.resumeDomain()
-
- try:
- dominfo.setName(domain_name)
- except:
- log.exception("Failed to reset the migrating domain's name")
-
- raise exn
-
-
-def restore(xd, fd, dominfo = None, paused = False, relocating = False):
- try:
- if not os.path.isdir("/var/lib/xen"):
- os.makedirs("/var/lib/xen")
- except Exception, exn:
- log.exception("Can't create directory '/var/lib/xen'")
- raise XendError("Can't create directory '/var/lib/xen'")
-
- signature = read_exact(fd, len(SIGNATURE),
- "not a valid guest state file: signature read")
- if signature != SIGNATURE:
- raise XendError("not a valid guest state file: found '%s'" %
- signature)
-
- l = read_exact(fd, sizeof_int,
- "not a valid guest state file: config size read")
- vmconfig_size = unpack("!i", l)[0]
- vmconfig_buf = read_exact(fd, vmconfig_size,
- "not a valid guest state file: config read")
-
- p = sxp.Parser()
- p.input(vmconfig_buf)
- if not p.ready:
- raise XendError("not a valid guest state file: config parse")
-
- vmconfig = p.get_val()
-
- if not relocating:
- domconfig = XendConfig(sxp_obj = vmconfig)
- othervm = xd.domain_lookup_nr(domconfig["name_label"])
- if othervm is None or othervm.domid is None:
- othervm = xd.domain_lookup_nr(domconfig["uuid"])
- if othervm is not None and othervm.domid is not None:
- raise VmError("Domain '%s' already exists with ID '%d'" % (domconfig["name_label"], othervm.domid))
-
- if dominfo:
- dominfo.resume()
- else:
- dominfo = xd.restore_(vmconfig)
-
- image_cfg = dominfo.info.get('image', {})
- is_hvm = dominfo.info.is_hvm()
-
- if is_hvm:
- nomigrate = dominfo.info['platform'].get('nomigrate', 0)
- else:
- nomigrate = dominfo.info['platform'].get('nomigrate')
- if nomigrate is None:
- nomigrate = 0
- if int(nomigrate) != 0:
- dominfo.destroy()
- raise XendError("cannot restore non-migratable domain")
-
- store_port = dominfo.getStorePort()
- console_port = dominfo.getConsolePort()
-
- assert store_port
- assert console_port
-
- # if hvm, pass mem size to calculate the store_mfn
- if is_hvm:
- apic = int(dominfo.info['platform'].get('apic', 0))
- pae = int(dominfo.info['platform'].get('pae', 0))
- log.info("restore hvm domain %d, apic=%d, pae=%d",
- dominfo.domid, apic, pae)
- else:
- apic = 0
- pae = 0
-
- try:
- restore_image = image.create(dominfo, dominfo.info)
- memory = restore_image.getRequiredAvailableMemory(
- dominfo.info['memory_dynamic_max'] / 1024)
- maxmem = restore_image.getRequiredAvailableMemory(
- dominfo.info['memory_static_max'] / 1024)
- shadow = restore_image.getRequiredShadowMemory(
- dominfo.info['shadow_memory'] * 1024,
- dominfo.info['memory_static_max'] / 1024)
-
- log.debug("restore:shadow=0x%x, _static_max=0x%x, _static_min=0x%x, ",
- dominfo.info['shadow_memory'],
- dominfo.info['memory_static_max'],
- dominfo.info['memory_static_min'])
-
- # Round shadow up to a multiple of a MiB, as shadow_mem_control
- # takes MiB and we must not round down and end up under-providing.
- shadow = ((shadow + 1023) / 1024) * 1024
-
- # set memory limit
- xc.domain_setmaxmem(dominfo.getDomid(), maxmem)
-
- vtd_mem = 0
- info = xc.physinfo()
- if 'hvm_directio' in info['virt_caps']:
- # Reserve 1 page per MiB of RAM for separate VT-d page table.
- vtd_mem = 4 * (dominfo.info['memory_static_max'] / 1024 / 1024)
- # Round vtd_mem up to a multiple of a MiB.
- vtd_mem = ((vtd_mem + 1023) / 1024) * 1024
-
- balloon.free(memory + shadow + vtd_mem, dominfo)
-
- shadow_cur = xc.shadow_mem_control(dominfo.getDomid(), shadow / 1024)
- dominfo.info['shadow_memory'] = shadow_cur
-
- superpages = restore_image.superpages
-
- cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE),
- fd, dominfo.getDomid(),
- store_port, console_port, int(is_hvm), pae, apic, superpages, 1])
- log.debug("[xc_restore]: %s", string.join(cmd))
-
- handler = RestoreInputHandler()
-
- forkHelper(cmd, fd, handler.handler, True)
-
- # We don't want to pass this fd to any other children -- we
- # might need to recover the disk space that backs it.
- try:
- flags = fcntl.fcntl(fd, fcntl.F_GETFD)
- flags |= fcntl.FD_CLOEXEC
- fcntl.fcntl(fd, fcntl.F_SETFD, flags)
- except:
- pass
-
- if handler.store_mfn is None:
- raise XendError('Could not read store MFN')
-
- if not is_hvm and handler.console_mfn is None:
- raise XendError('Could not read console MFN')
-
- restore_image.setCpuid()
-
- # xc_restore will wait for source to close connection
-
- dominfo.completeRestore(handler.store_mfn, handler.console_mfn)
-
- #
- # We shouldn't hold the domains_lock over a waitForDevices
- # As this function sometime gets called holding this lock,
- # we must release it and re-acquire it appropriately
- #
- from xen.xend import XendDomain
-
- lock = True;
- try:
- XendDomain.instance().domains_lock.release()
- except:
- lock = False;
-
- try:
- dominfo.waitForDevices() # Wait for backends to set up
- finally:
- if lock:
- XendDomain.instance().domains_lock.acquire()
-
- if not paused:
- dominfo.unpause()
-
- return dominfo
- except Exception, exn:
- dominfo.destroy()
- log.exception(exn)
- raise exn
-
-
-class RestoreInputHandler:
- def __init__(self):
- self.store_mfn = None
- self.console_mfn = None
-
-
- def handler(self, line, _):
- m = re.match(r"^(store-mfn) (\d+)$", line)
- if m:
- self.store_mfn = int(m.group(2))
- else:
- m = re.match(r"^(console-mfn) (\d+)$", line)
- if m:
- self.console_mfn = int(m.group(2))
-
-
-def forkHelper(cmd, fd, inputHandler, closeToChild):
- child = xPopen3(cmd, True, -1, [fd])
-
- if closeToChild:
- child.tochild.close()
-
- thread = threading.Thread(target = slurp, args = (child.childerr,))
- thread.start()
-
- try:
- try:
- while 1:
- line = child.fromchild.readline()
- if line == "":
- break
- else:
- line = line.rstrip()
- log.debug('%s', line)
- inputHandler(line, child.tochild)
-
- except IOError, exn:
- raise XendError('Error reading from child process for %s: %s' %
- (cmd, exn))
- finally:
- child.fromchild.close()
- if not closeToChild:
- child.tochild.close()
- thread.join()
- child.childerr.close()
- status = child.wait()
-
- if status >> 8 == 127:
- raise XendError("%s failed: popen failed" % string.join(cmd))
- elif status != 0:
- raise XendError("%s failed" % string.join(cmd))
-
-
-def slurp(infile):
- while 1:
- line = infile.readline()
- if line == "":
- break
- else:
- line = line.strip()
- m = re.match(r"^ERROR: (.*)", line)
- if m is None:
- log.info('%s', line)
- else:
- log.error('%s', m.group(1))
diff --git a/tools/python/xen/xend/XendClient.py b/tools/python/xen/xend/XendClient.py
deleted file mode 100644
index ef16699..0000000
--- a/tools/python/xen/xend/XendClient.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2006 Anthony Liguori <aliguori at us.ibm.com>
-#============================================================================
-
-from xen.util.xmlrpcclient import ServerProxy
-import os
-import sys
-
-XML_RPC_SOCKET = "/var/run/xend/xmlrpc.sock"
-XEN_API_SOCKET = "/var/run/xend/xen-api.sock"
-
-ERROR_INTERNAL = 1
-ERROR_GENERIC = 2
-ERROR_INVALID_DOMAIN = 3
-
-uri = 'httpu:///var/run/xend/xmlrpc.sock'
-if os.environ.has_key('XM_SERVER'):
- uri = os.environ['XM_SERVER']
-
-try:
- server = ServerProxy(uri)
-except ValueError, exn:
- print >>sys.stderr, exn
- sys.exit(1)
-
diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py
deleted file mode 100644
index 4a226a7..0000000
--- a/tools/python/xen/xend/XendConfig.py
+++ /dev/null
@@ -1,2265 +0,0 @@
-#===========================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006-2007 XenSource Ltd
-#============================================================================
-
-import logging
-import os
-import re
-import time
-import types
-
-from xen.xend import sxp
-from xen.xend import uuid
-from xen.xend import XendOptions
-from xen.xend import XendAPIStore
-from xen.xend.XendPPCI import XendPPCI
-from xen.xend.XendDPCI import XendDPCI
-from xen.xend.XendPSCSI import XendPSCSI
-from xen.xend.XendDSCSI import XendDSCSI, XendDSCSI_HBA
-from xen.xend.XendError import VmError
-from xen.xend.XendDevices import XendDevices
-from xen.xend.PrettyPrint import prettyprintstring
-from xen.xend.XendConstants import DOM_STATE_HALTED, AUTO_PHP_SLOT
-from xen.xend.xenstore.xstransact import xstransact
-from xen.xend.server.BlktapController import blktap_disk_types
-from xen.xend.server.netif import randomMAC
-from xen.util.blkif import blkdev_name_to_number, blkdev_uname_to_file
-from xen.util.pci import pci_opts_list_from_sxp, pci_convert_sxp_to_dict
-from xen.xend.XendSXPDev import dev_dict_to_sxp
-from xen.util import xsconstants
-from xen.util import auxbin
-from xen.xend.XendAPIConstants import *
-import xen.util.fileuri
-
-log = logging.getLogger("xend.XendConfig")
-log.setLevel(logging.WARN)
-
-
-"""
-XendConfig API
-
- XendConfig will try to mirror as closely the Xen API VM Struct
- with extra parameters for those options that are not supported.
-
-"""
-
-def reverse_dict(adict):
- """Return the reverse mapping of a dictionary."""
- return dict([(v, k) for k, v in adict.items()])
-
-def bool0(v):
- return v != '0' and v != 'False' and bool(v)
-
-def convert_on_crash(v):
- v = str(v)
- if v in XEN_API_ON_CRASH_BEHAVIOUR:
- return XEN_API_ON_CRASH_BEHAVIOUR_LEGACY[v]
- else:
- return v
-
-# Recursively copy a data struct, scrubbing out VNC passwords.
-# Will scrub any dict entry with a key of 'vncpasswd' or any
-# 2-element list whose first member is 'vncpasswd'. It will
-# also scrub a string matching '(vncpasswd XYZ)'. Everything
-# else is no-op passthrough
-def scrub_password(data):
- if type(data) == dict or type(data) == XendConfig:
- scrubbed = {}
- for key in data.keys():
- if key == "vncpasswd":
- scrubbed[key] = "XXXXXXXX"
- else:
- scrubbed[key] = scrub_password(data[key])
- return scrubbed
- elif type(data) == list:
- if len(data) == 2 and type(data[0]) == str and data[0] == 'vncpasswd':
- return ['vncpasswd', 'XXXXXXXX']
- else:
- scrubbed = []
- for entry in data:
- scrubbed.append(scrub_password(entry))
- return scrubbed
- elif type(data) == tuple:
- scrubbed = []
- for entry in data:
- scrubbed.append(scrub_password(entry))
- return tuple(scrubbed)
- elif type(data) == str:
- return re.sub(r'\(vncpasswd\s+[^\)]+\)','(vncpasswd XXXXXX)', data)
- else:
- return data
-
-#
-# CPU fields:
-#
-# VCPUs_max -- the maximum number of vcpus that this domain may ever have.
-# aka XendDomainInfo.getVCpuCount().
-# vcpus -- the legacy configuration name for above.
-# max_vcpu_id -- vcpus_number - 1. This is given to us by Xen.
-#
-# cpus -- the list of pCPUs available to each vCPU.
-#
-# vcpu_avail -- a bitmap telling the guest domain whether it may use each of
-# its VCPUs. This is translated to
-# <dompath>/cpu/<id>/availability = {online,offline} for use
-# by the guest domain.
-# VCPUs_live -- the number of VCPUs currently up, as reported by Xen. This
-# is changed by changing vcpu_avail, and waiting for the
-# domain to respond.
-#
-
-
-# Mapping from XendConfig configuration keys to the old
-# legacy configuration keys that map directly.
-
-XENAPI_CFG_TO_LEGACY_CFG = {
- 'uuid': 'uuid',
- 'VCPUs_max': 'vcpus',
- 'cpus': 'cpus',
- 'name_label': 'name',
- 'actions_after_shutdown': 'on_poweroff',
- 'actions_after_reboot': 'on_reboot',
- 'actions_after_crash': 'on_crash',
- 'PV_bootloader': 'bootloader',
- 'PV_bootloader_args': 'bootloader_args',
- 'Description': 'description',
- 'pool_name' : 'pool_name',
-}
-
-LEGACY_CFG_TO_XENAPI_CFG = reverse_dict(XENAPI_CFG_TO_LEGACY_CFG)
-
-# Platform configuration keys and their types.
-XENAPI_PLATFORM_CFG_TYPES = {
- 'acpi': int,
- 'apic': int,
- 'boot': str,
- 'device_model': str,
- 'loader': str,
- 'display' : str,
- 'fda': str,
- 'fdb': str,
- 'keymap': str,
- 'isa' : int,
- 'localtime': int,
- 'monitor': int,
- 'monitor_path': str,
- 'nographic': int,
- 'nomigrate': int,
- 'pae' : int,
- 'rtc_timeoffset': int,
- 'parallel': str,
- 'serial': str,
- 'sdl': int,
- 'opengl': int,
- 'soundhw': str,
- 'stdvga': int,
- 'videoram': int,
- 'usb': int,
- 'usbdevice': str,
- 'hpet': int,
- 'vnc': int,
- 'vncconsole': int,
- 'vncdisplay': int,
- 'vnclisten': str,
- 'timer_mode': int,
- 'tsc_mode': int,
- 'vpt_align': int,
- 'viridian': int,
- 'vncpasswd': str,
- 'vncunused': int,
- 'xauthority': str,
- 'pci': str,
- 'vhpt': int,
- 'guest_os_type': str,
- 'hap': int,
- 'nestedhvm' : int,
- 'xen_extended_power_mgmt': int,
- 'pci_msitranslate': int,
- 'pci_power_mgmt': int,
- 'xen_platform_pci': int,
- "gfx_passthru": int,
- 'oos' : int,
-}
-
-# Xen API console 'other_config' keys.
-XENAPI_CONSOLE_OTHER_CFG = ['vncunused', 'vncdisplay', 'vnclisten',
- 'vncpasswd', 'sdl', 'vnc', 'display', 'xauthority',
- 'keymap', 'opengl']
-
-# List of XendConfig configuration keys that have no direct equivalent
-# in the old world.
-
-XENAPI_CFG_TYPES = {
- 'uuid': str,
- 'name_label': str,
- 'name_description': str,
- 'user_version': str,
- 'is_a_template': bool0,
- 'auto_power_on': bool0,
- 'resident_on': str,
- 'memory_static_min': int, # note these are stored in bytes, not KB!
- 'memory_static_max': int,
- 'memory_dynamic_min': int,
- 'memory_dynamic_max': int,
- 'cpus': list,
- 'vcpus_params': dict,
- 'VCPUs_max': int,
- 'VCPUs_at_startup': int,
- 'VCPUs_live': int,
- 'actions_after_shutdown': str,
- 'actions_after_reboot': str,
- 'actions_after_crash': convert_on_crash,
- 'PV_bootloader': str,
- 'PV_kernel': str,
- 'PV_ramdisk': str,
- 'PV_args': str,
- 'PV_bootloader_args': str,
- 'HVM_boot_policy': str,
- 'HVM_boot_params': dict,
- 'PCI_bus': str,
- 'platform': dict,
- 'tools_version': dict,
- 'other_config': dict,
- 'target': int,
- 'security_label': str,
- 'pci': str,
- 'cpuid' : dict,
- 'cpuid_check' : dict,
- 'machine_address_size': int,
- 'suppress_spurious_page_faults': bool0,
- 's3_integrity' : int,
- 'superpages' : int,
- 'memory_sharing': int,
- 'pool_name' : str,
- 'Description': str,
-}
-
-# List of legacy configuration keys that have no equivalent in the
-# Xen API, but are still stored in XendConfig.
-
-LEGACY_UNSUPPORTED_BY_XENAPI_CFG = [
- # roundtripped (dynamic, unmodified)
- 'shadow_memory',
- 'vcpu_avail',
- 'features',
- # read/write
- 'on_xend_start',
- 'on_xend_stop',
- # read-only
- 'domid',
- 'start_time',
- 'cpu_time',
- 'online_vcpus',
- # write-once
- 'cpu',
- 'cpus',
-]
-
-LEGACY_CFG_TYPES = {
- 'uuid': str,
- 'name': str,
- 'vcpus': int,
- 'vcpu_avail': long,
- 'memory': int,
- 'shadow_memory': int,
- 'maxmem': int,
- 'start_time': float,
- 'cpu_time': float,
- 'features': str,
- 'localtime': int,
- 'on_poweroff': str,
- 'on_reboot': str,
- 'on_crash': str,
- 'on_xend_stop': str,
- 'on_xend_start': str,
- 'online_vcpus': int,
- 'rtc/timeoffset': str,
- 'bootloader': str,
- 'bootloader_args': str,
- 'description': str,
- 'pool_name': str,
-}
-
-# Values that should be stored in xenstore's /vm/<uuid> that is used
-# by Xend. Used in XendDomainInfo to restore running VM state from
-# xenstore.
-LEGACY_XENSTORE_VM_PARAMS = [
- 'uuid',
- 'name',
- 'vcpus',
- 'vcpu_avail',
- 'memory',
- 'shadow_memory',
- 'maxmem',
- 'start_time',
- 'on_poweroff',
- 'on_crash',
- 'on_reboot',
- 'on_xend_start',
- 'on_xend_stop',
- 'bootloader',
- 'bootloader_args',
- 'pool_name',
-]
-
-##
-## Config Choices
-##
-
-CONFIG_RESTART_MODES = ('restart', 'destroy', 'preserve', 'rename-restart',
- 'coredump-destroy', 'coredump-restart')
-CONFIG_OLD_DOM_STATES = ('running', 'blocked', 'paused', 'shutdown',
- 'crashed', 'dying')
-
-class XendConfigError(VmError):
- def __str__(self):
- return 'Invalid Configuration: %s' % str(self.value)
-
-##
-## XendConfig Class (an extended dictionary)
-##
-
-class XendConfig(dict):
- """ The new Xend VM Configuration.
-
- Stores the configuration in xenapi compatible format but retains
- import and export functions for SXP.
- """
- def __init__(self, filename = None, sxp_obj = None,
- xapi = None, dominfo = None):
-
- dict.__init__(self)
- self.update(self._defaults())
-
- if filename:
- try:
- sxp_obj = sxp.parse(open(filename,'r'))
- sxp_obj = sxp_obj[0]
- except IOError, e:
- raise XendConfigError("Unable to read file: %s" % filename)
-
- if sxp_obj:
- self._sxp_to_xapi(sxp_obj)
- self._sxp_to_xapi_unsupported(sxp_obj)
- elif xapi:
- self.update_with_xenapi_config(xapi)
- elif dominfo:
- # output from xc.domain_getinfo
- self._dominfo_to_xapi(dominfo, update_mem = True)
-
- self.handle_fileuris()
-
- log.debug('XendConfig.init: %s' % scrub_password(self))
-
- # validators go here
- self.validate()
-
- """ In time, we should enable this type checking addition. It is great
- also for tracking bugs and unintended writes to XendDomainInfo.info
- def __setitem__(self, key, value):
- type_conv = XENAPI_CFG_TYPES.get(key)
- if callable(type_conv):
- try:
- dict.__setitem__(self, key, type_conv(value))
- except (ValueError, TypeError):
- raise XendConfigError("Wrong type for configuration value " +
- "%s. Expected %s" %
- (key, type_conv.__name__))
- else:
- dict.__setitem__(self, key, value)
- """
-
- def _defaults(self):
- defaults = {
- 'name_label': 'Domain-Unnamed',
- 'actions_after_shutdown': 'destroy',
- 'actions_after_reboot': 'restart',
- 'actions_after_crash': 'restart',
- 'actions_after_suspend': '',
- 'is_a_template': False,
- 'auto_power_on': False,
- 'is_control_domain': False,
- 'features': '',
- 'PV_bootloader': '',
- 'PV_kernel': '',
- 'PV_ramdisk': '',
- 'PV_args': '',
- 'PV_bootloader_args': '',
- 'HVM_boot_policy': '',
- 'HVM_boot_params': {},
- 'memory_static_min': 0,
- 'memory_dynamic_min': 0,
- 'shadow_memory': 0,
- 'memory_static_max': 0,
- 'memory_dynamic_max': 0,
- 'memory_sharing': 0,
- 'devices': {},
- 'on_xend_start': 'ignore',
- 'on_xend_stop': 'ignore',
- 'cpus': [],
- 'VCPUs_max': 1,
- 'VCPUs_live': 1,
- 'VCPUs_at_startup': 1,
- 'vcpus_params': {},
- 'console_refs': [],
- 'vif_refs': [],
- 'vbd_refs': [],
- 'other_config': {},
- 'platform': {},
- 'target': 0,
- 'pool_name' : 'Pool-0',
- 'superpages': 0,
- 'description': '',
- }
-
- return defaults
-
- #
- # Here we assume these values exist in the dict.
- # If they don't we have a bigger problem, lets not
- # try and 'fix it up' but acutually fix the cause ;-)
- #
- def _memory_sanity_check(self):
- log.trace("_memory_sanity_check memory_static_min: %s, "
- "memory_static_max: %i, "
- "memory_dynamic_min: %i, "
- "memory_dynamic_max: %i",
- self["memory_static_min"],
- self["memory_static_max"],
- self["memory_dynamic_min"],
- self["memory_dynamic_max"])
-
- if not self["memory_static_min"] <= self["memory_static_max"]:
- raise XendConfigError("memory_static_min must be less " \
- "than or equal to memory_static_max")
- if not self["memory_static_min"] <= self["memory_dynamic_min"]:
- raise XendConfigError("memory_static_min must be less " \
- "than or equal to memory_dynamic_min")
- if not self["memory_dynamic_max"] <= self["memory_static_max"]:
- raise XendConfigError("memory_dynamic_max must be less " \
- "than or equal to memory_static_max")
- if not self["memory_dynamic_max"] > 0:
- raise XendConfigError("memory_dynamic_max must be greater " \
- "than zero")
- if not self["memory_static_max"] > 0:
- raise XendConfigError("memory_static_max must be greater " \
- "than zero")
- if self["memory_sharing"] and not self.is_hvm():
- raise XendConfigError("memory_sharing can only be enabled " \
- "for HVM domains")
- if self["memory_sharing"] and not self.is_hap():
- raise XendConfigError("memory_sharing can only be enabled " \
- "for HAP enabled boxes")
-
- def _actions_sanity_check(self):
- for event in ['shutdown', 'reboot', 'crash']:
- if self['actions_after_' + event] not in CONFIG_RESTART_MODES:
- raise XendConfigError('Invalid event handling mode: ' +
- event)
-
- def _vcpus_sanity_check(self):
- if 'VCPUs_max' in self and 'vcpu_avail' not in self:
- self['vcpu_avail'] = (1 << self['VCPUs_max']) - 1
- if 'online_vcpus' in self:
- self['VCPUs_live'] = self['online_vcpus']
-
- def _uuid_sanity_check(self):
- """Make sure UUID is in proper string format with hyphens."""
- if 'uuid' not in self or not self['uuid']:
- self['uuid'] = uuid.createString()
- else:
- self['uuid'] = uuid.toString(uuid.fromString(self['uuid']))
-
- def _name_sanity_check(self):
- if 'name_label' not in self:
- self['name_label'] = 'Domain-' + self['uuid']
-
- def _platform_sanity_check(self):
- if 'keymap' not in self['platform'] and XendOptions.instance().get_keymap():
- self['platform']['keymap'] = XendOptions.instance().get_keymap()
-
- if self.is_hvm() or self.has_rfb():
- if 'device_model' not in self['platform']:
- self['platform']['device_model'] = auxbin.pathTo("qemu-dm")
- # device_model may be set to 'qemu-dm' or 'stubdom-dm' w/o a path
- if os.path.dirname(self['platform']['device_model']) == "":
- self['platform']['device_model'] = \
- auxbin.pathTo(self['platform']['device_model'])
- # If the device_model is not set the os.path.exists() would raise
- # an exception so we return our error message instead if applicable
- if not self['platform']['device_model']:
- raise VmError("No valid device model specified")
- if not os.path.exists(self['platform']['device_model']):
- raise VmError("device model '%s' not found" % str(self['platform']['device_model']))
-
- if 'tsc_mode' not in self['platform']:
- self['platform']['tsc_mode'] = 0
-
- if 'nomigrate' not in self['platform']:
- self['platform']['nomigrate'] = 0
-
- if self.is_hvm():
- if 'timer_mode' not in self['platform']:
- self['platform']['timer_mode'] = 1
- if 'viridian' not in self['platform']:
- self['platform']['viridian'] = 0
- if 'rtc_timeoffset' not in self['platform']:
- self['platform']['rtc_timeoffset'] = 0
- if 'hpet' not in self['platform']:
- self['platform']['hpet'] = 0
- if 'xen_platform_pci' not in self['platform']:
- self['platform']['xen_platform_pci'] = 1
- if 'vpt_align' not in self['platform']:
- self['platform']['vpt_align'] = 1
- if 'loader' not in self['platform']:
- # Old configs may have hvmloader set as PV_kernel param
- if self.has_key('PV_kernel') and self['PV_kernel'] != '':
- if self['PV_kernel'] == 'hvmloader':
- self['PV_kernel'] = auxbin.pathTo("hvmloader")
- self['platform']['loader'] = self['PV_kernel']
- self['PV_kernel'] = ''
- else:
- self['platform']['loader'] = auxbin.pathTo("hvmloader")
- log.debug("Loader is %s" % str(self['platform']['loader']))
- elif self['platform']['loader'] == 'hvmloader':
- self['platform']['loader'] = auxbin.pathTo("hvmloader")
- if not os.path.exists(self['platform']['loader']):
- raise VmError("kernel '%s' not found" % str(self['platform']['loader']))
-
- # Compatibility hack, can go away soon.
- if 'soundhw' not in self['platform'] and \
- self['platform'].get('enable_audio'):
- self['platform']['soundhw'] = 'sb16'
-
- def _vfb_sanity_check(self):
- if 'keymap' in self['platform']:
- for con in self['console_refs']:
- if self['devices'][con][0] == 'vfb':
- if 'keymap' not in self['devices'][con][1]:
- self['devices'][con][1]['keymap'] = \
- self['platform']['keymap']
-
- def validate(self):
- self._uuid_sanity_check()
- self._name_sanity_check()
- self._memory_sanity_check()
- self._actions_sanity_check()
- self._vcpus_sanity_check()
- self._platform_sanity_check()
- self._vfb_sanity_check()
-
- def _dominfo_to_xapi(self, dominfo, update_mem = False):
- self['domid'] = dominfo['domid']
- self['online_vcpus'] = dominfo['online_vcpus']
- self['VCPUs_max'] = dominfo['max_vcpu_id'] + 1
-
- if update_mem:
- self['memory_dynamic_min'] = dominfo['mem_kb'] * 1024
- self['memory_dynamic_max'] = dominfo['mem_kb'] * 1024
- self['memory_static_min'] = 0
- self['memory_static_max'] = dominfo['maxmem_kb'] * 1024
- self._memory_sanity_check()
-
- self['cpu_time'] = dominfo['cpu_time']/1e9
- if dominfo.get('ssidref'):
- ssidref = int(dominfo.get('ssidref'))
- import xen.util.xsm.xsm as security
- self['security_label'] = security.ssidref2security_label(ssidref)
-
- self['shutdown_reason'] = dominfo['shutdown_reason']
-
- # parse state into Xen API states
- self['running'] = dominfo['running']
- self['crashed'] = dominfo['crashed']
- self['dying'] = dominfo['dying']
- self['shutdown'] = dominfo['shutdown']
- self['paused'] = dominfo['paused']
- self['blocked'] = dominfo['blocked']
-
- if 'name' in dominfo:
- self['name_label'] = dominfo['name']
-
- if 'handle' in dominfo:
- self['uuid'] = uuid.toString(dominfo['handle'])
-
- def _convert_cpus_to_list(self, s):
- # Convert the following string to list of ints.
- # The string supports a list of ranges (0-3),
- # seperated by commas, and negation (^1).
- # Precedence is settled by order of the string:
- # "0-3,^1" -> [0,2,3]
- # "0-3,^1,1" -> [0,1,2,3]
- l = []
- if s == "":
- return l
- for c in s.split(','):
- if c.find('-') != -1:
- (x, y) = c.split('-')
- for i in range(int(x), int(y)+1):
- l.append(int(i))
- else:
- # remove this element from the list
- if c[0] == '^':
- l = [x for x in l if x != int(c[1:])]
- else:
- l.append(int(c))
- return l
-
- def parse_cpuid(self, cfg, field):
- def int2bin(n, count=32):
- return "".join([str((n >> y) & 1) for y in range(count-1, -1, -1)])
-
- for input, regs in cfg[field].iteritems():
- if not regs is dict:
- cfg[field][input] = dict(regs)
-
- cpuid = {}
- for input in cfg[field]:
- inputs = input.split(',')
- if inputs[0][0:2] == '0x':
- inputs[0] = str(int(inputs[0], 16))
- if len(inputs) == 2:
- if inputs[1][0:2] == '0x':
- inputs[1] = str(int(inputs[1], 16))
- new_input = ','.join(inputs)
- cpuid[new_input] = {} # new input
- for reg in cfg[field][input]:
- val = cfg[field][input][reg]
- if val[0:2] == '0x':
- cpuid[new_input][reg] = int2bin(int(val, 16))
- else:
- cpuid[new_input][reg] = val
- cfg[field] = cpuid
-
- def _parse_sxp(self, sxp_cfg):
- """ Populate this XendConfig using the parsed SXP.
-
- @param sxp_cfg: Parsed SXP Configuration
- @type sxp_cfg: list of lists
- @rtype: dictionary
- @return: A dictionary containing the parsed options of the SXP.
- """
- cfg = {}
-
- for key, typ in XENAPI_CFG_TYPES.items():
- val = sxp.child_value(sxp_cfg, key)
- if val is not None:
- try:
- cfg[key] = typ(val)
- except (ValueError, TypeError), e:
- log.warn('Unable to convert type value for key: %s' % key)
-
- # Convert deprecated options to current equivalents.
-
- restart = sxp.child_value(sxp_cfg, 'restart')
- if restart:
- if restart == 'onreboot':
- cfg['on_poweroff'] = 'destroy'
- cfg['on_reboot'] = 'restart'
- cfg['on_crash'] = 'destroy'
- elif restart == 'always':
- for opt in ('on_poweroff', 'on_reboot', 'on_crash'):
- cfg[opt] = 'restart'
- elif restart == 'never':
- for opt in ('on_poweroff', 'on_reboot', 'on_crash'):
- cfg[opt] = 'never'
- else:
- log.warn('Ignoring unrecognised value for deprecated option:'
- 'restart = \'%s\'', restart)
-
- # Handle memory, passed in as MiB
-
- if sxp.child_value(sxp_cfg, "memory") != None:
- cfg["memory"] = int(sxp.child_value(sxp_cfg, "memory"))
- if sxp.child_value(sxp_cfg, "maxmem") != None:
- cfg["maxmem"] = int(sxp.child_value(sxp_cfg, "maxmem"))
-
- # Convert scheduling parameters to vcpus_params
- if 'vcpus_params' not in cfg:
- cfg['vcpus_params'] = {}
- if not cfg["vcpus_params"].has_key("weight"):
- cfg["vcpus_params"]["weight"] = \
- int(sxp.child_value(sxp_cfg, "cpu_weight", 256))
- else:
- cfg["vcpus_params"]["weight"] = int(cfg["vcpus_params"]["weight"])
-
- if not cfg["vcpus_params"].has_key("cap"):
- cfg["vcpus_params"]["cap"] = \
- int(sxp.child_value(sxp_cfg, "cpu_cap", 0))
- else:
- cfg["vcpus_params"]["cap"] = int(cfg["vcpus_params"]["cap"])
-
- # Only extract options we know about.
- extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG + \
- XENAPI_CFG_TO_LEGACY_CFG.values()
-
- for key in extract_keys:
- val = sxp.child_value(sxp_cfg, key)
- if val != None:
- try:
- cfg[key] = LEGACY_CFG_TYPES[key](val)
- except KeyError:
- cfg[key] = val
- except (TypeError, ValueError), e:
- log.warn("Unable to parse key %s: %s: %s" %
- (key, str(val), e))
-
- if 'platform' not in cfg:
- cfg['platform'] = {}
- localtime = sxp.child_value(sxp_cfg, 'localtime')
- if localtime is not None:
- cfg['platform']['localtime'] = localtime
-
- # Compatibility hack -- can go soon.
- for key in XENAPI_PLATFORM_CFG_TYPES.keys():
- val = sxp.child_value(sxp_cfg, "platform_" + key, None)
- if val is not None:
- self['platform'][key] = val
-
- # Compatibility hack -- can go soon.
- boot_order = sxp.child_value(sxp_cfg, 'HVM_boot')
- if boot_order:
- cfg['HVM_boot_policy'] = 'BIOS order'
- cfg['HVM_boot_params'] = { 'order' : boot_order }
-
-
- # Parsing the device SXP's.
- cfg['devices'] = {}
- for dev in sxp.children(sxp_cfg, 'device'):
- config = sxp.child0(dev)
- dev_type = sxp.name(config)
- self.device_add(dev_type, cfg_sxp = config, target = cfg)
-
- # Extract missing data from configuration entries
- image_sxp = sxp.child_value(sxp_cfg, 'image', [])
- if image_sxp:
- image_vcpus = sxp.child_value(image_sxp, 'vcpus')
- if image_vcpus != None:
- try:
- if 'VCPUs_max' not in cfg:
- cfg['VCPUs_max'] = int(image_vcpus)
- elif cfg['VCPUs_max'] != int(image_vcpus):
- cfg['VCPUs_max'] = int(image_vcpus)
- log.warn('Overriding vcpus from %d to %d using image'
- 'vcpus value.', cfg['VCPUs_max'])
- except ValueError, e:
- raise XendConfigError('integer expeceted: %s: %s' %
- image_sxp, e)
-
- # Deprecated cpu configuration
- if 'cpu' in cfg:
- if 'cpus' in cfg:
- cfg['cpus'] = "%s,%s" % (str(cfg['cpu']), cfg['cpus'])
- else:
- cfg['cpus'] = str(cfg['cpu'])
-
- # Convert 'cpus' to list of list of ints
- cpus_list = []
- if 'cpus' in cfg:
- if type(cfg['cpus']) == list:
- if len(cfg['cpus']) > 0 and type(cfg['cpus'][0]) == list:
- # If sxp_cfg was created from config.sxp,
- # the form of 'cpus' is list of list of string.
- # Convert 'cpus' to list of list of ints.
- # Conversion examples:
- # [['1']] -> [[1]]
- # [['0','2'],['1','3']] -> [[0,2],[1,3]]
- try:
- for c1 in cfg['cpus']:
- cpus = []
- for c2 in c1:
- cpus.append(int(c2))
- cpus_list.append(cpus)
- except ValueError, e:
- raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e))
- else:
- # Conversion examples:
- # ["1"] -> [[1]]
- # ["0,2","1,3"] -> [[0,2],[1,3]]
- # ["0-3,^1","1-4,^2"] -> [[0,2,3],[1,3,4]]
- try:
- for c in cfg['cpus']:
- cpus = self._convert_cpus_to_list(c)
- cpus_list.append(cpus)
- except ValueError, e:
- raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e))
-
- if len(cpus_list) != cfg['vcpus']:
- raise XendConfigError('vcpus and the item number of cpus are not same')
- else:
- # Conversion examples:
- # vcpus=1:
- # "1" -> [[1]]
- # "0-3,^1" -> [[0,2,3]]
- # vcpus=2:
- # "1" -> [[1],[1]]
- # "0-3,^1" -> [[0,2,3],[0,2,3]]
- try:
- cpus = self._convert_cpus_to_list(cfg['cpus'])
- for v in range(0, cfg['vcpus']):
- cpus_list.append(cpus)
- except ValueError, e:
- raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e))
- else:
- # Generation examples:
- # vcpus=1:
- # -> [[]]
- # vcpus=2:
- # -> [[],[]]
- for v in range(0, cfg['vcpus']):
- cpus_list.append(list())
-
- cfg['cpus'] = cpus_list
-
- # Parse cpuid
- if 'cpuid' in cfg:
- self.parse_cpuid(cfg, 'cpuid')
- if 'cpuid_check' in cfg:
- self.parse_cpuid(cfg, 'cpuid_check')
-
- import xen.util.xsm.xsm as security
- if security.on() == xsconstants.XS_POLICY_USE:
- from xen.util.acmpolicy import ACM_LABEL_UNLABELED
- if not 'security' in cfg and sxp.child_value(sxp_cfg, 'security'):
- cfg['security'] = sxp.child_value(sxp_cfg, 'security')
- elif not cfg.get('security_label'):
- cfg['security'] = [['access_control',
- ['policy', security.get_active_policy_name() ],
- ['label', ACM_LABEL_UNLABELED ]]]
-
- if 'security' in cfg and not cfg.get('security_label'):
- secinfo = cfg['security']
- # The xm command sends a list formatted like this:
- # [['access_control', ['policy', 'xm-test'],['label', 'red']],
- # ['ssidref', 196611]]
- policy = ""
- label = ""
- for idx in range(0, len(secinfo)):
- if secinfo[idx][0] == "access_control":
- for aidx in range(1, len(secinfo[idx])):
- if secinfo[idx][aidx][0] == "policy":
- policy = secinfo[idx][aidx][1]
- if secinfo[idx][aidx][0] == "label":
- label = secinfo[idx][aidx][1]
- cfg['security_label'] = \
- security.set_security_label(policy, label)
- if not sxp.child_value(sxp_cfg, 'security_label'):
- del cfg['security']
-
- old_state = sxp.child_value(sxp_cfg, 'state')
- if old_state:
- for i in range(len(CONFIG_OLD_DOM_STATES)):
- cfg[CONFIG_OLD_DOM_STATES[i]] = int(old_state[i] != '-')
-
- return cfg
-
-
- def _sxp_to_xapi(self, sxp_cfg):
- """Read in an SXP Configuration object and
- populate at much of the Xen API with valid values.
- """
- log.debug('_sxp_to_xapi(%s)' % scrub_password(sxp_cfg))
-
- # _parse_sxp() below will call device_add() and construct devices.
- # Some devices may require VM's uuid, so setup self['uuid']
- # beforehand.
- self['uuid'] = sxp.child_value(sxp_cfg, 'uuid', uuid.createString())
-
- cfg = self._parse_sxp(sxp_cfg)
-
- for key, typ in XENAPI_CFG_TYPES.items():
- val = cfg.get(key)
- if val is not None:
- self[key] = typ(val)
-
- # Convert parameters that can be directly mapped from
- # the Legacy Config to Xen API Config
-
- for apikey, cfgkey in XENAPI_CFG_TO_LEGACY_CFG.items():
- try:
- type_conv = XENAPI_CFG_TYPES.get(apikey)
- if callable(type_conv):
- self[apikey] = type_conv(cfg[cfgkey])
- else:
- log.warn("Unconverted key: " + apikey)
- self[apikey] = cfg[cfgkey]
- except KeyError:
- pass
-
- # Lets try and handle memory correctly
-
- MiB = 1024 * 1024
-
- if "memory" in cfg:
- self["memory_static_min"] = 0
- self["memory_static_max"] = int(cfg["memory"]) * MiB
- self["memory_dynamic_min"] = int(cfg["memory"]) * MiB
- self["memory_dynamic_max"] = int(cfg["memory"]) * MiB
-
- if "maxmem" in cfg:
- self["memory_static_max"] = int(cfg["maxmem"]) * MiB
-
- self._memory_sanity_check()
-
- def update_with(n, o):
- if not self.get(n):
- self[n] = cfg.get(o, '')
-
- update_with('PV_bootloader', 'bootloader')
- update_with('PV_bootloader_args', 'bootloader_args')
- update_with('Description', 'description')
-
- image_sxp = sxp.child_value(sxp_cfg, 'image', [])
- if image_sxp:
- self.update_with_image_sxp(image_sxp)
-
- # Convert Legacy HVM parameters to Xen API configuration
- for key in XENAPI_PLATFORM_CFG_TYPES.keys():
- if key in cfg:
- self['platform'][key] = cfg[key]
-
- # set device references in the configuration
- self['devices'] = cfg.get('devices', {})
- self['console_refs'] = cfg.get('console_refs', [])
- self['vif_refs'] = cfg.get('vif_refs', [])
- self['vbd_refs'] = cfg.get('vbd_refs', [])
-
- # coalesce hvm vnc frame buffer with vfb config
- if self.is_hvm() and int(self['platform'].get('vnc', 0)) != 0:
- # add vfb device if it isn't there already
- if not self.has_rfb():
- dev_config = ['vfb']
- dev_config.append(['vnc', '1'])
- # copy VNC related params from platform config to vfb dev conf
- for key in ['vncpasswd', 'vncunused', 'vncdisplay',
- 'vnclisten', 'keymap']:
- if key in self['platform']:
- dev_config.append([key, self['platform'][key]])
-
- self.device_add('vfb', cfg_sxp = dev_config)
-
-
- def has_rfb(self):
- for console_uuid in self['console_refs']:
- if self['devices'][console_uuid][1].get('protocol') == 'rfb':
- return True
- if self['devices'][console_uuid][0] == 'vfb':
- return True
- return False
-
- def _sxp_to_xapi_unsupported(self, sxp_cfg):
- """Read in an SXP configuration object and populate
- values are that not related directly supported in
- the Xen API.
- """
-
- log.debug('_sxp_to_xapi_unsupported(%s)' % scrub_password(sxp_cfg))
-
- # Parse and convert parameters used to configure
- # the image (as well as HVM images)
- image_sxp = sxp.child_value(sxp_cfg, 'image', [])
- if image_sxp:
- image_type = sxp.name(image_sxp)
- if image_type != 'hvm' and image_type != 'linux':
- self['platform']['image_type'] = image_type
-
- for key in XENAPI_PLATFORM_CFG_TYPES.keys():
- val = sxp.child_value(image_sxp, key, None)
- if val is not None and val != '':
- self['platform'][key] = val
-
- notes = sxp.children(image_sxp, 'notes')
- if notes:
- self['notes'] = self.notes_from_sxp(notes[0])
-
- self._hvm_boot_params_from_sxp(image_sxp)
-
- # extract backend value
-
- backend = []
- for c in sxp.children(sxp_cfg, 'backend'):
- backend.append(sxp.name(sxp.child0(c)))
- if backend:
- self['backend'] = backend
-
- # Parse and convert other Non Xen API parameters.
- def _set_cfg_if_exists(sxp_arg):
- val = sxp.child_value(sxp_cfg, sxp_arg)
- if val != None:
- if LEGACY_CFG_TYPES.get(sxp_arg):
- self[sxp_arg] = LEGACY_CFG_TYPES[sxp_arg](val)
- else:
- self[sxp_arg] = val
-
- _set_cfg_if_exists('shadow_memory')
- _set_cfg_if_exists('features')
- _set_cfg_if_exists('on_xend_stop')
- _set_cfg_if_exists('on_xend_start')
- _set_cfg_if_exists('vcpu_avail')
- _set_cfg_if_exists('change_home_server')
- _set_cfg_if_exists('description')
-
- # Parse and store runtime configuration
- _set_cfg_if_exists('start_time')
- _set_cfg_if_exists('cpu_time')
- _set_cfg_if_exists('shutdown_reason')
- _set_cfg_if_exists('up_time')
- _set_cfg_if_exists('status') # TODO, deprecated
-
- def _get_old_state_string(self):
- """Returns the old xm state string.
- @rtype: string
- @return: old state string
- """
- state_string = ''
- for state_name in CONFIG_OLD_DOM_STATES:
- on_off = self.get(state_name, 0)
- if on_off:
- state_string += state_name[0]
- else:
- state_string += '-'
-
- return state_string
-
-
- def update_config(self, dominfo):
- """Update configuration with the output from xc.domain_getinfo().
-
- @param dominfo: Domain information via xc.domain_getinfo()
- @type dominfo: dict
- """
- self._dominfo_to_xapi(dominfo)
- self.validate()
-
- def update_with_xenapi_config(self, xapi):
- """Update configuration with a Xen API VM struct
-
- @param xapi: Xen API VM Struct
- @type xapi: dict
- """
-
- log.debug('update_with_xenapi_config: %s' % scrub_password(xapi))
-
- for key, val in xapi.items():
- type_conv = XENAPI_CFG_TYPES.get(key)
- if type_conv is None:
- key = key.lower()
- type_conv = XENAPI_CFG_TYPES.get(key)
- if callable(type_conv):
- self[key] = type_conv(val)
- else:
- self[key] = val
-
- # XenAPI defines platform as a string-string map. If platform
- # configuration exists, convert values to appropriate type.
- if 'platform' in xapi:
- for key, val in xapi['platform'].items():
- type_conv = XENAPI_PLATFORM_CFG_TYPES.get(key)
- if type_conv is None:
- key = key.lower()
- type_conv = XENAPI_PLATFORM_CFG_TYPES.get(key)
- if callable(type_conv):
- self['platform'][key] = type_conv(val)
- else:
- self['platform'][key] = val
-
- self['vcpus_params']['weight'] = \
- int(self['vcpus_params'].get('weight', 256))
- self['vcpus_params']['cap'] = \
- int(self['vcpus_params'].get('cap', 0))
-
- for key, val in self['vcpus_params'].items():
- if key.startswith('cpumap'):
- self['vcpus_params'][key] = \
- ','.join(map(str, self._convert_cpus_to_list(val)))
-
- def cpuid_to_sxp(self, sxpr, field):
- regs_list = []
- for input, regs in self[field].iteritems():
- reg_list = []
- for reg, val in regs.iteritems():
- reg_list.append([reg, val])
- regs_list.append([input, reg_list])
- sxpr.append([field, regs_list])
-
-
- def to_sxp(self, domain = None, ignore_devices = False, ignore = [],
- legacy_only = True):
- """ Get SXP representation of this config object.
-
- Incompat: removed store_mfn, console_mfn
-
- @keyword domain: (optional) XendDomainInfo to get extra information
- from such as domid and running devices.
- @type domain: XendDomainInfo
- @keyword ignore: (optional) list of 'keys' that we do not want
- to export.
- @type ignore: list of strings
- @rtype: list of list (SXP representation)
- """
- sxpr = ['domain']
-
- # TODO: domid/dom is the same thing but called differently
- # depending if it is from xenstore or sxpr.
-
- if domain.getDomid() is not None:
- sxpr.append(['domid', domain.getDomid()])
-
- if legacy_only:
- sxpr.append(['cpu_weight', int(self['vcpus_params'].get('weight', 256))])
- sxpr.append(['cpu_cap', int(self['vcpus_params'].get('cap', 0))])
- else:
- for name, typ in XENAPI_CFG_TYPES.items():
- if name in self and self[name] not in (None, []):
- # Skip cpuid and cpuid_check. Custom conversion
- # methods for these are called below.
- if name in ("cpuid", "cpuid_check"):
- continue
- if typ == dict:
- s = self[name].items()
- elif typ == list:
- s = self[name]
- else:
- s = str(self[name])
- sxpr.append([name, s])
-
- for xenapi, legacy in XENAPI_CFG_TO_LEGACY_CFG.items():
- if self.has_key(xenapi) and self[xenapi] not in (None, []):
- if type(self[xenapi]) == bool:
- # convert booleans to ints before making an sxp item
- sxpr.append([legacy, int(self[xenapi])])
- else:
- sxpr.append([legacy, self[xenapi]])
-
- MiB = 1024*1024
-
- sxpr.append(["maxmem", int(self["memory_static_max"])/MiB])
- sxpr.append(["memory", int(self["memory_dynamic_max"])/MiB])
-
- for legacy in LEGACY_UNSUPPORTED_BY_XENAPI_CFG:
- if legacy in ('domid', 'uuid', 'cpus'): # skip these
- continue
- if self.has_key(legacy) and self[legacy] not in (None, []):
- sxpr.append([legacy, self[legacy]])
-
- if self.has_key('security_label'):
- sxpr.append(['security_label', self['security_label']])
-
- sxpr.append(['image', self.image_sxpr()])
- sxpr.append(['status', domain._stateGet()])
-
- if domain.getDomid() is not None:
- sxpr.append(['state', self._get_old_state_string()])
-
- if domain:
- if domain.store_mfn:
- sxpr.append(['store_mfn', domain.store_mfn])
- if domain.console_mfn:
- sxpr.append(['console_mfn', domain.console_mfn])
-
-
- # Marshall devices (running or from configuration)
- if not ignore_devices:
- txn = xstransact()
- try:
- for cls in XendDevices.valid_devices():
- found = False
-
- # figure if there is a dev controller is valid and running
- if domain and domain.getDomid() != None:
- try:
- controller = domain.getDeviceController(cls)
- configs = controller.configurations(txn)
- for config in configs:
- if sxp.name(config) in ('vbd', 'tap', 'tap2'):
- dev_uuid = sxp.child_value(config, 'uuid')
- dev_type, dev_cfg = self['devices'][dev_uuid]
- if sxp.child_value(config, 'bootable', None) is None:
- is_bootable = dev_cfg.get('bootable', 0)
- config.append(['bootable', int(is_bootable)])
- config.append(['VDI', dev_cfg.get('VDI', '')])
-
- sxpr.append(['device', config])
- found = True
-
- except:
- log.exception("dumping sxp from device controllers")
- pass
-
- # if we didn't find that device, check the existing config
- # for a device in the same class
- if not found:
- for dev_type, dev_info in self.all_devices_sxpr():
- if dev_type == cls:
- sxpr.append(['device', dev_info])
-
- txn.commit()
- except:
- txn.abort()
- raise
-
- if 'cpuid' in self:
- self.cpuid_to_sxp(sxpr, 'cpuid')
- if 'cpuid_check' in self:
- self.cpuid_to_sxp(sxpr, 'cpuid_check')
-
- if self.has_key('change_home_server'):
- sxpr.append(['change_home_server', self['change_home_server']])
-
- log.debug(sxpr)
-
- return sxpr
-
- def _blkdev_name_to_number(self, dev):
- if 'ioemu:' in dev:
- _, dev = dev.split(':', 1)
- try:
- dev, _ = dev.split(':', 1)
- except ValueError:
- pass
-
- try:
- devid = int(dev)
- except ValueError:
- # devid is not a number but a string containing either device
- # name (e.g. xvda) or device_type/device_id (e.g. vbd/51728)
- dev2 = type(dev) is str and dev.split('/')[-1] or None
- if dev2 == None:
- log.debug("Could not check the device %s", dev)
- return None
- try:
- devid = int(dev2)
- except ValueError:
- (xenbus, devid) = blkdev_name_to_number(dev2)
- if devid == None:
- log.debug("The device %s is not device name", dev2)
- return None
- return devid
-
- def device_duplicate_check(self, dev_type, dev_info, defined_config, config):
- defined_devices_sxpr = self.all_devices_sxpr(target = defined_config)
-
- if dev_type == 'vbd' or dev_type == 'tap' or dev_type == 'tap2':
- dev_uname = dev_info.get('uname')
- blkdev_name = dev_info.get('dev')
- devid = self._blkdev_name_to_number(blkdev_name)
- if devid == None or dev_uname == None:
- return
-
- for o_dev_type, o_dev_info in defined_devices_sxpr:
- if o_dev_type == 'vbd' or o_dev_type == 'tap' or o_dev_type == 'tap2':
- blkdev_file = blkdev_uname_to_file(dev_uname)
- o_dev_uname = sxp.child_value(o_dev_info, 'uname')
- if o_dev_uname and o_dev_uname != None:
- o_blkdev_file = blkdev_uname_to_file(o_dev_uname)
- if blkdev_file == o_blkdev_file:
- raise XendConfigError('The file "%s" is already used' %
- blkdev_file)
- if dev_uname and dev_uname == o_dev_uname:
- raise XendConfigError('The uname "%s" is already defined' %
- dev_uname)
- o_blkdev_name = sxp.child_value(o_dev_info, 'dev')
- o_devid = self._blkdev_name_to_number(o_blkdev_name)
- if o_devid != None and devid == o_devid:
- name_array = blkdev_name.split(':', 2)
- if len(name_array) == 2 and name_array[1] == 'cdrom':
- #
- # Since the device is a cdrom, we are most likely
- # inserting, changing, or removing a cd. We can
- # update the old device instead of creating a new
- # one.
- #
- if o_dev_uname != None and dev_uname == None:
- #
- # We are removing a cd. We can simply update
- # the uname on the existing device.
- #
- merge_sxp = sxp.from_string("('vbd' ('uname' ''))")
- else:
- merge_sxp = config
-
- dev_uuid = sxp.child_value(o_dev_info, 'uuid')
- if dev_uuid != None and \
- self.device_update(dev_uuid, cfg_sxp = merge_sxp):
- return dev_uuid
-
- raise XendConfigError('The device "%s" is already defined' %
- blkdev_name)
-
- elif dev_type == 'vif':
- dev_mac = dev_info.get('mac')
-
- for o_dev_type, o_dev_info in defined_devices_sxpr:
- if dev_type == o_dev_type:
- if dev_mac.lower() == sxp.child_value(o_dev_info, 'mac').lower():
- raise XendConfigError('The mac "%s" is already defined' %
- dev_mac)
- return None
-
- def create_dpci_from_sxp(self, pci_devs):
- for pci_dev in pci_devs:
- dpci_uuid = pci_dev.get('uuid')
- log.debug("create_dpci_from_sxp: %s" % pci_dev)
- ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'],
- pci_dev['bus'],
- pci_dev['slot'],
- pci_dev['func'])
- if ppci_uuid is None:
- continue
- dpci_record = {
- 'VM': self['uuid'],
- 'PPCI': ppci_uuid,
- 'hotplug_slot': pci_dev.get('vdevfn', '0x%02x' % AUTO_PHP_SLOT),
- 'key': pci_dev['key']
- }
-
- dpci_opts = pci_dev.get('opts')
- if dpci_opts and len(dpci_opts) > 0:
- dpci_record['options'] = dpci_opts
-
- XendDPCI(dpci_uuid, dpci_record)
-
- def device_add(self, dev_type, cfg_sxp = None, cfg_xenapi = None,
- target = None):
- """Add a device configuration in SXP format or XenAPI struct format.
-
- For SXP, it could be either:
-
- [device, [vbd, [uname ...]]
-
- or:
-
- [vbd, [uname ..]]
-
- @type cfg_sxp: list of lists (parsed sxp object)
- @param cfg_sxp: SXP configuration object
- @type cfg_xenapi: dict
- @param cfg_xenapi: A device configuration from Xen API (eg. vbd,vif)
- @param target: write device information to
- @type target: None or a dictionary
- @rtype: string
- @return: Assigned UUID of the device.
- """
- if target == None:
- target = self
-
- if dev_type not in XendDevices.valid_devices():
- raise XendConfigError("XendConfig: %s not a valid device type" %
- dev_type)
-
- if cfg_sxp == None and cfg_xenapi == None:
- raise XendConfigError("XendConfig: device_add requires some "
- "config.")
-
- #if cfg_sxp:
- # log.debug("XendConfig.device_add: %s" % str(cfg_sxp))
- #if cfg_xenapi:
- # log.debug("XendConfig.device_add: %s" % str(cfg_xenapi))
-
- if cfg_sxp:
- if sxp.child0(cfg_sxp) == 'device':
- config = sxp.child0(cfg_sxp)
- else:
- config = cfg_sxp
-
- dev_type = sxp.name(config)
- dev_info = {}
-
- if dev_type == 'pci':
- pci_devs_uuid = sxp.child_value(config, 'uuid',
- uuid.createString())
-
- pci_dict = pci_convert_sxp_to_dict(config)
- pci_devs = pci_dict['devs']
-
- # create XenAPI DPCI objects.
- self.create_dpci_from_sxp(pci_devs)
-
- target['devices'][pci_devs_uuid] = (dev_type,
- {'devs': pci_devs,
- 'uuid': pci_devs_uuid})
-
- log.debug("XendConfig: reading device: %s" % pci_devs)
-
- return pci_devs_uuid
-
- if dev_type == 'vscsi':
- vscsi_devs_uuid = sxp.child_value(config, 'uuid',
- uuid.createString())
- vscsi_dict = self.vscsi_convert_sxp_to_dict(config)
- vscsi_devs = vscsi_dict['devs']
- vscsi_mode = vscsi_dict['feature-host']
- vscsi_be = vscsi_dict.get('backend', None)
-
- # create XenAPI DSCSI_HBA objects.
- dscsi_HBA_record = {
- 'VM': self['uuid'],
- 'virtual_host': int(vscsi_devs[0]['v-dev'].split(':')[0]),
- 'assignment_mode': vscsi_mode and 'HOST' or 'LUN'
- }
- XendDSCSI_HBA(vscsi_devs_uuid, dscsi_HBA_record)
-
- # create XenAPI DSCSI objects.
- for vscsi_dev in vscsi_devs:
- dscsi_uuid = vscsi_dev.get('uuid')
- pscsi_uuid = XendPSCSI.get_by_HCTL(vscsi_dev['p-dev'])
- if pscsi_uuid is None:
- continue
- dscsi_record = {
- 'VM': self['uuid'],
- 'PSCSI': pscsi_uuid,
- 'HBA': vscsi_devs_uuid,
- 'virtual_HCTL': vscsi_dev.get('v-dev')
- }
- XendDSCSI(dscsi_uuid, dscsi_record)
-
- vscsi_info = {
- 'devs': vscsi_devs,
- 'feature-host': vscsi_mode,
- 'uuid': vscsi_devs_uuid
- }
- if vscsi_be is not None:
- vscsi_info['backend'] = vscsi_be
- target['devices'][vscsi_devs_uuid] = (dev_type, vscsi_info)
- log.debug("XendConfig: reading device: %s,%s" % \
- (vscsi_devs, vscsi_mode))
- return vscsi_devs_uuid
-
- if dev_type == 'vusb':
- vusb_devs_uuid = sxp.child_value(config, 'uuid',
- uuid.createString())
- vusb_dict = self.vusb_convert_sxp_to_dict(config)
- vusb_dict['uuid'] = vusb_devs_uuid
- target['devices'][vusb_devs_uuid] = (dev_type, vusb_dict)
- return vusb_devs_uuid
-
- for opt_val in config[1:]:
- try:
- opt, val = opt_val
- dev_info[opt] = val
- except (TypeError, ValueError): # unpack error
- pass
-
- if dev_type == 'vbd':
- if dev_info.get('dev', '').startswith('ioemu:'):
- dev_info['driver'] = 'ioemu'
- else:
- dev_info['driver'] = 'paravirtualised'
-
- if dev_type == 'tap' or dev_type == 'tap2':
- tap_disk_type = dev_info['uname'].split(':')[1]
- # tapdisk uname may be 'tap:<driver>' or 'tap:tapdisk:<driver>'
- if tap_disk_type == 'tapdisk':
- tap_disk_type = dev_info['uname'].split(':')[2]
- if tap_disk_type not in blktap_disk_types:
- raise XendConfigError("tap:%s not a valid disk type" %
- tap_disk_type)
-
- if dev_type == 'vif':
- if not dev_info.get('mac'):
- dev_info['mac'] = randomMAC()
-
- ret_uuid = self.device_duplicate_check(dev_type, dev_info, target, config)
- if ret_uuid != None:
- return ret_uuid
-
- if dev_type == 'vif':
- if dev_info.get('policy') and dev_info.get('label'):
- dev_info['security_label'] = "%s:%s:%s" % \
- (xsconstants.ACM_POLICY_ID,
- dev_info['policy'],dev_info['label'])
-
- # create uuid if it doesn't exist
- dev_uuid = dev_info.get('uuid', None)
- if not dev_uuid:
- dev_uuid = uuid.createString()
- dev_info['uuid'] = dev_uuid
-
- # store dev references by uuid for certain device types
- target['devices'][dev_uuid] = (dev_type, dev_info)
- if dev_type in ('vif', 'vbd'):
- param = '%s_refs' % dev_type
- if param not in target:
- target[param] = []
- if dev_uuid not in target[param]:
- if dev_type == 'vbd':
- if 'bootable' not in dev_info:
- # Compat hack -- mark first disk bootable
- dev_info['bootable'] = int(not target[param])
- else:
- # ensure type of bootable is int (on xend restart
- # it's of type str)
- dev_info['bootable'] = int(dev_info['bootable'])
- target[param].append(dev_uuid)
- elif dev_type == 'tap' or dev_type == 'tap2':
- if 'vbd_refs' not in target:
- target['vbd_refs'] = []
- if dev_uuid not in target['vbd_refs']:
- if 'bootable' not in dev_info:
- # Compat hack -- mark first disk bootable
- dev_info['bootable'] = int(not target['vbd_refs'])
- else:
- # ensure type of bootable is int (on xend restart it's
- # of type str)
- dev_info['bootable'] = int(dev_info['bootable'])
- target['vbd_refs'].append(dev_uuid)
-
- elif dev_type == 'vfb':
- # Populate other config with aux data that is associated
- # with vfb
-
- other_config = {}
- for key in XENAPI_CONSOLE_OTHER_CFG:
- if key in dev_info:
- other_config[key] = dev_info[key]
- target['devices'][dev_uuid][1]['other_config'] = other_config
-
-
- if 'console_refs' not in target:
- target['console_refs'] = []
-
- # Treat VFB devices as console devices so they are found
- # through Xen API
- if dev_uuid not in target['console_refs']:
- target['console_refs'].append(dev_uuid)
-
- # Cope with old-format save files which say under vfb
- # (type vfb) rather than (vfb 1)
- try:
- vfb_type = dev_info['type']
- except KeyError:
- vfb_type = None
- log.debug("iwj dev_type=%s vfb type %s" %
- (dev_type, `vfb_type`))
-
- if vfb_type == 'vnc' or vfb_type == 'sdl':
- dev_info[vfb_type] = 1
- del dev_info['type']
- log.debug("iwj dev_type=%s vfb setting dev_info['%s']" %
- (dev_type, vfb_type))
- # Create serial backends now, the location value is bogus, but does not matter
- i=0
- chardev=0
- if dev_info.get('serial') is not None :
- chardev = chardev + 1
- if dev_info.get('monitor') is not None :
- chardev = chardev + 1
- if chardev > 0 :
- chardev = chardev + 1
- while i < chardev :
- cfg = self.console_add('vt100', str(i))
- c_uuid = uuid.createString()
- target['devices'][c_uuid] = ('console', cfg)
- target['console_refs'].append(c_uuid)
- i = i + 1
- elif dev_type == 'console':
- if 'console_refs' not in target:
- target['console_refs'] = []
- if dev_uuid not in target['console_refs']:
- target['console_refs'].append(dev_uuid)
-
- log.debug("XendConfig: reading device: %s" % scrub_password(dev_info))
- return dev_uuid
-
- if cfg_xenapi:
- dev_info = {}
- dev_uuid = ''
- if dev_type == 'vif':
- dev_info['mac'] = cfg_xenapi.get('MAC')
- if not dev_info['mac']:
- dev_info['mac'] = randomMAC()
- # vifname is the name on the guest, not dom0
- # TODO: we don't have the ability to find that out or
- # change it from dom0
- #if cfg_xenapi.get('device'): # don't add if blank
- # dev_info['vifname'] = cfg_xenapi.get('device')
- if cfg_xenapi.get('type'):
- dev_info['type'] = cfg_xenapi.get('type')
- if cfg_xenapi.get('name'):
- dev_info['name'] = cfg_xenapi.get('name')
- if cfg_xenapi.get('network'):
- network = XendAPIStore.get(
- cfg_xenapi.get('network'), 'network')
- dev_info['bridge'] = network.get_name_label()
-
- if cfg_xenapi.get('security_label'):
- dev_info['security_label'] = \
- cfg_xenapi.get('security_label')
-
- dev_uuid = cfg_xenapi.get('uuid', None)
- if not dev_uuid:
- dev_uuid = uuid.createString()
- dev_info['uuid'] = dev_uuid
- target['devices'][dev_uuid] = (dev_type, dev_info)
- target['vif_refs'].append(dev_uuid)
-
- elif dev_type in ('vbd', 'tap', 'tap2'):
- dev_info['type'] = cfg_xenapi.get('type', 'Disk')
- if dev_info['type'] == 'CD':
- old_vbd_type = 'cdrom'
- else:
- old_vbd_type = 'disk'
-
- dev_info['uname'] = cfg_xenapi.get('image', '')
- dev_info['dev'] = '%s:%s' % (cfg_xenapi.get('device'),
- old_vbd_type)
- dev_info['bootable'] = int(cfg_xenapi.get('bootable', 0))
- dev_info['driver'] = cfg_xenapi.get('driver', '')
- dev_info['VDI'] = cfg_xenapi.get('VDI', '')
-
- if cfg_xenapi.get('mode') == 'RW':
- dev_info['mode'] = 'w'
- else:
- dev_info['mode'] = 'r'
-
- dev_uuid = cfg_xenapi.get('uuid', None)
- if not dev_uuid:
- dev_uuid = uuid.createString()
- dev_info['uuid'] = dev_uuid
- target['devices'][dev_uuid] = (dev_type, dev_info)
- target['vbd_refs'].append(dev_uuid)
-
- elif dev_type == 'console':
- dev_uuid = cfg_xenapi.get('uuid', None)
- if not dev_uuid:
- dev_uuid = uuid.createString()
- dev_info['uuid'] = dev_uuid
- dev_info['protocol'] = cfg_xenapi.get('protocol', 'rfb')
- console_other_config = cfg_xenapi.get('other_config', {})
- dev_info['other_config'] = console_other_config
- if dev_info['protocol'] == 'rfb':
- # collapse other config into devinfo for things
- # such as vncpasswd, vncunused, etc.
- dev_info.update(console_other_config)
- dev_info['vnc'] = console_other_config.get('vnc', '0')
- dev_info['sdl'] = console_other_config.get('sdl', '0')
- target['devices'][dev_uuid] = ('vfb', dev_info)
- target['console_refs'].append(dev_uuid)
-
- # if console is rfb, set device_model ensuring qemu
- # is invoked for pvfb services
- if 'device_model' not in target['platform']:
- target['platform']['device_model'] = \
- auxbin.pathTo("qemu-dm")
-
- # Finally, if we are a pvfb, we need to make a vkbd
- # as well that is not really exposed to Xen API
- vkbd_uuid = uuid.createString()
- target['devices'][vkbd_uuid] = ('vkbd', {})
-
- elif dev_info['protocol'] == 'vt100':
- # if someone tries to create a VT100 console
- # via the Xen API, we'll have to ignore it
- # because we create one automatically in
- # XendDomainInfo._update_consoles
- raise XendConfigError('Creating vt100 consoles via '
- 'Xen API is unsupported')
-
- return dev_uuid
-
- # no valid device to add
- return ''
-
- def phantom_device_add(self, dev_type, cfg_xenapi = None,
- target = None):
- """Add a phantom tap device configuration in XenAPI struct format.
- """
-
- if target == None:
- target = self
-
- if dev_type not in XendDevices.valid_devices() and \
- dev_type not in XendDevices.pseudo_devices():
- raise XendConfigError("XendConfig: %s not a valid device type" %
- dev_type)
-
- if cfg_xenapi == None:
- raise XendConfigError("XendConfig: device_add requires some "
- "config.")
-
- if cfg_xenapi:
- log.debug("XendConfig.phantom_device_add: %s" % str(cfg_xenapi))
-
- if cfg_xenapi:
- dev_info = {}
- if dev_type in ('vbd', 'tap'):
- if dev_type == 'vbd':
- dev_info['uname'] = cfg_xenapi.get('image', '')
- dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device')
- elif dev_type == 'tap':
- if cfg_xenapi.get('image').find('tap:') == -1:
- dev_info['uname'] = 'tap:qcow:%s' % cfg_xenapi.get('image')
- dev_info['dev'] = '/dev/%s' % cfg_xenapi.get('device')
- dev_info['uname'] = cfg_xenapi.get('image')
- dev_info['mode'] = cfg_xenapi.get('mode')
- dev_info['backend'] = '0'
- dev_uuid = cfg_xenapi.get('uuid', uuid.createString())
- dev_info['uuid'] = dev_uuid
- self['devices'][dev_uuid] = (dev_type, dev_info)
- self['vbd_refs'].append(dev_uuid)
- return dev_uuid
-
- return ''
-
- def vscsi_convert_sxp_to_dict(self, dev_sxp):
- """Convert vscsi device sxp to dict
- @param dev_sxp: device configuration
- @type dev_sxp: SXP object (parsed config)
- @return: dev_config
- @rtype: dictionary
- """
- # Parsing the device SXP's. In most cases, the SXP looks
- # like this:
- #
- # [device, [vif, [mac, xx:xx:xx:xx:xx:xx], [ip 1.3.4.5]]]
- #
- # However, for SCSI devices it looks like this:
- #
- # [device,
- # [vscsi,
- # [feature-host, 0],
- # [backend, 0],
- # [dev,
- # [devid, 0], [p-devname, sdb], [p-dev, 1:0:0:1],
- # [v-dev, 0:0:0:0], [state, 1]
- # ],
- # [dev,
- # [devid, 0], [p-devname, sdc], [p-dev, 1:0:0:2],
- # [v-dev, 0:0:0:1], [satet, 1]
- # ]
- # ],
- # [vscsi,
- # [feature-host, 1],
- # [backend, 0],
- # [dev,
- # [devid, 1], [p-devname, sdg], [p-dev, 2:0:0:0],
- # [v-dev, 1:0:0:0], [state, 1]
- # ],
- # [dev,
- # [devid, 1], [p-devname, sdh], [p-dev, 2:0:0:1],
- # [v-dev, 1:0:0:1], [satet, 1]
- # ]
- # ]
- # ]
- #
- # It seems the reasoning for this difference is because
- # vscsiif.py needs all the SCSI device configurations with
- # same host number at the same time when creating the devices.
-
- # For SCSI device hotplug support, the SXP of SCSI devices is
- # extendend like this:
- #
- # [device,
- # [vscsi,
- # [feature-host, 0],
- # [backend, 0],
- # [dev,
- # [devid, 0], [p-devname, sdd], [p-dev, 1:0:0:3],
- # [v-dev, 0:0:0:2], [state, 1]
- # ]
- # ]
- # ]
- #
- # state xenbusState['Initialising'] indicates that the device is
- # being attached, while state xenbusState['Closing'] indicates
- # that the device is being detached.
- #
- # The Dict looks like this:
- #
- # { devs: [ {devid: 0, p-devname: sdd, p-dev: 1:0:0:3,
- # v-dev: 0:0:0:2, state: 1} ],
- # feature-host: 1 , backend: 0 }
-
- dev_config = {}
-
- vscsi_devs = []
- for vscsi_dev in sxp.children(dev_sxp, 'dev'):
- vscsi_dev_info = {}
- for opt_val in vscsi_dev[1:]:
- try:
- opt, val = opt_val
- vscsi_dev_info[opt] = val
- except TypeError:
- pass
- # append uuid for each vscsi device.
- vscsi_uuid = vscsi_dev_info.get('uuid', uuid.createString())
- vscsi_dev_info['uuid'] = vscsi_uuid
- vscsi_devs.append(vscsi_dev_info)
- dev_config['devs'] = vscsi_devs
-
- vscsi_mode = sxp.children(dev_sxp, 'feature-host')[0]
- dev_config['feature-host'] = vscsi_mode[1]
- try:
- vscsi_be = sxp.children(dev_sxp, 'backend')[0]
- dev_config['backend'] = vscsi_be[1]
- except IndexError:
- pass
-
- return dev_config
-
- def vusb_convert_sxp_to_dict(self, dev_sxp):
- """Convert vusb device sxp to dict
- @param dev_sxp: device configuration
- @type dev_sxp: SXP object (parsed config)
- @return: dev_config
- @rtype: dictionary
- """
- # Parsing USB devices SXP.
- #
- # USB device's SXP looks like this:
- #
- # [device,
- # [vusb,
- # [usb-ver, 2],
- # [num-ports, 8],
- # [port,
- # [1, 1-1],
- # [2, 1-2],
- # [3, ''],
- # [4, ''],
- # [5, ''],
- # [6, ''],
- # [7, 6-2.1],
- # [8, '']
- # ]
- # ],
- # [vusb,
- # [usb-ver, 1],
- # [num-ports, 2],
- # [port,
- # [1, 4-1],
- # [2, 4-2]
- # ]
- # ]
- # ]
- #
- # The dict looks like this
- #
- # { usb-ver: 2,
- # num-ports: 8,
- # port-1: 1-1,
- # port-2: 1-2,
- # port-3: "",
- # port-4: "",
- # port-5: "",
- # port-6: "",
- # port-7: "",
- # port-8: "" }
-
- dev_config = {}
- dev_config['usb-ver'] = sxp.child(dev_sxp, 'usb-ver')[1]
- dev_config['num-ports'] = sxp.child(dev_sxp, 'num-ports')[1]
- ports = sxp.child(dev_sxp, 'port')
- for port in ports[1:]:
- try:
- num, bus = port
- dev_config['port-%i' % int(num)] = str(bus)
- except TypeError:
- pass
-
- return dev_config
-
- def console_add(self, protocol, location, other_config = {}):
- dev_uuid = uuid.createString()
- if protocol == 'vt100':
- dev_info = {
- 'uuid': dev_uuid,
- 'protocol': protocol,
- 'location': location,
- 'other_config': other_config,
- }
-
- if 'devices' not in self:
- self['devices'] = {}
-
- self['devices'][dev_uuid] = ('console', dev_info)
- self['console_refs'].append(dev_uuid)
- return dev_info
-
- return {}
-
- def console_update(self, console_uuid, key, value):
- for dev_uuid, (dev_type, dev_info) in self['devices'].items():
- if dev_uuid == console_uuid:
- dev_info[key] = value
- # collapse other_config into dev_info for things
- # such as vncpasswd, vncunused, etc.
- if key == 'other_config':
- for k in XENAPI_CONSOLE_OTHER_CFG:
- if k in dev_info and k not in value:
- del dev_info[k]
- dev_info.update(value)
- break
-
- def console_get_all(self, protocol):
- if protocol == 'vt100':
- consoles = [dinfo for dtype, dinfo in self['devices'].values()
- if dtype == 'console']
- return [c for c in consoles if c.get('protocol') == protocol]
-
- elif protocol == 'rfb':
- vfbs = [dinfo for dtype, dinfo in self['devices'].values()
- if dtype == 'vfb']
-
- # move all non-console key values to other_config before
- # returning console config
- valid_keys = ['uuid', 'location']
- for vfb in vfbs:
- other_config = {}
- for key, val in vfb.items():
- if key not in valid_keys:
- other_config[key] = vfb[key]
- del vfb[key]
- vfb['other_config'] = other_config
- vfb['protocol'] = 'rfb'
-
- return vfbs
-
- else:
- return []
-
- def device_update(self, dev_uuid, cfg_sxp = [], cfg_xenapi = {}):
- """Update an existing device with the new configuration.
-
- @rtype: boolean
- @return: Returns True if succesfully found and updated a device conf
- """
- if dev_uuid in self['devices'] and cfg_sxp:
- if sxp.child0(cfg_sxp) == 'device':
- config = sxp.child0(cfg_sxp)
- else:
- config = cfg_sxp
-
- dev_type, dev_info = self['devices'][dev_uuid]
-
- if dev_type == 'pci': # Special case for pci
- pci_dict = pci_convert_sxp_to_dict(config)
- pci_devs = pci_dict['devs']
-
- # destroy existing XenAPI DPCI objects
- for dpci_uuid in XendDPCI.get_by_VM(self['uuid']):
- XendAPIStore.deregister(dpci_uuid, "DPCI")
-
- # create XenAPI DPCI objects.
- self.create_dpci_from_sxp(pci_devs)
-
- self['devices'][dev_uuid] = (dev_type,
- {'devs': pci_devs,
- 'uuid': dev_uuid})
- return True
-
- if dev_type == 'vscsi': # Special case for vscsi
- vscsi_dict = self.vscsi_convert_sxp_to_dict(config)
- vscsi_devs = vscsi_dict['devs']
- vscsi_mode = vscsi_dict['feature-host']
- vscsi_be = vscsi_dict.get('backend', None)
-
- # destroy existing XenAPI DSCSI objects
- vscsi_devid = int(dev_info['devs'][0]['devid'])
- for dscsi_uuid in XendDSCSI.get_by_VM(self['uuid']):
- dscsi_inst = XendAPIStore.get(dscsi_uuid, 'DSCSI')
- if vscsi_devid == dscsi_inst.get_virtual_host():
- XendAPIStore.deregister(dscsi_uuid, "DSCSI")
-
- # destroy existing XenAPI DSCSI_HBA objects
- if not vscsi_devs:
- XendAPIStore.deregister(dev_uuid, 'DSCSI_HBA')
-
- # create XenAPI DSCSI objects.
- for vscsi_dev in vscsi_devs:
- dscsi_uuid = vscsi_dev.get('uuid')
- pscsi_uuid = XendPSCSI.get_by_HCTL(vscsi_dev['p-dev'])
- if pscsi_uuid is None:
- continue
- dscsi_record = {
- 'VM': self['uuid'],
- 'PSCSI': pscsi_uuid,
- 'HBA': dev_uuid,
- 'virtual_HCTL': vscsi_dev.get('v-dev')
- }
- XendDSCSI(dscsi_uuid, dscsi_record)
-
- vscsi_info = {
- 'devs': vscsi_devs,
- 'feature-host': vscsi_mode,
- 'uuid': dev_uuid
- }
- if vscsi_be is not None:
- vscsi_info['backend'] = vscsi_be
- self['devices'][dev_uuid] = (dev_type, vscsi_info)
- return True
-
- for opt_val in config[1:]:
- try:
- opt, val = opt_val
- dev_info[opt] = val
- except (TypeError, ValueError):
- pass # no value for this config option
-
- self['devices'][dev_uuid] = (dev_type, dev_info)
- return True
-
- elif dev_uuid in self['devices'] and cfg_xenapi:
- dev_type, dev_info = self['devices'][dev_uuid]
- for key, val in cfg_xenapi.items():
- dev_info[key] = val
- self['devices'][dev_uuid] = (dev_type, dev_info)
- return True
-
- return False
-
-
- def device_sxpr(self, dev_uuid = None, dev_type = None, dev_info = None, target = None):
- """Get Device SXPR by either giving the device UUID or (type, config).
-
- @rtype: list of lists
- @return: device config sxpr
- """
- sxpr = []
-
- if target == None:
- target = self
-
- if dev_uuid != None and dev_uuid in target['devices']:
- dev_type, dev_info = target['devices'][dev_uuid]
-
- if dev_type == None or dev_info == None:
- raise XendConfigError("Required either UUID or device type and "
- "configuration dictionary.")
-
- sxpr.append(dev_type)
- if dev_type in ('console', 'vfb'):
- config = [(opt, val) for opt, val in dev_info.items()
- if opt != 'other_config']
- else:
- config = [(opt, val) for opt, val in dev_info.items()]
-
- sxpr += config
-
- return sxpr
-
- def ordered_device_refs(self, target = None):
- result = []
-
- if target == None:
- target = self
-
- # vkbd devices *must* be before vfb devices, otherwise
- # there is a race condition when setting up devices
- # where the daemon spawned for the vfb may write stuff
- # into xenstore vkbd backend, before DevController has
- # setup permissions on the vkbd backend path. This race
- # results in domain creation failing with 'device already
- # connected' messages
- result.extend([u for u in target['devices'].keys() if target['devices'][u][0] == 'vkbd'])
-
- result.extend(target.get('console_refs', []) +
- target.get('vbd_refs', []) +
- target.get('vif_refs', []))
-
- result.extend([u for u in target['devices'].keys() if u not in result])
- return result
-
- def all_devices_sxpr(self, target = None):
- """Returns the SXPR for all devices in the current configuration."""
- sxprs = []
-
- if target == None:
- target = self
-
- if 'devices' not in target:
- return sxprs
-
- ordered_refs = self.ordered_device_refs(target = target)
- for dev_uuid in ordered_refs:
- dev_type, dev_info = target['devices'][dev_uuid]
- if dev_type == 'pci' or dev_type == 'vscsi': # special case for pci devices
- if dev_type == 'pci':
- sxpr = ['pci', ['uuid', dev_info['uuid']]]
- elif dev_type == 'vscsi':
- sxpr = ['vscsi', ['uuid', dev_info['uuid']],
- ['feature-host', dev_info['feature-host']]]
- if dev_info.has_key('backend'):
- sxpr.append(['backend', dev_info['backend']])
- for pci_dev_info in dev_info['devs']:
- sxpr.append(dev_dict_to_sxp(pci_dev_info))
- sxprs.append((dev_type, sxpr))
- elif dev_type == 'vusb':
- sxpr = ['vusb', ['uuid', dev_info['uuid']],
- ['usb-ver', dev_info['usb-ver']],
- ['num-ports', dev_info['num-ports']]]
- port_sxpr = ['port']
- for i in range(1, int(dev_info['num-ports']) + 1):
- if dev_info.has_key('port-%i' % i):
- port_sxpr.append([i, str(dev_info['port-%i' % i])])
- else:
- port_sxpr.append([i, ""])
- sxpr.append(port_sxpr)
- sxprs.append((dev_type, sxpr))
- else:
- sxpr = self.device_sxpr(dev_type = dev_type,
- dev_info = dev_info,
- target = target)
- sxprs.append((dev_type, sxpr))
-
- return sxprs
-
- def image_sxpr(self):
- """Returns a backwards compatible image SXP expression that is
- used in xenstore's /vm/<uuid>/image value and xm list."""
- image = [self.image_type()]
- if self.has_key('PV_kernel'):
- image.append(['kernel', self['PV_kernel']])
- if self.has_key('PV_ramdisk') and self['PV_ramdisk']:
- image.append(['ramdisk', self['PV_ramdisk']])
- if self.has_key('PV_args') and self['PV_args']:
- image.append(['args', self['PV_args']])
- if self.has_key('superpages'):
- image.append(['superpages', self['superpages']])
-
- for key in XENAPI_PLATFORM_CFG_TYPES.keys():
- if key in self['platform']:
- image.append([key, self['platform'][key]])
-
- if 'notes' in self:
- image.append(self.notes_sxp(self['notes']))
-
- return image
-
- def update_with_image_sxp(self, image_sxp, bootloader = False):
- # Convert Legacy "image" config to Xen API PV_*
- # configuration
- log.debug("update_with_image_sxp(%s)" % scrub_password(image_sxp))
-
- # user-specified args must come last: previous releases did this and
- # some domU kernels rely upon the ordering.
- kernel_args = sxp.child_value(image_sxp, 'args', '')
-
- # attempt to extract extra arguments from SXP config
- arg_ip = sxp.child_value(image_sxp, 'ip')
- if arg_ip and not re.search(r'ip=[^ ]+', kernel_args):
- kernel_args = 'ip=%s ' % arg_ip + kernel_args
- arg_root = sxp.child_value(image_sxp, 'root')
- if arg_root and not re.search(r'root=', kernel_args):
- kernel_args = 'root=%s ' % arg_root + kernel_args
-
- if bootloader:
- self['_temp_using_bootloader'] = '1'
- self['_temp_kernel'] = sxp.child_value(image_sxp, 'kernel','')
- self['_temp_ramdisk'] = sxp.child_value(image_sxp, 'ramdisk','')
- self['_temp_args'] = kernel_args
- self['use_tmp_kernel'] = True
- self['use_tmp_ramdisk'] = True
- else:
- self['PV_kernel'] = sxp.child_value(image_sxp, 'kernel','')
- self['PV_ramdisk'] = sxp.child_value(image_sxp, 'ramdisk','')
- self['PV_args'] = kernel_args
- self['use_tmp_kernel'] = False
- self['use_tmp_ramdisk'] = False
-
- val = sxp.child_value(image_sxp, 'superpages')
- if val is not None:
- self['superpages'] = val
-
- val = sxp.child_value(image_sxp, 'memory_sharing')
- if val is not None:
- self['memory_sharing'] = val
-
- for key in XENAPI_PLATFORM_CFG_TYPES.keys():
- val = sxp.child_value(image_sxp, key, None)
- if val is not None and val != '':
- self['platform'][key] = val
-
- notes = sxp.children(image_sxp, 'notes')
- if notes:
- self['notes'] = self.notes_from_sxp(notes[0])
-
- self._hvm_boot_params_from_sxp(image_sxp)
-
- def set_notes(self, notes):
- 'Add parsed elfnotes to image'
- self['notes'] = notes
-
- def get_notes(self):
- try:
- return self['notes'] or {}
- except KeyError:
- return {}
-
- def notes_from_sxp(self, nsxp):
- notes = {}
- for note in sxp.children(nsxp):
- notes[note[0]] = note[1]
- return notes
-
- def notes_sxp(self, notes):
- nsxp = ['notes']
- for k, v in notes.iteritems():
- nsxp.append([k, str(v)])
- return nsxp
-
- def _hvm_boot_params_from_sxp(self, image_sxp):
- boot = sxp.child_value(image_sxp, 'boot', None)
- if boot is not None:
- self['HVM_boot_policy'] = 'BIOS order'
- self['HVM_boot_params'] = { 'order' : boot }
-
- def is_hvm(self):
- return self['HVM_boot_policy'] != ''
-
- def is_stubdom(self):
- return (self['PV_kernel'].find('ioemu') >= 0)
-
- def target(self):
- return self['target']
-
- def image_type(self):
- stored_type = self['platform'].get('image_type')
- return stored_type or (self.is_hvm() and 'hvm' or 'linux')
-
- def is_hap(self):
- return self['platform'].get('hap', 0)
-
- def is_pv_and_has_pci(self):
- for dev_type, dev_info in self.all_devices_sxpr():
- if dev_type != 'pci':
- continue
- return not self.is_hvm()
- return False
-
- def update_platform_pci(self):
- pci = []
- for dev_type, dev_info in self.all_devices_sxpr():
- if dev_type != 'pci':
- continue
- for dev in sxp.children(dev_info, 'dev'):
- domain = sxp.child_value(dev, 'domain')
- bus = sxp.child_value(dev, 'bus')
- slot = sxp.child_value(dev, 'slot')
- func = sxp.child_value(dev, 'func')
- vdevfn = sxp.child_value(dev, 'vdevfn')
- opts = pci_opts_list_from_sxp(dev)
- pci.append([domain, bus, slot, func, vdevfn, opts])
- self['platform']['pci'] = pci
-
- def handle_fileuris(self):
- for arg in [('PV_kernel', 'use_tmp_kernel'),
- ('PV_ramdisk', 'use_tmp_ramdisk')]:
- if arg[0] in self and self[arg[0]]!='':
- self[arg[0]], self[arg[1]] \
- = xen.util.fileuri.schemes.decode(self[arg[0]])
- log.debug("fileuri '%s' = '%s'" % (arg[0], self[arg[0]][:100]))
-
diff --git a/tools/python/xen/xend/XendConstants.py b/tools/python/xen/xend/XendConstants.py
deleted file mode 100644
index bc1c400..0000000
--- a/tools/python/xen/xend/XendConstants.py
+++ /dev/null
@@ -1,164 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 XenSource Ltd.
-#============================================================================
-
-from xen.xend.XendAPIConstants import *
-from xen.util import auxbin
-
-#
-# Shutdown codes and reasons.
-#
-
-DOMAIN_POWEROFF = 0
-DOMAIN_REBOOT = 1
-DOMAIN_SUSPEND = 2
-DOMAIN_CRASH = 3
-DOMAIN_HALT = 4
-
-DOMAIN_SHUTDOWN_REASONS = {
- DOMAIN_POWEROFF: "poweroff",
- DOMAIN_REBOOT : "reboot",
- DOMAIN_SUSPEND : "suspend",
- DOMAIN_CRASH : "crash",
- DOMAIN_HALT : "halt"
-}
-REVERSE_DOMAIN_SHUTDOWN_REASONS = \
- dict([(y, x) for x, y in DOMAIN_SHUTDOWN_REASONS.items()])
-
-HVM_PARAM_CALLBACK_IRQ = 0
-HVM_PARAM_STORE_PFN = 1
-HVM_PARAM_STORE_EVTCHN = 2
-HVM_PARAM_PAE_ENABLED = 4
-HVM_PARAM_IOREQ_PFN = 5
-HVM_PARAM_BUFIOREQ_PFN = 6
-HVM_PARAM_NVRAM_FD = 7 # ia64
-HVM_PARAM_VHPT_SIZE = 8 # ia64
-HVM_PARAM_BUFPIOREQ_PFN = 9 # ia64
-HVM_PARAM_VIRIDIAN = 9 # x86
-HVM_PARAM_TIMER_MODE = 10
-HVM_PARAM_HPET_ENABLED = 11
-HVM_PARAM_ACPI_S_STATE = 14
-HVM_PARAM_VPT_ALIGN = 16
-HVM_PARAM_CONSOLE_PFN = 17
-HVM_PARAM_NESTEDHVM = 24 # x86
-
-restart_modes = [
- "restart",
- "destroy",
- "preserve",
- "rename-restart",
- "coredump-destroy",
- "coredump-restart"
- ]
-
-DOM_STATES = [
- 'halted',
- 'paused',
- 'running',
- 'suspended',
- 'shutdown',
- 'crashed',
- 'unknown',
-]
-
-DOM_STATE_HALTED = XEN_API_VM_POWER_STATE_HALTED
-DOM_STATE_PAUSED = XEN_API_VM_POWER_STATE_PAUSED
-DOM_STATE_RUNNING = XEN_API_VM_POWER_STATE_RUNNING
-DOM_STATE_SUSPENDED = XEN_API_VM_POWER_STATE_SUSPENDED
-DOM_STATE_SHUTDOWN = XEN_API_VM_POWER_STATE_SHUTTINGDOWN
-DOM_STATE_CRASHED = XEN_API_VM_POWER_STATE_CRASHED
-DOM_STATE_UNKNOWN = XEN_API_VM_POWER_STATE_UNKNOWN
-
-DOM_STATES_OLD = [
- 'running',
- 'blocked',
- 'paused',
- 'shutdown',
- 'crashed',
- 'dying'
- ]
-
-SHUTDOWN_TIMEOUT = (60.0 * 5)
-
-"""Minimum time between domain restarts in seconds."""
-MINIMUM_RESTART_TIME = 60
-
-RESTART_IN_PROGRESS = 'xend/restart_in_progress'
-DUMPCORE_IN_PROGRESS = 'xend/dumpcore_in_progress'
-LAST_SHUTDOWN_REASON = 'xend/last_shutdown_reason'
-
-TRIGGER_NMI = 0
-TRIGGER_RESET = 1
-TRIGGER_INIT = 2
-TRIGGER_POWER = 3
-TRIGGER_S3RESUME = 4
-
-TRIGGER_TYPE = {
- "nmi" : TRIGGER_NMI,
- "reset" : TRIGGER_RESET,
- "init" : TRIGGER_INIT,
- "s3resume": TRIGGER_S3RESUME,
- "power": TRIGGER_POWER
-}
-
-#
-# Device migration stages (eg. XendDomainInfo, XendCheckpoint)
-#
-
-DEV_MIGRATE_TEST = 0
-DEV_MIGRATE_STEP1 = 1
-DEV_MIGRATE_STEP2 = 2
-DEV_MIGRATE_STEP3 = 3
-
-#
-# Xenstore Constants
-#
-
-XS_VMROOT = "/vm/"
-
-XS_POOLROOT = "/local/pool/"
-
-NR_PCI_FUNC = 8
-NR_PCI_DEV = 32
-NR_PCI_DEVFN = NR_PCI_FUNC * NR_PCI_DEV
-AUTO_PHP_SLOT = 0x100
-
-#
-# tmem
-#
-
-TMEM_CONTROL = 0
-TMEM_NEW_POOL = 1
-TMEM_DESTROY_POOL = 2
-TMEM_NEW_PAGE = 3
-TMEM_PUT_PAGE = 4
-TMEM_GET_PAGE = 5
-TMEM_FLUSH_PAGE = 6
-TMEM_FLUSH_OBJECT = 7
-TMEM_READ = 8
-TMEM_WRITE = 9
-TMEM_XCHG = 10
-
-TMEMC_THAW = 0
-TMEMC_FREEZE = 1
-TMEMC_FLUSH = 2
-TMEMC_DESTROY = 3
-TMEMC_LIST = 4
-TMEMC_SET_WEIGHT = 5
-TMEMC_SET_CAP = 6
-TMEMC_SET_COMPRESS = 7
-TMEMC_QUERY_FREEABLE_MB = 8
-
diff --git a/tools/python/xen/xend/XendDPCI.py b/tools/python/xen/xend/XendDPCI.py
deleted file mode 100644
index e7507f0..0000000
--- a/tools/python/xen/xend/XendDPCI.py
+++ /dev/null
@@ -1,165 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (c) 2008 NEC Corporation
-# Yosuke Iwamatsu <y-iwamatsu at ab jp nec com>
-#============================================================================
-
-from xen.xend.XendBase import XendBase
-from xen.xend.XendPPCI import XendPPCI
-from xen.xend import XendAPIStore
-from xen.xend import uuid as genuuid
-
-import XendDomain, XendNode
-
-from XendError import *
-from XendTask import XendTask
-from XendLogging import log
-
-class XendDPCI(XendBase):
- """Representation of a passthrough PCI device."""
-
- def getClass(self):
- return "DPCI"
-
- def getAttrRO(self):
- attrRO = ['virtual_domain',
- 'virtual_bus',
- 'virtual_slot',
- 'virtual_func',
- 'virtual_name',
- 'VM',
- 'PPCI',
- 'hotplug_slot',
- 'key',
- 'options']
- return XendBase.getAttrRO() + attrRO
-
- def getAttrRW(self):
- attrRW = []
- return XendBase.getAttrRW() + attrRW
-
- def getAttrInst(self):
- attrInst = ['VM',
- 'PPCI',
- 'hotplug_slot',
- 'key']
- return XendBase.getAttrInst() + attrInst
-
- def getMethods(self):
- methods = ['destroy']
- return XendBase.getMethods() + methods
-
- def getFuncs(self):
- funcs = ['create']
- return XendBase.getFuncs() + funcs
-
- getClass = classmethod(getClass)
- getAttrRO = classmethod(getAttrRO)
- getAttrRW = classmethod(getAttrRW)
- getAttrInst = classmethod(getAttrInst)
- getMethods = classmethod(getMethods)
- getFuncs = classmethod(getFuncs)
-
- def create(self, dpci_struct):
-
- # Check if VM is valid
- xendom = XendDomain.instance()
- if not xendom.is_valid_vm(dpci_struct['VM']):
- raise InvalidHandleError('VM', dpci_struct['VM'])
- dom = xendom.get_vm_by_uuid(dpci_struct['VM'])
-
- # Check if PPCI is valid
- xennode = XendNode.instance()
- ppci_uuid = xennode.get_ppci_by_uuid(dpci_struct['PPCI'])
- if not ppci_uuid:
- raise InvalidHandleError('PPCI', dpci_struct['PPCI'])
- for existing_dpci in XendAPIStore.get_all('DPCI'):
- if ppci_uuid == existing_dpci.get_PPCI():
- raise DirectPCIError("Device is in use")
-
- # Assign PPCI to VM
- try:
- dpci_ref = XendTask.log_progress(0, 100, dom.create_dpci,
- dpci_struct)
- except XendError, e:
- raise DirectPCIError("Failed to assign device")
-
- # TODO: Retrive virtual pci device infomation.
-
- return dpci_ref
-
- create = classmethod(create)
-
- def get_by_VM(cls, VM_ref):
- result = []
- for dpci in XendAPIStore.get_all("DPCI"):
- if dpci.get_VM() == VM_ref:
- result.append(dpci.get_uuid())
- return result
-
- get_by_VM = classmethod(get_by_VM)
-
- def __init__(self, uuid, record):
- XendBase.__init__(self, uuid, record)
-
- self.virtual_domain = -1
- self.virtual_bus = -1
- self.virtual_slot = -1
- self.virtual_func = -1
-
- self.VM = record['VM']
- self.PPCI = record['PPCI']
- self.hotplug_slot = int(record['hotplug_slot'], 16)
- self.key = record['key']
- if 'options' in record.keys():
- self.options = record['options']
-
- def destroy(self):
- xendom = XendDomain.instance()
- dom = xendom.get_vm_by_uuid(self.get_VM())
- if not dom:
- raise InvalidHandleError("VM", self.get_VM())
- XendTask.log_progress(0, 100, dom.destroy_dpci, self.get_uuid())
-
- def get_virtual_domain(self):
- return self.virtual_domain
-
- def get_virtual_bus(self):
- return self.virtual_bus
-
- def get_virtual_slot(self):
- return self.virtual_slot
-
- def get_virtual_func(self):
- return self.virtual_func
-
- def get_virtual_name(self):
- return "%04x:%02x:%02x.%01x" % (self.virtual_domain, self.virtual_bus,
- self.virtual_slot, self.virtual_func)
-
- def get_VM(self):
- return self.VM
-
- def get_PPCI(self):
- return self.PPCI
-
- def get_hotplug_slot(self):
- return "%d" % self.hotplug_slot
-
- def get_key(self):
- return self.key
-
- def get_options(self):
- return self.options
diff --git a/tools/python/xen/xend/XendDSCSI.py b/tools/python/xen/xend/XendDSCSI.py
deleted file mode 100644
index 794a54f..0000000
--- a/tools/python/xen/xend/XendDSCSI.py
+++ /dev/null
@@ -1,299 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright FUJITSU LIMITED 2008
-# Masaki Kanno <kanno.masaki at jp.fujitsu.com>
-#============================================================================
-
-from xen.xend.XendBase import XendBase
-from xen.xend.XendPSCSI import XendPSCSI
-from xen.xend import XendAPIStore
-from xen.xend import sxp
-from xen.xend import uuid as genuuid
-
-import XendDomain, XendNode
-
-from XendError import *
-from XendTask import XendTask
-from XendLogging import log
-
-class XendDSCSI(XendBase):
- """Representation of a half-virtualized SCSI device."""
-
- def getClass(self):
- return "DSCSI"
-
- def getAttrRO(self):
- attrRO = ['VM',
- 'PSCSI',
- 'HBA',
- 'virtual_host',
- 'virtual_channel',
- 'virtual_target',
- 'virtual_lun',
- 'virtual_HCTL',
- 'runtime_properties']
- return XendBase.getAttrRO() + attrRO
-
- def getAttrRW(self):
- attrRW = []
- return XendBase.getAttrRW() + attrRW
-
- def getAttrInst(self):
- attrInst = ['VM',
- 'PSCSI',
- 'HBA',
- 'virtual_HCTL']
- return XendBase.getAttrInst() + attrInst
-
- def getMethods(self):
- methods = ['destroy']
- return XendBase.getMethods() + methods
-
- def getFuncs(self):
- funcs = ['create']
- return XendBase.getFuncs() + funcs
-
- getClass = classmethod(getClass)
- getAttrRO = classmethod(getAttrRO)
- getAttrRW = classmethod(getAttrRW)
- getAttrInst = classmethod(getAttrInst)
- getMethods = classmethod(getMethods)
- getFuncs = classmethod(getFuncs)
-
- def create(self, dscsi_struct):
-
- # Check if VM is valid
- xendom = XendDomain.instance()
- if not xendom.is_valid_vm(dscsi_struct['VM']):
- raise InvalidHandleError('VM', dscsi_struct['VM'])
- dom = xendom.get_vm_by_uuid(dscsi_struct['VM'])
-
- # Check if PSCSI is valid
- xennode = XendNode.instance()
- pscsi_uuid = xennode.get_pscsi_by_uuid(dscsi_struct['PSCSI'])
- if not pscsi_uuid:
- raise InvalidHandleError('PSCSI', dscsi_struct['PSCSI'])
-
- # Assign PSCSI to VM
- try:
- dscsi_ref = XendTask.log_progress(0, 100, \
- dom.create_dscsi, \
- dscsi_struct)
- except XendError, e:
- log.exception("Error in create_dscsi")
- raise
-
- return dscsi_ref
-
- create = classmethod(create)
-
- def get_by_VM(cls, VM_ref):
- result = []
- for dscsi in XendAPIStore.get_all("DSCSI"):
- if dscsi.get_VM() == VM_ref:
- result.append(dscsi.get_uuid())
- return result
-
- get_by_VM = classmethod(get_by_VM)
-
- def __init__(self, uuid, record):
- XendBase.__init__(self, uuid, record)
- v_hctl = self.virtual_HCTL.split(':')
- self.virtual_host = int(v_hctl[0])
- self.virtual_channel = int(v_hctl[1])
- self.virtual_target = int(v_hctl[2])
- self.virtual_lun = int(v_hctl[3])
-
- def get_VM(self):
- return self.VM
-
- def get_PSCSI(self):
- return self.PSCSI
-
- def get_HBA(self):
- return self.HBA
-
- def get_virtual_host(self):
- return self.virtual_host
-
- def get_virtual_channel(self):
- return self.virtual_channel
-
- def get_virtual_target(self):
- return self.virtual_target
-
- def get_virtual_lun(self):
- return self.virtual_lun
-
- def get_virtual_HCTL(self):
- return self.virtual_HCTL
-
- def get_runtime_properties(self):
- xendom = XendDomain.instance()
- dominfo = xendom.get_vm_by_uuid(self.VM)
-
- try:
- device_dict = {}
- for device_sxp in dominfo.getDeviceSxprs('vscsi'):
- target_dev = None
- for dev in device_sxp[1][0][1]:
- vdev = sxp.child_value(dev, 'v-dev')
- if vdev == self.virtual_HCTL:
- target_dev = dev
- break
- if target_dev is None:
- continue
-
- dev_dict = {}
- for info in target_dev[1:]:
- dev_dict[info[0]] = info[1]
- device_dict['dev'] = dev_dict
- for info in device_sxp[1][1:]:
- device_dict[info[0]] = info[1]
-
- return device_dict
- except Exception, exn:
- log.exception(exn)
- return {}
-
- def destroy(self):
- xendom = XendDomain.instance()
- dom = xendom.get_vm_by_uuid(self.get_VM())
- if not dom:
- raise InvalidHandleError("VM", self.get_VM())
- XendTask.log_progress(0, 100, \
- dom.destroy_dscsi, \
- self.get_uuid())
-
-
-class XendDSCSI_HBA(XendBase):
- """Representation of a half-virtualized SCSI HBA."""
-
- def getClass(self):
- return "DSCSI_HBA"
-
- def getAttrRO(self):
- attrRO = ['VM',
- 'PSCSI_HBAs',
- 'DSCSIs',
- 'virtual_host',
- 'assignment_mode']
- return XendBase.getAttrRO() + attrRO
-
- def getAttrRW(self):
- attrRW = []
- return XendBase.getAttrRW() + attrRW
-
- def getAttrInst(self):
- attrInst = ['VM',
- 'virtual_host',
- 'assignment_mode']
- return XendBase.getAttrInst() + attrInst
-
- def getMethods(self):
- methods = ['destroy']
- return XendBase.getMethods() + methods
-
- def getFuncs(self):
- funcs = ['create']
- return XendBase.getFuncs() + funcs
-
- getClass = classmethod(getClass)
- getAttrRO = classmethod(getAttrRO)
- getAttrRW = classmethod(getAttrRW)
- getAttrInst = classmethod(getAttrInst)
- getMethods = classmethod(getMethods)
- getFuncs = classmethod(getFuncs)
-
- def create(self, dscsi_HBA_struct):
-
- # Check if VM is valid
- xendom = XendDomain.instance()
- if not xendom.is_valid_vm(dscsi_HBA_struct['VM']):
- raise InvalidHandleError('VM', dscsi_HBA_struct['VM'])
- dom = xendom.get_vm_by_uuid(dscsi_HBA_struct['VM'])
-
- # Check if PSCSI_HBA is valid
- xennode = XendNode.instance()
- pscsi_HBA_uuid = xennode.get_pscsi_HBA_by_uuid(dscsi_HBA_struct['PSCSI_HBA'])
- if not pscsi_HBA_uuid:
- raise InvalidHandleError('PSCSI_HBA', dscsi_HBA_struct['PSCSI_HBA'])
-
- # Assign PSCSI_HBA and PSCSIs to VM
- try:
- dscsi_HBA_ref = XendTask.log_progress(0, 100, \
- dom.create_dscsi_HBA, \
- dscsi_HBA_struct)
- except XendError, e:
- log.exception("Error in create_dscsi_HBA")
- raise
-
- return dscsi_HBA_ref
-
- create = classmethod(create)
-
- def get_by_VM(cls, VM_ref):
- result = []
- for dscsi_HBA in XendAPIStore.get_all("DSCSI_HBA"):
- if dscsi_HBA.get_VM() == VM_ref:
- result.append(dscsi_HBA.get_uuid())
- return result
-
- get_by_VM = classmethod(get_by_VM)
-
- def __init__(self, uuid, record):
- XendBase.__init__(self, uuid, record)
- self.virtual_host = record['virtual_host']
- self.assignment_mode = record['assignment_mode']
-
- def get_VM(self):
- return self.VM
-
- def get_PSCSI_HBAs(self):
- PSCSIs = []
- uuid = self.get_uuid()
- for dscsi in XendAPIStore.get_all('DSCSI'):
- if dscsi.get_VM() == self.VM and dscsi.get_HBA() == uuid:
- PSCSIs.append(dscsi.get_PSCSI())
- PSCSI_HBAs = []
- for pscsi_uuid in PSCSIs:
- pscsi_HBA_uuid = XendAPIStore.get(pscsi_uuid, 'PSCSI').get_HBA()
- if not pscsi_HBA_uuid in PSCSI_HBAs:
- PSCSI_HBAs.append(pscsi_HBA_uuid)
- return PSCSI_HBAs
-
- def get_DSCSIs(self):
- DSCSIs = []
- uuid = self.get_uuid()
- for dscsi in XendAPIStore.get_all('DSCSI'):
- if dscsi.get_VM() == self.VM and dscsi.get_HBA() == uuid:
- DSCSIs.append(dscsi.get_uuid())
- return DSCSIs
-
- def get_virtual_host(self):
- return self.virtual_host
-
- def get_assignment_mode(self):
- return self.assignment_mode
-
- def destroy(self):
- xendom = XendDomain.instance()
- dom = xendom.get_vm_by_uuid(self.get_VM())
- if not dom:
- raise InvalidHandleError("VM", self.get_VM())
- XendTask.log_progress(0, 100, \
- dom.destroy_dscsi_HBA, \
- self.get_uuid())
-
diff --git a/tools/python/xen/xend/XendDevices.py b/tools/python/xen/xend/XendDevices.py
deleted file mode 100644
index bef4d8a..0000000
--- a/tools/python/xen/xend/XendDevices.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#===========================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 XenSource Ltd
-#============================================================================
-
-#
-# A collection of DevControllers
-#
-
-from xen.xend.server import blkif, netif, pciif, iopif, irqif, vfbif, vscsiif, netif2, vusbif
-from xen.xend.server.BlktapController import BlktapController, Blktap2Controller
-from xen.xend.server.ConsoleController import ConsoleController
-
-
-class XendDevices:
- """ An ugly halfway point between the module local device name
- to class map we used to have in XendDomainInfo and something
- slightly more managable.
-
- This class should contain all the functions that have to do
- with managing devices in Xend. Right now it is only a factory
- function.
- """
-
- controllers = {
- 'vbd': blkif.BlkifController,
- 'vif': netif.NetifController,
- 'vif2': netif2.NetifController2,
- 'pci': pciif.PciController,
- 'ioports': iopif.IOPortsController,
- 'irq': irqif.IRQController,
- 'tap': BlktapController,
- 'tap2': Blktap2Controller,
- 'vfb': vfbif.VfbifController,
- 'vkbd': vfbif.VkbdifController,
- 'console': ConsoleController,
- 'vscsi': vscsiif.VSCSIController,
- 'vusb': vusbif.VUSBController,
- }
-
- #@classmethod
- def valid_devices(cls):
- return cls.controllers.keys()
- valid_devices = classmethod(valid_devices)
-
- #@classmethod
- def make_controller(cls, name, domain):
- """Factory function to make device controllers per domain.
-
- @param name: device class name in L{VALID_DEVICES}
- @type name: String
- @param domain: domain this controller is handling devices for.
- @type domain: XendDomainInfo
- @return: DevController of class 'name' or None
- @rtype: subclass of DevController
- """
- if name in cls.controllers.keys():
- cls.controllers[name].deviceClass = name
- return cls.controllers[name](domain)
- return None
-
- make_controller = classmethod(make_controller)
-
- def destroy_device_state(cls, domain):
- """Destroy the state of (external) devices. This is necessary
- to do when a VM's configuration is destroyed.
-
- @param domain: domain this controller is handling devices for.
- @type domain: XendDomainInfo
- """
- from xen.xend.XendLogging import log
-
- destroy_device_state = classmethod(destroy_device_state)
diff --git a/tools/python/xen/xend/XendDmesg.py b/tools/python/xen/xend/XendDmesg.py
deleted file mode 100644
index f4d0ff6..0000000
--- a/tools/python/xen/xend/XendDmesg.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2007 XenSource Inc.
-#============================================================================
-
-"""Get dmesg output for this node.
-"""
-
-import xen.lowlevel.xc
-
-class XendDmesg:
- def __init__(self):
- self.xc = xen.lowlevel.xc.xc()
-
- def info(self):
- return self.xc.readconsolering()
-
- def clear(self):
- return self.xc.readconsolering(True)
-
-def instance():
- global inst
- try:
- inst
- except:
- inst = XendDmesg()
- return inst
-
diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py
deleted file mode 100644
index 1d4da8f..0000000
--- a/tools/python/xen/xend/XendDomain.py
+++ /dev/null
@@ -1,1958 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 Christian Limpach <Christian.Limpach at cl.cam.ac.uk>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-"""Handler for domain operations.
- Nothing here is persistent (across reboots).
- Needs to be persistent for one uptime.
-"""
-
-import os
-import stat
-import shutil
-import socket
-import tempfile
-import threading
-import re
-
-import xen.lowlevel.xc
-
-
-from xen.xend import XendOptions, XendCheckpoint, XendDomainInfo
-from xen.xend.PrettyPrint import prettyprint
-from xen.xend import XendConfig, image
-from xen.xend.XendError import XendError, XendInvalidDomain, VmError
-from xen.xend.XendError import VMBadState
-from xen.xend.XendLogging import log
-from xen.xend.XendAPIConstants import XEN_API_VM_POWER_STATE
-from xen.xend.XendConstants import XS_VMROOT
-from xen.xend.XendConstants import DOM_STATE_HALTED, DOM_STATE_PAUSED
-from xen.xend.XendConstants import DOM_STATE_RUNNING, DOM_STATE_SUSPENDED
-from xen.xend.XendConstants import DOM_STATE_SHUTDOWN, DOM_STATE_UNKNOWN
-from xen.xend.XendConstants import DOM_STATE_CRASHED, HVM_PARAM_ACPI_S_STATE
-from xen.xend.XendConstants import TRIGGER_TYPE, TRIGGER_S3RESUME
-from xen.xend.XendDevices import XendDevices
-from xen.xend.XendAPIConstants import *
-
-from xen.xend.xenstore.xstransact import xstransact
-from xen.xend.xenstore.xswatch import xswatch
-from xen.util import mkdir, rwlock
-from xen.xend import uuid
-
-xc = xen.lowlevel.xc.xc()
-xoptions = XendOptions.instance()
-
-__all__ = [ "XendDomain" ]
-
-CACHED_CONFIG_FILE = 'config.sxp'
-CHECK_POINT_FILE = 'checkpoint.chk'
-DOM0_UUID = "00000000-0000-0000-0000-000000000000"
-DOM0_NAME = "Domain-0"
-DOM0_ID = 0
-
-POWER_STATE_NAMES = dict([(x, XEN_API_VM_POWER_STATE[x])
- for x in [DOM_STATE_HALTED,
- DOM_STATE_PAUSED,
- DOM_STATE_RUNNING,
- DOM_STATE_SUSPENDED,
- DOM_STATE_SHUTDOWN,
- DOM_STATE_CRASHED,
- DOM_STATE_UNKNOWN]])
-POWER_STATE_ALL = 'all'
-
-
-class XendDomain:
- """Index of all domains. Singleton.
-
- @ivar domains: map of domains indexed by domid
- @type domains: dict of XendDomainInfo
- @ivar managed_domains: domains that are not running and managed by Xend
- @type managed_domains: dict of XendDomainInfo indexed by uuid
- @ivar domains_lock: lock that must be held when manipulating self.domains
- @type domains_lock: threaading.RLock
- @ivar _allow_new_domains: Flag to set that allows creating of new domains.
- @type _allow_new_domains: boolean
- """
-
- def __init__(self):
- self.domains = {}
- self.managed_domains = {}
- self.domains_lock = threading.RLock()
-
- self.policy_lock = rwlock.RWLock()
-
- # xen api instance vars
- # TODO: nothing uses this at the moment
- self._allow_new_domains = True
-
- # This must be called only the once, by instance() below. It is separate
- # from the constructor because XendDomainInfo calls back into this class
- # in order to check the uniqueness of domain names. This means that
- # instance() must be able to return a valid instance of this class even
- # during this initialisation.
- def init(self):
- """Singleton initialisation function."""
-
- dom_path = self._managed_path()
- mkdir.parents(dom_path, stat.S_IRWXU)
-
- xstransact.Mkdir(XS_VMROOT)
- xstransact.SetPermissions(XS_VMROOT, {'dom': DOM0_ID})
-
- self.domains_lock.acquire()
- try:
- try:
- dom0info = [d for d in self._running_domains() \
- if d.get('domid') == DOM0_ID][0]
-
- dom0info['name'] = DOM0_NAME
- dom0 = XendDomainInfo.recreate(dom0info, True)
- except IndexError:
- raise XendError('Unable to find Domain 0')
-
- self._setDom0CPUCount()
-
- # This watch registration needs to be before the refresh call, so
- # that we're sure that we haven't missed any releases, but inside
- # the domains_lock, as we don't want the watch to fire until after
- # the refresh call has completed.
- xswatch("@introduceDomain", self._on_domains_changed)
- xswatch("@releaseDomain", self._on_domains_changed)
-
- self._init_domains()
- finally:
- self.domains_lock.release()
-
-
- def _on_domains_changed(self, _):
- """ Callback method when xenstore changes.
-
- Calls refresh which will keep the local cache of domains
- in sync.
-
- @rtype: int
- @return: 1
- """
- self.domains_lock.acquire()
- try:
- self._refresh()
- finally:
- self.domains_lock.release()
- return 1
-
- def _init_domains(self):
- """Does the initial scan of managed and active domains to
- populate self.domains.
-
- Note: L{XendDomainInfo._checkName} will call back into XendDomain
- to make sure domain name is not a duplicate.
-
- """
- self.domains_lock.acquire()
- try:
- running = self._running_domains()
- managed = self._managed_domains()
-
- # add all active domains
- for dom in running:
- if dom['dying'] == 1:
- log.warn('Ignoring dying domain %d from now on' %
- dom['domid'])
- continue
-
- if dom['domid'] != DOM0_ID:
- try:
- new_dom = XendDomainInfo.recreate(dom, False)
- except Exception:
- log.exception("Failed to create reference to running "
- "domain id: %d" % dom['domid'])
-
- image.cleanup_stale_sentinel_fifos()
-
- # add all managed domains as dormant domains.
- for dom in managed:
- dom_uuid = dom.get('uuid')
- if not dom_uuid:
- continue
-
- dom_name = dom.get('name_label', 'Domain-%s' % dom_uuid)
- try:
- running_dom = self.domain_lookup_nr(dom_name)
- if not running_dom:
- # instantiate domain if not started.
- new_dom = XendDomainInfo.createDormant(dom)
- self._managed_domain_register(new_dom)
- else:
- self._managed_domain_register(running_dom)
- for key in XendConfig.XENAPI_CFG_TYPES.keys():
- if key not in XendConfig.LEGACY_XENSTORE_VM_PARAMS and \
- key in dom:
- running_dom.info[key] = dom[key]
- # Devices information is restored from xenstore,
- # but VDI value in devices information can be not
- # restored because there is not VDI value in
- # xenstore. So we restore VDI value by using the
- # domain config file.
- for vbd_ref in running_dom.info['vbd_refs']:
- if dom['devices'].has_key(vbd_ref):
- r_devtype, r_devinfo = running_dom.info['devices'][vbd_ref]
- _, m_devinfo = dom['devices'][vbd_ref]
- r_devinfo['VDI'] = m_devinfo.get('VDI', '')
- running_dom.info['devices'][vbd_ref] = (r_devtype, r_devinfo)
- except Exception:
- log.exception("Failed to create reference to managed "
- "domain: %s" % dom_name)
-
- finally:
- self.domains_lock.release()
-
-
- # -----------------------------------------------------------------
- # Getting managed domains storage path names
-
- def _managed_path(self, domuuid = None):
- """Returns the path of the directory where managed domain
- information is stored.
-
- @keyword domuuid: If not None, will return the path to the domain
- otherwise, will return the path containing
- the directories which represent each domain.
- @type: None or String.
- @rtype: String
- @return: Path.
- """
- dom_path = xoptions.get_xend_domains_path()
- if domuuid:
- dom_path = os.path.join(dom_path, domuuid)
- return dom_path
-
- def _managed_config_path(self, domuuid):
- """Returns the path to the configuration file of a managed domain.
-
- @param domname: Domain uuid
- @type domname: String
- @rtype: String
- @return: path to config file.
- """
- return os.path.join(self._managed_path(domuuid), CACHED_CONFIG_FILE)
- def domain_setpauseflag(self, dom, flag=False):
- try:
- dominfo = self.domain_lookup_nr(dom)
- dominfo.paused_by_admin = flag
- except Exception, err:
- log.debug("error in in setpauseflag")
- def domain_getpauseflag(self, dom):
- try:
- dominfo = self.domain_lookup_nr(dom)
- return dominfo.paused_by_admin
- except Exception, err:
- log.debug("error in in getpauseflag")
-
- def _managed_check_point_path(self, domuuid):
- """Returns absolute path to check point file for managed domain.
-
- @param domuuid: Name of managed domain
- @type domname: String
- @rtype: String
- @return: Path
- """
- return os.path.join(self._managed_path(domuuid), CHECK_POINT_FILE)
-
- def _managed_config_remove(self, domuuid):
- """Removes a domain configuration from managed list
-
- @param domuuid: Name of managed domain
- @type domname: String
- @raise XendError: fails to remove the domain.
- """
- config_path = self._managed_path(domuuid)
- try:
- if os.path.exists(config_path) and os.path.isdir(config_path):
- shutil.rmtree(config_path)
- except IOError:
- log.exception('managed_config_remove failed removing conf')
- raise XendError("Unable to remove managed configuration"
- " for domain: %s" % domuuid)
-
- def managed_config_save(self, dominfo):
- """Save a domain's configuration to disk
-
- @param domninfo: Managed domain to save.
- @type dominfo: XendDomainInfo
- @raise XendError: fails to save configuration.
- @rtype: None
- """
- if not self.is_domain_managed(dominfo):
- return # refuse to save configuration this domain isn't managed
-
- if dominfo:
- domains_dir = self._managed_path()
- dom_uuid = dominfo.get_uuid()
- domain_config_dir = self._managed_path(dom_uuid)
-
- def make_or_raise(path):
- try:
- mkdir.parents(path, stat.S_IRWXU)
- except:
- log.exception("%s could not be created." % path)
- raise XendError("%s could not be created." % path)
-
- make_or_raise(domains_dir)
- make_or_raise(domain_config_dir)
-
- try:
- fd, fn = tempfile.mkstemp()
- f = os.fdopen(fd, 'w+b')
- try:
- prettyprint(dominfo.sxpr(legacy_only = False), f,
- width = 78)
- finally:
- f.close()
-
- try:
- shutil.move(fn, self._managed_config_path(dom_uuid))
- except:
- log.exception("Renaming %s to %s", fn,
- self._managed_config_path(dom_uuid))
- os.remove(fn)
- except:
- log.exception("Error occurred saving configuration file " +
- "to %s" % domain_config_dir)
- raise XendError("Failed to save configuration file to: %s" %
- domain_config_dir)
- else:
- log.warn("Trying to save configuration for invalid domain")
-
-
- def _managed_domains(self):
- """ Returns list of domains that are managed.
-
- Expects to be protected by domains_lock.
-
- @rtype: list of XendConfig
- @return: List of domain configurations that are managed.
- """
- dom_path = self._managed_path()
- dom_uuids = os.listdir(dom_path)
- doms = []
- for dom_uuid in dom_uuids:
- try:
- cfg_file = self._managed_config_path(dom_uuid)
- cfg = XendConfig.XendConfig(filename = cfg_file)
- if cfg.get('uuid') != dom_uuid:
- # something is wrong with the SXP
- log.error("UUID mismatch in stored configuration: %s" %
- cfg_file)
- continue
- doms.append(cfg)
- except Exception:
- log.exception('Unable to open or parse config.sxp: %s' % \
- cfg_file)
- return doms
-
- def _managed_domain_unregister(self, dom):
- try:
- if self.is_domain_managed(dom):
- self._managed_config_remove(dom.get_uuid())
- del self.managed_domains[dom.get_uuid()]
- dom.destroy_xapi_instances()
- except ValueError:
- log.warn("Domain is not registered: %s" % dom.get_uuid())
-
- def _managed_domain_register(self, dom):
- self.managed_domains[dom.get_uuid()] = dom
-
- def is_domain_managed(self, dom = None):
- return (dom.get_uuid() in self.managed_domains)
-
- # End of Managed Domain Access
- # --------------------------------------------------------------------
-
- def _running_domains(self):
- """Get table of domains indexed by id from xc.
-
- @requires: Expects to be protected by domains_lock.
- @rtype: list of dicts
- @return: A list of dicts representing the running domains.
- """
- try:
- return xc.domain_getinfo()
- except RuntimeError, e:
- log.exception("Unable to get domain information.")
- return {}
-
- def _setDom0CPUCount(self):
- """Sets the number of VCPUs dom0 has. Retreived from the
- Xend configuration, L{XendOptions}.
-
- @requires: Expects to be protected by domains_lock.
- @rtype: None
- """
- dom0 = self.privilegedDomain()
-
- # get max number of vcpus to use for dom0 from config
- target = int(xoptions.get_dom0_vcpus())
- log.debug("number of vcpus to use is %d", target)
-
- # target == 0 means use all processors
- if target > 0:
- dom0.setVCpuCount(target)
-
-
- def _refresh(self, refresh_shutdown = True):
- """Refresh the domain list. Needs to be called when
- either xenstore has changed or when a method requires
- up to date information (like uptime, cputime stats).
-
- Expects to be protected by the domains_lock.
-
- @rtype: None
- """
-
- txn = xstransact()
- try:
- self._refreshTxn(txn, refresh_shutdown)
- txn.commit()
- except:
- txn.abort()
- raise
-
- def _refreshTxn(self, transaction, refresh_shutdown):
- running = self._running_domains()
- # Add domains that are not already tracked but running in Xen,
- # and update domain state for those that are running and tracked.
- for dom in running:
- domid = dom['domid']
- if domid in self.domains:
- self.domains[domid].update(dom, refresh_shutdown, transaction)
- elif domid not in self.domains and dom['dying'] != 1:
- try:
- new_dom = XendDomainInfo.recreate(dom, False)
- except VmError:
- log.exception("Unable to recreate domain")
- try:
- xc.domain_pause(domid)
- XendDomainInfo.do_FLR(domid, dom['hvm'])
- xc.domain_destroy(domid)
- except:
- log.exception("Hard destruction of domain failed: %d" %
- domid)
-
- # update information for all running domains
- # - like cpu_time, status, dying, etc.
- # remove domains that are not running from active domain list.
- # The list might have changed by now, because the update call may
- # cause new domains to be added, if the domain has rebooted. We get
- # the list again.
- running = self._running_domains()
- running_domids = [d['domid'] for d in running if d['dying'] != 1]
- for domid, dom in self.domains.items():
- if domid not in running_domids and domid != DOM0_ID:
- self._remove_domain(dom, domid)
-
-
- def add_domain(self, info):
- """Add a domain to the list of running domains
-
- @requires: Expects to be protected by the domains_lock.
- @param info: XendDomainInfo of a domain to be added.
- @type info: XendDomainInfo
- """
- log.debug("Adding Domain: %s" % info.getDomid())
- self.domains[info.getDomid()] = info
-
- # update the managed domains with a new XendDomainInfo object
- # if we are keeping track of it.
- if info.get_uuid() in self.managed_domains:
- self._managed_domain_register(info)
-
- def remove_domain(self, info, domid = None):
- """Remove the domain from the list of running domains, taking the
- domains_lock first.
- """
- self.domains_lock.acquire()
- try:
- self._remove_domain(info, domid)
- finally:
- self.domains_lock.release()
-
- def _remove_domain(self, info, domid = None):
- """Remove the domain from the list of running domains
-
- @requires: Expects to be protected by the domains_lock.
- @param info: XendDomainInfo of a domain to be removed.
- @type info: XendDomainInfo
- """
- if info:
- if domid == None:
- domid = info.getDomid()
-
- if info._stateGet() != DOM_STATE_HALTED:
- info.cleanupDomain()
-
- if domid in self.domains:
- del self.domains[domid]
-
- info.destroy_xapi_instances()
- else:
- log.warning("Attempted to remove non-existent domain.")
-
- def restore_(self, config):
- """Create a domain as part of the restore process. This is called
- only from L{XendCheckpoint}.
-
- A restore request comes into XendDomain through L{domain_restore}
- or L{domain_restore_fd}. That request is
- forwarded immediately to XendCheckpoint which, when it is ready, will
- call this method. It is necessary to come through here rather than go
- directly to L{XendDomainInfo.restore} because we need to
- serialise the domain creation process, but cannot lock
- domain_restore_fd as a whole, otherwise we will deadlock waiting for
- the old domain to die.
-
- @param config: Configuration of domain to restore
- @type config: SXP Object (eg. list of lists)
- """
- self.domains_lock.acquire()
- try:
- dominfo = XendDomainInfo.restore(config)
- return dominfo
- finally:
- self.domains_lock.release()
-
-
- def domain_lookup(self, domid):
- """Look up given I{domid} in the list of managed and running
- domains.
-
- @note: Will cause a refresh before lookup up domains, for
- a version that does not need to re-read xenstore
- use L{domain_lookup_nr}.
-
- @param domid: Domain ID or Domain Name.
- @type domid: int or string
- @return: Found domain.
- @rtype: XendDomainInfo
- @raise XendInvalidDomain: If domain is not found.
- """
- self.domains_lock.acquire()
- try:
- self._refresh(refresh_shutdown = False)
- dom = self.domain_lookup_nr(domid)
- if not dom:
- raise XendInvalidDomain(str(domid))
- return dom
- finally:
- self.domains_lock.release()
-
-
- def domain_lookup_nr(self, domid):
- """Look up given I{domid} in the list of managed and running
- domains.
-
- @param domid: Domain ID or Domain Name.
- @type domid: int or string
- @return: Found domain.
- @rtype: XendDomainInfo or None
- """
- self.domains_lock.acquire()
- try:
- # lookup by name
- match = [dom for dom in self.domains.values() \
- if dom.getName() == domid]
- if match:
- return match[0]
-
- match = [dom for dom in self.managed_domains.values() \
- if dom.getName() == domid]
- if match:
- return match[0]
-
- # lookup by id
- try:
- if int(domid) in self.domains:
- return self.domains[int(domid)]
- except ValueError:
- pass
-
- # lookup by uuid for running domains
- match = [dom for dom in self.domains.values() \
- if dom.get_uuid() == domid]
- if match:
- return match[0]
-
- # lookup by uuid for inactive managed domains
- if domid in self.managed_domains:
- return self.managed_domains[domid]
-
- return None
- finally:
- self.domains_lock.release()
-
- def privilegedDomain(self):
- """ Get the XendDomainInfo of a dom0
-
- @rtype: XendDomainInfo
- """
- self.domains_lock.acquire()
- try:
- return self.domains[DOM0_ID]
- finally:
- self.domains_lock.release()
-
- def autostart_domains(self):
- """ Autostart managed domains that are marked as such. """
-
- need_starting = []
-
- self.domains_lock.acquire()
- try:
- for dom_uuid, dom in self.managed_domains.items():
- if dom and dom._stateGet() == DOM_STATE_HALTED:
- on_xend_start = dom.info.get('on_xend_start', 'ignore')
- auto_power_on = dom.info.get('auto_power_on', False)
- should_start = (on_xend_start == 'start') or auto_power_on
- if should_start:
- need_starting.append(dom_uuid)
- finally:
- self.domains_lock.release()
-
- for dom_uuid in need_starting:
- self.domain_start(dom_uuid, False)
-
- def cleanup_domains(self):
- """Clean up domains that are marked as autostop.
- Should be called when Xend goes down. This is currently
- called from L{xen.xend.servers.XMLRPCServer}.
-
- """
- log.debug('cleanup_domains')
- self.domains_lock.acquire()
- try:
- for dom in self.domains.values():
- if dom.getName() == DOM0_NAME:
- continue
-
- try:
- if dom._stateGet() == DOM_STATE_RUNNING:
- shutdownAction = dom.info.get('on_xend_stop', 'ignore')
- if shutdownAction == 'shutdown':
- log.debug('Shutting down domain: %s' % dom.getName())
- dom.shutdown("poweroff")
- elif shutdownAction == 'suspend':
- self.domain_suspend(dom.getName())
- else:
- log.debug('Domain %s continues to run.' % dom.getName())
- except:
- log.exception('Domain %s failed to %s.' % \
- (dom.getName(), shutdownAction))
- finally:
- self.domains_lock.release()
-
-
-
- # ----------------------------------------------------------------
- # Xen API
-
-
- def set_allow_new_domains(self, allow_new_domains):
- self._allow_new_domains = allow_new_domains
-
- def allow_new_domains(self):
- return self._allow_new_domains
-
- def get_domain_refs(self):
- result = []
- try:
- self.domains_lock.acquire()
- result = [d.get_uuid() for d in self.domains.values()]
- for d in self.managed_domains.keys():
- if d not in result:
- result.append(d)
- return result
- finally:
- self.domains_lock.release()
-
- def get_all_vms(self):
- self.domains_lock.acquire()
- try:
- result = self.domains.values()
- result += [x for x in self.managed_domains.values() if
- x not in result]
- return result
- finally:
- self.domains_lock.release()
-
- def get_vm_by_uuid(self, vm_uuid):
- self.domains_lock.acquire()
- try:
- for dom in self.domains.values():
- if dom.get_uuid() == vm_uuid:
- return dom
-
- if vm_uuid in self.managed_domains:
- return self.managed_domains[vm_uuid]
-
- return None
- finally:
- self.domains_lock.release()
-
- def get_vm_with_dev_uuid(self, klass, dev_uuid):
- self.domains_lock.acquire()
- try:
- for dom in self.domains.values() + self.managed_domains.values():
- if dom.has_device(klass, dev_uuid):
- return dom
- return None
- finally:
- self.domains_lock.release()
-
- def get_dev_property_by_uuid(self, klass, dev_uuid, field):
- value = None
- self.domains_lock.acquire()
-
- try:
- try:
- dom = self.get_vm_with_dev_uuid(klass, dev_uuid)
- if dom:
- value = dom.get_dev_property(klass, dev_uuid, field)
- except ValueError, e:
- pass
- finally:
- self.domains_lock.release()
-
- return value
-
- def set_dev_property_by_uuid(self, klass, dev_uuid, field, value,
- old_val = None):
- rc = True
- self.domains_lock.acquire()
-
- try:
- try:
- dom = self.get_vm_with_dev_uuid(klass, dev_uuid)
- if dom:
- o_val = dom.get_dev_property(klass, dev_uuid, field)
- log.info("o_val=%s, old_val=%s" % (o_val, old_val))
- if old_val and old_val != o_val:
- return False
-
- dom.set_dev_property(klass, dev_uuid, field, value)
- self.managed_config_save(dom)
- except ValueError, e:
- pass
- finally:
- self.domains_lock.release()
-
- return rc
-
- def is_valid_vm(self, vm_ref):
- return (self.get_vm_by_uuid(vm_ref) != None)
-
- def is_valid_dev(self, klass, dev_uuid):
- return (self.get_vm_with_dev_uuid(klass, dev_uuid) != None)
-
- def do_legacy_api_with_uuid(self, fn, vm_uuid, *args, **kwargs):
- dom = self.uuid_to_dom(vm_uuid)
- fn(dom, *args, **kwargs)
-
- def uuid_to_dom(self, vm_uuid):
- self.domains_lock.acquire()
- try:
- for domid, dom in self.domains.items():
- if dom.get_uuid() == vm_uuid:
- return domid
-
- if vm_uuid in self.managed_domains:
- domid = self.managed_domains[vm_uuid].getDomid()
- if domid is None:
- return self.managed_domains[vm_uuid].getName()
- else:
- return domid
-
- raise XendInvalidDomain(vm_uuid)
- finally:
- self.domains_lock.release()
-
-
- def create_domain(self, xenapi_vm):
- self.domains_lock.acquire()
- try:
- try:
- xeninfo = XendConfig.XendConfig(xapi = xenapi_vm)
- dominfo = XendDomainInfo.createDormant(xeninfo)
- log.debug("Creating new managed domain: %s: %s" %
- (dominfo.getName(), dominfo.get_uuid()))
- self._managed_domain_register(dominfo)
- self.managed_config_save(dominfo)
- return dominfo.get_uuid()
- except XendError, e:
- raise
- except Exception, e:
- raise XendError(str(e))
- finally:
- self.domains_lock.release()
-
- def rename_domain(self, dom, new_name):
- self.domains_lock.acquire()
- try:
- old_name = dom.getName()
- dom.setName(new_name)
-
- finally:
- self.domains_lock.release()
-
-
- #
- # End of Xen API
- # ----------------------------------------------------------------
-
- # ------------------------------------------------------------
- # Xen Legacy API
-
- def list(self, state = DOM_STATE_RUNNING):
- """Get list of domain objects.
-
- @param: the state in which the VMs should be -- one of the
- DOM_STATE_XYZ constants, or the corresponding name, or 'all'.
- @return: domains
- @rtype: list of XendDomainInfo
- """
- if type(state) == int:
- state = POWER_STATE_NAMES[state]
- state = state.lower()
- resu = False
- count = 0
- while True:
- resu = self.domains_lock.acquire(0)
- if resu or count < 20:
- break
- count += 1
- try:
- if resu:
- self._refresh(refresh_shutdown = False)
-
- # active domains
- active_domains = self.domains.values()
- active_uuids = [d.get_uuid() for d in active_domains]
-
- # inactive domains
- inactive_domains = []
- for dom_uuid, dom in self.managed_domains.items():
- if dom_uuid not in active_uuids:
- inactive_domains.append(dom)
-
- if state == POWER_STATE_ALL:
- return active_domains + inactive_domains
- else:
- return filter(lambda x:
- POWER_STATE_NAMES[x._stateGet()].lower() == state,
- active_domains + inactive_domains)
- finally:
- if resu:
- self.domains_lock.release()
-
-
- def list_sorted(self, state = DOM_STATE_RUNNING):
- """Get list of domain objects, sorted by name.
-
- @param: the state in which the VMs should be -- one of the
- DOM_STATE_XYZ constants, or the corresponding name, or 'all'.
- @return: domain objects
- @rtype: list of XendDomainInfo
- """
- doms = self.list(state)
- doms.sort(lambda x, y: cmp(x.getName(), y.getName()))
- return doms
-
- def list_names(self, state = DOM_STATE_RUNNING):
- """Get list of domain names.
-
- @param: the state in which the VMs should be -- one of the
- DOM_STATE_XYZ constants, or the corresponding name, or 'all'.
- @return: domain names
- @rtype: list of strings.
- """
- return [d.getName() for d in self.list_sorted(state)]
-
- def domain_suspend(self, domname):
- """Suspends a domain that is persistently managed by Xend
-
- @param domname: Domain Name
- @type domname: string
- @rtype: None
- @raise XendError: Failure during checkpointing.
- """
-
- try:
- dominfo = self.domain_lookup_nr(domname)
- if not dominfo:
- raise XendInvalidDomain(domname)
-
- if dominfo.getDomid() == DOM0_ID:
- raise XendError("Cannot suspend privileged domain %s" % domname)
-
- if dominfo._stateGet() != DOM_STATE_RUNNING:
- raise VMBadState("Domain is not running",
- POWER_STATE_NAMES[DOM_STATE_RUNNING],
- POWER_STATE_NAMES[dominfo._stateGet()])
-
- dom_uuid = dominfo.get_uuid()
-
- if not os.path.exists(self._managed_config_path(dom_uuid)):
- raise XendError("Domain is not managed by Xend lifecycle " +
- "support.")
-
- path = self._managed_check_point_path(dom_uuid)
- oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
- if hasattr(os, "O_LARGEFILE"):
- oflags |= os.O_LARGEFILE
- fd = os.open(path, oflags)
- try:
- # For now we don't support 'live checkpoint'
- XendCheckpoint.save(fd, dominfo, False, False, path)
- finally:
- os.close(fd)
- except OSError, ex:
- raise XendError("can't write guest state file %s: %s" %
- (path, ex[1]))
-
- def domain_resume(self, domname, start_paused = False):
- """Resumes a domain that is persistently managed by Xend.
-
- @param domname: Domain Name
- @type domname: string
- @rtype: None
- @raise XendError: If failed to restore.
- """
- self.domains_lock.acquire()
- try:
- try:
- fd = None
- dominfo = self.domain_lookup_nr(domname)
-
- if not dominfo:
- raise XendInvalidDomain(domname)
-
- if dominfo.getDomid() == DOM0_ID:
- raise XendError("Cannot resume privileged domain %s" % domname)
-
- if dominfo._stateGet() != XEN_API_VM_POWER_STATE_SUSPENDED:
- raise XendError("Cannot resume domain that is not suspended.")
-
- dominfo.setResume(True)
-
- dom_uuid = dominfo.get_uuid()
- chkpath = self._managed_check_point_path(dom_uuid)
- if not os.path.exists(chkpath):
- raise XendError("Domain was not suspended by Xend")
-
- # Restore that replaces the existing XendDomainInfo
- try:
- log.debug('Current DomainInfo state: %d' % dominfo._stateGet())
- oflags = os.O_RDONLY
- if hasattr(os, "O_LARGEFILE"):
- oflags |= os.O_LARGEFILE
- fd = os.open(chkpath, oflags)
- XendCheckpoint.restore(self,
- fd,
- dominfo,
- paused = start_paused)
- os.unlink(chkpath)
- except OSError, ex:
- raise XendError("Failed to read stored checkpoint file")
- except IOError, ex:
- raise XendError("Failed to delete checkpoint file")
- except Exception, ex:
- log.exception("Exception occurred when resuming")
- raise XendError("Error occurred when resuming: %s" % str(ex))
- finally:
- if fd is not None:
- os.close(fd)
- self.domains_lock.release()
-
-
- def domain_create(self, config):
- """Create a domain from a configuration.
-
- @param config: configuration
- @type config: SXP Object (list of lists)
- @rtype: XendDomainInfo
- """
- self.domains_lock.acquire()
- try:
- self._refresh()
-
- dominfo = XendDomainInfo.create(config)
- return dominfo
- finally:
- self.domains_lock.release()
-
-
- def domain_create_from_dict(self, config_dict):
- """Create a domain from a configuration dictionary.
-
- @param config_dict: configuration
- @rtype: XendDomainInfo
- """
- self.domains_lock.acquire()
- try:
- self._refresh()
-
- dominfo = XendDomainInfo.create_from_dict(config_dict)
- return dominfo
- finally:
- self.domains_lock.release()
-
-
- def domain_new(self, config):
- """Create a domain from a configuration but do not start it.
-
- @param config: configuration
- @type config: SXP Object (list of lists)
- @rtype: XendDomainInfo
- """
- self.domains_lock.acquire()
- try:
- try:
- domconfig = XendConfig.XendConfig(sxp_obj = config)
- dominfo = XendDomainInfo.createDormant(domconfig)
- log.debug("Creating new managed domain: %s" %
- dominfo.getName())
- self._managed_domain_register(dominfo)
- self.managed_config_save(dominfo)
- # no return value because it isn't meaningful for client
- except XendError, e:
- raise
- except Exception, e:
- raise XendError(str(e))
- finally:
- self.domains_lock.release()
-
- def domain_start(self, domid, start_paused = True):
- """Start a managed domain
-
- @require: Domain must not be running.
- @param domid: Domain name or domain ID.
- @type domid: string or int
- @rtype: None
- @raise XendError: If domain is still running
- @rtype: None
- """
- self.domains_lock.acquire()
- try:
- self._refresh()
-
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
-
- if dominfo._stateGet() != DOM_STATE_HALTED:
- raise VMBadState("Domain is already running",
- POWER_STATE_NAMES[DOM_STATE_HALTED],
- POWER_STATE_NAMES[dominfo._stateGet()])
-
- dominfo.start(is_managed = True)
- finally:
- self.domains_lock.release()
-
- try:
- dominfo.waitForDevices()
- except Exception, ex:
- log.warn("Failed to setup devices for " + str(dominfo) + ": " + str(ex))
- dominfo.destroy()
- raise
-
- if not start_paused:
- dominfo.unpause()
-
- def domain_delete(self, domid):
- """Remove a managed domain from database
-
- @require: Domain must not be running.
- @param domid: Domain name or domain ID.
- @type domid: string or int
- @rtype: None
- @raise XendError: If domain is still running
- """
- self.domains_lock.acquire()
- try:
- try:
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
-
- if dominfo._stateGet() != XEN_API_VM_POWER_STATE_HALTED:
- raise VMBadState("Domain is not halted.",
- POWER_STATE_NAMES[DOM_STATE_HALTED],
- POWER_STATE_NAMES[dominfo._stateGet()])
-
- self._domain_delete_by_info(dominfo)
- except Exception, ex:
- raise XendError(str(ex))
- finally:
- self.domains_lock.release()
-
-
- def domain_delete_by_dominfo(self, dominfo):
- """Only for use by XendDomainInfo.
- """
- self.domains_lock.acquire()
- try:
- self._domain_delete_by_info(dominfo)
- finally:
- self.domains_lock.release()
-
-
- def _domain_delete_by_info(self, dominfo):
- """Expects to be protected by domains_lock.
- """
- log.info("Domain %s (%s) deleted." %
- (dominfo.getName(), dominfo.info.get('uuid')))
-
- self._managed_domain_unregister(dominfo)
- self._remove_domain(dominfo)
- XendDevices.destroy_device_state(dominfo)
-
-
- def domain_configure(self, config):
- """Configure an existing domain.
-
- @param vmconfig: vm configuration
- @type vmconfig: SXP Object (list of lists)
- @todo: Not implemented
- """
- # !!!
- raise XendError("Unsupported")
-
- def domain_restore(self, src, paused=False):
- """Restore a domain from file.
-
- @param src: filename of checkpoint file to restore from
- @type src: string
- @return: Restored domain
- @rtype: XendDomainInfo
- @raise XendError: Failure to restore domain
- """
- try:
- oflags = os.O_RDONLY
- if hasattr(os, "O_LARGEFILE"):
- oflags |= os.O_LARGEFILE
- fd = os.open(src, oflags)
- try:
- return self.domain_restore_fd(fd, paused=paused)
- finally:
- os.close(fd)
- except OSError, ex:
- raise XendError("can't read guest state file %s: %s" %
- (src, ex[1]))
-
- def domain_restore_fd(self, fd, paused=False, relocating=False):
- """Restore a domain from the given file descriptor.
-
- @param fd: file descriptor of the checkpoint file
- @type fd: File object
- @rtype: XendDomainInfo
- @raise XendError: if failed to restore
- """
-
- try:
- self.policy_lock.acquire_reader()
-
- try:
- dominfo = XendCheckpoint.restore(self, fd, paused=paused, relocating=relocating)
- if relocating and \
- dominfo.info.has_key("change_home_server"):
- chs = (dominfo.info["change_home_server"] == "True")
- dominfo.setChangeHomeServer(None)
- if chs:
- self.domains_lock.acquire()
- try:
- log.debug("Migrating new managed domain: %s: %s" %
- (dominfo.getName(), dominfo.get_uuid()))
- self._managed_domain_register(dominfo)
- self.managed_config_save(dominfo)
- finally:
- self.domains_lock.release()
- return dominfo
- except XendError, e:
- log.exception("Restore failed")
- raise
- except:
- # I don't really want to log this exception here, but the error
- # handling in the relocation-socket handling code (relocate.py) is
- # poor, so we need to log this for debugging.
- log.exception("Restore failed")
- raise XendError("Restore failed")
- finally:
- self.policy_lock.release()
-
- def domain_unpause(self, domid):
- """Unpause domain execution.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @rtype: None
- @raise XendError: Failed to unpause
- @raise XendInvalidDomain: Domain is not valid
- """
- try:
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
- if dominfo.getDomid() == DOM0_ID:
- raise XendError("Cannot unpause privileged domain %s" % domid)
- if dominfo._stateGet() not in (DOM_STATE_PAUSED, DOM_STATE_RUNNING):
- raise VMBadState("Domain '%s' is not started" % domid,
- POWER_STATE_NAMES[DOM_STATE_PAUSED],
- POWER_STATE_NAMES[dominfo._stateGet()])
- log.info("Domain %s (%d) unpaused.", dominfo.getName(),
- int(dominfo.getDomid()))
- dominfo.unpause()
- except XendInvalidDomain:
- log.exception("domain_unpause")
- raise
- except Exception, ex:
- log.exception("domain_unpause")
- raise XendError(str(ex))
-
- def domain_pause(self, domid, state=False):
- """Pause domain execution.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @keyword state: If True, will return the domain state before pause
- @type state: bool
- @rtype: int if state is True
- @return: Domain state (DOM_STATE_*)
- @rtype: None if state is False
- @raise XendError: Failed to pause
- @raise XendInvalidDomain: Domain is not valid
- """
- try:
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
- if dominfo.getDomid() == DOM0_ID:
- raise XendError("Cannot pause privileged domain %s" % domid)
- ds = dominfo._stateGet()
- if ds not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED, DOM_STATE_CRASHED):
- raise VMBadState("Domain '%s' is not started" % domid,
- POWER_STATE_NAMES[DOM_STATE_RUNNING],
- POWER_STATE_NAMES[ds])
- log.info("Domain %s (%d) paused.", dominfo.getName(),
- int(dominfo.getDomid()))
- if ds == DOM_STATE_RUNNING:
- dominfo.pause()
- if state:
- return ds
- except XendInvalidDomain:
- log.exception("domain_pause")
- raise
- except Exception, ex:
- log.exception("domain_pause")
- raise XendError(str(ex))
-
- def domain_dump(self, domid, filename=None, live=False, crash=False, reset=False):
- """Dump domain core."""
-
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
-
- if dominfo.getDomid() == DOM0_ID:
- raise XendError("Cannot dump core for privileged domain %s" % domid)
- if dominfo._stateGet() not in (DOM_STATE_PAUSED, DOM_STATE_RUNNING, DOM_STATE_CRASHED):
- raise VMBadState("Domain '%s' is not started" % domid,
- POWER_STATE_NAMES[DOM_STATE_PAUSED],
- POWER_STATE_NAMES[dominfo._stateGet()])
-
- dopause = (not live and dominfo._stateGet() == DOM_STATE_RUNNING)
- if dopause:
- dominfo.pause()
-
- try:
- try:
- log.info("Domain core dump requested for domain %s (%d) "
- "live=%d crash=%d reset=%d.",
- dominfo.getName(), dominfo.getDomid(), live, crash, reset)
- dominfo.dumpCore(filename)
- if crash:
- self.domain_destroy(domid)
- elif reset:
- self.domain_reset(domid)
- except Exception, ex:
- raise XendError(str(ex))
- finally:
- if dopause and not crash and not reset:
- dominfo.unpause()
-
- def domain_destroy(self, domid):
- """Terminate domain immediately.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @rtype: None
- @raise XendError: Failed to destroy
- @raise XendInvalidDomain: Domain is not valid
- """
-
- dominfo = self.domain_lookup_nr(domid)
- if dominfo and dominfo.getDomid() == DOM0_ID:
- raise XendError("Cannot destroy privileged domain %s" % domid)
-
- if dominfo:
- val = dominfo.destroy()
- else:
- try:
- xc.domain_pause(int(domid))
- dom = self.domains[int(domid)]
- XendDomainInfo.do_FLR(int(domid), dom.info.is_hvm())
- val = xc.domain_destroy(int(domid))
- except ValueError:
- raise XendInvalidDomain(domid)
- except Exception, e:
- raise XendError(str(e))
-
- return val
-
- def domain_migrate(self, domid, dst, live=False, port=0, node=-1, ssl=None,\
- chs=False):
- """Start domain migration.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @param dst: Destination IP address
- @type dst: string
- @keyword live: Live migration
- @type live: bool
- @keyword port: relocation port on destination
- @type port: int
- @keyword node: use node number for target
- @type node: int
- @keyword ssl: use ssl connection
- @type ssl: bool
- @keyword chs: change home server for managed domain
- @type chs: bool
- @rtype: None
- @raise XendError: Failed to migrate
- @raise XendInvalidDomain: Domain is not valid
- """
-
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
-
- if dominfo.getDomid() == DOM0_ID:
- raise XendError("Cannot migrate privileged domain %s" % domid)
- if dominfo._stateGet() != DOM_STATE_RUNNING:
- raise VMBadState("Domain is not running",
- POWER_STATE_NAMES[DOM_STATE_RUNNING],
- POWER_STATE_NAMES[dominfo._stateGet()])
- if chs and not self.is_domain_managed(dominfo):
- raise XendError("Domain is not a managed domain")
-
- """ The following call may raise a XendError exception """
- dominfo.testMigrateDevices(True, dst)
-
- if live:
- """ Make sure there's memory free for enabling shadow mode """
- dominfo.checkLiveMigrateMemory()
-
- if ssl is None:
- ssl = xoptions.get_xend_relocation_ssl()
-
- try:
- dominfo.setChangeHomeServer(chs)
- if ssl:
- self._domain_migrate_by_ssl(dominfo, dst, live, port, node)
- else:
- self._domain_migrate(dominfo, dst, live, port, node)
- except:
- dominfo.setChangeHomeServer(None)
- raise
-
- def _domain_migrate_by_ssl(self, dominfo, dst, live, port, node):
- from OpenSSL import SSL
- from xen.web import connection
- if port == 0:
- port = xoptions.get_xend_relocation_ssl_port()
- try:
- ctx = SSL.Context(SSL.SSLv23_METHOD)
- sock = SSL.Connection(ctx,
- socket.socket(socket.AF_INET, socket.SOCK_STREAM))
- sock.set_connect_state()
- sock.connect((dst, port))
- sock.send("sslreceive\n")
- sock.recv(80)
- except SSL.Error, err:
- raise XendError("SSL error: %s" % err)
- except socket.error, err:
- raise XendError("can't connect: %s" % err)
-
- p2cread, p2cwrite = os.pipe()
- threading.Thread(target=connection.SSLSocketServerConnection.fd2send,
- args=(sock, p2cread)).start()
-
- try:
- try:
- XendCheckpoint.save(p2cwrite, dominfo, True, live, dst,
- node=node,sock=sock)
- except Exception, ex:
- m_dsterr = None
- try:
- sock.settimeout(3.0)
- dsterr = sock.recv(1024)
- sock.settimeout(None)
- if dsterr:
- # See send_error at relocate.py. If an error occurred
- # in a destination side, an error message with the
- # following form is returned from the destination
- # side.
- m_dsterr = \
- re.match(r"^\(err\s\(type\s(.+)\)\s\(value\s'(.+)'\)\)", dsterr)
- except:
- # Probably socket.timeout exception occurred.
- # Ignore the exception because it has nothing to do with
- # an exception of XendCheckpoint.save.
- pass
-
- if m_dsterr:
- raise XendError("%s (from %s)" % (m_dsterr.group(2), dst))
- raise
- finally:
- if not live:
- try:
- sock.shutdown(2)
- except:
- # Probably the socket is already disconnected by sock.close
- # in the destination side.
- # Ignore the exception because it has nothing to do with
- # an exception of XendCheckpoint.save.
- pass
- sock.close()
-
- os.close(p2cread)
- os.close(p2cwrite)
-
- def _domain_migrate(self, dominfo, dst, live, port, node):
- if port == 0:
- port = xoptions.get_xend_relocation_port()
- try:
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- # When connecting to our ssl enabled relocation server using a
- # plain socket, send will success but recv will block. Add a
- # 30 seconds timeout to raise a socket.timeout exception to
- # inform the client.
- sock.settimeout(30.0)
- sock.connect((dst, port))
- sock.send("receive\n")
- sock.recv(80)
- sock.settimeout(None)
- except socket.error, err:
- raise XendError("can't connect: %s" % err)
-
- try:
- try:
- XendCheckpoint.save(sock.fileno(), dominfo, True, live,
- dst, node=node,sock=sock)
- except Exception, ex:
- m_dsterr = None
- try:
- sock.settimeout(3.0)
- dsterr = sock.recv(1024)
- sock.settimeout(None)
- if dsterr:
- # See send_error at relocate.py. If an error occurred
- # in a destination side, an error message with the
- # following form is returned from the destination
- # side.
- m_dsterr = \
- re.match(r"^\(err\s\(type\s(.+)\)\s\(value\s'(.+)'\)\)", dsterr)
- except:
- # Probably socket.timeout exception occurred.
- # Ignore the exception because it has nothing to do with
- # an exception of XendCheckpoint.save.
- pass
-
- if m_dsterr:
- raise XendError("%s (from %s)" % (m_dsterr.group(2), dst))
- raise
- finally:
- if not live:
- try:
- sock.shutdown(2)
- except:
- # Probably the socket is already disconnected by sock.close
- # in the destination side.
- # Ignore the exception because it has nothing to do with
- # an exception of XendCheckpoint.save.
- pass
- sock.close()
-
- def domain_save(self, domid, dst, checkpoint=False):
- """Start saving a domain to file.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @param dst: Destination filename
- @type dst: string
- @rtype: None
- @raise XendError: Failed to save domain
- @raise XendInvalidDomain: Domain is not valid
- """
- try:
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
-
- if dominfo.getDomid() == DOM0_ID:
- raise XendError("Cannot save privileged domain %s" % str(domid))
- if dominfo._stateGet() != DOM_STATE_RUNNING:
- raise VMBadState("Domain is not running",
- POWER_STATE_NAMES[DOM_STATE_RUNNING],
- POWER_STATE_NAMES[dominfo._stateGet()])
-
- oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
- if hasattr(os, "O_LARGEFILE"):
- oflags |= os.O_LARGEFILE
- fd = os.open(dst, oflags)
- try:
- XendCheckpoint.save(fd, dominfo, False, False, dst,
- checkpoint=checkpoint)
- except Exception, e:
- os.close(fd)
- raise e
- os.close(fd)
- except OSError, ex:
- raise XendError("can't write guest state file %s: %s" %
- (dst, ex[1]))
-
- def domain_usb_add(self, domid, dev_id):
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
-
- usb = dominfo.info['platform'].get('usb')
- if not usb:
- raise XendError("Can't add usb device to a guest with usb disabled in configure file")
-
- hvm = dominfo.info.is_hvm()
- if not hvm:
- raise XendError("Can't add usb device to a non-hvm guest")
-
- if dominfo._stateGet() != DOM_STATE_HALTED:
- dominfo.image.signalDeviceModel("usb-add",
- "usb-added", dev_id)
- else:
- log.debug("error: Domain is not running!")
-
-
- def domain_usb_del(self, domid, dev_id):
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
-
- usb = dominfo.info['platform'].get('usb')
- if not usb:
- raise XendError("Can't add usb device to a guest with usb disabled in configure file")
-
- hvm = dominfo.info.is_hvm()
- if not hvm:
- raise XendError("Can't del usb to a non-hvm guest")
-
- if dominfo._stateGet() != DOM_STATE_HALTED:
- dominfo.image.signalDeviceModel("usb-del",
- "usb-deleted", dev_id)
- else:
- log.debug("error: Domain is not running!")
-
- def domain_pincpu(self, domid, vcpu, cpumap):
- """Set which cpus vcpu can use
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @param vcpu: vcpu to pin to
- @type vcpu: int
- @param cpumap: string repr of usable cpus
- @type cpumap: string
- @rtype: 0
- """
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
-
- # if vcpu is keyword 'all', apply the cpumap to all vcpus
- if str(vcpu).lower() == "all":
- vcpus = range(0, int(dominfo.getVCpuCount()))
- else:
- vcpus = [ int(vcpu) ]
-
- # set the same cpumask for all vcpus
- rc = 0
- cpus = dominfo.getCpus()
- cpumap = map(int, cpumap.split(","))
- for v in vcpus:
- try:
- if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
- rc = xc.vcpu_setaffinity(dominfo.getDomid(), v, cpumap)
- cpus[v] = cpumap
- except Exception, ex:
- log.exception(ex)
- raise XendError("Cannot pin vcpu: %d to cpu: %s - %s" % \
- (v, cpumap, str(ex)))
- dominfo.setCpus(cpus)
- self.managed_config_save(dominfo)
-
- return rc
-
- def domain_cpu_sedf_set(self, domid, period, slice_, latency, extratime,
- weight):
- """Set Simple EDF scheduler parameters for a domain.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @rtype: 0
- """
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
- try:
- return xc.sedf_domain_set(dominfo.getDomid(), period, slice_,
- latency, extratime, weight)
- except Exception, ex:
- raise XendError(str(ex))
-
- def domain_cpu_sedf_get(self, domid):
- """Get Simple EDF scheduler parameters for a domain.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @rtype: SXP object
- @return: The parameters for Simple EDF schedule for a domain.
- """
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
- try:
- sedf_info = xc.sedf_domain_get(dominfo.getDomid())
- # return sxpr
- return ['sedf',
- ['domid', sedf_info['domid']],
- ['period', sedf_info['period']],
- ['slice', sedf_info['slice']],
- ['latency', sedf_info['latency']],
- ['extratime', sedf_info['extratime']],
- ['weight', sedf_info['weight']]]
-
- except Exception, ex:
- raise XendError(str(ex))
-
- def domain_shadow_control(self, domid, op):
- """Shadow page control.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @param op: operation
- @type op: int
- @rtype: 0
- """
- dominfo = self.domain_lookup(domid)
- try:
- return xc.shadow_control(dominfo.getDomid(), op)
- except Exception, ex:
- raise XendError(str(ex))
-
- def domain_shadow_mem_get(self, domid):
- """Get shadow pagetable memory allocation.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @rtype: int
- @return: shadow memory in MB
- """
- dominfo = self.domain_lookup(domid)
- try:
- return xc.shadow_mem_control(dominfo.getDomid())
- except Exception, ex:
- raise XendError(str(ex))
-
- def domain_shadow_mem_set(self, domid, mb):
- """Set shadow pagetable memory allocation.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @param mb: shadow memory to set in MB
- @type: mb: int
- @rtype: int
- @return: shadow memory in MB
- """
- dominfo = self.domain_lookup(domid)
- try:
- return xc.shadow_mem_control(dominfo.getDomid(), mb=mb)
- except Exception, ex:
- raise XendError(str(ex))
-
- def domain_sched_credit_get(self, domid):
- """Get credit scheduler parameters for a domain.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @rtype: dict with keys 'weight' and 'cap'
- @return: credit scheduler parameters
- """
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
-
- if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
- try:
- return xc.sched_credit_domain_get(dominfo.getDomid())
- except Exception, ex:
- raise XendError(str(ex))
- else:
- return {'weight' : dominfo.getWeight(),
- 'cap' : dominfo.getCap()}
-
- def domain_sched_credit_set(self, domid, weight = None, cap = None):
- """Set credit scheduler parameters for a domain.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @type weight: int
- @type cap: int
- @rtype: 0
- """
- set_weight = False
- set_cap = False
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
- try:
- if weight is None:
- weight = int(0)
- elif weight < 1 or weight > 65535:
- raise XendError("Cpu weight out of range, valid values are "
- "within range from 1 to 65535")
- else:
- set_weight = True
-
- if cap is None:
- cap = int(~0)
- elif cap < 0 or cap > dominfo.getVCpuCount() * 100:
- raise XendError("Cpu cap out of range, valid range is "
- "from 0 to %s for specified number of vcpus" %
- (dominfo.getVCpuCount() * 100))
- else:
- set_cap = True
-
- assert type(weight) == int
- assert type(cap) == int
-
- rc = 0
- if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
- rc = xc.sched_credit_domain_set(dominfo.getDomid(), weight, cap)
- if rc == 0:
- if set_weight:
- dominfo.setWeight(weight)
- if set_cap:
- dominfo.setCap(cap)
- self.managed_config_save(dominfo)
- return rc
- except Exception, ex:
- log.exception(ex)
- raise XendError(str(ex))
-
- def domain_sched_credit2_get(self, domid):
- """Get credit2 scheduler parameters for a domain.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @rtype: dict with keys 'weight'
- @return: credit2 scheduler parameters
- """
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
-
- if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
- try:
- return xc.sched_credit2_domain_get(dominfo.getDomid())
- except Exception, ex:
- raise XendError(str(ex))
- else:
- return {'weight' : dominfo.getWeight()}
-
- def domain_sched_credit2_set(self, domid, weight = None):
- """Set credit2 scheduler parameters for a domain.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @type weight: int
- @rtype: 0
- """
- set_weight = False
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
- try:
- if weight is None:
- weight = int(0)
- elif weight < 1 or weight > 65535:
- raise XendError("weight is out of range")
- else:
- set_weight = True
-
- assert type(weight) == int
-
- rc = 0
- if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
- rc = xc.sched_credit2_domain_set(dominfo.getDomid(), weight)
- if rc == 0:
- if set_weight:
- dominfo.setWeight(weight)
- self.managed_config_save(dominfo)
- return rc
- except Exception, ex:
- log.exception(ex)
- raise XendError(str(ex))
-
- def domain_maxmem_set(self, domid, mem):
- """Set the memory limit for a domain.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @param mem: memory limit (in MiB)
- @type mem: int
- @raise XendError: fail to set memory
- @rtype: 0
- """
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
- dominfo.setMemoryMaximum(mem)
-
- def domain_ioport_range_enable(self, domid, first, last):
- """Enable access to a range of IO ports for a domain
-
- @param first: first IO port
- @param last: last IO port
- @raise XendError: failed to set range
- @rtype: 0
- """
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
- nr_ports = last - first + 1
- try:
- return xc.domain_ioport_permission(dominfo.getDomid(),
- first_port = first,
- nr_ports = nr_ports,
- allow_access = 1)
- except Exception, ex:
- raise XendError(str(ex))
-
- def domain_ioport_range_disable(self, domid, first, last):
- """Disable access to a range of IO ports for a domain
-
- @param first: first IO port
- @param last: last IO port
- @raise XendError: failed to set range
- @rtype: 0
- """
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
- nr_ports = last - first + 1
- try:
- return xc.domain_ioport_permission(dominfo.getDomid(),
- first_port = first,
- nr_ports = nr_ports,
- allow_access = 0)
- except Exception, ex:
- raise XendError(str(ex))
-
- def domain_send_trigger(self, domid, trigger_name, vcpu = 0):
- """Send trigger to a domain.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @param trigger_name: trigger type name
- @type trigger_name: string
- @param vcpu: VCPU to send trigger (default is 0)
- @type vcpu: int
- @raise XendError: failed to send trigger
- @raise XendInvalidDomain: Domain is not valid
- @rtype: 0
- """
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
- if dominfo._stateGet() not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
- raise VMBadState("Domain '%s' is not started" % domid,
- POWER_STATE_NAMES[DOM_STATE_RUNNING],
- POWER_STATE_NAMES[dominfo._stateGet()])
- if trigger_name.lower() in TRIGGER_TYPE.keys():
- trigger = TRIGGER_TYPE[trigger_name.lower()]
- else:
- raise XendError("Invalid trigger: %s" % trigger_name)
- if trigger == TRIGGER_S3RESUME:
- xc.hvm_set_param(dominfo.getDomid(), HVM_PARAM_ACPI_S_STATE, 0)
- return None
- try:
- return xc.domain_send_trigger(dominfo.getDomid(),
- trigger,
- vcpu)
- except Exception, ex:
- raise XendError(str(ex))
-
- def domain_reset(self, domid):
- """Terminate domain immediately, and then create domain.
-
- @param domid: Domain ID or Name
- @type domid: int or string.
- @rtype: None
- @raise XendError: Failed to destroy or create
- @raise XendInvalidDomain: Domain is not valid
- """
-
- dominfo = self.domain_lookup_nr(domid)
- if not dominfo:
- raise XendInvalidDomain(str(domid))
- if dominfo and dominfo.getDomid() == DOM0_ID:
- raise XendError("Cannot reset privileged domain %s" % domid)
- if dominfo._stateGet() not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
- raise VMBadState("Domain '%s' is not started" % domid,
- POWER_STATE_NAMES[DOM_STATE_RUNNING],
- POWER_STATE_NAMES[dominfo._stateGet()])
- try:
- dominfo.resetDomain()
- except Exception, ex:
- raise XendError(str(ex))
-
-
-def instance():
- """Singleton constructor. Use this instead of the class constructor.
- """
- global inst
- try:
- inst
- except:
- inst = XendDomain()
- inst.init()
- return inst
diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py
deleted file mode 100644
index 8d4ff5c..0000000
--- a/tools/python/xen/xend/XendDomainInfo.py
+++ /dev/null
@@ -1,4429 +0,0 @@
-#===========================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005-2007 XenSource Ltd
-#============================================================================
-
-"""Representation of a single domain.
-Includes support for domain construction, using
-open-ended configurations.
-
-Author: Mike Wray <mike.wray at hp.com>
-
-"""
-
-import logging
-import time
-import threading
-import thread
-import re
-import copy
-import os
-import stat
-import shutil
-import traceback
-from types import StringTypes
-import errno
-
-import xen.lowlevel.xc
-from xen.lowlevel.xc import Error as XCError
-from xen.util import asserts, auxbin, mkdir
-from xen.util.blkif import parse_uname
-import xen.util.xsm.xsm as security
-from xen.util import xsconstants
-from xen.util import mkdir
-from xen.util.pci import serialise_pci_opts, pci_opts_list_to_sxp, \
- append_default_pci_opts, \
- pci_dict_to_bdf_str, pci_dict_to_xc_str, \
- pci_convert_sxp_to_dict, pci_convert_dict_to_sxp, \
- pci_dict_cmp, PCI_DEVFN, PCI_SLOT, PCI_FUNC, parse_hex
-
-from xen.xend import balloon, sxp, uuid, image, arch
-from xen.xend import XendOptions, XendNode, XendConfig
-
-from xen.xend.XendConfig import scrub_password
-from xen.xend.XendBootloader import bootloader, bootloader_tidy
-from xen.xend.XendError import XendError, VmError
-from xen.xend.XendDevices import XendDevices
-from xen.xend.XendTask import XendTask
-from xen.xend.xenstore.xstransact import xstransact, complete
-from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain, SetTarget, ResumeDomain
-from xen.xend.xenstore.xswatch import xswatch
-from xen.xend.XendConstants import *
-from xen.xend.XendAPIConstants import *
-from xen.xend.XendCPUPool import XendCPUPool
-from xen.xend.server.DevConstants import xenbusState
-from xen.xend.server.BlktapController import TapdiskController
-
-from xen.xend.XendVMMetrics import XendVMMetrics
-
-from xen.xend import XendAPIStore
-from xen.xend.XendPPCI import XendPPCI
-from xen.xend.XendDPCI import XendDPCI
-from xen.xend.XendPSCSI import XendPSCSI
-from xen.xend.XendDSCSI import XendDSCSI, XendDSCSI_HBA
-
-MIGRATE_TIMEOUT = 30.0
-BOOTLOADER_LOOPBACK_DEVICE = '/dev/xvdp'
-
-xc = xen.lowlevel.xc.xc()
-xoptions = XendOptions.instance()
-
-log = logging.getLogger("xend.XendDomainInfo")
-#log.setLevel(logging.TRACE)
-
-
-def create(config):
- """Creates and start a VM using the supplied configuration.
-
- @param config: A configuration object involving lists of tuples.
- @type config: list of lists, eg ['vm', ['image', 'xen.gz']]
-
- @rtype: XendDomainInfo
- @return: An up and running XendDomainInfo instance
- @raise VmError: Invalid configuration or failure to start.
- """
- from xen.xend import XendDomain
- domconfig = XendConfig.XendConfig(sxp_obj = config)
- othervm = XendDomain.instance().domain_lookup_nr(domconfig["name_label"])
- if othervm is None or othervm.domid is None:
- othervm = XendDomain.instance().domain_lookup_nr(domconfig["uuid"])
- if othervm is not None and othervm.domid is not None:
- raise VmError("Domain '%s' already exists with ID '%d'" % (domconfig["name_label"], othervm.domid))
- log.debug("XendDomainInfo.create(%s)", scrub_password(config))
- vm = XendDomainInfo(domconfig)
- try:
- vm.start()
- except:
- log.exception('Domain construction failed')
- vm.destroy()
- raise
-
- return vm
-
-def create_from_dict(config_dict):
- """Creates and start a VM using the supplied configuration.
-
- @param config_dict: An configuration dictionary.
-
- @rtype: XendDomainInfo
- @return: An up and running XendDomainInfo instance
- @raise VmError: Invalid configuration or failure to start.
- """
-
- log.debug("XendDomainInfo.create_from_dict(%s)",
- scrub_password(config_dict))
- vm = XendDomainInfo(XendConfig.XendConfig(xapi = config_dict))
- try:
- vm.start()
- except:
- log.exception('Domain construction failed')
- vm.destroy()
- raise
- return vm
-
-def recreate(info, priv):
- """Create the VM object for an existing domain. The domain must not
- be dying, as the paths in the store should already have been removed,
- and asking us to recreate them causes problems.
-
- @param xeninfo: Parsed configuration
- @type xeninfo: Dictionary
- @param priv: Is a privileged domain (Dom 0)
- @type priv: bool
-
- @rtype: XendDomainInfo
- @return: A up and running XendDomainInfo instance
- @raise VmError: Invalid configuration.
- @raise XendError: Errors with configuration.
- """
-
- log.debug("XendDomainInfo.recreate(%s)", scrub_password(info))
-
- assert not info['dying']
-
- xeninfo = XendConfig.XendConfig(dominfo = info)
- xeninfo['is_control_domain'] = priv
- xeninfo['is_a_template'] = False
- xeninfo['auto_power_on'] = False
- domid = xeninfo['domid']
- uuid1 = uuid.fromString(xeninfo['uuid'])
- needs_reinitialising = False
-
- dompath = GetDomainPath(domid)
- if not dompath:
- raise XendError('No domain path in store for existing '
- 'domain %d' % domid)
-
- log.info("Recreating domain %d, UUID %s. at %s" %
- (domid, xeninfo['uuid'], dompath))
-
- # need to verify the path and uuid if not Domain-0
- # if the required uuid and vm aren't set, then that means
- # we need to recreate the dom with our own values
- #
- # NOTE: this is probably not desirable, really we should just
- # abort or ignore, but there may be cases where xenstore's
- # entry disappears (eg. xenstore-rm /)
- #
- try:
- vmpath = xstransact.Read(dompath, "vm")
- if not vmpath:
- if not priv:
- log.warn('/local/domain/%d/vm is missing. recreate is '
- 'confused, trying our best to recover' % domid)
- needs_reinitialising = True
- raise XendError('reinit')
-
- uuid2_str = xstransact.Read(vmpath, "uuid")
- if not uuid2_str:
- log.warn('%s/uuid/ is missing. recreate is confused, '
- 'trying our best to recover' % vmpath)
- needs_reinitialising = True
- raise XendError('reinit')
-
- uuid2 = uuid.fromString(uuid2_str)
- if uuid1 != uuid2:
- log.warn('UUID in /vm does not match the UUID in /dom/%d.'
- 'Trying out best to recover' % domid)
- needs_reinitialising = True
- except XendError:
- pass # our best shot at 'goto' in python :)
-
- vm = XendDomainInfo(xeninfo, domid, dompath, augment = True, priv = priv,
- vmpath = vmpath)
-
- if needs_reinitialising:
- vm._recreateDom()
- vm._removeVm()
- vm._storeVmDetails()
- vm._storeDomDetails()
-
- vm.image = image.create(vm, vm.info)
- vm.image.recreate()
-
- vm._registerWatches()
- vm.refreshShutdown(xeninfo)
-
- # register the domain in the list
- from xen.xend import XendDomain
- XendDomain.instance().add_domain(vm)
-
- return vm
-
-
-def restore(config):
- """Create a domain and a VM object to do a restore.
-
- @param config: Domain SXP configuration
- @type config: list of lists. (see C{create})
-
- @rtype: XendDomainInfo
- @return: A up and running XendDomainInfo instance
- @raise VmError: Invalid configuration or failure to start.
- @raise XendError: Errors with configuration.
- """
-
- log.debug("XendDomainInfo.restore(%s)", scrub_password(config))
- vm = XendDomainInfo(XendConfig.XendConfig(sxp_obj = config),
- resume = True)
- try:
- vm.resume()
- return vm
- except:
- vm.destroy()
- raise
-
-def createDormant(domconfig):
- """Create a dormant/inactive XenDomainInfo without creating VM.
- This is for creating instances of persistent domains that are not
- yet start.
-
- @param domconfig: Parsed configuration
- @type domconfig: XendConfig object
-
- @rtype: XendDomainInfo
- @return: A up and running XendDomainInfo instance
- @raise XendError: Errors with configuration.
- """
-
- log.debug("XendDomainInfo.createDormant(%s)", scrub_password(domconfig))
-
- # domid does not make sense for non-running domains.
- domconfig.pop('domid', None)
- vm = XendDomainInfo(domconfig)
- return vm
-
-def domain_by_name(name):
- """Get domain by name
-
- @params name: Name of the domain
- @type name: string
- @return: XendDomainInfo or None
- """
- from xen.xend import XendDomain
- return XendDomain.instance().domain_lookup_by_name_nr(name)
-
-
-def shutdown_reason(code):
- """Get a shutdown reason from a code.
-
- @param code: shutdown code
- @type code: int
- @return: shutdown reason
- @rtype: string
- """
- return DOMAIN_SHUTDOWN_REASONS.get(code, "?")
-
-def dom_get(dom):
- """Get info from xen for an existing domain.
-
- @param dom: domain id
- @type dom: int
- @return: info or None
- @rtype: dictionary
- """
- try:
- domlist = xc.domain_getinfo(dom, 1)
- if domlist and dom == domlist[0]['domid']:
- return domlist[0]
- except Exception, err:
- # ignore missing domain
- log.trace("domain_getinfo(%d) failed, ignoring: %s", dom, str(err))
- return None
-
-from xen.xend.server.pciif import parse_pci_name, PciDevice,\
- get_assigned_pci_devices, get_all_assigned_pci_devices
-
-
-def do_FLR(domid, is_hvm):
- dev_str_list = get_assigned_pci_devices(domid)
-
- for dev_str in dev_str_list:
- try:
- dev = PciDevice(parse_pci_name(dev_str))
- except Exception, e:
- raise VmError("pci: failed to locate device and "+
- "parse it's resources - "+str(e))
- dev.do_FLR(is_hvm, xoptions.get_pci_dev_assign_strict_check())
-
-class XendDomainInfo:
- """An object represents a domain.
-
- @TODO: try to unify dom and domid, they mean the same thing, but
- xc refers to it as dom, and everywhere else, including
- xenstore it is domid. The best way is to change xc's
- python interface.
-
- @ivar info: Parsed configuration
- @type info: dictionary
- @ivar domid: Domain ID (if VM has started)
- @type domid: int or None
- @ivar paused_by_admin: Is this Domain paused by command or API
- @type paused_by_admin: bool
- @ivar guest_bitsize: the bitsize of guest
- @type guest_bitsize: int or None
- @ivar alloc_mem: the memory domain allocated when booting
- @type alloc_mem: int or None
- @ivar vmpath: XenStore path to this VM.
- @type vmpath: string
- @ivar dompath: XenStore path to this Domain.
- @type dompath: string
- @ivar image: Reference to the VM Image.
- @type image: xen.xend.image.ImageHandler
- @ivar store_port: event channel to xenstored
- @type store_port: int
- @ivar console_port: event channel to xenconsoled
- @type console_port: int
- @ivar store_mfn: xenstored mfn
- @type store_mfn: int
- @ivar console_mfn: xenconsoled mfn
- @type console_mfn: int
- @ivar notes: OS image notes
- @type notes: dictionary
- @ivar vmWatch: reference to a watch on the xenstored vmpath
- @type vmWatch: xen.xend.xenstore.xswatch
- @ivar shutdownWatch: reference to watch on the xenstored domain shutdown
- @type shutdownWatch: xen.xend.xenstore.xswatch
- @ivar shutdownStartTime: UNIX Time when domain started shutting down.
- @type shutdownStartTime: float or None
- @ivar restart_in_progress: Is a domain restart thread running?
- @type restart_in_progress: bool
-# @ivar state: Domain state
-# @type state: enum(DOM_STATE_HALTED, DOM_STATE_RUNNING, ...)
- @ivar state_updated: lock for self.state
- @type state_updated: threading.Condition
- @ivar refresh_shutdown_lock: lock for polling shutdown state
- @type refresh_shutdown_lock: threading.Condition
- @ivar _deviceControllers: device controller cache for this domain
- @type _deviceControllers: dict 'string' to DevControllers
- """
-
- def __init__(self, info, domid = None, dompath = None, augment = False,
- priv = False, resume = False, vmpath = None):
- """Constructor for a domain
-
- @param info: parsed configuration
- @type info: dictionary
- @keyword domid: Set initial domain id (if any)
- @type domid: int
- @keyword dompath: Set initial dompath (if any)
- @type dompath: string
- @keyword augment: Augment given info with xenstored VM info
- @type augment: bool
- @keyword priv: Is a privileged domain (Dom 0)
- @type priv: bool
- @keyword resume: Is this domain being resumed?
- @type resume: bool
- """
-
- self.info = info
- if domid == None:
- self.domid = self.info.get('domid')
- else:
- self.domid = domid
- self.guest_bitsize = None
- self.alloc_mem = None
- self.paused_by_admin = False
-
- maxmem = self.info.get('memory_static_max', 0)
- memory = self.info.get('memory_dynamic_max', 0)
-
- if self.info.is_hvm() and maxmem > memory:
- self.pod_enabled = True
- else:
- self.pod_enabled = False
-
- #REMOVE: uuid is now generated in XendConfig
- #if not self._infoIsSet('uuid'):
- # self.info['uuid'] = uuid.toString(uuid.create())
-
- # Find a unique /vm/<uuid>/<integer> path if not specified.
- # This avoids conflict between pre-/post-migrate domains when doing
- # localhost relocation.
- self.vmpath = vmpath
- i = 0
- while self.vmpath == None:
- self.vmpath = XS_VMROOT + self.info['uuid']
- if i != 0:
- self.vmpath = self.vmpath + '-' + str(i)
- try:
- if self._readVm("uuid"):
- self.vmpath = None
- i = i + 1
- except:
- pass
-
- self.dompath = dompath
-
- self.image = None
- self.store_port = None
- self.store_mfn = None
- self.console_port = None
- self.console_mfn = None
-
- self.native_protocol = None
-
- self.vmWatch = None
- self.shutdownWatch = None
- self.shutdownStartTime = None
- self._resume = resume
- self.restart_in_progress = False
-
- self.state_updated = threading.Condition()
- self.refresh_shutdown_lock = threading.Condition()
- self._stateSet(DOM_STATE_HALTED)
-
- self._deviceControllers = {}
-
- for state in DOM_STATES_OLD:
- self.info[state] = 0
-
- if augment:
- self._augmentInfo(priv)
-
- self._checkName(self.info['name_label'])
-
- self.metrics = XendVMMetrics(uuid.createString(), self)
-
-
- #
- # Public functions available through XMLRPC
- #
-
-
- def start(self, is_managed = False):
- """Attempts to start the VM by do the appropriate
- initialisation if it not started.
- """
- from xen.xend import XendDomain
-
- if self._stateGet() in (XEN_API_VM_POWER_STATE_HALTED, XEN_API_VM_POWER_STATE_SUSPENDED, XEN_API_VM_POWER_STATE_CRASHED):
- try:
- XendTask.log_progress(0, 30, self._constructDomain)
- XendTask.log_progress(31, 60, self._initDomain)
-
- XendTask.log_progress(61, 70, self._storeVmDetails)
- XendTask.log_progress(71, 80, self._storeDomDetails)
- XendTask.log_progress(81, 90, self._registerWatches)
- XendTask.log_progress(91, 100, self.refreshShutdown)
-
- xendomains = XendDomain.instance()
-
- # save running configuration if XendDomains believe domain is
- # persistent
- if is_managed:
- xendomains.managed_config_save(self)
- except:
- log.exception('VM start failed')
- self.destroy()
- raise
- else:
- raise XendError('VM already running')
-
- def resume(self):
- """Resumes a domain that has come back from suspension."""
- state = self._stateGet()
- if state in (DOM_STATE_SUSPENDED, DOM_STATE_HALTED):
- try:
- self._constructDomain()
-
- try:
- self._setCPUAffinity()
- except:
- # usually a CPU we want to set affinity to does not exist
- # we just ignore it so that the domain can still be restored
- log.warn("Cannot restore CPU affinity")
-
- self._setSchedParams()
- self._storeVmDetails()
- self._createChannels()
- self._createDevices()
- self._storeDomDetails()
- self._endRestore()
- except:
- log.exception('VM resume failed')
- self.destroy()
- raise
- else:
- raise XendError('VM is not suspended; it is %s'
- % XEN_API_VM_POWER_STATE[state])
-
- def shutdown(self, reason):
- """Shutdown a domain by signalling this via xenstored."""
- log.debug('XendDomainInfo.shutdown(%s)', reason)
- if self._stateGet() in (DOM_STATE_SHUTDOWN, DOM_STATE_HALTED,):
- raise XendError('Domain cannot be shutdown')
-
- if self.domid == 0:
- raise XendError('Domain 0 cannot be shutdown')
-
- if reason not in DOMAIN_SHUTDOWN_REASONS.values():
- raise XendError('Invalid reason: %s' % reason)
- self.storeDom("control/shutdown", reason)
-
- # HVM domain shuts itself down only if it has PV drivers
- if self.info.is_hvm():
- hvm_pvdrv = xc.hvm_get_param(self.domid, HVM_PARAM_CALLBACK_IRQ)
- hvm_s_state = xc.hvm_get_param(self.domid, HVM_PARAM_ACPI_S_STATE)
- if not hvm_pvdrv or hvm_s_state != 0:
- code = REVERSE_DOMAIN_SHUTDOWN_REASONS[reason]
- log.info("HVM save:remote shutdown dom %d!", self.domid)
- xc.domain_shutdown(self.domid, code)
-
- def pause(self):
- """Pause domain
-
- @raise XendError: Failed pausing a domain
- """
- try:
- if(self.domid):
- # get all blktap2 devices
- dev = xstransact.List(self.vmpath + '/device/tap2')
- for x in dev:
- path = self.getDeviceController('tap2').readBackend(x, 'params')
- if path and path.startswith(TapdiskController.TAP_DEV):
- TapdiskController.pause(path)
- except Exception, ex:
- log.warn('Could not pause blktap disk.');
-
- try:
- xc.domain_pause(self.domid)
- self._stateSet(DOM_STATE_PAUSED)
- except Exception, ex:
- log.exception(ex)
- raise XendError("Domain unable to be paused: %s" % str(ex))
-
- def unpause(self):
- """Unpause domain
-
- @raise XendError: Failed unpausing a domain
- """
- try:
- if(self.domid):
- dev = xstransact.List(self.vmpath + '/device/tap2')
- for x in dev:
- path = self.getDeviceController('tap2').readBackend(x, 'params')
- if path and path.startswith(TapdiskController.TAP_DEV):
- TapdiskController.unpause(path)
-
- except Exception, ex:
- log.warn('Could not unpause blktap disk: %s' % str(ex));
-
- try:
- xc.domain_unpause(self.domid)
- self._stateSet(DOM_STATE_RUNNING)
- except Exception, ex:
- log.exception(ex)
- raise XendError("Domain unable to be unpaused: %s" % str(ex))
-
- def send_sysrq(self, key):
- """ Send a Sysrq equivalent key via xenstored."""
- if self._stateGet() not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
- raise XendError("Domain '%s' is not started" % self.info['name_label'])
-
- asserts.isCharConvertible(key)
- self.storeDom("control/sysrq", '%c' % key)
-
- def pci_device_configure_boot(self):
-
- if not self.info.is_hvm():
- return
-
- devid = '0'
- first = True
- dev_info = self._getDeviceInfo_pci(devid)
- if dev_info is None:
- return
-
- # get the virtual slot info from xenstore
- dev_uuid = sxp.child_value(dev_info, 'uuid')
- pci_conf = self.info['devices'][dev_uuid][1]
- pci_devs = pci_conf['devs']
-
- # Keep a set of keys that are done rather than
- # just itterating through set(map(..., pci_devs))
- # to preserve any order information present.
- done = set()
- for key in map(lambda x: x['key'], pci_devs):
- if key in done:
- continue
- done |= set([key])
- dev = filter(lambda x: x['key'] == key, pci_devs)
-
- head_dev = dev.pop()
- dev_sxp = pci_convert_dict_to_sxp(head_dev, 'Initialising',
- 'Booting')
- self.pci_device_configure(dev_sxp, first_dev = first)
- first = False
-
- # That is all for single-function virtual devices
- if len(dev) == 0:
- continue
-
- if int(head_dev['vdevfn'], 16) & AUTO_PHP_SLOT:
- new_dev_info = self._getDeviceInfo_pci(devid)
- if new_dev_info is None:
- continue
- new_dev_uuid = sxp.child_value(new_dev_info, 'uuid')
- new_pci_conf = self.info['devices'][new_dev_uuid][1]
- new_pci_devs = new_pci_conf['devs']
-
- new_head_dev = filter(lambda x: pci_dict_cmp(x, head_dev),
- new_pci_devs)[0]
-
- if int(new_head_dev['vdevfn'], 16) & AUTO_PHP_SLOT:
- continue
-
- vdevfn = PCI_SLOT(int(new_head_dev['vdevfn'], 16))
- new_dev = []
- for i in dev:
- i['vdevfn'] = '0x%02x' % \
- PCI_DEVFN(vdevfn,
- PCI_FUNC(int(i['vdevfn'], 16)))
- new_dev.append(i)
-
- dev = new_dev
-
- for i in dev:
- dev_sxp = pci_convert_dict_to_sxp(i, 'Initialising', 'Booting')
- self.pci_device_configure(dev_sxp)
-
- def hvm_pci_device_create(self, dev_config):
- log.debug("XendDomainInfo.hvm_pci_device_create: %s"
- % scrub_password(dev_config))
-
- if not self.info.is_hvm():
- raise VmError("hvm_pci_device_create called on non-HVM guest")
-
- #all the PCI devs share one conf node
- devid = '0'
-
- new_dev = dev_config['devs'][0]
- dev_info = self._getDeviceInfo_pci(devid)#from self.info['devices']
-
- #check conflict before trigger hotplug event
- if dev_info is not None:
- dev_uuid = sxp.child_value(dev_info, 'uuid')
- pci_conf = self.info['devices'][dev_uuid][1]
- pci_devs = pci_conf['devs']
- for x in pci_devs:
- if (int(x['vdevfn'], 16) == int(new_dev['vdevfn'], 16) and
- not int(x['vdevfn'], 16) & AUTO_PHP_SLOT):
- raise VmError("vdevfn %s already have a device." %
- (new_dev['vdevfn']))
-
- if (pci_dict_cmp(x, new_dev)):
- raise VmError("device is already inserted")
-
- # Test whether the devices can be assigned.
- self.pci_dev_check_attachability_and_do_FLR(new_dev)
-
- return self.hvm_pci_device_insert_dev(new_dev)
-
- def iommu_check_pod_mode(self):
- """ Disallow PCI device assignment if pod is enabled. """
- if self.pod_enabled:
- raise VmError("failed to assign device since pod is enabled")
-
- def pci_dev_check_assignability_and_do_FLR(self, config):
- """ In the case of static device assignment(i.e., the 'pci' string in
- guest config file), we check if the device(s) specified in the 'pci'
- can be assigned to guest or not; if yes, we do_FLR the device(s).
- """
-
- self.iommu_check_pod_mode()
- pci_dev_ctrl = self.getDeviceController('pci')
- return pci_dev_ctrl.dev_check_assignability_and_do_FLR(config)
-
- def pci_dev_check_attachability_and_do_FLR(self, new_dev):
- """ In the case of dynamic device assignment(i.e., xm pci-attach), we
- check if the device can be attached to guest or not; if yes, we do_FLR
- the device.
- """
-
- self.iommu_check_pod_mode()
-
- # Test whether the devices can be assigned
-
- pci_name = pci_dict_to_bdf_str(new_dev)
- _all_assigned_pci_devices = get_all_assigned_pci_devices(self.domid)
- if pci_name in _all_assigned_pci_devices:
- raise VmError("failed to assign device %s that has"
- " already been assigned to other domain." % pci_name)
-
- # Test whether the device is owned by pciback or pci-stub.
- try:
- pci_device = PciDevice(new_dev)
- except Exception, e:
- raise VmError("pci: failed to locate device and "+
- "parse its resources - "+str(e))
- if pci_device.driver!='pciback' and pci_device.driver!='pci-stub':
- raise VmError(("pci: PCI Backend and pci-stub don't own device %s")\
- %pci_device.name)
-
- strict_check = xoptions.get_pci_dev_assign_strict_check()
- # Check non-page-aligned MMIO BAR.
- if pci_device.has_non_page_aligned_bar and strict_check:
- raise VmError("pci: %s: non-page-aligned MMIO BAR found." % \
- pci_device.name)
-
- # PV guest has less checkings.
- if not self.info.is_hvm():
- # try to do FLR for PV guest
- pci_device.do_FLR(self.info.is_hvm(), strict_check)
- return
-
- if not strict_check:
- return
-
- # Check if there is intermediate PCIe switch bewteen the device and
- # Root Complex.
- if pci_device.is_behind_switch_lacking_acs():
- err_msg = 'pci: to avoid potential security issue, %s is not'+\
- ' allowed to be assigned to guest since it is behind'+\
- ' PCIe switch that does not support or enable ACS.'
- raise VmError(err_msg % pci_device.name)
-
- # Check the co-assignment.
- # To pci-attach a device D to domN, we should ensure each of D's
- # co-assignment devices hasn't been assigned, or has been assigned to
- # domN.
- coassignment_list = pci_device.find_coassigned_devices()
- pci_device.devs_check_driver(coassignment_list)
- assigned_pci_device_str_list = self._get_assigned_pci_devices()
- for pci_str in coassignment_list:
- if not (pci_str in _all_assigned_pci_devices):
- continue
- if not pci_str in assigned_pci_device_str_list:
- raise VmError(("pci: failed to pci-attach %s to domain %s" + \
- " because one of its co-assignment device %s has been" + \
- " assigned to other domain." \
- )% (pci_device.name, self.info['name_label'], pci_str))
-
- # try to do FLR for HVM guest
- pci_device.do_FLR(self.info.is_hvm(), strict_check)
-
- def hvm_pci_device_insert(self, dev_config):
- log.debug("XendDomainInfo.hvm_pci_device_insert: %s"
- % scrub_password(dev_config))
-
- if not self.info.is_hvm():
- raise VmError("hvm_pci_device_create called on non-HVM guest")
-
- new_dev = dev_config['devs'][0]
-
- return self.hvm_pci_device_insert_dev(new_dev)
-
- def hvm_pci_device_insert_dev(self, new_dev):
- log.debug("XendDomainInfo.hvm_pci_device_insert_dev: %s"
- % scrub_password(new_dev))
-
- if self.domid is not None:
- opts = ''
- optslist = []
- pci_defopts = []
- if 'pci_msitranslate' in self.info['platform']:
- pci_defopts.append(['msitranslate',
- str(self.info['platform']['pci_msitranslate'])])
- if 'pci_power_mgmt' in self.info['platform']:
- pci_defopts.append(['power_mgmt',
- str(self.info['platform']['pci_power_mgmt'])])
- if new_dev.has_key('opts'):
- optslist += new_dev['opts']
-
- if optslist or pci_defopts:
- opts = ',' + serialise_pci_opts(
- append_default_pci_opts(optslist, pci_defopts))
-
- bdf_str = "%s@%02x%s" % (pci_dict_to_bdf_str(new_dev),
- int(new_dev['vdevfn'], 16), opts)
- log.debug("XendDomainInfo.hvm_pci_device_insert_dev: %s" % bdf_str)
- bdf = xc.assign_device(self.domid, pci_dict_to_xc_str(new_dev))
- if bdf > 0:
- raise VmError("Failed to assign device to IOMMU (%s)" % bdf_str)
- log.debug("pci: assign device %s" % bdf_str)
- self.image.signalDeviceModel('pci-ins', 'pci-inserted', bdf_str)
-
- vdevfn = xstransact.Read("/local/domain/0/device-model/%i/parameter"
- % self.getDomid())
- try:
- vdevfn_int = int(vdevfn, 16)
- except ValueError:
- raise VmError(("Cannot pass-through PCI function '%s'. " +
- "Device model reported an error: %s") %
- (bdf_str, vdevfn))
- else:
- vdevfn = new_dev['vdevfn']
-
- return vdevfn
-
-
- def device_create(self, dev_config):
- """Create a new device.
-
- @param dev_config: device configuration
- @type dev_config: SXP object (parsed config)
- """
- log.debug("XendDomainInfo.device_create: %s" % scrub_password(dev_config))
- dev_type = sxp.name(dev_config)
-
- if dev_type == 'vif':
- for x in dev_config:
- if x != 'vif' and x[0] == 'mac':
- if not re.match('^([0-9a-f]{2}:){5}[0-9a-f]{2}$', x[1], re.I):
- log.error("Virtual network interface creation error - invalid MAC Address entered: %s", x[1])
- raise VmError("Cannot create a new virtual network interface - MAC address is not valid!");
-
- dev_uuid = self.info.device_add(dev_type, cfg_sxp = dev_config)
- dev_config_dict = self.info['devices'][dev_uuid][1]
- log.debug("XendDomainInfo.device_create: %s" % scrub_password(dev_config_dict))
-
- if self.domid is not None:
- try:
- dev_config_dict['devid'] = devid = \
- self._createDevice(dev_type, dev_config_dict)
- if dev_type == 'tap2':
- # createDevice may create a blktap1 device if blktap2 is not
- # installed or if the blktap driver is not supported in
- # blktap1
- dev_type = self.getBlockDeviceClass(devid)
- self._waitForDevice(dev_type, devid)
- except VmError, ex:
- del self.info['devices'][dev_uuid]
- if dev_type == 'pci':
- for dev in dev_config_dict['devs']:
- XendAPIStore.deregister(dev['uuid'], 'DPCI')
- elif dev_type == 'vscsi':
- for dev in dev_config_dict['devs']:
- XendAPIStore.deregister(dev['uuid'], 'DSCSI')
- elif dev_type == 'tap' or dev_type == 'tap2':
- self.info['vbd_refs'].remove(dev_uuid)
- else:
- self.info['%s_refs' % dev_type].remove(dev_uuid)
- raise ex
- else:
- devid = None
-
- xen.xend.XendDomain.instance().managed_config_save(self)
- return self.getDeviceController(dev_type).sxpr(devid)
-
-
- def pci_device_configure(self, dev_sxp, devid = 0, first_dev = False):
- """Configure an existing pci device.
-
- @param dev_sxp: device configuration
- @type dev_sxp: SXP object (parsed config)
- @param devid: device id
- @type devid: int
- @return: Returns True if successfully updated device
- @rtype: boolean
- """
- log.debug("XendDomainInfo.pci_device_configure: %s"
- % scrub_password(dev_sxp))
-
- dev_class = sxp.name(dev_sxp)
-
- if dev_class != 'pci':
- return False
-
- pci_state = sxp.child_value(dev_sxp, 'state')
- pci_sub_state = sxp.child_value(dev_sxp, 'sub_state')
- existing_dev_info = self._getDeviceInfo_pci(devid)
-
- if existing_dev_info is None and pci_state != 'Initialising':
- raise XendError("Cannot detach when pci platform does not exist")
-
- pci_dev = sxp.children(dev_sxp, 'dev')[0]
- dev_config = pci_convert_sxp_to_dict(dev_sxp)
- dev = dev_config['devs'][0]
-
- stubdomid = self.getStubdomDomid()
- # Do HVM specific processing
- if self.info.is_hvm():
- from xen.xend import XendDomain
- if pci_state == 'Initialising':
- if stubdomid is not None :
- XendDomain.instance().domain_lookup(stubdomid).pci_device_configure(dev_sxp[:])
-
- # HVM PCI device attachment
- if pci_sub_state == 'Booting':
- vdevfn = self.hvm_pci_device_insert(dev_config)
- else:
- vdevfn = self.hvm_pci_device_create(dev_config)
- # Update vdevfn
- dev['vdevfn'] = vdevfn
- for n in sxp.children(pci_dev):
- if(n[0] == 'vdevfn'):
- n[1] = vdevfn
- else:
- # HVM PCI device detachment
- existing_dev_uuid = sxp.child_value(existing_dev_info, 'uuid')
- existing_pci_conf = self.info['devices'][existing_dev_uuid][1]
- existing_pci_devs = existing_pci_conf['devs']
- new_devs = filter(lambda x: pci_dict_cmp(x, dev),
- existing_pci_devs)
- if len(new_devs) < 0:
- raise VmError("Device %s is not connected" %
- pci_dict_to_bdf_str(dev))
- new_dev = new_devs[0]
- # Only tell qemu-dm to unplug function 0.
- # When unplugging a function, all functions in the
- # same vslot must be unplugged, and function 0 must
- # be one of the functions present when a vslot is
- # hot-plugged. Telling qemu-dm to unplug function 0
- # also tells it to unplug all other functions in the
- # same vslot.
- if (PCI_FUNC(int(new_dev['vdevfn'], 16)) == 0):
- self.hvm_destroyPCIDevice(new_dev)
- if stubdomid is not None :
- XendDomain.instance().domain_lookup(stubdomid).pci_device_configure(dev_sxp[:])
- # Update vdevfn
- dev['vdevfn'] = new_dev['vdevfn']
- for n in sxp.children(pci_dev):
- if(n[0] == 'vdevfn'):
- n[1] = new_dev['vdevfn']
- else:
- # Do PV specific checking
- if pci_state == 'Initialising':
- # PV PCI device attachment
- self.pci_dev_check_attachability_and_do_FLR(dev)
-
- # If pci platform does not exist, create and exit.
- if existing_dev_info is None :
- self.device_create(dev_sxp)
- return True
-
- if first_dev is True :
- existing_dev_uuid = sxp.child_value(existing_dev_info, 'uuid')
- existing_pci_conf = self.info['devices'][existing_dev_uuid][1]
- devid = self._createDevice('pci', existing_pci_conf)
- self.info['devices'][existing_dev_uuid][1]['devid'] = devid
-
- if self.domid is not None:
- # use DevController.reconfigureDevice to change device config
- dev_control = self.getDeviceController(dev_class)
- dev_uuid = dev_control.reconfigureDevice(devid, dev_config)
- if not self.info.is_hvm() and not self.info.is_stubdom():
- # in PV case, wait until backend state becomes connected.
- dev_control.waitForDevice_reconfigure(devid)
- num_devs = dev_control.cleanupDevice(devid)
-
- # update XendConfig with new device info
- if dev_uuid:
- new_dev_sxp = dev_control.configuration(devid)
- self.info.device_update(dev_uuid, new_dev_sxp)
-
- # If there is no device left, destroy pci and remove config.
- if num_devs == 0:
- if self.info.is_hvm():
- self.destroyDevice('pci', devid, True)
- else:
- self.destroyDevice('pci', devid)
- del self.info['devices'][dev_uuid]
- else:
- new_dev_sxp = ['pci']
- for cur_dev in sxp.children(existing_dev_info, 'dev'):
- if pci_state == 'Closing':
- if int(dev['domain'], 16) == int(sxp.child_value(cur_dev, 'domain'), 16) and \
- int(dev['bus'], 16) == int(sxp.child_value(cur_dev, 'bus'), 16) and \
- int(dev['slot'], 16) == int(sxp.child_value(cur_dev, 'slot'), 16) and \
- int(dev['func'], 16) == int(sxp.child_value(cur_dev, 'func'), 16):
- continue
- new_dev_sxp.append(cur_dev)
-
- if pci_state == 'Initialising' and pci_sub_state != 'Booting':
- for new_dev in sxp.children(dev_sxp, 'dev'):
- new_dev_sxp.append(new_dev)
-
- dev_uuid = sxp.child_value(existing_dev_info, 'uuid')
- self.info.device_update(dev_uuid, new_dev_sxp)
-
- # If there is no device left, remove config.
- if len(sxp.children(new_dev_sxp, 'dev')) == 0:
- del self.info['devices'][dev_uuid]
-
- xen.xend.XendDomain.instance().managed_config_save(self)
-
- return True
-
- def vscsi_device_configure(self, dev_sxp):
- """Configure an existing vscsi device.
- quoted pci funciton
- """
- def _is_vscsi_defined(dev_info, p_devs = None, v_devs = None):
- if not dev_info:
- return False
- for dev in sxp.children(dev_info, 'dev'):
- if p_devs is not None:
- if sxp.child_value(dev, 'p-dev') in p_devs:
- return True
- if v_devs is not None:
- if sxp.child_value(dev, 'v-dev') in v_devs:
- return True
- return False
-
- def _vscsi_be(be):
- be_xdi = xen.xend.XendDomain.instance().domain_lookup_nr(be)
- if be_xdi is not None:
- be_domid = be_xdi.getDomid()
- if be_domid is not None:
- return str(be_domid)
- return str(be)
-
- dev_class = sxp.name(dev_sxp)
- if dev_class != 'vscsi':
- return False
-
- dev_config = self.info.vscsi_convert_sxp_to_dict(dev_sxp)
- devs = dev_config['devs']
- v_devs = [d['v-dev'] for d in devs]
- state = devs[0]['state']
- req_devid = int(devs[0]['devid'])
- cur_dev_sxp = self._getDeviceInfo_vscsi(req_devid)
-
- if state == xenbusState['Initialising']:
- # new create
- # If request devid does not exist, create and exit.
- p_devs = [d['p-dev'] for d in devs]
- for dev_type, dev_info in self.info.all_devices_sxpr():
- if dev_type != 'vscsi':
- continue
- if _is_vscsi_defined(dev_info, p_devs = p_devs):
- raise XendError('The physical device "%s" is already defined' % \
- p_devs[0])
- if cur_dev_sxp is None:
- self.device_create(dev_sxp)
- return True
-
- if _is_vscsi_defined(cur_dev_sxp, v_devs = v_devs):
- raise XendError('The virtual device "%s" is already defined' % \
- v_devs[0])
-
- if int(dev_config['feature-host']) != \
- int(sxp.child_value(cur_dev_sxp, 'feature-host')):
- raise XendError('The physical device "%s" cannot define '
- 'because mode is different' % devs[0]['p-dev'])
-
- new_be = dev_config.get('backend', None)
- if new_be is not None:
- cur_be = sxp.child_value(cur_dev_sxp, 'backend', None)
- if cur_be is None:
- cur_be = xen.xend.XendDomain.DOM0_ID
- new_be_dom = _vscsi_be(new_be)
- cur_be_dom = _vscsi_be(cur_be)
- if new_be_dom != cur_be_dom:
- raise XendError('The physical device "%s" cannot define '
- 'because backend is different' % devs[0]['p-dev'])
-
- elif state == xenbusState['Closing']:
- if not _is_vscsi_defined(cur_dev_sxp, v_devs = v_devs):
- raise XendError("Cannot detach vscsi device does not exist")
-
- if self.domid is not None:
- # use DevController.reconfigureDevice to change device config
- dev_control = self.getDeviceController(dev_class)
- dev_uuid = dev_control.reconfigureDevice(req_devid, dev_config)
- dev_control.waitForDevice_reconfigure(req_devid)
- num_devs = dev_control.cleanupDevice(req_devid)
-
- # update XendConfig with new device info
- if dev_uuid:
- new_dev_sxp = dev_control.configuration(req_devid)
- self.info.device_update(dev_uuid, new_dev_sxp)
-
- # If there is no device left, destroy vscsi and remove config.
- if num_devs == 0:
- self.destroyDevice('vscsi', req_devid)
- del self.info['devices'][dev_uuid]
-
- else:
- new_dev_sxp = ['vscsi']
- cur_mode = sxp.children(cur_dev_sxp, 'feature-host')[0]
- new_dev_sxp.append(cur_mode)
- try:
- cur_be = sxp.children(cur_dev_sxp, 'backend')[0]
- new_dev_sxp.append(cur_be)
- except IndexError:
- pass
-
- for cur_dev in sxp.children(cur_dev_sxp, 'dev'):
- if state == xenbusState['Closing']:
- if int(cur_mode[1]) == 1:
- continue
- if sxp.child_value(cur_dev, 'v-dev') in v_devs:
- continue
- new_dev_sxp.append(cur_dev)
-
- if state == xenbusState['Initialising']:
- for new_dev in sxp.children(dev_sxp, 'dev'):
- new_dev_sxp.append(new_dev)
-
- dev_uuid = sxp.child_value(cur_dev_sxp, 'uuid')
- self.info.device_update(dev_uuid, new_dev_sxp)
-
- # If there is only 'vscsi' in new_dev_sxp, remove the config.
- if len(sxp.children(new_dev_sxp, 'dev')) == 0:
- del self.info['devices'][dev_uuid]
-
- xen.xend.XendDomain.instance().managed_config_save(self)
-
- return True
-
- def vusb_device_configure(self, dev_sxp, devid):
- """Configure a virtual root port.
- """
- dev_class = sxp.name(dev_sxp)
- if dev_class != 'vusb':
- return False
-
- dev_config = {}
- ports = sxp.child(dev_sxp, 'port')
- for port in ports[1:]:
- try:
- num, bus = port
- dev_config['port-%i' % int(num)] = str(bus)
- except TypeError:
- pass
-
- dev_control = self.getDeviceController(dev_class)
- dev_control.reconfigureDevice(devid, dev_config)
-
- return True
-
- def device_configure(self, dev_sxp, devid = None):
- """Configure an existing device.
-
- @param dev_config: device configuration
- @type dev_config: SXP object (parsed config)
- @param devid: device id
- @type devid: int
- @return: Returns True if successfully updated device
- @rtype: boolean
- """
-
- # convert device sxp to a dict
- dev_class = sxp.name(dev_sxp)
- dev_config = {}
-
- if dev_class == 'pci':
- return self.pci_device_configure(dev_sxp)
-
- if dev_class == 'vscsi':
- return self.vscsi_device_configure(dev_sxp)
-
- if dev_class == 'vusb':
- return self.vusb_device_configure(dev_sxp, devid)
-
- for opt_val in dev_sxp[1:]:
- try:
- dev_config[opt_val[0]] = opt_val[1]
- except IndexError:
- pass
-
- dev_control = self.getDeviceController(dev_class)
- if devid is None:
- dev = dev_config.get('dev', '')
- if not dev:
- raise VmError('Block device must have virtual details specified')
- if 'ioemu:' in dev:
- (_, dev) = dev.split(':', 1)
- try:
- (dev, _) = dev.split(':', 1) # Remove ":disk" or ":cdrom"
- except ValueError:
- pass
- devid = dev_control.convertToDeviceNumber(dev)
- dev_info = self._getDeviceInfo_vbd(devid)
- if dev_info is None:
- raise VmError("Device %s not connected" % devid)
- dev_uuid = sxp.child_value(dev_info, 'uuid')
-
- if self.domid is not None:
- # use DevController.reconfigureDevice to change device config
- dev_control.reconfigureDevice(devid, dev_config)
- else:
- (_, new_b, new_f) = dev_control.getDeviceDetails(dev_config)
- if (new_f['device-type'] == 'cdrom' and
- sxp.child_value(dev_info, 'dev').endswith(':cdrom') and
- new_b['mode'] == 'r' and
- sxp.child_value(dev_info, 'mode') == 'r'):
- pass
- else:
- raise VmError('Refusing to reconfigure device %s:%d to %s' %
- (dev_class, devid, dev_config))
-
- # update XendConfig with new device info
- self.info.device_update(dev_uuid, dev_sxp)
- xen.xend.XendDomain.instance().managed_config_save(self)
-
- return True
-
- def waitForDevices(self):
- """Wait for this domain's configured devices to connect.
-
- @raise VmError: if any device fails to initialise.
- """
- for devclass in XendDevices.valid_devices():
- self.getDeviceController(devclass).waitForDevices()
-
- def hvm_destroyPCIDevice(self, pci_dev):
- log.debug("hvm_destroyPCIDevice: %s", pci_dev)
-
- if not self.info.is_hvm():
- raise VmError("hvm_destroyPCIDevice called on non-HVM guest")
-
- # Check the co-assignment.
- # To pci-detach a device D from domN, we should ensure: for each DD in the
- # list of D's co-assignment devices, DD is not assigned (to domN).
- #
- from xen.xend.server.pciif import PciDevice
- try:
- pci_device = PciDevice(pci_dev)
- except Exception, e:
- raise VmError("pci: failed to locate device and "+
- "parse its resources - "+str(e))
- coassignment_list = pci_device.find_coassigned_devices()
- coassignment_list.remove(pci_device.name)
- assigned_pci_device_str_list = self._get_assigned_pci_devices()
- for pci_str in coassignment_list:
- if xoptions.get_pci_dev_assign_strict_check() and \
- pci_str in assigned_pci_device_str_list:
- raise VmError(("pci: failed to pci-detach %s from domain %s" + \
- " because one of its co-assignment device %s is still " + \
- " assigned to the domain." \
- )% (pci_device.name, self.info['name_label'], pci_str))
-
-
- bdf_str = pci_dict_to_bdf_str(pci_dev)
- log.info("hvm_destroyPCIDevice:%s:%s!", pci_dev, bdf_str)
- if self.domid is not None:
- self.image.signalDeviceModel('pci-rem', 'pci-removed', bdf_str)
-
- return 0
-
- def destroyDevice(self, deviceClass, devid, force = False, rm_cfg = False):
- log.debug("XendDomainInfo.destroyDevice: deviceClass = %s, device = %s",
- deviceClass, devid)
-
- if rm_cfg:
- # Convert devid to device number. A device number is
- # needed to remove its configuration.
- dev = self.getDeviceController(deviceClass).convertToDeviceNumber(devid)
-
- # Save current sxprs. A device number and a backend
- # path are needed to remove its configuration but sxprs
- # do not have those after calling destroyDevice.
- sxprs = self.getDeviceSxprs(deviceClass)
-
- rc = None
- if self.domid is not None:
-
- #new blktap implementation may need a sysfs write after everything is torn down.
- if deviceClass == 'tap2':
- dev = self.getDeviceController(deviceClass).convertToDeviceNumber(devid)
- path = self.getDeviceController(deviceClass).readBackend(dev, 'params')
- frontpath = self.getDeviceController(deviceClass).frontendPath(dev)
- backpath = xstransact.Read(frontpath, "backend")
- thread.start_new_thread(self.getDeviceController(deviceClass).finishDeviceCleanup, (backpath, path))
-
- rc = self.getDeviceController(deviceClass).destroyDevice(devid, force)
- if not force and rm_cfg:
- # The backend path, other than the device itself,
- # has to be passed because its accompanied frontend
- # path may be void until its removal is actually
- # issued. It is probable because destroyDevice is
- # issued first.
- for dev_num, dev_info in sxprs:
- dev_num = int(dev_num)
- if dev_num == dev:
- for x in dev_info:
- if x[0] == 'backend':
- backend = x[1]
- break
- break
- self._waitForDevice_destroy(deviceClass, devid, backend)
-
- if rm_cfg and deviceClass != "vif2":
- if deviceClass == 'vif':
- if self.domid is not None:
- mac = ''
- for dev_num, dev_info in sxprs:
- dev_num = int(dev_num)
- if dev_num == dev:
- for x in dev_info:
- if x[0] == 'mac':
- mac = x[1]
- break
- break
- dev_info = self._getDeviceInfo_vif(mac)
- else:
- _, dev_info = sxprs[dev]
- else: # 'vbd' or 'tap' or 'tap2'
- dev_info = self._getDeviceInfo_vbd(dev)
- # To remove the UUID of the device from refs,
- # deviceClass must be always 'vbd'.
- deviceClass = 'vbd'
- if dev_info is None:
- raise XendError("Device %s is not defined" % devid)
-
- dev_uuid = sxp.child_value(dev_info, 'uuid')
- del self.info['devices'][dev_uuid]
- self.info['%s_refs' % deviceClass].remove(dev_uuid)
- xen.xend.XendDomain.instance().managed_config_save(self)
-
- return rc
-
- def getDeviceSxprs(self, deviceClass):
- if deviceClass == 'pci':
- dev_info = self._getDeviceInfo_pci('0')#from self.info['devices']
- if dev_info is None:
- return []
- dev_uuid = sxp.child_value(dev_info, 'uuid')
- pci_devs = self.info['devices'][dev_uuid][1]['devs']
- return pci_devs
- if self._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED, DOM_STATE_CRASHED):
- return self.getDeviceController(deviceClass).sxprs()
- else:
- sxprs = []
- dev_num = 0
- for dev_type, dev_info in self.info.all_devices_sxpr():
- if (deviceClass == 'vbd' and dev_type not in ['vbd', 'tap', 'tap2']) or \
- (deviceClass != 'vbd' and dev_type != deviceClass):
- continue
-
- if deviceClass == 'vscsi':
- vscsi_devs = ['devs', []]
- for vscsi_dev in sxp.children(dev_info, 'dev'):
- vscsi_dev.append(['frontstate', None])
- vscsi_devs[1].append(vscsi_dev)
- dev_num = int(sxp.child_value(vscsi_dev, 'devid'))
- vscsi_mode = sxp.children(dev_info, 'feature-host')[0]
- sxprs.append([dev_num, [vscsi_devs, vscsi_mode]])
- elif deviceClass == 'vbd':
- dev = sxp.child_value(dev_info, 'dev')
- if 'ioemu:' in dev:
- (_, dev) = dev.split(':', 1)
- try:
- (dev_name, _) = dev.split(':', 1) # Remove ":disk" or ":cdrom"
- except ValueError:
- dev_name = dev
- dev_num = self.getDeviceController('vbd').convertToDeviceNumber(dev_name)
- sxprs.append([dev_num, dev_info])
- else:
- sxprs.append([dev_num, dev_info])
- dev_num += 1
- return sxprs
-
- def getBlockDeviceClass(self, devid):
- # if the domain is running we can get the device class from xenstore.
- # This is more accurate, as blktap1 devices show up as blktap2 devices
- # in the config.
- if self._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED, DOM_STATE_CRASHED):
- # All block devices have a vbd frontend, so we know the frontend path
- dev = self.getDeviceController('vbd').convertToDeviceNumber(devid)
- frontendPath = "%s/device/vbd/%s" % (self.dompath, dev)
- for devclass in XendDevices.valid_devices():
- for dev in xstransact.List("%s/device/%s" % (self.vmpath, devclass)):
- devFrontendPath = xstransact.Read("%s/device/%s/%s/frontend" % (self.vmpath, devclass, dev))
- if frontendPath == devFrontendPath:
- return devclass
-
- else: # the domain is not active so we must get the device class
- # from the config
- # To get a device number from the devid,
- # we temporarily use the device controller of VBD.
- dev = self.getDeviceController('vbd').convertToDeviceNumber(devid)
- dev_info = self._getDeviceInfo_vbd(dev)
- if dev_info:
- return dev_info[0]
-
- def _getDeviceInfo_vif(self, mac):
- for dev_type, dev_info in self.info.all_devices_sxpr():
- if dev_type != 'vif':
- continue
- if mac == sxp.child_value(dev_info, 'mac'):
- return dev_info
-
- def _getDeviceInfo_vbd(self, devid):
- for dev_type, dev_info in self.info.all_devices_sxpr():
- if dev_type != 'vbd' and dev_type != 'tap' and dev_type != 'tap2':
- continue
- dev = sxp.child_value(dev_info, 'dev')
- dev = dev.split(':')[0]
- dev = self.getDeviceController(dev_type).convertToDeviceNumber(dev)
- if devid == dev:
- return dev_info
-
- def _getDeviceInfo_pci(self, devid):
- for dev_type, dev_info in self.info.all_devices_sxpr():
- if dev_type != 'pci':
- continue
- return dev_info
- return None
-
- def _getDeviceInfo_vscsi(self, devid):
- devid = int(devid)
- for dev_type, dev_info in self.info.all_devices_sxpr():
- if dev_type != 'vscsi':
- continue
- devs = sxp.children(dev_info, 'dev')
- if devid == int(sxp.child_value(devs[0], 'devid')):
- return dev_info
- return None
-
- def _getDeviceInfo_vusb(self, devid):
- for dev_type, dev_info in self.info.all_devices_sxpr():
- if dev_type != 'vusb':
- continue
- return dev_info
- return None
-
- def _get_assigned_pci_devices(self, devid = 0):
- if self.domid is not None:
- return get_assigned_pci_devices(self.domid)
-
- dev_info = self._getDeviceInfo_pci(devid)
- if dev_info is None:
- return []
- dev_uuid = sxp.child_value(dev_info, 'uuid')
- pci_conf = self.info['devices'][dev_uuid][1]
- return map(pci_dict_to_bdf_str, pci_conf['devs'])
-
- def setMemoryTarget(self, target):
- """Set the memory target of this domain.
- @param target: In MiB.
- """
- log.debug("Setting memory target of domain %s (%s) to %d MiB.",
- self.info['name_label'], str(self.domid), target)
-
- MiB = 1024 * 1024
- memory_cur = self.get_memory_dynamic_max() / MiB
-
- if self.domid == 0:
- dom0_min_mem = xoptions.get_dom0_min_mem()
- if target < memory_cur and dom0_min_mem > target:
- raise XendError("memory_dynamic_max too small")
-
- self._safe_set_memory('memory_dynamic_min', target * MiB)
- self._safe_set_memory('memory_dynamic_max', target * MiB)
-
- if self.domid >= 0:
- if target > memory_cur:
- balloon.free((target - memory_cur) * 1024, self)
- self.storeVm("memory", target)
- self.storeDom("memory/target", target << 10)
- xc.domain_set_target_mem(self.domid,
- (target * 1024))
- xen.xend.XendDomain.instance().managed_config_save(self)
-
- def setMemoryMaximum(self, limit):
- """Set the maximum memory limit of this domain
- @param limit: In MiB.
- """
- log.debug("Setting memory maximum of domain %s (%s) to %d MiB.",
- self.info['name_label'], str(self.domid), limit)
-
- maxmem_cur = self.get_memory_static_max()
- MiB = 1024 * 1024
- self._safe_set_memory('memory_static_max', limit * MiB)
-
- if self.domid >= 0:
- maxmem = int(limit) * 1024
- try:
- return xc.domain_setmaxmem(self.domid, maxmem)
- except Exception, ex:
- self._safe_set_memory('memory_static_max', maxmem_cur)
- raise XendError(str(ex))
- xen.xend.XendDomain.instance().managed_config_save(self)
-
-
- def getVCPUInfo(self):
- try:
- # We include the domain name and ID, to help xm.
- sxpr = ['domain',
- ['domid', self.domid],
- ['name', self.info['name_label']],
- ['vcpu_count', self.info['VCPUs_max']]]
-
- for i in range(0, self.info['VCPUs_max']):
- if self.domid is not None:
- info = xc.vcpu_getinfo(self.domid, i)
-
- sxpr.append(['vcpu',
- ['number', i],
- ['online', info['online']],
- ['blocked', info['blocked']],
- ['running', info['running']],
- ['cpu_time', info['cpu_time'] / 1e9],
- ['cpu', info['cpu']],
- ['cpumap', info['cpumap']]])
- else:
- sxpr.append(['vcpu',
- ['number', i],
- ['online', 0],
- ['blocked', 0],
- ['running', 0],
- ['cpu_time', 0.0],
- ['cpu', -1],
- ['cpumap', self.info['cpus'][i] and \
- self.info['cpus'][i] or range(64)]])
-
- return sxpr
-
- except XCError, exn:
- # Domain already died.
- if exn.args[0] == errno.ESRCH:
- return sxpr
- raise XendError(str(exn))
-
-
- def getDomInfo(self):
- return dom_get(self.domid)
-
- #
- # internal functions ... TODO: re-categorised
- #
-
- def _augmentInfo(self, priv):
- """Augment self.info, as given to us through L{recreate}, with
- values taken from the store. This recovers those values known
- to xend but not to the hypervisor.
- """
- augment_entries = XendConfig.LEGACY_XENSTORE_VM_PARAMS[:]
- if priv:
- augment_entries.remove('memory')
- augment_entries.remove('maxmem')
- augment_entries.remove('vcpus')
- augment_entries.remove('vcpu_avail')
-
- vm_config = self._readVMDetails([(k, XendConfig.LEGACY_CFG_TYPES[k])
- for k in augment_entries])
-
- # make returned lists into a dictionary
- vm_config = dict(zip(augment_entries, vm_config))
-
- for arg in augment_entries:
- val = vm_config[arg]
- if val != None:
- if arg in XendConfig.LEGACY_CFG_TO_XENAPI_CFG:
- xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
- self.info[xapiarg] = val
- elif arg == "memory":
- self.info["static_memory_min"] = val
- elif arg == "maxmem":
- self.info["static_memory_max"] = val
- else:
- self.info[arg] = val
-
- # read CPU Affinity
- self.info['cpus'] = []
- vcpus_info = self.getVCPUInfo()
- for vcpu_info in sxp.children(vcpus_info, 'vcpu'):
- self.info['cpus'].append(sxp.child_value(vcpu_info, 'cpumap'))
-
- # For dom0, we ignore any stored value for the vcpus fields, and
- # read the current value from Xen instead. This allows boot-time
- # settings to take precedence over any entries in the store.
- if priv:
- xeninfo = dom_get(self.domid)
- self.info['VCPUs_max'] = xeninfo['online_vcpus']
- self.info['vcpu_avail'] = (1 << xeninfo['online_vcpus']) - 1
-
- # read image value
- image_sxp = self._readVm('image')
- if image_sxp:
- self.info.update_with_image_sxp(sxp.from_string(image_sxp))
-
- # read devices
- devices = []
- for devclass in XendDevices.valid_devices():
- devconfig = self.getDeviceController(devclass).configurations()
- if devconfig:
- devices.extend(devconfig)
-
- if not self.info['devices'] and devices is not None:
- for device in devices:
- self.info.device_add(device[0], cfg_sxp = device)
-
- self._update_consoles()
-
- def _update_consoles(self, transaction = None):
- if self.domid == None or self.domid == 0:
- return
-
- # Update VT100 port if it exists
- if transaction is None:
- self.console_port = self.readDom('console/port')
- else:
- self.console_port = self.readDomTxn(transaction, 'console/port')
- if self.console_port is not None:
- serial_consoles = self.info.console_get_all('vt100')
- if not serial_consoles:
- cfg = self.info.console_add('vt100', self.console_port)
- self._createDevice('console', cfg)
- else:
- console_uuid = serial_consoles[0].get('uuid')
- self.info.console_update(console_uuid, 'location',
- self.console_port)
- # Notify xenpv device model that console info is ready
- if not self.info.is_hvm() and self.info.has_rfb():
- console_ctrl = self.getDeviceController('console')
- # The value is unchanged. Just for xenstore watcher
- console_ctrl.writeBackend(0, 'uuid', console_uuid)
-
-
- # Update VNC port if it exists and write to xenstore
- if transaction is None:
- vnc_port = self.readDom('console/vnc-port')
- else:
- vnc_port = self.readDomTxn(transaction, 'console/vnc-port')
- if vnc_port is not None:
- for dev_uuid, (dev_type, dev_info) in self.info['devices'].items():
- if dev_type == 'vfb':
- old_location = dev_info.get('location')
- listen_host = dev_info.get('vnclisten', \
- XendOptions.instance().get_vnclisten_address())
- new_location = '%s:%s' % (listen_host, str(vnc_port))
- if old_location == new_location:
- break
-
- dev_info['location'] = new_location
- self.info.device_update(dev_uuid, cfg_xenapi = dev_info)
- vfb_ctrl = self.getDeviceController('vfb')
- vfb_ctrl.reconfigureDevice(0, dev_info)
- break
-
- #
- # Function to update xenstore /vm/*
- #
-
- def _readVm(self, *args):
- return xstransact.Read(self.vmpath, *args)
-
- def _writeVm(self, *args):
- return xstransact.Write(self.vmpath, *args)
-
- def _removeVm(self, *args):
- return xstransact.Remove(self.vmpath, *args)
-
- def _gatherVm(self, *args):
- return xstransact.Gather(self.vmpath, *args)
-
- def _listRecursiveVm(self, *args):
- return xstransact.ListRecursive(self.vmpath, *args)
-
- def storeVm(self, *args):
- return xstransact.Store(self.vmpath, *args)
-
- def permissionsVm(self, *args):
- return xstransact.SetPermissions(self.vmpath, *args)
-
- #
- # Function to update xenstore /dom/*
- #
-
- def readDom(self, *args):
- return xstransact.Read(self.dompath, *args)
-
- def gatherDom(self, *args):
- return xstransact.Gather(self.dompath, *args)
-
- def _writeDom(self, *args):
- return xstransact.Write(self.dompath, *args)
-
- def _removeDom(self, *args):
- return xstransact.Remove(self.dompath, *args)
-
- def storeDom(self, *args):
- return xstransact.Store(self.dompath, *args)
-
-
- def readDomTxn(self, transaction, *args):
- paths = map(lambda x: self.dompath + "/" + x, args)
- return transaction.read(*paths)
-
- def gatherDomTxn(self, transaction, *args):
- paths = map(lambda x: self.dompath + "/" + x, args)
- return transaction.gather(*paths)
-
- def _writeDomTxn(self, transaction, *args):
- paths = map(lambda x: self.dompath + "/" + x, args)
- return transaction.write(*paths)
-
- def _removeDomTxn(self, transaction, *args):
- paths = map(lambda x: self.dompath + "/" + x, args)
- return transaction.remove(*paths)
-
- def storeDomTxn(self, transaction, *args):
- paths = map(lambda x: self.dompath + "/" + x, args)
- return transaction.store(*paths)
-
-
- def _recreateDom(self):
- complete(self.dompath, lambda t: self._recreateDomFunc(t))
-
- def _recreateDomFunc(self, t):
- t.remove()
- t.mkdir()
- t.set_permissions({'dom' : self.domid, 'read' : True})
- t.write('vm', self.vmpath)
- # NB. Solaris guests use guest/ and hvmpv/ xenstore directories
- # XCP Windows paravirtualized guests use data/
- for i in [ 'device', 'control', 'error', 'memory', 'guest', \
- 'hvmpv', 'data' ]:
- t.mkdir(i)
- t.set_permissions(i, {'dom' : self.domid})
-
- def _storeDomDetails(self):
- to_store = {
- 'domid': str(self.domid),
- 'vm': self.vmpath,
- 'name': self.info['name_label'],
- 'console/limit': str(xoptions.get_console_limit() * 1024),
- 'memory/target': str(self.info['memory_dynamic_max'] / 1024),
- 'description': str(self.info['description']),
- }
-
- def f(n, v):
- if v is not None:
- if type(v) == bool:
- to_store[n] = v and "1" or "0"
- else:
- to_store[n] = str(v)
-
- # Figure out if we need to tell xenconsoled to ignore this guest's
- # console - device model will handle console if it is running
- constype = "ioemu"
- if 'device_model' not in self.info['platform']:
- constype = "xenconsoled"
-
- f('console/port', self.console_port)
- f('console/ring-ref', self.console_mfn)
- f('console/type', constype)
- f('store/port', self.store_port)
- f('store/ring-ref', self.store_mfn)
-
- f('control/platform-feature-xs_reset_watches', True)
- if arch.type == "x86":
- f('control/platform-feature-multiprocessor-suspend', True)
-
- # elfnotes
- for n, v in self.info.get_notes().iteritems():
- n = n.lower().replace('_', '-')
- if n == 'features':
- for v in v.split('|'):
- v = v.replace('_', '-')
- if v.startswith('!'):
- f('image/%s/%s' % (n, v[1:]), False)
- else:
- f('image/%s/%s' % (n, v), True)
- else:
- f('image/%s' % n, v)
-
- if self.info.has_key('security_label'):
- f('security_label', self.info['security_label'])
-
- to_store.update(self._vcpuDomDetails())
-
- log.debug("Storing domain details: %s", scrub_password(to_store))
-
- self._writeDom(to_store)
-
- def _vcpuDomDetails(self):
- def availability(n):
- if self.info['vcpu_avail'] & (1 << n):
- return 'online'
- else:
- return 'offline'
-
- result = {}
- for v in range(0, self.info['VCPUs_max']):
- result["cpu/%d/availability" % v] = availability(v)
- return result
-
- #
- # xenstore watches
- #
-
- def _registerWatches(self):
- """Register a watch on this VM's entries in the store, and the
- domain's control/shutdown node, so that when they are changed
- externally, we keep up to date. This should only be called by {@link
- #create}, {@link #recreate}, or {@link #restore}, once the domain's
- details have been written, but before the new instance is returned."""
- self.vmWatch = xswatch(self.vmpath, self._storeChanged)
- self.shutdownWatch = xswatch(self.dompath + '/control/shutdown',
- self._handleShutdownWatch)
-
- def _storeChanged(self, _):
- log.trace("XendDomainInfo.storeChanged");
-
- changed = False
-
- # Check whether values in the configuration have
- # changed in Xenstore.
-
- cfg_vm = ['name', 'on_poweroff', 'on_reboot', 'on_crash',
- 'rtc/timeoffset']
-
- vm_details = self._readVMDetails([(k,XendConfig.LEGACY_CFG_TYPES[k])
- for k in cfg_vm])
-
- # convert two lists into a python dictionary
- vm_details = dict(zip(cfg_vm, vm_details))
-
- for arg, val in vm_details.items():
- if arg in XendConfig.LEGACY_CFG_TO_XENAPI_CFG:
- xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
- if val != None and val != self.info[xapiarg]:
- self.info[xapiarg] = val
- changed = True
- elif arg == "memory":
- if val != None and val != self.info["static_memory_min"]:
- self.info["static_memory_min"] = val
- changed = True
- elif arg == "maxmem":
- if val != None and val != self.info["static_memory_max"]:
- self.info["static_memory_max"] = val
- changed = True
-
- # Check whether image definition has been updated
- image_sxp = self._readVm('image')
- if image_sxp and image_sxp != sxp.to_string(self.info.image_sxpr()):
- self.info.update_with_image_sxp(sxp.from_string(image_sxp))
- changed = True
-
- # Update the rtc_timeoffset to be preserved across reboot.
- # NB. No need to update xenstore domain section.
- val = int(vm_details.get("rtc/timeoffset", 0))
- self.info["platform"]["rtc_timeoffset"] = val
-
- if changed:
- # Update the domain section of the store, as this contains some
- # parameters derived from the VM configuration.
- self.refresh_shutdown_lock.acquire()
- try:
- state = self._stateGet()
- if state not in (DOM_STATE_SHUTDOWN, DOM_STATE_HALTED,):
- self._storeDomDetails()
- finally:
- self.refresh_shutdown_lock.release()
-
- return 1
-
- def _handleShutdownWatch(self, _):
- log.debug('XendDomainInfo.handleShutdownWatch')
-
- reason = self.readDom('control/shutdown')
-
- if reason and reason != 'suspend':
- sst = self.readDom('xend/shutdown_start_time')
- now = time.time()
- if sst:
- self.shutdownStartTime = float(sst)
- timeout = float(sst) + SHUTDOWN_TIMEOUT - now
- else:
- self.shutdownStartTime = now
- self.storeDom('xend/shutdown_start_time', now)
- timeout = SHUTDOWN_TIMEOUT
-
- log.trace(
- "Scheduling refreshShutdown on domain %d in %ds.",
- self.domid, timeout)
- threading.Timer(timeout, self.refreshShutdown).start()
-
- return True
-
-
- #
- # Public Attributes for the VM
- #
-
-
- def getDomid(self):
- return self.domid
-
- def getStubdomDomid(self):
- dom_list = xstransact.List('/local/domain')
- for d in dom_list:
- target = xstransact.Read('/local/domain/' + d + '/target')
- if target is not None and int(target) == self.domid:
- return int(d)
- return None
-
- def setName(self, name, to_store = True):
- self._checkName(name)
- self.info['name_label'] = name
- if to_store:
- self.storeVm("name", name)
-
- def getName(self):
- return self.info['name_label']
-
- def getDomainPath(self):
- return self.dompath
-
- def getShutdownReason(self):
- return self.readDom('control/shutdown')
-
- def getStorePort(self):
- """For use only by image.py and XendCheckpoint.py."""
- return self.store_port
-
- def getConsolePort(self):
- """For use only by image.py and XendCheckpoint.py"""
- return self.console_port
-
- def getFeatures(self):
- """For use only by image.py."""
- return self.info['features']
-
- def getVCpuCount(self):
- return self.info['VCPUs_max']
-
- def getVCpuAvail(self):
- return self.info['vcpu_avail']
-
- def setVCpuCount(self, vcpus):
- def vcpus_valid(n):
- if vcpus <= 0:
- raise XendError('Zero or less VCPUs is invalid')
- if self.domid >= 0 and vcpus > self.info['VCPUs_max']:
- raise XendError('Cannot set vcpus greater than max vcpus on running domain')
- vcpus_valid(vcpus)
-
- self.info['vcpu_avail'] = (1 << vcpus) - 1
- if self.domid >= 0:
- self.storeVm('vcpu_avail', self.info['vcpu_avail'])
- self._writeDom(self._vcpuDomDetails())
- self.info['VCPUs_live'] = vcpus
- else:
- if self.info['VCPUs_max'] > vcpus:
- # decreasing
- del self.info['cpus'][vcpus:]
- elif self.info['VCPUs_max'] < vcpus:
- # increasing
- for c in range(self.info['VCPUs_max'], vcpus):
- self.info['cpus'].append(list())
- self.info['VCPUs_max'] = vcpus
- xen.xend.XendDomain.instance().managed_config_save(self)
- log.info("Set VCPU count on domain %s to %d", self.info['name_label'],
- vcpus)
-
- def getMemoryTarget(self):
- """Get this domain's target memory size, in KB."""
- return self.info['memory_dynamic_max'] / 1024
-
- def getMemoryMaximum(self):
- """Get this domain's maximum memory size, in KB."""
- # remember, info now stores memory in bytes
- return self.info['memory_static_max'] / 1024
-
- def getResume(self):
- return str(self._resume)
-
- def setResume(self, isresume):
- self._resume = isresume
-
- def getCpus(self):
- return self.info['cpus']
-
- def setCpus(self, cpumap):
- self.info['cpus'] = cpumap
-
- def getCap(self):
- return self.info['vcpus_params']['cap']
-
- def setCap(self, cpu_cap):
- self.info['vcpus_params']['cap'] = cpu_cap
-
- def getWeight(self):
- return self.info['vcpus_params']['weight']
-
- def setWeight(self, cpu_weight):
- self.info['vcpus_params']['weight'] = cpu_weight
-
- def getRestartCount(self):
- return self._readVm('xend/restart_count')
-
- def refreshShutdown(self, xeninfo = None):
- """ Checks the domain for whether a shutdown is required.
-
- Called from XendDomainInfo and also image.py for HVM images.
- """
-
- # If set at the end of this method, a restart is required, with the
- # given reason. This restart has to be done out of the scope of
- # refresh_shutdown_lock.
- restart_reason = None
-
- self.refresh_shutdown_lock.acquire()
- try:
- if xeninfo is None:
- xeninfo = dom_get(self.domid)
- if xeninfo is None:
- # The domain no longer exists. This will occur if we have
- # scheduled a timer to check for shutdown timeouts and the
- # shutdown succeeded. It will also occur if someone
- # destroys a domain beneath us. We clean up the domain,
- # just in case, but we can't clean up the VM, because that
- # VM may have migrated to a different domain on this
- # machine.
- self.cleanupDomain()
- self._stateSet(DOM_STATE_HALTED)
- return
-
- if xeninfo['dying']:
- # Dying means that a domain has been destroyed, but has not
- # yet been cleaned up by Xen. This state could persist
- # indefinitely if, for example, another domain has some of its
- # pages mapped. We might like to diagnose this problem in the
- # future, but for now all we do is make sure that it's not us
- # holding the pages, by calling cleanupDomain. We can't
- # clean up the VM, as above.
- self.cleanupDomain()
- self._stateSet(DOM_STATE_SHUTDOWN)
- return
-
- elif xeninfo['crashed']:
- if self.readDom('xend/shutdown_completed'):
- # We've seen this shutdown already, but we are preserving
- # the domain for debugging. Leave it alone.
- return
-
- log.warn('Domain has crashed: name=%s id=%d.',
- self.info['name_label'], self.domid)
- self._writeVm(LAST_SHUTDOWN_REASON, 'crash')
-
- restart_reason = 'crash'
- self._stateSet(DOM_STATE_HALTED)
-
- elif xeninfo['shutdown']:
- self._stateSet(DOM_STATE_SHUTDOWN)
- if self.readDom('xend/shutdown_completed'):
- # We've seen this shutdown already, but we are preserving
- # the domain for debugging. Leave it alone.
- return
-
- else:
- reason = shutdown_reason(xeninfo['shutdown_reason'])
-
- log.info('Domain has shutdown: name=%s id=%d reason=%s.',
- self.info['name_label'], self.domid, reason)
- self._writeVm(LAST_SHUTDOWN_REASON, reason)
-
- self._clearRestart()
-
- if reason == 'suspend':
- self._stateSet(DOM_STATE_SUSPENDED)
- # Don't destroy the domain. XendCheckpoint will do
- # this once it has finished. However, stop watching
- # the VM path now, otherwise we will end up with one
- # watch for the old domain, and one for the new.
- self._unwatchVm()
- elif reason in ('poweroff', 'reboot'):
- restart_reason = reason
- else:
- self.destroy()
-
- elif self.dompath is None:
- # We have yet to manage to call introduceDomain on this
- # domain. This can happen if a restore is in progress, or has
- # failed. Ignore this domain.
- pass
- else:
- # Domain is alive. If we are shutting it down, log a message
- # if it seems unresponsive.
- if xeninfo['paused']:
- self._stateSet(DOM_STATE_PAUSED)
- else:
- self._stateSet(DOM_STATE_RUNNING)
-
- if self.shutdownStartTime:
- timeout = (SHUTDOWN_TIMEOUT - time.time() +
- self.shutdownStartTime)
- if (timeout < 0 and not self.readDom('xend/unresponsive')):
- log.info(
- "Domain shutdown timeout expired: name=%s id=%s",
- self.info['name_label'], self.domid)
- self.storeDom('xend/unresponsive', 'True')
- finally:
- self.refresh_shutdown_lock.release()
-
- if restart_reason and not self.restart_in_progress:
- self.restart_in_progress = True
- threading.Thread(target = self._maybeRestart,
- args = (restart_reason,)).start()
-
-
- #
- # Restart functions - handling whether we come back up on shutdown.
- #
-
- def _clearRestart(self):
- self._removeDom("xend/shutdown_start_time")
-
- def _maybeDumpCore(self, reason):
- if reason == 'crash':
- if xoptions.get_enable_dump() or self.get_on_crash() \
- in ['coredump_and_destroy', 'coredump_and_restart']:
- try:
- self.dumpCore()
- except XendError:
- # This error has been logged -- there's nothing more
- # we can do in this context.
- pass
-
- def _maybeRestart(self, reason):
- # Before taking configured action, dump core if configured to do so.
- #
- self._maybeDumpCore(reason)
-
- # Dispatch to the correct method based upon the configured on_{reason}
- # behaviour.
- actions = {"destroy" : self.destroy,
- "restart" : self._restart,
- "preserve" : self._preserve,
- "rename-restart" : self._renameRestart,
- "coredump-destroy" : self.destroy,
- "coredump-restart" : self._restart}
-
- action_conf = {
- 'poweroff': 'actions_after_shutdown',
- 'reboot': 'actions_after_reboot',
- 'crash': 'actions_after_crash',
- }
-
- action_target = self.info.get(action_conf.get(reason))
- func = actions.get(action_target, None)
- if func and callable(func):
- func()
- else:
- self.destroy() # default to destroy
-
- def _renameRestart(self):
- self._restart(True)
-
- def _restart(self, rename = False):
- """Restart the domain after it has exited.
-
- @param rename True if the old domain is to be renamed and preserved,
- False if it is to be destroyed.
- """
- from xen.xend import XendDomain
-
- if self._readVm(RESTART_IN_PROGRESS):
- log.error('Xend failed during restart of domain %s. '
- 'Refusing to restart to avoid loops.',
- str(self.domid))
- self.destroy()
- return
-
- old_domid = self.domid
- self._writeVm(RESTART_IN_PROGRESS, 'True')
-
- elapse = time.time() - self.info['start_time']
- if elapse < MINIMUM_RESTART_TIME:
- log.error('VM %s restarting too fast (Elapsed time: %f seconds). '
- 'Refusing to restart to avoid loops.',
- self.info['name_label'], elapse)
- self.destroy()
- return
-
- prev_vm_xend = self._listRecursiveVm('xend')
- new_dom_info = self.info
- try:
- if rename:
- new_dom_info = self._preserveForRestart()
- else:
- self._unwatchVm()
- self.destroy()
-
- # new_dom's VM will be the same as this domain's VM, except where
- # the rename flag has instructed us to call preserveForRestart.
- # In that case, it is important that we remove the
- # RESTART_IN_PROGRESS node from the new domain, not the old one,
- # once the new one is available.
-
- new_dom = None
- try:
- new_dom = XendDomain.instance().domain_create_from_dict(
- new_dom_info)
- for x in prev_vm_xend[0][1]:
- new_dom._writeVm('xend/%s' % x[0], x[1])
- new_dom.waitForDevices()
- new_dom.unpause()
- rst_cnt = new_dom._readVm('xend/restart_count')
- rst_cnt = int(rst_cnt) + 1
- new_dom._writeVm('xend/restart_count', str(rst_cnt))
- new_dom._removeVm(RESTART_IN_PROGRESS)
- except:
- if new_dom:
- new_dom._removeVm(RESTART_IN_PROGRESS)
- new_dom.destroy()
- else:
- self._removeVm(RESTART_IN_PROGRESS)
- raise
- except:
- log.exception('Failed to restart domain %s.', str(old_domid))
-
- def _preserveForRestart(self):
- """Preserve a domain that has been shut down, by giving it a new UUID,
- cloning the VM details, and giving it a new name. This allows us to
- keep this domain for debugging, but restart a new one in its place
- preserving the restart semantics (name and UUID preserved).
- """
-
- new_uuid = uuid.createString()
- new_name = 'Domain-%s' % new_uuid
- log.info("Renaming dead domain %s (%d, %s) to %s (%s).",
- self.info['name_label'], self.domid, self.info['uuid'],
- new_name, new_uuid)
- self._unwatchVm()
- self._releaseDevices()
- # Remove existing vm node in xenstore
- self._removeVm()
- new_dom_info = self.info.copy()
- new_dom_info['name_label'] = self.info['name_label']
- new_dom_info['uuid'] = self.info['uuid']
- self.info['name_label'] = new_name
- self.info['uuid'] = new_uuid
- self.vmpath = XS_VMROOT + new_uuid
- # Write out new vm node to xenstore
- self._storeVmDetails()
- self._preserve()
- return new_dom_info
-
-
- def _preserve(self):
- log.info("Preserving dead domain %s (%d).", self.info['name_label'],
- self.domid)
- self._unwatchVm()
- self.storeDom('xend/shutdown_completed', 'True')
- self._stateSet(DOM_STATE_HALTED)
-
- #
- # Debugging ..
- #
-
- def dumpCore(self, corefile = None):
- """Create a core dump for this domain.
-
- @raise: XendError if core dumping failed.
- """
-
- if not corefile:
- # To prohibit directory traversal
- based_name = os.path.basename(self.info['name_label'])
-
- coredir = "/var/xen/dump/%s" % (based_name)
- if not os.path.exists(coredir):
- try:
- mkdir.parents(coredir, stat.S_IRWXU)
- except Exception, ex:
- log.error("Cannot create directory: %s" % str(ex))
-
- if not os.path.isdir(coredir):
- # Use former directory to dump core
- coredir = '/var/xen/dump'
-
- this_time = time.strftime("%Y-%m%d-%H%M.%S", time.localtime())
- corefile = "%s/%s-%s.%s.core" % (coredir, this_time,
- self.info['name_label'], self.domid)
-
- if os.path.isdir(corefile):
- raise XendError("Cannot dump core in a directory: %s" %
- corefile)
-
- try:
- try:
- self._writeVm(DUMPCORE_IN_PROGRESS, 'True')
- xc.domain_dumpcore(self.domid, corefile)
- except RuntimeError, ex:
- corefile_incomp = corefile+'-incomplete'
- try:
- os.rename(corefile, corefile_incomp)
- except:
- pass
-
- log.error("core dump failed: id = %s name = %s: %s",
- self.domid, self.info['name_label'], str(ex))
- raise XendError("Failed to dump core: %s" % str(ex))
- finally:
- self._removeVm(DUMPCORE_IN_PROGRESS)
-
- #
- # Device creation/deletion functions
- #
-
- def _createDevice(self, deviceClass, devConfig):
- return self.getDeviceController(deviceClass).createDevice(devConfig)
-
- def _waitForDevice(self, deviceClass, devid):
- return self.getDeviceController(deviceClass).waitForDevice(devid)
-
- def _waitForDeviceUUID(self, dev_uuid):
- deviceClass, config = self.info['devices'].get(dev_uuid)
- self._waitForDevice(deviceClass, config['devid'])
-
- def _waitForDevice_destroy(self, deviceClass, devid, backpath):
- return self.getDeviceController(deviceClass).waitForDevice_destroy(
- devid, backpath)
-
- def _reconfigureDevice(self, deviceClass, devid, devconfig):
- return self.getDeviceController(deviceClass).reconfigureDevice(
- devid, devconfig)
-
- def _createDevices(self):
- """Create the devices for a vm.
-
- @raise: VmError for invalid devices
- """
- if self.image:
- self.image.prepareEnvironment()
-
- vscsi_uuidlist = {}
- vscsi_devidlist = []
- ordered_refs = self.info.ordered_device_refs()
- for dev_uuid in ordered_refs:
- devclass, config = self.info['devices'][dev_uuid]
- if devclass in XendDevices.valid_devices() and devclass != 'vscsi':
- log.info("createDevice: %s : %s" % (devclass, scrub_password(config)))
- dev_uuid = config.get('uuid')
-
- if devclass == 'pci':
- self.pci_dev_check_assignability_and_do_FLR(config)
-
- if devclass != 'pci' or not self.info.is_hvm() :
- devid = self._createDevice(devclass, config)
-
- # store devid in XendConfig for caching reasons
- if dev_uuid in self.info['devices']:
- self.info['devices'][dev_uuid][1]['devid'] = devid
-
- elif devclass == 'vscsi':
- vscsi_config = config.get('devs', [])[0]
- devid = vscsi_config.get('devid', '')
- dev_uuid = config.get('uuid')
- vscsi_uuidlist[devid] = dev_uuid
- vscsi_devidlist.append(devid)
-
- #It is necessary to sorted it for /dev/sdxx in guest.
- if len(vscsi_uuidlist) > 0:
- vscsi_devidlist.sort()
- for vscsiid in vscsi_devidlist:
- dev_uuid = vscsi_uuidlist[vscsiid]
- devclass, config = self.info['devices'][dev_uuid]
- log.info("createDevice: %s : %s" % (devclass, scrub_password(config)))
- dev_uuid = config.get('uuid')
- devid = self._createDevice(devclass, config)
- # store devid in XendConfig for caching reasons
- if dev_uuid in self.info['devices']:
- self.info['devices'][dev_uuid][1]['devid'] = devid
-
-
- if self.image:
- self.image.createDeviceModel()
-
- #if have pass-through devs, need the virtual pci slots info from qemu
- self.pci_device_configure_boot()
-
- def _releaseDevices(self, suspend = False):
- """Release all domain's devices. Nothrow guarantee."""
- if self.image:
- try:
- log.debug("Destroying device model")
- self.image.destroyDeviceModel()
- except Exception, e:
- log.exception("Device model destroy failed %s" % str(e))
- else:
- log.debug("No device model")
-
- log.debug("Releasing devices")
- t = xstransact("%s/device" % self.vmpath)
- try:
- for devclass in XendDevices.valid_devices():
- for dev in t.list(devclass):
- try:
- log.debug("Removing %s", dev);
- self.destroyDevice(devclass, dev, False);
- except:
- # Log and swallow any exceptions in removal --
- # there's nothing more we can do.
- log.exception("Device release failed: %s; %s; %s",
- self.info['name_label'],
- devclass, dev)
- finally:
- t.abort()
-
- def getDeviceController(self, name):
- """Get the device controller for this domain, and if it
- doesn't exist, create it.
-
- @param name: device class name
- @type name: string
- @rtype: subclass of DevController
- """
- if name not in self._deviceControllers:
- devController = XendDevices.make_controller(name, self)
- if not devController:
- raise XendError("Unknown device type: %s" % name)
- self._deviceControllers[name] = devController
-
- return self._deviceControllers[name]
-
- #
- # Migration functions (public)
- #
-
- def testMigrateDevices(self, network, dst):
- """ Notify all device about intention of migration
- @raise: XendError for a device that cannot be migrated
- """
- for (n, c) in self.info.all_devices_sxpr():
- rc = self.migrateDevice(n, c, network, dst, DEV_MIGRATE_TEST, self.getName())
- if rc != 0:
- raise XendError("Device of type '%s' refuses migration." % n)
-
- def migrateDevices(self, network, dst, step, domName=''):
- """Notify the devices about migration
- """
- ctr = 0
- try:
- for (dev_type, dev_conf) in self.info.all_devices_sxpr():
- self.migrateDevice(dev_type, dev_conf, network, dst,
- step, domName)
- ctr = ctr + 1
- except:
- for dev_type, dev_conf in self.info.all_devices_sxpr():
- if ctr == 0:
- step = step - 1
- ctr = ctr - 1
- self._recoverMigrateDevice(dev_type, dev_conf, network,
- dst, step, domName)
- raise
-
- def migrateDevice(self, deviceClass, deviceConfig, network, dst,
- step, domName=''):
- return self.getDeviceController(deviceClass).migrate(deviceConfig,
- network, dst, step, domName)
-
- def _recoverMigrateDevice(self, deviceClass, deviceConfig, network,
- dst, step, domName=''):
- return self.getDeviceController(deviceClass).recover_migrate(
- deviceConfig, network, dst, step, domName)
-
- def setChangeHomeServer(self, chs):
- if chs is not None:
- self.info['change_home_server'] = bool(chs)
- else:
- if self.info.has_key('change_home_server'):
- del self.info['change_home_server']
-
-
- ## private:
-
- def _constructDomain(self):
- """Construct the domain.
-
- @raise: VmError on error
- """
-
- log.debug('XendDomainInfo.constructDomain')
-
- self.shutdownStartTime = None
- self.restart_in_progress = False
-
- hap = 0
- hvm = self.info.is_hvm()
- if hvm:
- hap = self.info.is_hap()
- info = xc.xeninfo()
- if 'hvm' not in info['xen_caps']:
- raise VmError("HVM guest support is unavailable: is VT/AMD-V "
- "supported by your CPU and enabled in your "
- "BIOS?")
-
- # Hack to pre-reserve some memory for initial domain creation.
- # There is an implicit memory overhead for any domain creation. This
- # overhead is greater for some types of domain than others. For
- # example, an x86 HVM domain will have a default shadow-pagetable
- # allocation of 4MB. We free up 16MB here to be on the safe side.
- balloon.free(16*1024, self) # 16MB should be plenty
-
- ssidref = 0
- if security.on() == xsconstants.XS_POLICY_USE:
- ssidref = security.calc_dom_ssidref_from_info(self.info)
- if security.has_authorization(ssidref) == False:
- raise VmError("VM is not authorized to run.")
-
- s3_integrity = 0
- if self.info.has_key('s3_integrity'):
- s3_integrity = self.info['s3_integrity']
-
- oos = self.info['platform'].get('oos', 1)
- oos_off = 1 - int(oos)
-
- # look-up pool id to use
- pool_name = self.info['pool_name']
- if len(pool_name) == 0:
- pool_name = "Pool-0"
-
- pool = XendCPUPool.lookup_pool(pool_name)
-
- if pool is None:
- raise VmError("unknown pool %s" % pool_name)
- pool_id = pool.query_pool_id()
- if pool_id is None:
- raise VmError("pool %s not activated" % pool_name)
-
- flags = (int(hvm) << 0) | (int(hap) << 1) | (int(s3_integrity) << 2) | (int(oos_off) << 3)
-
- try:
- self.domid = xc.domain_create(
- domid = 0,
- ssidref = ssidref,
- handle = uuid.fromString(self.info['uuid']),
- flags = flags,
- #cpupool = pool_id,
- target = self.info.target())
- except Exception, e:
- # may get here if due to ACM the operation is not permitted
- if security.on() == xsconstants.XS_POLICY_ACM:
- raise VmError('Domain in conflict set with running domain?')
- log.exception(e)
-
- if not self.domid or self.domid < 0:
- failmsg = 'Creating domain failed: name=%s' % self.info['name_label']
- if self.domid:
- failmsg += ', error=%i' % int(self.domid)
- raise VmError(failmsg)
-
- try:
- xc.cpupool_movedomain(pool_id, self.domid)
- except Exception, e:
- raise VmError('Moving domain to target pool failed')
-
- self.dompath = GetDomainPath(self.domid)
-
- self._recreateDom()
-
- # Set TSC mode of domain
- tsc_mode = self.info["platform"].get("tsc_mode")
- if arch.type == "x86" and tsc_mode is not None:
- xc.domain_set_tsc_info(self.domid, int(tsc_mode))
-
- # Set timer configuration of domain
- timer_mode = self.info["platform"].get("timer_mode")
- if hvm and timer_mode is not None:
- xc.hvm_set_param(self.domid, HVM_PARAM_TIMER_MODE,
- long(timer_mode))
-
- if arch.type == "x86" and hvm:
- # Set Viridian interface configuration of domain
- viridian = self.info["platform"].get("viridian")
- if viridian is not None:
- xc.hvm_set_param(self.domid, HVM_PARAM_VIRIDIAN, long(viridian))
- # Set nestedhvm of domain
- nestedhvm = self.info["platform"].get("nestedhvm")
- if nestedhvm is not None:
- xc.hvm_set_param(self.domid, HVM_PARAM_NESTEDHVM, long(nestedhvm))
-
- # If nomigrate is set, disable migration
- nomigrate = self.info["platform"].get("nomigrate")
- if nomigrate is not None and long(nomigrate) != 0:
- xc.domain_disable_migrate(self.domid)
-
- # Optionally enable virtual HPET
- hpet = self.info["platform"].get("hpet")
- if hvm and hpet is not None:
- xc.hvm_set_param(self.domid, HVM_PARAM_HPET_ENABLED,
- long(hpet))
-
- # Optionally enable periodic vpt aligning
- vpt_align = self.info["platform"].get("vpt_align")
- if hvm and vpt_align is not None:
- xc.hvm_set_param(self.domid, HVM_PARAM_VPT_ALIGN,
- long(vpt_align))
-
- # Set maximum number of vcpus in domain
- xc.domain_max_vcpus(self.domid, int(self.info['VCPUs_max']))
-
- # Check for cpu_{cap|weight} validity for credit scheduler
- if XendNode.instance().xenschedinfo() == 'credit':
- cap = self.getCap()
- weight = self.getWeight()
-
- assert type(weight) == int
- assert type(cap) == int
-
- if weight < 1 or weight > 65535:
- raise VmError("Cpu weight out of range, valid values are within range from 1 to 65535")
-
- if cap < 0 or cap > self.getVCpuCount() * 100:
- raise VmError("Cpu cap out of range, valid range is from 0 to %s for specified number of vcpus" %
- (self.getVCpuCount() * 100))
-
- # Test whether the devices can be assigned with VT-d
- self.info.update_platform_pci()
- pci = self.info["platform"].get("pci")
- pci_str = ''
- if pci and len(pci) > 0:
- pci = map(lambda x: x[0:4], pci) # strip options
- pci_str = str(pci)
-
- # This test is done for both pv and hvm guest.
- for p in pci:
- pci_name = '%04x:%02x:%02x.%x' % \
- (parse_hex(p[0]), parse_hex(p[1]), parse_hex(p[2]), parse_hex(p[3]))
- try:
- pci_device = PciDevice(parse_pci_name(pci_name))
- except Exception, e:
- raise VmError("pci: failed to locate device and "+
- "parse its resources - "+str(e))
- if pci_device.driver!='pciback' and pci_device.driver!='pci-stub':
- raise VmError(("pci: PCI Backend and pci-stub don't own device %s")\
- %pci_device.name)
- if pci_name in get_all_assigned_pci_devices():
- raise VmError("failed to assign device %s that has"
- " already been assigned to other domain." % pci_name)
-
- if hvm and pci_str != '':
- bdf = xc.test_assign_device(0, 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("failed to assign device %02x:%02x.%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
- XendDomain.instance().add_domain(self)
-
- def _introduceDomain(self):
- assert self.domid is not None
- assert self.store_mfn is not None
- assert self.store_port is not None
-
- try:
- IntroduceDomain(self.domid, self.store_mfn, self.store_port)
- except RuntimeError, exn:
- raise XendError(str(exn))
-
- def _setTarget(self, target):
- assert self.domid is not None
-
- try:
- SetTarget(self.domid, target)
- self.storeDom('target', target)
- except RuntimeError, exn:
- raise XendError(str(exn))
-
-
- def _setCPUAffinity(self):
- """ Repin domain vcpus if a restricted cpus list is provided.
- Returns the choosen node number.
- """
-
- def has_cpus():
- if self.info['cpus'] is not None:
- for c in self.info['cpus']:
- if c:
- return True
- return False
-
- def has_cpumap():
- if self.info.has_key('vcpus_params'):
- for k, v in self.info['vcpus_params'].items():
- if k.startswith('cpumap'):
- return True
- return False
-
- index = 0
- if has_cpumap():
- for v in range(0, self.info['VCPUs_max']):
- if self.info['vcpus_params'].has_key('cpumap%i' % v):
- cpumask = map(int, self.info['vcpus_params']['cpumap%i' % v].split(','))
- xc.vcpu_setaffinity(self.domid, v, cpumask)
- elif has_cpus():
- for v in range(0, self.info['VCPUs_max']):
- if self.info['cpus'][v]:
- xc.vcpu_setaffinity(self.domid, v, self.info['cpus'][v])
- else:
- def find_relaxed_node(node_list):
- import sys
- nr_nodes = info['max_node_index'] + 1
- if node_list is None:
- node_list = range(0, nr_nodes)
- nodeload = [0]
- nodeload = nodeload * nr_nodes
- from xen.xend import XendDomain
- doms = XendDomain.instance().list('all')
- for dom in filter (lambda d: d.domid != self.domid, doms):
- cpuinfo = dom.getVCPUInfo()
- for vcpu in sxp.children(cpuinfo, 'vcpu'):
- if sxp.child_value(vcpu, 'online') == 0: continue
- cpumap = list(sxp.child_value(vcpu,'cpumap'))
- for i in range(0, nr_nodes):
- node_cpumask = node_to_cpu[i]
- for j in node_cpumask:
- if j in cpumap:
- nodeload[i] += 1
- break
- for i in range(0, nr_nodes):
- if len(node_to_cpu[i]) == 0:
- nodeload[i] += 8
- else:
- nodeload[i] = int(nodeload[i] * 16 / len(node_to_cpu[i]))
- if i not in node_list:
- nodeload[i] += 8
- return map(lambda x: x[0], sorted(enumerate(nodeload), key=lambda x:x[1]))
-
- info = xc.numainfo()
- if info['max_node_index'] > 0 and XendCPUPool.number_of_pools() < 2:
- node_memory_list = info['node_memfree']
- node_to_cpu = []
- for i in range(0, info['max_node_index'] + 1):
- node_to_cpu.append([])
- for cpu, node in enumerate(xc.topologyinfo()['cpu_to_node']):
- node_to_cpu[node].append(cpu)
- needmem = self.image.getRequiredAvailableMemory(self.info['memory_dynamic_max']) / 1024
- candidate_node_list = []
- for i in range(0, info['max_node_index'] + 1):
- if node_memory_list[i] >= needmem and len(node_to_cpu[i]) > 0:
- candidate_node_list.append(i)
- best_node = find_relaxed_node(candidate_node_list)[0]
- cpumask = node_to_cpu[best_node]
- best_nodes = find_relaxed_node(filter(lambda x: x != best_node, range(0,info['max_node_index']+1)))
- for node_idx in best_nodes:
- if len(cpumask) >= self.info['VCPUs_max']:
- break
- cpumask = cpumask + node_to_cpu[node_idx]
- log.debug("allocating additional NUMA node %d", node_idx)
- for v in range(0, self.info['VCPUs_max']):
- xc.vcpu_setaffinity(self.domid, v, cpumask)
- return index
-
- def _freeDMAmemory(self, node):
-
- # If we are PV and have PCI devices the guest will
- # turn on a SWIOTLB. The SWIOTLB _MUST_ be located in the DMA32
- # zone (under 4GB). To do so, we need to balloon down Dom0 to where
- # there is enough (64MB) memory under the 4GB mark. This balloon-ing
- # might take more memory out than just 64MB thought :-(
- if not self.info.is_pv_and_has_pci():
- return
-
- retries = 2000
- ask_for_mem = 0
- need_mem = 0
- try:
- while (retries > 0):
- physinfo = xc.physinfo()
- free_mem = physinfo['free_memory']
- max_node_id = physinfo['max_node_id']
- node_to_dma32_mem = physinfo['node_to_dma32_mem']
- if (node > max_node_id):
- return
- # Extra 2MB above 64GB seems to do the trick.
- need_mem = 64 * 1024 + 2048 - node_to_dma32_mem[node]
- # our starting point. We ask just for the difference to
- # be have an extra 64MB under 4GB.
- ask_for_mem = max(need_mem, ask_for_mem);
- if (need_mem > 0):
- log.debug('_freeDMAmemory (%d) Need %dKiB DMA memory. '
- 'Asking for %dKiB', retries, need_mem,
- ask_for_mem)
-
- balloon.free(ask_for_mem, self)
- ask_for_mem = ask_for_mem + 2048
- else:
- # OK. We got enough DMA memory.
- break
- retries = retries - 1
- except:
- # This is best-try after all.
- need_mem = max(1, need_mem)
- pass
-
- if (need_mem > 0):
- log.warn('We tried our best to balloon down DMA memory to '
- 'accomodate your PV guest. We need %dKiB extra memory.',
- need_mem)
-
- def _setSchedParams(self):
- if XendNode.instance().xenschedinfo() == 'credit':
- from xen.xend import XendDomain
- XendDomain.instance().domain_sched_credit_set(self.getDomid(),
- self.getWeight(),
- self.getCap())
- elif XendNode.instance().xenschedinfo() == 'credit2':
- from xen.xend import XendDomain
- XendDomain.instance().domain_sched_credit2_set(self.getDomid(),
- self.getWeight())
-
- def _initDomain(self):
- log.debug('XendDomainInfo.initDomain: %s %s',
- self.domid,
- self.info['vcpus_params']['weight'])
-
- self._configureBootloader()
-
- try:
- self.image = image.create(self, self.info)
-
- # repin domain vcpus if a restricted cpus list is provided
- # this is done prior to memory allocation to aide in memory
- # distribution for NUMA systems.
- node = self._setCPUAffinity()
-
- # Set scheduling parameters.
- self._setSchedParams()
-
- # Use architecture- and image-specific calculations to determine
- # the various headrooms necessary, given the raw configured
- # values. maxmem, memory, and shadow are all in KiB.
- # but memory_static_max etc are all stored in bytes now.
- memory = self.image.getRequiredAvailableMemory(
- self.info['memory_dynamic_max'] / 1024)
- maxmem = self.image.getRequiredAvailableMemory(
- self.info['memory_static_max'] / 1024)
- shadow = self.image.getRequiredShadowMemory(
- self.info['shadow_memory'] * 1024,
- self.info['memory_static_max'] / 1024)
-
- log.debug("_initDomain:shadow_memory=0x%x, memory_static_max=0x%x, memory_static_min=0x%x.", self.info['shadow_memory'], self.info['memory_static_max'], self.info['memory_static_min'],)
- # Round shadow up to a multiple of a MiB, as shadow_mem_control
- # takes MiB and we must not round down and end up under-providing.
- shadow = ((shadow + 1023) / 1024) * 1024
-
- # set memory limit
- xc.domain_setmaxmem(self.domid, maxmem)
-
- vtd_mem = 0
- info = xc.physinfo()
- if 'hvm_directio' in info['virt_caps']:
- # Reserve 1 page per MiB of RAM for separate VT-d page table.
- vtd_mem = 4 * (self.info['memory_static_max'] / 1024 / 1024)
- # Round vtd_mem up to a multiple of a MiB.
- vtd_mem = ((vtd_mem + 1023) / 1024) * 1024
-
- self.guest_bitsize = self.image.getBitSize()
- # Make sure there's enough RAM available for the domain
- balloon.free(memory + shadow + vtd_mem, self)
-
- # Set up the shadow memory
- shadow_cur = xc.shadow_mem_control(self.domid, shadow / 1024)
- self.info['shadow_memory'] = shadow_cur
-
- # machine address size
- if self.info.has_key('machine_address_size'):
- log.debug("_initDomain: setting maximum machine address size %d" % self.info['machine_address_size'])
- xc.domain_set_machine_address_size(self.domid, self.info['machine_address_size'])
-
- if self.info.has_key('suppress_spurious_page_faults') and self.info['suppress_spurious_page_faults']:
- log.debug("_initDomain: suppressing spurious page faults")
- xc.domain_suppress_spurious_page_faults(self.domid)
-
- self._createChannels()
-
- channel_details = self.image.createImage()
-
- self.store_mfn = channel_details['store_mfn']
- if 'console_mfn' in channel_details:
- self.console_mfn = channel_details['console_mfn']
- if 'notes' in channel_details:
- self.info.set_notes(channel_details['notes'])
- if 'native_protocol' in channel_details:
- self.native_protocol = channel_details['native_protocol'];
-
- self._introduceDomain()
- if self.info.target():
- self._setTarget(self.info.target())
-
- self._freeDMAmemory(node)
-
- self._createDevices()
-
- self.image.cleanupTmpImages()
-
- self.info['start_time'] = time.time()
-
- self._stateSet(DOM_STATE_RUNNING)
- except VmError, exn:
- log.exception("XendDomainInfo.initDomain: exception occurred")
- if self.image:
- self.image.cleanupTmpImages()
- raise exn
- except RuntimeError, exn:
- log.exception("XendDomainInfo.initDomain: exception occurred")
- if self.image:
- self.image.cleanupTmpImages()
- raise VmError(str(exn))
-
-
- def cleanupDomain(self):
- """Cleanup domain resources; release devices. Idempotent. Nothrow
- guarantee."""
-
- self.refresh_shutdown_lock.acquire()
- try:
- self.unwatchShutdown()
- self._releaseDevices()
- bootloader_tidy(self)
-
- if self.image:
- self.image = None
-
- try:
- self._removeDom()
- except:
- log.exception("Removing domain path failed.")
-
- self._stateSet(DOM_STATE_HALTED)
- self.domid = None # Do not push into _stateSet()!
- finally:
- self.refresh_shutdown_lock.release()
-
-
- def unwatchShutdown(self):
- """Remove the watch on the domain's control/shutdown node, if any.
- Idempotent. Nothrow guarantee. Expects to be protected by the
- refresh_shutdown_lock."""
-
- try:
- try:
- if self.shutdownWatch:
- self.shutdownWatch.unwatch()
- finally:
- self.shutdownWatch = None
- except:
- log.exception("Unwatching control/shutdown failed.")
-
- def waitForShutdown(self):
- self.state_updated.acquire()
- try:
- while self._stateGet() in (DOM_STATE_RUNNING,DOM_STATE_PAUSED):
- self.state_updated.wait(timeout=1.0)
- finally:
- self.state_updated.release()
-
- def waitForSuspend(self):
- """Wait for the guest to respond to a suspend request by
- shutting down. If the guest hasn't re-written control/shutdown
- after a certain amount of time, it's obviously not listening and
- won't suspend, so we give up. HVM guests with no PV drivers
- should already be shutdown.
- """
- state = "suspend"
- nr_tries = 60
-
- self.state_updated.acquire()
- try:
- while self._stateGet() in (DOM_STATE_RUNNING,DOM_STATE_PAUSED):
- self.state_updated.wait(1.0)
- if state == "suspend":
- if nr_tries == 0:
- msg = ('Timeout waiting for domain %s to suspend'
- % self.domid)
- self._writeDom('control/shutdown', '')
- raise XendError(msg)
- state = self.readDom('control/shutdown')
- nr_tries -= 1
- finally:
- self.state_updated.release()
-
- #
- # TODO: recategorise - called from XendCheckpoint
- #
-
- def completeRestore(self, store_mfn, console_mfn):
-
- log.debug("XendDomainInfo.completeRestore")
-
- self.store_mfn = store_mfn
- self.console_mfn = console_mfn
-
- self._introduceDomain()
- self.image = image.create(self, self.info)
- if self.image:
- self.image.createDeviceModel(True)
- self._storeDomDetails()
- self._registerWatches()
- self.refreshShutdown()
-
- log.debug("XendDomainInfo.completeRestore done")
-
-
- def _endRestore(self):
- self.setResume(False)
-
- #
- # VM Destroy
- #
-
- def _prepare_phantom_paths(self):
- # get associated devices to destroy
- # build list of phantom devices to be removed after normal devices
- plist = []
- if self.domid is not None:
- t = xstransact("%s/device/vbd" % GetDomainPath(self.domid))
- try:
- for dev in t.list():
- backend_phantom_vbd = xstransact.Read("%s/device/vbd/%s/phantom_vbd" \
- % (self.dompath, dev))
- if backend_phantom_vbd is not None:
- frontend_phantom_vbd = xstransact.Read("%s/frontend" \
- % backend_phantom_vbd)
- plist.append(backend_phantom_vbd)
- plist.append(frontend_phantom_vbd)
- finally:
- t.abort()
- return plist
-
- def _cleanup_phantom_devs(self, plist):
- # remove phantom devices
- if not plist == []:
- time.sleep(2)
- for paths in plist:
- if paths.find('backend') != -1:
- # Modify online status /before/ updating state (latter is watched by
- # drivers, so this ordering avoids a race).
- xstransact.Write(paths, 'online', "0")
- xstransact.Write(paths, 'state', str(xenbusState['Closing']))
- # force
- xstransact.Remove(paths)
-
- def destroy(self):
- """Cleanup VM and destroy domain. Nothrow guarantee."""
-
- if self.domid is None:
- return
- from xen.xend import XendDomain
- log.debug("XendDomainInfo.destroy: domid=%s", str(self.domid))
-
- paths = self._prepare_phantom_paths()
-
- if self.dompath is not None:
- try:
- xc.domain_destroy_hook(self.domid)
- xc.domain_pause(self.domid)
- do_FLR(self.domid, self.info.is_hvm())
- xc.domain_destroy(self.domid)
- for state in DOM_STATES_OLD:
- self.info[state] = 0
- self._stateSet(DOM_STATE_HALTED)
- except:
- log.exception("XendDomainInfo.destroy: domain destruction failed.")
-
- XendDomain.instance().remove_domain(self)
- self.cleanupDomain()
-
- if self.info.is_hvm() or self.guest_bitsize != 32:
- if self.alloc_mem:
- import MemoryPool
- log.debug("%s KiB need to add to Memory pool" %self.alloc_mem)
- MemoryPool.instance().increase_memory(self.alloc_mem)
-
- self._cleanup_phantom_devs(paths)
- self._cleanupVm()
-
- if ("transient" in self.info["other_config"] and \
- bool(self.info["other_config"]["transient"])) or \
- ("change_home_server" in self.info and \
- bool(self.info["change_home_server"])):
- XendDomain.instance().domain_delete_by_dominfo(self)
-
-
- def resetDomain(self):
- log.debug("XendDomainInfo.resetDomain(%s)", str(self.domid))
-
- old_domid = self.domid
- prev_vm_xend = self._listRecursiveVm('xend')
- new_dom_info = self.info
- try:
- self._unwatchVm()
- self.destroy()
-
- new_dom = None
- try:
- from xen.xend import XendDomain
- new_dom_info['domid'] = None
- new_dom = XendDomain.instance().domain_create_from_dict(
- new_dom_info)
- for x in prev_vm_xend[0][1]:
- new_dom._writeVm('xend/%s' % x[0], x[1])
- new_dom.waitForDevices()
- new_dom.unpause()
- except:
- if new_dom:
- new_dom.destroy()
- raise
- except:
- log.exception('Failed to reset domain %s.', str(old_domid))
-
-
- def resumeDomain(self):
- log.debug("XendDomainInfo.resumeDomain(%s)", str(self.domid))
-
- # resume a suspended domain (e.g. after live checkpoint, or after
- # a later error during save or migate); checks that the domain
- # is currently suspended first so safe to call from anywhere
-
- xeninfo = dom_get(self.domid)
- if xeninfo is None:
- return
- if not xeninfo['shutdown']:
- return
- reason = shutdown_reason(xeninfo['shutdown_reason'])
- if reason != 'suspend':
- return
-
- try:
- # could also fetch a parsed note from xenstore
- fast = self.info.get_notes().get('SUSPEND_CANCEL') and 1 or 0
- if not fast:
- self._releaseDevices()
- self.testDeviceComplete()
- self.testvifsComplete()
- log.debug("XendDomainInfo.resumeDomain: devices released")
-
- self._resetChannels()
-
- self._removeDom('control/shutdown')
- self._removeDom('device-misc/vif/nextDeviceID')
-
- self._createChannels()
- self._introduceDomain()
- self._storeDomDetails()
-
- self._createDevices()
- log.debug("XendDomainInfo.resumeDomain: devices created")
-
- xc.domain_resume(self.domid, fast)
- ResumeDomain(self.domid)
- except:
- log.exception("XendDomainInfo.resume: xc.domain_resume failed on domain %s." % (str(self.domid)))
- self.image.resumeDeviceModel()
- log.debug("XendDomainInfo.resumeDomain: completed")
-
-
- #
- # Channels for xenstore and console
- #
-
- def _createChannels(self):
- """Create the channels to the domain.
- """
- self.store_port = self._createChannel()
- self.console_port = self._createChannel()
-
-
- def _createChannel(self):
- """Create an event channel to the domain.
- """
- try:
- if self.domid != None:
- return xc.evtchn_alloc_unbound(domid = self.domid,
- remote_dom = 0)
- except:
- log.exception("Exception in alloc_unbound(%s)", str(self.domid))
- raise
-
- def _resetChannels(self):
- """Reset all event channels in the domain.
- """
- try:
- if self.domid != None:
- return xc.evtchn_reset(dom = self.domid)
- except:
- log.exception("Exception in evtcnh_reset(%s)", str(self.domid))
- raise
-
-
- #
- # Bootloader configuration
- #
-
- def _configureBootloader(self):
- """Run the bootloader if we're configured to do so."""
-
- blexec = self.info['PV_bootloader']
- bootloader_args = self.info['PV_bootloader_args']
- kernel = self.info['PV_kernel']
- ramdisk = self.info['PV_ramdisk']
- args = self.info['PV_args']
- boot = self.info['HVM_boot_policy']
-
- if boot:
- # HVM booting.
- pass
- elif not blexec and kernel:
- # Boot from dom0. Nothing left to do -- the kernel and ramdisk
- # will be picked up by image.py.
- pass
- else:
- # Boot using bootloader
- if not blexec or blexec == 'pygrub':
- blexec = auxbin.pathTo('pygrub')
-
- blcfg = None
- disks = [x for x in self.info['vbd_refs']
- if self.info['devices'][x][1]['bootable']]
-
- if not disks:
- msg = "Had a bootloader specified, but no disks are bootable"
- log.error(msg)
- raise VmError(msg)
-
- devinfo = self.info['devices'][disks[0]]
- devtype = devinfo[0]
- disk = devinfo[1]['uname']
-
- (fn, types) = parse_uname(disk)
- def _shouldMount(types):
- if types[0] in ('file', 'phy'):
- return False
- if types[0] in ('tap', 'tap2'):
- if types[1] in ('aio', 'sync'):
- return False
- else:
- return True
- return os.access('/etc/xen/scripts/block-%s' % types[0], os.X_OK)
-
- mounted = _shouldMount(types)
- mounted_vbd_uuid = 0
- if mounted:
- # This is a file, not a device. pygrub can cope with a
- # file if it's raw, but if it's QCOW or other such formats
- # used through blktap, then we need to mount it first.
-
- log.info("Mounting %s on %s." %
- (fn, BOOTLOADER_LOOPBACK_DEVICE))
-
- vbd = {
- 'mode': 'RO',
- 'device': BOOTLOADER_LOOPBACK_DEVICE,
- }
-
- from xen.xend import XendDomain
- dom0 = XendDomain.instance().privilegedDomain()
- mounted_vbd_uuid = dom0.create_vbd(vbd, disk);
- dom0._waitForDeviceUUID(mounted_vbd_uuid)
- fn = BOOTLOADER_LOOPBACK_DEVICE
-
- try:
- blcfg = bootloader(blexec, fn, self, False,
- bootloader_args, kernel, ramdisk, args)
- finally:
- if mounted:
- log.info("Unmounting %s from %s." %
- (fn, BOOTLOADER_LOOPBACK_DEVICE))
- _, vbd_info = dom0.info['devices'][mounted_vbd_uuid]
- dom0.destroyDevice(dom0.getBlockDeviceClass(vbd_info['devid']),
- BOOTLOADER_LOOPBACK_DEVICE, force = True)
-
- if blcfg is None:
- msg = "Had a bootloader specified, but can't find disk"
- log.error(msg)
- raise VmError(msg)
-
- self.info.update_with_image_sxp(blcfg, True)
-
-
- #
- # VM Functions
- #
-
- def _readVMDetails(self, params):
- """Read the specified parameters from the store.
- """
- try:
- return self._gatherVm(*params)
- except ValueError:
- # One of the int/float entries in params has a corresponding store
- # entry that is invalid. We recover, because older versions of
- # Xend may have put the entry there (memory/target, for example),
- # but this is in general a bad situation to have reached.
- log.exception(
- "Store corrupted at %s! Domain %d's configuration may be "
- "affected.", self.vmpath, self.domid)
- return []
-
- def _cleanupVm(self):
- """Cleanup VM resources. Idempotent. Nothrow guarantee."""
-
- self._unwatchVm()
-
- try:
- self._removeVm()
- except:
- log.exception("Removing VM path failed.")
-
-
- def checkLiveMigrateMemory(self):
- """ Make sure there's enough memory to migrate this domain """
- overhead_kb = 0
- if arch.type == "x86":
- # 1MB per vcpu plus 4Kib/Mib of RAM. This is higher than
- # the minimum that Xen would allocate if no value were given.
- overhead_kb = self.info['VCPUs_max'] * 1024 + \
- (self.info['memory_static_max'] / 1024 / 1024) * 4
- overhead_kb = ((overhead_kb + 1023) / 1024) * 1024
- # The domain might already have some shadow memory
- overhead_kb -= xc.shadow_mem_control(self.domid) * 1024
- if overhead_kb > 0:
- balloon.free(overhead_kb, self)
-
- def _unwatchVm(self):
- """Remove the watch on the VM path, if any. Idempotent. Nothrow
- guarantee."""
- try:
- try:
- if self.vmWatch:
- self.vmWatch.unwatch()
- finally:
- self.vmWatch = None
- except:
- log.exception("Unwatching VM path failed.")
-
- def testDeviceComplete(self):
- """ For Block IO migration safety we must ensure that
- the device has shutdown correctly, i.e. all blocks are
- flushed to disk
- """
- start = time.time()
- while True:
- test = 0
- diff = time.time() - start
- vbds = self.getDeviceController('vbd').deviceIDs()
- taps = self.getDeviceController('tap').deviceIDs()
- tap2s = self.getDeviceController('tap2').deviceIDs()
- for i in vbds + taps + tap2s:
- test = 1
- log.info("Dev %s still active, looping...", i)
- time.sleep(0.1)
-
- if test == 0:
- break
- if diff >= MIGRATE_TIMEOUT:
- log.info("Dev still active but hit max loop timeout")
- break
-
- def testvifsComplete(self):
- """ In case vifs are released and then created for the same
- domain, we need to wait the device shut down.
- """
- start = time.time()
- while True:
- test = 0
- diff = time.time() - start
- for i in self.getDeviceController('vif').deviceIDs():
- test = 1
- log.info("Dev %s still active, looping...", i)
- time.sleep(0.1)
-
- if test == 0:
- break
- if diff >= MIGRATE_TIMEOUT:
- log.info("Dev still active but hit max loop timeout")
- break
-
- def _storeVmDetails(self):
- to_store = {}
-
- for key in XendConfig.LEGACY_XENSTORE_VM_PARAMS:
- info_key = XendConfig.LEGACY_CFG_TO_XENAPI_CFG.get(key, key)
- if self._infoIsSet(info_key):
- to_store[key] = str(self.info[info_key])
-
- if self._infoIsSet("static_memory_min"):
- to_store["memory"] = str(self.info["static_memory_min"])
- if self._infoIsSet("static_memory_max"):
- to_store["maxmem"] = str(self.info["static_memory_max"])
-
- image_sxpr = self.info.image_sxpr()
- if image_sxpr:
- to_store['image'] = sxp.to_string(image_sxpr)
-
- if not self._readVm('xend/restart_count'):
- to_store['xend/restart_count'] = str(0)
-
- log.debug("Storing VM details: %s", scrub_password(to_store))
-
- self._writeVm(to_store)
- self._setVmPermissions()
-
- def _setVmPermissions(self):
- """Allow the guest domain to read its UUID. We don't allow it to
- access any other entry, for security."""
- xstransact.SetPermissions('%s/uuid' % self.vmpath,
- { 'dom' : self.domid,
- 'read' : True,
- 'write' : False })
-
- #
- # Utility functions
- #
-
- def __getattr__(self, name):
- if name == "state":
- log.warn("Somebody tried to read XendDomainInfo.state... should us _stateGet()!!!")
- log.warn("".join(traceback.format_stack()))
- return self._stateGet()
- else:
- raise AttributeError(name)
-
- def __setattr__(self, name, value):
- if name == "state":
- log.warn("Somebody tried to set XendDomainInfo.state... should us _stateGet()!!!")
- log.warn("".join(traceback.format_stack()))
- self._stateSet(value)
- else:
- self.__dict__[name] = value
-
- def _stateSet(self, state):
- self.state_updated.acquire()
- try:
- # TODO Not sure this is correct...
- # _stateGet is live now. Why not fire event
- # even when it hasn't changed?
- if self._stateGet() != state:
- self.state_updated.notifyAll()
- import XendAPI
- XendAPI.event_dispatch('mod', 'VM', self.info['uuid'],
- 'power_state')
- finally:
- self.state_updated.release()
-
- def _stateGet(self):
- # Lets try and reconsitute the state from xc
- # first lets try and get the domain info
- # from xc - this will tell us if the domain
- # exists
- info = dom_get(self.getDomid())
- if info is None or info['shutdown']:
- # We are either HALTED or SUSPENDED
- # check saved image exists
- from xen.xend import XendDomain
- managed_config_path = \
- XendDomain.instance()._managed_check_point_path( \
- self.get_uuid())
- if os.path.exists(managed_config_path):
- return XEN_API_VM_POWER_STATE_SUSPENDED
- else:
- return XEN_API_VM_POWER_STATE_HALTED
- elif info['crashed']:
- # Crashed
- return XEN_API_VM_POWER_STATE_CRASHED
- else:
- # We are either RUNNING or PAUSED
- if info['paused']:
- return XEN_API_VM_POWER_STATE_PAUSED
- else:
- return XEN_API_VM_POWER_STATE_RUNNING
-
- def _infoIsSet(self, name):
- return name in self.info and self.info[name] is not None
-
- def _checkName(self, name):
- """Check if a vm name is valid. Valid names contain alphabetic
- characters, digits, or characters in '_-.:+'.
- The same name cannot be used for more than one vm at the same time.
-
- @param name: name
- @raise: VmError if invalid
- """
- from xen.xend import XendDomain
-
- if name is None or name == '':
- raise VmError('Missing VM Name')
-
- if not re.search(r'^[A-Za-z0-9_\-\.\:\+]+$', name):
- raise VmError('Invalid VM Name')
-
- dom = XendDomain.instance().domain_lookup_nr(name)
- if dom and dom.info['uuid'] != self.info['uuid']:
- raise VmError("VM name '%s' already exists%s" %
- (name,
- dom.domid is not None and
- (" as domain %s" % str(dom.domid)) or ""))
-
-
- def update(self, info = None, refresh = True, transaction = None):
- """Update with info from xc.domain_getinfo().
- """
- log.trace("XendDomainInfo.update(%s) on domain %s", info,
- str(self.domid))
-
- if not info:
- info = dom_get(self.domid)
- if not info:
- return
-
- if info["maxmem_kb"] < 0:
- info["maxmem_kb"] = XendNode.instance() \
- .physinfo_dict()['total_memory'] * 1024
-
- # make sure state is reset for info
- # TODO: we should eventually get rid of old_dom_states
-
- self.info.update_config(info)
- self._update_consoles(transaction)
-
- if refresh:
- self.refreshShutdown(info)
-
- log.trace("XendDomainInfo.update done on domain %s: %s",
- str(self.domid), self.info)
-
- def sxpr(self, ignore_store = False, legacy_only = True):
- result = self.info.to_sxp(domain = self,
- ignore_devices = ignore_store,
- legacy_only = legacy_only)
-
- return result
-
- # Xen API
- # ----------------------------------------------------------------
-
- def get_uuid(self):
- dom_uuid = self.info.get('uuid')
- if not dom_uuid: # if it doesn't exist, make one up
- dom_uuid = uuid.createString()
- self.info['uuid'] = dom_uuid
- return dom_uuid
-
- def get_memory_static_max(self):
- return self.info.get('memory_static_max', 0)
- def get_memory_static_min(self):
- return self.info.get('memory_static_min', 0)
- def get_memory_dynamic_max(self):
- return self.info.get('memory_dynamic_max', 0)
- def get_memory_dynamic_min(self):
- return self.info.get('memory_dynamic_min', 0)
-
- # only update memory-related config values if they maintain sanity
- def _safe_set_memory(self, key, newval):
- oldval = self.info.get(key, 0)
- try:
- self.info[key] = newval
- self.info._memory_sanity_check()
- except Exception, ex:
- self.info[key] = oldval
- raise
-
- def set_memory_static_max(self, val):
- self._safe_set_memory('memory_static_max', val)
- def set_memory_static_min(self, val):
- self._safe_set_memory('memory_static_min', val)
- def set_memory_dynamic_max(self, val):
- self._safe_set_memory('memory_dynamic_max', val)
- def set_memory_dynamic_min(self, val):
- self._safe_set_memory('memory_dynamic_min', val)
-
- def get_vcpus_params(self):
- if self.getDomid() is None:
- return self.info['vcpus_params']
-
- retval = xc.sched_credit_domain_get(self.getDomid())
- return retval
- def get_cpu_pool(self):
- if self.getDomid() is None:
- return None
- xeninfo = dom_get(self.domid)
- return xeninfo['cpupool']
- def get_power_state(self):
- return XEN_API_VM_POWER_STATE[self._stateGet()]
- def get_platform(self):
- return self.info.get('platform', {})
- def get_pci_bus(self):
- return self.info.get('pci_bus', '')
- def get_tools_version(self):
- return self.info.get('tools_version', {})
- def get_metrics(self):
- return self.metrics.get_uuid();
-
-
- def get_security_label(self, xspol=None):
- import xen.util.xsm.xsm as security
- label = security.get_security_label(self, xspol)
- return label
-
- def set_security_label(self, seclab, old_seclab, xspol=None,
- xspol_old=None):
- """
- Set the security label of a domain from its old to
- a new value.
- @param seclab New security label formatted in the form
- <policy type>:<policy name>:<vm label>
- @param old_seclab The current security label that the
- VM must have.
- @param xspol An optional policy under which this
- update should be done. If not given,
- then the current active policy is used.
- @param xspol_old The old policy; only to be passed during
- the updating of a policy
- @return Returns return code, a string with errors from
- the hypervisor's operation, old label of the
- domain
- """
- rc = 0
- errors = ""
- old_label = ""
- new_ssidref = 0
- domid = self.getDomid()
- res_labels = None
- is_policy_update = (xspol_old != None)
-
- from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
-
- state = self._stateGet()
- # Relabel only HALTED or RUNNING or PAUSED domains
- if domid != 0 and \
- state not in \
- [ DOM_STATE_HALTED, DOM_STATE_RUNNING, DOM_STATE_PAUSED, \
- DOM_STATE_SUSPENDED ]:
- log.warn("Relabeling domain not possible in state '%s'" %
- DOM_STATES[state])
- return (-xsconstants.XSERR_VM_WRONG_STATE, "", "", 0)
-
- # Remove security label. Works only for halted or suspended domains
- if not seclab or seclab == "":
- if state not in [ DOM_STATE_HALTED, DOM_STATE_SUSPENDED ]:
- return (-xsconstants.XSERR_VM_WRONG_STATE, "", "", 0)
-
- if self.info.has_key('security_label'):
- old_label = self.info['security_label']
- # Check label against expected one.
- if old_label != old_seclab:
- return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
- del self.info['security_label']
- xen.xend.XendDomain.instance().managed_config_save(self)
- return (xsconstants.XSERR_SUCCESS, "", "", 0)
-
- tmp = seclab.split(":")
- if len(tmp) != 3:
- return (-xsconstants.XSERR_BAD_LABEL_FORMAT, "", "", 0)
- typ, policy, label = tmp
-
- poladmin = XSPolicyAdminInstance()
- if not xspol:
- xspol = poladmin.get_policy_by_name(policy)
-
- try:
- xen.xend.XendDomain.instance().policy_lock.acquire_writer()
-
- if state in [ DOM_STATE_RUNNING, DOM_STATE_PAUSED ]:
- #if domain is running or paused try to relabel in hypervisor
- if not xspol:
- return (-xsconstants.XSERR_POLICY_NOT_LOADED, "", "", 0)
-
- if typ != xspol.get_type_name() or \
- policy != xspol.get_name():
- return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
-
- if typ == xsconstants.ACM_POLICY_ID:
- new_ssidref = xspol.vmlabel_to_ssidref(label)
- if new_ssidref == xsconstants.INVALID_SSIDREF:
- return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
-
- # Check that all used resources are accessible under the
- # new label
- if not is_policy_update and \
- not security.resources_compatible_with_vmlabel(xspol,
- self, label):
- return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
-
- #Check label against expected one. Can only do this
- # if the policy hasn't changed underneath in the meantime
- if xspol_old == None:
- old_label = self.get_security_label()
- if old_label != old_seclab:
- log.info("old_label != old_seclab: %s != %s" %
- (old_label, old_seclab))
- return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
-
- # relabel domain in the hypervisor
- rc, errors = security.relabel_domains([[domid, new_ssidref]])
- log.info("rc from relabeling in HV: %d" % rc)
- else:
- return (-xsconstants.XSERR_POLICY_TYPE_UNSUPPORTED, "", "", 0)
-
- if rc == 0:
- # HALTED, RUNNING or PAUSED
- if domid == 0:
- if xspol:
- self.info['security_label'] = seclab
- ssidref = poladmin.set_domain0_bootlabel(xspol, label)
- else:
- return (-xsconstants.XSERR_POLICY_NOT_LOADED, "", "", 0)
- else:
- if self.info.has_key('security_label'):
- old_label = self.info['security_label']
- # Check label against expected one, unless wildcard
- if old_label != old_seclab:
- return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
-
- self.info['security_label'] = seclab
-
- try:
- xen.xend.XendDomain.instance().managed_config_save(self)
- except:
- pass
- return (rc, errors, old_label, new_ssidref)
- finally:
- xen.xend.XendDomain.instance().policy_lock.release()
-
- def get_on_shutdown(self):
- after_shutdown = self.info.get('actions_after_shutdown')
- if not after_shutdown or after_shutdown not in XEN_API_ON_NORMAL_EXIT:
- return XEN_API_ON_NORMAL_EXIT[-1]
- return after_shutdown
-
- def get_on_reboot(self):
- after_reboot = self.info.get('actions_after_reboot')
- if not after_reboot or after_reboot not in XEN_API_ON_NORMAL_EXIT:
- return XEN_API_ON_NORMAL_EXIT[-1]
- return after_reboot
-
- def get_on_suspend(self):
- # TODO: not supported
- after_suspend = self.info.get('actions_after_suspend')
- if not after_suspend or after_suspend not in XEN_API_ON_NORMAL_EXIT:
- return XEN_API_ON_NORMAL_EXIT[-1]
- return after_suspend
-
- def get_on_crash(self):
- after_crash = self.info.get('actions_after_crash')
- if not after_crash or after_crash not in \
- XEN_API_ON_CRASH_BEHAVIOUR + restart_modes:
- return XEN_API_ON_CRASH_BEHAVIOUR[0]
- return XEN_API_ON_CRASH_BEHAVIOUR_FILTER[after_crash]
-
- def get_dev_config_by_uuid(self, dev_class, dev_uuid):
- """ Get's a device configuration either from XendConfig or
- from the DevController.
-
- @param dev_class: device class, either, 'vbd' or 'vif'
- @param dev_uuid: device UUID
-
- @rtype: dictionary
- """
- dev_type, dev_config = self.info['devices'].get(dev_uuid, (None, None))
-
- # shortcut if the domain isn't started because
- # the devcontrollers will have no better information
- # than XendConfig.
- if self._stateGet() in (XEN_API_VM_POWER_STATE_HALTED,
- XEN_API_VM_POWER_STATE_SUSPENDED):
- if dev_config:
- return copy.deepcopy(dev_config)
- return None
-
- # instead of using dev_class, we use the dev_type
- # that is from XendConfig.
- controller = self.getDeviceController(dev_type)
- if not controller:
- return None
-
- all_configs = controller.getAllDeviceConfigurations()
- if not all_configs:
- return None
-
- updated_dev_config = copy.deepcopy(dev_config)
- for _devid, _devcfg in all_configs.items():
- if _devcfg.get('uuid') == dev_uuid:
- updated_dev_config.update(_devcfg)
- updated_dev_config['id'] = _devid
- return updated_dev_config
-
- return updated_dev_config
-
- def get_dev_xenapi_config(self, dev_class, dev_uuid):
- config = self.get_dev_config_by_uuid(dev_class, dev_uuid)
- if not config:
- return {}
-
- config['VM'] = self.get_uuid()
-
- if dev_class == 'vif':
- if not config.has_key('name'):
- config['name'] = config.get('vifname', '')
- if not config.has_key('MAC'):
- config['MAC'] = config.get('mac', '')
- if not config.has_key('type'):
- config['type'] = 'paravirtualised'
- if not config.has_key('device'):
- devid = config.get('id')
- if devid != None:
- config['device'] = 'eth%s' % devid
- else:
- config['device'] = ''
-
- if not config.has_key('network'):
- try:
- bridge = config.get('bridge', None)
- if bridge is None:
- from xen.util import Brctl
- if_to_br = dict([(i,b)
- for (b,ifs) in Brctl.get_state().items()
- for i in ifs])
- vifname = "vif%s.%s" % (self.getDomid(),
- config.get('id'))
- bridge = if_to_br.get(vifname, None)
- config['network'] = \
- XendNode.instance().bridge_to_network(
- config.get('bridge')).get_uuid()
- except Exception:
- log.exception('bridge_to_network')
- # Ignore this for now -- it may happen if the device
- # has been specified using the legacy methods, but at
- # some point we're going to have to figure out how to
- # handle that properly.
-
- config['MTU'] = 1500 # TODO
-
- if self._stateGet() not in (XEN_API_VM_POWER_STATE_HALTED,):
- xennode = XendNode.instance()
- rx_bps, tx_bps = xennode.get_vif_util(self.domid, devid)
- config['io_read_kbs'] = rx_bps/1024
- config['io_write_kbs'] = tx_bps/1024
- rx, tx = xennode.get_vif_stat(self.domid, devid)
- config['io_total_read_kbs'] = rx/1024
- config['io_total_write_kbs'] = tx/1024
- else:
- config['io_read_kbs'] = 0.0
- config['io_write_kbs'] = 0.0
- config['io_total_read_kbs'] = 0.0
- config['io_total_write_kbs'] = 0.0
-
- config['security_label'] = config.get('security_label', '')
-
- if dev_class == 'vbd':
-
- if self._stateGet() not in (XEN_API_VM_POWER_STATE_HALTED,):
- controller = self.getDeviceController(dev_class)
- devid, _1, _2 = controller.getDeviceDetails(config)
- xennode = XendNode.instance()
- rd_blkps, wr_blkps = xennode.get_vbd_util(self.domid, devid)
- config['io_read_kbs'] = rd_blkps
- config['io_write_kbs'] = wr_blkps
- else:
- config['io_read_kbs'] = 0.0
- config['io_write_kbs'] = 0.0
-
- config['VDI'] = config.get('VDI', '')
- config['device'] = config.get('dev', '')
- if config['device'].startswith('ioemu:'):
- _, vbd_device = config['device'].split(':', 1)
- config['device'] = vbd_device
- if ':' in config['device']:
- vbd_name, vbd_type = config['device'].split(':', 1)
- config['device'] = vbd_name
- if vbd_type == 'cdrom':
- config['type'] = XEN_API_VBD_TYPE[0]
- else:
- config['type'] = XEN_API_VBD_TYPE[1]
-
- config['driver'] = 'paravirtualised' # TODO
- config['image'] = config.get('uname', '')
-
- if config.get('mode', 'r') == 'r':
- config['mode'] = 'RO'
- else:
- config['mode'] = 'RW'
-
- return config
-
- def get_dev_property(self, dev_class, dev_uuid, field):
- config = self.get_dev_xenapi_config(dev_class, dev_uuid)
- try:
- return config[field]
- except KeyError:
- raise XendError('Invalid property for device: %s' % field)
-
- def set_dev_property(self, dev_class, dev_uuid, field, value):
- self.info['devices'][dev_uuid][1][field] = value
-
- def get_vcpus_util(self):
- vcpu_util = {}
- xennode = XendNode.instance()
- if 'VCPUs_max' in self.info and self.domid != None:
- for i in range(0, self.info['VCPUs_max']):
- util = xennode.get_vcpu_util(self.domid, i)
- vcpu_util[str(i)] = util
-
- return vcpu_util
-
- def get_consoles(self):
- return self.info.get('console_refs', [])
-
- def get_vifs(self):
- return self.info.get('vif_refs', [])
-
- def get_vbds(self):
- return self.info.get('vbd_refs', [])
-
- def get_dpcis(self):
- return XendDPCI.get_by_VM(self.info.get('uuid'))
-
- def get_dscsis(self):
- return XendDSCSI.get_by_VM(self.info.get('uuid'))
-
- def get_dscsi_HBAs(self):
- return XendDSCSI_HBA.get_by_VM(self.info.get('uuid'))
-
- def create_vbd(self, xenapi_vbd, vdi_image_path):
- """Create a VBD using a VDI from XendStorageRepository.
-
- @param xenapi_vbd: vbd struct from the Xen API
- @param vdi_image_path: VDI UUID
- @rtype: string
- @return: uuid of the device
- """
- xenapi_vbd['image'] = vdi_image_path
- if vdi_image_path.startswith('tap'):
- dev_uuid = self.info.device_add('tap2', cfg_xenapi = xenapi_vbd)
- else:
- dev_uuid = self.info.device_add('vbd', cfg_xenapi = xenapi_vbd)
-
- if not dev_uuid:
- raise XendError('Failed to create device')
-
- if self._stateGet() in (XEN_API_VM_POWER_STATE_RUNNING,
- XEN_API_VM_POWER_STATE_PAUSED):
- _, config = self.info['devices'][dev_uuid]
-
- if vdi_image_path.startswith('tap'):
- dev_control = self.getDeviceController('tap2')
- else:
- dev_control = self.getDeviceController('vbd')
-
- try:
- devid = dev_control.createDevice(config)
- dev_type = self.getBlockDeviceClass(devid)
- self._waitForDevice(dev_type, devid)
- self.info.device_update(dev_uuid,
- cfg_xenapi = {'devid': devid})
- except Exception, exn:
- log.exception(exn)
- del self.info['devices'][dev_uuid]
- self.info['vbd_refs'].remove(dev_uuid)
- raise
-
- return dev_uuid
-
- def create_phantom_vbd_with_vdi(self, xenapi_vbd, vdi_image_path):
- """Create a VBD using a VDI from XendStorageRepository.
-
- @param xenapi_vbd: vbd struct from the Xen API
- @param vdi_image_path: VDI UUID
- @rtype: string
- @return: uuid of the device
- """
- xenapi_vbd['image'] = vdi_image_path
- dev_uuid = self.info.phantom_device_add('tap', cfg_xenapi = xenapi_vbd)
- if not dev_uuid:
- raise XendError('Failed to create device')
-
- if self._stateGet() == XEN_API_VM_POWER_STATE_RUNNING:
- _, config = self.info['devices'][dev_uuid]
- config['devid'] = self.getDeviceController('tap').createDevice(config)
-
- return config['devid']
-
- def create_vif(self, xenapi_vif):
- """Create VIF device from the passed struct in Xen API format.
-
- @param xenapi_vif: Xen API VIF Struct.
- @rtype: string
- @return: UUID
- """
- dev_uuid = self.info.device_add('vif', cfg_xenapi = xenapi_vif)
- if not dev_uuid:
- raise XendError('Failed to create device')
-
- if self._stateGet() in (XEN_API_VM_POWER_STATE_RUNNING,
- XEN_API_VM_POWER_STATE_PAUSED):
-
- _, config = self.info['devices'][dev_uuid]
- dev_control = self.getDeviceController('vif')
-
- try:
- devid = dev_control.createDevice(config)
- dev_control.waitForDevice(devid)
- self.info.device_update(dev_uuid,
- cfg_xenapi = {'devid': devid})
- except Exception, exn:
- log.exception(exn)
- del self.info['devices'][dev_uuid]
- self.info['vif_refs'].remove(dev_uuid)
- raise
-
- return dev_uuid
-
- def create_console(self, xenapi_console):
- """ Create a console device from a Xen API struct.
-
- @return: uuid of device
- @rtype: string
- """
- if self._stateGet() not in (DOM_STATE_HALTED,):
- raise VmError("Can only add console to a halted domain.")
-
- dev_uuid = self.info.device_add('console', cfg_xenapi = xenapi_console)
- if not dev_uuid:
- raise XendError('Failed to create device')
-
- return dev_uuid
-
- def set_console_other_config(self, console_uuid, other_config):
- self.info.console_update(console_uuid, 'other_config', other_config)
-
- def create_dpci(self, xenapi_pci):
- """Create pci device from the passed struct in Xen API format.
-
- @param xenapi_pci: DPCI struct from Xen API
- @rtype: bool
- #@rtype: string
- @return: True if successfully created device
- #@return: UUID
- """
-
- dpci_uuid = uuid.createString()
-
- dpci_opts = []
- opts_dict = xenapi_pci.get('options')
- for k in opts_dict.keys():
- dpci_opts.append([k, opts_dict[k]])
- opts_sxp = pci_opts_list_to_sxp(dpci_opts)
-
- # Convert xenapi to sxp
- ppci = XendAPIStore.get(xenapi_pci.get('PPCI'), 'PPCI')
-
- dev_sxp = ['dev',
- ['domain', '0x%02x' % ppci.get_domain()],
- ['bus', '0x%02x' % ppci.get_bus()],
- ['slot', '0x%02x' % ppci.get_slot()],
- ['func', '0x%1x' % ppci.get_func()],
- ['vdevfn', '0x%02x' % xenapi_pci.get('hotplug_slot')],
- ['key', xenapi_pci['key']],
- ['uuid', dpci_uuid]]
- dev_sxp = sxp.merge(dev_sxp, opts_sxp)
-
- target_pci_sxp = ['pci', dev_sxp, ['state', 'Initialising'] ]
-
- if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING:
-
- old_pci_sxp = self._getDeviceInfo_pci(0)
-
- if old_pci_sxp is None:
- dev_uuid = self.info.device_add('pci', cfg_sxp = target_pci_sxp)
- if not dev_uuid:
- raise XendError('Failed to create device')
-
- else:
- new_pci_sxp = ['pci']
- for existing_dev in sxp.children(old_pci_sxp, 'dev'):
- new_pci_sxp.append(existing_dev)
- new_pci_sxp.append(sxp.child0(target_pci_sxp, 'dev'))
-
- dev_uuid = sxp.child_value(old_pci_sxp, 'uuid')
- self.info.device_update(dev_uuid, new_pci_sxp)
-
- xen.xend.XendDomain.instance().managed_config_save(self)
-
- else:
- try:
- self.device_configure(target_pci_sxp)
-
- except Exception, exn:
- raise XendError('Failed to create device')
-
- return dpci_uuid
-
- def create_dscsi(self, xenapi_dscsi):
- """Create scsi device from the passed struct in Xen API format.
-
- @param xenapi_dscsi: DSCSI struct from Xen API
- @rtype: string
- @return: UUID
- """
-
- dscsi_uuid = uuid.createString()
-
- # Convert xenapi to sxp
- pscsi = XendAPIStore.get(xenapi_dscsi.get('PSCSI'), 'PSCSI')
- devid = int(xenapi_dscsi.get('virtual_HCTL').split(':')[0])
- target_vscsi_sxp = \
- ['vscsi',
- ['dev',
- ['devid', devid],
- ['p-devname', pscsi.get_dev_name()],
- ['p-dev', pscsi.get_physical_HCTL()],
- ['v-dev', xenapi_dscsi.get('virtual_HCTL')],
- ['state', xenbusState['Initialising']],
- ['uuid', dscsi_uuid]
- ],
- ['feature-host', 0]
- ]
-
- if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING:
-
- cur_vscsi_sxp = self._getDeviceInfo_vscsi(devid)
-
- if cur_vscsi_sxp is None:
- dev_uuid = self.info.device_add('vscsi', cfg_sxp = target_vscsi_sxp)
- if not dev_uuid:
- raise XendError('Failed to create device')
-
- else:
- new_vscsi_sxp = ['vscsi', ['feature-host', 0]]
- for existing_dev in sxp.children(cur_vscsi_sxp, 'dev'):
- new_vscsi_sxp.append(existing_dev)
- new_vscsi_sxp.append(sxp.child0(target_vscsi_sxp, 'dev'))
-
- dev_uuid = sxp.child_value(cur_vscsi_sxp, 'uuid')
- self.info.device_update(dev_uuid, new_vscsi_sxp)
-
- xen.xend.XendDomain.instance().managed_config_save(self)
-
- else:
- try:
- self.device_configure(target_vscsi_sxp)
- except Exception, exn:
- log.exception('create_dscsi: %s', exn)
- raise XendError('Failed to create device')
-
- return dscsi_uuid
-
- def create_dscsi_HBA(self, xenapi_dscsi):
- """Create scsi devices from the passed struct in Xen API format.
-
- @param xenapi_dscsi: DSCSI_HBA struct from Xen API
- @rtype: string
- @return: UUID
- """
-
- dscsi_HBA_uuid = uuid.createString()
-
- # Convert xenapi to sxp
- feature_host = xenapi_dscsi.get('assignment_mode', 'HOST') == 'HOST' and 1 or 0
- target_vscsi_sxp = \
- ['vscsi',
- ['feature-host', feature_host],
- ['uuid', dscsi_HBA_uuid],
- ]
- pscsi_HBA = XendAPIStore.get(xenapi_dscsi.get('PSCSI_HBA'), 'PSCSI_HBA')
- devid = pscsi_HBA.get_physical_host()
- for pscsi_uuid in pscsi_HBA.get_PSCSIs():
- pscsi = XendAPIStore.get(pscsi_uuid, 'PSCSI')
- pscsi_HCTL = pscsi.get_physical_HCTL()
- dscsi_uuid = uuid.createString()
- dev = \
- ['dev',
- ['devid', devid],
- ['p-devname', pscsi.get_dev_name()],
- ['p-dev', pscsi_HCTL],
- ['v-dev', pscsi_HCTL],
- ['state', xenbusState['Initialising']],
- ['uuid', dscsi_uuid]
- ]
- target_vscsi_sxp.append(dev)
-
- if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING:
- if not self.info.device_add('vscsi', cfg_sxp = target_vscsi_sxp):
- raise XendError('Failed to create device')
- xen.xend.XendDomain.instance().managed_config_save(self)
- else:
- try:
- self.device_configure(target_vscsi_sxp)
- except Exception, exn:
- log.exception('create_dscsi_HBA: %s', exn)
- raise XendError('Failed to create device')
-
- return dscsi_HBA_uuid
-
-
- def change_vdi_of_vbd(self, xenapi_vbd, vdi_image_path):
- """Change current VDI with the new VDI.
-
- @param xenapi_vbd: vbd struct from the Xen API
- @param vdi_image_path: path of VDI
- """
- dev_uuid = xenapi_vbd['uuid']
- if dev_uuid not in self.info['devices']:
- raise XendError('Device does not exist')
-
- # Convert xenapi to sxp
- if vdi_image_path.startswith('tap'):
- dev_class = 'tap'
- else:
- dev_class = 'vbd'
- dev_sxp = [
- dev_class,
- ['uuid', dev_uuid],
- ['uname', vdi_image_path],
- ['dev', '%s:cdrom' % xenapi_vbd['device']],
- ['mode', 'r'],
- ['VDI', xenapi_vbd['VDI']]
- ]
-
- if self._stateGet() in (XEN_API_VM_POWER_STATE_RUNNING,
- XEN_API_VM_POWER_STATE_PAUSED):
- self.device_configure(dev_sxp)
- else:
- self.info.device_update(dev_uuid, dev_sxp)
-
-
- def destroy_device_by_uuid(self, dev_type, dev_uuid):
- if dev_uuid not in self.info['devices']:
- raise XendError('Device does not exist')
-
- try:
- if self._stateGet() in (XEN_API_VM_POWER_STATE_RUNNING,
- XEN_API_VM_POWER_STATE_PAUSED):
- _, config = self.info['devices'][dev_uuid]
- devid = config.get('devid')
- if devid != None:
- self.getDeviceController(dev_type).destroyDevice(devid, force = False)
- else:
- raise XendError('Unable to get devid for device: %s:%s' %
- (dev_type, dev_uuid))
- finally:
- del self.info['devices'][dev_uuid]
- self.info['%s_refs' % dev_type].remove(dev_uuid)
-
- def destroy_vbd(self, dev_uuid):
- self.destroy_device_by_uuid('vbd', dev_uuid)
-
- def destroy_vif(self, dev_uuid):
- self.destroy_device_by_uuid('vif', dev_uuid)
-
- def destroy_dpci(self, dev_uuid):
-
- dpci = XendAPIStore.get(dev_uuid, 'DPCI')
- ppci = XendAPIStore.get(dpci.get_PPCI(), 'PPCI')
-
- old_pci_sxp = self._getDeviceInfo_pci(0)
- dev_uuid = sxp.child_value(old_pci_sxp, 'uuid')
- target_dev = None
- new_pci_sxp = ['pci']
- for dev in sxp.children(old_pci_sxp, 'dev'):
- pci_dev = {}
- pci_dev['domain'] = sxp.child_value(dev, 'domain')
- pci_dev['bus'] = sxp.child_value(dev, 'bus')
- pci_dev['slot'] = sxp.child_value(dev, 'slot')
- pci_dev['func'] = sxp.child_value(dev, 'func')
- if ppci.get_name() == pci_dict_to_bdf_str(pci_dev):
- target_dev = dev
- else:
- new_pci_sxp.append(dev)
-
- if target_dev is None:
- raise XendError('Failed to destroy device')
-
- target_pci_sxp = ['pci', target_dev, ['state', 'Closing']]
-
- if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING:
-
- self.info.device_update(dev_uuid, new_pci_sxp)
- if len(sxp.children(new_pci_sxp, 'dev')) == 0:
- del self.info['devices'][dev_uuid]
- xen.xend.XendDomain.instance().managed_config_save(self)
-
- else:
- try:
- self.device_configure(target_pci_sxp)
-
- except Exception, exn:
- raise XendError('Failed to destroy device')
-
- def destroy_dscsi(self, dev_uuid):
- dscsi = XendAPIStore.get(dev_uuid, 'DSCSI')
- devid = dscsi.get_virtual_host()
- vHCTL = dscsi.get_virtual_HCTL()
- cur_vscsi_sxp = self._getDeviceInfo_vscsi(devid)
- dev_uuid = sxp.child_value(cur_vscsi_sxp, 'uuid')
-
- target_dev = None
- new_vscsi_sxp = ['vscsi', ['feature-host', 0]]
- for dev in sxp.children(cur_vscsi_sxp, 'dev'):
- if vHCTL == sxp.child_value(dev, 'v-dev'):
- target_dev = dev
- else:
- new_vscsi_sxp.append(dev)
-
- if target_dev is None:
- raise XendError('Failed to destroy device')
-
- target_dev.append(['state', xenbusState['Closing']])
- target_vscsi_sxp = ['vscsi', target_dev, ['feature-host', 0]]
-
- if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING:
-
- self.info.device_update(dev_uuid, new_vscsi_sxp)
- if len(sxp.children(new_vscsi_sxp, 'dev')) == 0:
- del self.info['devices'][dev_uuid]
- xen.xend.XendDomain.instance().managed_config_save(self)
-
- else:
- try:
- self.device_configure(target_vscsi_sxp)
- except Exception, exn:
- log.exception('destroy_dscsi: %s', exn)
- raise XendError('Failed to destroy device')
-
- def destroy_dscsi_HBA(self, dev_uuid):
- dscsi_HBA = XendAPIStore.get(dev_uuid, 'DSCSI_HBA')
- devid = dscsi_HBA.get_virtual_host()
- cur_vscsi_sxp = self._getDeviceInfo_vscsi(devid)
- feature_host = sxp.child_value(cur_vscsi_sxp, 'feature-host')
-
- if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING:
- new_vscsi_sxp = ['vscsi', ['feature-host', feature_host]]
- self.info.device_update(dev_uuid, new_vscsi_sxp)
- del self.info['devices'][dev_uuid]
- xen.xend.XendDomain.instance().managed_config_save(self)
- else:
- # If feature_host is 1, all devices are destroyed by just
- # one reconfiguration.
- # If feature_host is 0, we should reconfigure all devices
- # one-by-one to destroy all devices.
- # See reconfigureDevice at VSCSIController.
- for dev in sxp.children(cur_vscsi_sxp, 'dev'):
- target_vscsi_sxp = [
- 'vscsi',
- dev + [['state', xenbusState['Closing']]],
- ['feature-host', feature_host]
- ]
- try:
- self.device_configure(target_vscsi_sxp)
- except Exception, exn:
- log.exception('destroy_dscsi_HBA: %s', exn)
- raise XendError('Failed to destroy device')
- if feature_host:
- break
-
- def destroy_xapi_instances(self):
- """Destroy Xen-API instances stored in XendAPIStore.
- """
- # Xen-API classes based on XendBase have their instances stored
- # in XendAPIStore. Cleanup these instances here, if they are supposed
- # to be destroyed when the parent domain is dead.
- #
- # Most of the virtual devices (vif, vbd, vfb, etc) are not based on
- # XendBase and there's no need to remove them from XendAPIStore.
-
- from xen.xend import XendDomain
- if XendDomain.instance().is_valid_vm(self.info.get('uuid')):
- # domain still exists.
- return
-
- # Destroy the VMMetrics instance.
- if XendAPIStore.get(self.metrics.get_uuid(), self.metrics.getClass()) \
- is not None:
- self.metrics.destroy()
-
- # Destroy DPCI instances.
- for dpci_uuid in XendDPCI.get_by_VM(self.info.get('uuid')):
- XendAPIStore.deregister(dpci_uuid, "DPCI")
-
- # Destroy DSCSI instances.
- for dscsi_uuid in XendDSCSI.get_by_VM(self.info.get('uuid')):
- XendAPIStore.deregister(dscsi_uuid, "DSCSI")
-
- # Destroy DSCSI_HBA instances.
- for dscsi_HBA_uuid in XendDSCSI_HBA.get_by_VM(self.info.get('uuid')):
- XendAPIStore.deregister(dscsi_HBA_uuid, "DSCSI_HBA")
-
- def has_device(self, dev_class, dev_uuid):
- return (dev_uuid in self.info['%s_refs' % dev_class.lower()])
-
- def __str__(self):
- return '<domain id=%s name=%s memory=%s state=%s>' % \
- (str(self.domid), self.info['name_label'],
- str(self.info['memory_dynamic_max']), DOM_STATES[self._stateGet()])
-
- __repr__ = __str__
-
diff --git a/tools/python/xen/xend/XendError.py b/tools/python/xen/xend/XendError.py
deleted file mode 100644
index d7ec42d..0000000
--- a/tools/python/xen/xend/XendError.py
+++ /dev/null
@@ -1,252 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (c) 2006, 2007 XenSource Inc.
-#============================================================================
-
-from xmlrpclib import Fault
-
-import types
-import XendClient
-
-class XendInvalidDomain(Fault):
- def __init__(self, value):
- Fault.__init__(self, XendClient.ERROR_INVALID_DOMAIN, value)
-
-class XendError(Fault):
-
- def __init__(self, value):
- Fault.__init__(self, XendClient.ERROR_GENERIC, value)
- self.value = value
-
- def __str__(self):
- return self.value
-
-class VMBadState(XendError):
- def __init__(self, value, expected, actual):
- XendError.__init__(self, value)
- self.expected = expected
- self.actual = actual
-
-class NetworkAlreadyConnected(XendError):
- def __init__(self, pif_uuid):
- XendError.__init__(self, 'Network already connected')
- self.pif_uuid = pif_uuid
-
-class PIFIsPhysical(XendError):
- def __init__(self):
- XendError.__init__(self, 'PIF is physical')
-
-class VmError(XendError):
- """Vm construction error."""
- pass
-
-class HVMRequired(VmError):
- def __init__(self):
- XendError.__init__(self,
- 'HVM guest support is unavailable: is VT/AMD-V '
- 'supported by your CPU and enabled in your BIOS?')
-
-class XendAPIError(XendError):
- """Extend this class for all error thrown by
- autoplugged classes"""
- def __init__(self):
- XendError.__init__(self, 'XendAPI Error: You should never see this'
- ' message; this class need to be overidden')
-
- def get_api_error(self):
- return ['INTERNAL_ERROR', 'You should never see this message; '
- 'this method needs to be overidden']
-
-class CreateUnspecifiedAttributeError(XendAPIError):
- def __init__(self, attr_name, class_name):
- XendAPIError.__init__(self)
- self.attr_name = attr_name
- self.class_name = class_name
-
- def get_api_error(self):
- return ['CREATE_UNSPECIFIED_ATTRIBUTE', self.attr_name,
- self.class_name]
-
- def __str__(self):
- return "CREATE_UNSPECIFIED_ATTRIBUTE: %s, %s" % (self.attr_name,
- self.class_name)
-
-class UnmanagedNetworkError(XendAPIError):
- def __init__(self, attr_name):
- XendAPIError.__init__(self)
- self.attr_name = attr_name
-
- def get_api_error(self):
- return ['UNMANAGED_NETWORK_ERROR', self.attr_name]
-
- def __str__(self):
- return "UNMANAGED_NETWORK_ERROR: %s" % self.attr_name
-
-class UniqueNameError(XendAPIError):
- def __init__(self, name, class_name):
- XendAPIError.__init__(self)
- self.name = name
- self.class_name = class_name
-
- def get_api_error(self):
- return ['UNIQUE_NAME_ERROR', self.name, self.class_name]
-
- def __str__(self):
- return 'UNIQUE_NAME_ERROR: %s, %s' % (self.name, self.class_name)
-
-class InvalidDeviceError(XendAPIError):
- def __init__(self, dev):
- XendAPIError.__init__(self)
- self.dev = dev
-
- def get_api_error(self):
- return ['INVALID_DEVICE_ERROR', self.dev]
-
- def __str__(self):
- return 'INVALID_DEVICE_ERROR: %s' % self.dev
-
-class DeviceExistsError(XendAPIError):
- def __init__(self, dev):
- XendAPIError.__init__(self)
- self.dev = dev
-
- def get_api_error(self):
- return ['DEVICE_EXISTS_ERROR', self.dev]
-
- def __str__(self):
- return 'DEVICE_EXISTS_ERROR: %s' % self.dev
-
-class InvalidHandleError(XendAPIError):
- def __init__(self, klass, handle):
- XendAPIError.__init__(self)
- self.klass = klass
- self.handle = handle
-
- def get_api_error(self):
- return ['HANDLE_INVALID', self.klass, self.handle]
-
- def __str__(self):
- return 'HANDLE_INVALID: %s %s' % (self.klass, self.handle)
-
-class ImplementationError(XendAPIError):
- def __init__(self, klass, func):
- XendAPIError.__init__(self)
- self.klass = klass
- self.func = func
-
- def get_api_error(self):
- return ['IMPLEMENTATION_ERROR', self.klass, self.func]
-
- def __str__(self):
- return 'IMPLEMENTATION_ERROR: %s %s' % (self.klass, self.func)
-
-class VLANTagInvalid(XendAPIError):
- def __init__(self, vlan):
- XendAPIError.__init__(self)
- self.vlan = vlan
-
- def get_api_error(self):
- return ['VLAN_TAG_INVALID', self.vlan]
-
- def __str__(self):
- return 'VLAN_TAG_INVALID: %s' % self.vlan
-
-class NetworkError(XendAPIError):
- def __init__(self, error, network):
- XendAPIError.__init__(self)
- self.network = network
- self.error = error
-
- def get_api_error(self):
- return ['NETWORK_ERROR', self.error, self.network]
-
- def __str__(self):
- return 'NETWORK_ERROR: %s %s' % (self.error, self.network)
-
-class DirectPCIError(XendAPIError):
- def __init__(self, error):
- XendAPIError.__init__(self)
- self.error = error
-
- def get_api_error(self):
- return ['DIRECT_PCI_ERROR', self.error]
-
- def __str__(self):
- return 'DIRECT_PCI_ERROR: %s' % self.error
-
-class PoolError(XendAPIError):
- def __init__(self, error, spec=None):
- XendAPIError.__init__(self)
- self.spec = []
- if spec:
- if isinstance(spec, types.ListType):
- self.spec = spec
- else:
- self.spec = [spec]
- self.error = error
-
- def get_api_error(self):
- return [self.error] + self.spec
-
- def __str__(self):
- if self.spec:
- return '%s: %s' % (self.error, self.spec)
- else:
- return '%s' % self.error
-
-class VDIError(XendAPIError):
- def __init__(self, error, vdi):
- XendAPIError.__init__(self)
- self.vdi = vdi
- self.error = error
-
- def get_api_error(self):
- return ['VDI_ERROR', self.error, self.vdi]
-
- def __str__(self):
- return 'VDI_ERROR: %s %s' % (self.error, self.vdi)
-
-from xen.util.xsconstants import xserr2string
-
-class SecurityError(XendAPIError):
- def __init__(self, error, message=None):
- XendAPIError.__init__(self)
- self.error = error
- if not message:
- self.message = xserr2string(-error)
- else:
- self.message = message
-
- def get_api_error(self):
- return ['SECURITY_ERROR', self.error, self.message]
-
- def __str__(self):
- return 'SECURITY_ERROR: %s:%s' % (self.error, self.message)
-
-XEND_ERROR_AUTHENTICATION_FAILED = ('ELUSER', 'Authentication Failed')
-XEND_ERROR_SESSION_INVALID = ('EPERMDENIED', 'Session Invalid')
-XEND_ERROR_DOMAIN_INVALID = ('EINVALIDDOMAIN', 'Domain Invalid')
-XEND_ERROR_HOST_INVALID = ('EINVALIDHOST', 'Host Invalid')
-XEND_ERROR_HOST_RUNNING = ('EHOSTRUNNING', 'Host is still Running')
-XEND_ERROR_HOST_CPU_INVALID = ('EHOSTCPUINVALID', 'Host CPU Invalid')
-XEND_ERROR_UNSUPPORTED = ('EUNSUPPORTED', 'Method Unsupported')
-XEND_ERROR_VM_INVALID = ('EVMINVALID', 'VM Invalid')
-XEND_ERROR_VBD_INVALID = ('EVBDINVALID', 'VBD Invalid')
-XEND_ERROR_VIF_INVALID = ('EVIFINVALID', 'VIF Invalid')
-XEND_ERROR_VDI_INVALID = ('EVDIINVALID', 'VDI Invalid')
-XEND_ERROR_SR_INVALID = ('ESRINVALID', 'SR Invalid')
-XEND_ERROR_XSPOLICY_INVALID = ('EXSPOLICYINVALID', 'XS Invalid')
-XEND_ERROR_TODO = ('ETODO', 'Lazy Programmer Error')
diff --git a/tools/python/xen/xend/XendLocalStorageRepo.py b/tools/python/xen/xend/XendLocalStorageRepo.py
deleted file mode 100644
index 31b86f6..0000000
--- a/tools/python/xen/xend/XendLocalStorageRepo.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/python
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2007 XenSource Ltd.
-#============================================================================
-#
-# A pseudo-StorageRepository to provide a representation for the images
-# that can be specified by xm.
-#
-
-import commands
-import logging
-import os
-import stat
-import threading
-import re
-import sys
-import struct
-
-from xen.util import mkdir
-import uuid
-from XendError import XendError
-from XendVDI import *
-from XendTask import XendTask
-from XendStorageRepository import XendStorageRepository
-from XendStateStore import XendStateStore
-from XendOptions import instance as xendoptions
-
-MB = 1024 * 1024
-
-log = logging.getLogger("xend.XendLocalStorageRepo")
-
-class XendLocalStorageRepo(XendStorageRepository):
- """A backwards compatibility storage repository so that
- traditional file:/dir/file.img and phy:/dev/hdxx images can
- still be represented in terms of the Xen API.
- """
-
- def __init__(self, sr_uuid, sr_type = 'local',
- name_label = 'Local',
- name_description = 'Traditional Local Storage Repo'):
- """
- @ivar images: mapping of all the images.
- @type images: dictionary by image uuid.
- @ivar lock: lock to provide thread safety.
- """
-
- XendStorageRepository.__init__(self, sr_uuid, sr_type,
- name_label, name_description)
-
- self.state = XendStateStore(xendoptions().get_xend_state_path()
- + '/local_sr')
-
- stored_images = self.state.load_state('vdi')
- if stored_images:
- for image_uuid, image in stored_images.items():
- self.images[image_uuid] = XendLocalVDI(image)
-
- def create_vdi(self, vdi_struct):
- """ Creates a fake VDI image for a traditional image string.
-
- The image uri is stored in the attribute 'uri'
- """
- vdi_struct['uuid'] = uuid.createString()
- vdi_struct['SR'] = self.uuid
- new_image = XendLocalVDI(vdi_struct)
- self.images[new_image.uuid] = new_image
- self.save_state()
- return new_image.uuid
-
- def save_state(self):
- vdi_records = dict([(k, v.get_record(transient = False))
- for k, v in self.images.items()])
- self.state.save_state('vdi', vdi_records)
-
- def destroy_vdi(self, vdi_uuid):
- if vdi_uuid in self.images:
- del self.images[vdi_uuid]
-
- self.save_state()
-
diff --git a/tools/python/xen/xend/XendLogging.py b/tools/python/xen/xend/XendLogging.py
deleted file mode 100644
index d95133b..0000000
--- a/tools/python/xen/xend/XendLogging.py
+++ /dev/null
@@ -1,149 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005, 2006 XenSource Ltd.
-#============================================================================
-
-import inspect
-import os
-import os.path
-import sys
-import stat
-import tempfile
-import types
-import logging
-import logging.handlers
-
-from xen.util import mkdir
-from xen.xend.server import params
-from xen.util import oshelp
-
-
-__all__ = [ 'log', 'init', 'getLogFilename' ]
-
-
-if 'TRACE' not in logging.__dict__:
- logging.TRACE = logging.DEBUG - 1
- logging.addLevelName(logging.TRACE,'TRACE')
- def trace(self, *args, **kwargs):
- self.log(logging.TRACE, *args, **kwargs)
- logging.Logger.trace = trace
-
- def findCaller(self):
- """
- Override logging.Logger.findCaller so that the above trace function
- does not appear as the source of log messages. The signature of this
- function changed between Python 2.3 and 2.4.
- """
- frames = inspect.stack()
- thisfile = os.path.normcase(frames[0][1])
- for frame in frames:
- filename = os.path.normcase(frame[1])
- if filename != thisfile and filename != logging._srcfile:
- major, minor, micro, _, _ = sys.version_info
- if (major, minor, micro) >= (2, 4, 2):
- return filename, frame[2], frame[3]
- else:
- return filename, frame[2]
- logging.Logger.findCaller = findCaller
-
- # Work around a bug in Python's inspect module: findsource is supposed to
- # raise IOError if it fails, with other functions in that module coping
- # with that, but some people are seeing IndexError raised from there.
- # This is Python bug 1628987. http://python.org/sf/1628987.
- if hasattr(inspect, 'findsource'):
- real_findsource = getattr(inspect, 'findsource')
- def findsource(*args, **kwargs):
- try:
- return real_findsource(*args, **kwargs)
- except IndexError, exn:
- raise IOError(exn)
- inspect.findsource = findsource
-
-
-log = logging.getLogger("xend")
-
-
-MAX_BYTES = 1 << 20 # 1MB
-BACKUP_COUNT = 5
-
-STDERR_FORMAT = "[%(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
-LOGFILE_FORMAT = "[%(asctime)s %(process)d] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
-DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
-
-
-logfilename = None
-
-class XendRotatingFileHandler(logging.handlers.RotatingFileHandler):
-
- def __init__(self, fname, mode, maxBytes, backupCount):
- logging.handlers.RotatingFileHandler.__init__(self, fname, mode, maxBytes, backupCount)
- self.setCloseOnExec()
-
- def doRollover(self):
- logging.handlers.RotatingFileHandler.doRollover(self)
- self.setCloseOnExec()
-
- # NB yes accessing 'self.stream' violates OO encapsulation somewhat,
- # but python logging API gives no other way to access the file handle
- # and the entire python logging stack is already full of OO encapsulation
- # violations. The other alternative is copy-and-paste duplicating the
- # entire FileHandler, StreamHandler & RotatingFileHandler classes which
- # is even worse
- def setCloseOnExec(self):
- oshelp.fcntl_setfd_cloexec(self.stream, True)
-
-
-def init(filename, level):
- """Initialise logging. Logs to the given filename, and logs to stderr if
- XEND_DEBUG is set.
- """
-
- global logfilename
-
- def openFileHandler(fname):
- mkdir.parents(os.path.dirname(fname), stat.S_IRWXU)
- return XendRotatingFileHandler(fname, mode = 'a',
- maxBytes = MAX_BYTES,
- backupCount = BACKUP_COUNT)
-
- # Rather unintuitively, getLevelName will get the number corresponding to
- # a level name, as well as getting the name corresponding to a level
- # number. setLevel seems to take the number only though, so convert if we
- # are given a string.
- if isinstance(level, types.StringType):
- level = logging.getLevelName(level)
-
- log.setLevel(level)
-
- try:
- fileHandler = openFileHandler(filename)
- logfilename = filename
- except IOError:
- logfilename = tempfile.mkstemp("-xend.log")[1]
- fileHandler = openFileHandler(logfilename)
-
- fileHandler.setFormatter(logging.Formatter(LOGFILE_FORMAT, DATE_FORMAT))
- log.addHandler(fileHandler)
-
- if params.XEND_DEBUG:
- stderrHandler = logging.StreamHandler()
- stderrHandler.setFormatter(logging.Formatter(STDERR_FORMAT,
- DATE_FORMAT))
- log.addHandler(stderrHandler)
-
-
-def getLogFilename():
- return logfilename
diff --git a/tools/python/xen/xend/XendMonitor.py b/tools/python/xen/xend/XendMonitor.py
deleted file mode 100644
index 83fcb18..0000000
--- a/tools/python/xen/xend/XendMonitor.py
+++ /dev/null
@@ -1,340 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2007 XenSource Ltd.
-#============================================================================
-
-from xen.lowlevel.xc import xc
-import time
-import threading
-import os
-import re
-
-"""Monitoring thread to keep track of Xend statistics. """
-
-VBD_SYSFS_PATH = '/sys/devices/xen-backend/'
-VBD_WR_PATH = VBD_SYSFS_PATH + '%s/statistics/wr_sect'
-VBD_RD_PATH = VBD_SYSFS_PATH + '%s/statistics/rd_sect'
-VBD_DOMAIN_RE = r'vbd-(?P<domid>\d+)-(?P<devid>\d+)$'
-
-NET_PROCFS_PATH = '/proc/net/dev'
-PROC_NET_DEV_RE = r'(?P<rx_bytes>\d+)\s+' \
- r'(?P<rx_packets>\d+)\s+' \
- r'(?P<rx_errs>\d+)\s+' \
- r'(?P<rx_drop>\d+)\s+' \
- r'(?P<rx_fifo>\d+)\s+' \
- r'(?P<rx_frame>\d+)\s+' \
- r'(?P<rx_compressed>\d+)\s+' \
- r'(?P<rx_multicast>\d+)\s+' \
- r'(?P<tx_bytes>\d+)\s+' \
- r'(?P<tx_packets>\d+)\s+' \
- r'(?P<tx_errs>\d+)\s+' \
- r'(?P<tx_drop>\d+)\s+' \
- r'(?P<tx_fifo>\d+)\s+' \
- r'(?P<tx_collisions>\d+)\s+' \
- r'(?P<tx_carrier>\d+)\s+' \
- r'(?P<tx_compressed>\d+)\s*$'
-
-
-VIF_DOMAIN_RE = re.compile(r'vif(?P<domid>\d+)\.(?P<iface>\d+):\s*' +
- PROC_NET_DEV_RE)
-PIF_RE = re.compile(r'^\s*(?P<iface>peth\d+):\s*' + PROC_NET_DEV_RE)
-
-# Interval to poll xc, sysfs and proc
-POLL_INTERVAL = 2.0
-SECTOR_SIZE = 512
-class XendMonitor(threading.Thread):
- """Monitors VCPU, VBD, VIF and PIF statistics for Xen API.
-
- Polls sysfs and procfs for statistics on VBDs and VIFs respectively.
-
- @ivar domain_vcpus_util: Utilisation for VCPUs indexed by domain
- @type domain_vcpus_util: {domid: {vcpuid: float, vcpuid: float}}
- @ivar domain_vifs_util: Bytes per second for VIFs indexed by domain
- @type domain_vifs_util: {domid: {vifid: (rx_bps, tx_bps)}}
- @ivar domain_vifs_stat: Total amount of bytes used for VIFs indexed by domain
- @type domain_vifs_stat: {domid: {vbdid: (rx, tx)}}
- @ivar domain_vbds_util: Blocks per second for VBDs index by domain.
- @type domain_vbds_util: {domid: {vbdid: (rd_reqps, wr_reqps)}}
-
- """
- def __init__(self):
- threading.Thread.__init__(self)
- self.setDaemon(True)
- self.xc = xc()
-
- self.lock = threading.Lock()
-
- # tracks the last polled statistics
- self._domain_vcpus = {}
- self._domain_vifs = {}
- self._domain_vbds = {}
- self.pifs = {}
-
- # instantaneous statistics
- self._domain_vcpus_util = {}
- self._domain_vifs_util = {}
- self._domain_vifs_stat = {}
- self._domain_vbds_util = {}
- self.pifs_util = {}
-
- def get_domain_vcpus_util(self):
- self.lock.acquire()
- try:
- return self._domain_vcpus_util
- finally:
- self.lock.release()
-
- def get_domain_vbds_util(self):
- self.lock.acquire()
- try:
- return self._domain_vbds_util
- finally:
- self.lock.release()
-
- def get_domain_vifs_util(self):
- self.lock.acquire()
- try:
- return self._domain_vifs_util
- finally:
- self.lock.release()
-
- def get_domain_vifs_stat(self):
- self.lock.acquire()
- try:
- return self._domain_vifs_stat
- finally:
- self.lock.release()
-
- def get_pifs_util(self):
- self.lock.acquire()
- try:
- return self.pifs_util
- finally:
- self.lock.release()
-
- def _get_vif_stats(self):
- stats = {}
-
- if not os.path.exists(NET_PROCFS_PATH):
- return stats
-
- usage_at = time.time()
- for line in open(NET_PROCFS_PATH):
- is_vif = re.search(VIF_DOMAIN_RE, line.strip())
- if not is_vif:
- continue
-
- domid = int(is_vif.group('domid'))
- vifid = int(is_vif.group('iface'))
- rx_bytes = int(is_vif.group('rx_bytes'))
- tx_bytes = int(is_vif.group('tx_bytes'))
- if not domid in stats:
- stats[domid] = {}
-
- stats[domid][vifid] = (usage_at, rx_bytes, tx_bytes)
-
- return stats
-
- def _get_pif_stats(self):
- stats = {}
-
- if not os.path.exists(NET_PROCFS_PATH):
- return stats
-
- usage_at = time.time()
- for line in open(NET_PROCFS_PATH):
- is_pif = re.search(PIF_RE, line.strip())
- if not is_pif:
- continue
-
- pifname = is_pif.group('iface')
- rx_bytes = int(is_pif.group('rx_bytes'))
- tx_bytes = int(is_pif.group('tx_bytes'))
- stats[pifname] = (usage_at, rx_bytes, tx_bytes)
-
- return stats
-
- def _get_vbd_stats(self):
- stats = {}
-
- if not os.path.exists(VBD_SYSFS_PATH):
- return stats
-
- for vbd_path in os.listdir(VBD_SYSFS_PATH):
- is_vbd = re.search(VBD_DOMAIN_RE, vbd_path)
- if not is_vbd:
- continue
-
- domid = int(is_vbd.group('domid'))
- vbdid = int(is_vbd.group('devid'))
- rd_stat_path = VBD_RD_PATH % vbd_path
- wr_stat_path = VBD_WR_PATH % vbd_path
-
- if not os.path.exists(rd_stat_path) or \
- not os.path.exists(wr_stat_path):
- continue
-
-
- try:
- usage_at = time.time()
- rd_stat = int(open(rd_stat_path).readline().strip())
- wr_stat = int(open(wr_stat_path).readline().strip())
- rd_stat *= SECTOR_SIZE
- wr_stat *= SECTOR_SIZE
- if domid not in stats:
- stats[domid] = {}
-
- stats[domid][vbdid] = (usage_at, rd_stat, wr_stat)
-
- except (IOError, ValueError):
- continue
-
- return stats
-
- def _get_cpu_stats(self):
- stats = {}
- for domain in self.xc.domain_getinfo():
- domid = domain['domid']
- vcpu_count = domain['online_vcpus']
- stats[domid] = {}
- for i in range(vcpu_count):
- vcpu_info = self.xc.vcpu_getinfo(domid, i)
- usage = vcpu_info['cpu_time']
- usage_at = time.time()
- stats[domid][i] = (usage_at, usage)
-
- return stats
-
-
- def run(self):
-
- # loop every second for stats
- while True:
- self.lock.acquire()
- try:
- active_domids = []
- # Calculate utilisation for VCPUs
-
- for domid, cputimes in self._get_cpu_stats().items():
- active_domids.append(domid)
- if domid not in self._domain_vcpus:
- # if not initialised, save current stats
- # and skip utilisation calculation
- self._domain_vcpus[domid] = cputimes
- self._domain_vcpus_util[domid] = {}
- continue
-
- for vcpu, (usage_at, usage) in cputimes.items():
- if vcpu not in self._domain_vcpus[domid]:
- continue
-
- prv_usage_at, prv_usage = \
- self._domain_vcpus[domid][vcpu]
- interval_s = (usage_at - prv_usage_at) * 1000000000
- if interval_s > 0:
- util = (usage - prv_usage) / interval_s
- self._domain_vcpus_util[domid][vcpu] = util
-
- self._domain_vcpus[domid] = cputimes
-
- # Calculate utilisation for VBDs
-
- for domid, vbds in self._get_vbd_stats().items():
- if domid not in self._domain_vbds:
- self._domain_vbds[domid] = vbds
- self._domain_vbds_util[domid] = {}
- continue
-
- for devid, (usage_at, rd, wr) in vbds.items():
- if devid not in self._domain_vbds[domid]:
- continue
-
- prv_at, prv_rd, prv_wr = \
- self._domain_vbds[domid][devid]
- interval = usage_at - prv_at
- rd_util = (rd - prv_rd)/interval
- wr_util = (wr - prv_wr)/interval
- self._domain_vbds_util[domid][devid] = \
- (rd_util, wr_util)
-
- self._domain_vbds[domid] = vbds
-
-
- # Calculate utilisation for VIFs
-
- for domid, vifs in self._get_vif_stats().items():
-
- if domid not in self._domain_vifs:
- self._domain_vifs[domid] = vifs
- self._domain_vifs_util[domid] = {}
- self._domain_vifs_stat[domid] = {}
- continue
-
- for devid, (usage_at, rx, tx) in vifs.items():
- if devid not in self._domain_vifs[domid]:
- continue
-
- prv_at, prv_rx, prv_tx = \
- self._domain_vifs[domid][devid]
- interval = usage_at - prv_at
- rx_util = (rx - prv_rx)/interval
- tx_util = (tx - prv_tx)/interval
-
- # note these are flipped around because
- # we are measuring the host interface,
- # not the guest interface
- self._domain_vifs_util[domid][devid] = \
- (tx_util, rx_util)
- self._domain_vifs_stat[domid][devid] = \
- (float(tx), float(rx))
-
- self._domain_vifs[domid] = vifs
-
- # Calculate utilisation for PIFs
-
- for pifname, stats in self._get_pif_stats().items():
- if pifname not in self.pifs:
- self.pifs[pifname] = stats
- continue
-
- usage_at, rx, tx = stats
- prv_at, prv_rx, prv_tx = self.pifs[pifname]
- interval = usage_at - prv_at
- rx_util = (rx - prv_rx)/interval
- tx_util = (tx - prv_tx)/interval
-
- self.pifs_util[pifname] = (rx_util, tx_util)
- self.pifs[pifname] = stats
-
- for domid in self._domain_vcpus_util.keys():
- if domid not in active_domids:
- del self._domain_vcpus_util[domid]
- del self._domain_vcpus[domid]
- for domid in self._domain_vifs_util.keys():
- if domid not in active_domids:
- del self._domain_vifs_util[domid]
- del self._domain_vifs[domid]
- del self._domain_vifs_stat[domid]
- for domid in self._domain_vbds_util.keys():
- if domid not in active_domids:
- del self._domain_vbds_util[domid]
- del self._domain_vbds[domid]
-
- finally:
- self.lock.release()
-
- # Sleep a while before next poll
- time.sleep(POLL_INTERVAL)
-
diff --git a/tools/python/xen/xend/XendNetwork.py b/tools/python/xen/xend/XendNetwork.py
deleted file mode 100644
index 489d5d5..0000000
--- a/tools/python/xen/xend/XendNetwork.py
+++ /dev/null
@@ -1,238 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (c) 2006 Xensource Inc.
-#============================================================================
-
-import os
-import commands
-import re
-import struct
-import socket
-
-import XendDomain
-import XendNode
-from XendLogging import log
-from xen.xend import uuid as genuuid
-from xen.xend.XendBase import XendBase
-from xen.xend.XendError import *
-from xen.util import Brctl
-from xen.xend import XendAPIStore
-
-IP_ROUTE_RE = r'^default via ([\d\.]+) dev (\w+)'
-
-def bridge_exists(name):
- return name in Brctl.get_state().keys()
-
-class XendNetwork(XendBase):
- """We're going to assert that the name_label of this
- network is just the name of the bridge"""
-
- def getClass(self):
- return "network"
-
- def getAttrRW(self):
- attrRW = ['name_label',
- 'name_description',
- 'other_config',
- 'default_gateway',
- 'default_netmask']
- return XendBase.getAttrRW() + attrRW
-
- def getAttrRO(self):
- attrRO = ['VIFs',
- 'PIFs',
- 'managed']
- return XendBase.getAttrRO() + attrRO
-
- def getAttrInst(self):
- return XendBase.getAttrInst() + self.getAttrRW()
-
- def getMethods(self):
- methods = ['add_to_other_config',
- 'remove_from_other_config',
- 'destroy']
- return XendBase.getMethods() + methods
-
- def getFuncs(self):
- funcs = ['create', 'get_by_name_label']
- return XendBase.getFuncs() + funcs
-
- getClass = classmethod(getClass)
- getAttrRO = classmethod(getAttrRO)
- getAttrRW = classmethod(getAttrRW)
- getAttrInst = classmethod(getAttrInst)
- getMethods = classmethod(getMethods)
- getFuncs = classmethod(getFuncs)
-
- def create_phy(self, name):
- """
- Called when a new bridge is found on xend start
- """
- # Create new uuids
- uuid = genuuid.createString()
-
- # Create instance
- record = {
- 'name_label': name,
- 'name_description': '',
- 'other_config': {},
- 'default_gateway': '',
- 'default_netmask': '',
- 'managed': False,
- }
- network = XendNetwork(record, uuid)
-
- return uuid
-
- def recreate(self, record, uuid):
- """
- Called on xend start / restart, or machine
- restart, when read from saved config.
- Needs to check network exists, create it otherwise
- """
-
- # Create instance (do this first, to check record)
- network = XendNetwork(record, uuid)
-
- # Create network if it doesn't already exist
- if not bridge_exists(network.name_label):
- if network.managed:
- Brctl.bridge_create(network.name_label)
- else:
- log.info("Not recreating missing unmanaged network %s" % network.name_label)
-
- return uuid
-
- def create(self, record):
- """
- Called from API, to create a new network
- """
- # Create new uuids
- uuid = genuuid.createString()
-
- # Create instance (do this first, to check record)
- network = XendNetwork(record, uuid)
-
- # Check network doesn't already exist
- name_label = network.name_label
- if bridge_exists(name_label):
- del network
- raise UniqueNameError(name_label, "network")
-
- # Create the bridge
- Brctl.bridge_create(network.name_label)
-
- XendNode.instance().save_networks()
-
- return uuid
-
- def get_by_name_label(cls, name):
- return [inst.get_uuid()
- for inst in XendAPIStore.get_all(cls.getClass())
- if inst.get_name_label() == name]
-
- create_phy = classmethod(create_phy)
- recreate = classmethod(recreate)
- create = classmethod(create)
- get_by_name_label = classmethod(get_by_name_label)
-
- def __init__(self, record, uuid):
- # This is a read-only attr, so we need to
- # set it here, as super class won't try to
- if record.has_key("managed"):
- self.managed = record["managed"]
- else:
- self.managed = True
- XendBase.__init__(self, uuid, record)
-
- #
- # XenAPI Mehtods
- #
-
- def destroy(self):
- # check no VIFs or PIFs attached
- if len(self.get_VIFs()) > 0:
- raise NetworkError("Cannot destroy network with VIFs attached",
- self.get_name_label())
-
- if len(self.get_PIFs()) > 0:
- raise NetworkError("Cannot destroy network with PIFs attached",
- self.get_name_label())
-
- XendBase.destroy(self)
- Brctl.bridge_del(self.get_name_label())
- XendNode.instance().save_networks()
-
- def get_name_label(self):
- return self.name_label
-
- def get_name_description(self):
- return self.name_description
-
- def set_name_label(self, new_name):
- pass
-
- def set_name_description(self, new_desc):
- self.name_description = new_desc
- XendNode.instance().save_networks()
-
- def get_managed(self):
- return self.managed
-
- def get_VIFs(self):
- result = []
- vms = XendDomain.instance().get_all_vms()
- for vm in vms:
- vifs = vm.get_vifs()
- for vif in vifs:
- vif_cfg = vm.get_dev_xenapi_config('vif', vif)
- if vif_cfg.get('network') == self.get_uuid():
- result.append(vif)
- return result
-
- def get_PIFs(self):
- pifs = XendAPIStore.get_all("PIF")
- return [pif.get_uuid() for pif in pifs
- if pif.get_network() == self.get_uuid()]
-
- def get_other_config(self):
- return self.other_config
-
- def set_other_config(self, value):
- self.other_config = value
- XendNode.instance().save_networks()
-
- def add_to_other_config(self, key, value):
- self.other_config[key] = value
- XendNode.instance().save_networks()
-
- def remove_from_other_config(self, key):
- if key in self.other_config:
- del self.other_config[key]
- XendNode.instance().save_networks()
-
- def get_default_gateway(self):
- return self.default_gateway
-
- def set_default_gateway(self, gateway):
- self.default_gateway = gateway
- XendNode.instance().save_networks()
-
- def get_default_netmask(self):
- return self.default_netmask
-
- def set_default_netmask(self, netmask):
- self.default_netmask = netmask
- XendNode.instance().save_networks()
diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py
deleted file mode 100644
index f16932c..0000000
--- a/tools/python/xen/xend/XendNode.py
+++ /dev/null
@@ -1,1183 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (c) 2006, 2007 Xensource Inc.
-#============================================================================
-
-import os
-import socket
-import time
-import xen.lowlevel.xc
-
-from xen.util import Brctl
-from xen.util import pci as PciUtil
-from xen.util import vscsi_util
-from xen.util import vusb_util
-from xen.xend import XendAPIStore
-from xen.xend import osdep
-from xen.xend.XendConstants import *
-
-import uuid, arch
-from XendPBD import XendPBD
-from XendError import *
-from XendOptions import instance as xendoptions
-from XendQCoWStorageRepo import XendQCoWStorageRepo
-from XendLocalStorageRepo import XendLocalStorageRepo
-from XendLogging import log
-from XendPIF import *
-from XendPIFMetrics import XendPIFMetrics
-from XendNetwork import *
-from XendStateStore import XendStateStore
-from XendMonitor import XendMonitor
-from XendPPCI import XendPPCI
-from XendPSCSI import XendPSCSI, XendPSCSI_HBA
-from xen.xend.XendCPUPool import XendCPUPool
-
-class XendNode:
- """XendNode - Represents a Domain 0 Host."""
-
- def __init__(self):
- """Initalises the state of all host specific objects such as
-
- * host
- * host_CPU
- * host_metrics
- * PIF
- * PIF_metrics
- * network
- * Storage Repository
- * PPCI
- * PSCSI
- """
-
- self.xc = xen.lowlevel.xc.xc()
- self.state_store = XendStateStore(xendoptions().get_xend_state_path())
- self.monitor = XendMonitor()
- self.monitor.start()
-
- # load host state from XML file
- saved_host = self.state_store.load_state('host')
- if saved_host and len(saved_host.keys()) == 1:
- self.uuid = saved_host.keys()[0]
- host = saved_host[self.uuid]
- self.name = host.get('name_label', socket.gethostname())
- self.desc = host.get('name_description', '')
- self.host_metrics_uuid = host.get('metrics_uuid',
- uuid.createString())
- try:
- self.other_config = eval(host['other_config'])
- except:
- self.other_config = {}
- self.cpus = {}
- else:
- self.uuid = uuid.createString()
- self.name = socket.gethostname()
- self.desc = ''
- self.other_config = {}
- self.cpus = {}
- self.host_metrics_uuid = uuid.createString()
-
- # put some arbitrary params in other_config as this
- # is directly exposed via XenAPI
- self.other_config["xen_pagesize"] = self.xeninfo_dict()["xen_pagesize"]
- self.other_config["platform_params"] = self.xeninfo_dict()["platform_params"]
- self.other_config["xen_commandline"] = self.xeninfo_dict()["xen_commandline"]
-
- # load CPU UUIDs
- saved_cpus = self.state_store.load_state('cpu')
- for cpu_uuid, cpu in saved_cpus.items():
- self.cpus[cpu_uuid] = cpu
-
- cpuinfo = osdep.get_cpuinfo()
- physinfo = self.physinfo_dict()
- cpu_count = physinfo['nr_cpus']
- cpu_features = physinfo['hw_caps']
- virt_caps = physinfo['virt_caps']
-
- # If the number of CPUs don't match, we should just reinitialise
- # the CPU UUIDs.
- if cpu_count != len(self.cpus):
- self.cpus = {}
- for i in range(cpu_count):
- u = uuid.createString()
- self.cpus[u] = {'uuid': u, 'number': i }
-
- for u in self.cpus.keys():
- number = self.cpus[u]['number']
- # We can run off the end of the cpuinfo list if domain0 does not
- # have #vcpus == #pcpus. In that case we just replicate one that's
- # in the hash table.
- if not cpuinfo.has_key(number):
- number = cpuinfo.keys()[0]
- if arch.type == "x86":
- self.cpus[u].update(
- { 'host' : self.uuid,
- 'features' : cpu_features,
- 'virt_caps': virt_caps,
- 'speed' : int(float(cpuinfo[number]['cpu MHz'])),
- 'vendor' : cpuinfo[number]['vendor_id'],
- 'modelname': cpuinfo[number]['model name'],
- 'stepping' : cpuinfo[number]['stepping'],
- 'flags' : cpuinfo[number]['flags'],
- })
- elif arch.type == "ia64":
- self.cpus[u].update(
- { 'host' : self.uuid,
- 'features' : cpu_features,
- 'speed' : int(float(cpuinfo[number]['cpu MHz'])),
- 'vendor' : cpuinfo[number]['vendor'],
- 'modelname': cpuinfo[number]['family'],
- 'stepping' : cpuinfo[number]['model'],
- 'flags' : cpuinfo[number]['features'],
- })
- else:
- self.cpus[u].update(
- { 'host' : self.uuid,
- 'features' : cpu_features,
- })
-
- self.srs = {}
-
- self._init_networks()
- self._init_PIFs()
-
- self._init_SRs()
- self._init_PBDs()
-
- self._init_PPCIs()
-
- self._init_PSCSIs()
-
- self._init_cpu_pools()
-
-
- def _init_networks(self):
- # Initialise networks
- # First configure ones off disk
- saved_networks = self.state_store.load_state('network')
- if saved_networks:
- for net_uuid, network in saved_networks.items():
- try:
- XendNetwork.recreate(network, net_uuid)
- except CreateUnspecifiedAttributeError:
- log.warn("Error recreating network %s", net_uuid)
-
- # Next discover any existing bridges and check
- # they are not already configured
-
- # 'tmpbridge' is a temporary bridge created by network-bridge script.
- # Wait a couple of seconds for it to be renamed.
- for i in xrange(20):
- bridges = Brctl.get_state().keys()
- if 'tmpbridge' in bridges:
- time.sleep(0.1)
- else:
- break
-
- configured_bridges = [XendAPIStore.get(
- network_uuid, "network")
- .get_name_label()
- for network_uuid in XendNetwork.get_all()]
- unconfigured_bridges = [bridge
- for bridge in bridges
- if bridge not in configured_bridges]
- for unconfigured_bridge in unconfigured_bridges:
- if unconfigured_bridge != 'tmpbridge':
- XendNetwork.create_phy(unconfigured_bridge)
-
- def _init_PIFs(self):
- # Initialise PIFs
- # First configure ones off disk
- saved_pifs = self.state_store.load_state('pif')
- if saved_pifs:
- for pif_uuid, pif in saved_pifs.items():
- try:
- XendPIF.recreate(pif, pif_uuid)
- except CreateUnspecifiedAttributeError:
- log.warn("Error recreating PIF %s", pif_uuid)
-
- # Next discover any existing PIFs and check
- # they are not already configured
- configured_pifs = [XendAPIStore.get(
- pif_uuid, "PIF")
- .get_interface_name()
- for pif_uuid in XendPIF.get_all()]
- unconfigured_pifs = [(name, mtu, mac)
- for name, mtu, mac in linux_get_phy_ifaces()
- if name not in configured_pifs]
-
- # Get a mapping from interface to bridge
- if_to_br = dict([(i,b)
- for (b,ifs) in Brctl.get_state().items()
- for i in ifs])
-
- for name, mtu, mac in unconfigured_pifs:
- # Check PIF is on bridge
- # if not, ignore
- bridge_name = if_to_br.get(name, None)
- if bridge_name is not None:
- # Translate bridge name to network uuid
- for network_uuid in XendNetwork.get_all():
- network = XendAPIStore.get(
- network_uuid, 'network')
- if network.get_name_label() == bridge_name:
- XendPIF.create_phy(network_uuid, name,
- mac, mtu)
- break
- else:
- log.debug("Cannot find network for bridge %s "
- "when configuring PIF %s",
- (bridge_name, name))
-
- def _init_SRs(self):
- # initialise storage
- saved_srs = self.state_store.load_state('sr')
- if saved_srs:
- for sr_uuid, sr_cfg in saved_srs.items():
- if sr_cfg['type'] == 'qcow_file':
- self.srs[sr_uuid] = XendQCoWStorageRepo(sr_uuid)
- elif sr_cfg['type'] == 'local':
- self.srs[sr_uuid] = XendLocalStorageRepo(sr_uuid)
-
- # Create missing SRs if they don't exist
- if not self.get_sr_by_type('local'):
- image_sr_uuid = uuid.createString()
- self.srs[image_sr_uuid] = XendLocalStorageRepo(image_sr_uuid)
-
- if not self.get_sr_by_type('qcow_file'):
- qcow_sr_uuid = uuid.createString()
- self.srs[qcow_sr_uuid] = XendQCoWStorageRepo(qcow_sr_uuid)
-
- def _init_PBDs(self):
- saved_pbds = self.state_store.load_state('pbd')
- if saved_pbds:
- for pbd_uuid, pbd_cfg in saved_pbds.items():
- try:
- XendPBD.recreate(pbd_uuid, pbd_cfg)
- except CreateUnspecifiedAttributeError:
- log.warn("Error recreating PBD %s", pbd_uuid)
-
- def _init_PPCIs(self):
- saved_ppcis = self.state_store.load_state('ppci')
- saved_ppci_table = {}
- if saved_ppcis:
- for ppci_uuid, ppci_record in saved_ppcis.items():
- try:
- saved_ppci_table[ppci_record['name']] = ppci_uuid
- except KeyError:
- pass
-
- for pci_dev in PciUtil.get_all_pci_devices():
- ppci_record = {
- 'domain': pci_dev.domain,
- 'bus': pci_dev.bus,
- 'slot': pci_dev.slot,
- 'func': pci_dev.func,
- 'vendor_id': pci_dev.vendor,
- 'vendor_name': pci_dev.vendorname,
- 'device_id': pci_dev.device,
- 'device_name': pci_dev.devicename,
- 'revision_id': pci_dev.revision,
- 'class_code': pci_dev.classcode,
- 'class_name': pci_dev.classname,
- 'subsystem_vendor_id': pci_dev.subvendor,
- 'subsystem_vendor_name': pci_dev.subvendorname,
- 'subsystem_id': pci_dev.subdevice,
- 'subsystem_name': pci_dev.subdevicename,
- 'driver': pci_dev.driver
- }
- # If saved uuid exists, use it. Otherwise create one.
- ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
- XendPPCI(ppci_uuid, ppci_record)
-
- def _init_PSCSIs(self):
- # Initialise PSCSIs and PSCSI_HBAs
- saved_pscsis = self.state_store.load_state('pscsi')
- saved_pscsi_table = {}
- if saved_pscsis:
- for pscsi_uuid, pscsi_record in saved_pscsis.items():
- try:
- saved_pscsi_table[pscsi_record['scsi_id']] = pscsi_uuid
- except KeyError:
- pass
-
- saved_pscsi_HBAs = self.state_store.load_state('pscsi_HBA')
- saved_pscsi_HBA_table = {}
- if saved_pscsi_HBAs:
- for pscsi_HBA_uuid, pscsi_HBA_record in saved_pscsi_HBAs.items():
- try:
- physical_host = int(pscsi_HBA_record['physical_host'])
- saved_pscsi_HBA_table[physical_host] = pscsi_HBA_uuid
- except (KeyError, ValueError):
- pass
-
- pscsi_table = {}
- pscsi_HBA_table = {}
-
- pscsi_records = []
- for pscsi_mask in xendoptions().get_pscsi_device_mask():
- pscsi_records += vscsi_util.get_all_scsi_devices(pscsi_mask)
- log.debug("pscsi record count: %s" % len(pscsi_records))
-
- for pscsi_record in pscsi_records:
- scsi_id = pscsi_record['scsi_id']
- if scsi_id:
- saved_HBA_uuid = None
-
- pscsi_uuid = saved_pscsi_table.get(scsi_id, None)
- if pscsi_uuid is None:
- pscsi_uuid = uuid.createString()
- saved_pscsi_table[scsi_id] = pscsi_uuid
- else:
- try:
- saved_HBA_uuid = saved_pscsis[pscsi_uuid].get('HBA', None)
- except KeyError:
- log.warn("Multi-path SCSI devices are not supported for XenAPI")
- return
-
- physical_host = int(pscsi_record['physical_HCTL'].split(':')[0])
- if pscsi_HBA_table.has_key(physical_host):
- pscsi_HBA_uuid = pscsi_HBA_table[physical_host]
- elif saved_pscsi_HBA_table.has_key(physical_host):
- pscsi_HBA_uuid = saved_pscsi_HBA_table[physical_host]
- pscsi_HBA_table[physical_host] = pscsi_HBA_uuid
- else:
- pscsi_HBA_uuid = uuid.createString()
- pscsi_HBA_table[physical_host] = pscsi_HBA_uuid
-
- if saved_HBA_uuid is not None and \
- saved_HBA_uuid != pscsi_HBA_uuid:
- log.debug('The PSCSI(%s) host number was changed', scsi_id)
- pscsi_record['HBA'] = pscsi_HBA_uuid
- pscsi_table[pscsi_uuid] = pscsi_record
-
- for pscsi_uuid, pscsi_record in pscsi_table.items():
- XendPSCSI(pscsi_uuid, pscsi_record)
-
- for physical_host, pscsi_HBA_uuid in pscsi_HBA_table.items():
- XendPSCSI_HBA(pscsi_HBA_uuid, {'physical_host': physical_host})
-
- def _init_cpu_pools(self):
- # Initialise cpu_pools
- saved_cpu_pools = self.state_store.load_state(XendCPUPool.getClass())
- if saved_cpu_pools:
- for cpu_pool_uuid, cpu_pool in saved_cpu_pools.items():
- try:
- XendCPUPool.recreate(cpu_pool, cpu_pool_uuid)
- except CreateUnspecifiedAttributeError:
- log.warn("Error recreating %s %s",
- (XendCPUPool.getClass(), cpu_pool_uuid))
- XendCPUPool.recreate_active_pools()
-
-
- def add_network(self, interface):
- # TODO
- log.debug("add_network(): Not implemented.")
-
-
- def remove_network(self, interface):
- # TODO
- log.debug("remove_network(): Not implemented.")
-
-
- def add_PPCI(self, pci_name):
- # Update lspci info
- PciUtil.create_lspci_info()
-
- # Initialise the PPCI
- saved_ppcis = self.state_store.load_state('ppci')
- saved_ppci_table = {}
- if saved_ppcis:
- for ppci_uuid, ppci_record in saved_ppcis.items():
- try:
- saved_ppci_table[ppci_record['name']] = ppci_uuid
- except KeyError:
- pass
-
- pci_dev = PciUtil.PciDevice(PciUtil.parse_pci_name(pci_name))
- ppci_record = {
- 'domain': pci_dev.domain,
- 'bus': pci_dev.bus,
- 'slot': pci_dev.slot,
- 'func': pci_dev.func,
- 'vendor_id': pci_dev.vendor,
- 'vendor_name': pci_dev.vendorname,
- 'device_id': pci_dev.device,
- 'device_name': pci_dev.devicename,
- 'revision_id': pci_dev.revision,
- 'class_code': pci_dev.classcode,
- 'class_name': pci_dev.classname,
- 'subsystem_vendor_id': pci_dev.subvendor,
- 'subsystem_vendor_name': pci_dev.subvendorname,
- 'subsystem_id': pci_dev.subdevice,
- 'subsystem_name': pci_dev.subdevicename,
- 'driver': pci_dev.driver
- }
- # If saved uuid exists, use it. Otherwise create one.
- ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
- XendPPCI(ppci_uuid, ppci_record)
-
- self.save_PPCIs()
-
-
- def remove_PPCI(self, pci_name):
- # Update lspci info
- PciUtil.create_lspci_info()
-
- # Remove the PPCI
- (domain, bus, slot, func) = PciUtil.parse_pci_name(pci_name)
- ppci_ref = XendPPCI.get_by_sbdf(domain, bus, slot, func)
- XendAPIStore.get(ppci_ref, "PPCI").destroy()
-
- self.save_PPCIs()
-
-
- def add_PSCSI(self, add_HCTL):
- saved_pscsis = self.state_store.load_state('pscsi')
- saved_pscsi_table = {}
- if saved_pscsis:
- for saved_uuid, saved_record in saved_pscsis.items():
- try:
- saved_pscsi_table[saved_record['scsi_id']] = saved_uuid
- except KeyError:
- pass
-
- saved_pscsi_HBAs = self.state_store.load_state('pscsi_HBA')
- saved_pscsi_HBA_table = {}
- if saved_pscsi_HBAs:
- for saved_HBA_uuid, saved_HBA_record in saved_pscsi_HBAs.items():
- try:
- physical_host = int(saved_HBA_record['physical_host'])
- saved_pscsi_HBA_table[physical_host] = saved_HBA_uuid
- except (KeyError, ValueError):
- pass
-
- # Initialise the PSCSI and the PSCSI_HBA
- pscsi_record = vscsi_util.get_scsi_device(add_HCTL)
- if pscsi_record and pscsi_record['scsi_id']:
- pscsi_uuid = saved_pscsi_table.get(pscsi_record['scsi_id'], None)
- if pscsi_uuid is None:
- physical_host = int(add_HCTL.split(':')[0])
- pscsi_HBA_uuid = saved_pscsi_HBA_table.get(physical_host, None)
- if pscsi_HBA_uuid is None:
- pscsi_HBA_uuid = uuid.createString()
- XendPSCSI_HBA(pscsi_HBA_uuid, {'physical_host': physical_host})
- pscsi_record['HBA'] = pscsi_HBA_uuid
-
- pscsi_uuid = uuid.createString()
- XendPSCSI(pscsi_uuid, pscsi_record)
- self.save_PSCSIs()
- self.save_PSCSI_HBAs()
-
-
- def remove_PSCSI(self, rem_HCTL):
- saved_pscsis = self.state_store.load_state('pscsi')
- if not saved_pscsis:
- return
-
- # Remove the PSCSI
- for pscsi_record in saved_pscsis.values():
- if rem_HCTL == pscsi_record['physical_HCTL']:
- pscsi_ref = XendPSCSI.get_by_HCTL(rem_HCTL)
- XendAPIStore.get(pscsi_ref, "PSCSI").destroy()
- self.save_PSCSIs()
-
- physical_host = int(rem_HCTL.split(':')[0])
- pscsi_HBA_ref = XendPSCSI_HBA.get_by_physical_host(physical_host)
- if pscsi_HBA_ref:
- if not XendAPIStore.get(pscsi_HBA_ref, 'PSCSI_HBA').get_PSCSIs():
- XendAPIStore.get(pscsi_HBA_ref, 'PSCSI_HBA').destroy()
- self.save_PSCSI_HBAs()
-
- return
-
- def add_usbdev(self, busid):
- # if the adding usb device should be owned by usbback
- # and is probed by other usb drivers, seize it!
- bus, intf = busid.split(':')
- buses = vusb_util.get_assigned_buses()
- if str(bus) in buses:
- if not vusb_util.usb_intf_is_binded(busid):
- log.debug("add_usb(): %s is binded to other driver" % busid)
- vusb_util.unbind_usb_device(bus)
- vusb_util.bind_usb_device(bus)
- return
-
- def remove_usbdev(self, busid):
- log.debug("remove_usbdev(): Not implemented.")
-
-## def network_destroy(self, net_uuid):
- ## del self.networks[net_uuid]
- ## self.save_networks()
-
-
- def get_PIF_refs(self):
- log.debug(XendPIF.get_all())
- return XendPIF.get_all()
-
-## def _PIF_create(self, name, mtu, vlan, mac, network, persist = True,
-## pif_uuid = None, metrics_uuid = None):
-## for pif in self.pifs.values():
-## if pif.network == network:
-## raise NetworkAlreadyConnected(pif.uuid)
-
-## if pif_uuid is None:
-## pif_uuid = uuid.createString()
-## if metrics_uuid is None:
-## metrics_uuid = uuid.createString()
-
-## metrics = XendPIFMetrics(metrics_uuid)
-## pif = XendPIF(pif_uuid, metrics, name, mtu, vlan, mac, network, self)
-## metrics.set_PIF(pif)
-
-## self.pif_metrics[metrics_uuid] = metrics
-## self.pifs[pif_uuid] = pif
-
-## if persist:
-## self.save_PIFs()
-## self.refreshBridges()
-## return pif_uuid
-
-## def PIF_destroy(self, pif_uuid):
-## pif = self.pifs[pif_uuid]
-
-## if pif.vlan == -1:
-## raise PIFIsPhysical()
-
-## del self.pifs[pif_uuid]
-## self.save_PIFs()
-
-
- def get_PPCI_refs(self):
- return XendPPCI.get_all()
-
- def get_ppci_by_uuid(self, ppci_uuid):
- if ppci_uuid in self.get_PPCI_refs():
- return ppci_uuid
- return None
-
-
- def get_PSCSI_refs(self):
- return XendPSCSI.get_all()
-
- def get_pscsi_by_uuid(self, pscsi_uuid):
- if pscsi_uuid in self.get_PSCSI_refs():
- return pscsi_uuid
- return None
-
- def get_PSCSI_HBA_refs(self):
- return XendPSCSI_HBA.get_all()
-
- def get_pscsi_HBA_by_uuid(self, pscsi_HBA_uuid):
- if pscsi_HBA_uuid in self.get_PSCSI_HBA_refs():
- return pscsi_HBA_uuid
- return None
-
-
- def save(self):
- # save state
- host_record = {self.uuid: {'name_label':self.name,
- 'name_description':self.desc,
- 'metrics_uuid': self.host_metrics_uuid,
- 'other_config': self.other_config}}
- self.state_store.save_state('host',host_record)
- self.state_store.save_state('cpu', self.cpus)
- self.save_PIFs()
- self.save_networks()
- self.save_PBDs()
- self.save_SRs()
- self.save_PPCIs()
- self.save_PSCSIs()
- self.save_PSCSI_HBAs()
- self.save_cpu_pools()
-
- def save_PIFs(self):
- pif_records = dict([(pif_uuid, XendAPIStore.get(
- pif_uuid, "PIF").get_record())
- for pif_uuid in XendPIF.get_all()])
- self.state_store.save_state('pif', pif_records)
-
- def save_networks(self):
- net_records = dict([(network_uuid, XendAPIStore.get(
- network_uuid, "network").get_record())
- for network_uuid in XendNetwork.get_all()])
- self.state_store.save_state('network', net_records)
-
- def save_PBDs(self):
- pbd_records = dict([(pbd_uuid, XendAPIStore.get(
- pbd_uuid, "PBD").get_record())
- for pbd_uuid in XendPBD.get_all()])
- self.state_store.save_state('pbd', pbd_records)
-
- def save_SRs(self):
- sr_records = dict([(k, v.get_record(transient = False))
- for k, v in self.srs.items()])
- self.state_store.save_state('sr', sr_records)
-
- def save_PPCIs(self):
- ppci_records = dict([(ppci_uuid, XendAPIStore.get(
- ppci_uuid, "PPCI").get_record())
- for ppci_uuid in XendPPCI.get_all()])
- self.state_store.save_state('ppci', ppci_records)
-
- def save_PSCSIs(self):
- pscsi_records = dict([(pscsi_uuid, XendAPIStore.get(
- pscsi_uuid, "PSCSI").get_record())
- for pscsi_uuid in XendPSCSI.get_all()])
- self.state_store.save_state('pscsi', pscsi_records)
-
- def save_PSCSI_HBAs(self):
- pscsi_HBA_records = dict([(pscsi_HBA_uuid, XendAPIStore.get(
- pscsi_HBA_uuid, "PSCSI_HBA").get_record())
- for pscsi_HBA_uuid in XendPSCSI_HBA.get_all()])
- self.state_store.save_state('pscsi_HBA', pscsi_HBA_records)
-
- def save_cpu_pools(self):
- cpu_pool_records = dict([(cpu_pool_uuid, XendAPIStore.get(
- cpu_pool_uuid, XendCPUPool.getClass()).get_record())
- for cpu_pool_uuid in XendCPUPool.get_all_managed()])
- self.state_store.save_state(XendCPUPool.getClass(), cpu_pool_records)
-
- def shutdown(self):
- return 0
-
- def reboot(self):
- return 0
-
- def notify(self, _):
- return 0
-
- #
- # Ref validation
- #
-
- def is_valid_host(self, host_ref):
- return (host_ref == self.uuid)
-
- def is_valid_cpu(self, cpu_ref):
- return (cpu_ref in self.cpus)
-
- def is_valid_sr(self, sr_ref):
- return (sr_ref in self.srs)
-
- def is_valid_vdi(self, vdi_ref):
- for sr in self.srs.values():
- if sr.is_valid_vdi(vdi_ref):
- return True
- return False
-
- #
- # Storage Repositories
- #
-
- def get_sr(self, sr_uuid):
- return self.srs.get(sr_uuid)
-
- def get_sr_by_type(self, sr_type):
- return [sr.uuid for sr in self.srs.values() if sr.type == sr_type]
-
- def get_sr_by_name(self, name):
- return [sr.uuid for sr in self.srs.values() if sr.name_label == name]
-
- def get_all_sr_uuid(self):
- return self.srs.keys()
-
- def get_vdi_by_uuid(self, vdi_uuid):
- for sr in self.srs.values():
- if sr.is_valid_vdi(vdi_uuid):
- return sr.get_vdi_by_uuid(vdi_uuid)
- return None
-
- def get_vdi_by_name_label(self, name):
- for sr in self.srs.values():
- vdi = sr.get_vdi_by_name_label(name)
- if vdi:
- return vdi
- return None
-
- def get_sr_containing_vdi(self, vdi_uuid):
- for sr in self.srs.values():
- if sr.is_valid_vdi(vdi_uuid):
- return sr
- return None
-
-
- #
- # Host Functions
- #
-
- def xen_version(self):
- info = self.xc.xeninfo()
-
- info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info}
-
- # Add xend_config_format
- info.update(self.xendinfo_dict())
-
- # Add version info about machine
- info.update(self.nodeinfo_dict())
-
- # Add specific xen version info
- xeninfo_dict = self.xeninfo_dict()
-
- info.update({
- "xen_major": xeninfo_dict["xen_major"],
- "xen_minor": xeninfo_dict["xen_minor"],
- "xen_extra": xeninfo_dict["xen_extra"],
- "cc_compiler": xeninfo_dict["cc_compiler"],
- "cc_compile_by": xeninfo_dict["cc_compile_by"],
- "cc_compile_domain": xeninfo_dict["cc_compile_domain"],
- "cc_compile_date": xeninfo_dict["cc_compile_date"],
- "xen_changeset": xeninfo_dict["xen_changeset"],
- "xen_commandline": xeninfo_dict["xen_commandline"]
- })
-
- return info
-
- def get_name(self):
- return self.name
-
- def set_name(self, new_name):
- self.name = new_name
-
- def get_description(self):
- return self.desc
-
- def set_description(self, new_desc):
- self.desc = new_desc
-
- def get_uuid(self):
- return self.uuid
-
- def get_capabilities(self):
- return self.xc.xeninfo()['xen_caps'].split(" ")
-
- #
- # Host CPU Functions
- #
-
- def get_host_cpu_by_uuid(self, host_cpu_uuid):
- if host_cpu_uuid in self.cpus:
- return host_cpu_uuid
- raise XendError('Invalid CPU UUID')
-
- def get_host_cpu_refs(self):
- return self.cpus.keys()
-
- def get_host_cpu_uuid(self, host_cpu_ref):
- if host_cpu_ref in self.cpus:
- return host_cpu_ref
- else:
- raise XendError('Invalid CPU Reference')
-
- def get_host_cpu_field(self, ref, field):
- try:
- return self.cpus[ref][field]
- except KeyError:
- raise XendError('Invalid CPU Reference')
-
- def get_host_cpu_load(self, host_cpu_ref):
- host_cpu = self.cpus.get(host_cpu_ref)
- if not host_cpu:
- return 0.0
-
- vcpu = int(host_cpu['number'])
- cpu_loads = self.monitor.get_domain_vcpus_util()
- if 0 in cpu_loads and vcpu in cpu_loads[0]:
- return cpu_loads[0][vcpu]
-
- return 0.0
-
- def get_vcpus_policy(self):
- sched_id = self.xc.sched_id_get()
- if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
- return 'sedf'
- elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
- return 'credit'
- elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT2:
- return 'credit2'
- else:
- return 'unknown'
-
- def get_cpu_configuration(self):
- phys_info = self.physinfo_dict()
-
- cpu_info = {
- "nr_nodes": phys_info["nr_nodes"],
- "nr_cpus": phys_info["nr_cpus"],
- "cores_per_socket": phys_info["cores_per_socket"],
- "threads_per_core": phys_info["threads_per_core"]
- }
-
- return cpu_info
-
- #
- # Network Functions
- #
-
- def bridge_to_network(self, bridge):
- """
- Determine which network a particular bridge is attached to.
-
- @param bridge The name of the bridge. If empty, the default bridge
- will be used instead (the first one in the list returned by brctl
- show); this is the behaviour of the vif-bridge script.
- @return The XendNetwork instance to which this bridge is attached.
- @raise Exception if the interface is not connected to a network.
- """
- if not bridge:
- rc, bridge = commands.getstatusoutput(
- 'brctl show | cut -d "\n" -f 2 | cut -f 1')
- if rc != 0 or not bridge:
- raise Exception(
- 'Could not find default bridge, and none was specified')
-
- for network_uuid in XendNetwork.get_all():
- network = XendAPIStore.get(network_uuid, "network")
- if network.get_name_label() == bridge:
- return network
- else:
- raise Exception('Cannot find network for bridge %s' % bridge)
-
- #
- # Debug keys.
- #
-
- def send_debug_keys(self, keys):
- return self.xc.send_debug_keys(keys)
-
- #
- # Getting host information.
- #
-
- def info(self, show_numa = 1):
- return (self.nodeinfo() + self.physinfo(show_numa) + self.xeninfo() +
- self.xendinfo())
-
- def nodeinfo(self):
- (sys, host, rel, ver, mch) = os.uname()
- return [['system', sys],
- ['host', host],
- ['release', rel],
- ['version', ver],
- ['machine', mch]]
-
- def list_to_rangepairs(self,cmap):
- cmap.sort()
- pairs = []
- x = y = 0
- for i in range(0,len(cmap)):
- try:
- if ((cmap[y+1] - cmap[i]) > 1):
- pairs.append((cmap[x],cmap[y]))
- x = y = i+1
- else:
- y = y + 1
- # if we go off the end, then just add x to y
- except IndexError:
- pairs.append((cmap[x],cmap[y]))
-
- return pairs
-
- def format_pairs(self,pairs):
- if not pairs:
- return "no cpus"
- out = ""
- for f,s in pairs:
- if (f==s):
- out += '%d'%f
- else:
- out += '%d-%d'%(f,s)
- out += ','
- # trim trailing ','
- return out[:-1]
-
- def list_to_strrange(self,list):
- return self.format_pairs(self.list_to_rangepairs(list))
-
- def format_cpu_to_core_socket_node(self, tinfo):
- max_cpu_index=tinfo['max_cpu_index']
- str='\ncpu: core socket node\n'
- for i in range(0, max_cpu_index+1):
- try:
- str+='%3d:%8d %8d %8d\n' % (i,
- tinfo['cpu_to_core'][i],
- tinfo['cpu_to_socket'][i],
- tinfo['cpu_to_node'][i])
- except:
- pass
- return str[:-1];
-
- def format_numa_info(self, ninfo):
- try:
- max_node_index=ninfo['max_node_index']
- str='\nnode: TotalMemory FreeMemory dma32Memory NodeDist:'
- for i in range(0, max_node_index+1):
- str+='%4d ' % i
- str+='\n'
- for i in range(0, max_node_index+1):
- str+='%4d: %8dMB %8dMB %8dMB :' % (i,
- ninfo['node_memsize'][i],
- ninfo['node_memfree'][i],
- ninfo['node_to_dma32_mem'][i])
- for j in range(0, nr_nodes):
- try:
- str+='%4d ' % ninfo['node_to_node_dist'][i][j]
- except:
- str+='- '
- str+='\n'
- except:
- str='none\n'
- return str[:-1];
-
- def physinfo(self, show_numa):
- info = self.xc.physinfo()
- tinfo = self.xc.topologyinfo()
- ninfo = self.xc.numainfo()
-
- info['cpu_mhz'] = info['cpu_khz'] / 1000
-
- # physinfo is in KiB, need it in MiB
- info['total_memory'] = info['total_memory'] / 1024
- info['free_memory'] = info['free_memory'] / 1024
- info['free_cpus'] = len(XendCPUPool.unbound_cpus())
-
- ITEM_ORDER = ['nr_cpus',
- 'nr_nodes',
- 'cores_per_socket',
- 'threads_per_core',
- 'cpu_mhz',
- 'hw_caps',
- 'virt_caps',
- 'total_memory',
- 'free_memory',
- 'free_cpus',
- ]
-
- if show_numa != 0:
- info['cpu_topology'] = \
- self.format_cpu_to_core_socket_node(tinfo)
-
- info['numa_info'] = \
- self.format_numa_info(ninfo)
-
- ITEM_ORDER += [ 'cpu_topology', 'numa_info' ]
-
- return [[k, info[k]] for k in ITEM_ORDER]
-
- def pciinfo(self):
- from xen.xend.server.pciif import get_all_assigned_pci_devices
- assigned_devs = get_all_assigned_pci_devices()
-
- # Each element of dev_list is a PciDevice
- dev_list = PciUtil.find_all_assignable_devices()
- if dev_list is None:
- return None
-
- # Each element of devs_list is a list of PciDevice
- devs_list = PciUtil.check_FLR_capability(dev_list)
-
- devs_list = PciUtil.check_mmio_bar(devs_list)
-
- # Check if the devices have been assigned to guests.
- final_devs_list = []
- for dev_list in devs_list:
- available = True
- for d in dev_list:
- if d.name in assigned_devs:
- available = False
- break
- if available:
- final_devs_list = final_devs_list + [dev_list]
-
- pci_sxp_list = []
- for dev_list in final_devs_list:
- for d in dev_list:
- pci_sxp = ['dev', ['domain', '0x%04x' % d.domain],
- ['bus', '0x%02x' % d.bus],
- ['slot', '0x%02x' % d.slot],
- ['func', '0x%x' % d.func]]
- pci_sxp_list.append(pci_sxp)
-
- return pci_sxp_list
-
-
- def xenschedinfo(self):
- sched_id = self.xc.sched_id_get()
- if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
- return 'sedf'
- elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
- return 'credit'
- elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT2:
- return 'credit2'
- else:
- return 'unknown'
-
- def xeninfo(self):
- info = self.xc.xeninfo()
- info['xen_scheduler'] = self.xenschedinfo()
-
- ITEM_ORDER = ['xen_major',
- 'xen_minor',
- 'xen_extra',
- 'xen_caps',
- 'xen_scheduler',
- 'xen_pagesize',
- 'platform_params',
- 'xen_changeset',
- 'xen_commandline',
- 'cc_compiler',
- 'cc_compile_by',
- 'cc_compile_domain',
- 'cc_compile_date',
- ]
-
- return [[k, info[k]] for k in ITEM_ORDER]
-
- def xendinfo(self):
- return [['xend_config_format', 4]]
-
- #
- # utilisation tracking
- #
-
- def get_vcpu_util(self, domid, vcpuid):
- cpu_loads = self.monitor.get_domain_vcpus_util()
- if domid in cpu_loads:
- return cpu_loads[domid].get(vcpuid, 0.0)
- return 0.0
-
- def get_vif_util(self, domid, vifid):
- vif_loads = self.monitor.get_domain_vifs_util()
- if domid in vif_loads:
- return vif_loads[domid].get(vifid, (0.0, 0.0))
- return (0.0, 0.0)
-
- def get_vif_stat(self, domid, vifid):
- vif_loads = self.monitor.get_domain_vifs_stat()
- if domid in vif_loads:
- return vif_loads[domid].get(vifid, (0.0, 0.0))
- return (0.0, 0.0)
-
- def get_vbd_util(self, domid, vbdid):
- vbd_loads = self.monitor.get_domain_vbds_util()
- if domid in vbd_loads:
- return vbd_loads[domid].get(vbdid, (0.0, 0.0))
- return (0.0, 0.0)
-
- # dictionary version of *info() functions to get rid of
- # SXPisms.
- def nodeinfo_dict(self):
- return dict(self.nodeinfo())
- def xendinfo_dict(self):
- return dict(self.xendinfo())
- def xeninfo_dict(self):
- return dict(self.xeninfo())
- def physinfo_dict(self):
- return dict(self.physinfo(1))
- def info_dict(self):
- return dict(self.info())
-
- # tmem
- def tmem_list(self, cli_id, use_long):
- pool_id = -1
- subop = TMEMC_LIST
- arg1 = 32768
- arg2 = use_long
- arg3 = 0
- buf = ''
- return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)
-
- def tmem_thaw(self, cli_id):
- pool_id = -1
- subop = TMEMC_THAW
- arg1 = 0
- arg2 = 0
- arg3 = 0
- buf = ''
- return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)
-
- def tmem_freeze(self, cli_id):
- pool_id = -1
- subop = TMEMC_FREEZE
- arg1 = 0
- arg2 = 0
- arg3 = 0
- buf = ''
- return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)
-
- def tmem_flush(self, cli_id, pages):
- pool_id = -1
- subop = TMEMC_FLUSH
- arg1 = pages
- arg2 = 0
- arg3 = 0
- buf = ''
- return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)
-
- def tmem_destroy(self, cli_id):
- pool_id = -1
- subop = TMEMC_DESTROY
- arg1 = 0
- arg2 = 0
- arg3 = 0
- buf = ''
- return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)
-
- def tmem_set_weight(self, cli_id, arg1):
- pool_id = -1
- subop = TMEMC_SET_WEIGHT
- arg2 = 0
- arg3 = 0
- buf = ''
- return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)
-
- def tmem_set_cap(self, cli_id, arg1):
- pool_id = -1
- subop = TMEMC_SET_CAP
- arg2 = 0
- arg3 = 0
- buf = ''
- return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)
-
- def tmem_set_compress(self, cli_id, arg1):
- pool_id = -1
- subop = TMEMC_SET_COMPRESS
- arg2 = 0
- arg3 = 0
- buf = ''
- return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)
-
- def tmem_query_freeable_mb(self):
- pool_id = -1
- cli_id = -1
- subop = TMEMC_QUERY_FREEABLE_MB
- arg1 = 0
- arg2 = 0
- arg3 = 0
- buf = ''
- return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)
-
- def tmem_shared_auth(self, cli_id, uuid_str, auth):
- return self.xc.tmem_auth(cli_id, uuid_str, auth)
-
-def instance():
- global inst
- try:
- inst
- except:
- inst = XendNode()
- inst.save()
- return inst
diff --git a/tools/python/xen/xend/XendOptions.py b/tools/python/xen/xend/XendOptions.py
deleted file mode 100644
index cc6f38e..0000000
--- a/tools/python/xen/xend/XendOptions.py
+++ /dev/null
@@ -1,567 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-"""Xend root class.
-Creates the servers and handles configuration.
-
-Other classes get config variables by importing this module,
-using instance() to get a XendOptions instance, and then
-the config functions (e.g. get_xend_port()) to get
-configured values.
-"""
-
-import os
-import os.path
-import string
-import sys
-
-from xen.xend import sxp, osdep, XendLogging
-from xen.xend.XendError import XendError
-from xen.util import auxbin
-
-if os.uname()[0] == 'SunOS':
- from xen.lowlevel import scf
-
-class XendOptions:
- """Configuration options."""
-
- """Where network control scripts live."""
- network_script_dir = auxbin.scripts_dir()
-
- """Where block control scripts live."""
- block_script_dir = auxbin.scripts_dir()
-
- """Default path to the log file. """
- logfile_default = "/var/log/xen/xend.log"
-
- """Default level of information to be logged."""
- loglevel_default = 'DEBUG'
-
- """Default Xen-API server configuration. """
- xen_api_server_default = [['unix']]
-
- """Default for the flag indicating whether xend should run an http server
- (deprecated)."""
- xend_http_server_default = 'no'
-
- xend_tcp_xmlrpc_server_default = 'no'
-
- xend_tcp_xmlrpc_server_address_default = 'localhost'
-
- xend_tcp_xmlrpc_server_port_default = 8006
-
- xend_unix_xmlrpc_server_default = 'yes'
-
- """Default interface address xend listens at. """
- xend_address_default = ''
-
- """Default for the flag indicating whether xend should run a relocation server."""
- xend_relocation_server_default = 'no'
-
- """Default for the flag indicating whether xend should run a ssl relocation server."""
- xend_relocation_ssl_server_default = 'no'
-
- """Default for the flag indicating whether xend should run a udev event server."""
- xend_udev_event_server_default = 'no'
-
- """Default interface address the xend relocation server listens at. """
- xend_relocation_address_default = ''
-
- """Default port xend serves HTTP at. """
- xend_port_default = 8000
-
- """Default port xend serves relocation at. """
- xend_relocation_port_default = 8002
-
- """Default port xend serves ssl relocation at. """
- xend_relocation_ssl_port_default = 8003
-
- xend_relocation_hosts_allow_default = ''
-
- """Default for the flag indicating whether xend should run a unix-domain
- server (deprecated)."""
- xend_unix_server_default = 'no'
-
- """Default external migration tool """
- external_migration_tool_default = ''
-
- """Default path the unix-domain server listens at."""
- xend_unix_path_default = '/var/lib/xend/xend-socket'
-
- dom0_min_mem_default = 0
-
- reserved_memory_default = 0
-
- dom0_vcpus_default = 0
-
- vncpasswd_default = None
-
- """Default interface to listen for VNC connections on"""
- xend_vnc_listen_default = '127.0.0.1'
-
- """Use of TLS mode in QEMU VNC server"""
- xend_vnc_tls = 0
-
- """x509 certificate directory for QEMU VNC server"""
- xend_vnc_x509_cert_dir = auxbin.xen_configdir() + "/vnc"
-
- """Verify incoming client x509 certs"""
- xend_vnc_x509_verify = 0
-
- """Default session storage path."""
- xend_domains_path_default = '/var/lib/xend/domains'
-
- """Default xend management state storage."""
- xend_state_path_default = '/var/lib/xend/state'
-
- """Default xend QCoW storage repository location."""
- xend_storage_path_default = '/var/lib/xend/storage'
-
- """Default xend security state storage path."""
- xend_security_path_default = '/var/lib/xend/security'
-
- """Default script to configure a backend network interface"""
- vif_script = osdep.vif_script
-
- """Default Xen Security Module"""
- xsm_module_default = 'dummy'
-
- """Default rotation count of qemu-dm log file."""
- qemu_dm_logrotate_count = 10
-
- """Default timeout for device creation."""
- device_create_timeout_default = 100
-
- """Default timeout for device destruction."""
- device_destroy_timeout_default = 100
-
- """By default, we use the strict check for HVM guest. (For PV guest, we
- use loose check automatically if necessary."""
- pci_dev_assign_strict_check_default = True
-
- def __init__(self):
- self.configure()
-
- def _logError(self, fmt, *args):
- """Logging function to log to stderr. We use this for XendOptions log
- messages because they may be logged before the logger has been
- configured. Other components can safely use the logger.
- """
- print >>sys.stderr, "xend [ERROR]", fmt % args
-
- """Default mask for pscsi device scan."""
- xend_pscsi_device_mask = ['*']
-
-
- def configure(self):
- self.set_config()
- XendLogging.init(self.get_config_string("logfile",
- self.logfile_default),
- self.get_config_string("loglevel",
- self.loglevel_default))
-
- def set_config(self):
- raise NotImplementedError()
-
- def get_config_bool(self, name, val=None):
- raise NotImplementedError()
-
- def get_config_int(self, name, val=None):
- raise NotImplementedError()
-
- def get_config_string(self, name, val=None):
- raise NotImplementedError()
-
- def get_xen_api_server(self):
- raise NotImplementedError()
-
- def get_xend_http_server(self):
- """Get the flag indicating whether xend should run an http server.
- """
- return self.get_config_bool("xend-http-server", self.xend_http_server_default)
-
- def get_xend_tcp_xmlrpc_server(self):
- return self.get_config_bool("xend-tcp-xmlrpc-server",
- self.xend_tcp_xmlrpc_server_default)
-
- def get_xend_tcp_xmlrpc_server_port(self):
- return self.get_config_int("xend-tcp-xmlrpc-server-port",
- self.xend_tcp_xmlrpc_server_port_default)
-
- def get_xend_tcp_xmlrpc_server_address(self):
- return self.get_config_string("xend-tcp-xmlrpc-server-address",
- self.xend_tcp_xmlrpc_server_address_default)
-
- def get_xend_tcp_xmlrpc_server_ssl_key_file(self):
- name = 'xend-tcp-xmlrpc-server-ssl-key-file'
- file = self.get_config_string(name)
- if file and os.path.dirname(file) == "":
- file = auxbin.xen_configdir() + '/' + file;
- if file and not os.path.exists(file):
- raise XendError("invalid xend config %s: directory '%s' does not exist" % (name, file))
- return file
-
- def get_xend_tcp_xmlrpc_server_ssl_cert_file(self):
- name = 'xend-tcp-xmlrpc-server-ssl-cert-file'
- file = self.get_config_string(name)
- if file and os.path.dirname(file) == "":
- file = auxbin.xen_configdir() + '/' + file;
- if file and not os.path.exists(file):
- raise XendError("invalid xend config %s: directory '%s' does not exist" % (name, file))
- return file
-
- def get_xend_unix_xmlrpc_server(self):
- return self.get_config_bool("xend-unix-xmlrpc-server",
- self.xend_unix_xmlrpc_server_default)
-
- def get_xend_relocation_server(self):
- """Get the flag indicating whether xend should run a relocation server.
- """
- return self.get_config_bool("xend-relocation-server",
- self.xend_relocation_server_default)
-
- def get_xend_relocation_ssl_server(self):
- """Get the flag indicating whether xend should run a ssl relocation server.
- """
- return self.get_config_bool("xend-relocation-ssl-server",
- self.xend_relocation_ssl_server_default)
-
- def get_xend_relocation_server_ssl_key_file(self):
- name = 'xend-relocation-server-ssl-key-file'
- file = self.get_config_string(name)
- if os.path.dirname(file) == "":
- file = auxbin.xen_configdir() + '/' + file;
- if not os.path.exists(file):
- raise XendError("invalid xend config %s: directory '%s' does not exist" % (name, file))
- return file
-
- def get_xend_relocation_server_ssl_cert_file(self):
- name = 'xend-relocation-server-ssl-cert-file'
- file = self.get_config_string(name)
- if os.path.dirname(file) == "":
- file = auxbin.xen_configdir() + '/' + file;
- if not os.path.exists(file):
- raise XendError("invalid xend config %s: directory '%s' does not exist" % (name, file))
- return file
-
- def get_xend_udev_event_server(self):
- return self.get_config_bool("xend-udev-event-server",
- self.xend_udev_event_server_default)
-
- def get_xend_port(self):
- """Get the port xend listens at for its HTTP interface.
- """
- return self.get_config_int('xend-port', self.xend_port_default)
-
- def get_xend_relocation_port(self):
- """Get the port xend listens at for connection to its relocation server.
- """
- return self.get_config_int('xend-relocation-port',
- self.xend_relocation_port_default)
-
- def get_xend_relocation_ssl_port(self):
- """Get the port xend listens at for ssl connection to its relocation
- server.
- """
- return self.get_config_int('xend-relocation-ssl-port',
- self.xend_relocation_ssl_port_default)
-
- def get_xend_relocation_ssl(self):
- """Whether to use ssl when relocating.
- """
- return self.get_config_bool('xend-relocation-ssl', 'no')
-
- def get_xend_relocation_hosts_allow(self):
- return self.get_config_string("xend-relocation-hosts-allow",
- self.xend_relocation_hosts_allow_default)
-
- def get_xend_address(self):
- """Get the address xend listens at for its HTTP port.
- This defaults to the empty string which allows all hosts to connect.
- If this is set to 'localhost' only the localhost will be able to connect
- to the HTTP port.
- """
- return self.get_config_string('xend-address', self.xend_address_default)
-
- def get_xend_relocation_address(self):
- """Get the address xend listens at for its relocation server port.
- This defaults to the empty string which allows all hosts to connect.
- If this is set to 'localhost' only the localhost will be able to connect
- to the relocation port.
- """
- return self.get_config_string('xend-relocation-address', self.xend_relocation_address_default)
-
- def get_xend_unix_server(self):
- """Get the flag indicating whether xend should run a unix-domain server.
- """
- return self.get_config_bool("xend-unix-server", self.xend_unix_server_default)
-
- def get_xend_unix_path(self):
- """Get the path the xend unix-domain server listens at.
- """
- return self.get_config_string("xend-unix-path", self.xend_unix_path_default)
-
- def get_xend_domains_path(self):
- """ Get the path for persistent domain configuration storage
- """
- return self.get_config_string("xend-domains-path", self.xend_domains_path_default)
-
- def get_xend_state_path(self):
- """ Get the path for persistent domain configuration storage
- """
- return self.get_config_string("xend-state-path", self.xend_state_path_default)
-
- def get_xend_storage_path(self):
- """ Get the path for persistent domain configuration storage
- """
- return self.get_config_string("xend-storage-path", self.xend_storage_path_default)
-
- def get_xend_security_path(self):
- """ Get the path for security state
- """
- return self.get_config_string("xend-security-path", self.xend_security_path_default)
-
- def get_network_script(self):
- """@return the script used to alter the network configuration when
- Xend starts and stops, or None if no such script is specified."""
-
- s = self.get_config_string('network-script')
-
- if s:
- result = s.split(" ")
- result[0] = os.path.join(self.network_script_dir, result[0])
- return result
- else:
- return None
-
- def get_external_migration_tool(self):
- """@return the name of the tool to handle virtual device migration."""
- return self.get_config_string('external-migration-tool', self.external_migration_tool_default)
-
- def get_enable_dump(self):
- return self.get_config_bool('enable-dump', 'no')
-
- def get_vif_script(self):
- return self.get_config_string('vif-script', self.vif_script)
-
- def get_dom0_min_mem(self):
- return self.get_config_int('dom0-min-mem', self.dom0_min_mem_default)
-
- def get_enable_dom0_ballooning(self):
- enable_dom0_ballooning_default = 'yes'
- if self.get_dom0_min_mem() == 0:
- enable_dom0_ballooning_default = 'no'
- return self.get_config_bool('enable-dom0-ballooning',
- enable_dom0_ballooning_default)
-
- def get_reserved_memory(self):
- if not self.get_enable_dom0_ballooning():
- return 0 #no ballooning of dom0 will close this item
- else:
- return self.get_config_int('total_available_memory', self.reserved_memory_default)
-
-
- def get_dom0_vcpus(self):
- return self.get_config_int('dom0-cpus', self.dom0_vcpus_default)
-
- def get_console_limit(self):
- return self.get_config_int('console-limit', 1024)
-
- def get_vnclisten_address(self):
- return self.get_config_string('vnc-listen', self.xend_vnc_listen_default)
-
- def get_vncpasswd_default(self):
- return self.get_config_string('vncpasswd',
- self.vncpasswd_default)
-
- def get_keymap(self):
- return self.get_config_string('keymap', None)
-
- def get_resource_label_change_script(self):
- s = self.get_config_string('resource-label-change-script')
- if s:
- result = s.split(" ")
- result[0] = os.path.join(auxbin.scripts_dir(), result[0])
- return result
- else:
- return None
-
-
- def get_vnc_tls(self):
- return self.get_config_string('vnc-tls', self.xend_vnc_tls)
-
- def get_vnc_x509_cert_dir(self):
- name = 'vnc-x509-cert-dir'
- vncdir = self.get_config_string(name, self.xend_vnc_x509_cert_dir)
- if os.path.dirname(vncdir) == "":
- vncdir = auxbin.xen_configdir() + '/' + vncdir
- if not os.path.exists(vncdir):
- raise XendError("invalid xend config %s: directory '%s' does not exist" % (name, vncdir))
- return vncdir
-
- def get_vnc_x509_verify(self):
- return self.get_config_string('vnc-x509-verify', self.xend_vnc_x509_verify)
-
- def get_qemu_dm_logrotate_count(self):
- return self.get_config_int("qemu-dm-logrotate-count",
- self.qemu_dm_logrotate_count)
-
- def get_device_create_timeout(self):
- return self.get_config_int("device-create-timeout",
- self.device_create_timeout_default)
-
- def get_device_destroy_timeout(self):
- return self.get_config_int("device-destroy-timeout",
- self.device_destroy_timeout_default)
-
- def get_pci_dev_assign_strict_check(self):
- return self.get_config_bool("pci-passthrough-strict-check",
- self.pci_dev_assign_strict_check_default)
-
- def get_pscsi_device_mask(self):
- return self.get_config_value("pscsi-device-mask",
- self.xend_pscsi_device_mask)
-
-class XendOptionsFile(XendOptions):
-
- """Default path to the config file."""
- config_default = auxbin.xen_configdir() + "/xend-config.sxp"
-
- """Environment variable used to override config_default."""
- config_var = "XEND_CONFIG"
-
- def set_config(self):
- """If the config file exists, read it. If not, ignore it.
-
- The config file is a sequence of sxp forms.
- """
- self.config_path = os.getenv(self.config_var, self.config_default)
- if os.path.exists(self.config_path):
- try:
- fin = file(self.config_path, 'rb')
- try:
- config = sxp.parse(fin)
- finally:
- fin.close()
- if config is None:
- config = ['xend-config']
- else:
- config.insert(0, 'xend-config')
- self.config = config
- except Exception, ex:
- self._logError('Reading config file %s: %s',
- self.config_path, str(ex))
- raise
- else:
- self._logError('Config file does not exist: %s',
- self.config_path)
- self.config = ['xend-config']
-
- def get_config_value(self, name, val=None):
- """Get the value of an atomic configuration element.
-
- @param name: element name
- @param val: default value (optional, defaults to None)
- @return: value
- """
- return sxp.child_value(self.config, name, val=val)
-
- def get_config_bool(self, name, val=None):
- v = string.lower(str(self.get_config_value(name, val)))
- if v in ['yes', 'y', '1', 'on', 'true', 't']:
- return True
- if v in ['no', 'n', '0', 'off', 'false', 'f']:
- return False
- raise XendError("invalid xend config %s: expected bool: %s" % (name, v))
-
- def get_config_int(self, name, val=None):
- v = self.get_config_value(name, val)
- try:
- return int(v)
- except Exception:
- raise XendError("invalid xend config %s: expected int: %s" % (name, v))
-
- def get_config_string(self, name, val=None):
- return self.get_config_value(name, val)
-
- def get_xen_api_server(self):
- """Get the Xen-API server configuration.
- """
- return self.get_config_value('xen-api-server',
- self.xen_api_server_default)
-
- def get_xsm_module_name(self):
- """Get the Xen Security Module name.
- """
- return self.get_config_string('xsm_module_name', self.xsm_module_default)
-
-if os.uname()[0] == 'SunOS':
- class XendOptionsSMF(XendOptions):
-
- def set_config(self):
- pass
-
- def get_config_bool(self, name, val=None):
- try:
- return scf.get_bool(name)
- except scf.error, e:
- if e[0] == scf.SCF_ERROR_NOT_FOUND:
- if val in ['yes', 'y', '1', 'on', 'true', 't']:
- return True
- if val in ['no', 'n', '0', 'off', 'false', 'f']:
- return False
- return val
- else:
- raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
-
- def get_config_int(self, name, val=None):
- try:
- return scf.get_int(name)
- except scf.error, e:
- if e[0] == scf.SCF_ERROR_NOT_FOUND:
- return val
- else:
- raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
-
- def get_config_string(self, name, val=None):
- try:
- return scf.get_string(name)
- except scf.error, e:
- if e[0] == scf.SCF_ERROR_NOT_FOUND:
- return val
- else:
- raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
-
- def get_xen_api_server(self):
- # When the new server is a supported configuration, we should
- # expand this.
- return [["unix"]]
-
-def instance():
- """Get an instance of XendOptions.
- Use this instead of the constructor.
- """
- global inst
- try:
- inst
- except:
- if os.uname()[0] == 'SunOS':
- inst = XendOptionsSMF()
- else:
- inst = XendOptionsFile()
- return inst
diff --git a/tools/python/xen/xend/XendPBD.py b/tools/python/xen/xend/XendPBD.py
deleted file mode 100644
index 2187cd7..0000000
--- a/tools/python/xen/xend/XendPBD.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (c) 2007 Xensource Inc.
-#============================================================================
-
-
-import uuid
-from XendLogging import log
-from xen.xend.XendBase import XendBase
-from xen.xend import XendAPIStore
-from xen.xend import uuid as genuuid
-
-class XendPBD(XendBase):
- """Physical block devices."""
-
- def getClass(self):
- return "PBD"
-
- def getAttrRO(self):
- attrRO = ['host',
- 'SR',
- 'device_config',
- 'currently_attached']
- return XendBase.getAttrRO() + attrRO
-
- def getAttrRW(self):
- attrRW = []
- return XendBase.getAttrRW() + attrRW
-
- def getAttrInst(self):
- return ['host',
- 'SR',
- 'device_config']
-
- def getMethods(self):
- methods = ['destroy']
- return XendBase.getMethods() + methods
-
- def getFuncs(self):
- funcs = ['create',
- 'get_by_SR']
- return XendBase.getFuncs() + funcs
-
- getClass = classmethod(getClass)
- getAttrRO = classmethod(getAttrRO)
- getAttrRW = classmethod(getAttrRW)
- getAttrInst = classmethod(getAttrInst)
- getMethods = classmethod(getMethods)
- getFuncs = classmethod(getFuncs)
-
- def recreate(uuid, record):
- pbd = XendPBD(record, uuid)
- return uuid
-
- def create(cls, record):
- uuid = genuuid.createString()
- pbd = XendPBD(record, uuid)
- return uuid
-
- create = classmethod(create)
-
- def __init__(self, record, uuid):
- XendBase.__init__(self, uuid, record)
- self.currently_attached = True
-
- def get_host(self):
- return self.host
-
- def get_SR(self):
- return self.SR
-
- def get_device_config(self):
- return self.device_config
-
- def get_currently_attached(self):
- return self.currently_attached
-
- def destroy(self):
- pass
-
- def get_by_SR(cls, sr_ref):
- pbds = XendAPIStore.get_all("PBD")
- return [pbd.get_uuid()
- for pbd in pbds
- if pbd.get_SR() == sr_ref]
-
- get_by_SR = classmethod(get_by_SR)
diff --git a/tools/python/xen/xend/XendPIF.py b/tools/python/xen/xend/XendPIF.py
deleted file mode 100644
index d6e073e..0000000
--- a/tools/python/xen/xend/XendPIF.py
+++ /dev/null
@@ -1,390 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (c) 2006 Xensource Inc.
-#============================================================================
-
-import commands
-import logging
-import os
-import re
-from xen.xend import uuid as genuuid
-from xen.xend import XendAPIStore
-from xen.xend.XendBase import XendBase
-from xen.xend.XendPIFMetrics import XendPIFMetrics
-from xen.xend.XendError import *
-from xen.xend import Vifctl
-from xen.util import auxbin
-
-log = logging.getLogger("xend.XendPIF")
-log.setLevel(logging.TRACE)
-
-MAC_RE = re.compile(':'.join(['[0-9a-f]{2}'] * 6))
-IP_IFACE_RE = re.compile(r'^\d+: (\w+):.*mtu (\d+) .* link/\w+ ([0-9a-f:]+)')
-
-
-Vifctl.network('start')
-
-def linux_phy_to_virt(pif_name):
- return 'eth' + re.sub(r'^[a-z]+', '', pif_name)
-
-def linux_get_phy_ifaces():
- """Returns a list of physical interfaces.
-
- Identifies PIFs as those that have a interface name starting with
- 'peth'.
-
- See /etc/xen/scripts/network-bridge for how the devices are renamed.
-
- @rtype: array of 3-element tuple (name, mtu, mac)
- """
-
- ip_cmd = 'ip -o link show'
- rc, output = commands.getstatusoutput(ip_cmd)
- ifaces = {}
- phy_ifaces = []
- if rc == 0:
- # parse all interfaces into (name, mtu, mac)
- for line in output.split('\n'):
- has_if = re.search(IP_IFACE_RE, line)
- if has_if:
- ifaces[has_if.group(1)] = has_if.groups()
-
- # resolve pifs' mac addresses
- for name, mtu, mac in ifaces.values():
- if name.startswith('peth'):
- bridged_ifname = linux_phy_to_virt(name)
- bridged_if = ifaces.get(bridged_ifname)
- bridged_mac = ''
- if bridged_if:
- bridged_mac = bridged_if[2]
- phy_ifaces.append((name, int(mtu), bridged_mac))
-
- return phy_ifaces
-
-def linux_set_mac(iface, mac):
- if not re.search(MAC_RE, mac):
- return False
-
- ip_mac_cmd = 'ip link set %s addr %s' % \
- (linux_phy_to_virt(iface), mac)
- rc, output = commands.getstatusoutput(ip_mac_cmd)
- if rc == 0:
- return True
-
- return False
-
-def linux_set_mtu(iface, mtu):
- try:
- ip_mtu_cmd = 'ip link set %s mtu %d' % \
- (linux_phy_to_virt(iface), int(mtu))
- rc, output = commands.getstatusoutput(ip_mtu_cmd)
- if rc == 0:
- return True
- return False
- except ValueError:
- return False
-
-def linux_get_mtu(device):
- return _linux_get_pif_param(device, 'mtu')
-
-def linux_get_mac(device):
- return _linux_get_pif_param(device, 'link/ether')
-
-def _linux_get_pif_param(device, param_name):
- ip_get_dev_data = 'ip link show %s' % device
- rc, output = commands.getstatusoutput(ip_get_dev_data)
- if rc == 0:
- params = output.split(' ')
- for i in xrange(len(params)):
- if params[i] == param_name:
- return params[i+1]
- return ''
-
-def _create_VLAN(dev, vlan):
- rc, _ = commands.getstatusoutput('vconfig add %s %d' %
- (dev, vlan))
- if rc != 0:
- return False
-
- rc, _ = commands.getstatusoutput('ifconfig %s.%d up' %
- (dev, vlan))
- return rc == 0
-
-def _destroy_VLAN(dev, vlan):
- rc, _ = commands.getstatusoutput('ifconfig %s.%d down' %
- (dev, vlan))
- if rc != 0:
- return False
-
- rc, _ = commands.getstatusoutput('vconfig rem %s.%d' %
- (dev, vlan))
- return rc == 0
-
-class XendPIF(XendBase):
- """Representation of a Physical Network Interface."""
-
- def getClass(self):
- return "PIF"
-
- def getAttrRO(self):
- attrRO = ['network',
- 'host',
- 'metrics',
- 'device',
- 'VLAN']
- return XendBase.getAttrRO() + attrRO
-
- def getAttrRW(self):
- attrRW = ['MAC',
- 'MTU']
- return XendBase.getAttrRW() + attrRW
-
- def getAttrInst(self):
- attrInst = ['network',
- 'device',
- 'MAC',
- 'MTU',
- 'VLAN']
- return attrInst
-
- def getMethods(self):
- methods = ['plug',
- 'unplug',
- 'destroy']
- return XendBase.getMethods() + methods
-
- def getFuncs(self):
- funcs = ['create_VLAN']
- return XendBase.getFuncs() + funcs
-
- getClass = classmethod(getClass)
- getAttrRO = classmethod(getAttrRO)
- getAttrRW = classmethod(getAttrRW)
- getAttrInst = classmethod(getAttrInst)
- getMethods = classmethod(getMethods)
- getFuncs = classmethod(getFuncs)
-
- def create_phy(self, network_uuid, device,
- MAC, MTU):
- """
- Called when a new physical PIF is found
- Could be a VLAN...
- """
- # Create new uuids
- pif_uuid = genuuid.createString()
- metrics_uuid = genuuid.createString()
-
- # Create instances
- metrics = XendPIFMetrics(metrics_uuid, pif_uuid)
-
- # Is this a VLAN?
- VLANdot = device.split(".")
- VLANcolon = device.split(":")
-
- if len(VLANdot) > 1:
- VLAN = VLANdot[1]
- device = VLANdot[0]
- elif len(VLANcolon) > 1:
- VLAN = VLANcolon[1]
- device = VLANcolon[0]
- else:
- VLAN = -1
-
- record = {
- 'network': network_uuid,
- 'device': device,
- 'MAC': MAC,
- 'MTU': MTU,
- 'VLAN': VLAN
- }
- pif = XendPIF(record, pif_uuid, metrics_uuid)
-
- return pif_uuid
-
- def recreate(self, record, uuid):
- """Called on xend start / restart"""
- pif_uuid = uuid
- metrics_uuid = record['metrics']
-
- # Create instances
- metrics = XendPIFMetrics(metrics_uuid, pif_uuid)
- pif = XendPIF(record, pif_uuid, metrics_uuid)
-
- # If physical PIF, check exists
- # If VLAN, create if not exist
- ifs = [dev for dev, _1, _2 in linux_get_phy_ifaces()]
- if pif.get_VLAN() == -1:
- if pif.get_device() not in ifs:
- XendBase.destroy(pif)
- metrics.destroy()
- return None
- else:
- if pif.get_interface_name() not in ifs:
- _create_VLAN(pif.get_device(), pif.get_VLAN())
- pif.plug()
-
- return pif_uuid
-
- def create_VLAN(self, device, network_uuid, host_ref, vlan):
- """Exposed via API - create a new VLAN from existing VIF"""
-
- ifs = [name for name, _, _ in linux_get_phy_ifaces()]
-
- vlan = int(vlan)
-
- # Check VLAN tag is valid
- if vlan < 0 or vlan >= 4096:
- raise VLANTagInvalid(vlan)
-
- # Check device exists
- if device not in ifs:
- raise InvalidDeviceError(device)
-
- # Check VLAN doesn't already exist
- if "%s.%d" % (device, vlan) in ifs:
- raise DeviceExistsError("%s.%d" % (device, vlan))
-
- # Check network ref is valid
- from XendNetwork import XendNetwork
- if network_uuid not in XendNetwork.get_all():
- raise InvalidHandleError("Network", network_uuid)
-
- # Check host_ref is this host
- import XendNode
- if host_ref != XendNode.instance().get_uuid():
- raise InvalidHandleError("Host", host_ref)
-
- # Create the VLAN
- _create_VLAN(device, vlan)
-
- # Create new uuids
- pif_uuid = genuuid.createString()
- metrics_uuid = genuuid.createString()
-
- # Create the record
- record = {
- "device": device,
- "MAC": linux_get_mac('%s.%d' % (device, vlan)),
- "MTU": linux_get_mtu('%s.%d' % (device, vlan)),
- "network": network_uuid,
- "VLAN": vlan
- }
-
- # Create instances
- metrics = XendPIFMetrics(metrics_uuid, pif_uuid)
- pif = XendPIF(record, pif_uuid, metrics_uuid)
-
- # Not sure if they should be created plugged or not...
- pif.plug()
-
- XendNode.instance().save_PIFs()
- return pif_uuid
-
- create_phy = classmethod(create_phy)
- recreate = classmethod(recreate)
- create_VLAN = classmethod(create_VLAN)
-
- def __init__(self, record, uuid, metrics_uuid):
- XendBase.__init__(self, uuid, record)
- self.metrics = metrics_uuid
-
- def plug(self):
- """Plug the PIF into the network"""
- network = XendAPIStore.get(self.network,
- "network")
- bridge_name = network.get_name_label()
-
- from xen.util import Brctl
- Brctl.vif_bridge_add({
- "bridge": bridge_name,
- "vif": self.get_interface_name()
- })
-
- def unplug(self):
- """Unplug the PIF from the network"""
- network = XendAPIStore.get(self.network,
- "network")
- bridge_name = network.get_name_label()
-
- from xen.util import Brctl
- Brctl.vif_bridge_rem({
- "bridge": bridge_name,
- "vif": self.get_interface_name()
- })
-
- def destroy(self):
- # Figure out if this is a physical device
- if self.get_interface_name() == \
- self.get_device():
- raise PIFIsPhysical()
-
- self.unplug()
-
- if _destroy_VLAN(self.get_device(), self.get_VLAN()):
- XendBase.destroy(self)
- import XendNode
- XendNode.instance().save_PIFs()
- else:
- raise NetworkError("Unable to delete VLAN", self.get_uuid())
-
- def get_interface_name(self):
- if self.get_VLAN() == -1:
- return self.get_device()
- else:
- return "%s.%d" % (self.get_device(), self.get_VLAN())
-
- def get_device(self):
- """
- This is the base interface.
- For phy if (VLAN == -1) this is same as
- if name.
- For VLANs, this it the bit before the period
- """
- return self.device
-
- def get_network(self):
- return self.network
-
- def get_host(self):
- from xen.xend import XendNode
- return XendNode.instance().get_uuid()
-
- def get_metrics(self):
- return self.metrics
-
- def get_MAC(self):
- return self.MAC
-
- def set_MAC(self, new_mac):
- success = linux_set_mac(self.device, new_mac)
- if success:
- self.MAC = new_mac
- import XendNode
- XendNode.instance().save_PIFs()
- return success
-
- def get_MTU(self):
- return self.MTU
-
- def set_MTU(self, new_mtu):
- success = linux_set_mtu(self.device, new_mtu)
- if success:
- self.MTU = new_mtu
- import XendNode
- XendNode.instance().save_PIFs()
- return success
-
- def get_VLAN(self):
- return self.VLAN
diff --git a/tools/python/xen/xend/XendPIFMetrics.py b/tools/python/xen/xend/XendPIFMetrics.py
deleted file mode 100644
index aca8083..0000000
--- a/tools/python/xen/xend/XendPIFMetrics.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (c) 2006-2007 Xensource Inc.
-#============================================================================
-
-from XendBase import XendBase
-
-class XendPIFMetrics(XendBase):
- """PIF Metrics."""
-
- def getClass(self):
- return "PIF_metrics"
-
- def getAttrRO(self):
- attrRO = ['io_read_kbs',
- 'io_write_kbs',
- 'last_updated',
- 'pif']
- return XendBase.getAttrRO() + attrRO
-
- getClass = classmethod(getClass)
- getAttrRO = classmethod(getAttrRO)
-
- def __init__(self, uuid, pif_uuid):
- XendBase.__init__(self, uuid, {})
- self.pif_uuid = pif_uuid
-
- def get_pif(self):
- return self.pif_uuid
-
- def get_io_read_kbs(self):
- return self._get_stat(0)
-
- def get_io_write_kbs(self):
- return self._get_stat(1)
-
- def _get_stat(self, n):
- from xen.xend.XendNode import instance as xennode
- #pifname = self.pif.device
- #pifs_util = xennode().monitor.get_pifs_util()
- #if pifname in pifs_util:
- # return pifs_util[pifname][n]
- return 0.0
-
- def get_last_updated(self):
- import xen.xend.XendAPI as XendAPI
- return XendAPI.now()
diff --git a/tools/python/xen/xend/XendPPCI.py b/tools/python/xen/xend/XendPPCI.py
deleted file mode 100644
index e6248b7..0000000
--- a/tools/python/xen/xend/XendPPCI.py
+++ /dev/null
@@ -1,160 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (c) 2008 NEC Corporation
-# Yosuke Iwamatsu <y-iwamatsu at ab jp nec com>
-#============================================================================
-
-from xen.xend.XendBase import XendBase
-from xen.xend.XendBase import XendAPIStore
-from xen.xend import uuid as genuuid
-
-from xen.util.pci import parse_hex
-
-class XendPPCI(XendBase):
- """Representation of a physical PCI device."""
-
- def getClass(self):
- return "PPCI"
-
- def getAttrRO(self):
- attrRO = ['host',
- 'domain',
- 'bus',
- 'slot',
- 'func',
- 'name',
- 'vendor_id',
- 'vendor_name',
- 'device_id',
- 'device_name',
- 'revision_id',
- 'class_code',
- 'class_name',
- 'subsystem_vendor_id',
- 'subsystem_vendor_name',
- 'subsystem_id',
- 'subsystem_name',
- 'driver']
- return XendBase.getAttrRO() + attrRO
-
- def getAttrRW(self):
- attrRW = []
- return XendBase.getAttrRW() + attrRW
-
- def getAttrInst(self):
- attrInst = []
- return XendBase.getAttrInst() + attrInst
-
- def getMethods(self):
- methods = []
- return XendBase.getMethods() + methods
-
- def getFuncs(self):
- funcs = []
- return XendBase.getFuncs() + funcs
-
- getClass = classmethod(getClass)
- getAttrRO = classmethod(getAttrRO)
- getAttrRW = classmethod(getAttrRW)
- getAttrInst = classmethod(getAttrInst)
- getMethods = classmethod(getMethods)
- getFuncs = classmethod(getFuncs)
-
- def get_by_sbdf(self, domain, bus, slot, func):
- for ppci in XendAPIStore.get_all("PPCI"):
- if ppci.get_domain() == parse_hex(domain) and \
- ppci.get_bus() == parse_hex(bus) and \
- ppci.get_slot() == parse_hex(slot) and \
- ppci.get_func() == parse_hex(func):
- return ppci.get_uuid()
- return None
-
- get_by_sbdf = classmethod(get_by_sbdf)
-
- def __init__(self, uuid, record):
- self.domain = record['domain']
- self.bus = record['bus']
- self.slot = record['slot']
- self.func = record['func']
- self.vendor_id = record['vendor_id']
- self.vendor_name = record['vendor_name']
- self.device_id = record['device_id']
- self.device_name = record['device_name']
- self.revision_id = record['revision_id']
- self.class_code = record['class_code']
- self.class_name = record['class_name']
- self.subsystem_vendor_id = record['subsystem_vendor_id']
- self.subsystem_vendor_name = record['subsystem_vendor_name']
- self.subsystem_id = record['subsystem_id']
- self.subsystem_name = record['subsystem_name']
- self.driver = record['driver']
- XendBase.__init__(self, uuid, record)
-
- def get_host(self):
- from xen.xend import XendNode
- return XendNode.instance().get_uuid()
-
- def get_domain(self):
- return self.domain
-
- def get_bus(self):
- return self.bus
-
- def get_slot(self):
- return self.slot
-
- def get_func(self):
- return self.func
-
- def get_name(self):
- return "%04x:%02x:%02x.%01x" % (self.domain, self.bus, self.slot,
- self.func)
-
- def get_vendor_id(self):
- return self.vendor_id
-
- def get_vendor_name(self):
- return self.vendor_name
-
- def get_device_id(self):
- return self.device_id
-
- def get_device_name(self):
- return self.device_name
-
- def get_class_code(self):
- return self.class_code
-
- def get_class_name(self):
- return self.class_name
-
- def get_revision_id(self):
- return self.revision_id
-
- def get_subsystem_vendor_id(self):
- return self.subsystem_vendor_id
-
- def get_subsystem_vendor_name(self):
- return self.subsystem_vendor_name
-
- def get_subsystem_id(self):
- return self.subsystem_id
-
- def get_subsystem_name(self):
- return self.subsystem_name
-
- def get_driver(self):
- return self.driver
-
diff --git a/tools/python/xen/xend/XendPSCSI.py b/tools/python/xen/xend/XendPSCSI.py
deleted file mode 100644
index e50aa5b..0000000
--- a/tools/python/xen/xend/XendPSCSI.py
+++ /dev/null
@@ -1,211 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright FUJITSU LIMITED 2008
-# Masaki Kanno <kanno.masaki at jp.fujitsu.com>
-#============================================================================
-
-from xen.xend.XendBase import XendBase
-from xen.xend.XendBase import XendAPIStore
-from xen.xend import uuid as genuuid
-
-class XendPSCSI(XendBase):
- """Representation of a physical SCSI device."""
-
- def getClass(self):
- return "PSCSI"
-
- def getAttrRO(self):
- attrRO = ['host',
- 'physical_host',
- 'physical_channel',
- 'physical_target',
- 'physical_lun',
- 'physical_HCTL',
- 'HBA',
- 'vendor_name',
- 'model',
- 'type_id',
- 'type',
- 'dev_name',
- 'sg_name',
- 'revision',
- 'scsi_id',
- 'scsi_level']
- return XendBase.getAttrRO() + attrRO
-
- def getAttrRW(self):
- attrRW = []
- return XendBase.getAttrRW() + attrRW
-
- def getAttrInst(self):
- attrInst = []
- return XendBase.getAttrInst() + attrInst
-
- def getMethods(self):
- methods = []
- return XendBase.getMethods() + methods
-
- def getFuncs(self):
- funcs = []
- return XendBase.getFuncs() + funcs
-
- getClass = classmethod(getClass)
- getAttrRO = classmethod(getAttrRO)
- getAttrRW = classmethod(getAttrRW)
- getAttrInst = classmethod(getAttrInst)
- getMethods = classmethod(getMethods)
- getFuncs = classmethod(getFuncs)
-
- def get_by_HCTL(self, physical_HCTL):
- for pscsi in XendAPIStore.get_all("PSCSI"):
- if pscsi.get_physical_HCTL() == physical_HCTL:
- return pscsi.get_uuid()
- return None
-
- get_by_HCTL = classmethod(get_by_HCTL)
-
- def __init__(self, uuid, record):
- self.physical_HCTL = record['physical_HCTL']
- self.physical_HBA = record['HBA']
- self.vendor_name = record['vendor_name']
- self.model = record['model']
- self.type_id = record['type_id']
- self.type = record['type']
- self.dev_name = record['dev_name']
- self.sg_name = record['sg_name']
- self.revision = record['revision']
- self.scsi_id = record['scsi_id']
- self.scsi_level = record['scsi_level']
-
- p_hctl = self.physical_HCTL.split(':')
- self.physical_host = int(p_hctl[0])
- self.physical_channel = int(p_hctl[1])
- self.physical_target = int(p_hctl[2])
- self.physical_lun = int(p_hctl[3])
-
- XendBase.__init__(self, uuid, record)
-
- def get_host(self):
- from xen.xend import XendNode
- return XendNode.instance().get_uuid()
-
- def get_physical_host(self):
- return self.physical_host
-
- def get_physical_channel(self):
- return self.physical_channel
-
- def get_physical_target(self):
- return self.physical_target
-
- def get_physical_lun(self):
- return self.physical_lun
-
- def get_physical_HCTL(self):
- return self.physical_HCTL
-
- def get_HBA(self):
- return self.physical_HBA
-
- def get_vendor_name(self):
- return self.vendor_name
-
- def get_model(self):
- return self.model
-
- def get_type_id(self):
- return self.type_id
-
- def get_type(self):
- return self.type
-
- def get_dev_name(self):
- return self.dev_name
-
- def get_sg_name(self):
- return self.sg_name
-
- def get_revision(self):
- return self.revision
-
- def get_scsi_id(self):
- return self.scsi_id
-
- def get_scsi_level(self):
- return self.scsi_level
-
-
-class XendPSCSI_HBA(XendBase):
- """Representation of a physical SCSI HBA."""
-
- def getClass(self):
- return "PSCSI_HBA"
-
- def getAttrRO(self):
- attrRO = ['host',
- 'physical_host',
- 'PSCSIs']
- return XendBase.getAttrRO() + attrRO
-
- def getAttrRW(self):
- attrRW = []
- return XendBase.getAttrRW() + attrRW
-
- def getAttrInst(self):
- attrInst = []
- return XendBase.getAttrInst() + attrInst
-
- def getMethods(self):
- methods = []
- return XendBase.getMethods() + methods
-
- def getFuncs(self):
- funcs = []
- return XendBase.getFuncs() + funcs
-
- getClass = classmethod(getClass)
- getAttrRO = classmethod(getAttrRO)
- getAttrRW = classmethod(getAttrRW)
- getAttrInst = classmethod(getAttrInst)
- getMethods = classmethod(getMethods)
- getFuncs = classmethod(getFuncs)
-
- def get_by_physical_host(self, physical_host):
- for pscsi_HBA in XendAPIStore.get_all('PSCSI_HBA'):
- if pscsi_HBA.get_physical_host() == physical_host:
- return pscsi_HBA.get_uuid()
- return None
-
- get_by_physical_host = classmethod(get_by_physical_host)
-
- def __init__(self, uuid, record):
- self.physical_host = record['physical_host']
- XendBase.__init__(self, uuid, record)
-
- def get_host(self):
- from xen.xend import XendNode
- return XendNode.instance().get_uuid()
-
- def get_physical_host(self):
- return self.physical_host
-
- def get_PSCSIs(self):
- PSCSIs = []
- uuid = self.get_uuid()
- for pscsi in XendAPIStore.get_all('PSCSI'):
- if pscsi.get_HBA() == uuid:
- PSCSIs.append(pscsi.get_uuid())
- return PSCSIs
-
diff --git a/tools/python/xen/xend/XendProtocol.py b/tools/python/xen/xend/XendProtocol.py
deleted file mode 100644
index 34af4a4..0000000
--- a/tools/python/xen/xend/XendProtocol.py
+++ /dev/null
@@ -1,225 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd.
-#============================================================================
-
-import socket
-import httplib
-import time
-import types
-
-from encode import *
-from xen.xend import sxp
-
-from xen.xend import XendOptions
-
-DEBUG = 0
-
-HTTP_OK = 200
-HTTP_CREATED = 201
-HTTP_ACCEPTED = 202
-HTTP_NO_CONTENT = 204
-
-
-xoptions = XendOptions.instance()
-
-
-class XendError(RuntimeError):
- """Error class for 'expected errors' when talking to xend.
- """
- pass
-
-class XendRequest:
- """A request to xend.
- """
-
- def __init__(self, url, method, args):
- """Create a request. Sets up the headers, argument data, and the
- url.
-
- @param url: the url to request
- @param method: request method, GET or POST
- @param args: dict containing request args, if any
- """
- if url.proto != 'http':
- raise ValueError('Invalid protocol: ' + url.proto)
- (hdr, data) = encode_data(args)
- if args and method == 'GET':
- url.query = data
- data = None
- if method == "POST" and url.path.endswith('/'):
- url.path = url.path[:-1]
-
- self.headers = hdr
- self.data = data
- self.url = url
- self.method = method
-
-class XendClientProtocol:
- """Abstract class for xend clients.
- """
- def xendRequest(self, url, method, args=None):
- """Make a request to xend.
- Implement in a subclass.
-
- @param url: xend request url
- @param method: http method: POST or GET
- @param args: request arguments (dict)
- """
- raise NotImplementedError()
-
- def xendGet(self, url, args=None):
- """Make a xend request using HTTP GET.
- Requests using GET are usually 'safe' and may be repeated without
- nasty side-effects.
-
- @param url: xend request url
- @param data: request arguments (dict)
- """
- return self.xendRequest(url, "GET", args)
-
- def xendPost(self, url, args):
- """Make a xend request using HTTP POST.
- Requests using POST potentially cause side-effects, and should
- not be repeated unless you really want to repeat the side
- effect.
-
- @param url: xend request url
- @param args: request arguments (dict)
- """
- return self.xendRequest(url, "POST", args)
-
- def handleStatus(self, _, status, message):
- """Handle the status returned from the request.
- """
- status = int(status)
- if status in [ HTTP_NO_CONTENT ]:
- return None
- if status not in [ HTTP_OK, HTTP_CREATED, HTTP_ACCEPTED ]:
- return self.handleException(XendError(message))
- return 'ok'
-
- def handleResponse(self, data):
- """Handle the data returned in response to the request.
- """
- if data is None: return None
- typ = self.getHeader('Content-Type')
- if typ != sxp.mime_type:
- return data
- try:
- pin = sxp.Parser()
- pin.input(data);
- pin.input_eof()
- val = pin.get_val()
- except sxp.ParseError, err:
- return self.handleException(err)
- if isinstance(val, types.ListType) and sxp.name(val) == 'xend.err':
- err = XendError(val[1])
- return self.handleException(err)
- return val
-
- def handleException(self, err):
- """Handle an exception during the request.
- May be overridden in a subclass.
- """
- raise err
-
- def getHeader(self, key):
- """Get a header from the response.
- Case is ignored in the key.
-
- @param key: header key
- @return: header
- """
- raise NotImplementedError()
-
-class HttpXendClientProtocol(XendClientProtocol):
- """A synchronous xend client. This will make a request, wait for
- the reply and return the result.
- """
-
- resp = None
- request = None
-
- def makeConnection(self, url):
- return httplib.HTTPConnection(url.location())
-
- def makeRequest(self, url, method, args):
- return XendRequest(url, method, args)
-
- def xendRequest(self, url, method, args=None):
- """Make a request to xend.
-
- @param url: xend request url
- @param method: http method: POST or GET
- @param args: request arguments (dict)
- """
- retries = 0
- while retries < 2:
- self.request = self.makeRequest(url, method, args)
- conn = self.makeConnection(url)
- try:
- if DEBUG: conn.set_debuglevel(1)
- conn.request(method, url.fullpath(), self.request.data,
- self.request.headers)
- try:
- resp = conn.getresponse()
- self.resp = resp
- val = self.handleStatus(resp.version, resp.status,
- resp.reason)
- if val is None:
- data = None
- else:
- data = resp.read()
- val = self.handleResponse(data)
- return val
- except httplib.BadStatusLine:
- retries += 1
- time.sleep(5)
- finally:
- conn.close()
-
- raise XendError("Received invalid response from Xend, twice.")
-
-
- def getHeader(self, key):
- return self.resp.getheader(key)
-
-
-class UnixConnection(httplib.HTTPConnection):
- """Subclass of Python library HTTPConnection that uses a unix-domain socket.
- """
-
- def __init__(self, path):
- httplib.HTTPConnection.__init__(self, 'localhost')
- self.path = path
-
- def connect(self):
- sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- sock.connect(self.path)
- self.sock = sock
-
-class UnixXendClientProtocol(HttpXendClientProtocol):
- """A synchronous xend client using a unix-domain socket.
- """
-
- def __init__(self, path=None):
- if path is None:
- path = xoptions.get_xend_unix_path()
- self.path = path
-
- def makeConnection(self, _):
- return UnixConnection(self.path)
diff --git a/tools/python/xen/xend/XendQCoWStorageRepo.py b/tools/python/xen/xend/XendQCoWStorageRepo.py
deleted file mode 100644
index 726df0b..0000000
--- a/tools/python/xen/xend/XendQCoWStorageRepo.py
+++ /dev/null
@@ -1,340 +0,0 @@
-#!/usr/bin/python
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006,2007 XenSource Ltd.
-#============================================================================
-#
-# The default QCOW Xen API Storage Repository
-#
-
-import commands
-import logging
-import os
-import stat
-import threading
-import re
-import sys
-import struct
-
-from xen.util import mkdir
-import uuid
-from XendPBD import XendPBD
-from XendError import XendError
-from XendVDI import *
-from XendTask import XendTask
-from XendStorageRepository import XendStorageRepository
-from XendOptions import instance as xendoptions
-
-XEND_STORAGE_NO_MAXIMUM = sys.maxint
-XEND_STORAGE_QCOW_FILENAME = "%s.qcow"
-XEND_STORAGE_VDICFG_FILENAME = "%s.vdi.xml"
-QCOW_CREATE_COMMAND = "/usr/sbin/qcow-create -r %d %s"
-
-MB = 1024 * 1024
-
-log = logging.getLogger("xend.XendQCowStorageRepo")
-
-
-def qcow_virtual_size(qcow_file):
- """Read the first 32 bytes of the QCoW header to determine its size.
-
- See: http://www.gnome.org/~markmc/qcow-image-format.html.
- """
- try:
- qcow_header = open(qcow_file, 'rb').read(32)
- parts = struct.unpack('>IIQIIQ', qcow_header)
- return parts[-1]
- except IOError:
- return -1
-
-class XendQCoWStorageRepo(XendStorageRepository):
- """A simple file backed QCOW Storage Repository.
-
- This class exposes the interface to create VDI's via the
- Xen API. The backend is a file-backed QCOW format that is stored
- in XEND_STORAGE_DIR or any that is specified in the constructor.
-
- The actual images are created in the format <uuid>.img and <uuid>.qcow.
- """
-
- def __init__(self, sr_uuid,
- sr_type = "qcow_file",
- name_label = "QCoW",
- name_description = "Xend QCoW Storage Repository",
- storage_max = XEND_STORAGE_NO_MAXIMUM):
- """
- @keyword storage_max: Maximum disk space to use in bytes.
- @type storage_max: int
-
- @ivar storage_free: storage space free for this repository
- @ivar images: mapping of all the images.
- @type images: dictionary by image uuid.
- @ivar lock: lock to provide thread safety.
- """
-
- XendStorageRepository.__init__(self, sr_uuid, sr_type, name_label,
- name_description, storage_max)
- self.storage_free = 0
- self.location = xendoptions().get_xend_storage_path()
- self._refresh()
-
- def get_record(self, transient = True):
- retval = {'uuid': self.uuid,
- 'name_label': self.name_label,
- 'name_description': self.name_description,
- 'virtual_allocation': self.virtual_allocation,
- 'physical_utilisation': self.physical_utilisation,
- 'physical_size': self.physical_size,
- 'type': self.type,
- 'content_type': self.content_type,
- 'VDIs': self.images.keys(),
- 'PBDs': XendPBD.get_by_SR(self.uuid)}
-
- if self.physical_size == XEND_STORAGE_NO_MAXIMUM:
- stfs = os.statvfs(self.location)
- retval['physical_size'] = stfs.f_blocks * stfs.f_frsize
-
- return retval
-
- def _refresh(self):
- """Internal function that refreshes the state of the disk and
- updates the list of images available.
- """
- self.lock.acquire()
- try:
- mkdir.parents(self.location, stat.S_IRWXU)
-
- # scan the directory and populate self.images
- virtual_alloc = 0
- physical_used = 0
- seen_images = []
- for filename in os.listdir(self.location):
- if filename[-5:] == XEND_STORAGE_QCOW_FILENAME[-5:]:
- image_uuid = filename[:-5]
- seen_images.append(image_uuid)
-
- qcow_file = XEND_STORAGE_QCOW_FILENAME % image_uuid
- cfg_file = XEND_STORAGE_VDICFG_FILENAME % image_uuid
- qcow_path = os.path.join(self.location, qcow_file)
- cfg_path = os.path.join(self.location, cfg_file)
-
- phys_size = os.stat(qcow_path).st_size
- virt_size = qcow_virtual_size(qcow_path)
-
- # add this image if we haven't seen it before
- if image_uuid not in self.images:
- vdi = XendQCoWVDI(image_uuid, self.uuid,
- qcow_path, cfg_path,
- virt_size, phys_size)
-
- if cfg_path and os.path.exists(cfg_path):
- try:
- vdi.load_config(cfg_path)
- except:
- log.error('Corrupt VDI configuration file %s' %
- cfg_path)
-
- self.images[image_uuid] = vdi
-
- physical_used += phys_size
- virtual_alloc += virt_size
-
- # remove images that aren't valid
- for image_uuid in self.images.keys():
- if image_uuid not in seen_images:
- try:
- os.unlink(self.images[image_uuid].qcow_path)
- except OSError:
- pass
- del self.images[image_uuid]
-
- self.virtual_allocation = virtual_alloc
- self.physical_utilisation = physical_used
-
- # update free storage if we have to track that
- if self.physical_size == XEND_STORAGE_NO_MAXIMUM:
- self.storage_free = self._get_free_space()
- else:
- self.storage_free = self.physical_size - self.virtual_allocation
-
- finally:
- self.lock.release()
-
- def _get_free_space(self):
- """Returns the amount of free space in bytes available in the storage
- partition. Note that this may not be used if the storage repository
- is initialised with a maximum size in storage_max.
-
- @rtype: int
- """
- stfs = os.statvfs(self.location)
- return stfs.f_bavail * stfs.f_frsize
-
- def _has_space_available_for(self, size_bytes):
- """Returns whether there is enough space for an image in the
- partition which the storage_dir resides on.
-
- @rtype: bool
- """
- if self.physical_size != XEND_STORAGE_NO_MAXIMUM:
- return self.storage_free > size_bytes
-
- bytes_free = self._get_free_space()
- if size_bytes < bytes_free:
- return True
- return False
-
- def _create_image_files(self, desired_size_bytes):
- """Create an image and return its assigned UUID.
-
- @param desired_size_bytes: Desired image size in bytes
- @type desired_size_bytes: int
- @rtype: string
- @return: uuid
-
- @raises XendError: If an error occurs.
- """
- self.lock.acquire()
- try:
- if not self._has_space_available_for(desired_size_bytes):
- raise XendError("Not enough space (need %d)" %
- desired_size_bytes)
-
- image_uuid = uuid.createString()
- qcow_path = os.path.join(self.location,
- XEND_STORAGE_QCOW_FILENAME % image_uuid)
-
- if qcow_path and os.path.exists(qcow_path):
- raise XendError("Image with same UUID alreaady exists:" %
- image_uuid)
-
- cmd = QCOW_CREATE_COMMAND % (desired_size_bytes/MB, qcow_path)
- rc, output = commands.getstatusoutput(cmd)
-
- if rc != 0:
- # cleanup the image file
- os.unlink(qcow_path)
- raise XendError("Failed to create QCOW Image: %s" % output)
-
- self._refresh()
- return image_uuid
- finally:
- self.lock.release()
-
- def destroy_vdi(self, image_uuid):
- """Destroy an image that is managed by this storage repository.
-
- @param image_uuid: Image UUID
- @type image_uuid: String
- @rtype: String
- """
- self.lock.acquire()
- try:
- if image_uuid in self.images:
- # TODO: check if it is being used?
- qcow_path = self.images[image_uuid].qcow_path
- cfg_path = self.images[image_uuid].cfg_path
- try:
- os.unlink(qcow_path)
- if cfg_path and os.path.exists(cfg_path):
- os.unlink(cfg_path)
- except OSError:
- log.exception("Failed to destroy image")
- del self.images[image_uuid]
- self._refresh()
- return True
- finally:
- self.lock.release()
-
- return False
-
- def free_space_bytes(self):
- """Returns the amount of available space in KB.
- @rtype: int
- """
- self.lock.acquire()
- try:
- return self.storage_free
- finally:
- self.lock.release()
-
- def total_space_bytes(self):
- """Returns the total usable space of the storage repo in KB.
- @rtype: int
- """
- self.lock.acquire()
- try:
- if self.physical_size == XEND_STORAGE_NO_MAXIMUM:
- stfs = os.statvfs(self.location)
- return stfs.f_blocks * stfs.f_frsize
- else:
- return self.physical_size
- finally:
- self.lock.release()
-
- def used_space_bytes(self):
- """Returns the total amount of space used by this storage repository.
- @rtype: int
- """
- self.lock.acquire()
- try:
- return self.physical_utilisation
- finally:
- self.lock.release()
-
- def virtual_allocation(self):
- """Returns the total virtual space allocated within the storage repo.
- @rtype: int
- """
- self.lock.acquire()
- try:
- return self.virtual_allocation
- finally:
- self.lock.release()
-
-
- def create_vdi(self, vdi_struct):
- image_uuid = None
- try:
- size_bytes = int(vdi_struct.get('virtual_size', 0))
-
- image_uuid = self._create_image_files(size_bytes)
-
- image = self.images[image_uuid]
- image_cfg = {
- 'virtual_size': size_bytes,
- 'type': vdi_struct.get('type', 'system'),
- 'name_label': vdi_struct.get('name_label', ''),
- 'name_description': vdi_struct.get('name_description', ''),
- 'sharable': bool(vdi_struct.get('sharable', False)),
- 'read_only': bool(vdi_struct.get('read_only', False)),
- }
-
- # load in configuration from vdi_struct
- image.load_config_dict(image_cfg)
-
- # save configuration to file
- cfg_filename = XEND_STORAGE_VDICFG_FILENAME % image_uuid
- cfg_path = os.path.join(self.location, cfg_filename)
- image.save_config(cfg_path)
-
- except Exception, e:
- # cleanup before raising exception
- if image_uuid:
- self.destroy_vdi(image_uuid)
-
- raise
-
- return image_uuid
diff --git a/tools/python/xen/xend/XendSXPDev.py b/tools/python/xen/xend/XendSXPDev.py
deleted file mode 100644
index f145701..0000000
--- a/tools/python/xen/xend/XendSXPDev.py
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/env python
-#
-# Helper functions for dealing with the sxp representation of devices
-
-import types
-
-def dev_dict_to_sxp(dev):
- def f((key, val)):
- if isinstance(val, types.ListType):
- return map(lambda x: [key, x], val)
- return [[key, val]]
- dev_sxp = ['dev'] + reduce(lambda x, y: x + y, map(f, dev.items()))
- return dev_sxp
diff --git a/tools/python/xen/xend/XendStateStore.py b/tools/python/xen/xend/XendStateStore.py
deleted file mode 100644
index a66181d..0000000
--- a/tools/python/xen/xend/XendStateStore.py
+++ /dev/null
@@ -1,234 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (c) 2006 Xensource Inc.
-#============================================================================
-
-import os
-
-from xen.xend import uuid
-from xen.xend.XendLogging import log
-from xml.dom import minidom
-from xml.dom import Node
-
-class XendStateStore:
- """Manages persistent storage of Xend's internal state, mainly
- relating to API objects.
-
- It stores objects atomically in the file system as flat XML files
- categorised by their 'class'.
-
- For example:
-
- /var/lib/xend/state/cpu.xml will contain the host cpu state
- /var/lib/xend/state/sr.xml will contain the storage repository state.
-
- For the application, it will load the state via this class:
-
- load_state('cpu') will return a marshalled dictionary object
- containing the cpu state.
-
- save_state('cpu', dict) will save the state contained in the dictionary
- object about the 'cpu'.
-
- The state is stored where each top level element has a UUID in its
- attributes. eg:
-
- host['49c01812-3c28-1ad4-a59d-2a3f81b13ec2'] = {
- 'name': 'norwich',
- 'desc': 'Test Xen Host',
- 'cpu': {'6fc2d1ed-7eb0-4c9d-8006-3657d5483ae0': <obj>,
- '669df3b8-62be-4e61-800b-bbe8ee63a760': <obj>}
- }
-
- will turn into:
-
- <hosts>
- <host uuid='49c01812-3c28-1ad4-a59d-2a3f81b13ec2'>
- <name type='string'>norwich</name>
- <description type='string'>Test Xen Host</description>
- <cpu type='dict'>
- <item uuid='6fc2d1ed-7eb0-4c9d-8006-3657d5483ae0' />
- <item uuid='669df3b8-62be-4e61-800b-bbe8ee63a760' />
- </cpu>
- </host>
- </hosts>
-
- Note that it only dumps one level, so the references to CPU are
- stored in a separate file.
-
- """
-
- def __init__(self, base = "/var/lib/xend/state"):
- self.base = base
- if not os.path.exists(self.base):
- os.makedirs(self.base)
-
- def _xml_file(self, cls):
- """Return the absolute filename of the XML state storage file.
-
- @param cls: name of the class.
- @type cls: string
- @rtype: string
- @return absolute filename of XML file to write/read from.
- """
- return os.path.join(self.base, '%s.xml' % cls)
-
- def load_state(self, cls):
- """Load the saved state of a class from persistent XML storage.
-
- References loaded from the XML will just point to an empty
- dictionary which the caller will need to replace manually.
-
- @param cls: name of the class to load.
- @type cls: string
- @rtype: dict
- """
-
- xml_path = self._xml_file(cls)
- if not os.path.exists(xml_path):
- return {}
-
- if os.path.getsize(xml_path) == 0:
- return {}
-
- dom = minidom.parse(xml_path)
- root = dom.documentElement
- state = {}
-
- for child in root.childNodes:
- if child.nodeType != Node.ELEMENT_NODE:
- continue # skip non element nodes
-
- uuid = child.getAttribute('uuid').encode('utf8')
- cls_dict = {}
- for val_elem in child.childNodes:
- if val_elem.nodeType != Node.ELEMENT_NODE:
- continue # skip non element nodes
-
- val_name = val_elem.tagName
- val_type = val_elem.getAttribute('type').encode('utf8')
- val_uuid = val_elem.getAttribute('uuid').encode('utf8')
- val_elem.normalize()
- val_text = ''
- if val_elem.firstChild:
- val_text = val_elem.firstChild.nodeValue.strip()
-
- if val_type == 'list':
- cls_dict[val_name] = []
- for item in val_elem.childNodes:
- if item.nodeType != Node.ELEMENT_NODE:
- continue # skip non element nodes
- cls_dict[val_name].append(item.getAttribute('uuid'))
- elif val_type == 'dict':
- cls_dict[val_name] = {}
- for item in val_elem.childNodes:
- if item.nodeType != Node.ELEMENT_NODE:
- continue # skip non element nodes
- k = item.getAttribute('key').encode('utf8')
- v = item.getAttribute('value').encode('utf8')
- cls_dict[val_name][k] = v
- elif val_type == 'string':
- cls_dict[val_name] = val_text.encode('utf8')
- elif val_type == 'float':
- cls_dict[val_name] = float(val_text)
- elif val_type == 'int':
- cls_dict[val_name] = int(val_text)
- elif val_type == 'bool':
- cls_dict[val_name] = bool(int(val_text))
- state[uuid] = cls_dict
-
- dom.unlink()
- return state
-
- def save_state(self, cls, state):
- """Save a Xen API record struct into an XML persistent storage
- for future loading when Xend restarts.
-
- If we encounter a dictionary or a list, we only store the
- keys because they are going to be UUID references to another
- object.
-
- @param cls: Class name (singular) of the record
- @type cls: string
- @param state: a Xen API struct of the state of the class.
- @type state: dict
- @rtype: None
- """
- xml_path = self._xml_file(cls)
-
- doc = minidom.getDOMImplementation().createDocument(None,
- cls + 's',
- None)
- root = doc.documentElement
-
- # Marshall a dictionary into our custom XML file format.
- for uuid, info in state.items():
- node = doc.createElement(cls)
- root.appendChild(node)
- node.setAttribute('uuid', uuid)
-
- for key, val in info.items():
- store_val = val
- store_type = None
-
- # deal with basic types
- if type(val) in (str, unicode):
- store_val = val
- store_type = 'string'
- elif type(val) == int:
- store_val = str(val)
- store_type = 'int'
- elif type(val) == float:
- store_val = str(val)
- store_type = 'float'
- elif type(val) == bool:
- store_val = str(int(val))
- store_type = 'bool'
-
- if store_type is not None:
- val_node = doc.createElement(key)
- val_node.setAttribute('type', store_type)
- node.appendChild(val_node)
- # attach the value
- val_text = doc.createTextNode(store_val)
- val_node.appendChild(val_text)
- continue
-
- # deal with dicts and lists
- if type(val) == dict:
- val_node = doc.createElement(key)
- val_node.setAttribute('type', 'dict')
- for val_item in val.keys():
- tmp = doc.createElement("item")
- if key in ['other_config', 'device_config']:
- tmp.setAttribute('key', str(val_item))
- tmp.setAttribute('value', str(val[val_item]))
- else:
- tmp.setAttribute('uuid', val_uuid)
- val_node.appendChild(tmp)
- node.appendChild(val_node)
- elif type(val) in (list, tuple):
- val_node = doc.createElement(key)
- val_node.setAttribute('type', 'list')
- for val_uuid in val:
- tmp = doc.createElement("item")
- tmp.setAttribute('uuid', val_uuid)
- val_node.appendChild(tmp)
- node.appendChild(val_node)
-
- open(xml_path, 'w').write(doc.toprettyxml())
- doc.unlink()
-
diff --git a/tools/python/xen/xend/XendStorageRepository.py b/tools/python/xen/xend/XendStorageRepository.py
deleted file mode 100644
index 6ac94d3..0000000
--- a/tools/python/xen/xend/XendStorageRepository.py
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/usr/bin/python
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006, 2007 XenSource Ltd.
-#============================================================================
-#
-# Abstract class for XendStorageRepositories
-#
-
-import threading
-import sys
-
-from XendError import XendError
-from XendVDI import *
-from XendPBD import XendPBD
-
-XEND_STORAGE_NO_MAXIMUM = sys.maxint
-
-class XendStorageRepository:
- """ Base class for Storage Repos. """
-
- def __init__(self, uuid,
- sr_type = "unknown",
- name_label = 'Unknown',
- name_description = 'Not Implemented',
- storage_max = XEND_STORAGE_NO_MAXIMUM):
- """
- @keyword storage_max: Maximum disk space to use in bytes.
- @type storage_max: int
-
- @ivar storage_free: storage space free for this repository
- @ivar images: mapping of all the images.
- @type images: dictionary by image uuid.
- @ivar lock: lock to provide thread safety.
- """
-
- # XenAPI Parameters
- self.uuid = uuid
- self.type = sr_type
- self.name_label = name_label
- self.name_description = name_description
- self.images = {}
-
- self.physical_size = storage_max
- self.physical_utilisation = 0
- self.virtual_allocation = 0
- self.content_type = ''
-
- self.lock = threading.RLock()
-
- def get_record(self, transient = True):
- retval = {'uuid': self.uuid,
- 'name_label': self.name_label,
- 'name_description': self.name_description,
- 'virtual_allocation': self.virtual_allocation,
- 'physical_utilisation': self.physical_utilisation,
- 'physical_size': self.physical_size,
- 'type': self.type,
- 'content_type': self.content_type,
- 'VDIs': self.images.keys()}
- if not transient:
- retval ['PBDs'] = XendPBD.get_by_SR(self.uuid)
- return retval
-
-
- def is_valid_vdi(self, vdi_uuid):
- return (vdi_uuid in self.images)
-
- def get_vdi_by_uuid(self, image_uuid):
- self.lock.acquire()
- try:
- return self.images.get(image_uuid)
- finally:
- self.lock.release()
-
- def get_vdi_by_name_label(self, label):
- self.lock.acquire()
- try:
- for image_uuid, image in self.images.items():
- if image.name_label == label:
- return image_uuid
- return None
- finally:
- self.lock.release()
-
- def get_vdis(self):
- return self.images.keys()
-
- def create_vdi(self, vdi_struct):
- raise NotImplementedError()
-
- def destroy_vdi(self, vdi_struct):
- raise NotImplementedError()
-
- def list_images(self):
- """ List all the available images by UUID.
-
- @rtype: list of strings.
- @return: list of UUIDs
- """
- self.lock.acquire()
- try:
- return self.images.keys()
- finally:
- self.lock.release()
-
diff --git a/tools/python/xen/xend/XendTask.py b/tools/python/xen/xend/XendTask.py
deleted file mode 100644
index 5045a06..0000000
--- a/tools/python/xen/xend/XendTask.py
+++ /dev/null
@@ -1,224 +0,0 @@
-#===========================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2007 XenSource Ltd
-#============================================================================
-
-from xen.xend.XendAPIConstants import XEN_API_TASK_STATUS_TYPE
-from xen.xend.XendLogging import log
-import thread
-import threading
-
-class XendTask(threading.Thread):
- """Represents a Asynchronous Task used by Xen API.
-
- Basically proxies the callable object in a thread and returns the
- results via self.{type,result,error_info}.
-
- @cvar task_progress: Thread local storage for progress tracking.
- It is a dict indexed by thread_id. Note that the
- thread_id may be reused when the previous
- thread with the thread_id ends.
-
- @cvar task_progress_lock: lock on thread access to task_progress
-
- """
-
- # progress stack:
- # thread_id : [(start_task, end_task),
- # (start_sub_task, end_sub_task)..]
- # example : (0, 100), (50, 100) (50, 100) ...
- # That would mean that the task is 75% complete.
- # as it is 50% of the last 50% of the task.
-
- task_progress = {}
- task_progress_lock = threading.Lock()
-
- def __init__(self, uuid, func, args, func_name, return_type, label, desc,
- session):
- """
- @param uuid: UUID of the task
- @type uuid: string
- @param func: Method to call (from XendAPI)
- @type func: callable object
- @param args: arguments to pass to function
- @type args: list or tuple
- @param label: name label of the task.
- @type label: string
- @param desc: name description of the task.
- @type desc: string
- @param func_name: function name, eg ('VM.start')
- @type desc: string
- """
-
- threading.Thread.__init__(self)
- self.status_lock = threading.Lock()
- self.status = XEN_API_TASK_STATUS_TYPE[0]
-
- self.progress = 0
- self.type = return_type
- self.uuid = uuid
-
- self.result = None
- self.error_info = []
-
- self.name_label = label or func.__name__
- self.name_description = desc
- self.thread_id = 0
-
- self.func_name = func_name
- self.func = func
- self.args = args
-
- self.session = session
-
- def set_status(self, new_status):
- self.status_lock.acquire()
- try:
- self.status = new_status
- finally:
- self.status_lock.release()
-
- def get_status(self):
- self.status_lock.acquire()
- try:
- return self.status
- finally:
- self.status_lock.release()
-
- def run(self):
- """Runs the method and stores the result for later access.
-
- Is invoked by threading.Thread.start().
- """
-
- self.thread_id = thread.get_ident()
- self.task_progress_lock.acquire()
- try:
- self.task_progress[self.thread_id] = {}
- self.progress = 0
- finally:
- self.task_progress_lock.release()
-
- try:
- result = self.func(*self.args)
- if result['Status'] == 'Success':
- self.result = result['Value']
- self.set_status(XEN_API_TASK_STATUS_TYPE[1])
- else:
- self.error_info = result['ErrorDescription']
- self.set_status(XEN_API_TASK_STATUS_TYPE[2])
- except Exception, e:
- log.exception('Error running Async Task')
- self.error_info = ['INTERNAL ERROR', str(e)]
- self.set_status(XEN_API_TASK_STATUS_TYPE[2])
-
- self.task_progress_lock.acquire()
- try:
- del self.task_progress[self.thread_id]
- self.progress = 100
- finally:
- self.task_progress_lock.release()
-
- def get_record(self):
- """Returns a Xen API compatible record."""
- return {
- 'uuid': self.uuid,
- 'name_label': self.name_label,
- 'name_description': self.name_description,
- 'status': self.status,
- 'progress': self.get_progress(),
- 'type': self.type,
- 'result': self.result,
- 'error_info': self.error_info,
- 'allowed_operations': {},
- 'session': self.session,
- }
-
- def get_progress(self):
- """ Checks the thread local progress storage. """
- if self.status != XEN_API_TASK_STATUS_TYPE[0]:
- return 100
-
- self.task_progress_lock.acquire()
- try:
- # Pop each progress range in the stack and map it on to
- # the next progress range until we find out cumulative
- # progress based on the (start, end) range of each level
- start = 0
- prog_stack = self.task_progress.get(self.thread_id, [])[:]
- if len(prog_stack) > 0:
- start, stop = prog_stack.pop()
- while prog_stack:
- new_start, new_stop = prog_stack.pop()
- start = new_start + ((new_stop - new_start)/100.0 * start)
-
- # only update progress if it increases, this will prevent
- # progress from going backwards when tasks are popped off
- # the stack
- if start > self.progress:
- self.progress = int(start)
- finally:
- self.task_progress_lock.release()
-
- return self.progress
-
-
- def log_progress(cls, progress_min, progress_max,
- func, *args, **kwds):
- """ Callable function wrapper that logs the progress of the
- function to thread local storage for task progress calculation.
-
- This is a class method so other parts of Xend will update
- the task progress by calling:
-
- XendTask.push_progress(progress_min, progress_max,
- func, *args, **kwds)
-
- The results of the progress is stored in thread local storage
- and the result of the func(*args, **kwds) is returned back
- to the caller.
-
- """
- thread_id = thread.get_ident()
- retval = None
-
- # Log the start of the method
- cls.task_progress_lock.acquire()
- try:
- if type(cls.task_progress.get(thread_id)) != list:
- cls.task_progress[thread_id] = []
-
- cls.task_progress[thread_id].append((progress_min,
- progress_max))
- finally:
- cls.task_progress_lock.release()
-
- # Execute the method
- retval = func(*args, **kwds)
-
- # Log the end of the method by popping the progress range
- # off the stack.
- cls.task_progress_lock.acquire()
- try:
- cls.task_progress[thread_id].pop()
- finally:
- cls.task_progress_lock.release()
-
- return retval
-
- log_progress = classmethod(log_progress)
-
-
-
diff --git a/tools/python/xen/xend/XendTaskManager.py b/tools/python/xen/xend/XendTaskManager.py
deleted file mode 100644
index 6282078..0000000
--- a/tools/python/xen/xend/XendTaskManager.py
+++ /dev/null
@@ -1,110 +0,0 @@
-#===========================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2007 XenSource Ltd
-#============================================================================
-
-"""
-Task Manager for Xen API asynchronous tasks.
-
-Stores all tasks in a simple dictionary in module's own local storage to
-avoid the 'instance()' methods.
-
-Tasks are indexed by UUID.
-
-"""
-
-from xen.xend.XendTask import XendTask
-from xen.xend import uuid
-import threading
-
-tasks = {}
-tasks_lock = threading.Lock()
-
-def create_task(func, args, func_name, return_type, label, session):
- """Creates a new Task and registers it with the XendTaskManager.
-
- @param func: callable object XMLRPC method
- @type func: callable object
- @param args: tuple or list of arguments
- @type args: tuple or list
- @param func_name: XMLRPC method name, so we can estimate the progress
- @type func_name: string
-
- @return: Task UUID
- @rtype: string.
- """
- task_uuid = uuid.createString()
- try:
- tasks_lock.acquire()
- task = XendTask(task_uuid, func, args, func_name, return_type, label,
- '', session)
- tasks[task_uuid] = task
- finally:
- tasks_lock.release()
-
- task.start()
-
- return task_uuid
-
-def destroy_task(task_uuid):
- """Destroys a task.
-
- @param task_uuid: Task UUID
- @type task_uuid: string.
- """
- try:
- tasks_lock.acquire()
- if task_uuid in tasks:
- del tasks[task_uuid]
- finally:
- tasks_lock.release()
-
-def get_all_tasks():
- """ Returns all the UUID of tracked tasks, completed or pending.
-
- @returns: list of UUIDs
- @rtype: list of strings
- """
- try:
- tasks_lock.acquire()
- return tasks.keys()
- finally:
- tasks_lock.release()
-
-def get_task(task_uuid):
- """ Retrieves a task by UUID.
-
- @rtype: XendTask or None
- @return: Task denoted by UUID.
- """
- try:
- tasks_lock.acquire()
- return tasks.get(task_uuid)
- finally:
- tasks_lock.release()
-
-def get_tasks_by_name(task_name):
- """ Retrieves a task by UUID.
-
- @rtype: XendTask or None
- @return: Task denoted by UUID.
- """
- try:
- tasks_lock.acquire()
- return [t.uuid for t in tasks if t.name_label == name]
- finally:
- tasks_lock.release()
-
-
diff --git a/tools/python/xen/xend/XendVDI.py b/tools/python/xen/xend/XendVDI.py
deleted file mode 100644
index f8abea6..0000000
--- a/tools/python/xen/xend/XendVDI.py
+++ /dev/null
@@ -1,214 +0,0 @@
-#!/usr/bin/python
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 XenSource Ltd.
-#============================================================================
-#
-# Representation of a Xen API VDI
-#
-
-import os
-
-from xen.util.xmlrpclib2 import stringify
-from xmlrpclib import dumps, loads
-from xen.util import xsconstants
-import xen.util.xsm.xsm as security
-from xen.xend.XendError import SecurityError
-
-KB = 1024
-MB = 1024 * 1024
-
-class AutoSaveObject(object):
-
- def __init__(self):
- self.cfg_path = None
- self.auto_save = True
- object
-
- def save_config(self, cfg_file = None):
- raise NotImplementedError()
-
- def __setattr__(self, name, value):
- """A very simple way of making sure all attribute changes are
- flushed to disk.
- """
- object.__setattr__(self, name, value)
- if name != 'auto_save' and getattr(self, 'auto_save', False):
- self.save_config()
-
-class XendVDI(AutoSaveObject):
- """Generic Xen API compatible VDI representation.
-
- @cvar SAVED_CFG: list of configuration attributes to save.
- @cvar SAVED_CFG_INT: list of configurations that should be ints.
- """
-
- SAVED_CFG = ['name_label',
- 'name_description',
- 'virtual_size',
- 'physical_utilisation',
- 'sharable',
- 'read_only',
- 'type']
-
- SAVED_CFG_INT = ['sector_size', 'virtual_size', 'physical_utilisation']
-
- def __init__(self, uuid, sr_uuid):
- self.uuid = uuid
- self.sr_uuid = sr_uuid
- self.name_label = ""
- self.name_description = ""
- self.virtual_size = 0
- self.physical_utilisation = 0
- self.sharable = False
- self.read_only = False
- self.type = "system"
- self.other_config = {}
-
- def getVBDs(self):
- from xen.xend import XendDomain
- vbd_refs = [d.get_vbds() for d in XendDomain.instance().list('all')]
- vbd_refs = reduce(lambda x, y: x + y, vbd_refs)
- vbds = []
- for vbd_ref in vbd_refs:
- vdi = XendDomain.instance().get_dev_property_by_uuid('vbd', vbd_ref, 'VDI')
- if vdi == self.uuid:
- vbds.append(vbd_ref)
- return vbds
-
- def load_config_dict(self, cfg):
- """Loads configuration into the object from a dict.
-
- @param cfg: configuration dict
- @type cfg: dict
- """
- self.auto_save = False
- for key in self.SAVED_CFG:
- if key in cfg:
- if key in self.SAVED_CFG_INT:
- setattr(self, key, int(cfg[key]))
- else:
- setattr(self, key, cfg[key])
- self.auto_save = True
-
- def load_config(self, cfg_path):
- """Loads configuration from an XMLRPC parameter format.
-
- @param cfg_path: configuration file path
- @type cfg_path: type
- @rtype: bool
- @return: Successful or not.
- """
- try:
- cfg, _ = loads(open(cfg_path).read())
- cfg = cfg[0]
- self.load_config_dict(cfg)
- self.cfg_path = cfg_path
- except IOError, e:
- return False
-
- return True
-
- def save_config(self, cfg_path = None):
- """Saves configuration at give path in XMLRPC parameter format.
-
- If cfg_path is not give, it defaults to the where the VDI
- configuration as loaded if it load_config was called.
-
- @keyword cfg_path: optional configuration file path
- @rtype: bool
- @return: Successful or not.
- """
- try:
- if not cfg_path and not self.cfg_path:
- return False
-
- if not cfg_path:
- cfg_path = self.cfg_path
-
- cfg = {}
- for key in self.SAVED_CFG:
- try:
- cfg[key] = getattr(self, key)
- except AttributeError:
- pass
- open(cfg_path, 'w').write(dumps((stringify(cfg),),
- allow_none = True))
- except IOError, e:
- return False
-
- return True
-
- def get_record(self, transient = True):
- return {'uuid': self.uuid,
- 'name_label': self.name_label,
- 'name_description': self.name_description,
- 'virtual_size': self.virtual_size,
- 'physical_utilisation': self.physical_utilisation,
- 'sharable': self.sharable,
- 'read_only': self.read_only,
- 'type': self.type,
- 'SR': self.sr_uuid,
- 'other_config': self.other_config,
- 'VBDs': self.getVBDs()}
-
- def get_location(self):
- raise NotImplementedError()
-
- def set_security_label(self, sec_lab, old_lab):
- image = self.get_location()
- rc = security.set_resource_label_xapi(image, sec_lab, old_lab)
- if rc != xsconstants.XSERR_SUCCESS:
- raise SecurityError(rc)
- return rc
-
- def get_security_label(self):
- image = self.get_location()
- return security.get_resource_label_xapi(image)
-
-
-class XendQCoWVDI(XendVDI):
- def __init__(self, uuid, sr_uuid, qcow_path, cfg_path, vsize, psize):
- XendVDI.__init__(self, uuid, sr_uuid)
- self.auto_save = False
- self.qcow_path = qcow_path
- self.cfg_path = cfg_path
- self.physical_utilisation = psize
- self.virtual_size = vsize
- self.auto_save = True
- self.other_config['location'] = 'tap:qcow:%s' % self.qcow_path
-
- def get_location(self):
- return self.other_config['location']
-
-class XendLocalVDI(XendVDI):
- def __init__(self, vdi_struct):
- vdi_uuid = vdi_struct['uuid']
- sr_uuid = vdi_struct['SR']
- XendVDI.__init__(self, vdi_uuid, sr_uuid)
-
- self.auto_save = False
- self.cfg_path = None
- self.name_label = vdi_struct.get('name_label','')
- self.name_description = vdi_struct.get('name_description', '')
- self.physical_utilisation = 0
- self.virtual_size = 0
- self.type = vdi_struct.get('type', '')
- self.sharable = vdi_struct.get('sharable', False)
- self.read_only = vdi_struct.get('read_only', False)
- self.other_config = vdi_struct.get('other_config', {})
-
- def get_location(self):
- return self.other_config['location']
diff --git a/tools/python/xen/xend/XendVMMetrics.py b/tools/python/xen/xend/XendVMMetrics.py
deleted file mode 100644
index 9577060..0000000
--- a/tools/python/xen/xend/XendVMMetrics.py
+++ /dev/null
@@ -1,146 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (c) 2006-2007 Xensource Inc.
-# Copyright (c) 2007 Tom Wilkie
-#============================================================================
-
-from xen.xend.XendLogging import log
-from xen.xend.XendBase import XendBase
-import xen.lowlevel.xc
-
-xc = xen.lowlevel.xc.xc()
-
-class XendVMMetrics(XendBase):
- """VM Metrics."""
-
- def getClass(self):
- return "VM_metrics"
-
- def getAttrRO(self):
- attrRO = ['memory_actual',
- 'VCPUs_number',
- 'VCPUs_utilisation',
- 'VCPUs_CPU',
- 'VCPUs_flags',
- 'VCPUs_params',
- 'state',
- 'start_time',
- 'last_updated']
- return XendBase.getAttrRO() + attrRO
-
- getClass = classmethod(getClass)
- getAttrRO = classmethod(getAttrRO)
-
- def __init__(self, uuid, xend_domain_instance):
- XendBase.__init__(self, uuid, {})
- self.xend_domain_instance = xend_domain_instance
-
- def get_memory_actual(self):
- domInfo = self.xend_domain_instance.getDomInfo()
- if domInfo:
- return domInfo["mem_kb"] * 1024
- else:
- return 0
-
- def get_VCPUs_number(self):
- domInfo = self.xend_domain_instance.getDomInfo()
- if domInfo:
- return domInfo["online_vcpus"]
- else:
- return 0
-
- def get_VCPUs_utilisation(self):
- return self.xend_domain_instance.get_vcpus_util()
-
- def get_VCPUs_CPU(self):
- domid = self.xend_domain_instance.getDomid()
- if domid is not None:
- vcpus_cpu = {}
- vcpus_max = self.xend_domain_instance.info['VCPUs_max']
- for i in range(0, vcpus_max):
- info = xc.vcpu_getinfo(domid, i)
- vcpus_cpu[i] = info['cpu']
- return vcpus_cpu
- else:
- return {}
-
- def get_VCPUs_flags(self):
- domid = self.xend_domain_instance.getDomid()
- if domid is not None:
- vcpus_flags = {}
- vcpus_max = self.xend_domain_instance.info['VCPUs_max']
- for i in range(0, vcpus_max):
- info = xc.vcpu_getinfo(domid, i)
- flags = []
- def set_flag(flag):
- if info[flag] == 1:
- flags.append(flag)
- set_flag('blocked')
- set_flag('online')
- set_flag('running')
- vcpus_flags[i] = flags
- return vcpus_flags
- else:
- return {}
-
- def get_state(self):
- try:
- domid = self.xend_domain_instance.getDomid()
- domlist = xc.domain_getinfo(domid, 1)
- if domlist and domid == domlist[0]['domid']:
- dominfo = domlist[0]
-
- states = []
- def addState(key):
- if dominfo[key] == 1:
- states.append(key)
-
- addState("running")
- addState("blocked")
- addState("paused")
- addState("dying")
- addState("crashed")
- addState("shutdown")
- return states
- except Exception, err:
- # ignore missing domain
- log.trace("domain_getinfo(%d) failed, ignoring: %s", domid, str(err))
- return []
-
- def get_VCPUs_params(self):
- domid = self.xend_domain_instance.getDomid()
- if domid is not None:
- params_live = {}
- vcpus_max = self.xend_domain_instance.info['VCPUs_max']
- for i in range(0, vcpus_max):
- info = xc.vcpu_getinfo(domid, i)
- params_live['cpumap%i' % i] = \
- ",".join(map(str, info['cpumap']))
-
- # FIXME: credit2??
- params_live.update(xc.sched_credit_domain_get(domid))
-
- return params_live
- else:
- return {}
-
- def get_start_time(self):
- import xen.xend.XendAPI as XendAPI
- return XendAPI.datetime(
- self.xend_domain_instance.info.get("start_time", 0))
-
- def get_last_updated(self):
- import xen.xend.XendAPI as XendAPI
- return XendAPI.now()
diff --git a/tools/python/xen/xend/XendVnet.py b/tools/python/xen/xend/XendVnet.py
deleted file mode 100644
index 8f5b6d7..0000000
--- a/tools/python/xen/xend/XendVnet.py
+++ /dev/null
@@ -1,181 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-"""Handler for vnet operations.
-"""
-
-from xen.util import Brctl
-from xen.xend import sxp
-from xen.xend.XendError import XendError
-from xen.xend.XendLogging import log
-from xen.xend.xenstore.xstransact import xstransact
-
-
-def vnet_cmd(cmd):
- out = None
- try:
- try:
- out = file("/proc/vnet/policy", "wb")
- sxp.show(cmd, out)
- except IOError, ex:
- raise XendError(str(ex))
- finally:
- if out: out.close()
-
-class XendVnetInfo:
-
- vifctl_ops = {'up': 'vif.add', 'down': 'vif.del'}
-
- def __init__(self, dbpath, config=None):
- if config:
- self.id = str(sxp.child_value(config, 'id'))
- self.dbid = self.id.replace(':', '-')
- self.dbpath = dbpath + '/' + self.dbid
- self.config = config
- else:
- self.dbpath = dbpath
- self.importFromDB()
-
- self.bridge = sxp.child_value(self.config, 'bridge')
- if not self.bridge:
- self.bridge = "vnet%s" % self.id
- self.vnetif = sxp.child_value(self.config, 'vnetif')
- if not self.vnetif:
- self.vnetif = "vnif%s" % self.id
-
-
- def exportToDB(self, save=False, sync=False):
- to_store = {
- 'id' : self.id,
- 'dbid' : self.dbid,
- 'config' : sxp.to_string(self.config)
- }
- xstransact.Write(self.dbpath, to_store)
-
-
- def importFromDB(self):
- (self.id, self.dbid, c) = xstransact.Gather(self.dbpath,
- ('id', str),
- ('dbid', str),
- ('config', str))
- self.config = sxp.from_string(c)
-
-
- def sxpr(self):
- return self.config
-
- def configure(self):
- log.info("Configuring vnet %s", self.id)
- val = vnet_cmd(['vnet.add'] + sxp.children(self.config))
- Brctl.bridge_create(self.bridge)
- Brctl.vif_bridge_add({'bridge': self.bridge, 'vif': self.vnetif})
- return val
-
- def delete(self):
- log.info("Deleting vnet %s", self.id)
- Brctl.vif_bridge_rem({'bridge': self.bridge, 'vif': self.vnetif})
- Brctl.bridge_del(self.bridge)
- val = vnet_cmd(['vnet.del', self.id])
- xstransact.Remove(self.dbpath)
- return val
-
- def vifctl(self, op, vif, vmac):
- try:
- fn = self.vifctl_ops[op]
- return vnet_cmd([fn, ['vnet', self.id], ['vif', vif], ['vmac', vmac]])
- except XendError:
- log.warning("vifctl failed: op=%s vif=%s mac=%s", op, vif, vmac)
-
-class XendVnet:
- """Index of all vnets. Singleton.
- """
-
- dbpath = "/vnet"
-
- def __init__(self):
- # Table of vnet info indexed by vnet id.
- self.vnet = {}
- listing = xstransact.List(self.dbpath)
- for entry in listing:
- try:
- info = XendVnetInfo(self.dbpath + '/' + entry)
- self.vnet[info.id] = info
- info.configure()
- except XendError, ex:
- log.warning("Failed to configure vnet %s: %s", str(info.id), str(ex))
- except Exception, ex:
- log.exception("Vnet error")
- xstransact.Remove(self.dbpath + '/' + entry)
-
- def vnet_of_bridge(self, bridge):
- """Get the vnet for a bridge (if any).
-
- @param bridge: bridge name
- @return vnet or None
- """
- for v in self.vnet.values():
- if v.bridge == bridge:
- return v
- else:
- return None
-
- def vnet_ls(self):
- """List all vnet ids.
- """
- return self.vnet.keys()
-
- def vnets(self):
- """List all vnets.
- """
- return self.vnet.values()
-
- def vnet_get(self, id):
- """Get a vnet.
-
- @param id vnet id
- """
- id = str(id)
- return self.vnet.get(id)
-
- def vnet_create(self, config):
- """Create a vnet.
-
- @param config: config
- """
- info = XendVnetInfo(self.dbpath, config=config)
- self.vnet[info.id] = info
- info.exportToDB()
- info.configure()
-
- def vnet_delete(self, id):
- """Delete a vnet.
-
- @param id: vnet id
- """
- info = self.vnet_get(id)
- if info:
- del self.vnet[id]
- info.delete()
-
-def instance():
- global inst
- try:
- inst
- except:
- inst = XendVnet()
- return inst
diff --git a/tools/python/xen/xend/XendXSPolicy.py b/tools/python/xen/xend/XendXSPolicy.py
deleted file mode 100644
index dd508d9..0000000
--- a/tools/python/xen/xend/XendXSPolicy.py
+++ /dev/null
@@ -1,305 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (c) 2007 IBM Corporation
-# Copyright (c) 2006 Xensource
-#============================================================================
-
-import base64
-import logging
-from xen.xend import XendDomain
-from xen.xend.XendBase import XendBase
-from xen.xend.XendError import *
-from xen.xend.XendAPIConstants import *
-from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
-from xen.util import xsconstants
-import xen.util.xsm.xsm as security
-
-log = logging.getLogger("xend.XendXSPolicy")
-log.setLevel(logging.TRACE)
-
-
-class XendXSPolicy(XendBase):
- """ Administration class for an XSPolicy. """
-
- def getClass(self):
- return "XSPolicy"
-
- def getMethods(self):
- methods = ['activate_xspolicy']
- return XendBase.getMethods() + methods
-
- def getFuncs(self):
- funcs = [ 'get_xstype',
- 'set_xspolicy',
- 'reset_xspolicy',
- 'get_xspolicy',
- 'rm_xsbootpolicy',
- 'get_resource_label',
- 'set_resource_label',
- 'get_labeled_resources',
- 'can_run',
- 'getenforce',
- 'setenforce']
- return XendBase.getFuncs() + funcs
-
- getClass = classmethod(getClass)
- getMethods = classmethod(getMethods)
- getFuncs = classmethod(getFuncs)
-
- def __init__(self, xspol, record, uuid):
- """ xspol = actual XSPolicy object """
- self.xspol = xspol
- XendBase.__init__(self, uuid, record)
-
- def get_record(self):
- xspol_record = {
- 'uuid' : self.get_uuid(),
- 'flags' : XSPolicyAdminInstance().get_policy_flags(self.xspol),
- 'repr' : self.xspol.toxml(),
- 'type' : self.xspol.get_type(),
- }
- return xspol_record
-
- def get_xstype(self):
- return XSPolicyAdminInstance().isXSEnabled()
-
- def set_xspolicy(self, xstype, policy, flags, overwrite):
- ref = ""
- xstype = int(xstype)
- flags = int(flags)
-
- polstate = { 'xs_ref': "", 'repr' : "", 'type' : 0,
- 'flags' : 0 , 'version': 0 , 'errors' : "", 'xserr' : 0 }
- if xstype == xsconstants.XS_POLICY_ACM:
- poladmin = XSPolicyAdminInstance()
- try:
- (xspol, rc, errors) = poladmin.add_acmpolicy_to_system(
- policy, flags,
- overwrite)
- if rc != 0:
- polstate.update( { 'xserr' : rc,
- 'errors': base64.b64encode(errors) } )
- else:
- ref = xspol.get_ref()
- polstate = {
- 'xs_ref' : ref,
- 'flags' : poladmin.get_policy_flags(xspol),
- 'type' : xstype,
- 'repr' : "",
- 'version': xspol.get_version(),
- 'errors' : base64.b64encode(errors),
- 'xserr' : rc,
- }
- except Exception, e:
- raise
- elif xstype == xsconstants.XS_POLICY_FLASK:
- rc, errors = security.set_policy(xstype, policy);
- if rc != 0:
- polstate.update( { 'xserr' : -xsconstants.XSERR_POLICY_LOAD_FAILED,
- 'errors': errors } )
- else:
- polstate.update( { 'xserr' : xsconstants.XSERR_SUCCESS,
- 'errors': errors } )
- else:
- raise SecurityError(-xsconstants.XSERR_POLICY_TYPE_UNSUPPORTED)
- return polstate
-
-
- def reset_xspolicy(self, xstype):
- xstype = int(xstype)
- polstate = { 'xs_ref': "", 'repr' : "", 'type' : 0,
- 'flags' : 0 , 'version': 0 , 'errors' : "", 'xserr' : 0 }
- if xstype == xsconstants.XS_POLICY_ACM:
- poladmin = XSPolicyAdminInstance()
- try:
- (xspol, rc, errors) = poladmin.reset_acmpolicy()
- if rc != 0:
- polstate.update( { 'xserr' : rc,
- 'errors': base64.b64encode(errors) } )
- else:
- ref = xspol.get_ref()
- polstate = {
- 'xs_ref' : ref,
- 'flags' : poladmin.get_policy_flags(xspol),
- 'type' : xstype,
- 'repr' : "",
- 'version': xspol.get_version(),
- 'errors' : base64.b64encode(errors),
- 'xserr' : rc,
- }
- except Exception, e:
- raise
- else:
- raise SecurityError(-xsconstants.XSERR_POLICY_TYPE_UNSUPPORTED)
- return polstate
-
-
- def activate_xspolicy(self, flags):
- flags = int(flags)
- rc = -xsconstants.XSERR_GENERAL_FAILURE
- poladmin = XSPolicyAdminInstance()
- try:
- rc = poladmin.activate_xspolicy(self.xspol, flags)
- except Exception, e:
- log.info("Activate_policy: %s" % str(e))
- if rc != flags:
- raise SecurityError(rc)
- return flags
-
- def get_xspolicy(self):
- polstate = { 'xs_ref' : "",
- 'repr' : "",
- 'type' : 0,
- 'flags' : 0,
- 'version': "",
- 'errors' : "",
- 'xserr' : 0 }
- poladmin = XSPolicyAdminInstance()
- refs = poladmin.get_policies_refs()
- # Will return one or no policy
- if refs and len(refs) > 0:
- ref = refs[0]
- xspol = XSPolicyAdminInstance().policy_from_ref(ref)
- if xspol:
- polstate = {
- 'xs_ref' : ref,
- 'repr' : xspol.toxml(),
- 'type' : xspol.get_type(),
- 'flags' : poladmin.get_policy_flags(xspol),
- 'version': xspol.get_version(),
- 'errors' : "",
- 'xserr' : 0,
- }
- return polstate
-
- def rm_xsbootpolicy(self):
- rc = XSPolicyAdminInstance().rm_bootpolicy()
- if rc != xsconstants.XSERR_SUCCESS:
- raise SecurityError(rc)
-
- def get_labeled_resources(self):
- return security.get_labeled_resources_xapi()
-
- def set_resource_label(self, resource, sec_lab, old_lab):
- rc = security.set_resource_label_xapi(resource, sec_lab, old_lab)
- if rc != xsconstants.XSERR_SUCCESS:
- raise SecurityError(rc)
-
- def get_resource_label(self, resource):
- res = security.get_resource_label_xapi(resource)
- return res
-
- def can_run(self, sec_label):
- irc = security.validate_label_xapi(sec_label, 'dom')
- if irc != xsconstants.XSERR_SUCCESS:
- raise SecurityError(irc)
- return security.check_can_run(sec_label)
-
- def getenforce(self):
- return security.getenforce()
-
- def setenforce(self, mode):
- return security.setenforce(mode)
-
- get_xstype = classmethod(get_xstype)
- get_xspolicy = classmethod(get_xspolicy)
- set_xspolicy = classmethod(set_xspolicy)
- reset_xspolicy = classmethod(reset_xspolicy)
- rm_xsbootpolicy = classmethod(rm_xsbootpolicy)
- set_resource_label = classmethod(set_resource_label)
- get_resource_label = classmethod(get_resource_label)
- get_labeled_resources = classmethod(get_labeled_resources)
- can_run = classmethod(can_run)
- getenforce = classmethod(getenforce)
- setenforce = classmethod(setenforce)
-
-
-class XendACMPolicy(XendXSPolicy):
- """ Administration class of an ACMPolicy """
-
- def getClass(self):
- return "ACMPolicy"
-
- def getAttrRO(self):
- attrRO = [ 'xml',
- 'map',
- 'binary',
- 'header' ]
- return XendXSPolicy.getAttrRO() + attrRO
-
- def getFuncs(self):
- funcs = [ 'get_enforced_binary', 'get_VM_ssidref' ]
- return XendBase.getFuncs() + funcs
-
- getClass = classmethod(getClass)
- getAttrRO = classmethod(getAttrRO)
- getFuncs = classmethod(getFuncs)
-
- def __init__(self, acmpol, record, uuid):
- """ acmpol = actual ACMPolicy object """
- self.acmpol = acmpol
- XendXSPolicy.__init__(self, acmpol, record, uuid)
-
- def get_record(self):
- polstate = {
- 'uuid' : self.get_uuid(),
- 'flags' : XSPolicyAdminInstance().get_policy_flags(self.acmpol),
- 'repr' : self.acmpol.toxml(),
- 'type' : self.acmpol.get_type(),
- }
- return polstate
-
- def get_header(self):
- header = {
- 'policyname' : "", 'policyurl' : "", 'reference' : "",
- 'date' : "", 'namespaceurl' : "", 'version' : "",
- }
- try:
- header = self.acmpol.get_header_fields_map()
- except:
- pass
- return header
-
- def get_xml(self):
- return self.acmpol.toxml()
-
- def get_map(self):
- return self.acmpol.get_map()
-
- def get_binary(self):
- polbin = self.acmpol.get_bin()
- return base64.b64encode(polbin)
-
- def get_VM_ssidref(self, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- if not dom:
- raise InvalidHandleError("VM", vm_ref)
- if dom._stateGet() not in [ XEN_API_VM_POWER_STATE_RUNNING, \
- XEN_API_VM_POWER_STATE_PAUSED ]:
- raise VMBadState("Domain is not running or paused.")
- ssid = security.get_ssid(dom.getDomid())
- if not ssid:
- raise SecurityError(-xsconstants.XSERR_GENERAL_FAILURE)
- return ssid[3]
-
- def get_enforced_binary(self):
- polbin = XSPolicyAdminInstance(). \
- get_enforced_binary(xsconstants.XS_POLICY_ACM)
- if polbin:
- return base64.b64encode(polbin)
- return None
-
- get_enforced_binary = classmethod(get_enforced_binary)
- get_VM_ssidref = classmethod(get_VM_ssidref)
diff --git a/tools/python/xen/xend/XendXSPolicyAdmin.py b/tools/python/xen/xend/XendXSPolicyAdmin.py
deleted file mode 100644
index 8df8d0d..0000000
--- a/tools/python/xen/xend/XendXSPolicyAdmin.py
+++ /dev/null
@@ -1,386 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006,2007 International Business Machines Corp.
-# Author: Stefan Berger <stefanb at us.ibm.com>
-#============================================================================
-import os
-import shutil
-
-from xml.dom import minidom, Node
-
-from xen.xend.XendLogging import log
-from xen.xend import uuid
-from xen.util import xsconstants, bootloader
-import xen.util.xsm.acm.acm as security
-from xen.util.xspolicy import XSPolicy
-from xen.util.acmpolicy import ACMPolicy, initialize
-from xen.xend.XendError import SecurityError
-
-
-class XSPolicyAdmin:
- """ The class that handles the managed policies in the system.
- Handles adding and removing managed policies. All managed
- policies are handled using a reference (UUID) which is
- assigned to the policy by this class.
- """
-
- def __init__(self, maxpolicies):
- """ Create a management class for managing the system's
- policies.
-
- @param maxpolicies: The max. number of policies allowed
- on the system (currently '1')
- """
- self.maxpolicies = maxpolicies
- self.policies = {}
- self.xsobjs = {}
- bootloader.init()
-
- if security.on() == xsconstants.XS_POLICY_ACM:
- self.__acm_init()
-
- def __acm_init(self):
- act_pol_name = self.get_hv_loaded_policy_name()
- initialize()
-
- ref = uuid.createString()
- try:
- self.xsobjs[ref] = ACMPolicy(name=act_pol_name, ref=ref)
- self.policies[ref] = (act_pol_name, xsconstants.ACM_POLICY_ID)
- self.xsobjs[ref].validate_enforced_policy_hash()
- except Exception, e:
- log.error("Could not find XML representation of policy '%s': "
- "%s" % (act_pol_name,e))
- rc, errors, acmpol_def = ACMPolicy.force_default_policy(ref)
- if rc == xsconstants.XSERR_SUCCESS:
- self.xsobjs[ref] = acmpol_def
- self.policies[ref] = (acmpol_def.get_name(),
- xsconstants.ACM_POLICY_ID)
- log.info("Switched to DEFAULT policy.")
-
- log.debug("XSPolicyAdmin: Known policies: %s" % self.policies)
-
-
- def isXSEnabled(self):
- """ Check whether 'security' is enabled on this system.
- """
- rc = 0
- if security.on() == xsconstants.XS_POLICY_ACM:
- rc |= xsconstants.XS_POLICY_ACM
- else:
- rc |= xsconstants.XS_POLICY_FLASK
- return rc
-
- def add_acmpolicy_to_system(self, xmltext, flags, overwrite):
- """ Add an ACM policy's xml representation to the system. The
- policy will automatically be compiled
- flags:
- XS_INST_BOOT : make policy the one to boot the system with
- by default; if there's a policy already installed,
- refuse to install this policy unless its one with
- the same name
- XS_INST_LOAD : load the policy immediately; if this does not work
- refuse to install this policy
- overwrite:
- If any policy is installed and this is False, refuse to install
- this policy
- If flags is True, then any existing policy will be removed from
- the system and the new one will be installed
- """
- from xen.xend import XendDomain
- domains = XendDomain.instance()
- try:
- domains.domains_lock.acquire()
- return self.__add_acmpolicy_to_system(xmltext, flags, overwrite)
- finally:
- domains.domains_lock.release()
-
- def __add_acmpolicy_to_system(self, xmltext, flags, overwrite):
- errors = ""
- if security.on() != xsconstants.XS_POLICY_ACM:
- raise SecurityError(-xsconstants.XSERR_POLICY_TYPE_UNSUPPORTED)
- loadedpol = self.get_loaded_policy()
- if loadedpol:
- # This is meant as an update to a currently loaded policy
- if flags & xsconstants.XS_INST_LOAD == 0:
- raise SecurityError(-xsconstants.XSERR_POLICY_LOADED)
-
- # Remember old flags, so they can be restored if update fails
- old_flags = self.get_policy_flags(loadedpol)
-
- # Remove policy from bootloader in case of new name of policy
- self.rm_bootpolicy()
-
- rc, errors = loadedpol.update(xmltext)
- if rc == 0:
- irc = self.activate_xspolicy(loadedpol, flags)
- # policy is loaded; if setting the boot flag fails it's ok.
- else:
- old_flags = old_flags & xsconstants.XS_INST_BOOT
- log.info("OLD FLAGS TO RESTORE: %s" % str(old_flags))
- if old_flags != 0:
- self.activate_xspolicy(loadedpol, xsconstants.XS_INST_BOOT)
-
- return (loadedpol, rc, errors)
-
- try:
- dom = minidom.parseString(xmltext.encode("utf-8"))
- except:
- raise SecurityError(-xsconstants.XSERR_BAD_XML)
-
- ref = uuid.createString()
-
- acmpol = ACMPolicy(dom=dom, ref=ref)
-
- #First some basic tests that do not modify anything:
-
- if flags & xsconstants.XS_INST_BOOT and not overwrite:
- filename = acmpol.get_filename(".bin","",dotted=True)
- if bootloader.get_default_policy != None and \
- not bootloader.loads_default_policy(filename):
- raise SecurityError(-xsconstants.XSERR_BOOTPOLICY_INSTALLED)
-
- if not overwrite and len(self.policies) >= self.maxpolicies:
- raise SecurityError(-xsconstants.XSERR_BOOTPOLICY_INSTALLED)
-
- if overwrite:
- #This should only give one key since only one policy is
- #allowed.
- keys = self.policies.keys()
- for k in keys:
- self.rm_bootpolicy()
- rc = self.rm_policy_from_system(k, force=overwrite)
- if rc != xsconstants.XSERR_SUCCESS:
- raise SecurityError(rc)
-
- rc = acmpol.compile()
- if rc != 0:
- raise SecurityError(rc)
-
- if flags & xsconstants.XS_INST_LOAD:
- rc = acmpol.loadintohv()
- if rc != 0:
- raise SecurityError(rc)
-
- if flags & xsconstants.XS_INST_BOOT:
- rc = self.make_boot_policy(acmpol)
- if rc != 0:
- # If it cannot be installed due to unsupported
- # bootloader, let it be ok.
- pass
-
- if dom:
- new_entry = { ref : tuple([acmpol.get_name(),
- xsconstants.ACM_POLICY_ID]) }
- self.policies.update(new_entry)
- self.xsobjs[ref] = acmpol
- return (acmpol, xsconstants.XSERR_SUCCESS, errors)
-
-
- def reset_acmpolicy(self):
- """
- Attempt to reset the system's policy by udating it with
- the DEFAULT policy.
- """
- from xen.xend import XendDomain
- domains = XendDomain.instance()
- try:
- domains.domains_lock.acquire()
- xml = ACMPolicy.get_reset_policy_xml()
- flags = xsconstants.XS_INST_BOOT | xsconstants.XS_INST_LOAD
- return self.__add_acmpolicy_to_system(xml, flags, True)
- finally:
- domains.domains_lock.release()
-
-
- def make_boot_policy(self, acmpol):
- if acmpol.is_default_policy():
- return xsconstants.XSERR_SUCCESS
- rc = acmpol.copy_policy_file(".bin","/boot")
- if rc != xsconstants.XSERR_SUCCESS:
- return rc
-
- try:
- filename = acmpol.get_filename(".bin","",dotted=True)
- if bootloader.set_default_boot_policy(filename) != True:
- return xsconstants.XSERR_BOOTPOLICY_INSTALL_ERROR
- except:
- return xsconstants.XSERR_FILE_ERROR
- return xsconstants.XSERR_SUCCESS
-
- def activate_xspolicy(self, xspol, flags):
- from xen.xend import XendDomain
- domains = XendDomain.instance()
- try:
- domains.domains_lock.acquire()
- return self.__activate_xspolicy(xspol, flags)
- finally:
- domains.domains_lock.release()
-
- def __activate_xspolicy(self, xspol, flags):
- rc = xsconstants.XSERR_SUCCESS
- if flags & xsconstants.XS_INST_LOAD:
- rc = xspol.loadintohv()
- if rc == xsconstants.XSERR_SUCCESS and \
- flags & xsconstants.XS_INST_BOOT:
- rc = self.make_boot_policy(xspol)
- if rc == xsconstants.XSERR_SUCCESS:
- rc = flags
- return rc
-
- def rm_policy_from_system(self, ref, force=False):
- if self.policies.has_key(ref):
- acmpol = self.xsobjs[ref]
- rc = acmpol.destroy()
- if rc == xsconstants.XSERR_SUCCESS or force:
- del self.policies[ref]
- del self.xsobjs[ref]
- rc = xsconstants.XSERR_SUCCESS
- return rc
-
- def rm_bootpolicy(self):
- """ Remove any (ACM) boot policy from the grub configuration file
- """
- rc = 0
- title = bootloader.get_default_title()
- if title != None:
- polnames = []
- for (k, v) in self.xsobjs.items():
- polnames.append(v.get_filename(".bin","",dotted=True))
- bootloader.rm_policy_from_boottitle(title, polnames)
- else:
- rc = -xsconstants.XSERR_NO_DEFAULT_BOOT_TITLE
- return rc
-
- def get_policy_flags(self, acmpol):
- """ Get the currently active flags of a policy, i.e., whether the
- system is using this policy as its boot policy for the default
- boot title.
- """
- flags = 0
-
- filename = acmpol.get_filename(".bin","", dotted=True)
- if bootloader.loads_default_policy(filename) or \
- acmpol.is_default_policy():
- flags |= xsconstants.XS_INST_BOOT
-
- if acmpol.isloaded():
- flags |= xsconstants.XS_INST_LOAD
- return flags
-
- def get_policies(self):
- """ Get all managed policies. """
- return self.xsobjs.values()
-
- def get_policies_refs(self):
- """ Get all managed policies' references. """
- return self.xsobjs.keys()
-
- def has_ref(self, ref):
- """ Check whether there is a policy with the given reference """
- return self.xsobjs.has_key(ref)
-
- def policy_from_ref(self, ref):
- """ Get the policy's object given its reference """
- if ref in self.xsobjs.keys():
- return self.xsobjs[ref]
- return None
-
- def ref_from_polname(self, polname):
- """ Get the reference of the policy given its name """
- ref = None
- for (k, v) in self.xsobjs.items():
- if v.get_name() == polname:
- ref = k
- break
- return ref
-
- def lock_policy(self, ref):
- """ get exclusive access to a policy """
- self.xsobjs[ref].grab_lock()
-
- def unlock_policy(self, ref):
- """ release exclusive access to a policy """
- self.xsobjs[ref].unlock()
-
- def get_loaded_policy(self):
- for pol in self.xsobjs.values():
- if pol.isloaded():
- return pol
- return None
-
- def get_hv_loaded_policy_name(self):
- return security.get_active_policy_name()
-
- def get_policy_by_name(self, name):
- for pol in self.xsobjs.values():
- if pol.get_name() == name:
- return pol
- return None
-
- def get_domain0_bootlabel(self):
- """ Get the domain0 bootlabel from the default boot title """
- title = ""
- def_title = bootloader.get_default_title()
- line = bootloader.get_kernel_val(def_title, "ssidref")
- if line:
- parms = line.split(":",1)
- if len(parms) > 1:
- title = parms[1]
- return title
-
- def set_domain0_bootlabel(self, xspol, label):
- """ Set the domain-0 bootlabel under the given policy. If the
- current policy is the default policy, it will remove it. """
- rm_entry = (xspol.get_name() == "DEFAULT")
- return xspol.set_vm_bootlabel(label, rm_entry)
-
- def rm_domain0_bootlabel(self):
- """ Remove the domain-0 bootlabel from the default boot title """
- def_title = bootloader.get_default_title()
- return bootloader.set_kernel_attval(def_title, "ssidref", None)
-
- def ssidref_to_vmlabel(self, ssidref):
- """ Given an ssidref, return the vmlabel under the current policy """
- vmlabel = ""
- pol = self.get_loaded_policy()
- if pol:
- vmlabel = pol.policy_get_domain_label_by_ssidref_formatted(ssidref)
- return vmlabel
-
- def get_stes_of_vmlabel(self, vmlabel_xapi):
- """ Get the list of STEs given a VM label in XenAPI format """
- stes = []
- loadedpol = self.get_loaded_policy()
- if loadedpol:
- tmp = vmlabel_xapi.split(":")
- if len(tmp) != 3:
- return []
- stes = loadedpol.policy_get_stes_of_vmlabel(tmp[2])
- return stes
-
- def get_enforced_binary(self, xstype):
- res = None
- if xstype == xsconstants.XS_POLICY_ACM:
- res = ACMPolicy.get_enforced_binary()
- return res
-
-poladmin = None
-
-def XSPolicyAdminInstance(maxpolicies=1):
- global poladmin
- if poladmin == None:
- poladmin = XSPolicyAdmin(maxpolicies)
- return poladmin
diff --git a/tools/python/xen/xend/__init__.py b/tools/python/xen/xend/__init__.py
deleted file mode 100644
index 8d1c8b6..0000000
--- a/tools/python/xen/xend/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tools/python/xen/xend/arch.py b/tools/python/xen/xend/arch.py
deleted file mode 100644
index 6d789d9..0000000
--- a/tools/python/xen/xend/arch.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-# Copyright (C) IBM Corp. 2006
-#
-# Authors: Hollis Blanchard <hollisb at us.ibm.com>
-
-import os
-
-_types = {
- "i386": "x86",
- "i486": "x86",
- "i586": "x86",
- "i686": "x86",
- "x86_64": "x86",
- "amd64": "x86",
- "i86pc": "x86",
- "ia64": "ia64",
-}
-type = _types.get(os.uname()[4], "unknown")
diff --git a/tools/python/xen/xend/balloon.py b/tools/python/xen/xend/balloon.py
deleted file mode 100644
index 89965d7..0000000
--- a/tools/python/xen/xend/balloon.py
+++ /dev/null
@@ -1,244 +0,0 @@
-#===========================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-
-import time
-
-import xen.lowlevel.xc
-
-import XendDomain
-import XendOptions
-import MemoryPool
-from XendLogging import log
-from XendError import VmError
-import osdep
-from xen.xend.XendConstants import *
-
-RETRY_LIMIT = 20
-RETRY_LIMIT_INCR = 5
-##
-# The time to sleep between retries grows linearly, using this value (in
-# seconds). When the system is lightly loaded, memory should be scrubbed and
-# returned to the system very quickly, whereas when it is loaded, the system
-# needs idle time to get the scrubbing done. This linear growth accommodates
-# such requirements.
-SLEEP_TIME_GROWTH = 0.1
-
-# A mapping between easy-to-remember labels and the more verbose
-# label actually shown in the PROC_XEN_BALLOON file.
-#labels = { 'current' : 'Current allocation',
-# 'target' : 'Requested target',
-# 'low-balloon' : 'Low-mem balloon',
-# 'high-balloon' : 'High-mem balloon',
-# 'limit' : 'Xen hard limit' }
-
-def _get_proc_balloon(label):
- """Returns the value for the named label. Returns None if the label was
- not found or the value was non-numeric."""
-
- return osdep.lookup_balloon_stat(label)
-
-def get_dom0_current_alloc():
- """Returns the current memory allocation (in KiB) of dom0."""
-
- kb = _get_proc_balloon('current')
- if kb == None:
- raise VmError('Failed to query current memory allocation of dom0.')
- return kb
-
-def get_dom0_target_alloc():
- """Returns the target memory allocation (in KiB) of dom0."""
-
- kb = _get_proc_balloon('target')
- if kb == None:
- raise VmError('Failed to query target memory allocation of dom0.')
- return kb
-
-def free(need_mem, dominfo):
- """Balloon out memory from the privileged domain so that there is the
- specified required amount (in KiB) free.
- """
-
- # We check whether there is enough free memory, and if not, instruct dom0
- # to balloon out to free some up. Memory freed by a destroyed domain may
- # not appear in the free_memory field immediately, because it needs to be
- # scrubbed before it can be released to the free list, which is done
- # asynchronously by Xen; ballooning is asynchronous also. Such memory
- # does, however, need to be accounted for when calculating how much dom0
- # needs to balloon. No matter where we expect the free memory to come
- # from, we need to wait for it to become available.
- #
- # We are not allowed to balloon below dom0_min_mem, or if dom0_ballooning
- # is False, we cannot balloon at all. Memory can still become available
- # through a rebooting domain, however.
- #
- # Eventually, we time out (presumably because there really isn't enough
- # free memory).
- #
- # We don't want to set the memory target (triggering a watch) when that
- # has already been done, but we do want to respond to changing memory
- # usage, so we recheck the required alloc each time around the loop, but
- # track the last used value so that we don't trigger too many watches.
-
- xoptions = XendOptions.instance()
- dom0 = XendDomain.instance().privilegedDomain()
- xc = xen.lowlevel.xc.xc()
- memory_pool = MemoryPool.instance()
- try:
- dom0_min_mem = xoptions.get_dom0_min_mem() * 1024
- dom0_ballooning = xoptions.get_enable_dom0_ballooning()
- guest_size = 0
- hvm = dominfo.info.is_hvm()
- if memory_pool.is_enabled() and dominfo.domid:
- if not hvm :
- if need_mem <= 4 * 1024:
- guest_size = 32
- else:
- guest_size = dominfo.image.getBitSize()
- if guest_size == 32:
- dom0_ballooning = 0
- else: #no ballooning as memory pool enabled
- dom0_ballooning = xoptions.get_enable_dom0_ballooning()
- dom0_alloc = get_dom0_current_alloc()
-
- retries = 0
- sleep_time = SLEEP_TIME_GROWTH
- new_alloc = 0
- last_new_alloc = None
- last_free = None
- rlimit = RETRY_LIMIT
- mem_need_balloon = 0
- left_memory_pool = 0
- mem_target = 0
- untouched_memory_pool = 0
- real_need_mem = need_mem
-
- # stop tmem from absorbing any more memory (must THAW when done!)
- xc.tmem_control(0,TMEMC_FREEZE,-1, 0, 0, 0, "")
-
- # If unreasonable memory size is required, we give up waiting
- # for ballooning or scrubbing, as if had retried.
- physinfo = xc.physinfo()
- free_mem = physinfo['free_memory']
- scrub_mem = physinfo['scrub_memory']
- total_mem = physinfo['total_memory']
- if memory_pool.is_enabled() and dominfo.domid:
- if guest_size != 32 or hvm:
- if need_mem > 4 * 1024:
- dominfo.alloc_mem = need_mem
- left_memory_pool = memory_pool.get_left_memory()
- if need_mem > left_memory_pool:
- dominfo.alloc_mem = 0
- raise VmError(('Not enough free memory'
- ' so I cannot release any more. '
- 'I need %d KiB but only have %d in the pool.') %
- (need_mem, memory_pool.get_left_memory()))
- else:
- untouched_memory_pool = memory_pool.get_untouched_memory()
- if (left_memory_pool - untouched_memory_pool) > need_mem:
- dom0_ballooning = 0
- else:
- mem_need_balloon = need_mem - left_memory_pool + untouched_memory_pool
- need_mem = free_mem + scrub_mem + mem_need_balloon
-
- if dom0_ballooning:
- max_free_mem = total_mem - dom0_min_mem
- else:
- max_free_mem = total_mem - dom0_alloc
- if need_mem >= max_free_mem:
- retries = rlimit
-
- freeable_mem = free_mem + scrub_mem
- if freeable_mem < need_mem and need_mem < max_free_mem:
- # flush memory from tmem to scrub_mem and reobtain physinfo
- need_tmem_kb = need_mem - freeable_mem
- tmem_kb = xc.tmem_control(0,TMEMC_FLUSH,-1, need_tmem_kb, 0, 0, "")
- log.debug("Balloon: tmem relinquished %d KiB of %d KiB requested.",
- tmem_kb, need_tmem_kb)
- physinfo = xc.physinfo()
- free_mem = physinfo['free_memory']
- scrub_mem = physinfo['scrub_memory']
-
- while retries < rlimit:
- physinfo = xc.physinfo()
- free_mem = physinfo['free_memory']
- scrub_mem = physinfo['scrub_memory']
- if free_mem >= need_mem:
- if (guest_size != 32 or hvm) and dominfo.domid:
- memory_pool.decrease_untouched_memory(mem_need_balloon)
- memory_pool.decrease_memory(real_need_mem)
- else:
- log.debug("Balloon: %d KiB free; need %d; done.",
- free_mem, need_mem)
- return
-
- if retries == 0:
- rlimit += ((need_mem - free_mem)/1024/1024) * RETRY_LIMIT_INCR
- log.debug("Balloon: %d KiB free; %d to scrub; need %d; retries: %d.",
- free_mem, scrub_mem, need_mem, rlimit)
-
- if dom0_ballooning:
- dom0_alloc = get_dom0_current_alloc()
- new_alloc = dom0_alloc - (need_mem - free_mem - scrub_mem)
- if free_mem + scrub_mem >= need_mem:
- if last_new_alloc == None:
- log.debug("Balloon: waiting on scrubbing")
- last_new_alloc = dom0_alloc
- else:
- if (new_alloc >= dom0_min_mem and
- new_alloc != last_new_alloc):
- new_alloc_mb = new_alloc / 1024 # Round down
- log.debug("Balloon: setting dom0 target to %d MiB.",
- new_alloc_mb)
- dom0.setMemoryTarget(new_alloc_mb)
- last_new_alloc = new_alloc
- # Continue to retry, waiting for ballooning or scrubbing.
-
- time.sleep(sleep_time)
- if retries < 2 * RETRY_LIMIT:
- sleep_time += SLEEP_TIME_GROWTH
- if last_free != None and last_free >= free_mem + scrub_mem:
- retries += 1
- last_free = free_mem + scrub_mem
-
- # Not enough memory; diagnose the problem.
- if not dom0_ballooning:
- dominfo.alloc_mem = 0
- raise VmError(('Not enough free memory and enable-dom0-ballooning '
- 'is False, so I cannot release any more. '
- 'I need %d KiB but only have %d.') %
- (need_mem, free_mem))
- elif new_alloc < dom0_min_mem:
- dominfo.alloc_mem = 0
- raise VmError(
- ('I need %d KiB, but dom0_min_mem is %d and shrinking to '
- '%d KiB would leave only %d KiB free.') %
- (need_mem, dom0_min_mem, dom0_min_mem,
- free_mem + scrub_mem + dom0_alloc - dom0_min_mem))
- else:
- dom0_start_alloc_mb = get_dom0_current_alloc() / 1024
- dom0.setMemoryTarget(dom0_start_alloc_mb)
- dominfo.alloc_mem = 0
- raise VmError(
- ('Not enough memory is available, and dom0 cannot'
- ' be shrunk any further'))
-
- finally:
- # allow tmem to accept pages again
- xc.tmem_control(0,TMEMC_THAW,-1, 0, 0, 0, "")
- del xc
diff --git a/tools/python/xen/xend/encode.py b/tools/python/xen/xend/encode.py
deleted file mode 100644
index f47c18a..0000000
--- a/tools/python/xen/xend/encode.py
+++ /dev/null
@@ -1,180 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
-
-"""Encoding for arguments to HTTP calls.
- Uses the url-encoding with MIME type 'application/x-www-form-urlencoded'
- if the data does not include files. Otherwise it uses the encoding with
- MIME type 'multipart/form-data'. See the HTML4 spec for details.
-
- """
-import sys
-import types
-from StringIO import StringIO
-
-import urllib
-import random
-import md5
-
-# Extract from HTML4 spec.
-## The following example illustrates "multipart/form-data"
-## encoding. Suppose we have the following form:
-
-## <FORM action="http://server.com/cgi/handle"
-## enctype="multipart/form-data"
-## method="post">
-## <P>
-## What is your name? <INPUT type="text" name="submit-name"><BR>
-## What files are you sending? <INPUT type="file" name="files"><BR>
-## <INPUT type="submit" value="Send"> <INPUT type="reset">
-## </FORM>
-
-## If the user enters "Larry" in the text input, and selects the text
-## file "file1.txt", the user agent might send back the following data:
-
-## Content-Type: multipart/form-data; boundary=AaB03x
-
-## --AaB03x
-## Content-Disposition: form-data; name="submit-name"
-
-## Larry
-## --AaB03x
-## Content-Disposition: form-data; name="files"; filename="file1.txt"
-## Content-Type: text/plain
-
-## ... contents of file1.txt ...
-## --AaB03x--
-
-## If the user selected a second (image) file "file2.gif", the user agent
-## might construct the parts as follows:
-
-## Content-Type: multipart/form-data; boundary=AaB03x
-
-## --AaB03x
-## Content-Disposition: form-data; name="submit-name"
-
-## Larry
-## --AaB03x
-## Content-Disposition: form-data; name="files"
-## Content-Type: multipart/mixed; boundary=BbC04y
-
-## --BbC04y
-## Content-Disposition: file; filename="file1.txt"
-## Content-Type: text/plain
-
-## ... contents of file1.txt ...
-## --BbC04y
-## Content-Disposition: file; filename="file2.gif"
-## Content-Type: image/gif
-## Content-Transfer-Encoding: binary
-
-## ...contents of file2.gif...
-## --BbC04y--
-## --AaB03x--
-
-__all__ = ['encode_data', 'encode_multipart', 'encode_form', 'mime_boundary' ]
-
-def data_values(d):
- if isinstance(d, types.DictType):
- return d.items()
- else:
- return d
-
-def encode_data(d):
- """Encode some data for HTTP transport.
- The encoding used is stored in 'Content-Type' in the headers.
-
- d data - sequence of tuples or dictionary
- returns a 2-tuple of the headers and the encoded data
- """
- val = ({}, None)
- if d is None: return val
- multipart = 0
- for (_, v) in data_values(d):
- if encode_isfile(v):
- multipart = 1
- break
- if multipart:
- val = encode_multipart(d)
- else:
- val = encode_form(d)
- return val
-
-def encode_isfile(v):
- if isinstance(v, types.FileType):
- return 1
- if hasattr(v, 'readlines'):
- return 1
- return 0
-
-def encode_multipart(d):
- boundary = mime_boundary()
- hdr = { 'Content-Type': 'multipart/form-data; boundary=' + boundary }
- out = StringIO()
- for (k,v) in data_values(d):
- out.write('--')
- out.write(boundary)
- out.write('\r\n')
- if encode_isfile(v):
- out.write('Content-Disposition: form-data; name="')
- out.write(k)
- if hasattr(v, 'name'):
- out.write('"; filename="')
- out.write(v.name)
- out.write('"\r\n')
- out.write('Content-Type: application/octet-stream\r\n')
- out.write('\r\n')
- for l in v.readlines():
- out.write(l)
- else:
- out.write('Content-Disposition: form-data; name="')
- out.write(k)
- out.write('"\r\n')
- out.write('\r\n')
- out.write(str(v))
- out.write('\r\n')
- out.write('--')
- out.write(boundary)
- out.write('--')
- out.write('\r\n')
- return (hdr, out.getvalue())
-
-def mime_boundary():
- random.seed()
- m = md5.new()
- for _ in range(0, 10):
- c = chr(random.randint(1, 255))
- m.update(c)
- b = m.hexdigest()
- return b[0:16]
-
-def encode_form(d):
- hdr = { 'Content-Type': 'application/x-www-form-urlencoded' }
- val = urllib.urlencode(d)
- return (hdr, val)
-
-def main():
- #d = {'a': 1, 'b': 'x y', 'c': file('conf.sxp') }
- #d = {'a': 1, 'b': 'x y' }
- d = [ ('a', 1), ('b', 'x y'), ('c', file('conf.sxp')) ]
- #d = [ ('a', 1), ('b', 'x y')]
- v = encode_data(d)
- print v[0]
- sys.stdout.write(v[1])
- print
-
-if __name__ == "__main__":
- main()
diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py
deleted file mode 100644
index 832c168..0000000
--- a/tools/python/xen/xend/image.py
+++ /dev/null
@@ -1,1103 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005-2007 XenSource Ltd
-#============================================================================
-
-
-import os, os.path, string
-import re
-import math
-import time
-import signal
-import thread
-import fcntl
-import sys
-import errno
-import glob
-import traceback
-import platform
-
-import xen.lowlevel.xc
-from xen.xend.XendConstants import *
-from xen.xend.XendError import VmError, XendError, HVMRequired
-from xen.xend.XendLogging import log
-from xen.xend.XendOptions import instance as xenopts
-from xen.xend.xenstore.xstransact import xstransact
-from xen.xend.xenstore.xswatch import xswatch
-from xen.xend import arch
-from xen.xend import XendOptions
-from xen.util import oshelp
-from xen.util import utils
-from xen.xend import osdep
-
-xc = xen.lowlevel.xc.xc()
-
-MAX_GUEST_CMDLINE = 1024
-
-sentinel_path_prefix = '/var/run/xend/dm-'
-sentinel_fifos_inuse = { }
-
-def cleanup_stale_sentinel_fifos():
- for path in glob.glob(sentinel_path_prefix + '*.fifo'):
- if path in sentinel_fifos_inuse: continue
- try: os.unlink(path)
- except OSError, e:
- log.warning('could not delete stale fifo %s: %s',
- path, utils.exception_string(e))
-
-def create(vm, vmConfig):
- """Create an image handler for a vm.
-
- @return ImageHandler instance
- """
- return findImageHandlerClass(vmConfig)(vm, vmConfig)
-
-
-class ImageHandler:
- """Abstract base class for image handlers.
-
- createImage() is called to configure and build the domain from its
- kernel image and ramdisk etc.
-
- The method buildDomain() is used to build the domain, and must be
- defined in a subclass. Usually this is the only method that needs
- defining in a subclass.
-
- The method createDeviceModel() is called to create the domain device
- model.
-
- The method destroyDeviceModel() is called to reap the device model
- """
-
- ostype = None
- superpages = 0
- memory_sharing = 0
-
- def __init__(self, vm, vmConfig):
- self.vm = vm
-
- self.bootloader = False
- self.use_tmp_kernel = False
- self.use_tmp_ramdisk = False
- self.kernel = None
- self.ramdisk = None
- self.cmdline = None
-
- self.configure(vmConfig)
-
- def configure(self, vmConfig):
- """Config actions common to all unix-like domains."""
- if '_temp_using_bootloader' in vmConfig:
- self.bootloader = True
- self.kernel = vmConfig['_temp_kernel']
- self.cmdline = vmConfig['_temp_args']
- self.ramdisk = vmConfig['_temp_ramdisk']
- else:
- self.kernel = vmConfig['PV_kernel']
- self.cmdline = vmConfig['PV_args']
- self.ramdisk = vmConfig['PV_ramdisk']
- # There a code-paths where use_tmp_xxx is not set at all; but if
- # this is set, the variable itself is a boolean.
- if 'use_tmp_kernel' in vmConfig and vmConfig['use_tmp_kernel']:
- self.use_tmp_kernel = True
- if 'use_tmp_ramdisk' in vmConfig and vmConfig['use_tmp_ramdisk']:
- self.use_tmp_ramdisk = True
- self.vm.storeVm(("image/ostype", self.ostype),
- ("image/kernel", self.kernel),
- ("image/cmdline", self.cmdline),
- ("image/ramdisk", self.ramdisk))
- self.vm.permissionsVm("image/cmdline", { 'dom': self.vm.getDomid(), 'read': True } )
-
- self.device_model = vmConfig['platform'].get('device_model')
-
- self.display = vmConfig['platform'].get('display')
- self.xauthority = vmConfig['platform'].get('xauthority')
- self.vncconsole = int(vmConfig['platform'].get('vncconsole', 0))
- self.dmargs = self.parseDeviceModelArgs(vmConfig)
- self.pid = None
- rtc_timeoffset = int(vmConfig['platform'].get('rtc_timeoffset', 0))
- if int(vmConfig['platform'].get('localtime', 0)):
- if time.localtime(time.time())[8]:
- rtc_timeoffset -= time.altzone
- else:
- rtc_timeoffset -= time.timezone
- if rtc_timeoffset != 0:
- xc.domain_set_time_offset(self.vm.getDomid(), rtc_timeoffset)
-
- self.cpuid = None
- self.cpuid_check = None
- if 'cpuid' in vmConfig:
- self.cpuid = vmConfig['cpuid'];
- if 'cpuid_check' in vmConfig:
- self.cpuid_check = vmConfig['cpuid_check']
-
- def cleanupTmpImages(self):
- if self.use_tmp_kernel:
- self.unlink(self.kernel)
- if self.use_tmp_ramdisk:
- self.unlink(self.ramdisk)
-
- def unlink(self, f):
- if not f: return
- try:
- os.unlink(f)
- except OSError, ex:
- log.warning("error removing bootloader file '%s': %s", f, ex)
-
-
- def createImage(self):
- """Entry point to create domain memory image.
- Override in subclass if needed.
- """
- return self.createDomain()
-
-
- def createDomain(self):
- """Build the domain boot image.
- """
- # Set params and call buildDomain().
-
- if self.kernel and not os.path.isfile(self.kernel):
- raise VmError('Kernel image does not exist: %s' % self.kernel)
- if self.ramdisk and not os.path.isfile(self.ramdisk):
- raise VmError('Kernel ramdisk does not exist: %s' % self.ramdisk)
- if len(self.cmdline) >= MAX_GUEST_CMDLINE:
- log.warning('kernel cmdline too long, domain %d',
- self.vm.getDomid())
-
- log.info("buildDomain os=%s dom=%d vcpus=%d", self.ostype,
- self.vm.getDomid(), self.vm.getVCpuCount())
-
- result = self.buildDomain()
-
- if isinstance(result, dict):
- return result
- else:
- raise VmError('Building domain failed: ostype=%s dom=%d err=%s'
- % (self.ostype, self.vm.getDomid(), str(result)))
-
- def getRequiredAvailableMemory(self, mem_kb):
- """@param mem_kb The configured maxmem or memory, in KiB.
- @return The corresponding required amount of memory for the domain,
- also in KiB. This is normally the given mem_kb, but architecture- or
- image-specific code may override this to add headroom where
- necessary."""
- return mem_kb
-
- def getRequiredInitialReservation(self):
- """@param mem_kb The configured memory, in KiB.
- @return The corresponding required amount of memory to be free, also
- in KiB. This is normally the same as getRequiredAvailableMemory, but
- architecture- or image-specific code may override this to
- add headroom where necessary."""
- return self.getRequiredAvailableMemory(self.vm.getMemoryTarget())
-
- def getRequiredMaximumReservation(self):
- """@param mem_kb The maximum possible memory, in KiB.
- @return The corresponding required amount of memory to be free, also
- in KiB. This is normally the same as getRequiredAvailableMemory, but
- architecture- or image-specific code may override this to
- add headroom where necessary."""
- return self.getRequiredAvailableMemory(self.vm.getMemoryMaximum())
-
- def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
- """@param shadow_mem_kb The configured shadow memory, in KiB.
- @param maxmem_kb The configured maxmem, in KiB.
- @return The corresponding required amount of shadow memory, also in
- KiB."""
- # PV domains don't need any shadow memory
- return 0
-
- def buildDomain(self):
- """Build the domain. Define in subclass."""
- raise NotImplementedError()
-
- def prepareEnvironment(self):
- """Prepare the environment for the execution of the domain. This
- method is called before any devices are set up."""
-
- domid = self.vm.getDomid()
-
- # Delete left-over pipes
- try:
- os.unlink('/var/run/tap/qemu-read-%d' % domid)
- os.unlink('/var/run/tap/qemu-write-%d' % domid)
- except:
- pass
-
- # No device model, don't create pipes
- if self.device_model is None:
- return
-
- if platform.system() != 'SunOS':
- # If we use a device model, the pipes for communication between
- # blktapctrl and ioemu must be present before the devices are
- # created (blktapctrl must access them for new block devices)
-
- try:
- os.makedirs('/var/run/tap', 0755)
- except:
- pass
-
- try:
- os.mkfifo('/var/run/tap/qemu-read-%d' % domid, 0600)
- os.mkfifo('/var/run/tap/qemu-write-%d' % domid, 0600)
- except OSError, e:
- log.warn('Could not create blktap pipes for domain %d' % domid)
- log.exception(e)
- pass
-
-
- # Return a list of cmd line args to the device models based on the
- # xm config file
- def parseDeviceModelArgs(self, vmConfig):
- ret = ["-domain-name", str(self.vm.info['name_label'])]
-
- xen_extended_power_mgmt = int(vmConfig['platform'].get(
- 'xen_extended_power_mgmt', 0))
- if xen_extended_power_mgmt != 0:
- xstransact.Store("/local/domain/0/device-model/%i"
- % self.vm.getDomid(),
- ('xen_extended_power_mgmt',
- xen_extended_power_mgmt))
-
- # Find RFB console device, and if it exists, make QEMU enable
- # the VNC console.
- if int(vmConfig['platform'].get('nographic', 0)) != 0:
- # skip vnc init if nographic is set
- ret.append('-nographic')
- return ret
-
- vram = str(vmConfig['platform'].get('videoram',4))
- ret.append('-videoram')
- ret.append(vram)
-
- vnc_config = {}
- has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
- has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
- opengl = 1
- keymap = vmConfig['platform'].get("keymap")
- for dev_uuid in vmConfig['console_refs']:
- dev_type, dev_info = vmConfig['devices'][dev_uuid]
- if dev_type == 'vfb':
- if 'keymap' in dev_info:
- keymap = dev_info.get('keymap',{})
- if 'monitor' in dev_info:
- ret.append("-serial")
- ret.append(dev_info.get('monitor',{}))
- ret.append("-monitor")
- ret.append("null")
- if 'serial' in dev_info:
- ret.append("-serial")
- ret.append(dev_info.get('serial',{}))
- if int(dev_info.get('vnc', 0)) != 0 :
- has_vnc = True
- if int(dev_info.get('sdl', 0)) != 0 :
- has_sdl = True
- if has_sdl:
- self.display = dev_info.get('display', self.display)
- self.xauthority = dev_info.get('xauthority', self.xauthority)
- opengl = int(dev_info.get('opengl', opengl))
- if has_vnc:
- vnc_config = dev_info.get('other_config', {})
- break
-
- if keymap:
- ret.append("-k")
- ret.append(keymap)
-
- if has_vnc:
- if not vnc_config:
- for key in ('vncunused', 'vnclisten', 'vncdisplay',
- 'vncpasswd'):
- if key in vmConfig['platform']:
- vnc_config[key] = vmConfig['platform'][key]
- if vnc_config.has_key("vncpasswd"):
- passwd = vnc_config["vncpasswd"]
- else:
- passwd = XendOptions.instance().get_vncpasswd_default()
- vncopts = ""
- if passwd:
- self.vm.storeVm("vncpasswd", passwd)
- self.vm.permissionsVm("vncpasswd", { 'dom': self.vm.getDomid(), 'read': True } )
- vncopts = vncopts + ",password"
- log.debug("Stored a VNC password for vfb access")
- else:
- log.debug("No VNC passwd configured for vfb access")
-
- if XendOptions.instance().get_vnc_tls():
- vncx509certdir = XendOptions.instance().get_vnc_x509_cert_dir()
- vncx509verify = XendOptions.instance().get_vnc_x509_verify()
-
- if not os.path.exists(vncx509certdir):
- raise VmError("VNC x509 certificate dir %s does not exist" % vncx509certdir)
-
- if vncx509verify:
- vncopts = vncopts + ",tls,x509verify=%s" % vncx509certdir
- else:
- vncopts = vncopts + ",tls,x509=%s" % vncx509certdir
-
-
- vnclisten = vnc_config.get('vnclisten',
- XendOptions.instance().get_vnclisten_address())
- vncdisplay = int(vnc_config.get('vncdisplay', 0))
- ret.append('-vnc')
- ret.append("%s:%s%s" % (vnclisten, vncdisplay, vncopts))
-
- if int(vnc_config.get('vncunused', 1)) != 0:
- ret.append('-vncunused')
-
- if has_sdl:
- ret.append('-sdl')
- if int(vmConfig['platform'].get('opengl', opengl)) != 1 :
- ret.append('-disable-opengl')
-
- if not has_sdl and not has_vnc :
- ret.append('-nographic')
-
- if vmConfig['platform'].get('parallel'):
- ret = ret + ["-parallel", vmConfig['platform'].get('parallel')]
-
- if int(vmConfig['platform'].get('monitor', 0)) != 0:
- if vmConfig['platform'].get('monitor_path'):
- ret = ret + ['-monitor', vmConfig['platform'].get('monitor_path')]
- else:
- ret = ret + ['-monitor', 'vc']
-
- return ret
-
- def getDeviceModelArgs(self, restore = False):
- args = [self.device_model]
- args = args + ([ "-d", "%d" % self.vm.getDomid() ])
- args = args + self.dmargs
- return args
-
- def _openSentinel(self, sentinel_path_fifo):
- self.sentinel_fifo = file(sentinel_path_fifo, 'r')
- self.sentinel_lock = thread.allocate_lock()
- oshelp.fcntl_setfd_cloexec(self.sentinel_fifo, True)
- sentinel_fifos_inuse[sentinel_path_fifo] = 1
- self.sentinel_path_fifo = sentinel_path_fifo
-
- def createDeviceModel(self, restore = False):
- if self.device_model is None:
- return
- if self.pid:
- return
- # Execute device model.
- #todo: Error handling
- args = self.getDeviceModelArgs(restore)
- env = dict(os.environ)
- if self.display:
- env['DISPLAY'] = self.display
- if self.xauthority:
- env['XAUTHORITY'] = self.xauthority
- unique_id = "%i-%i" % (self.vm.getDomid(), time.time())
- sentinel_path = sentinel_path_prefix + unique_id
- sentinel_path_fifo = sentinel_path + '.fifo'
- os.mkfifo(sentinel_path_fifo, 0600)
- sentinel_write = file(sentinel_path_fifo, 'r+')
- self._openSentinel(sentinel_path_fifo)
- self.vm.storeDom("image/device-model-fifo", sentinel_path_fifo)
- xstransact.Mkdir("/local/domain/0/device-model/%i" % self.vm.getDomid())
- xstransact.SetPermissions("/local/domain/0/device-model/%i" % self.vm.getDomid(),
- { 'dom': self.vm.getDomid(), 'read': True, 'write': True })
- log.info("spawning device models: %s %s", self.device_model, args)
- # keep track of pid and spawned options to kill it later
-
- self.logfile = "/var/log/xen/qemu-dm-%s.log" % str(self.vm.info['name_label'])
-
- # rotate log
- logfile_mode = os.O_WRONLY|os.O_CREAT|os.O_APPEND
- logrotate_count = XendOptions.instance().get_qemu_dm_logrotate_count()
- if logrotate_count > 0:
- logfile_mode |= os.O_TRUNC
- if os.path.exists("%s.%d" % (self.logfile, logrotate_count)):
- os.unlink("%s.%d" % (self.logfile, logrotate_count))
- for n in range(logrotate_count - 1, 0, -1):
- if os.path.exists("%s.%d" % (self.logfile, n)):
- os.rename("%s.%d" % (self.logfile, n),
- "%s.%d" % (self.logfile, (n + 1)))
- if os.path.exists(self.logfile):
- os.rename(self.logfile, self.logfile + ".1")
-
- null = os.open("/dev/null", os.O_RDONLY)
- logfd = os.open(self.logfile, logfile_mode, 0666)
-
- sys.stderr.flush()
- contract = osdep.prefork("%s:%d" %
- (self.vm.getName(), self.vm.getDomid()))
- pid = os.fork()
- if pid == 0: #child
- try:
- osdep.postfork(contract)
- os.dup2(null, 0)
- os.dup2(logfd, 1)
- os.dup2(logfd, 2)
- oshelp.close_fds((sentinel_write.fileno(),))
- try:
- os.execve(self.device_model, args, env)
- except Exception, e:
- print >>sys.stderr, (
- 'failed to set up fds or execute dm %s: %s' %
- (self.device_model, utils.exception_string(e)))
- os._exit(126)
- except:
- os._exit(127)
- else:
- osdep.postfork(contract, abandon=True)
- self.pid = pid
- os.close(null)
- os.close(logfd)
- sentinel_write.close()
- self.vm.storeDom("image/device-model-pid", self.pid)
- log.info("device model pid: %d", self.pid)
- # we would very much prefer not to have a thread here and instead
- # have a callback but sadly we don't have Twisted in xend
- self.sentinel_thread = thread.start_new_thread(self._sentinel_watch,())
- if self.device_model.find('stubdom-dm') > -1 :
- from xen.xend import XendDomain
- domains = XendDomain.instance()
- domains.domains_lock.release()
-
- count = 0
- while True:
- orig_state = xstransact.Read("/local/domain/0/device-model/%i/state"
- % self.vm.getDomid())
- # This can occur right after start-up
- if orig_state != None:
- break
-
- log.debug('createDeviceModel %i: orig_state is None, retrying' % self.vm.getDomid())
-
- time.sleep(0.1)
- count += 1
- if count > 100:
- break
-
- domains.domains_lock.acquire()
-
- def signalDeviceModel(self, cmd, ret, par = None):
- if self.device_model is None:
- return
- # Signal the device model to for action
- if cmd is '' or ret is '':
- raise VmError('need valid command and result when signal device model')
-
- count = 0
- while True:
- orig_state = xstransact.Read("/local/domain/0/device-model/%i/state"
- % self.vm.getDomid())
- # This can occur right after start-up
- if orig_state != None:
- break
-
- log.debug('signalDeviceModel: orig_state is None, retrying')
-
- time.sleep(0.1)
- count += 1
- if count < 100:
- continue
-
- raise VmError('Device model isn\'t ready for commands')
-
- if par is not None:
- xstransact.Store("/local/domain/0/device-model/%i"
- % self.vm.getDomid(), ('parameter', par))
-
- xstransact.Store("/local/domain/0/device-model/%i"
- % self.vm.getDomid(), ('command', cmd))
- # Wait for confirmation. Could do this with a watch but we'd
- # still end up spinning here waiting for the watch to fire.
- state = ''
- count = 0
- while state != ret:
- state = xstransact.Read("/local/domain/0/device-model/%i/state"
- % self.vm.getDomid())
- time.sleep(0.1)
- count += 1
- if count > 100:
- raise VmError('Timed out waiting for device model action')
-
- #resotre orig state
- xstransact.Store("/local/domain/0/device-model/%i"
- % self.vm.getDomid(), ('state', orig_state))
- log.info("signalDeviceModel:restore dm state to %s", orig_state)
-
- def saveDeviceModel(self):
- # Signal the device model to pause itself and save its state
- self.signalDeviceModel('save', 'paused')
-
- def resumeDeviceModel(self):
- if self.device_model is None:
- return
- # Signal the device model to resume activity after pausing to save.
- xstransact.Store("/local/domain/0/device-model/%i"
- % self.vm.getDomid(), ('command', 'continue'))
-
- def _dmfailed(self, message):
- log.warning("domain %s: %s", self.vm.getName(), message)
- try:
- xc.domain_shutdown(self.vm.getDomid(), DOMAIN_CRASH)
- except:
- pass
-
- def recreate(self):
- if self.device_model is None:
- return
- name = self.vm.getName()
- sentinel_path_fifo = self.vm.readDom('image/device-model-fifo')
- fifo_fd = -1
- log.debug("rediscovering %s", sentinel_path_fifo)
- if sentinel_path_fifo is None:
- log.debug("%s device model no sentinel, cannot rediscover", name)
- else:
- try:
- # We open it O_WRONLY because that fails ENXIO if no-one
- # has it open for reading (see SuSv3). The dm process got
- # a read/write descriptor from our earlier invocation.
- fifo_fd = os.open(sentinel_path_fifo, os.O_WRONLY|os.O_NONBLOCK)
- except OSError, e:
- if e.errno == errno.ENXIO:
- self._dmfailed("%s device model no longer running"%name)
- elif e.errno == errno.ENOENT:
- log.debug("%s device model sentinel %s absent!",
- name, sentinel_path_fifo)
- else:
- raise
- if fifo_fd >= 0:
- self._openSentinel(sentinel_path_fifo)
- os.close(fifo_fd)
- self.pid = self.vm.gatherDom(('image/device-model-pid', int))
- log.debug("%s device model rediscovered, pid %s sentinel fifo %s",
- name, self.pid, sentinel_path_fifo)
- self.sentinel_thread = thread.start_new_thread(self._sentinel_watch,())
-
- def _sentinel_watch(self):
- log.info("waiting for sentinel_fifo")
- try: self.sentinel_fifo.read(1)
- except OSError, e: pass
- self.sentinel_lock.acquire()
- if self.pid:
- try:
- (p,st) = os.waitpid(self.pid, os.WNOHANG)
- if p == self.pid:
- message = oshelp.waitstatus_description(st)
- else:
- # obviously it is malfunctioning, kill it now
- try:
- os.kill(self.pid, signal.SIGKILL)
- message = "malfunctioning (closed sentinel), killed"
- except:
- message = "malfunctioning or died ?"
- message = "pid %d: %s" % (self.pid, message)
- except Exception, e:
- message = "waitpid failed: %s" % utils.exception_string(e)
- message = "device model failure: %s" % message
- try: message += "; see %s " % self.logfile
- except: pass
- self._dmfailed(message)
- self.pid = None
- else:
- log.info("%s device model terminated", self.vm.getName())
- self.sentinel_lock.release()
-
- def destroyDeviceModel(self):
- if self.device_model is None:
- return
- self.sentinel_lock.acquire()
- try:
- stubdomid = self.vm.getStubdomDomid()
- if stubdomid is not None :
- from xen.xend import XendDomain
- XendDomain.instance().domain_destroy(stubdomid)
- elif self.pid:
- try:
- os.kill(self.pid, signal.SIGHUP)
- except OSError, exn:
- log.exception(exn)
- # Try to reap the child every 100ms for 10s. Then SIGKILL it.
- for i in xrange(100):
- try:
- (p, rv) = os.waitpid(self.pid, os.WNOHANG)
- if p == self.pid:
- break
- except OSError:
- # This is expected if Xend has been restarted within
- # the life of this domain. In this case, we can kill
- # the process, but we can't wait for it because it's
- # not our child. We continue this loop, and after it is
- # terminated make really sure the process is going away
- # (SIGKILL).
- pass
- time.sleep(0.1)
- else:
- log.warning("DeviceModel %d took more than 10s "
- "to terminate: sending SIGKILL" % self.pid)
- try:
- os.kill(self.pid, signal.SIGKILL)
- os.waitpid(self.pid, 0)
- except OSError:
- # This happens if the process doesn't exist.
- pass
- finally:
- self.pid = None
- self.sentinel_lock.release()
-
- state = xstransact.Remove("/local/domain/0/device-model/%i"
- % self.vm.getDomid())
- try:
- os.unlink('/var/run/tap/qemu-read-%d' % self.vm.getDomid())
- os.unlink('/var/run/tap/qemu-write-%d' % self.vm.getDomid())
- except:
- pass
- try:
- del sentinel_fifos_inuse[self.sentinel_path_fifo]
- os.unlink(self.sentinel_path_fifo)
- except:
- pass
-
- def setCpuid(self):
- xc.domain_set_policy_cpuid(self.vm.getDomid())
-
- if self.cpuid is not None:
- cpuid = self.cpuid
- transformed = {}
- for sinput, regs in cpuid.iteritems():
- inputs = sinput.split(',')
- input = long(inputs[0])
- sub_input = None
- if len(inputs) == 2:
- sub_input = long(inputs[1])
- t = xc.domain_set_cpuid(self.vm.getDomid(),
- input, sub_input, regs)
- transformed[sinput] = t
- self.cpuid = transformed
-
- if self.cpuid_check is not None:
- cpuid_check = self.cpuid_check
- transformed = {}
- for sinput, regs_check in cpuid_check.iteritems():
- inputs = sinput.split(',')
- input = long(inputs[0])
- sub_input = None
- if len(inputs) == 2:
- sub_input = long(inputs[1])
- t = xc.domain_check_cpuid(input, sub_input, regs_check)
- transformed[sinput] = t
- self.cpuid_check = transformed
-
-class LinuxImageHandler(ImageHandler):
-
- ostype = "linux"
- flags = 0
- vhpt = 0
-
- def configure(self, vmConfig):
- ImageHandler.configure(self, vmConfig)
- self.vramsize = int(vmConfig['platform'].get('videoram',4)) * 1024
- self.is_stubdom = (self.kernel.find('stubdom') >= 0)
- self.superpages = int(vmConfig['superpages'])
-
- def buildDomain(self):
- store_evtchn = self.vm.getStorePort()
- console_evtchn = self.vm.getConsolePort()
-
- mem_mb = self.getRequiredInitialReservation() / 1024
-
- log.debug("domid = %d", self.vm.getDomid())
- log.debug("memsize = %d", mem_mb)
- log.debug("image = %s", self.kernel)
- log.debug("store_evtchn = %d", store_evtchn)
- log.debug("console_evtchn = %d", console_evtchn)
- log.debug("cmdline = %s", self.cmdline)
- log.debug("ramdisk = %s", self.ramdisk)
- log.debug("vcpus = %d", self.vm.getVCpuCount())
- log.debug("features = %s", self.vm.getFeatures())
- log.debug("flags = %d", self.flags)
- log.debug("superpages = %d", self.superpages)
- if arch.type == "ia64":
- log.debug("vhpt = %d", self.vhpt)
-
- return xc.linux_build(domid = self.vm.getDomid(),
- memsize = mem_mb,
- image = self.kernel,
- store_evtchn = store_evtchn,
- console_evtchn = console_evtchn,
- cmdline = self.cmdline,
- ramdisk = self.ramdisk,
- features = self.vm.getFeatures(),
- flags = self.flags,
- vhpt = self.vhpt,
- superpages = self.superpages)
-
- def getBitSize(self):
- return xc.getBitSize(image = self.kernel,
- cmdline = self.cmdline,
- features = self.vm.getFeatures()
- ).get('type')
-
- def getRequiredAvailableMemory(self, mem_kb):
- if self.is_stubdom :
- mem_kb += self.vramsize
- return mem_kb
-
- def getRequiredInitialReservation(self):
- return self.vm.getMemoryTarget()
-
- def getRequiredMaximumReservation(self):
- return self.vm.getMemoryMaximum()
-
- def parseDeviceModelArgs(self, vmConfig):
- ret = ImageHandler.parseDeviceModelArgs(self, vmConfig)
- if vmConfig['platform'].get('serial'):
- ret = ["-serial", vmConfig['platform'].get('serial')] + ret
- else:
- ret = ["-serial", "pty"] + ret
- return ret
-
- def getDeviceModelArgs(self, restore = False):
- args = ImageHandler.getDeviceModelArgs(self, restore)
- args = args + ([ "-M", "xenpv"])
- return args
-
-
-class HVMImageHandler(ImageHandler):
-
- ostype = "hvm"
-
- def __init__(self, vm, vmConfig):
- ImageHandler.__init__(self, vm, vmConfig)
- self.shutdownWatch = None
- self.rebootFeatureWatch = None
-
- def getBitSize(self):
- return None
-
- def configure(self, vmConfig):
- ImageHandler.configure(self, vmConfig)
-
- self.loader = vmConfig['platform'].get('loader')
-
- info = xc.xeninfo()
- if 'hvm' not in info['xen_caps']:
- raise HVMRequired()
-
- xen_platform_pci = int(vmConfig['platform'].get('xen_platform_pci',1))
- rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset')
-
- if not self.display :
- self.display = ''
-
- store_dmargs = [ x for x in self.dmargs
- if x not in ['-sdl', '-disable-opengl'] ]
- try :
- midx = store_dmargs.index('-monitor')
- store_dmargs[midx + 1] = 'pty'
- except ValueError :
- pass
- self.vm.storeVm(("image/dmargs", " ".join(store_dmargs)),
- ("image/device-model", self.device_model),
- ("image/display", self.display))
- self.vm.permissionsVm("image/dmargs", { 'dom': self.vm.getDomid(), 'read': True } )
-
- if xen_platform_pci == 0:
- disable_pf = 1
- log.info("No need to create platform device.[domid:%d]", self.vm.getDomid())
- else:
- disable_pf = 0
- log.info("Need to create platform device.[domid:%d]", self.vm.getDomid())
-
- xstransact.Store("/local/domain/0/device-model/%i"%self.vm.getDomid(),
- ('disable_pf', disable_pf))
- self.vm.storeVm(("rtc/timeoffset", rtc_timeoffset))
- self.vm.permissionsVm("rtc/timeoffset", { 'dom': self.vm.getDomid(), 'read': True } )
-
- self.apic = int(vmConfig['platform'].get('apic', 0))
- self.acpi = int(vmConfig['platform'].get('acpi', 0))
- self.guest_os_type = vmConfig['platform'].get('guest_os_type')
- self.memory_sharing = int(vmConfig['memory_sharing'])
- try:
- xc.dom_set_memshr(self.vm.getDomid(), self.memory_sharing)
- except:
- pass
-
- # Return a list of cmd line args to the device models based on the
- # xm config file
- def parseDeviceModelArgs(self, vmConfig):
- ret = ImageHandler.parseDeviceModelArgs(self, vmConfig)
- ret = ret + ['-vcpus', str(self.vm.getVCpuCount())]
- ret = ret + ['-vcpu_avail', hex(self.vm.getVCpuAvail())]
-
- if self.kernel:
- log.debug("kernel = %s", self.kernel)
- ret = ret + ['-kernel', self.kernel]
- if self.ramdisk:
- log.debug("ramdisk = %s", self.ramdisk)
- ret = ret + ['-initrd', self.ramdisk]
- if self.cmdline:
- log.debug("cmdline = %s", self.cmdline)
- ret = ret + ['-append', self.cmdline]
-
-
- dmargs = [ 'boot', 'fda', 'fdb', 'soundhw',
- 'localtime', 'serial', 'stdvga', 'isa',
- 'acpi', 'usb', 'usbdevice', 'gfx_passthru' ]
-
- for a in dmargs:
- v = vmConfig['platform'].get(a)
-
- # python doesn't allow '-' in variable names
- if a == 'stdvga': a = 'std-vga'
- if a == 'keymap': a = 'k'
-
- # Handle booleans gracefully
- if a in ['localtime', 'std-vga', 'isa', 'usb', 'acpi']:
- try:
- if v != None: v = int(v)
- if v: ret.append("-%s" % a)
- except (ValueError, TypeError):
- pass # if we can't convert it to a sane type, ignore it
- elif a == 'serial':
- if v:
- if type(v) == str:
- v = [v]
- for s in v:
- if s:
- ret.append("-serial")
- ret.append("%s" % s)
- else:
- if v:
- ret.append("-%s" % a)
- ret.append("%s" % v)
-
- if a in ['fda', 'fdb']:
- if v:
- if not os.path.isabs(v):
- raise VmError("Floppy file %s does not exist." % v)
- log.debug("args: %s, val: %s" % (a,v))
-
- # Handle disk/network related options
- mac = None
- nics = 0
-
- for devuuid in vmConfig['vbd_refs']:
- devinfo = vmConfig['devices'][devuuid][1]
- uname = devinfo.get('uname')
- if uname is not None and 'file:' in uname:
- (_, vbdparam) = string.split(uname, ':', 1)
- if not os.path.isfile(vbdparam):
- raise VmError('Disk image does not exist: %s' %
- vbdparam)
-
- for devuuid in vmConfig['vif_refs']:
- devinfo = vmConfig['devices'][devuuid][1]
- dtype = devinfo.get('type', 'ioemu')
- if dtype != 'ioemu':
- continue
- nics += 1
- mac = devinfo.get('mac')
- if mac is None:
- raise VmError("MAC address not specified or generated.")
- bridge = devinfo.get('bridge', 'xenbr0')
- model = devinfo.get('model', 'rtl8139')
- ret.append("-net")
- ret.append("nic,vlan=%d,macaddr=%s,model=%s" %
- (nics, mac, model))
- vifname = "vif%d.%d-emu" % (self.vm.getDomid(), nics-1)
- ret.append("-net")
- if osdep.tapif_script is not None:
- script=",script=%s,downscript=%s" % \
- (osdep.tapif_script, osdep.tapif_script)
- else:
- script=""
- ret.append("tap,vlan=%d,ifname=%s,bridge=%s%s" %
- (nics, vifname, bridge, script))
-
- if nics == 0:
- ret.append("-net")
- ret.append("none")
-
- return ret
-
- def getDeviceModelArgs(self, restore = False):
- args = ImageHandler.getDeviceModelArgs(self, restore)
- args = args + ([ "-M", "xenfv"])
- if restore:
- args = args + ([ "-loadvm", "/var/lib/xen/qemu-resume.%d" %
- self.vm.getDomid() ])
- return args
-
- def buildDomain(self):
- store_evtchn = self.vm.getStorePort()
-
- memmax_mb = self.getRequiredMaximumReservation() / 1024
- mem_mb = self.getRequiredInitialReservation() / 1024
-
- log.debug("domid = %d", self.vm.getDomid())
- log.debug("image = %s", self.loader)
- log.debug("store_evtchn = %d", store_evtchn)
- log.debug("memsize = %d", memmax_mb)
- log.debug("target = %d", mem_mb)
- log.debug("vcpus = %d", self.vm.getVCpuCount())
- log.debug("vcpu_avail = %li", self.vm.getVCpuAvail())
- log.debug("acpi = %d", self.acpi)
- log.debug("apic = %d", self.apic)
-
- rc = xc.hvm_build(domid = self.vm.getDomid(),
- image = self.loader,
- memsize = memmax_mb,
- target = mem_mb,
- vcpus = self.vm.getVCpuCount(),
- vcpu_avail = self.vm.getVCpuAvail(),
- acpi = self.acpi,
- apic = self.apic)
- rc['notes'] = { 'SUSPEND_CANCEL': 1 }
-
- rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
- HVM_PARAM_STORE_PFN)
- xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_STORE_EVTCHN,
- store_evtchn)
-
- console_mfn = xc.hvm_get_param(self.vm.getDomid(), HVM_PARAM_CONSOLE_PFN)
- xc.gnttab_hvm_seed(domid = self.vm.getDomid(),
- console_gmfn = console_mfn,
- xenstore_gmfn = rc['store_mfn'],
- console_domid = 0,
- xenstore_domid = 0)
-
- return rc
-
-
-class IA64_HVM_ImageHandler(HVMImageHandler):
-
- def configure(self, vmConfig):
- HVMImageHandler.configure(self, vmConfig)
- self.vhpt = int(vmConfig['platform'].get('vhpt', 0))
- self.vramsize = int(vmConfig['platform'].get('videoram',4)) * 1024
-
- def buildDomain(self):
- xc.nvram_init(self.vm.getName(), self.vm.getDomid())
- xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_VHPT_SIZE, self.vhpt)
- if self.guest_os_type is not None:
- xc.set_os_type(self.guest_os_type.lower(), self.vm.getDomid())
- return HVMImageHandler.buildDomain(self)
-
- def getRequiredAvailableMemory(self, mem_kb):
- page_kb = 16
- # ROM size for guest firmware, io page, xenstore page
- # buffer io page, buffer pio page and memmap info page
- extra_pages = 1024 + 5
- mem_kb += extra_pages * page_kb
- mem_kb += self.vramsize
- return mem_kb
-
- def getRequiredInitialReservation(self):
- return self.vm.getMemoryTarget()
-
- def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
- # Explicit shadow memory is not a concept
- return 0
-
- def getDeviceModelArgs(self, restore = False):
- args = HVMImageHandler.getDeviceModelArgs(self, restore)
- args = args + ([ "-m", "%s" %
- (self.getRequiredInitialReservation() / 1024) ])
- return args
-
- def setCpuid(self):
- # Guest CPUID configuration is not implemented yet.
- return
-
-class IA64_Linux_ImageHandler(LinuxImageHandler):
-
- def configure(self, vmConfig):
- LinuxImageHandler.configure(self, vmConfig)
- self.vhpt = int(vmConfig['platform'].get('vhpt', 0))
-
- def setCpuid(self):
- # Guest CPUID configuration is not implemented yet.
- return
-
-class X86_HVM_ImageHandler(HVMImageHandler):
-
- def configure(self, vmConfig):
- HVMImageHandler.configure(self, vmConfig)
- self.pae = int(vmConfig['platform'].get('pae', 0))
- self.vramsize = int(vmConfig['platform'].get('videoram',4)) * 1024
-
- def buildDomain(self):
- xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_PAE_ENABLED, self.pae)
- rc = HVMImageHandler.buildDomain(self)
- self.setCpuid()
- return rc
-
- def getBitSize(self):
- return None
-
- def getRequiredAvailableMemory(self, mem_kb):
- return mem_kb + self.vramsize
-
- def getRequiredInitialReservation(self):
- return self.vm.getMemoryTarget()
-
- def getRequiredMaximumReservation(self):
- return self.vm.getMemoryMaximum()
-
- def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
- # 256 pages (1MB) per vcpu,
- # plus 1 page per MiB of RAM for the P2M map,
- # plus 1 page per MiB of RAM to shadow the resident processes.
- # This is higher than the minimum that Xen would allocate if no value
- # were given (but the Xen minimum is for safety, not performance).
- return max(4 * (256 * self.vm.getVCpuCount() + 2 * (maxmem_kb / 1024)),
- shadow_mem_kb)
-
-
-class X86_Linux_ImageHandler(LinuxImageHandler):
-
- def buildDomain(self):
- # set physical mapping limit
- # add an 8MB slack to balance backend allocations.
- mem_kb = self.getRequiredMaximumReservation() + (8 * 1024)
- xc.domain_set_memmap_limit(self.vm.getDomid(), mem_kb)
- rc = LinuxImageHandler.buildDomain(self)
- self.setCpuid()
- return rc
-
-_handlers = {
- "ia64": {
- "linux": IA64_Linux_ImageHandler,
- "hvm": IA64_HVM_ImageHandler,
- },
- "x86": {
- "linux": X86_Linux_ImageHandler,
- "hvm": X86_HVM_ImageHandler,
- },
-}
-
-def findImageHandlerClass(image):
- """Find the image handler class for an image config.
-
- @param image config
- @return ImageHandler subclass or None
- """
- image_type = image.image_type()
- try:
- return _handlers[arch.type][image_type]
- except KeyError:
- raise VmError('unknown image type: ' + image_type)
-
diff --git a/tools/python/xen/xend/osdep.py b/tools/python/xen/xend/osdep.py
deleted file mode 100644
index b51dd2e..0000000
--- a/tools/python/xen/xend/osdep.py
+++ /dev/null
@@ -1,268 +0,0 @@
-#!/usr/bin/env python
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-
-import os
-import commands
-
-_xend_autorestart = {
- "NetBSD": True,
- "Linux": True,
- "SunOS": False,
-}
-
-_vif_script = {
- "SunOS": "vif-vnic"
-}
-
-_tapif_script = {
- "Linux": "no",
-}
-
-PROC_XEN_BALLOON = '/proc/xen/balloon'
-SYSFS_XEN_MEMORY = '/sys/devices/system/xen_memory/xen_memory0'
-
-def _linux_balloon_stat_proc(label):
- """Returns the value for the named label, or None if an error occurs."""
-
- xend2linux_labels = { 'current' : 'Current allocation',
- 'target' : 'Requested target',
- 'low-balloon' : 'Low-mem balloon',
- 'high-balloon' : 'High-mem balloon',
- 'limit' : 'Xen hard limit' }
-
- f = file(PROC_XEN_BALLOON, 'r')
- try:
- for line in f:
- keyvalue = line.split(':')
- if keyvalue[0] == xend2linux_labels[label]:
- values = keyvalue[1].split()
- if values[0].isdigit():
- return int(values[0])
- else:
- return None
- return None
- finally:
- f.close()
-
-def _linux_balloon_stat_sysfs(label):
- sysfiles = { 'target' : 'target_kb',
- 'current' : 'info/current_kb',
- 'low-balloon' : 'info/low_kb',
- 'high-balloon' : 'info/high_kb',
- 'limit' : 'info/hard_limit_kb' }
-
- name = os.path.join(SYSFS_XEN_MEMORY, sysfiles[label])
- f = file(name, 'r')
-
- val = f.read().strip()
- if val.isdigit():
- return int(val)
- return None
-
-def _linux_balloon_stat(label):
- if os.access(PROC_XEN_BALLOON, os.F_OK):
- return _linux_balloon_stat_proc(label)
- elif os.access(SYSFS_XEN_MEMORY, os.F_OK):
- return _linux_balloon_stat_sysfs(label)
- return None
-
-def _netbsd_balloon_stat(label):
- """Returns the value for the named label, or None if an error occurs."""
-
- import commands
-
- xend2netbsd_labels = { 'current' : 'kern.xen.balloon.current',
- 'target' : 'kern.xen.balloon.target',
- 'low-balloon' : None,
- 'high-balloon' : None,
- 'limit' : None }
-
- cmdarg = xend2netbsd_labels[label]
- if cmdarg is None:
- return None
- cmd = "/sbin/sysctl " + cmdarg
- sysctloutput = commands.getoutput(cmd)
- (name, value) = sysctloutput.split('=')
- return int(value)
-
-def _solaris_balloon_stat(label):
- """Returns the value for the named label, or None if an error occurs."""
-
- import fcntl
- import array
- DEV_XEN_BALLOON = '/dev/xen/balloon'
- BLN_IOCTL_CURRENT = 0x42410001
- BLN_IOCTL_TARGET = 0x42410002
- BLN_IOCTL_LOW = 0x42410003
- BLN_IOCTL_HIGH = 0x42410004
- BLN_IOCTL_LIMIT = 0x42410005
- label_to_ioctl = { 'current' : BLN_IOCTL_CURRENT,
- 'target' : BLN_IOCTL_TARGET,
- 'low-balloon' : BLN_IOCTL_LOW,
- 'high-balloon' : BLN_IOCTL_HIGH,
- 'limit' : BLN_IOCTL_LIMIT }
-
- f = file(DEV_XEN_BALLOON, 'r')
- try:
- values = array.array('L', [0])
- if fcntl.ioctl(f.fileno(), label_to_ioctl[label], values, 1) == 0:
- return values[0]
- else:
- return None
- finally:
- f.close()
-
-_balloon_stat = {
- "SunOS": _solaris_balloon_stat,
- "NetBSD": _netbsd_balloon_stat,
-}
-
-def _linux_get_cpuinfo():
- cpuinfo = {}
- f = file('/proc/cpuinfo', 'r')
- try:
- p = -1
- d = {}
- for line in f:
- keyvalue = line.split(':')
- if len(keyvalue) != 2:
- continue
- key = keyvalue[0].strip()
- val = keyvalue[1].strip()
- if key == 'processor':
- if p != -1:
- cpuinfo[p] = d
- p = int(val)
- d = {}
- else:
- d[key] = val
- cpuinfo[p] = d
- return cpuinfo
- finally:
- f.close()
-
-def _solaris_get_cpuinfo():
- cpuinfo = {}
-
- # call kstat to extrace specific cpu_info output
- cmd = "/usr/bin/kstat -p -c misc -m cpu_info"
- kstatoutput = commands.getoutput (cmd)
-
- # walk each line
- for kstatline in kstatoutput.split('\n'):
-
- # split the line on
- # module:cpu #:module#:name value
- (module, cpunum, combo, namevalue) = kstatline.split (":")
-
- # check to see if this cpunum is already a key. If not,
- # initialize an empty hash table
- if not cpuinfo.has_key (int(cpunum)):
- cpuinfo[int(cpunum)] = {}
-
- # split the namevalue output on whitespace
- data = namevalue.split()
-
- # the key will be data[0]
- key = data[0]
-
- # check the length of the data list. If it's larger than
- # 2, join the rest of the list together with a space.
- # Otherwise, value is just data[1]
- if len (data) > 2:
- value = ' '.join (data[1:])
- else:
- value = data[1]
-
- # add this key/value pair to the cpuhash
- cpuinfo[int(cpunum)][key] = value
-
- # Translate Solaris tokens into what Xend expects
- for key in cpuinfo.keys():
- cpuinfo[key]["flags"] = ""
- cpuinfo[key]["model name"] = cpuinfo[key]["brand"]
- cpuinfo[key]["cpu MHz"] = cpuinfo[key]["clock_MHz"]
-
- # return the hash table
- return cpuinfo
-
-def _netbsd_get_cpuinfo():
- import commands
- cpuinfo = {}
-
- cmd = "/sbin/sysctl hw.ncpu"
- sysctloutput = commands.getoutput(cmd)
- (name, ncpu) = sysctloutput.split('=')
-
- for i in range(int(ncpu)):
- if not cpuinfo.has_key(i):
- cpuinfo[i] = {}
-
- # Translate NetBSD tokens into what xend expects
- for key in cpuinfo.keys():
- cpuinfo[key]['flags'] = ""
- cpuinfo[key]['vendor_id'] = ""
- cpuinfo[key]['model name'] = ""
- cpuinfo[key]['stepping'] = ""
- cpuinfo[key]['cpu MHz'] = 0
-
- return cpuinfo
-
-
-_get_cpuinfo = {
- "SunOS": _solaris_get_cpuinfo,
- "NetBSD": _netbsd_get_cpuinfo
-}
-
-def _default_prefork(name):
- pass
-
-def _default_postfork(ct, abandon=False):
- pass
-
-# call this for long-running processes that should survive a xend
-# restart
-def _solaris_prefork(name):
- from xen.lowlevel import process
- return process.activate(name)
-
-def _solaris_postfork(ct, abandon=False):
- from xen.lowlevel import process
- process.clear(ct)
- if abandon:
- process.abandon_latest()
-
-_get_prefork = {
- "SunOS": _solaris_prefork
-}
-
-_get_postfork = {
- "SunOS": _solaris_postfork
-}
-
-def _get(var, default=None):
- return var.get(os.uname()[0], default)
-
-xend_autorestart = _get(_xend_autorestart)
-vif_script = _get(_vif_script, "vif-bridge")
-tapif_script = _get(_tapif_script)
-lookup_balloon_stat = _get(_balloon_stat, _linux_balloon_stat)
-get_cpuinfo = _get(_get_cpuinfo, _linux_get_cpuinfo)
-prefork = _get(_get_prefork, _default_prefork)
-postfork = _get(_get_postfork, _default_postfork)
diff --git a/tools/python/xen/xend/server/BlktapController.py b/tools/python/xen/xend/server/BlktapController.py
deleted file mode 100644
index 60079eb..0000000
--- a/tools/python/xen/xend/server/BlktapController.py
+++ /dev/null
@@ -1,313 +0,0 @@
-# Copyright (c) 2005, XenSource Ltd.
-import string, re, os
-
-from xen.xend.server.blkif import BlkifController
-from xen.xend.XendLogging import log
-from xen.util.xpopen import xPopen3
-
-phantomDev = 0;
-phantomId = 0;
-
-blktap1_disk_types = [
- 'aio',
- 'sync',
- 'vmdk',
- 'ram',
- 'qcow',
- 'qcow2',
- 'ioemu',
- ]
-
-blktap2_disk_types = [
- 'aio',
- 'ram',
- 'qcow',
- 'vhd',
- 'remus',
- ]
-
-blktap_disk_types = blktap1_disk_types + blktap2_disk_types
-
-def doexec(args, inputtext=None):
- """Execute a subprocess, then return its return code, stdout and stderr"""
- proc = xPopen3(args, True)
- if inputtext != None:
- proc.tochild.write(inputtext)
- stdout = proc.fromchild
- stderr = proc.childerr
- rc = proc.wait()
- return (rc,stdout,stderr)
-
-# blktap1 device controller
-class BlktapController(BlkifController):
- def __init__(self, vm):
- BlkifController.__init__(self, vm)
-
- def frontendRoot(self):
- """@see DevController#frontendRoot"""
-
- return "%s/device/vbd" % self.vm.getDomainPath()
-
- def getDeviceDetails(self, config):
- (devid, back, front) = BlkifController.getDeviceDetails(self, config)
-
- phantomDevid = 0
- wrapped = False
-
- try:
- imagetype = self.vm.info['image']['type']
- except:
- imagetype = ""
-
- if imagetype == 'hvm':
- tdevname = back['dev']
- index = ['c', 'd', 'e', 'f', 'g', 'h', 'i', \
- 'j', 'l', 'm', 'n', 'o', 'p']
- while True:
- global phantomDev
- global phantomId
- import os, stat
-
- phantomId = phantomId + 1
- if phantomId == 16:
- if index[phantomDev] == index[-1]:
- if wrapped:
- raise VmError(" No loopback block \
- devices are available. ")
- wrapped = True
- phantomDev = 0
- else:
- phantomDev = phantomDev + 1
- phantomId = 1
- devname = 'xvd%s%d' % (index[phantomDev], phantomId)
- try:
- info = os.stat('/dev/%s' % devname)
- except:
- break
-
- vbd = { 'mode': 'w', 'device': devname }
- fn = 'tap:%s' % back['params']
-
- # recurse ... by creating the vbd, then fallthrough
- # and finish creating the original device
-
- from xen.xend import XendDomain
- dom0 = XendDomain.instance().privilegedDomain()
- phantomDevid = dom0.create_phantom_vbd_with_vdi(vbd, fn)
- # we need to wait for this device at a higher level
- # the vbd that gets created will have a link to us
- # and will let them do it there
-
- # add a hook to point to the phantom device,
- # root path is always the same (dom0 tap)
- if phantomDevid != 0:
- front['phantom_vbd'] = '/local/domain/0/backend/tap/0/%s' \
- % str(phantomDevid)
-
- return (devid, back, front)
-
-class Blktap2Controller(BlktapController):
- def __init__(self, vm):
- BlktapController.__init__(self, vm)
-
- def backendPath(self, backdom, devid):
- if self.deviceClass == 'tap2':
- deviceClass = 'vbd'
- else:
- deviceClass = 'tap'
- return "%s/backend/%s/%s/%d" % (backdom.getDomainPath(),
- deviceClass,
- self.vm.getDomid(), devid)
-
- def getDeviceDetails(self, config):
-
- (devid, back, front) = BlktapController.getDeviceDetails(self, config)
- if self.deviceClass == 'tap2':
- # since blktap2 uses blkback as a backend the 'params' feild contains
- # the path to the blktap2 device (/dev/xen/blktap-2/tapdev*). As well,
- # we need to store the params used to create the blktap2 device
- # (tap:tapdisk:<driver>:/<image-path>)
- tapdisk_uname = config.get('tapdisk_uname', '')
- (_, tapdisk_params) = string.split(tapdisk_uname, ':', 1)
- back['tapdisk-params'] = tapdisk_params
-
- return (devid, back, front)
-
- def getDeviceConfiguration(self, devid, transaction = None):
-
- # this is a blktap2 device, so we need to overwrite the 'params' feild
- # with the actual blktap2 parameters. (the vbd parameters are of little
- # use to us)
- config = BlktapController.getDeviceConfiguration(self, devid, transaction)
- if transaction is None:
- tapdisk_params = self.readBackend(devid, 'tapdisk-params')
- else:
- tapdisk_params = self.readBackendTxn(transaction, devid, 'tapdisk-params')
- if tapdisk_params:
- config['uname'] = 'tap:' + tapdisk_params
-
- return config
-
-
- def createDevice(self, config):
-
- uname = config.get('uname', '')
- try:
- (typ, subtyp, params, file) = string.split(uname, ':', 3)
- if subtyp not in ('tapdisk', 'ioemu'):
- raise ValueError('invalid subtype')
- except:
- (typ, params, file) = string.split(uname, ':', 2)
- subtyp = 'tapdisk'
-
- if typ in ('tap'):
- if subtyp in ('tapdisk', 'ioemu'):
- if params not in blktap2_disk_types or \
- TapdiskController.check():
- # pass this device off to BlktapController
- log.warn('WARNING: using deprecated blktap module')
- self.deviceClass = 'tap'
- devid = BlktapController.createDevice(self, config)
- self.deviceClass = 'tap2'
- return devid
-
- device = TapdiskController.create(params, file)
-
- # modify the configutration to create a blkback for the underlying
- # blktap2 device. Note: we need to preserve the original tapdisk uname
- # (it is used during save/restore and for managed domains).
- config.update({'tapdisk_uname' : uname})
- config.update({'uname' : 'phy:' + device.rstrip()})
-
- devid = BlkifController.createDevice(self, config)
- config.update({'uname' : uname})
- config.pop('tapdisk_uname')
- return devid
-
- # This function is called from a thread when the
- # domain is detached from the disk.
- def finishDeviceCleanup(self, backpath, path):
- """Perform any device specific cleanup
-
- @backpath backend xenstore path.
- @path frontend device path
-
- """
-
- #Figure out what we're going to wait on.
- self.waitForBackend_destroy(backpath)
- TapdiskController.destroy(path)
-
-class TapdiskException(Exception):
- pass
-
-class TapdiskController(object):
- '''class which encapsulates all tapdisk control operations'''
-
- TAP_CTL = 'tap-ctl'
- TAP_DEV = '/dev/xen/blktap-2/tapdev'
-
- class Tapdisk(object):
- def __init__(self, pid=None, minor=-1, state=None,
- dtype='', image=None, device=None):
- self.pid = pid
- self.minor = minor
- self.state = state
- self.dtype = dtype
- self.image = image
- self.device = device
-
- def __str__(self):
- return 'image=%s pid=%s minor=%s state=%s type=%s device=%s' \
- % (self.image, self.pid, self.minor, self.state, self.dtype,
- self.device)
-
- @staticmethod
- def exc(*args):
- rc, stdout, stderr = doexec([TapdiskController.TAP_CTL] + list(args))
- out, err = stdout.read().strip(), stderr.read().strip()
- stdout.close()
- stderr.close()
- if rc:
- raise TapdiskException('%s failed (%s %s %s)' % \
- (args, rc, out, err))
- return out
-
- @staticmethod
- def check():
- try:
- TapdiskController.exc('check')
- return 0
- except Exception, e:
- log.warn("tapdisk2 check failed: %s" % e)
- return -1
-
- @staticmethod
- def list():
- tapdisks = []
-
- _list = TapdiskController.exc('list')
- if not _list: return []
-
- for line in _list.splitlines():
- tapdisk = TapdiskController.Tapdisk()
-
- # Since 'tap-ctl list' does not escape blanks in the path, hard-code the current format using 4 pairs to prevent splitting the path
- for pair in line.split(None, 3):
- key, value = pair.split('=', 1)
- if key == 'pid':
- tapdisk.pid = value
- elif key == 'minor':
- tapdisk.minor = int(value)
- if tapdisk.minor >= 0:
- tapdisk.device = '%s%s' % \
- (TapdiskController.TAP_DEV, tapdisk.minor)
- elif key == 'state':
- tapdisk.state = value
- elif key == 'args' and value.find(':') != -1:
- tapdisk.dtype, tapdisk.image = value.split(':', 1)
-
- tapdisks.append(tapdisk)
-
- return tapdisks
-
- @staticmethod
- def fromDevice(device):
- if device.startswith(TapdiskController.TAP_DEV):
- minor = os.minor(os.stat(device).st_rdev)
- tapdisks = filter(lambda x: x.minor == minor,
- TapdiskController.list())
- if len(tapdisks) == 1:
- return tapdisks[0]
- return None
-
- @staticmethod
- def create(dtype, image):
- return TapdiskController.exc('create', '-a%s:%s' % (dtype, image))
-
- @staticmethod
- def destroy(device):
- tapdisk = TapdiskController.fromDevice(device)
- if tapdisk:
- if tapdisk.pid:
- TapdiskController.exc('destroy',
- '-p%s' % tapdisk.pid,
- '-m%s' % tapdisk.minor)
- else:
- TapdiskController.exc('free', '-m%s' % tapdisk.minor)
-
- @staticmethod
- def pause(device):
- tapdisk = TapdiskController.fromDevice(device)
- if tapdisk and tapdisk.pid:
- TapdiskController.exc('pause',
- '-p%s' % tapdisk.pid,
- '-m%s' % tapdisk.minor)
-
- @staticmethod
- def unpause(device):
- tapdisk = TapdiskController.fromDevice(device)
- if tapdisk and tapdisk.pid:
- TapdiskController.exc('unpause',
- '-p%s' % tapdisk.pid,
- '-m%s' % tapdisk.minor)
diff --git a/tools/python/xen/xend/server/ConsoleController.py b/tools/python/xen/xend/server/ConsoleController.py
deleted file mode 100644
index bb746f3..0000000
--- a/tools/python/xen/xend/server/ConsoleController.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from xen.xend.server.DevController import DevController
-from xen.xend.XendLogging import log
-
-from xen.xend.XendError import VmError
-
-class ConsoleController(DevController):
- """A dummy controller for us to represent serial and vnc
- console devices with persistent UUIDs.
- """
-
- valid_cfg = ['location', 'uuid', 'protocol']
-
- def __init__(self, vm):
- DevController.__init__(self, vm)
- self.hotplug = False
-
- def getDeviceDetails(self, config):
- back = dict([(k, config[k]) for k in self.valid_cfg if k in config])
- return (self.allocateDeviceID(), back, {})
-
-
- def getDeviceConfiguration(self, devid, transaction = None):
- result = DevController.getDeviceConfiguration(self, devid, transaction)
- if transaction is None:
- devinfo = self.readBackend(devid, *self.valid_cfg)
- else:
- devinfo = self.readBackendTxn(transaction, devid, *self.valid_cfg)
- config = dict(zip(self.valid_cfg, devinfo))
- config = dict([(key, val) for key, val in config.items()
- if val != None])
- return config
-
- def migrate(self, deviceConfig, network, dst, step, domName):
- return 0
-
- def destroyDevice(self, devid, force):
- DevController.destroyDevice(self, devid, True)
-
diff --git a/tools/python/xen/xend/server/DevConstants.py b/tools/python/xen/xend/server/DevConstants.py
deleted file mode 100644
index ed5fd29..0000000
--- a/tools/python/xen/xend/server/DevConstants.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-from xen.xend import XendOptions
-
-xoptions = XendOptions.instance()
-
-DEVICE_CREATE_TIMEOUT = xoptions.get_device_create_timeout();
-DEVICE_DESTROY_TIMEOUT = xoptions.get_device_destroy_timeout();
-HOTPLUG_STATUS_NODE = "hotplug-status"
-HOTPLUG_ERROR_NODE = "hotplug-error"
-HOTPLUG_STATUS_ERROR = "error"
-HOTPLUG_STATUS_BUSY = "busy"
-
-Connected = 1
-Error = 2
-Missing = 3
-Timeout = 4
-Busy = 5
-Disconnected = 6
-
-xenbusState = {
- 'Unknown' : 0,
- 'Initialising' : 1,
- 'InitWait' : 2,
- 'Initialised' : 3,
- 'Connected' : 4,
- 'Closing' : 5,
- 'Closed' : 6,
- 'Reconfiguring' : 7,
- 'Reconfigured' : 8,
- }
-xenbusState.update(dict(zip(xenbusState.values(), xenbusState.keys())))
-
diff --git a/tools/python/xen/xend/server/DevController.py b/tools/python/xen/xend/server/DevController.py
deleted file mode 100644
index 0431cc2..0000000
--- a/tools/python/xen/xend/server/DevController.py
+++ /dev/null
@@ -1,677 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-from threading import Event
-import types
-
-from xen.xend import sxp, XendOptions
-from xen.xend.XendError import VmError
-from xen.xend.XendLogging import log
-import xen.xend.XendConfig
-from xen.xend.server.DevConstants import *
-
-from xen.xend.xenstore.xstransact import xstransact, complete
-from xen.xend.xenstore.xswatch import xswatch
-import xen.xend.server.DevConstants
-import os, re
-
-xoptions = XendOptions.instance()
-
-
-class DevController:
- """Abstract base class for a device controller. Device controllers create
- appropriate entries in the store to trigger the creation, reconfiguration,
- and destruction of devices in guest domains. Each subclass of
- DevController is responsible for a particular device-class, and
- understands the details of configuration specific to that device-class.
-
- DevController itself provides the functionality common to all device
- creation tasks, as well as providing an interface to XendDomainInfo for
- triggering those events themselves.
- """
-
- # Set when registered.
- deviceClass = None
-
-
- ## public:
-
- def __init__(self, vm):
- self.vm = vm
- self.hotplug = True
-
- def createDevice(self, config):
- """Trigger the creation of a device with the given configuration.
-
- @return The ID for the newly created device.
- """
- (devid, back, front) = self.getDeviceDetails(config)
- if devid is None:
- return 0
-
- self.setupDevice(config)
-
- (backpath, frontpath) = self.addStoreEntries(config, devid, back,
- front)
-
- import xen.xend.XendDomain
- xd = xen.xend.XendDomain.instance()
- backdom_name = config.get('backend')
- if backdom_name is None:
- backdom = xen.xend.XendDomain.DOM0_ID
- else:
- bd = xd.domain_lookup_nr(backdom_name)
- backdom = bd.getDomid()
- count = 0
- while True:
- t = xstransact()
- try:
- if devid in self.deviceIDs(t):
- if 'dev' in back:
- dev_str = '%s (%d, %s)' % (back['dev'], devid,
- self.deviceClass)
- else:
- dev_str = '%s (%s)' % (devid, self.deviceClass)
-
- raise VmError("Device %s is already connected." % dev_str)
-
- if count == 0:
- log.debug('DevController: writing %s to %s.',
- str(front), frontpath)
- log.debug('DevController: writing %s to %s.',
- str(xen.xend.XendConfig.scrub_password(back)), backpath)
- elif count % 50 == 0:
- log.debug(
- 'DevController: still waiting to write device entries.')
-
- devpath = self.devicePath(devid)
-
- t.remove(frontpath)
- t.remove(backpath)
- t.remove(devpath)
-
- t.mkdir(backpath)
- t.set_permissions(backpath,
- {'dom': backdom },
- {'dom' : self.vm.getDomid(),
- 'read' : True })
- t.mkdir(frontpath)
- t.set_permissions(frontpath,
- {'dom': self.vm.getDomid()},
- {'dom': backdom, 'read': True})
-
- t.write2(frontpath, front)
- t.write2(backpath, back)
-
- t.mkdir(devpath)
- t.write2(devpath, {
- 'backend' : backpath,
- 'backend-id' : "%i" % backdom,
- 'frontend' : frontpath,
- 'frontend-id' : "%i" % self.vm.getDomid()
- })
-
- if t.commit():
- return devid
-
- count += 1
- except:
- t.abort()
- raise
-
-
- def waitForDevices(self):
- log.debug("Waiting for devices %s.", self.deviceClass)
- return map(self.waitForDevice, self.deviceIDs())
-
-
- def waitForDevice(self, devid):
- log.debug("Waiting for %s.", devid)
-
- if not self.hotplug:
- return
-
- (status, err) = self.waitForBackend(devid)
-
- if status == Timeout:
- self.destroyDevice(devid, False)
- raise VmError("Device %s (%s) could not be connected. "
- "Hotplug scripts not working." %
- (devid, self.deviceClass))
-
- elif status == Error:
- self.destroyDevice(devid, False)
- if err is None:
- raise VmError("Device %s (%s) could not be connected. "
- "Backend device not found." %
- (devid, self.deviceClass))
- else:
- raise VmError("Device %s (%s) could not be connected. "
- "%s" % (devid, self.deviceClass, err))
- elif status == Missing:
- # Don't try to destroy the device; it's already gone away.
- raise VmError("Device %s (%s) could not be connected. "
- "Device not found." % (devid, self.deviceClass))
-
- elif status == Busy:
- self.destroyDevice(devid, False)
- if err is None:
- err = "Busy."
- raise VmError("Device %s (%s) could not be connected.\n%s" %
- (devid, self.deviceClass, err))
-
-
- def waitForDevice_destroy(self, devid, backpath):
- log.debug("Waiting for %s - destroyDevice.", devid)
-
- if not self.hotplug:
- return
-
- status = self.waitForBackend_destroy(backpath)
-
- if status == Timeout:
- raise VmError("Device %s (%s) could not be disconnected. " %
- (devid, self.deviceClass))
-
- def waitForDevice_reconfigure(self, devid):
- log.debug("Waiting for %s - reconfigureDevice.", devid)
-
- (status, err) = self.waitForBackend_reconfigure(devid)
-
- if status == Timeout:
- raise VmError("Device %s (%s) could not be reconfigured. " %
- (devid, self.deviceClass))
-
-
- def reconfigureDevice(self, devid, config):
- """Reconfigure the specified device.
-
- The implementation here just raises VmError. This may be overridden
- by those subclasses that can reconfigure their devices.
- """
- raise VmError('%s devices may not be reconfigured' % self.deviceClass)
-
-
- def destroyDevice(self, devid, force):
- """Destroy the specified device.
-
- @param devid The device ID, or something device-specific from which
- the device ID can be determined (such as a guest-side device name).
-
- The implementation here simply deletes the appropriate paths from the
- store. This may be overridden by subclasses who need to perform other
- tasks on destruction. The implementation here accepts integer device
- IDs or paths containg integer deviceIDs, e.g. vfb/0. Subclasses may
- accept other values and convert them to integers before passing them
- here.
- """
-
- dev = self.convertToDeviceNumber(devid)
-
- # Modify online status /before/ updating state (latter is watched by
- # drivers, so this ordering avoids a race).
- self.writeBackend(dev, 'online', "0")
- self.writeBackend(dev, 'state', str(xenbusState['Closing']))
-
- if force:
- frontpath = self.frontendPath(dev)
- backpath = self.readVm(dev, "backend")
- if backpath:
- xstransact.Remove(backpath)
- xstransact.Remove(frontpath)
-
- # xstransact.Remove(self.devicePath()) ?? Below is the same ?
- self.vm._removeVm("device/%s/%d" % (self.deviceClass, dev))
-
- def configurations(self, transaction = None):
- return map(lambda x: self.configuration(x, transaction), self.deviceIDs(transaction))
-
-
- def configuration(self, devid, transaction = None):
- """@return an s-expression giving the current configuration of the
- specified device. This would be suitable for giving to {@link
- #createDevice} in order to recreate that device."""
- configDict = self.getDeviceConfiguration(devid, transaction)
- sxpr = [self.deviceClass]
- for key, val in configDict.items():
- if isinstance(val, (types.ListType, types.TupleType)):
- for v in val:
- if v != None:
- sxpr.append([key, v])
- else:
- if val != None:
- sxpr.append([key, val])
- return sxpr
-
- def sxprs(self):
- """@return an s-expression describing all the devices of this
- controller's device-class.
- """
- return xstransact.ListRecursive(self.frontendRoot())
-
-
- def sxpr(self, devid):
- """@return an s-expression describing the specified device.
- """
- return [self.deviceClass, ['dom', self.vm.getDomid(),
- 'id', devid]]
-
-
- def getDeviceConfiguration(self, devid, transaction = None):
- """Returns the configuration of a device.
-
- @note: Similar to L{configuration} except it returns a dict.
- @return: dict
- """
- if transaction is None:
- backdomid = xstransact.Read(self.devicePath(devid), "backend-id")
- else:
- backdomid = transaction.read(self.devicePath(devid) + "/backend-id")
-
- if backdomid is None:
- raise VmError("Device %s not connected" % devid)
-
- return {'backend': int(backdomid)}
-
- def getAllDeviceConfigurations(self):
- all_configs = {}
- for devid in self.deviceIDs():
- config_dict = self.getDeviceConfiguration(devid)
- all_configs[devid] = config_dict
- return all_configs
-
-
- def convertToDeviceNumber(self, devid):
- try:
- return int(devid)
- except ValueError:
- # Does devid contain devicetype/deviceid?
- # Propogate exception if unable to find an integer devid
- return int(type(devid) is str and devid.split('/')[-1] or None)
-
- ## protected:
-
- def getDeviceDetails(self, config):
- """Compute the details for creation of a device corresponding to the
- given configuration. These details consist of a tuple of (devID,
- backDetails, frontDetails), where devID is the ID for the new device,
- and backDetails and frontDetails are the device configuration
- specifics for the backend and frontend respectively.
-
- backDetails and frontDetails should be dictionaries, the keys and
- values of which will be used as paths in the store. There is no need
- for these dictionaries to include the references from frontend to
- backend, nor vice versa, as these will be handled by DevController.
-
- Abstract; must be implemented by every subclass.
-
- @return (devID, backDetails, frontDetails), as specified above.
- """
-
- raise NotImplementedError()
-
- def setupDevice(self, config):
- """ Setup device from config.
- """
- return
-
- def migrate(self, deviceConfig, network, dst, step, domName):
- """ Migration of a device. The 'network' parameter indicates
- whether the device is network-migrated (True). 'dst' then gives
- the hostname of the machine to migrate to.
- This function is called for 4 steps:
- If step == 0: Check whether the device is ready to be migrated
- or can at all be migrated; return a '-1' if
- the device is NOT ready, a '0' otherwise. If it is
- not ready ( = not possible to migrate this device),
- migration will not take place.
- step == 1: Called immediately after step 0; migration
- of the kernel has started;
- step == 2: Called after the suspend has been issued
- to the domain and the domain is not scheduled anymore.
- Synchronize with what was started in step 1, if necessary.
- Now the device should initiate its transfer to the
- given target. Since there might be more than just
- one device initiating a migration, this step should
- put the process performing the transfer into the
- background and return immediately to achieve as much
- concurrency as possible.
- step == 3: Synchronize with the migration of the device that
- was initiated in step 2.
- Make sure that the migration has finished and only
- then return from the call.
- """
- tool = xoptions.get_external_migration_tool()
- if tool:
- log.info("Calling external migration tool for step %d" % step)
- fd = os.popen("%s -type %s -step %d -host %s -domname %s" %
- (tool, self.deviceClass, step, dst, domName))
- for line in fd:
- log.info(line.rstrip())
- rc = fd.close()
- if rc:
- raise VmError('Migration tool returned %d' % (rc >> 8))
- return 0
-
-
- def recover_migrate(self, deviceConfig, network, dst, step, domName):
- """ Recover from device migration. The given step was the
- last one that was successfully executed.
- """
- tool = xoptions.get_external_migration_tool()
- if tool:
- log.info("Calling external migration tool")
- fd = os.popen("%s -type %s -step %d -host %s -domname %s -recover" %
- (tool, self.deviceClass, step, dst, domName))
- for line in fd:
- log.info(line.rstrip())
- rc = fd.close()
- if rc:
- raise VmError('Migration tool returned %d' % (rc >> 8))
- return 0
-
-
- def getDomid(self):
- """Stub to {@link XendDomainInfo.getDomid}, for use by our
- subclasses.
- """
- return self.vm.getDomid()
-
-
- def allocateDeviceID(self):
- """Allocate a device ID, allocating them consecutively on a
- per-domain, per-device-class basis, and using the store to record the
- next available ID.
-
- This method is available to our subclasses, though it is not
- compulsory to use it; subclasses may prefer to allocate IDs based upon
- the device configuration instead.
- """
- path = self.frontendMiscPath()
- return complete(path, self._allocateDeviceID)
-
-
- def _allocateDeviceID(self, t):
- result = t.read("nextDeviceID")
- if result:
- result = int(result)
- else:
- result = 0
- t.write("nextDeviceID", str(result + 1))
- return result
-
-
- def removeBackend(self, devid, *args):
- frontpath = self.frontendPath(devid)
- backpath = xstransact.Read(frontpath, "backend")
- if backpath:
- return xstransact.Remove(backpath, *args)
- else:
- raise VmError("Device %s not connected" % devid)
-
- def readVm(self, devid, *args):
- devpath = self.devicePath(devid)
- if devpath:
- return xstransact.Read(devpath, *args)
- else:
- raise VmError("Device config %s not found" % devid)
-
- def readBackend(self, devid, *args):
- backpath = self.readVm(devid, "backend")
- if backpath:
- return xstransact.Read(backpath, *args)
- else:
- raise VmError("Device %s not connected" % devid)
-
- def readBackendTxn(self, transaction, devid, *args):
- backpath = self.readVm(devid, "backend")
- if backpath:
- paths = map(lambda x: backpath + "/" + x, args)
- return transaction.read(*paths)
- else:
- raise VmError("Device %s not connected" % devid)
-
- def readFrontend(self, devid, *args):
- return xstransact.Read(self.frontendPath(devid), *args)
-
- def readFrontendTxn(self, transaction, devid, *args):
- paths = map(lambda x: self.frontendPath(devid) + "/" + x, args)
- return transaction.read(*paths)
-
- def deviceIDs(self, transaction = None):
- """@return The IDs of each of the devices currently configured for
- this instance's deviceClass.
- """
- fe = self.deviceRoot()
-
- if transaction:
- return map(lambda x: int(x.split('/')[-1]), transaction.list(fe))
- else:
- return map(int, xstransact.List(fe))
-
-
- def writeBackend(self, devid, *args):
- backpath = self.readVm(devid, "backend")
-
- if backpath:
- xstransact.Write(backpath, *args)
- else:
- raise VmError("Device %s not connected" % devid)
-
-
-## private:
-
- def addStoreEntries(self, config, devid, backDetails, frontDetails):
- """Add to backDetails and frontDetails the entries to be written in
- the store to trigger creation of a device. The backend domain ID is
- taken from the given config, paths for frontend and backend are
- computed, and these are added to the backDetails and frontDetails
- dictionaries for writing to the store, including references from
- frontend to backend and vice versa.
-
- @return A pair of (backpath, frontpath). backDetails and frontDetails
- will have been updated appropriately, also.
-
- @param config The configuration of the device, as given to
- {@link #createDevice}.
- @param devid As returned by {@link #getDeviceDetails}.
- @param backDetails As returned by {@link #getDeviceDetails}.
- @param frontDetails As returned by {@link #getDeviceDetails}.
- """
-
- import xen.xend.XendDomain
- xd = xen.xend.XendDomain.instance()
-
- backdom_name = config.get('backend')
- if backdom_name:
- backdom = xd.domain_lookup_nr(backdom_name)
- else:
- backdom = xd.privilegedDomain()
-
- if not backdom:
- raise VmError("Cannot configure device for unknown backend %s" %
- backdom_name)
-
- frontpath = self.frontendPath(devid)
- backpath = self.backendPath(backdom, devid)
-
- frontDetails.update({
- 'backend' : backpath,
- 'backend-id' : "%i" % backdom.getDomid(),
- 'state' : str(xenbusState['Initialising'])
- })
-
- if self.vm.native_protocol:
- frontDetails.update({'protocol' : self.vm.native_protocol})
-
- backDetails.update({
- 'domain' : self.vm.getName(),
- 'frontend' : frontpath,
- 'frontend-id' : "%i" % self.vm.getDomid(),
- 'state' : str(xenbusState['Initialising']),
- 'online' : "1"
- })
-
- return (backpath, frontpath)
-
-
- def waitForBackend(self, devid):
- frontpath = self.frontendPath(devid)
- # lookup a phantom
- phantomPath = xstransact.Read(frontpath, 'phantom_vbd')
- if phantomPath is not None:
- log.debug("Waiting for %s's phantom %s.", devid, phantomPath)
- statusPath = phantomPath + '/' + HOTPLUG_STATUS_NODE
- ev = Event()
- result = { 'status': Timeout }
- xswatch(statusPath, hotplugStatusCallback, ev, result)
- ev.wait(DEVICE_CREATE_TIMEOUT)
- err = xstransact.Read(statusPath, HOTPLUG_ERROR_NODE)
- if result['status'] != Connected:
- return (result['status'], err)
-
- backpath = self.readVm(devid, "backend")
-
- if backpath:
- statusPath = backpath + '/' + HOTPLUG_STATUS_NODE
- ev = Event()
- result = { 'status': Timeout }
-
- xswatch(statusPath, hotplugStatusCallback, ev, result)
-
- ev.wait(DEVICE_CREATE_TIMEOUT)
-
- err = xstransact.Read(backpath, HOTPLUG_ERROR_NODE)
-
- return (result['status'], err)
- else:
- return (Missing, None)
-
-
- def waitForBackend_destroy(self, backpath):
-
- statusPath = backpath + '/' + HOTPLUG_STATUS_NODE
- ev = Event()
- result = { 'status': Timeout }
-
- xswatch(statusPath, deviceDestroyCallback, ev, result)
-
- ev.wait(DEVICE_DESTROY_TIMEOUT)
-
- return result['status']
-
- def waitForBackend_reconfigure(self, devid):
- frontpath = self.frontendPath(devid)
- backpath = xstransact.Read(frontpath, "backend")
- if backpath:
- statusPath = backpath + '/' + "state"
- ev = Event()
- result = { 'status': Timeout }
-
- xswatch(statusPath, xenbusStatusCallback, ev, result)
-
- ev.wait(DEVICE_CREATE_TIMEOUT)
-
- return (result['status'], None)
- else:
- return (Missing, None)
-
-
- def backendPath(self, backdom, devid):
- """Construct backend path given the backend domain and device id.
-
- @param backdom [XendDomainInfo] The backend domain info."""
-
- return "%s/backend/%s/%s/%d" % (backdom.getDomainPath(),
- self.deviceClass,
- self.vm.getDomid(), devid)
-
-
- def frontendPath(self, devid):
- return "%s/%d" % (self.frontendRoot(), devid)
-
-
- def frontendRoot(self):
- return "%s/device/%s" % (self.vm.getDomainPath(), self.deviceClass)
-
- def frontendMiscPath(self):
- return "%s/device-misc/%s" % (self.vm.getDomainPath(),
- self.deviceClass)
-
- def deviceRoot(self):
- """Return the /vm/device. Because backendRoot assumes the
- backend domain is 0"""
- return "%s/device/%s" % (self.vm.vmpath, self.deviceClass)
-
- def devicePath(self, devid):
- """Return the /device entry of the given VM. We use it to store
- backend/frontend locations"""
- return "%s/device/%s/%s" % (self.vm.vmpath,
- self.deviceClass, devid)
-
-def hotplugStatusCallback(statusPath, ev, result):
- log.debug("hotplugStatusCallback %s.", statusPath)
-
- status = xstransact.Read(statusPath)
-
- if status is not None:
- if status == HOTPLUG_STATUS_ERROR:
- result['status'] = Error
- elif status == HOTPLUG_STATUS_BUSY:
- result['status'] = Busy
- else:
- result['status'] = Connected
- else:
- return 1
-
- log.debug("hotplugStatusCallback %d.", result['status'])
-
- ev.set()
- return 0
-
-
-def deviceDestroyCallback(statusPath, ev, result):
- log.debug("deviceDestroyCallback %s.", statusPath)
-
- status = xstransact.Read(statusPath)
-
- if status is None:
- result['status'] = Disconnected
- else:
- return 1
-
- log.debug("deviceDestroyCallback %d.", result['status'])
-
- ev.set()
- return 0
-
-
-def xenbusStatusCallback(statusPath, ev, result):
- log.debug("xenbusStatusCallback %s.", statusPath)
-
- status = xstransact.Read(statusPath)
-
- if status == str(xenbusState['Connected']):
- result['status'] = Connected
- else:
- return 1
-
- log.debug("xenbusStatusCallback %d.", result['status'])
-
- ev.set()
- return 0
diff --git a/tools/python/xen/xend/server/SSLXMLRPCServer.py b/tools/python/xen/xend/server/SSLXMLRPCServer.py
deleted file mode 100644
index 1bbd636..0000000
--- a/tools/python/xen/xend/server/SSLXMLRPCServer.py
+++ /dev/null
@@ -1,103 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2007 XenSource Inc.
-#============================================================================
-
-
-"""
-HTTPS wrapper for an XML-RPC server interface. Requires PyOpenSSL (Debian
-package python-pyopenssl).
-"""
-
-import socket
-
-from OpenSSL import SSL
-
-from xen.util.xmlrpclib2 import XMLRPCRequestHandler, TCPXMLRPCServer
-
-
-class SSLXMLRPCRequestHandler(XMLRPCRequestHandler):
- def setup(self):
- self.connection = self.request
- self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
- self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
-
-#
-# Taken from pyOpenSSL-0.6 examples (public-domain)
-#
-
-class SSLWrapper:
- """
- """
- def __init__(self, conn):
- """
- Connection is not yet a new-style class,
- so I'm making a proxy instead of subclassing.
- """
- self.__dict__["conn"] = conn
- def __getattr__(self, name):
- return getattr(self.__dict__["conn"], name)
- def __setattr__(self, name, value):
- setattr(self.__dict__["conn"], name, value)
-
- def close(self):
- self.shutdown()
- return self.__dict__["conn"].close()
-
- def shutdown(self, how=1):
- """
- SimpleXMLRpcServer.doPOST calls shutdown(1),
- and Connection.shutdown() doesn't take
- an argument. So we just discard the argument.
- """
- # Block until the shutdown is complete
- self.__dict__["conn"].shutdown()
- self.__dict__["conn"].shutdown()
-
- def accept(self):
- """
- This is the other part of the shutdown() workaround.
- Since servers create new sockets, we have to infect
- them with our magic. :)
- """
- c, a = self.__dict__["conn"].accept()
- return (SSLWrapper(c), a)
-
-#
-# End of pyOpenSSL-0.6 example code.
-#
-
-class SSLXMLRPCServer(TCPXMLRPCServer):
- def __init__(self, addr, allowed, xenapi, logRequests = 1,
- ssl_key_file = None, ssl_cert_file = None):
-
- TCPXMLRPCServer.__init__(self, addr, allowed, xenapi,
- SSLXMLRPCRequestHandler, logRequests)
-
- if not ssl_key_file or not ssl_cert_file:
- raise ValueError("SSLXMLRPCServer requires ssl_key_file "
- "and ssl_cert_file to be set.")
-
- # make a SSL socket
- ctx = SSL.Context(SSL.SSLv23_METHOD)
- ctx.set_options(SSL.OP_NO_SSLv2)
- ctx.use_privatekey_file (ssl_key_file)
- ctx.use_certificate_file(ssl_cert_file)
- self.socket = SSLWrapper(SSL.Connection(ctx,
- socket.socket(self.address_family,
- self.socket_type)))
- self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- self.server_bind()
- self.server_activate()
diff --git a/tools/python/xen/xend/server/SrvDaemon.py b/tools/python/xen/xend/server/SrvDaemon.py
deleted file mode 100644
index 0a330f1..0000000
--- a/tools/python/xen/xend/server/SrvDaemon.py
+++ /dev/null
@@ -1,420 +0,0 @@
-###########################################################
-## Xen controller daemon
-## Copyright (c) 2004, K A Fraser (University of Cambridge)
-## Copyright (C) 2004, Mike Wray <mike.wray at hp.com>
-## Copyright (C) 2005, XenSource Ltd
-###########################################################
-
-import os
-import os.path
-import signal
-import stat
-import sys
-import threading
-import time
-import linecache
-import pwd
-import re
-import traceback
-
-import xen.lowlevel.xc
-
-from xen.xend.XendLogging import log
-from xen.xend import osdep
-from xen.util import mkdir
-
-import relocate
-import udevevent
-import SrvServer
-from params import *
-
-
-XEND_PROCESS_NAME = 'xend'
-
-
-class Daemon:
- """The xend daemon.
- """
- def __init__(self):
- self.traceon = False
- self.tracefile = None
- self.traceindent = 0
- self.child = 0
- self.traceLock = threading.Lock()
-
-
- def cleanup_xend(self, kill):
- """Clean up the Xend pidfile.
- If a running process is found, kills it if 'kill' is true.
-
- @param kill: whether to kill the process
- @return running process id or 0
- """
- running = 0
- pid = read_pid(XEND_PID_FILE)
- if find_process(pid, XEND_PROCESS_NAME):
- if kill:
- os.kill(pid, signal.SIGTERM)
- else:
- running = pid
- if running == 0 and os.path.isfile(XEND_PID_FILE):
- os.remove(XEND_PID_FILE)
- return running
-
-
- def reloadConfig(self):
- """
- """
- pid = read_pid(XEND_PID_FILE)
- if find_process(pid, XEND_PROCESS_NAME):
- os.kill(pid, signal.SIGHUP)
-
-
- def status(self):
- """Returns the status of the xend daemon.
- The return value is defined by the LSB:
- 0 Running
- 3 Not running
- """
- if self.cleanup_xend(False) == 0:
- return 3
- else:
- return 0
-
-
- def fork_pid(self):
- """Fork and write the pid of the child to XEND_PID_FILE.
-
- @return: pid of child in parent, 0 in child
- """
-
- self.child = os.fork()
-
- if self.child:
- # Parent
- pidfile = open(XEND_PID_FILE, 'w')
- try:
- pidfile.write(str(self.child))
- finally:
- pidfile.close()
-
- return self.child
-
-
- def daemonize(self):
- # Detach from TTY.
-
- # Become the group leader (already a child process)
- os.setsid()
-
- # Fork, this allows the group leader to exit,
- # which means the child can never again regain control of the
- # terminal
- if os.fork():
- os._exit(0)
-
- # Detach from standard file descriptors, and redirect them to
- # /dev/null or the log as appropriate.
- # We open the log file first, so that we can diagnose a failure to do
- # so _before_ we close stderr.
- try:
- parent = os.path.dirname(XEND_DEBUG_LOG)
- mkdir.parents(parent, stat.S_IRWXU)
- fd = os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT|os.O_APPEND, 0666)
- except Exception, exn:
- print >>sys.stderr, exn
- print >>sys.stderr, ("Xend failed to open %s. Exiting!" %
- XEND_DEBUG_LOG)
- sys.exit(1)
-
- os.close(0)
- os.close(1)
- os.close(2)
- if XEND_DEBUG:
- os.open('/dev/null', os.O_RDONLY)
- os.dup(fd)
- os.dup(fd)
- else:
- os.open('/dev/null', os.O_RDWR)
- os.dup(0)
- os.dup(fd)
- os.close(fd)
-
- print >>sys.stderr, ("Xend started at %s." %
- time.asctime(time.localtime()))
-
-
- def start(self, trace=0):
- """Attempts to start the daemons.
- The return value is defined by the LSB:
- 0 Success
- 4 Insufficient privileges
- """
- xend_pid = self.cleanup_xend(False)
-
- if self.set_user():
- return 4
- os.chdir("/")
-
- if xend_pid > 0:
- # Trying to run an already-running service is a success.
- return 0
-
- ret = 0
-
- # If we're not going to create a daemon, simply
- # call the run method right here.
- if not XEND_DAEMONIZE:
- self.tracing(trace)
- self.run(None)
- return ret
-
- # we use a pipe to communicate between the parent and the child process
- # this way we know when the child has actually initialized itself so
- # we can avoid a race condition during startup
-
- r,w = os.pipe()
- if os.fork():
- os.close(w)
- r = os.fdopen(r, 'r')
- try:
- s = r.read()
- finally:
- r.close()
- if not len(s):
- ret = 1
- else:
- ret = int(s)
- else:
- os.close(r)
- # Child
- self.daemonize()
- self.tracing(trace)
-
- # If Xend proper segfaults, then we want to restart it. Thus,
- # we fork a child for running Xend itself, and if it segfaults
- # (or exits any way other than cleanly) then we run it again.
- # The first time through we want the server to write to the (r,w)
- # pipe created above, so that we do not exit until the server is
- # ready to receive requests. All subsequent restarts we don't
- # want this behaviour, or the pipe will eventually fill up, so
- # we just pass None into run in subsequent cases (by clearing w
- # in the parent of the first fork). On some operating systems,
- # restart is managed externally, so we won't fork, and just exit.
- while True:
-
- if not osdep.xend_autorestart:
- self.run(os.fdopen(w, 'w'))
- os._exit(0)
-
- pid = self.fork_pid()
- if pid:
- if w is not None:
- os.close(w)
- w = None
-
- (_, status) = os.waitpid(pid, 0)
-
- if os.WIFEXITED(status):
- code = os.WEXITSTATUS(status)
- log.info('Xend exited with status %d.', code)
- sys.exit(code)
-
- if os.WIFSIGNALED(status):
- sig = os.WTERMSIG(status)
-
- if sig in (signal.SIGINT, signal.SIGTERM):
- log.info('Xend stopped due to signal %d.', sig)
- sys.exit(0)
- else:
- log.fatal(
- 'Xend died due to signal %d! Restarting it.',
- sig)
- else:
- self.run(w and os.fdopen(w, 'w') or None)
- # if we reach here, the child should quit.
- os._exit(0)
-
- return ret
-
- def tracing(self, traceon):
- """Turn tracing on or off.
-
- @param traceon: tracing flag
- """
- if traceon == self.traceon:
- return
- self.traceon = traceon
- if traceon:
- self.tracefile = open(XEND_TRACE_FILE, 'w+', 1)
- self.traceindent = 0
- sys.settrace(self.trace)
- try:
- threading.settrace(self.trace) # Only in Python >= 2.3
- except:
- pass
-
- def print_trace(self, string):
- self.tracefile.write("%s: "% threading.currentThread().getName())
- for i in range(self.traceindent):
- ch = " "
- if (i % 5):
- ch = ' '
- else:
- ch = '|'
- self.tracefile.write(ch)
- self.tracefile.write(string)
-
- def trace(self, frame, event, arg):
- self.traceLock.acquire()
- try:
- if not self.traceon:
- print >>self.tracefile
- print >>self.tracefile, '-' * 20, 'TRACE OFF', '-' * 20
- self.tracefile.close()
- self.tracefile = None
- return None
- if event == 'call':
- code = frame.f_code
- filename = code.co_filename
- m = re.search('.*xend/(.*)', filename)
- if not m:
- return None
- modulename = m.group(1)
- if modulename.endswith('.pyc'):
- modulename = modulename[:-1]
- if modulename == 'sxp.py' or \
- modulename == 'XendLogging.py' or \
- modulename == 'XendMonitor.py' or \
- modulename == 'server/SrvServer.py':
- return None
- self.traceindent += 1
- self.print_trace("> %s:%s\n"
- % (modulename, code.co_name))
- elif event == 'line':
- filename = frame.f_code.co_filename
- lineno = frame.f_lineno
- self.print_trace("%4d %s" %
- (lineno, linecache.getline(filename, lineno)))
- elif event == 'return':
- code = frame.f_code
- filename = code.co_filename
- m = re.search('.*xend/(.*)', filename)
- if not m:
- return None
- modulename = m.group(1)
- self.print_trace("< %s:%s\n"
- % (modulename, code.co_name))
- self.traceindent -= 1
- elif event == 'exception':
- self.print_trace("! Exception:\n")
- (ex, val, tb) = arg
- traceback.print_exception(ex, val, tb, 10, self.tracefile)
- #del tb
- return self.trace
- finally:
- self.traceLock.release()
-
- def set_user(self):
- # Set the UID.
- try:
- os.setuid(pwd.getpwnam(XEND_USER)[2])
- return 0
- except KeyError:
- print >>sys.stderr, "Error: no such user '%s'" % XEND_USER
- return 1
-
- def stop(self):
- return self.cleanup_xend(True)
-
- def run(self, status):
- try:
- log.info("Xend Daemon started")
-
- xc = xen.lowlevel.xc.xc()
- xinfo = xc.xeninfo()
- log.info("Xend changeset: %s.", xinfo['xen_changeset'])
- del xc
-
- relocate.listenRelocation()
- udevevent.listenUdevEvent()
- servers = SrvServer.create()
- servers.start(status)
- del servers
-
- except Exception, ex:
- print >>sys.stderr, 'Exception starting xend:', ex
- if XEND_DEBUG:
- traceback.print_exc()
- log.exception("Exception starting xend (%s)" % ex)
- if status:
- status.write('1')
- status.close()
- sys.exit(1)
-
-def instance():
- global inst
- try:
- inst
- except:
- inst = Daemon()
- return inst
-
-
-def read_pid(pidfile):
- """Read process id from a file.
-
- @param pidfile: file to read
- @return pid or 0
- """
- if os.path.isfile(pidfile) and os.path.getsize(pidfile):
- try:
- f = open(pidfile, 'r')
- try:
- return int(f.read())
- finally:
- f.close()
- except:
- return 0
- else:
- return 0
-
-
-def find_process(pid, name):
- """Search for a process.
-
- @param pid: process id
- @param name: process name
- @return: pid if found, 0 otherwise
- """
- running = 0
- if pid:
- lines = os.popen('ps %d 2>/dev/null' % pid).readlines()
- exp = '^ *%d.+%s' % (pid, name)
- for line in lines:
- if re.search(exp, line):
- running = pid
- break
- return running
-
-
-def main(argv = None):
- global XEND_DAEMONIZE
-
- XEND_DAEMONIZE = False
- if argv is None:
- argv = sys.argv
-
- try:
- daemon = instance()
-
- r,w = os.pipe()
- daemon.run(os.fdopen(w, 'w'))
- return 0
- except Exception, exn:
- log.fatal(exn)
- return 1
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/tools/python/xen/xend/server/SrvDmesg.py b/tools/python/xen/xend/server/SrvDmesg.py
deleted file mode 100644
index 18c453a..0000000
--- a/tools/python/xen/xend/server/SrvDmesg.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-
-from xen.xend import XendDmesg
-
-from xen.web.SrvDir import SrvDir
-
-
-class SrvDmesg(SrvDir):
- """Xen Dmesg output.
- """
-
- def __init__(self):
- SrvDir.__init__(self)
- self.xd = XendDmesg.instance()
-
- def render_POST(self, req):
- self.perform(req)
-
- def render_GET(self, req):
- if self.use_sxp(req):
- req.setHeader("Content-Type", "text/plain")
- req.write(self.info())
- else:
- req.write('<html><head></head><body>')
- self.print_path(req)
- req.write('<pre>')
- req.write(self.info())
- req.write('</pre></body></html>')
-
- def info(self):
- return self.xd.info()
-
- def op_clear(self, _1, _2):
- self.xd.clear()
- return 0
diff --git a/tools/python/xen/xend/server/SrvDomain.py b/tools/python/xen/xend/server/SrvDomain.py
deleted file mode 100644
index aa07b7a..0000000
--- a/tools/python/xen/xend/server/SrvDomain.py
+++ /dev/null
@@ -1,329 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 Xensource Ltd
-#============================================================================
-
-from xen.web import http
-
-from xen.xend import sxp
-from xen.xend import XendDomain
-from xen.xend.Args import FormFn
-from xen.xend.XendLogging import log
-
-from xen.web.SrvDir import SrvDir
-
-class SrvDomain(SrvDir):
- """Service managing a single domain.
- """
-
- def __init__(self, dom):
- SrvDir.__init__(self)
- self.dom = dom
- self.xd = XendDomain.instance()
-
- def op_configure(self, _, req):
- """Configure an existing domain.
- Configure is unusual in that it requires a domain id,
- not a domain name.
- """
- fn = FormFn(self.xd.domain_configure,
- [['dom', 'int'],
- ['config', 'sxpr']])
- return fn(req.args, {'dom': self.dom.domid})
-
- def op_unpause(self, _1, _2):
- val = self.xd.domain_unpause(self.dom.domid)
- return val
-
- def op_pause(self, _1, _2):
- val = self.xd.domain_pause(self.dom.domid)
- return val
-
- def acceptCommand(self, req):
- req.setResponseCode(http.ACCEPTED)
- req.setHeader("Location", "%s/.." % req.prePathURL())
-
- def op_rename(self, _, req):
- self.acceptCommand(req)
- return self.dom.setName(req.args['name'][0])
-
- def op_shutdown(self, _, req):
- self.acceptCommand(req)
- return self.dom.shutdown(req.args['reason'][0])
-
- def op_delete(self, _, req):
- self.acceptCommand(req)
- return self.xd.domain_delete(self.dom.getName())
-
- def op_start(self, _, req):
- self.acceptCommand(req)
- paused = False
- if 'paused' in req.args and req.args['paused'] == [1]:
- paused = True
- log.debug("Starting domain " + self.dom.getName() + " " + str(paused))
- return self.xd.domain_start(self.dom.getName(), paused)
-
- def op_sysrq(self, _, req):
- self.acceptCommand(req)
- return self.dom.send_sysrq(int(req.args['key'][0]))
-
- def op_wait_for_devices(self, _, req):
- self.acceptCommand(req)
- return self.dom.waitForDevices()
-
- def op_destroy(self, _, req):
- self.acceptCommand(req)
- return self.xd.domain_destroy(self.dom.domid)
-
- def op_save(self, op, req):
- self.acceptCommand(req)
- return req.threadRequest(self.do_save, op, req)
-
- def do_save(self, _, req):
- return self.xd.domain_save(self.dom.domid, req.args['file'][0])
-
- def op_dump(self, op, req):
- self.acceptCommand(req)
- return req.threadRequest(self.do_dump, op, req)
-
- def do_dump(self, _, req):
- fn = FormFn(self.xd.domain_dump,
- [['dom', 'int'],
- ['file', 'str'],
- ['live', 'int'],
- ['crash', 'int'],
- ['reset', 'int']])
- return fn(req.args, {'dom': self.dom.domid})
-
- def op_migrate(self, op, req):
- return req.threadRequest(self.do_migrate, op, req)
-
- def do_migrate(self, _, req):
- fn = FormFn(self.xd.domain_migrate,
- [['dom', 'int'],
- ['destination', 'str'],
- ['live', 'int'],
- ['port', 'int'],
- ['node', 'int'],
- ['ssl', 'int'],
- ['change_home_server', 'bool']])
- return fn(req.args, {'dom': self.dom.domid})
-
- def op_pincpu(self, _, req):
- fn = FormFn(self.xd.domain_pincpu,
- [['dom', 'str'],
- ['vcpu', 'str'],
- ['cpumap', 'str']])
- val = fn(req.args, {'dom': self.dom.getName()})
- return val
-
- def op_cpu_sedf_get(self, _, req):
- fn = FormFn(self.xd.domain_cpu_sedf_get,
- [['dom', 'int']])
- val = fn(req.args, {'dom': self.dom.domid})
- return val
-
-
- def op_cpu_sedf_set(self, _, req):
- fn = FormFn(self.xd.domain_cpu_sedf_set,
- [['dom', 'int'],
- ['period', 'int'],
- ['slice', 'int'],
- ['latency', 'int'],
- ['extratime', 'int'],
- ['weight', 'int']])
- val = fn(req.args, {'dom': self.dom.domid})
- return val
-
- def op_domain_sched_credit_get(self, _, req):
- fn = FormFn(self.xd.domain_sched_credit_get,
- [['dom', 'str']])
- val = fn(req.args, {'dom': self.dom.getName()})
- return val
-
-
- def op_domain_sched_credit_set(self, _, req):
- fn = FormFn(self.xd.domain_sched_credit_set,
- [['dom', 'str'],
- ['weight', 'int'],
- ['cap', 'int']])
- val = fn(req.args, {'dom': self.dom.getName()})
- return val
-
- def op_domain_sched_credit2_get(self, _, req):
- fn = FormFn(self.xd.domain_sched_credit2_get,
- [['dom', 'str']])
- val = fn(req.args, {'dom': self.dom.getName()})
- return val
-
-
- def op_domain_sched_credit2_set(self, _, req):
- fn = FormFn(self.xd.domain_sched_credit2_set,
- [['dom', 'str'],
- ['weight', 'int']])
- val = fn(req.args, {'dom': self.dom.getName()})
- return val
-
- def op_maxmem_set(self, _, req):
- return self.call(self.dom.setMemoryMaximum,
- [['memory', 'int']],
- req)
-
- def call(self, fn, args, req):
- return FormFn(fn, args)(req.args)
-
-
- def op_mem_target_set(self, _, req):
- return self.call(self.dom.setMemoryTarget,
- [['target', 'int']],
- req)
-
- def op_devices(self, _, req):
- return self.call(self.dom.getDeviceSxprs,
- [['type', 'str']],
- req)
-
- def op_device_create(self, _, req):
- return self.call(self.dom.device_create,
- [['config', 'sxpr']],
- req)
-
- def op_device_destroy(self, _, req):
- return self.call(self.dom.destroyDevice,
- [['type', 'str'],
- ['dev', 'str'],
- ['force', 'int'],
- ['rm_cfg', 'int']],
- req)
-
- def op_device_configure(self, _, req):
- return self.call(self.dom.device_configure,
- [['config', 'sxpr'],
- ['dev', 'str']],
- req)
-
-
- def op_vif_limit_set(self, _, req):
- fn = FormFn(self.xd.domain_vif_limit_set,
- [['dom', 'int'],
- ['vif', 'int'],
- ['credit', 'int'],
- ['period', 'int']])
- val = fn(req.args, {'dom': self.dom.domid})
- return val
-
- def op_set_vcpus(self, _, req):
- return self.call(self.dom.setVCpuCount,
- [['vcpus', 'int']],
- req)
-
-
- def op_vcpuinfo(self, _1, req):
- return self.call(self.dom.getVCPUInfo, [], req)
-
-
- def op_reset(self, _, req):
- self.acceptCommand(req)
- return self.xd.domain_reset(self.dom.getName())
-
- def op_do_get_pauseflag(self, op, req):
- self.acceptCommand(req)
- return req.threadRequest(self.do_get_pauseflag, op, req)
-
- def do_get_pauseflag(self, _, req):
- return self.xd.domain_getpauseflag(self.dom.getName(), req)
-
- def op_do_set_pauseflag(self, op, req):
- self.acceptCommand(req)
- return req.threadRequest(self.do_set_pauseflag, op, req)
-
- def do_set_pauseflag(self, _, req):
- return self.xd.domain_setpauseflag(self.dom.getName(), req)
-
- def op_usb_add(self, op, req):
- self.acceptCommand(req)
- return req.threadRequest(self.do_usb_add, op, req)
-
- def do_usb_add(self, _, req):
- return self.xd.domain_usb_add(self.dom.getName(), req)
-
- def op_usb_del(self, op, req):
- self.acceptCommand(req)
- return req.threadRequest(self.do_usb_del, op, req)
-
- def do_usb_del(self, _, req):
- return self.xd.domain_usb_del(self.dom.getName(), req)
-
- def render_POST(self, req):
- return self.perform(req)
-
- def render_GET(self, req):
- op = req.args.get('op')
-
- if op and op[0] in ['vcpuinfo']:
- return self.perform(req)
-
- #
- # XXX SMH: below may be useful once again if we ever try to get
- # the raw 'web' interface to xend working once more. But for now
- # is useless and out of date (i.e. no ops called 'v???' anymore).
- #
- # if op and op[0] in ['vifs', 'vif', 'vbds', 'vbd', 'mem_target_set']:
- # return self.perform(req)
- if self.use_sxp(req):
- req.setHeader("Content-Type", sxp.mime_type)
- sxp.show(self.dom.sxpr(), out=req)
- else:
- req.write('<html><head></head><body>')
- self.print_path(req)
- #self.ls()
- req.write('<p>%s</p>' % self.dom)
- self.form(req)
- req.write('</body></html>')
- return ''
-
- def form(self, req):
- url = req.prePathURL()
- req.write('<form method="post" action="%s">' % url)
- req.write('<input type="submit" name="op" value="unpause">')
- req.write('<input type="submit" name="op" value="pause">')
- req.write('</form>')
-
- req.write('<form method="post" action="%s">' % url)
- req.write('<input type="submit" name="op" value="destroy">')
- req.write('</form>')
-
- req.write('<form method="post" action="%s">' % url)
- req.write('<input type="submit" name="op" value="reset">')
- req.write('</form>')
-
- req.write('<form method="post" action="%s">' % url)
- req.write('<input type="submit" name="op" value="shutdown">')
- req.write('<input type="radio" name="reason" value="poweroff" checked>Poweroff')
- req.write('<input type="radio" name="reason" value="halt">Halt')
- req.write('<input type="radio" name="reason" value="reboot">Reboot')
- req.write('</form>')
-
- req.write('<form method="post" action="%s">' % url)
- req.write('<br><input type="submit" name="op" value="save">')
- req.write(' To file: <input type="text" name="file">')
- req.write('</form>')
-
- req.write('<form method="post" action="%s">' % url)
- req.write('<br><input type="submit" name="op" value="migrate">')
- req.write(' To host: <input type="text" name="destination">')
- req.write('<input type="checkbox" name="live" value="1">Live')
- req.write('</form>')
diff --git a/tools/python/xen/xend/server/SrvDomainDir.py b/tools/python/xen/xend/server/SrvDomainDir.py
deleted file mode 100644
index dcd79b0..0000000
--- a/tools/python/xen/xend/server/SrvDomainDir.py
+++ /dev/null
@@ -1,222 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
-
-import traceback
-from StringIO import StringIO
-
-from xen.web import http
-
-from xen.xend import sxp
-from xen.xend import XendDomain
-from xen.xend.XendDomainInfo import XendDomainInfo
-from xen.xend.Args import FormFn
-from xen.xend.XendError import XendError
-from xen.xend.XendLogging import log
-from xen.xend.XendConstants import DOM_STATE_RUNNING
-
-from xen.web.SrvDir import SrvDir
-from SrvDomain import SrvDomain
-
-
-class SrvDomainDir(SrvDir):
- """Service that manages the domain directory.
- """
-
- def __init__(self):
- SrvDir.__init__(self)
- self.xd = XendDomain.instance()
-
- def domain(self, x):
- dom = self.xd.domain_lookup(x)
- return SrvDomain(dom)
-
- def get(self, x):
- v = SrvDir.get(self, x)
- if v is not None:
- return v
- else:
- return self.domain(x)
-
- def op_create(self, _, req):
- """Create a domain.
- Expects the domain config in request parameter 'config' in SXP format.
- """
- ok = 0
- errmsg = ''
- try:
- configstring = req.args.get('config')[0]
- #print 'op_create>', 'config:', configstring
- pin = sxp.Parser()
- pin.input(configstring)
- pin.input_eof()
- config = pin.get_val()
- ok = 1
- except sxp.ParseError, ex:
- errmsg = 'Invalid configuration ' + str(ex)
- except Exception, ex:
- print 'op_create> Exception in config', ex
- traceback.print_exc()
- errmsg = 'Configuration error ' + str(ex)
- if not ok:
- raise XendError(errmsg)
- try:
- dominfo = self.xd.domain_create(config)
- return self._op_create_cb(dominfo, configstring, req)
- except Exception, ex:
- print 'op_create> Exception creating domain:'
- traceback.print_exc()
- raise XendError("Error creating domain: " + str(ex))
-
- def _op_create_cb(self, dominfo, configstring, req):
- """Callback to handle domain creation.
- """
- dom = dominfo.getName()
- domurl = "%s/%s" % (req.prePathURL(), dom)
- req.setResponseCode(http.CREATED, "created")
- req.setHeader("Location", domurl)
- if self.use_sxp(req):
- return dominfo.sxpr()
- else:
- out = StringIO()
- print >> out, ('<p> Created <a href="%s">Domain %s</a></p>'
- % (domurl, dom))
- print >> out, '<p><pre>'
- print >> out, configstring
- print >> out, '</pre></p>'
- val = out.getvalue()
- out.close()
- return val
-
- def op_new(self, _, req):
- """Define a new domain.
- Expects the domain config in request parameter 'config' in SXP format.
- """
- ok = 0
- errmsg = ''
- try:
- configstring = req.args.get('config')[0]
- #print 'op_create>', 'config:', configstring
- pin = sxp.Parser()
- pin.input(configstring)
- pin.input_eof()
- config = pin.get_val()
- ok = 1
- except sxp.ParseError, ex:
- errmsg = 'Invalid configuration ' + str(ex)
- except Exception, ex:
- print 'op_create> Exception in config', ex
- traceback.print_exc()
- errmsg = 'Configuration error ' + str(ex)
- if not ok:
- raise XendError(errmsg)
- try:
- self.xd.domain_new(config)
- except Exception, ex:
- print 'op_create> Exception creating domain:'
- traceback.print_exc()
- raise XendError("Error creating domain: " + str(ex))
-
- def op_restore(self, op, req):
- """Restore a domain from file.
-
- """
- return req.threadRequest(self.do_restore, op, req)
-
- def do_restore(self, _, req):
- fn = FormFn(self.xd.domain_restore,
- [['file', 'str']])
- dominfo = fn(req.args)
- dom = dominfo.getName()
- domurl = "%s/%s" % (req.prePathURL(), dom)
- req.setResponseCode(http.CREATED)
- req.setHeader("Location", domurl)
- if self.use_sxp(req):
- return dominfo.sxpr()
- else:
- out = StringIO()
- print >> out, ('<p> Created <a href="%s">Domain %s</a></p>'
- % (domurl, dom))
- val = out.getvalue()
- out.close()
- return val
-
-
- def op_list(self, _, req):
- """List the details for this domain."""
- self._list(req, True)
-
-
- def render_POST(self, req):
- return self.perform(req)
-
- def render_GET(self, req):
- self._list(req, 'detail' in req.args and req.args['detail'] == ['1'])
-
-
- def _list(self, req, detail):
- if self.use_sxp(req):
- req.setHeader("Content-Type", sxp.mime_type)
- self.ls_domain(req, detail, True)
- else:
- req.write("<html><head></head><body>")
- self.print_path(req)
- self.ls(req)
- self.ls_domain(req, detail, False)
- self.form(req)
- req.write("</body></html>")
-
-
- def ls_domain(self, req, detail, use_sxp):
- url = req.prePathURL()
- if not url.endswith('/'):
- url += '/'
- if use_sxp:
- if detail:
- sxp.show(map(XendDomainInfo.sxpr, self.xd.list()), out=req)
- else:
- state = DOM_STATE_RUNNING
- if 'state' in req.args and len(req.args['state']) > 0:
- state = req.args['state'][0]
- log.trace("Listing domains in state " + str(state))
- sxp.show(self.xd.list_names(state), out=req)
- else:
- domains = self.xd.list_sorted()
- req.write('<ul>')
- for d in domains:
- req.write(
- '<li><a href="%s%s">Domain %s</a>: id = %s, memory = %d'
- % (url, d.getName(), d.getName(), d.getDomid(),
- d.getMemoryTarget()))
- req.write('</li>')
- req.write('</ul>')
-
-
- def form(self, req):
- """Generate the form(s) for domain dir operations.
- """
- req.write('<form method="post" action="%s" enctype="multipart/form-data">'
- % req.prePathURL())
- req.write('<button type="submit" name="op" value="create">Create Domain</button>')
- req.write('Config <input type="file" name="config"><br>')
- req.write('</form>')
-
- req.write('<form method="post" action="%s" enctype="multipart/form-data">'
- % req.prePathURL())
- req.write('<button type="submit" name="op" value="restore">Restore Domain</button>')
- req.write('State <input type="string" name="state"><br>')
- req.write('</form>')
-
diff --git a/tools/python/xen/xend/server/SrvNode.py b/tools/python/xen/xend/server/SrvNode.py
deleted file mode 100644
index 1f9030d..0000000
--- a/tools/python/xen/xend/server/SrvNode.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
-
-
-from xen.web.SrvDir import SrvDir
-from xen.xend import sxp
-from xen.xend import XendNode
-from xen.xend.Args import FormFn
-
-class SrvNode(SrvDir):
- """Information about the node.
- """
-
- def __init__(self):
- SrvDir.__init__(self)
- self.xn = XendNode.instance()
- self.add('dmesg', 'SrvDmesg')
- self.add('log', 'SrvXendLog')
-
- def op_shutdown(self, _1, _2):
- val = self.xn.shutdown()
- return val
-
- def op_reboot(self, _1, _2):
- val = self.xn.reboot()
- return val
-
- def render_POST(self, req):
- return self.perform(req)
-
- def render_GET(self, req):
- if self.use_sxp(req):
- req.setHeader("Content-Type", sxp.mime_type)
- sxp.show(['node'] + self.info(), out=req)
- else:
- url = req.prePathURL()
- if not url.endswith('/'):
- url += '/'
- req.write('<html><head></head><body>')
- self.print_path(req)
- req.write('<ul>')
- for d in self.info():
- req.write('<li> %10s: %s' % (d[0], str(d[1])))
- req.write('<li><a href="%sdmesg">Xen dmesg output</a>' % url)
- req.write('<li><a href="%slog">Xend log</a>' % url)
- req.write('</ul>')
- req.write('</body></html>')
-
- def info(self):
- return self.xn.info()
diff --git a/tools/python/xen/xend/server/SrvRoot.py b/tools/python/xen/xend/server/SrvRoot.py
deleted file mode 100644
index bd194f3..0000000
--- a/tools/python/xen/xend/server/SrvRoot.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-from xen.web.SrvDir import SrvDir
-
-class SrvRoot(SrvDir):
- """The root of the xend server.
- """
-
- """Server sub-components. Each entry is (name, class), where
- 'name' is the entry name and 'class' is the name of its class.
- """
- #todo Get this list from the XendOptions config.
- subdirs = [
- ('node', 'SrvNode' ),
- ('domain', 'SrvDomainDir' ),
- ('vnet', 'SrvVnetDir' ),
- ]
-
- def __init__(self):
- SrvDir.__init__(self)
- for (name, klass) in self.subdirs:
- self.add(name, klass)
- for (name, klass) in self.subdirs:
- self.get(name)
-
- def __repr__(self):
- return "<SrvRoot %x %s>" %(id(self), self.table.keys())
diff --git a/tools/python/xen/xend/server/SrvServer.py b/tools/python/xen/xend/server/SrvServer.py
deleted file mode 100644
index 9f581f0..0000000
--- a/tools/python/xen/xend/server/SrvServer.py
+++ /dev/null
@@ -1,261 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2006 XenSource Ltd.
-#============================================================================
-
-"""Example xend HTTP
-
- Can be accessed from a browser or from a program.
- Do 'python SrvServer.py' to run the server.
- Then point a web browser at http://localhost:8000/xend and follow the links.
- Most are stubs, except /domain which has a list of domains and a 'create domain'
- button.
-
- You can also access the server from a program.
- Do 'python XendClient.py' to run a few test operations.
-
- The data served differs depending on the client (as defined by User-Agent
- and Accept in the HTTP headers). If the client is a browser, data
- is returned in HTML, with interactive forms. If the client is a program,
- data is returned in SXP format, with no forms.
-
- The server serves to the world by default. To restrict it to the local host
- change 'interface' in main().
-
- Mike Wray <mike.wray at hp.com>
-"""
-# todo Support security settings etc. in the config file.
-# todo Support command-line args.
-
-import fcntl
-import re
-import time
-import signal
-from threading import Thread
-
-from xen.web.httpserver import HttpServer, UnixHttpServer
-
-from xen.xend import XendNode, XendOptions, XendAPI
-from xen.xend.XendLogging import log
-from xen.xend.XendClient import XEN_API_SOCKET
-from xen.xend.XendDomain import instance as xenddomain
-from xen.xend.XendCPUPool import XendCPUPool
-from xen.web.SrvDir import SrvDir
-
-from SrvRoot import SrvRoot
-from XMLRPCServer import XMLRPCServer
-
-xoptions = XendOptions.instance()
-
-
-class XendServers:
-
- def __init__(self, root):
- self.servers = []
- self.root = root
- self.running = False
- self.cleaningUp = False
- self.reloadingConfig = False
-
- def add(self, server):
- self.servers.append(server)
-
- def cleanup(self, signum = 0, frame = None, reloading = False):
- log.debug("SrvServer.cleanup()")
- self.cleaningUp = True
- for server in self.servers:
- try:
- server.shutdown()
- except:
- pass
-
- # clean up domains for those that have on_xend_stop
- if not reloading:
- xenddomain().cleanup_domains()
-
- self.running = False
-
-
- def reloadConfig(self, signum = 0, frame = None):
- log.debug("SrvServer.reloadConfig()")
- self.reloadingConfig = True
- self.cleanup(signum, frame, reloading = True)
-
- def start(self, status):
- # Running the network script will spawn another process, which takes
- # the status fd with it unless we set FD_CLOEXEC. Failing to do this
- # causes the read in SrvDaemon to hang even when we have written here.
- if status:
- fcntl.fcntl(status, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
-
- # Prepare to catch SIGTERM (received when 'xend stop' is executed)
- # and call each server's cleanup if possible
- signal.signal(signal.SIGTERM, self.cleanup)
- signal.signal(signal.SIGHUP, self.reloadConfig)
-
- while True:
- threads = []
- for server in self.servers:
- if server.ready:
- continue
-
- thread = Thread(target=server.run,
- name=server.__class__.__name__)
- thread.setDaemon(True)
- thread.start()
- threads.append(thread)
-
- # check for when all threads have initialized themselves and then
- # close the status pipe
-
- retryCount = 0
- threads_left = True
- while threads_left:
- threads_left = False
-
- for server in self.servers:
- if not server.ready:
- threads_left = True
- break
-
- if threads_left:
- time.sleep(.5)
- retryCount += 1
- if retryCount > 60:
- for server in self.servers:
- if not server.ready:
- log.error("Server " +
- server.__class__.__name__ +
- " did not initialise!")
- break
-
- if status:
- status.write('0')
- status.close()
- status = None
-
- # auto start pools before domains are started
- try:
- XendCPUPool.autostart_pools()
- except Exception, e:
- log.exception("Failed while autostarting pools")
-
- # Reaching this point means we can auto start domains
- try:
- xenddomain().autostart_domains()
- except Exception, e:
- log.exception("Failed while autostarting domains")
-
- # loop to keep main thread alive until it receives a SIGTERM
- self.running = True
- while self.running:
- time.sleep(100000000)
-
- if self.reloadingConfig:
- log.info("Restarting all XML-RPC and Xen-API servers...")
- self.cleaningUp = False
- self.reloadingConfig = False
- xoptions.set_config()
- self.servers = []
- _loadConfig(self, self.root, True)
- else:
- break
-
-def _loadConfig(servers, root, reload):
- if xoptions.get_xend_http_server():
- servers.add(HttpServer(root,
- xoptions.get_xend_address(),
- xoptions.get_xend_port()))
- if xoptions.get_xend_unix_server():
- path = xoptions.get_xend_unix_path()
- log.info('unix path=' + path)
- servers.add(UnixHttpServer(root, path))
-
- api_cfg = xoptions.get_xen_api_server()
- if api_cfg:
- try:
- for server_cfg in api_cfg:
- # Parse the xen-api-server config
-
- ssl_key_file = None
- ssl_cert_file = None
- auth_method = XendAPI.AUTH_NONE
- hosts_allowed = None
-
- host_addr = server_cfg[0].split(':', 1)
- if len(host_addr) == 1:
- if host_addr[0].lower() == 'unix':
- use_tcp = False
- host = 'localhost'
- port = 0
- else:
- use_tcp = True
- host = ''
- port = int(host_addr[0])
- else:
- use_tcp = True
- host = str(host_addr[0])
- port = int(host_addr[1])
-
- if len(server_cfg) > 1:
- if server_cfg[1] in [XendAPI.AUTH_PAM, XendAPI.AUTH_NONE]:
- auth_method = server_cfg[1]
-
- if len(server_cfg) > 2 and len(server_cfg[2]):
- hosts_allowed = map(re.compile, server_cfg[2].split(' '))
-
- if len(server_cfg) > 4:
- # SSL key and cert file
- ssl_key_file = server_cfg[3]
- ssl_cert_file = server_cfg[4]
-
-
- servers.add(XMLRPCServer(auth_method, True, use_tcp = use_tcp,
- ssl_key_file = ssl_key_file,
- ssl_cert_file = ssl_cert_file,
- host = host, port = port,
- path = XEN_API_SOCKET,
- hosts_allowed = hosts_allowed))
-
- except (ValueError, TypeError), exn:
- log.exception('Xen API Server init failed')
- log.error('Xen-API server configuration %s is invalid.', api_cfg)
-
- if xoptions.get_xend_tcp_xmlrpc_server():
- addr = xoptions.get_xend_tcp_xmlrpc_server_address()
- port = xoptions.get_xend_tcp_xmlrpc_server_port()
- ssl_key_file = xoptions.get_xend_tcp_xmlrpc_server_ssl_key_file()
- ssl_cert_file = xoptions.get_xend_tcp_xmlrpc_server_ssl_cert_file()
-
- if ssl_key_file and ssl_cert_file:
- servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, use_tcp = True,
- ssl_key_file = ssl_key_file,
- ssl_cert_file = ssl_cert_file,
- host = addr, port = port))
- else:
- servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, use_tcp = True,
- host = addr, port = port))
-
- if xoptions.get_xend_unix_xmlrpc_server():
- servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False))
-
-
-def create():
- root = SrvDir()
- root.putChild('xend', SrvRoot())
- servers = XendServers(root)
- _loadConfig(servers, root, False)
- return servers
diff --git a/tools/python/xen/xend/server/SrvVnetDir.py b/tools/python/xen/xend/server/SrvVnetDir.py
deleted file mode 100644
index 5dc5b59..0000000
--- a/tools/python/xen/xend/server/SrvVnetDir.py
+++ /dev/null
@@ -1,128 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
-
-from xen.xend import sxp
-from xen.xend.Args import FormFn
-from xen.xend import PrettyPrint
-from xen.xend import XendVnet
-from xen.xend.XendError import XendError
-
-from xen.web.SrvDir import SrvDir
-
-class SrvVnet(SrvDir):
-
- def __init__(self, vnetinfo):
- SrvDir.__init__(self)
- self.vnetinfo = vnetinfo
- self.xvnet = XendVnet.instance()
-
- def op_delete(self, op, req):
- val = self.xvnet.vnet_delete(self.vnetinfo.id)
- return val
-
- def render_POST(self, req):
- return self.perform(req)
-
- def render_GET(self, req):
- if self.use_sxp(req):
- req.setHeader("Content-Type", sxp.mime_type)
- sxp.show(self.vnetinfo.sxpr(), out=req)
- else:
- req.write('<html><head></head><body>')
- self.print_path(req)
- req.write('<p>Vnet %s</p>' % self.vnetinfo.id)
- req.write("<code><pre>")
- PrettyPrint.prettyprint(self.vnetinfo.sxpr(), out=req)
- req.write("</pre></code>")
- self.form(req)
- req.write('</body></html>')
- return ''
-
- def form(self, req):
- url = req.prePathURL()
- req.write('<form method="post" action="%s">' % url)
- req.write('<input type="submit" name="op" value="delete">')
- req.write('</form>')
-
-class SrvVnetDir(SrvDir):
- """Vnet directory.
- """
-
- def __init__(self):
- SrvDir.__init__(self)
- self.xvnet = XendVnet.instance()
-
- def vnet(self, x):
- val = None
- vnetinfo = self.xvnet.vnet_get(x)
- if not vnetinfo:
- raise XendError('No such vnet ' + str(x))
- val = SrvVnet(vnetinfo)
- return val
-
- def get(self, x):
- v = SrvDir.get(self, x)
- if v is not None:
- return v
- v = self.vnet(x)
- return v
-
- def op_create(self, op, req):
- fn = FormFn(self.xvnet.vnet_create,
- [['config', 'sxpr']])
- val = fn(req.args, {})
- return val
-
- def render_POST(self, req):
- return self.perform(req)
-
- def render_GET(self, req):
- if self.use_sxp(req):
- req.setHeader("Content-Type", sxp.mime_type)
- self.ls_vnet(req, 1)
- else:
- req.write("<html><head></head><body>")
- self.print_path(req)
- self.ls(req)
- self.ls_vnet(req)
- self.form(req)
- req.write("</body></html>")
-
- def ls_vnet(self, req, use_sxp=0):
- url = req.prePathURL()
- if not url.endswith('/'):
- url += '/'
- if use_sxp:
- vnets = self.xvnet.vnet_ls()
- sxp.show(vnets, out=req)
- else:
- vnets = self.xvnet.vnets()
- vnets.sort(lambda x, y: cmp(x.id, y.id))
- req.write('<ul>')
- for v in vnets:
- req.write('<li><a href="%s%s"> Vnet %s</a>' % (url, v.id, v.id))
- req.write('</li>')
- req.write('</ul>')
-
- def form(self, req):
- """Generate the form(s) for vnet dir operations.
- """
- req.write('<form method="post" action="%s" enctype="multipart/form-data">'
- % req.prePathURL())
- req.write('<button type="submit" name="op" value="create">Create Vnet</button>')
- req.write('Config <input type="file" name="config"><br>')
- req.write('</form>')
diff --git a/tools/python/xen/xend/server/SrvXendLog.py b/tools/python/xen/xend/server/SrvXendLog.py
deleted file mode 100644
index a0dc67a..0000000
--- a/tools/python/xen/xend/server/SrvXendLog.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-from xen.web import static
-
-from xen.xend import XendLogging
-
-from xen.web.SrvDir import SrvDir
-
-class SrvXendLog(SrvDir):
- """Xend log.
- """
-
- def __init__(self):
- SrvDir.__init__(self)
- self.logfile = static.File(XendLogging.getLogFilename(),
- defaultType="text/plain")
- self.logfile.type = "text/plain"
- self.logfile.encoding = None
-
- def render_GET(self, req):
- return self.logfile.render(req)
diff --git a/tools/python/xen/xend/server/XMLRPCServer.py b/tools/python/xen/xend/server/XMLRPCServer.py
deleted file mode 100644
index e3a82dc..0000000
--- a/tools/python/xen/xend/server/XMLRPCServer.py
+++ /dev/null
@@ -1,273 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 Anthony Liguori <aliguori at us.ibm.com>
-# Copyright (C) 2006 XenSource Ltd.
-#============================================================================
-
-import errno
-import socket
-import types
-import xmlrpclib
-from xen.util.xmlrpclib2 import UnixXMLRPCServer, TCPXMLRPCServer
-try:
- from SSLXMLRPCServer import SSLXMLRPCServer
- ssl_enabled = True
-except ImportError:
- ssl_enabled = False
-
-from xen.xend import XendAPI, XendDomain, XendDomainInfo, XendNode
-from xen.xend import XendLogging, XendDmesg
-from xen.xend.XendClient import XML_RPC_SOCKET
-from xen.xend.XendConstants import DOM_STATE_RUNNING
-from xen.xend.XendLogging import log
-from xen.xend.XendError import XendInvalidDomain
-from xen.xend.XendCPUPool import XendCPUPool
-
-# vcpu_avail is a long and is not needed by the clients. It's far easier
-# to just remove it then to try and marshal the long.
-def fixup_sxpr(sexpr):
- ret = []
- for k in sexpr:
- if type(k) in (list, tuple):
- if len(k) != 2 or k[0] != 'vcpu_avail':
- ret.append(fixup_sxpr(k))
- else:
- ret.append(k)
- return ret
-
-def lookup(domid):
- info = XendDomain.instance().domain_lookup(domid)
- return info
-
-def dispatch(domid, fn, args):
- info = lookup(domid)
- return getattr(info, fn)(*args)
-
-def domain(domid, full = 0):
- info = lookup(domid)
- return fixup_sxpr(info.sxpr(not full))
-
-def domains(detail = True, full = False):
- return domains_with_state(detail, DOM_STATE_RUNNING, full)
-
-def domains_with_state(detail, state, full):
- if detail:
- domains = XendDomain.instance().list_sorted(state)
- ret = []
- for dom in domains:
- try:
- ret.append(fixup_sxpr(dom.sxpr(not full)))
- except:
- log.warn("Failed to query SXPR for domain %s" % str(dom))
- pass
- return ret
- else:
- return XendDomain.instance().list_names(state)
-
-def domain_create(config):
- info = XendDomain.instance().domain_create(config)
- return fixup_sxpr(info.sxpr())
-
-def domain_restore(src, paused=False):
- info = XendDomain.instance().domain_restore(src, paused)
- return fixup_sxpr(info.sxpr())
-
-def get_log():
- f = open(XendLogging.getLogFilename(), 'r')
- try:
- return f.read()
- finally:
- f.close()
-
-methods = ['device_create', 'device_configure',
- 'destroyDevice','getDeviceSxprs',
- 'setMemoryTarget', 'setName', 'setVCpuCount', 'shutdown',
- 'send_sysrq', 'getVCPUInfo', 'waitForDevices',
- 'getRestartCount', 'getBlockDeviceClass']
-
-exclude = ['domain_create', 'domain_restore']
-
-POOL_FUNCS = ['pool_create', 'pool_new', 'pool_start', 'pool_list',
- 'pool_destroy', 'pool_delete', 'pool_cpu_add', 'pool_cpu_remove',
- 'pool_migrate']
-
-class XMLRPCServer:
- def __init__(self, auth, use_xenapi, use_tcp = False,
- ssl_key_file = None, ssl_cert_file = None,
- host = "localhost", port = 8006, path = XML_RPC_SOCKET,
- hosts_allowed = None):
-
- self.use_tcp = use_tcp
- self.port = port
- self.host = host
- self.path = path
- self.hosts_allowed = hosts_allowed
-
- self.ssl_key_file = ssl_key_file
- self.ssl_cert_file = ssl_cert_file
-
- self.ready = False
- self.running = True
- self.auth = auth
- self.xenapi = use_xenapi and XendAPI.XendAPI(auth) or None
-
- def run(self):
- authmsg = (self.auth == XendAPI.AUTH_NONE and
- "; authentication has been disabled for this server." or
- ".")
-
- try:
- if self.use_tcp:
- using_ssl = self.ssl_key_file and self.ssl_cert_file
-
- log.info("Opening %s XML-RPC server on %s%d%s",
- using_ssl and 'HTTPS' or 'TCP',
- self.host and '%s:' % self.host or
- 'all interfaces, port ',
- self.port, authmsg)
-
- if using_ssl:
- if not ssl_enabled:
- raise ValueError("pyOpenSSL not installed. "
- "Unable to start HTTPS XML-RPC server")
- self.server = SSLXMLRPCServer(
- (self.host, self.port),
- self.hosts_allowed,
- self.xenapi is not None,
- logRequests = False,
- ssl_key_file = self.ssl_key_file,
- ssl_cert_file = self.ssl_cert_file)
- else:
- self.server = TCPXMLRPCServer(
- (self.host, self.port),
- self.hosts_allowed,
- self.xenapi is not None,
- logRequests = False)
-
- else:
- log.info("Opening Unix domain socket XML-RPC server on %s%s",
- self.path, authmsg)
- self.server = UnixXMLRPCServer(self.path, self.hosts_allowed,
- self.xenapi is not None,
- logRequests = False)
- except socket.error, exn:
- log.error('Cannot start server: %s!', exn.args[1])
- ready = True
- running = False
- return
- except Exception, e:
- log.exception('Cannot start server: %s!', e)
- ready = True
- running = False
- return
-
- # Register Xen API Functions
- # -------------------------------------------------------------------
- # exportable functions are ones that do not begin with '_'
- # and has the 'api' attribute.
-
- for meth_name in dir(self.xenapi):
- if meth_name[0] != '_':
- meth = getattr(self.xenapi, meth_name)
- if callable(meth) and hasattr(meth, 'api'):
- self.server.register_function(meth, getattr(meth, 'api'))
-
- self.server.register_instance(XendAPI.XendAPIAsyncProxy(self.xenapi))
-
- # Legacy deprecated xm xmlrpc api
- # --------------------------------------------------------------------
-
- # Functions in XendDomainInfo
- for name in methods:
- fn = eval("lambda domid, *args: dispatch(domid, '%s', args)"%name)
- self.server.register_function(fn, "xend.domain.%s" % name)
-
- inst = XendDomain.instance()
-
- for name in dir(inst):
- fn = getattr(inst, name)
- if name.startswith("domain_") and callable(fn):
- if name not in exclude:
- self.server.register_function(fn, "xend.domain.%s" % name[7:])
-
- # Functions in XendPool
- for name in POOL_FUNCS:
- fn = getattr(XendCPUPool, name)
- self.server.register_function(fn, "xend.cpu_pool.%s" % name[5:])
-
- # Functions in XendNode and XendDmesg
- for type, lst, n in [(XendNode,
- ['info', 'pciinfo', 'send_debug_keys',
- 'tmem_list', 'tmem_freeze', 'tmem_thaw',
- 'tmem_flush', 'tmem_destroy', 'tmem_set_weight',
- 'tmem_set_cap', 'tmem_set_compress',
- 'tmem_query_freeable_mb', 'tmem_shared_auth'],
- 'node'),
- (XendDmesg, ['info', 'clear'], 'node.dmesg')]:
- inst = type.instance()
- for name in lst:
- self.server.register_function(getattr(inst, name),
- "xend.%s.%s" % (n, name))
-
- # A few special cases
- self.server.register_function(domain, 'xend.domain')
- self.server.register_function(domains, 'xend.domains')
- self.server.register_function(domains_with_state,
- 'xend.domains_with_state')
- self.server.register_function(get_log, 'xend.node.log')
- self.server.register_function(domain_create, 'xend.domain.create')
- self.server.register_function(domain_restore, 'xend.domain.restore')
-
- # A couple of the security functions
- from xen.util.xsm import xsm as security
- for name in security.xmlrpc_exports:
- fn = getattr(security, name)
- self.server.register_function(fn, "xend.security.%s" % name)
-
- self.server.register_introspection_functions()
- self.ready = True
-
- # Custom runloop so we can cleanup when exiting.
- # -----------------------------------------------------------------
- try:
- while self.running:
- self.server.handle_request()
- finally:
- self.shutdown()
-
- def cleanup(self):
- log.debug('XMLRPCServer.cleanup()')
- if hasattr(self, 'server'):
- try:
- # This is here to make sure the socket is actually
- # cleaned up when close() is called. Otherwise
- # SO_REUSEADDR doesn't take effect. To replicate,
- # try 'xend reload' and look for EADDRINUSE.
- #
- # May be caued by us calling close() outside of
- # the listen()ing thread.
- self.server.socket.shutdown(2)
- except socket.error, e:
- pass # ignore any socket errors
- try:
- self.server.socket.close()
- except socket.error, e:
- pass
-
- def shutdown(self):
- self.running = False
- if self.ready:
- self.ready = False
- self.cleanup()
diff --git a/tools/python/xen/xend/server/__init__.py b/tools/python/xen/xend/server/__init__.py
deleted file mode 100644
index 8b13789..0000000
--- a/tools/python/xen/xend/server/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py
deleted file mode 100644
index 60e1625..0000000
--- a/tools/python/xen/xend/server/blkif.py
+++ /dev/null
@@ -1,221 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005, 2006 XenSource Inc.
-#============================================================================
-
-import re
-import string
-import os
-
-from xen.util import blkif
-import xen.util.xsm.xsm as security
-from xen.xend.XendError import VmError
-from xen.xend.server.DevController import DevController
-from xen.util import xsconstants, auxbin
-
-class BlkifController(DevController):
- """Block device interface controller. Handles all block devices
- for a domain.
- """
-
- def __init__(self, vm):
- """Create a block device controller.
- """
- DevController.__init__(self, vm)
-
- def _isValidProtocol(self, protocol):
- if protocol in ('phy', 'file', 'tap'):
- return True
-
- return os.access(auxbin.scripts_dir() + '/block-%s' % protocol, os.X_OK)
-
-
- def getDeviceDetails(self, config):
- """@see DevController.getDeviceDetails"""
- uname = config.get('uname', '')
- dev = config.get('dev', '')
-
- if 'ioemu:' in dev:
- (_, dev) = string.split(dev, ':', 1)
- try:
- (dev, dev_type) = string.split(dev, ':', 1)
- except ValueError:
- dev_type = "disk"
-
- if not uname:
- if dev_type == 'cdrom':
- (typ, params) = ("", "")
- else:
- raise VmError(
- 'Block device must have physical details specified')
- else:
- try:
- (typ, params) = string.split(uname, ':', 1)
- if not self._isValidProtocol(typ):
- raise VmError('Block device type "%s" is invalid.' % typ)
- except ValueError:
- raise VmError(
- 'Block device must have physical details specified')
-
- mode = config.get('mode', 'r')
- if mode not in ('r', 'w', 'w!'):
- raise VmError('Invalid mode')
-
- back = {'dev' : dev,
- 'type' : typ,
- 'params' : params,
- 'mode' : mode,
- }
-
- uuid = config.get('uuid')
- if uuid:
- back['uuid'] = uuid
-
- bootable = config.get('bootable', None)
- if bootable != None:
- back['bootable'] = str(bootable)
-
- if security.on() == xsconstants.XS_POLICY_USE:
- self.do_access_control(config, uname)
-
- (device_path, devid) = blkif.blkdev_name_to_number(dev)
- if devid is None:
- raise VmError('Unable to find number for device (%s)' % (dev))
-
- front = { device_path : "%i" % devid,
- 'device-type' : dev_type
- }
-
- protocol = config.get('protocol')
- if protocol:
- front['protocol'] = protocol
-
- return (devid, back, front)
-
- def do_access_control(self, config, uname):
- (label, ssidref, policy) = \
- security.get_res_security_details(uname)
- domain_label = self.vm.get_security_label()
- if domain_label:
- rc = security.res_security_check_xapi(label, ssidref, policy,
- domain_label)
- if rc == 0:
- raise VmError("VM's access to block device '%s' denied" %
- uname)
- else:
- from xen.util.acmpolicy import ACM_LABEL_UNLABELED
- if label != ACM_LABEL_UNLABELED:
- raise VmError("VM must have a security label to access "
- "block device '%s'" % uname)
-
- def reconfigureDevice(self, _, config):
- """@see DevController.reconfigureDevice"""
- (devid, new_back, new_front) = self.getDeviceDetails(config)
-
- (dev, mode) = self.readBackend(devid, 'dev', 'mode')
- dev_type = self.readFrontend(devid, 'device-type')
-
- if (dev_type == 'cdrom' and new_front['device-type'] == 'cdrom' and
- dev == new_back['dev'] and mode == 'r'):
- # dummy device
- self.writeBackend(devid,
- 'type', new_back['type'],
- 'params', '')
- # new backend-device
- self.writeBackend(devid,
- 'type', new_back['type'],
- 'params', new_back['params'])
- return new_back.get('uuid')
- else:
- raise VmError('Refusing to reconfigure device %s:%d to %s' %
- (self.deviceClass, devid, config))
-
-
- def getDeviceConfiguration(self, devid, transaction = None):
- """Returns the configuration of a device.
-
- @note: Similar to L{configuration} except it returns a dict.
- @return: dict
- """
- config = DevController.getDeviceConfiguration(self, devid, transaction)
- if transaction is None:
- devinfo = self.readBackend(devid, 'dev', 'type', 'params', 'mode',
- 'uuid', 'bootable')
- else:
- devinfo = self.readBackendTxn(transaction, devid,
- 'dev', 'type', 'params', 'mode', 'uuid',
- 'bootable')
- dev, typ, params, mode, uuid, bootable = devinfo
-
- if dev:
- if transaction is None:
- dev_type = self.readFrontend(devid, 'device-type')
- else:
- dev_type = self.readFrontendTxn(transaction, devid, 'device-type')
- if dev_type:
- dev += ':' + dev_type
- config['dev'] = dev
- if typ and params:
- config['uname'] = typ +':' + params
- else:
- config['uname'] = None
- if mode:
- config['mode'] = mode
- if uuid:
- config['uuid'] = uuid
- if bootable != None:
- config['bootable'] = int(bootable)
-
- proto = self.readFrontend(devid, 'protocol')
- if proto:
- config['protocol'] = proto
-
- return config
-
- def destroyDevice(self, devid, force):
- """@see DevController.destroyDevice"""
-
- # vbd device IDs can be either string or integer. Further, the
- # following string values are possible:
- # - devicetype/deviceid (vbd/51728)
- # - devicetype/devicename (/dev/xvdb)
- # - devicename (xvdb)
- # Let our superclass handle integer or devicetype/deviceid forms.
- # If we are given a device name form, then look up the device ID
- # from it, and destroy that ID instead.
- try:
- DevController.destroyDevice(self, devid, force)
- except ValueError:
- dev = self.convertToDeviceNumber(devid)
-
- for i in self.deviceIDs():
- if i == dev:
- DevController.destroyDevice(self, i, force)
- return
- raise VmError("Device %s not connected" % devid)
-
- def convertToDeviceNumber(self, devid):
- try:
- dev = int(devid)
- except ValueError:
- if type(devid) is not str:
- raise VmError("devid %s is wrong type" % str(devid))
- try:
- dev = devid.split('/')[-1]
- dev = int(dev)
- except ValueError:
- (device_path, dev) = blkif.blkdev_name_to_number(dev)
- return dev
diff --git a/tools/python/xen/xend/server/iopif.py b/tools/python/xen/xend/server/iopif.py
deleted file mode 100644
index 4c6e612..0000000
--- a/tools/python/xen/xend/server/iopif.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-# Copyright (C) 2005 Jody Belka
-#============================================================================
-
-
-import types
-
-import xen.lowlevel.xc
-
-from xen.xend.XendError import VmError
-
-from xen.xend.server.DevController import DevController
-
-
-xc = xen.lowlevel.xc.xc()
-
-
-def parse_ioport(val):
- """Parse an i/o port field.
- """
- if isinstance(val, types.StringType):
- radix = 10
- if val.startswith('0x') or val.startswith('0X'):
- radix = 16
- v = int(val, radix)
- else:
- v = val
- return v
-
-
-class IOPortsController(DevController):
-
- valid_cfg = ['to', 'from', 'uuid']
-
- def __init__(self, vm):
- DevController.__init__(self, vm)
-
- def getDeviceConfiguration(self, devid, transaction = None):
- result = DevController.getDeviceConfiguration(self, devid, transaction)
- if transaction is None:
- devinfo = self.readBackend(devid, *self.valid_cfg)
- else:
- devinfo = self.readBackendTxn(transaction, devid, *self.valid_cfg)
- config = dict(zip(self.valid_cfg, devinfo))
- config = dict([(key, val) for key, val in config.items()
- if val != None])
- return config
-
- def getDeviceDetails(self, config):
- """@see DevController.getDeviceDetails"""
-
- def get_param(field):
- try:
- val = config.get(field)
-
- if not val:
- raise VmError('ioports: Missing %s config setting' % field)
-
- return parse_ioport(val)
- except:
- raise VmError('ioports: Invalid config setting %s: %s' %
- (field, val))
-
- io_from = get_param('from')
- io_to = get_param('to')
-
- if io_to < io_from or io_to >= 65536:
- raise VmError('ioports: Invalid i/o range: %s - %s' %
- (io_from, io_to))
-
- rc = xc.domain_ioport_permission(domid = self.getDomid(),
- first_port = io_from,
- nr_ports = io_to - io_from + 1,
- allow_access = True)
-
- if rc < 0:
- #todo non-fatal
- raise VmError(
- 'ioports: Failed to configure legacy i/o range: %s - %s' %
- (io_from, io_to))
-
- back = dict([(k, config[k]) for k in self.valid_cfg if k in config])
- return (self.allocateDeviceID(), back, {})
-
- def waitForDevice(self, devid):
- # don't wait for hotplug
- return
diff --git a/tools/python/xen/xend/server/irqif.py b/tools/python/xen/xend/server/irqif.py
deleted file mode 100644
index 723f346..0000000
--- a/tools/python/xen/xend/server/irqif.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-# Copyright (C) 2005 Jody Belka
-#============================================================================
-# This code based on tools/python/xen/xend/server/iopif.py and modified
-# to handle interrupts
-#============================================================================
-
-
-import types
-
-import xen.lowlevel.xc
-
-from xen.xend import sxp
-from xen.xend.XendError import VmError
-
-from xen.xend.server.DevController import DevController
-
-
-xc = xen.lowlevel.xc.xc()
-
-
-class IRQController(DevController):
-
- def __init__(self, vm):
- DevController.__init__(self, vm)
-
- valid_cfg = ['irq', 'uuid']
-
- def getDeviceConfiguration(self, devid, transaction = None):
- result = DevController.getDeviceConfiguration(self, devid, transaction)
- if transaction is None:
- devinfo = self.readBackend(devid, *self.valid_cfg)
- else:
- devinfo = self.readBackendTxn(transaction, devid, *self.valid_cfg)
- config = dict(zip(self.valid_cfg, devinfo))
- config = dict([(key, val) for key, val in config.items()
- if val != None])
- return config
-
- def getDeviceDetails(self, config):
- """@see DevController.getDeviceDetails"""
-
- def get_param(field):
- try:
- val = config.get(field)
-
- if not val:
- raise VmError('irq: Missing %s config setting' % field)
-
- if isinstance(val, types.StringType):
- return int(val,10)
- radix = 10
- else:
- return val
- except:
- raise VmError('irq: Invalid config setting %s: %s' %
- (field, val))
-
- pirq = get_param('irq')
-
- rc = xc.physdev_map_pirq(domid = self.getDomid(),
- index = pirq,
- pirq = pirq)
- if rc < 0:
- raise VmError('irq: Failed to map irq %x' % (pirq))
-
- rc = xc.domain_irq_permission(domid = self.getDomid(),
- pirq = pirq,
- allow_access = True)
-
- if rc < 0:
- #todo non-fatal
- raise VmError(
- 'irq: Failed to configure irq: %d' % (pirq))
- back = dict([(k, config[k]) for k in self.valid_cfg if k in config])
- return (self.allocateDeviceID(), back, {})
-
- def waitForDevice(self, devid):
- # don't wait for hotplug
- return
diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py
deleted file mode 100644
index 1f0d2a0..0000000
--- a/tools/python/xen/xend/server/netif.py
+++ /dev/null
@@ -1,218 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-
-"""Support for virtual network interfaces.
-"""
-
-import os
-import random
-import re
-
-from xen.xend import XendOptions, sxp
-from xen.xend.server.DevController import DevController
-from xen.xend.XendError import VmError
-from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
-import xen.util.xsm.xsm as security
-from xen.util import xsconstants
-
-from xen.xend.XendLogging import log
-
-xoptions = XendOptions.instance()
-
-def randomMAC():
- """Generate a random MAC address.
-
- Uses OUI (Organizationally Unique Identifier) 00-16-3E, allocated to
- Xensource, Inc. The OUI list is available at
- http://standards.ieee.org/regauth/oui/oui.txt.
-
- The remaining 3 fields are random, with the first bit of the first
- random field set 0.
-
- @return: MAC address string
- """
- mac = [ 0x00, 0x16, 0x3e,
- random.randint(0x00, 0x7f),
- random.randint(0x00, 0xff),
- random.randint(0x00, 0xff) ]
- return ':'.join(map(lambda x: "%02x" % x, mac))
-
-rate_re = re.compile("^([0-9]+)([GMK]?)([Bb])/s(@([0-9]+)([mu]?)s)?$")
-
-def parseRate(ratestr):
- """if parsing fails this will return default of unlimited rate"""
- bytes_per_interval = 0xffffffffL # 0xffffffff # big default
- interval_usecs = 0L # disabled
-
- m = rate_re.match(ratestr)
- if m:
- bytes_per_sec = long(m.group(1))
-
- if m.group(2) == 'G':
- bytes_per_sec *= 1000 * 1000 * 1000
- elif m.group(2) == 'M':
- bytes_per_sec *= 1000 * 1000
- elif m.group(2) == 'K':
- bytes_per_sec *= 1000
-
- if m.group(3) == 'b':
- bytes_per_sec /= 8
-
- if m.group(5) is None:
- interval_usecs = 50000L # 50ms default
- else:
- interval_usecs = long(m.group(5))
- if m.group(6) == '':
- interval_usecs *= 1000 * 1000
- elif m.group(6) == 'm':
- interval_usecs *= 1000
-
- bytes_per_interval = (bytes_per_sec * interval_usecs) / 1000000L
-
- # overflow / underflow checking: default to unlimited rate
- if bytes_per_interval == 0 or bytes_per_interval > 0xffffffffL or \
- interval_usecs == 0 or interval_usecs > 0xffffffffL:
- bytes_per_interval = 0xffffffffL
- interval_usecs = 0L
-
- return "%lu,%lu" % (bytes_per_interval, interval_usecs)
-
-
-class NetifController(DevController):
- """Network interface controller. Handles all network devices for a domain.
- """
-
- def __init__(self, vm):
- DevController.__init__(self, vm)
-
- def getDeviceDetails(self, config):
- """@see DevController.getDeviceDetails"""
-
- script = config.get('script', xoptions.get_vif_script())
- typ = config.get('type')
- bridge = config.get('bridge')
- mac = config.get('mac')
- vifname = config.get('vifname')
- rate = config.get('rate')
- uuid = config.get('uuid')
- ipaddr = config.get('ip')
- model = config.get('model')
- accel = config.get('accel')
- sec_lab = config.get('security_label')
-
- if not mac:
- raise VmError("MAC address not specified or generated.")
-
- devid = self.allocateDeviceID()
-
- back = { 'script' : script,
- 'mac' : mac }
- if typ:
- back['type'] = typ
- if ipaddr:
- back['ip'] = ipaddr
- if bridge:
- back['bridge'] = bridge
- if vifname:
- back['vifname'] = vifname
- if rate:
- back['rate'] = rate
- if uuid:
- back['uuid'] = uuid
- if model:
- back['model'] = model
- if accel:
- back['accel'] = accel
- if sec_lab:
- back['security_label'] = sec_lab
-
- back['handle'] = "%i" % devid
- back['script'] = os.path.join(xoptions.network_script_dir, script)
- if rate:
- back['rate'] = parseRate(rate)
-
- front = {}
- if typ != 'ioemu':
- front = { 'handle' : "%i" % devid,
- 'mac' : mac }
-
- if security.on() == xsconstants.XS_POLICY_USE:
- self.do_access_control(config)
-
- return (devid, back, front)
-
-
- def do_access_control(self, config):
- """ do access control checking. Throws a VMError if access is denied """
- domain_label = self.vm.get_security_label()
- stes = XSPolicyAdminInstance().get_stes_of_vmlabel(domain_label)
- res_label = config.get('security_label')
- if len(stes) > 1 or res_label:
- if not res_label:
- raise VmError("'VIF' must be labeled")
- (label, ssidref, policy) = \
- security.security_label_to_details(res_label)
- if domain_label:
- rc = security.res_security_check_xapi(label, ssidref,
- policy,
- domain_label)
- if rc == 0:
- raise VmError("VM's access to network device denied. "
- "Check labeling")
- else:
- raise VmError("VM must have a security label to access "
- "network device")
-
-
- def getDeviceConfiguration(self, devid, transaction = None):
- """@see DevController.configuration"""
-
- result = DevController.getDeviceConfiguration(self, devid, transaction)
-
- for x in ( 'script', 'ip', 'bridge', 'mac',
- 'type', 'vifname', 'rate', 'uuid', 'model', 'accel',
- 'security_label'):
- if transaction is None:
- y = self.readBackend(devid, x)
- else:
- y = self.readBackendTxn(transaction, devid, x)
- if y:
- result[x] = y
-
- return result
-
- # match a VIF ID from xenstore, or a MAC address stored in the domain config
- def convertToDeviceNumber(self, devid):
- try:
- return int(devid)
- except ValueError:
- if type(devid) is not str:
- raise VmError("devid %s is wrong type" % str(devid))
- try:
- dev = devid.split('/')[-1]
- return (int(dev))
- except ValueError:
- devs = [d for d in self.vm.info.all_devices_sxpr()
- if d[0] == 'vif']
- for nr in range(len(devs)):
- dev_type, dev_info = devs[nr]
- if (sxp.child_value(dev_info, 'mac').lower() ==
- devid.lower()):
- return nr
- raise VmError("unknown devid %s" % str(devid))
diff --git a/tools/python/xen/xend/server/netif2.py b/tools/python/xen/xend/server/netif2.py
deleted file mode 100644
index a098c13..0000000
--- a/tools/python/xen/xend/server/netif2.py
+++ /dev/null
@@ -1,163 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-# Copyright (C) 2008 Citrix Systems Inc.
-#============================================================================
-#
-# Based closely on netif.py.
-#
-
-"""Support for virtual network interfaces, version 2.
-"""
-
-import os
-import random
-import re
-import time
-
-from xen.xend import XendOptions
-from xen.xend.server.DevController import DevController
-from xen.xend.XendError import VmError
-from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
-from xen.xend.xenstore.xstransact import xstransact
-import xen.util.xsm.xsm as security
-
-from xen.xend.XendLogging import log
-
-xoptions = XendOptions.instance()
-
-def randomMAC():
- """Generate a random MAC address.
-
- Uses OUI (Organizationally Unique Identifier) 00-16-3E, allocated to
- Xensource, Inc. The OUI list is available at
- http://standards.ieee.org/regauth/oui/oui.txt.
-
- The remaining 3 fields are random, with the first bit of the first
- random field set 0.
-
- @return: MAC address string
- """
- mac = [ 0x00, 0x16, 0x3e,
- random.randint(0x00, 0x7f),
- random.randint(0x00, 0xff),
- random.randint(0x00, 0xff) ]
- return ':'.join(map(lambda x: "%02x" % x, mac))
-
-class NetifController2(DevController):
- def __init__(self, vm):
- DevController.__init__(self, vm)
-
- def getDeviceDetails(self, config):
- """@see DevController.getDeviceDetails"""
-
- devid = self.allocateDeviceID()
-
- bridge = config.get('bridge')
- back_mac = config.get('back_mac')
- if not back_mac:
- if bridge:
- back_mac = "fe:ff:ff:ff:ff:ff"
- else:
- back_mac = randomMAC()
- front_mac = config.get('front_mac') or randomMAC()
- front_trust = config.get("trusted") or "0"
- back_trust = config.get("back_trusted") or "1"
- max_bypasses = config.get("max_bypasses") or "5"
- pdev = config.get('pdev')
- front_filter = config.get("front_filter_mac")
- if front_filter == None:
- if back_trust == "0":
- front_filter = "1"
- else:
- front_filter = "0"
- back_filter = config.get("filter_mac")
- if back_filter == None:
- if front_trust == "0":
- back_filter = "1"
- else:
- back_filter = "0"
- back = { 'mac': back_mac, 'remote-mac': front_mac,
- 'handle': "%i" % devid, 'local-trusted': back_trust,
- 'remote-trusted': front_trust, 'filter-mac': back_filter,
- 'max-bypasses': max_bypasses }
-
- front = { 'mac': front_mac, 'remote-mac': back_mac,
- 'local-trusted': front_trust, 'remote-trusted': back_trust,
- 'filter-mac': front_filter }
-
- if bridge:
- back['bridge'] = bridge
-
- if pdev:
- back['pdev'] = pdev
-
- return (devid, back, front)
-
- def getDeviceConfiguration(self, devid, transaction = None):
- """@see DevController.configuration"""
-
- if transaction is None:
- read_fn = xstransact.Read
- else:
- read_fn = transaction.read
- def front_read(x):
- return read_fn(frontpath + x)
- def back_read(x):
- return read_fn(backpath + x)
-
- result = DevController.getDeviceConfiguration(self, devid, transaction)
-
- dev = self.convertToDeviceNumber(devid)
- frontpath = self.frontendPath(dev) + "/"
-
- backpath = front_read("backend") + "/"
-
- front_mac = front_read("mac")
- back_mac = back_read("mac")
-
- front_trusted = back_read("remote-trusted")
- back_trusted = back_read("local-trusted")
- max_bypasses = back_read("max-bypasses")
-
- bridge = back_read("bridge")
-
- pdev = back_read("pdev")
-
- if front_mac:
- result["front_mac"] = front_mac
- if back_mac:
- result["back_mac"] = back_mac
- if front_trusted:
- result["front_trusted"] = front_trusted
- if back_trusted:
- result["back_trusted"] = back_trusted
- if bridge:
- result["bridge"] = bridge
- if pdev:
- result["pdev"] = pdev
- if max_bypasses:
- result["max-bypasses"] = max_bypasses
- return result
-
- def destroyDevice(self, devid, force):
- dev = self.convertToDeviceNumber(devid)
- self.writeBackend(dev, "online", "0")
- if force:
- self.writeBackend(dev, "shutdown-request", "force")
- else:
- self.writeBackend(dev, "shutdown-request", "normal")
- self.vm._removeVm("device/%s/%d" % (self.deviceClass, dev))
diff --git a/tools/python/xen/xend/server/params.py b/tools/python/xen/xend/server/params.py
deleted file mode 100644
index c7099e2..0000000
--- a/tools/python/xen/xend/server/params.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
-
-import os
-
-def getenv(var, val, conv=None):
- """Get a value from the environment, with optional conversion.
-
- @param var name of environment variable
- @param val default value
- @param conv conversion function to apply to env value
- @return converted value or default
- """
- try:
- v = os.getenv(var)
- if v is None:
- v = val
- else:
- print var, '=', v
- if conv:
- v = conv(v)
- except:
- v = val
- return v
-
-# The following parameters could be placed in a configuration file.
-XEND_PID_FILE = '/var/run/xend.pid'
-XEND_TRACE_FILE = '/var/log/xen/xend.trace'
-XEND_DEBUG_LOG = '/var/log/xen/xend-debug.log'
-XEND_USER = 'root'
-XEND_DEBUG = getenv("XEND_DEBUG", 0, conv=int)
-XEND_DAEMONIZE = getenv("XEND_DAEMONIZE", not XEND_DEBUG, conv=int)
diff --git a/tools/python/xen/xend/server/pciif.py b/tools/python/xen/xend/server/pciif.py
deleted file mode 100644
index 27c1b75..0000000
--- a/tools/python/xen/xend/server/pciif.py
+++ /dev/null
@@ -1,596 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-
-import types
-import time
-
-from xen.xend import sxp
-from xen.xend import XendOptions
-xoptions = XendOptions.instance()
-
-from xen.xend import arch
-from xen.xend.XendError import VmError
-from xen.xend.XendLogging import log
-from xen.xend.XendConstants import *
-
-from xen.xend.server.DevController import DevController
-from xen.xend.server.DevConstants import xenbusState
-
-import xen.lowlevel.xc
-
-from xen.util.pci import *
-import resource
-import re
-
-from xen.xend.server.pciquirk import *
-from xen.xend.xenstore.xstransact import xstransact
-from xen.xend.xenstore.xswatch import xswatch
-
-xc = xen.lowlevel.xc.xc()
-
-#Calculate PAGE_SHIFT: number of bits to shift an address to get the page number
-PAGE_SIZE = resource.getpagesize()
-PAGE_SHIFT = 0
-t = PAGE_SIZE
-while not (t&1):
- t>>=1
- PAGE_SHIFT+=1
-
-def parse_hex(val):
- try:
- if isinstance(val, types.StringTypes):
- return int(val, 16)
- else:
- return val
- except ValueError:
- return None
-
-def get_assigned_pci_devices(domid):
- dev_str_list = []
- path = '/local/domain/0/backend/pci/%u/0/' % domid
- num_devs = xstransact.Read(path + 'num_devs');
- if num_devs is None or num_devs == "":
- return dev_str_list
- num_devs = int(num_devs)
- for i in range(num_devs):
- dev_str = xstransact.Read(path + 'dev-%i' % i)
- dev_str_list = dev_str_list + [dev_str]
- return dev_str_list
-
-def get_all_assigned_pci_devices(domid = 0):
- dom_list = xstransact.List('/local/domain')
- pci_str_list = []
- ti = 0
- ts = xstransact.Read('/local/domain/' + str(domid) + '/target')
- if ts is not None :
- ti = int(ts)
- for d in dom_list:
- target = xstransact.Read('/local/domain/' + d + '/target')
- if int(d) is not ti and target is None :
- pci_str_list = pci_str_list + get_assigned_pci_devices(int(d))
- return pci_str_list
-
-class PciController(DevController):
-
- def __init__(self, vm):
- self.aerStateWatch = None
- DevController.__init__(self, vm)
-
-
- def getDeviceDetails(self, config):
- """@see DevController.getDeviceDetails"""
- back = {}
- pcidevid = 0
- pci_defopts = []
-
- if 'pci_msitranslate' in self.vm.info['platform']:
- pci_defopts.append(['msitranslate',
- str(self.vm.info['platform']['pci_msitranslate'])])
- if 'pci_power_mgmt' in self.vm.info['platform']:
- pci_defopts.append(['power_mgmt',
- str(self.vm.info['platform']['pci_power_mgmt'])])
-
- for pci_config in config.get('devs', []):
- domain = parse_hex(pci_config.get('domain', 0))
- bus = parse_hex(pci_config.get('bus', 0))
- slot = parse_hex(pci_config.get('slot', 0))
- func = parse_hex(pci_config.get('func', 0))
- vdevfn = parse_hex(pci_config.get('vdevfn', \
- '0x%02x' % AUTO_PHP_SLOT))
-
- optslist = []
- if pci_config.has_key('opts'):
- optslist += pci_config['opts']
- if optslist or pci_defopts:
- opts = serialise_pci_opts(
- append_default_pci_opts(optslist, pci_defopts))
- back['opts-%i' % pcidevid] = opts
-
- back['dev-%i' % pcidevid] = "%04x:%02x:%02x.%01x" % \
- (domain, bus, slot, func)
- back['uuid-%i' % pcidevid] = pci_config.get('uuid', '')
- back['key-%i' % pcidevid] = pci_config.get('key', '')
- back['vdevfn-%i' % pcidevid] = "%02x" % vdevfn
- pcidevid += 1
-
- back['num_devs']=str(pcidevid)
- back['uuid'] = config.get('uuid','')
-
- return (0, back, {})
-
- def reconfigureDevice_find(self, devid, nsearch_dev, match_dev):
- for j in range(nsearch_dev):
- if match_dev == self.readBackend(devid, 'dev-%i' % j):
- return j
- return None
-
- def reconfigureDevice(self, _, config):
- """@see DevController.reconfigureDevice"""
- (devid, back, front) = self.getDeviceDetails(config)
- num_devs = int(back['num_devs'])
- states = config.get('states', [])
- num_olddevs = int(self.readBackend(devid, 'num_devs'))
-
- for i in range(num_devs):
- try:
- dev = back['dev-%i' % i]
- state = states[i]
- uuid = back['uuid-%i' %i]
- key = back['key-%i' %i]
- opts = ''
- if 'opts-%i' % i in back:
- opts = back['opts-%i' % i]
- except:
- raise XendError('Error reading config')
-
- if state == 'Initialising':
- devno = self.reconfigureDevice_find(devid, num_olddevs, dev)
- if devno == None:
- devno = num_olddevs + i
- log.debug('Attaching PCI device %s.' % dev)
- attaching = True
- else:
- log.debug('Reconfiguring PCI device %s.' % dev)
- attaching = False
-
- self.setupOneDevice(parse_pci_name(dev))
-
- self.writeBackend(devid, 'dev-%i' % devno, dev)
- self.writeBackend(devid, 'state-%i' % devno,
- str(xenbusState['Initialising']))
- self.writeBackend(devid, 'uuid-%i' % devno, uuid)
- self.writeBackend(devid, 'key-%i' % devno, key)
- if len(opts) > 0:
- self.writeBackend(devid, 'opts-%i' % devno, opts)
- if back.has_key('vdevfn-%i' % i):
- self.writeBackend(devid, 'vdevfn-%i' % devno,
- back['vdevfn-%i' % i])
-
- # If a device is being attached then num_devs will grow
- if attaching:
- self.writeBackend(devid, 'num_devs', str(devno + 1))
-
- elif state == 'Closing':
- # PCI device detachment
- devno = self.reconfigureDevice_find(devid, num_olddevs, dev)
- if devno == None:
- raise XendError('Device %s is not connected' % dev)
- log.debug('Detaching device %s' % dev)
- self.writeBackend(devid, 'state-%i' % devno,
- str(xenbusState['Closing']))
-
- else:
- raise XendError('Error configuring device %s: invalid state %s'
- % (dev,state))
-
- self.writeBackend(devid, 'state', str(xenbusState['Reconfiguring']))
-
- return self.readBackend(devid, 'uuid')
-
-
- def getDeviceConfiguration(self, devid, transaction = None):
- result = DevController.getDeviceConfiguration(self, devid, transaction)
- num_devs = self.readBackend(devid, 'num_devs')
- pci_devs = []
-
- for i in range(int(num_devs)):
- pci_dev = parse_pci_name(self.readBackend(devid, 'dev-%d' % i))
-
- # Per device uuid info
- pci_dev['uuid'] = self.readBackend(devid, 'uuid-%d' % i)
- pci_dev['key'] = self.readBackend(devid, 'key-%d' % i)
- pci_dev['vdevfn'] = '0x%s' % self.readBackend(devid,
- 'vdevfn-%d' % i)
-
- #append opts info
- opts = self.readBackend(devid, 'opts-%d' % i)
- if opts is not None:
- pci_dev['opts'] = opts
-
- pci_devs.append(pci_dev)
-
- result['devs'] = pci_devs
- result['uuid'] = self.readBackend(devid, 'uuid')
- return result
-
- def configuration(self, devid, transaction = None):
- """Returns SXPR for devices on domain.
-
- @note: we treat this dict especially to convert to
- SXP because it is not a straight dict of strings."""
-
- configDict = self.getDeviceConfiguration(devid, transaction)
- sxpr = [self.deviceClass]
-
- # remove devs
- devs = configDict.pop('devs', [])
-
- for dev in devs:
- dev_sxpr = ['dev']
- for dev_key, dev_val in dev.items():
- if dev_key == 'opts':
- opts_sxpr = pci_opts_list_to_sxp(split_pci_opts(dev_val))
- dev_sxpr = sxp.merge(dev_sxpr, opts_sxpr)
- else:
- dev_sxpr.append([dev_key, dev_val])
- sxpr.append(dev_sxpr)
-
- for key, val in configDict.items():
- if type(val) == type(list()):
- for v in val:
- sxpr.append([key, v])
- else:
- sxpr.append([key, val])
-
- return sxpr
-
- def CheckSiblingDevices(self, domid, dev):
- """ Check if all sibling devices of dev are owned by pciback or pci-stub
- """
- if not self.vm.info.is_hvm():
- return
-
- group_str = xc.get_device_group(domid, dev.domain, dev.bus, dev.slot, dev.func)
- if group_str == "":
- return
-
- #group string format xx:xx.x,xx:xx.x,
- for i in group_str.split(','):
- if i == '':
- continue
- pci_dev = parse_pci_name(i)
- pci_dev['domain'] = '%04x' % dev.domain
- try:
- sdev = PciDevice(pci_dev)
- except Exception, e:
- #no dom0 drivers bound to sdev
- continue
-
- if sdev.driver!='pciback' and sdev.driver!='pci-stub':
- raise VmError(("pci: PCI Backend and pci-stub don't "+ \
- "own sibling device %s of device %s"\
- )%(sdev.name, dev.name))
- return
-
- def setupOneDevice(self, pci_dev):
- """ Attach I/O resources for device to frontend domain
- """
- fe_domid = self.getDomid()
-
- try:
- dev = PciDevice(pci_dev)
- except Exception, e:
- raise VmError("pci: failed to locate device and "+
- "parse its resources - "+str(e))
-
- if dev.driver!='pciback' and dev.driver!='pci-stub':
- raise VmError(("pci: PCI Backend and pci-stub don't own "+ \
- "device %s") %(dev.name))
-
- self.CheckSiblingDevices(fe_domid, dev)
-
- if dev.driver == 'pciback':
- PCIQuirk(dev)
-
- if not self.vm.info.is_hvm() and not self.vm.info.is_stubdom() :
- # Setup IOMMU device assignment
- bdf = xc.assign_device(fe_domid, pci_dict_to_xc_str(pci_dev))
- pci_str = pci_dict_to_bdf_str(pci_dev)
- if bdf > 0:
- raise VmError("Failed to assign device to IOMMU (%s)" % pci_str)
- log.debug("pci: assign device %s" % pci_str)
-
- for (start, size) in dev.ioports:
- log.debug('pci: enabling ioport 0x%x/0x%x'%(start,size))
- rc = xc.domain_ioport_permission(domid = fe_domid, first_port = start,
- nr_ports = size, allow_access = True)
- if rc<0:
- raise VmError(('pci: failed to configure I/O ports on device '+
- '%s - errno=%d')%(dev.name,rc))
-
- for (start, size) in dev.iomem:
- # Convert start/size from bytes to page frame sizes
- start_pfn = start>>PAGE_SHIFT
- # Round number of pages up to nearest page boundary (if not on one)
- nr_pfns = (size+(PAGE_SIZE-1))>>PAGE_SHIFT
-
- log.debug('pci: enabling iomem 0x%x/0x%x pfn 0x%x/0x%x'% \
- (start,size,start_pfn,nr_pfns))
- rc = xc.domain_iomem_permission(domid = fe_domid,
- first_pfn = start_pfn,
- nr_pfns = nr_pfns,
- allow_access = True)
- if rc<0:
- raise VmError(('pci: failed to configure I/O memory on device '+
- '%s - errno=%d')%(dev.name,rc))
-
- if dev.irq > 0:
- rc = xc.physdev_map_pirq(domid = fe_domid,
- index = dev.irq,
- pirq = dev.irq)
- if rc < 0:
- raise VmError(('pci: failed to map irq on device '+
- '%s - errno=%d')%(dev.name,rc))
- if dev.irq>0:
- log.debug('pci: enabling irq %d'%dev.irq)
- rc = xc.domain_irq_permission(domid = fe_domid, pirq = dev.irq,
- allow_access = True)
- if rc<0:
- raise VmError(('pci: failed to configure irq on device '+
- '%s - errno=%d')%(dev.name,rc))
-
- def dev_check_assignability_and_do_FLR(self, config):
- pci_dev_list = config.get('devs', [])
- pci_str_list = map(pci_dict_to_bdf_str, pci_dev_list)
-
- if len(pci_str_list) != len(set(pci_str_list)):
- raise VmError('pci: duplicate devices specified in guest config?')
-
- strict_check = xoptions.get_pci_dev_assign_strict_check()
- devs = []
- for pci_dev in pci_dev_list:
- try:
- dev = PciDevice(pci_dev)
- except Exception, e:
- raise VmError("pci: failed to locate device and "+
- "parse its resources - "+str(e))
- if dev.driver!='pciback' and dev.driver!='pci-stub':
- raise VmError(("pci: PCI Backend and pci-stub don't own device"\
- " %s") %(dev.name))
-
- devs.append(dev)
-
- if dev.has_non_page_aligned_bar and strict_check:
- raise VmError("pci: %s: non-page-aligned MMIO BAR found." % dev.name)
-
- # Check if there is intermediate PCIe switch bewteen the device and
- # Root Complex.
- if self.vm.info.is_hvm() and dev.is_behind_switch_lacking_acs() \
- and strict_check:
- err_msg = 'pci: to avoid potential security issue, %s is not'+\
- ' allowed to be assigned to guest since it is behind'+\
- ' PCIe switch that does not support or enable ACS.'
- raise VmError(err_msg % dev.name)
-
- if (dev.dev_type == DEV_TYPE_PCIe_ENDPOINT) and not dev.pcie_flr:
- if dev.bus == 0:
- # We cope with this case by using the Dstate transition
- # method or some vendor specific methods for now.
- err_msg = 'pci: %s: it is on bus 0, but has no PCIe' +\
- ' FLR Capability. Will try the Dstate transition'+\
- ' method or some vendor specific methods if available.'
- log.warn(err_msg % dev.name)
- else:
- if not self.vm.info.is_hvm():
- continue
- if not strict_check:
- continue
-
- funcs = dev.find_all_the_multi_functions()
- dev.devs_check_driver(funcs)
- for f in funcs:
- if not f in pci_str_list:
- # f has been assigned to other guest?
- if f in get_all_assigned_pci_devices():
- 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 or arch.type == "ia64":
- if not dev.pci_af_flr:
- # We cope with this case by using the Dstate transition
- # method or some vendor specific methods 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 or some vendor' +\
- ' specific methods if available.'
- log.warn(err_msg % dev.name)
- else:
- if not self.vm.info.is_hvm():
- continue
- if not strict_check:
- continue
-
- # All devices behind the uppermost PCI/PCI-X bridge must be\
- # co-assigned to the same guest.
- devs_str = dev.find_coassigned_pci_devices(True)
- # Remove the element 0 which is a bridge
- del devs_str[0]
-
- dev.devs_check_driver(devs_str)
- for s in devs_str:
- if not s in pci_str_list:
- # s has been assigned to other guest?
- if s in get_all_assigned_pci_devices():
- err_msg = 'pci: %s must be co-assigned to the'+\
- ' same guest with %s'
- raise VmError(err_msg % (s, dev.name))
- # try to do FLR
- for dev in devs:
- dev.do_FLR(self.vm.info.is_hvm(), strict_check)
-
- def setupDevice(self, config):
- """Setup devices from config
- """
- pci_dev_list = config.get('devs', [])
- for d in pci_dev_list:
- self.setupOneDevice(d)
- wPath = '/local/domain/0/backend/pci/%u/0/aerState' % (self.getDomid())
- self.aerStateWatch = xswatch(wPath, self._handleAerStateWatch)
- log.debug('pci: register aer watch %s', wPath)
- return
-
- def _handleAerStateWatch(self, _):
- log.debug('XendDomainInfo.handleAerStateWatch')
- if self.getDomid() == 0:
- raise XendError('Domain 0 cannot be shutdown')
- readPath = '/local/domain/0/backend/pci/%u/0/aerState' % (self.getDomid())
- action = xstransact.Read(readPath)
- if action and action=='aerfail':
- log.debug('shutdown domain because of aer handle error')
- self.vm.shutdown('poweroff')
- return True
-
-
- def cleanupOneDevice(self, pci_dev):
- """ Detach I/O resources for device from frontend domain
- """
- fe_domid = self.getDomid()
-
- try:
- dev = PciDevice(pci_dev)
- except Exception, e:
- raise VmError("pci: failed to locate device and "+
- "parse its resources - "+str(e))
-
- if dev.driver!='pciback' and dev.driver!='pci-stub':
- raise VmError(("pci: PCI Backend and pci-stub don't own device "+ \
- "%s") %(dev.name))
-
- # Need to do FLR here before deassign device in order to terminate
- # DMA transaction, etc
- dev.do_FLR(self.vm.info.is_hvm(),
- xoptions.get_pci_dev_assign_strict_check())
-
- if not self.vm.info.is_stubdom() :
- bdf = xc.deassign_device(fe_domid, pci_dict_to_xc_str(pci_dev))
- pci_str = pci_dict_to_bdf_str(pci_dev)
- if bdf > 0:
- raise VmError("Failed to deassign device from IOMMU (%s)" % pci_str)
- log.debug("pci: Deassign device %s" % pci_str)
-
- for (start, size) in dev.ioports:
- log.debug('pci: disabling ioport 0x%x/0x%x'%(start,size))
- rc = xc.domain_ioport_permission(domid = fe_domid, first_port = start,
- nr_ports = size, allow_access = False)
- if rc<0:
- raise VmError(('pci: failed to configure I/O ports on device '+
- '%s - errno=%d')%(dev.name,rc))
-
- for (start, size) in dev.iomem:
- # Convert start/size from bytes to page frame sizes
- start_pfn = start>>PAGE_SHIFT
- # Round number of pages up to nearest page boundary (if not on one)
- nr_pfns = (size+(PAGE_SIZE-1))>>PAGE_SHIFT
-
- log.debug('pci: disabling iomem 0x%x/0x%x pfn 0x%x/0x%x'% \
- (start,size,start_pfn,nr_pfns))
- rc = xc.domain_iomem_permission(domid = fe_domid,
- first_pfn = start_pfn,
- nr_pfns = nr_pfns,
- allow_access = False)
- if rc<0:
- raise VmError(('pci: failed to configure I/O memory on device '+
- '%s - errno=%d')%(dev.name,rc))
-
- if dev.irq>0:
- log.debug('pci: disabling irq %d'%dev.irq)
- rc = xc.domain_irq_permission(domid = fe_domid, pirq = dev.irq,
- allow_access = False)
- if rc<0:
- raise VmError(('pci: failed to configure irq on device '+
- '%s - errno=%d')%(dev.name,rc))
-
- def cleanupDevice(self, devid):
- """ Detach I/O resources for device and cleanup xenstore nodes
- after reconfigure.
-
- @param devid: The device ID
- @type devid: int
- @return: Return the number of devices connected
- @rtype: int
- """
- num_devs = int(self.readBackend(devid, 'num_devs'))
- new_num_devs = 0
- for i in range(num_devs):
- try:
- state = int(self.readBackend(devid, 'state-%i' % i))
- except:
- state = xenbusState['Unknown']
-
- if state == xenbusState['Closing']:
- # Detach I/O resources.
- pci_dev = parse_pci_name(self.readBackend(devid, 'dev-%i' % i))
- # In HVM case, I/O resources are disabled in ioemu.
- self.cleanupOneDevice(pci_dev)
- # Remove xenstore nodes.
- list = ['dev', 'vdev', 'state', 'uuid', 'vdevfn', 'key']
- if self.readBackend(devid, 'opts-%i' % i) is not None:
- list.append('opts')
- for key in list:
- self.removeBackend(devid, '%s-%i' % (key, i))
- else:
- new_num_devs = new_num_devs + 1
- if new_num_devs == i + 1:
- continue
-
- list = ['dev', 'vdev', 'state', 'uuid', 'opts', 'vdevfn', 'key']
- for key in list:
- tmp = self.readBackend(devid, '%s-%i' % (key, i))
- if tmp is None:
- continue
- self.removeBackend(devid, '%s-%i' % (key, i))
- self.writeBackend(devid,
- '%s-%i' % (key, new_num_devs - 1), tmp)
-
- self.writeBackend(devid, 'num_devs', str(new_num_devs))
-
- return new_num_devs
-
- def destroyDevice(self, devid, force):
- DevController.destroyDevice(self, devid, True)
- log.debug('pci: unregister aer watch')
- self.unwatchAerState()
-
- def unwatchAerState(self):
- """Remove the watch on the domain's aerState node, if any."""
- try:
- try:
- if self.aerStateWatch:
- self.aerStateWatch.unwatch()
- finally:
- self.aerStateWatch = None
- except:
- log.exception("Unwatching aerState failed.")
-
- def waitForBackend(self,devid):
- return (0, "ok - no hotplug")
-
- def migrate(self, config, network, dst, step, domName):
- raise XendError('Migration not permitted with assigned PCI device.')
diff --git a/tools/python/xen/xend/server/pciquirk.py b/tools/python/xen/xend/server/pciquirk.py
deleted file mode 100644
index ba56ebd..0000000
--- a/tools/python/xen/xend/server/pciquirk.py
+++ /dev/null
@@ -1,149 +0,0 @@
-from xen.xend.XendLogging import log
-from xen.xend.XendError import XendError, VmError
-import sys
-import os.path
-from xen.xend.sxp import *
-from xen.util import auxbin
-
-QUIRK_SYSFS_NODE = "/sys/bus/pci/drivers/pciback/quirks"
-QUIRK_CONFIG_FILE = auxbin.xen_configdir() + "/xend-pci-quirks.sxp"
-PERMISSIVE_CONFIG_FILE = auxbin.xen_configdir() + "/xend-pci-permissive.sxp"
-PERMISSIVE_SYSFS_NODE = "/sys/bus/pci/drivers/pciback/permissive"
-
-class PCIQuirk:
- def __init__(self, dev):
- self.vendor = dev.vendor
- self.device = dev.device
- self.subvendor = dev.subvendor
- self.subdevice = dev.subdevice
- self.domain = dev.domain
- self.bus = dev.bus
- self.slot = dev.slot
- self.func = dev.func
-
- self.devid = "%04x:%04x:%04x:%04x" % (self.vendor, self.device,
- self.subvendor, self.subdevice)
- self.pciid = dev.name
- self.quirks = self.__getQuirksByID()
-
- self.__sendQuirks()
- self.__sendPermDevs()
-
- def __matchPCIdev( self, list ):
- ret = False
- if list == None:
- return False
- for id in list:
- if id.startswith(self.devid[:9]): # id's vendor and device ID match
- skey = id.split(':')
- size = len(skey)
- if (size == 2): # subvendor/subdevice not suplied
- ret = True
- break
- elif (size == 4): # check subvendor/subdevice
- # check subvendor
- subven = '%04x' % self.subvendor
- if ((skey[2] != 'FFFF') and
- (skey[2] != 'ffff') and
- (skey[2] != subven)):
- continue
- # check subdevice
- subdev = '%04x' % self.subdevice
- if ((skey[3] != 'FFFF') and
- (skey[3] != 'ffff') and
- (skey[3] != subdev)):
- continue
- ret = True
- break
- else:
- log.debug("WARNING: invalid configuration entry: %s" % id)
- ret = False
- break
- return ret
-
- def __getQuirksByID( self ):
- if os.path.exists(QUIRK_CONFIG_FILE):
- try:
- fin = file(QUIRK_CONFIG_FILE, 'rb')
- try:
- pci_quirks_config = parse(fin)
- finally:
- fin.close()
- if pci_quirks_config is None:
- pci_quirks_config = ['xend-pci-quirks']
- else:
- pci_quirks_config.insert(0, 'xend-pci-quirks')
- self.pci_quirks_config = pci_quirks_config
- except Exception, ex:
- raise XendError("Reading config file %s: %s" %
- (QUIRK_CONFIG_FILE, str(ex)))
- else:
- log.info("Config file does not exist: %s" % QUIRK_CONFIG_FILE)
- self.pci_quirks_config = ['xend-pci-quirks']
-
- devices = children(self.pci_quirks_config)
- for dev in devices:
- ids = child_at(child(dev,'pci_ids'),0)
- fields = child_at(child(dev,'pci_config_space_fields'),0)
- if self.__matchPCIdev( ids ):
- log.info("Quirks found for PCI device [%s]" % self.devid)
- return fields
-
- log.info("NO quirks found for PCI device [%s]" % self.devid)
- return []
-
- def __sendQuirks(self):
- for quirk in self.quirks:
- log.debug("Quirk Info: %04x:%02x:%02x.%1x-%s" % (self.domain,
- self.bus, self.slot, self.func, quirk))
- try:
- f = file(QUIRK_SYSFS_NODE ,"w")
- f.write( "%04x:%02x:%02x.%1x-%s" % (self.domain, self.bus,
- self.slot, self.func, quirk) )
- f.close()
- except Exception, e:
- raise VmError("pci: failed to open/write/close quirks " +
- "sysfs node - " + str(e))
-
- def __devIsUnconstrained( self ):
- if os.path.exists(PERMISSIVE_CONFIG_FILE):
- try:
- fin = file(PERMISSIVE_CONFIG_FILE, 'rb')
- try:
- pci_perm_dev_config = parse(fin)
- finally:
- fin.close()
- if pci_perm_dev_config is None:
- pci_perm_dev_config = ['']
- else:
- pci_perm_dev_config.insert(0, '')
- except Exception, ex:
- raise XendError("Reading config file %s: %s" %
- (PERMISSIVE_CONFIG_FILE,str(ex)))
- else:
- log.info("Config file does not exist: %s" % PERMISSIVE_CONFIG_FILE)
- pci_perm_dev_config = ['xend-pci-perm-devs']
-
- self.pci_perm_dev_config = pci_perm_dev_config
- devices = child_at(child(self.pci_perm_dev_config,
- 'unconstrained_dev_ids'),0)
- if self.__matchPCIdev( devices ):
- log.debug("Permissive mode enabled for PCI device [%s]" %
- self.devid)
- return True
- log.debug("Permissive mode NOT enabled for PCI device [%s]" %
- self.devid)
- return False
-
- def __sendPermDevs(self):
- if self.__devIsUnconstrained( ):
- log.debug("Unconstrained device: %04x:%02x:%02x.%1x" %
- (self.domain, self.bus, self.slot, self.func))
- try:
- f = file(PERMISSIVE_SYSFS_NODE ,"w")
- f.write( "%04x:%02x:%02x.%1x" % (self.domain, self.bus,
- self.slot, self.func))
- f.close()
- except Exception, e:
- raise VmError("pci: failed to open/write/close permissive " +
- "sysfs node: " + str(e))
diff --git a/tools/python/xen/xend/server/relocate.py b/tools/python/xen/xend/server/relocate.py
deleted file mode 100644
index 6aa6f83..0000000
--- a/tools/python/xen/xend/server/relocate.py
+++ /dev/null
@@ -1,173 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-import re
-import os
-import sys
-import StringIO
-import threading
-
-from xen.web import protocol, tcp, unix, connection
-
-from xen.xend import sxp
-from xen.xend import XendDomain
-from xen.xend import XendOptions
-from xen.xend.XendError import XendError
-from xen.xend.XendLogging import log
-
-
-class RelocationProtocol(protocol.Protocol):
- """Asynchronous handler for a connected relocation socket.
- """
-
- def __init__(self):
- protocol.Protocol.__init__(self)
- self.parser = sxp.Parser()
-
- def dataReceived(self, data):
- try:
- self.parser.input(data)
- while(self.parser.ready()):
- val = self.parser.get_val()
- res = self.dispatch(val)
- self.send_result(res)
- if self.parser.at_eof():
- self.close()
- except SystemExit:
- raise
- except:
- self.send_error()
-
- def close(self):
- if self.transport:
- self.transport.close()
-
- def send_reply(self, sxpr):
- io = StringIO.StringIO()
- sxp.show(sxpr, out=io)
- print >> io
- io.seek(0)
- if self.transport:
- return self.transport.write(io.getvalue())
- else:
- return 0
-
- def send_result(self, res):
- if res is None:
- resp = ['ok']
- else:
- resp = ['ok', res]
- return self.send_reply(resp)
-
- def send_error(self):
- (extype, exval) = sys.exc_info()[:2]
- return self.send_reply(['err',
- ['type', str(extype)],
- ['value', str(exval)]])
-
- def opname(self, name):
- return 'op_' + name.replace('.', '_')
-
- def operror(self, name, _):
- raise XendError('Invalid operation: ' +name)
-
- def dispatch(self, req):
- op_name = sxp.name(req)
- op_method_name = self.opname(op_name)
- op_method = getattr(self, op_method_name, self.operror)
- return op_method(op_name, req)
-
- def op_help(self, _1, _2):
- def nameop(x):
- if x.startswith('op_'):
- return x[3:].replace('_', '.')
- else:
- return x
-
- l = [ nameop(k) for k in dir(self) if k.startswith('op_') ]
- return l
-
- def op_quit(self, _1, _2):
- self.close()
-
- def op_receive(self, name, _):
- if self.transport:
- self.send_reply(["ready", name])
- try:
- XendDomain.instance().domain_restore_fd(
- self.transport.sock.fileno(), relocating=True)
- except:
- self.send_error()
- self.close()
- else:
- log.error(name + ": no transport")
- raise XendError(name + ": no transport")
-
- def op_sslreceive(self, name, _):
- if self.transport:
- self.send_reply(["ready", name])
- p2cread, p2cwrite = os.pipe()
- from xen.util import oshelp
- oshelp.fcntl_setfd_cloexec(p2cwrite, True)
- threading.Thread(target=connection.SSLSocketServerConnection.recv2fd,
- args=(self.transport.sock, p2cwrite)).start()
- try:
- XendDomain.instance().domain_restore_fd(p2cread,
- relocating=True)
- except:
- os.close(p2cread)
- os.close(p2cwrite)
- self.send_error()
- self.close()
- else:
- log.error(name + ": no transport")
- raise XendError(name + ": no transport")
-
-
-def listenRelocation():
- xoptions = XendOptions.instance()
- if xoptions.get_xend_unix_server():
- path = '/var/lib/xend/relocation-socket'
- unix.UnixListener(path, RelocationProtocol)
-
- interface = xoptions.get_xend_relocation_address()
-
- hosts_allow = xoptions.get_xend_relocation_hosts_allow()
- if hosts_allow == '':
- hosts_allow = None
- else:
- hosts_allow = map(re.compile, hosts_allow.split(" "))
-
- if xoptions.get_xend_relocation_server():
- port = xoptions.get_xend_relocation_port()
- tcp.TCPListener(RelocationProtocol, port, interface = interface,
- hosts_allow = hosts_allow)
-
- if xoptions.get_xend_relocation_ssl_server():
- port = xoptions.get_xend_relocation_ssl_port()
- ssl_key_file = xoptions.get_xend_relocation_server_ssl_key_file()
- ssl_cert_file = xoptions.get_xend_relocation_server_ssl_cert_file()
-
- if ssl_key_file and ssl_cert_file:
- tcp.SSLTCPListener(RelocationProtocol, port, interface = interface,
- hosts_allow = hosts_allow,
- ssl_key_file = ssl_key_file,
- ssl_cert_file = ssl_cert_file)
- else:
- raise XendError("ssl_key_file or ssl_cert_file for ssl relocation server is missing.")
-
diff --git a/tools/python/xen/xend/server/tests/__init__.py b/tools/python/xen/xend/server/tests/__init__.py
deleted file mode 100644
index 8d1c8b6..0000000
--- a/tools/python/xen/xend/server/tests/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tools/python/xen/xend/server/tests/test_controllers.py b/tools/python/xen/xend/server/tests/test_controllers.py
deleted file mode 100644
index dd26775..0000000
--- a/tools/python/xen/xend/server/tests/test_controllers.py
+++ /dev/null
@@ -1,81 +0,0 @@
-import os
-import re
-import unittest
-
-import xen.xend.XendOptions
-
-xen.xend.XendOptions.XendOptions.config_default = '/dev/null'
-
-from xen.xend.server import netif
-
-
-FAKE_DOMID = 42
-FAKE_DEVID = 63
-
-
-xoptions = xen.xend.XendOptions.instance()
-
-
-class test_controllers(unittest.TestCase):
-
- def testNetif(self):
- controller = self.controllerInstance(netif.NetifController)
-
- self.assertNetif(controller.getDeviceDetails({}), None)
- self.assertNetif(
- controller.getDeviceDetails({'mac': 'aa:bb:cc:dd:ee:ff'}),
- 'aa:bb:cc:dd:ee:ff')
-
-
-
- def assertNetif(self, results, expectedMac):
-
- (devid, backdets, frontdets) = results
-
- self.assertEqual(devid, FAKE_DEVID)
-
- self.assertEqual(backdets['handle'], str(FAKE_DEVID))
- self.assertEqual(backdets['script'],
- os.path.join(xoptions.network_script_dir,
- xoptions.get_vif_script()))
- self.assertValidMac(backdets['mac'], expectedMac)
-
- self.assertEqual(frontdets['handle'], str(FAKE_DEVID))
- self.assertValidMac(frontdets['mac'], expectedMac)
-
-
- MAC_REGEXP = re.compile('^' +
- ':'.join([r'[0-9a-f][0-9a-f]'
- for i in range(0, 6)]) +
- '$')
-
- def assertValidMac(self, mac, expected):
- if expected:
- self.assertEqual(mac, expected)
- else:
- self.assert_(self.MAC_REGEXP.match(mac))
-
-
- def controllerInstance(self, cls):
- """Allocate an instance of the given controller class, and override
- methods as appropriate so that we can run tests without needing
- Xenstored."""
-
- result = cls(FakeXendDomainInfo())
-
- result.allocateDeviceID = fakeID
-
- return result
-
-
-class FakeXendDomainInfo:
- def getDomainPath(self):
- return "/test/fake/domain/%d/" % FAKE_DOMID
-
-
-def fakeID():
- return FAKE_DEVID
-
-
-def test_suite():
- return unittest.makeSuite(test_controllers)
diff --git a/tools/python/xen/xend/server/udevevent.py b/tools/python/xen/xend/server/udevevent.py
deleted file mode 100644
index 6d61b8e..0000000
--- a/tools/python/xen/xend/server/udevevent.py
+++ /dev/null
@@ -1,92 +0,0 @@
-import socket
-
-from xen.web import protocol, unix
-
-from xen.xend.XendLogging import log
-from xen.xend import XendNode
-from xen.xend import XendOptions
-
-UDEV_EVENT_PATH = '\0/org/xen/xend/udev_event'
-
-class UdevEventProtocol(protocol.Protocol):
-
- def __init__(self):
- protocol.Protocol.__init__(self)
-
- def dataReceived(self, data):
- udev_event = {}
- for entry in data.split('\0'):
- try:
- opt, val = entry.split("=")
- udev_event[opt] = val
- except (TypeError, ValueError):
- pass
- if udev_event.get('ACTION', None) is None:
- log.warn("Invalid udev event received")
- return
-
- log.debug("udev event received: %s", udev_event)
-
- self._process_event(udev_event)
-
- def _process_event(self, udev_event):
- try:
- if (udev_event.get('SUBSYSTEM', None) == 'pci'):
- pci_name = udev_event.get('PCI_SLOT_NAME', None)
- if (udev_event['ACTION'] == 'add'):
- log.info("Adding pci device %s", pci_name)
- XendNode.instance().add_PPCI(pci_name)
- elif (udev_event['ACTION'] == 'remove'):
- log.info("Removing pci device %s", pci_name)
- XendNode.instance().remove_PPCI(pci_name)
-
- elif (udev_event.get('SUBSYSTEM', None) == 'scsi'):
- hctl = None
- devpath = udev_event.get('DEVPATH', None)
- if devpath:
- hctl = devpath.split('/')[-1]
- if len(hctl.split(':')) != 4:
- hctl = None
- if hctl is None:
- # By any possibility, if an HCTL isn't gotten from
- # the udev event, the udev event is ignored.
- log.warn("Invalid udev event about scsi received")
- return
-
- if (udev_event['ACTION'] == 'add'):
- log.info("Adding scsi device %s", hctl)
- XendNode.instance().add_PSCSI(hctl)
- elif (udev_event['ACTION'] == 'remove'):
- log.info("Removing scsi device %s", hctl)
- XendNode.instance().remove_PSCSI(hctl)
-
- elif (udev_event.get('SUBSYSTEM', None) == 'usb'):
- busid = udev_event.get('KERNEL', None)
- if busid:
- if len(busid.split(':')) != 2:
- return
- if (udev_event['ACTION'] == 'add'):
- log.info("Adding usb device %s", busid)
- XendNode.instance().add_usbdev(busid)
- elif (udev_event['ACTION'] == 'remove'):
- log.info("Removing usb device %s", busid)
- XendNode.instance().remove_usbdev(busid)
-
- elif (udev_event.get('SUBSYSTEM', None) == 'net'):
- interface = udev_event.get('INTERFACE', None)
- if (udev_event['ACTION'] == 'add'):
- log.info("Adding net device %s", interface)
- XendNode.instance().add_network(interface)
- elif (udev_event['ACTION'] == 'remove'):
- log.info("Removing net device %s", interface)
- XendNode.instance().remove_network(interface)
-
- except Exception, e:
- log.warn("error while processing udev event(): %s" % str(e))
-
-
-def listenUdevEvent():
- xoptions = XendOptions.instance()
- if xoptions.get_xend_udev_event_server():
- unix.UnixDgramListener(UDEV_EVENT_PATH, UdevEventProtocol)
-
diff --git a/tools/python/xen/xend/server/vfbif.py b/tools/python/xen/xend/server/vfbif.py
deleted file mode 100644
index 80e81b1..0000000
--- a/tools/python/xen/xend/server/vfbif.py
+++ /dev/null
@@ -1,91 +0,0 @@
-from xen.xend.server.DevController import DevController
-from xen.xend.XendLogging import log
-
-from xen.xend.XendError import VmError
-import xen.xend
-import os
-
-CONFIG_ENTRIES = ['type', 'vncdisplay', 'vnclisten', 'vncpasswd', 'vncunused',
- 'display', 'xauthority', 'keymap', 'vnc', 'sdl', 'uuid',
- 'location', 'protocol', 'opengl']
-
-class VfbifController(DevController):
- """Virtual frame buffer controller. Handles all vfb devices for a domain.
- Note that we only support a single vfb per domain at the moment.
- """
-
- def __init__(self, vm):
- DevController.__init__(self, vm)
-
- def getDeviceDetails(self, config):
- """@see DevController.getDeviceDetails"""
-
- back = dict([(k, str(config[k])) for k in CONFIG_ENTRIES
- if config.has_key(k)])
-
- devid = 0
- return (devid, back, {})
-
-
- def getDeviceConfiguration(self, devid, transaction = None):
- result = DevController.getDeviceConfiguration(self, devid, transaction)
-
- if transaction is None:
- devinfo = self.readBackend(devid, *CONFIG_ENTRIES)
- else:
- devinfo = self.readBackendTxn(transaction, devid, *CONFIG_ENTRIES)
- return dict([(CONFIG_ENTRIES[i], devinfo[i])
- for i in range(len(CONFIG_ENTRIES))
- if devinfo[i] is not None])
-
- def waitForDevice(self, devid):
- # is a qemu-dm managed device, don't wait for hotplug for these.
- return
-
- def reconfigureDevice(self, _, config):
- """ Only allow appending location information of vnc port into
- xenstore."""
-
- if 'location' in config:
- (devid, back, front) = self.getDeviceDetails(config)
- self.writeBackend(devid, 'location', config['location'])
- return back.get('uuid')
-
- raise VmError('Refusing to reconfigure device vfb:%d' % devid)
-
- def destroyDevice(self, devid, force):
- # remove the backend xenstore entries no matter what
- # because we kill qemu-dm with extreme prejudice
- # not giving it a chance to remove them itself
- DevController.destroyDevice(self, devid, True)
-
-
- def migrate(self, deviceConfig, network, dst, step, domName):
- # Handled by qemu-dm so no action needed
- return 0
-
-
-class VkbdifController(DevController):
- """Virtual keyboard controller. Handles all vkbd devices for a domain.
- """
-
- def getDeviceDetails(self, config):
- """@see DevController.getDeviceDetails"""
- devid = 0
- back = {}
- front = {}
- return (devid, back, front)
-
- def waitForDevice(self, config):
- # is a qemu-dm managed device, don't wait for hotplug for these.
- return
-
- def destroyDevice(self, devid, force):
- # remove the backend xenstore entries no matter what
- # because we kill qemu-dm with extreme prejudice
- # not giving it a chance to remove them itself
- DevController.destroyDevice(self, devid, True)
-
- def migrate(self, deviceConfig, network, dst, step, domName):
- # Handled by qemu-dm so no action needed
- return 0
diff --git a/tools/python/xen/xend/server/vscsiif.py b/tools/python/xen/xend/server/vscsiif.py
deleted file mode 100644
index 9657e4f..0000000
--- a/tools/python/xen/xend/server/vscsiif.py
+++ /dev/null
@@ -1,246 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2007 FUJITSU Limited
-# Based on the blkif.py
-#============================================================================
-
-
-"""Support for VSCSI Devices.
-"""
-import re
-import string
-
-import types
-
-from xen.xend import sxp
-from xen.xend.XendError import VmError
-from xen.xend.XendLogging import log
-
-from xen.xend.server.DevController import DevController
-from xen.xend.server.DevConstants import xenbusState
-from xen.xend.xenstore.xstransact import xstransact
-
-class VSCSIController(DevController):
- """VSCSI Devices.
- """
- def __init__(self, vm):
- """Create a VSCSI Devices.
- """
- DevController.__init__(self, vm)
-
-
- def sxprs(self):
- """@see DevController.sxprs"""
- devslist = []
- for devid in self.deviceIDs():
- vscsi_devs = self.readBackendList(devid, "vscsi-devs")
- vscsipath = "vscsi-devs/"
- devs = []
- vscsi_config = []
- for dev in vscsi_devs:
- devpath = vscsipath + dev
- backstate = self.readBackend(devid, devpath + '/state')
- pdev = self.readBackend(devid, devpath + '/p-dev')
- pdevname = self.readBackend(devid, devpath + '/p-devname')
- vdev = self.readBackend(devid, devpath + '/v-dev')
- localdevid = self.readBackend(devid, devpath + '/devid')
- frontstate = self.readFrontend(devid, devpath + '/state')
- devs.append(['dev', \
- ['state', backstate], \
- ['devid', localdevid], \
- ['p-dev', pdev], \
- ['p-devname', pdevname], \
- ['v-dev', vdev], \
- ['frontstate', frontstate] ])
-
- vscsi_config.append(['devs', devs])
- state = self.readFrontend(devid, 'state')
- vscsi_config.append(['state', state])
- hostmode = self.readBackend(devid, 'feature-host')
- vscsi_config.append(['feature-host', hostmode])
- backid = self.readFrontend(devid, 'backend-id')
- vscsi_config.append(['backend-id', backid])
- backpath = self.readFrontend(devid, 'backend')
- vscsi_config.append(['backend', backpath])
-
- devslist.append([devid, vscsi_config])
-
- return devslist
-
-
- def getDeviceDetails(self, config):
- """@see DevController.getDeviceDetails"""
- back = {}
- vscsipath = "vscsi-devs/"
- for vscsi_config in config.get('devs', []):
- localdevid = self.allocateDeviceID()
- # vscsi-devs/dev-0
- devpath = vscsipath + 'dev-%i' % localdevid
- back[devpath] = ""
- pdev = vscsi_config.get('p-dev', '')
- back[devpath + '/p-dev'] = pdev
- pdevname = vscsi_config.get('p-devname', '')
- back[devpath + '/p-devname'] = pdevname
- vdev = vscsi_config.get('v-dev', '')
- back[devpath + '/v-dev'] = vdev
- state = vscsi_config.get('state', xenbusState['Unknown'])
- back[devpath + '/state'] = str(state)
- devid = vscsi_config.get('devid', '')
- back[devpath + '/devid'] = str(devid)
-
- host_mode = config.get('feature-host','')
- back['feature-host'] = str(host_mode)
- back['uuid'] = config.get('uuid','')
- devid = int(devid)
- return (devid, back, {})
-
-
- def readBackendList(self, devid, *args):
- frontpath = self.frontendPath(devid)
- backpath = xstransact.Read(frontpath + "/backend")
- if backpath:
- paths = map(lambda x: backpath + "/" + x, args)
- return xstransact.List(*paths)
-
-
- def getDeviceConfiguration(self, devid, transaction = None):
- config = DevController.getDeviceConfiguration(self, devid, transaction)
-
- vscsi_devs = []
-
- devs = self.readBackendList(devid, "vscsi-devs")
- vscsipath = "vscsi-devs/"
- for dev in devs:
- devpath = vscsipath + dev
- pdev = self.readBackend(devid, devpath + '/p-dev')
- pdevname = self.readBackend(devid, devpath + '/p-devname')
- vdev = self.readBackend(devid, devpath + '/v-dev')
- state = self.readBackend(devid, devpath + '/state')
- localdevid = self.readBackend(devid, devpath + '/devid')
- dev_dict = {'p-dev': pdev,
- 'p-devname': pdevname,
- 'v-dev': vdev,
- 'state': state,
- 'devid': localdevid }
- vscsi_devs.append(dev_dict)
-
- config['devs'] = vscsi_devs
- config['feature-host'] = self.readBackend(devid, 'feature-host')
- config['uuid'] = self.readBackend(devid, 'uuid')
- return config
-
-
- def configuration(self, devid, transaction = None):
- """Returns SXPR for devices on domain.
- @note: we treat this dict especially to convert to
- SXP because it is not a straight dict of strings."""
-
- configDict = self.getDeviceConfiguration(devid, transaction)
- sxpr = [self.deviceClass]
-
- # remove devs
- devs = configDict.pop('devs', [])
-
- for dev in devs:
- dev_sxpr = ['dev']
- for dev_item in dev.items():
- dev_sxpr.append(list(dev_item))
- sxpr.append(dev_sxpr)
-
- for key, val in configDict.items():
- if type(val) == type(list()):
- for v in val:
- sxpr.append([key, v])
- else:
- sxpr.append([key, val])
-
- return sxpr
-
-
- def reconfigureDevice(self, _, config):
- """@see DevController.reconfigureDevice"""
- (devid, back, front) = self.getDeviceDetails(config)
- devid = int(devid)
- vscsi_config = config['devs'][0]
- state = vscsi_config.get('state', xenbusState['Unknown'])
- driver_state = self.readBackend(devid, 'state')
-
- if str(xenbusState['Connected']) != driver_state:
- raise VmError("Driver status is not connected")
-
- uuid = self.readBackend(devid, 'uuid')
- if state == xenbusState['Initialising']:
- back['uuid'] = uuid
- self.writeBackend(devid, back)
-
- elif state == xenbusState['Closing']:
- found = False
- devs = self.readBackendList(devid, "vscsi-devs")
- hostmode = int(self.readBackend(devid, 'feature-host'))
- vscsipath = "vscsi-devs/"
- vdev = vscsi_config.get('v-dev', '')
-
- for dev in devs:
- devpath = vscsipath + dev
- old_vdev = self.readBackend(devid, devpath + '/v-dev')
-
- if hostmode == 1:
- #At hostmode, all v-dev that belongs to devid is deleted.
- found = True
- self.writeBackend(devid, devpath + '/state', \
- str(xenbusState['Closing']))
- elif vdev == old_vdev:
- found = True
- self.writeBackend(devid, devpath + '/state', \
- str(xenbusState['Closing']))
- break
-
- if not found:
- raise VmError("Device %s not connected" % vdev)
-
- else:
- raise XendError("Error configuring device invalid "
- "state '%s'" % xenbusState[state])
-
- self.writeBackend(devid, 'state', str(xenbusState['Reconfiguring']))
- return self.readBackend(devid, 'uuid')
-
-
- def cleanupDevice(self, devid):
- devs = self.readBackendList(devid, "vscsi-devs")
- vscsipath = "vscsi-devs/"
- new_num_devs = 0
-
- for dev in devs:
- new_num_devs = new_num_devs + 1
- devpath = vscsipath + dev
- devstate = self.readBackend(devid, devpath + '/state')
-
- if str(xenbusState['Closed']) == devstate:
- self.removeBackend(devid, devpath)
- frontpath = self.frontendPath(devid)
- xstransact.Remove(frontpath + '/' + devpath)
- new_num_devs = new_num_devs - 1
-
- frontpath = self.frontendPath(devid)
- front_devstate = xstransact.Read(frontpath + '/' + devpath)
- if front_devstate is not None:
- if str(xenbusState['Closed']) == front_devstate:
- self.removeBackend(devid, devpath)
- xstransact.Remove(frontpath + '/' + devpath)
- new_num_devs = new_num_devs - 1
-
- return new_num_devs
-
diff --git a/tools/python/xen/xend/server/vusbif.py b/tools/python/xen/xend/server/vusbif.py
deleted file mode 100644
index 7b37e6e..0000000
--- a/tools/python/xen/xend/server/vusbif.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2009, FUJITSU LABORATORIES LTD.
-# Author: Noboru Iwamatsu <n_iwamatsu at jp.fujitsu.com>
-#============================================================================
-
-"""Support for virtual USB host controllers.
-"""
-import re
-import string
-
-import types
-
-from xen.xend import sxp
-from xen.xend.XendError import VmError
-from xen.xend.XendLogging import log
-
-from xen.xend.server.DevController import DevController
-from xen.xend.server.DevConstants import xenbusState
-from xen.xend.xenstore.xstransact import xstransact
-
-from xen.util import vusb_util
-
-class VUSBController(DevController):
- """VUSB Devices.
- """
- def __init__(self, vm):
- """Create a VUSB Devices.
- """
- DevController.__init__(self, vm)
-
- def sxprs(self):
- """@see DevController.sxprs"""
- devslist = []
- for devid in self.deviceIDs():
- vusb_config = []
- backid = self.readFrontend(devid, 'backend-id')
- vusb_config.append(['backend-id', backid])
- state = self.readFrontend(devid, 'state')
- vusb_config.append(['state', state])
- backpath = self.readFrontend(devid, 'backend')
- vusb_config.append(['backend', backpath])
- usbver = self.readBackend(devid, 'usb-ver')
- vusb_config.append(['usb-ver', usbver])
- numports = self.readBackend(devid, 'num-ports')
- vusb_config.append(['num-ports', numports])
-
- portpath = "port/"
- ports = ['port']
- for i in range(1, int(numports) + 1):
- bus = self.readBackend(devid, portpath + '%i' % i)
- ports.append(['%i' % i, str(bus)])
-
- vusb_config.append(ports)
- devslist.append([devid, vusb_config])
-
- return devslist
-
- def getDeviceDetails(self, config):
- """@see DevController.getDeviceDetails"""
- back = {}
- devid = self.allocateDeviceID()
- usbver = config.get('usb-ver', '')
- numports = config.get('num-ports', '')
- back['usb-ver'] = str(usbver)
- back['num-ports'] = str(numports)
- for i in range(1, int(numports) + 1):
- back['port/%i' % i] = config['port-%i' % i]
- return (devid, back, {})
-
- def getDeviceConfiguration(self, devid, transaction = None):
- """@see DevController.configuration"""
- config = DevController.getDeviceConfiguration(self, devid, transaction)
- if transaction is None:
- hcinfo = self.readBackend(devid, 'usb-ver', 'num-ports')
- else:
- hcinfo = self.readBackendTxn(transaction, devid,
- 'usb-ver', 'num-ports')
- (usbver, numports) = hcinfo
- config['usb-ver'] = str(usbver)
- config['num-ports'] = str(numports)
- for i in range(1, int(numports) + 1):
- if transaction is None:
- config['port-%i' % i] = self.readBackend(devid, 'port/%i' % i)
- else:
- config['port-%i' % i] = self.readBackendTxn(transaction, devid,
- 'port/%i' % i)
- return config
-
- def reconfigureDevice(self, devid, config):
- """@see DevController.reconfigureDevice"""
- cur_config = self.getDeviceConfiguration(devid)
-
- numports = cur_config['num-ports']
- for i in range(1, int(numports) + 1):
- if config.has_key('port-%i' % i):
- if not config['port-%i' % i] == cur_config['port-%i' % i]:
- if not cur_config['port-%i' % i] == "":
- vusb_util.unbind_usb_device(cur_config['port-%i' % i])
- self.writeBackend(devid, 'port/%i' % i,
- config['port-%i' % i])
- if not config['port-%i' % i] == "":
- vusb_util.bind_usb_device(config['port-%i' % i])
-
- return self.readBackend(devid, 'uuid')
-
- def waitForBackend(self, devid):
- return (0, "ok - no hotplug")
-
- def waitForBackend_destroy(self, backpath):
- return 0
-
- def migrate(self, deviceConfig, network, dst, step, domName):
- raise VmError('Migration not permitted with assigned USB device.')
diff --git a/tools/python/xen/xend/sxp.py b/tools/python/xen/xend/sxp.py
deleted file mode 100644
index c87270f..0000000
--- a/tools/python/xen/xend/sxp.py
+++ /dev/null
@@ -1,765 +0,0 @@
-#!/usr/bin/env python
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
-
-"""
-Input-driven parsing for s-expression (sxp) format.
-Create a parser: pin = Parser();
-Then call pin.input(buf) with your input.
-Call pin.input_eof() when done.
-Use pin.read() to see if a value has been parsed, pin.get_val()
-to get a parsed value. You can call ready and get_val at any time -
-you don't have to wait until after calling input_eof.
-
-"""
-from __future__ import generators
-
-import sys
-import types
-import errno
-import string
-from StringIO import StringIO
-
-__all__ = [
- "mime_type",
- "ParseError",
- "Parser",
- "atomp",
- "show",
- "show_xml",
- "elementp",
- "name",
- "attributes",
- "attribute",
- "children",
- "child",
- "child_at",
- "child0",
- "child1",
- "child2",
- "child3",
- "child4",
- "child_value",
- "has_id",
- "with_id",
- "child_with_id",
- "elements",
- "merge",
- "to_string",
- "from_string",
- "all_from_string",
- "parse",
- ]
-
-mime_type = "application/sxp"
-
-escapes = {
- 'a': '\a',
- 'b': '\b',
- 't': '\t',
- 'n': '\n',
- 'v': '\v',
- 'f': '\f',
- 'r': '\r',
- '\\': '\\',
- '\'': '\'',
- '\"': '\"'}
-
-k_list_open = "("
-k_list_close = ")"
-k_attr_open = "@"
-k_eval = "!"
-
-escapes_rev = {}
-for k in escapes:
- escapes_rev[escapes[k]] = k
-
-class ParseError(StandardError):
-
- def __init__(self, parser, value):
- self.parser = parser
- self.value = value
-
- def __str__(self):
- return self.value
-
-class ParserState:
-
- def __init__(self, fn, parent=None):
- self.parent = parent
- self.buf = ''
- self.val = []
- self.delim = None
- self.fn = fn
-
- def push(self, fn):
- return ParserState(fn, parent=self)
-
-class Parser:
-
- def __init__(self):
- self.error = sys.stderr
- self.reset()
-
- def reset(self):
- self.val = []
- self.eof = 0
- self.err = 0
- self.line_no = 0
- self.char_no = 0
- self.state = None
-
- def push_state(self, fn):
- self.state = self.state.push(fn)
-
- def pop_state(self):
- val = self.state
- self.state = self.state.parent
- if self.state and self.state.fn == self.state_start:
- # Return to start state - produce the value.
- self.val += self.state.val
- self.state.val = []
- return val
-
- def in_class(self, c, s):
- return s.find(c) >= 0
-
- def in_space_class(self, c):
- return self.in_class(c, ' \t\n\v\f\r')
-
- def is_separator(self, c):
- return self.in_class(c, '{}()<>[];')
-
- def in_comment_class(self, c):
- return self.in_class(c, '#')
-
- def in_string_quote_class(self, c):
- return self.in_class(c, '"\'')
-
- def in_printable_class(self, c):
- return self.in_class(c, string.printable)
-
- def set_error_stream(self, error):
- self.error = error
-
- def has_error(self):
- return self.err > 0
-
- def at_eof(self):
- return self.eof
-
- def input_eof(self):
- self.eof = 1
- self.input_char(-1)
-
- def input(self, buf):
- if not buf or len(buf) == 0:
- self.input_eof()
- else:
- for c in buf:
- self.input_char(c)
-
- def input_char(self, c):
- if self.at_eof():
- pass
- elif c == '\n':
- self.line_no += 1
- self.char_no = 0
- else:
- self.char_no += 1
-
- if self.state is None:
- self.begin_start(None)
- self.state.fn(c)
-
- def ready(self):
- return len(self.val) > 0
-
- def get_val(self):
- v = self.val[0]
- self.val = self.val[1:]
- return v
-
- def get_all(self):
- return self.val
-
- def begin_start(self, c):
- self.state = ParserState(self.state_start)
-
- def end_start(self):
- self.val += self.state.val
- self.pop_state()
-
- def state_start(self, c):
- if self.at_eof():
- self.end_start()
- elif self.in_space_class(c):
- pass
- elif self.in_comment_class(c):
- self.begin_comment(c)
- elif c == k_list_open:
- self.begin_list(c)
- elif c == k_list_close:
- raise ParseError(self, "syntax error: "+c)
- elif self.in_string_quote_class(c):
- self.begin_string(c)
- elif self.in_printable_class(c):
- self.begin_atom(c)
- elif c == chr(4):
- # ctrl-D, EOT: end-of-text.
- self.input_eof()
- else:
- raise ParseError(self, "invalid character: code %d" % ord(c))
-
- def begin_comment(self, c):
- self.push_state(self.state_comment)
- self.state.buf += c
-
- def end_comment(self):
- self.pop_state()
-
- def state_comment(self, c):
- if c == '\n' or self.at_eof():
- self.end_comment()
- else:
- self.state.buf += c
-
- def begin_string(self, c):
- self.push_state(self.state_string)
- self.state.delim = c
-
- def end_string(self):
- val = self.state.buf
- self.state.parent.val.append(val)
- self.pop_state()
-
- def state_string(self, c):
- if self.at_eof():
- raise ParseError(self, "unexpected EOF")
- elif c == self.state.delim:
- self.end_string()
- elif c == '\\':
- self.push_state(self.state_escape)
- else:
- self.state.buf += c
-
- def state_escape(self, c):
- if self.at_eof():
- raise ParseError(self, "unexpected EOF")
- d = escapes.get(c)
- if d:
- self.state.parent.buf += d
- self.pop_state()
- elif c == 'x':
- self.state.fn = self.state_hex
- self.state.val = 0
- elif c in string.octdigits:
- self.state.fn = self.state_octal
- self.state.val = 0
- self.input_char(c)
- else:
- # ignore escape if it doesn't match anything we know
- self.state.parent.buf += '\\'
- self.pop_state()
-
- def state_octal(self, c):
- def octaldigit(c):
- self.state.val *= 8
- self.state.val += ord(c) - ord('0')
- self.state.buf += c
- if self.state.val < 0 or self.state.val > 0xff:
- raise ParseError(self, "invalid octal escape: out of range " + self.state.buf)
- if len(self.state.buf) == 3:
- octaldone()
-
- def octaldone():
- d = chr(self.state.val)
- self.state.parent.buf += d
- self.pop_state()
-
- if self.at_eof():
- raise ParseError(self, "unexpected EOF")
- elif '0' <= c <= '7':
- octaldigit(c)
- elif len(self.state.buf):
- octaldone()
- self.input_char(c)
-
- def state_hex(self, c):
- def hexdone():
- d = chr(self.state.val)
- self.state.parent.buf += d
- self.pop_state()
-
- def hexdigit(c, d):
- self.state.val *= 16
- self.state.val += ord(c) - ord(d)
- self.state.buf += c
- if self.state.val < 0 or self.state.val > 0xff:
- raise ParseError(self, "invalid hex escape: out of range " + self.state.buf)
- if len(self.state.buf) == 2:
- hexdone()
-
- if self.at_eof():
- raise ParseError(self, "unexpected EOF")
- elif '0' <= c <= '9':
- hexdigit(c, '0')
- elif 'A' <= c <= 'F':
- hexdigit(c, 'A')
- elif 'a' <= c <= 'f':
- hexdigit(c, 'a')
- elif len(buf):
- hexdone()
- self.input_char(c)
-
- def begin_atom(self, c):
- self.push_state(self.state_atom)
- self.state.buf = c
-
- def end_atom(self):
- val = self.state.buf
- self.state.parent.val.append(val)
- self.pop_state()
-
- def state_atom(self, c):
- if self.at_eof():
- self.end_atom()
- elif (self.is_separator(c) or
- self.in_space_class(c) or
- self.in_comment_class(c)):
- self.end_atom()
- self.input_char(c)
- else:
- self.state.buf += c
-
- def begin_list(self, c):
- self.push_state(self.state_list)
-
- def end_list(self):
- val = self.state.val
- self.state.parent.val.append(val)
- self.pop_state()
-
- def state_list(self, c):
- if self.at_eof():
- raise ParseError(self, "unexpected EOF")
- elif c == k_list_close:
- self.end_list()
- else:
- self.state_start(c)
-
-def atomp(sxpr):
- """Check if an sxpr is an atom.
- """
- if sxpr == '':
- return 0
- if sxpr.isalnum() or sxpr == '@':
- return 1
- for c in sxpr:
- if c in string.whitespace: return 0
- if c in '"\'\\(){}[]<>$#&%^': return 0
- if c in string.ascii_letters: continue
- if c in string.digits: continue
- if c in '.-_:/~': continue
- return 0
- return 1
-
-def show(sxpr, out=sys.stdout):
- """Print an sxpr in bracketed (lisp-style) syntax.
- """
- if isinstance(sxpr, (types.ListType, types.TupleType)):
- out.write(k_list_open)
- i = 0
- for x in sxpr:
- if i: out.write(' ')
- show(x, out)
- i += 1
- out.write(k_list_close)
- elif isinstance(sxpr, (types.IntType, types.FloatType)):
- out.write(str(sxpr))
- elif isinstance(sxpr, types.StringType) and atomp(sxpr):
- out.write(sxpr)
- else:
- out.write(repr(str(sxpr)))
-
-def show_xml(sxpr, out=sys.stdout):
- """Print an sxpr in XML syntax.
- """
- if isinstance(sxpr, (types.ListType, types.TupleType)):
- element = name(sxpr)
- out.write('<%s' % element)
- for attr in attributes(sxpr):
- out.write(' %s=%s' % (attr[0], attr[1]))
- out.write('>')
- i = 0
- for x in children(sxpr):
- if i: out.write(' ')
- show_xml(x, out)
- i += 1
- out.write('</%s>' % element)
- elif isinstance(sxpr, types.StringType) and atomp(sxpr):
- out.write(sxpr)
- else:
- out.write(str(sxpr))
-
-def elementp(sxpr, elt=None):
- """Check if an sxpr is an element of the given type.
-
- sxpr sxpr
- elt element type
- """
- return (isinstance(sxpr, (types.ListType, types.TupleType))
- and len(sxpr)
- and (None == elt or sxpr[0] == elt))
-
-def name(sxpr):
- """Get the element name of an sxpr.
- If the sxpr is not an element (i.e. it's an atomic value) its name
- is None.
-
- sxpr
-
- returns name (None if not an element).
- """
- val = None
- if isinstance(sxpr, types.StringType):
- val = sxpr
- elif isinstance(sxpr, (types.ListType, types.TupleType)) and len(sxpr):
- val = sxpr[0]
- return val
-
-def attributes(sxpr):
- """Get the attribute list of an sxpr.
-
- sxpr
-
- returns attribute list
- """
- val = []
- if isinstance(sxpr, (types.ListType, types.TupleType)) and len(sxpr) > 1:
- attr = sxpr[1]
- if elementp(attr, k_attr_open):
- val = attr[1:]
- return val
-
-def attribute(sxpr, key, val=None):
- """Get an attribute of an sxpr.
-
- sxpr sxpr
- key attribute key
- val default value (default None)
-
- returns attribute value
- """
- for x in attributes(sxpr):
- if x[0] == key:
- val = x[1]
- break
- return val
-
-def children(sxpr, elt=None):
- """Get children of an sxpr.
-
- sxpr sxpr
- elt optional element type to filter by
-
- returns children (filtered by elt if specified)
- """
- val = []
- if isinstance(sxpr, (types.ListType, types.TupleType)) and len(sxpr) > 1:
- i = 1
- x = sxpr[i]
- if elementp(x, k_attr_open):
- i += 1
- val = sxpr[i : ]
- if elt:
- def iselt(x):
- return elementp(x, elt)
- val = filter(iselt, val)
- return val
-
-def child(sxpr, elt, val=None):
- """Get the first child of the given element type.
-
- sxpr sxpr
- elt element type
- val default value
- """
- for x in children(sxpr):
- if elementp(x, elt):
- val = x
- break
- return val
-
-def child_at(sxpr, index, val=None):
- """Get the child at the given index (zero-based).
-
- sxpr sxpr
- index index
- val default value
- """
- kids = children(sxpr)
- if len(kids) > index:
- val = kids[index]
- return val
-
-def child0(sxpr, val=None):
- """Get the zeroth child.
- """
- return child_at(sxpr, 0, val)
-
-def child1(sxpr, val=None):
- """Get the first child.
- """
- return child_at(sxpr, 1, val)
-
-def child2(sxpr, val=None):
- """Get the second child.
- """
- return child_at(sxpr, 2, val)
-
-def child3(sxpr, val=None):
- """Get the third child.
- """
- return child_at(sxpr, 3, val)
-
-def child4(sxpr, val=None):
- """Get the fourth child.
- """
- return child_at(sxpr, 4, val)
-
-def child_value(sxpr, elt, val=None):
- """Get the value of the first child of the given element type.
- Assumes the child has an atomic value.
-
- sxpr sxpr
- elt element type
- val default value
- """
- kid = child(sxpr, elt)
- if kid:
- val = child_at(kid, 0, val)
- return val
-
-def has_id(sxpr, id):
- """Test if an s-expression has a given id.
- """
- return attribute(sxpr, 'id') == id
-
-def with_id(sxpr, id, val=None):
- """Find the first s-expression with a given id, at any depth.
-
- sxpr s-exp or list
- id id
- val value if not found (default None)
-
- return s-exp or val
- """
- if isinstance(sxpr, (types.ListType, types.TupleType)):
- for n in sxpr:
- if has_id(n, id):
- val = n
- break
- v = with_id(n, id)
- if v is None: continue
- val = v
- break
- return val
-
-def child_with_id(sxpr, id, val=None):
- """Find the first child with a given id.
-
- sxpr s-exp or list
- id id
- val value if not found (default None)
-
- return s-exp or val
- """
- if isinstance(sxpr, (types.ListType, types.TupleType)):
- for n in sxpr:
- if has_id(n, id):
- val = n
- break
- return val
-
-def elements(sxpr, ctxt=None):
- """Generate elements (at any depth).
- Visit elements in pre-order.
- Values generated are (node, context)
- The context is None if there is no parent, otherwise
- (index, parent, context) where index is the node's index w.r.t its parent,
- and context is the parent's context.
-
- sxpr s-exp
-
- returns generator
- """
- yield (sxpr, ctxt)
- i = 0
- for n in children(sxpr):
- if isinstance(n, (types.ListType, types.TupleType)):
- # Calling elements() recursively does not generate recursively,
- # it just returns a generator object. So we must iterate over it.
- for v in elements(n, (i, sxpr, ctxt)):
- yield v
- i += 1
-
-def merge(s1, s2):
- """Merge sxprs s1 and s2.
- Returns an sxpr containing all the fields from s1 and s2, with
- entries in s1 overriding s2. Recursively merges fields.
-
- @param s1 sxpr
- @param s2 sxpr
- @return merged sxpr
- """
- if s1 is None:
- val = s2
- elif s2 is None:
- val = s1
- elif elementp(s1):
- name1 = name(s1)
- (m1, v1) = child_map(s1)
- (m2, v2) = child_map(s2)
- val = [name1]
- for (k1, f1) in m1.items():
- merge_list(val, f1, m2.get(k1, []))
- for (k2, f2) in m2.items():
- if k2 in m1: continue
- val.extend(f2)
- val.extend(v1)
- else:
- val = s1
- return val
-
-def merge_list(sxpr, l1, l2):
- """Merge element lists l1 and l2 into sxpr.
- The lists l1 and l2 are all element with the same name.
- Values from l1 are merged with values in l2 and stored in sxpr.
- If one list is longer than the other the excess values are used
- as they are.
-
- @param sxpr to merge into
- @param l1 sxpr list
- @param l2 sxpr list
- @return modified sxpr
- """
- n1 = len(l1)
- n2 = len(l2)
- nmin = min(n1, n2)
- for i in range(0, nmin):
- sxpr.append(merge(l1[i], l2[i]))
- for i in range(nmin, n1):
- sxpr.append(l1[i])
- for i in range(nmin, n2):
- sxpr.append(l2[i])
- return sxpr
-
-def child_map(sxpr):
- """Get a dict of the elements in sxpr and a list of its values.
- The dict maps element name to the list of elements with that name,
- and the list is the non-element children.
-
- @param sxpr
- @return (dict, list)
- """
- m = {}
- v = []
- for x in children(sxpr):
- if elementp(x):
- n = name(x)
- l = m.get(n, [])
- l.append(x)
- m[n] = l
- else:
- v.append(x)
- return (m, v)
-
-def to_string(sxpr):
- """Convert an sxpr to a string.
-
- sxpr sxpr
- returns string
- """
- io = StringIO()
- show(sxpr, io)
- io.seek(0)
- val = io.getvalue()
- io.close()
- return val
-
-def from_string(s):
- """Create an sxpr by parsing a string.
-
- s string
- returns sxpr
- """
- if s == '':
- return []
-
- io = StringIO(s)
- vals = parse(io)
- if vals is []:
- return None
- else:
- return vals[0]
-
-
-def all_from_string(s):
- """Create an sxpr list by parsing a string.
-
- s string
- returns sxpr list
- """
- io = StringIO(s)
- vals = parse(io)
- return vals
-
-def parse(io):
- """Completely parse all input from 'io'.
-
- io input file object
- returns list of values, None if incomplete
- raises ParseError on parse error
- """
- pin = Parser()
- while 1:
- buf = io.readline()
- pin.input(buf)
- if len(buf) == 0:
- break
- if pin.ready():
- val = pin.get_all()
- else:
- val = None
- return val
-
-
-if __name__ == '__main__':
- print ">main"
- pin = Parser()
- while 1:
- buf = sys.stdin.read(1024)
- #buf = sys.stdin.readline()
- pin.input(buf)
- while pin.ready():
- val = pin.get_val()
- print
- print '****** val=', val
- if len(buf) == 0:
- break
-
diff --git a/tools/python/xen/xend/tests/__init__.py b/tools/python/xen/xend/tests/__init__.py
deleted file mode 100644
index 8d1c8b6..0000000
--- a/tools/python/xen/xend/tests/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tools/python/xen/xend/tests/test_XendConfig.py b/tools/python/xen/xend/tests/test_XendConfig.py
deleted file mode 100644
index 472a49e..0000000
--- a/tools/python/xen/xend/tests/test_XendConfig.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import unittest
-
-import xen.xend.XendConfig as XendConfig
-
-
-class test_XendConfig(unittest.TestCase):
-
- def testParseFromSXP(self):
- cfg = XendConfig.XendConfig(
- sxp_obj = (
- ['vm',
- ['bootloader_args', '-q --default_args="root=/dev/sda1 ro" --extra_args="quiet" /images/VM1.sda'],
- ['bootloader', '/usr/bin/pygrub'],
- ['device', ['vif', ['mac', '00:16:3E:4C:D1:00'], ['script', 'vif-bridge'], ['bridge', 'xenbr0']]],
- ['device', ['vif', ['mac', '00:16:3E:48:56:26'], ['script', 'vif-bridge'], ['bridge', 'vbridge0']]],
- ['device', ['vbd', ['uname', 'phy:/images/VM1.sda'], ['dev', 'sda'], ['mode', 'w']]],
- ['device', ['vbd', ['uname', 'phy:/images/VM1.sdb'], ['dev', 'sdb'], ['mode', 'w']]],
- ['memory', '256'], ['name', 'VM1'], ['on_crash', 'restart'],
- ['uuid', '10927a76-fe27-49b2-8f57-2970b7bbed6c'], ['vcpus', '1']
- ]))
-
- self.assertEqual(cfg['uuid'], '10927a76-fe27-49b2-8f57-2970b7bbed6c')
- self.assertEqual(cfg['name_label'], 'VM1')
- self.assertEqual(cfg['memory_static_max'], 256)
-
- ordered_refs = cfg.ordered_device_refs()
- self.assertEqual(cfg['devices'][ordered_refs[0]][0], 'vbd')
- self.assertEqual(cfg['devices'][ordered_refs[1]][0], 'vbd')
- self.assertEqual(cfg['devices'][ordered_refs[2]][0], 'vif')
- self.assertEqual(cfg['devices'][ordered_refs[3]][0], 'vif')
- self.assertEqual(cfg['devices'][ordered_refs[0]][1]['uname'],
- 'phy:/images/VM1.sda')
- self.assertEqual(cfg['devices'][ordered_refs[1]][1]['uname'],
- 'phy:/images/VM1.sdb')
- self.assertEqual(cfg['devices'][ordered_refs[2]][1]['mac'],
- '00:16:3E:4C:D1:00')
- self.assertEqual(cfg['devices'][ordered_refs[3]][1]['mac'],
- '00:16:3E:48:56:26')
-
-
-def test_suite():
- return unittest.makeSuite(test_XendConfig)
diff --git a/tools/python/xen/xend/tests/test_sxp.py b/tools/python/xen/xend/tests/test_sxp.py
deleted file mode 100644
index dab2719..0000000
--- a/tools/python/xen/xend/tests/test_sxp.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import unittest
-
-import xen.xend.sxp
-
-
-class test_sxp(unittest.TestCase):
-
- def testAllFromString(self):
- def t(inp, expected):
- self.assertEqual(xen.xend.sxp.all_from_string(inp), expected)
-
- t('String', ['String'])
- t('(String Thing)', [['String', 'Thing']])
- t('(String) (Thing)', [['String'], ['Thing']])
-
-
- def testParseFixed(self):
- fin = file('../xen/xend/tests/xend-config.sxp', 'rb')
- try:
- config = xen.xend.sxp.parse(fin)
- self.assertEqual(
- xen.xend.sxp.child_value(
- config,
- 'xend-relocation-hosts-allow'),
- '^localhost$ ^localhost\\.localdomain$')
- finally:
- fin.close()
-
-
- def testParseConfigExample(self):
- fin = file('../../examples/xend-config.sxp', 'rb')
- try:
- config = xen.xend.sxp.parse(fin)
- finally:
- fin.close()
-
-
-def test_suite():
- return unittest.makeSuite(test_sxp)
diff --git a/tools/python/xen/xend/tests/test_uuid.py b/tools/python/xen/xend/tests/test_uuid.py
deleted file mode 100644
index d96c904..0000000
--- a/tools/python/xen/xend/tests/test_uuid.py
+++ /dev/null
@@ -1,30 +0,0 @@
-import unittest
-
-from xen.xend import uuid
-
-
-class test_uuid(unittest.TestCase):
-
- def testStringRoundtrip(self):
- def t(inp):
- self.assertEqual(uuid.fromString(uuid.toString(inp)), inp)
-
- t(uuid.create())
- t(uuid.create())
- t(uuid.create())
- t(uuid.create())
- t(uuid.create())
-
-
- def testToFromString(self):
- def t(inp, expected):
- self.assertEqual(uuid.toString(inp), expected)
- self.assertEqual(uuid.fromString(expected), inp)
-
- t([0 for _ in range(0, 16)], "00000000-0000-0000-0000-000000000000")
- t([185, 158, 125, 206, 250, 178, 125, 57, 2, 6, 162, 74, 178, 236,
- 196, 5], "b99e7dce-fab2-7d39-0206-a24ab2ecc405")
-
-
-def test_suite():
- return unittest.makeSuite(test_uuid)
diff --git a/tools/python/xen/xend/tests/xend-config.sxp b/tools/python/xen/xend/tests/xend-config.sxp
deleted file mode 100644
index 8f9ec5b..0000000
--- a/tools/python/xen/xend/tests/xend-config.sxp
+++ /dev/null
@@ -1,131 +0,0 @@
-# -*- sh -*-
-
-#
-# Xend configuration file.
-#
-
-# This example configuration is appropriate for an installation that
-# utilizes a bridged network configuration. Access to xend via http
-# is disabled.
-
-# Commented out entries show the default for that entry, unless otherwise
-# specified.
-
-#(logfile /var/log/xend.log)
-#(loglevel DEBUG)
-
-#(xend-http-server no)
-#(xend-unix-server no)
-#(xend-tcp-xmlrpc-server no)
-#(xend-unix-xmlrpc-server yes)
-#(xend-relocation-server no)
-(xend-relocation-server yes)
-
-#(xend-unix-path /var/lib/xend/xend-socket)
-
-# Port xend should use for the HTTP interface, if xend-http-server is set.
-#(xend-port 8000)
-
-# Port xend should use for the relocation interface, if xend-relocation-server
-# is set.
-#(xend-relocation-port 8002)
-
-# Address xend should listen on for HTTP connections, if xend-http-server is
-# set.
-# Specifying 'localhost' prevents remote connections.
-# Specifying the empty string '' (the default) allows all connections.
-#(xend-address '')
-#(xend-address localhost)
-
-# Address xend should listen on for relocation-socket connections, if
-# xend-relocation-server is set.
-# Meaning and default as for xend-address above.
-#(xend-relocation-address '')
-
-# The hosts allowed to talk to the relocation port. If this is empty (the
-# default), then all connections are allowed (assuming that the connection
-# arrives on a port and interface on which we are listening; see
-# xend-relocation-port and xend-relocation-address above). Otherwise, this
-# should be a space-separated sequence of regular expressions. Any host with
-# a fully-qualified domain name or an IP address that matches one of these
-# regular expressions will be accepted.
-#
-# For example:
-# (xend-relocation-hosts-allow '^localhost$ ^.*\\.example\\.org$')
-#
-#(xend-relocation-hosts-allow '')
-(xend-relocation-hosts-allow '^localhost$ ^localhost\\.localdomain$')
-
-# The limit (in kilobytes) on the size of the console buffer
-#(console-limit 1024)
-
-##
-# To bridge network traffic, like this:
-#
-#
-# dom0: ----------------- bridge -> real eth0 -> the network
-# |
-# domU: fake eth0 -> vifN.0 -+
-#
-# use
-#
-# (network-script network-bridge)
-#
-# Your default ethernet device is used as the outgoing interface, by default.
-# To use a different one (e.g. eth1) use
-#
-# (network-script 'network-bridge netdev=eth1')
-#
-# The bridge is named xenbr0, by default. To rename the bridge, use
-#
-# (network-script 'network-bridge bridge=<name>')
-#
-# It is possible to use the network-bridge script in more complicated
-# scenarios, such as having two outgoing interfaces, with two bridges, and
-# two fake interfaces per guest domain. To do things like this, write
-# yourself a wrapper script, and call network-bridge from it, as appropriate.
-#
-(network-script network-bridge)
-
-# The script used to control virtual interfaces. This can be overridden on a
-# per-vif basis when creating a domain or a configuring a new vif. The
-# vif-bridge script is designed for use with the network-bridge script, or
-# similar configurations.
-#
-# If you have overridden the bridge name using
-# (network-script 'network-bridge bridge=<name>') then you may wish to do the
-# same here. The bridge name can also be set when creating a domain or
-# configuring a new vif, but a value specified here would act as a default.
-#
-# If you are using only one bridge, the vif-bridge script will discover that,
-# so there is no need to specify it explicitly.
-#
-(vif-script vif-bridge)
-
-
-## Use the following if network traffic is routed, as an alternative to the
-# settings for bridged networking given above.
-#(network-script network-route)
-#(vif-script vif-route)
-
-
-## Use the following if network traffic is routed with NAT, as an alternative
-# to the settings for bridged networking given above.
-#(network-script network-nat)
-#(vif-script vif-nat)
-
-
-# Dom0 will balloon out when needed to free memory for domU.
-# dom0-min-mem is the lowest memory level (in MB) dom0 will get down to.
-# If dom0-min-mem=0, dom0 will never balloon out.
-(dom0-min-mem 196)
-
-# In SMP system, dom0 will use dom0-cpus # of CPUS
-# If dom0-cpus = 0, dom0 will take all cpus available
-(dom0-cpus 0)
-
-# Whether to enable core-dumps when domains crash.
-#(enable-dump no)
-
-# The tool used for initiating virtual device migration
-#(external-migration-tool '')
diff --git a/tools/python/xen/xend/uuid.py b/tools/python/xen/xend/uuid.py
deleted file mode 100644
index 7fe52cb..0000000
--- a/tools/python/xen/xend/uuid.py
+++ /dev/null
@@ -1,69 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-
-"""Universal Unique Identifiers (UUIDs). By default, UUIDs generated here are
-purely random, with no internal structure. However, they are the same size,
-and are formatted by the same conventions, as the UUIDs in the Open Software
-Foundation's Distributed Computing Environment (OSF DCE). This allows Xend to
-be used with UUIDs generated as per the DCE specification, should that be
-required. These UUIDs are also, by no coincidence, the same size as the
-'handle' stored by the Xen hypervisor along with the domain structure."""
-
-
-import commands
-import random
-
-
-def getUuidUuidgen(randomly = True):
- """Generate a UUID using the command uuidgen.
-
- If randomly is true (default) generates a random uuid.
- If randomly is false generates a time-based uuid.
- """
- cmd = "uuidgen"
- if randomly:
- cmd += " -r"
- else:
- cmd += " -t"
- return fromString(commands.getoutput(cmd))
-
-
-def getUuidRandom():
- """Generate a random UUID."""
-
- return [ random.randint(0, 255) for _ in range(0, 16) ]
-
-
-#uuidFactory = getUuidUuidgen
-uuidFactory = getUuidRandom
-
-
-def toString(u):
- return "-".join(["%02x" * 4, "%02x" * 2, "%02x" * 2, "%02x" * 2,
- "%02x" * 6]) % tuple(u)
-
-def fromString(s):
- s = s.replace('-', '')
- return [ int(s[i : i + 2], 16) for i in range(0, 32, 2) ]
-
-def create():
- return uuidFactory()
-
-def createString():
- return toString(create())
diff --git a/tools/python/xen/xend/xend b/tools/python/xen/xend/xend
deleted file mode 100644
index 9ef0210..0000000
--- a/tools/python/xen/xend/xend
+++ /dev/null
@@ -1,110 +0,0 @@
-#!/usr/bin/env python
-# -*- mode: python; -*-
-#============================================================================
-# Copyright (C) 2004 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005-2006 XenSource Inc
-#============================================================================
-
-"""Xen management daemon.
- Provides console server and HTTP management api.
-
- Run:
- xend start
-
- Restart:
- xend restart
-
- The daemon is stopped with:
- xend stop
-
- The daemon should reconnect to device control interfaces
- and recover its state when restarted.
-
- On Solaris, the daemons are SMF managed, and you should not attempt
- to start xend by hand.
-"""
-import fcntl
-import glob
-import os
-import os.path
-import sys
-import socket
-import signal
-import time
-import commands
-
-from xen.xend.server import SrvDaemon
-
-class CheckError(ValueError):
- pass
-
-def hline():
- print >>sys.stderr, "*" * 70
-
-def msg(message):
- print >>sys.stderr, "*" * 3, message
-
-def check_logging():
- """Check python logging is installed and raise an error if not.
- Logging is standard from Python 2.3 on.
- """
- try:
- import logging
- except ImportError:
- hline()
- msg("Python logging is not installed.")
- msg("Use 'make install-logging' at the xen root to install.")
- msg("")
- msg("Alternatively download and install from")
- msg("http://www.red-dove.com/python_logging.html")
- hline()
- raise CheckError("logging is not installed")
-
-def check_user():
- """Check that the effective user id is 0 (root).
- """
- if os.geteuid() != 0:
- hline()
- msg("Xend must be run as root.")
- hline()
- raise CheckError("invalid user")
-
-def start_daemon(daemon, *args):
- if os.fork() == 0:
- os.execvp(daemon, (daemon,) + args)
-
-def start_blktapctrl():
- start_daemon("blktapctrl", "")
-
-def main():
- try:
- check_logging()
- check_user()
- except CheckError:
- sys.exit(1)
-
- daemon = SrvDaemon.instance()
- if not sys.argv[1:]:
- print 'usage: %s {start|stop|reload|restart}' % sys.argv[0]
- elif sys.argv[1] == 'start':
- if os.uname()[0] != "SunOS":
- start_blktapctrl()
- return daemon.start()
- elif sys.argv[1] == 'trace_start':
- start_blktapctrl()
- return daemon.start(trace=1)
- elif sys.argv[1] == 'stop':
- return daemon.stop()
- elif sys.argv[1] == 'reload':
- return daemon.reloadConfig()
- elif sys.argv[1] == 'restart':
- start_blktapctrl()
- return daemon.stop() or daemon.start()
- elif sys.argv[1] == 'status':
- return daemon.status()
- else:
- print 'not an option:', sys.argv[1]
- return 1
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/tools/python/xen/xend/xenstore/__init__.py b/tools/python/xen/xend/xenstore/__init__.py
deleted file mode 100644
index fb12065..0000000
--- a/tools/python/xen/xend/xenstore/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
diff --git a/tools/python/xen/xend/xenstore/tests/__init__.py b/tools/python/xen/xend/xenstore/tests/__init__.py
deleted file mode 100644
index 139597f..0000000
--- a/tools/python/xen/xend/xenstore/tests/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/tools/python/xen/xend/xenstore/tests/stress_xs.py b/tools/python/xen/xend/xenstore/tests/stress_xs.py
deleted file mode 100644
index 647eb8b..0000000
--- a/tools/python/xen/xend/xenstore/tests/stress_xs.py
+++ /dev/null
@@ -1,121 +0,0 @@
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-# Copyright (c) 2005 XenSource Ltd
-
-
-import random
-import sys
-import threading
-import time
-
-import xen.lowlevel.xs
-
-from xen.xend.xenstore import xsutil
-from xen.xend.xenstore.xstransact import xstransact
-from xen.xend.xenstore.xswatch import xswatch
-
-
-PATH = '/tool/stress_xs'
-
-
-def stress():
- xstransact.Remove(PATH)
- xstransact.Mkdir(PATH)
-
- xswatch(PATH, watch_callback)
-
- def do(f):
- t = threading.Thread(target=stress_write)
- t.setDaemon(True)
- t.start()
-
- do(stress_write)
- do(stress_get_domain_path)
- do(stress_get_domain_path_xsutil)
- do(stress_open_close)
-
- while True:
- # Wait for Ctrl-C.
- time.sleep(100000000)
-
-
-def stress_write():
- xstransact.Write(PATH, 'key', '1')
- while True:
- val = xstransact.Gather(PATH, ('key', int))
- xstransact.Store(PATH, ('key', val + 1))
-
- random_sleep()
-
-
-def stress_get_domain_path():
- xs_handle = xen.lowlevel.xs.xs()
-
- domid = 0
- while True:
- xs_handle.get_domain_path(domid)
- domid += 1
-
- random_sleep()
-
-
-def stress_get_domain_path_xsutil():
- domid = 0
- while True:
- xsutil.GetDomainPath(domid)
- domid += 1
-
- random_sleep()
-
-
-def stress_open_close():
- while True:
- xs_handle = xen.lowlevel.xs.xs()
-
- try:
- try:
- trans = xs_handle.transaction_start()
- val = int(xs_handle.read(trans, PATH + '/key'))
- xs_handle.write(trans, PATH + '/key', str(val + 1))
- xs_handle.transaction_end(trans, False)
- except:
- xs_handle.transaction_end(trans, True)
-
- random_sleep()
- finally:
- del xs_handle
-
-
-def watch_callback(path):
- random_sleep()
- return True
-
-
-def random_sleep():
- d = random.randint(-50000, 500)
- if d > 0:
- time.sleep(d / 1000.0)
-
-
-def main(argv = None):
- if argv is None:
- argv = sys.argv
-
- stress()
-
- return 0
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/tools/python/xen/xend/xenstore/xstransact.py b/tools/python/xen/xend/xenstore/xstransact.py
deleted file mode 100644
index af07298..0000000
--- a/tools/python/xen/xend/xenstore/xstransact.py
+++ /dev/null
@@ -1,368 +0,0 @@
-# Copyright (C) 2005 Christian Limpach <Christian.Limpach at cl.cam.ac.uk>
-# Copyright (C) 2005 XenSource Ltd
-
-# This file is subject to the terms and conditions of the GNU General
-# Public License. See the file "COPYING" in the main directory of
-# this archive for more details.
-
-from xen.xend.xenstore.xsutil import xshandle
-
-class xstransact:
- """WARNING: Be very careful if you're instantiating an xstransact object
- yourself (i.e. not using the capitalized static helpers like .Read().
- It is essential that you clean up the object in place via
- t.commit/abort(): GC can happen at any time, including contexts where
- it's not safe to to use the shared xenstore socket fd. In particular,
- if xend forks, and GC occurs, we can have two processes trying to
- use the same xenstore fd, and all hell breaks loose.
- """
-
-
- def __init__(self, path = ""):
-
- self.in_transaction = False # Set this temporarily -- if this
- # constructor fails, then we need to
- # protect __del__.
-
- assert path is not None
- self.path = path.rstrip("/")
- self.transaction = xshandle().transaction_start()
- self.in_transaction = True
-
- def __del__(self):
- # see above.
- if self.in_transaction:
- raise RuntimeError("ERROR: GC of live transaction")
-
- def commit(self):
- if not self.in_transaction:
- raise RuntimeError
- self.in_transaction = False
- rc = xshandle().transaction_end(self.transaction, False)
- self.transaction = "0"
- return rc
-
- def abort(self):
- if not self.in_transaction:
- return True
- self.in_transaction = False
- rc = xshandle().transaction_end(self.transaction, True)
- self.transaction = "0"
- return rc
-
- def _read(self, key):
- path = self.prependPath(key)
- try:
- return xshandle().read(self.transaction, path)
- except RuntimeError, ex:
- raise RuntimeError(ex.args[0],
- '%s, while reading %s' % (ex.args[1], path))
-
- def read(self, *args):
- """If no arguments are given, return the value at this transaction's
- path. If one argument is given, treat that argument as a subpath to
- this transaction's path, and return the value at that path.
- Otherwise, treat each argument as a subpath to this transaction's
- path, and return a list composed of the values at each of those
- instead.
- """
- if len(args) == 0:
- return xshandle().read(self.transaction, self.path)
- if len(args) == 1:
- return self._read(args[0])
- ret = []
- for key in args:
- ret.append(self._read(key))
- return ret
-
- def _write(self, key, data):
- path = self.prependPath(key)
- try:
- xshandle().write(self.transaction, path, data)
- except RuntimeError, ex:
- raise RuntimeError(ex.args[0],
- ('%s, while writing %s : %s' %
- (ex.args[1], path, str(data))))
-
- def write(self, *args):
- if len(args) == 0:
- raise TypeError
- if isinstance(args[0], dict):
- for d in args:
- if not isinstance(d, dict):
- raise TypeError
- for key in d.keys():
- try:
- self._write(key, d[key])
- except TypeError, msg:
- raise TypeError('Writing %s: %s: %s' %
- (key, str(d[key]), msg))
- elif isinstance(args[0], list):
- for l in args:
- if not len(l) == 2:
- raise TypeError
- self._write(l[0], l[1])
- elif len(args) % 2 == 0:
- for i in range(len(args) / 2):
- self._write(args[i * 2], args[i * 2 + 1])
- else:
- raise TypeError
-
- def _remove(self, key):
- path = self.prependPath(key)
- return xshandle().rm(self.transaction, path)
-
- def remove(self, *args):
- """If no arguments are given, remove this transaction's path.
- Otherwise, treat each argument as a subpath to this transaction's
- path, and remove each of those instead.
- """
- if len(args) == 0:
- xshandle().rm(self.transaction, self.path)
- else:
- for key in args:
- self._remove(key)
-
- def _list(self, key):
- path = self.prependPath(key)
- l = xshandle().ls(self.transaction, path)
- if l:
- return map(lambda x: key + "/" + x, l)
- return []
-
- def list(self, *args):
- """If no arguments are given, list this transaction's path, returning
- the entries therein, or the empty list if no entries are found.
- Otherwise, treat each argument as a subpath to this transaction's
- path, and return the cumulative listing of each of those instead.
- """
- if len(args) == 0:
- ret = xshandle().ls(self.transaction, self.path)
- if ret is None:
- return []
- else:
- return ret
- else:
- ret = []
- for key in args:
- ret.extend(self._list(key))
- return ret
-
-
- def list_recursive_(self, subdir, keys):
- ret = []
- for key in keys:
- new_subdir = subdir + "/" + key
- l = xshandle().ls(self.transaction, new_subdir)
- if l:
- ret.append([key, self.list_recursive_(new_subdir, l)])
- else:
- ret.append([key, xshandle().read(self.transaction, new_subdir)])
- return ret
-
-
- def list_recursive(self, *args):
- """If no arguments are given, list this transaction's path, returning
- the entries therein, or the empty list if no entries are found.
- Otherwise, treat each argument as a subpath to this transaction's
- path, and return the cumulative listing of each of those instead.
- """
- if len(args) == 0:
- args = self.list()
- if args is None or len(args) == 0:
- return []
-
- return self.list_recursive_(self.path, args)
-
-
- def gather(self, *args):
- if len(args) and type(args[0]) != tuple:
- args = args,
- ret = []
- for tup in args:
- if len(tup) == 2:
- (key, fn) = tup
- defval = None
- else:
- (key, fn, defval) = tup
-
- val = self._read(key)
- # If fn is str, then this will successfully convert None to 'None'
- # (which we don't want). If it is int or float, then it will
- # throw ValueError on any non-convertible value. We check
- # explicitly for None, using defval instead, but allow ValueError
- # to propagate.
- if val is None:
- val = defval
- else:
- val = fn(val)
- ret.append(val)
- if len(ret) == 1:
- return ret[0]
- return ret
-
- def store(self, *args):
- if len(args) and type(args[0]) != tuple:
- args = args,
- for tup in args:
- if len(tup) == 2:
- (key, val) = tup
- try:
- fmt = { str : "%s",
- int : "%i",
- float : "%f",
- long : "%li",
- type(None) : None }[type(val)]
- except KeyError:
- raise TypeError
- else:
- (key, val, fmt) = tup
- if val is None:
- self._remove(key)
- else:
- self._write(key, fmt % val)
-
-
- def mkdir(self, *args):
- if len(args) == 0:
- xshandle().mkdir(self.transaction, self.path)
- else:
- for key in args:
- xshandle().mkdir(self.transaction, self.prependPath(key))
-
-
- def get_permissions(self, *args):
- """If no arguments are given, return the permissions at this
- transaction's path. If one argument is given, treat that argument as
- a subpath to this transaction's path, and return the permissions at
- that path. Otherwise, treat each argument as a subpath to this
- transaction's path, and return a list composed of the permissions at
- each of those instead.
- """
- if len(args) == 0:
- return xshandle().get_permissions(self.transaction, self.path)
- if len(args) == 1:
- return self._get_permissions(args[0])
- ret = []
- for key in args:
- ret.append(self._get_permissions(key))
- return ret
-
-
- def _get_permissions(self, key):
- path = self.prependPath(key)
- try:
- return xshandle().get_permissions(self.transaction, path)
- except RuntimeError, ex:
- raise RuntimeError(ex.args[0],
- '%s, while getting permissions from %s' %
- (ex.args[1], path))
-
-
- def set_permissions(self, *args):
- if len(args) == 0:
- raise TypeError
- elif isinstance(args[0], str):
- self.callRebased(args[0], self.set_permissions, *args[1:])
- else:
- if not self.path:
- raise RuntimeError('Cannot set permissions on the root')
-
- xshandle().set_permissions(self.transaction, self.path,
- list(args))
-
-
- def remove2(self, middlePath, *args):
- self.callRebased(middlePath, self.remove, *args)
-
-
- def write2(self, middlePath, *args):
- self.callRebased(middlePath, self.write, *args)
-
-
- def callRebased(self, middlePath, func, *args):
- oldpath = self.path
- self.path = self.prependPath(middlePath)
- try:
- func(*args)
- finally:
- self.path = oldpath
-
-
- def prependPath(self, key):
- if self.path:
- return self.path + '/' + key
- else:
- return key
-
-
- def Read(cls, path, *args):
- """If only one argument is given (path), return the value stored at
- that path. If two arguments are given, treat the second argument as a
- subpath within the first, and return the value at the composed path.
- Otherwise, treat each argument after the first as a subpath to the
- given path, and return a list composed of the values at each of those
- instead. This operation is performed inside a transaction.
- """
- return complete(path, lambda t: t.read(*args))
- Read = classmethod(Read)
-
- def Write(cls, path, *args):
- complete(path, lambda t: t.write(*args))
- Write = classmethod(Write)
-
- def Remove(cls, path, *args):
- """If only one argument is given (path), remove it. Otherwise, treat
- each further argument as a subpath to the given path, and remove each
- of those instead. This operation is performed inside a transaction.
- """
- complete(path, lambda t: t.remove(*args))
- Remove = classmethod(Remove)
-
- def List(cls, path, *args):
- """If only one argument is given (path), list its contents, returning
- the entries therein, or the empty list if no entries are found.
- Otherwise, treat each further argument as a subpath to the given path,
- and return the cumulative listing of each of those instead. This
- operation is performed inside a transaction.
- """
- return complete(path, lambda t: t.list(*args))
- List = classmethod(List)
-
- def ListRecursive(cls, path, *args):
- """If only one argument is given (path), list its contents
- recursively, returning the entries therein, or the empty list if no
- entries are found. Otherwise, treat each further argument as a
- subpath to the given path, and return the cumulative listing of each
- of those instead. This operation is performed inside a transaction.
- """
- return complete(path, lambda t: t.list_recursive(*args))
- ListRecursive = classmethod(ListRecursive)
-
- def Gather(cls, path, *args):
- return complete(path, lambda t: t.gather(*args))
- Gather = classmethod(Gather)
-
- def Store(cls, path, *args):
- complete(path, lambda t: t.store(*args))
- Store = classmethod(Store)
-
- def SetPermissions(cls, path, *args):
- complete(path, lambda t: t.set_permissions(*args))
- SetPermissions = classmethod(SetPermissions)
-
- def Mkdir(cls, path, *args):
- complete(path, lambda t: t.mkdir(*args))
- Mkdir = classmethod(Mkdir)
-
-
-def complete(path, f):
- while True:
- t = xstransact(path)
- try:
- result = f(t)
- if t.commit():
- return result
- except:
- t.abort()
- raise
diff --git a/tools/python/xen/xend/xenstore/xsutil.py b/tools/python/xen/xend/xenstore/xsutil.py
deleted file mode 100644
index b1bf69d..0000000
--- a/tools/python/xen/xend/xenstore/xsutil.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2005 Christian Limpach <Christian.Limpach at cl.cam.ac.uk>
-
-# This file is subject to the terms and conditions of the GNU General
-# Public License. See the file "COPYING" in the main directory of
-# this archive for more details.
-
-import threading
-import xen.lowlevel.xs
-
-xs_lock = threading.Lock()
-xs_handle = None
-
-def xshandle():
- global xs_handle, xs_lock
- if not xs_handle:
- xs_lock.acquire()
- if not xs_handle:
- xs_handle = xen.lowlevel.xs.xs()
- xs_lock.release()
- return xs_handle
-
-def IntroduceDomain(domid, page, port):
- return xshandle().introduce_domain(domid, page, port)
-
-def SetTarget(domid, target):
- return xshandle().set_target(domid, target)
-
-def GetDomainPath(domid):
- return xshandle().get_domain_path(domid)
-
-def ResumeDomain(domid):
- return xshandle().resume_domain(domid)
diff --git a/tools/python/xen/xend/xenstore/xswatch.py b/tools/python/xen/xend/xenstore/xswatch.py
deleted file mode 100644
index 0465168..0000000
--- a/tools/python/xen/xend/xenstore/xswatch.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# Copyright (C) 2005 Christian Limpach <Christian.Limpach at cl.cam.ac.uk>
-# Copyright (C) 2005 XenSource Ltd
-
-# This file is subject to the terms and conditions of the GNU General
-# Public License. See the file "COPYING" in the main directory of
-# this archive for more details.
-
-import errno
-import threading
-from xen.xend.xenstore.xsutil import xshandle
-
-
-class xswatch:
-
- ##
- # Create a watch on the given path in the store. The watch will fire
- # immediately, then subsequently each time the watched path is changed,
- # until the watch is deregistered, either by the return value from the
- # watch callback being False, or by an explicit call to unwatch.
- #
- # @param fn The function to be called when the watch fires. This function
- # should take the path that has changed as its first argument, followed by
- # the extra arguments given to this constructor, if any. It should return
- # True if the watch is to remain registered, or False if it is to be
- # deregistered.
- #
- def __init__(self, path, fn, *args, **kwargs):
- self.path = path
- self.fn = fn
- self.args = args
- self.kwargs = kwargs
- watchStart()
- xs.watch(path, self)
-
-
- def unwatch(self):
- xs.unwatch(self.path, self)
-
-
-watchThread = None
-xs = None
-xslock = threading.Lock()
-
-def watchStart():
- global watchThread
- global xs
-
- xslock.acquire()
- try:
- if watchThread:
- return
- xs = xshandle()
- watchThread = threading.Thread(name="Watcher", target=watchMain)
- watchThread.setDaemon(True)
- watchThread.start()
- finally:
- xslock.release()
-
-
-def watchMain():
- while True:
- try:
- we = xs.read_watch()
- watch = we[1]
- res = watch.fn(we[0], *watch.args, **watch.kwargs)
- if not res:
- try:
- watch.unwatch()
- except RuntimeError, exn:
- if exn.args[0] == errno.ENOENT:
- # The watch has already been unregistered -- that's
- # fine.
- pass
- else:
- raise
- except:
- pass
- # Ignore this exception -- there's no point throwing it
- # further on because that will just kill the watcher thread,
- # which achieves nothing.
diff --git a/tools/python/xen/xm/XenAPI.py b/tools/python/xen/xm/XenAPI.py
deleted file mode 100644
index f459cec..0000000
--- a/tools/python/xen/xm/XenAPI.py
+++ /dev/null
@@ -1,206 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006-2007 XenSource Inc.
-#============================================================================
-#
-# Parts of this file are based upon xmlrpclib.py, the XML-RPC client
-# interface included in the Python distribution.
-#
-# Copyright (c) 1999-2002 by Secret Labs AB
-# Copyright (c) 1999-2002 by Fredrik Lundh
-#
-# By obtaining, using, and/or copying this software and/or its
-# associated documentation, you agree that you have read, understood,
-# and will comply with the following terms and conditions:
-#
-# Permission to use, copy, modify, and distribute this software and
-# its associated documentation for any purpose and without fee is
-# hereby granted, provided that the above copyright notice appears in
-# all copies, and that both that copyright notice and this permission
-# notice appear in supporting documentation, and that the name of
-# Secret Labs AB or the author not be used in advertising or publicity
-# pertaining to distribution of the software without specific, written
-# prior permission.
-#
-# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
-# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
-# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
-# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
-# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
-# OF THIS SOFTWARE.
-# --------------------------------------------------------------------
-
-import xmlrpclib
-
-import xen.util.xmlrpcclient as xmlrpcclient
-
-errormap = {
- "INTERNAL_ERROR": "Internal error: %(1)s.",
- "MAP_DUPLICATE_KEY": "This map already contains %(1)s -> %(2)s.",
- "MESSAGE_METHOD_UNKNOWN": "The method %(1)s is unsupported.",
- "MESSAGE_PARAMETER_COUNT_MISMATCH": "The method %(1)s takes %(2)s argument(s) (%(3)s given).",
- "SESSION_AUTHENTICATION_FAILED": "Permission denied.",
- "VALUE_NOT_SUPPORTED": "Value \"%(2)s\" for %(1)s is not supported by this server. The server said \"%(3)s\".",
- "HANDLE_INVALID": "The %(1)s handle %(2)s is invalid.",
- "OPERATION_NOT_ALLOWED": "You attempted an operation that was not allowed.",
- "NETWORK_ALREADY_CONNECTED": "The network you specified already has a PIF attached to it, and so another one may not be attached.",
- "SECURITY_ERROR": "%(2)s",
- }
-
-class Failure(Exception):
- def __init__(self, details):
- try:
- # If this failure is MESSAGE_PARAMETER_COUNT_MISMATCH, then we
- # correct the return values here, to account for the fact that we
- # transparently add the session handle as the first argument.
- if details[0] == 'MESSAGE_PARAMETER_COUNT_MISMATCH':
- details[2] = str(int(details[2]) - 1)
- details[3] = str(int(details[3]) - 1)
-
- self.details = details
- except Exception, exn:
- self.details = ['INTERNAL_ERROR', 'Client-side: ' + str(exn)]
-
- def __str__(self):
- try:
- return errormap[self.details[0]] % self._details_map()
- except TypeError, exn:
- return "Message database broken: %s.\nXen-API failure: %s" % \
- (exn, str(self.details))
- except Exception, exn:
- import sys
- print >>sys.stderr, exn
- return "Xen-API failure: %s" % str(self.details)
-
- def _details_map(self):
- return dict([(str(i), self.details[i])
- for i in range(len(self.details))])
-
-
-_RECONNECT_AND_RETRY = (lambda _ : ())
-
-
-class Session(xmlrpcclient.ServerProxy):
- """A server proxy and session manager for communicating with Xend using
- the Xen-API.
-
- Example:
-
- session = Session('http://localhost:9363/')
- session.login_with_password('me', 'mypassword')
- session.xenapi.VM.start(vm_uuid)
- session.xenapi.session.logout()
-
- For now, this class also supports the legacy XML-RPC API, using
- session.xend.domain('Domain-0') and similar. This support will disappear
- once there is a working Xen-API replacement for every call in the legacy
- API.
- """
-
- def __init__(self, uri, transport=None, encoding=None, verbose=0,
- allow_none=1):
- xmlrpcclient.ServerProxy.__init__(self, uri, transport, encoding,
- verbose, allow_none)
- self._session = None
- self.last_login_method = None
- self.last_login_params = None
-
-
- def getSession(self):
- return self._session
-
- def xenapi_request(self, methodname, params):
- if methodname.startswith('login'):
- self._login(methodname, params)
- return None
- else:
- retry_count = 0
- while retry_count < 3:
- full_params = (self._session,) + params
- result = _parse_result(getattr(self, methodname)(*full_params))
- if result == _RECONNECT_AND_RETRY:
- retry_count += 1
- if self.last_login_method:
- self._login(self.last_login_method,
- self.last_login_params)
- else:
- raise xmlrpclib.Fault(401, 'You must log in')
- else:
- return result
- raise xmlrpclib.Fault(
- 500, 'Tried 3 times to get a valid session, but failed')
-
-
- def _login(self, method, params):
- result = _parse_result(getattr(self, 'session.%s' % method)(*params))
- if result == _RECONNECT_AND_RETRY:
- raise xmlrpclib.Fault(
- 500, 'Received SESSION_INVALID when logging in')
- self._session = result
- self.last_login_method = method
- self.last_login_params = params
-
-
- def __getattr__(self, name):
- if name == 'xenapi':
- return _Dispatcher(self.xenapi_request, None)
- elif name.startswith('login'):
- return lambda *params: self._login(name, params)
- else:
- return xmlrpcclient.ServerProxy.__getattr__(self, name)
-
-
-def _parse_result(result):
- if type(result) != dict or 'Status' not in result:
- raise xmlrpclib.Fault(500, 'Missing Status in response from server: ' + str(result))
- if result['Status'] == 'Success':
- if 'Value' in result:
- return result['Value']
- else:
- raise xmlrpclib.Fault(500,
- 'Missing Value in response from server')
- else:
- if 'ErrorDescription' in result:
- if result['ErrorDescription'][0] == 'SESSION_INVALID':
- return _RECONNECT_AND_RETRY
- else:
- raise Failure(result['ErrorDescription'])
- else:
- raise xmlrpclib.Fault(
- 500, 'Missing ErrorDescription in response from server')
-
-
-# Based upon _Method from xmlrpclib.
-class _Dispatcher:
- def __init__(self, send, name):
- self.__send = send
- self.__name = name
-
- def __repr__(self):
- if self.__name:
- return '<XenAPI._Dispatcher for %s>' % self.__name
- else:
- return '<XenAPI._Dispatcher>'
-
- def __getattr__(self, name):
- if self.__name is None:
- return _Dispatcher(self.__send, name)
- else:
- return _Dispatcher(self.__send, "%s.%s" % (self.__name, name))
-
- def __call__(self, *args):
- return self.__send(self.__name, args)
diff --git a/tools/python/xen/xm/__init__.py b/tools/python/xen/xm/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/tools/python/xen/xm/addlabel.py b/tools/python/xen/xm/addlabel.py
deleted file mode 100644
index 45fde49..0000000
--- a/tools/python/xen/xm/addlabel.py
+++ /dev/null
@@ -1,274 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 International Business Machines Corp.
-# Author: Reiner Sailer <sailer at us.ibm.com>
-# Author: Bryan D. Payne <bdpayne at us.ibm.com>
-#============================================================================
-
-"""Labeling a domain configuration file or a resource.
-"""
-import os
-import sys
-
-import xen.util.xsm.xsm as security
-from xen.xm.opts import OptionError
-from xen.util import xsconstants, auxbin
-from xen.xm import main as xm_main
-from xen.xm.main import server
-
-def help():
- return """
- Format: xm addlabel <label> dom <configfile> [<policy>]
- xm addlabel <label> mgt <domain name> [<policy type>:<policy>]
- xm addlabel <label> res <resource> [[<policy type>:]<policy>]
- xm addlabel <label> vif-<idx> <domain name> [<policy type>:<policy>]
-
- This program adds an acm_label entry into the 'configfile'
- for a domain, allows to label a xend-managed domain, resources
- of the VIF of a mangaged domain (requires xm to be used in
- Xen-API mode).
-
- For xend-managed domains, the 'mgt' parameter should be used and
- the 'xm' tool must have been configured to use the xen-npi for
- communication with xen. If a policy is provided as last parameter,
- its type must also be given. Currently only one type of policy is
- supported and identified as 'ACM'. An example for a valid string
- is 'ACM:xm-test'. """
-
-
-def validate_config_file(configfile):
- """Performs a simple sanity check on the configuration file passed on
- the command line. We basically just want to make sure that it's
- not a domain image file so we check for a few configuration values
- and then we are satisfied. Returned 1 on success, otherwise 0.
- """
- # read in the config file
- globs = {}
- locs = {}
- try:
- execfile(configfile, globs, locs)
- except:
- print "Invalid configuration file."
- return 0
-
- # sanity check on the data from the file
- # requiring 'memory,' 'name,' and ether 'kernel' or 'bootloader'
- count = 0
- required = ['kernel', 'bootloader', 'memory', 'name']
- for (k, v) in locs.items():
- if k in required:
- count += 1
- if count < len(required) - 1:
- print "Invalid configuration file."
- return 0
- else:
- return 1
-
-
-def add_resource_label(label, resource, policyref, policy_type):
- """Adds a resource label to the global resource label file.
- """
-
- if xm_main.serverType != xm_main.SERVER_XEN_API:
- old = server.xend.security.get_resource_label(resource)
- if len(old) == 0:
- try:
- rc = server.xend.security.set_resource_label(resource,
- policy_type,
- policyref,
- label)
- except Exception, e:
- raise
- if rc != xsconstants.XSERR_SUCCESS:
- security.err("An error occurred labeling the resource: %s" % \
- xsconstants.xserr2string(-rc))
- else:
- old = security.format_resource_label(old)
- security.err("'%s' is already labeled with '%s'." % \
- (resource,old))
- else:
- res = [ policy_type, policyref, label ]
- res_xapi = security.format_resource_label(res)
- old = server.xenapi.XSPolicy.get_resource_label(resource)
- if old == "":
- try:
- server.xenapi.XSPolicy.set_resource_label(resource,
- res_xapi,
- "")
- except Exception, e:
- raise security.XSMError("Could not label this resource: %s" %
- str(e))
- else:
- raise security.XSMError("'%s' is already labeled with '%s'" %
- (resource,old))
-
-def add_domain_label(label, configfile, policyref):
- # sanity checks: make sure this label can be instantiated later on
- ssidref = security.label2ssidref(label, policyref, 'dom')
-
- new_label = "access_control = ['policy=%s,label=%s']\n" % \
- (policyref, label)
- if not os.path.isfile(configfile):
- security.err("Configuration file \'" + configfile + "\' not found.")
- config_fd = open(configfile, "ra+")
- for line in config_fd:
- if not security.access_control_re.match(line):
- continue
- config_fd.close()
- security.err("Config file \'" + configfile + "\' is already labeled.")
- config_fd.write(new_label)
- config_fd.close()
-
-def add_domain_label_xapi(label, domainname, policyref, policy_type):
- sec_lab = "%s:%s:%s" % (policy_type, policyref, label)
- if xm_main.serverType != xm_main.SERVER_XEN_API:
- old_seclab = server.xend.security.get_domain_label(domainname)
- if old_seclab[0] == '\'':
- old_seclab = old_seclab[1:]
- results = server.xend.security.set_domain_label(domainname,
- sec_lab,
- old_seclab)
- rc, ssidref = results
- if rc == xsconstants.XSERR_SUCCESS:
- if ssidref != 0:
- print "Successfully set the label of domain '%s' to '%s'.\n" \
- % (domainname,label)
- else:
- print "Successfully set the label of the dormant domain " \
- "'%s' to '%s'." % (domainname,label)
- else:
- msg = xsconstants.xserr2string(-rc)
- raise security.XSMError("An error occurred relabeling "
- "the domain: %s" % msg)
- else:
- uuids = server.xenapi.VM.get_by_name_label(domainname)
- if len(uuids) == 0:
- raise OptionError('A VM with that name does not exist.')
- if len(uuids) != 1:
- raise OptionError('There are multiple domains with the same name.')
- uuid = uuids[0]
- try:
- old_lab = server.xenapi.VM.get_security_label(uuid)
- rc = server.xenapi.VM.set_security_label(uuid, sec_lab, old_lab)
- except Exception, e:
- raise security.XSMError("Could not label the domain: %s" % e)
- if int(rc) < 0:
- raise OptionError('Could not label domain.')
- else:
- ssidref = int(rc)
- if ssidref != 0:
- print "Successfully set the label of domain '%s' to '%s'.\n" \
- % (domainname,label)
- else:
- print "Successfully set the label of the dormant domain " \
- "'%s' to '%s'." % (domainname,label)
-
-def add_vif_label(label, vmname, idx, policyref, policy_type):
- if xm_main.serverType != xm_main.SERVER_XEN_API:
- raise OptionError('Need to be configure for using xen-api.')
- vm_refs = server.xenapi.VM.get_by_name_label(vmname)
- if len(vm_refs) == 0:
- raise OptionError('A VM with the name %s does not exist.' %
- vmname)
- vif_refs = server.xenapi.VM.get_VIFs(vm_refs[0])
- if len(vif_refs) <= idx:
- raise OptionError("Bad VIF index.")
- vif_ref = server.xenapi.VIF.get_by_uuid(vif_refs[idx])
- if not vif_ref:
- print "Internal error: VIF does not exist."
- sec_lab = "%s:%s:%s" % (policy_type, policyref, label)
- try:
- old_lab = server.xenapi.VIF.get_security_label(vif_ref)
- rc = server.xenapi.VIF.set_security_label(vif_ref,
- sec_lab, old_lab)
- if int(rc) != 0:
- print "Could not label the VIF."
- else:
- print "Successfully labeled the VIF."
- except Exception, e:
- print "Could not label the VIF: %s" % str(e)
-
-
-def main(argv):
- policyref = None
- policy_type = ""
- if len(argv) not in (4, 5):
- raise OptionError('Needs either 2 or 3 arguments')
-
- label = argv[1]
-
- if len(argv) == 5:
- policyref = argv[4]
- elif security.on() == xsconstants.XS_POLICY_ACM:
- policyref = security.active_policy
- policy_type = xsconstants.ACM_POLICY_ID
- else:
- raise OptionError("ACM security is not enabled. You must specify "\
- "the policy on the command line.")
-
- if argv[2].lower() == "dom":
- configfile = argv[3]
- if configfile[0] != '/':
- for prefix in [os.path.realpath(os.path.curdir), auxbin.xen_configdir()]:
- configfile = prefix + "/" + configfile
- if os.path.isfile(configfile):
- break
- if not validate_config_file(configfile):
- raise OptionError('Invalid config file')
- else:
- add_domain_label(label, configfile, policyref)
- elif argv[2].lower() == "mgt":
- domain = argv[3]
- if policy_type == "":
- tmp = policyref.split(":")
- if len(tmp) != 2:
- raise OptionError("Policy name in wrong format.")
- policy_type, policyref = tmp
- add_domain_label_xapi(label, domain, policyref, policy_type)
- elif argv[2].lower() == "res":
- resource = argv[3]
- if policy_type == "":
- tmp = policyref.split(":")
- if len(tmp) == 1:
- policy_type = xsconstants.ACM_POLICY_ID
- elif len(tmp) == 2:
- policy_type, policyref = tmp
- else:
- raise OptionError("Policy name in wrong format.")
- add_resource_label(label, resource, policyref, policy_type)
- elif argv[2].lower().startswith("vif-"):
- try:
- idx = int(argv[2][4:])
- if idx < 0:
- raise
- except:
- raise OptionError("Bad VIF device index.")
- vmname = argv[3]
- if policy_type == "":
- tmp = policyref.split(":")
- if len(tmp) != 2:
- raise OptionError("Policy name in wrong format.")
- policy_type, policyref = tmp
- add_vif_label(label, vmname, idx, policyref, policy_type)
- else:
- raise OptionError('Need to specify either "dom", "mgt" or "res" as '
- 'object to add label to.')
-
-if __name__ == '__main__':
- try:
- main(sys.argv)
- except Exception, e:
- sys.stderr.write('Error: %s\n' % str(e))
- sys.exit(-1)
diff --git a/tools/python/xen/xm/console.py b/tools/python/xen/xm/console.py
deleted file mode 100644
index ce86369..0000000
--- a/tools/python/xen/xm/console.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# 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"
-
-def execConsole(domid, num = 0):
- xen.util.auxbin.execute(XENCONSOLE, [str(domid), "--num", str(num)])
-
-
-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:
- print >>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)
- try:
- os.execvp('vncviewer', cmdl)
- except OSError:
- print >>sys.stderr, 'Error: external vncviewer missing or not \
-in the path\nExiting'
- os._exit(-1)
diff --git a/tools/python/xen/xm/cpupool-create.py b/tools/python/xen/xm/cpupool-create.py
deleted file mode 100644
index d045fc1..0000000
--- a/tools/python/xen/xm/cpupool-create.py
+++ /dev/null
@@ -1,51 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2009 Fujitsu Technology Solutions
-#============================================================================
-
-""" Create a new unmanaged cpupool.
-"""
-
-import sys
-from xen.xm.main import serverType, SERVER_XEN_API, server
-from xen.xm.cpupool import parseCommandLine, err, help as help_options
-from xen.util.sxputils import sxp2map
-
-def help():
- return help_options()
-
-
-def main(argv):
- try:
- (opts, config) = parseCommandLine(argv)
- except StandardError, ex:
- err(str(ex))
-
- if not opts:
- return
-
- if serverType == SERVER_XEN_API:
- record = sxp2map(config)
- if type(record.get('proposed_CPUs', [])) != list:
- record['proposed_CPUs'] = [record['proposed_CPUs']]
- ref = server.xenapi.cpu_pool.create(record)
- if ref:
- server.xenapi.cpu_pool.activate(ref)
- else:
- server.xend.cpu_pool.create(config)
-
-if __name__ == '__main__':
- main(sys.argv)
-
diff --git a/tools/python/xen/xm/cpupool-new.py b/tools/python/xen/xm/cpupool-new.py
deleted file mode 100644
index d604d99..0000000
--- a/tools/python/xen/xm/cpupool-new.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2009 Fujitsu Technology Solutions
-#============================================================================
-
-""" Create a new managed cpupool.
-"""
-
-import sys
-from xen.xm.main import serverType, SERVER_XEN_API, server
-from xen.xm.cpupool import parseCommandLine, err, help as help_options
-from xen.util.sxputils import sxp2map
-
-
-def help():
- return help_options()
-
-
-def main(argv):
- try:
- (opts, config) = parseCommandLine(argv)
- except StandardError, ex:
- err(str(ex))
-
- if not opts:
- return
-
- if serverType == SERVER_XEN_API:
- record = sxp2map(config)
- if type(record.get('proposed_CPUs', [])) != list:
- record['proposed_CPUs'] = [record['proposed_CPUs']]
- server.xenapi.cpu_pool.create(record)
- else:
- server.xend.cpu_pool.new(config)
-
-if __name__ == '__main__':
- main(sys.argv)
-
diff --git a/tools/python/xen/xm/cpupool.py b/tools/python/xen/xm/cpupool.py
deleted file mode 100644
index 86372f0..0000000
--- a/tools/python/xen/xm/cpupool.py
+++ /dev/null
@@ -1,236 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2009 Fujitsu Technology Solutions
-#============================================================================
-
-""" Common function of cmds cpupool-new / cpupool-create.
-"""
-
-import sys
-import types
-import os
-
-from xen.xend import PrettyPrint
-from xen.xend import sxp
-
-from xen.xm.opts import Opts, set_value, set_true, append_value, OptionError
-
-GOPTS = Opts(use="""[options] [vars]
-
-Create a cpupool.
-
-Pool creation parameters can be set by command-line switches, from
-a python configuration script or an SXP config file. See documentation
-for --defconfig, --config. Configuration variables can be set using
-VAR=VAL on the command line. For example name=Pool-1 sets name to Pool-1.
-
-""")
-
-GOPTS.opt('help', short='h',
- fn=set_true, default=0,
- use="Print this help.")
-
-GOPTS.opt('help_config',
- fn=set_true, default=0,
- use="Print the available configuration variables (vars) for the "
- "configuration script.")
-
-GOPTS.opt('path', val='PATH',
- fn=set_value, default='.:/etc/xen/cpupool',
- use="Search path for configuration scripts. "
- "The value of PATH is a colon-separated directory list.")
-
-GOPTS.opt('defconfig', short='f', val='FILE',
- fn=set_value, default='xmdefconfig',
- use="Use the given Python configuration script."
- "The configuration script is loaded after arguments have been "
- "processed. Each command-line option sets a configuration "
- "variable named after its long option name, and these "
- "variables are placed in the environment of the script before "
- "it is loaded. Variables for options that may be repeated have "
- "list values. Other variables can be set using VAR=VAL on the "
- "command line. "
- "After the script is loaded, option values that were not set "
- "on the command line are replaced by the values set in the script.")
-
-GOPTS.default('defconfig')
-
-GOPTS.opt('config', short='F', val='FILE',
- fn=set_value, default=None,
- use="CPU pool configuration to use (SXP).\n"
- "SXP is the underlying configuration format used by Xen.\n"
- "SXP configurations can be hand-written or generated from Python "
- "configuration scripts, using the -n (dryrun) option to print "
- "the configuration.")
-
-GOPTS.opt('dryrun', short='n',
- fn=set_true, default=0,
- use="Dry run - prints the resulting configuration in SXP but "
- "does not create the CPU pool.")
-
-GOPTS.var('name', val='NAME', fn=set_value, default=None,
- use="CPU pool name.")
-
-GOPTS.var('sched', val='SCHED', fn=set_value, default='credit',
- use="Scheduler to use for the CPU pool.")
-
-GOPTS.var('cpus', val='CPUS', fn=set_value, default=1,
- use="CPUS to assign to the CPU pool.")
-
-GOPTS.var('other_config', val='OTHER_CONFIG', fn=append_value, default=[],
- use="Additional info for CPU pool")
-
-
-def sxp2map(sxp_val):
- record = {}
- for x in sxp_val:
- if isinstance(x, (types.ListType, types.TupleType)) \
- and len(x) > 1:
- if isinstance(x[1], (types.ListType, types.TupleType)):
- record[x[0]] = sxp2map(x[1])
- else:
- record[x[0]] = x[1]
- return record
-
-def err(msg):
- print >> sys.stderr, "Error: %s" % msg
- sys.exit(-1)
-
-def make_cpus_config(cfg_cpus):
- """ Taken from XendConfig. """
- # Convert 'cpus' to list of list of ints
-
- cpus_list = []
- # Convert the following string to list of ints.
- # The string supports a list of ranges (0-3),
- # seperated by commas, and negation (^1).
- # Precedence is settled by order of the string:
- # "0-3,^1" -> [0,2,3]
- # "0-3,^1,1" -> [0,1,2,3]
- def cnv(s):
- l = []
- for c in s.split(','):
- if c.find('-') != -1:
- (x, y) = c.split('-')
- for i in range(int(x), int(y)+1):
- l.append(int(i))
- else:
- # remove this element from the list
- if len(c) > 0:
- if c[0] == '^':
- l = [x for x in l if x != int(c[1:])]
- else:
- l.append(int(c))
- return l
-
- if type(cfg_cpus) == list:
- if len(cfg_cpus) > 0 and type(cfg_cpus[0]) == list:
- # If sxp_cfg was created from config.sxp,
- # the form of 'cpus' is list of list of string.
- # Convert 'cpus' to list of list of ints.
- # Conversion examples:
- # [['1']] -> [[1]]
- # [['0','2'],['1','3']] -> [[0,2],[1,3]]
- try:
- for c1 in cfg_cpus:
- cpus = []
- for c2 in c1:
- cpus.append(int(c2))
- cpus_list.append(cpus)
- except ValueError, e:
- raise err('cpus = %s: %s' % (cfg_cpus, e))
- else:
- # Conversion examples:
- # ["1"] -> [[1]]
- # ["0,2","1,3"] -> [[0,2],[1,3]]
- # ["0-3,^1","1-4,^2"] -> [[0,2,3],[1,3,4]]
- try:
- for c in cfg_cpus:
- cpus = cnv(c)
- cpus_list.append(cpus)
- except ValueError, e:
- raise err('cpus = %s: %s' % (cfg_cpus, e))
- else:
- # Conversion examples:
- # cpus=1:
- # "1" -> [[1]]
- # "0-3,^1" -> [[0,2,3]]
- # cpus=2:
- # "1" -> [[1],[1]]
- # "0-3,^1" -> [[0,2,3],[0,2,3]]
- try:
- cpus_list = cnv(cfg_cpus)
- except ValueError, e:
- err('cpus = %s: %s' % (cfg_cpus, e))
- return cpus_list
-
-def make_config(vals):
- config = ['pool']
- config += [['name_label', vals.name]]
- config += [['sched_policy', vals.sched]]
- if type(vals.cpus) == int:
- config += [['ncpu', vals.cpus], ['proposed_CPUs' , []]]
- elif type(vals.cpus) == str and len(vals.cpus) > 1 and vals.cpus[0] == '#':
- try:
- config += [['ncpu', int(vals.cpus[1:])], ['proposed_CPUs' , []]]
- except ValueError, ex:
- err('Wrong illegal of parameter "cpus"')
- else:
- prop_cpus = make_cpus_config(vals.cpus)
- config += [['ncpu', len(prop_cpus)],
- ['proposed_CPUs'] + prop_cpus]
- other_config = []
- for entry in vals.other_config:
- if '=' in entry:
- (var, val) = entry.strip().split('=', 1)
- other_config.append([var, val])
- config += [['other_config'] + other_config]
- return config
-
-def parseCommandLine(argv):
- GOPTS.reset()
- args = GOPTS.parse(argv)
-
- if GOPTS.vals.help or GOPTS.vals.help_config:
- if GOPTS.vals.help_config:
- print GOPTS.val_usage()
- return (None, None)
-
- # Process remaining args as config variables.
- for arg in args:
- if '=' in arg:
- (var, val) = arg.strip().split('=', 1)
- GOPTS.setvar(var.strip(), val.strip())
- if GOPTS.vals.config:
- try:
- config = sxp.parse(file(GOPTS.vals.config))[0]
- except IOError, ex:
- raise OptionError("Cannot read file %s: %s" % (config, ex[1]))
- else:
- GOPTS.load_defconfig()
- if not GOPTS.getopt('name') and GOPTS.getopt('defconfig'):
- GOPTS.setopt('name', os.path.basename(
- GOPTS.getopt('defconfig')))
- config = make_config(GOPTS.vals)
-
- if GOPTS.vals.dryrun:
- PrettyPrint.prettyprint(config)
- return (None, None)
-
- return (GOPTS, config)
-
-def help():
- return str(GOPTS)
-
diff --git a/tools/python/xen/xm/create.dtd b/tools/python/xen/xm/create.dtd
deleted file mode 100644
index c91ea90..0000000
--- a/tools/python/xen/xm/create.dtd
+++ /dev/null
@@ -1,154 +0,0 @@
-<!ENTITY % HTMLlat1 PUBLIC
- "-//W3C//ENTITIES Latin 1 for XHTML//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
-%HTMLlat1;
-<!ENTITY % HTMLsymbol PUBLIC
- "-//W3C//ENTITIES Symbols for XHTML//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent">
-%HTMLsymbol;
-<!ENTITY % HTMLspecial PUBLIC
- "-//W3C//ENTITIES Special for XHTML//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent">
-%HTMLspecial;
-<!-- a Uniform Resource Identifier, see [RFC2396] -->
-<!ENTITY % URI "CDATA">
-<!ENTITY % NAMEID "name ID #REQUIRED">
-<!ENTITY % CRASH_BEHAVIOUR "( destroy
- | coredump_and_destroy
- | restart
- | coredump_and_restart
- | preserve
- | rename_restart )">
-<!ENTITY % NORMAL_EXIT "( destroy | restart )">
-<!ENTITY % VDI_TYPE "( system
- | user
- | ephemeral
- | suspend
- | crashdump )">
-
-<!ELEMENT xm (vm*,
- vdi*,
- network*)>
-
-<!ELEMENT version (#PCDATA)>
-
-<!ELEMENT vm (name,
- version,
- (pv|hvm),
- memory,
- vbd*,
- vif*,
- pci*,
- vscsi*,
- console*,
- platform*,
- vcpu_param*,
- other_config*)>
-<!ATTLIST vm is_a_template CDATA #REQUIRED
- auto_power_on CDATA #REQUIRED
- s3_integrity CDATA #REQUIRED
- vcpus_max CDATA #REQUIRED
- vcpus_at_startup CDATA #REQUIRED
- pool_name CDATA #REQUIRED
- actions_after_shutdown %NORMAL_EXIT; #REQUIRED
- actions_after_reboot %NORMAL_EXIT; #REQUIRED
- actions_after_crash %CRASH_BEHAVIOUR; #REQUIRED
- PCI_bus CDATA #REQUIRED
- superpages CDATA #REQUIRED
- security_label CDATA #IMPLIED>
-
-<!ELEMENT memory EMPTY>
-<!ATTLIST memory static_min CDATA #REQUIRED
- static_max CDATA #REQUIRED
- dynamic_min CDATA #REQUIRED
- dynamic_max CDATA #REQUIRED>
-
-<!ELEMENT vbd (qos_algorithm_param*)>
-<!ATTLIST vbd %NAMEID;
- mode (RO | RW) #REQUIRED
- vdi IDREF #REQUIRED
- device CDATA #REQUIRED
- bootable CDATA #REQUIRED
- type (CD | disk) #REQUIRED
- qos_algorithm_type CDATA #REQUIRED>
-
-<!ELEMENT vif (qos_algorithm_param*)>
-<!ATTLIST vif %NAMEID;
- mac CDATA #REQUIRED
- mtu CDATA #REQUIRED
- device CDATA #REQUIRED
- qos_algorithm_type CDATA #REQUIRED
- network CDATA #IMPLIED
- security_label CDATA #IMPLIED>
-
-<!ELEMENT pci (pci_opt*)>
-<!ATTLIST pci domain CDATA #REQUIRED
- bus CDATA #REQUIRED
- slot CDATA #REQUIRED
- func CDATA #REQUIRED
- opts_str CDATA #IMPLIED
- vdevfn CDATA #IMPLIED
- key CDATA #IMPLIED>
-
-<!ELEMENT vscsi EMPTY>
-<!ATTLIST vscsi feature-host CDATA #REQUIRED
- p-dev CDATA #IMPLIED
- v-dev CDATA #IMPLIED
- devid CDATA #IMPLIED>
-
-<!ELEMENT console (other_config*)>
-<!ATTLIST console protocol (vt100|rfb|rdp) #REQUIRED>
-
-<!ELEMENT pv EMPTY>
-<!ATTLIST pv kernel CDATA #REQUIRED
- bootloader CDATA #REQUIRED
- ramdisk CDATA #REQUIRED
- args CDATA #REQUIRED
- bootloader_args CDATA #REQUIRED>
-
-<!ELEMENT hvm (boot_param*)>
-<!ATTLIST hvm boot_policy CDATA #REQUIRED>
-
-<!ELEMENT boot_param EMPTY>
-<!ATTLIST boot_param key CDATA #REQUIRED
- value CDATA #REQUIRED>
-
-<!ELEMENT vdi (name)>
-<!ATTLIST vdi %NAMEID;
- src %URI; #REQUIRED
- type %VDI_TYPE; #REQUIRED
- size CDATA #REQUIRED
- sharable CDATA #REQUIRED
- read_only CDATA #REQUIRED>
-
-<!ELEMENT network (name,
- other_config*)>
-<!ATTLIST network %NAMEID;
- default_gateway CDATA #REQUIRED
- default_netmask CDATA #REQUIRED>
-
-<!ELEMENT name (label,
- description)>
-
-<!ELEMENT label (#PCDATA)>
-<!ELEMENT description (#PCDATA)>
-
-<!ELEMENT platform EMPTY>
-<!ATTLIST platform key CDATA #REQUIRED
- value CDATA #REQUIRED>
-
-<!ELEMENT vcpu_param EMPTY>
-<!ATTLIST vcpu_param key CDATA #REQUIRED
- value CDATA #REQUIRED>
-
-<!ELEMENT pci_opt EMPTY>
-<!ATTLIST pci_opt key CDATA #REQUIRED
- value CDATA #REQUIRED>
-
-<!ELEMENT other_config EMPTY>
-<!ATTLIST other_config key CDATA #REQUIRED
- value CDATA #REQUIRED>
-
-<!ELEMENT qos_algorithm_param EMPTY>
-<!ATTLIST qos_algorithm_param key CDATA #REQUIRED
- value CDATA #REQUIRED>
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
deleted file mode 100644
index 22841aa..0000000
--- a/tools/python/xen/xm/create.py
+++ /dev/null
@@ -1,1529 +0,0 @@
-#============================================================================UTO
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 Nguyen Anh Quynh <aquynh at gmail.com>
-# Copyright (C) 2005-2006 XenSource Ltd
-#============================================================================
-
-"""Domain creation.
-"""
-import os
-import os.path
-import sys
-import socket
-import re
-import time
-import xmlrpclib
-
-from xen.xend import sxp
-from xen.xend import PrettyPrint as SXPPrettyPrint
-import xen.xend.XendClient
-from xen.xend.XendBootloader import bootloader
-from xen.xend.XendConstants import *
-from xen.xend.server.DevConstants import xenbusState
-from xen.util import blkif
-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, auxbin
-from xen.util.pci import dev_dict_to_sxp, \
- parse_pci_name_extended, PciDeviceParseError
-
-from xen.xm.opts import *
-
-from main import server
-from main import domain_name_to_domid
-import console
-
-
-gopts = Opts(use="""[options] [vars]
-
-Create a domain.
-
-Domain creation parameters can be set by command-line switches, from
-a python configuration script or an SXP config file. See documentation
-for --defconfig, --config. Configuration variables can be set using
-VAR=VAL on the command line. For example vmid=3 sets vmid to 3.
-
-""")
-
-gopts.opt('help', short='h',
- fn=set_true, default=0,
- use="Print this help.")
-
-gopts.opt('help_config',
- fn=set_true, default=0,
- use="Print the available configuration variables (vars) for the "
- "configuration script.")
-
-gopts.opt('quiet', short='q',
- fn=set_true, default=0,
- use="Quiet.")
-
-gopts.opt('path', val='PATH',
- fn=set_value, default='.:' + auxbin.xen_configdir(),
- use="Search path for configuration scripts. "
- "The value of PATH is a colon-separated directory list.")
-
-gopts.opt('defconfig', short='f', val='FILE',
- fn=set_value, default='xmdefconfig',
- use="Use the given Python configuration script."
- "The configuration script is loaded after arguments have been "
- "processed. Each command-line option sets a configuration "
- "variable named after its long option name, and these "
- "variables are placed in the environment of the script before "
- "it is loaded. Variables for options that may be repeated have "
- "list values. Other variables can be set using VAR=VAL on the "
- "command line. "
- "After the script is loaded, option values that were not set "
- "on the command line are replaced by the values set in the script.")
-
-gopts.default('defconfig')
-
-gopts.opt('config', short='F', val='FILE',
- fn=set_value, default=None,
- use="Domain configuration to use (SXP).\n"
- "SXP is the underlying configuration format used by Xen.\n"
- "SXP configurations can be hand-written or generated from Python "
- "configuration scripts, using the -n (dryrun) option to print "
- "the configuration.")
-
-gopts.opt('dryrun', short='n',
- fn=set_true, default=0,
- use="Dry run - prints the resulting configuration in SXP but "
- "does not create the domain.")
-
-gopts.opt('xmldryrun', short='x',
- fn=set_true, default=0,
- use="XML dry run - prints the resulting configuration in XML but "
- "does not create the domain.")
-
-gopts.opt('skipdtd', short='s',
- fn=set_true, default=0,
- use="Skip DTD checking - skips checks on XML before creating. "
- " Experimental. Can decrease create time." )
-
-gopts.opt('paused', short='p',
- fn=set_true, default=0,
- use='Leave the domain paused after it is created.')
-
-gopts.opt('console_autoconnect', short='c',
- 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.")
-
-gopts.var('vncviewer', val='no|yes',
- fn=set_bool, default=None,
- use="Spawn a vncviewer listening for a vnc server in the domain.\n"
- "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.\nDEPRECATED")
-
-gopts.var('vncconsole', val='no|yes',
- fn=set_bool, default=None,
- use="Spawn a vncviewer process for the domain's graphical console.\n"
- "Only valid when vnc=1.")
-
-gopts.var('name', val='NAME',
- fn=set_value, default=None,
- use="Domain name. Must be unique.")
-
-gopts.var('bootloader', val='FILE',
- fn=set_value, default=None,
- use="Path to bootloader.")
-
-gopts.var('bootargs', val='NAME',
- fn=set_value, default=None,
- use="Arguments to pass to boot loader")
-
-gopts.var('bootentry', val='NAME',
- fn=set_value, default=None,
- use="DEPRECATED. Entry to boot via boot loader. Use bootargs.")
-
-gopts.var('kernel', val='FILE',
- fn=set_value, default=None,
- use="Path to kernel image.")
-
-gopts.var('ramdisk', val='FILE',
- fn=set_value, default='',
- use="Path to ramdisk.")
-
-gopts.var('loader', val='FILE',
- fn=set_value, default='',
- use="Path to HVM firmware.")
-
-gopts.var('features', val='FEATURES',
- fn=set_value, default='',
- use="Features to enable in guest kernel")
-
-gopts.var('builder', val='FUNCTION',
- fn=set_value, default='linux',
- use="Function to use to build the domain.")
-
-gopts.var('memory', val='MEMORY',
- fn=set_int, default=128,
- use="Domain memory in MB.")
-
-gopts.var('maxmem', val='MEMORY',
- fn=set_int, default=None,
- use="Maximum domain memory in MB.")
-
-gopts.var('shadow_memory', val='MEMORY',
- fn=set_int, default=0,
- use="Domain shadow memory in MB.")
-
-gopts.var('memory_sharing', val='no|yes',
- fn=set_bool, default=0,
- use="Should memory be shared?")
-
-gopts.var('cpu', val='CPU',
- fn=set_int, default=None,
- use="CPU to run the VCPU0 on.")
-
-gopts.var('cpus', val='CPUS',
- fn=set_value, default=None,
- use="CPUS to run the domain on.")
-
-gopts.var('rtc_timeoffset', val='RTC_TIMEOFFSET',
- fn=set_int, default=0,
- use="Set RTC offset.")
-
-gopts.var('pae', val='PAE',
- fn=set_int, default=1,
- use="Disable or enable PAE of HVM domain.")
-
-gopts.var('hpet', val='HPET',
- fn=set_int, default=0,
- use="Enable virtual high-precision event timer.")
-
-gopts.var('timer_mode', val='TIMER_MODE',
- fn=set_int, default=1,
- use="""Timer mode (0=delay virtual time when ticks are missed;
- 1=virtual time is always wallclock time.""")
-
-gopts.var('tsc_mode', val='TSC_MODE',
- fn=set_int, default=0,
- use="""TSC mode (0=default, 1=always emulate, 2=never emulate, 3=pvrdtscp).""")
-
-gopts.var('nomigrate', val='NOMIGRATE',
- fn=set_int, default=0,
- use="""migratability (0=migration enabled, 1=migration disabled).""")
-
-gopts.var('vpt_align', val='VPT_ALIGN',
- fn=set_int, default=1,
- use="Enable aligning all periodic vpt to reduce timer interrupts.")
-
-gopts.var('viridian', val='VIRIDIAN',
- fn=set_int, default=0,
- use="""Expose Viridian interface to x86 HVM guest?
- (Default is 0).""")
-
-gopts.var('acpi', val='ACPI',
- fn=set_int, default=1,
- use="Disable or enable ACPI of HVM domain.")
-
-gopts.var('apic', val='APIC',
- fn=set_int, default=1,
- use="Disable or enable APIC mode.")
-
-gopts.var('vcpus', val='VCPUS',
- fn=set_int, default=1,
- use="# of Virtual CPUS in domain.")
-
-gopts.var('vcpu_avail', val='VCPUS',
- fn=set_long, default=None,
- use="Bitmask for virtual CPUs to make available immediately.")
-
-gopts.var('vhpt', val='VHPT',
- fn=set_int, default=0,
- use="Log2 of domain VHPT size for IA64.")
-
-gopts.var('cpu_cap', val='CAP',
- fn=set_int, default=None,
- use="""Set the maximum amount of cpu.
- CAP is a percentage that fixes the maximum amount of cpu.""")
-
-gopts.var('cpu_weight', val='WEIGHT',
- fn=set_int, default=None,
- use="""Set the cpu time ratio to be allocated to the domain.""")
-
-gopts.var('restart', val='onreboot|always|never',
- fn=set_value, default=None,
- use="""Deprecated. Use on_poweroff, on_reboot, and on_crash
- instead.
-
- Whether the domain should be restarted on exit.
- - onreboot: restart on exit with shutdown code reboot
- - always: always restart on exit, ignore exit code
- - never: never restart on exit, ignore exit code""")
-
-gopts.var('on_poweroff', val='destroy|restart|preserve|rename-restart',
- fn=set_value, default=None,
- use="""Behaviour when a domain exits with reason 'poweroff'.
- - destroy: the domain is cleaned up as normal;
- - restart: a new domain is started in place of the old one;
- - preserve: no clean-up is done until the domain is manually
- destroyed (using xm destroy, for example);
- - rename-restart: the old domain is not cleaned up, but is
- renamed and a new domain started in its place.
- """)
-
-gopts.var('on_reboot', val='destroy|restart|preserve|rename-restart',
- fn=set_value, default=None,
- use="""Behaviour when a domain exits with reason 'reboot'.
- - destroy: the domain is cleaned up as normal;
- - restart: a new domain is started in place of the old one;
- - preserve: no clean-up is done until the domain is manually
- destroyed (using xm destroy, for example);
- - rename-restart: the old domain is not cleaned up, but is
- renamed and a new domain started in its place.
- """)
-
-gopts.var('on_crash', val='destroy|restart|preserve|rename-restart|coredump-destroy|coredump-restart',
- fn=set_value, default=None,
- use="""Behaviour when a domain exits with reason 'crash'.
- - destroy: the domain is cleaned up as normal;
- - restart: a new domain is started in place of the old one;
- - preserve: no clean-up is done until the domain is manually
- destroyed (using xm destroy, for example);
- - rename-restart: the old domain is not cleaned up, but is
- renamed and a new domain started in its place.
- - coredump-destroy: dump the domain's core, followed by destroy
- - coredump-restart: dump the domain's core, followed by restart
- """)
-
-gopts.var('blkif', val='no|yes',
- fn=set_bool, default=0,
- use="Make the domain a block device backend.")
-
-gopts.var('netif', val='no|yes',
- fn=set_bool, default=0,
- use="Make the domain a network interface backend.")
-
-gopts.var('disk', val='phy:DEV,VDEV,MODE[,DOM]',
- fn=append_value, default=[],
- use="""Add a disk device to a domain. The physical device is DEV,
- which is exported to the domain as VDEV. The disk is read-only if MODE
- is 'r', read-write if MODE is 'w'. If DOM is specified it defines the
- backend driver domain to use for the disk.
- The option may be repeated to add more than one disk.""")
-
-gopts.var('pci', val='BUS:DEV.FUNC[@VSLOT][,msitranslate=0|1][,power_mgmt=0|1]',
- fn=append_value, default=[],
- use="""Add a PCI device to a domain, using given params (in hex).
- For example 'pci=c0:02.1'.
- If VSLOT is supplied the device will be inserted into that
- virtual slot in the guest, else a free slot is selected.
- If msitranslate is set, MSI-INTx translation is enabled if possible.
- Guest that doesn't support MSI will get IO-APIC type IRQs
- translated from physical MSI, HVM only. Default is 1.
- The option may be repeated to add more than one pci device.
- If power_mgmt is set, the guest OS will be able to program the power
- states D0-D3hot of the device, HVM only. Default=0.""")
-
-gopts.var('vscsi', val='PDEV,VDEV[,DOM]',
- fn=append_value, default=[],
- use="""Add a SCSI device to a domain. The physical device is PDEV,
- which is exported to the domain as VDEV(X:X:X:X).""")
-
-gopts.var('vusb', val="usbver=USBVER,numports=NUMPORTS," + \
- "port_1=PORT1,port_2=PORT2,port_3=PORT3,port_4=PORT4" + \
- "port_5=PORT5,port_6=PORT6,port_7=PORT7,port_8=PORT8" + \
- "port_9=PORT9,port_10=PORT10,port_11=PORT11,port_12=PORT12" + \
- "port_13=PORT13,port_14=PORT14,port_15=PORT15,port_16=PORT16",
- fn=append_value, default=[],
- use="""Add a Virtual USB Host Controller to a domain.
- The USB Spec Version is usbver (1|2, default: 2).
- usbver=1 means USB1.1, usbver=2 mens USB2.0.
- The number of root ports is numports (1 to 16, default: 8).
- This option may be repeated to add more than one host controller.""")
-
-gopts.var('ioports', val='FROM[-TO]',
- fn=append_value, default=[],
- use="""Add a legacy I/O range to a domain, using given params (in hex).
- For example 'ioports=02f8-02ff'.
- The option may be repeated to add more than one i/o range.""")
-
-gopts.var('irq', val='IRQ',
- fn=append_value, default=[],
- use="""Add an IRQ (interrupt line) to a domain.
- For example 'irq=7'.
- This option may be repeated to add more than one IRQ.""")
-
-gopts.var('vfb', val="vnc=1,sdl=1,vncunused=1,vncdisplay=N,vnclisten=ADDR,display=DISPLAY,xauthority=XAUTHORITY,vncpasswd=PASSWORD,opengl=1,keymap=FILE,serial=FILE,monitor=FILE",
- fn=append_value, default=[],
- use="""Make the domain a framebuffer backend.
- Both sdl=1 and vnc=1 can be enabled at the same time.
- For vnc=1, connect an external vncviewer. The server will listen
- on ADDR (default 127.0.0.1) on port N+5900. N defaults to the
- domain id. If vncunused=1, the server will try to find an arbitrary
- unused port above 5900. vncpasswd overrides the XenD configured
- default password.
- For sdl=1, a viewer will be started automatically using the
- given DISPLAY and XAUTHORITY, which default to the current user's
- ones. OpenGL will be used by default unless opengl is set to 0.
- keymap overrides the XendD configured default layout file.
- Serial adds a second serial support to qemu.
- Monitor adds a backend for the stubdom monitor.""")
-
-gopts.var('vif', val="type=TYPE,mac=MAC,bridge=BRIDGE,ip=IPADDR,script=SCRIPT," + \
- "backend=DOM,vifname=NAME,rate=RATE,model=MODEL,accel=ACCEL",
- fn=append_value, default=[],
- use="""Add a network interface with the given MAC address and bridge.
- The vif is configured by calling the given configuration script.
- If type is not specified, default is netfront.
- If mac is not specified a random MAC address is used.
- If not specified then the network backend chooses it's own MAC address.
- If bridge is not specified the first bridge found is used.
- If script is not specified the default script is used.
- If backend is not specified the default backend driver domain is used.
- If vifname is not specified the backend virtual interface will have name vifD.N
- where D is the domain id and N is the interface id.
- If rate is not specified the default rate is used.
- If model is not specified the default model is used.
- If accel is not specified an accelerator plugin module is not used.
- This option may be repeated to add more than one vif.
- Specifying vifs will increase the number of interfaces as needed.""")
-
-gopts.var('vif2', val="front_mac=MAC,back_mac=MAC,backend=DOM,pdev=PDEV,max_bypasses=N,bridge=BRIDGE,filter_mac=<0|1>,front_filter_mac=<0|1>",
- fn=append_value, default=[],
- use="""Add a netchannel2 network interface using given front
- and backend MAC addresses. Randomly generated
- addresses will be used if either address is missing.""")
-
-gopts.var('access_control', val="policy=POLICY,label=LABEL",
- fn=append_value, default=[],
- use="""Add a security label and the security policy reference that defines it.
- The local ssid reference is calculated when starting/resuming the domain. At
- this time, the policy is checked against the active policy as well. This way,
- migrating through save/restore is covered and local labels are automatically
- created correctly on the system where a domain is started / resumed.""")
-
-gopts.var('nics', val="NUM",
- fn=set_int, default=-1,
- use="""DEPRECATED. Use empty vif entries instead.
-
- Set the number of network interfaces.
- Use the vif option to define interface parameters, otherwise
- defaults are used. Specifying vifs will increase the
- number of interfaces as needed.""")
-
-gopts.var('root', val='DEVICE',
- fn=set_value, default='',
- use="""Set the root= parameter on the kernel command line.
- Use a device, e.g. /dev/sda1, or /dev/nfs for NFS root.""")
-
-gopts.var('extra', val="ARGS",
- fn=set_value, default='',
- use="Set extra arguments to append to the kernel command line.")
-
-gopts.var('ip', val='IPADDR',
- fn=set_value, default='',
- use="Set the kernel IP interface address.")
-
-gopts.var('gateway', val="IPADDR",
- fn=set_value, default='',
- use="Set the kernel IP gateway.")
-
-gopts.var('netmask', val="MASK",
- fn=set_value, default = '',
- use="Set the kernel IP netmask.")
-
-gopts.var('hostname', val="NAME",
- fn=set_value, default='',
- use="Set the kernel IP hostname.")
-
-gopts.var('interface', val="INTF",
- fn=set_value, default="eth0",
- use="Set the kernel IP interface name.")
-
-gopts.var('dhcp', val="off|dhcp",
- fn=set_value, default='off',
- use="Set the kernel dhcp option.")
-
-gopts.var('nfs_server', val="IPADDR",
- fn=set_value, default=None,
- use="Set the address of the NFS server for NFS root.")
-
-gopts.var('nfs_root', val="PATH",
- fn=set_value, default=None,
- use="Set the path of the root NFS directory.")
-
-gopts.var('device_model', val='FILE',
- fn=set_value, default=None,
- use="Path to device model program.")
-
-gopts.var('fda', val='FILE',
- fn=set_value, default='',
- use="Path to fda")
-
-gopts.var('fdb', val='FILE',
- fn=set_value, default='',
- use="Path to fdb")
-
-gopts.var('parallel', val='FILE',
- fn=set_value, default='',
- use="Path to parallel or pty or vc")
-
-gopts.var('serial', val='FILE',
- fn=set_value, default='',
- use="Path to serial or pty or vc")
-
-gopts.var('monitor', val='no|yes',
- fn=set_bool, default=0,
- use="""Should the device model use monitor?""")
-
-gopts.var('monitor_path', val='FILE',
- fn=set_value, default='',
- use="Non-default path to device model monitor")
-
-gopts.var('localtime', val='no|yes',
- fn=set_bool, default=0,
- use="Is RTC set to localtime?")
-
-gopts.var('keymap', val='FILE',
- fn=set_value, default='',
- use="Set keyboard layout used")
-
-gopts.var('usb', val='no|yes',
- fn=set_bool, default=0,
- use="Emulate USB devices?")
-
-gopts.var('usbdevice', val='NAME',
- fn=set_value, default='',
- use="Name of USB device to add?")
-
-gopts.var('description', val='NAME',
- fn=set_value, default='',
- use="Description of a domain")
-
-gopts.var('guest_os_type', val='NAME',
- fn=set_value, default='default',
- use="Guest OS type running in HVM")
-
-gopts.var('stdvga', val='no|yes',
- fn=set_bool, default=0,
- use="Use std vga or cirrhus logic graphics")
-
-gopts.var('isa', val='no|yes',
- fn=set_bool, default=0,
- use="Simulate an ISA only system?")
-
-gopts.var('boot', val="a|b|c|d",
- fn=set_value, default='c',
- use="Default boot device")
-
-gopts.var('nographic', val='no|yes',
- fn=set_bool, default=0,
- use="Should device models use graphics?")
-
-gopts.var('soundhw', val='audiodev',
- fn=set_value, default='',
- use="Should device models enable audio device?")
-
-gopts.var('vnc', val='',
- fn=set_value, default=None,
- use="""Should the device model use VNC?""")
-
-gopts.var('vncdisplay', val='',
- fn=set_value, default=None,
- use="""VNC display to use""")
-
-gopts.var('vnclisten', val='',
- fn=set_value, default=None,
- use="""Address for VNC server to listen on.""")
-
-gopts.var('vncunused', val='',
- fn=set_bool, default=1,
- use="""Try to find an unused port for the VNC server.
- Only valid when vnc=1.""")
-
-gopts.var('videoram', val='MEMORY',
- fn=set_int, default=4,
- use="""Maximum amount of videoram a guest can allocate
- for frame buffer.""")
-
-gopts.var('sdl', val='',
- fn=set_value, default=None,
- use="""Should the device model use SDL?""")
-
-gopts.var('gfx_passthru', val='',
- fn=set_value, default=None,
- use="""Passthrough graphics card?""")
-
-gopts.var('opengl', val='',
- fn=set_value, default=None,
- use="""Enable\Disable OpenGL""")
-
-gopts.var('display', val='DISPLAY',
- fn=set_value, default=None,
- use="X11 display to use")
-
-gopts.var('xauthority', val='XAUTHORITY',
- fn=set_value, default=None,
- use="X11 Authority to use")
-
-gopts.var('uuid', val='',
- fn=set_value, default=None,
- use="""xenstore UUID (universally unique identifier) to use. One
- will be randomly generated if this option is not set, just like MAC
- addresses for virtual network interfaces. This must be a unique
- value across the entire cluster.""")
-
-gopts.var('on_xend_start', val='ignore|start',
- fn=set_value, default='ignore',
- use='Action to perform when xend starts')
-
-gopts.var('on_xend_stop', val='ignore|shutdown|suspend',
- fn=set_value, default="ignore",
- use="""Behaviour when Xend stops:
- - ignore: Domain continues to run;
- - shutdown: Domain is shutdown;
- - suspend: Domain is suspended;
- """)
-
-gopts.var('target', val='TARGET',
- fn=set_int, default=0,
- use="Set domain target.")
-
-gopts.var('hap', val='HAP',
- fn=set_int, default=1,
- use="""Hap status (0=hap is disabled;
- 1=hap is enabled.""")
-
-gopts.var('nestedhvm', val='NESTEDHVM',
- fn=set_int, default=0,
- use="""Nested HVM status (0=Nested HVM is disabled;
- 1=Nested HVM is enabled.""")
-
-gopts.var('s3_integrity', val='TBOOT_MEMORY_PROTECT',
- fn=set_int, default=1,
- use="""Should domain memory integrity be verified during S3?
- (0=protection is disabled; 1=protection is enabled.""")
-
-gopts.var('oos', val='OOS',
- fn=set_int, default=1,
- use="""Should out-of-sync shadow page tabled be enabled?
- (0=OOS is disabled; 1=OOS is enabled.""")
-
-gopts.var('cpuid', val="IN[,SIN]:eax=EAX,ebx=EBX,ecx=ECX,edx=EDX",
- fn=append_value, default=[],
- use="""Cpuid description.""")
-
-gopts.var('cpuid_check', val="IN[,SIN]:eax=EAX,ebx=EBX,ecx=ECX,edx=EDX",
- fn=append_value, default=[],
- use="""Cpuid check description.""")
-
-gopts.var('machine_address_size', val='BITS',
- fn=set_int, default=None,
- use="""Maximum machine address size""")
-
-gopts.var('suppress_spurious_page_faults', val='yes|no',
- fn=set_bool, default=None,
- use="""Do not inject spurious page faults into this guest""")
-
-gopts.var('pool', val='POOL NAME',
- fn=set_value, default=None,
- use="""CPU pool to use for the VM""")
-
-gopts.var('pci_msitranslate', val='TRANSLATE',
- fn=set_int, default=1,
- use="""Global PCI MSI-INTx translation flag (0=disable;
- 1=enable.""")
-
-gopts.var('pci_power_mgmt', val='POWERMGMT',
- fn=set_int, default=0,
- use="""Global PCI Power Management flag (0=disable;1=enable).""")
-
-gopts.var('xen_platform_pci', val='0|1',
- fn=set_int, default=1,
- use="Is xen_platform_pci used?")
-
-gopts.var('superpages', val='0|1',
- fn=set_int, default=0,
- use="Create domain with superpages")
-
-def err(msg):
- """Print an error to stderr and exit.
- """
- print >>sys.stderr, "Error:", msg
- sys.exit(1)
-
-
-def warn(msg):
- """Print a warning to stdout.
- """
- print >>sys.stderr, "Warning:", msg
-
-
-def strip(pre, s):
- """Strip prefix 'pre' if present.
- """
- if s.startswith(pre):
- return s[len(pre):]
- else:
- return s
-
-def configure_image(vals):
- """Create the image config.
- """
- if not vals.builder:
- return None
- config_image = [ vals.builder ]
- if vals.kernel:
- if vals.bootloader:
- # If bootloader is specified, vals.kernel will be used
- # by bootloader when boots DomU. So it is needless to
- # check the path is existent or not.
- config_image.append([ 'kernel', vals.kernel ])
- elif os.path.dirname(vals.kernel) != "" and os.path.exists(vals.kernel):
- config_image.append([ 'kernel', vals.kernel ])
- elif vals.kernel == 'hvmloader':
- # Keep hvmloader w/o a path and let xend find it.
- # This allows guest migration to a Dom0 having different
- # xen install pathes.
- config_image.append([ 'kernel', vals.kernel ])
- elif os.path.exists(os.path.abspath(vals.kernel)):
- # Keep old behaviour, if path is valid.
- config_image.append([ 'kernel', os.path.abspath(vals.kernel) ])
- else:
- raise ValueError('Cannot find kernel "%s"' % vals.kernel)
- if vals.ramdisk:
- if vals.bootloader:
- # Same with 'kernel' above
- config_image.append([ 'ramdisk', vals.ramdisk ])
- elif os.path.dirname(vals.ramdisk) != "" and os.path.exists(vals.ramdisk):
- config_image.append([ 'ramdisk', vals.ramdisk ])
- elif os.path.exists(os.path.abspath(vals.ramdisk)):
- # Keep old behaviour, if path is valid.
- config_image.append([ 'ramdisk', os.path.abspath(vals.ramdisk) ])
- else:
- raise ValueError('Cannot find ramdisk "%s"' % vals.ramdisk)
- if vals.loader:
- if os.path.dirname(vals.loader) != "" and os.path.exists(vals.loader):
- config_image.append([ 'loader', vals.loader ])
- elif vals.loader == 'hvmloader':
- # Keep hvmloader w/o a path and let xend find it.
- # This allows guest migration to a Dom0 having different
- # xen install pathes.
- config_image.append([ 'loader', vals.loader ])
- elif os.path.exists(os.path.abspath(vals.loader)):
- # Keep old behaviour, if path is valid.
- config_image.append([ 'loader', os.path.abspath(vals.loader) ])
- else:
- raise ValueError('Cannot find loader "%s"' % vals.loader)
- if vals.cmdline_ip:
- cmdline_ip = strip('ip=', vals.cmdline_ip)
- config_image.append(['ip', cmdline_ip])
- if vals.root:
- cmdline_root = strip('root=', vals.root)
- config_image.append(['root', cmdline_root])
- if vals.videoram:
- config_image.append(['videoram', vals.videoram])
- if vals.parallel:
- config_image.append(['parallel', vals.parallel])
- if vals.serial:
- config_image.append(['serial', vals.serial])
- if vals.monitor_path:
- config_image.append(['monitor_path', vals.monitor_path])
- config_image.append(['monitor', 1])
- elif vals.monitor:
- config_image.append(['monitor', vals.monitor])
- if vals.extra:
- config_image.append(['args', vals.extra])
- if vals.superpages:
- config_image.append(['superpages', vals.superpages])
-
- if vals.builder == 'hvm':
- configure_hvm(config_image, vals)
-
- if vals.vhpt != 0:
- config_image.append(['vhpt', vals.vhpt])
-
- if vals.machine_address_size:
- config_image.append(['machine_address_size', vals.machine_address_size])
-
- if vals.suppress_spurious_page_faults:
- config_image.append(['suppress_spurious_page_faults', vals.suppress_spurious_page_faults])
-
- if vals.tsc_mode is not None:
- config_image.append(['tsc_mode', vals.tsc_mode])
-
- if vals.nomigrate is not None:
- config_image.append(['nomigrate', vals.nomigrate])
-
- return config_image
-
-def configure_disks(config_devs, vals):
- """Create the config for disks (virtual block devices).
- """
- for (uname, dev, mode, backend, protocol) in vals.disk:
- if uname.startswith('tap2:'):
- cls = 'tap2'
- elif uname.startswith('tap:'):
- cls = 'tap'
- else:
- cls = 'vbd'
-
- config_vbd = [cls,
- ['uname', uname],
- ['dev', dev ],
- ['mode', mode ] ]
- if backend:
- config_vbd.append(['backend', backend])
- if protocol:
- config_vbd.append(['protocol', protocol])
- config_devs.append(['device', config_vbd])
-
-def configure_pci(config_devs, vals):
- """Create the config for pci devices.
- """
- config_pci = []
- for pci_tuple in vals.pci:
- pci_dev = pci_tuple_to_dict(pci_tuple)
- config_pci.append(dev_dict_to_sxp(pci_dev))
-
- if len(config_pci)>0:
- config_pci.insert(0, 'pci')
- config_devs.append(['device', config_pci])
-
-def configure_vscsis(config_devs, vals):
- """Create the config for vscsis (virtual scsi devices).
- """
-
- def get_devid(hctl):
- return int(hctl.split(':')[0])
-
- if len(vals.vscsi) == 0:
- return 0
-
- config_scsi = {}
- pHCTL_list = []
- vHCTL_list = []
-
- scsi_devices = vscsi_util.vscsi_get_scsidevices()
- for (p_dev, v_dev, backend) in vals.vscsi:
- (p_hctl, devname) = \
- vscsi_util.vscsi_get_hctl_and_devname_by(p_dev, scsi_devices)
-
- if p_hctl == None:
- raise ValueError('Cannot find device "%s"' % p_dev)
-
- feature_host = 0
- if v_dev == 'host':
- feature_host = 1
- scsi_info = []
- devid = get_devid(p_hctl)
- for (pHCTL, devname, _, _) in scsi_devices:
- if get_devid(pHCTL) == devid:
- scsi_info.append([devid, pHCTL, devname, pHCTL])
- else:
- scsi_info = [[get_devid(v_dev), p_hctl, devname, v_dev]]
-
- devid_key = scsi_info[0][0]
- try:
- config = config_scsi[devid_key]
- except KeyError:
- config = {'feature-host': feature_host, 'backend': backend, 'devs': []}
-
- devs = config['devs']
- for (devid, pHCTL, devname, vHCTL) in scsi_info:
- if pHCTL in pHCTL_list:
- raise ValueError('The physical device "%s" is already defined' % pHCTL)
- if vHCTL in vHCTL_list:
- raise ValueError('The virtual device "%s" is already defined' % vHCTL)
- pHCTL_list.append(pHCTL)
- vHCTL_list.append(vHCTL)
- devs.append(['dev', \
- ['state', xenbusState['Initialising']], \
- ['devid', devid], \
- ['p-dev', pHCTL], \
- ['p-devname', devname], \
- ['v-dev', vHCTL] ])
-
- if config['feature-host'] != feature_host:
- raise ValueError('The physical device "%s" cannot define '
- 'because mode is different' % scsi_info[0][1])
- if config['backend'] != backend:
- raise ValueError('The physical device "%s" cannot define '
- 'because backend is different' % scsi_info[0][1])
-
- config['devs'] = devs
- config_scsi[devid_key] = config
-
- for config in config_scsi.values():
- device = ['vscsi', ['feature-host', config['feature-host']]]
- for dev in config['devs']:
- device.append(dev)
- if config['backend']:
- device.append(['backend', config['backend']])
- config_devs.append(['device', device])
-
-def configure_vusbs(config_devs, vals):
- """Create the config for virtual usb host controllers.
- """
- for f in vals.vusb:
- d = comma_sep_kv_to_dict(f)
- config = ['vusb']
-
- usbver = 2
- if d.has_key('usbver'):
- usbver = int(d['usbver'])
- if usbver == 1 or usbver == 2:
- config.append(['usb-ver', str(usbver)])
- else:
- err('Invalid vusb option: ' + 'usbver')
-
- numports = 8
- if d.has_key('numports'):
- numports = d['numports']
- if int(numports) < 1 or int(numports) > 16:
- err('Invalid vusb option: ' + 'numports')
- config.append(['num-ports', str(numports)])
-
- port_config = []
- for i in range(1, int(numports) + 1):
- if d.has_key('port_%i' % i):
- port_config.append(['%i' % i, str(d['port_%i' % i])])
- else:
- port_config.append(['%i' % i, ""])
- port_config.insert(0, 'port')
- config.append(port_config)
- config_devs.append(['device', config])
-
-def configure_ioports(config_devs, vals):
- """Create the config for legacy i/o ranges.
- """
- for (io_from, io_to) in vals.ioports:
- config_ioports = ['ioports', ['from', io_from], ['to', io_to]]
- config_devs.append(['device', config_ioports])
-
-def configure_irq(config_devs, vals):
- """Create the config for irqs.
- """
- for irq in vals.irq:
- config_irq = ['irq', ['irq', irq]]
- config_devs.append(['device', config_irq])
-
-def configure_vfbs(config_devs, vals):
- for f in vals.vfb:
- d = comma_sep_kv_to_dict(f)
- config = ['vfb']
- #handle the legacy case
- if d.has_key("type"):
- d[d['type']] = '1'
- del d['type']
- for (k,v) in d.iteritems():
- if not k in [ 'vnclisten', 'vncunused', 'vncdisplay', 'display',
- 'videoram', 'xauthority', 'sdl', 'vnc', 'vncpasswd',
- 'opengl', 'keymap', 'serial', 'monitor' ]:
- err("configuration option %s unknown to vfbs" % k)
- config.append([k,v])
- if not d.has_key("keymap"):
- if vals.keymap:
- config.append(['keymap',vals.keymap])
- if not d.has_key("display") and os.environ.has_key("DISPLAY"):
- config.append(["display", os.environ['DISPLAY']])
- if not d.has_key("xauthority"):
- config.append(["xauthority", get_xauthority()])
- config_devs.append(['device', ['vkbd']])
- config_devs.append(['device', config])
-
-def configure_security(config, vals):
- """Create the config for ACM security labels.
- """
- access_control = vals.access_control
- num = len(access_control)
- if num == 1:
- d = access_control[0]
- policy = d.get('policy')
- label = d.get('label')
- if policy != security.active_policy:
- err("Security policy (" + policy + ") incompatible with enforced policy ("
- + security.active_policy + ")." )
- config_access_control = ['access_control',
- ['policy', policy],
- ['label', label] ]
-
- security_label = ['security', [ config_access_control ] ]
- config.append(security_label)
- elif num > 1:
- err("VM config error: Multiple access_control definitions!")
-
-def configure_mem_prot(config_image, vals):
- """Create the config for S3 memory integrity verification under tboot.
- """
- config_image.append(['s3_integrity', vals.s3_integrity])
-
-def configure_vifs(config_devs, vals):
- """Create the config for virtual network interfaces.
- """
-
- vifs = vals.vif
- vifs_n = len(vifs)
- vifs2 = vals.vif2
- vifs2_n = len(vifs2)
-
- if hasattr(vals, 'nics'):
- if vals.nics > 0:
- warn("The nics option is deprecated. Please use an empty vif "
- "entry instead:\n\n vif = [ '' ]\n")
- for _ in range(vifs_n, vals.nics):
- vifs.append('')
- vifs_n = len(vifs)
- elif vals.nics == 0:
- warn("The nics option is deprecated. Please remove it.")
-
- for c in vifs:
- d = comma_sep_kv_to_dict(c)
- config_vif = ['vif']
-
- def f(k):
- if k not in ['backend', 'bridge', 'ip', 'mac', 'script', 'type',
- 'vifname', 'rate', 'model', 'accel',
- 'policy', 'label']:
- err('Invalid vif option: ' + k)
-
- config_vif.append([k, d[k]])
-
- map(f, d.keys())
- config_devs.append(['device', config_vif])
-
- for c in vifs2:
- d = comma_sep_kv_to_dict(c)
- config_vif = ['vif2']
-
- for k in d.keys():
- if k not in ['front_mac', 'back_mac', 'backend', 'trusted',
- 'back_trusted', 'front_filter_mac', 'filter_mac',
- 'bridge', 'pdev', 'max_bypasses' ]:
- err('Invalid vif2 option: ' + k)
- config_vif.append([k, d[k]])
- config_devs.append(['device', config_vif])
-
-
-def configure_hvm(config_image, vals):
- """Create the config for HVM devices.
- """
- args = [ 'acpi', 'apic',
- 'boot',
- 'cpuid', 'cpuid_check',
- 'device_model', 'display',
- 'fda', 'fdb',
- 'gfx_passthru', 'guest_os_type',
- 'hap', 'hpet',
- 'isa',
- 'keymap',
- 'localtime',
- 'nestedhvm', 'nographic',
- 'opengl', 'oos',
- 'pae', 'pci', 'pci_msitranslate', 'pci_power_mgmt',
- 'rtc_timeoffset',
- 'sdl', 'soundhw', 'stdvga',
- 'timer_mode',
- 'usb', 'usbdevice',
- 'vcpus', 'vnc', 'vncconsole', 'vncdisplay', 'vnclisten',
- 'vncunused', 'viridian', 'vpt_align',
- 'xauthority', 'xen_extended_power_mgmt', 'xen_platform_pci',
- 'memory_sharing' ]
-
- for a in args:
- if a in vals.__dict__ and vals.__dict__[a] is not None:
- config_image.append([a, vals.__dict__[a]])
- if vals.vncpasswd is not None:
- config_image.append(['vncpasswd', vals.vncpasswd])
-
-
-def make_config(vals):
- """Create the domain configuration.
- """
-
- config = ['vm']
-
- def vcpu_conf():
- maxvcpus = False
- vcpus = False
- if hasattr(vals, 'maxvcpus'):
- maxvcpus = getattr(vals, 'maxvcpus')
- if hasattr(vals, 'vcpus'):
- vcpus = getattr(vals, 'vcpus')
-
- if maxvcpus and not vcpus:
- config.append(['vcpus', maxvcpus])
- if maxvcpus and vcpus:
- config.append(['vcpu_avail', (1 << vcpus) - 1])
- config.append(['vcpus', maxvcpus])
-
- # For case we don't have maxvcpus set but we have vcpus we preserve
- # old behaviour
- if not maxvcpus and vcpus:
- config.append(['vcpus', vcpus])
-
- def add_conf(n):
- if hasattr(vals, n):
- v = getattr(vals, n)
- if v:
- config.append([n, v])
-
- map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory',
- 'restart', 'on_poweroff', 'tsc_mode', 'nomigrate',
- 'on_reboot', 'on_crash', 'features', 'on_xend_start',
- 'on_xend_stop', 'target', 'cpuid', 'cpuid_check',
- 'machine_address_size', 'suppress_spurious_page_faults',
- 'description'])
-
- vcpu_conf()
- if vals.uuid is not None:
- config.append(['uuid', vals.uuid])
- if vals.cpu is not None:
- config.append(['cpu', vals.cpu])
- if vals.cpus is not None:
- config.append(['cpus', vals.cpus])
- if vals.cpu_cap is not None:
- config.append(['cpu_cap', vals.cpu_cap])
- if vals.cpu_weight is not None:
- config.append(['cpu_weight', vals.cpu_weight])
- if vals.blkif:
- config.append(['backend', ['blkif']])
- if vals.netif:
- config.append(['backend', ['netif']])
- if vals.localtime:
- config.append(['localtime', vals.localtime])
- if vals.oos:
- config.append(['oos', vals.oos])
- if vals.pool:
- config.append(['pool_name', vals.pool])
-
- config_image = configure_image(vals)
- if vals.bootloader:
- if vals.bootloader == "pygrub":
- vals.bootloader = auxbin.pathTo(vals.bootloader)
-
- config.append(['bootloader', vals.bootloader])
- if vals.bootargs:
- config.append(['bootloader_args', vals.bootargs])
- else:
- if vals.console_autoconnect:
- config.append(['bootloader_args', ''])
- else:
- config.append(['bootloader_args', '-q'])
- config.append(['image', config_image])
- configure_mem_prot(config, vals);
-
- config_devs = []
- configure_disks(config_devs, vals)
- configure_pci(config_devs, vals)
- configure_vscsis(config_devs, vals)
- configure_vusbs(config_devs, vals)
- configure_ioports(config_devs, vals)
- configure_irq(config_devs, vals)
- configure_vifs(config_devs, vals)
- configure_vfbs(config_devs, vals)
- configure_security(config, vals)
- config += config_devs
-
- return config
-
-def preprocess_disk(vals):
- if not vals.disk: return
- disk = []
- for v in vals.disk:
- d = v.split(',')
- n = len(d)
- if n == 3:
- d.append(None)
- d.append(None)
- elif n == 4:
- d.append(None)
- elif n == 5:
- pass
- else:
- err('Invalid disk specifier: ' + v)
- disk.append(d)
- vals.disk = disk
-
-def preprocess_cpuid(vals, attr_name):
- if not vals.cpuid: return
- cpuid = {}
- for cpuid_input in getattr(vals, attr_name):
- input_re = "(0x)?[0-9A-Fa-f]+(,(0x)?[0-9A-Fa-f]+)?"
- cpuid_match = re.match(r'(?P<input>%s):(?P<regs>.*)' % \
- input_re, cpuid_input)
- if cpuid_match != None:
- res_cpuid = cpuid_match.groupdict()
- input = res_cpuid['input']
- regs = res_cpuid['regs'].split(',')
- cpuid[input]= {} # New input
- for reg in regs:
- reg_match = re.match(r"(?P<reg>eax|ebx|ecx|edx)=(?P<val>.*)", reg)
- if reg_match == None:
- err("cpuid's syntax is (eax|ebx|ecx|edx)=value")
- res = reg_match.groupdict()
- if (res['val'][:2] != '0x' and len(res['val']) != 32):
- err("cpuid: We should specify all the bits " \
- "of the register %s for input %s\n"
- % (res['reg'], input) )
- cpuid[input][res['reg']] = res['val'] # new register
- setattr(vals, attr_name, cpuid)
-
-def pci_dict_to_tuple(dev):
- return (dev['domain'], dev['bus'], dev['slot'], dev['func'],
- dev['vdevfn'], dev.get('opts', []), dev['key'])
-
-def pci_tuple_to_dict((domain, bus, slot, func, vdevfn, opts, key)):
- pci_dev = { 'domain': domain,
- 'bus': bus,
- 'slot': slot,
- 'func': func,
- 'vdevfn': vdevfn,
- 'key': key}
- if len(opts) > 0:
- pci_dev['opts'] = opts
- return pci_dev
-
-def preprocess_pci(vals):
- if not vals.pci:
- return
- try:
- vals.pci = map(pci_dict_to_tuple, reduce(lambda x, y: x + y,
- map(parse_pci_name_extended, vals.pci)))
- except PciDeviceParseError, ex:
- err(str(ex))
-
-def preprocess_vscsi(vals):
- if not vals.vscsi: return
- scsi = []
- for scsi_str in vals.vscsi:
- d = [tmp.strip() for tmp in scsi_str.split(',')]
- n = len(d)
- if n == 2:
- tmp = d[1].split(':')
- if d[1] != 'host' and len(tmp) != 4:
- err('vscsi syntax error "%s"' % d[1])
- else:
- d.append(None)
- elif n == 3:
- pass
- else:
- err('vscsi syntax error "%s"' % scsi_str)
- scsi.append(d)
- vals.vscsi = scsi
-
-def preprocess_ioports(vals):
- if not vals.ioports: return
- ioports = []
- for v in vals.ioports:
- d = v.split('-')
- if len(d) < 1 or len(d) > 2:
- err('Invalid i/o port range specifier: ' + v)
- if len(d) == 1:
- d.append(d[0])
- # Components are in hex: add hex specifier.
- hexd = ['0x' + x for x in d]
- ioports.append(hexd)
- vals.ioports = ioports
-
-def preprocess_irq(vals):
- if not vals.irq: return
- irq = []
- for v in vals.irq:
- d = repr(v)
- irq.append(d)
- vals.irq = irq
-
-def preprocess_access_control(vals):
- if not vals.access_control:
- return
- access_controls = []
- num = len(vals.access_control)
- if num == 1:
- access_control = (vals.access_control)[0]
- acc_re = 'policy=(?P<policy>.*),label=(?P<label>.*)'
- acc_match = re.match(acc_re,access_control)
- if acc_match == None:
- err('Invalid access_control specifier: ' + access_control)
- d = acc_match.groupdict();
- access_controls.append(d)
- vals.access_control = access_controls
- elif num > 1:
- err('Multiple access_control definitions.')
-
-def preprocess_ip(vals):
- if vals.ip or vals.dhcp != 'off':
- dummy_nfs_server = '127.0.255.255'
- ip = (vals.ip
- + ':' + (vals.nfs_server or dummy_nfs_server)
- + ':' + vals.gateway
- + ':' + vals.netmask
- + ':' + vals.hostname
- + ':' + vals.interface
- + ':' + vals.dhcp)
- else:
- ip = ''
- vals.cmdline_ip = ip
-
-def preprocess_nfs(vals):
- if not vals.nfs_root: return
- if not vals.nfs_server:
- err('Must set nfs root and nfs server')
- nfs = 'nfsroot=' + vals.nfs_server + ':' + vals.nfs_root
- vals.extra = nfs + ' ' + vals.extra
-
-
-def get_host_addr():
- host = socket.gethostname()
- addr = socket.gethostbyname(host)
- return addr
-
-VNC_BASE_PORT = 5500
-
-def choose_vnc_display():
- """Try to choose a free vnc display.
- """
- def netstat_local_ports():
- """Run netstat to get a list of the local ports in use.
- """
- l = os.popen("netstat -nat").readlines()
- r = []
- # Skip 2 lines of header.
- for x in l[2:]:
- # Local port is field 3.
- y = x.split()[3]
- # Field is addr:port, split off the port.
- y = y.split(':')[-1]
- r.append(int(y))
- return r
-
- ports = netstat_local_ports()
- for d in range(1, 100):
- port = VNC_BASE_PORT + d
- if port in ports: continue
- return d
- return None
-
-def preprocess(vals):
- preprocess_disk(vals)
- preprocess_pci(vals)
- preprocess_vscsi(vals)
- preprocess_ioports(vals)
- preprocess_ip(vals)
- preprocess_irq(vals)
- preprocess_nfs(vals)
- preprocess_access_control(vals)
- preprocess_cpuid(vals, 'cpuid')
- preprocess_cpuid(vals, 'cpuid_check')
-
-
-def comma_sep_kv_to_dict(c):
- """Convert comma-separated, equals-separated key-value pairs into a
- dictionary.
- """
- d = {}
- c = c.strip()
- if len(c) > 0:
- a = c.split(',')
- for b in a:
- if b.find('=') == -1:
- err("%s should be a pair, separated by an equals sign." % b)
- (k, v) = b.split('=', 1)
- k = k.strip()
- v = v.strip()
- d[k] = v
- return d
-
-
-def make_domain(opts, config):
- """Create, build and start a domain.
-
- @param opts: options
- @param config: configuration
- @return: domain id
- @rtype: int
- """
-
- try:
- dominfo = server.xend.domain.create(config)
- except xmlrpclib.Fault, ex:
- if ex.faultCode == xen.xend.XendClient.ERROR_INVALID_DOMAIN:
- err("the domain '%s' does not exist." % ex.faultString)
- else:
- err("%s" % ex.faultString)
-
- dom = sxp.child_value(dominfo, 'name')
-
- try:
- server.xend.domain.waitForDevices(dom)
- except xmlrpclib.Fault, ex:
- server.xend.domain.destroy(dom)
- err("%s" % ex.faultString)
- except:
- server.xend.domain.destroy(dom)
- err("Device creation failed for domain %s" % dom)
-
- if not opts.vals.paused:
- try:
- server.xend.domain.unpause(dom)
- except:
- server.xend.domain.destroy(dom)
- err("Failed to unpause domain %s" % dom)
- domid = int(sxp.child_value(dominfo, 'domid'))
- opts.info("Started domain %s (id=%d)" % (dom, domid))
- return domid
-
-
-def get_xauthority():
- xauth = os.getenv("XAUTHORITY")
- if not xauth:
- home = os.getenv("HOME")
- if not home:
- import posix, pwd
- home = pwd.getpwuid(posix.getuid())[5]
- xauth = home + "/.Xauthority"
- return xauth
-
-
-def parseCommandLine(argv):
- gopts.reset()
- args = gopts.parse(argv)
-
- if gopts.vals.help or gopts.vals.help_config:
- if gopts.vals.help_config:
- print gopts.val_usage()
- return (None, None)
-
- if not gopts.vals.display:
- gopts.vals.display = os.getenv("DISPLAY")
-
- if not gopts.vals.xauthority:
- gopts.vals.xauthority = get_xauthority()
-
- gopts.is_xml = False
-
- # Process remaining args as config variables.
- for arg in args:
- if '=' in arg:
- (var, val) = arg.strip().split('=', 1)
- gopts.setvar(var.strip(), val.strip())
- if gopts.vals.config:
- config = gopts.vals.config
- else:
- try:
- gopts.load_defconfig()
- preprocess(gopts.vals)
- if not gopts.getopt('name') and gopts.getopt('defconfig'):
- gopts.setopt('name', os.path.basename(gopts.getopt('defconfig')))
- config = make_config(gopts.vals)
- except XMLFileError, ex:
- XMLFile = ex.getFile()
- gopts.is_xml = True
- config = ex.getFile()
-
- return (gopts, config)
-
-def help():
- return str(gopts)
-
-def main(argv):
- is_xml = False
-
- try:
- (opts, config) = parseCommandLine(argv)
- except StandardError, ex:
- err(str(ex))
-
- if not opts:
- return
-
- if not opts.is_xml:
- if type(config) == str:
- try:
- config = sxp.parse(file(config))[0]
- except IOError, exn:
- raise OptionError("Cannot read file %s: %s" % (config, exn[1]))
-
- if serverType == SERVER_XEN_API:
- from xen.xm.xenapi_create import sxp2xml
- sxp2xml_inst = sxp2xml()
- doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True)
-
- if opts.vals.dryrun and not opts.is_xml:
- SXPPrettyPrint.prettyprint(config)
-
- if opts.vals.xmldryrun and serverType == SERVER_XEN_API:
- print doc.toprettyxml()
-
- if opts.vals.dryrun or opts.vals.xmldryrun:
- return
-
- if opts.vals.console_autoconnect:
- do_console(sxp.child_value(config, 'name', -1))
-
- if serverType == SERVER_XEN_API:
- from xen.xm.xenapi_create import xenapi_create
- xenapi_create_inst = xenapi_create()
- if opts.is_xml:
- vm_refs = xenapi_create_inst.create(filename = config,
- skipdtd = opts.vals.skipdtd)
- else:
- vm_refs = xenapi_create_inst.create(document = doc,
- skipdtd = opts.vals.skipdtd)
-
- map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs)
- elif not opts.is_xml:
- dom = make_domain(opts, config)
-
- if opts.vals.vncconsole:
- 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:
- for i in range(10):
- # Catch failure of the create process
- time.sleep(1)
- try:
- (p, rv) = os.waitpid(cpid, os.WNOHANG)
- except OSError:
- # Domain has started cleanly and then exiting,
- # the child process used to do this has detached
- print("Domain has already finished");
- break
- if os.WIFEXITED(rv):
- if os.WEXITSTATUS(rv) != 0:
- sys.exit(os.WEXITSTATUS(rv))
- try:
- domid = domain_name_to_domid(domain_name)
- console.execConsole(domid)
- except:
- pass
- print("Could not start console\n");
- sys.exit(0)
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/tools/python/xen/xm/dry-run.py b/tools/python/xen/xm/dry-run.py
deleted file mode 100644
index 4e7f9c8..0000000
--- a/tools/python/xen/xm/dry-run.py
+++ /dev/null
@@ -1,161 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 International Business Machines Corp.
-# Author: Bryan D. Payne <bdpayne at us.ibm.com>
-#============================================================================
-
-"""Tests the security settings for a domain and its resources.
-"""
-import sys
-import xen.util.xsm.xsm as security
-from xen.xm import create
-from xen.xend import sxp
-from xen.util import xsconstants
-from xen.xm.opts import OptionError
-
-def help():
- return """
- This program checks each resource listed in the configfile
- to see if the domain created by the configfile can access
- the resources. The status of each resource is listed
- individually along with the final security decision."""
-
-
-def check_domain_label(config, verbose):
- """All that we need to check here is that the domain label exists and
- is not null when security is on. Other error conditions are
- handled when the config file is parsed.
- """
- answer = 0
- default_label = None
- secon = 0
- if security.on() == xsconstants.XS_POLICY_ACM:
- default_label = security.ssidref2label(security.NULL_SSIDREF)
- secon = 1
-
- # get the domain acm_label
- dom_label = None
- dom_name = None
- for x in sxp.children(config):
- if sxp.name(x) == 'security':
- dom_label = sxp.child_value(sxp.name(sxp.child0(x)), 'label')
- if sxp.name(x) == 'name':
- dom_name = sxp.child0(x)
-
- # sanity check on domain label
- if verbose:
- print "Checking domain:"
- if (not secon) and (not dom_label):
- answer = 1
- if verbose:
- print " %s: PERMITTED" % (dom_name)
- elif (secon) and (dom_label) and (dom_label != default_label):
- answer = 1
- if verbose:
- print " %s: PERMITTED" % (dom_name)
- else:
- print " %s: DENIED" % (dom_name)
- if not secon:
- print " --> Security off, but domain labeled"
- else:
- print " --> Domain not labeled"
- answer = 0
-
- return answer
-
-def config_security_check(config, verbose):
- """Checks each resource listed in the config to see if the active
- policy will permit creation of a new domain using the config.
- Returns 1 if the config passes all tests, otherwise 0.
- """
- answer = 1
-
- # get the domain acm_label
- domain_label = None
- domain_policy = None
- for x in sxp.children(config):
- if sxp.name(x) == 'security':
- domain_label = sxp.child_value(sxp.name(sxp.child0(x)), 'label')
- domain_policy = sxp.child_value(sxp.name(sxp.child0(x)), 'policy')
-
- # if no domain label, use default
- if not domain_label and security.on() == xsconstants.XS_POLICY_ACM:
- try:
- domain_label = security.ssidref2label(security.NULL_SSIDREF)
- except:
- import traceback
- traceback.print_exc(limit=1)
- return 0
- domain_policy = 'NULL'
- elif not domain_label:
- domain_label = ""
- domain_policy = 'NULL'
-
- if verbose:
- print "Checking resources:"
-
- # build a list of all resources in the config file
- resources = []
- for x in sxp.children(config):
- if sxp.name(x) == 'device':
- if sxp.name(sxp.child0(x)) == 'vbd':
- resources.append(sxp.child_value(sxp.child0(x), 'uname'))
-
- # perform a security check on each resource
- for resource in resources:
- try:
- security.res_security_check(resource, domain_label)
- if verbose:
- print " %s: PERMITTED" % (resource)
-
- except security.XSMError:
- print " %s: DENIED" % (resource)
- (poltype, res_label, res_policy) = security.get_res_label(resource)
- if not res_label:
- res_label = ""
- print " --> res: %s (%s:%s)" % (str(res_label),
- str(poltype), str(res_policy))
- print " --> dom: %s (%s:%s)" % (str(domain_label),
- str(poltype), str(domain_policy))
-
- answer = 0
-
- return answer
-
-
-def main (argv):
- if len(argv) != 2:
- raise OptionError('Invalid number of arguments')
-
- passed = 0
- (opts, config) = create.parseCommandLine(argv)
- if check_domain_label(config, verbose=1):
- if config_security_check(config, verbose=1):
- passed = 1
- else:
- print "Checking resources: (skipped)"
-
- if passed:
- print "Dry Run: PASSED"
- else:
- print "Dry Run: FAILED"
- sys.exit(-1)
-
-if __name__ == '__main__':
- try:
- main(sys.argv)
- except Exception, e:
- sys.stderr.write('Error: %s\n' % str(e))
- sys.exit(-1)
diff --git a/tools/python/xen/xm/dumppolicy.py b/tools/python/xen/xm/dumppolicy.py
deleted file mode 100644
index 7bd2ba1..0000000
--- a/tools/python/xen/xm/dumppolicy.py
+++ /dev/null
@@ -1,69 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 International Business Machines Corp.
-# Author: Reiner Sailer <sailer at us.ibm.com>
-#============================================================================
-"""Display currently enforced policy (low-level hypervisor representation).
-"""
-import os
-import sys
-import base64
-import tempfile
-import commands
-from xen.util.xsm.xsm import XSMError, err, dump_policy, dump_policy_file
-from xen.xm.opts import OptionError
-from xen.xm import main as xm_main
-from xen.xm.main import server
-from xen.util import xsconstants
-
-DOM0_UUID = "00000000-0000-0000-0000-000000000000"
-
-def help():
- return """
- Retrieve and print currently enforced hypervisor policy information
- (low-level)."""
-
-def main(argv):
- if len(argv) != 1:
- raise OptionError("No arguments expected.")
-
- if xm_main.serverType == xm_main.SERVER_XEN_API:
- try:
- bin_pol = server.xenapi.ACMPolicy.get_enforced_binary()
- if bin_pol:
- dom0_ssid = server.xenapi.ACMPolicy.get_VM_ssidref(DOM0_UUID)
- bin = base64.b64decode(bin_pol)
- try:
- fd, filename = tempfile.mkstemp(suffix=".bin")
- os.write(fd, bin)
- os.close(fd)
- dump_policy_file(filename, dom0_ssid)
- finally:
- os.unlink(filename)
- else:
- err("No policy is installed.")
- except Exception, e:
- err("An error occurred getting the running policy: %s" % str(e))
- else:
- dump_policy()
-
-if __name__ == '__main__':
- try:
- main(sys.argv)
- except Exception, e:
- sys.stderr.write('Error: %s\n' % str(e))
- sys.exit(-1)
-
-
diff --git a/tools/python/xen/xm/getenforce.py b/tools/python/xen/xm/getenforce.py
deleted file mode 100644
index 526be82..0000000
--- a/tools/python/xen/xm/getenforce.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Author: Machon Gregory <mbgrego at tycho.ncsc.mil>
-#============================================================================
-
-"""Get the current mode of the Flask XSM module.
-"""
-
-from xen.xm.opts import OptionError
-from xen.xm import main as xm_main
-from xen.xm.main import server
-from xen.util import xsconstants
-
-def help():
- return """
- Usage: xm getenforce
-
- Returns the current mode (Permissive, Enforcing) of the
- Flask XSM module."""
-
-def getenforce():
- if xm_main.serverType == xm_main.SERVER_XEN_API:
- if xsconstants.XS_POLICY_FLASK != \
- int(server.xenapi.XSPolicy.get_xstype()):
- raise OptionError("Unsupported policy type")
- mode = int(server.xenapi.XSPolicy.getenforce())
- else:
- if server.xend.security.on() != xsconstants.XS_POLICY_FLASK:
- raise OptionError("Unsupported policy type")
- mode = server.xend.security.getenforce()
-
- if mode == 0:
- print "Permissive"
- elif mode == 1:
- print "Enforcing"
-
-def main(argv):
- if "-?" in argv:
- help()
- return
-
- if len(argv) != 1:
- raise OptionError("No arguments expected.")
-
- getenforce()
-
-if __name__ == '__main__':
- try:
- main(sys.argv)
- except Exception, e:
- sys.stderr.write('Error: %s\n' % str(e))
- sys.exit(-1)
-
-
diff --git a/tools/python/xen/xm/getlabel.py b/tools/python/xen/xm/getlabel.py
deleted file mode 100644
index 2d26de3..0000000
--- a/tools/python/xen/xm/getlabel.py
+++ /dev/null
@@ -1,157 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 International Business Machines Corp.
-# Author: Bryan D. Payne <bdpayne at us.ibm.com>
-#============================================================================
-
-"""Show the label for a domain or resoruce.
-"""
-import sys, os, re
-import xen.util.xsm.xsm as security
-from xen.util import xsconstants, auxbin
-from xen.xm.opts import OptionError
-from xen.xm import main as xm_main
-from xen.xm.main import server
-
-def help():
- return """
- Usage: xm getlabel dom <configfile>
- xm getlabel mgt <domain name>
- xm getlabel res <resource>
- xm getlabel vif-<idx> <vmname>
-
- This program shows the label for a domain from its configuration
- file, the label of a Xend-managed domain, that of a resources or
- the label of a virtual network interface of a managed domain
- (requires xm to be used in Xen-API mode).
- """
-
-def get_resource_label(resource):
- """Gets the resource label
- """
- if xm_main.serverType == xm_main.SERVER_XEN_API:
- reslabel = server.xenapi.XSPolicy.get_resource_label(resource)
- if reslabel == "":
- raise security.XSMError("Resource not labeled")
- print reslabel
- else:
- reslabel = server.xend.security.get_resource_label(resource)
- if len(reslabel) == 0:
- raise security.XSMError("Resource not labeled")
- print ":".join(reslabel)
-
-
-def get_domain_label(configfile):
- # open the domain config file
- fd = None
- if configfile[0] == '/':
- fd = open(configfile, "rb")
- else:
- for prefix in [".", auxbin.xen_configdir() ]:
- abs_file = prefix + "/" + configfile
- if os.path.isfile(abs_file):
- fd = open(abs_file, "rb")
- break
- if not fd:
- raise OptionError("Configuration file '%s' not found." % configfile)
-
- # read in the domain config file, finding the label line
- ac_entry_re = re.compile("^access_control\s*=.*", re.IGNORECASE)
- ac_exit_re = re.compile(".*'\].*")
- acline = ""
- record = 0
- for line in fd.readlines():
- if ac_entry_re.match(line):
- record = 1
- if record:
- acline = acline + line
- if record and ac_exit_re.match(line):
- record = 0
- fd.close()
-
- # send error message if we didn't find anything
- if acline == "":
- raise security.XSMError("Domain not labeled")
-
- # print out the label
- (title, data) = acline.split("=", 1)
- data = data.strip()
- data = data.lstrip("[\'")
- data = data.rstrip("\']")
- print "policytype=%s," % xsconstants.ACM_POLICY_ID + data
-
-def get_vif_label(vmname, idx):
- if xm_main.serverType != xm_main.SERVER_XEN_API:
- raise OptionError('xm needs to be configure to use the xen-api.')
- vm_refs = server.xenapi.VM.get_by_name_label(vmname)
- if len(vm_refs) == 0:
- raise OptionError('A VM with the name %s does not exist.' %
- vmname)
- vif_refs = server.xenapi.VM.get_VIFs(vm_refs[0])
- if len(vif_refs) <= idx:
- raise OptionError("Bad VIF index.")
- vif_ref = server.xenapi.VIF.get_by_uuid(vif_refs[idx])
- if not vif_ref:
- print "No VIF with this UUID."
- sec_lab = server.xenapi.VIF.get_security_label(vif_ref)
- print "%s" % sec_lab
-
-def get_domain_label_xapi(domain):
- if xm_main.serverType != xm_main.SERVER_XEN_API:
- sec_lab = server.xend.security.get_domain_label(domain)
- if len(sec_lab) > 0 and sec_lab[0] == '\'':
- sec_lab = sec_lab[1:]
- else:
- uuids = server.xenapi.VM.get_by_name_label(domain)
- if len(uuids) == 0:
- raise OptionError('A VM with that name does not exist.')
- if len(uuids) != 1:
- raise OptionError('There are multiple domains with the same name.')
- uuid = uuids[0]
- sec_lab = server.xenapi.VM.get_security_label(uuid)
- print "%s" %sec_lab
-
-def main(argv):
- if len(argv) != 3:
- raise OptionError('Requires 2 arguments')
-
- if argv[1].lower() == "dom":
- configfile = argv[2]
- get_domain_label(configfile)
- elif argv[1].lower() == "mgt":
- domainname = argv[2]
- get_domain_label_xapi(domainname)
- elif argv[1].lower() == "res":
- resource = argv[2]
- get_resource_label(resource)
- elif argv[1].lower().startswith("vif-"):
- try:
- idx = int(argv[1][4:])
- if idx < 0:
- raise
- except:
- raise OptionError("Bad VIF device index.")
- vmname = argv[2]
- get_vif_label(vmname, idx)
- else:
- raise OptionError('First subcommand argument must be "dom"'
- ', "mgt" or "res"')
-
-if __name__ == '__main__':
- try:
- main(sys.argv)
- except Exception, e:
- sys.stderr.write('Error: %s\n' % str(e))
- sys.exit(-1)
diff --git a/tools/python/xen/xm/getpolicy.py b/tools/python/xen/xm/getpolicy.py
deleted file mode 100644
index a96dde0..0000000
--- a/tools/python/xen/xm/getpolicy.py
+++ /dev/null
@@ -1,135 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2007 International Business Machines Corp.
-# Author: Stefan Berger <stefanb at us.ibm.com>
-#============================================================================
-
-"""Get the managed policy of the system.
-"""
-
-import sys
-from xen.util import xsconstants
-from xml.dom import minidom
-from xen.xm.opts import OptionError
-from xen.util.acmpolicy import ACMPolicy
-from xen.xm import main as xm_main
-from xen.xm.main import server
-
-def help():
- return """
- Usage: xm getpolicy [options]
-
- The following options are defined
- --dumpxml Display the XML of the policy
-
- Get the policy managed by xend."""
-
-
-def display_policy_info(acmpol, policytype, uuid, version, flags,
- dumpxml, xml):
- print "Policy name : %s" % acmpol.get_name()
- print "Policy type : %s" % policytype
- if uuid:
- print "Reference : %s" % uuid
- print "Version of XML policy : %s" % version
-
- state = []
- if flags & xsconstants.XS_INST_LOAD:
- state.append("loaded")
- if flags & xsconstants.XS_INST_BOOT:
- state.append("activated for boot")
- print "Policy configuration : %s" % ", ".join(state)
- if dumpxml:
- if xml:
- dom = minidom.parseString(xml.encode("utf-8"))
- print "%s" % dom.toprettyxml(indent=" ",newl="\n")
-
-
-def display_security_subsystems(xstype):
- types = []
- if xstype & xsconstants.XS_POLICY_ACM:
- types.append("ACM")
- xstype ^= xsconstants.XS_POLICY_ACM
- if xstype != 0:
- types.append("unsupported (%08x)" % xstype)
- if len(types) == 0:
- types.append("None")
- print "Supported security subsystems : %s \n" % ", ".join(types)
-
-
-def getpolicy(dumpxml):
- if xm_main.serverType == xm_main.SERVER_XEN_API:
- xstype = int(server.xenapi.XSPolicy.get_xstype())
- display_security_subsystems(xstype)
-
- policystate = server.xenapi.XSPolicy.get_xspolicy()
- if int(policystate['type']) == 0:
- print "No policy is installed."
- return
- if int(policystate['type']) != xsconstants.XS_POLICY_ACM:
- print "Unknown policy type '%s'." % policystate['type']
- else:
- xml = policystate['repr']
- acmpol = None
- if xml:
- acmpol = ACMPolicy(xml=xml)
-
- display_policy_info(acmpol,
- xsconstants.ACM_POLICY_ID,
- policystate['xs_ref'],
- policystate['version'],
- int(policystate['flags']),
- dumpxml,
- xml)
- else:
- xstype = server.xend.security.get_xstype()
- display_security_subsystems(xstype)
-
- xml, flags = server.xend.security.get_policy()
- acmpol = None
- if xml != "":
- dom = None
- try:
- dom = minidom.parseString(xml)
- if dom:
- acmpol = ACMPolicy(dom=dom)
- except Exception, e:
- print "Error parsing the library: " + str(e)
-
- if acmpol:
- display_policy_info(acmpol,
- xsconstants.ACM_POLICY_ID,
- None,
- acmpol.get_version(),
- flags,
- dumpxml,
- xml)
- else:
- print "No policy is installed."
-
-def main(argv):
- dumpxml = False
-
- if '--dumpxml' in argv:
- dumpxml = True
-
- getpolicy(dumpxml)
-
-if __name__ == '__main__':
- try:
- main(sys.argv)
- except Exception, e:
- sys.stderr.write('Error: %s\n' % str(e))
- sys.exit(-1)
diff --git a/tools/python/xen/xm/help.py b/tools/python/xen/xm/help.py
deleted file mode 100644
index 9db2e31..0000000
--- a/tools/python/xen/xm/help.py
+++ /dev/null
@@ -1,100 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
-
-"""Variable definition and help support for Python defconfig files.
-"""
-
-import sys
-
-class Vars:
- """A set of configuration variables.
- """
-
- def __init__(self, name, help, env):
- """Create a variable set.
-
- name name of the defconfig file
- help help flag
- env local environment
- """
- self.name = name
- self.help = help
- self.env = env
- self.vars = []
-
- def var(self, name, use=None, check=None):
- """Define a configuration variable.
- If provided, the check function will be called as check(var, val)
- where var is the variable name and val is its value (string).
- It should return a new value for the variable, or raise ValueError if
- the value is not acceptable.
-
- name variable name
- use variable usage string
- check variable check function
- """
- self.vars.append(Var(name, use, check))
-
- def check(self):
- """Execute the variable checks or print help, depending on the value
- of the help flag passed to the constructor.
- """
- if self.help:
- self.doHelp()
- else:
- for v in self.vars:
- v.doCheck(self.env)
-
- def doHelp(self, out=sys.stderr):
- """Print help for the variables.
- """
- if self.vars:
- print >>out, "\nConfiguration variables for %s:\n" % self.name
- for v in self.vars:
- v.doHelp(out)
- print >>out
-
-class Var:
- """A single variable.
- """
-
- def __init__(self, name, use, check):
- """Create a variable.
-
- name variable name
- use variable use string
- check variable value check function
- """
- self.name = name
- self.use = use or ''
- self.check = check
-
- def doCheck(self, env):
- """Execute the check and set the variable to the new value.
- """
- if not self.check: return
- try:
- env[self.name] = self.check(self.name, env.get(self.name))
- except StandardError, ex:
- raise sys.exc_type, self.name + " - " + str(ex)
-
- def doHelp(self, out):
- """Print help for the variable.
- """
- print >>out, "%-12s" % self.name, self.use
-
-
diff --git a/tools/python/xen/xm/labels.py b/tools/python/xen/xm/labels.py
deleted file mode 100644
index 0ad0d9b..0000000
--- a/tools/python/xen/xm/labels.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 International Business Machines Corp.
-# Author: Reiner Sailer <sailer at us.ibm.com>
-#============================================================================
-
-"""Listing available labels for a policy.
-"""
-import sys
-import traceback
-from xen.util.xsm.xsm import XSMError, err
-from xen.xm.opts import OptionError
-from xen.util.acmpolicy import ACMPolicy
-from xen.util import xsconstants
-from xen.xm.main import server
-from xen.xm import main as xm_main
-
-
-def help():
- return """
- Prints labels of the specified type (default is dom)
- that are defined in policy (default is current hypervisor policy)."""
-
-def main(argv):
- policy = None
- ptype = None
- for arg in argv[1:]:
- key_val = arg.split('=')
- if len(key_val) == 2 and key_val[0] == 'type':
- if ptype:
- raise OptionError('type is definied twice')
- ptype = key_val[1].lower()
-
- elif len(key_val) == 1:
- if policy:
- raise OptionError('policy is defined twice')
- policy = arg
- else:
- raise OptionError('Unrecognised option: %s' % arg)
-
- if xm_main.serverType != xm_main.SERVER_XEN_API:
- labels(policy, ptype)
- else:
- labels_xapi(policy, ptype)
-
-def labels(policy, ptype):
-
- labels = server.xend.security.list_labels(policy, ptype)
- labels.sort()
- for label in labels:
- print label
-
-
-def labels_xapi(policy, ptype):
- policystate = server.xenapi.XSPolicy.get_xspolicy()
- if int(policystate['type']) == xsconstants.XS_POLICY_ACM:
- acmpol = ACMPolicy(xml=policystate['repr'])
- if policy and policy != acmpol.get_name():
- print "Warning: '%s' is not the currently loaded policy." % policy
- return labels(policy, ptype)
- names1 = []
- names2 = []
- if not ptype or ptype == 'dom' or ptype == 'any':
- names1 = acmpol.policy_get_virtualmachinelabel_names()
- if ptype == 'res' or ptype == 'any':
- names2 = acmpol.policy_get_resourcelabel_names()
- names = list(set(names1).union(names2))
- names.sort()
- for n in names:
- print n
- elif int(policystate['type']) == 0:
- err("No policy installed on the system.")
- else:
- err("Unsupported type of policy installed on the system.")
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py
deleted file mode 100644
index 5ed781c..0000000
--- a/tools/python/xen/xm/main.py
+++ /dev/null
@@ -1,4030 +0,0 @@
-# (C) Copyright IBM Corp. 2005
-# Copyright (C) 2004 Mike Wray
-# Copyright (c) 2005-2006 XenSource Ltd.
-#
-# Authors:
-# Sean Dague <sean at dague dot net>
-# Mike Wray <mike dot wray at hp dot com>
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""Grand unified management application for Xen.
-"""
-import atexit
-import cmd
-import os
-import pprint
-import shlex
-import sys
-import re
-import getopt
-import socket
-import traceback
-import xmlrpclib
-import time
-import datetime
-from select import select
-import xml.dom.minidom
-from xen.util.blkif import blkdev_name_to_number
-from xen.util import vscsi_util
-from xen.util.pci import *
-from xen.util import vusb_util
-
-import warnings
-warnings.filterwarnings('ignore', category=FutureWarning)
-
-from xen.xend import PrettyPrint
-from xen.xend import sxp
-from xen.xend import XendClient
-from xen.xend.XendConstants import *
-from xen.xend.server.DevConstants import xenbusState
-
-from xen.xm.opts import OptionError, Opts, wrap, set_true
-from xen.xm import console
-from xen.util.xmlrpcclient import ServerProxy
-import xen.util.xsm.xsm as security
-from xen.util.xsm.xsm import XSMError
-from xen.util.acmpolicy import ACM_LABEL_UNLABELED_DISPLAY
-from xen.util.sxputils import sxp2map, map2sxp as map_to_sxp
-from xen.util import auxbin
-
-import XenAPI
-
-import inspect
-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.
-if not hasattr(getopt, 'gnu_getopt'):
- getopt.gnu_getopt = getopt.getopt
-
-XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
-XM_CONFIG_FILE_DEFAULT = auxbin.xen_configdir() + '/xm-config.xml'
-
-# Supported types of server
-SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
-SERVER_XEN_API = 'Xen-API'
-
-# General help message
-
-USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
- "Control, list, and manipulate Xen guest instances.\n"
-
-USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
- 'For more help on \'xm\' see the xm(1) man page.\n' \
- 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
- ' man page.\n'
-
-# Help strings are indexed by subcommand name in this way:
-# 'subcommand': (argstring, description)
-
-SUBCOMMAND_HELP = {
- # common commands
-
- 'shell' : ('', 'Launch an interactive shell.'),
-
- '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>',
- 'Terminate a domain immediately.'),
- 'help' : ('', 'Display this message.'),
- 'list' : ('[options] [Domain, ...]',
- 'List information about all/some domains.'),
- 'mem-max' : ('<Domain> <Mem>',
- 'Set the maximum amount reservation for a domain.'),
- 'mem-set' : ('<Domain> <Mem>',
- 'Set the current memory usage for a domain.'),
- 'migrate' : ('<Domain> <Host>',
- 'Migrate a domain to another machine.'),
- 'pause' : ('<Domain>', 'Pause execution of a domain.'),
- 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
- 'reset' : ('<Domain>', 'Reset a domain.'),
- 'restore' : ('<CheckpointFile> [-p]',
- 'Restore a domain from a saved state.'),
- 'save' : ('[-c] <Domain> <CheckpointFile>',
- 'Save a domain state to restore later.'),
- 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
- 'top' : ('', 'Monitor a host and the domains in real time.'),
- 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
- 'uptime' : ('[-s] [Domain, ...]',
- 'Print uptime for all/some domains.'),
-
- # Life cycle xm commands
- 'new' : ('<ConfigFile> [options] [vars]',
- 'Adds a domain to Xend domain management'),
- 'delete' : ('<DomainName>',
- 'Remove a domain from Xend domain management.'),
- 'start' : ('<DomainName>', 'Start a Xend managed domain'),
- 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
- 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
-
- # less used commands
-
- 'dmesg' : ('[-c|--clear]',
- 'Read and/or clear Xend\'s message buffer.'),
- 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
- 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
- 'dump-core' : ('[-L|--live] [-C|--crash] [-R|--reset] <Domain> [Filename]',
- 'Dump core for a specific domain.'),
- 'info' : ('[-c|--config] [-n|--numa]',
- 'Get information about Xen host.'),
- 'log' : ('', 'Print Xend log'),
- 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
- 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
- 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
- 'Get/set credit scheduler parameters.'),
- 'sched-credit2': ('[-d <Domain> [-w[=WEIGHT]]',
- 'Get/set credit2 scheduler parameters.'),
- 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
- 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
- 'trigger' : ('<Domain> <nmi|reset|init|s3resume|power> [<VCPU>]',
- 'Send a trigger to a domain.'),
- 'vcpu-list' : ('[Domain, ...]',
- 'List the VCPUs for all/some domains.'),
- 'vcpu-pin' : ('<Domain> <VCPU|all> <CPUs|all>',
- 'Set which CPUs a VCPU can use.'),
- 'vcpu-set' : ('<Domain> <vCPUs>',
- 'Set the number of active VCPUs allowed for the'
- ' domain.'),
- #usb
- 'usb-add' : ('<domain> <[host:bus.addr] [host:vendor_id:product_id]>','Add the usb device to FV VM.'),
- 'usb-del' : ('<domain> <[host:bus.addr] [host:vendor_id:product_id]>','Delete the usb device to FV VM.'),
- #domstate
- 'domstate' : ('<domain> ', 'get the state of a domain'),
-
- # device commands
-
- 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
- 'Create a new virtual block device.'),
- 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
- 'Change block device configuration'),
- 'block-detach' : ('<Domain> <DevId> [-f|--force]',
- 'Destroy a domain\'s virtual block device.'),
- 'block-list' : ('<Domain> [--long]',
- 'List virtual block devices for a domain.'),
- 'network-attach': ('<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] '
- '[ip=<ip>] [script=<script>] [backend=<BackDomain>] '
- '[vifname=<name>] [rate=<rate>] [model=<model>]'
- '[accel=<accel>]',
- 'Create a new virtual network device.'),
- 'network-detach': ('<Domain> <DevId|mac> [-f|--force]',
- 'Destroy a domain\'s virtual network device.'),
- 'network-list' : ('<Domain> [--long]',
- 'List virtual network interfaces for a domain.'),
- 'network2-attach': ('<Domain> [front_mac=<mac>] [back_mac=<mac>] '
- '[backend=<BackDomain>] [trusted=<0|1>] '
- '[back_trusted=<0|1>] [bridge=<bridge>] '
- '[filter_mac=<0|1>] [front_filter_mac=<0|1>] '
- '[pdev=<PDEV>] [max_bypasses=n]',
- 'Create a new version 2 virtual network device.'),
- 'network2-detach': ('<Domain> <DevId> [-f|--force]',
- 'Destroy a domain\'s version 2 virtual network device.'),
- 'network2-list' : ('<Domain> [--long]',
- 'List version 2 virtual network interfaces for a domain.'),
- 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
- 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
- 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
- 'pci-attach' : ('[-o|--options=<opt>] <Domain> <domain:bus:slot.func> [virtual slot]',
- 'Insert a new pass-through pci device.'),
- 'pci-detach' : ('<Domain> <domain:bus:slot.func>',
- 'Remove a domain\'s pass-through pci device.'),
- 'pci-list' : ('<Domain>',
- 'List pass-through pci devices for a domain.'),
- 'pci-list-assignable-devices' : ('', 'List all the assignable pci devices'),
- 'scsi-attach' : ('<Domain> <PhysDevice> <VirtDevice> [BackDomain]',
- 'Attach a new SCSI device.'),
- 'scsi-detach' : ('<Domain> <VirtDevice>',
- 'Detach a specified SCSI device.'),
- 'scsi-list' : ('<Domain> [--long]',
- 'List all SCSI devices currently attached.'),
- 'usb-attach' : ('<Domain> <DevId> <PortNumber> <BusId>',
- 'Attach a new USB physical bus to domain\'s virtual port.'),
- 'usb-detach' : ('<Domain> <DevId> <PortNumber>',
- 'Detach a USB physical bus from domain\'s virtual port.'),
- 'usb-list' : ('<Domain>',
- 'List domain\'s attachment state of all virtual port .'),
- 'usb-list-assignable-devices' : ('', 'List all the assignable usb devices'),
- 'usb-hc-create' : ('<Domain> <USBSpecVer> <NumberOfPorts>',
- 'Create a domain\'s new virtual USB host controller.'),
- 'usb-hc-destroy' : ('<Domain> <DevId>',
- 'Destroy a domain\'s virtual USB host controller.'),
-
- # tmem
- 'tmem-list' : ('[-l|--long] [<Domain>|-a|--all]', 'List tmem pools.'),
- 'tmem-thaw' : ('[<Domain>|-a|--all]', 'Thaw tmem pools.'),
- 'tmem-freeze' : ('[<Domain>|-a|--all]', 'Freeze tmem pools.'),
- 'tmem-destroy' : ('[<Domain>|-a|--all]', 'Destroy tmem pools.'),
- 'tmem-set' : ('[<Domain>|-a|--all] [weight=<weight>] [cap=<cap>] '
- '[compress=<compress>]',
- 'Change tmem settings.'),
- 'tmem-freeable' : ('', 'Print freeable tmem (in MiB).'),
- 'tmem-shared-auth' : ('[<Domain>|-a|--all] [--uuid=<uuid>] [--auth=<0|1>]', 'De/authenticate shared tmem pool.'),
-
- #
- # cpupool commands
- #
- 'cpupool-create' : ('<ConfigFile> [vars]',
- 'Create a CPU pool based an ConfigFile.'),
- 'cpupool-new' : ('<ConfigFile> [vars]',
- 'Adds a CPU pool to Xend CPU pool management'),
- 'cpupool-start' : ('<CPU Pool>', 'Starts a Xend CPU pool'),
- 'cpupool-list' : ('[<CPU Pool>] [-l|--long] [-c|--cpus]', 'List CPU pools on host'),
- 'cpupool-destroy' : ('<CPU Pool>', 'Deactivates a CPU pool'),
- 'cpupool-delete' : ('<CPU Pool>',
- 'Removes a CPU pool from Xend management'),
- 'cpupool-cpu-add' : ('<CPU Pool> <CPU nr>', 'Adds a CPU to a CPU pool'),
- 'cpupool-cpu-remove': ('<CPU Pool> <CPU nr>', 'Removes a CPU from a CPU pool'),
- 'cpupool-migrate' : ('<Domain> <CPU Pool>',
- 'Moves a domain into a CPU pool'),
-
- # security
-
- 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>|mgt <managed domain>} [<policy>]',
- 'Add security label to domain.'),
- 'rmlabel' : ('{dom <ConfigFile>|res <Resource>|mgt<managed domain>}',
- 'Remove a security label from domain.'),
- 'getlabel' : ('{dom <ConfigFile>|res <Resource>|mgt <managed domain>}',
- 'Show security label for domain or resource.'),
- 'dry-run' : ('<ConfigFile>',
- 'Test if a domain can access its resources.'),
- 'resources' : ('', 'Show info for each labeled resource.'),
- 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
- 'setpolicy' : ('<policytype> <policyfile> [options]',
- 'Set the policy of the system.'),
- 'resetpolicy' : ('',
- 'Set the policy of the system to the default policy.'),
- 'getpolicy' : ('[options]', 'Get the policy of the system.'),
- 'labels' : ('[policy] [type=dom|res|any]',
- 'List <type> labels for (active) policy.'),
- 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
- 'getenforce' : ('', 'Returns the current enforcing mode for the Flask XSM module (Enforcing,Permissive)'),
- 'setenforce' : ('[ (Enforcing|1) | (Permissive|0) ]',
- 'Modifies the current enforcing mode for the Flask XSM module'),
-}
-
-SUBCOMMAND_OPTIONS = {
- 'sched-sedf': (
- ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
- ('-s [MS]', '--slice[=MS]' ,
- 'Worst-case execution time(ms). (slice < period)'),
- ('-l [MS]', '--latency[=MS]',
- 'Scaled period (ms) when domain performs heavy I/O'),
- ('-e [FLAG]', '--extra[=FLAG]',
- 'Flag (0 or 1) controls if domain can run in extra time.'),
- ('-w [FLOAT]', '--weight[=FLOAT]',
- 'CPU Period/slice (do not set with --period/--slice)'),
- ),
- 'sched-credit': (
- ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
- ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
- ('-c CAP', '--cap=CAP', 'Cap (int)'),
- ),
- 'sched-credit2': (
- ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
- ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
- ),
- 'list': (
- ('-l', '--long', 'Output all VM details in SXP'),
- ('', '--label', 'Include security labels'),
- ('', '--state=<state>', 'Select only VMs with the specified state'),
- ('', '--pool=<pool>', 'Select only VMs in specified cpu pool'),
- ),
- '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'),
- ),
- 'vnet-list': (
- ('-l', '--long', 'List Vnets as SXP'),
- ),
- 'network-list': (
- ('-l', '--long', 'List resources as SXP'),
- ),
- 'dump-core': (
- ('-L', '--live', 'Dump core without pausing the domain'),
- ('-C', '--crash', 'Crash domain after dumping core'),
- ('-R', '--reset', 'Reset domain after dumping core'),
- ),
- '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'),
- ),
- 'save': (
- ('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
- ),
- 'restore': (
- ('-p', '--paused', 'Do not unpause domain after restoring it'),
- ),
- 'info': (
- ('-c', '--config', 'List Xend configuration parameters'),
- ('-n', '--numa', 'List host NUMA topology information'),
- ),
- 'tmem-list': (
- ('-l', '--long', 'List tmem stats.'),
- ),
- 'tmem-thaw': (
- ('-a', '--all', 'Thaw all tmem.'),
- ),
- 'tmem-freeze': (
- ('-a', '--all', 'Freeze all tmem.'),
- ),
- 'tmem-destroy': (
- ('-a', '--all', 'Destroy all tmem.'),
- ),
- 'tmem-set': (
- ('-a', '--all', 'Operate on all tmem.'),
- ),
- 'tmem-shared-auth': (
- ('-a', '--all', 'Authenticate for all tmem pools.'),
- ('-u', '--uuid', 'Specify uuid (abcdef01-2345-6789-01234567890abcdef).'),
- ('-A', '--auth', '0=auth,1=deauth'),
- ),
- 'cpupool-list': (
- ('-l', '--long', 'Output all CPU pool details in SXP format'),
- ('-c', '--cpus', 'Output list of CPUs used by a pool'),
- ),
-}
-
-common_commands = [
- "console",
- "vncviewer",
- "create",
- "new",
- "delete",
- "destroy",
- "dump-core",
- "help",
- "list",
- "mem-set",
- "migrate",
- "pause",
- "reboot",
- "reset",
- "restore",
- "resume",
- "save",
- "shell",
- "shutdown",
- "start",
- "suspend",
- "top",
- "unpause",
- "uptime",
- "usb-add",
- "usb-del",
- "domstate",
- "vcpu-set",
- ]
-
-domain_commands = [
- "console",
- "vncviewer",
- "create",
- "new",
- "delete",
- "destroy",
- "domid",
- "domname",
- "dump-core",
- "list",
- "mem-max",
- "mem-set",
- "migrate",
- "pause",
- "reboot",
- "rename",
- "reset",
- "restore",
- "resume",
- "save",
- "shutdown",
- "start",
- "suspend",
- "sysrq",
- "trigger",
- "top",
- "unpause",
- "uptime",
- "usb-add",
- "usb-del",
- "domstate",
- "vcpu-list",
- "vcpu-pin",
- "vcpu-set",
- ]
-
-host_commands = [
- "debug-keys",
- "dmesg",
- "info",
- "log",
- "serve",
- ]
-
-scheduler_commands = [
- "sched-credit2",
- "sched-credit",
- "sched-sedf",
- ]
-
-device_commands = [
- "block-attach",
- "block-detach",
- "block-list",
- "block-configure",
- "network-attach",
- "network-detach",
- "network-list",
- "network2-attach",
- "network2-detach",
- "network2-list",
- "pci-attach",
- "pci-detach",
- "pci-list",
- "pci-list-assignable-devices",
- "scsi-attach",
- "scsi-detach",
- "scsi-list",
- "usb-attach",
- "usb-detach",
- "usb-list",
- "usb-list-assignable-devices",
- "usb-hc-create",
- "usb-hc-destroy",
- ]
-
-vnet_commands = [
- "vnet-list",
- "vnet-create",
- "vnet-delete",
- ]
-
-security_commands = [
- "setpolicy",
- ]
-
-acm_commands = [
- "labels",
- "addlabel",
- "rmlabel",
- "getlabel",
- "dry-run",
- "resources",
- "dumppolicy",
- "resetpolicy",
- "getpolicy",
- ]
-
-flask_commands = [
- "getenforce",
- "setenforce",
- ]
-
-tmem_commands = [
- "tmem-list",
- "tmem-thaw",
- "tmem-freeze",
- "tmem-destroy",
- "tmem-set",
- "tmem-shared-auth",
- ]
-
-cpupool_commands = [
- "cpupool-create",
- "cpupool-new",
- "cpupool-start",
- "cpupool-list",
- "cpupool-destroy",
- "cpupool-delete",
- "cpupool-cpu-add",
- "cpupool-cpu-remove",
- "cpupool-migrate",
- ]
-
-all_commands = (domain_commands + host_commands + scheduler_commands +
- device_commands + vnet_commands + security_commands +
- acm_commands + flask_commands + tmem_commands + cpupool_commands +
- ['shell', 'event-monitor'])
-
-
-##
-# Configuration File Parsing
-##
-
-xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
-config = None
-if os.path.isfile(xmConfigFile):
- try:
- config = xml.dom.minidom.parse(xmConfigFile)
- except:
- print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
- xmConfigFile)
-
-def parseServer():
- if config:
- server = config.getElementsByTagName('server')
- if server:
- st = server[0].getAttribute('type')
- if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
- print >>sys.stderr, ('Invalid server type %s; using %s.' %
- (st, SERVER_LEGACY_XMLRPC))
- st = SERVER_LEGACY_XMLRPC
- return (st, server[0].getAttribute('uri'))
-
- return SERVER_LEGACY_XMLRPC, XendClient.uri
-
-def parseAuthentication():
- server = config.getElementsByTagName('server')[0]
- return (server.getAttribute('username'),
- server.getAttribute('password'))
-
-serverType, serverURI = parseServer()
-server = None
-
-
-####################################################################
-#
-# Help/usage printing functions
-#
-####################################################################
-
-def cmdHelp(cmd):
- """Print help for a specific subcommand."""
-
- if not SUBCOMMAND_HELP.has_key(cmd):
- for fc in SUBCOMMAND_HELP.keys():
- if fc[:len(cmd)] == cmd:
- cmd = fc
- break
-
- try:
- args, desc = SUBCOMMAND_HELP[cmd]
- except KeyError:
- shortHelp()
- return
-
- print 'Usage: xm %s %s' % (cmd, args)
- print
- print desc
-
- try:
- # If options help message is defined, print this.
- for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
- if shortopt and longopt:
- optdesc = '%s, %s' % (shortopt, longopt)
- elif shortopt:
- optdesc = shortopt
- elif longopt:
- optdesc = longopt
-
- wrapped_desc = wrap(desc, 43)
- print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
- for line in wrapped_desc[1:]:
- print ' ' * 33 + line
- print
- except KeyError:
- # if the command is an external module, we grab usage help
- # from the module itself.
- if cmd in IMPORTED_COMMANDS:
- try:
- cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
- cmd_usage = getattr(cmd_module, "help", None)
- if cmd_usage:
- print cmd_usage()
- except ImportError:
- pass
-
-def shortHelp():
- """Print out generic help when xm is called without subcommand."""
-
- print USAGE_HELP
- print 'Common \'xm\' commands:\n'
-
- for command in common_commands:
- try:
- args, desc = SUBCOMMAND_HELP[command]
- except KeyError:
- continue
- wrapped_desc = wrap(desc, 50)
- print ' %-20s %-50s' % (command, wrapped_desc[0])
- for line in wrapped_desc[1:]:
- print ' ' * 22 + line
-
- print
- print USAGE_FOOTER
- print 'For a complete list of subcommands run \'xm help\'.'
-
-def longHelp():
- """Print out full help when xm is called with xm --help or xm help"""
-
- print USAGE_HELP
- print 'xm full list of subcommands:\n'
-
- for command in all_commands:
- try:
- args, desc = SUBCOMMAND_HELP[command]
- except KeyError:
- continue
-
- wrapped_desc = wrap(desc, 50)
- print ' %-20s %-50s' % (command, wrapped_desc[0])
- for line in wrapped_desc[1:]:
- print ' ' * 22 + line
-
- print
- print USAGE_FOOTER
-
-def _usage(cmd):
- """ Print help usage information """
- if cmd:
- cmdHelp(cmd)
- else:
- shortHelp()
-
-def usage(cmd = None):
- """ Print help usage information and exits """
- _usage(cmd)
- sys.exit(1)
-
-
-####################################################################
-#
-# Utility functions
-#
-####################################################################
-
-def get_default_SR():
- return [sr_ref
- for sr_ref in server.xenapi.SR.get_all()
- if server.xenapi.SR.get_type(sr_ref) == "local"][0]
-
-def get_default_Network():
- return [network_ref
- for network_ref in server.xenapi.network.get_all()][0]
-
-class XenAPIUnsupportedException(Exception):
- pass
-
-def xenapi_unsupported():
- if serverType == SERVER_XEN_API:
- raise XenAPIUnsupportedException, "This function is not supported by Xen-API"
-
-def xenapi_only():
- if serverType != SERVER_XEN_API:
- raise XenAPIUnsupportedException, "This function is only supported by Xen-API"
-
-def map2sxp(m):
- return [[k, m[k]] for k in m.keys()]
-
-def arg_check(args, name, lo, hi = -1):
- n = len([i for i in args if i != '--'])
-
- if hi == -1:
- if n != lo:
- err("'xm %s' requires %d argument%s.\n" % (name, lo,
- lo == 1 and '' or 's'))
- usage(name)
- else:
- if n < lo or n > hi:
- err("'xm %s' requires between %d and %d arguments.\n" %
- (name, lo, hi))
- usage(name)
-
-
-def unit(c):
- if not c.isalpha():
- return 0
- base = 1
- if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
- elif c == 'M' or c == 'm': base = 1024 * 1024
- elif c == 'K' or c == 'k': base = 1024
- else:
- print 'ignoring unknown unit'
- return base
-
-def int_unit(str, dest):
- base = unit(str[-1])
- if not base:
- return int(str)
-
- value = int(str[:-1])
- dst_base = unit(dest)
- if dst_base == 0:
- dst_base = 1
- if dst_base > base:
- return value / (dst_base / base)
- else:
- return value * (base / dst_base)
-
-def err(msg):
- print >>sys.stderr, "Error:", msg
-
-
-def get_single_vm(dom):
- if serverType == SERVER_XEN_API:
- uuids = server.xenapi.VM.get_by_name_label(dom)
- if len(uuids) > 0:
- return uuids[0]
-
- refs = []
-
- try:
- domid = int(dom)
- refs = [vm_ref
- for vm_ref in server.xenapi.VM.get_all()
- if int(server.xenapi.VM.get_domid(vm_ref)) == domid]
- except:
- pass
-
- if len(refs) > 0:
- return refs[0]
-
- raise OptionError("Domain '%s' not found." % dom)
- else:
- dominfo = server.xend.domain(dom, False)
- return dominfo['uuid']
-
-##
-#
-# Xen-API Shell
-#
-##
-
-class Shell(cmd.Cmd):
- def __init__(self):
- cmd.Cmd.__init__(self)
- self.prompt = "xm> "
- if serverType == SERVER_XEN_API:
- try:
- res = server.xenapi.host.list_methods()
- for f in res:
- setattr(Shell, 'do_' + f + ' ', self.default)
- except:
- pass
-
- def preloop(self):
- cmd.Cmd.preloop(self)
- try:
- import readline
- readline.set_completer_delims(' ')
- except ImportError:
- pass
-
- def default(self, line):
- words = shlex.split(line)
- if len(words) > 0 and words[0] == 'xm':
- words = words[1:]
- if len(words) > 0:
- cmd = xm_lookup_cmd(words[0])
- if cmd:
- _run_cmd(cmd, words[0], words[1:])
- elif serverType == SERVER_XEN_API:
- ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
- tuple(x)),
- words[0], words[1:])
- if ok and res is not None and res != '':
- pprint.pprint(res)
- else:
- print '*** Unknown command: %s' % words[0]
- return False
-
- def completedefault(self, text, line, begidx, endidx):
- words = shlex.split(line[:begidx])
- clas, func = words[0].split('.')
- if len(words) > 1 or \
- func.startswith('get_by_') or \
- func == 'get_all':
- return []
- uuids = server.xenapi_request('%s.get_all' % clas, ())
- return [u + " " for u in uuids if u.startswith(text)]
-
- def emptyline(self):
- pass
-
- def do_EOF(self, line):
- print
- sys.exit(0)
-
- def do_help(self, line):
- _usage(line)
-
-
-def xm_shell(args):
- Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
-
-
-def xm_event_monitor(args):
- if serverType == SERVER_XEN_API:
- while True:
- server.xenapi.event.register(args)
- events = server.xenapi.event.next()
- for e in events:
- print e
- else:
- err("Event monitoring not supported unless using Xen-API.")
-
-
-#########################################################################
-#
-# Main xm functions
-#
-#########################################################################
-
-def xm_save(args):
-
- arg_check(args, "save", 2, 3)
-
- try:
- (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('save')
-
- checkpoint = False
- for (k, v) in options:
- if k in ['-c', '--checkpoint']:
- checkpoint = True
-
- if len(params) != 2:
- err("Wrong number of parameters")
- usage('save')
-
- dom = params[0]
- savefile = os.path.abspath(params[1])
-
- if not os.access(os.path.dirname(savefile), os.W_OK):
- err("xm save: Unable to create file %s" % savefile)
- sys.exit(1)
-
- if serverType == SERVER_XEN_API:
- server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
- else:
- server.xend.domain.save(dom, savefile, checkpoint)
-
-def xm_restore(args):
- arg_check(args, "restore", 1, 2)
-
- try:
- (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('restore')
-
- paused = False
- for (k, v) in options:
- if k in ['-p', '--paused']:
- paused = True
-
- if len(params) != 1:
- err("Wrong number of parameters")
- usage('restore')
-
- savefile = os.path.abspath(params[0])
-
- if not os.access(savefile, os.R_OK):
- err("xm restore: Unable to read file %s" % savefile)
- sys.exit(1)
-
- if serverType == SERVER_XEN_API:
- server.xenapi.VM.restore(savefile, paused)
- else:
- server.xend.domain.restore(savefile, paused)
-
-
-def datetime_to_secs(v):
- unwanted = ":-."
- for c in unwanted:
- v = str(v).replace(c, "")
- return time.mktime(time.strptime(v[0:14], '%Y%m%dT%H%M%S'))
-
-def getDomains(domain_names, state, full = 0, pool = None):
- if serverType == SERVER_XEN_API:
- doms_sxp = []
- doms_dict = []
-
- dom_recs = server.xenapi.VM.get_all_records()
- dom_metrics_recs = server.xenapi.VM_metrics.get_all_records()
-
- for dom_ref, dom_rec in dom_recs.items():
- if pool and pool != dom_rec['pool_name']:
- continue
-
- dom_metrics_rec = dom_metrics_recs[dom_rec['metrics']]
-
- states = ('running', 'blocked', 'paused', 'shutdown',
- 'crashed', 'dying')
- def state_on_off(state):
- if state in dom_metrics_rec['state']:
- return state[0]
- else:
- return "-"
- state_str = "".join([state_on_off(state)
- for state in states])
- dom_rec.update({'name': dom_rec['name_label'],
- 'memory_actual': int(dom_metrics_rec['memory_actual'])/1024,
- 'vcpus': dom_metrics_rec['VCPUs_number'],
- 'state': state_str,
- 'cpu_time': dom_metrics_rec['VCPUs_utilisation'],
- 'start_time': datetime_to_secs(
- dom_metrics_rec['start_time'])})
-
- doms_sxp.append(['domain'] + map2sxp(dom_rec))
- doms_dict.append(dom_rec)
-
- if domain_names:
- doms = [['domain'] + map2sxp(dom) for dom in doms_dict
- if dom["name"] in domain_names]
-
- if len(doms) > 0:
- return doms
- else:
- print "Error: no domain%s named %s" % \
- (len(domain_names) > 1 and 's' or '',
- ', '.join(domain_names))
- sys.exit(-1)
- else:
- return doms_sxp
- else:
- if domain_names:
- return [server.xend.domain(dom, full) for dom in domain_names]
- else:
- doms = server.xend.domains_with_state(True, state, full)
- if not pool:
- return doms
- else:
- doms_in_pool = []
- for dom in doms:
- if sxp.child_value(dom, 'pool_name', '') == pool:
- doms_in_pool.append(dom)
- return doms_in_pool
-
-
-def xm_list(args):
- use_long = 0
- show_vcpus = 0
- show_labels = 0
- state = 'all'
- pool = None
- try:
- (options, params) = getopt.gnu_getopt(args, 'lv',
- ['long','vcpus','label',
- 'state=','pool='])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('list')
-
- for (k, v) in options:
- if k in ['-l', '--long']:
- use_long = 1
- if k in ['-v', '--vcpus']:
- show_vcpus = 1
- if k in ['--label']:
- show_labels = 1
- if k in ['--state']:
- state = v
- if k in ['--pool']:
- pool = v
-
- if state != 'all' and len(params) > 0:
- raise OptionError(
- "You may specify either a state or a particular VM, but not both")
-
- if pool and len(params) > 0:
- raise OptionError(
- "You may specify either a pool or a particular VM, but not both")
-
- if show_vcpus:
- print >>sys.stderr, (
- "xm list -v is deprecated. Please use xm vcpu-list.")
- xm_vcpu_list(params)
- return
-
- doms = getDomains(params, state, use_long, pool)
-
- if use_long:
- map(PrettyPrint.prettyprint, doms)
- elif show_labels:
- xm_label_list(doms)
- else:
- xm_brief_list(doms)
-
-
-def parse_doms_info(info):
- def get_info(n, t, d):
- return t(sxp.child_value(info, n, d))
-
- def get_status(n, t, d):
- return DOM_STATES[t(sxp.child_value(info, n, d))]
-
- start_time = get_info('start_time', float, -1)
- if start_time == -1:
- up_time = float(-1)
- else:
- up_time = time.time() - start_time
-
- parsed_info = {
- 'domid' : get_info('domid', str, ''),
- 'name' : get_info('name', str, '??'),
- 'state' : get_info('state', str, ''),
-
- # VCPUs is the number online when the VM is up, or the number
- # configured otherwise.
- 'vcpus' : get_info('online_vcpus', int,
- get_info('vcpus', int, 0)),
- 'up_time' : up_time
- }
-
- security_label = get_info('security_label', str, '')
- parsed_info['seclabel'] = security.parse_security_label(security_label)
-
- if serverType == SERVER_XEN_API:
- parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
- cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
- if sum(cpu_times.values()) > 0:
- parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
- else:
- parsed_info['cpu_time'] = 0
- else:
- parsed_info['mem'] = get_info('memory', int,0)
- parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
-
- return parsed_info
-
-def check_sched_type(sched):
- if serverType == SERVER_XEN_API:
- current = server.xenapi.host.get_sched_policy(
- server.xenapi.session.get_this_host(server.getSession()))
- else:
- current = 'unknown'
- for x in server.xend.node.info()[1:]:
- if len(x) > 1 and x[0] == 'xen_scheduler':
- current = x[1]
- break
- if sched != current:
- err("Xen is running with the %s scheduler" % current)
- sys.exit(1)
-
-def parse_sedf_info(info):
- def get_info(n, t, d):
- return t(sxp.child_value(info, n, d))
-
- return {
- 'domid' : get_info('domid', int, -1),
- 'period' : get_info('period', int, -1),
- 'slice' : get_info('slice', int, -1),
- 'latency' : get_info('latency', int, -1),
- 'extratime': get_info('extratime', int, -1),
- 'weight' : get_info('weight', int, -1),
- }
-
-def domid_match(domid, info):
- return domid is None or domid == info['name'] or \
- domid == str(info['domid'])
-
-def xm_brief_list(doms):
- print '%-40s %5s %5s %5s %10s %9s' % \
- ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
-
- format = "%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s " \
- "%(cpu_time)8.1f"
-
- for dom in doms:
- d = parse_doms_info(dom)
- print format % d
-
-def xm_label_list(doms):
- print '%-40s %5s %5s %5s %10s %9s %-10s' % \
- ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
-
- output = []
- format = '%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s ' \
- '%(cpu_time)8.1f %(seclabel)10s'
-
- for dom in doms:
- d = parse_doms_info(dom)
- if d['seclabel'] == "" and serverType != SERVER_XEN_API:
- seclab = server.xend.security.get_domain_label(d['name'])
- if len(seclab) > 0 and seclab[0] == '\'':
- seclab = seclab[1:]
- d['seclabel'] = seclab
- output.append((format % d, d['seclabel']))
-
- #sort by labels
- output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
- for line, label in output:
- print line
-
-
-def xm_vcpu_list(args):
- if serverType == SERVER_XEN_API:
- if args:
- vm_refs = map(get_single_vm, args)
- else:
- vm_refs = server.xenapi.VM.get_all()
-
- vm_records = dict(map(lambda vm_ref:
- (vm_ref, server.xenapi.VM.get_record(
- vm_ref)),
- vm_refs))
-
- vm_metrics = dict(map(lambda (ref, record):
- (ref,
- server.xenapi.VM_metrics.get_record(
- record['metrics'])),
- vm_records.items()))
-
- dominfo = []
-
- # vcpu_list doesn't list 'managed' domains
- # when they are not running, so filter them out
-
- vm_refs = [vm_ref
- for vm_ref in vm_refs
- if vm_records[vm_ref]["power_state"] != "Halted"]
-
- for vm_ref in vm_refs:
- info = ['domain',
- ['domid', vm_records[vm_ref]['domid']],
- ['name', vm_records[vm_ref]['name_label']],
- ['vcpu_count', vm_records[vm_ref]['VCPUs_max']]]
-
- for i in range(int(vm_records[vm_ref]['VCPUs_max'])):
- def chk_flag(flag):
- return flag in vm_metrics[vm_ref]['VCPUs_flags'][str(i)] \
- and 1 or 0
-
- vcpu_info = ['vcpu',
- ['number',
- i],
- ['online',
- chk_flag("online")],
- ['blocked',
- chk_flag("blocked")],
- ['running',
- chk_flag("running")],
- ['cpu_time',
- vm_metrics[vm_ref]['VCPUs_utilisation'][str(i)]],
- ['cpu',
- vm_metrics[vm_ref]['VCPUs_CPU'][str(i)]],
- ['cpumap',
- vm_metrics[vm_ref]['VCPUs_params']\
- ['cpumap%i' % i].split(",")]]
-
- info.append(vcpu_info)
-
- dominfo.append(info)
- else:
- if args:
- dominfo = map(server.xend.domain.getVCPUInfo, args)
- else:
- doms = server.xend.domains_with_state(False, 'all', False)
- dominfo = map(server.xend.domain.getVCPUInfo, doms)
-
- print '%-32s %5s %5s %5s %5s %9s %s' % \
- ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
-
- format = '%(name)-32s %(domid)5s %(number)5d %(c)5s %(s)5s ' \
- ' %(cpu_time)8.1f %(cpumap)s'
-
- for dom in dominfo:
- def get_info(n):
- return sxp.child_value(dom, n)
-
- #
- # convert a list of integers into a list of pairs indicating
- # continuous sequences in the list:
- #
- # [0,1,2,3] -> [(0,3)]
- # [1,2,4,5] -> [(1,2),(4,5)]
- # [0] -> [(0,0)]
- # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
- #
- def list_to_rangepairs(cmap):
- cmap.sort()
- pairs = []
- x = y = 0
- for i in range(0,len(cmap)):
- try:
- if ((cmap[y+1] - cmap[i]) > 1):
- pairs.append((cmap[x],cmap[y]))
- x = y = i+1
- else:
- y = y + 1
- # if we go off the end, then just add x to y
- except IndexError:
- pairs.append((cmap[x],cmap[y]))
-
- return pairs
-
- #
- # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
- #
- def format_pairs(pairs):
- if not pairs:
- return "no cpus"
- out = ""
- for f,s in pairs:
- if (f==s):
- out += '%d'%f
- else:
- out += '%d-%d'%(f,s)
- out += ','
- # trim trailing ','
- return out[:-1]
-
- def format_cpumap(cpumap):
- cpumap = map(lambda x: int(x), cpumap)
- cpumap.sort()
-
- if serverType == SERVER_XEN_API:
- nr_cpus = len(server.xenapi.host.get_host_CPUs(
- server.xenapi.session.get_this_host(server.getSession())))
- else:
- for x in server.xend.node.info()[1:]:
- if len(x) > 1 and x[0] == 'nr_cpus':
- nr_cpus = int(x[1])
-
- # normalize cpumap by modulus nr_cpus, and drop duplicates
- cpumap = dict.fromkeys(
- filter(lambda x: x < nr_cpus, cpumap)).keys()
- if len(cpumap) == nr_cpus:
- return "any cpu"
-
- return format_pairs(list_to_rangepairs(cpumap))
-
- name = get_info('name')
- domid = get_info('domid')
- if domid is not None:
- domid = str(domid)
- else:
- domid = ''
-
- for vcpu in sxp.children(dom, 'vcpu'):
- def vinfo(n, t):
- return t(sxp.child_value(vcpu, n))
-
- number = vinfo('number', int)
- cpu = vinfo('cpu', int)
- cpumap = format_cpumap(vinfo('cpumap', list))
- online = vinfo('online', int)
- cpu_time = vinfo('cpu_time', float)
- running = vinfo('running', int)
- blocked = vinfo('blocked', int)
-
- if cpu < 0:
- c = ''
- s = ''
- elif online:
- c = str(cpu)
- if running:
- s = 'r'
- else:
- s = '-'
- if blocked:
- s += 'b'
- else:
- s += '-'
- s += '-'
- else:
- c = '-'
- s = '--p'
-
- print format % locals()
-
-def start_do_console(domain_name):
- cpid = os.fork()
- if cpid != 0:
- for i in range(10):
- # Catch failure of the create process
- time.sleep(1)
- (p, rv) = os.waitpid(cpid, os.WNOHANG)
- if os.WIFEXITED(rv):
- 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'))
- console.execConsole(domid)
- except:
- pass
- print("Could not start console\n");
- sys.exit(0)
-
-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','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")
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('start')
-
- dom = params[0]
-
- if console_autoconnect:
- start_do_console(dom)
-
- try:
- if serverType == SERVER_XEN_API:
- server.xenapi.VM.start(get_single_vm(dom), paused)
- domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
- else:
- server.xend.domain.start(dom, paused)
- info = server.xend.domain(dom)
- domid = int(sxp.child_value(info, 'domid', '-1'))
- except:
- raise
-
- if domid == -1:
- raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
-
- if vncviewer:
- console.runVncViewer(domid, vncviewer_autopass, True)
-
-
-def xm_delete(args):
- arg_check(args, "delete", 1)
- dom = args[0]
- if serverType == SERVER_XEN_API:
- server.xenapi.VM.destroy(get_single_vm(dom))
- else:
- server.xend.domain.delete(dom)
-
-def xm_suspend(args):
- arg_check(args, "suspend", 1)
- dom = args[0]
- if serverType == SERVER_XEN_API:
- server.xenapi.VM.suspend(get_single_vm(dom))
- else:
- server.xend.domain.suspend(dom)
-
-def xm_resume(args):
- arg_check(args, "resume", 1, 2)
-
- try:
- (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('resume')
-
- paused = False
- for (k, v) in options:
- if k in ['-p', '--paused']:
- paused = True
-
- if len(params) != 1:
- err("Wrong number of parameters")
- usage('resume')
-
- dom = params[0]
- if serverType == SERVER_XEN_API:
- server.xenapi.VM.resume(get_single_vm(dom), paused)
- else:
- server.xend.domain.resume(dom, paused)
-
-def xm_reboot(args):
- arg_check(args, "reboot", 1, 3)
- from xen.xm import shutdown
- shutdown.main(["shutdown", "-R"] + args)
-
-def xm_shutdown(args):
- arg_check(args, "shutdown", 1, 4)
- from xen.xm import shutdown
- shutdown.main(["shutdown"] + args)
-
-def xm_reset(args):
- arg_check(args, "reset", 1)
- dom = args[0]
-
- if serverType == SERVER_XEN_API:
- server.xenapi.VM.hard_reboot(get_single_vm(dom))
- else:
- server.xend.domain.reset(dom)
-
-def xm_pause(args):
- arg_check(args, "pause", 1)
- dom = args[0]
-
- if serverType == SERVER_XEN_API:
- server.xenapi.VM.pause(get_single_vm(dom))
- server.xenapi.VM.set_pauseflag(get_single_vm(dom), True)
- else:
- server.xend.domain.pause(dom)
- server.xend.domain.setpauseflag(dom, True)
-
-def xm_unpause(args):
- arg_check(args, "unpause", 1)
- dom = args[0]
-
- if serverType == SERVER_XEN_API:
- server.xenapi.VM.unpause(get_single_vm(dom))
- server.xenapi.VM.set_pauseflag(get_single_vm(dom), False)
- else:
- server.xend.domain.unpause(dom)
- server.xend.domain.setpauseflag(dom, False)
-
-def xm_dump_core(args):
- live = False
- crash = False
- reset = False
- try:
- (options, params) = getopt.gnu_getopt(args, 'LCR', ['live', 'crash', 'reset'])
- for (k, v) in options:
- if k in ('-L', '--live'):
- live = True
- elif k in ('-C', '--crash'):
- crash = True
- elif k in ('-R', '--reset'):
- reset = True
-
- if crash and reset:
- raise OptionError("You may not specify more than one '-CR' option")
- if len(params) not in (1, 2):
- raise OptionError("Expects 1 or 2 argument(s)")
- except getopt.GetoptError, e:
- raise OptionError(str(e))
-
- dom = params[0]
- if len(params) == 2:
- filename = os.path.abspath(params[1])
- else:
- filename = None
-
- print "Dumping core of domain: %s ..." % str(dom)
- server.xend.domain.dump(dom, filename, live, crash, reset)
-
-def xm_rename(args):
- arg_check(args, "rename", 2)
-
- if serverType == SERVER_XEN_API:
- server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
- else:
- server.xend.domain.setName(args[0], args[1])
-
-def xm_importcommand(command, args):
- cmd = __import__(command, globals(), locals(), 'xen.xm')
- cmd.main([command] + args)
-
-
-#############################################################
-
-def xm_vcpu_pin(args):
- arg_check(args, "vcpu-pin", 3)
-
- def cpu_make_map(cpulist):
- cpus = []
- for c in cpulist.split(','):
- if c == '':
- continue
- if c.find('-') != -1:
- (x,y) = c.split('-')
- for i in range(int(x),int(y)+1):
- cpus.append(int(i))
- else:
- # remove this element from the list
- if c[0] == '^':
- cpus = [x for x in cpus if x != int(c[1:])]
- else:
- cpus.append(int(c))
- cpus.sort()
- return ",".join(map(str, cpus))
-
- dom = args[0]
- vcpu = args[1]
- if args[2] == 'all':
- cpumap = cpu_make_map('0-63')
- else:
- cpumap = cpu_make_map(args[2])
-
- if serverType == SERVER_XEN_API:
- server.xenapi.VM.add_to_VCPUs_params_live(
- get_single_vm(dom), "cpumap%i" % int(vcpu), cpumap)
- else:
- server.xend.domain.pincpu(dom, vcpu, cpumap)
-
-def xm_mem_max(args):
- arg_check(args, "mem-max", 2)
-
- dom = args[0]
-
- if serverType == SERVER_XEN_API:
- mem = int_unit(args[1], 'k') * 1024
- server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
- else:
- mem = int_unit(args[1], 'm')
- server.xend.domain.maxmem_set(dom, mem)
-
-def xm_mem_set(args):
- arg_check(args, "mem-set", 2)
-
- dom = args[0]
-
- if serverType == SERVER_XEN_API:
- mem_target = int_unit(args[1], 'm') * 1024 * 1024
- server.xenapi.VM.set_memory_dynamic_max_live(get_single_vm(dom),
- mem_target)
- server.xenapi.VM.set_memory_dynamic_min_live(get_single_vm(dom),
- mem_target)
- else:
- mem_target = int_unit(args[1], 'm')
- server.xend.domain.setMemoryTarget(dom, mem_target)
-
-def xm_usb_add(args):
- arg_check(args, "usb-add", 2)
- server.xend.domain.usb_add(args[0],args[1])
-
-def xm_domstate(args):
- arg_check(args, "domstate", 1)
- (opitons, params) = getopt.gnu_getopt(args, 's', ['domname='])
- doms = getDomains(params, 'all')
- d = parse_doms_info(doms[0])
- state = d['state']
- if state:
- if state.find('s') > 0:
- print 'shutoff'
- elif state.find('b') > 0:
- print 'idle'
- elif state.find('d') > 0:
- print 'shutdown'
- elif state.find('r') > 0:
- print 'running'
- elif state.find('c') > 0:
- print 'crashed'
- elif state.find('p') > 0:
- if server.xend.domain.getpauseflag(args[0]):
- print 'paused by admin'
- else:
- print 'paused'
- else:
- print 'shutoff'
- return
-
-def xm_usb_del(args):
- arg_check(args, "usb-del", 2)
- server.xend.domain.usb_del(args[0],args[1])
-
-def xm_vcpu_set(args):
- arg_check(args, "vcpu-set", 2)
-
- dom = args[0]
- vcpus = int(args[1])
-
- if serverType == SERVER_XEN_API:
- server.xenapi.VM.set_VCPUs_number_live(get_single_vm(dom), vcpus)
- else:
- server.xend.domain.setVCpuCount(dom, vcpus)
-
-def xm_destroy(args):
- arg_check(args, "destroy", 1)
-
- dom = args[0]
-
- if serverType == SERVER_XEN_API:
- server.xenapi.VM.hard_shutdown(get_single_vm(dom))
- else:
- server.xend.domain.destroy(dom)
-
-def xm_domid(args):
- arg_check(args, "domid", 1)
-
- name = args[0]
-
- if serverType == SERVER_XEN_API:
- print server.xenapi.VM.get_domid(get_single_vm(name))
- else:
- dom = server.xend.domain(name)
- print sxp.child_value(dom, 'domid')
-
-def xm_domname(args):
- arg_check(args, "domname", 1)
-
- name = args[0]
-
- if serverType == SERVER_XEN_API:
- print server.xenapi.VM.get_name_label(get_single_vm(name))
- else:
- dom = server.xend.domain(name)
- print sxp.child_value(dom, 'name')
-
-def xm_sched_sedf(args):
- xenapi_unsupported()
-
- def ns_to_ms(val):
- return float(val) * 0.000001
-
- def ms_to_ns(val):
- return (float(val) / 0.000001)
-
- def print_sedf(info):
- info['period'] = ns_to_ms(info['period'])
- info['slice'] = ns_to_ms(info['slice'])
- info['latency'] = ns_to_ms(info['latency'])
- print( ("%(name)-32s %(domid)5d %(period)9.1f %(slice)9.1f" +
- " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
-
- check_sched_type('sedf')
-
- # we want to just display current info if no parameters are passed
- if len(args) == 0:
- domid = None
- else:
- # we expect at least a domain id (name or number)
- # and at most a domid up to 5 options with values
- arg_check(args, "sched-sedf", 1, 11)
- domid = args[0]
- # drop domid from args since get_opt doesn't recognize it
- args = args[1:]
-
- opts = {}
- try:
- (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
- ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('sched-sedf')
-
- # convert to nanoseconds if needed
- for (k, v) in options:
- if k in ['-p', '--period']:
- opts['period'] = ms_to_ns(v)
- elif k in ['-s', '--slice']:
- opts['slice'] = ms_to_ns(v)
- elif k in ['-l', '--latency']:
- opts['latency'] = ms_to_ns(v)
- elif k in ['-e', '--extratime']:
- opts['extratime'] = v
- elif k in ['-w', '--weight']:
- opts['weight'] = v
-
- doms = filter(lambda x : domid_match(domid, x),
- [parse_doms_info(dom)
- for dom in getDomains(None, 'running')])
- if domid is not None and doms == []:
- err("Domain '%s' does not exist." % domid)
- usage('sched-sedf')
-
- # print header if we aren't setting any parameters
- if len(opts.keys()) == 0:
- print '%-33s %4s %-4s %-4s %-7s %-5s %-6s' % \
- ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
- 'Extra','Weight')
-
- for d in doms:
- # fetch current values so as not to clobber them
- try:
- sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
- except xmlrpclib.Fault:
- # domain does not support sched-sedf?
- sedf_raw = {}
-
- sedf_info = parse_sedf_info(sedf_raw)
- sedf_info['name'] = d['name']
- # update values in case of call to set
- if len(opts.keys()) > 0:
- for k in opts.keys():
- sedf_info[k]=opts[k]
-
- # send the update, converting user input
- v = map(int, [sedf_info['period'], sedf_info['slice'],
- sedf_info['latency'],sedf_info['extratime'],
- sedf_info['weight']])
- rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
- if int(rv) != 0:
- err("Failed to set sedf parameters (rv=%d)."%(rv))
-
- # not setting values, display info
- else:
- print_sedf(sedf_info)
-
-def xm_sched_credit(args):
- """Get/Set options for Credit Scheduler."""
-
- check_sched_type('credit')
-
- try:
- opts, params = getopt.getopt(args, "d:w:c:",
- ["domain=", "weight=", "cap="])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('sched-credit')
-
- domid = None
- weight = None
- cap = None
-
- for o, a in opts:
- if o in ["-d", "--domain"]:
- domid = a
- elif o in ["-w", "--weight"]:
- weight = int(a)
- elif o in ["-c", "--cap"]:
- cap = int(a);
-
- doms = filter(lambda x : domid_match(domid, x),
- [parse_doms_info(dom)
- for dom in getDomains(None, 'all')])
-
- if weight is None and cap is None:
- if domid is not None and doms == []:
- err("Domain '%s' does not exist." % domid)
- usage('sched-credit')
- # print header if we aren't setting any parameters
- print '%-33s %4s %6s %4s' % ('Name','ID','Weight','Cap')
-
- for d in doms:
- try:
- if serverType == SERVER_XEN_API:
- info = server.xenapi.VM_metrics.get_VCPUs_params(
- server.xenapi.VM.get_metrics(
- get_single_vm(d['name'])))
- else:
- info = server.xend.domain.sched_credit_get(d['name'])
- except xmlrpclib.Fault:
- pass
-
- if 'weight' not in info or 'cap' not in info:
- # domain does not support sched-credit?
- info = {'weight': -1, 'cap': -1}
-
- info['weight'] = int(info['weight'])
- info['cap'] = int(info['cap'])
-
- info['name'] = d['name']
- info['domid'] = str(d['domid'])
- print( ("%(name)-32s %(domid)5s %(weight)6d %(cap)4d") % info)
- else:
- if domid is None:
- # place holder for system-wide scheduler parameters
- err("No domain given.")
- usage('sched-credit')
-
- if serverType == SERVER_XEN_API:
- if doms[0]['domid']:
- server.xenapi.VM.add_to_VCPUs_params_live(
- get_single_vm(domid),
- "weight",
- weight)
- server.xenapi.VM.add_to_VCPUs_params_live(
- get_single_vm(domid),
- "cap",
- cap)
- else:
- server.xenapi.VM.add_to_VCPUs_params(
- get_single_vm(domid),
- "weight",
- weight)
- server.xenapi.VM.add_to_VCPUs_params(
- get_single_vm(domid),
- "cap",
- cap)
- else:
- result = server.xend.domain.sched_credit_set(domid, weight, cap)
- if result != 0:
- err(str(result))
-
-def xm_sched_credit2(args):
- """Get/Set options for Credit2 Scheduler."""
-
- check_sched_type('credit2')
-
- try:
- opts, params = getopt.getopt(args, "d:w:",
- ["domain=", "weight="])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('sched-credit2')
-
- domid = None
- weight = None
-
- for o, a in opts:
- if o in ["-d", "--domain"]:
- domid = a
- elif o in ["-w", "--weight"]:
- weight = int(a)
-
- doms = filter(lambda x : domid_match(domid, x),
- [parse_doms_info(dom)
- for dom in getDomains(None, 'all')])
-
- if weight is None:
- if domid is not None and doms == []:
- err("Domain '%s' does not exist." % domid)
- usage('sched-credit2')
- # print header if we aren't setting any parameters
- print '%-33s %4s %6s' % ('Name','ID','Weight')
-
- for d in doms:
- try:
- if serverType == SERVER_XEN_API:
- info = server.xenapi.VM_metrics.get_VCPUs_params(
- server.xenapi.VM.get_metrics(
- get_single_vm(d['name'])))
- else:
- info = server.xend.domain.sched_credit2_get(d['name'])
- except xmlrpclib.Fault:
- pass
-
- if 'weight' not in info:
- # domain does not support sched-credit2?
- info = {'weight': -1}
-
- info['weight'] = int(info['weight'])
-
- info['name'] = d['name']
- info['domid'] = str(d['domid'])
- print( ("%(name)-32s %(domid)5s %(weight)6d") % info)
- else:
- if domid is None:
- # place holder for system-wide scheduler parameters
- err("No domain given.")
- usage('sched-credit2')
-
- if serverType == SERVER_XEN_API:
- if doms[0]['domid']:
- server.xenapi.VM.add_to_VCPUs_params_live(
- get_single_vm(domid),
- "weight",
- weight)
- else:
- server.xenapi.VM.add_to_VCPUs_params(
- get_single_vm(domid),
- "weight",
- weight)
- else:
- result = server.xend.domain.sched_credit2_set(domid, weight)
- if result != 0:
- err(str(result))
-
-def xm_info(args):
- arg_check(args, "info", 0, 1)
-
- try:
- (options, params) = getopt.gnu_getopt(args, 'cn', ['config','numa'])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('info')
-
- show_xend_config = 0
- show_numa_topology = 0
- for (k, v) in options:
- if k in ['-c', '--config']:
- show_xend_config = 1
- if k in ['-n', '--numa']:
- show_numa_topology = 1
-
- if show_xend_config:
- for name, obj in inspect.getmembers(xoptions):
- if not inspect.ismethod(obj):
- if name == "config":
- for x in obj[1:]:
- if len(x) < 2:
- print "%-38s: (none)" % x[0]
- else:
- print "%-38s:" % x[0], x[1]
- else:
- print "%-38s:" % name, obj
- return
-
- if serverType == SERVER_XEN_API:
-
- # Need to fake out old style xm info as people rely on parsing it
-
- host_record = server.xenapi.host.get_record(
- server.xenapi.session.get_this_host(server.getSession()))
-
- host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
-
- host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
-
- def getVal(keys, default=""):
- data = host_record
- for key in keys:
- if key in data:
- data = data[key]
- else:
- return default
- return data
-
- def getCpuMhz():
- cpu_speeds = [int(host_cpu_record["speed"])
- for host_cpu_record in host_cpu_records
- if "speed" in host_cpu_record]
- if len(cpu_speeds) > 0:
- return sum(cpu_speeds) / len(cpu_speeds)
- else:
- return 0
-
- getCpuMhz()
-
- def getCpuFeatures():
- if len(host_cpu_records) > 0:
- return host_cpu_records[0].get("features", "")
- else:
- return ""
-
- def getFreeCpuCount():
- cnt = 0
- for host_cpu_record in host_cpu_records:
- if len(host_cpu_record.get("cpu_pool", [])) == 0:
- cnt += 1
- return cnt
-
- info = {
- "host": getVal(["name_label"]),
- "release": getVal(["software_version", "release"]),
- "version": getVal(["software_version", "version"]),
- "machine": getVal(["software_version", "machine"]),
- "nr_cpus": getVal(["cpu_configuration", "nr_cpus"]),
- "nr_nodes": getVal(["cpu_configuration", "nr_nodes"]),
- "cores_per_socket": getVal(["cpu_configuration", "cores_per_socket"]),
- "threads_per_core": getVal(["cpu_configuration", "threads_per_core"]),
- "cpu_mhz": getCpuMhz(),
- "hw_caps": getCpuFeatures(),
- "free_cpus": getFreeCpuCount(),
- "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
- "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
- "xen_major": getVal(["software_version", "xen_major"]),
- "xen_minor": getVal(["software_version", "xen_minor"]),
- "xen_extra": getVal(["software_version", "xen_extra"]),
- "xen_caps": " ".join(getVal(["capabilities"], [])),
- "xen_scheduler": getVal(["sched_policy"]),
- "xen_pagesize": getVal(["other_config", "xen_pagesize"]),
- "platform_params": getVal(["other_config", "platform_params"]),
- "xen_commandline": getVal(["other_config", "xen_commandline"]),
- "xen_changeset": getVal(["software_version", "xen_changeset"]),
- "cc_compiler": getVal(["software_version", "cc_compiler"]),
- "cc_compile_by": getVal(["software_version", "cc_compile_by"]),
- "cc_compile_domain": getVal(["software_version", "cc_compile_domain"]),
- "cc_compile_date": getVal(["software_version", "cc_compile_date"]),
- "xend_config_format":getVal(["software_version", "xend_config_format"])
- }
-
- sorted = info.items()
- sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
-
- for (k, v) in sorted:
- print "%-23s:" % k, v
- else:
- info = server.xend.node.info(show_numa_topology)
- for x in info[1:]:
- if len(x) < 2:
- print "%-23s: (none)" % x[0]
- else:
- print "%-23s:" % x[0], x[1]
-
-def xm_console(args):
- arg_check(args, "console", 1, 3)
-
- num = 0
- quiet = False;
-
- try:
- (options, params) = getopt.gnu_getopt(args, 'qn:', ['quiet', 'num'])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('console')
-
- for (k, v) in options:
- if k in ['-q', '--quiet']:
- quiet = True
- elif k in ['-n', '--num']:
- num = int(v[0])
- else:
- assert False
-
- if len(params) != 1:
- err('No domain given')
- usage('console')
-
- dom = params[0]
-
- try:
- if serverType == SERVER_XEN_API:
- domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
- else:
- info = server.xend.domain(dom)
- domid = int(sxp.child_value(info, 'domid', '-1'))
- except:
- if quiet:
- sys.exit(1)
- else:
- raise
-
- if domid == -1:
- if quiet:
- sys.exit(1)
- else:
- raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
-
- console.execConsole(domid, num)
-
-
-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 int(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
-
- try:
- (options, params) = getopt.gnu_getopt(args, 's', ['short'])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('uptime')
-
- for (k, v) in options:
- if k in ['-s', '--short']:
- short_mode = 1
-
- doms = getDomains(params, 'all')
-
- if short_mode == 0:
- print '%-33s %4s %s ' % ('Name','ID','Uptime')
-
- for dom in doms:
- d = parse_doms_info(dom)
- if d['domid'] == '':
- uptime = 0
- elif int(d['domid']) > 0:
- uptime = int(round(d['up_time']))
- else:
- f=open('/proc/uptime', 'r')
- upfile = f.read()
- uptime = int(round(float(upfile.split(' ')[0])))
- f.close()
-
- days = int(uptime / 86400)
- uptime -= (days * 86400)
- hours = int(uptime / 3600)
- uptime -= (hours * 3600)
- minutes = int(uptime / 60)
- uptime -= (minutes * 60)
- seconds = uptime
-
- upstring = ""
- if days > 0:
- upstring += str(days) + " day"
- if days > 1:
- upstring += "s"
- upstring += ", "
- upstring += '%(hours)2d:%(minutes)02d' % vars()
-
- if short_mode:
- now = datetime.datetime.now()
- upstring = now.strftime(" %H:%M:%S") + " up " + upstring
- upstring += ", " + d['name'] + " (" + d['domid'] + ")"
- else:
- upstring += ':%(seconds)02d' % vars()
- upstring = ("%(name)-32s %(domid)5s " % d) + upstring
-
- print upstring
-
-def xm_sysrq(args):
- arg_check(args, "sysrq", 2)
- dom = args[0]
- req = args[1]
- if serverType == SERVER_XEN_API:
- server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
- else:
- server.xend.domain.send_sysrq(dom, req)
-
-def xm_trigger(args):
- vcpu = 0
-
- arg_check(args, "trigger", 2, 3)
- dom = args[0]
- trigger = args[1]
- if len(args) == 3:
- vcpu = int(args[2])
-
- if serverType == SERVER_XEN_API:
- server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
- else:
- server.xend.domain.send_trigger(dom, trigger, vcpu)
-
-def xm_debug_keys(args):
- arg_check(args, "debug-keys", 1)
-
- keys = str(args[0])
-
- if serverType == SERVER_XEN_API:
- server.xenapi.host.send_debug_keys(
- server.xenapi.session.get_this_host(server.getSession()),
- keys)
- else:
- server.xend.node.send_debug_keys(keys)
-
-def xm_top(args):
- arg_check(args, "top", 0)
-
- os.system('xentop')
-
-def xm_dmesg(args):
- arg_check(args, "dmesg", 0, 1)
-
- try:
- (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('dmesg')
-
- use_clear = 0
- for (k, v) in options:
- if k in ['-c', '--clear']:
- use_clear = 1
-
- if len(params) :
- err("No parameter required")
- usage('dmesg')
-
- if serverType == SERVER_XEN_API:
- host = server.xenapi.session.get_this_host(server.getSession())
- if use_clear:
- print server.xenapi.host.dmesg_clear(host),
- else:
- print server.xenapi.host.dmesg(host),
- else:
- if not use_clear:
- print server.xend.node.dmesg.info(),
- else:
- print server.xend.node.dmesg.clear(),
-
-def xm_log(args):
- arg_check(args, "log", 0)
-
- if serverType == SERVER_XEN_API:
- print server.xenapi.host.get_log(
- server.xenapi.session.get_this_host(server.getSession()))
- else:
- print server.xend.node.log()
-
-def xm_serve(args):
- if serverType == SERVER_XEN_API:
- print "Not supported with XenAPI"
- sys.exit(-1)
-
- arg_check(args, "serve", 0)
-
- from fcntl import fcntl, F_SETFL
-
- s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- s.connect(XendClient.XML_RPC_SOCKET)
- fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
-
- while True:
- iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
- if s in iwtd:
- data = s.recv(4096)
- if len(data) > 0:
- sys.stdout.write(data)
- sys.stdout.flush()
- else:
- break
- if sys.stdin in iwtd:
- data = sys.stdin.read(4096)
- if len(data) > 0:
- s.sendall(data)
- else:
- break
- s.close()
-
-def parse_dev_info(info):
- def get_info(n, t, d):
- i = 0
- while i < len(info):
- if (info[i][0] == n):
- return t(info[i][1])
- i = i + 1
- return t(d)
- return {
- #common
- 'backend-id' : get_info('backend-id', int, -1),
- 'handle' : get_info('handle', int, 0),
- 'state' : get_info('state', int, -1),
- 'be-path' : get_info('backend', str, '??'),
- 'event-ch' : get_info('event-channel',int, -1),
- #network specific
- 'virtual-device' : get_info('virtual-device', str, '??'),
- 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
- 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
- 'mac' : get_info('mac', str, '??'),
- #block-device specific
- 'ring-ref' : get_info('ring-ref', int, -1),
- #vscsi specific
- 'feature-host' : get_info('feature-host', int, -1),
- }
-
-def arg_check_for_resource_list(args, name):
- use_long = 0
- try:
- (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage(name)
-
- for (k, v) in options:
- if k in ['-l', '--long']:
- use_long = 1
-
- if len(params) == 0:
- print 'No domain parameter given'
- usage(name)
- if len(params) > 1:
- print 'No multiple domain parameters allowed'
- usage(name)
-
- return (use_long, params)
-
-def xm_network_list(args):
- (use_long, params) = arg_check_for_resource_list(args, "network-list")
-
- dom = params[0]
-
- if serverType == SERVER_XEN_API:
- vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
- vif_properties = []
- for vif_ref in vif_refs:
- vif_property = server.xenapi.VIF.get_runtime_properties(vif_ref)
- vif_property['mac'] = server.xenapi.VIF.get_MAC(vif_ref)
- vif_properties.append(vif_property)
- devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
- zip(range(len(vif_properties)), vif_properties))
- else:
- devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
-
- if use_long:
- map(PrettyPrint.prettyprint, devs)
- else:
- hdr = 0
- for x in devs:
- if hdr == 0:
- print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
- hdr = 1
- ni = parse_dev_info(x[1])
- ni['idx'] = int(x[0])
- print ("%(idx)-3d "
- "%(backend-id)-3d"
- "%(mac)-17s "
- "%(handle)-3d "
- "%(state)-3d "
- "%(event-ch)-3d "
- "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
- "%(be-path)-30s "
- % ni)
-
-def xm_block_list(args):
- (use_long, params) = arg_check_for_resource_list(args, "block-list")
-
- dom = params[0]
-
- if serverType == SERVER_XEN_API:
- vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
- vbd_properties = \
- map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
- vbd_devs = \
- map(server.xenapi.VBD.get_device, vbd_refs)
- vbd_devids = [blkdev_name_to_number(x)[1] for x in vbd_devs]
- devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
- zip(vbd_devids, vbd_properties))
- else:
- devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
-
- if use_long:
- map(PrettyPrint.prettyprint, devs)
- else:
- hdr = 0
- for x in devs:
- if hdr == 0:
- print 'Vdev BE handle state evt-ch ring-ref BE-path'
- hdr = 1
- ni = parse_dev_info(x[1])
- ni['idx'] = int(x[0])
- print ("%(idx)-5d "
- "%(backend-id)-3d "
- "%(handle)-3d "
- "%(state)-3d "
- "%(event-ch)-3d "
- "%(ring-ref)-5d "
- "%(be-path)-30s "
- % ni)
-
-def attached_pci_dict_bin(dom):
- 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': int(ppci_record['domain']),
- 'bus': int(ppci_record['bus']),
- 'slot': int(ppci_record['slot']),
- 'func': int(ppci_record['func']),
- 'vdevfn': int(server.xenapi.DPCI.get_hotplug_slot(dpci_ref)),
- 'key': server.xenapi.DPCI.get_key(dpci_ref)
- }
- devs.append(dev)
-
- else:
- for x in server.xend.domain.getDeviceSxprs(dom, 'pci'):
- dev = {
- 'domain': int(x['domain'], 16),
- 'bus': int(x['bus'], 16),
- 'slot': int(x['slot'], 16),
- 'func': int(x['func'], 16),
- 'vdevfn': int(x['vdevfn'], 16),
- 'key': x['key']
- }
- devs.append(dev)
-
- return devs
-
-def pci_dict_bin_to_str(pci_dev):
- new_dev = pci_dev.copy()
-
- new_dev['domain'] = '0x%04x' % pci_dev['domain']
- new_dev['bus'] = '0x%02x' % pci_dev['bus']
- new_dev['slot'] = '0x%02x' % pci_dev['slot']
- new_dev['func'] = '0x%x' % pci_dev['func']
- new_dev['vdevfn'] = '0x%02x' % pci_dev['vdevfn']
-
- return new_dev
-
-def attached_pci_dict(dom):
- return map(pci_dict_bin_to_str, attached_pci_dict_bin(dom))
-
-def xm_pci_list(args):
- (use_long, params) = arg_check_for_resource_list(args, "pci-list")
-
- devs = attached_pci_dict_bin(params[0])
- if len(devs) == 0:
- return
-
- devs.sort(None,
- lambda x: (x['vdevfn'] - PCI_FUNC(x['vdevfn'])) << 32 |
- PCI_BDF(x['domain'], x['bus'], x['slot'], x['func']))
-
- has_vdevfn = False
- for x in devs:
- if x['vdevfn'] & AUTO_PHP_SLOT:
- x['show_vdevfn'] = '-'
- else:
- x['show_vdevfn'] = "%02x.%01x" % (PCI_SLOT(x['vdevfn']), PCI_FUNC(x['vdevfn']))
- has_vdevfn = True
-
- hdr_str = 'Device'
- fmt_str = '%(domain)04x:%(bus)02x:%(slot)02x.%(func)x'
- if has_vdevfn:
- hdr_str = 'Vdev ' + hdr_str
- fmt_str = '%(show_vdevfn)-4s ' + fmt_str
-
- print hdr_str
- for x in devs:
- print fmt_str % x
-
-
-def parse_pci_info(info):
- def get_info(n, t, d):
- return t(sxp.child_value(info, n, d))
- return {
- 'domain' : get_info('domain', parse_hex, 0),
- 'bus' : get_info('bus', parse_hex, -1),
- 'slot' : get_info('slot', parse_hex, -1),
- 'func' : get_info('func', parse_hex, -1)
- }
-
-def xm_pci_list_assignable_devices(args):
- xenapi_unsupported()
- arg_check(args, "pci-list-assignable-devices", 0)
-
- devs = server.xend.node.pciinfo()
- if devs is None:
- print "Error: pciback/pci-stub not loaded?"
- return
-
- fmt_str = "%(domain)04x:%(bus)02x:%(slot)02x.%(func)01x"
- for x in devs:
- pci = parse_pci_info(x)
- print fmt_str % pci
-
-
-def vscsi_sort(devs):
- def sort_hctl(ds, l):
- s = []
- for d1 in ds:
- for d2 in d1:
- v_dev = sxp.child_value(d2, 'v-dev')
- n = int(v_dev.split(':')[l])
- try:
- j = s[n]
- except IndexError:
- j = []
- s.extend([ [] for _ in range(len(s), n+1) ])
- j.append(d2)
- s[n] = j
- return s
-
- for i in range(len(devs)):
- ds1 = [ devs[i][1][0][1] ]
- ds1 = sort_hctl(ds1, 3)
- ds1 = sort_hctl(ds1, 2)
- ds1 = sort_hctl(ds1, 1)
- ds2 = []
- for d in ds1:
- ds2.extend(d)
- devs[i][1][0][1] = ds2
- return devs
-
-def vscsi_convert_sxp_to_dict(dev_sxp):
- dev_dict = {}
- for opt_val in dev_sxp[1:]:
- try:
- opt, val = opt_val
- dev_dict[opt] = val
- except TypeError:
- pass
- return dev_dict
-
-def xm_scsi_list(args):
- (use_long, params) = arg_check_for_resource_list(args, "scsi-list")
-
- dom = params[0]
-
- devs = []
- if serverType == SERVER_XEN_API:
-
- dscsi_refs = server.xenapi.VM.get_DSCSIs(get_single_vm(dom))
- dscsi_properties = \
- map(server.xenapi.DSCSI.get_runtime_properties, dscsi_refs)
- dscsi_dict = {}
- for dscsi_property in dscsi_properties:
- devid = int(dscsi_property['dev']['devid'])
- try:
- dscsi_sxp = dscsi_dict[devid]
- except:
- dscsi_sxp = [['devs', []]]
- for key, value in dscsi_property.items():
- if key != 'dev':
- dscsi_sxp.append([key, value])
- dev_sxp = ['dev']
- dev_sxp.extend(map2sxp(dscsi_property['dev']))
- dscsi_sxp[0][1].append(dev_sxp)
- dscsi_dict[devid] = dscsi_sxp
- devs = map2sxp(dscsi_dict)
-
- else:
- devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi')
-
- # Sort devs by virtual HCTL.
- devs = vscsi_sort(devs)
-
- if use_long:
- map(PrettyPrint.prettyprint, devs)
- else:
- hdr = 0
- for x in devs:
- if hdr == 0:
- print "%-3s %-3s %-5s %-4s %-10s %-5s %-10s %-4s" \
- % ('Idx', 'BE', 'state', 'host', 'phy-hctl', 'phy', 'vir-hctl', 'devstate')
- hdr = 1
- ni = parse_dev_info(x[1])
- ni['idx'] = int(x[0])
- for dev in x[1][0][1]:
- mi = vscsi_convert_sxp_to_dict(dev)
- print "%(idx)-3d %(backend-id)-3d %(state)-5d %(feature-host)-4d " % ni,
- print "%(p-dev)-10s %(p-devname)-5s %(v-dev)-10s %(frontstate)-4s" % mi
-
-def xm_usb_list(args):
- xenapi_unsupported()
- arg_check(args, 'usb-list', 1)
- dom = args[0]
- devs = server.xend.domain.getDeviceSxprs(dom, 'vusb')
- for x in devs:
- print "%-3s %-3s %-5s %-7s %-30s" \
- % ('Idx', 'BE', 'state', 'usb-ver', 'BE-path')
- ni = parse_dev_info(x[1])
- ni['idx'] = int(x[0])
- usbver = sxp.child_value(x[1], 'usb-ver')
- if int(usbver) == 1:
- ni['usb-ver'] = 'USB1.1'
- else:
- ni['usb-ver'] = 'USB2.0'
- print "%(idx)-3d %(backend-id)-3d %(state)-5d %(usb-ver)-7s %(be-path)-30s " % ni
-
- ports = sxp.child(x[1], 'port')
- for port in ports[1:]:
- try:
- num, bus = port
- if bus != "" and vusb_util.usb_device_is_connected(bus):
- idvendor = vusb_util.get_usb_idvendor(bus)
- idproduct = vusb_util.get_usb_idproduct(bus)
- prodinfo = vusb_util.get_usbdevice_info(bus)
- print "port %i: %s [ID %-4s:%-4s %s]" \
- % (int(num), str(bus), idvendor, idproduct, prodinfo)
- else:
- print "port %i: " % int(num) + str(bus)
- except TypeError:
- pass
-
-def xm_usb_list_assignable_devices(args):
- xenapi_unsupported()
- arg_check(args, 'usb-list-assignable-devices', 0)
-
- usb_devs = vusb_util.get_usb_devices()
- buses = vusb_util.get_assigned_buses()
-
- for x in buses:
- try:
- usb_devs.remove(x)
- except ValueError:
- pass
-
- for dev in usb_devs:
- idvendor = vusb_util.get_usb_idvendor(dev)
- idproduct = vusb_util.get_usb_idproduct(dev)
- prodinfo = vusb_util.get_usbdevice_info(dev)
- print "%-13s: ID %-4s:%-4s %s" \
- % (dev, idvendor, idproduct, prodinfo)
-
-def parse_block_configuration(args):
- dom = args[0]
-
- if args[1].startswith('tap2:'):
- cls = 'tap2'
- elif args[1].startswith('tap:'):
- cls = 'tap'
- else:
- cls = 'vbd'
-
- vbd = [cls,
- ['uname', args[1]],
- ['dev', args[2]],
- ['mode', args[3]]]
- if len(args) == 5:
- vbd.append(['backend', args[4]])
-
- return (dom, vbd)
-
-
-def xm_block_attach(args):
- arg_check(args, 'block-attach', 4, 5)
-
- if serverType == SERVER_XEN_API:
- dom = args[0]
- uname = args[1]
- dev = args[2]
- mode = args[3]
-
- # First create new VDI
- vdi_record = {
- "name_label": "vdi" + str(uname.__hash__()),
- "name_description": "",
- "SR": get_default_SR(),
- "virtual_size": 0,
- "sector_size": 512,
- "type": "system",
- "sharable": False,
- "read_only": mode!="w",
- "other_config": {"location": uname}
- }
-
- vdi_ref = server.xenapi.VDI.create(vdi_record)
-
- # Now create new VBD
-
- vbd_record = {
- "VM": get_single_vm(dom),
- "VDI": vdi_ref,
- "device": dev,
- "bootable": True,
- "mode": mode=="w" and "RW" or "RO",
- "type": "Disk",
- "qos_algorithm_type": "",
- "qos_algorithm_params": {}
- }
-
- server.xenapi.VBD.create(vbd_record)
-
- else:
- (dom, vbd) = parse_block_configuration(args)
- server.xend.domain.device_create(dom, vbd)
-
-
-def xm_block_configure(args):
- arg_check(args, 'block-configure', 4, 5)
-
- (dom, vbd) = parse_block_configuration(args)
- server.xend.domain.device_configure(dom, vbd)
-
-
-def xm_network2_attach(args):
- xenapi_unsupported()
- arg_check(args, 'network2-attach', 1, 11)
- dom = args[0]
- vif = ['vif2']
- vif_params = ['front_mac', 'back_mac', 'backend', 'trusted',
- 'back_trusted', "front_filter_mac", "filter_mac",
- 'bridge', 'pdev', "max_bypasses" ]
- for a in args[1:]:
- vif_param = a.split("=")
- if len(vif_param) != 2 or vif_param[1] == "" or \
- vif_param[0] not in vif_params:
- err("Invalid argument: %s" % a)
- usage("network2-attach")
- vif.append(vif_param)
- server.xend.domain.device_create(dom, vif)
-
-def xm_network2_detach(args):
- xenapi_unsupported()
- arg_check(args, "network2-detach", 2, 3)
- detach(args, "vif2")
-
-def xm_network2_list(args):
- xenapi_unsupported()
- (use_long, params) = arg_check_for_resource_list(args, "network2-list")
- dom = params[0]
- devs = server.xend.domain.getDeviceSxprs(dom, 'vif2')
- map(PrettyPrint.prettyprint, devs)
-
-def xm_network_attach(args):
- arg_check(args, 'network-attach', 1, 11)
-
- dom = args[0]
- vif = ['vif']
- vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
- 'backend', 'vifname', 'rate', 'model', 'accel']
-
- if serverType == SERVER_XEN_API:
- vif_record = {
- "device": "eth0",
- "network": get_default_Network(),
- "VM": get_single_vm(dom),
- "MAC": "",
- "MTU": "",
- "qos_algorithm_type": "",
- "qos_algorithm_params": {},
- "other_config": {}
- }
-
- def set(keys, val):
- record = vif_record
- for key in keys[:-1]:
- record = record[key]
- record[keys[-1]] = val
-
- def get_net_from_bridge(bridge):
- # In OSS, we just assert network.name_label == bridge name
- networks = dict([(record['name_label'], ref)
- for ref, record in server.xenapi.network
- .get_all_records().items()])
- if bridge not in networks.keys():
- raise ValueError("Unknown bridge name!")
- return networks[bridge]
-
- vif_conv = {
- 'type':
- lambda x: None,
- 'mac':
- lambda x: set(['MAC'], x),
- 'bridge':
- lambda x: set(['network'], get_net_from_bridge(x)),
- 'ip':
- lambda x: set(['other_config', 'ip'], x),
- 'script':
- lambda x: set(['other_config', 'script'], x),
- 'backend':
- lambda x: set(['other_config', 'backend'], x),
- 'vifname':
- lambda x: set(['device'], x),
- 'rate':
- lambda x: set(['qos_algorithm_params', 'rate'], x),
- 'model':
- lambda x: None,
- 'accel':
- lambda x: set(['other_config', 'accel'], x)
- }
-
- for a in args[1:]:
- vif_param = a.split("=")
- if len(vif_param) != 2 or vif_param[1] == '' or \
- vif_param[0] not in vif_params:
- err("Invalid argument: %s" % a)
- usage('network-attach')
- else:
- vif_conv[vif_param[0]](vif_param[1])
-
- server.xenapi.VIF.create(vif_record)
- else:
- for a in args[1:]:
- vif_param = a.split("=")
- if len(vif_param) != 2 or vif_param[1] == '' or \
- vif_param[0] not in vif_params:
- err("Invalid argument: %s" % a)
- usage('network-attach')
- vif.append(vif_param)
- server.xend.domain.device_create(dom, vif)
-
-def parse_pci_configuration(args, opts = ''):
- dom = args[0]
- pci_dev_str = args[1]
- if len(args) == 3:
- pci_dev_str += '@' + args[2]
- if len(opts) > 0:
- pci_dev_str += ',' + serialise_pci_opts(opts)
-
- try:
- pci_dev = parse_pci_name_extended(pci_dev_str)
- except PciDeviceParseError, ex:
- raise OptionError(str(ex))
-
- return (dom, pci_dev)
-
-def xm_pci_attach(args):
- config_pci_opts = []
- (options, params) = getopt.gnu_getopt(args, 'o:', ['options='])
- for (k, v) in options:
- if k in ('-o', '--options'):
- if len(v.split('=')) != 2:
- err("Invalid pci attach option: %s" % v)
- usage('pci-attach')
- config_pci_opts.append(v.split('='))
-
- n = len([i for i in params if i != '--'])
- if n < 2 or n > 3:
- err("Invalid argument for 'xm pci-attach'")
- usage('pci-attach')
-
- (dom, dev) = parse_pci_configuration(params, config_pci_opts)
-
- attached = attached_pci_dict(dom)
-
- attached_dev = map(lambda x: find_attached(attached, x, False), dev)
-
- head_dev = dev.pop(0)
- xm_pci_attach_one(dom, head_dev)
-
- # That is all for single-function virtual devices
- if len(dev) == 0:
- return
-
- # If the slot wasn't spefified in the args then use the slot
- # assigned to the head by qemu-xen for the rest of the functions
- if int(head_dev['vdevfn'], 16) & AUTO_PHP_SLOT:
- vdevfn = int(find_attached_devfn(attached_pci_dict(dom), head_dev), 16)
- if not vdevfn & AUTO_PHP_SLOT:
- vslot = PCI_SLOT(vdevfn)
- for i in dev:
- i['vdevfn'] = '0x%02x' % \
- PCI_DEVFN(vslot, PCI_FUNC(int(i['vdevfn'], 16)))
-
- for i in dev:
- xm_pci_attach_one(dom, i)
-
-def xm_pci_attach_one(dom, pci_dev):
- if serverType == SERVER_XEN_API:
- name = pci_dict_to_bdf_str(pci_dev)
- 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": int(pci_dev['vdevfn'], 16),
- "options": dict(pci_dev.get('opts', [])),
- "key": pci_dev['key']
- }
- server.xenapi.DPCI.create(dpci_record)
-
- else:
- pci = pci_convert_dict_to_sxp(pci_dev, 'Initialising')
- server.xend.domain.device_configure(dom, pci)
-
-def parse_scsi_configuration(p_scsi, v_hctl, state):
- def get_devid(hctl):
- return int(hctl.split(':')[0])
-
- host_mode = 0
- scsi_devices = None
-
- if p_scsi is not None:
- # xm scsi-attach
- if v_hctl == "host":
- host_mode = 1
- scsi_devices = vscsi_util.vscsi_get_scsidevices()
- elif len(v_hctl.split(':')) != 4:
- raise OptionError("Invalid argument: %s" % v_hctl)
- (p_hctl, devname) = \
- vscsi_util.vscsi_get_hctl_and_devname_by(p_scsi, scsi_devices)
- if p_hctl is None:
- raise OptionError("Cannot find device '%s'" % p_scsi)
- if host_mode:
- scsi_info = []
- devid = get_devid(p_hctl)
- for pHCTL, devname, _, _ in scsi_devices:
- if get_devid(pHCTL) == devid:
- scsi_info.append([devid, pHCTL, devname, pHCTL])
- else:
- scsi_info = [[get_devid(v_hctl), p_hctl, devname, v_hctl]]
- else:
- # xm scsi-detach
- if len(v_hctl.split(':')) != 4:
- raise OptionError("Invalid argument: %s" % v_hctl)
- scsi_info = [[get_devid(v_hctl), None, None, v_hctl]]
-
- scsi = ['vscsi', ['feature-host', host_mode]]
- for devid, pHCTL, devname, vHCTL in scsi_info:
- scsi.append(['dev', \
- ['state', state], \
- ['devid', devid], \
- ['p-dev', pHCTL], \
- ['p-devname', devname], \
- ['v-dev', vHCTL] \
- ])
- return scsi
-
-def xm_scsi_attach(args):
- arg_check(args, 'scsi-attach', 3, 4)
- dom = args[0]
- p_scsi = args[1]
- v_hctl = args[2]
- scsi = parse_scsi_configuration(p_scsi, v_hctl, xenbusState['Initialising'])
-
- if serverType == SERVER_XEN_API:
-
- scsi_dev = sxp.children(scsi, 'dev')[0]
-
- if sxp.child_value(scsi, 'feature-host'):
- p_host = sxp.child_value(scsi_dev, 'devid')
- target_ref = None
- for pscsi_ref in server.xenapi.PSCSI_HBA.get_all():
- if p_host == int(server.xenapi.PSCSI_HBA.get_physical_host(pscsi_ref)):
- target_ref = pscsi_ref
- break
- if target_ref is None:
- raise OptionError("Cannot find device '%s'" % p_scsi)
-
- dscsi_record = {
- "VM": get_single_vm(dom),
- "PSCSI_HBA": target_ref,
- "assignment_mode": "HOST"
- }
- server.xenapi.DSCSI_HBA.create(dscsi_record)
- else:
- p_hctl = sxp.child_value(scsi_dev, 'p-dev')
- target_ref = None
- for pscsi_ref in server.xenapi.PSCSI.get_all():
- if p_hctl == server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
- target_ref = pscsi_ref
- break
- if target_ref is None:
- raise OptionError("Cannot find device '%s'" % p_scsi)
-
- dscsi_record = {
- "VM": get_single_vm(dom),
- "PSCSI": target_ref,
- "virtual_HCTL": v_hctl
- }
- server.xenapi.DSCSI.create(dscsi_record)
-
- else:
- if len(args) == 4:
- scsi.append(['backend', args[3]])
- server.xend.domain.device_configure(dom, scsi)
-
-def xm_usb_attach(args):
- xenapi_unsupported()
- arg_check(args, 'usb-attach', 4)
- dom = args[0]
- dev = args[1]
- port = args[2]
- bus = args[3]
-
- dev_exist = 0
- num_ports = 0
- devs = server.xend.domain.getDeviceSxprs(dom, 'vusb')
- for x in devs:
- if int(x[0]) == int(dev):
- dev_exist = 1
- num_ports = sxp.child_value(x[1], 'num-ports')
-
- if dev_exist == 0:
- print "Cannot find device '%s' in domain '%s'" % (dev,dom)
- return False
-
- if int(port) < 1 or int(port) > int(num_ports):
- print "Invalid Port Number '%s'" % port
- return False
-
- bus_match = re.match(r"(^(?P<bus>[0-9]{1,2})[-,])" + \
- r"(?P<root_port>[0-9]{1,2})" + \
- r"(?P<port>([\.,]{1}[0-9]{1,2}){0,5})$", bus)
- if bus_match is None:
- print "Invalid Busid '%s'" % bus
- return False
-
- if vusb_util.bus_is_assigned(bus):
- print "Cannot assign already attached bus '%s', detach first." % bus
- return False
-
- prev_bus = vusb_util.get_assigned_bus(domain_name_to_domid(dom), dev, port)
- if not prev_bus == "":
- print "Cannot override already attached port '%s', detach first." % port
- return False
-
- usb = ['vusb', ['port', [port, str(bus)]]]
- server.xend.domain.device_configure(dom, usb, dev)
-
-def xm_usb_hc_create(args):
- xenapi_unsupported()
- arg_check(args, 'usb-hc-create', 3)
- dom = args[0]
- ver = args[1]
- num = args[2]
- vusb_config = ['vusb']
- vusb_config.append(['usb-ver', str(ver)])
- vusb_config.append(['num-ports', str(num)])
- port_config = ['port']
- for i in range(1, int(num) + 1):
- port_config.append(['%i' % i, ""])
- vusb_config.append(port_config)
- server.xend.domain.device_create(dom, vusb_config)
-
-def detach(args, deviceClass):
- rm_cfg = True
- dom = args[0]
- dev = args[1]
- try:
- force = args[2]
- if (force != "--force") and (force != "-f"):
- print "Ignoring option %s"%(force)
- force = None
- except IndexError:
- force = None
-
- server.xend.domain.destroyDevice(dom, deviceClass, dev, force, rm_cfg)
-
-
-def xm_block_detach(args):
- if serverType == SERVER_XEN_API:
- arg_check(args, "block-detach", 2, 3)
- dom = args[0]
- dev = args[1]
- vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
- vbd_refs = [vbd_ref for vbd_ref in vbd_refs
- if server.xenapi.VBD.get_device(vbd_ref) == dev]
- if len(vbd_refs) > 0:
- vbd_ref = vbd_refs[0]
- vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
-
- server.xenapi.VBD.destroy(vbd_ref)
-
- if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
- server.xenapi.VDI.destroy(vdi_ref)
- else:
- raise OptionError("Cannot find device '%s' in domain '%s'"
- % (dev,dom))
- else:
- arg_check(args, 'block-detach', 2, 3)
- dom = args[0]
- dev = args[1]
- dc = server.xend.domain.getBlockDeviceClass(dom, dev)
- if dc == "tap2":
- detach(args, 'tap2')
- elif dc == "tap":
- detach(args, 'tap')
- else:
- detach(args, 'vbd')
-
-def xm_network_detach(args):
- arg_check(args, "network-detach", 2, 3)
- dom = args[0]
- devid = args[1]
- if serverType == SERVER_XEN_API:
- vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
- if len(devid.split(":")) == 6:
- mac = devid.lower()
- vif_refs = [vif_ref for vif_ref in vif_refs
- if server.xenapi.VIF.\
- get_record(vif_ref)["MAC"].lower() == mac]
- else:
- vif_refs = [vif_ref for vif_ref in vif_refs
- if server.xenapi.VIF.\
- get_runtime_properties(vif_ref)["handle"] == devid]
-
- if len(vif_refs) > 0:
- vif_ref = vif_refs[0]
-
- server.xenapi.VIF.destroy(vif_ref)
- else:
- raise OptionError("Cannot find device '%s' in domain '%s'" % (devid, dom))
- else:
- if len(devid.split(":")) == 6:
- mac = devid.lower()
- vifs = server.xend.domain.getDeviceSxprs(dom, "vif")
- devids = [vif[0] for vif in vifs
- if parse_dev_info(vif[1])["mac"].lower() == mac]
- if len(devids) > 0:
- devid = str(devids[0])
- else:
- raise OptionError("Cannot find device '%s' in domain '%s'" % (devid, dom))
-
- vif_args = [dom, devid]
- try:
- vif_args.append(args[2])
- except IndexError:
- pass
- detach(vif_args, 'vif')
-
-def find_attached(attached, key, detaching):
- l = filter(lambda dev: pci_dict_cmp(dev, key), attached)
-
- if detaching:
- if len(l) == 0:
- raise OptionError("pci: device %s is not attached!" %\
- pci_dict_to_bdf_str(key))
- # There shouldn't ever be more than one match,
- # but perhaps an exception should be thrown if there is
- return l[0]
- else:
- if len(l) == 1:
- raise OptionError("pci: device %s has been attached! " %\
- pci_dict_to_bdf_str(key))
- return None
-
-def find_attached_devfn(attached, key):
- pci_dev = find_attached(attached, key, True)
- return pci_dev['vdevfn']
-
-def xm_pci_detach(args):
- arg_check(args, 'pci-detach', 2)
-
- (dom, dev) = parse_pci_configuration(args)
- attached = attached_pci_dict(dom)
-
- attached_dev = map(lambda x: find_attached(attached, x, True), dev)
-
- def f(pci_dev):
- vdevfn = int(pci_dev['vdevfn'], 16)
- return PCI_SLOT(vdevfn) | (vdevfn & AUTO_PHP_SLOT)
- vdevfns = map(f, attached_dev)
- if len(set(vdevfns)) > 1:
- err_str = map(lambda x: "\t%s is in slot 0x%02x\n" %
- (pci_dict_to_bdf_str(x),
- PCI_SLOT(int(x['vdevfn'], 16))), dev)
- raise OptionError("More than one slot used by specified devices\n"
- + ''.join(err_str))
-
- attached_to_slot = filter(lambda x:
- f(x) == vdevfns[0] and
- attached_dev[0]["key"] ==
- x["key"], attached_dev)
-
- if len(attached_to_slot) != len(dev):
- err_str_ = map(lambda x: '\t%s\n' % pci_dict_to_bdf_str(x), dev)
- err_str = "Requested:\n" + ''.join(err_str_)
- err_str_ = map(lambda x: '\t%s (%s)\n' %
- (pci_dict_to_bdf_str(x), x['key']),
- attached_to_slot)
- err_str += "Present:\n" + ''.join(err_str_)
- raise OptionError(("Not all functions in slot 0x%02x have had "
- "detachment requested.\n" % vdevfns[0]) + err_str)
-
- for i in dev:
- xm_pci_detach_one(dom, i)
-
-def xm_pci_detach_one(dom, pci_dev):
- if serverType == SERVER_XEN_API:
- name = pci_dict_to_bdf_str(pci_dev)
- 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:
- pci = pci_convert_dict_to_sxp(pci_dev, 'Closing')
- server.xend.domain.device_configure(dom, pci)
-
-def xm_scsi_detach(args):
- arg_check(args, 'scsi-detach', 2)
- dom = args[0]
- v_hctl = args[1]
- scsi = parse_scsi_configuration(None, v_hctl, xenbusState['Closing'])
-
- if serverType == SERVER_XEN_API:
-
- target_ref = None
- for dscsi_ref in server.xenapi.VM.get_DSCSIs(get_single_vm(dom)):
- if v_hctl == server.xenapi.DSCSI.get_virtual_HCTL(dscsi_ref):
- target_ref = dscsi_ref
- break
- if target_ref is None:
- raise OptionError("Device %s not assigned" % v_hctl)
-
- target_HBA_ref = server.xenapi.DSCSI.get_HBA(target_ref)
- if server.xenapi.DSCSI_HBA.get_assignment_mode(target_HBA_ref) == "HOST":
- server.xenapi.DSCSI_HBA.destroy(target_HBA_ref)
- else:
- server.xenapi.DSCSI.destroy(target_ref)
-
- else:
- server.xend.domain.device_configure(dom, scsi)
-
-def xm_usb_detach(args):
- xenapi_unsupported()
- arg_check(args, 'usb-detach', 3)
- dom = args[0]
- dev = args[1]
- port = args[2]
- usb = ['vusb', ['port', [port, '']]]
- server.xend.domain.device_configure(dom, usb, dev)
-
-def xm_usb_hc_destroy(args):
- xenapi_unsupported()
- arg_check(args, 'usb-hc-destroy', 2)
- dom = args[0]
- dev = args[1]
- server.xend.domain.destroyDevice(dom, 'vusb', dev)
-
-def xm_vnet_list(args):
- xenapi_unsupported()
- try:
- (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('vnet-list')
-
- use_long = 0
- for (k, v) in options:
- if k in ['-l', '--long']:
- use_long = 1
-
- if params:
- use_long = 1
- vnets = params
- else:
- vnets = server.xend_vnets()
-
- for vnet in vnets:
- try:
- if use_long:
- info = server.xend_vnet(vnet)
- PrettyPrint.prettyprint(info)
- else:
- print vnet
- except Exception, ex:
- print vnet, ex
-
-def xm_vnet_create(args):
- xenapi_unsupported()
- arg_check(args, "vnet-create", 1)
- conf = args[0]
- if not os.access(conf, os.R_OK):
- print "File not found: %s" % conf
- sys.exit(1)
-
- server.xend_vnet_create(conf)
-
-def xm_vnet_delete(args):
- xenapi_unsupported()
- arg_check(args, "vnet-delete", 1)
- vnet = args[0]
- server.xend_vnet_delete(vnet)
-
-def xm_network_new(args):
- xenapi_only()
- arg_check(args, "network-new", 1)
- network = args[0]
-
- record = {
- "name_label": network,
- "name_description": "",
- "other_config": {},
- "default_gateway": "",
- "default_netmask": ""
- }
-
- server.xenapi.network.create(record)
-
-def xm_network_del(args):
- xenapi_only()
- arg_check(args, "network-del", 1)
- network = args[0]
-
- networks = dict([(record['name_label'], ref)
- for ref, record in
- server.xenapi.network.get_all_records().items()])
-
- if network not in networks.keys():
- raise ValueError("'%s' is not a valid network name" % network)
-
- server.xenapi.network.destroy(networks[network])
-
-def xm_network_show(args):
- xenapi_only()
- arg_check(args, "network-show", 0)
-
- networks = server.xenapi.network.get_all_records()
- pifs = server.xenapi.PIF.get_all_records()
- vifs = server.xenapi.VIF.get_all_records()
-
- print '%-20s %-40s %-10s' % \
- ('Name', 'VIFs', 'PIFs')
-
- format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s"
-
- for network_ref, network in networks.items():
- for i in range(max(len(network['PIFs']),
- len(network['VIFs']), 1)):
- if i < len(network['PIFs']):
- pif_uuid = network['PIFs'][i]
- else:
- pif_uuid = None
-
- if i < len(network['VIFs']):
- vif_uuid = network['VIFs'][i]
- else:
- vif_uuid = None
-
- pif = pifs.get(pif_uuid, None)
- vif = vifs.get(vif_uuid, None)
-
- if vif:
- dom_name = server.xenapi.VM.get_name_label(vif['VM'])
- vif = "%s.%s" % (dom_name, vif['device'])
- else:
- vif = ''
-
- if pif:
- if int(pif['VLAN']) > -1:
- pif = '%s.%s' % (pif['device'], pif['VLAN'])
- else:
- pif = pif['device']
- else:
- pif = ''
-
- if i == 0:
- r = {'name_label':network['name_label'],
- 'vif':vif, 'pif':pif}
- else:
- r = {'name_label':'', 'vif':vif, 'pif':pif}
-
- print format2 % r
-
-def xm_tmem_list(args):
- try:
- (options, params) = getopt.gnu_getopt(args, 'la', ['long','all'])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('tmem-list')
-
- use_long = False
- for (k, v) in options:
- if k in ['-l', '--long']:
- use_long = True
-
- all = False
- for (k, v) in options:
- if k in ['-a', '--all']:
- all = True
-
- if not all and len(params) == 0:
- err('You must specify -a or --all or a domain id.')
- usage('tmem-list')
-
- if all:
- domid = -1
- else:
- try:
- domid = int(params[0])
- params = params[1:]
- except:
- err('Unrecognized domain id: %s' % params[0])
- usage('tmem-list')
-
- if serverType == SERVER_XEN_API:
- print server.xenapi.host.tmem_list(domid,use_long)
- else:
- print server.xend.node.tmem_list(domid,use_long)
-
-def parse_tmem_args(args, name):
- try:
- (options, params) = getopt.gnu_getopt(args, 'a', ['all'])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage(name)
-
- all = False
- for (k, v) in options:
- if k in ['-a', '--all']:
- all = True
-
- if not all and len(params) == 0:
- err('You must specify -a or --all or a domain id.')
- usage(name)
-
- if all:
- domid = -1
- else:
- try:
- domid = int(params[0])
- params = params[1:]
- except:
- err('Unrecognized domain id: %s' % params[0])
- usage(name)
-
- return domid, params
-
-def xm_tmem_destroy(args):
- (domid, _) = parse_tmem_args(args, 'tmem-destroy')
- if serverType == SERVER_XEN_API:
- server.xenapi.host.tmem_destroy(domid)
- else:
- server.xend.node.tmem_destroy(domid)
-
-def xm_tmem_thaw(args):
- (domid, _) = parse_tmem_args(args, 'tmem-thaw')
- if serverType == SERVER_XEN_API:
- server.xenapi.host.tmem_thaw(domid)
- else:
- server.xend.node.tmem_thaw(domid)
-
-def xm_tmem_freeze(args):
- (domid, _) = parse_tmem_args(args, 'tmem-freeze')
- if serverType == SERVER_XEN_API:
- server.xenapi.host.tmem_freeze(domid)
- else:
- server.xend.node.tmem_freeze(domid)
-
-def xm_tmem_flush(args):
- try:
- (options, params) = getopt.gnu_getopt(args, 'a', ['all'])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage(name)
-
- all = False
- for (k, v) in options:
- if k in ['-a', '--all']:
- all = True
-
- if not all and len(params) == 0:
- err('You must specify -a or --all or a domain id.')
- usage('tmem-flush')
-
- if all:
- domid = -1
- else:
- try:
- domid = int(params[0])
- params = params[1:]
- except:
- err('Unrecognized domain id: %s' % params[0])
- usage('tmem-flush')
-
- pages = -1
- for (k, v) in options:
- if k in ['-p', '--pages']:
- pages = v
-
- if serverType == SERVER_XEN_API:
- server.xenapi.host.tmem_flush(domid,pages)
- else:
- server.xend.node.tmem_flush(domid,pages)
-
-def xm_tmem_set(args):
- try:
- (options, params) = getopt.gnu_getopt(args, 'a', ['all'])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage(name)
-
- all = False
- for (k, v) in options:
- if k in ['-a', '--all']:
- all = True
-
- if not all and len(params) == 0:
- err('You must specify -a or --all or a domain id.')
- usage('tmem-set')
-
- if all:
- domid = -1
- else:
- try:
- domid = int(params[0])
- params = params[1:]
- except:
- err('Unrecognized domain id: %s' % params[0])
- usage('tmem-set')
-
- weight = None
- cap = None
- compress = None
- for item in params:
- if item.startswith('weight='):
- try:
- weight = int(item[7:])
- except:
- err('weight should be a integer')
- usage('tmem-set')
- if item.startswith('cap='):
- cap = int(item[4:])
- if item.startswith('compress='):
- compress = int(item[9:])
-
- if weight is None and cap is None and compress is None:
- err('Unrecognized tmem configuration option: %s' % item)
- usage('tmem-set')
-
- if serverType == SERVER_XEN_API:
- if weight is not None:
- server.xenapi.host.tmem_set_weight(domid, weight)
- if cap is not None:
- server.xenapi.host.tmem_set_cap(domid, cap)
- if compress is not None:
- server.xenapi.host.tmem_set_compress(domid, compress)
- else:
- if weight is not None:
- server.xend.node.tmem_set_weight(domid, weight)
- if cap is not None:
- server.xend.node.tmem_set_cap(domid, cap)
- if compress is not None:
- server.xend.node.tmem_set_compress(domid, compress)
-
-def xm_tmem_freeable_mb(args):
- if serverType == SERVER_XEN_API:
- print server.xenapi.host.tmem_query_freeable_mb()
- else:
- print server.xend.node.tmem_query_freeable_mb()
-
-def xm_tmem_shared_auth(args):
- try:
- (options, params) = getopt.gnu_getopt(args, 'au:A:', ['all','uuid=','auth='])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('tmem-shared-auth')
-
- all = False
- for (k, v) in options:
- if k in ['-a', '--all']:
- all = True
-
- if not all and len(params) == 0:
- err('You must specify -a or --all or a domain id.')
- usage('tmem-shared-auth')
-
- if all:
- domid = -1
- else:
- try:
- domid = int(params[0])
- params = params[1:]
- except:
- err('Unrecognized domain id: %s' % params[0])
- usage('tmem-shared-auth')
-
- for (k, v) in options:
- if k in ['-u', '--uuid']:
- uuid_str = v
-
- auth = 0
- for (k, v) in options:
- if k in ['-A', '--auth']:
- auth = v
-
- if serverType == SERVER_XEN_API:
- return server.xenapi.host.tmem_shared_auth(domid,uuid_str,auth)
- else:
- return server.xend.node.tmem_shared_auth(domid,uuid_str,auth)
-
-def get_cpupool_ref(name):
- refs = server.xenapi.cpu_pool.get_by_name_label(name)
- if len(refs) > 0:
- return refs[0]
- else:
- err('unknown pool name')
- sys.exit(1)
-
-def xm_cpupool_start(args):
- arg_check(args, "cpupool-start", 1)
- if serverType == SERVER_XEN_API:
- ref = get_cpupool_ref(args[0])
- server.xenapi.cpu_pool.activate(ref)
- else:
- server.xend.cpu_pool.start(args[0])
-
-def brief_cpupool_list(sxprs):
- format_str = "%-16s %3s %8s %s %s"
- for sxpr in sxprs:
- if sxpr == sxprs[0]:
- print "Name CPUs Sched Active Domain count"
- record = sxp2map(sxpr)
- name = record['name_label']
- sched_policy = record['sched_policy']
- if record['activated']:
- cpus = record.get('host_CPU_numbers', [])
- vms = record.get('started_VM_names', [])
- if not isinstance(cpus, types.ListType):
- cpus = [cpus]
- if not isinstance(vms, types.ListType):
- vms = [vms]
- cpu_count = len(cpus)
- vm_count = len(vms)
- active = 'y'
- else:
- cpu_count = record['ncpu']
- vm_count = 0
- active = 'n'
- print format_str % (name, cpu_count, sched_policy, active, vm_count)
-
-def brief_cpupool_list_cpus(sxprs):
- format_str = "%-16s %s"
- for sxpr in sxprs:
- if sxpr == sxprs[0]:
- print format_str % ("Name", "CPU list")
- record = sxp2map(sxpr)
- name = record['name_label']
- cpus = ""
- if record['activated']:
- cpus = record.get('host_CPU_numbers', [])
- if isinstance(cpus, types.ListType):
- cpus.sort()
- cpus = reduce(lambda x,y: x + "%s," % y, cpus, "")
- cpus = cpus[0:len(cpus)-1]
- else:
- cpus = str(cpus)
- if len(cpus) == 0:
- cpus = "-"
- print format_str % (name, cpus)
-
-def xm_cpupool_list(args):
- arg_check(args, "cpupool-list", 0, 2)
- try:
- (options, params) = getopt.gnu_getopt(args, 'lc', ['long','cpus'])
- except getopt.GetoptError, opterr:
- err(opterr)
- usage('cpupool-list')
- if len(params) > 1:
- err("Only one cpupool name for selection allowed")
- usage('cpupool-list')
-
- use_long = False
- show_cpus = False
- for (k, _) in options:
- if k in ['-l', '--long']:
- use_long = True
- if k in ['-c', '--cpus']:
- show_cpus = True
-
- if serverType == SERVER_XEN_API:
- pools = server.xenapi.cpu_pool.get_all_records()
- cpu_recs = server.xenapi.host_cpu.get_all_records()
- sxprs = []
- for pool in pools.values():
- if pool['name_label'] in params or len(params) == 0:
- started_VM_names = [['started_VM_names'] + [
- server.xenapi.VM.get_name_label(started_VM)
- for started_VM in pool['started_VMs'] ] ]
- host_CPU_numbers = [['host_CPU_numbers'] + [
- cpu_recs[cpu_ref]['number']
- for cpu_ref in pool['host_CPUs'] ] ]
- sxpr = [ pool['uuid'] ] + map_to_sxp(pool) + \
- host_CPU_numbers + started_VM_names
- sxprs.append(sxpr)
- else:
- sxprs = server.xend.cpu_pool.list(params)
-
- if len(params) > 0 and len(sxprs) == 0:
- # pool not found
- err("Pool '%s' does not exist." % params[0])
-
- if use_long:
- for sxpr in sxprs:
- PrettyPrint.prettyprint(sxpr)
- elif show_cpus:
- brief_cpupool_list_cpus(sxprs)
- else:
- brief_cpupool_list(sxprs)
-
-def xm_cpupool_destroy(args):
- arg_check(args, "cpupool-destroy", 1)
- if serverType == SERVER_XEN_API:
- ref = get_cpupool_ref(args[0])
- server.xenapi.cpu_pool.deactivate(ref)
- else:
- server.xend.cpu_pool.destroy(args[0])
-
-def xm_cpupool_delete(args):
- arg_check(args, "cpupool-delete", 1)
- if serverType == SERVER_XEN_API:
- ref = get_cpupool_ref(args[0])
- server.xenapi.cpu_pool.destroy(ref)
- else:
- server.xend.cpu_pool.delete(args[0])
-
-def xm_cpupool_cpu_add(args):
- arg_check(args, "cpupool-cpu-add", 2)
- if serverType == SERVER_XEN_API:
- ref = get_cpupool_ref(args[0])
- cpu_ref_list = server.xenapi.host_cpu.get_all_records()
- cpu_ref = [ c_rec['uuid'] for c_rec in cpu_ref_list.values()
- if c_rec['number'] == args[1] ]
- if len(cpu_ref) == 0:
- err('cpu number unknown')
- else:
- server.xenapi.cpu_pool.add_host_CPU_live(ref, cpu_ref[0])
- else:
- server.xend.cpu_pool.cpu_add(args[0], args[1])
-
-def xm_cpupool_cpu_remove(args):
- arg_check(args, "cpupool-cpu-remove", 2)
- if serverType == SERVER_XEN_API:
- ref = get_cpupool_ref(args[0])
- cpu_ref_list = server.xenapi.host_cpu.get_all_records()
- cpu_ref = [ c_rec['uuid'] for c_rec in cpu_ref_list.values()
- if c_rec['number'] == args[1] ]
- if len(cpu_ref) == 0:
- err('cpu number unknown')
- else:
- server.xenapi.cpu_pool.remove_host_CPU_live(ref, cpu_ref[0])
- else:
- server.xend.cpu_pool.cpu_remove(args[0], args[1])
-
-def xm_cpupool_migrate(args):
- arg_check(args, "cpupool-migrate", 2)
- domname = args[0]
- poolname = args[1]
- if serverType == SERVER_XEN_API:
- pool_ref = get_cpupool_ref(poolname)
- server.xenapi.VM.cpu_pool_migrate(get_single_vm(domname), pool_ref)
- else:
- server.xend.cpu_pool.migrate(domname, poolname)
-
-
-commands = {
- "shell": xm_shell,
- "event-monitor": xm_event_monitor,
- # console commands
- "console": xm_console,
- "vncviewer": xm_vncviewer,
- # xenstat commands
- "top": xm_top,
- # domain commands
- "delete": xm_delete,
- "destroy": xm_destroy,
- "domid": xm_domid,
- "domname": xm_domname,
- "dump-core": xm_dump_core,
- "reboot": xm_reboot,
- "rename": xm_rename,
- "reset": xm_reset,
- "restore": xm_restore,
- "resume": xm_resume,
- "save": xm_save,
- "shutdown": xm_shutdown,
- "start": xm_start,
- "sysrq": xm_sysrq,
- "trigger": xm_trigger,
- "uptime": xm_uptime,
- "suspend": xm_suspend,
- "list": xm_list,
- # memory commands
- "mem-max": xm_mem_max,
- "mem-set": xm_mem_set,
- # cpu commands
- "vcpu-pin": xm_vcpu_pin,
- "vcpu-list": xm_vcpu_list,
- "vcpu-set": xm_vcpu_set,
- # special
- "pause": xm_pause,
- "unpause": xm_unpause,
- # host commands
- "debug-keys": xm_debug_keys,
- "dmesg": xm_dmesg,
- "info": xm_info,
- "log": xm_log,
- "serve": xm_serve,
- # scheduler
- "sched-sedf": xm_sched_sedf,
- "sched-credit": xm_sched_credit,
- "sched-credit2": xm_sched_credit2,
- # block
- "block-attach": xm_block_attach,
- "block-detach": xm_block_detach,
- "block-list": xm_block_list,
- "block-configure": xm_block_configure,
- # network (AKA vifs)
- "network-attach": xm_network_attach,
- "network-detach": xm_network_detach,
- "network-list": xm_network_list,
- "network2-attach": xm_network2_attach,
- "network2-detach": xm_network2_detach,
- "network2-list": xm_network2_list,
- # network (as in XenAPI)
- "network-new": xm_network_new,
- "network-del": xm_network_del,
- "network-show": xm_network_show,
- # vnet
- "vnet-list": xm_vnet_list,
- "vnet-create": xm_vnet_create,
- "vnet-delete": xm_vnet_delete,
- #pci
- "pci-attach": xm_pci_attach,
- "pci-detach": xm_pci_detach,
- "pci-list": xm_pci_list,
- "pci-list-assignable-devices": xm_pci_list_assignable_devices,
- # vscsi
- "scsi-attach": xm_scsi_attach,
- "scsi-detach": xm_scsi_detach,
- "scsi-list": xm_scsi_list,
- # vusb
- "usb-attach": xm_usb_attach,
- "usb-detach": xm_usb_detach,
- "usb-list": xm_usb_list,
- "usb-list-assignable-devices": xm_usb_list_assignable_devices,
- "usb-hc-create": xm_usb_hc_create,
- "usb-hc-destroy": xm_usb_hc_destroy,
- # cpupool
- "cpupool-start": xm_cpupool_start,
- "cpupool-list": xm_cpupool_list,
- "cpupool-destroy": xm_cpupool_destroy,
- "cpupool-delete": xm_cpupool_delete,
- "cpupool-cpu-add": xm_cpupool_cpu_add,
- "cpupool-cpu-remove": xm_cpupool_cpu_remove,
- "cpupool-migrate": xm_cpupool_migrate,
- # tmem
- "tmem-thaw": xm_tmem_thaw,
- "tmem-freeze": xm_tmem_freeze,
- "tmem-flush": xm_tmem_flush,
- "tmem-destroy": xm_tmem_destroy,
- "tmem-list": xm_tmem_list,
- "tmem-set": xm_tmem_set,
- "tmem-freeable": xm_tmem_freeable_mb,
- "tmem-shared-auth": xm_tmem_shared_auth,
- #usb
- "usb-add": xm_usb_add,
- "usb-del": xm_usb_del,
- #domstate
- "domstate": xm_domstate,
- }
-
-## The commands supported by a separate argument parser in xend.xm.
-IMPORTED_COMMANDS = [
- 'create',
- 'new',
- 'migrate',
- 'labels',
- 'dumppolicy',
- 'addlabel',
- 'rmlabel',
- 'getlabel',
- 'dry-run',
- 'resources',
- 'getpolicy',
- 'setpolicy',
- 'resetpolicy',
- 'getenforce',
- 'setenforce',
- 'cpupool-create',
- 'cpupool-new',
- ]
-
-for c in IMPORTED_COMMANDS:
- commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
-
-aliases = {
- "balloon": "mem-set",
- "pool-create": "cpupool-create",
- "pool-new": "cpupool-new",
- "pool-start": "cpupool-start",
- "pool-list": "cpupool-list",
- "pool-destroy": "cpupool-destroy",
- "pool-delete": "cpupool-delete",
- "pool-cpu-add": "cpupool-cpu-add",
- "pool-cpu-remove": "cpupool-cpu-remove",
- "pool-migrate": "cpupool-migrate",
- "set-vcpus": "vcpu-set",
- "vif-list": "network-list",
- "vbd-create": "block-attach",
- "vbd-destroy": "block-detach",
- "vbd-list": "block-list",
- }
-
-
-def xm_lookup_cmd(cmd):
- if commands.has_key(cmd):
- return commands[cmd]
- elif aliases.has_key(cmd):
- deprecated(cmd,aliases[cmd])
- return commands[aliases[cmd]]
- elif cmd == 'help':
- longHelp()
- sys.exit(0)
- else:
- # simulate getopt's prefix matching behaviour
- if len(cmd) > 1:
- same_prefix_cmds = [commands[c] for c in commands.keys() \
- if c[:len(cmd)] == cmd]
- # only execute if there is only 1 match
- if len(same_prefix_cmds) == 1:
- return same_prefix_cmds[0]
- return None
-
-def deprecated(old,new):
- print >>sys.stderr, (
- "Command %s is deprecated. Please use xm %s instead." % (old, new))
-
-def main(argv=sys.argv):
- if len(argv) < 2:
- usage()
-
- # intercept --help(-h) and output our own help
- for help in ['--help', '-h']:
- if help in argv[1:]:
- if help == argv[1]:
- longHelp()
- sys.exit(0)
- else:
- usage(argv[1])
-
- cmd_name = argv[1]
- cmd = xm_lookup_cmd(cmd_name)
- if cmd:
- # strip off prog name and subcmd
- args = argv[2:]
- _, rc = _run_cmd(cmd, cmd_name, args)
- sys.exit(rc)
- else:
- err('Subcommand %s not found!' % cmd_name)
- usage()
-
-def _run_cmd(cmd, cmd_name, args):
- global server
-
- try:
- if server is None:
- if serverType == SERVER_XEN_API:
- server = XenAPI.Session(serverURI)
- username, password = parseAuthentication()
- server.login_with_password(username, password)
- def logout():
- try:
- server.xenapi.session.logout()
- except:
- pass
- atexit.register(logout)
- else:
- server = ServerProxy(serverURI)
-
- return True, cmd(args)
- except socket.error, ex:
- if os.geteuid() != 0:
- err("Most commands need root access. Please try again as root.")
- else:
- err("Unable to connect to xend: %s. Is xend running?" % ex[1])
- except KeyboardInterrupt:
- print "Interrupted."
- return True, ''
- except IOError, ex:
- if os.geteuid() != 0:
- err("Most commands need root access. Please try again as root.")
- else:
- err("Unable to connect to xend: %s." % ex[1])
- except SystemExit, code:
- return code == 0, code
- except XenAPI.Failure, exn:
- for line in [''] + wrap(str(exn), 80) + ['']:
- print >>sys.stderr, line
- except xmlrpclib.Fault, ex:
- if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
- err("Domain '%s' does not exist." % ex.faultString)
- return False, ex.faultCode
- else:
- err(ex.faultString)
- _usage(cmd_name)
- except xmlrpclib.ProtocolError, ex:
- if ex.errcode == -1:
- print >>sys.stderr, (
- "Xend has probably crashed! Invalid or missing HTTP "
- "status code.")
- else:
- print >>sys.stderr, (
- "Xend has probably crashed! ProtocolError(%d, %s)." %
- (ex.errcode, ex.errmsg))
- except (ValueError, OverflowError):
- err("Invalid argument.")
- _usage(cmd_name)
- except OptionError, e:
- err(str(e))
- _usage(cmd_name)
- print e.usage
- except XenAPIUnsupportedException, e:
- err(str(e))
- except XSMError, e:
- err(str(e))
- except Exception, e:
- if serverType != SERVER_XEN_API:
- import xen.util.xsm.xsm as security
- if isinstance(e, security.XSMError):
- err(str(e))
- return False, 1
- print "Unexpected error:", sys.exc_info()[0]
- print
- print "Please report to xen-devel at lists.xen.org"
- raise
-
- return False, 1
-
-if __name__ == "__main__":
- main()
diff --git a/tools/python/xen/xm/migrate.py b/tools/python/xen/xm/migrate.py
deleted file mode 100644
index c1ea19d..0000000
--- a/tools/python/xen/xm/migrate.py
+++ /dev/null
@@ -1,87 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (c) 2005 XenSource Ltd.
-#============================================================================
-
-"""Domain migration.
-"""
-
-import sys
-
-from xen.xm.opts import *
-
-from main import server, serverType, get_single_vm, SERVER_XEN_API
-
-gopts = Opts(use="""[options] DOM HOST
-
-Migrate domain DOM to host HOST.
-Xend must be running on the local host and on HOST.
-""")
-
-gopts.opt('help', short='h',
- fn=set_true, default=0,
- use="Print this help.")
-
-gopts.opt('live', short='l',
- fn=set_true, default=0,
- use="Use live migration.")
-
-gopts.opt('port', short='p', val='portnum',
- fn=set_int, default=0,
- use="Use specified port for migration.")
-
-gopts.opt('node', short='n', val='nodenum',
- fn=set_int, default=-1,
- use="Use specified NUMA node on target.")
-
-gopts.opt('ssl', short='s',
- fn=set_true, default=None,
- use="Use ssl connection for migration.")
-
-gopts.opt('change_home_server', short='c',
- fn=set_true, default=0,
- use="Change home server for managed domains.")
-
-def help():
- return str(gopts)
-
-def main(argv):
- opts = gopts
- opts.reset()
- args = opts.parse(argv)
-
- if len(args) != 2:
- raise OptionError('Invalid number of arguments')
-
- dom = args[0]
- dst = args[1]
-
- if serverType == SERVER_XEN_API:
- vm_ref = get_single_vm(dom)
- other_config = {
- "port": opts.vals.port,
- "node": opts.vals.node,
- "ssl": opts.vals.ssl,
- "change_home_server": opts.vals.change_home_server
- }
- server.xenapi.VM.migrate(vm_ref, dst, bool(opts.vals.live),
- other_config)
- else:
- server.xend.domain.migrate(dom, dst, opts.vals.live,
- opts.vals.port,
- opts.vals.node,
- opts.vals.ssl,
- opts.vals.change_home_server)
diff --git a/tools/python/xen/xm/new.py b/tools/python/xen/xm/new.py
deleted file mode 100644
index cb9dc73..0000000
--- a/tools/python/xen/xm/new.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 XenSource Ltd
-#============================================================================
-
-import os
-import xmlrpclib
-
-from xen.xend import PrettyPrint
-from xen.xend import sxp
-from xen.xend import XendClient
-
-from xen.xm.main import serverType, SERVER_XEN_API
-from xen.xm.xenapi_create import *
-
-from opts import *
-from create import *
-
-def make_unstarted_domain(opts, config):
- """Create an unstarted domain.
-
- @param opts: options
- @param config: configuration
- """
- try:
- server.xend.domain.new(config)
- except xmlrpclib.Fault, ex:
- if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
- err("the domain '%s' does not exist." % ex.faultString)
- else:
- err("%s" % ex.faultString)
- except Exception, ex:
- err(str(ex))
-
-
-def main(argv):
- try:
- (opts, config) = parseCommandLine(argv)
- except StandardError, ex:
- err(str(ex))
-
- if not opts:
- return
-
- if type(config) == str:
- try:
- config = sxp.parse(file(config))[0]
- except IOError, exn:
- raise OptionError("Cannot read file %s: %s" % (config, exn[1]))
-
- if opts.vals.dryrun:
- PrettyPrint.prettyprint(config)
- return
-
- if serverType == SERVER_XEN_API:
- sxp2xml_inst = sxp2xml()
- doc = sxp2xml_inst.convert_sxp_to_xml(config)
-
- xenapi_create_inst = xenapi_create()
- vm_refs = xenapi_create_inst.create(document = doc,
- skipdtd=opts.vals.skipdtd)
- else:
- make_unstarted_domain(opts, config)
-
-if __name__ == '__main__':
- main(sys.argv)
-
diff --git a/tools/python/xen/xm/opts.py b/tools/python/xen/xm/opts.py
deleted file mode 100644
index 5b69fa2..0000000
--- a/tools/python/xen/xm/opts.py
+++ /dev/null
@@ -1,627 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-# Copyright (C) 2005 XenSource Ltd.
-#============================================================================
-
-"""Object-oriented command-line option support.
-"""
-import getopt
-import os
-import os.path
-import sys
-import types
-
-
-
-def _line_wrap(text, width = 70):
- lines = []
- current_line = ''
- words = text.strip().split()
- while words:
- word = words.pop(0)
- if len(current_line) + len(word) + 1 < width:
- current_line += word + ' '
- else:
- lines.append(current_line.strip())
- current_line = word + ' '
-
- if current_line:
- lines.append(current_line.strip())
- return lines
-
-def wrap(text, width = 70):
- """ Really basic textwrap. Useful because textwrap is not available
- for Python 2.2, and textwrap.wrap ignores newlines in Python 2.3+.
- """
- if len(text) < width:
- return [text]
-
- lines = []
- for line in text.split('\n'):
- lines += _line_wrap(line, width)
- return lines
-
-class OptionError(Exception):
- def _get_message(self):
- return self.__message
-
- def _set_message(self, value):
- self.__message = value
-
- message = property(_get_message, _set_message)
-
- """Denotes an error in option parsing."""
- def __init__(self, message, usage = ''):
- self.message = message
- self.usage = usage
- Exception.__init__(self, message)
- def __str__(self):
- return self.message
-
-class XMLFileError(Exception):
- """Thrown is input is an XML File"""
- def __init__(self, XMLFile):
- self.XMLFile = XMLFile
- def __str__(self):
- return "XMLFileError: %s" % self.XMLFile
- def getFile(self):
- return self.XMLFile
-
-class Opt:
- """An individual option.
- """
- def __init__(self, opts, name, short=None, long=None,
- val=None, fn=None, use=None, default=None):
- """Create an option.
-
- opts parent options object
- name name of the field it controls
- short short (1-char) command line switch (optional)
- long long command-line switch. Defaults to option name.
- val string used to print option args in help.
- If val is not specified the option has no arg.
- fn function to call when the option is specified.
- use usage (help) string
- default default value if not specified on command-line
- """
- self.opts = opts
- self.name = name
- self.short = short
- if long is None:
- long = name
- self.long = long
- self.val = val
- self.use = use
- self.default = default
- self.optkeys = []
- if self.short:
- self.optkeys.append('-' + self.short)
- if self.long:
- self.optkeys.append('--' + self.long)
- self.fn = fn
- self.specified_opt = None
- self.specified_val = None
- self.value = None
- self.set(default)
-
-
- def reset(self):
- self.specified_opt = None
- self.specified_val = None
- self.value = None
- self.set(self.default)
-
-
- def __repr__(self):
- return self.name + '=' + str(self.specified_val)
-
- def __str__(self):
- """ Formats the option into:
- '-k, --key description'
- """
- PARAM_WIDTH = 20
- if self.val:
- keys = ', '.join(['%s=%s' % (k, self.val) for k in self.optkeys])
- else:
- keys = ', '.join(self.optkeys)
- desc = wrap(self.use, 55)
- if len(keys) > PARAM_WIDTH:
- desc = [''] + desc
-
- wrapped = ('\n' + ' ' * (PARAM_WIDTH + 1)).join(desc)
- return keys.ljust(PARAM_WIDTH + 1) + wrapped
-
- def set(self, value):
- """Set the option value.
- """
- self.opts.setopt(self.name, value)
-
- def get(self):
- """Get the option value.
- """
- return self.opts.getopt(self.name)
-
- def append(self, value):
- """Append a value to the option value.
- """
- v = self.get() or []
- v.append(value)
- self.set(v)
-
- def short_opt(self):
- """Short option spec.
- """
- if self.short:
- if self.val:
- return self.short + ':'
- else:
- return self.short
- else:
- return None
-
- def long_opt(self):
- """Long option spec.
- """
- if self.long:
- if self.val:
- return self.long + '='
- else:
- return self.long
- else:
- return None
-
- def format(self, str, start=' ', out=sys.stdout):
- """Print a string, with consistent indentation at the start of lines.
- """
- lines = str.split('\n')
- for l in lines:
- l = l.strip()
- if start:
- out.write(start)
- out.write(l)
- out.write('\n')
-
- def show(self, out=sys.stdout):
- sep = ' '
- for x in self.optkeys:
- out.write(sep)
- out.write(x)
- sep = ', '
- if self.val:
- out.write(' ')
- out.write(self.val)
- out.write('\n')
- if self.use:
- self.format(self.use, out=out);
- if self.val:
- self.format('Default ' + str(self.default or 'None'), out=out)
-
- def specify(self, k, v):
- """Specify the option. Called when the option is set
- from the command line.
-
- k option switch used
- v optional value given (if any)
- """
- if k in self.optkeys:
- if self.val is None and v:
- self.opts.err("Option '%s' does not take a value" % k)
- self.specified_opt = k
- self.specified_val = v
- if self.fn:
- self.fn(self, k, v)
- return 1
- else:
- return 0
-
- def specified(self):
- """Test whether the option has been specified: set
- from the command line.
- """
- return self.specified_opt
-
-class OptVar(Opt):
- """An individual option variable.
- """
- def __init__(self, opts, name,
- val=None, fn=None, use=None, default=None):
- """Create an option.
-
- opts parent options object
- name name of the field it controls
- val string used to print option args in help.
- If val is not specified the option has no arg.
- fn function to call when the option is specified.
- use usage (help) string
- default default value if not specified on command-line
- """
- if val is None:
- val = name.upper()
- Opt.__init__(self, opts, name, val=val, fn=fn, use=use, default=default)
- self.optkeys = []
- self.optkeys.append(self.long)
-
- def short_opt(self):
- return None
-
- def long_opt(self):
- return None
-
- def show(self, out=sys.stdout):
- print >>out, ' %s=%s' % (self.optkeys[0], self.val)
- if self.use:
- self.format(self.use, out=out);
- if self.val:
- self.format('Default ' + str(self.default or 'None'), out=out)
-
-class OptVals:
- """Class to hold option values.
- """
- def __init__(self):
- self.quiet = False
-
-class Opts:
- """Container for options.
- """
-
- imports = ["import sys",
- "import os",
- "import os.path",
- "from xen.util.ip import *",
- ]
-
- def __init__(self, use=None):
- """Options constructor.
-
- use usage string
- """
- self.use = use
- # List of options.
- self.options = []
- # Options indexed by name.
- self.options_map = {}
- # Command-line arguments.
- self.argv = []
- # Option values.
- self.vals = OptVals()
- # Variables for default scripts.
- self.vars = {}
- # Option to use for bare words.
- self.default_opt = None
-
-
- def reset(self):
- self.vals = OptVals()
- self.vars = {}
- for opt in self.options:
- opt.reset()
-
-
- def __repr__(self):
- return '\n'.join(map(str, self.options))
-
- def __str__(self):
- options = [s for s in self.options if s.optkeys[0][0] == '-']
- output = ''
- if options:
- output += '\nOptions:\n\n'
- output += '\n'.join([str(o) for o in options])
- output += '\n'
- return output
-
- def val_usage(self):
- optvals = [s for s in self.options if s.optkeys[0][0] != '-']
- output = ''
- if optvals:
- output += '\nValues:\n\n'
- output += '\n'.join([str(o) for o in optvals])
- output += '\n'
- return output
-
- def opt(self, name, **args):
- """Add an option.
-
- name option name
- **args keyword params for option constructor
- """
- x = Opt(self, name, **args)
- self.options.append(x)
- self.options_map[name] = x
- return x
-
- def default(self, name):
- self.default_opt = name
-
- def getdefault(self, val):
- if self.default_opt is None:
- return 0
- opt = self.option(self.default_opt)
- return opt.set(val)
-
- def var(self, name, **args):
- x = OptVar(self, name, **args)
- self.options.append(x)
- self.options_map[name] = x
- return x
-
- def setvar(self, var, val):
- """Set a default script variable.
- """
- self.vars[var] = val
-
- def getvar(self, var):
- """Get a default script variable.
- """
- return self.vars.get(var)
-
- def option(self, name):
- """Get an option (object).
- """
- return self.options_map.get(name)
-
- def setopt(self, name, val):
- """Set an option value.
- An option can also be set using 'opts.vals.name = val'.
- """
- setattr(self.vals, name, val)
-
- def getopt(self, name):
- """Get an option value.
- An option value can also be got using 'opts.vals.name'.
- """
- return getattr(self.vals, name)
-
- def specified(self, name):
- """Test if an option has been specified.
- """
- opt = self.option(name)
- return opt and opt.specified()
-
- def err(self, msg):
- """Print an error to stderr and exit.
- """
- print >>sys.stderr, "Error:", msg
- sys.exit(1)
-
- def info(self, msg):
- """Print a message to stdout (unless quiet is set).
- """
- if self.vals.quiet: return
- print msg
-
- def warn(self, msg):
- """Print a warning to stdout.
- """
- print >>sys.stderr, "Warning:", msg
-
- def parse(self, argv):
- """Parse arguments argv using the options.
-
- return remaining arguments
- """
- self.argv = argv
-
- # hack to work around lack of gnu getopts parsing in python 2.2
- args = argv[1:]
- xargs = []
- while args:
- # let getopt parse whatever it feels like -- if anything
- try:
- (xvals, args) = getopt.getopt(args[0:],
- self.short_opts(),
- self.long_opts())
- except getopt.GetoptError, err:
- raise OptionError(str(err), self.use)
- #self.err(str(err))
-
- for (k, v) in xvals:
- for opt in self.options:
- if opt.specify(k, v): break
- else:
- raise OptionError('Unknown option: %s' % k, self.use)
-
- if not args:
- break
-
- # then process the 1st arg
- (arg,args) = (args[0], args[1:])
-
- isvar = 0
- if '=' in arg:
- (k, v) = arg.split('=', 1)
- for opt in self.options:
- if opt.specify(k, v):
- isvar = 1
- break
- elif self.getdefault(arg):
- isvar = 1
- if not isvar:
- xargs.append(arg)
-
- return xargs
-
- def short_opts(self):
- """Get short options specifier for getopt.
- """
- l = []
- for x in self.options:
- y = x.short_opt()
- if not y: continue
- l.append(y)
- return ''.join(l)
-
- def long_opts(self):
- """Get long options specifier for getopt.
- """
- l = []
- for x in self.options:
- y = x.long_opt()
- if not y: continue
- l.append(y)
- return l
-
- def usage(self):
- print 'Usage: ', self.argv[0], self.use or 'OPTIONS'
- print
- if self.options:
- for opt in self.options:
- opt.show()
- print
- print
-
- def var_usage(self):
- if self.vars:
- print 'The config file defines the following variables:'
- for var in self.vars:
- var.show()
- print
- print
-
- def config_usage(self):
- if self.imports:
- print 'The following are automically imported:'
- for x in self.imports:
- print ' ', x
- print
- self.var_usage()
-
- def load_defconfig(self, help=0):
- """Load a defconfig script. Assumes these options set:
- 'path' search path
- 'defconfig' script name
- """
- for x in [ '' ] + self.vals.path.split(':'):
- if x:
- p = os.path.join(x, self.vals.defconfig)
- else:
- p = self.vals.defconfig
- if not p.startswith('/'):
- p = os.path.join(os.path.curdir, p)
- if os.path.exists(p):
- self.info('Using config file "%s".' % p)
-
- f = open(p)
- is_xml = (f.read(1) == '<')
- f.close()
-
- if is_xml:
- raise XMLFileError(p)
-
- self.load(p, help)
- break
- else:
- raise OptionError('Unable to open config file: %s' % \
- self.vals.defconfig,
- self.use)
-
- def load(self, defconfig, help):
- """Load a defconfig file. Local variables in the file
- are used to set options with the same names.
- Variables are not used to set options that are already specified.
- """
- # Create global and local dicts for the file.
- # Initialize locals to the vars.
- # Use exec to do the standard imports and
- # define variables we are passing to the script.
- globs = {}
- locs = {}
- locs.update(self.vars)
- cmd = '\n'.join(self.imports +
- [ "from xen.xm.help import Vars",
- "xm_file = '%s'" % defconfig,
- "xm_help = %d" % help,
- "xm_vars = Vars(xm_file, xm_help, locals())"
- ])
- exec cmd in globs, locs
- try:
- execfile(defconfig, globs, locs)
- except SyntaxError,e:
- raise SyntaxError, \
- "Errors were found at line %d while processing %s:\n\t%s"\
- %(e.lineno,defconfig,e.text)
- except:
- if not help: raise
- if help:
- self.config_usage()
- return
- # Extract the values set by the script and set the corresponding
- # options, if not set on the command line.
- vtypes = [ types.StringType,
- types.ListType,
- types.IntType,
- types.FloatType
- ]
- for (k, v) in locs.items():
- if self.specified(k): continue
- if not(type(v) in vtypes): continue
- self.setopt(k, v)
-
-def set_true(opt, k, v):
- """Set an option true."""
- opt.set(1)
-
-def set_false(opt, k, v):
- """Set an option false."""
- opt.set(0)
-
-def set_bool(opt, k, v):
- """Set a boolean option.
- """
- if v in ('yes', 'y'):
- opt.set(1)
- elif v in ('no', 'n'):
- opt.set(0)
- else:
- opt.opts.err('Invalid value:' +v)
-
-def set_value(opt, k, v):
- """Set an option to a value."""
- opt.set(v)
-
-def set_int(opt, k, v):
- """Set an option to an integer value."""
- try:
- v = int(v)
- except:
- opt.opts.err('Invalid value: ' + str(v))
- opt.set(v)
-
-def set_long(opt, k, v):
- """Set an option to a long integer value."""
- try:
- v = long(v)
- except:
- opt.opts.err('Invalid value: ' + str(v))
- opt.set(v)
-
-def set_float(opt, k, v):
- """Set an option to a float value."""
- try:
- v = float(v)
- except:
- opt.opts.err('Invalid value: ' + str(v))
- opt.set(v)
-
-def append_value(opt, k, v):
- """Append a value to a list option."""
- opt.append(v)
-
-def set_var(opt, k, v):
- """Set a default script variable.
- """
- (var, val) = v.strip().split('=', 1)
- opt.opts.setvar(var.strip(), val.strip())
-
diff --git a/tools/python/xen/xm/resetpolicy.py b/tools/python/xen/xm/resetpolicy.py
deleted file mode 100644
index c88b427..0000000
--- a/tools/python/xen/xm/resetpolicy.py
+++ /dev/null
@@ -1,106 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2007 International Business Machines Corp.
-# Author: Stefan Berger <stefanb at us.ibm.com>
-#============================================================================
-""" Reset the system's current policy to the default state.
-"""
-import sys
-import xen.util.xsm.xsm as security
-from xen.util.xsm.xsm import XSMError
-from xen.xm.opts import OptionError
-from xen.xm import main as xm_main
-from xen.xm.main import server
-from xen.util import xsconstants
-from xen.util.acmpolicy import ACMPolicy
-
-
-def help():
- return """
- Reset the system's policy to the default.
-
- When the system's policy is reset, all guest VMs should be halted,
- since otherwise this operation will fail.
- """
-
-
-def resetpolicy():
- msg = None
- xs_type = xsconstants.XS_POLICY_ACM
- flags = xsconstants.XS_INST_LOAD
-
- if xm_main.serverType == xm_main.SERVER_XEN_API:
- if int(server.xenapi.XSPolicy.get_xstype()) & xs_type == 0:
- raise security.XSMError("ACM policy type not supported.")
-
- policystate = server.xenapi.XSPolicy.get_xspolicy()
-
- acmpol = ACMPolicy(xml=policystate['repr'])
-
- now_flags = int(policystate['flags'])
-
- if now_flags & xsconstants.XS_INST_BOOT == 0 and \
- not acmpol.is_default_policy():
- msg = "Old policy not found in bootloader file."
-
- try:
- policystate = server.xenapi.XSPolicy.reset_xspolicy(xs_type)
- except Exception, e:
- raise security.XSMError("An error occurred resetting the "
- "policy: %s" % str(e))
-
- xserr = int(policystate['xserr'])
- if xserr != xsconstants.XSERR_SUCCESS:
- raise security.XSMError("Could not reset the system's policy. "
- "Try to halt all guests.")
- else:
- print "Successfully reset the system's policy."
- if msg:
- print msg
- else:
- if server.xend.security.get_xstype() & xs_type == 0:
- raise security.XSMError("ACM policy type not supported.")
-
- xml, now_flags = server.xend.security.get_policy()
-
- acmpol = ACMPolicy(xml=xml)
-
- if int(now_flags) & xsconstants.XS_INST_BOOT == 0 and \
- not acmpol.is_default_policy():
- msg = "Old policy not found in bootloader file."
-
- rc, errors = server.xend.security.reset_policy()
- if rc != xsconstants.XSERR_SUCCESS:
- raise security.XSMError("Could not reset the system's policy. "
- "Try to halt all guests.")
- else:
- print "Successfully reset the system's policy."
- if msg:
- print msg
-
-
-def main(argv):
- if len(argv) != 1:
- raise OptionError("No arguments expected.")
-
- resetpolicy()
-
-
-if __name__ == '__main__':
- try:
- main(sys.argv)
- except Exception, e:
- sys.stderr.write('Error: %s\n' % str(e))
- sys.exit(-1)
diff --git a/tools/python/xen/xm/resources.py b/tools/python/xen/xm/resources.py
deleted file mode 100644
index cc8a6cc..0000000
--- a/tools/python/xen/xm/resources.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 International Business Machines Corp.
-# Author: Bryan D. Payne <bdpayne at us.ibm.com>
-#============================================================================
-
-"""List the resource label information from the global resource label file
-"""
-import sys
-from xen.util import xsconstants
-from xen.xm.opts import OptionError
-from xen.xm import main as xm_main
-from xen.xm.main import server
-
-def help():
- return """
- This program lists information for each resource in the
- global resource label file."""
-
-def print_resource_data(access_control):
- """Prints out a resource dictionary to stdout
- """
- for resource in access_control:
- tmp = access_control[resource]
- if len(tmp) == 2:
- policytype = xsconstants.ACM_POLICY_ID
- (policy, label) = access_control[resource]
- elif len(tmp) == 3:
- policytype, policy, label = access_control[resource]
- print resource
- print " type: "+ policytype
- print " policy: "+ policy
- print " label: "+ label
-
-def main (argv):
- if len(argv) > 1:
- raise OptionError("No arguments required")
-
- if xm_main.serverType == xm_main.SERVER_XEN_API:
- access_control = server.xenapi.XSPolicy.get_labeled_resources()
- for key, value in access_control.items():
- access_control[key] = tuple(value.split(':'))
- else:
- access_control = server.xend.security.get_labeled_resources()
-
- print_resource_data(access_control)
-
-if __name__ == '__main__':
- try:
- main(sys.argv)
- except Exception, e:
- sys.stderr.write('Error: %s\n' % str(e))
- sys.exit(-1)
diff --git a/tools/python/xen/xm/rmlabel.py b/tools/python/xen/xm/rmlabel.py
deleted file mode 100644
index 7b27ac5..0000000
--- a/tools/python/xen/xm/rmlabel.py
+++ /dev/null
@@ -1,216 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 International Business Machines Corp.
-# Author: Bryan D. Payne <bdpayne at us.ibm.com>
-#============================================================================
-
-"""Remove a label from a domain configuration file or a resoruce.
-"""
-import os
-import re
-import sys
-import xen.util.xsm.xsm as security
-from xen.util import xsconstants, auxbin
-from xen.util.acmpolicy import ACM_LABEL_UNLABELED
-from xen.xm.opts import OptionError
-from xen.xm import main as xm_main
-from xen.xm.main import server
-
-def help():
- return """
- Example: xm rmlabel dom <configfile>
- xm rmlabel res <resource>
- xm rmlabel mgt <domain name>
- xm rmlabel vif-<idx> <domain name>
-
- This program removes an acm_label entry from the 'configfile'
- for a domain, the label from a Xend-managed domain or a resources
- or from the network interface of a Xend-managed domain (requires
- xm to be used in Xen-API mode). If the label does not exist for
- the given domain or resource, then rmlabel fails and reports an error.
- """
-
-
-def rm_resource_label(resource):
- """Removes a resource label from the global resource label file.
- """
- # Try Xen-API first if configured to use it
- if xm_main.serverType == xm_main.SERVER_XEN_API:
- try:
- oldlabel = server.xenapi.XSPolicy.get_resource_label(resource)
- if oldlabel != "":
- server.xenapi.XSPolicy.set_resource_label(resource,"",
- oldlabel)
- else:
- raise security.XSMError("Resource not labeled")
- except Exception, e:
- raise security.XSMError("Could not remove label "
- "from resource: %s" % e)
- return
- else:
- oldlabel = server.xend.security.get_resource_label(resource)
- if len(oldlabel) != 0:
- rc = server.xend.security.set_resource_label(resource,
- "",
- "",
- "")
- if rc != xsconstants.XSERR_SUCCESS:
- raise security.XSMError("An error occurred removing the "
- "label: %s" % \
- xsconstants.xserr2string(-rc))
- else:
- raise security.XSMError("Resource not labeled")
-
-def rm_domain_label(configfile):
- # open the domain config file
- fd = None
- fil = None
- if configfile[0] == '/':
- fil = configfile
- fd = open(fil, "rb")
- else:
- for prefix in [".", auxbin.xen_configdir() ]:
- fil = prefix + "/" + configfile
- if os.path.isfile(fil):
- fd = open(fil, "rb")
- break
- if not fd:
- raise OptionError("Configuration file '%s' not found." % configfile)
-
- # read in the domain config file, removing label
- ac_entry_re = re.compile("^access_control\s*=.*", re.IGNORECASE)
- ac_exit_re = re.compile(".*'\].*")
- file_contents = ""
- comment = 0
- removed = 0
- for line in fd.readlines():
- if ac_entry_re.match(line):
- comment = 1
- if comment:
- removed = 1
- line = "#"+line
- if comment and ac_exit_re.match(line):
- comment = 0
- file_contents = file_contents + line
- fd.close()
-
- # send error message if we didn't find anything to remove
- if not removed:
- raise security.XSMError('Domain not labeled')
-
- # write the data back out to the file
- fd = open(fil, "wb")
- fd.writelines(file_contents)
- fd.close()
-
-def rm_domain_label_xapi(domain):
- if xm_main.serverType != xm_main.SERVER_XEN_API:
- old_lab = server.xend.security.get_domain_label(domain)
-
- vmlabel = ""
- if old_lab != "":
- tmp = old_lab.split(":")
- if len(tmp) == 3:
- vmlabel = tmp[2]
-
- if old_lab != "" and vmlabel != ACM_LABEL_UNLABELED:
- server.xend.security.set_domain_label(domain, "", old_lab)
- print "Successfully removed label from domain %s." % domain
- else:
- raise security.XSMError("Domain was not labeled.")
- else:
- uuids = server.xenapi.VM.get_by_name_label(domain)
- if len(uuids) == 0:
- raise OptionError('A VM with that name does not exist.')
- if len(uuids) != 1:
- raise OptionError('Too many domains with the same name.')
- uuid = uuids[0]
- try:
- old_lab = server.xenapi.VM.get_security_label(uuid)
-
- vmlabel = ""
- if old_lab != "":
- tmp = old_lab.split(":")
- if len(tmp) == 3:
- vmlabel = tmp[2]
-
- if old_lab != "":
- server.xenapi.VM.set_security_label(uuid, "", old_lab)
- else:
- raise security.XSMError("Domain was not labeled.")
- except Exception, e:
- raise security.XSMError('Could not remove label from domain: %s' % e)
-
-def rm_vif_label(vmname, idx):
- if xm_main.serverType != xm_main.SERVER_XEN_API:
- raise OptionError('Need to be configure for using xen-api.')
- vm_refs = server.xenapi.VM.get_by_name_label(vmname)
- if len(vm_refs) == 0:
- raise OptionError('A VM with the name %s does not exist.' %
- vmname)
- vif_refs = server.xenapi.VM.get_VIFs(vm_refs[0])
- if len(vif_refs) <= idx:
- raise OptionError("Bad VIF index.")
- vif_ref = server.xenapi.VIF.get_by_uuid(vif_refs[idx])
- if not vif_ref:
- raise security.XSMError("A VIF with this UUID does not exist.")
- try:
- old_lab = server.xenapi.VIF.get_security_label(vif_ref)
- if old_lab != "":
- rc = server.xenapi.VIF.set_security_label(vif_ref, "", old_lab)
- if int(rc) != 0:
- raise security.XSMError("Could not remove the label from"
- " the VIF.")
- else:
- print "Successfully removed the label from the VIF."
- else:
- raise security.XSMError("VIF is not labeled.")
- except Exception, e:
- raise security.XSMError("Could not remove the label from the VIF: %s" %
- str(e))
-
-
-def main (argv):
-
- if len(argv) != 3:
- raise OptionError('Requires 2 arguments')
-
- if argv[1].lower() == "dom":
- configfile = argv[2]
- rm_domain_label(configfile)
- elif argv[1].lower() == "mgt":
- domain = argv[2]
- rm_domain_label_xapi(domain)
- elif argv[1].lower().startswith("vif-"):
- try:
- idx = int(argv[1][4:])
- if idx < 0:
- raise
- except:
- raise OptionError("Bad VIF device index.")
- vmname = argv[2]
- rm_vif_label(vmname, idx)
- elif argv[1].lower() == "res":
- resource = argv[2]
- rm_resource_label(resource)
- else:
- raise OptionError('Unrecognised type argument: %s' % argv[1])
-
-if __name__ == '__main__':
- try:
- main(sys.argv)
- except Exception, e:
- sys.stderr.write('Error: %s\n' % str(e))
- sys.exit(-1)
diff --git a/tools/python/xen/xm/setenforce.py b/tools/python/xen/xm/setenforce.py
deleted file mode 100644
index 38f245d..0000000
--- a/tools/python/xen/xm/setenforce.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Author: Machon Gregory <mbgrego at tycho.ncsc.mil>
-#============================================================================
-
-"""Modify the current mode of the Flask XSM module.
-"""
-
-from xen.xm.opts import OptionError
-from xen.xm import main as xm_main
-from xen.xm.main import server
-from xen.util import xsconstants
-
-def help():
- return """
- Usage: xm setenforce [ Enforcing | Permissive | 1 | 0 ]
-
- Modifies the current mode of the Flask XSM module to be permissive or
- enforcing. Using Enforcing or 1 will put the Flask module in enforcing
- mode. Using Permissive or 0 will put the Flask module in permissive
- mode."""
-
-def setenforce(mode):
- if len(mode) == 1 and ( mode == "0" or mode == "1" ):
- val = int(mode)
- elif mode.lower() == "enforcing":
- val = 1
- elif mode.lower() == "permissive":
- val = 0
- else:
- raise OptionError("%s is an unsupported mode" % mode)
-
- if xm_main.serverType == xm_main.SERVER_XEN_API:
- if xsconstants.XS_POLICY_FLASK != \
- int(server.xenapi.XSPolicy.get_xstype()):
- raise OptionError("Unsupported policy type")
- ret = server.xenapi.XSPolicy.setenforce(val)
- else:
- if server.xend.security.on() != xsconstants.XS_POLICY_FLASK:
- raise OptionError("Unsupported policy type")
- ret = server.xend.security.setenforce(val)
-
-def main(argv):
- if len(argv) != 2:
- raise OptionError("Invalid arguments")
-
- if "-?" in argv:
- help()
- return
-
- mode = argv[1];
-
- setenforce(mode)
-
-if __name__ == '__main__':
- try:
- main(sys.argv)
- except Exception, e:
- sys.stderr.write('Error: %s\n' % str(e))
- sys.exit(-1)
-
-
diff --git a/tools/python/xen/xm/setpolicy.py b/tools/python/xen/xm/setpolicy.py
deleted file mode 100644
index 00a0af8..0000000
--- a/tools/python/xen/xm/setpolicy.py
+++ /dev/null
@@ -1,181 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2007 International Business Machines Corp.
-# Author: Stefan Berger <stefanb at us.ibm.com>
-#============================================================================
-
-"""Get the managed policy of the system.
-"""
-
-import os
-import sys
-import base64
-import struct
-import xen.util.xsm.xsm as security
-from xen.util import xsconstants
-from xen.util.xsm.acm.acm import install_policy_dir_prefix
-from xen.util.acmpolicy import ACMPolicy, \
- ACM_EVTCHN_SHARING_VIOLATION,\
- ACM_GNTTAB_SHARING_VIOLATION, \
- ACM_DOMAIN_LOOKUP, \
- ACM_CHWALL_CONFLICT, \
- ACM_SSIDREF_IN_USE
-from xen.xm.opts import OptionError
-from xen.xm import main as xm_main
-from xen.xm.getpolicy import getpolicy
-from xen.xm.main import server
-
-def help():
- return """
- Usage: xm setpolicy <policytype> <policyname>
-
- Set the policy managed by xend.
-
- Only 'ACM' and 'FLASK' are supported as valid policytype parameters.
-
- ACM:
- The filename of the policy is the policy name plus the suffic
- '-security_policy.xml'. The location of the policy file is either
- the the current directory or '/etc/xen/acm-security/policies'.
-
- """
-
-def build_hv_error_message(errors):
- """
- Build a message from the error codes return by the hypervisor.
- """
- txt = "Hypervisor reported errors:"
- i = 0
- while i + 7 < len(errors):
- code, data = struct.unpack("!ii", errors[i:i+8])
- err_msgs = {
- ACM_EVTCHN_SHARING_VIOLATION : \
- ["event channel sharing violation between domains",2],
- ACM_GNTTAB_SHARING_VIOLATION : \
- ["grant table sharing violation between domains",2],
- ACM_DOMAIN_LOOKUP : \
- ["domain lookup",1],
- ACM_CHWALL_CONFLICT : \
- ["Chinese Wall conflict between domains",2],
- ACM_SSIDREF_IN_USE : \
- ["A domain used SSIDREF",1],
- }
- num = err_msgs[code][1]
- if num == 1:
- txt += "%s %d" % (err_msgs[code][0], data)
- else:
- txt += "%s %d and %d" % (err_msgs[code][0],
- data >> 16 , data & 0xffff)
- i += 8
- return txt
-
-
-def setpolicy(policytype, policy_name, flags, overwrite):
-
- if policytype.upper() == xsconstants.ACM_POLICY_ID:
- xs_type = xsconstants.XS_POLICY_ACM
-
- for prefix in [ './', install_policy_dir_prefix+"/" ]:
- policy_file = prefix + "/".join(policy_name.split(".")) + \
- "-security_policy.xml"
-
- if os.path.exists(policy_file):
- break
-
- elif policytype.upper() == xsconstants.FLASK_POLICY_ID:
- xs_type = xsconstants.XS_POLICY_FLASK
- policy_file = policy_name
-
- else:
- raise OptionError("Unsupported policytype '%s'." % policytype)
-
- try:
- f = open(policy_file,"r")
- policy = f.read()
- f.close()
- except:
- raise OptionError("Could not read policy file: %s" % policy_file)
-
-
- if xs_type == xsconstants.XS_POLICY_FLASK:
- policy = base64.b64encode(policy)
-
- if xm_main.serverType == xm_main.SERVER_XEN_API:
- if xs_type != int(server.xenapi.XSPolicy.get_xstype()):
- raise security.XSMError("Policy type not supported.")
-
- try:
- policystate = server.xenapi.XSPolicy.set_xspolicy(xs_type,
- policy,
- flags,
- overwrite)
- except Exception, e:
- raise security.XSMError("An error occurred setting the "
- "policy: %s" % str(e))
- xserr = int(policystate['xserr'])
- if xserr != xsconstants.XSERR_SUCCESS:
- txt = "An error occurred trying to set the policy: %s." % \
- xsconstants.xserr2string(abs(xserr))
- errors = policystate['errors']
- if len(errors) > 0:
- txt += " " + build_hv_error_message(base64.b64decode(errors))
- raise security.XSMError(txt)
- else:
- print "Successfully set the new policy."
- if xs_type == xsconstants.XS_POLICY_ACM:
- getpolicy(False)
- else:
- # Non-Xen-API call.
- if xs_type != server.xend.security.on():
- raise security.XSMError("Policy type not supported.")
-
- rc, errors = server.xend.security.set_policy(xs_type,
- policy,
- flags,
- overwrite)
- if rc != xsconstants.XSERR_SUCCESS:
- txt = "An error occurred trying to set the policy: %s." % \
- xsconstants.xserr2string(abs(rc))
- if len(errors) > 0:
- txt += " " + build_hv_error_message(
- base64.b64decode(errors))
- raise security.XSMError(txt)
- else:
- print "Successfully set the new policy."
- if xs_type == xsconstants.XS_POLICY_ACM:
- getpolicy(False)
-
-def main(argv):
- if len(argv) < 3:
- raise OptionError("Need at least 3 arguments.")
-
- if "-?" in argv:
- help()
- return
-
- policytype = argv[1]
- policy_name = argv[2]
-
- flags = xsconstants.XS_INST_LOAD | xsconstants.XS_INST_BOOT
- overwrite = True
-
- setpolicy(policytype, policy_name, flags, overwrite)
-
-if __name__ == '__main__':
- try:
- main(sys.argv)
- except Exception, e:
- sys.stderr.write('Error: %s\n' % str(e))
- sys.exit(-1)
diff --git a/tools/python/xen/xm/shutdown.py b/tools/python/xen/xm/shutdown.py
deleted file mode 100644
index 125dcc1..0000000
--- a/tools/python/xen/xm/shutdown.py
+++ /dev/null
@@ -1,164 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray at hp.com>
-#============================================================================
-
-"""Domain shutdown.
-"""
-import time
-
-from xen.xend import sxp
-from opts import *
-from main import server, serverType, SERVER_XEN_API, get_single_vm
-from xen.xend.XendAPIConstants import *
-
-RECREATING_TIMEOUT = 30
-
-gopts = Opts(use="""[options] [DOM]
-
-Shutdown one or more domains gracefully.
-""")
-
-gopts.opt('help', short='h',
- fn=set_true, default=0,
- use="Print this help.")
-
-gopts.opt('all', short='a',
- fn=set_true, default=0,
- use="Shutdown all domains.")
-
-gopts.opt('wait', short='w',
- fn=set_true, default=0,
- use='Wait for shutdown to complete.')
-
-gopts.opt('halt', short='H',
- fn=set_true, default=0,
- use='Shutdown without reboot.')
-
-gopts.opt('reboot', short='R',
- fn=set_true, default=0,
- use='Shutdown and reboot.')
-
-def wait_reboot(opts, doms, rcs):
- if serverType == SERVER_XEN_API:
- opts.err("Cannot wait for reboot w/ XenAPI (yet)")
-
- recreating = {}
- while doms:
- alive = server.xend.domains(0)
- reboot = []
- for d in doms:
- if d in alive:
- rc = server.xend.domain.getRestartCount(d)
- if rc == rcs[d]: continue
- reboot.append(d)
-
- # Probably the domain is being recreated now.
- # We have to wait just a bit for recreating the domain.
- elif not recreating.has_key(d):
- recreating[d] = 0
- else:
- recreating[d] += 1
- if recreating[d] > RECREATING_TIMEOUT:
- opts.info("Domain %s destroyed for failing to reboot" % d)
- doms.remove(d)
-
- for d in reboot:
- opts.info("Domain %s rebooted" % d)
- doms.remove(d)
- time.sleep(1)
- opts.info("All domains rebooted")
-
-def wait_shutdown(opts, doms):
- while doms:
- if serverType == SERVER_XEN_API:
- alive = [dom for dom in server.xenapi.VM.get_all()
- if server.xenapi.VM.get_power_state(dom) ==
- XEN_API_VM_POWER_STATE[XEN_API_VM_POWER_STATE_RUNNING]]
- else:
- alive = server.xend.domains(0)
- dead = []
- for d in doms:
- if d in alive: continue
- dead.append(d)
- for d in dead:
- opts.info("Domain %s terminated" % d)
- doms.remove(d)
- time.sleep(1)
- opts.info("All domains terminated")
-
-def shutdown(opts, doms, mode, wait):
- rcs = {}
- for d in doms:
- if serverType == SERVER_XEN_API:
- if mode == 'halt':
- server.xenapi.VM.clean_shutdown(d)
- if mode == 'reboot':
- server.xenapi.VM.clean_reboot(d)
- if mode == 'poweroff':
- server.xenapi.VM.clean_shutdown(d)
- else:
- rcs[d] = server.xend.domain.getRestartCount(d)
- server.xend.domain.shutdown(d, mode)
-
- if wait:
- if mode == 'reboot':
- wait_reboot(opts, doms, rcs)
- else:
- wait_shutdown(opts, doms)
-
-def shutdown_mode(opts):
- if opts.vals.halt and opts.vals.reboot:
- opts.err("Can't specify halt and reboot")
-
- if opts.vals.halt:
- return 'halt'
- elif opts.vals.reboot:
- return 'reboot'
- else:
- return 'poweroff'
-
-def main_all(opts, args):
- if serverType == SERVER_XEN_API:
- doms = [dom for dom in server.xenapi.VM.get_all()
- if not server.xenapi.VM.get_is_control_domain(dom)]
- else:
- doms = server.xend.domains(0)
- dom0_name = sxp.child_value(server.xend.domain(0), 'name')
- doms.remove(dom0_name)
- mode = shutdown_mode(opts)
- shutdown(opts, doms, mode, opts.vals.wait)
-
-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')
- if serverType == SERVER_XEN_API:
- 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)
-
-def main(argv):
- opts = gopts
- opts.reset()
- args = opts.parse(argv)
- if opts.vals.help:
- return
- if opts.vals.all:
- main_all(opts, args)
- else:
- main_dom(opts, args)
-
diff --git a/tools/python/xen/xm/tests/__init__.py b/tools/python/xen/xm/tests/__init__.py
deleted file mode 100644
index 139597f..0000000
--- a/tools/python/xen/xm/tests/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/tools/python/xen/xm/tests/test_create.py b/tools/python/xen/xm/tests/test_create.py
deleted file mode 100644
index 54a0573..0000000
--- a/tools/python/xen/xm/tests/test_create.py
+++ /dev/null
@@ -1,206 +0,0 @@
-import os
-import os.path
-import tempfile
-import unittest
-
-import xen.xend.XendOptions
-
-xen.xend.XendOptions.XendOptions.config_default = '/dev/null'
-
-import xen.xm.create
-from xen.util import auxbin
-
-
-class test_create(unittest.TestCase):
-
- def assertEqualModuloNulls_(self, a, b):
- for k, v in a.iteritems():
- if v:
- self.failUnless(k in b, '%s not in b' % k)
- self.assertEqual(v, b[k])
- else:
- self.assert_(k not in b or not b[k], '%s in b' % k)
-
-
- def assertEqualModuloNulls(self, a, b):
- self.assertEqualModuloNulls_(a, b)
- self.assertEqualModuloNulls_(b, a)
-
-
- def t(self, args, expected):
- self.assertEqualModuloNulls(
- xen.xm.create.parseCommandLine(args.split(' '))[0].vals.__dict__,
- expected)
-
-
- def testCommandLine(self):
- (fd, fname) = tempfile.mkstemp()
- os.close(fd)
- self.t('-f %s kernel=/mykernel display=fakedisplay '
- 'macaddr=ab:cd:ef:ed' % fname,
- { 'name' : os.path.basename(fname),
- 'xm_file' : fname,
- 'defconfig' : fname,
- 'kernel' : '/mykernel',
- 'display' : 'fakedisplay',
- 'macaddr' : 'ab:cd:ef:ed',
- 'memory' : 128,
- 'vcpus' : 1,
- 'boot' : 'c',
- 'dhcp' : 'off',
- 'interface' : 'eth0',
- 'path' : '.:' + auxbin.xen_configdir(),
- 'builder' : 'linux',
- 'nics' : -1,
- 'vncunused' : 1,
- 'xauthority': xen.xm.create.get_xauthority(),
- })
-
-
- def testConfigFile(self):
- (fd, fname) = tempfile.mkstemp()
- try:
- os.write(fd,
- '''
-kernel = "/boot/vmlinuz-xenU-smp"
-memory = 768
-name = "dom1"
-vcpus = 4
-disk = ['phy:/dev/virt-blkdev-backend/dom1,sda1,w',
-'phy:/dev/virt-blkdev-backend/usr,sda2,r']
-root = "/dev/sda1 ro"
-extra = " profile=1 GATEWAY=192.0.2.254 NETMASK=255.255.255.0 IPADDR=192.0.2.1 HOSTNAME=dom1"
-on_poweroff = 'destroy'
-on_reboot = 'destroy'
-on_crash = 'destroy'
- ''')
- finally:
- os.close(fd)
-
- self.t('-f %s display=fakedisplay' % fname,
- { 'kernel' : '/boot/vmlinuz-xenU-smp',
- 'memory' : 768,
- 'name' : 'dom1',
- 'vcpus' : 4,
- 'nics' : -1,
- 'root' : '/dev/sda1 ro',
- 'extra' : ' profile=1 GATEWAY=192.0.2.254 NETMASK=255.255.255.0 IPADDR=192.0.2.1 HOSTNAME=dom1',
- 'on_poweroff' : 'destroy',
- 'on_reboot' : 'destroy',
- 'on_crash' : 'destroy',
- 'disk' : [['phy:/dev/virt-blkdev-backend/dom1',
- 'sda1', 'w', None],
- ['phy:/dev/virt-blkdev-backend/usr',
- 'sda2', 'r', None]],
-
- 'xm_file' : fname,
- 'defconfig' : fname,
- 'display' : 'fakedisplay',
-
- 'boot' : 'c',
- 'dhcp' : 'off',
- 'interface' : 'eth0',
- 'path' : '.:' + auxbin.xen_configdir(),
- 'builder' : 'linux',
-
- 'vncunused' : 1,
- 'xauthority' : xen.xm.create.get_xauthority(),
- })
-
-
- def testConfigFileAndCommandLine(self):
- (fd, fname) = tempfile.mkstemp()
- try:
- os.write(fd,
- '''
-name = "testname"
-memory = 256
-kernel = "/mykernel"
-maxmem = 1024
-cpu = 2
-cpu_weight = 0.75
- ''')
- finally:
- os.close(fd)
-
- self.t('-f %s display=fakedisplay macaddr=ab:cd:ef:ed' %
- fname,
- { 'name' : 'testname',
- 'xm_file' : fname,
- 'defconfig' : fname,
- 'kernel' : '/mykernel',
- 'display' : 'fakedisplay',
- 'macaddr' : 'ab:cd:ef:ed',
- 'memory' : 256,
- 'maxmem' : 1024,
- 'cpu' : 2,
- 'cpu_weight' : 0.75,
- 'vcpus' : 1,
- 'boot' : 'c',
- 'dhcp' : 'off',
- 'interface' : 'eth0',
- 'path' : '.:' + auxbin.xen_configdir(),
- 'builder' : 'linux',
- 'nics' : -1,
-
- 'vncunused' : 1,
- 'xauthority' : xen.xm.create.get_xauthority(),
- })
-
-
- def testHVMConfigFile(self):
- (fd, fname) = tempfile.mkstemp()
- try:
- os.write(fd,
- '''
-kernel = "hvmloader"
-builder='hvm'
-memory = 128
-name = "ExampleHVMDomain"
-vcpus=1
-vif = [ 'type=ioemu, bridge=xenbr0' ]
-disk = [ 'file:/var/images/min-el3-i386.img,ioemu:hda,w' ]
-device_model = 'qemu-dm'
-sdl=0
-vnc=1
-vncviewer=1
-ne2000=0
- ''')
- finally:
- os.close(fd)
-
- self.t('-f %s display=fakedisplay' % fname,
- { 'kernel' : 'hvmloader',
- 'builder' : 'hvm',
- 'memory' : 128,
- 'name' : 'ExampleHVMDomain',
- 'vcpus' : 1,
- 'nics' : -1,
- 'vif' : ['type=ioemu, bridge=xenbr0'],
- 'disk' : [['file:/var/images/min-el3-i386.img',
- 'ioemu:hda', 'w', None]],
- 'device_model': 'qemu-dm',
-
- 'extra' : ('VNC_VIEWER=%s:%d ' %
- (xen.xm.create.get_host_addr(),
- xen.xm.create.VNC_BASE_PORT +
- xen.xm.create.choose_vnc_display())),
- 'vnc' : 1,
- 'vncunused' : 1,
- 'vncviewer' : 1,
-
- 'xm_file' : fname,
- 'defconfig' : fname,
- 'display' : 'fakedisplay',
-
- 'boot' : 'c',
- 'dhcp' : 'off',
- 'interface' : 'eth0',
- 'path' : '.:' + auxbin.xen_configdir(),
-
- 'xauthority' : xen.xm.create.get_xauthority(),
- })
-
-
-def test_suite():
- return unittest.makeSuite(test_create)
diff --git a/tools/python/xen/xm/xenapi_create.py b/tools/python/xen/xm/xenapi_create.py
deleted file mode 100644
index 346ff20..0000000
--- a/tools/python/xen/xm/xenapi_create.py
+++ /dev/null
@@ -1,1129 +0,0 @@
-#!/usr/bin/python
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2007 Tom Wilkie <tom.wilkie at gmail.com>
-# Copyright (C) 2010 ANEXIA Internetdienstleistungs GmbH
-# Author: Stephan Peijnik <spe at anexia.at>
-#============================================================================
-"""Domain creation using new XenAPI
-"""
-
-from xen.xm.main import server, get_default_SR
-from xml.dom.minidom import parse, getDOMImplementation
-from lxml import etree
-from xen.xend import sxp
-from xen.xend.XendAPIConstants import XEN_API_ON_NORMAL_EXIT, \
- XEN_API_ON_CRASH_BEHAVIOUR
-from xen.xm.opts import OptionError
-from xen.util import xsconstants
-from xen.util.pci import pci_opts_list_from_sxp
-from xen.util.path import SHAREDIR
-import xen.util.xsm.xsm as security
-
-import sys
-import os
-from os.path import join
-import traceback
-import re
-import warnings # Used by lxml-based validator
-
-def log(_, msg):
- #print "> " + msg
- pass
-
-DEBUG = 0
-
-def get_name_label(node):
- name_node = node.getElementsByTagName("name")[0]
- label_node = name_node.getElementsByTagName("label")[0]
- return " ".join([child.nodeValue for child in label_node.childNodes])
-
-def get_name_description(node):
- name_node = node.getElementsByTagName("name")[0]
- description_node = name_node.getElementsByTagName("description")[0]
- return " ".join([child.nodeValue for child in description_node.childNodes])
-
-def get_text_in_child_node(node, child):
- tag_node = node.getElementsByTagName(child)[0]
- return " ".join([child.nodeValue for child in tag_node.childNodes])
-
-def get_child_node_attribute(node, child, attribute):
- tag_node = node.getElementsByTagName(child)[0]
- return tag_node.attributes[attribute].value
-
-def get_child_nodes_as_dict(node, child_name,
- key_attribute_name,
- value_attribute_name):
- return dict([(child.attributes[key_attribute_name].value,
- child.attributes[value_attribute_name].value)
- for child in node.getElementsByTagName(child_name)])
-
-def try_quietly(fn, *args):
- try:
- return fn(*args)
- except:
- return None
-
-class xenapi_create:
-
- def __init__(self):
- self.DEFAULT_STORAGE_REPOSITORY = get_default_SR()
-
- self.dtd = join(SHAREDIR, "xen", "create.dtd")
-
- def create(self, filename=None, document=None, skipdtd=False):
- """
- Create a domain from an XML file or DOM tree
- """
- if skipdtd:
- print "Skipping DTD checks. Dangerous!"
-
- if filename is not None:
- if not skipdtd:
- self.check_dtd(filename)
- document = parse(filename)
- elif document is not None:
- if not skipdtd:
- self.check_dom_against_dtd(document)
-
- self.check_doc(document)
-
- vdis = document.getElementsByTagName("vdi")
- vdi_refs_dict = self.create_vdis(vdis)
-
- networks = document.getElementsByTagName("network")
- network_refs_dict = self.create_networks(networks)
-
- try:
- vms = document.getElementsByTagName("vm")
- return self.create_vms(vms, vdi_refs_dict, network_refs_dict)
- except Exception, exn:
- try_quietly(self.cleanup_vdis(vdi_refs_dict))
- raise exn
-
- # Methods to check xml file
- # try to use dtd to check where possible
- def check_dtd(self, file):
- """
- Check file against DTD.
- Use this if possible as it gives nice
- error messages
- """
- try:
- dtd = etree.DTD(open(self.dtd, 'r'))
- except IOError:
- # The old code did neither raise an exception here, nor
- # did it report an error. For now we issue a warning.
- # TODO: How to handle a missing dtd file?
- # --sp
- warnings.warn('DTD file %s not found.' % (self.dtd),
- UserWarning)
- return
-
- tree = etree.parse(file)
- root = tree.getroot()
- if not dtd.validate(root):
- self.handle_dtd_errors(dtd)
-
- def check_dom_against_dtd(self, dom):
- """
- Check DOM again DTD.
- Doesn't give as nice error messages.
- (no location info)
- """
- try:
- dtd = etree.DTD(open(self.dtd, 'r'))
- except IOError:
- # The old code did neither raise an exception here, nor
- # did it report an error. For now we issue a warning.
- # TODO: How to handle a missing dtd file?
- # --sp
- warnings.warn('DTD file %s not found.' % (self.dtd),
- UserWarning)
- return
-
- # XXX: This may be a bit slow. Maybe we should use another way
- # of getting an etree root element from the minidom DOM tree...
- # -- sp
- root = etree.XML(dom.toxml())
- if not dtd.validate(root):
- self.handle_dtd_errors(dtd)
-
- # Do the same that was done in report_error before. This is directly
- # called by check_dtd and check_dom_against_dtd.
- # We are using sys.stderr instead of print though (python3k clean).
- def handle_dtd_errors(self, dtd):
- # XXX: Do we really want to bail out here?
- # -- sp
- for err in dtd.error_log:
- err_str = 'ERROR: %s\n' % (str(err),)
- sys.stderr.write(err_str)
- sys.stderr.flush()
- sys.exit(-1)
-
- #
- # Checks which cannot be done with dtd
- #
- def check_doc(self, doc):
- vms = doc.getElementsByTagName("vm")
- self.check_vms(vms)
-
- def check_vms(self, vms):
- map(self.check_vm, vms)
-
- def check_vm(self, vm):
- vifs = vm.getElementsByTagName("vif")
- self.check_vifs(vifs)
-
- def check_vifs(self, vifs):
- map(self.check_vif, vifs)
-
- def check_vif(self, vif):
- pass
-
- # Cleanup methods here
- def cleanup_vdis(self, vdi_refs_dict):
- map(self.cleanup_vdi, vdi_refs_dict.values())
-
- def cleanup_vdi(self, vdi_ref):
- server.xenapi.VDI.destroy(vdi_ref)
-
- def cleanup_vms(self, vm_refs):
- map(self.cleanup_vm, vm_refs)
-
- def cleanup_vm(self, vm_ref):
- server.xenapi.VM.destroy(vm_ref)
-
- # Create methods here
- def create_vdis(self, vdis):
- log(DEBUG, "create_vdis")
- return dict(map(self.create_vdi, vdis))
-
- def create_vdi(self, vdi):
- log(DEBUG, "create_vdi")
-
- for ref, record in server.xenapi.VDI.get_all_records().items():
- location = record["other_config"]["location"]
- if vdi.attributes["src"].value != location:
- continue
-
- # Reuse the VDI because the location is same.
- key = vdi.attributes["name"].value
- return (key, ref)
-
- # Create a new VDI.
- vdi_record = {
- "name_label": get_name_label(vdi),
- "name_description": get_name_description(vdi),
- "SR": self.DEFAULT_STORAGE_REPOSITORY,
- "virtual_size": vdi.attributes["size"].value,
- "type": vdi.attributes["type"].value,
- "sharable": vdi.attributes["sharable"].value == "True",
- "read_only": vdi.attributes["read_only"].value == "True",
- "other_config": {"location":
- vdi.attributes["src"].value}
- }
-
- key = vdi.attributes["name"].value
- value = server.xenapi.VDI.create(vdi_record)
-
- return (key, value)
-
- def create_networks(self, networks):
- log(DEBUG, "create_networks")
- return dict(map(self.create_network, networks))
-
- def create_network(self, network):
- log(DEBUG, "create_network")
-
- network_record = {
- "name_label": get_name_label(network),
- "name_description": get_name_description(network),
- "other_config":
- get_child_nodes_as_dict(network, "other_config",
- "key", "value"),
- "default_netmask": network.attributes["default_netmask"].value,
- "default_gateway": network.attributes["default_gateway"].value
- }
-
- key = network.attributes["name"].value
- value = server.xenapi.network.create(network_record)
-
- return (key, value)
-
- def create_vms(self, vms, vdis, networks):
- log(DEBUG, "create_vms")
- return map(lambda vm: self.create_vm(vm, vdis, networks), vms)
-
- def create_vm(self, vm, vdis, networks):
- log(DEBUG, "create_vm")
-
- vm_record = {
- "name_label":
- get_name_label(vm),
- "name_description":
- get_name_description(vm),
- "user_version":
- get_text_in_child_node(vm, "version"),
- "is_a_template":
- vm.attributes["is_a_template"].value == 'true',
- "auto_power_on":
- vm.attributes["auto_power_on"].value == 'true',
- "s3_integrity":
- vm.attributes["s3_integrity"].value,
- "superpages":
- vm.attributes["superpages"].value,
- "memory_static_max":
- get_child_node_attribute(vm, "memory", "static_max"),
- "memory_static_min":
- get_child_node_attribute(vm, "memory", "static_min"),
- "memory_dynamic_max":
- get_child_node_attribute(vm, "memory", "dynamic_max"),
- "memory_dynamic_min":
- get_child_node_attribute(vm, "memory", "dynamic_min"),
- "VCPUs_params":
- get_child_nodes_as_dict(vm, "vcpu_param", "key", "value"),
- "VCPUs_max":
- vm.attributes["vcpus_max"].value,
- "VCPUs_at_startup":
- vm.attributes["vcpus_at_startup"].value,
- "actions_after_shutdown":
- vm.attributes["actions_after_shutdown"].value,
- "actions_after_reboot":
- vm.attributes["actions_after_reboot"].value,
- "actions_after_crash":
- vm.attributes["actions_after_crash"].value,
- "platform":
- get_child_nodes_as_dict(vm, "platform", "key", "value"),
- "other_config":
- get_child_nodes_as_dict(vm, "other_config", "key", "value"),
- "pool_name":
- vm.attributes["pool_name"].value,
- "PV_bootloader":
- "",
- "PV_kernel":
- "",
- "PV_ramdisk":
- "",
- "PV_args":
- "",
- "PV_bootloader_args":
- "",
- "HVM_boot_policy":
- "",
- "HVM_boot_params":
- {},
- "PCI_bus":
- ""
- }
-
- if vm.attributes.has_key("security_label"):
- vm_record.update({
- "security_label":
- vm.attributes["security_label"].value
- })
-
- if len(vm.getElementsByTagName("pv")) > 0:
- vm_record.update({
- "PV_bootloader":
- get_child_node_attribute(vm, "pv", "bootloader"),
- "PV_kernel":
- get_child_node_attribute(vm, "pv", "kernel"),
- "PV_ramdisk":
- get_child_node_attribute(vm, "pv", "ramdisk"),
- "PV_args":
- get_child_node_attribute(vm, "pv", "args"),
- "PV_bootloader_args":
- get_child_node_attribute(vm, "pv", "bootloader_args")
- })
- else:
- hvm = vm.getElementsByTagName("hvm")[0]
- vm_record.update({
- "HVM_boot_policy":
- get_child_node_attribute(vm, "hvm", "boot_policy"),
- "HVM_boot_params":
- get_child_nodes_as_dict(hvm, "boot_param", "key", "value")
- })
- try:
- vm_ref = server.xenapi.VM.create(vm_record)
- except:
- traceback.print_exc()
- sys.exit(-1)
-
- try:
- # Now create vbds
-
- vbds = vm.getElementsByTagName("vbd")
-
- self.create_vbds(vm_ref, vbds, vdis)
-
- # Now create vifs
-
- vifs = vm.getElementsByTagName("vif")
-
- self.create_vifs(vm_ref, vifs, networks)
-
- # Now create consoles
-
- consoles = vm.getElementsByTagName("console")
-
- self.create_consoles(vm_ref, consoles)
-
- # Now create pcis
-
- pcis = vm.getElementsByTagName("pci")
-
- self.create_pcis(vm_ref, pcis)
-
- # Now create scsis
-
- scsis = vm.getElementsByTagName("vscsi")
-
- self.create_scsis(vm_ref, scsis)
-
- return vm_ref
- except:
- server.xenapi.VM.destroy(vm_ref)
- raise
-
- def create_vbds(self, vm_ref, vbds, vdis):
- log(DEBUG, "create_vbds")
- return map(lambda vbd: self.create_vbd(vm_ref, vbd, vdis), vbds)
-
- def create_vbd(self, vm_ref, vbd, vdis):
- log(DEBUG, "create_vbd")
-
- vbd_record = {
- "VM":
- vm_ref,
- "VDI":
- vdis[vbd.attributes["vdi"].value],
- "device":
- vbd.attributes["device"].value,
- "bootable":
- vbd.attributes["bootable"].value == "1",
- "mode":
- vbd.attributes["mode"].value,
- "type":
- vbd.attributes["type"].value,
- "qos_algorithm_type":
- vbd.attributes["qos_algorithm_type"].value,
- "qos_algorithm_params":
- get_child_nodes_as_dict(vbd,
- "qos_algorithm_param", "key", "value")
- }
-
- return server.xenapi.VBD.create(vbd_record)
-
- def create_vifs(self, vm_ref, vifs, networks):
- log(DEBUG, "create_vifs")
- return map(lambda vif: self.create_vif(vm_ref, vif, networks), vifs)
-
- def create_vif(self, vm_ref, vif, networks):
- log(DEBUG, "create_vif")
-
- if 'network' in vif.attributes.keys():
- network_name = vif.attributes['network'].value
-
- if network_name in networks.keys():
- network_uuid = networks[network_name]
- else:
- networks = dict([(record['name_label'], ref)
- for ref, record in
- server.xenapi.network.get_all_records().items()])
- if network_name in networks.keys():
- network_uuid = networks[network_name]
- else:
- raise OptionError("Network %s doesn't exist"
- % vif.attributes["network"].value)
- else:
- network_uuid = self._get_network_ref()
-
- vif_record = {
- "device":
- vif.attributes["device"].value,
- "network":
- network_uuid,
- "VM":
- vm_ref,
- "MAC":
- vif.attributes["mac"].value,
- "MTU":
- vif.attributes["mtu"].value,
- "qos_algorithm_type":
- vif.attributes["qos_algorithm_type"].value,
- "qos_algorithm_params":
- get_child_nodes_as_dict(vif,
- "qos_algorithm_param", "key", "value"),
- "security_label":
- vif.attributes["security_label"].value
- }
-
- return server.xenapi.VIF.create(vif_record)
-
- _network_refs = []
-
- def _get_network_ref(self):
- try:
- return self._network_refs.pop(0)
- except IndexError:
- self._network_refs = server.xenapi.network.get_all()
- return self._network_refs.pop(0)
-
- def create_consoles(self, vm_ref, consoles):
- log(DEBUG, "create_consoles")
- return map(lambda console: self.create_console(vm_ref, console),
- consoles)
-
- def create_console(self, vm_ref, console):
- log(DEBUG, "create_consoles")
-
- console_record = {
- "VM":
- vm_ref,
- "protocol":
- console.attributes["protocol"].value,
- "other_config":
- get_child_nodes_as_dict(console,
- "other_config", "key", "value")
- }
-
- 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["vdevfn"].value, 16),
- "options":
- get_child_nodes_as_dict(pci,
- "pci_opt", "key", "value"),
- "key":
- pci.attributes["key"].value
- }
-
- return server.xenapi.DPCI.create(dpci_record)
-
- def create_scsis(self, vm_ref, scsis):
- log(DEBUG, "create_scsis")
- return map(lambda scsi: self.create_scsi(vm_ref, scsi), scsis)
-
- def create_scsi(self, vm_ref, scsi):
- log(DEBUG, "create_scsi")
-
- if scsi.attributes["feature-host"].value == "True":
- target_HBA_ref = None
- for pscsi_HBA_ref in server.xenapi.PSCSI_HBA.get_all():
- if int(scsi.attributes["devid"].value) == \
- int(server.xenapi.PSCSI_HBA.get_physical_host(pscsi_HBA_ref)):
- target_HBA_ref = pscsi_HBA_ref
- break
- if target_HBA_ref is None:
- log(DEBUG, "create_scsi: scsi device not found")
- return None
-
- dscsi_record = {
- "VM":
- vm_ref,
- "PSCSI_HBA":
- target_HBA_ref,
- "assignment_mode":
- "HOST"
- }
-
- return server.xenapi.DSCSI_HBA.create(dscsi_record)
- else:
- target_ref = None
- for pscsi_ref in server.xenapi.PSCSI.get_all():
- if scsi.attributes["p-dev"].value == \
- server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
- target_ref = pscsi_ref
- break
- if target_ref is None:
- log(DEBUG, "create_scsi: scsi device not found")
- return None
-
- dscsi_record = {
- "VM":
- vm_ref,
- "PSCSI":
- target_ref,
- "virtual_HCTL":
- scsi.attributes["v-dev"].value
- }
-
- return server.xenapi.DSCSI.create(dscsi_record)
-
-def get_child_by_name(exp, childname, default = None):
- try:
- return [child for child in sxp.children(exp)
- if child[0] == childname][0][1]
- except:
- return default
-
-# Convert old sxp into new xml
-
-class sxp2xml:
-
- def convert_sxp_to_xml(self, config, transient=False):
-
- devices = [child for child in sxp.children(config)
- if len(child) > 0 and child[0] == "device"]
-
- vbds_sxp = map(lambda x: x[1], [device for device in devices
- if device[1][0] in ("vbd", "tap", "tap2")])
-
- vifs_sxp = map(lambda x: x[1], [device for device in devices
- if device[1][0] == "vif"])
-
- 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"])
-
- scsis_sxp = map(lambda x: x[1], [device for device in devices
- if device[1][0] == "vscsi"])
-
- # Create XML Document
-
- impl = getDOMImplementation()
-
- document = impl.createDocument(None, "xm", None)
-
- # Lets make the VM tag..
-
- vm = document.createElement("vm")
-
- # Some string compatibility
-
- actions_after_shutdown \
- = get_child_by_name(config, "on_poweroff", "destroy")
- actions_after_reboot \
- = get_child_by_name(config, "on_reboot", "restart")
- actions_after_crash \
- = get_child_by_name(config, "on_crash", "restart")
-
- def conv_chk(val, vals):
- lval = val.replace("-", "_")
- if lval not in vals:
- raise ValueError("Invalid value: %s" % val)
- else:
- return lval
-
- actions_after_shutdown = conv_chk(actions_after_shutdown,\
- XEN_API_ON_NORMAL_EXIT)
- actions_after_reboot = conv_chk(actions_after_reboot, \
- XEN_API_ON_NORMAL_EXIT)
- actions_after_crash = conv_chk(actions_after_crash, \
- XEN_API_ON_CRASH_BEHAVIOUR)
- # Flesh out tag attributes
-
- vm.attributes["is_a_template"] = "false"
- vm.attributes["auto_power_on"] = "false"
- vm.attributes["actions_after_shutdown"] \
- = actions_after_shutdown
- vm.attributes["actions_after_reboot"] \
- = actions_after_reboot
- vm.attributes["actions_after_crash"] \
- = actions_after_crash
- vm.attributes["PCI_bus"] = ""
-
- vm.attributes["vcpus_max"] \
- = str(get_child_by_name(config, "vcpus", 1))
- vm.attributes["vcpus_at_startup"] \
- = str(get_child_by_name(config, "vcpus", 1))
- vm.attributes["s3_integrity"] \
- = str(get_child_by_name(config, "s3_integrity", 0))
- vm.attributes["superpages"] \
- = str(get_child_by_name(config, "superpages", 0))
- vm.attributes["pool_name"] \
- = str(get_child_by_name(config, "pool_name", "Pool-0"))
-
- sec_data = get_child_by_name(config, "security")
- if sec_data:
- try :
- vm.attributes['security_label'] = \
- security.set_security_label(sec_data[0][1][1],sec_data[0][2][1])
- except Exception, e:
- raise ValueError("Invalid security data format: %s" % str(sec_data))
-
- # Make the name tag
-
- vm.appendChild(self.make_name_tag(
- get_child_by_name(config, "name"), document))
-
- # Make version tag
-
- version = document.createElement("version")
- version.appendChild(document.createTextNode("0"))
- vm.appendChild(version)
-
- # Make pv or hvm tag
-
- image = get_child_by_name(config, "image")
-
- if image[0] == "linux":
- pv = document.createElement("pv")
- pv.attributes["kernel"] \
- = get_child_by_name(image, "kernel", "")
- 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"] \
- = get_child_by_name(config, "bootloader_args","")
-
- vm.appendChild(pv)
- elif image[0] == "hvm":
- hvm = document.createElement("hvm")
- hvm.attributes["boot_policy"] = "BIOS order"
-
- boot_order = document.createElement("boot_param")
- boot_order.attributes["key"] = "order"
- boot_order.attributes["value"] \
- = get_child_by_name(image, "boot", "abcd")
- hvm.appendChild
-
- vm.appendChild(hvm)
-
- # Make memory tag
-
- memory = document.createElement("memory")
-
- memory_str = str(int(
- get_child_by_name(config, "memory"))*1024*1024)
-
- memory.attributes["static_min"] = str(0)
- memory.attributes["static_max"] = memory_str
- memory.attributes["dynamic_min"] = memory_str
- memory.attributes["dynamic_max"] = memory_str
-
- if get_child_by_name(config, "maxmem"):
- memory.attributes["static_max"] = \
- str(int(get_child_by_name(config, "maxmem")*1024*1024))
-
- vm.appendChild(memory)
-
- # And now the vbds
-
- vbds = map(lambda vbd: self.extract_vbd(vbd, document), vbds_sxp)
-
- map(vm.appendChild, vbds)
-
- # And now the vifs
-
- vifs = map(lambda vif: self.extract_vif(vif, document), vifs_sxp)
-
- map(vm.appendChild, vifs)
-
- # And now the pcis
-
- pcis = self.extract_pcis(pcis_sxp, document)
-
- map(vm.appendChild, pcis)
-
- # And now the scsis
-
- scsis = self.extract_scsis(scsis_sxp, document)
-
- map(vm.appendChild, scsis)
-
- # Last but not least the consoles...
-
- consoles = self.extract_consoles(image, document)
-
- map(vm.appendChild, consoles)
-
- vfbs = map(lambda vfb: self.extract_vfb(vfb, document), vfbs_sxp)
-
- map(vm.appendChild, vfbs)
-
- # Platform variables...
-
- platform = self.extract_platform(image, document)
-
- map(vm.appendChild, platform)
-
- # And now the vcpu_params
-
- vcpu_params = self.extract_vcpu_params(config, document)
-
- map(vm.appendChild, vcpu_params)
-
- # transient?
-
- if transient:
- other_config = document.createElement("other_config")
- other_config.attributes["key"] = "transient"
- other_config.attributes["value"] = "True"
- vm.appendChild(other_config)
-
- # Add it to doc_root
-
- document.documentElement.appendChild(vm)
-
- # We want to pull out vdis
-
- vdis = map(lambda vdb: self.extract_vdi(vdb, document), vbds_sxp)
-
- map(document.documentElement.appendChild, vdis)
-
- return document
-
- def make_name_tag(self, label_text, document):
- name = document.createElement("name")
-
- label = document.createElement("label")
- label.appendChild(document.createTextNode(str(label_text)))
- name.appendChild(label)
-
- description = document.createElement("description")
- description.appendChild(document.createTextNode(" "))
- name.appendChild(description)
-
- return name
-
- def extract_vbd(self, vbd_sxp, document):
- src = get_child_by_name(vbd_sxp, "uname")
- mode = get_child_by_name(vbd_sxp, "mode")
- name = str(src.__hash__())
-
- vbd = document.createElement("vbd")
-
- vbd.attributes["name"] = "vdb" + name
- vbd.attributes["vdi"] = "vdi" + name
- vbd.attributes["mode"] \
- = re.search("^w!{0,1}$", mode) and "RW" or "RO"
- vbd.attributes["device"] \
- = re.sub(":cdrom$", "", get_child_by_name(vbd_sxp, "dev"))
- vbd.attributes["bootable"] = "1"
- vbd.attributes["type"] \
- = re.search(":cdrom$", get_child_by_name(vbd_sxp, "dev")) \
- and "CD" or "disk"
- vbd.attributes["qos_algorithm_type"] = ""
-
- return vbd
-
- def extract_vdi(self, vbd_sxp, document):
- src = get_child_by_name(vbd_sxp, "uname")
- mode = get_child_by_name(vbd_sxp, "mode")
- name = "vdi" + str(src.__hash__())
-
- vdi = document.createElement("vdi")
-
- vdi.attributes["src"] = src
- vdi.attributes["read_only"] \
- = re.search("^w!{0,1}$", mode) and "False" or "True"
- vdi.attributes["size"] = '-1'
- vdi.attributes["type"] = "system"
- vdi.attributes["sharable"] \
- = re.search("^w!$", mode) and "True" or "False"
- vdi.attributes["name"] = name
-
- vdi.appendChild(self.make_name_tag(name, document))
-
- return vdi
-
- def extract_vif(self, vif_sxp, document):
-
- vif = document.createElement("vif")
-
- dev = get_child_by_name(vif_sxp, "vifname", None)
-
- if dev is None:
- dev = self.getFreshEthDevice()
-
- vif.attributes["name"] \
- = "vif" + str(dev.__hash__())
- vif.attributes["mac"] \
- = get_child_by_name(vif_sxp, "mac", "")
- vif.attributes["mtu"] \
- = get_child_by_name(vif_sxp, "mtu", "")
- vif.attributes["device"] = dev
- vif.attributes["qos_algorithm_type"] = ""
-
- policy = get_child_by_name(vif_sxp, "policy")
- label = get_child_by_name(vif_sxp, "label")
-
- vif.attributes["security_label"] = security.set_security_label(policy, label)
-
- if get_child_by_name(vif_sxp, "bridge") is not None:
- vif.attributes["network"] \
- = get_child_by_name(vif_sxp, "bridge")
-
- return vif
-
- def extract_vfb(self, vfb_sxp, document):
-
- vfb = document.createElement("console")
- vfb.attributes["protocol"] = "rfb"
-
- if get_child_by_name(vfb_sxp, "type", "") == "vnc":
- vfb.appendChild(self.mk_other_config(
- "type", "vnc",
- document))
- vfb.appendChild(self.mk_other_config(
- "vncunused", get_child_by_name(vfb_sxp, "vncunused", "1"),
- document))
- vfb.appendChild(self.mk_other_config(
- "vnclisten",
- get_child_by_name(vfb_sxp, "vnclisten", "127.0.0.1"),
- document))
- vfb.appendChild(self.mk_other_config(
- "vncdisplay", get_child_by_name(vfb_sxp, "vncdisplay", "0"),
- document))
- vfb.appendChild(self.mk_other_config(
- "vncpasswd", get_child_by_name(vfb_sxp, "vncpasswd", ""),
- document))
-
- if get_child_by_name(vfb_sxp, "type", "") == "sdl":
- vfb.appendChild(self.mk_other_config(
- "type", "sdl",
- document))
- vfb.appendChild(self.mk_other_config(
- "display", get_child_by_name(vfb_sxp, "display", ""),
- document))
- vfb.appendChild(self.mk_other_config(
- "xauthority",
- get_child_by_name(vfb_sxp, "xauthority", ""),
- document))
- vfb.appendChild(self.mk_other_config(
- "opengl", get_child_by_name(vfb_sxp, "opengl", "1"),
- document))
-
- return vfb
-
- 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["vdevfn"] \
- = get_child_by_name(dev_sxp, "vdevfn", "0")
- pci.attributes["key"] \
- = get_child_by_name(dev_sxp, "key", "0")
- for opt in pci_opts_list_from_sxp(dev_sxp):
- pci_opt = document.createElement("pci_opt")
- pci_opt.attributes["key"] = opt[0]
- pci_opt.attributes["value"] = opt[1]
- pci.appendChild(pci_opt)
-
- pcis.append(pci)
-
- return pcis
-
- def extract_scsis(self, scsis_sxp, document):
-
- scsis = []
-
- for scsi_sxp in scsis_sxp:
- feature_host = sxp.child_value(scsi_sxp, "feature-host")
- for dev_sxp in sxp.children(scsi_sxp, "dev"):
- scsi = document.createElement("vscsi")
-
- scsi.attributes["feature-host"] \
- = feature_host and "True" or "False"
- if feature_host:
- scsi.attributes["devid"] \
- = str(get_child_by_name(dev_sxp, "devid"))
- scsis.append(scsi)
- break
- else:
- scsi.attributes["p-dev"] \
- = get_child_by_name(dev_sxp, "p-dev")
- scsi.attributes["v-dev"] \
- = get_child_by_name(dev_sxp, "v-dev")
- scsis.append(scsi)
-
- return scsis
-
- def mk_other_config(self, key, value, document):
- other_config = document.createElement("other_config")
- other_config.attributes["key"] = key
- other_config.attributes["value"] = value
- return other_config
-
- def extract_consoles(self, image, document):
- consoles = []
-
- if int(get_child_by_name(image, "nographic", "1")) == 1:
- return consoles
-
- if int(get_child_by_name(image, "vnc", "0")) == 1:
- console = document.createElement("console")
- console.attributes["protocol"] = "rfb"
- console.appendChild(self.mk_other_config(
- "type", "vnc",
- document))
- console.appendChild(self.mk_other_config(
- "vncunused", str(get_child_by_name(image, "vncunused", "1")),
- document))
- console.appendChild(self.mk_other_config(
- "vnclisten",
- get_child_by_name(image, "vnclisten", "127.0.0.1"),
- document))
- console.appendChild(self.mk_other_config(
- "vncdisplay", str(get_child_by_name(image, "vncdisplay", "0")),
- document))
- console.appendChild(self.mk_other_config(
- "vncpasswd", get_child_by_name(image, "vncpasswd", ""),
- document))
- consoles.append(console)
- if int(get_child_by_name(image, "sdl", "0")) == 1:
- console = document.createElement("console")
- console.attributes["protocol"] = "rfb"
- console.appendChild(self.mk_other_config(
- "type", "sdl",
- document))
- console.appendChild(self.mk_other_config(
- "display", get_child_by_name(image, "display", ""),
- document))
- console.appendChild(self.mk_other_config(
- "xauthority", get_child_by_name(image, "xauthority", ""),
- document))
- console.appendChild(self.mk_other_config(
- "opengl", str(get_child_by_name(image, "opengl", "1")),
- document))
- consoles.append(console)
-
- return consoles
-
-
- def extract_platform(self, image, document):
-
- platform_keys = [
- 'acpi',
- 'apic',
- 'boot',
- 'device_model',
- 'loader',
- 'fda',
- 'fdb',
- 'keymap',
- 'isa',
- 'localtime',
- 'monitor',
- 'pae',
- 'rtc_timeoffset',
- 'serial',
- 'soundhw',
- 'stdvga',
- 'usb',
- 'usbdevice',
- 'hpet',
- 'timer_mode',
- 'vpt_align',
- 'viridian',
- 'vhpt',
- 'guest_os_type',
- 'hap',
- 'oos',
- 'pci_msitranslate',
- 'pci_power_mgmt',
- 'xen_platform_pci',
- 'tsc_mode'
- 'description',
- 'nomigrate'
- ]
-
- platform_configs = []
- for key in platform_keys:
- value = get_child_by_name(image, key, None)
- if value is not None:
- platform = document.createElement("platform")
- platform.attributes["key"] = key
- platform.attributes["value"] = str(value)
- platform_configs.append(platform)
-
- return platform_configs
-
- def extract_vcpu_params(self, config, document):
- vcpu_params = []
-
- vcpu_param = document.createElement("vcpu_param")
- vcpu_param.attributes["key"] = "weight"
- vcpu_param.attributes["value"] \
- = str(get_child_by_name(config, "cpu_weight", 256))
- vcpu_params.append(vcpu_param)
-
- vcpu_param = document.createElement("vcpu_param")
- vcpu_param.attributes["key"] = "cap"
- vcpu_param.attributes["value"] \
- = str(get_child_by_name(config, "cpu_cap", 0))
- vcpu_params.append(vcpu_param)
-
- cpus = get_child_by_name(config, "cpus", [])
- if type(cpus) == list:
- vcpu = 0
- for cpu in cpus:
- if cpu:
- vcpu_param = document.createElement("vcpu_param")
- vcpu_param.attributes["key"] = "cpumap%i" % vcpu
- vcpu_param.attributes["value"] = str(cpu)
- vcpu_params.append(vcpu_param)
- vcpu = vcpu + 1
- else:
- for vcpu in range(0, int(get_child_by_name(config, "vcpus", 1))):
- vcpu_param = document.createElement("vcpu_param")
- vcpu_param.attributes["key"] = "cpumap%i" % vcpu
- vcpu_param.attributes["value"] = str(cpus)
- vcpu_params.append(vcpu_param)
-
- return vcpu_params
-
- _eths = -1
-
- def getFreshEthDevice(self):
- self._eths += 1
- return "eth%i" % self._eths
diff --git a/tools/python/xen/xm/xm b/tools/python/xen/xm/xm
deleted file mode 100755
index fef4272..0000000
--- a/tools/python/xen/xm/xm
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env python
-# -*- mode: python; -*-
-import sys, os.path
-
-from xen.xm import main
-
-print >>sys.stderr, ("WARNING: xend/xm is deprecated.")
-
-if not os.path.exists("/var/run/xm-deprecation-long-warning"):
- print >>sys.stderr, ("""
-xend is deprecated and scheduled for removal. Please migrate to another
-toolstack ASAP.
-
-See http://wiki.xen.org/wiki/Choice_of_Toolstacks for information on
-other alternatives, including xl which is designed to be a drop in
-replacement for xm (http://wiki.xen.org/wiki/XL).
-""")
- open("/var/run/xm-deprecation-long-warning", "w").close()
-
-main.main(sys.argv)
diff --git a/tools/remus/Makefile b/tools/remus/Makefile
deleted file mode 100644
index ae82376..0000000
--- a/tools/remus/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-XEN_ROOT=$(CURDIR)/../..
-include $(XEN_ROOT)/tools/Rules.mk
-
-SCRIPTS = remus
-
-.PHONY: all
-all: subdirs-all
-
-.PHONY: install
-install: subdirs-install
- $(INSTALL_DIR) $(DESTDIR)$(BINDIR)
- $(INSTALL_PYTHON_PROG) $(SCRIPTS) $(DESTDIR)$(BINDIR)
-
-.PHONY: clean
-clean: subdirs-clean
diff --git a/tools/remus/README b/tools/remus/README
deleted file mode 100644
index 9e8140b..0000000
--- a/tools/remus/README
+++ /dev/null
@@ -1,4 +0,0 @@
-Remus provides fault tolerance for virtual machines by sending continuous
-checkpoints to a backup, which will activate if the target VM fails.
-
-See the website at http://nss.cs.ubc.ca/remus/ for details.
diff --git a/tools/remus/remus b/tools/remus/remus
deleted file mode 100644
index 38f0365..0000000
--- a/tools/remus/remus
+++ /dev/null
@@ -1,230 +0,0 @@
-#!/usr/bin/env python
-#
-# This is a save process which also buffers outgoing I/O between
-# rounds, so that external viewers never see anything that hasn't
-# been committed at the backup
-#
-# TODO: fencing.
-
-import optparse, os, re, select, signal, sys, time
-
-from xen.remus import save, util, vm
-from xen.remus.device import ReplicatedDisk, ReplicatedDiskException
-from xen.remus.device import BufferedNIC, BufferedNICException
-from xen.xend import XendOptions
-
-class CfgException(Exception): pass
-
-class Cfg(object):
-
- REMUS_FLAGS_COMPRESSION = 1
-
- def __init__(self):
- # must be set
- self.domid = 0
-
- self.host = 'localhost'
- self.nullremus = False
- self.port = XendOptions.instance().get_xend_relocation_port()
- self.interval = 200
- self.netbuffer = True
- self.flags = self.REMUS_FLAGS_COMPRESSION
- self.timer = False
-
- parser = optparse.OptionParser()
- parser.usage = '%prog [options] domain [destination]'
- parser.add_option('-i', '--interval', dest='interval', type='int',
- metavar='MS',
- help='checkpoint every MS milliseconds')
- parser.add_option('-p', '--port', dest='port', type='int',
- help='send stream to port PORT', metavar='PORT')
- parser.add_option('', '--blackhole', dest='nullremus', action='store_true',
- help='replicate to /dev/null (no disk checkpoints, only memory & net buffering)')
- parser.add_option('', '--no-net', dest='nonet', action='store_true',
- help='run without net buffering (benchmark option)')
- parser.add_option('', '--no-compression', dest='nocompress', action='store_true',
- help='run without checkpoint compression')
- parser.add_option('', '--timer', dest='timer', action='store_true',
- help='force pause at checkpoint interval (experimental)')
- self.parser = parser
-
- def usage(self):
- self.parser.print_help()
-
- def getargs(self):
- opts, args = self.parser.parse_args()
-
- if opts.interval:
- self.interval = opts.interval
- if opts.port:
- self.port = opts.port
- if opts.nullremus:
- self.nullremus = True
- if opts.nonet:
- self.netbuffer = False
- if opts.nocompress:
- self.flags &= ~self.REMUS_FLAGS_COMPRESSION
- if opts.timer:
- self.timer = True
-
- if not args:
- raise CfgException('Missing domain')
- self.domid = args[0]
- if (len(args) > 1):
- self.host = args[1]
-
-class SignalException(Exception): pass
-
-def run(cfg):
- closure = lambda: None
- closure.cmd = None
-
- def sigexception(signo, frame):
- raise SignalException(signo)
-
- def die():
- # I am not sure what the best way to die is. xm destroy is another option,
- # or we could attempt to trigger some instant reboot.
- print "dying..."
- print util.runcmd(['sudo', 'ifdown', 'eth2'])
- # dangling imq0 handle on vif locks up the system
- for buf in bufs:
- buf.uninstall()
- print util.runcmd(['sudo', 'xm', 'destroy', cfg.domid])
- print util.runcmd(['sudo', 'ifup', 'eth2'])
-
- def getcommand():
- """Get a command to execute while running.
- Commands include:
- s: die prior to postsuspend hook
- s2: die after postsuspend hook
- r: die prior to preresume hook
- r2: die after preresume hook
- c: die prior to commit hook
- c2: die after commit hook
- """
- r, w, x = select.select([sys.stdin], [], [], 0)
- if sys.stdin not in r:
- return
-
- cmd = sys.stdin.readline().strip()
- if cmd not in ('s', 's2', 'r', 'r2', 'c', 'c2'):
- print "unknown command: %s" % cmd
- closure.cmd = cmd
-
- signal.signal(signal.SIGTERM, sigexception)
-
- dom = vm.VM(cfg.domid)
-
- # set up I/O buffers
- bufs = []
-
- # disks must commit before network can be released
- if not cfg.nullremus:
- for disk in dom.disks:
- try:
- bufs.append(ReplicatedDisk(disk))
- except ReplicatedDiskException, e:
- print e
- continue
-
- if cfg.netbuffer:
- for vif in dom.vifs:
- bufs.append(BufferedNIC(vif))
-
- if cfg.nullremus:
- fd = save.NullSocket((cfg.host, cfg.port))
- else:
- fd = save.MigrationSocket((cfg.host, cfg.port))
-
- def postsuspend():
- 'Begin external checkpointing after domain has paused'
- if not cfg.timer:
- # when not using a timer thread, sleep until now + interval
- closure.starttime = time.time()
-
- if closure.cmd == 's':
- die()
-
- for buf in bufs:
- buf.postsuspend()
-
- if closure.cmd == 's2':
- die()
-
- def preresume():
- 'Complete external checkpointing before domain resumes'
- if closure.cmd == 'r':
- die()
-
- for buf in bufs:
- buf.preresume()
-
- if closure.cmd == 'r2':
- die()
-
- def commit():
- 'commit network buffer'
- if closure.cmd == 'c':
- die()
-
- print >> sys.stderr, "PROF: flushed memory at %0.6f" % (time.time())
-
- for buf in bufs:
- buf.commit()
-
- if closure.cmd == 'c2':
- die()
-
- # Since the domain is running at this point, it's a good time to
- # check for control channel commands
- getcommand()
-
- if not cfg.timer:
- endtime = time.time()
- elapsed = (endtime - closure.starttime) * 1000
-
- if elapsed < cfg.interval:
- time.sleep((cfg.interval - elapsed) / 1000.0)
-
- # False ends checkpointing
- return True
-
- if cfg.timer:
- interval = cfg.interval
- else:
- interval = 0
-
- rc = 0
-
- checkpointer = save.Saver(cfg.domid, fd, postsuspend, preresume, commit,
- interval, cfg.flags)
-
- try:
- checkpointer.start()
- except save.CheckpointError, e:
- print e
- rc = 1
- except KeyboardInterrupt:
- pass
- except SignalException:
- print '*** signalled ***'
-
- for buf in bufs:
- buf.uninstall()
-
- sys.exit(rc)
-
-cfg = Cfg()
-try:
- cfg.getargs()
-except CfgException, inst:
- print str(inst)
- cfg.usage()
- sys.exit(1)
-
-try:
- run(cfg)
-except vm.VMException, inst:
- print str(inst)
- sys.exit(1)
diff --git a/tools/tests/mce-test/tools/Makefile b/tools/tests/mce-test/tools/Makefile
index 8a23b83..aba7177 100644
--- a/tools/tests/mce-test/tools/Makefile
+++ b/tools/tests/mce-test/tools/Makefile
@@ -3,14 +3,16 @@ include $(XEN_ROOT)/tools/Rules.mk
CFLAGS += -Werror
CFLAGS += $(CFLAGS_libxenctrl)
+# xen-mceinj.c incorrectly use libxc internals
+CFLAGS += -I$(XEN_ROOT)/tools/libxc
CFLAGS += $(CFLAGS_libxenguest)
-CFLAGS += $(CFLAGS_libxenstore)
-CFLAGS += $(CFLAGS_xeninclude)
+CFLAGS += $(CFLAGS_libxenstore)
+CFLAGS += $(CFLAGS_xeninclude)
.PHONY: all
all: xen-mceinj
-install:
+install: xen-mceinj
$(INSTALL_PROG) xen-mceinj $(DESTDIR)$(SBINDIR)
.PHONY: clean
diff --git a/tools/tests/mce-test/tools/xen-mceinj.c b/tools/tests/mce-test/tools/xen-mceinj.c
index 21a488b..8ad045f 100644
--- a/tools/tests/mce-test/tools/xen-mceinj.c
+++ b/tools/tests/mce-test/tools/xen-mceinj.c
@@ -58,28 +58,59 @@
#define MSR_IA32_MC0_MISC 0x00000403
#define MSR_IA32_MC0_CTL2 0x00000280
-/* LLC (Last Level Cache) EWB (Explicit Write Back) SRAO MCE */
-#define MCG_STATUS_SRAO_LLC_VAL 0x5
-#define MCE_SRAO_LLC_BANK 0x7
-#define MCi_STATUS_SRAO_LLC_VAL 0xBD2000008000017AUL
-#define MCi_MISC_SRAO_LLC_VAL 0x86UL
-
-/* Memory Patrol Scrub SRAO MCE */
-#define MCG_STATUS_SRAO_MEM_VAL 0x5
-#define MCE_SRAO_MEM_BANK 0x8
-#define MCi_STATUS_SRAO_MEM_VAL 0xBD000000004000CFUL
-#define MCi_MISC_SRAO_MEM_VAL 0x86UL
-
-/* LLC EWB UCNA Error */
-#define MCG_STATUS_UCNA_LLC_VAL 0x0
-#define CMCI_UCNA_LLC_BANK 0x9
-#define MCi_STATUS_UCNA_LLC_VAL 0xBC20000080000136UL
-#define MCi_MISC_UCNA_LLC_VAL 0x86UL
-
-/* Error Types */
-#define MCE_SRAO_MEM 0x0
-#define MCE_SRAO_LLC 0x1
-#define CMCI_UCNA_LLC 0x2
+struct mce_info {
+ const char *description;
+ uint8_t mcg_stat;
+ unsigned int bank;
+ uint64_t mci_stat;
+ uint64_t mci_misc;
+ bool cmci;
+};
+
+static struct mce_info mce_table[] = {
+ /* LLC (Last Level Cache) EWB (Explicit Write Back) SRAO MCE */
+ {
+ .description = "MCE_SRAO_MEM",
+ .mcg_stat = 0x5,
+ .bank = 7,
+ .mci_stat = 0xBD2000008000017Aull,
+ .mci_misc = 0x86ull,
+ },
+ /* Memory Patrol Scrub SRAO MCE */
+ {
+ .description = "MCE_SRAO_LLC",
+ .mcg_stat = 0x5,
+ .bank = 8,
+ .mci_stat = 0xBD000000004000CFull,
+ .mci_misc = 0x86ull,
+ },
+ /* LLC EWB UCNA Error */
+ {
+ .description = "CMCI_UCNA_LLC",
+ .mcg_stat = 0x0,
+ .bank = 9,
+ .mci_stat = 0xBC20000080000136ull,
+ .mci_misc = 0x86ull,
+ .cmci = true,
+ },
+ /* AMD L1 instruction cache data or tag parity. */
+ {
+ .description = "AMD L1 icache parity",
+ .mcg_stat = 0x5,
+ .bank = 1,
+ .mci_stat = 0x9400000000000151ull,
+ .mci_misc = 0x86ull,
+ },
+ /* LLC (Last Level Cache) EWB (Explicit Write Back) SRAO MCE */
+ {
+ .description = "MCE_SRAO_MEM (Fatal)",
+ .mcg_stat = 0x5,
+ .bank = 7,
+ .mci_stat = 0xBF2000008000017Aull,
+ .mci_misc = 0x86ull,
+ },
+};
+#define MCE_TABLE_SIZE (sizeof(mce_table)/sizeof(mce_table[0]))
#define LOGFILE stdout
@@ -94,7 +125,7 @@ static void Lprintf(const char *fmt, ...)
va_start(args, fmt);
if (vasprintf(&buf, fmt, args) < 0)
abort();
- fprintf(LOGFILE, "%s", buf);
+ fprintf(LOGFILE, "%s\n", buf);
va_end(args);
free(buf);
}
@@ -156,7 +187,7 @@ static int inject_cmci(xc_interface *xc_handle, int cpu_nr)
nr_cpus = mca_cpuinfo(xc_handle);
if (!nr_cpus)
- err(xc_handle, "Failed to get mca_cpuinfo\n");
+ err(xc_handle, "Failed to get mca_cpuinfo");
mc.cmd = XEN_MC_inject_v2;
mc.interface_version = XEN_MCA_INTERFACE_VERSION;
@@ -273,32 +304,31 @@ static uint64_t guest_mfn(xc_interface *xc_handle,
max_gpfn = do_memory_op(xc_handle, XENMEM_maximum_gpfn, &domain,
sizeof(domain)) + 1;
if ( max_gpfn <= 0 )
- err(xc_handle, "Failed to get max_gpfn 0x%lx\n", max_gpfn);
+ err(xc_handle, "Failed to get max_gpfn 0x%lx", max_gpfn);
- Lprintf("Maxium gpfn for dom %d is 0x%lx\n", domain, max_gpfn);
+ Lprintf("Maxium gpfn for dom %d is 0x%lx", domain, max_gpfn);
/* Get max mfn */
if ( !get_platform_info(xc_handle, domain,
&max_mfn, &hvirt_start,
&pt_levels, &guest_width) )
- err(xc_handle, "Failed to get platform information\n");
+ err(xc_handle, "Failed to get platform information");
/* Get guest's pfn list */
- pfn_buf = malloc(sizeof(uint64_t) * max_gpfn);
+ pfn_buf = calloc(max_gpfn, sizeof(uint64_t));
if ( !pfn_buf )
- err(xc_handle, "Failed to alloc pfn buf\n");
- memset(pfn_buf, 0, sizeof(uint64_t) * max_gpfn);
+ err(xc_handle, "Failed to alloc pfn buf");
ret = xc_get_pfn_list(xc_handle, domain, pfn_buf, max_gpfn);
if ( ret < 0 ) {
free(pfn_buf);
- err(xc_handle, "Failed to get pfn list %x\n", ret);
+ err(xc_handle, "Failed to get pfn list %x", ret);
}
/* Now get the m2p table */
live_m2p = xc_map_m2p(xc_handle, max_mfn, PROT_READ, &m2p_mfn0);
if ( !live_m2p )
- err(xc_handle, "Failed to map live M2P table\n");
+ err(xc_handle, "Failed to map live M2P table");
/* match the mapping */
for ( i = 0; i < max_gpfn; i++ )
@@ -309,7 +339,7 @@ static uint64_t guest_mfn(xc_interface *xc_handle,
if (mfn_valid(tmp) && (mfn_to_pfn(tmp) == gpfn))
{
mfn = tmp;
- Lprintf("We get the mfn 0x%lx for this injection\n", mfn);
+ Lprintf("We get the mfn 0x%lx for this injection", mfn);
break;
}
}
@@ -334,7 +364,7 @@ static uint64_t mca_gpfn_to_mfn(xc_interface *xc_handle,
max_gpfn = do_memory_op(xc_handle, XENMEM_maximum_gpfn, &domain,
sizeof(domain)) + 1;
if ( max_gpfn <= 0 )
- err(xc_handle, "Failed to get max_gpfn 0x%lx\n", max_gpfn);
+ err(xc_handle, "Failed to get max_gpfn 0x%lx", max_gpfn);
index = gfn % max_gpfn;
return guest_mfn(xc_handle, domain, index);
@@ -375,125 +405,44 @@ static int inject_mci_addr(xc_interface *xc_handle,
MCi_type_ADDR, bank, val);
}
-static int inject_llc_srao(xc_interface *xc_handle,
- uint32_t cpu_nr,
- uint32_t domain,
- uint64_t gaddr)
-{
- uint64_t gpfn, mfn, haddr;
- int ret = 0;
-
- ret = inject_mcg_status(xc_handle, cpu_nr, MCG_STATUS_SRAO_LLC_VAL);
- if ( ret )
- err(xc_handle, "Failed to inject MCG_STATUS MSR\n");
-
- ret = inject_mci_status(xc_handle, cpu_nr,
- MCE_SRAO_LLC_BANK, MCi_STATUS_SRAO_LLC_VAL);
- if ( ret )
- err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
-
- ret = inject_mci_misc(xc_handle, cpu_nr,
- MCE_SRAO_LLC_BANK, MCi_MISC_SRAO_LLC_VAL);
- if ( ret )
- err(xc_handle, "Failed to inject MCi_MISC MSR\n");
-
- gpfn = gaddr >> PAGE_SHIFT;
- mfn = mca_gpfn_to_mfn(xc_handle, domain, gpfn);
- if (!mfn_valid(mfn))
- err(xc_handle, "The MFN is not valid\n");
- haddr = (mfn << PAGE_SHIFT) | (gaddr & (PAGE_SIZE - 1));
- ret = inject_mci_addr(xc_handle, cpu_nr, MCE_SRAO_LLC_BANK, haddr);
- if ( ret )
- err(xc_handle, "Failed to inject MCi_ADDR MSR\n");
-
- ret = flush_msr_inj(xc_handle);
- if ( ret )
- err(xc_handle, "Failed to inject MSR\n");
- ret = inject_mce(xc_handle, cpu_nr);
- if ( ret )
- err(xc_handle, "Failed to inject MCE error\n");
-
- return 0;
-}
-
-static int inject_mem_srao(xc_interface *xc_handle,
- uint32_t cpu_nr,
- uint32_t domain,
- uint64_t gaddr)
+static int inject(xc_interface *xc_handle, struct mce_info *mce,
+ uint32_t cpu_nr, uint32_t domain, uint64_t gaddr)
{
uint64_t gpfn, mfn, haddr;
int ret = 0;
- ret = inject_mcg_status(xc_handle, cpu_nr, MCG_STATUS_SRAO_MEM_VAL);
+ ret = inject_mcg_status(xc_handle, cpu_nr, mce->mcg_stat);
if ( ret )
- err(xc_handle, "Failed to inject MCG_STATUS MSR\n");
+ err(xc_handle, "Failed to inject MCG_STATUS MSR");
ret = inject_mci_status(xc_handle, cpu_nr,
- MCE_SRAO_MEM_BANK, MCi_STATUS_SRAO_MEM_VAL);
+ mce->bank, mce->mci_stat);
if ( ret )
- err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
+ err(xc_handle, "Failed to inject MCi_STATUS MSR");
ret = inject_mci_misc(xc_handle, cpu_nr,
- MCE_SRAO_MEM_BANK, MCi_MISC_SRAO_MEM_VAL);
+ mce->bank, mce->mci_misc);
if ( ret )
- err(xc_handle, "Failed to inject MCi_MISC MSR\n");
+ err(xc_handle, "Failed to inject MCi_MISC MSR");
gpfn = gaddr >> PAGE_SHIFT;
mfn = mca_gpfn_to_mfn(xc_handle, domain, gpfn);
if (!mfn_valid(mfn))
- err(xc_handle, "The MFN is not valid\n");
+ err(xc_handle, "The MFN is not valid");
haddr = (mfn << PAGE_SHIFT) | (gaddr & (PAGE_SIZE - 1));
- ret = inject_mci_addr(xc_handle, cpu_nr, MCE_SRAO_MEM_BANK, haddr);
+ ret = inject_mci_addr(xc_handle, cpu_nr, mce->bank, haddr);
if ( ret )
- err(xc_handle, "Failed to inject MCi_ADDR MSR\n");
+ err(xc_handle, "Failed to inject MCi_ADDR MSR");
ret = flush_msr_inj(xc_handle);
if ( ret )
- err(xc_handle, "Failed to inject MSR\n");
- ret = inject_mce(xc_handle, cpu_nr);
- if ( ret )
- err(xc_handle, "Failed to inject MCE error\n");
-
- return 0;
-}
-
-static int inject_llc_ucna(xc_interface *xc_handle,
- uint32_t cpu_nr,
- uint32_t domain,
- uint64_t gaddr)
-{
- uint64_t gpfn, mfn, haddr;
- int ret = 0;
-
- ret = inject_mcg_status(xc_handle, cpu_nr, MCG_STATUS_UCNA_LLC_VAL);
- if ( ret )
- err(xc_handle, "Failed to inject MCG_STATUS MSR\n");
-
- ret = inject_mci_status(xc_handle, cpu_nr,
- CMCI_UCNA_LLC_BANK, MCi_STATUS_UCNA_LLC_VAL);
- if ( ret )
- err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
-
- ret = inject_mci_misc(xc_handle, cpu_nr,
- CMCI_UCNA_LLC_BANK, MCi_MISC_UCNA_LLC_VAL);
- if ( ret )
- err(xc_handle, "Failed to inject MCi_MISC MSR\n");
-
- gpfn = gaddr >> PAGE_SHIFT;
- mfn = mca_gpfn_to_mfn(xc_handle, domain, gpfn);
- if (!mfn_valid(mfn))
- err(xc_handle, "The MFN is not valid\n");
- haddr = (mfn << PAGE_SHIFT) | (gaddr & (PAGE_SIZE - 1));
- ret = inject_mci_addr(xc_handle, cpu_nr, CMCI_UCNA_LLC_BANK, haddr);
- if ( ret )
- err(xc_handle, "Failed to inject MCi_ADDR MSR\n");
-
- ret = flush_msr_inj(xc_handle);
- if ( ret )
- err(xc_handle, "Failed to inject MSR\n");
- ret = inject_cmci(xc_handle, cpu_nr);
+ err(xc_handle, "Failed to inject MSR");
+ if ( mce->cmci )
+ ret = inject_cmci(xc_handle, cpu_nr);
+ else
+ ret = inject_mce(xc_handle, cpu_nr);
if ( ret )
- err(xc_handle, "Failed to inject MCE error\n");
+ err(xc_handle, "Failed to inject MCE error");
return 0;
}
@@ -528,33 +477,33 @@ static struct option opts[] = {
{"domain", 0, 0, 'd'},
{"dump", 0, 0, 'D'},
{"help", 0, 0, 'h'},
- {"log", 0, 0, 'l'},
{"page", 0, 0, 'p'},
{"", 0, 0, '\0'}
};
static void help(void)
{
+ unsigned int i;
+
printf("Usage: xen-mceinj [OPTION]...\n"
"\n"
"Mandatory arguments to long options are mandatory"
"for short options too.\n"
" -D, --dump dump addr info without error injection\n"
- " -c, --cpu=CPU_ID target CPU\n"
- " -d, --domain=DomID target domain, the default is Xen itself\n"
+ " -c, --cpu=CPU target CPU\n"
+ " -d, --domain=DOMID target domain, the default is Xen itself\n"
" -h, --help print this page\n"
- " -p, --phyaddr physical address\n"
- " -t, --type=error error type\n"
- " 0 : MCE_SRAO_MEM\n"
- " 1 : MCE_SRAO_LLC\n"
- " 2 : CMCI_UCNA_LLC\n"
- "\n"
- );
+ " -p, --page=ADDR physical address to report\n"
+ " -t, --type=ERROR error type\n");
+
+ for ( i = 0; i < MCE_TABLE_SIZE; i++ )
+ printf(" %2d : %s\n",
+ i, mce_table[i].description);
}
int main(int argc, char *argv[])
{
- int type = MCE_SRAO_MEM;
+ int type = 0;
int c, opt_index;
uint32_t domid;
xc_interface *xc_handle;
@@ -569,12 +518,12 @@ int main(int argc, char *argv[])
init_msr_inj();
xc_handle = xc_interface_open(0, 0, 0);
if ( !xc_handle ) {
- Lprintf("Failed to get xc interface\n");
+ Lprintf("Failed to get xc interface");
exit(EXIT_FAILURE);
}
while ( 1 ) {
- c = getopt_long(argc, argv, "c:Dd:t:hp:r", opts, &opt_index);
+ c = getopt_long(argc, argv, "c:Dd:t:hp:", opts, &opt_index);
if ( c == -1 )
break;
switch ( c ) {
@@ -584,17 +533,17 @@ int main(int argc, char *argv[])
case 'c':
cpu_nr = strtol(optarg, &optarg, 10);
if ( strlen(optarg) != 0 )
- err(xc_handle, "Please input a digit parameter for CPU\n");
+ err(xc_handle, "Please input a digit parameter for CPU");
break;
case 'd':
domid = strtol(optarg, &optarg, 10);
if ( strlen(optarg) != 0 )
- err(xc_handle, "Please input a digit parameter for domain\n");
+ err(xc_handle, "Please input a digit parameter for domain");
break;
case 'p':
gaddr = strtol(optarg, &optarg, 0);
if ( strlen(optarg) != 0 )
- err(xc_handle, "Please input correct page address\n");
+ err(xc_handle, "Please input correct page address");
break;
case 't':
type = strtol(optarg, NULL, 0);
@@ -608,43 +557,33 @@ int main(int argc, char *argv[])
if ( domid != DOMID_XEN ) {
max_gpa = xs_get_dom_mem(domid);
- Lprintf("get domain %d max gpa is: 0x%lx \n", domid, max_gpa);
+ Lprintf("get domain %d max gpa is: 0x%lx", domid, max_gpa);
if ( gaddr >= max_gpa )
- err(xc_handle, "Fail: gaddr exceeds max_gpa 0x%lx\n", max_gpa);
+ err(xc_handle, "Fail: gaddr exceeds max_gpa 0x%lx", max_gpa);
}
- Lprintf("get gaddr of error inject is: 0x%lx \n", gaddr);
+ Lprintf("get gaddr of error inject is: 0x%lx", gaddr);
if ( dump ) {
gpfn = gaddr >> PAGE_SHIFT;
mfn = mca_gpfn_to_mfn(xc_handle, domid, gpfn);
if (!mfn_valid(mfn))
- err(xc_handle, "The MFN is not valid\n");
+ err(xc_handle, "The MFN is not valid");
haddr = (mfn << PAGE_SHIFT) | (gaddr & (PAGE_SIZE - 1));
if ( domid == DOMID_XEN )
- Lprintf("Xen: mfn=0x%lx, haddr=0x%lx\n", mfn, haddr);
+ Lprintf("Xen: mfn=0x%lx, haddr=0x%lx", mfn, haddr);
else
- Lprintf("Dom%d: gaddr=0x%lx, gpfn=0x%lx,"
- "mfn=0x%lx, haddr=0x%lx\n",
+ Lprintf("Dom%d: gaddr=0x%lx, gpfn=0x%lx, mfn=0x%lx, haddr=0x%lx",
domid, gaddr, gpfn, mfn, haddr);
goto out;
}
- switch ( type )
- {
- case MCE_SRAO_MEM:
- inject_mem_srao(xc_handle, cpu_nr, domid, gaddr);
- break;
- case MCE_SRAO_LLC:
- inject_llc_srao(xc_handle, cpu_nr, domid, gaddr);
- break;
- case CMCI_UCNA_LLC:
- inject_llc_ucna(xc_handle, cpu_nr, domid, gaddr);
- break;
- default:
- err(xc_handle, "Unsupported error type\n");
- break;
+ if ( type < 0 || type >= MCE_TABLE_SIZE ) {
+ err(xc_handle, "Unsupported error type");
+ goto out;
}
+ inject(xc_handle, &mce_table[type], cpu_nr, domid, gaddr);
+
out:
xc_interface_close(xc_handle);
return 0;
diff --git a/tools/tests/utests/run_all_tests.py b/tools/tests/utests/run_all_tests.py
index e36fa4d..3e302dd 100644
--- a/tools/tests/utests/run_all_tests.py
+++ b/tools/tests/utests/run_all_tests.py
@@ -17,15 +17,7 @@
import unittest
-import utests.ut_util.ut_fileuri
-import utests.ut_xend.ut_XendConfig
-import utests.ut_xend.ut_image
-
-suite = unittest.TestSuite(
- [utests.ut_util.ut_fileuri.suite(),
- utests.ut_xend.ut_XendConfig.suite(),
- utests.ut_xend.ut_image.suite(),
- ])
+suite = unittest.TestSuite([])
if __name__ == "__main__":
testresult = unittest.TextTestRunner(verbosity=3).run(suite)
diff --git a/tools/tests/utests/ut_util/ut_fileuri.py b/tools/tests/utests/ut_util/ut_fileuri.py
deleted file mode 100644
index cd64e7d..0000000
--- a/tools/tests/utests/ut_util/ut_fileuri.py
+++ /dev/null
@@ -1,209 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2009 flonatel GmbH & Co. KG
-#============================================================================
-
-import os
-import unittest
-
-from xen.util.fileuri import scheme_error
-from xen.util.fileuri import scheme_data
-from xen.util.fileuri import scheme_file
-from xen.util.fileuri import schemes
-
-class scheme_data_unit_tests(unittest.TestCase):
-
- def check_basic_encoding(self):
- "util.fileuri.scheme_data - basic encoding"
- sd = scheme_data.encode('Hello!')
- self.assertEqual(sd, 'data:application/octet-stream;base64,SGVsbG8h')
-
- def check_encoding_with_given_mediatype(self):
- "util.fileuri.scheme_data - encoding with given media name"
- sd = scheme_data.encode('Hello!', 'application/x-my-linux-kernel')
- self.assertEqual(sd,
- 'data:application/x-my-linux-kernel;base64,SGVsbG8h')
-
- def check_parse_01(self):
- "util.fileuri.scheme_data - parsing of None"
- self.assertRaises(scheme_error, scheme_data.parse, None)
-
- def check_parse_02(self):
- "util.fileuri.scheme_data - parsing of empty string"
- self.assertRaises(scheme_error, scheme_data.parse, "")
-
- def check_parse_03(self):
- "util.fileuri.scheme_data - parsing of unstructured data"
- self.assertRaises(scheme_error, scheme_data.parse, "akskdjdfhezezu")
-
- def check_parse_04(self):
- "util.fileuri.scheme_data - data: is not at the first place"
- self.assertRaises(scheme_error, scheme_data.parse, 'ggdata:sossm')
-
- def check_parse_05(self):
- "util.fileuri.scheme_data - no comma in data"
- self.assertRaises(scheme_error, scheme_data.parse, 'data:sossm')
-
- def check_parse_06(self):
- "util.fileuri.scheme_data - encoding is empty"
- self.assertRaises(scheme_error, scheme_data.parse, 'data:,')
-
- def check_parse_07(self):
- "util.fileuri.scheme_data - unknown encoding"
- self.assertRaises(scheme_error, scheme_data.parse,
- 'data:somemediatype;unknown,')
-
- def check_parse_08(self):
- "util.fileuri.scheme_data - parse ok - empty data"
- mediatype, encoding, data_start = scheme_data.parse(
- 'data:somemedia;base64,')
- self.assertEqual(mediatype, 'somemedia')
- self.assertEqual(encoding, 'base64')
- self.assertEqual(data_start, 22)
-
- def check_parse_09(self):
- "util.fileuri.scheme_data - parse ok - some data"
- mediatype, encoding, data_start = scheme_data.parse(
- 'data:somemedia;base64,HereComesTheSun')
- self.assertEqual(mediatype, 'somemedia')
- self.assertEqual(encoding, 'base64')
- self.assertEqual(data_start, 22)
-
- def check_parse_10(self):
- "util.fileuri.scheme_data - header ok - data error"
- self.assertRaises(scheme_error, scheme_data.decode,
- 'data:application/octet-stream;base64,H!$ere"Co<mesT>heS_.un')
-
- def check_cff_file_does_not_exist(self):
- "util.fileuri.scheme_data - create from file - non existent file"
- self.assertRaises(scheme_error, scheme_data.create_from_file,
- "/there/is/hopefully/no/file/like/this")
-
- def check_cff_ok(self):
- "util.fileuri.scheme_data - create from file - ok"
- tmppath = "/tmp/scheme_data_check_cff_ok"
- f = open(tmppath, "w")
- f.write("huhuhu")
- f.close()
- d = scheme_data.create_from_file(tmppath)
- os.unlink(tmppath)
- self.assertEqual(d, "data:application/octet-stream;base64,aHVodWh1")
-
-
-class scheme_file_unit_tests(unittest.TestCase):
-
- def check_encode_empty_filename(self):
- "util.fileuri.scheme_file - encode empty filename"
- self.assertRaises(scheme_error, scheme_file.encode, "")
-
- def check_encode_relative_filename(self):
- "util.fileuri.scheme_file - encode relative filename"
- self.assertRaises(scheme_error, scheme_file.encode, "../there")
-
- def check_encode_absolut_filename(self):
- "util.fileuri.scheme_file - encode absolut filename"
- self.assertEqual(
- scheme_file.encode("/here/and/there/again"),
- 'file:///here/and/there/again')
-
- def check_decode_01(self):
- "util.fileuri.scheme_file - decode empty data"
- self.assertRaises(scheme_error, scheme_file.decode, "")
-
- def check_decode_02(self):
- "util.fileuri.scheme_file - decode data with no file:// at the beginning (1)"
- self.assertRaises(scheme_error, scheme_file.decode,
- "phonehome://bbbb")
-
- def check_decode_03(self):
- "util.fileuri.scheme_file - decode data with no file:// at the beginning (2)"
- self.assertRaises(scheme_error, scheme_file.decode,
- "file:/bbbb")
-
- def check_decode_04(self):
- "util.fileuri.scheme_file - decode empty path"
- self.assertRaises(scheme_error, scheme_file.decode,
- "file://")
-
- def check_decode_05(self):
- "util.fileuri.scheme_file - decode empty relative path"
- self.assertRaises(scheme_error, scheme_file.decode,
- "file://somewhere")
-
- def check_decode_06(self):
- "util.fileuri.scheme_file - decode ok"
- path, tmp_file = scheme_file.decode("file:///boot/vmlinuz")
- self.assertEqual(path, "/boot/vmlinuz")
- self.assertEqual(tmp_file, False)
-
-class scheme_set_unit_tests(unittest.TestCase):
-
- def check_data_01(self):
- "util.fileuri.scheme_set - data with error in media type"
-
- u = "data:something_wrong,base64:swer"
- uri, tmp_file = schemes.decode(u)
- self.assertEqual(uri, u)
- self.assertEqual(tmp_file, False)
-
- def check_data_02(self):
- "util.fileuri.scheme_set - data with error in base64 data"
-
- u = "data:application/octet-stream;base64,S!VsbG8h"
- uri, tmp_file = schemes.decode(u)
- self.assertEqual(uri, u)
- self.assertEqual(tmp_file, False)
-
- def check_data_03(self):
- "util.fileuri.scheme_set - data ok"
-
- u = "data:application/octet-stream;base64,SGVsbG8h"
- uri, tmp_file = schemes.decode(u)
-
- # Read file contents
- f = open(uri, "r")
- d = f.read()
- f.close()
- os.unlink(uri)
-
- self.assertEqual(d, "Hello!")
- self.assertEqual(tmp_file, True)
-
- def check_file_01(self):
- "util.fileuri.scheme_set - file ok"
-
- f = "/The/Path/To/The/File.txt"
- uri, tmp_file = schemes.decode("file://" + f)
- self.assertEqual(uri, f)
- self.assertEqual(tmp_file, False)
-
- def check_without_scheme_01(self):
- "util.fileuri.scheme_set - without scheme"
-
- f = "/The/Path/To/The/File.txt"
- uri, tmp_file = schemes.decode(f)
- self.assertEqual(uri, f)
- self.assertEqual(tmp_file, False)
-
-
-def suite():
- return unittest.TestSuite(
- [unittest.makeSuite(scheme_data_unit_tests, 'check_'),
- unittest.makeSuite(scheme_file_unit_tests, 'check_'),
- unittest.makeSuite(scheme_set_unit_tests, 'check_'),])
-
-if __name__ == "__main__":
- testresult = unittest.TextTestRunner(verbosity=3).run(suite())
-
diff --git a/tools/tests/utests/ut_xend/ut_XendConfig.py b/tools/tests/utests/ut_xend/ut_XendConfig.py
deleted file mode 100644
index 724ad08..0000000
--- a/tools/tests/utests/ut_xend/ut_XendConfig.py
+++ /dev/null
@@ -1,117 +0,0 @@
-#===========================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2009 flonatel GmbH & Co. KG
-#============================================================================
-
-import os
-import unittest
-
-# This does not work because of a cyclic import loop
-#from xen.xend.XendConfig import XendConfig
-import xen.xend.XendDomain
-
-class XendConfigUnitTest(unittest.TestCase):
-
- def minimal_vmconf(self):
- return {
- 'memory_dynamic_min': 64,
- 'memory_dynamic_max': 128,
- 'memory_static_max': 128,
- }
-
- def check_hf_01(self):
- "xend.XendConfig.handle_fileutils - PV_kernel/ramdisk not set"
- vmconf = self.minimal_vmconf()
- xc = xen.xend.XendConfig.XendConfig(xapi = vmconf)
-
- self.assert_(not xc.has_key('use_tmp_kernel'))
- self.assert_(not xc.has_key('use_tmp_ramdisk'))
-
- def check_hf_02(self):
- "xend.XendConfig.handle_fileutils - PV_kernel/ramdisk set to some path"
- vmconf = self.minimal_vmconf()
- vmconf['PV_kernel'] = '/some/where/under/the/rainbow-kernel'
- vmconf['PV_ramdisk'] = '/some/where/under/the/rainbow-ramdisk'
- xc = xen.xend.XendConfig.XendConfig(xapi = vmconf)
-
- self.assert_(xc.has_key('use_tmp_kernel'))
- self.assert_(xc.has_key('use_tmp_ramdisk'))
-
- self.assert_(not xc['use_tmp_kernel'])
- self.assert_(not xc['use_tmp_ramdisk'])
-
- def check_hf_03(self):
- "xend.XendConfig.handle_fileutils - PV_kernel/ramdisk using file: scheme"
- vmconf = self.minimal_vmconf()
- vmconf['PV_kernel'] = 'file:///some/where/under/the/rainbow-kernel'
- vmconf['PV_ramdisk'] = 'file:///some/where/under/the/rainbow-ramdisk'
- xc = xen.xend.XendConfig.XendConfig(xapi = vmconf)
-
- self.assert_(xc.has_key('use_tmp_kernel'))
- self.assert_(xc.has_key('use_tmp_ramdisk'))
-
- self.assert_(not xc['use_tmp_kernel'])
- self.assert_(not xc['use_tmp_ramdisk'])
-
- self.assert_('PV_kernel' in xc)
- self.assert_('PV_ramdisk' in xc)
-
- self.assertEqual("/some/where/under/the/rainbow-kernel",
- xc['PV_kernel'])
- self.assertEqual("/some/where/under/the/rainbow-ramdisk",
- xc['PV_ramdisk'])
-
- def check_hf_04(self):
- "xend.XendConfig.handle_fileutils - PV_kernel/ramdisk using data: scheme"
- vmconf = self.minimal_vmconf()
- vmconf['PV_kernel'] = 'data:application/octet-stream;base64,VGhpcyBpcyB0aGUga2VybmVsCg=='
- vmconf['PV_ramdisk'] = 'data:application/octet-stream;base64,TXkgZ3JlYXQgcmFtZGlzawo='
- xc = xen.xend.XendConfig.XendConfig(xapi = vmconf)
-
- self.assert_(xc.has_key('use_tmp_kernel'))
- self.assert_(xc.has_key('use_tmp_ramdisk'))
-
- self.assert_(xc['use_tmp_kernel'])
- self.assert_(xc['use_tmp_ramdisk'])
-
- self.assert_('PV_kernel' in xc)
- self.assert_('PV_ramdisk' in xc)
-
- self.assert_(xc['PV_kernel'].startswith(
- "/var/run/xend/boot/data_uri_file."))
- self.assert_(xc['PV_ramdisk'].startswith(
- "/var/run/xend/boot/data_uri_file."))
-
- f = file(xc['PV_kernel'])
- kc = f.read()
- f.close()
-
- f = file(xc['PV_ramdisk'])
- rc = f.read()
- f.close()
-
- os.unlink(xc['PV_kernel'])
- os.unlink(xc['PV_ramdisk'])
-
- self.assertEqual(kc, "This is the kernel\n")
- self.assertEqual(rc, "My great ramdisk\n")
-
-def suite():
- return unittest.TestSuite(
- [unittest.makeSuite(XendConfigUnitTest, 'check_'),])
-
-if __name__ == "__main__":
- testresult = unittest.TextTestRunner(verbosity=3).run(suite())
-
diff --git a/tools/tests/utests/ut_xend/ut_image.py b/tools/tests/utests/ut_xend/ut_image.py
deleted file mode 100644
index 92ec645..0000000
--- a/tools/tests/utests/ut_xend/ut_image.py
+++ /dev/null
@@ -1,147 +0,0 @@
-#===========================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2009 flonatel GmbH & Co. KG
-#============================================================================
-
-import unittest
-import tempfile
-import os
-
-import xen.xend.image
-
-class ImageHandlerUnitTests(unittest.TestCase):
-
- class ImageHandlerUnitTestsVirtualMachine:
-
- def __init__(self):
- self.info = {
- 'name_label': 'ItsMyParty',
- }
-
- def storeVm(self, *args):
- pass
-
- def permissionsVm(self, *args):
- pass
-
- def getDomid(self):
- return 7
-
- # Sets up a vm_config with no bootloader.
- def vm_config_no_bootloader(self):
- return {
- 'PV_kernel': 'value_of_PV_kernel',
- 'PV_args': 'value_of_PV_args',
- 'PV_ramdisk': 'value_of_PV_ramdisk',
- 'platform': {},
- 'console_refs': [],
- }
-
- def check_configure_01(self):
- # This retests the problem reported by Jun Koi on 24.07.2009
- # see http://lists.xensource.com/archives/html/xen-devel/2009-07/msg01006.html
- "ImageHandler - call configure with mostly empty vmConfig"
-
- vmConfig = self.vm_config_no_bootloader()
- vm = self.ImageHandlerUnitTestsVirtualMachine()
- ih = xen.xend.image.ImageHandler(vm, vmConfig)
-
- self.assertEqual(ih.use_tmp_kernel, False)
- self.assertEqual(ih.use_tmp_ramdisk, False)
-
- def check_configure_02(self):
- "ImageHandler - call configure with use_tmp_xxx set to false"
-
- vmConfig = self.vm_config_no_bootloader()
- vmConfig['use_tmp_kernel'] = False
- vmConfig['use_tmp_ramdisk'] = False
- vm = self.ImageHandlerUnitTestsVirtualMachine()
- ih = xen.xend.image.ImageHandler(vm, vmConfig)
-
- self.assertEqual(ih.use_tmp_kernel, False)
- self.assertEqual(ih.use_tmp_ramdisk, False)
-
-
- def check_configure_03(self):
- "ImageHandler - call configure with use_tmp_xxx set to true"
-
- vmConfig = self.vm_config_no_bootloader()
- vmConfig['use_tmp_kernel'] = True
- vmConfig['use_tmp_ramdisk'] = True
- vm = self.ImageHandlerUnitTestsVirtualMachine()
- ih = xen.xend.image.ImageHandler(vm, vmConfig)
-
- self.assertEqual(ih.use_tmp_kernel, True)
- self.assertEqual(ih.use_tmp_ramdisk, True)
-
- def cleanup_tmp_images_base(self, vmConfig):
- vm = self.ImageHandlerUnitTestsVirtualMachine()
- ih = xen.xend.image.ImageHandler(vm, vmConfig)
-
- k, ih.kernel = tempfile.mkstemp(
- prefix = "ImageHandler-cleanupTmpImages-k", dir = "/tmp")
- r, ih.ramdisk = tempfile.mkstemp(
- prefix = "ImageHandler-cleanupTmpImages-r", dir = "/tmp")
-
- ih.cleanupTmpImages()
-
- kres = os.path.exists(ih.kernel)
- rres = os.path.exists(ih.ramdisk)
-
- if not ih.use_tmp_kernel:
- os.unlink(ih.kernel)
- if not ih.use_tmp_ramdisk:
- os.unlink(ih.ramdisk)
-
- return kres, rres
-
- def check_cleanup_tmp_images_01(self):
- "ImageHandler - cleanupTmpImages with use_tmp_xxx unset"
-
- vmConfig = self.vm_config_no_bootloader()
- kres, rres = self.cleanup_tmp_images_base(vmConfig)
-
- self.assertEqual(kres, True)
- self.assertEqual(rres, True)
-
- def check_cleanup_tmp_images_02(self):
- "ImageHandler - cleanupTmpImages with use_tmp_xxx set to false"
-
- vmConfig = self.vm_config_no_bootloader()
- vmConfig['use_tmp_kernel'] = False
- vmConfig['use_tmp_ramdisk'] = False
- kres, rres = self.cleanup_tmp_images_base(vmConfig)
-
- self.assertEqual(kres, True)
- self.assertEqual(rres, True)
-
- def check_cleanup_tmp_images_03(self):
- "ImageHandler - cleanupTmpImages with use_tmp_xxx set to true"
-
- vmConfig = self.vm_config_no_bootloader()
- vmConfig['use_tmp_kernel'] = True
- vmConfig['use_tmp_ramdisk'] = True
- kres, rres = self.cleanup_tmp_images_base(vmConfig)
-
- self.assertEqual(kres, False)
- self.assertEqual(rres, False)
-
-def suite():
- return unittest.TestSuite(
- [unittest.makeSuite(ImageHandlerUnitTests, 'check_'),])
-
-if __name__ == "__main__":
- testresult = unittest.TextTestRunner(verbosity=3).run(suite())
-
diff --git a/tools/tests/vhpet/.gitignore b/tools/tests/vhpet/.gitignore
new file mode 100644
index 0000000..4cefa62
--- /dev/null
+++ b/tools/tests/vhpet/.gitignore
@@ -0,0 +1,4 @@
+test_vhpet
+test_vhpet.out
+hpet.h
+hpet.c
diff --git a/tools/tests/vhpet/Makefile b/tools/tests/vhpet/Makefile
new file mode 100644
index 0000000..763409d
--- /dev/null
+++ b/tools/tests/vhpet/Makefile
@@ -0,0 +1,36 @@
+
+XEN_ROOT=$(CURDIR)/../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+TARGET := test_vhpet
+
+.PHONY: all
+all: $(TARGET)
+
+.PHONY: run
+run: $(TARGET)
+ ./$(TARGET) > $(TARGET).out
+ ./$(TARGET) 0 > $(TARGET).0.out
+ ./$(TARGET) 0 1 0 20 > $(TARGET).0.1.0.20.out
+ ./$(TARGET) 200 > $(TARGET).200.out
+ ./$(TARGET) 200 1 0 20 > $(TARGET).200.1.0.20.out
+ ./$(TARGET) 300 5 > $(TARGET).200.5.out
+ ./$(TARGET) 400 4 2000 > $(TARGET).200.4.2000.out
+ ./$(TARGET) 0 1 0 20 0x0103 > $(TARGET).0.1.0.20.0x0103.out
+ ./$(TARGET) 200 1 0 20 0x0103 > $(TARGET).200.1.0.20.0x0103.out
+
+$(TARGET): hpet.c main.c hpet.h emul.h Makefile
+ $(HOSTCC) -g -o $@ hpet.c main.c
+
+.PHONY: clean
+clean:
+ rm -rf $(TARGET) $(TARGET).out *.o *~ core* hpet.h hpet.c
+
+.PHONY: install
+install:
+
+hpet.h: $(XEN_ROOT)/xen/include/asm-x86/hpet.h
+ cp $< $@
+
+hpet.c: $(XEN_ROOT)/xen/arch/x86/hvm/hpet.c
+ sed -e "/#include/d" -e "1i#include \"emul.h\"\n" <$< >$@
diff --git a/tools/tests/vhpet/emul.h b/tools/tests/vhpet/emul.h
new file mode 100644
index 0000000..09e4611
--- /dev/null
+++ b/tools/tests/vhpet/emul.h
@@ -0,0 +1,416 @@
+/*
+ * Xen emulation for hpet
+ *
+ * Copyright (C) 2014 Verizon Corporation
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License Version 2 (GPLv2)
+ * as published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details. <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+
+#define PCI_HAVE_64BIT_ADDRESS
+#include <pci/types.h>
+
+#include "hpet.h"
+
+#define NR_CPUS 8
+
+typedef int64_t s_time_t;
+typedef int spinlock_t;
+typedef int bool_t;
+
+#define BITS_PER_LONG __WORDSIZE
+#define BITS_TO_LONGS(bits) \
+ (((bits) + BITS_PER_LONG - 1) / BITS_PER_LONG)
+#define DECLARE_BITMAP(name, bits) \
+ unsigned long name[BITS_TO_LONGS(bits)]
+typedef struct cpumask
+{
+ DECLARE_BITMAP(bits, NR_CPUS);
+} cpumask_t;
+typedef cpumask_t *cpumask_var_t;
+struct msi_desc
+{
+ struct msi_attrib
+ {
+ u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */
+ u8 maskbit : 1; /* mask-pending bit supported ? */
+ u8 masked : 1;
+ u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
+ u8 pos; /* Location of the msi capability */
+ u16 entry_nr; /* specific enabled entry */
+ } msi_attrib;
+};
+
+struct msi_msg
+{
+ u32 address_lo; /* low 32 bits of msi message address */
+ u32 address_hi; /* high 32 bits of msi message address */
+ u32 data; /* 16 bits of msi message data */
+ u32 dest32; /* used when Interrupt Remapping with EIM is enabled */
+};
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif
+
+#define X86EMUL_OKAY 100
+#define EINVAL 101
+
+#define DBG_LEVEL_PIT 200
+
+#define TRC_HW_VCHIP_HPET_START_TIMER 300
+#define TRC_HW_VCHIP_HPET_STOP_TIMER 301
+#define TRC_HW_VCHIP_PIT_STOP_TIMER 302
+
+#define TRC_HVM_VCHIP_HPET_START_TIMER 400
+#define TRC_HVM_VCHIP_HPET_STOP_TIMER 401
+#define TRC_HVM_VCHIP_PIT_STOP_TIMER 402
+
+#define TRC_HVM_EMUL_HPET_START_TIMER 400
+#define TRC_HVM_EMUL_HPET_STOP_TIMER 401
+#define TRC_HVM_EMUL_PIT_STOP_TIMER 402
+
+#define __read_mostly
+#define __initdata
+#define __init
+#define __maybe_unused
+#define __cacheline_aligned
+#define boolean_param(a, b)
+#define fix_to_virt(a) a
+#define xmalloc_array(_type, _num) (void *)(_type)(_num)
+#define DEFINE_PER_CPU(_type, _name) _type _name
+
+#define KERN_DEBUG
+#define KERN_INFO
+
+#define XENLOG_WARNING
+#define XENLOG_INFO
+#define XENLOG_ERR
+#define XENLOG_GUEST
+
+#define MSI_TYPE_UNKNOWN 0
+#define MSI_TYPE_HPET 1
+#define MSI_TYPE_IOMMU 2
+
+#define STIME_MAX ((s_time_t)((uint64_t)~0ull>>1))
+
+/* Low-latency softirqs come first in the following list. */
+enum
+{
+ TIMER_SOFTIRQ = 0,
+ SCHEDULE_SOFTIRQ,
+ NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ,
+ RCU_SOFTIRQ,
+ TASKLET_SOFTIRQ,
+ NR_COMMON_SOFTIRQS
+};
+/*
+ * ..and if you can't take the strict
+ * types, you can specify one yourself.
+ *
+ * Or not use min/max at all, of course.
+ */
+#define min_t(type, x, y) \
+ ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; })
+#define max_t(type, x, y) \
+ ({ type __x = (x); type __y = (y); __x > __y ? __x : __y; })
+#define offsetof(t, m) ((unsigned long )&((t *)0)->m)
+#define container_of(ptr, type, member) ({ \
+ typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) ); })
+
+struct domain;
+
+struct vcpu
+{
+ int vcpu_id;
+ struct domain *domain;
+};
+
+typedef void time_cb(struct vcpu *v, void *opaque);
+
+struct periodic_time
+{
+#define PTSRC_isa 1 /* ISA time source */
+#define PTSRC_lapic 2 /* LAPIC time source */
+ u8 source; /* PTSRC_ */
+};
+
+void destroy_periodic_time(struct periodic_time *pt);
+void create_periodic_time(
+ struct vcpu *v, struct periodic_time *pt, uint64_t delta,
+ uint64_t period, uint8_t irq, time_cb *cb, void *data);
+
+#define HPET_TIMER_NUM 3
+
+struct hpet_registers
+{
+ /* Memory-mapped, software visible registers */
+ uint64_t capability; /* capabilities */
+ uint64_t config; /* configuration */
+ uint64_t isr; /* interrupt status reg */
+ uint64_t mc64; /* main counter */
+ struct /* timers */
+ {
+ uint64_t config; /* configuration/cap */
+ uint64_t cmp; /* comparator */
+ uint64_t fsb; /* FSB route, not supported now */
+ } timers[HPET_TIMER_NUM];
+
+ /* Hidden register state */
+ uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */
+ uint64_t comparator64[HPET_TIMER_NUM]; /* 64 bit running comparator */
+ uint64_t offset64[HPET_TIMER_NUM]; /* offset so comparator calc "works" */
+ uint64_t first_mc64[HPET_TIMER_NUM]; /* 1st interval main counter */
+ bool_t first_enabled[HPET_TIMER_NUM]; /* In 1st interval */
+};
+
+typedef struct HPETState
+{
+ struct hpet_registers hpet;
+ uint64_t stime_freq;
+ uint64_t hpet_to_ns_scale; /* hpet ticks to ns (multiplied by 2^10) */
+ uint64_t hpet_to_ns_limit; /* max hpet ticks convertable to ns */
+ uint64_t mc_offset;
+ struct periodic_time pt[HPET_TIMER_NUM];
+ spinlock_t lock;
+} HPETState;
+
+typedef struct PITState
+{
+ struct periodic_time pt0;
+ spinlock_t lock;
+} PITState;
+
+
+struct pl_time /* platform time */
+{
+ struct HPETState vhpet;
+ /* guest_time = Xen sys time + stime_offset */
+ int64_t stime_offset;
+ /* Ensures monotonicity in appropriate timer modes. */
+ uint64_t last_guest_time;
+ spinlock_t pl_time_lock;
+};
+
+#define HVM_PARAM_HPET_ENABLED 11
+
+struct hvm_domain
+{
+ struct pl_time pl_time;
+ long params[20];
+};
+
+struct arch_domain
+{
+ struct hvm_domain hvm_domain;
+ struct PITState vpit;
+};
+
+struct domain
+{
+ int domain_id;
+ struct arch_domain arch;
+ struct vcpu *vcpu[NR_CPUS];
+};
+
+typedef int (*hvm_mmio_read_t)(struct vcpu *v,
+ unsigned long addr,
+ unsigned long length,
+ unsigned long *val);
+typedef int (*hvm_mmio_write_t)(struct vcpu *v,
+ unsigned long addr,
+ unsigned long length,
+ unsigned long val);
+typedef int (*hvm_mmio_check_t)(struct vcpu *v, unsigned long addr);
+
+
+struct hvm_mmio_handler
+{
+ hvm_mmio_check_t check_handler;
+ hvm_mmio_read_t read_handler;
+ hvm_mmio_write_t write_handler;
+};
+
+/* Marshalling and unmarshalling uses a buffer with size and cursor. */
+typedef struct hvm_domain_context
+{
+ uint32_t cur;
+ uint32_t size;
+ uint8_t *data;
+} hvm_domain_context_t;
+
+int current_domain_id(void);
+#define dprintk(_l, _f, _a...) \
+ printk(_l "%s:%d: " _f, __FILE__ , __LINE__ , ## _a )
+#define gdprintk(_l, _f, _a...) \
+ printk(XENLOG_GUEST _l "%s:%d:d%d " _f, __FILE__, \
+ __LINE__, current_domain_id() , ## _a )
+struct vcpu *get_current();
+#define current get_current()
+
+#define HVM_SAVE_CODE(_x) HVM_SAVE_CODE_##_x
+#define HVM_SAVE_LENGTH(_x) HVM_SAVE_LENGTH_##_x
+
+/*
+ * HPET
+ */
+
+uint64_t hvm_get_guest_time(struct vcpu *v);
+
+#define HPET_TIMER_NUM 3 /* 3 timers supported now */
+struct hvm_hw_hpet
+{
+ /* Memory-mapped, software visible registers */
+ uint64_t capability; /* capabilities */
+ uint64_t res0; /* reserved */
+ uint64_t config; /* configuration */
+ uint64_t res1; /* reserved */
+ uint64_t isr; /* interrupt status reg */
+ uint64_t res2[25]; /* reserved */
+ uint64_t mc64; /* main counter */
+ uint64_t res3; /* reserved */
+ struct /* timers */
+ {
+ uint64_t config; /* configuration/cap */
+ uint64_t cmp; /* comparator */
+ uint64_t fsb; /* FSB route, not supported now */
+ uint64_t res4; /* reserved */
+ } timers[HPET_TIMER_NUM];
+ uint64_t res5[4 * (24 - HPET_TIMER_NUM)]; /* reserved, up to 0x3ff */
+
+ /* Hidden register state */
+ uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */
+};
+
+typedef int (*hvm_save_handler)(struct domain *d,
+ hvm_domain_context_t *h);
+typedef int (*hvm_load_handler)(struct domain *d,
+ hvm_domain_context_t *h);
+
+struct hvm_save_descriptor
+{
+ uint16_t typecode; /* Used to demux the various types below */
+ uint16_t instance; /* Further demux within a type */
+ uint32_t length; /* In bytes, *not* including this descriptor */
+};
+
+void hvm_register_savevm(uint16_t typecode,
+ const char *name,
+ hvm_save_handler save_state,
+ hvm_load_handler load_state,
+ size_t size, int kind);
+
+#define HVMSR_PER_DOM 1
+
+#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load, _num, _k) \
+ int __init __hvm_register_##_x##_save_and_restore(void) \
+ { \
+ hvm_register_savevm(HVM_SAVE_CODE(_x), \
+ #_x, \
+ &_save, \
+ &_load, \
+ (_num) * (HVM_SAVE_LENGTH(_x) \
+ + sizeof(struct hvm_save_descriptor)), \
+ _k); \
+ return 0; \
+ } \
+
+#define HVM_SAVE_CODE_HPET 0
+#define HVM_SAVE_LENGTH_HPET sizeof(struct hvm_hw_hpet)
+
+#define printk printf
+
+#define spin_lock(a)
+#define spin_unlock(a)
+#define spin_lock_init(a)
+#define spin_is_locked(a) 1
+#define ASSERT(a)
+
+#define ADDR (*(volatile long *) addr)
+
+static inline void __set_bit(int nr, volatile void *addr)
+{
+ asm volatile(
+ "btsl %1,%0"
+ : "=m"(ADDR)
+ : "Ir"(nr), "m"(ADDR) : "memory");
+}
+
+static inline void __clear_bit(int nr, volatile void *addr)
+{
+ asm volatile(
+ "btrl %1,%0"
+ : "=m"(ADDR)
+ : "Ir"(nr), "m"(ADDR) : "memory");
+}
+
+static inline unsigned int find_first_set_bit(unsigned long word)
+{
+ asm("bsf %1,%0" : "=r"(word) : "r"(word));
+ return (unsigned int)word;
+}
+
+#define HVM_DBG_LOG(level, _f, _a...) \
+ do { \
+ printf("[HVM:%d.%d] <%s> " _f "\n", \
+ current->domain->domain_id, current->vcpu_id, __func__, \
+ ## _a); \
+ } while ( 0 )
+
+void __domain_crash(struct domain *d);
+#define domain_crash(d) do { \
+ printf("domain_crash called from %s:%d\n", __FILE__, __LINE__); \
+ __domain_crash(d); \
+ } while ( 0 )
+
+#define MICROSECS(_us) ((s_time_t)((_us) * 1000ULL))
+
+#define pt_global_vcpu_target(d) \
+ ((d)->vcpu ? (d)->vcpu[0] : NULL)
+
+#define TRACE_0D(a)
+#define TRACE_1D(a, b)
+#define TRACE_2D(a, b, c)
+#define TRACE_3D(a, b, c, d)
+#define TRACE_4D(a, b, c, d, e)
+#define TRACE_5D(a, b, c, d, e, f)
+#define TRACE_6D(a, b, c, d, e, f, g)
+
+#define TRC_PAR_LONG(par) ((par)&0xFFFFFFFF),((par)>>32)
+
+#define TRACE_2_LONG_2D(_e, d1, d2, ...) \
+ TRACE_4D(_e, d1, d2)
+#define TRACE_2_LONG_3D(_e, d1, d2, d3, ...) \
+ TRACE_5D(_e, d1, d2, d3)
+#define TRACE_2_LONG_4D(_e, d1, d2, d3, d4, ...) \
+ TRACE_6D(_e, d1, d2, d3, d4)
+
+/* debug */
+
+extern int __read_mostly hpet_debug;
+extern uint64_t __read_mostly hpet_force_diff;
+extern uint64_t __read_mostly hpet_force_mc64;
+extern uint64_t __read_mostly hpet_force_cmp;
+extern uint64_t __read_mostly hpet_force_period;
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/tests/vhpet/main.c b/tools/tests/vhpet/main.c
new file mode 100644
index 0000000..fbd7510
--- /dev/null
+++ b/tools/tests/vhpet/main.c
@@ -0,0 +1,776 @@
+/*
+ * Xen emulation for hpet
+ *
+ * Copyright (C) 2014 Verizon Corporation
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License Version 2 (GPLv2)
+ * as published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details. <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * http://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf
+ *
+ * xen_source is a directory that has all xen source below it.
+ *
+ * Usage:
+ *
+
+
+ xen_source=../../..
+ sed -e "/#include/d" -e "1i#include \"emul.h\"\n" <$xen_source/xen/arch/x86/hvm/hpet.c >hpet.c
+ cp $xen_source/xen/include/asm-x86/hpet.h .
+
+ gcc -g -o test_vhpet hpet.c main.c
+ ./test_vhpet >test_vhpet.out
+
+ *
+ *
+ * This is almost the same as
+ *
+
+ make run
+
+ *
+ * Or
+ *
+ * make -C tools/tests/vhpet run
+ *
+ * From a xen source tree. The differance
+ * is that you need to be in a xen source tree
+ * and normal make rules apply.
+ *
+ */
+
+#define FORCE_THOUSANDS_SEP
+
+#include <locale.h>
+#include <langinfo.h>
+#include <stdarg.h>
+#include "emul.h"
+#include "hpet.h"
+
+#define S_TO_NS 1000000000ULL /* 1s = 10^9 ns */
+
+#define START_MC64 0x108a8
+
+static int hpet_mult = 1;
+static int hpet_add;
+static int hvm_clock_cost = 1234567;
+static int tick_count = 1;
+static int debug = 3;
+
+static int skip_load;
+static int skip_error_on_load;
+
+static char *global_thousep;
+
+extern const struct hvm_mmio_handler hpet_mmio_handler;
+
+struct domain dom1;
+struct vcpu vcpu0;
+struct hvm_hw_hpet hpet_save;
+
+
+uint64_t hvm_guest_time;
+
+static struct
+{
+ hvm_save_handler save;
+ hvm_load_handler load;
+ const char *name;
+ size_t size;
+ int kind;
+} hvm_sr_handlers[3] = {{NULL, NULL, "<?>"},};
+
+static uint64_t new_guest_time[] = {
+ 0x20,
+ 0x2a840,
+ 0xf4200,
+ 0x10000000000ULL,
+ 0x0fffffffffefff00ULL,
+ 0x20,
+ 0xffffffff00000000ULL,
+ 0x20,
+};
+
+static int print_error(const char *fmt, ...)
+{
+ va_list args;
+ int i = 0;
+
+ if ( (debug & 0x0100) && skip_error_on_load )
+ return i;
+
+ va_start(args, fmt);
+ if ( debug & 0x0001 )
+ i = vfprintf(stdout, fmt, args);
+ va_end(args);
+ va_start(args, fmt);
+ if ( debug & 0x0002 )
+ i = vfprintf(stderr, fmt, args);
+ va_end(args);
+ return i;
+}
+
+
+int current_domain_id(void)
+{
+ return current->domain->domain_id;
+}
+
+struct vcpu *get_current()
+{
+ return &vcpu0;
+}
+
+void __domain_crash(struct domain *d)
+{
+ exit(42);
+}
+
+uint64_t hvm_get_guest_time(struct vcpu *v)
+{
+ uint64_t ret = hvm_guest_time;
+
+ hvm_guest_time += hvm_clock_cost;
+ return ret;
+}
+
+int _hvm_init_entry(struct hvm_domain_context *h,
+ uint16_t tc, uint16_t inst, uint32_t len)
+{
+ h->cur = 0;
+ h->size = sizeof(hpet_save);
+ h->data = (void *)&hpet_save;
+
+ return 0;
+}
+
+int _hvm_check_entry(struct hvm_domain_context *h,
+ uint16_t type, uint32_t len, bool_t strict_length)
+{
+ h->cur = 0;
+ h->size = sizeof(hpet_save);
+ h->data = (void *)&hpet_save;
+
+ return 0;
+}
+
+void __init hvm_register_savevm(uint16_t typecode,
+ const char *name,
+ hvm_save_handler save_state,
+ hvm_load_handler load_state,
+ size_t size, int kind)
+{
+ hvm_sr_handlers[typecode].save = save_state;
+ hvm_sr_handlers[typecode].load = load_state;
+ hvm_sr_handlers[typecode].name = name;
+ hvm_sr_handlers[typecode].size = size;
+ hvm_sr_handlers[typecode].kind = kind;
+}
+
+int do_save(uint16_t typecode, struct domain *d, hvm_domain_context_t *h)
+{
+ return hvm_sr_handlers[typecode].save(d, h);
+}
+
+int do_load(uint16_t typecode, struct domain *d, hvm_domain_context_t *h)
+{
+ if (skip_load & 0x1)
+ {
+ printf("skip_load=%#x\n", skip_load);
+ }
+ else
+ {
+ int ret;
+
+ printf("do_load\n");
+ skip_error_on_load = 1;
+ ret = hvm_sr_handlers[typecode].load(d, h);
+ skip_error_on_load = 0;
+ }
+}
+
+static void dump_hpet(void)
+{
+ int i;
+ unsigned long long conf;
+ struct hvm_hw_hpet h = hpet_save;
+ conf = (unsigned long long) h.config;
+ printf(" HPET: capability %#llx config %#llx(%s%s)\n",
+ (unsigned long long) h.capability,
+ conf,
+ conf & HPET_CFG_ENABLE ? "E" : "",
+ conf & HPET_CFG_LEGACY ? "L" : "");
+ printf(" isr %#llx counter %#llx(%'lld)\n",
+ (unsigned long long) h.isr,
+ (unsigned long long) h.mc64,
+ (unsigned long long) h.mc64);
+ for (i = 0; i < HPET_TIMER_NUM; i++)
+ {
+ conf = (unsigned long long) h.timers[i].config;
+ printf(" timer%i config %#llx(%s%s%s) cmp %#llx(%'lld)\n", i,
+ conf,
+ conf & HPET_TN_ENABLE ? "E" : "",
+ conf & HPET_TN_PERIODIC ? "P" : "",
+ conf & HPET_TN_32BIT ? "32" : "",
+ (unsigned long long) h.timers[i].cmp,
+ (unsigned long long) h.timers[i].cmp);
+ printf(" timer%i period %#llx(%'lld) fsb %#llx\n", i,
+ (unsigned long long) h.period[i],
+ (unsigned long long) h.period[i],
+ (unsigned long long) h.timers[i].fsb);
+ }
+}
+
+void pit_stop_channel0_irq(PITState *pit)
+{
+ printf("pit_stop_channel0_irq: pit=%p\n", pit);
+
+ TRACE_1D(TRC_HVM_VCHIP_PIT_STOP_TIMER, get_cycles());
+ spin_lock(&pit->lock);
+ destroy_periodic_time(&pit->pt0);
+ spin_unlock(&pit->lock);
+}
+
+void destroy_periodic_time(struct periodic_time *pt)
+{
+ int idx = ((long)pt) & 0x7;
+
+ printf("destroy_periodic_time: pt=%d\n", idx);
+}
+
+void create_periodic_time(struct vcpu *v, struct periodic_time *pt,
+ uint64_t delta, uint64_t period, uint8_t irq,
+ time_cb *cb, void *data)
+{
+ int idx = ((long)pt) & 0x7;
+
+ if ( debug & 0x0010 )
+ {
+ int i;
+
+ printf("create_periodic_time: "
+ "mc64=%#lx(%'ld) mc_offset=%#lx(%'ld)\n",
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.mc64,
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.mc64,
+ dom1.arch.hvm_domain.pl_time.vhpet.mc_offset,
+ dom1.arch.hvm_domain.pl_time.vhpet.mc_offset);
+ for (i = 0; i < 3; i++)
+ {
+ printf(" "
+ "[%d] cmp64=%#lx(%'ld) cmp=%#lx(%'ld)\n", i,
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.comparator64[i],
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.comparator64[i],
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.timers[i].cmp,
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.timers[i].cmp);
+ }
+ }
+ if ( period )
+ {
+ printf("create_periodic_time: pt=%d delta=%'"PRId64" period=%'"PRIu64
+ " - %'"PRIu64".%02d Hz irq=%d\n",
+ idx, delta, period, (uint64_t)(S_TO_NS / period),
+ (int)((S_TO_NS / (period / 100ULL)) % 100), irq);
+ /* +160 is for hpet_tick_to_ns() not simple. */
+ if ( delta > (period * (hpet_mult + hpet_add + 160)) )
+ print_error("%s(%ld): Possible ..MP-BIOS bug: 8254 timer...: delta=%'"PRId64
+ " period=%'"PRIu64"\n", __func__, __LINE__,
+ delta, period);
+ }
+ else
+ printf("create_periodic_time: pt=%d delta=%'"PRId64
+ " period=%'"PRIu64" irq=%d\n",
+ idx, delta, period, irq);
+}
+
+void udelay(int w)
+{
+}
+
+unsigned int hpet_readl(unsigned long a)
+{
+ unsigned long ret = 0;
+ hpet_mmio_handler.read_handler(current, a, 4, &ret);
+ return ret;
+}
+
+void hpet_writel(unsigned long d, unsigned long a)
+{
+ hpet_mmio_handler.write_handler(current, a, 4, d);
+ return;
+}
+
+static void _hpet_print_config(const char *function, int line)
+{
+ u32 i, timers, l, h;
+ printk(KERN_INFO "hpet: %s(%d):\n", function, line);
+ l = hpet_readl(HPET_ID);
+ h = hpet_readl(HPET_PERIOD);
+ timers = ((l & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
+ printk(KERN_INFO "hpet: ID: 0x%x, PERIOD: 0x%x\n", l, h);
+ l = hpet_readl(HPET_CFG);
+ h = hpet_readl(HPET_STATUS);
+ printk(KERN_INFO "hpet: CFG: 0x%x, STATUS: 0x%x\n", l, h);
+ l = hpet_readl(HPET_COUNTER);
+ h = hpet_readl(HPET_COUNTER + 4);
+ printk(KERN_INFO "hpet: COUNTER_l: 0x%x, COUNTER_h: 0x%x\n", l, h);
+
+ for (i = 0; i < timers; i++)
+ {
+ l = hpet_readl(HPET_Tn_CFG(i));
+ h = hpet_readl(HPET_Tn_CFG(i) + 4);
+ printk(KERN_INFO "hpet: T%d: CFG_l: 0x%x, CFG_h: 0x%x\n",
+ i, l, h);
+ l = hpet_readl(HPET_Tn_CMP(i));
+ h = hpet_readl(HPET_Tn_CMP(i) + 4);
+ printk(KERN_INFO "hpet: T%d: CMP_l: 0x%x, CMP_h: 0x%x\n",
+ i, l, h);
+ l = hpet_readl(HPET_Tn_ROUTE(i));
+ h = hpet_readl(HPET_Tn_ROUTE(i) + 4);
+ printk(KERN_INFO "hpet: T%d ROUTE_l: 0x%x, ROUTE_h: 0x%x\n",
+ i, l, h);
+ }
+}
+
+#define hpet_print_config() \
+ do { \
+ _hpet_print_config(__func__, __LINE__); \
+ } while ( 0 )
+
+static void hpet_stop_counter(void)
+{
+ unsigned long cfg = hpet_readl(HPET_CFG);
+ cfg &= ~HPET_CFG_ENABLE;
+ hpet_writel(cfg, HPET_CFG);
+}
+
+static void hpet_reset_counter(unsigned long low, unsigned long high)
+{
+ hpet_writel(low, HPET_COUNTER);
+ hpet_writel(high, HPET_COUNTER + 4);
+}
+
+static void hpet_start_counter(void)
+{
+ unsigned long cfg = hpet_readl(HPET_CFG);
+ cfg |= HPET_CFG_ENABLE;
+ hpet_writel(cfg, HPET_CFG);
+}
+
+static void hpet_restart_counter(void)
+{
+ hpet_stop_counter();
+ hpet_reset_counter(0, 0);
+ hpet_start_counter();
+}
+
+static void hpet_set_mode(uint64_t delta, int timer)
+{
+ unsigned long cfg, cmp, cmp2, now;
+
+ hpet_stop_counter();
+ now = hpet_readl(HPET_COUNTER);
+ cmp = now + (unsigned long)(hpet_mult * delta) + hpet_add;
+ cfg = hpet_readl(HPET_Tn_CFG(timer));
+ /* Make sure we use edge triggered interrupts */
+ cfg &= ~HPET_TN_LEVEL;
+ cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
+ HPET_TN_SETVAL | HPET_TN_32BIT;
+ /* Mask to 32 bits just like the hardware */
+ cmp = (uint32_t)cmp;
+ delta = (uint32_t)delta;
+ /* Do the config */
+ hpet_writel(cfg, HPET_Tn_CFG(timer));
+ hpet_writel(cmp, HPET_Tn_CMP(timer));
+ printf("%s(%ld): HPET_TN_SETVAL cmp=%#lx(%'ld) timer=%d\n",
+ __func__, __LINE__, cmp, cmp, timer);
+ udelay(1);
+ /*
+ * HPET on AMD 81xx needs a second write (with HPET_TN_SETVAL
+ * cleared) to T0_CMP to set the period. The HPET_TN_SETVAL
+ * bit is automatically cleared after the first write.
+ * (See AMD-8111 HyperTransport I/O Hub Data Sheet,
+ * Publication # 24674)
+ */
+ hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer));
+ printf("%s(%ld): period=%#lx(%'ld) timer=%d\n", __func__, __LINE__,
+ (unsigned long) delta, (unsigned long) delta, timer);
+ cmp2 = hpet_readl(HPET_Tn_CMP(timer));
+ if ( cmp2 != cmp )
+ print_error("%s(%ld): T%d Error: Set %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, cmp, cmp, cmp2, cmp2);
+
+ hpet_start_counter();
+ hpet_print_config();
+}
+
+
+hpet_check_stopped(uint64_t old_delta, int timer)
+{
+ unsigned long mc_low, mc_high, old_cmp, now;
+ unsigned long cfg, cmp, delta, cmp2, cmp3;
+
+ if (skip_load & 0x2)
+ {
+ printf("Skip hpet_check_stopped. skip_load=%#x\n", skip_load);
+ return;
+ }
+ hpet_stop_counter();
+ mc_low = hpet_readl(HPET_COUNTER);
+ mc_high = hpet_readl(HPET_COUNTER + 4);
+ old_cmp = hpet_readl(HPET_Tn_CMP(timer));
+
+ hpet_reset_counter(67752, 0);
+ cmp = 255252;
+ delta = 62500;
+
+ now = hpet_readl(HPET_COUNTER);
+ if ( now != 67752 )
+ print_error("%s(%ld): T%d Error: Set mc %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, 67752, 67752, now, now);
+ cfg = hpet_readl(HPET_Tn_CFG(timer));
+ cfg |= HPET_TN_SETVAL;
+ hpet_writel(cfg, HPET_Tn_CFG(timer));
+ hpet_writel(cmp, HPET_Tn_CMP(timer));
+ printf("%s(%ld): HPET_TN_SETVAL cmp=%#lx(%'ld) timer=%d\n",
+ __func__, __LINE__, cmp, cmp, timer);
+ cmp2 = hpet_readl(HPET_Tn_CMP(timer));
+ if ( cmp2 != cmp )
+ print_error("%s(%ld): T%d Error: Set cmp %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, cmp, cmp, cmp2, cmp2);
+
+ hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer));
+ printf("%s(%ld): period=%#lx(%'ld) timer=%d\n", __func__, __LINE__,
+ (unsigned long) delta, (unsigned long) delta, timer);
+ cmp3 = hpet_readl(HPET_Tn_CMP(timer));
+ if ( cmp3 != cmp )
+ print_error("%s(%ld): T%d Error: Set period, cmp %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, cmp, cmp, cmp3, cmp3);
+
+ if ( dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer] != delta )
+ printf("%s(%ld): T%d Warning: Set period %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, delta, delta,
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer],
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer]);
+
+ hpet_reset_counter(67752, 0);
+ cmp = 255252;
+ delta = 62500;
+
+ now = hpet_readl(HPET_COUNTER);
+ if ( now != 67752 )
+ print_error("%s(%ld): T%d Error: Set mc %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, 67752, 67752, now, now);
+ cfg = hpet_readl(HPET_Tn_CFG(timer));
+ cfg |= HPET_TN_SETVAL;
+ hpet_writel(cfg, HPET_Tn_CFG(timer));
+ hpet_writel(cmp, HPET_Tn_CMP(timer));
+ printf("%s(%ld): HPET_TN_SETVAL cmp=%#lx(%'ld) timer=%d\n",
+ __func__, __LINE__, cmp, cmp, timer);
+ cmp2 = hpet_readl(HPET_Tn_CMP(timer));
+ if ( cmp2 != cmp )
+ print_error("%s(%ld): T%d Error: Set cmp %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, cmp, cmp, cmp2, cmp2);
+
+ hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer));
+ printf("%s(%ld): period=%#lx(%'ld) timer=%d\n", __func__, __LINE__,
+ (unsigned long) delta, (unsigned long) delta, timer);
+ cmp3 = hpet_readl(HPET_Tn_CMP(timer));
+ if ( cmp3 != cmp )
+ print_error("%s(%ld): T%d Error: Set period, cmp %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, cmp, cmp, cmp3, cmp3);
+
+ if ( dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer] != delta )
+ printf("%s(%ld): T%d Warning: Set period %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, delta, delta,
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer],
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer]);
+
+ hpet_reset_counter(67700, 0);
+
+ now = hpet_readl(HPET_COUNTER);
+ if ( now != 67700 )
+ print_error("%s(%ld): T%d Error: Set mc %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, 67752, 67752, now, now);
+ cmp2 = hpet_readl(HPET_Tn_CMP(timer));
+ if ( cmp2 != cmp )
+ print_error("%s(%ld): T%d Error: Set mc, cmp %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, cmp, cmp, cmp2, cmp2);
+
+ cmp3 = hpet_readl(HPET_Tn_CMP(timer));
+ if ( cmp3 != cmp )
+ print_error("%s(%ld): T%d Error: Set mc, cmp %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, cmp, cmp, cmp3, cmp3);
+
+ if ( dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer] != delta )
+ printf("%s(%ld): T%d Warning: Set mc, period %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, delta, delta,
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer],
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer]);
+
+ cmp = 67701;
+
+ now = hpet_readl(HPET_COUNTER);
+ if ( now != 67700 )
+ print_error("%s(%ld): T%d Error: Set cmp, mc %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, 67752, 67752, now, now);
+ cfg = hpet_readl(HPET_Tn_CFG(timer));
+ cfg |= HPET_TN_SETVAL;
+ hpet_writel(cfg, HPET_Tn_CFG(timer));
+ hpet_writel(cmp, HPET_Tn_CMP(timer));
+ printf("%s(%ld): HPET_TN_SETVAL cmp=%#lx(%'ld) timer=%d\n",
+ __func__, __LINE__, cmp, cmp, timer);
+ cmp2 = hpet_readl(HPET_Tn_CMP(timer));
+ if ( cmp2 != cmp )
+ print_error("%s(%ld): T%d Error: Set cmp, cmp %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, cmp, cmp, cmp2, cmp2);
+
+ cmp3 = hpet_readl(HPET_Tn_CMP(timer));
+ if ( cmp3 != cmp )
+ print_error("%s(%ld): T%d Error: Set cmp, cmp %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, cmp, cmp, cmp3, cmp3);
+
+ if ( dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer] != delta )
+ printf("%s(%ld): T%d Warning: Set cmp, period %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, delta, delta,
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer],
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer]);
+
+ delta = 500;
+
+ now = hpet_readl(HPET_COUNTER);
+ if ( now != 67700 )
+ print_error("%s(%ld): T%d Error: Set period, mc %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, 67752, 67752, now, now);
+ cmp2 = hpet_readl(HPET_Tn_CMP(timer));
+ if ( cmp2 != cmp )
+ print_error("%s(%ld): T%d Error: Set period, cmp %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, cmp, cmp, cmp2, cmp2);
+
+ hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer));
+ printf("%s(%ld): period=%#lx(%'ld) timer=%d\n", __func__, __LINE__,
+ (unsigned long) delta, (unsigned long) delta, timer);
+ cmp3 = hpet_readl(HPET_Tn_CMP(timer));
+ if ( cmp3 != cmp )
+ print_error("%s(%ld): T%d Error: Set period, cmp %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, cmp, cmp, cmp3, cmp3);
+
+ if ( dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer] != delta )
+ printf("%s(%ld): T%d Warning: Set period, period %#lx(%'ld) != %#lx(%'ld)\n",
+ __func__, __LINE__, timer, delta, delta,
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer],
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer]);
+
+ hpet_reset_counter(mc_low, mc_high);
+ cfg = hpet_readl(HPET_Tn_CFG(timer));
+ cfg |= HPET_TN_SETVAL;
+ hpet_writel(cfg, HPET_Tn_CFG(timer));
+ hpet_writel(old_cmp, HPET_Tn_CMP(timer));
+ hpet_writel(old_delta, HPET_Tn_CMP(timer));
+ hpet_start_counter();
+}
+
+
+int
+main(int argc, char **argv)
+{
+ hvm_domain_context_t hdc;
+ struct hvm_hw_hpet hpet0;
+ struct hvm_hw_hpet hpet1;
+ struct hvm_hw_hpet hpet2;
+ int i, k;
+
+ setlocale(LC_ALL, "");
+
+#ifdef FORCE_THOUSANDS_SEP
+ setlocale(LC_NUMERIC, "en_US.utf8");
+#endif
+ global_thousep = nl_langinfo(THOUSEP);
+
+ printf("test_vhpet 1.0\n");
+
+ if ( argc > 1 )
+ hvm_clock_cost = atoi(argv[1]);
+ if ( argc > 2 )
+ hpet_mult = atoi(argv[2]);
+ if ( argc > 3 )
+ hpet_add = atoi(argv[3]);
+ if ( argc > 4 )
+ tick_count = atoi(argv[4]);
+ if ( argc > 5 )
+ debug = strtol(argv[5], NULL, 0);
+
+ printf("hvm_clock_cost=%'d hpet_mult=%'d hpet_add=%'d tick_count=%d debug=%#x\n",
+ hvm_clock_cost, hpet_mult, hpet_add, tick_count, debug);
+
+ dom1.domain_id = 1;
+ dom1.vcpu[0] = &vcpu0;
+ vcpu0.vcpu_id = 0;
+ vcpu0.domain = &dom1;
+
+ __hvm_register_HPET_save_and_restore();
+
+ for (skip_load = 3; skip_load >= 0; skip_load--)
+ {
+
+ printf("\nskip_load=%d\n", skip_load);
+
+ hvm_guest_time = 16;
+
+ hpet_init(&vcpu0);
+
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet0 = hpet_save;
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet1 = hpet_save;
+ if (hpet0.mc64 != hpet1.mc64)
+ print_error("%s(%ld): With clock stopped mc64 changed: %'ld to %'ld\n",
+ __func__, __LINE__, hpet0.mc64, hpet1.mc64);
+
+ do_load(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet2 = hpet_save;
+ if (hpet1.mc64 != hpet2.mc64)
+ print_error("%s(%ld): With clock stopped mc64 changed: %'ld to %'ld\n",
+ __func__, __LINE__, hpet1.mc64, hpet2.mc64);
+
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.mc64 = START_MC64;
+ dom1.arch.hvm_domain.pl_time.vhpet.mc_offset = START_MC64
+ - hvm_guest_time - hvm_clock_cost;
+ printf("\n"
+ "mc64=%#lx(%'ld) mc_offset=%#lx(%'ld)\n",
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.mc64,
+ dom1.arch.hvm_domain.pl_time.vhpet.hpet.mc64,
+ dom1.arch.hvm_domain.pl_time.vhpet.mc_offset,
+ dom1.arch.hvm_domain.pl_time.vhpet.mc_offset);
+
+ printf("\nhvm_guest_time=%#lx(%'ld)\n",
+ hvm_guest_time, hvm_guest_time);
+
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet0 = hpet_save;
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet1 = hpet_save;
+ if (hpet0.mc64 != hpet1.mc64)
+ print_error("%s(%ld): With clock stopped mc64 changed: %'ld to %'ld\n",
+ __func__, __LINE__, hpet0.mc64, hpet1.mc64);
+
+ do_load(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet2 = hpet_save;
+ if (hpet1.mc64 != hpet2.mc64)
+ print_error("%s(%ld): With clock stopped mc64 changed: %'ld to %'ld\n",
+ __func__, __LINE__, hpet1.mc64, hpet2.mc64);
+
+ hpet_set_mode(0xf424, 0);
+ hpet_check_stopped(0xf424, 0);
+
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet0 = hpet_save;
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet1 = hpet_save;
+ do_load(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet2 = hpet_save;
+
+ hpet_set_mode(0, 1);
+ hpet_check_stopped(0, 1);
+
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet0 = hpet_save;
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet1 = hpet_save;
+
+ do_load(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet2 = hpet_save;
+
+ hpet_set_mode(~0ULL, 2);
+ hpet_check_stopped(~0ULL, 2);
+
+ hpet_set_mode(0x80000000, 2);
+ hpet_check_stopped(0x80000000, 2);
+
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet0 = hpet_save;
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet1 = hpet_save;
+
+ do_load(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet2 = hpet_save;
+
+
+ for (k = 0; k < ARRAY_SIZE(new_guest_time); k++)
+ {
+ hvm_guest_time = new_guest_time[k];
+ printf("\nhvm_guest_time=%#lx(%'ld)\n",
+ hvm_guest_time, hvm_guest_time);
+
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet0 = hpet_save;
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet1 = hpet_save;
+
+ do_load(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet2 = hpet_save;
+
+ for (i = 0; i < tick_count; i++)
+ {
+ hvm_guest_time += 0x10;
+ printf("\nhvm_guest_time=%#lx(%'ld)\n",
+ hvm_guest_time, hvm_guest_time);
+
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet0 = hpet_save;
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet1 = hpet_save;
+
+ do_load(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc);
+ dump_hpet();
+ hpet2 = hpet_save;
+
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/tests/x86_emulator/test_x86_emulator.c b/tools/tests/x86_emulator/test_x86_emulator.c
index 3166674..6f67fc7 100644
--- a/tools/tests/x86_emulator/test_x86_emulator.c
+++ b/tools/tests/x86_emulator/test_x86_emulator.c
@@ -7,6 +7,8 @@
#include <xen/xen.h>
#include <sys/mman.h>
+#define __packed __attribute__((packed))
+
#include "x86_emulate/x86_emulate.h"
#include "blowfish.h"
@@ -100,11 +102,11 @@ static int cpuid(
static inline uint64_t xgetbv(uint32_t xcr)
{
- uint64_t res;
+ uint32_t lo, hi;
- asm ( ".byte 0x0f, 0x01, 0xd0" : "=A" (res) : "c" (xcr) );
+ asm ( ".byte 0x0f, 0x01, 0xd0" : "=a" (lo), "=d" (hi) : "c" (xcr) );
- return res;
+ return ((uint64_t)hi << 32) | lo;
}
#define cpu_has_avx ({ \
diff --git a/tools/tests/x86_emulator/x86_emulate.c b/tools/tests/x86_emulator/x86_emulate.c
index b157ade..ef9bfe9 100644
--- a/tools/tests/x86_emulator/x86_emulate.c
+++ b/tools/tests/x86_emulator/x86_emulate.c
@@ -14,5 +14,7 @@ typedef bool bool_t;
#define cpu_has_amd_erratum(nr) 0
#define mark_regs_dirty(r) ((void)(r))
+#define __packed __attribute__((packed))
+
#include "x86_emulate/x86_emulate.h"
#include "x86_emulate/x86_emulate.c"
diff --git a/tools/tests/xen-access/xen-access.c b/tools/tests/xen-access/xen-access.c
index b00c05a..6cb382d 100644
--- a/tools/tests/xen-access/xen-access.c
+++ b/tools/tests/xen-access/xen-access.c
@@ -26,23 +26,24 @@
* DEALINGS IN THE SOFTWARE.
*/
+#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdbool.h>
+#include <string.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
+#include <sys/mman.h>
#include <sys/poll.h>
-#include <xc_private.h>
-#include <xg_save_restore.h>
+#include <xenctrl.h>
#include <xen/mem_event.h>
-//#if 0
-#undef DPRINTF
#define DPRINTF(a, b...) fprintf(stderr, a, ## b)
-//#endif
+#define ERROR(a, b...) fprintf(stderr, a "\n", ## b)
+#define PERROR(a, b...) fprintf(stderr, a ": %s\n", ## b, strerror(errno))
/* Spinlock and mem event definitions */
@@ -104,17 +105,9 @@ typedef struct mem_event {
spinlock_t ring_lock;
} mem_event_t;
-typedef struct xc_platform_info {
- unsigned long max_mfn;
- unsigned long hvirt_start;
- unsigned int pt_levels;
- unsigned int guest_width;
-} xc_platform_info_t;
-
typedef struct xenaccess {
xc_interface *xc_handle;
- xc_platform_info_t *platform_info;
xc_domaininfo_t *domain_info;
mem_event_t mem_event;
@@ -178,7 +171,7 @@ int xenaccess_teardown(xc_interface *xch, xenaccess_t *xenaccess)
/* Tear down domain xenaccess in Xen */
if ( xenaccess->mem_event.ring_page )
- munmap(xenaccess->mem_event.ring_page, PAGE_SIZE);
+ munmap(xenaccess->mem_event.ring_page, XC_PAGE_SIZE);
if ( mem_access_enable )
{
@@ -219,7 +212,6 @@ int xenaccess_teardown(xc_interface *xch, xenaccess_t *xenaccess)
}
xenaccess->xc_handle = NULL;
- free(xenaccess->platform_info);
free(xenaccess->domain_info);
free(xenaccess);
@@ -231,7 +223,6 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t domain_id)
xenaccess_t *xenaccess = 0;
xc_interface *xch;
int rc;
- unsigned long ring_pfn, mmap_pfn;
xch = xc_interface_open(NULL, NULL, 0);
if ( !xch )
@@ -253,40 +244,12 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t domain_id)
/* Initialise lock */
mem_event_ring_lock_init(&xenaccess->mem_event);
- /* Map the ring page */
- xc_get_hvm_param(xch, xenaccess->mem_event.domain_id,
- HVM_PARAM_ACCESS_RING_PFN, &ring_pfn);
- mmap_pfn = ring_pfn;
- xenaccess->mem_event.ring_page =
- xc_map_foreign_batch(xch, xenaccess->mem_event.domain_id,
- PROT_READ | PROT_WRITE, &mmap_pfn, 1);
- if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
- {
- /* Map failed, populate ring page */
- rc = xc_domain_populate_physmap_exact(xenaccess->xc_handle,
- xenaccess->mem_event.domain_id,
- 1, 0, 0, &ring_pfn);
- if ( rc != 0 )
- {
- PERROR("Failed to populate ring gfn\n");
- goto err;
- }
-
- mmap_pfn = ring_pfn;
- xenaccess->mem_event.ring_page =
- xc_map_foreign_batch(xch, xenaccess->mem_event.domain_id,
- PROT_READ | PROT_WRITE, &mmap_pfn, 1);
- if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
- {
- PERROR("Could not map the ring page\n");
- goto err;
- }
- }
-
- /* Initialise Xen */
- rc = xc_mem_access_enable(xenaccess->xc_handle, xenaccess->mem_event.domain_id,
- &xenaccess->mem_event.evtchn_port);
- if ( rc != 0 )
+ /* Enable mem_access */
+ xenaccess->mem_event.ring_page =
+ xc_mem_access_enable(xenaccess->xc_handle,
+ xenaccess->mem_event.domain_id,
+ &xenaccess->mem_event.evtchn_port);
+ if ( xenaccess->mem_event.ring_page == NULL )
{
switch ( errno ) {
case EBUSY:
@@ -296,7 +259,7 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t domain_id)
ERROR("EPT not supported for this guest");
break;
default:
- perror("Error initialising shared page");
+ perror("Error enabling mem_access");
break;
}
goto err;
@@ -328,31 +291,7 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t domain_id)
SHARED_RING_INIT((mem_event_sring_t *)xenaccess->mem_event.ring_page);
BACK_RING_INIT(&xenaccess->mem_event.back_ring,
(mem_event_sring_t *)xenaccess->mem_event.ring_page,
- PAGE_SIZE);
-
- /* Now that the ring is set, remove it from the guest's physmap */
- if ( xc_domain_decrease_reservation_exact(xch,
- xenaccess->mem_event.domain_id, 1, 0, &ring_pfn) )
- PERROR("Failed to remove ring from guest physmap");
-
- /* Get platform info */
- xenaccess->platform_info = malloc(sizeof(xc_platform_info_t));
- if ( xenaccess->platform_info == NULL )
- {
- ERROR("Error allocating memory for platform info");
- goto err;
- }
-
- rc = get_platform_info(xenaccess->xc_handle, domain_id,
- &xenaccess->platform_info->max_mfn,
- &xenaccess->platform_info->hvirt_start,
- &xenaccess->platform_info->pt_levels,
- &xenaccess->platform_info->guest_width);
- if ( rc != 1 )
- {
- ERROR("Error getting platform info");
- goto err;
- }
+ XC_PAGE_SIZE);
/* Get domaininfo */
xenaccess->domain_info = malloc(sizeof(xc_domaininfo_t));
@@ -437,8 +376,7 @@ static int xenaccess_resume_page(xenaccess_t *paging, mem_event_response_t *rsp)
goto out;
/* Tell Xen page is ready */
- ret = xc_mem_access_resume(paging->xc_handle, paging->mem_event.domain_id,
- rsp->gfn);
+ ret = xc_mem_access_resume(paging->xc_handle, paging->mem_event.domain_id);
ret = xc_evtchn_notify(paging->mem_event.xce_handle,
paging->mem_event.port);
@@ -467,8 +405,8 @@ int main(int argc, char *argv[])
int rc = -1;
int rc1;
xc_interface *xch;
- hvmmem_access_t default_access = HVMMEM_access_rwx;
- hvmmem_access_t after_first_access = HVMMEM_access_rwx;
+ xenmem_access_t default_access = XENMEM_access_rwx;
+ xenmem_access_t after_first_access = XENMEM_access_rwx;
int required = 0;
int int3 = 0;
int shutting_down = 0;
@@ -502,13 +440,13 @@ int main(int argc, char *argv[])
if ( !strcmp(argv[0], "write") )
{
- default_access = HVMMEM_access_rx;
- after_first_access = HVMMEM_access_rwx;
+ default_access = XENMEM_access_rx;
+ after_first_access = XENMEM_access_rwx;
}
else if ( !strcmp(argv[0], "exec") )
{
- default_access = HVMMEM_access_rw;
- after_first_access = HVMMEM_access_rwx;
+ default_access = XENMEM_access_rw;
+ after_first_access = XENMEM_access_rwx;
}
else if ( !strcmp(argv[0], "int3") )
{
@@ -547,15 +485,15 @@ int main(int argc, char *argv[])
}
/* Set the default access type and convert all pages to it */
- rc = xc_hvm_set_mem_access(xch, domain_id, default_access, ~0ull, 0);
+ rc = xc_set_mem_access(xch, domain_id, default_access, ~0ull, 0);
if ( rc < 0 )
{
ERROR("Error %d setting default mem access type\n", rc);
goto exit;
}
- rc = xc_hvm_set_mem_access(xch, domain_id, default_access, 0,
- xenaccess->domain_info->max_pages);
+ rc = xc_set_mem_access(xch, domain_id, default_access, 0,
+ xenaccess->domain_info->max_pages);
if ( rc < 0 )
{
ERROR("Error %d setting all memory to access type %d\n", rc,
@@ -564,9 +502,9 @@ int main(int argc, char *argv[])
}
if ( int3 )
- rc = xc_set_hvm_param(xch, domain_id, HVM_PARAM_MEMORY_EVENT_INT3, HVMPME_mode_sync);
+ rc = xc_hvm_param_set(xch, domain_id, HVM_PARAM_MEMORY_EVENT_INT3, HVMPME_mode_sync);
else
- rc = xc_set_hvm_param(xch, domain_id, HVM_PARAM_MEMORY_EVENT_INT3, HVMPME_mode_disabled);
+ rc = xc_hvm_param_set(xch, domain_id, HVM_PARAM_MEMORY_EVENT_INT3, HVMPME_mode_disabled);
if ( rc < 0 )
{
ERROR("Error %d setting int3 mem_event\n", rc);
@@ -581,9 +519,10 @@ int main(int argc, char *argv[])
DPRINTF("xenaccess shutting down on signal %d\n", interrupted);
/* Unregister for every event */
- rc = xc_hvm_set_mem_access(xch, domain_id, HVMMEM_access_rwx, ~0ull, 0);
- rc = xc_hvm_set_mem_access(xch, domain_id, HVMMEM_access_rwx, 0, xenaccess->domain_info->max_pages);
- rc = xc_set_hvm_param(xch, domain_id, HVM_PARAM_MEMORY_EVENT_INT3, HVMPME_mode_disabled);
+ rc = xc_set_mem_access(xch, domain_id, XENMEM_access_rwx, ~0ull, 0);
+ rc = xc_set_mem_access(xch, domain_id, XENMEM_access_rwx, 0,
+ xenaccess->domain_info->max_pages);
+ rc = xc_hvm_param_set(xch, domain_id, HVM_PARAM_MEMORY_EVENT_INT3, HVMPME_mode_disabled);
shutting_down = 1;
}
@@ -602,7 +541,7 @@ int main(int argc, char *argv[])
while ( RING_HAS_UNCONSUMED_REQUESTS(&xenaccess->mem_event.back_ring) )
{
- hvmmem_access_t access;
+ xenmem_access_t access;
rc = get_request(&xenaccess->mem_event, &req);
if ( rc != 0 )
@@ -618,7 +557,7 @@ int main(int argc, char *argv[])
switch (req.reason) {
case MEM_EVENT_REASON_VIOLATION:
- rc = xc_hvm_get_mem_access(xch, domain_id, req.gfn, &access);
+ rc = xc_get_mem_access(xch, domain_id, req.gfn, &access);
if (rc < 0)
{
ERROR("Error %d getting mem_access event\n", rc);
@@ -627,19 +566,22 @@ int main(int argc, char *argv[])
}
printf("PAGE ACCESS: %c%c%c for GFN %"PRIx64" (offset %06"
- PRIx64") gla %016"PRIx64" (vcpu %d)\n",
+ PRIx64") gla %016"PRIx64" (valid: %c; fault in gpt: %c; fault with gla: %c) (vcpu %u)\n",
req.access_r ? 'r' : '-',
req.access_w ? 'w' : '-',
req.access_x ? 'x' : '-',
req.gfn,
req.offset,
req.gla,
+ req.gla_valid ? 'y' : 'n',
+ req.fault_in_gpt ? 'y' : 'n',
+ req.fault_with_gla ? 'y': 'n',
req.vcpu_id);
if ( default_access != after_first_access )
{
- rc = xc_hvm_set_mem_access(xch, domain_id,
- after_first_access, req.gfn, 1);
+ rc = xc_set_mem_access(xch, domain_id, after_first_access,
+ req.gfn, 1);
if (rc < 0)
{
ERROR("Error %d setting gfn to access_type %d\n", rc,
diff --git a/tools/xcutils/Makefile b/tools/xcutils/Makefile
index 6c502f1..1c5237c 100644
--- a/tools/xcutils/Makefile
+++ b/tools/xcutils/Makefile
@@ -11,13 +11,12 @@
XEN_ROOT = $(CURDIR)/../..
include $(XEN_ROOT)/tools/Rules.mk
-PROGRAMS = xc_restore xc_save readnotes lsevtchn
+PROGRAMS = readnotes lsevtchn
CFLAGS += -Werror
-CFLAGS_xc_restore.o := $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest)
-CFLAGS_xc_save.o := $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) $(CFLAGS_libxenstore)
-CFLAGS_readnotes.o := $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest)
+# incorrectly uses libxc internals
+CFLAGS_readnotes.o := $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) -I$(XEN_ROOT)/tools/libxc
CFLAGS_lsevtchn.o := $(CFLAGS_libxenctrl)
.PHONY: all
@@ -26,12 +25,6 @@ all: build
.PHONY: build
build: $(PROGRAMS)
-xc_restore: xc_restore.o
- $(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(APPEND_LDFLAGS)
-
-xc_save: xc_save.o
- $(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS)
-
readnotes: readnotes.o
$(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(APPEND_LDFLAGS)
@@ -40,8 +33,8 @@ lsevtchn: lsevtchn.o
.PHONY: install
install: build
- $(INSTALL_DIR) $(DESTDIR)$(PRIVATE_BINDIR)
- $(INSTALL_PROG) $(PROGRAMS) $(DESTDIR)$(PRIVATE_BINDIR)
+ $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN)
+ $(INSTALL_PROG) $(PROGRAMS) $(DESTDIR)$(LIBEXEC_BIN)
.PHONY: clean
diff --git a/tools/xcutils/xc_restore.c b/tools/xcutils/xc_restore.c
deleted file mode 100644
index 4ea261b..0000000
--- a/tools/xcutils/xc_restore.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file "COPYING" in the main directory of
- * this archive for more details.
- *
- * Copyright (C) 2005 by Christian Limpach
- *
- */
-
-#include <err.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include <xenctrl.h>
-#include <xenguest.h>
-
-int
-main(int argc, char **argv)
-{
- unsigned int domid, store_evtchn, console_evtchn;
- unsigned int hvm, pae, apic, lflags, checkpointed;
- xc_interface *xch;
- int io_fd, ret;
- int superpages;
- unsigned long store_mfn = 0, console_mfn = 0;
- xentoollog_level lvl;
- xentoollog_logger *l;
-
- if ( !( argc >= 8 && argc <= 10) )
- errx(1, "usage: %s iofd domid store_evtchn "
- "console_evtchn hvm pae apic [superpages [checkpointed]]", argv[0]);
-
- lvl = XTL_DETAIL;
- lflags = XTL_STDIOSTREAM_SHOW_PID | XTL_STDIOSTREAM_HIDE_PROGRESS;
- l = (xentoollog_logger *)xtl_createlogger_stdiostream(stderr, lvl, lflags);
- xch = xc_interface_open(l, 0, 0);
- if ( !xch )
- errx(1, "failed to open control interface");
-
- io_fd = atoi(argv[1]);
- domid = atoi(argv[2]);
- store_evtchn = atoi(argv[3]);
- console_evtchn = atoi(argv[4]);
- hvm = atoi(argv[5]);
- pae = atoi(argv[6]);
- apic = atoi(argv[7]);
- if ( argc >= 9 )
- superpages = atoi(argv[8]);
- else
- superpages = !!hvm;
- if ( argc >= 10 )
- checkpointed = atoi(argv[9]);
- else
- checkpointed = 0;
-
- ret = xc_domain_restore(xch, io_fd, domid, store_evtchn, &store_mfn, 0,
- console_evtchn, &console_mfn, 0, hvm, pae, superpages,
- 0, checkpointed, NULL, NULL);
-
- if ( ret == 0 )
- {
- printf("store-mfn %li\n", store_mfn);
- if ( !hvm )
- printf("console-mfn %li\n", console_mfn);
- fflush(stdout);
- }
-
- xc_interface_close(xch);
-
- return ret;
-}
diff --git a/tools/xcutils/xc_save.c b/tools/xcutils/xc_save.c
deleted file mode 100644
index e34bd2c..0000000
--- a/tools/xcutils/xc_save.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file "COPYING" in the main directory of
- * this archive for more details.
- *
- * Copyright (C) 2005 by Christian Limpach
- *
- */
-
-#include <err.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <err.h>
-
-#include <xenstore.h>
-#include <xenctrl.h>
-#include <xenguest.h>
-
-static struct suspendinfo {
- xc_interface *xch;
- xc_evtchn *xce; /* event channel handle */
- int suspend_evtchn;
- int domid;
- unsigned int flags;
-} si;
-
-/**
- * Issue a suspend request through stdout, and receive the acknowledgement
- * from stdin. This is handled by XendCheckpoint in the Python layer.
- */
-static int compat_suspend(void)
-{
- char ans[30];
-
- printf("suspend\n");
- fflush(stdout);
-
- return (fgets(ans, sizeof(ans), stdin) != NULL &&
- !strncmp(ans, "done\n", 5));
-}
-
-/**
- * Issue a suspend request to a dedicated event channel in the guest, and
- * receive the acknowledgement from the subscribe event channel. */
-static int evtchn_suspend(void)
-{
- int rc;
-
- rc = xc_evtchn_notify(si.xce, si.suspend_evtchn);
- if (rc < 0) {
- warnx("failed to notify suspend request channel: %d", rc);
- return 0;
- }
-
- if (xc_await_suspend(si.xch, si.xce, si.suspend_evtchn) < 0) {
- warnx("suspend failed");
- return 0;
- }
-
- /* notify xend that it can do device migration */
- printf("suspended\n");
- fflush(stdout);
-
- return 1;
-}
-
-static int suspend(void* data)
-{
- unsigned long sx_state = 0;
-
- /* Cannot notify guest to shut itself down if it's in ACPI sleep state. */
- if (si.flags & XCFLAGS_HVM)
- xc_get_hvm_param(si.xch, si.domid,
- HVM_PARAM_ACPI_S_STATE, &sx_state);
-
- if ((sx_state == 0) && (si.suspend_evtchn >= 0))
- return evtchn_suspend();
-
- return compat_suspend();
-}
-
-/* For HVM guests, there are two sources of dirty pages: the Xen shadow
- * log-dirty bitmap, which we get with a hypercall, and qemu's version.
- * The protocol for getting page-dirtying data from qemu uses a
- * double-buffered shared memory interface directly between xc_save and
- * qemu-dm.
- *
- * xc_save calculates the size of the bitmaps and notifies qemu-dm
- * through the store that it wants to share the bitmaps. qemu-dm then
- * starts filling in the 'active' buffer.
- *
- * To change the buffers over, xc_save writes the other buffer number to
- * the store and waits for qemu to acknowledge that it is now writing to
- * the new active buffer. xc_save can then process and clear the old
- * active buffer. */
-
-
-static int switch_qemu_logdirty(int domid, unsigned int enable, void *data)
-{
- struct xs_handle *xs;
- char *path, *p, *ret_str, *cmd_str, **watch;
- unsigned int len;
- struct timeval tv;
- fd_set fdset;
-
- if ((xs = xs_daemon_open()) == NULL)
- errx(1, "Couldn't contact xenstore");
- if (!(path = strdup("/local/domain/0/device-model/")))
- errx(1, "can't get domain path in store");
- if (!(path = realloc(path, strlen(path)
- + 10
- + strlen("/logdirty/cmd") + 1)))
- errx(1, "no memory for constructing xenstore path");
- snprintf(path + strlen(path), 11, "%i", domid);
- strcat(path, "/logdirty/");
- p = path + strlen(path);
-
-
- /* Watch for qemu's return value */
- strcpy(p, "ret");
- if (!xs_watch(xs, path, "qemu-logdirty-ret"))
- errx(1, "can't set watch in store (%s)\n", path);
-
- if (!(cmd_str = strdup( enable == 0 ? "disable" : "enable")))
- errx(1, "can't get logdirty cmd path in store");
-
- /* Tell qemu that we want it to start logging dirty page to Xen */
- strcpy(p, "cmd");
- if (!xs_write(xs, XBT_NULL, path, cmd_str, strlen(cmd_str)))
- errx(1, "can't write to store path (%s)\n",
- path);
-
- /* Wait a while for qemu to signal that it has service logdirty command */
- read_again:
- tv.tv_sec = 5;
- tv.tv_usec = 0;
- FD_ZERO(&fdset);
- FD_SET(xs_fileno(xs), &fdset);
-
- if ((select(xs_fileno(xs) + 1, &fdset, NULL, NULL, &tv)) != 1)
- errx(1, "timed out waiting for qemu logdirty response.\n");
-
- watch = xs_read_watch(xs, &len);
- free(watch);
-
- strcpy(p, "ret");
- ret_str = xs_read(xs, XBT_NULL, path, &len);
- if (ret_str == NULL || strcmp(ret_str, cmd_str))
- /* Watch fired but value is not yet right */
- goto read_again;
-
- free(path);
- free(cmd_str);
- free(ret_str);
-
- return 0;
-}
-
-int
-main(int argc, char **argv)
-{
- unsigned int maxit, max_f, lflags;
- int io_fd, ret, port;
- struct save_callbacks callbacks;
- xentoollog_level lvl;
- xentoollog_logger *l;
-
- if (argc != 6)
- errx(1, "usage: %s iofd domid maxit maxf flags", argv[0]);
-
- io_fd = atoi(argv[1]);
- si.domid = atoi(argv[2]);
- maxit = atoi(argv[3]);
- max_f = atoi(argv[4]);
- si.flags = atoi(argv[5]);
-
- si.suspend_evtchn = -1;
-
- lvl = si.flags & XCFLAGS_DEBUG ? XTL_DEBUG: XTL_DETAIL;
- lflags = XTL_STDIOSTREAM_SHOW_PID | XTL_STDIOSTREAM_HIDE_PROGRESS;
- l = (xentoollog_logger *)xtl_createlogger_stdiostream(stderr, lvl, lflags);
- si.xch = xc_interface_open(l, 0, 0);
- if (!si.xch)
- errx(1, "failed to open control interface");
-
- si.xce = xc_evtchn_open(NULL, 0);
- if (si.xce == NULL)
- warnx("failed to open event channel handle");
- else
- {
- port = xs_suspend_evtchn_port(si.domid);
-
- if (port < 0)
- warnx("failed to get the suspend evtchn port\n");
- else
- {
- si.suspend_evtchn =
- xc_suspend_evtchn_init(si.xch, si.xce, si.domid, port);
-
- if (si.suspend_evtchn < 0)
- warnx("suspend event channel initialization failed, "
- "using slow path");
- }
- }
- memset(&callbacks, 0, sizeof(callbacks));
- callbacks.suspend = suspend;
- callbacks.switch_qemu_logdirty = switch_qemu_logdirty;
- ret = xc_domain_save(si.xch, io_fd, si.domid, maxit, max_f, si.flags,
- &callbacks, !!(si.flags & XCFLAGS_HVM), 0);
-
- if (si.suspend_evtchn > 0)
- xc_suspend_evtchn_release(si.xch, si.xce, si.domid, si.suspend_evtchn);
-
- if (si.xce > 0)
- xc_evtchn_close(si.xce);
-
- xc_interface_close(si.xch);
-
- return ret;
-}
diff --git a/tools/xenmon/xenbaked.c b/tools/xenmon/xenbaked.c
index 985f1dd..dc61d14 100644
--- a/tools/xenmon/xenbaked.c
+++ b/tools/xenmon/xenbaked.c
@@ -674,7 +674,7 @@ static void alloc_qos_data(int ncpu)
new_qos = (_new_qos_data *) mmap(0, sizeof(_new_qos_data), PROT_READ|PROT_WRITE,
MAP_SHARED, qos_fd, off);
off += i;
- if (new_qos == NULL) {
+ if (new_qos == MAP_FAILED) {
PERROR("mmap");
exit(3);
}
diff --git a/tools/xenpaging/Makefile b/tools/xenpaging/Makefile
index 548d9dd..c742e62 100644
--- a/tools/xenpaging/Makefile
+++ b/tools/xenpaging/Makefile
@@ -1,7 +1,8 @@
XEN_ROOT=$(CURDIR)/../..
include $(XEN_ROOT)/tools/Rules.mk
-CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenstore) $(PTHREAD_CFLAGS)
+# xenpaging.c and file_ops.c incorrectly use libxc internals
+CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenstore) $(PTHREAD_CFLAGS) -I$(XEN_ROOT)/tools/libxc
LDLIBS += $(LDLIBS_libxenctrl) $(LDLIBS_libxenstore) $(PTHREAD_LIBS)
LDFLAGS += $(PTHREAD_LDFLAGS)
@@ -13,7 +14,6 @@ SRCS += pagein.c
CFLAGS += -Werror
CFLAGS += -Wno-unused
-CFLAGS += -g
OBJS = $(SRCS:.c=.o)
IBINS = xenpaging
@@ -24,9 +24,9 @@ xenpaging: $(OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(APPEND_LDFLAGS)
install: all
- $(INSTALL_DIR) $(DESTDIR)$(XEN_PAGING_DIR)
- $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC)
- $(INSTALL_PROG) $(IBINS) $(DESTDIR)$(LIBEXEC)
+ $(INSTALL_DIR) -m 0700 $(DESTDIR)$(XEN_PAGING_DIR)
+ $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN)
+ $(INSTALL_PROG) $(IBINS) $(DESTDIR)$(LIBEXEC_BIN)
clean:
rm -f *.o *~ $(DEPS) xen TAGS $(IBINS) $(LIB)
diff --git a/tools/xenpaging/xenpaging.c b/tools/xenpaging/xenpaging.c
index 5ef2f09..82c1ee4 100644
--- a/tools/xenpaging/xenpaging.c
+++ b/tools/xenpaging/xenpaging.c
@@ -912,7 +912,7 @@ int main(int argc, char *argv[])
if ( req.gfn > paging->max_pages )
{
- ERROR("Requested gfn %"PRIx64" higher than max_pages %lx\n", req.gfn, paging->max_pages);
+ ERROR("Requested gfn %"PRIx64" higher than max_pages %x\n", req.gfn, paging->max_pages);
goto out;
}
diff --git a/tools/xenstat/libxenstat/Makefile b/tools/xenstat/libxenstat/Makefile
index 21aad89..86068cb 100644
--- a/tools/xenstat/libxenstat/Makefile
+++ b/tools/xenstat/libxenstat/Makefile
@@ -15,10 +15,6 @@
XEN_ROOT=$(CURDIR)/../../..
include $(XEN_ROOT)/tools/Rules.mk
-prefix=$(PREFIX)
-includedir=$(prefix)/include
-libdir=$(prefix)/lib
-
LDCONFIG=ldconfig
MAKE_LINK=ln -sf
@@ -32,10 +28,9 @@ OBJECTS-y=src/xenstat.o
OBJECTS-$(CONFIG_Linux) += src/xenstat_linux.o
OBJECTS-$(CONFIG_SunOS) += src/xenstat_solaris.o
OBJECTS-$(CONFIG_NetBSD) += src/xenstat_netbsd.o
+OBJECTS-$(CONFIG_FreeBSD) += src/xenstat_freebsd.o
SONAME_FLAGS=-Wl,$(SONAME_LDFLAG) -Wl,libxenstat.so.$(MAJOR)
-WARN_FLAGS=-Wall -Werror
-
CFLAGS+=-fPIC
CFLAGS+=-Isrc $(CFLAGS_libxenctrl) $(CFLAGS_libxenstore) $(CFLAGS_xeninclude)
diff --git a/tools/xenstat/libxenstat/src/xenstat.c b/tools/xenstat/libxenstat/src/xenstat.c
index e5facb8..8072a90 100644
--- a/tools/xenstat/libxenstat/src/xenstat.c
+++ b/tools/xenstat/libxenstat/src/xenstat.c
@@ -164,7 +164,7 @@ xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags)
xenstat_node *node;
xc_physinfo_t physinfo = { 0 };
xc_domaininfo_t domaininfo[DOMAIN_CHUNK_SIZE];
- unsigned int new_domains;
+ int new_domains;
unsigned int i;
/* Create the node */
diff --git a/tools/xenstat/libxenstat/src/xenstat_freebsd.c b/tools/xenstat/libxenstat/src/xenstat_freebsd.c
new file mode 100644
index 0000000..0c488df
--- /dev/null
+++ b/tools/xenstat/libxenstat/src/xenstat_freebsd.c
@@ -0,0 +1,47 @@
+/* libxenstat: statistics-collection library for Xen
+ * Copyright (C) International Business Machines Corp., 2005
+ * Authors: Josh Triplett <josht at us.ibm.com>
+ * Judy Fischbach <jfisch at us.ibm.com>
+ * David Hendricks <dhendrix at us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "xenstat_priv.h"
+
+/* Collect information about networks */
+int xenstat_collect_networks(xenstat_node * node)
+{
+
+ return 1;
+}
+
+/* Free network information in handle */
+void xenstat_uninit_networks(xenstat_handle * handle)
+{
+}
+
+/* Collect information about VBDs */
+int xenstat_collect_vbds(xenstat_node * node)
+{
+
+ return 1;
+}
+
+/* Free VBD information in handle */
+void xenstat_uninit_vbds(xenstat_handle * handle)
+{
+}
diff --git a/tools/xenstat/libxenstat/src/xenstat_linux.c b/tools/xenstat/libxenstat/src/xenstat_linux.c
index 931b24e..7fdf70a 100644
--- a/tools/xenstat/libxenstat/src/xenstat_linux.c
+++ b/tools/xenstat/libxenstat/src/xenstat_linux.c
@@ -64,14 +64,12 @@ static const char PROCNETDEV_HEADER[] =
/* We need to get the name of the bridge interface for use with bonding interfaces */
/* Use excludeName parameter to avoid adding bridges we don't care about, eg. virbr0 */
-char *getBridge(char *excludeName)
+void getBridge(char *excludeName, char *result, size_t resultLen)
{
struct dirent *de;
DIR *d;
- char tmp[256] = { 0 }, *bridge;
-
- bridge = (char *)malloc(16 * sizeof(char));
+ char tmp[256] = { 0 };
d = opendir("/sys/class/net");
while ((de = readdir(d)) != NULL) {
@@ -79,14 +77,14 @@ char *getBridge(char *excludeName)
&& (strstr(de->d_name, excludeName) == NULL)) {
sprintf(tmp, "/sys/class/net/%s/bridge", de->d_name);
- if (access(tmp, F_OK) == 0)
- bridge = de->d_name;
+ if (access(tmp, F_OK) == 0) {
+ strncpy(result, de->d_name, resultLen - 1);
+ result[resultLen - 1] = 0;
+ }
}
}
closedir(d);
-
- return bridge;
}
/* parseNetLine provides regular expression based parsing for lines from /proc/net/dev, all the */
@@ -235,6 +233,29 @@ int parseNetDevLine(char *line, char *iface, unsigned long long *rxBytes, unsign
return 0;
}
+/* Find out the domid and network number given an interface name.
+ * Return 0 if the iface cannot be recognized as a Xen VIF. */
+static int get_iface_domid_network(const char *iface, unsigned int *domid_p, unsigned int *netid_p)
+{
+ char nodename_path[48];
+ FILE * nodename_file;
+ int ret;
+
+ snprintf(nodename_path, 48, "/sys/class/net/%s/device/nodename", iface);
+ nodename_file = fopen(nodename_path, "r");
+ if (nodename_file != NULL) {
+ ret = fscanf(nodename_file, "backend/vif/%u/%u", domid_p, netid_p);
+ fclose(nodename_file);
+ if (ret == 2)
+ return 1;
+ }
+
+ if (sscanf(iface, "vif%u.%u", domid_p, netid_p) == 2)
+ return 1;
+
+ return 0;
+}
+
/* Collect information about networks */
int xenstat_collect_networks(xenstat_node * node)
{
@@ -279,7 +300,7 @@ int xenstat_collect_networks(xenstat_node * node)
SEEK_SET);
/* We get the bridge devices for use with bonding interface to get bonding interface stats */
- snprintf(devBridge, 16, "%s", getBridge("vir"));
+ getBridge("vir", devBridge, sizeof(devBridge));
snprintf(devNoBridge, 16, "p%s", devBridge);
while (fgets(line, 512, priv->procnetdev)) {
@@ -311,8 +332,7 @@ int xenstat_collect_networks(xenstat_node * node)
}
}
else /* Otherwise we need to preserve old behaviour */
- if (strstr(iface, "vif") != NULL) {
- sscanf(iface, "vif%u.%u", &domid, &net.id);
+ if (get_iface_domid_network(iface, &domid, &net.id)) {
net.tbytes = txBytes;
net.tpackets = txPackets;
diff --git a/tools/xenstat/xentop/Makefile b/tools/xenstat/xentop/Makefile
index afed0d1..076e44c 100644
--- a/tools/xenstat/xentop/Makefile
+++ b/tools/xenstat/xentop/Makefile
@@ -18,12 +18,13 @@ ifneq ($(XENSTAT_XENTOP),y)
all install xentop:
else
-CFLAGS += -DGCC_PRINTF -Wall -Werror $(CFLAGS_libxenstat)
-LDLIBS += $(LDLIBS_libxenstat) $(CURSES_LIBS) $(SOCKET_LIBS)
+CFLAGS += -DGCC_PRINTF -Werror $(CFLAGS_libxenstat)
+LDLIBS += $(LDLIBS_libxenstat) $(CURSES_LIBS) $(SOCKET_LIBS) -lm
CFLAGS += -DHOST_$(XEN_OS)
# Include configure output (config.h) to headers search path
CFLAGS += -I$(XEN_ROOT)/tools
+LDFLAGS += $(APPEND_LDFLAGS)
.PHONY: all
all: xentop
diff --git a/tools/xenstat/xentop/xentop.1 b/tools/xenstat/xentop/xentop.1
index 0a78e4c..8f6ab01 100644
--- a/tools/xenstat/xentop/xentop.1
+++ b/tools/xenstat/xentop/xentop.1
@@ -25,6 +25,7 @@
[\fB\-n\fR]
[\fB\-r\fR]
[\fB\-v\fR]
+[\fB\-f\fR]
[\fB\-b\fR]
[\fB\-i\fRITERATIONS]
@@ -56,6 +57,9 @@ repeat table header before each domain
\fB\-v\fR, \fB\-\-vcpus\fR
output VCPU data
.TP
+\fB\-f\fR, \fB\-\-full\-name\fR
+output the full domain name (not truncated)
+.TP
\fB\-b\fR, \fB\-\-batch\fR
output data in batch mode (to stdout)
.TP
diff --git a/tools/xenstat/xentop/xentop.c b/tools/xenstat/xentop/xentop.c
index dd11927..3062cb5 100644
--- a/tools/xenstat/xentop/xentop.c
+++ b/tools/xenstat/xentop/xentop.c
@@ -27,6 +27,7 @@
#include <ctype.h>
#include <errno.h>
+#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -70,6 +71,8 @@
#define curses_str_t const char *
#endif
+#define INT_FIELD_WIDTH(n) ((unsigned int)(log10(n) + 1))
+
/*
* Function prototypes
*/
@@ -127,7 +130,8 @@ static int compare_vbd_rsect(xenstat_domain *domain1, xenstat_domain *domain2);
static void print_vbd_rsect(xenstat_domain *domain);
static int compare_vbd_wsect(xenstat_domain *domain1, xenstat_domain *domain2);
static void print_vbd_wsect(xenstat_domain *domain);
-
+static void reset_field_widths(void);
+static void adjust_field_widths(xenstat_domain *domain);
/* Section printing functions */
static void do_summary(void);
@@ -444,7 +448,7 @@ int compare_name(xenstat_domain *domain1, xenstat_domain *domain2)
void print_name(xenstat_domain *domain)
{
if(show_full_name)
- print("%10s", xenstat_domain_name(domain));
+ print("%*s", fields[FIELD_NAME-1].default_width, xenstat_domain_name(domain));
else
print("%10.10s", xenstat_domain_name(domain));
}
@@ -623,7 +627,7 @@ static int compare_net_tx(xenstat_domain *domain1, xenstat_domain *domain2)
/* Prints number of total network tx bytes statistic */
static void print_net_tx(xenstat_domain *domain)
{
- print("%8llu", tot_net_bytes(domain, FALSE)/1024);
+ print("%*llu", fields[FIELD_NET_TX-1].default_width, tot_net_bytes(domain, FALSE)/1024);
}
/* Compares number of total network rx bytes of two domains, returning -1,0,1
@@ -637,7 +641,7 @@ static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2)
/* Prints number of total network rx bytes statistic */
static void print_net_rx(xenstat_domain *domain)
{
- print("%8llu", tot_net_bytes(domain, TRUE)/1024);
+ print("%*llu", fields[FIELD_NET_RX-1].default_width, tot_net_bytes(domain, TRUE)/1024);
}
/* Gets number of total network bytes statistic, if rx true, then rx bytes
@@ -705,7 +709,7 @@ static int compare_vbd_rd(xenstat_domain *domain1, xenstat_domain *domain2)
/* Prints number of total VBD READ requests statistic */
static void print_vbd_rd(xenstat_domain *domain)
{
- print("%8llu", tot_vbd_reqs(domain, FIELD_VBD_RD));
+ print("%*llu", fields[FIELD_VBD_RD-1].default_width, tot_vbd_reqs(domain, FIELD_VBD_RD));
}
/* Compares number of total VBD WRITE requests of two domains,
@@ -719,7 +723,7 @@ static int compare_vbd_wr(xenstat_domain *domain1, xenstat_domain *domain2)
/* Prints number of total VBD WRITE requests statistic */
static void print_vbd_wr(xenstat_domain *domain)
{
- print("%8llu", tot_vbd_reqs(domain, FIELD_VBD_WR));
+ print("%*llu", fields[FIELD_VBD_WR-1].default_width, tot_vbd_reqs(domain, FIELD_VBD_WR));
}
/* Compares number of total VBD READ sectors of two domains,
@@ -733,7 +737,7 @@ static int compare_vbd_rsect(xenstat_domain *domain1, xenstat_domain *domain2)
/* Prints number of total VBD READ sectors statistic */
static void print_vbd_rsect(xenstat_domain *domain)
{
- print("%10llu", tot_vbd_reqs(domain, FIELD_VBD_RSECT));
+ print("%*llu", fields[FIELD_VBD_RSECT-1].default_width, tot_vbd_reqs(domain, FIELD_VBD_RSECT));
}
/* Compares number of total VBD WRITE sectors of two domains,
@@ -747,7 +751,7 @@ static int compare_vbd_wsect(xenstat_domain *domain1, xenstat_domain *domain2)
/* Prints number of total VBD WRITE sectors statistic */
static void print_vbd_wsect(xenstat_domain *domain)
{
- print("%10llu", tot_vbd_reqs(domain, FIELD_VBD_WSECT));
+ print("%*llu", fields[FIELD_VBD_WSECT-1].default_width, tot_vbd_reqs(domain, FIELD_VBD_WSECT));
}
@@ -806,6 +810,54 @@ static void print_ssid(xenstat_domain *domain)
print("%4u", xenstat_domain_ssid(domain));
}
+/* Resets default_width for fields with potentially large numbers */
+void reset_field_widths(void)
+{
+ fields[FIELD_NET_TX-1].default_width = 8;
+ fields[FIELD_NET_RX-1].default_width = 8;
+ fields[FIELD_VBD_RD-1].default_width = 8;
+ fields[FIELD_VBD_WR-1].default_width = 8;
+ fields[FIELD_VBD_RSECT-1].default_width = 10;
+ fields[FIELD_VBD_WSECT-1].default_width = 10;
+}
+
+/* Adjusts default_width for fields with potentially large numbers */
+void adjust_field_widths(xenstat_domain *domain)
+{
+ unsigned int length;
+
+ if (show_full_name) {
+ length = strlen(xenstat_domain_name(domain));
+ if (length > fields[FIELD_NAME-1].default_width)
+ fields[FIELD_NAME-1].default_width = length;
+ }
+
+ length = INT_FIELD_WIDTH((tot_net_bytes(domain, FALSE)/1024) + 1);
+ if (length > fields[FIELD_NET_TX-1].default_width)
+ fields[FIELD_NET_TX-1].default_width = length;
+
+ length = INT_FIELD_WIDTH((tot_net_bytes(domain, TRUE)/1024) + 1);
+ if (length > fields[FIELD_NET_RX-1].default_width)
+ fields[FIELD_NET_RX-1].default_width = length;
+
+ length = INT_FIELD_WIDTH((tot_vbd_reqs(domain, FIELD_VBD_RD)) + 1);
+ if (length > fields[FIELD_VBD_RD-1].default_width)
+ fields[FIELD_VBD_RD-1].default_width = length;
+
+ length = INT_FIELD_WIDTH((tot_vbd_reqs(domain, FIELD_VBD_WR)) + 1);
+ if (length > fields[FIELD_VBD_WR-1].default_width)
+ fields[FIELD_VBD_WR-1].default_width = length;
+
+ length = INT_FIELD_WIDTH((tot_vbd_reqs(domain, FIELD_VBD_RSECT)) + 1);
+ if (length > fields[FIELD_VBD_RSECT-1].default_width)
+ fields[FIELD_VBD_RSECT-1].default_width = length;
+
+ length = INT_FIELD_WIDTH((tot_vbd_reqs(domain, FIELD_VBD_WSECT)) + 1);
+ if (length > fields[FIELD_VBD_WSECT-1].default_width)
+ fields[FIELD_VBD_WSECT-1].default_width = length;
+}
+
+
/* Section printing functions */
/* Prints the top summary, above the domain table */
void do_summary(void)
@@ -1088,6 +1140,12 @@ static void top(void)
if(first_domain_index >= num_domains)
first_domain_index = num_domains-1;
+ /* Adjust default_width for fields with potentially large numbers */
+ reset_field_widths();
+ for (i = first_domain_index; i < num_domains; i++) {
+ adjust_field_widths(domains[i]);
+ }
+
for (i = first_domain_index; i < num_domains; i++) {
if(!batch && current_row() == lines()-1)
break;
diff --git a/tools/xenstore/Makefile b/tools/xenstore/Makefile
index 262f401..bff9b25 100644
--- a/tools/xenstore/Makefile
+++ b/tools/xenstore/Makefile
@@ -6,16 +6,26 @@ MINOR = 3
CFLAGS += -Werror
CFLAGS += -I.
+CFLAGS += -I$(XEN_ROOT)/tools/
+CFLAGS += -I./include
CFLAGS += $(CFLAGS_libxenctrl)
+CFLAGS += -DXEN_LIB_STORED="\"$(XEN_LIB_STORED)\""
+
+CFLAGS-$(CONFIG_SYSTEMD) += $(SYSTEMD_CFLAGS)
+LDFLAGS-$(CONFIG_SYSTEMD) += $(SYSTEMD_LIBS)
+
+CFLAGS += $(CFLAGS-y)
+LDFLAGS += $(LDFLAGS-y)
CLIENTS := xenstore-exists xenstore-list xenstore-read xenstore-rm xenstore-chmod
CLIENTS += xenstore-write xenstore-ls xenstore-watch
XENSTORED_OBJS = xenstored_core.o xenstored_watch.o xenstored_domain.o xenstored_transaction.o xs_lib.o talloc.o utils.o tdb.o hashtable.o
-XENSTORED_OBJS_$(CONFIG_Linux) = xenstored_linux.o xenstored_posix.o
+XENSTORED_OBJS_$(CONFIG_Linux) = xenstored_posix.o
XENSTORED_OBJS_$(CONFIG_SunOS) = xenstored_solaris.o xenstored_posix.o xenstored_probes.o
-XENSTORED_OBJS_$(CONFIG_NetBSD) = xenstored_netbsd.o xenstored_posix.o
+XENSTORED_OBJS_$(CONFIG_NetBSD) = xenstored_posix.o
+XENSTORED_OBJS_$(CONFIG_FreeBSD) = xenstored_posix.o
XENSTORED_OBJS_$(CONFIG_MiniOS) = xenstored_minios.o
XENSTORED_OBJS += $(XENSTORED_OBJS_y)
@@ -27,7 +37,13 @@ LIBXENSTORE := libxenstore.a
xenstore xenstore-control: CFLAGS += -static
endif
-ALL_TARGETS = libxenstore.so libxenstore.a clients xs_tdb_dump xenstored
+ALL_TARGETS = libxenstore.a clients
+ifneq ($(nosharedlibs),y)
+ALL_TARGETS += libxenstore.so
+endif
+ifeq ($(XENSTORE_XENSTORED),y)
+ALL_TARGETS += xs_tdb_dump xenstored
+endif
ifeq ($(CONFIG_Linux),y)
ALL_TARGETS += init-xenstore-domain
@@ -86,7 +102,7 @@ libxenstore.so.$(MAJOR): libxenstore.so.$(MAJOR).$(MINOR)
xs.opic: CFLAGS += -DUSE_PTHREAD
libxenstore.so.$(MAJOR).$(MINOR): xs.opic xs_lib.opic
- $(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenstore.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(SOCKET_LIBS) -lpthread $(APPEND_LDFLAGS)
+ $(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenstore.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(SOCKET_LIBS) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
libxenstore.a: xs.o xs_lib.o
$(AR) rcs $@ $^
@@ -110,29 +126,38 @@ tarball: clean
.PHONY: install
install: all
$(INSTALL_DIR) $(DESTDIR)$(BINDIR)
- $(INSTALL_DIR) $(DESTDIR)$(SBINDIR)
$(INSTALL_DIR) $(DESTDIR)$(INCLUDEDIR)
$(INSTALL_DIR) $(DESTDIR)$(INCLUDEDIR)/xenstore-compat
- $(INSTALL_DIR) $(DESTDIR)/var/run/xenstored
- $(INSTALL_DIR) $(DESTDIR)/var/lib/xenstored
+ifeq ($(XENSTORE_XENSTORED),y)
+ $(INSTALL_DIR) $(DESTDIR)$(SBINDIR)
+ $(INSTALL_DIR) $(DESTDIR)$(XEN_LIB_STORED)
$(INSTALL_PROG) xenstored $(DESTDIR)$(SBINDIR)
+endif
$(INSTALL_PROG) xenstore-control $(DESTDIR)$(BINDIR)
$(INSTALL_PROG) xenstore $(DESTDIR)$(BINDIR)
set -e ; for c in $(CLIENTS) ; do \
ln -f $(DESTDIR)$(BINDIR)/xenstore $(DESTDIR)$(BINDIR)/$${c} ; \
done
$(INSTALL_DIR) $(DESTDIR)$(LIBDIR)
- $(INSTALL_PROG) libxenstore.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)
+ $(INSTALL_SHLIB) libxenstore.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)
ln -sf libxenstore.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libxenstore.so.$(MAJOR)
ln -sf libxenstore.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libxenstore.so
$(INSTALL_DATA) libxenstore.a $(DESTDIR)$(LIBDIR)
- $(INSTALL_DATA) xenstore.h $(DESTDIR)$(INCLUDEDIR)
- $(INSTALL_DATA) xenstore_lib.h $(DESTDIR)$(INCLUDEDIR)
- $(INSTALL_DATA) compat/xs.h $(DESTDIR)$(INCLUDEDIR)/xenstore-compat/xs.h
- $(INSTALL_DATA) compat/xs_lib.h $(DESTDIR)$(INCLUDEDIR)/xenstore-compat/xs_lib.h
+ $(INSTALL_DATA) include/xenstore.h $(DESTDIR)$(INCLUDEDIR)
+ $(INSTALL_DATA) include/xenstore_lib.h $(DESTDIR)$(INCLUDEDIR)
+ $(INSTALL_DATA) include/compat/xs.h $(DESTDIR)$(INCLUDEDIR)/xenstore-compat/xs.h
+ $(INSTALL_DATA) include/compat/xs_lib.h $(DESTDIR)$(INCLUDEDIR)/xenstore-compat/xs_lib.h
ln -sf xenstore-compat/xs.h $(DESTDIR)$(INCLUDEDIR)/xs.h
ln -sf xenstore-compat/xs_lib.h $(DESTDIR)$(INCLUDEDIR)/xs_lib.h
+.PHONY: clients-install
+clients-install: clients
+ $(INSTALL_DIR) $(DESTDIR)$(BINDIR)
+ $(INSTALL_PROG) xenstore $(DESTDIR)$(BINDIR)
+ set -e ; for c in $(CLIENTS) ; do \
+ ln -f $(DESTDIR)$(BINDIR)/xenstore $(DESTDIR)$(BINDIR)/$${c} ; \
+ done
+
-include $(DEPS)
# never delete any intermediate files.
diff --git a/tools/xenstore/compat/xs.h b/tools/xenstore/include/compat/xs.h
similarity index 100%
rename from tools/xenstore/compat/xs.h
rename to tools/xenstore/include/compat/xs.h
diff --git a/tools/xenstore/compat/xs_lib.h b/tools/xenstore/include/compat/xs_lib.h
similarity index 100%
rename from tools/xenstore/compat/xs_lib.h
rename to tools/xenstore/include/compat/xs_lib.h
diff --git a/tools/xenstore/xenstore.h b/tools/xenstore/include/xenstore.h
similarity index 100%
rename from tools/xenstore/xenstore.h
rename to tools/xenstore/include/xenstore.h
diff --git a/tools/xenstore/xenstore_lib.h b/tools/xenstore/include/xenstore_lib.h
similarity index 100%
rename from tools/xenstore/xenstore_lib.h
rename to tools/xenstore/include/xenstore_lib.h
diff --git a/tools/xenstore/init-xenstore-domain.c b/tools/xenstore/init-xenstore-domain.c
index 56a3c72..0d12169 100644
--- a/tools/xenstore/init-xenstore-domain.c
+++ b/tools/xenstore/init-xenstore-domain.c
@@ -13,7 +13,7 @@
static uint32_t domid = -1;
-static int build(xc_interface *xch, char** argv)
+static int build(xc_interface *xch, int argc, char** argv)
{
char cmdline[512];
uint32_t ssid;
@@ -44,6 +44,12 @@ static int build(xc_interface *xch, char** argv)
dom = xc_dom_allocate(xch, cmdline, NULL);
rv = xc_dom_kernel_file(dom, argv[1]);
if (rv) goto err;
+
+ if (argc > 4) {
+ rv = xc_dom_ramdisk_file(dom, argv[4]);
+ if (rv) goto err;
+ }
+
rv = xc_dom_boot_xen_init(dom, xch, domid);
if (rv) goto err;
rv = xc_dom_parse_image(dom);
@@ -81,15 +87,15 @@ int main(int argc, char** argv)
char buf[16];
int rv, fd;
- if (argc != 4) {
- printf("Use: %s <xenstore-kernel> <memory_mb> <flask-label>\n", argv[0]);
+ if (argc < 4 || argc > 5) {
+ printf("Use: %s <xenstore-kernel> <memory_mb> <flask-label> [<ramdisk-file>]\n", argv[0]);
return 2;
}
xch = xc_interface_open(NULL, NULL, 0);
if (!xch) return 1;
- rv = build(xch, argv);
+ rv = build(xch, argc, argv);
xc_interface_close(xch);
diff --git a/tools/xenstore/xenstore_client.c b/tools/xenstore/xenstore_client.c
index 0ec103f..1054f18 100644
--- a/tools/xenstore/xenstore_client.c
+++ b/tools/xenstore/xenstore_client.c
@@ -40,6 +40,7 @@ enum mode {
static char *output_buf = NULL;
static int output_pos = 0;
+static struct expanding_buffer ebuf;
static int output_size = 0;
@@ -126,13 +127,16 @@ static int show_whole_path = 0;
static void do_ls(struct xs_handle *h, char *path, int cur_depth, int show_perms)
{
- static struct expanding_buffer ebuf;
char **e;
- char newpath[STRING_MAX], *val;
+ char *newpath, *val;
int newpath_len;
int i;
unsigned int num, len;
+ newpath = malloc(STRING_MAX);
+ if (!newpath)
+ err(1, "malloc in do_ls");
+
e = xs_directory(h, XBT_NULL, path, &num);
if (e == NULL)
err(1, "xs_directory (%s)", path);
@@ -144,7 +148,7 @@ static void do_ls(struct xs_handle *h, char *path, int cur_depth, int show_perms
int linewid;
/* Compose fullpath */
- newpath_len = snprintf(newpath, sizeof(newpath), "%s%s%s", path,
+ newpath_len = snprintf(newpath, STRING_MAX, "%s%s%s", path,
path[strlen(path)-1] == '/' ? "" : "/",
e[i]);
@@ -161,7 +165,7 @@ static void do_ls(struct xs_handle *h, char *path, int cur_depth, int show_perms
}
/* Fetch value */
- if ( newpath_len < sizeof(newpath) ) {
+ if ( newpath_len < STRING_MAX ) {
val = xs_read(h, XBT_NULL, newpath, &len);
}
else {
@@ -217,6 +221,7 @@ static void do_ls(struct xs_handle *h, char *path, int cur_depth, int show_perms
do_ls(h, newpath, cur_depth+1, show_perms);
}
free(e);
+ free(newpath);
}
static void
@@ -308,7 +313,6 @@ perform(enum mode mode, int optind, int argc, char **argv, struct xs_handle *xsh
/* CANNOT BE REACHED */
errx(1, "invalid mode %d", mode);
case MODE_read: {
- static struct expanding_buffer ebuf;
unsigned len;
char *val = xs_read(xsh, xth, argv[optind], &len);
if (val == NULL) {
@@ -323,7 +327,6 @@ perform(enum mode mode, int optind, int argc, char **argv, struct xs_handle *xsh
break;
}
case MODE_write: {
- static struct expanding_buffer ebuf;
char *val_spec = argv[optind + 1];
unsigned len;
expanding_buffer_ensure(&ebuf, strlen(val_spec)+1);
@@ -655,5 +658,11 @@ again:
if (output_pos)
printf("%s", output_buf);
+ free(output_buf);
+ free(ebuf.buf);
+
+ if (xsh)
+ xs_close(xsh);
+
return ret;
}
diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index 2324e53..4eaff57 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -40,6 +40,7 @@
#include <signal.h>
#include <assert.h>
#include <setjmp.h>
+#include <config.h>
#include "utils.h"
#include "list.h"
@@ -54,6 +55,16 @@
#include "hashtable.h"
+#ifndef NO_SOCKETS
+#if defined(HAVE_SYSTEMD)
+#define XEN_SYSTEMD_ENABLED 1
+#endif
+#endif
+
+#if defined(XEN_SYSTEMD_ENABLED)
+#include <systemd/sd-daemon.h>
+#endif
+
extern xc_evtchn *xce_handle; /* in xenstored_domain.c */
static int xce_pollfd_idx = -1;
static struct pollfd *fds;
@@ -1714,6 +1725,75 @@ static int destroy_fd(void *_fd)
return 0;
}
+#if defined(XEN_SYSTEMD_ENABLED)
+/* Will work regardless of the order systemd gives them to us */
+static int xs_get_sd_fd(const char *connect_to)
+{
+ int fd = SD_LISTEN_FDS_START;
+ int r;
+
+ while (fd <= SD_LISTEN_FDS_START + 1) {
+ r = sd_is_socket_unix(fd, SOCK_STREAM, 1, connect_to, 0);
+ if (r > 0)
+ return fd;
+ fd++;
+ }
+
+ return -EBADR;
+}
+
+static int xs_validate_active_socket(const char *connect_to)
+{
+ if ((strcmp("/var/run/xenstored/socket_ro", connect_to) != 0) &&
+ (strcmp("/var/run/xenstored/socket", connect_to) != 0)) {
+ sd_notifyf(0, "STATUS=unexpected socket: %s\n"
+ "ERRNO=%i",
+ connect_to,
+ EBADR);
+ return -EBADR;
+ }
+
+ return xs_get_sd_fd(connect_to);
+}
+
+static void xen_claim_active_sockets(int **psock, int **pro_sock)
+{
+ int *sock, *ro_sock;
+ const char *soc_str = xs_daemon_socket();
+ const char *soc_str_ro = xs_daemon_socket_ro();
+ int n;
+
+ n = sd_listen_fds(0);
+ if (n <= 0) {
+ sd_notifyf(0, "STATUS=Failed to get any active sockets: %s\n"
+ "ERRNO=%i",
+ strerror(errno),
+ errno);
+ barf_perror("sd_listen_fds() failed\n");
+ } else if (n != 2) {
+ fprintf(stderr, SD_ERR "Expected 2 fds but given %d\n", n);
+ sd_notifyf(0, "STATUS=Mismatch on number (2): %s\n"
+ "ERRNO=%d",
+ strerror(EBADR),
+ EBADR);
+ barf_perror("sd_listen_fds() gave too many fds\n");
+ }
+
+ *psock = sock = talloc(talloc_autofree_context(), int);
+ *sock = xs_validate_active_socket(soc_str);
+ if (*sock <= 0)
+ barf_perror("%s", soc_str);
+
+ *pro_sock = ro_sock = talloc(talloc_autofree_context(), int);
+ *ro_sock = xs_validate_active_socket(soc_str_ro);
+ if (*ro_sock <= 0)
+ barf_perror("%s", soc_str_ro);
+
+ talloc_set_destructor(sock, destroy_fd);
+ talloc_set_destructor(ro_sock, destroy_fd);
+}
+#endif
+
static void init_sockets(int **psock, int **pro_sock)
{
struct sockaddr_un addr;
@@ -1795,6 +1875,7 @@ static struct option options[] = {
{ "entry-nb", 1, NULL, 'E' },
{ "pid-file", 1, NULL, 'F' },
{ "event", 1, NULL, 'e' },
+ { "master-domid", 1, NULL, 'm' },
{ "help", 0, NULL, 'H' },
{ "no-fork", 0, NULL, 'N' },
{ "priv-domid", 1, NULL, 'p' },
@@ -1810,6 +1891,7 @@ static struct option options[] = {
{ NULL, 0, NULL, 0 } };
extern void dump_conn(struct connection *conn);
+int dom0_domid = 0;
int dom0_event = 0;
int priv_domid = 0;
@@ -1871,6 +1953,9 @@ int main(int argc, char *argv[])
case 'e':
dom0_event = strtol(optarg, NULL, 10);
break;
+ case 'm':
+ dom0_domid = strtol(optarg, NULL, 10);
+ break;
case 'p':
priv_domid = strtol(optarg, NULL, 10);
break;
@@ -1879,6 +1964,15 @@ int main(int argc, char *argv[])
if (optind != argc)
barf("%s: No arguments desired", argv[0]);
+#if defined(XEN_SYSTEMD_ENABLED)
+ if (sd_booted()) {
+ dofork = false;
+ if (pidfile)
+ barf("%s: PID file not needed on systemd", argv[0]);
+ pidfile = NULL;
+ }
+#endif
+
reopen_log();
/* make sure xenstored directories exist */
@@ -1900,7 +1994,13 @@ int main(int argc, char *argv[])
/* Don't kill us with SIGPIPE. */
signal(SIGPIPE, SIG_IGN);
- init_sockets(&sock, &ro_sock);
+#if defined(XEN_SYSTEMD_ENABLED)
+ if (sd_booted())
+ xen_claim_active_sockets(&sock, &ro_sock);
+ else
+#endif
+ init_sockets(&sock, &ro_sock);
+
init_pipe(reopen_log_pipe);
/* Setup the database */
@@ -1931,6 +2031,13 @@ int main(int argc, char *argv[])
/* Tell the kernel we're up and running. */
xenbus_notify_running();
+#if defined(XEN_SYSTEMD_ENABLED)
+ if (sd_booted()) {
+ sd_notify(1, "READY=1");
+ fprintf(stderr, SD_NOTICE "xenstored is ready\n");
+ }
+#endif
+
/* Main loop. */
for (;;) {
struct connection *conn, *next;
diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
index cfbcf6f..dcf95b5 100644
--- a/tools/xenstore/xenstored_core.h
+++ b/tools/xenstore/xenstored_core.h
@@ -170,6 +170,7 @@ void trace(const char *fmt, ...);
void dtrace_io(const struct connection *conn, const struct buffered_data *data, int out);
extern int event_fd;
+extern int dom0_domid;
extern int dom0_event;
extern int priv_domid;
@@ -177,6 +178,8 @@ extern int priv_domid;
void *xenbus_map(void);
void unmap_xenbus(void *interface);
+static inline int xenbus_master_domid(void) { return dom0_domid; }
+
/* Return the event channel used by xenbus. */
evtchn_port_t xenbus_evtchn(void);
diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c
index f24bd6b..6d0394d 100644
--- a/tools/xenstore/xenstored_domain.c
+++ b/tools/xenstore/xenstored_domain.c
@@ -22,7 +22,6 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
-#include <xenctrl.h>
#include "utils.h"
#include "talloc.h"
@@ -606,7 +605,7 @@ static int dom0_init(void)
if (port == -1)
return -1;
- dom0 = new_domain(NULL, 0, port);
+ dom0 = new_domain(NULL, xenbus_master_domid(), port);
if (dom0 == NULL)
return -1;
diff --git a/tools/xenstore/xenstored_linux.c b/tools/xenstore/xenstored_linux.c
deleted file mode 100644
index cf40213..0000000
--- a/tools/xenstore/xenstored_linux.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (C) 2005 Rusty Russell IBM Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- */
-
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-
-#include "xenstored_core.h"
-
-#define XENSTORED_PROC_KVA "/proc/xen/xsd_kva"
-#define XENSTORED_PROC_PORT "/proc/xen/xsd_port"
-
-evtchn_port_t xenbus_evtchn(void)
-{
- int fd;
- int rc;
- evtchn_port_t port;
- char str[20];
-
- fd = open(XENSTORED_PROC_PORT, O_RDONLY);
- if (fd == -1)
- return -1;
-
- rc = read(fd, str, sizeof(str) - 1);
- if (rc == -1)
- {
- int err = errno;
- close(fd);
- errno = err;
- return -1;
- }
-
- str[rc] = '\0';
- port = strtoul(str, NULL, 0);
-
- close(fd);
- return port;
-}
-
-void *xenbus_map(void)
-{
- int fd;
- void *addr;
-
- fd = open(XENSTORED_PROC_KVA, O_RDWR);
- if (fd == -1)
- return NULL;
-
- addr = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE,
- MAP_SHARED, fd, 0);
-
- if (addr == MAP_FAILED)
- addr = NULL;
-
- close(fd);
-
- return addr;
-}
-
-void xenbus_notify_running(void)
-{
-}
diff --git a/tools/xenstore/xenstored_minios.c b/tools/xenstore/xenstored_minios.c
index 1c6f794..f9c921e 100644
--- a/tools/xenstore/xenstored_minios.c
+++ b/tools/xenstore/xenstored_minios.c
@@ -51,7 +51,7 @@ evtchn_port_t xenbus_evtchn(void)
void *xenbus_map(void)
{
- return xc_gnttab_map_grant_ref(*xcg_handle, 0,
+ return xc_gnttab_map_grant_ref(*xcg_handle, xenbus_master_domid(),
GNTTAB_RESERVED_XENSTORE, PROT_READ|PROT_WRITE);
}
diff --git a/tools/xenstore/xenstored_netbsd.c b/tools/xenstore/xenstored_netbsd.c
deleted file mode 100644
index 1e94e41..0000000
--- a/tools/xenstore/xenstored_netbsd.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (C) 2005 Rusty Russell IBM Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- */
-
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-
-#include "xenstored_core.h"
-
-#define XENSTORED_PROC_KVA "/dev/xsd_kva"
-#define XENSTORED_PROC_PORT "/kern/xen/xsd_port"
-
-evtchn_port_t xenbus_evtchn(void)
-{
- int fd;
- int rc;
- evtchn_port_t port;
- char str[20];
-
- fd = open(XENSTORED_PROC_PORT, O_RDONLY);
- if (fd == -1)
- return -1;
-
- rc = read(fd, str, sizeof(str));
- if (rc == -1)
- {
- int err = errno;
- close(fd);
- errno = err;
- return -1;
- }
-
- str[rc] = '\0';
- port = strtoul(str, NULL, 0);
-
- close(fd);
- return port;
-}
-
-void *xenbus_map(void)
-{
- int fd;
- void *addr;
-
- fd = open(XENSTORED_PROC_KVA, O_RDWR);
- if (fd == -1)
- return NULL;
-
- addr = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE,
- MAP_SHARED, fd, 0);
-
- if (addr == MAP_FAILED)
- addr = NULL;
-
- close(fd);
-
- return addr;
-}
-
-void xenbus_notify_running(void)
-{
-}
diff --git a/tools/xenstore/xenstored_osdep.h b/tools/xenstore/xenstored_osdep.h
new file mode 100644
index 0000000..b3e630c
--- /dev/null
+++ b/tools/xenstore/xenstored_osdep.h
@@ -0,0 +1,20 @@
+/*
+ * OS specific bits for xenstored
+ * Copyright (C) 2014 Citrix Systems R&D.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#if defined(__linux__)
+#define XENSTORED_KVA_DEV "/proc/xen/xsd_kva"
+#define XENSTORED_PORT_DEV "/proc/xen/xsd_port"
+#elif defined(__NetBSD__)
+#define XENSTORED_KVA_DEV "/dev/xsd_kva"
+#define XENSTORED_PORT_DEV "/kern/xen/xsd_port"
+#elif defined(__FreeBSD__)
+#define XENSTORED_KVA_DEV "/dev/xen/xenstored"
+#define XENSTORED_PORT_DEV "/dev/xen/xenstored"
+#endif
diff --git a/tools/xenstore/xenstored_posix.c b/tools/xenstore/xenstored_posix.c
index 0c93e6d..ecf4386 100644
--- a/tools/xenstore/xenstored_posix.c
+++ b/tools/xenstore/xenstored_posix.c
@@ -26,6 +26,7 @@
#include "utils.h"
#include "xenstored_core.h"
+#include "xenstored_osdep.h"
void write_pidfile(const char *pidfile)
{
@@ -99,3 +100,56 @@ void unmap_xenbus(void *interface)
{
munmap(interface, getpagesize());
}
+
+#ifndef __sun__
+evtchn_port_t xenbus_evtchn(void)
+{
+ int fd;
+ int rc;
+ evtchn_port_t port;
+ char str[20];
+
+ fd = open(XENSTORED_PORT_DEV, O_RDONLY);
+ if (fd == -1)
+ return -1;
+
+ rc = read(fd, str, sizeof(str) - 1);
+ if (rc == -1)
+ {
+ int err = errno;
+ close(fd);
+ errno = err;
+ return -1;
+ }
+
+ str[rc] = '\0';
+ port = strtoul(str, NULL, 0);
+
+ close(fd);
+ return port;
+}
+
+void *xenbus_map(void)
+{
+ int fd;
+ void *addr;
+
+ fd = open(XENSTORED_KVA_DEV, O_RDWR);
+ if (fd == -1)
+ return NULL;
+
+ addr = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE,
+ MAP_SHARED, fd, 0);
+
+ if (addr == MAP_FAILED)
+ addr = NULL;
+
+ close(fd);
+
+ return addr;
+}
+
+void xenbus_notify_running(void)
+{
+}
+#endif /* !__sun__ */
diff --git a/tools/xenstore/xs.c b/tools/xenstore/xs.c
index dd03a85..968141d 100644
--- a/tools/xenstore/xs.c
+++ b/tools/xenstore/xs.c
@@ -724,7 +724,10 @@ bool xs_watch(struct xs_handle *h, const char *path, const char *token)
struct iovec iov[2];
#ifdef USE_PTHREAD
-#define READ_THREAD_STACKSIZE PTHREAD_STACK_MIN
+#define DEFAULT_THREAD_STACKSIZE (16 * 1024)
+#define READ_THREAD_STACKSIZE \
+ ((DEFAULT_THREAD_STACKSIZE < PTHREAD_STACK_MIN) ? \
+ PTHREAD_STACK_MIN : DEFAULT_THREAD_STACKSIZE)
/* We dynamically create a reader thread on demand. */
mutex_lock(&h->request_mutex);
diff --git a/tools/xenstore/xs_lib.c b/tools/xenstore/xs_lib.c
index f7076cc..d166497 100644
--- a/tools/xenstore/xs_lib.c
+++ b/tools/xenstore/xs_lib.c
@@ -30,7 +30,7 @@
const char *xs_daemon_rootdir(void)
{
char *s = getenv("XENSTORED_ROOTDIR");
- return (s ? s : "/var/lib/xenstored");
+ return (s ? s : XEN_LIB_STORED);
}
const char *xs_daemon_rundir(void)
@@ -79,8 +79,9 @@ const char *xs_domain_dev(void)
char *s = getenv("XENSTORED_PATH");
if (s)
return s;
-
-#if defined(__linux__)
+#if defined(__RUMPUSER_XEN__)
+ return "/dev/xen/xenbus";
+#elif defined(__linux__)
return "/proc/xen/xenbus";
#elif defined(__NetBSD__)
return "/kern/xen/xenbus";
diff --git a/tools/xenstore/xs_tdb_dump.c b/tools/xenstore/xs_tdb_dump.c
index 7aa7158..b91cdef 100644
--- a/tools/xenstore/xs_tdb_dump.c
+++ b/tools/xenstore/xs_tdb_dump.c
@@ -5,6 +5,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
+#include <sys/types.h>
#include "xenstore_lib.h"
#include "tdb.h"
#include "talloc.h"
diff --git a/tools/xentrace/Makefile b/tools/xentrace/Makefile
index 63b09c0..b821952 100644
--- a/tools/xentrace/Makefile
+++ b/tools/xentrace/Makefile
@@ -21,12 +21,12 @@ build: $(BIN) $(LIBBIN)
.PHONY: install
install: build
$(INSTALL_DIR) $(DESTDIR)$(BINDIR)
- [ -z "$(LIBBIN)" ] || $(INSTALL_DIR) $(DESTDIR)$(PRIVATE_BINDIR)
+ [ -z "$(LIBBIN)" ] || $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN)
$(INSTALL_DIR) $(DESTDIR)$(MAN1DIR)
$(INSTALL_DIR) $(DESTDIR)$(MAN8DIR)
$(INSTALL_PROG) $(BIN) $(DESTDIR)$(BINDIR)
$(INSTALL_PYTHON_PROG) $(SCRIPTS) $(DESTDIR)$(BINDIR)
- [ -z "$(LIBBIN)" ] || $(INSTALL_PROG) $(LIBBIN) $(DESTDIR)$(PRIVATE_BINDIR)
+ [ -z "$(LIBBIN)" ] || $(INSTALL_PROG) $(LIBBIN) $(DESTDIR)$(LIBEXEC_BIN)
$(INSTALL_DATA) $(MAN1) $(DESTDIR)$(MAN1DIR)
$(INSTALL_DATA) $(MAN8) $(DESTDIR)$(MAN8DIR)
diff --git a/tools/xentrace/formats b/tools/xentrace/formats
index 67fd42d..da658bf 100644
--- a/tools/xentrace/formats
+++ b/tools/xentrace/formats
@@ -152,3 +152,21 @@
0x00802006 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) assign_vector [ irq = %(1)d = vector 0x%(2)x, CPU mask: 0x%(3)08x ]
0x00802007 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) bogus_vector [ 0x%(1)x ]
0x00802008 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) do_irq [ irq = %(1)d, began = %(2)dus, ended = %(3)dus ]
+
+0x00084001 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) hpet create [ tn = %(1)d, irq = %(2)d, delta = 0x%(4)08x%(3)08x, period = 0x%(6)08x%(5)08x ]
+0x00084002 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) pit create [ delta = 0x%(1)016x, period = 0x%(2)016x ]
+0x00084003 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) rtc create [ delta = 0x%(1)016x , period = 0x%(2)016x ]
+0x00084004 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) vlapic create [ delta = 0x%(2)08x%(1)08x , period = 0x%(4)08x%(3)08x, irq = %(5)d ]
+0x00084005 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) hpet destroy [ tn = %(1)d ]
+0x00084006 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) pit destroy [ ]
+0x00084007 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) rtc destroy [ ]
+0x00084008 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) vlapic destroy [ ]
+0x00084009 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) pit callback [ ]
+0x0008400a CPU%(cpu)d %(tsc)d (+%(reltsc)8d) vlapic callback [ ]
+0x0008400b CPU%(cpu)d %(tsc)d (+%(reltsc)8d) vpic_update_int_output [ int_output = %(1)d, is_master = %(2)d, irq = %(3)d ]
+0x0008400c CPU%(cpu)d %(tsc)d (+%(reltsc)8d) vpic vcpu_kick [ irq = %(1)d ]
+0x0008400d CPU%(cpu)d %(tsc)d (+%(reltsc)8d) __vpic_intack [ is_master = %(1)d, irq = %(2)d ]
+0x0008400e CPU%(cpu)d %(tsc)d (+%(reltsc)8d) vpic_irq_positive_edge [ irq = %(1)d ]
+0x0008400f CPU%(cpu)d %(tsc)d (+%(reltsc)8d) vpic_irq_negative_edge [ irq = %(1)d ]
+0x00084010 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) vpic_ack_pending_irq [ accept_pic_intr = %(1)d, int_output = %(2)d ]
+0x00084011 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) vlapic_accept_pic_intr [ i8259_target = %(1)d, accept_pic_int = %(2)d ]
diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c
index 7275a00..4ed120a 100644
--- a/tools/xentrace/xenctx.c
+++ b/tools/xentrace/xenctx.c
@@ -23,25 +23,31 @@
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
+#include <limits.h>
#include "xenctrl.h"
#include <xen/foreign/x86_32.h>
#include <xen/foreign/x86_64.h>
#include <xen/hvm/save.h>
-static struct xenctx {
- xc_interface *xc_handle;
- int domid;
- int frame_ptrs;
- int stack_trace;
- int disp_all;
- int all_vcpus;
- int self_paused;
- xc_dominfo_t dominfo;
-} xenctx;
+#define DEFAULT_NR_STACK_PAGES 1
+#define DEFAULT_BYTES_PER_LINE 32
+#define DEFAULT_LINES 5
+
+/* Note: the order of these matter.
+ * NOT_KERNEL_ADDR must be < both KERNEL_DATA_ADDR and KERNEL_TEXT_ADDR.
+ * KERNEL_DATA_ADDR must be < KERNEL_TEXT_ADDR. */
+typedef enum type_of_addr_ {
+ NOT_KERNEL_ADDR,
+ KERNEL_DATA_ADDR,
+ KERNEL_TEXT_ADDR,
+} type_of_addr;
#if defined (__i386__) || defined (__x86_64__)
+static const uint64_t cr_reg_mask[5] = { [2] = ~UINT64_C(0) };
+static const uint64_t dr_reg_mask[8] = { [0 ... 3] = ~UINT64_C(0) };
typedef unsigned long long guest_word_t;
+#define FMT_16B_WORD "%04llx"
#define FMT_32B_WORD "%08llx"
#define FMT_64B_WORD "%016llx"
/* Word-length of the guest's own data structures */
@@ -52,15 +58,42 @@ int guest_protected_mode = 1;
#elif defined(__arm__)
#define NO_TRANSLATION
typedef uint64_t guest_word_t;
+#define FMT_16B_WORD "%04llx"
#define FMT_32B_WORD "%08llx"
#define FMT_64B_WORD "%016llx"
#elif defined(__aarch64__)
#define NO_TRANSLATION
typedef uint64_t guest_word_t;
-#define FMT_32B_WORD "%08lx"
-#define FMT_64B_WORD "%016lx"
+#define FMT_16B_WORD "%04llx"
+#define FMT_32B_WORD "%08llx"
+#define FMT_64B_WORD "%016llx"
#endif
+#define MAX_BYTES_PER_LINE 128
+
+static struct xenctx {
+ xc_interface *xc_handle;
+ int domid;
+ int frame_ptrs;
+ int stack_trace;
+ int disp_all;
+ int nr_stack_pages;
+ int bytes_per_line;
+ int lines;
+ int decode_as_ascii;
+ int tag_stack_dump;
+ int tag_call_trace;
+ int all_vcpus;
+#ifndef NO_TRANSLATION
+ guest_word_t mem_addr;
+ guest_word_t stk_addr;
+ int do_memory;
+ int do_stack;
+#endif
+ int kernel_start_set;
+ xc_dominfo_t dominfo;
+} xenctx;
+
struct symbol {
guest_word_t address;
char *name;
@@ -68,30 +101,52 @@ struct symbol {
} *symbol_table = NULL;
guest_word_t kernel_stext, kernel_etext, kernel_sinittext, kernel_einittext, kernel_hypercallpage;
+guest_word_t kernel_text;
#if defined (__i386__) || defined (__arm__)
unsigned long long kernel_start = 0xc0000000;
+unsigned long long kernel_end = 0xffffffffULL;
#elif defined (__x86_64__)
unsigned long long kernel_start = 0xffffffff80000000UL;
+unsigned long long kernel_end = 0xffffffffffffffffUL;
#elif defined (__aarch64__)
unsigned long long kernel_start = 0xffffff8000000000UL;
+unsigned long long kernel_end = 0xffffffffffffffffULL;
#endif
-static int is_kernel_text(guest_word_t addr)
+static type_of_addr kernel_addr(guest_word_t addr)
{
- if (symbol_table == NULL)
- return (addr > kernel_start);
+ if ( symbol_table == NULL )
+ {
+ if ( addr > kernel_start )
+ return KERNEL_TEXT_ADDR;
+ else
+ return NOT_KERNEL_ADDR;
+ }
if (addr >= kernel_stext &&
addr <= kernel_etext)
- return 1;
- if (addr >= kernel_hypercallpage &&
- addr <= kernel_hypercallpage + 4096)
- return 1;
+ return KERNEL_TEXT_ADDR;
+ if ( kernel_hypercallpage &&
+ (addr >= kernel_hypercallpage &&
+ addr <= kernel_hypercallpage + 4096) )
+ return KERNEL_TEXT_ADDR;
if (addr >= kernel_sinittext &&
addr <= kernel_einittext)
- return 1;
- return 0;
+ return KERNEL_TEXT_ADDR;
+ if ( xenctx.kernel_start_set )
+ {
+ if ( addr > kernel_start )
+ return KERNEL_TEXT_ADDR;
+ } else {
+ if ( addr >= kernel_text &&
+ addr <= kernel_end )
+ return KERNEL_DATA_ADDR;
+ if ( addr >= kernel_start &&
+ addr <= kernel_end )
+ return KERNEL_TEXT_ADDR;
+ }
+ return NOT_KERNEL_ADDR;
}
#if 0
@@ -145,11 +200,11 @@ static struct symbol *lookup_symbol(guest_word_t address)
return s->next && s->next->address <= address ? s->next : s;
}
-static void print_symbol(guest_word_t addr)
+static void print_symbol(guest_word_t addr, type_of_addr type)
{
struct symbol *s;
- if (!is_kernel_text(addr))
+ if ( kernel_addr(addr) < type )
return;
s = lookup_symbol(addr);
@@ -158,9 +213,9 @@ static void print_symbol(guest_word_t addr)
return;
if (addr==s->address)
- printf("%s ", s->name);
+ printf(" %s", s->name);
else
- printf("%s+%#x ", s->name, (unsigned int)(addr - s->address));
+ printf(" %s+%#x", s->name, (unsigned int)(addr - s->address));
}
static void read_symbol_table(const char *symtab)
@@ -229,6 +284,10 @@ static void read_symbol_table(const char *symtab)
kernel_stext = address;
else if (strcmp(p, "_etext") == 0)
kernel_etext = address;
+ else if ( strcmp(p, "_text") == 0 )
+ kernel_text = address;
+ else if ( strcmp(p, "_end") == 0 || strcmp(p, "__bss_stop") == 0 )
+ kernel_end = address;
else if (strcmp(p, "_sinittext") == 0)
kernel_sinittext = address;
else if (strcmp(p, "_einittext") == 0)
@@ -281,17 +340,29 @@ static void print_flags(uint64_t flags)
printf("\n");
}
-static void print_special(void *regs, const char *name, unsigned int mask, int width)
+static void print_special(void *regs, const char *name, unsigned int mask,
+ const uint64_t reg_is_addr_mask[], int width)
{
unsigned int i;
printf("\n");
for (i = 0; mask; mask >>= 1, ++i)
if (mask & 1) {
- if (width == 4)
- printf("%s%u: %08"PRIx32"\n", name, i, ((uint32_t *) regs)[i]);
+ if ( width == 4 )
+ {
+ printf("%s%u: %08"PRIx32, name, i, ((uint32_t *) regs)[i]);
+ if ( reg_is_addr_mask[i] )
+ print_symbol(reg_is_addr_mask[i] & ((uint32_t *) regs)[i],
+ KERNEL_DATA_ADDR);
+ }
else
- printf("%s%u: %08"PRIx64"\n", name, i, ((uint64_t *) regs)[i]);
+ {
+ printf("%s%u: %016"PRIx64, name, i, ((uint64_t *) regs)[i]);
+ if ( reg_is_addr_mask[i] )
+ print_symbol(reg_is_addr_mask[i] & ((uint64_t *) regs)[i],
+ KERNEL_DATA_ADDR);
+ }
+ printf("\n");
}
}
@@ -299,8 +370,8 @@ static void print_ctx_32(vcpu_guest_context_x86_32_t *ctx)
{
struct cpu_user_regs_x86_32 *regs = &ctx->user_regs;
- printf("cs:eip: %04x:%08x ", regs->cs, regs->eip);
- print_symbol(regs->eip);
+ printf("cs:eip: %04x:%08x", regs->cs, regs->eip);
+ print_symbol(regs->eip, KERNEL_TEXT_ADDR);
print_flags(regs->eflags);
printf("ss:esp: %04x:%08x\n", regs->ss, regs->esp);
@@ -319,8 +390,8 @@ static void print_ctx_32(vcpu_guest_context_x86_32_t *ctx)
printf(" gs: %04x\n", regs->gs);
if (xenctx.disp_all) {
- print_special(ctx->ctrlreg, "cr", 0x1d, 4);
- print_special(ctx->debugreg, "dr", 0xcf, 4);
+ print_special(ctx->ctrlreg, "cr", 0x1d, cr_reg_mask, 4);
+ print_special(ctx->debugreg, "dr", 0xcf, dr_reg_mask, 4);
}
}
@@ -328,8 +399,8 @@ static void print_ctx_32on64(vcpu_guest_context_x86_64_t *ctx)
{
struct cpu_user_regs_x86_64 *regs = &ctx->user_regs;
- printf("cs:eip: %04x:%08x ", regs->cs, (uint32_t)regs->eip);
- print_symbol((uint32_t)regs->eip);
+ printf("cs:eip: %04x:%08x", regs->cs, (uint32_t)regs->eip);
+ print_symbol((uint32_t)regs->eip, KERNEL_TEXT_ADDR);
print_flags((uint32_t)regs->eflags);
printf("ss:esp: %04x:%08x\n", regs->ss, (uint32_t)regs->esp);
@@ -348,8 +419,15 @@ static void print_ctx_32on64(vcpu_guest_context_x86_64_t *ctx)
printf(" gs: %04x\n", regs->gs);
if (xenctx.disp_all) {
- print_special(ctx->ctrlreg, "cr", 0x1d, 4);
- print_special(ctx->debugreg, "dr", 0xcf, 4);
+ uint32_t tmp_regs[8];
+ int i;
+
+ for (i = 0; i < 5; i++)
+ tmp_regs[i] = ctx->ctrlreg[i];
+ print_special(tmp_regs, "cr", 0x1d, cr_reg_mask, 4);
+ for (i = 0; i < 8; i++)
+ tmp_regs[i] = ctx->debugreg[i];
+ print_special(tmp_regs, "dr", 0xcf, dr_reg_mask, 4);
}
}
@@ -357,8 +435,8 @@ static void print_ctx_64(vcpu_guest_context_x86_64_t *ctx)
{
struct cpu_user_regs_x86_64 *regs = &ctx->user_regs;
- printf("rip: %016"PRIx64" ", regs->rip);
- print_symbol(regs->rip);
+ printf("rip: %016"PRIx64, regs->rip);
+ print_symbol(regs->rip, KERNEL_TEXT_ADDR);
print_flags(regs->rflags);
printf("rsp: %016"PRIx64"\n", regs->rsp);
@@ -387,13 +465,22 @@ static void print_ctx_64(vcpu_guest_context_x86_64_t *ctx)
printf(" ds: %04x\t", regs->ds);
printf(" es: %04x\n", regs->es);
- printf(" fs: %04x @ %016"PRIx64"\n", regs->fs, ctx->fs_base);
- printf(" gs: %04x @ %016"PRIx64"/%016"PRIx64"\n", regs->gs,
+ printf(" fs: %04x @ %016"PRIx64, regs->fs, ctx->fs_base);
+ print_symbol(ctx->fs_base, KERNEL_DATA_ADDR);
+ printf("\n");
+ printf(" gs: %04x @ %016"PRIx64"/%016"PRIx64, regs->gs,
ctx->gs_base_kernel, ctx->gs_base_user);
+ if ( symbol_table )
+ {
+ print_symbol(ctx->gs_base_kernel, KERNEL_DATA_ADDR);
+ printf("/");
+ print_symbol(ctx->gs_base_user, KERNEL_DATA_ADDR);
+ }
+ printf("\n");
if (xenctx.disp_all) {
- print_special(ctx->ctrlreg, "cr", 0x1d, 8);
- print_special(ctx->debugreg, "dr", 0xcf, 8);
+ print_special(ctx->ctrlreg, "cr", 0x1d, cr_reg_mask, 8);
+ print_special(ctx->debugreg, "dr", 0xcf, dr_reg_mask, 8);
}
}
@@ -401,7 +488,7 @@ static void print_ctx(vcpu_guest_context_any_t *ctx)
{
if (ctxt_word_size == 4)
print_ctx_32(&ctx->x32);
- else if (guest_word_size == 4)
+ else if (guest_word_size != 8)
print_ctx_32on64(&ctx->x64);
else
print_ctx_64(&ctx->x64);
@@ -420,8 +507,13 @@ static guest_word_t instr_pointer(vcpu_guest_context_any_t *ctx)
r += ctx->x32.user_regs.cs << NONPROT_MODE_SEGMENT_SHIFT;
}
else
+ {
r = ctx->x64.user_regs.rip;
+ if ( !guest_protected_mode )
+ r += ctx->x64.user_regs.cs << NONPROT_MODE_SEGMENT_SHIFT;
+ }
+
return r;
}
@@ -436,8 +528,13 @@ static guest_word_t stack_pointer(vcpu_guest_context_any_t *ctx)
r += ctx->x32.user_regs.ss << NONPROT_MODE_SEGMENT_SHIFT;
}
else
+ {
r = ctx->x64.user_regs.rsp;
+ if ( !guest_protected_mode )
+ r += ctx->x64.user_regs.ss << NONPROT_MODE_SEGMENT_SHIFT;
+ }
+
return r;
}
@@ -455,8 +552,8 @@ static void print_ctx_32(vcpu_guest_context_t *ctx)
{
vcpu_guest_core_regs_t *regs = &ctx->user_regs;
- printf("PC: %08"PRIx32" ", regs->pc32);
- print_symbol(regs->pc32);
+ printf("PC: %08"PRIx32, regs->pc32);
+ print_symbol(regs->pc32, KERNEL_TEXT_ADDR);
printf("\n");
printf("CPSR: %08"PRIx32"\n", regs->cpsr);
printf("USR: SP:%08"PRIx32" LR:%08"PRIx32"\n",
@@ -507,8 +604,8 @@ static void print_ctx_64(vcpu_guest_context_t *ctx)
{
vcpu_guest_core_regs_t *regs = &ctx->user_regs;
- printf("PC: %016"PRIx64" ", regs->pc64);
- print_symbol(regs->pc64);
+ printf("PC: %016"PRIx64, regs->pc64);
+ print_symbol(regs->pc64, KERNEL_TEXT_ADDR);
printf("\n");
printf("LR: %016"PRIx64"\n", regs->x30);
@@ -605,7 +702,7 @@ static void *map_page(vcpu_guest_context_any_t *ctx, int vcpu, guest_word_t virt
mapped = xc_map_foreign_range(xenctx.xc_handle, xenctx.domid, XC_PAGE_SIZE, PROT_READ, mfn);
if (mapped == NULL) {
- fprintf(stderr, "failed to map page.\n");
+ fprintf(stderr, "\nfailed to map page for "FMT_32B_WORD".\n", virt);
return NULL;
}
@@ -621,14 +718,125 @@ static guest_word_t read_stack_word(guest_word_t *src, int width)
return word;
}
+static guest_word_t read_mem_word(vcpu_guest_context_any_t *ctx, int vcpu,
+ guest_word_t virt, int width)
+{
+ if ( (virt & 7) == 0 )
+ {
+ guest_word_t *p = map_page(ctx, vcpu, virt);
+
+ if ( p )
+ return read_stack_word(p, width);
+ else
+ return -1;
+ }
+ else
+ {
+ guest_word_t word = 0;
+ char *src, *dst;
+ int i;
+
+ /* Little-endian only */
+ dst = (char *)&word;
+ for (i = 0; i < width; i++)
+ {
+ src = map_page(ctx, vcpu, virt + i);
+ if ( src )
+ *dst++ = *src;
+ else
+ {
+ guest_word_t missing = -1LL;
+
+ /* Return all ones for missing memory */
+ memcpy(dst, &missing, width - i);
+ return word;
+ }
+ }
+ return word;
+ }
+}
+
static void print_stack_word(guest_word_t word, int width)
{
- if (width == 4)
+ if (width == 2)
+ printf(FMT_16B_WORD, word);
+ else if (width == 4)
printf(FMT_32B_WORD, word);
else
printf(FMT_64B_WORD, word);
}
+static int print_lines(vcpu_guest_context_any_t *ctx, int vcpu, int width,
+ guest_word_t mem_addr, guest_word_t mem_limit)
+{
+ guest_word_t mem_start = mem_addr;
+ guest_word_t word;
+ guest_word_t ascii[MAX_BYTES_PER_LINE/4];
+ int i;
+
+ for (i = 1; i < xenctx.lines + 1 && mem_addr < mem_limit; i++)
+ {
+ int j = 0;
+ int k;
+
+ if ( xenctx.tag_stack_dump )
+ {
+ print_stack_word(mem_addr, width);
+ printf(":");
+ }
+ while ( mem_addr < mem_limit &&
+ mem_addr < mem_start + i * xenctx.bytes_per_line )
+ {
+ void *p = map_page(ctx, vcpu, mem_addr);
+ if ( !p )
+ return -1;
+ word = read_mem_word(ctx, vcpu, mem_addr, width);
+ if ( xenctx.decode_as_ascii )
+ ascii[j++] = word;
+ printf(" ");
+ print_stack_word(word, width);
+ mem_addr += width;
+ }
+ if ( xenctx.decode_as_ascii )
+ {
+ /*
+ * Line up ascii output if less than bytes_per_line
+ * were printed.
+ */
+ for (k = j; k < xenctx.bytes_per_line / width; k++)
+ printf(" %*s", width * 2, "");
+ printf(" ");
+ for (k = 0; k < j; k++)
+ {
+ int l;
+ unsigned char *bytep = (unsigned char *)&ascii[k];
+
+ for (l = 0; l < width; l++)
+ {
+ if (isprint(*bytep))
+ printf("%c", *bytep);
+ else
+ printf(".");
+ bytep++;
+ }
+ }
+ }
+ printf("\n");
+ }
+ printf("\n");
+ return 0;
+}
+
+static void print_mem(vcpu_guest_context_any_t *ctx, int vcpu, int width,
+ guest_word_t mem_addr)
+{
+ printf("Memory (address ");
+ print_stack_word(mem_addr, width);
+ printf("):\n");
+ print_lines(ctx, vcpu, width, mem_addr,
+ mem_addr + xenctx.lines * xenctx.bytes_per_line);
+}
+
static int print_code(vcpu_guest_context_any_t *ctx, int vcpu)
{
guest_word_t instr;
@@ -646,49 +854,54 @@ static int print_code(vcpu_guest_context_any_t *ctx, int vcpu)
else
printf("%02x ", *c);
}
- printf("\n");
-
- printf("\n");
+ printf("\n\n\n");
return 0;
}
-static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width)
+static void print_stack_addr(guest_word_t addr, int width)
{
- guest_word_t stack = stack_pointer(ctx);
+ print_stack_word(addr, width);
+ printf(": ");
+}
+
+static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width,
+ guest_word_t stk_addr_start)
+{
+ guest_word_t stack = stk_addr_start;
guest_word_t stack_limit;
guest_word_t frame;
guest_word_t word;
guest_word_t *p;
- int i;
+ if ( width )
+ xenctx.bytes_per_line =
+ ((xenctx.bytes_per_line + width - 1) / width) * width;
stack_limit = ((stack_pointer(ctx) + XC_PAGE_SIZE)
- & ~((guest_word_t) XC_PAGE_SIZE - 1));
- printf("\n");
- printf("Stack:\n");
- for (i=1; i<5 && stack < stack_limit; i++) {
- while(stack < stack_limit && stack < stack_pointer(ctx) + i*32) {
- p = map_page(ctx, vcpu, stack);
- if (!p)
- return -1;
- word = read_stack_word(p, width);
- printf(" ");
- print_stack_word(word, width);
- stack += width;
- }
- printf("\n");
+ & ~((guest_word_t) XC_PAGE_SIZE - 1))
+ + (xenctx.nr_stack_pages - 1) * XC_PAGE_SIZE;
+ if ( xenctx.lines )
+ {
+ printf("Stack:\n");
+ if ( print_lines(ctx, vcpu, width, stack, stack_limit) )
+ return -1;
}
- printf("\n");
+
+ if ( !guest_protected_mode )
+ return 0;
if(xenctx.stack_trace)
printf("Stack Trace:\n");
else
printf("Call Trace:\n");
- printf("%c [<", xenctx.stack_trace ? '*' : ' ');
- print_stack_word(instr_pointer(ctx), width);
- printf(">] ");
+ if ( !xenctx.do_stack )
+ {
+ printf("%*s %c [<", width*2, "", xenctx.stack_trace ? '*' : ' ');
+ print_stack_word(instr_pointer(ctx), width);
+ printf(">]");
- print_symbol(instr_pointer(ctx));
- printf(" <--\n");
+ print_symbol(instr_pointer(ctx), KERNEL_TEXT_ADDR);
+ printf(" <--\n");
+ }
if (xenctx.frame_ptrs) {
stack = stack_pointer(ctx);
frame = frame_pointer(ctx);
@@ -698,9 +911,10 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width)
p = map_page(ctx, vcpu, stack);
if (!p)
return -1;
+ print_stack_addr(stack, width);
printf("| ");
print_stack_word(read_stack_word(p, width), width);
- printf(" \n");
+ printf("\n");
stack += width;
}
} else {
@@ -712,6 +926,7 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width)
return -1;
frame = read_stack_word(p, width);
if (xenctx.stack_trace) {
+ print_stack_addr(stack, width);
printf("|-- ");
print_stack_word(read_stack_word(p, width), width);
printf("\n");
@@ -723,28 +938,32 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width)
if (!p)
return -1;
word = read_stack_word(p, width);
+ print_stack_addr(stack, width);
printf("%c [<", xenctx.stack_trace ? '|' : ' ');
print_stack_word(word, width);
- printf(">] ");
- print_symbol(word);
+ printf(">]");
+ print_symbol(word, KERNEL_TEXT_ADDR);
printf("\n");
stack += width;
}
}
} else {
- stack = stack_pointer(ctx);
+ stack = stk_addr_start;
while(stack < stack_limit) {
p = map_page(ctx, vcpu, stack);
if (!p)
return -1;
- word = read_stack_word(p, width);
- if (is_kernel_text(word)) {
+ word = read_mem_word(ctx, vcpu, stack, width);
+ if ( kernel_addr(word) >= KERNEL_TEXT_ADDR )
+ {
+ print_stack_addr(stack, width);
printf(" [<");
print_stack_word(word, width);
- printf(">] ");
- print_symbol(word);
+ printf(">]");
+ print_symbol(word, KERNEL_TEXT_ADDR);
printf("\n");
} else if (xenctx.stack_trace) {
+ print_stack_addr(stack, width);
printf(" ");
print_stack_word(word, width);
printf("\n");
@@ -776,8 +995,9 @@ static void dump_ctx(int vcpu)
perror("xc_domain_hvm_getcontext_partial");
return;
}
- guest_word_size = (cpuctx.msr_efer & 0x400) ? 8 : 4;
guest_protected_mode = (cpuctx.cr0 & CR0_PE);
+ guest_word_size = (cpuctx.msr_efer & 0x400) ? 8 :
+ guest_protected_mode ? 4 : 2;
/* HVM guest context records are always host-sized */
if (xc_version(xenctx.xc_handle, XENVER_capabilities, &xen_caps) != 0) {
perror("xc_version");
@@ -792,12 +1012,26 @@ static void dump_ctx(int vcpu)
}
#endif
+#ifndef NO_TRANSLATION
+ if ( xenctx.do_memory )
+ {
+ print_mem(&ctx, vcpu, guest_word_size, xenctx.mem_addr);
+ return;
+ }
+ if ( xenctx.do_stack )
+ {
+ print_stack(&ctx, vcpu, guest_word_size, xenctx.stk_addr);
+ return;
+ }
+#endif
print_ctx(&ctx);
#ifndef NO_TRANSLATION
if (print_code(&ctx, vcpu))
return;
- if (is_kernel_text(instr_pointer(&ctx)))
- if (print_stack(&ctx, vcpu, guest_word_size))
+ if ( !guest_protected_mode ||
+ kernel_addr(instr_pointer(&ctx)) >= KERNEL_TEXT_ADDR )
+ if ( print_stack(&ctx, vcpu, guest_word_size,
+ stack_pointer(&ctx)) )
return;
#endif
}
@@ -811,7 +1045,13 @@ static void dump_all_vcpus(void)
if ( xc_vcpu_getinfo(xenctx.xc_handle, xenctx.domid, vcpu, &vinfo) )
continue;
if ( vinfo.online )
+ {
+ printf("vcpu%d:\n", vcpu);
dump_ctx(vcpu);
+ printf("\n");
+ }
+ else
+ printf("vcpu%d offline\n\n", vcpu);
}
}
@@ -823,27 +1063,66 @@ static void usage(void)
printf("options:\n");
printf(" -f, --frame-pointers\n");
- printf(" assume the kernel was compiled with\n");
- printf(" frame pointers.\n");
+ printf(" assume the kernel was compiled with\n");
+ printf(" frame pointers.\n");
printf(" -s SYMTAB, --symbol-table=SYMTAB\n");
- printf(" read symbol table from SYMTAB.\n");
- printf(" -S --stack-trace print a complete stack trace.\n");
- printf(" -k, --kernel-start\n");
- printf(" set user/kernel split. (default 0xc0000000)\n");
- printf(" -a --all display more registers\n");
- printf(" -C --all-vcpus print info for all vcpus\n");
+ printf(" read symbol table from SYMTAB.\n");
+ printf(" -S, --stack-trace print a complete stack trace.\n");
+ printf(" -k KADDR, --kernel-start=KADDR\n");
+ printf(" set user/kernel split. (default 0x"FMT_32B_WORD")\n",
+ kernel_start);
+ printf(" -a, --all display more registers\n");
+ printf(" -C, --all-vcpus print info for all vcpus\n");
+ printf(" -n PAGES, --display-stack-pages=PAGES\n");
+ printf(" Display N pages from the stack pointer. (default %d)\n",
+ DEFAULT_NR_STACK_PAGES);
+ printf(" Changes stack limit. Note: use with caution (easy\n");
+ printf(" to get garbage).\n");
+ printf(" -b <bytes>, --bytes-per-line <bytes>\n");
+ printf(" change the number of bytes per line output for Stack.\n");
+ printf(" (default %d) Note: rounded to native size (4 or 8 bytes).\n",
+ DEFAULT_BYTES_PER_LINE);
+ printf(" -l <lines>, --lines <lines>\n");
+ printf(" change the number of lines output for Stack. (default %d)\n",
+ DEFAULT_LINES);
+ printf(" Can be specified as MAX. Note: Fewer lines will be output\n");
+ printf(" if stack limit reached.\n");
+ printf(" -D, --decode-as-ascii\n");
+ printf(" add a decode of Stack dump as ascii.\n");
+ printf(" -t, --tag-stack-dump\n");
+ printf(" add address on each line of Stack dump.\n");
+#ifndef NO_TRANSLATION
+ printf(" -m maddr, --memory=maddr\n");
+ printf(" dump memory at maddr.\n");
+ printf(" -d daddr, --dump-as-stack=daddr\n");
+ printf(" dump memory as a stack at daddr.\n");
+#endif
}
int main(int argc, char **argv)
{
int ch;
int ret;
- static const char *sopts = "fs:hak:SC";
+ const char *prog = argv[0];
+ static const char *sopts = "fs:hak:SCn:b:l:Dt"
+#ifndef NO_TRANSLATION
+ "m:d:"
+#endif
+ ;
static const struct option lopts[] = {
{"stack-trace", 0, NULL, 'S'},
{"symbol-table", 1, NULL, 's'},
{"frame-pointers", 0, NULL, 'f'},
{"kernel-start", 1, NULL, 'k'},
+ {"display-stack-pages", 0, NULL, 'n'},
+ {"decode-as-ascii", 0, NULL, 'D'},
+ {"tag-stack-dump", 0, NULL, 't'},
+#ifndef NO_TRANSLATION
+ {"memory", 1, NULL, 'm'},
+ {"dump-as-stack", 1, NULL, 'd'},
+#endif
+ {"bytes-per-line", 1, NULL, 'b'},
+ {"lines", 1, NULL, 'l'},
{"all", 0, NULL, 'a'},
{"all-vcpus", 0, NULL, 'C'},
{"help", 0, NULL, 'h'},
@@ -852,6 +1131,11 @@ int main(int argc, char **argv)
const char *symbol_table = NULL;
int vcpu = 0;
+ int do_default = 1;
+
+ xenctx.bytes_per_line = DEFAULT_BYTES_PER_LINE;
+ xenctx.lines = DEFAULT_LINES;
+ xenctx.nr_stack_pages = DEFAULT_NR_STACK_PAGES;
while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
switch(ch) {
@@ -867,17 +1151,73 @@ int main(int argc, char **argv)
case 'a':
xenctx.disp_all = 1;
break;
+ case 'n':
+ xenctx.nr_stack_pages = strtol(optarg, NULL, 0);
+ if ( xenctx.nr_stack_pages < 1)
+ {
+ fprintf(stderr,
+ "%s: Unsupported value(%d) for --display-stack-pages '%s'. Needs to be >= 1\n",
+ prog, xenctx.nr_stack_pages, optarg);
+ exit(-1);
+ }
+ break;
+ case 'D':
+ xenctx.decode_as_ascii = 1;
+ break;
+ case 't':
+ xenctx.tag_stack_dump = 1;
+ break;
+ case 'b':
+ xenctx.bytes_per_line = strtol(optarg, NULL, 0);
+ if ( xenctx.bytes_per_line < 4 ||
+ xenctx.bytes_per_line > MAX_BYTES_PER_LINE )
+ {
+ fprintf(stderr,
+ "%s: Unsupported value for --bytes-per-line '%s'. Needs to be 4 <= %d <= %d\n",
+ prog, optarg, xenctx.bytes_per_line,
+ MAX_BYTES_PER_LINE);
+ exit(-1);
+ }
+ break;
+ case 'l':
+ if ( !strcmp(optarg, "all") || !strcmp(optarg, "ALL") ||
+ !strcmp(optarg, "max") || !strcmp(optarg, "MAX") )
+ xenctx.lines = INT_MAX - 1;
+ else
+ xenctx.lines = strtol(optarg, NULL, 0);
+ if ( xenctx.lines < 0 || xenctx.lines == INT_MAX)
+ {
+ fprintf(stderr,
+ "%s: Unsupported value(%d) for --lines '%s'. Needs to be >= 0, < %d\n",
+ prog, xenctx.lines, optarg, INT_MAX);
+ exit(-1);
+ }
+ break;
case 'C':
xenctx.all_vcpus = 1;
+ do_default = 0;
break;
case 'k':
kernel_start = strtoull(optarg, NULL, 0);
+ xenctx.kernel_start_set = 1;
break;
+#ifndef NO_TRANSLATION
+ case 'm':
+ xenctx.mem_addr = strtoull(optarg, NULL, 0);
+ xenctx.do_memory = 1;
+ do_default = 0;
+ break;
+ case 'd':
+ xenctx.stk_addr = strtoull(optarg, NULL, 0);
+ xenctx.do_stack = 1;
+ do_default = 0;
+ break;
+#endif
case 'h':
usage();
exit(-1);
case '?':
- fprintf(stderr, "%s --help for more options\n", argv[0]);
+ fprintf(stderr, "%s --help for more options\n", prog);
exit(-1);
}
}
@@ -889,14 +1229,33 @@ int main(int argc, char **argv)
exit(-1);
}
+#ifndef NO_TRANSLATION
+ if ( xenctx.frame_ptrs && xenctx.do_stack )
+ {
+ fprintf(stderr,
+ "%s: both --frame-pointers and --dump-as-stack is not supported\n",
+ prog);
+ exit(-1);
+ }
+#endif
+
xenctx.domid = atoi(argv[0]);
if (xenctx.domid==0) {
fprintf(stderr, "cannot trace dom0\n");
exit(-1);
}
- if (argc == 2)
+ if ( argc == 2 )
+ {
+ if ( xenctx.all_vcpus )
+ {
+ fprintf(stderr,
+ "%s: both --all-vcpus and [VCPU] is not supported\n",
+ prog);
+ exit(-1);
+ }
vcpu = atoi(argv[1]);
+ }
if (symbol_table)
read_symbol_table(symbol_table);
@@ -913,26 +1272,37 @@ int main(int argc, char **argv)
exit(-1);
}
- if (!xenctx.dominfo.paused) {
- ret = xc_domain_pause(xenctx.xc_handle, xenctx.domid);
- if (ret < 0) {
- perror("xc_domain_pause");
- exit(-1);
- }
- xenctx.self_paused = 1;
+ ret = xc_domain_pause(xenctx.xc_handle, xenctx.domid);
+ if (ret < 0) {
+ perror("xc_domain_pause");
+ exit(-1);
}
+#ifndef NO_TRANSLATION
+ if ( xenctx.do_memory )
+ {
+ dump_ctx(vcpu);
+ if ( xenctx.do_stack || xenctx.all_vcpus )
+ printf("\n");
+ }
+ xenctx.do_memory = 0;
+ if ( xenctx.do_stack )
+ {
+ dump_ctx(vcpu);
+ if ( xenctx.all_vcpus )
+ printf("\n");
+ }
+ xenctx.do_stack = 0;
+#endif
if (xenctx.all_vcpus)
dump_all_vcpus();
- else
+ if ( do_default )
dump_ctx(vcpu);
- if (xenctx.self_paused) {
- ret = xc_domain_unpause(xenctx.xc_handle, xenctx.domid);
- if (ret < 0) {
- perror("xc_domain_unpause");
- exit(-1);
- }
+ ret = xc_domain_unpause(xenctx.xc_handle, xenctx.domid);
+ if (ret < 0) {
+ perror("xc_domain_unpause");
+ exit(-1);
}
ret = xc_interface_close(xenctx.xc_handle);
diff --git a/tools/xentrace/xentrace.8 b/tools/xentrace/xentrace.8
index c84e2e9..ac18e9f 100644
--- a/tools/xentrace/xentrace.8
+++ b/tools/xentrace/xentrace.8
@@ -37,10 +37,10 @@ set the time, p, (in milliseconds) to sleep between polling the buffers
for new data.
.TP
.B -c, --cpu-mask=c
-set cpu-mask
+set bitmask of CPUs to trace. It is limited to 32-bits.
.TP
.B -e, --evt-mask=e
-set evt-mask
+set event capture mask. If not specified the TRC_ALL will be used.
.TP
.B -?, --help
Give this help list
diff --git a/tools/xm-test/COPYING b/tools/xm-test/COPYING
deleted file mode 100644
index d60c31a..0000000
--- a/tools/xm-test/COPYING
+++ /dev/null
@@ -1,340 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/tools/xm-test/ChangeLog b/tools/xm-test/ChangeLog
deleted file mode 100644
index daa02a5..0000000
--- a/tools/xm-test/ChangeLog
+++ /dev/null
@@ -1,11 +0,0 @@
-0.1.1
- Dan Smith <danms at us.ibm.com>
-
- - More tests
- - Added build check for Flex/Bison
-
-
-0.1.0
- Dan Smith <danms at us.ibm.com>
-
- - initial release
diff --git a/tools/xm-test/Makefile.am b/tools/xm-test/Makefile.am
deleted file mode 100644
index 8d0c84b..0000000
--- a/tools/xm-test/Makefile.am
+++ /dev/null
@@ -1,18 +0,0 @@
-SUBDIRS = ramdisk tests
-EXTRA_DIST = lib runtest.sh mkreport
-
-existing:
- $(MAKE) -C ramdisk existing
-
-# Remove any pyc's, CVS dirs, and prune the skel dirs
-dist-hook:
- find $(distdir) -name '*~' -delete -print
- find $(distdir) -name '*.pyc' -delete -print
- for i in Root Repository Entries; do \
- find $(distdir) -name $$i -delete ;\
- done
- find $(distdir) -name CVS -delete
- find $(distdir) -name '*.test' -delete
- cd $(distdir)/ramdisk/skel && find . -empty -delete
- chmod a+x $(distdir)/runtest.sh
-
diff --git a/tools/xm-test/README b/tools/xm-test/README
deleted file mode 100644
index 88c0083..0000000
--- a/tools/xm-test/README
+++ /dev/null
@@ -1,310 +0,0 @@
-
-----------------------------------------------------------------------
-
-Status of xm-test
-
-The xm-test environment was written in 2006. It was mostly not
-updated or adapted to new / changed functionality since then.
-("it's slowly rotting", Keir Fraser, xen-devel mailing list,
-June 2009)
-During the last weeks there was the attempt to fix most of the
-problems - but there are still some major issues:
-o The reporting infrastructure is 'long gone' (Dan Smith, Mail from
- Aug 2009). Therefore there is no way to send out reports. When
- running the runtests.sh you should therefore specify the '-d'
- option.
-o The initrd.img (which is downloaded) is quite old and needs an
- update. Especially functionality for migration it is missing.
- [It should be discussed using an existing distribution instead of
- compiling a micro distribution and put this into the initrd.)
-
-Andreas Florath <xen at flonatel.org>
-August 2009
-
-----------------------------------------------------------------------
-
-
-xm-test README
-
-Copyright (C) International Business Machines Corp., 2005
-Author(s): Dan Smith <danms at us.ibm.com>
- Woody Marvel <marvel at us.ibm.com>
-
-Overview
-========
-
-This suite provides a framework for testing the Xen userspace tools.
-The directory structure is:
-
- ./xm-test
- |
- +-/lib: Python support libraries
- |
- +-/ramdisk: Staging area for building the test ramdisk
- |
- +-/tests
- | |
- | +-/create: Tests for the 'xm create' command
- | +-/destroy: Tests for the 'xm destroy' command
- | . . .
- |
- +-/utils: Utility scripts for ramdisk building
-
-Reports are posted here:
-
- http://xmtest.dague.org
-
-
-Building
-========
-
-Before the test suite can be used, the ramdisk must be built from
-source. All source needed for this process is automatically
-downloaded, extracted, and compiled. Due to the need to create
-special files, this process must be done as root:
-
- # ./autogen
- # ./configure
- # make
-
-NB: If you have the initrd.img from another installation of xm-test,
-you can copy it into the ramdisk directory to eliminate the need to
-rebuild it. If you do this, there is no need to run 'make' again.
-Simply copy the initrd-X.Y-ARCH.img file into ramdisk/ and then run:
-
- # make existing
-
-Or, you can run:
- # INITRD="http://url.of.initrd.repo/" make existing
-
-You do not need to include the name of the image itself in the url,
-however, an initrd with the right name (initrd.X.Y-ARCH.img) and version
-number must exist at that location. The script will determine which
-version of the initrd it needs and try to download the right file from
-that location.
-
-This will set up the link so that xm-test will use the existing
-ramdisk. Next, just run "runtest.sh" normally. Note that in general,
-you should not attempt to use a ramdisk from a previous minor version
-of xm-test (i.e., don't use a ramdisk from 0.4.0 with 0.5.0. 0.5.0
-should work for 0.5.3 though)
-
-
-BUILDING with HVM Support
-=========================
-
-If you'd like to build and run this with hardware virtual machine assist
-(HVM) support to test fully virtualized disk images on VMX/SVM hardware,
-please add the --enable-hvm-support option to configure:
-
- # ./autogen
- # ./configure --enable-hvm-support
- # make
-
-The ramdisk/bin/create_disk_image script, which builds the full virt
-disk.img, requires Lilo 22.7+ to be installed on the system. Lilo is
-used to install the bootloader on the disk.img.
-
-If HVM support is enabled, the ramdisk/bin/create_disk_image script
-will be run to create a full virt disk.img in the ramdisk directory. The
-script, by default, will look in /boot for the first non-Xen kernel it
-runs across. If you'd like to set xm-test to use a specific kernel,
-rather than the first one it finds in /boot, you can configure it in
-with the "--with-hvm-kernel=KERNEL" option:
-
-# ./autogen
-# ./configure --enable-hvm-support --with-hvm-kernel=KERNEL
-# make
-
-Otherwise, you can always rerun the create script using the -k option
-to use a specific kernel.
-
-The disk.img created for HVM testing must contain a pcnet32 driver for
-network tests. The ramdisk/bin/create_disk_image script will, by default,
-look in the /lib/modules directory associated with the kernel being
-used. If you'd like to specify a different location for the driver or
-want to tell the script that the driver is built into the kernel, please
-use the "--with-driver-dir=DRVDIR" configure option. If built into
-the kernel, please use the key word "builtin" with the option:
-
-# ./autogen
-# ./configure --enable-hvm-support --with-driver-dir=builtin
-- or -
-# ./configure --enable-hvm-support --with-driver-dir=/driver/directory
-# make
-
-Xm-test will look for disk.img in the ramdisk directory when run by
-default.
-
-
-Running
-=======
-
-To run the full test suite, do the following as root:
-
- # ./runtest.sh <logfile>
-
-This will run all tests, as well as generate and submit a report at
-the end. All output files will begin with "<logfile>."
-If you wish to prevent submission of a report, add "-d" to the
-command line like this:
-
- # ./runtest.sh -d <logfile>
-
-It may be useful to run tests without submission as above, and then
-submit the report at a later time. To do so, run runtest.sh with the
--s flag and the name of the previously-generated report:
-
- # ./runtest.sh -s <logfile>
-
-Group test sets are supported in xm-test. This is form of layering of
-tests groups/cases/tests. In the framework directory "grouptest",
-files exist for group processing. The user can add groups, casenames
-and test lists as required. Default group run is "grouptest/default".
-
- # ./runtest.sh -g <groupname> <logfile>
-
-* NOTE: There is a quick set of tests in group mode, that was added to
-run certain casenames and tests, and there is a "medium" group, which is a
-medium-length run (around 20 minutes). Neither is a substitute for the full
-xm-test test suite.
- # ./runtest.sh -g quick <logfile>
- # ./runtest.sh -g medium <logfile>
-
-
-
-It may be desirable to run a specific test group. This can be
-accomplished by doing the following:
-
- # cd tests/create
- # TEST_VERBOSE=1 make check
-
-When developing or debugging a specific feature, a single test can be
-run to avoid having to run even a whole test group:
-
- # cd tests/create
- # TEST_VERBOSE=1 make check TESTS=01_create_basic_pos.test
-
-The runtest.sh script will create several files, including a .report
-file, which is the cleaned up, email-friendly report of failures.
-Additionally, the script will submit your results to the development
-team for trend analysis. This helps us determine the level of success
-people "out there" are having with different versions of Xen.
-
-Note: you should generally run xm-test with a minimum of memory
-allocated to Dom0. More memory available for allocation to DomUs
-means a more rigorous test.
-
-BIG FAT WARNING: The test framework assumes it is running on a
-dedicated machine. As such, the library automatically destroys any
-running DomUs on the system to provide each test with a "clean slate".
-
-
-Testing the XML-RPC and Xen-API interfaces of xend
-==================================================
-
-The xm-test suite can be used to test xm's interface with xend using
-either XML-RPC or the Xen-API. In order to use either one of these modes,
-xm needs to be configured using its configuration file
-'/etc/xen/xm-config.xml'.
-Note: The current default configuration after a fresh install of the xen
-sources currently is to use the XML-RPC interface for communication with xend.
-
-Example content for the xm-config.xml for using the Xen-API looks as
-follows:
-
-<xm>
- <server type='Xen-API'
- uri='http://localhost:9363/'
- username='me'
- password='mypassword' />
-</xm>
-
-This configuration makes xm talk to xend using port 9363. For this to
-work, also xend needs to be configured to listen to port 9363. Therefore
-The following line must be in /etc/xen/xend-config.sxp.
-
-(xen-api-server (( 127.0.0.1:9363 none )))
-
-To communicate via the legacy XML-RPC interface, the file
-'/etc/xen/xm-config.xml' may simply have the following content or
-may be complete remove from the /etc/xen directory.
-
-<xm>
-</xm>
-
-A few tests have been written for the xm-test suite that test the
-Xen-API interface directly without relying on 'xm'. These tests can be
-found in the grouptest 'xapi' and for them to work properly, xm must have
-been configured to use the Xen-API following the instructions above. To
-run these test, the following command line can be invoked:
-
- # ./runtest.sh -g xapi <logfile>
-
-
-
-Extending
-=========
-
-Additional tests may be added in existing groups to test additional
-cases for a given xm subcommand. Test programs should be named
-according to the following scheme:
-
- XY_group_name_{pos,neg}.py
-
-Where:
- XY is the next number in line
- group is the name of the subcommand being tested
- name is the short name of the test
- {pos,neg} denotes whether this is a positive or negative test case
-
-New subcommand groups should be added as directories named after the
-subcommand itself. The "Makefile.am.template" should be copied into
-the new group directory as "Makefile.am".
-
-See the Writing_Tests_HOWTO file for more detailed information on
-adding tests to the suite.
-
-
-Developer Notes
-===============
-
-Our library provides a DomU console abstraction for automated
-execution of commands. Please note that this is relatively fragile,
-and is intended for use only with the ramdisk built by the framework.
-Because the console experiences some occasional corruption, this
-method is not completely perfect at the moment, although the authors
-use it with relatively few problems.
-
-
-Known Issues
-============
-
-If you create a domain with a small amount of memory, under 32MBs, you
-may run into out of memory situations for the domain. There's no way
-to know the amount of memory needed by the kernel and modules used. Xm-test
-uses 64MBs as default and that should work. If there are out of memory
-issues, the default can be changed. Edit xm-test/lib/XmTestLib/XenDomain.py
-and change ParavirtDefaults and HVMDefaults "memory".
-
-There are two tests that work with small memory, 15_create_smallmem_pos.py
-and 16_create_smallmem_neg.py. The first makes sure the default 32 MBs
-limit works. The second checks a low memory fail situation. These tests
-are located in the xm-test/tests/create directory and can be easily edited
-to change the MEM value they should test. If the 32MBs test fails, the
-failure should be reported to the Xen xen-devel mailing list. The Xen
-tools use 32MBs as a lower acceptable limit for domain creation. The Xen
-mailing lists are located here:
-
-http://lists.xensource.com/
-
-
-Reporting Bugs
-==============
-
-If you find a bug in the test framework, report it to:
-
- Dan Smith <danms at us.ibm.com>
-
-If you find a bug in a specific test case, contact the author of the
-test case first.
diff --git a/tools/xm-test/TODO b/tools/xm-test/TODO
deleted file mode 100644
index 14e42d3..0000000
--- a/tools/xm-test/TODO
+++ /dev/null
@@ -1,3 +0,0 @@
-Todo List for xm-test
-
-
diff --git a/tools/xm-test/Writing_Tests_HOWTO b/tools/xm-test/Writing_Tests_HOWTO
deleted file mode 100644
index 379b0b1..0000000
--- a/tools/xm-test/Writing_Tests_HOWTO
+++ /dev/null
@@ -1,136 +0,0 @@
-
-Writing Tests HOWTO
-===================
-
-One goal for xm-test is to make test writing very easy. Xm-test includes
-a library in lib/XmTestLib that contains all the necessary methods for
-creating and shutting down domains. Include the library in your test by
-importing it:
-
- from XmTestLib import *
-
-
-Guidelines
-==========
-
-1. Tests should be short and single purposed. This means testing as
- little as possible in a single test. Do not overload tests. The more
- that's in a test the more difficult it is to track down what failed.
-
-2. Tests should report as much information as possible when calling
- FAIL() or SKIP().
-
-3. A test should report SKIP() only if it cannot be run on the current
- machine or it makes no sense to run it. SMP tests on an UP system,
- for example, may not make sense. Or, there are some tests for
- para-virtualized guests that won't work on a fully virtualized
- guest.
-
-4. Use the traceCommand() function to run commands on Domain0, the
- Xen management domain. This function logs everything, which is useful
- in case of failure.
-
-5. Use the domain's console.runCmd method to run commands on a guest
- domain. This ensures logging and consistency. Please see 'Creating
- and Using Domains' below for an example.
-
-6. Tests need to capture and handle libary exceptions such as:
-
- - ConsoleError can be raised when sending a command to a console.
- - DomainError can be raised when a domain is started, indicating
- a possible configuration error.
- - TimeoutError can be raised when the traceCommand() method is used.
-
-7. Tests shouldn't depend on where the test is being run from or the
- system on which it is run.
-
-8. Please use the existing tests for a guide, especially:
-
- - create/01_create_basic_pos.py
- - create/13_create_multinic_pos.py
- - memset/01_memset_basic_pos.py
- - reboot/01_reboot_basic_pos.py
- - migrate/01_migrate_localhost_pos.py
-
-
-Creating and Using Domains
-==========================
-
-Xen domains, both full and para virtualized, are represented by the
-XmTestDomain class. The class contains methods for starting a Xen domain,
-shutting it down, or destroying it. Consoles, used to execute commands
-on guest test domains, are opened and closed through the XmTestDomain
-class. Devices, which are represented by the XenDevice class, are also
-added and removed using XmTestDomain methods.
-
-Here's a simple example for creating a domain, opening a console, running
-a command, and then shutting down the domain:
-
-1) Create a domain:
-
- domain = XmTestDomain()
-
-2) Start the domain and grab a console:
-
- try:
- console = domain.start()
- except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-3) Run a command inside the new domain using the console, saving the
- console log if an error is encountered:
-
- try:
- # Run 'ls'
- run = console.runCmd("ls")
- except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-4) Stop the domain, which nicely shuts it down:
-
- domain.stop()
-
-
-Writing Tests with Networking
-=============================
-
-The xm-test suite includes the ability to test networking for domains.
-Networking is configured at configuration time. While testing NAT and
-routing environments in the future, the current xm-test only supports
-a bridging environment. Xm-test currently only supports a range of
-IPs, the dhcp feature will be added soon.
-
-The network tests will need to know what IPs to use. IPs are
-configured when you build xm-test. Xm-test by default a range chosen
-at random from the RFC1918 private use space, and published at
-www.ucam.org/cam-grin, 172.30.206.1-172.30.206.254 from
-172.30.206.0/24. If you'd like to set a new range, do so at configure
-time, a netmask and network address must also be defined:
-
- # ./configure --with-net-ip-range=192.0.2.1-192.0.2.100 --with-network-address=192.0.2.0 --with-netmask=255.255.255.0
-
-The tests will not need to set network information, this is done by
-the library once it's configured.
-
-As mentioned above, xm-test's goal is to make writing tests easy. Creating
-domains with networking should also be easy. To create a domain with
-a single network interface, tests can use a XmTestNetDomain object. It
-creates a XenNetDevice for the domain automatically using the pre-configured
-IP information. Otherwise, a network interface can be added to a domain
-prior to starting it (the ability to attach devices will be added):
-
- domain = XmTestDomain()
- domain.newDevice(XenNetDevice, "eth0")
- domain.newDevice(XenNetDevice, "eth1")
-
-Here, the domain is created and then the XenDomain factory newDevice
-is called to create a new device of class XenNetDevice to the domain.
-The xm-test library will automatically assign an IP from the configured
-list, execute ifconfig on the guest domain console, and create an
-alias on Domain0.
-
-
diff --git a/tools/xm-test/autogen b/tools/xm-test/autogen
deleted file mode 100755
index d0130f3..0000000
--- a/tools/xm-test/autogen
+++ /dev/null
@@ -1,9 +0,0 @@
-#! /bin/sh -ex
-
-# if libtool is ever added, turn this on
-# libtoolize --copy --force --automake
-aclocal
-automake --add-missing --copy --foreign
-autoconf
-chmod a+x runtest.sh
-
diff --git a/tools/xm-test/configure.ac b/tools/xm-test/configure.ac
deleted file mode 100644
index c142140..0000000
--- a/tools/xm-test/configure.ac
+++ /dev/null
@@ -1,155 +0,0 @@
-# xm-test configure.ac input script
-
-# Basic header information
-AC_INIT([xm-test], [1.1.0])
-AM_INIT_AUTOMAKE([1.7 foreign])
-
-MK=''; AC_SUBST(MK)
-
-# Check for dependencies
-AC_PROG_CC
-#AC_PROG_INSTALL
-AC_CHECK_PROG([LILO], lilo, lilo, "no", [$PATH])
-
-XEN_PYTHON_PATH=$(/usr/sbin/xen-python-path)
-
-# Right now, we can assume that the lib/ directory
-# is two levels above the tests
-TESTLIB=../../lib
-TENV="PYTHONPATH=$PYTHONPATH:$TESTLIB:$XEN_PYTHON_PATH"
-
-AC_ARG_ENABLE(hvm-support,
- [[ --enable-hvm-support enable hardware virtual machine assist]],
- [
- ENABLE_HVM=True
- ],[
- ENABLE_HVM=False
- ])
-
-if test "x$ENABLE_HVM" = "xTrue"; then
- if test "$LILO" = "no"; then
- AC_MSG_ERROR([lilo not found
-lilo version 22.7 or greater must be installed for testing with hvm enabled.])
- else
- pass=`$LILO -V | sed -e "s/LILO version //" | awk -F "." '{if ($1 >=22 && $2 >= 7) print "true"; else print "false"}'`
- if test "$pass" != "true"; then
- AC_MSG_ERROR(Lilo version must be equal or greater to 22.7+.)
- fi
- fi
-fi
-
-AM_CONDITIONAL(HVM, test x$ENABLE_HVM = xTrue)
-AC_SUBST(ENABLE_HVM)
-
-# Network needs to know ips to use: dhcp or a range of IPs in the form
-# of: 192.0.2.1-192.0.2.100
-# If not dhcp, a netmask and network address must be supplied. Defaults to
-# range allocated in www.ucam.org/cam-grin.
-NET_IP_RANGE="172.30.206.1-172.30.206.254"
-AC_ARG_WITH(net-ip-range,
- [ --with-net-ip-range=ip-range Set a range of ip addresses to use for xm-test guest domain networks. Can specify dhcp or a range of IPs: 192.0.2.1-192.0.2.100 [[default="172.30.206.1-172.30.206.254"]]],
- [ NET_IP_RANGE="$withval" ])
-
-iprange=`echo $NET_IP_RANGE | perl -e 'while(<>) { print if /\d+\.\d+\.\d+\.\d+-\d+\.\d+\.\d+\.\d+/ }'`
-
-NETWORK_ADDRESS="172.30.206.0"
-AC_ARG_WITH(network-address,
- [ --with-network-address=ip Set network address to use with ip range [[default="172.30.206.0"]]],
- [ NETWORK_ADDRESS="$withval" ])
-
-NETMASK="255.255.255.0"
-AC_ARG_WITH(netmask,
- [ --with-netmask=mask Set netmask to use with ip range [[default="255.255.255.0"]]],
- [ NETMASK="$withval" ])
-
-if test "x$NET_IP_RANGE" != "xdhcp" && test -z "$iprange"
-then
- AC_MSG_ERROR(Invalid net-ip-range.)
-fi
-
-AC_SUBST(NET_IP_RANGE)
-AC_SUBST(NETWORK_ADDRESS)
-AC_SUBST(NETMASK)
-
-DOM0_INTF="eth0"
-AC_ARG_WITH(dom0-intf,
- [ --with-dom0-intf=intf Set dom0 interface name [[default="eth0"]]],
- [ DOM0_INTF="$withval" ])
-
-AC_SUBST(DOM0_INTF)
-
-AC_ARG_WITH(hvm-kernel,
- [[ --with-hvm-kernel=kernel Use this kernel for hvm disk.img testing]],
- HVMKERNEL=$withval,
- HVMKERNEL="no")
-
-dnl substitute @HVMKERNEL@ in all Makefiles
-AC_SUBST(HVMKERNEL)
-
-AC_ARG_WITH(driver-dir,
- [[ --with-driver-dir=drvdir Look in this directory for the pcnet32 driver for the vmx disk.img. drvdir can equal key word "builtin" if driver is built into the kernel]],
- DRVDIR=$withval,
- DRVDIR="no")
-
-dnl substitute @DRVDIR@ in all Makefiles
-AC_SUBST(DRVDIR)
-
-NETDRV="8139too.ko"
-AC_ARG_WITH(network-drv,
- [ --with-network-drv=driver Set network driver to use [[default="8139too.ko"]]],
- [ NETDRV="$withval" ])
-
-dnl substitute @DRVDIR@ in all Makefiles
-AC_SUBST(NETDRV)
-
-AC_SUBST(TENV)
-AC_SUBST(PACKAGE_VERSION)
-
-AC_PROG_YACC
-AC_PROG_LEX
-
-# basic build files
-AC_CONFIG_FILES([
- Makefile
- ramdisk/Makefile
- tests/Makefile
- tests/_sanity/Makefile
- tests/block-list/Makefile
- tests/block-create/Makefile
- tests/block-destroy/Makefile
- tests/block-integrity/Makefile
- tests/console/Makefile
- tests/create/Makefile
- tests/destroy/Makefile
- tests/dmesg/Makefile
- tests/domid/Makefile
- tests/domname/Makefile
- tests/help/Makefile
- tests/info/Makefile
- tests/list/Makefile
- tests/memmax/Makefile
- tests/memset/Makefile
- tests/migrate/Makefile
- tests/network-attach/Makefile
- tests/network/Makefile
- tests/pause/Makefile
- tests/reboot/Makefile
- tests/restore/Makefile
- tests/save/Makefile
- tests/sched-credit/Makefile
- tests/sedf/Makefile
- tests/shutdown/Makefile
- tests/sysrq/Makefile
- tests/unpause/Makefile
- tests/vcpu-pin/Makefile
- tests/vcpu-disable/Makefile
- tests/xapi/Makefile
- tests/enforce_dom0_cpus/Makefile
- tests/cpupool/Makefile
- lib/XmTestReport/xmtest.py
- lib/XmTestLib/config.py
- ])
-
-AC_OUTPUT
-
-chmod a+x lib/XmTestReport/xmtest.py
diff --git a/tools/xm-test/grouptest/cpupool b/tools/xm-test/grouptest/cpupool
deleted file mode 100644
index 6a56bab..0000000
--- a/tools/xm-test/grouptest/cpupool
+++ /dev/null
@@ -1 +0,0 @@
-cpupool
diff --git a/tools/xm-test/grouptest/create b/tools/xm-test/grouptest/create
deleted file mode 100644
index 359af40..0000000
--- a/tools/xm-test/grouptest/create
+++ /dev/null
@@ -1 +0,0 @@
-create
diff --git a/tools/xm-test/grouptest/default b/tools/xm-test/grouptest/default
deleted file mode 100644
index e04591b..0000000
--- a/tools/xm-test/grouptest/default
+++ /dev/null
@@ -1,30 +0,0 @@
-block-create
-block-destroy
-block-list
-block-integrity
-console
-create
-destroy
-dmesg
-domid
-domname
-enforce_dom0_cpus
-help
-info
-list
-memmax
-memset
-migrate
-network
-network-attach
-pause
-reboot
-restore
-save
-sched-credit
-shutdown
-sysrq
-unpause
-vcpu-disable
-vcpu-pin
-xapi
diff --git a/tools/xm-test/grouptest/medium b/tools/xm-test/grouptest/medium
deleted file mode 100644
index 5c3e1b1..0000000
--- a/tools/xm-test/grouptest/medium
+++ /dev/null
@@ -1,24 +0,0 @@
-block-create 09_block_attach_and_dettach_device_check_data_pos.test
-block-list
-console
-destroy 01_destroy_basic_pos.test 02_destroy_noparm_neg.test 03_destroy_nonexist_neg.test 04_destroy_badparm_neg.test 05_destroy_byid_pos.test 06_destroy_dom0_neg.test
-dmesg
-domid
-domname
-enforce_dom0_cpus
-help
-info
-list
-memmax
-memset 01_memset_basic_pos.test 02_memset_badparm_neg.test 04_memset_smallmem_pos.test
-migrate
-network-attach 03_network_attach_detach_multiple_pos.test
-reboot
-restore 02_restore_badparm_neg.test 03_restore_badfilename_neg.test 04_restore_withdevices_pos.test
-save
-sched-credit
-shutdown
-sysrq 01_sysrq_basic_neg.test 02_sysrq_sync_pos.test
-unpause
-vcpu-disable
-vcpu-pin
diff --git a/tools/xm-test/grouptest/quick b/tools/xm-test/grouptest/quick
deleted file mode 100644
index 2b538af..0000000
--- a/tools/xm-test/grouptest/quick
+++ /dev/null
@@ -1,4 +0,0 @@
-create 01_create_basic_pos.test 07_create_mem64_pos.test 10_create_fastdestroy.test 14_create_blockroot_pos.test
-unpause 01_unpause_basic_pos.test
-memset 01_memset_basic_pos.test 03_memset_random_pos.test
-help 06_help_allcmds.test
diff --git a/tools/xm-test/grouptest/xapi b/tools/xm-test/grouptest/xapi
deleted file mode 100644
index 7a08b77..0000000
--- a/tools/xm-test/grouptest/xapi
+++ /dev/null
@@ -1 +0,0 @@
-xapi
diff --git a/tools/xm-test/lib/XmTestLib/Console.py b/tools/xm-test/lib/XmTestLib/Console.py
deleted file mode 100755
index e05cf0d..0000000
--- a/tools/xm-test/lib/XmTestLib/Console.py
+++ /dev/null
@@ -1,302 +0,0 @@
-#!/usr/bin/python
-"""
- XmConsole.py - Interact with a xen console, getting return codes and
- output from commands executed there.
-
- Copyright (C) International Business Machines Corp., 2005
- Author: Dan Smith <danms at us.ibm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- NB: This requires the domU's prompt to be set to
- a _very_ specific value, set in the PROMPT
- variable of this script
-"""
-import sys
-import os
-import pty
-import tty
-import termios
-import fcntl
-import select
-
-import arch
-from Test import *
-
-TIMEDOUT = 1
-RUNAWAY = 2
-
-class ConsoleError(Exception):
- def __init__(self, msg, reason=TIMEDOUT):
- self.errMsg = msg
- self.reason = reason
-
- def __str__(self):
- return str(self.errMsg)
-
-class XmConsole:
-
- def __init__(self, domain, historyLimit=256, historySaveAll=True, historySaveCmds=False, cLimit=131072):
- """
- Parameters:
- historyLimit: specifies how many lines of history are maintained
- historySaveAll: determines whether or not extra messages in
- between commands are saved
- historySaveCmds : determines whether or not the command echos
- are included in the history buffer
- """
-
- self.TIMEOUT = 30
- self.PROMPT = "@%@%> "
- self.domain = domain
- self.historyBuffer = []
- self.historyLines = 0
- self.historyLimit = historyLimit
- self.historySaveAll = historySaveAll
- self.historySaveCmds = historySaveCmds
- self.debugMe = False
- self.limit = cLimit
-
- consoleCmd = ["/usr/sbin/xm", "xm", "console", domain]
-
- if verbose:
- print "Console executing: %s" % str(consoleCmd)
-
- pid, fd = pty.fork()
-
- if pid == 0:
- os.execvp("/usr/sbin/xm", consoleCmd[1:])
-
- self.consolePid = pid
- self.consoleFd = fd
-
- tty.setraw(self.consoleFd, termios.TCSANOW)
-
- def __addToHistory(self, line):
- self.historyBuffer.append(line)
- self.historyLines += 1
- if self.historyLines > self.historyLimit:
- self.historyBuffer = self.historyBuffer[1:]
- self.historyLines -= 1
-
-
- def clearHistory(self):
- """Clear the history buffer"""
- self.historyBuffer = []
- self.historyLines = 0
-
-
- def getHistory(self):
- """Returns a string containing the entire history buffer"""
- output = ""
-
- for line in self.historyBuffer:
- output += line + "\n"
-
- return output
-
-
- def setTimeout(self, timeout):
- """Sets the timeout used to determine if a remote command
- has blocked"""
- self.TIMEOUT = timeout
-
-
- def setPrompt(self, prompt):
- """Sets the string key used to delimit the end of command
- output"""
- self.PROMPT = prompt
-
- def __getprompt(self, fd):
- timeout = 0
- bytes = 0
- buffer = ""
- while timeout < 180:
- # eat anything while total bytes less than limit else raise RUNAWAY
- while (not self.limit) or (bytes < self.limit):
- i, o, e = select.select([fd], [], [], 1)
- if fd in i:
- try:
- foo = os.read(fd, 1)
- if self.debugMe:
- sys.stdout.write(foo)
- bytes += 1
- buffer += foo
- except Exception, exn:
- raise ConsoleError(str(exn))
- else:
- break
- else:
- raise ConsoleError("Console run-away (exceeded %i bytes)"
- % self.limit, RUNAWAY)
- # Check to see if the buffer contains anything interetsing
- arch.checkBuffer(buffer)
- # press enter
- os.write(self.consoleFd, "\n")
- # look for prompt
- for prompt_char in "\r\n" + self.PROMPT:
- i, o, e = select.select([fd], [], [], 1)
- if fd in i:
- try:
- foo = os.read(fd, 1)
- if self.debugMe:
- sys.stdout.write(foo)
- if foo != prompt_char:
- break
- except Exception, exn:
- raise ConsoleError(str(exn))
- else:
- timeout += 1
- break
- else:
- break
- else:
- raise ConsoleError("Timed out waiting for console prompt")
-
- def __runCmd(self, command, saveHistory=True):
- output = ""
- line = ""
- lines = 0
- bytes = 0
-
- self.__getprompt(self.consoleFd)
-
- if verbose:
- print "[%s] Sending `%s'" % (self.domain, command)
-
- os.write(self.consoleFd, "%s\n" % command)
-
- while True:
- i, o, e = select.select([self.consoleFd], [], [], self.TIMEOUT)
-
- if self.consoleFd in i:
- try:
- str = os.read(self.consoleFd, 1)
- if self.debugMe:
- sys.stdout.write(str)
- bytes += 1
- except Exception, exn:
- raise ConsoleError(
- "Failed to read from console (fd=%i): %s" %
- (self.consoleFd, exn))
- else:
- raise ConsoleError("Timed out waiting for console command")
-
- if self.limit and bytes >= self.limit:
- raise ConsoleError("Console run-away (exceeded %i bytes)"
- % self.limit, RUNAWAY)
-
- if str == "\n":
- if lines > 0:
- output += line + "\n"
- if saveHistory:
- self.__addToHistory(line)
- elif self.historySaveCmds and saveHistory:
- self.__addToHistory("*" + line)
- lines += 1
- line = ""
- elif str == "\r":
- pass # ignore \r's
- else:
- line += str
-
- if line == self.PROMPT:
- break
-
- return output
-
-
- def runCmd(self, command):
- """Runs a command on the remote terminal and returns the output
- as well as the return code. For example:
-
- ret = c.runCmd("ls")
- print ret["output"]
- sys.exit(run["return"])
-
- """
-
- # Allow exceptions to bubble up
- realOutput = self.__runCmd(command)
- retOutput = self.__runCmd("echo $?", saveHistory=False)
-
- try:
- retCode = int(retOutput)
- except:
- retCode = 255
- return {
- "output": realOutput,
- "return": retCode,
- }
-
- def sendInput(self, input):
- """Sends input to the remote terminal, but doesn't check
- for a return code"""
- realOutput = self.__runCmd(input)
- return {
- "output": realOutput,
- "return": 0,
- }
-
- def __closeConsole(self):
- """Closes the console connection and ensures that the console
- process is killed. This should only be called by the domain.
- Tests should call domain.closeConsole()"""
- if self.consolePid != 0:
- os.close(self.consoleFd)
- os.kill(self.consolePid, 2)
- self.consolePid = 0
-
-
- def setLimit(self, limit):
- """Sets a limit on the number of bytes that can be
- read in an attempt to run a command. We need this when
- running something that can run away"""
- try:
- self.limit = int(limit)
- except Exception, e:
- self.limit = None
-
- def setHistorySaveCmds(self, value):
- # True or False
- self.historySaveCmds = value
-
-
-if __name__ == "__main__":
- """This is both an example of using the XmConsole class, as
- well as a utility for command-line execution of single commands
- on a domU console. Prints output to stdout. Exits with the same
- code as the domU command.
- """
-
- verbose = True
-
- try:
- t = XmConsole(sys.argv[1])
- except ConsoleError, e:
- print "Failed to attach to console (%s)" % str(e)
- sys.exit(255)
-
- try:
- run = t.runCmd(sys.argv[2])
- except ConsoleError, e:
- print "Console failed (%s)" % str(e)
- sys.exit(255)
-
- t._XmConsole__closeConsole()
-
- print run["output"],
- sys.exit(run["return"])
-
-
diff --git a/tools/xm-test/lib/XmTestLib/DomainTracking.py b/tools/xm-test/lib/XmTestLib/DomainTracking.py
deleted file mode 100644
index 7e0bb30..0000000
--- a/tools/xm-test/lib/XmTestLib/DomainTracking.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/python
-"""
- Copyright (C) International Business Machines Corp., 2005
- Author: Dan Smith <danms at us.ibm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-
-import atexit
-import Test
-import xapi
-
-# Tracking of managed domains
-_managedDomains = []
-_VMuuids = []
-registered = 0
-
-def addManagedDomain(name):
- global registered
- _managedDomains.append(name)
- if not registered:
- atexit.register(destroyManagedDomains)
- registered = 1
-
-def delManagedDomain(name):
- if name in _managedDomains:
- del _managedDomains[_managedDomains.index(name)]
-
-def addXAPIDomain(uuid):
- global registered
- _VMuuids.append(uuid)
- if not registered:
- atexit.register(destroyManagedDomains)
- registered = 1
-
-def delXAPIDomain(uuid):
- _VMuuids.remove(uuid)
-
-def destroyManagedDomains():
- if len(_managedDomains) > 0:
- for m in _managedDomains:
- Test.traceCommand("xm destroy %s" % m)
- Test.traceCommand("xm delete %s" % m)
- if len(_VMuuids) > 0:
- for uuid in _VMuuids:
- Test.traceCommand("xm destroy %s" % uuid)
- Test.traceCommand("xm delete %s" % uuid)
-
-
diff --git a/tools/xm-test/lib/XmTestLib/NetConfig.py b/tools/xm-test/lib/XmTestLib/NetConfig.py
deleted file mode 100644
index 5013bef..0000000
--- a/tools/xm-test/lib/XmTestLib/NetConfig.py
+++ /dev/null
@@ -1,268 +0,0 @@
-#!/usr/bin/python
-"""
- Copyright (C) International Business Machines Corp., 2005, 2006
- Authors: Dan Smith <danms at us.ibm.com>
- Daniel Stekloff <dsteklof at us.ibm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-
-import sys
-import commands
-import os
-import re
-import time
-import random
-from xen.xend.sxp import Parser
-
-from Xm import *
-from Test import *
-from config import *
-
-class NetworkError(Exception):
- def __init__(self, msg):
- self.errMsg = msg
-
- def __str__(self):
- return str(self.errMsg)
-
-def getXendNetConfig():
- # Find out what environment we're in: bridge, nat, or route
- xconfig = os.getenv("XEND_CONFIG")
- if not xconfig:
- xconfig = "/etc/xen/xend-config.sxp"
-
- try:
- configfile = open(xconfig, 'r')
- except:
- return "bridge"
-
- S = configfile.read()
- pin = Parser()
- pin.input(S)
- pin.input_eof()
- val = pin.get_val()
- while val[0] != 'network-script':
- val = pin.get_val()
-
- if val[0] != 'network-script' or len(val) < 2:
- # entry network-script not found or no type specified
- netenv = "bridge"
- else:
- # split network command into script name and its parameters
- sub_val = val[1].split()
- if sub_val[0] == "network-bridge":
- netenv = "bridge"
- elif sub_val[0] == "network-route":
- netenv = "route"
- elif sub_val[0] == "network-nat":
- netenv = "nat"
- else:
- raise NetworkError("Failed to get network env from xend config")
-
- configfile.close()
- return netenv
-
-class NetConfig:
-
- def __init__(self):
- self.netenv = getXendNetConfig()
- self.used_ips = {}
- self.free_oct_ips = [ 0, 0, 0, 0 ]
- self.total_ips = 0
-
- if NETWORK_IP_RANGE == 'dhcp':
- self.netmask = NETWORK_IP_RANGE
- self.network = NETWORK_IP_RANGE
- self.max_ip = NETWORK_IP_RANGE
- self.min_ip = NETWORK_IP_RANGE
- else:
- self.netmask = NETMASK
- self.network = NETWORK
- s_ip = ''
-
- # Get starting ip and max ip from configured ip range
- s_ip = NETWORK_IP_RANGE
- ips = s_ip.split("-")
- self.max_ip = ips[1]
- self.min_ip = ips[0]
-
- self.__setMaxNumberIPs()
-
- # Clean out any aliases in the network range for dom0's interface.
- # If an alias exists, a test xendevice add command could fail.
- if NETWORK_IP_RANGE != "dhcp":
- self.__cleanDom0Aliases()
-
- def __setMaxNumberIPs(self):
- # Count the number of IPs available, to help tests know whether they
- # have enough to run or not
- masko = self.netmask.split('.')
- maxo = self.max_ip.split('.')
- mino = self.min_ip.split('.')
- ips = 0
-
- # Last octet
- self.free_oct_ips[3] = (int(maxo[3]) - int(mino[3])) + 1
-
- # 3rd octet
- self.free_oct_ips[2] = (int(maxo[2]) - int(mino[2])) + 1
-
- # 2nd octet
- self.free_oct_ips[1] = (int(maxo[1]) - int(mino[1])) + 1
-
- # 1st octet
- self.free_oct_ips[0] = (int(maxo[0]) - int(mino[0])) + 1
-
- self.total_ips = self.free_oct_ips[3]
- if self.free_oct_ips[2] > 1:
- self.total_ips = (self.total_ips * self.free_oct_ips[2])
- if self.free_oct_ips[1] > 1:
- self.total_ips = (self.total_ips * self.free_oct_ips[1])
- if self.free_oct_ips[0] > 1:
- self.total_ips = (self.total_ips * self.free_oct_ips[0])
-
- def __cleanDom0Aliases(self):
- # Remove any aliases within the supplied network IP range on dom0
- scmd = 'ip addr show dev %s' % (DOM0_INTF)
-
- status, output = traceCommand(scmd)
- if status:
- raise NetworkError("Failed to show %s aliases: %d" %
- (DOM0_INTF, status))
-
- lines = output.split("\n")
- for line in lines:
- ip = re.search('(\d+\.\d+\.\d+\.\d+)', line)
- if ip and self.isIPInRange(ip.group(1)) == True:
- dcmd = 'ip addr del %s/32 dev %s' % (ip.group(1), DOM0_INTF)
- dstatus, doutput = traceCommand(dcmd)
- if dstatus:
- raise NetworkError("Failed to remove %s aliases: %d" %
- (DOM0_INTF, status))
-
- def getNetEnv(self):
- return self.netenv
-
- def setUsedIP(self, domname, interface, ip):
- self.used_ips['%s:%s' % (domname, interface)] = ip
-
- def __findFirstOctetIP(self, prefix, min, len):
- max = min + len
- for i in range(min, max):
- ip = '%s%s' % (prefix, str(i))
- found = False
- for k in self.used_ips.keys():
- if self.used_ips[k] == ip:
- found = True
- if found == False:
- return ip
-
- if found == True:
- return None
-
- def getFreeIP(self, domname, interface):
- # Get a free IP. It uses the starting ip octets and then the
- # total number of allowed numbers for that octet. It only
- # calculates ips for the last two octets, we shouldn't need more
- start_octets = self.min_ip.split(".")
- ip = None
-
- # Only working with ips from last two octets, shouldn't need more
- max = int(start_octets[2]) + self.free_oct_ips[2]
- for i in range(int(start_octets[2]), max):
- prefix = '%s.%s.%s.' % (start_octets[0], start_octets[1], str(i))
- ip = self.__findFirstOctetIP(prefix, int(start_octets[3]), self.free_oct_ips[3])
- if ip:
- break
-
- if not ip:
- raise NetworkError("Ran out of configured addresses.")
-
- self.setUsedIP(domname, interface, ip)
- return ip
-
- def getNetMask(self):
- return self.netmask
-
- def getNetwork(self):
- return self.network
-
- def getIP(self, domname, interface):
- # Depending on environment, set an IP. Uses the configured range
- # of IPs, network address, and netmask
- if NETWORK_IP_RANGE == "dhcp":
- return None
-
- # Make sure domain and interface aren't already assigned an IP
- if self.used_ips.has_key('%s:%s' % (domname, interface)):
- raise NetworkError("Domain %s interface %s is already has IP"
- % (domname, interface))
-
- return self.getFreeIP(domname, interface)
-
- def setIP(self, domname, interface, ip):
- # Make sure domain and interface aren't already assigned an IP
- if self.used_ips.has_key('%s:%s' % (domname, interface)):
- raise NetworkError("Domain %s interface %s is already has IP"
- % (domname, interface))
-
- self.setUsedIP(domname, interface, ip)
-
- def releaseIP(self, domname, interface, ip):
- if self.used_ips.has_key('%s:%s' % (domname, interface)):
- del self.used_ips['%s:%s' % (domname, interface)]
-
- def getNumberAllowedIPs(self):
- return self.total_ips
-
- def canRunNetTest(self, ips):
- # Check to see if a test can run, returns true or false. Input is
- # number of ips needed.
- if NETWORK_IP_RANGE == "dhcp":
- return True
-
- if self.total_ips >= ips:
- return True
-
- return False
-
- def isIPInRange(self, ip):
- # Checks to see if supplied ip is in the range of allowed ips
- maxo = self.max_ip.split('.')
- mino = self.min_ip.split('.')
- ipo = ip.split('.')
-
- if int(ipo[0]) < int(mino[0]):
- return False
- elif int(ipo[0]) > int(maxo[0]):
- return False
-
- if int(ipo[1]) < int(mino[1]):
- return False
- elif int(ipo[1]) > int(maxo[1]):
- return False
-
- if int(ipo[2]) < int(mino[2]):
- return False
- elif int(ipo[2]) > int(maxo[2]):
- return False
-
- if int(ipo[3]) < int(mino[3]):
- return False
- elif int(ipo[3]) > int(maxo[3]):
- return False
-
- return True
diff --git a/tools/xm-test/lib/XmTestLib/Test.py b/tools/xm-test/lib/XmTestLib/Test.py
deleted file mode 100644
index 68a176c..0000000
--- a/tools/xm-test/lib/XmTestLib/Test.py
+++ /dev/null
@@ -1,203 +0,0 @@
-#!/usr/bin/python
-
-"""
- Copyright (C) International Business Machines Corp., 2005
- Author: Dan Smith <danms at us.ibm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-
-##
-## These are utility functions for test cases
-##
-
-import sys
-import commands
-import os
-import pwd
-import time
-import pty
-import select
-import signal
-import re
-import glob
-
-TEST_PASS = 0
-TEST_FAIL = 255
-TEST_SKIP = 77
-
-# We currently advise waiting this many seconds for the ramdisk to
-# boot inside a domU
-TEST_DOMU_BOOT_DELAY = 20
-
-if os.environ.get("TEST_VERBOSE"):
- verbose = True
-else:
- verbose = False
-
-class TimeoutError(Exception):
- def __init__(self, msg, outputSoFar):
- self.msg = msg
- self.output = outputSoFar
-
- def __str__(self):
- return str(self.msg)
-
-def runWithTimeout(cmd, timeout):
- args = cmd.split()
-
- pid, fd = pty.fork();
-
- startTime = time.time()
-
- if pid == 0:
- os.execvp(args[0], args)
-
- output = ""
-
- while time.time() - startTime < timeout:
- i, o, e = select.select([fd], [], [], timeout)
-
- if fd in i:
- try:
- str = os.read(fd, 1)
- output += str
- except OSError, e:
- exitPid, status = os.waitpid(pid, os.WNOHANG)
-
- if exitPid == pid:
- if verbose:
- print "Child exited with %i" % status
- return status, output
-
- if verbose:
- print "Command timed out: killing pid %i" % pid
-
- os.kill(pid, signal.SIGINT)
- raise TimeoutError("Command execution time exceeded %i seconds" % timeout,
- outputSoFar=output)
-
-def traceCommand(command, timeout=None, logOutput=True):
- if verbose:
- print "[dom0] Running `%s'" % command
-
- if timeout:
- status, output = runWithTimeout(command, timeout)
- else:
- status, output = commands.getstatusoutput(command)
-
- if logOutput and verbose:
- print output
-
- return status, output
-
-def getTestName():
- script = sys.argv[0]
- fname = os.path.basename(script)
- match = re.match("([^\.]+)\.[a-z]+", fname)
- if match:
- tname = match.group(1)
- else:
- tname = "UNKNOWN"
-
- return tname
-
-def becomeNonRoot():
- """Become a non-root user, or FAIL if this is not possible. This call
- succeeds if we are already running as a non-root user.
- """
-
- if os.geteuid() == 0:
- # Try and become "nobody". This user is commonly in place, but this
- # could be extended to consider any number of users to be acceptable,
- # if there are systems where "nobody" is not present.
- allusers = pwd.getpwall()
- for u in allusers:
- if u[0] == "nobody":
- os.setreuid(u[2], u[2])
- break
- if os.geteuid() == 0:
- FAIL("Could not become a non-root user")
-
-def FAIL(format, *args):
- print "\nREASON:", (format % args)
- sys.exit(TEST_FAIL)
-
-def SKIP(format, *args):
- print "\nREASON:", (format % args)
- sys.exit(TEST_SKIP)
-
-def saveLog(logText, filename=None):
- if not filename:
- filename = "log";
- logfile = open(filename, 'w');
- date = commands.getoutput("date");
- logfile.write("-- BEGIN XmTest Log @" + date + "\n");
- logfile.write(logText);
- logfile.write("\n-- END XmTest Log\n");
- logfile.close();
-
-def waitForBoot():
- if verbose:
- print "[dom0] Waiting %i seconds for domU boot..." % TEST_DOMU_BOOT_DELAY
- time.sleep(TEST_DOMU_BOOT_DELAY)
-
-def timeStamp():
- name = getTestName()
-
- t = time.asctime(time.localtime())
-
- print "*** Test %s started at %s %s" % (name, t,
- time.tzname[time.daylight])
-
-#
-# Try to start a domain and attach a console to it to see if
-# the console system is working
-#
-def isConsoleDead():
-
- from XmTestLib import XmTestDomain, DomainError, XmConsole, ConsoleError
-
- domain = XmTestDomain()
-
- try:
- console = domain.start()
- console.runCmd("ls")
- except DomainError, e:
- return True
- except ConsoleError, e:
- domain.destroy()
- return True
-
- domain.destroy()
-
- return False
-
-#
-# We currently can only load as many concurrent HVM domains as loop
-# devices, need to find how many devices the system has.
-def getMaxHVMDomains():
- nodes = glob.glob("/dev/loop*")
- maxd = len(nodes)
-
- return maxd
-
-
-if __name__ == "__main__":
-
- timeStamp()
-
- FAIL("foo")
-
diff --git a/tools/xm-test/lib/XmTestLib/XenAPIDomain.py b/tools/xm-test/lib/XmTestLib/XenAPIDomain.py
deleted file mode 100644
index 1ca2307..0000000
--- a/tools/xm-test/lib/XmTestLib/XenAPIDomain.py
+++ /dev/null
@@ -1,183 +0,0 @@
-#!/usr/bin/python
-"""
- Copyright (C) International Business Machines Corp., 2005
- Author: Stefan Berger <stefanb at us.ibm.com>
-
- Based on XenDomain.py by Dan Smith <danms at us.ibm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-import os
-import sys
-from XmTestLib import *
-from types import DictType
-
-
-class XenAPIConfig:
- """An object to help create a VM configuration usable via Xen-API"""
- def __init__(self):
- self.opts = {}
- #Array to translate old option to new ones
- self.opttrlate = { 'name' : 'name_label' ,
- 'memory' : [ 'memory_static_max' ,
- 'memory_static_min' ,
- 'memory_dynamic_min',
- 'memory_dynamic_max' ],
- 'kernel' : 'PV_kernel',
- 'ramdisk': 'PV_ramdisk',
- 'root' : 'PV_args',
- 'extra' : 'PV_args' }
-
- def setOpt(self, name, value):
- """Set an option in the config"""
- if name == "memory":
- value <<= 20
- if name == "root":
- value = "root=" + value
- if name in self.opttrlate.keys():
- _name = self.opttrlate[name]
- else:
- _name = name
-
- if isinstance(_name, list):
- for _n in _name:
- self.opts[_n] = value
- else:
- if not self.opts.get(_name) or \
- not _name in [ "PV_args" ]:
- self.opts[_name] = value
- else:
- self.opts[_name] += " " + value
-
- def getOpt(self, name):
- """Return the value of a config option"""
- if name in self.opts.keys():
- return self.opts[name]
- else:
- return None
-
- def setOpts(self, opts):
- """Batch-set options from a dictionary"""
- for k, v in opts.items():
- self.setOpt(k, v)
-
- def getOpts(self):
- return self.opts
-
-
-class XenAPIDomain(XenDomain):
-
- def __init__(self, name=None, config=None):
- if name:
- self.name = name
- else:
- self.name = getUniqueName()
-
- self.config = config
- self.console = None
- self.netEnv = "bridge"
-
- self.session = xapi.connect()
- try:
- self.vm_uuid = self.session.xenapi.VM.create(self.config.getOpts())
- addXAPIDomain(self.vm_uuid)
- except:
- raise DomainError("Could not create VM config file for "
- "managed domain.")
-
- #Only support PV for now.
- self.type = "PV"
-
- def start(self, noConsole=False, startpaused=False):
- #start the VM
- session = self.session
- if self.vm_uuid:
- try:
- session.xenapi.VM.start(self.vm_uuid, startpaused)
- except:
- raise DomainError("Could not start domain")
- else:
- raise DomainError("VM has no UUID - does VM config exist?")
-
- if startpaused:
- return
-
- if self.getDomainType() == "HVM":
- waitForBoot()
-
- if self.console and noConsole == True:
- self.closeConsole()
-
- elif self.console and noConsole == False:
- return self.console
-
- elif not self.console and noConsole == False:
- return self.getConsole()
-
- def stop(self):
- if self.vm_uuid:
- self.session.xenapi.VM.hard_shutdown(self.vm_uuid)
- else:
- raise DomainError("VM has no UUID - does VM config exist?")
-
- def destroy(self):
- #Stop VM first.
- self.stop()
- if self.vm_uuid:
- self.session.xenapi.VM.destroy(self.vm_uuid)
- delXAPIDomain(self.vm_uuid)
- else:
- raise DomainError("VM has no UUID - does VM config exist?")
-
- def get_uuid(self):
- return self.vm_uuid
-
- def newDevice(self, Device, *args):
- raise DomainError("No support for newDevice().")
-
- def removeDevice(self, id):
- raise DomainError("No support for removeDevice().")
-
- def removeAllDevices(self, id):
- raise DomainError("No support for removeAllDevices().")
-
- def isRunning(self):
- return isDomainRunning(self.name)
-
- def getDevice(self, id):
- raise DomainError("No support for getDevice().")
-
-
-class XmTestAPIDomain(XenAPIDomain):
-
- """Create a new managed xm-test domain
- @param name: The requested domain name
- @param extraConfig: Additional configuration options
- @param baseConfig: The initial configuration defaults to use
- """
- def __init__(self, name=None, extraConfig=None,
- baseConfig=arch.configDefaults):
- config = XenAPIConfig()
- config.setOpts(baseConfig)
- if extraConfig:
- config.setOpts(extraConfig)
-
- if name:
- config.setOpt("name_label", name)
- elif not config.getOpt("name_label"):
- config.setOpt("name_label", getUniqueName())
-
- XenAPIDomain.__init__(self, config.getOpt("name_label"),
- config=config)
diff --git a/tools/xm-test/lib/XmTestLib/XenDevice.py b/tools/xm-test/lib/XmTestLib/XenDevice.py
deleted file mode 100644
index d51ee28..0000000
--- a/tools/xm-test/lib/XmTestLib/XenDevice.py
+++ /dev/null
@@ -1,275 +0,0 @@
-#!/usr/bin/python
-"""
- Copyright (C) International Business Machines Corp., 2005, 2006
- Authors: Dan Smith <danms at us.ibm.com>
- Daniel Stekloff <dsteklof at us.ibm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-
-import sys
-import commands
-import os
-import re
-import time
-
-from Xm import *
-from Test import *
-from config import *
-from XenDomain import *
-from NetConfig import *
-from XmTestLib import *
-from __init__ import *
-
-class XenNetDevCmd:
-
- def __init__(self, netDevice, addCmd, removeCmd):
- """Object representing a network device command"""
- self.addcmd = addCmd
- self.removecmd = removeCmd
- self.addhasrun = False
- self.rmvhasrun = False
- self.netdevice = netDevice
-
- def getAddCmd(self):
- return self.addcmd
-
- def getRemoveCmd(self):
- return self.removecmd
-
- def hasAddRun(self):
- return self.addhasrun
-
- def hasRemoveRun(self):
- self.rmvhasrun
-
- def runAddCmd(self, runOnDom0=False):
- # Defaults running command on dom0, if console then will run there
- if runOnDom0 == False:
- dom = self.netdevice.getDomain()
- console = dom.getConsole()
- console.runCmd(self.addcmd)
- else:
- status, output = traceCommand(self.addcmd)
- if status:
- raise NetworkError("Device add cmd failed: %s Status: %d"
- % (self.addcmd, status))
- self.addhasrun = True
-
- def runRemoveCmd(self, runOnDom0=False):
- # Defaults running command on dom0, if console then will run there
- if runOnDom0 == False:
- dom = self.netdevice.getDomain()
- console = dom.getConsole()
- console.runCmd(self.removecmd)
- else:
- status, output = traceCommand(self.removecmd)
- if status:
- raise NetworkError("Device remove cmd failed: %s Status: %d"
- % (self.removecmd, status))
- self.removehasrun = True
-
-class XenDevice:
-
- def __init__(self, domain, id, devConfig=None):
- """An object to represent Xen Devices like network and block
- @param domain: Domain the device will be added to
- @param id: Device identifier
- @param devConfig: Initial configuration dictionary for XenDevice
- """
- if config:
- self.config = devConfig
- else:
- self.config = {}
-
- self.id = id
- self.domain = domain
- self.configNode = None
- # Commands run when domain is started or devices added and removed.
- self.dom0_cmds = []
- self.domU_cmds = []
-
- def __str__(self):
- """Convert device config to XenConfig node compatible string"""
- confstr = ''
- for k, v in self.config.items():
- if len(confstr) > 0:
- confstr += ', '
- if isinstance(v, int):
- confstr += "%s=%i" % (k, v)
- elif isinstance(v, list) and v:
- confstr += "%s=%s" % (k, v)
- elif isinstance(v, str) and v:
- confstr += "%s=%s" % (k, v)
-
- return confstr
-
- def execAddCmds(self):
- # Cmds for when a device is added to the system
- if len(self.dom0_cmds) > 0:
- for i in range(0, len(self.dom0_cmds)):
- if self.dom0_cmds[i].getAddCmd():
- self.dom0_cmds[i].runAddCmd(runOnDom0=True)
-
- if len(self.domU_cmds) > 0:
- for i in range(0, len(self.domU_cmds)):
- if self.domU_cmds[i].getAddCmd():
- self.domU_cmds[i].runAddCmd()
-
- def execRemoveCmds(self):
- # Cmds for when a device is removed from the system
- if len(self.dom0_cmds) > 0:
- for i in range(0, len(self.dom0_cmds)):
- if (self.dom0_cmds[i].getRemoveCmd()
- and self.dom0_cmds[i].hasAddRun() == True):
- self.dom0_cmds[i].runRemoveCmd(runOnDom0=True)
-
- if len(self.domU_cmds) > 0:
- for i in range(0, len(self.domU_cmds)):
- if (self.domU_cmds[i].getRemoveCmd()
- and self.domU_cmds[i].hasAddRun() == True):
- self.domU_cmds[i].runRemoveCmd()
-
- def removeDevice(self):
- self.execRemoveCmds()
-
- def getId(self):
- return self.id
-
- def getConfigOpt(self):
- return self.configNode
-
- def getDomain(self):
- return self.domain
-
-class XenNetDevice(XenDevice):
-
- def __init__(self, domain, id, devConfig=None):
- """An object to represent Xen Network Device
- @param domain: Domain the device is being added to
- @param id: Network device identifier, interface name like eth0
- @param devConfig: Initial dictionary configuration for XenNetDevice
- """
- if devConfig:
- self.config = devConfig
- else:
- self.config = {}
-
- self.id = id
- self.domain = domain
- self.configNode = "vif"
- self.dom0_cmds = []
- self.domU_cmds = []
- self.network = None
- self.netmask = None
- self.ip = None
- self.dom0_alias_ip = None
-
- if domain.getDomainType() == "HVM":
- self.config["type"] = "ioemu"
- if not self.config.has_key('bridge'):
- self.config["bridge"] = "xenbr0"
-
- if self.config.has_key("ip"):
- self.setNetDevIP(ip=self.config["ip"])
- else:
- if NETWORK_IP_RANGE != "dhcp":
- self.setNetDevIP()
-
- def __del__(self):
- # Make sure we clean up NetConfig's list of ips, so the ip can be
- # reused
- self.releaseNetDevIP()
-
- def addIfconfigCmd(self, domU=True):
- # Method to add start and remove ifconfig functions
- if domU == True:
- locmd = XenNetDevCmd(self, addCmd="ifconfig lo 127.0.0.1", removeCmd=None)
- ifcmd = []
-
-
- # Start or Add cmd
- acmd = 'ifconfig %s inet %s netmask %s up' % (self.id, self.ip, self.netmask)
- rcmd = 'ifconfig %s down' % self.id
- ifcmd = XenNetDevCmd(self, addCmd=acmd, removeCmd=rcmd)
-
- if domU == True:
- self.domU_cmds.append(locmd)
- self.domU_cmds.append(ifcmd)
- else:
- self.dom0_cmds.append(ifcmd)
-
- def removeDevice(self):
- self.releaseNetDevIP()
-
- def addDom0AliasCmd(self, dev=DOM0_INTF):
- # Method to add start and remove dom0 alias cmds
- acmd = 'ip addr add %s dev %s' % (self.dom0_alias_ip, dev)
- rcmd = 'ip addr del %s/32 dev %s' % (self.dom0_alias_ip, dev)
- aliascmd = XenNetDevCmd(self, addCmd=acmd, removeCmd=rcmd)
-
- self.dom0_cmds.append(aliascmd)
-
- def releaseNetDevIP(self):
- # Must remove start cmds for ip configuration and then release from
- # NetConfig
- self.execRemoveCmds()
- self.dom0_cmds = []
- self.domU_cmds = []
- if self.config.has_key("ip"):
- del self.config["ip"]
-
- if self.dom0_alias_ip:
- xmtest_netconf.releaseIP("domain0", self.domain.getName(), self.dom0_alias_ip)
- xmtest_netconf.releaseIP(self.domain.getName(), self.id, self.ip)
-
- def getNetDevIP(self):
- return self.ip
-
- def getDom0AliasIP(self):
- return self.dom0_alias_ip
-
- def getNetwork(self):
- return self.network
-
- def get_netmask(self):
- return self.netmask
-
- def setNetDevIP(self, ip=None):
- # Function to set a new IP for NetDevice.
- if NETWORK_IP_RANGE == "dhcp":
- raise NetworkError("System configured for dhcp, cannot set new ip.")
-
- if (self.ip and not ip) or ((self.ip and ip) and (self.ip != ip)):
- self.releaseNetDevIP()
-
- if not self.netmask:
- self.netmask = xmtest_netconf.getNetMask()
-
- if not self.network:
- self.network = xmtest_netconf.getNetwork()
-
- if ip:
- xmtest_netconf.setIP(self.domain.getName(), self.id, ip)
- self.ip = ip
- else:
- self.ip = xmtest_netconf.getIP(self.domain.getName(), self.id)
-
- self.addIfconfigCmd()
- self.config["ip"] = str(self.ip)
-
- # Setup an alias for Dom0
- self.dom0_alias_ip = xmtest_netconf.getIP("domain0", self.domain.getName())
- self.addDom0AliasCmd()
diff --git a/tools/xm-test/lib/XmTestLib/XenDomain.py b/tools/xm-test/lib/XmTestLib/XenDomain.py
deleted file mode 100644
index 3ba7433..0000000
--- a/tools/xm-test/lib/XmTestLib/XenDomain.py
+++ /dev/null
@@ -1,385 +0,0 @@
-#!/usr/bin/python
-"""
- Copyright (C) International Business Machines Corp., 2005
- Author: Dan Smith <danms at us.ibm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-
-import sys
-import commands
-import re
-import time
-
-from Xm import *
-from arch import *
-from Test import *
-from config import *
-from Console import *
-from XenDevice import *
-from DomainTracking import *
-
-
-DOM0_UUID = "00000000-0000-0000-0000-000000000000"
-
-
-def getDefaultKernel():
- return arch.getDefaultKernel()
-
-def getRdPath():
- return arch.getRdPath()
-
-def getUniqueName():
- """Get a uniqueish name for use in a domain"""
- unixtime = int(time.time())
- test_name = sys.argv[0]
- test_name = re.sub("\.test", "", test_name)
- test_name = re.sub("[\/\.]", "", test_name)
- name = "%s-%i" % (test_name, unixtime)
-
- return name
-
-class XenConfig:
- """An object to help create a xen-compliant config file"""
- def __init__(self):
- self.defaultOpts = {}
-
- # These options need to be lists
- self.defaultOpts["disk"] = []
- self.defaultOpts["vif"] = []
-
- self.opts = self.defaultOpts
-
- def toString(self):
- """Convert this config to a string for writing out
- to a file"""
- string = "# Xen configuration generated by xm-test\n"
- for k, v in self.opts.items():
- if isinstance(v, int):
- piece = "%s = %i" % (k, v)
- elif isinstance(v, list) and v:
- piece = "%s = %s" % (k, v)
- elif isinstance(v, str) and v:
- piece = "%s = \"%s\"" % (k, v)
- else:
- piece = None
-
- if piece:
- string += "%s\n" % piece
-
- return string
-
- def write(self, filename):
- """Write this config out to filename"""
- output = file(filename, "w")
- output.write(self.toString())
- output.close()
-
- def __str__(self):
- """When used as a string, we represent ourself by a config
- filename, which points to a temporary config that we write
- out ahead of time"""
- filename = "/tmp/xm-test.conf"
- self.write(filename)
- return filename
-
- def setOpt(self, name, value):
- """Set an option in the config"""
- if name in self.opts.keys() and isinstance(self.opts[name] ,
- list) and not isinstance(value, list):
- self.opts[name] = [value]
- # "extra" is special so append to it.
- elif name == "extra" and name in self.opts.keys():
- self.opts[name] += " %s" % (value)
- else:
- self.opts[name] = value
-
- def appOpt(self, name, value):
- """Append a value to a list option"""
- if name in self.opts.keys() and isinstance(self.opts[name], list):
- self.opts[name].append(value)
-
- def getOpt(self, name):
- """Return the value of a config option"""
- if name in self.opts.keys():
- return self.opts[name]
- else:
- return None
-
- def setOpts(self, opts):
- """Batch-set options from a dictionary"""
- for k, v in opts.items():
- self.setOpt(k, v)
-
- def clearOpts(self, name=None):
- """Clear one or all config options"""
- if name:
- self.opts[name] = self.defaultOpts[name]
- else:
- self.opts = self.defaultOpts
-
-class DomainError(Exception):
- def __init__(self, msg, extra="", errorcode=0):
- self.msg = msg
- self.extra = extra
- try:
- self.errorcode = int(errorcode)
- except Exception, e:
- self.errorcode = -1
-
- def __str__(self):
- return str(self.msg)
-
-
-class XenDomain:
-
- def __init__(self, name=None, config=None, isManaged=False):
- """Create a domain object.
- @param config: String filename of config file
- """
-
- if name:
- self.name = name
- else:
- self.name = getUniqueName()
-
- self.config = config
- self.console = None
- self.devices = {}
- self.netEnv = "bridge"
-
- if os.getenv("XM_MANAGED_DOMAINS"):
- isManaged = True
- self.isManaged = isManaged
-
- # Set domain type, either PV for ParaVirt domU or HVM for
- # FullVirt domain
- if ENABLE_HVM_SUPPORT:
- self.type = "HVM"
- else:
- self.type = "PV"
-
- def start(self, noConsole=False):
-
- if not self.isManaged:
- ret, output = traceCommand("xm create %s" % self.config)
- print self.config
- else:
- ret, output = traceCommand("xm new %s" % self.config)
- if ret != 0:
- _ret, output = traceCommand("xm delete " +
- self.config.getOpt("name"))
- else:
- ret, output = traceCommand("xm start " +
- self.config.getOpt("name"))
- addManagedDomain(self.config.getOpt("name"))
-
- if ret != 0:
- raise DomainError("Failed to create domain",
- extra=output,
- errorcode=ret)
-
- # HVM domains require waiting for boot
- if self.getDomainType() == "HVM":
- waitForBoot()
-
- # Go through device list and run console cmds
- for dev in self.devices.keys():
- self.devices[dev].execAddCmds()
-
- if self.console and noConsole == True:
- self.closeConsole()
-
- elif self.console and noConsole == False:
- return self.console
-
- elif not self.console and noConsole == False:
- return self.getConsole()
-
- def stop(self):
- prog = "xm"
- cmd = " shutdown "
-
- self.removeAllDevices()
-
- if self.console:
- self.closeConsole()
-
- ret, output = traceCommand(prog + cmd + self.config.getOpt("name"))
-
- return ret
-
- def destroy(self):
- prog = "xm"
- cmd = " destroy "
-
- self.removeAllDevices()
-
- if self.console:
- self.closeConsole()
-
- ret, output = traceCommand(prog + cmd + self.config.getOpt("name"))
- if self.isManaged:
- ret, output = traceCommand(prog + " delete " +
- self.config.getOpt("name"))
- delManagedDomain(self.config.getOpt("name"))
-
- return ret
-
- def getName(self):
- return self.name
-
- def getId(self):
- return domid(self.getName());
-
- def getDomainType(self):
- return self.type
-
- def closeConsole(self):
- # The domain closeConsole command must be called by tests, not the
- # console's close command. Once close is called, the console is
- # gone. You can't get history or anything else from it.
- if self.console:
- self.console._XmConsole__closeConsole()
- self.console = None
-
- def getConsole(self):
- if self.console:
- self.closeConsole()
-
- self.console = XmConsole(self.getName())
- # Activate the console
- self.console.sendInput("input")
-
- return self.console
-
- def newDevice(self, Device, *args):
- """Device Factory: Generic factory for creating new XenDevices.
- All device creation should be done through the XenDomain
- factory. Supply a XenDevice instance and its args and the
- constructor will be called."""
- # Make sure device with id hasn't already been added
- if self.devices.has_key(args[0]):
- raise DeviceError("Error: Domain already has device %s" % args[0])
-
- # Call constructor for supplied Device instance
- dargs = (self,)
- dargs += args
- dev = apply(Device, dargs)
-
- if self.isRunning():
- # Note: This needs to be done, XenDevice should have an attach
- # method.
- print "Domain is running, need to attach new device to domain."
-
- self.devices[dev.id] = dev
- self.config.appOpt(dev.configNode, str(dev))
- return dev
-
- def removeDevice(self, id):
- if self.devices.has_key(id):
- self.devices[id].removeDevice()
-
- def removeAllDevices(self):
- for k in self.devices.keys():
- self.removeDevice(k)
-
- def isRunning(self):
- return isDomainRunning(self.name)
-
- def getNetEnv(self):
- # We need to know the network environment: bridge, NAT, or routed.
- return self.netEnv
-
- def getDevice(self, id):
- dev = self.devices[id]
- if dev:
- return dev
- print "Device %s not found for domain %s" % (id, self.getName())
-
-
-class XmTestDomain(XenDomain):
-
- def __init__(self, name=None, extraConfig=None,
- baseConfig=arch.configDefaults, isManaged=False):
- """Create a new xm-test domain
- @param name: The requested domain name
- @param extraConfig: Additional configuration options
- @param baseConfig: The initial configuration defaults to use
- """
- config = XenConfig()
- config.setOpts(baseConfig)
- if extraConfig:
- config.setOpts(extraConfig)
-
- if name:
- config.setOpt("name", name)
- elif not config.getOpt("name"):
- config.setOpt("name", getUniqueName())
-
- XenDomain.__init__(self, config.getOpt("name"), config=config,
- isManaged=isManaged)
-
- def minSafeMem(self):
- return arch.minSafeMem
-
-class XmTestNetDomain(XmTestDomain):
-
- def __init__(self, name=None, extraConfig=None,
- baseConfig=arch.configDefaults):
- """Create a new xm-test domain with one network device
- @param name: The requested domain name
- @param extraConfig: Additional configuration options
- @param baseConfig: The initial configuration defaults to use
- """
- config = XenConfig()
- config.setOpts(baseConfig)
- if extraConfig:
- config.setOpts(extraConfig)
-
- if name:
- config.setOpt("name", name)
- elif not config.getOpt("name"):
- config.setOpt("name", getUniqueName())
-
- XenDomain.__init__(self, config.getOpt("name"), config=config)
-
- # Add one network devices to domain
- self.newDevice(XenNetDevice, "eth0")
-
-
-if __name__ == "__main__":
-
- c = XenConfig()
-
- c.setOpt("foo", "bar")
- c.setOpt("foob", 1)
- opts = {"opt1" : 19,
- "opt2" : "blah"}
- c.setOpts(opts)
-
- c.setOpt("disk", "phy:/dev/ram0,hda1,w")
- c.appOpt("disk", "phy:/dev/ram1,hdb1,w")
-
- print str(c)
-
-
-
-# c.write("/tmp/foo.conf")
-
-# d = XmTestDomain();
-#
-# d.start();
-
diff --git a/tools/xm-test/lib/XmTestLib/XenMemory.py b/tools/xm-test/lib/XmTestLib/XenMemory.py
deleted file mode 100644
index e8da5eb..0000000
--- a/tools/xm-test/lib/XmTestLib/XenMemory.py
+++ /dev/null
@@ -1,68 +0,0 @@
-"""
- XenMemory.py - grep memory from domU
-
- This module can handle the /proc/xen/balloon as well as the sysfs
- memory interface.
-
- Copyright (C) flonatel GmbH & Co. KG, 2009
- Author: Andreas Florath
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-"""
-
-import os
-
-from Test import *
-
-class XenMemory:
-
- def __init__(self, console):
- self.console = console
- self.sysfs_mem_dir = "/sys/devices/system/xen_memory/xen_memory0"
-
- try:
- res = self.console.runCmd("ls " + self.sysfs_mem_dir)
- self.use_sysfs = res['return'] == 0
- except ConsoleError, e:
- FAIL(str(e))
-
-
- def get_mem_from_domU_sysfs(self):
- try:
- run = self.console.runCmd(
- "cat " + os.path.join(self.sysfs_mem_dir, "info/current_kb"))
- except ConsoleError, e:
- FAIL(str(e))
-
- return int(run["output"]) / 1024
-
- def get_mem_from_domU_balloon(self):
- try:
- run = self.console.runCmd("cat /proc/xen/balloon | grep Current");
- except ConsoleError, e:
- FAIL(str(e))
-
- match = re.match("^Current allocation:\s+(\d+)\skB", run["output"])
- if not match:
- FAIL("Invalid domU meminfo line")
-
- return int(match.group(1)) / 1024
-
- # Prefer sysfs interface
- def get_mem_from_domU(self):
- if self.use_sysfs:
- return self.get_mem_from_domU_sysfs()
- else:
- return self.get_mem_from_domU_balloon()
-
diff --git a/tools/xm-test/lib/XmTestLib/Xm.py b/tools/xm-test/lib/XmTestLib/Xm.py
deleted file mode 100644
index 6eeab7b..0000000
--- a/tools/xm-test/lib/XmTestLib/Xm.py
+++ /dev/null
@@ -1,245 +0,0 @@
-#!/usr/bin/python
-
-"""
- Copyright (C) International Business Machines Corp., 2005
- Author: Dan Smith <danms at us.ibm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-"""
-
-
-##
-## These are miscellaneous utility functions that query xm
-##
-
-import commands
-import re
-import os
-import time
-
-from Test import *;
-
-class XmError(Exception):
- def __init__(self, msg, trace="", status=0):
- self.msg = msg
- self.trace = trace
- try:
- self.status = int(status)
- except Exception, e:
- self.status = -1
-
- def __str__(self):
- return trace
-
-def domid(name):
- status, output = traceCommand("xm domid " + name);
-
- if status != 0 or "Traceback" in output:
- return -1
- if output == "None":
- return -1
- try:
- return int(output)
- except:
- raise XmError("xm domid failed", trace=output, status=status)
-
-
-def domname(id):
- status, output = traceCommand("xm domname " + str(id));
- return output;
-
-def isDomainRunning(domain):
- id = domid(domain);
- if id == -1:
- return False;
- else:
- return True;
-
-def getRunningDomains():
- status, output = traceCommand("xm list");
- if status != 0 or "Traceback" in output:
- raise XmError("xm failed", trace=output, status=status)
-
- lines = output.splitlines();
- domains = [];
- for l in lines[1:]:
- elms = l.split(" ", 1);
- domains.append(elms[0]);
- return domains;
-
-def destroyDomU(name):
- status, output = traceCommand("xm destroy " + name, logOutput=False);
- return status;
-
-def destroyAllDomUs():
- if verbose:
- print "*** Cleaning all running domU's"
-
- attempt = 0
- trying = True
-
- while trying:
- try:
- attempt += 1
- domainList = getRunningDomains()
- trying = False
- except XmError, e:
- if attempt >= 10:
- FAIL("XM-TEST: xm list not responding")
- time.sleep(1)
- print e.trace
- print "!!! Trying again to get a clean domain list..."
-
- for d in domainList:
- if not d == "Domain-0":
- destroyDomU(d);
-
- if verbose:
- print "*** Finished cleaning domUs"
-
-def getDomMem(domain):
- status, output = traceCommand("xm list")
- if status != 0:
- if verbose:
- print "xm list failed with %i" % status
- return None
-
- lines = re.split("\n", output)
- for line in lines:
- fields = re.sub(" +", " ", line).split()
- if domain.isdigit():
- if fields[1] == domain:
- return int(fields[2])
- else:
- if fields[0] == domain:
- return int(fields[2])
- if verbose:
- print "Did not find domain " + str(domain)
- return None
-
-def getDomInfo(domain, key, opts=None):
- if opts:
- cmd = "xm list %s" % opts
- else:
- cmd = "xm list"
-
- status, output = traceCommand(cmd)
-
- if status != 0:
- if verbose:
- print "xm list failed with %i" % status
- return None
-
- lines = output.split("\n")
-
- # Get the key values from the first line headers
- cleanHeader = re.sub("\([^\)]+\)", "", lines[0])
- colHeaders = re.split(" +", cleanHeader)
-
- doms = {}
-
- for line in lines[1:]:
- domValues = {}
- values = re.split(" +", line)
- i = 1
- for value in values[1:]:
- domValues[colHeaders[i]] = value
- i += 1
- doms[values[0]] = domValues
-
-
- if doms.has_key(domain) and doms[domain].has_key(key):
- return doms[domain].get(key)
-
- return ""
-
-def getVcpuInfo(domain):
-
- status, output = traceCommand("xm vcpu-list %s" % domain)
-
- lines = output.split("\n")
-
- vcpus = {}
-
- for line in lines[1:]:
- cols = re.split(" +", line)
- if cols[3] == '-':
- vcpus[int(cols[2])] = None
- else:
- vcpus[int(cols[2])] = int(cols[3])
-
- return vcpus
-
-def getInfo(key):
-
- info = {}
-
- status, output = traceCommand("xm info")
- lines = output.split("\n")
- for line in lines:
- match = re.match("^([A-z_]+)[^:]*: (.*)$", line)
- if match:
- info[match.group(1)] = match.group(2)
-
- if info.has_key(key):
- return info[key]
- else:
- return ""
-
-def restartXend():
- if verbose:
- print "*** Restarting xend ..."
-
- if os.access("/etc/init.d/xend", os.X_OK):
- status, output = traceCommand("/etc/init.d/xend stop")
- time.sleep(1)
- status, output = traceCommand("/etc/init.d/xend start")
-
- return status
-
- else:
- status, output = traceCommand("xend stop")
- time.sleep(1)
- status, output = traceCommand("xend start")
-
- return status
-
-def smpConcurrencyLevel():
- nr_cpus = int(getInfo("nr_cpus"))
-
- return nr_cpus
-
-if __name__ == "__main__":
- if isDomainRunning("0"):
- print "Domain-0 is running; I must be working!"
- else:
- print "Domain-0 is not running; I may be broken!"
-
- mem = getDomMem("Domain-0")
- if not mem:
- print "Failed to get memory for Domain-0!"
- else:
- print "Domain-0 mem: %i" % mem
-
- cpu = getDomInfo("Domain-0", "CPU")
- state = getDomInfo("Domain-0", "State")
-
- print "Domain-0 CPU: " + cpu
- print "Domain-0 state: " + state
-
- v = getVcpuInfo("Domain-0")
- for key in v.keys():
- print "VCPU%i is on CPU %i" % (key, v[key])
diff --git a/tools/xm-test/lib/XmTestLib/__init__.py b/tools/xm-test/lib/XmTestLib/__init__.py
deleted file mode 100644
index 1aa7afe..0000000
--- a/tools/xm-test/lib/XmTestLib/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-#
-
-from Console import *
-from Test import *
-from Xm import *
-from XenDomain import *
-from config import *
-from XenDevice import *
-from NetConfig import *
-from XenMemory import *
-
-# Give this test a clean slate
-destroyAllDomUs()
-
-if os.environ.get("TEST_VERBOSE"):
- verbose = True
-else:
- verbose = False
-
-if verbose:
- timeStamp()
-
-# We need to track network configuration, like ips, etc.
-xmtest_netconf = NetConfig()
diff --git a/tools/xm-test/lib/XmTestLib/arch.py b/tools/xm-test/lib/XmTestLib/arch.py
deleted file mode 100644
index d505cc0..0000000
--- a/tools/xm-test/lib/XmTestLib/arch.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/python
-"""
- arch.py - Encapsulate all logic regarding what type of hardware xen
- is running on to make adding new platforms easier.
-
- Copyright (C) 2006 Tony Breeds IBM Corporation
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-
-import os
-import re
-import config
-import commands
-
-from Test import *
-
-BLOCK_ROOT_DEV = "hda"
-
-# This isn't truly platform related but it makes the code tidier
-def getRdPath():
- """Locate the full path to ramdisks needed by domUs"""
- rdpath = os.environ.get("RD_PATH")
- if not rdpath:
- rdpath = "../../ramdisk"
- rdpath = os.path.abspath(rdpath)
-
- return rdpath
-
-# Begin: Intel ia32 and ia64 as well as AMD 32-bit and 64-bit processors
-def ia_checkBuffer(buffer):
- return
-
-def ia_minSafeMem():
- return 32
-
-def ia64_minSafeMem():
- return 128
-
-def ia_getDeviceModel():
- """Get the path to the device model based on
- the architecture reported in uname"""
- architecture = os.uname()[4]
- if re.search("64", architecture):
- return "/usr/lib64/xen/bin/qemu-dm"
- else:
- return "/usr/lib/xen/bin/qemu-dm"
-
-def ia_getDefaultKernel():
- """Get the path to the default DomU kernel"""
- dom0Ver = commands.getoutput("uname -r");
- domUVer = dom0Ver.replace("xen0", "xenU");
-
- return "/boot/vmlinuz-" + domUVer;
-
-ia_ParavirtDefaults = {"memory" : 64,
- "vcpus" : 1,
- "kernel" : ia_getDefaultKernel(),
- "root" : "/dev/ram0",
- "ramdisk" : getRdPath() + "/initrd.img",
-}
-ia_HVMDefaults = {"memory" : 64,
- "vcpus" : 1,
- "acpi" : 0,
- "disk" : ["file:%s/disk.img,ioemu:%s,w!" %
- (getRdPath(), BLOCK_ROOT_DEV)],
- "kernel" : "hvmloader",
- "builder" : "hvm",
- "sdl" : 0,
- "vnc" : 0,
- "vncviewer" : 0,
- "nographic" : 1,
- "serial" : "pty",
- "device_model" : ia_getDeviceModel(),
-}
-# End : Intel ia32 and ia64 as well as AMD 32-bit and 64-bit processors
-
-"""Convert from uname specification to a more general platform."""
-_uname_to_arch_map = {
- "i386" : "x86",
- "i486" : "x86",
- "i586" : "x86",
- "i686" : "x86",
- "x86_64": "x86_64",
- "ia64" : "ia64",
-}
-
-# Lookup current platform.
-_arch = _uname_to_arch_map.get(os.uname()[4], "Unknown")
-if _arch == "x86" or _arch == "x86_64" or _arch == "ia64":
- minSafeMem = ia_minSafeMem
- getDefaultKernel = ia_getDefaultKernel
- checkBuffer = ia_checkBuffer
- if config.ENABLE_HVM_SUPPORT:
- configDefaults = ia_HVMDefaults
- else:
- configDefaults = ia_ParavirtDefaults
-
- # note: xm-test generates an uncompressed image, and this code
- # expects one. This will fail with a gzip-ed image.
- if configDefaults['ramdisk']:
- rd_size = os.stat(configDefaults['ramdisk']).st_size
- clause = 'ramdisk_size=' + str((rd_size / 1024)+1)
- if configDefaults.has_key('extra'):
- configDefaults['extra'] = configDefaults['extra'] + " " + clause
- else:
- configDefaults['extra'] = clause
-
- if _arch == "ia64":
- minSafeMem = ia64_minSafeMem
- configDefaults['memory'] = ia64_minSafeMem()
-
-else:
- raise ValueError, "Unknown architecture!"
diff --git a/tools/xm-test/lib/XmTestLib/block_utils.py b/tools/xm-test/lib/XmTestLib/block_utils.py
deleted file mode 100644
index c302efe..0000000
--- a/tools/xm-test/lib/XmTestLib/block_utils.py
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2006 XenSource Inc.
-# Author: Ewan Mellor <ewan at xensource.com>
-
-import time
-
-from XmTestLib import *
-
-import xen.util.blkif
-
-
-__all__ = [ "block_attach", "block_detach" ]
-
-
-def get_state(domain, devname):
- (path, number) = xen.util.blkif.blkdev_name_to_number(devname)
- s, o = traceCommand("xm block-list %s | awk '/^%d/ {print $4}'" %
- (domain.getName(), number))
- if s != 0:
- FAIL("block-list failed")
- if o == "":
- return 0
- else:
- return int(o)
-
-
-def block_attach(domain, phy, virt):
- status, output = traceCommand("xm block-attach %s %s %s w" %
- (domain.getName(), phy, virt))
- if status != 0:
- FAIL("xm block-attach returned invalid %i != 0" % status)
-
- for i in range(10):
- if get_state(domain, virt) == 4:
- break
- time.sleep(1)
- else:
- FAIL("block-attach failed: device did not switch to Connected state")
-
-
-def block_detach(domain, virt):
- status, output = traceCommand("xm block-detach %s %s" %
- (domain.getName(), virt))
- if status != 0:
- FAIL("xm block-detach returned invalid %i != 0" % status)
-
- for i in range(10):
- if get_state(domain, virt) == 0:
- break
- time.sleep(1)
- else:
- FAIL("block-detach failed: device did not disappear")
diff --git a/tools/xm-test/lib/XmTestLib/config.py.in b/tools/xm-test/lib/XmTestLib/config.py.in
deleted file mode 100644
index 21c6cc5..0000000
--- a/tools/xm-test/lib/XmTestLib/config.py.in
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/python
-
-ENABLE_HVM_SUPPORT = @ENABLE_HVM@
-NETWORK_IP_RANGE = "@NET_IP_RANGE@"
-NETWORK = "@NETWORK_ADDRESS@"
-NETMASK = "@NETMASK@"
-DOM0_INTF = "@DOM0_INTF@"
diff --git a/tools/xm-test/lib/XmTestLib/network_utils.py b/tools/xm-test/lib/XmTestLib/network_utils.py
deleted file mode 100644
index 5c06f2f..0000000
--- a/tools/xm-test/lib/XmTestLib/network_utils.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Murillo F. Bernardes <mfb at br.ibm.com>
-
-from XmTestLib import *
-
-def count_eth(console):
- try:
- run = console.runCmd("ifconfig -a | grep eth")
- except ConsoleError, e:
- FAIL(str(e))
- return len(run['output'].splitlines())
-
-def get_state(domain_name, number):
- s, o = traceCommand("xm network-list %s | awk '/^%d/ {print $5}'" %
- (domain_name, number))
- print o
-
- if s != 0:
- FAIL("network-list failed")
- if o == "":
- return 0
- else:
- return int(o)
-
-def network_attach(domain_name, console, bridge=None):
- eths_before = count_eth(console)
- if bridge:
- status, output = traceCommand("xm network-attach %s bridge=%s"
- % (domain_name, bridge))
- else:
- status, output = traceCommand("xm network-attach %s" % domain_name)
- if status != 0:
- return -1, "xm network-attach returned invalid %i != 0" % status
-
- eths_after = count_eth(console)
- if (eths_after != (eths_before+1)):
- return -2, "Network device is not actually connected to domU"
-
- return 0, None
-
-def network_detach(domain_name, console, num=0):
- eths_before = count_eth(console)
- status, output = traceCommand("xm network-detach %s %d" % (domain_name, num))
- if status != 0:
- return -1, "xm network-detach returned invalid %i != 0" % status
-
- for i in range(10):
- if get_state(domain_name, num) == 0:
- break
- time.sleep(1)
- else:
- FAIL("network-detach failed: device did not disappear")
-
- eths_after = count_eth(console)
- if eths_after != (eths_before-1):
- return -2, "Network device was not actually disconnected from domU"
-
- return 0, None
diff --git a/tools/xm-test/lib/XmTestLib/xapi.py b/tools/xm-test/lib/XmTestLib/xapi.py
deleted file mode 100644
index de552ef..0000000
--- a/tools/xm-test/lib/XmTestLib/xapi.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/python
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 XenSource Ltd.
-# Copyright (C) 2006 IBM Corporation
-# Copyright (C) 2009 flonatel GmbH & Co. KG
-#============================================================================
-
-import atexit
-import os
-import sys
-from XmTestLib import *
-from xen.xm import main as xmmain
-from xen.xm import XenAPI
-from xen.xm.opts import OptionError
-from types import DictType
-import xml.dom.minidom
-
-sessions=[]
-
-def connect(*args):
- creds = ("", "")
- uri = "http://localhost:9363"
-
- try:
- session = XenAPI.Session(uri)
- except:
- raise OptionError("Could not create XenAPI session with Xend." \
- "URI=%s" % uri)
- try:
- session.login_with_password(*creds)
- except:
- raise OptionError("Could not login to Xend. URI=%s" % uri)
- def logout():
- try:
- for s in sessions:
- s.xenapi.session.logout()
- except:
- pass
- sessions.append(session)
- atexit.register(logout)
- return session
diff --git a/tools/xm-test/lib/XmTestReport/OSReport.py b/tools/xm-test/lib/XmTestReport/OSReport.py
deleted file mode 100644
index 4eaa20c..0000000
--- a/tools/xm-test/lib/XmTestReport/OSReport.py
+++ /dev/null
@@ -1,248 +0,0 @@
-#!/usr/bin/python
-
-"""
- OSReport.py - Handles the gathering and xml-formatting of operating
- system environment information.
-
- Copyright (C) International Business Machines Corp., 2005
- Author: Dan Smith <danms at us.ibm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-
-import utils
-
-import posix
-import re
-import os
-import commands
-import sys
-import arch
-
-class Machine:
-
- def __parseInfoLine(self, line):
- if ":" in line:
- name, value = line.split(":", 1)
- name = name.strip()
- value = value.strip()
-
- name = re.sub(" ", "_", name)
-
- return name, value
- else:
- return None, None
-
- def __getCpuInfo(self, values):
-
- processors = 0
- cpuinfo = file("/proc/cpuinfo")
-
- if not cpuinfo:
- return "Unable to read /proc/cpuinfo"
-
- lines = cpuinfo.readlines()
-
- for l in lines:
- name, value = self.__parseInfoLine(l)
-
- if name in values.keys():
- values[name] = value
-
- if name == "processor":
- processors += 1
-
- values["dom0procs"] = str(processors)
-
- return values
-
- def __getXenInfo(self, values):
-
- status, output = commands.getstatusoutput("xm info")
- if status != 0:
- self.errors += 1
- return values
-
- lines = output.split("\n")
-
- for l in lines:
- name, value = self.__parseInfoLine(l)
-
- if name in values.keys():
- values[name] = value
-
- return values
-
- def __init__(self):
-
- self.values = {}
- self.errors = 0
-
- xenValues = {"nr_cpus" : "Unknown",
- "nr_nodes" : "Unknown",
- "cores_per_socket" : "Unknown",
- "threads_per_core" : "Unknown",
- "cpu_mhz" : "Unknown",
- "total_memory" : "Unknown"}
-
- xen = self.__getXenInfo(xenValues)
- cpu = self.__getCpuInfo(arch.cpuValues)
-
- for k in xen.keys():
- self.values[k] = xen[k]
- if xen[k] == "Unknown":
- self.errors += 1
-
- for k in cpu.keys():
- self.values[k] = cpu[k]
- if cpu[k] == "Unknown":
- self.errors += 1
-
-
- def __str__(self):
- string = "<machine>\n"
-
- for k in self.values.keys():
- string += " " + utils.tagify(k, self.values[k]) + "\n"
-
- string += "</machine>\n"
-
- return string
-
-class OperatingSystem:
-
- def __redhatStyleRelease(self):
- rFile = None
-
- if os.access("/etc/redhat-release", os.R_OK):
- rFile = file("/etc/redhat-release")
- if os.access("/etc/SuSe-release", os.R_OK):
- rFile = file("/etc/SuSe-release")
- if os.access("/etc/SuSE-release", os.R_OK):
- rFile = file("/etc/SuSE-release")
- if os.access("/etc/mandrake-release", os.R_OK):
- rFile = file("/etc/mandrake-release")
-
- if not rFile:
- return None, None
-
- rLine = rFile.readline()
- rFile.close()
-
- match = re.match("^([^0-9]+)([0-9\.]+).*$", rLine)
- if match:
- return match.group(1), match.group(2)
- else:
- return None, None
-
- def __debianStyleRelease(self):
- if os.access("/etc/debian_version", os.R_OK):
- rFile = file("/etc/debian_version")
- else:
- rFile = None
-
- if not rFile:
- return None, None
-
- line = rFile.readline()
- return "Debian", line.rstrip("\n");
-
- def __lsbStyleRelease(self):
- if os.access("/etc/lsb-release", os.R_OK):
- rFile = file("/etc/lsb-release")
- else:
- rFile = None
-
- if not rFile:
- return None, None
-
- lines = rFile.readlines()
-
- vendor = None
- version = None
-
- for l in lines:
- match = re.match("^DISTRIB_ID=(.*)$", l)
- if match:
- vendor = match.group(1)
- match = re.match("^DISTRIB_RELEASE=(.*)$", l)
- if match:
- version = match.group(1)
-
- return vendor, version
-
- def __init__(self):
-
- self.values = {}
- self.errors = 0
-
- # Try to resolve the vendor and version information
- # for the distro we're running on
- vendor = None
- version = None
- for r in [self.__redhatStyleRelease, self.__debianStyleRelease, self.__lsbStyleRelease]:
- vendor, version = r()
- if vendor and version:
- break
-
- self.values["vendor"] = vendor or "Unknown vendor"
- self.values["version"] = version or "Unknown version"
-
- self.values["name"], nodename, release, version, self.values["arch"] = posix.uname()
-
- for k in self.values.keys():
- if not self.values[k]:
- self.errors += 1
-
- def __str__(self):
- string = "<os>\n"
-
- for k in self.values.keys():
- string += " " + utils.tagify(k, self.values[k]) + "\n"
-
- string += "</os>\n"
-
- return string
-
-
-class OSReport:
-
- def __init__(self):
-
- self.reports = {}
- self.reports["os"] = OperatingSystem()
- self.reports["machine"] = Machine()
- self.errors = 0
-
- for k in self.reports.keys():
- self.errors += self.reports[k].errors
-
- def __str__(self):
-
- string = ""
-
- for k in self.reports.keys():
- string += str(self.reports[k])
-
- return string
-
-if __name__ == "__main__":
- r = OSReport()
-
- print str(r)
-
- sys.exit(r.errors)
-
-
diff --git a/tools/xm-test/lib/XmTestReport/ProgReport.py b/tools/xm-test/lib/XmTestReport/ProgReport.py
deleted file mode 100644
index 31f5437..0000000
--- a/tools/xm-test/lib/XmTestReport/ProgReport.py
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/usr/bin/python
-
-"""
- ProgReport.py - Handles the gathering and xml-formatting of supporting
- program information
-
- Copyright (C) International Business Machines Corp., 2005
- Author: Dan Smith <danms at us.ibm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-
-import utils
-
-import commands
-import re
-import distutils.sysconfig
-import sys
-
-from xmtest import XM_TEST_VERSION
-
-class Prog:
-
- def __init__(self, name, version):
- self.vars = {}
- self.vars["name"] = name
- self.vars["version"] = version
-
- def __str__(self):
- string = "<prog>\n"
-
- for k in self.vars.keys():
- string += " " + utils.tagify(k, self.vars[k]) + "\n"
-
- string += "</prog>\n"
-
- return string
-
-class UnknownProg(Prog):
-
- def __init__(self, name):
- Prog.__init__(self, name, "Unknown Version")
-
-class ProgFactory:
-
- def getXen(self):
- status, output = commands.getstatusoutput("xm info")
- if status != 0:
- return UnknownProg("xen")
-
- for l in output.split("\n"):
- match = re.match("^([a-z_]+)[ ]*: (.*)$", l)
- if match and match.group(1) == "xen_changeset":
- return Prog("xen", match.group(2))
-
- return UnknownProg("xen")
-
- def getXmTest(self):
- return Prog("xm-test", XM_TEST_VERSION)
-
- def getPython(self):
- return Prog("python", distutils.sysconfig.get_python_version())
-
- def getXenCaps(self):
- s, o = commands.getstatusoutput("xm info")
- if s != 0:
- return UnknownProg("xen_caps")
-
- for l in o.split("\n"):
- match = re.match("^xen_caps[ \t]*: (.*)$", l)
- if match:
- return Prog("xen_caps", match.group(1))
-
-class ProgReport:
-
- def __init__(self):
-
- self.progs = []
- self.errors = 0
-
- f = ProgFactory()
-
- self.progs.append(f.getXen())
- self.progs.append(f.getXmTest())
- self.progs.append(f.getPython())
- self.progs.append(f.getXenCaps())
-
- for p in self.progs:
- if isinstance(p, UnknownProg):
- self.errors += 1
-
- def __str__(self):
- string = "<progs>\n"
-
- for p in self.progs:
- string += str(p)
-
- string += "</progs>\n"
-
- return string
-
-if __name__ == "__main__":
- r = ProgReport()
-
- print str(r)
-
- sys.exit(r.errors)
diff --git a/tools/xm-test/lib/XmTestReport/Report.py b/tools/xm-test/lib/XmTestReport/Report.py
deleted file mode 100644
index 4cca826..0000000
--- a/tools/xm-test/lib/XmTestReport/Report.py
+++ /dev/null
@@ -1,156 +0,0 @@
-#!/usr/bin/python
-
-"""
- Report.py - Handles the coordination of xm-test xml-reporting modules
-
- Copyright (C) International Business Machines Corp., 2005
- Author: Dan Smith <danms at us.ibm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-
-import OSReport
-import ProgReport
-import ResultReport
-import utils
-
-import sys
-import os
-import xml.dom.minidom
-import httplib
-import urllib
-import re
-from urlparse import urlparse
-
-class XmTestReport:
-
- def __init__(self, files):
- self.files = files
-
- def __getContactInfo(self):
- if os.access("contact_info", os.R_OK):
- c = file("contact_info")
- line = c.readline()
- line = line.strip()
- return line
- else:
- return "nobody at nowhere.com"
-
- def __stringify(self, fileName):
- f = file(fileName)
- str = f.read()
- f.close()
-
- return str
-
- def __str__(self):
- string = "<testname>xm-test</testname>\n"
- string += "<user>%s</user>\n" % self.__getContactInfo()
-
- for f in self.files:
- string += self.__stringify(f)
-
- return string
-
-# Taken from example in Python Cookbook
-def encodeForm(fieldList):
- body = []
- boundary = "-------XmTestReportingXML"
-
- for name in fieldList.keys():
- body.append('--' + boundary)
- body.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (name, "%s.txt" % name))
- body.append('Content-Type: text/plain')
- body.append('')
- body.append(fieldList[name])
-
- body.append('')
- body.append("--" + boundary + "--")
- body.append('')
-
- textBody = "\r\n".join(body)
-
- return 'multipart/form-data; boundary=%s' % boundary, textBody
-
-def postResults(report_server, results):
- if not re.match('http://', report_server):
- report_server = 'http://'+report_server
- (report_host,report_url) = urlparse(report_server)[1:3]
- conn = httplib.HTTPConnection(report_host)
-
- type, body = encodeForm({"log" : results})
-
- headers = {"content-type" : type}
-
- # DEBUG OUTPUT
- # print "BODY\n%s\nBODY\n" % body
- # print "%s\n" % type
- # print headers
-
- conn.request("POST", report_url, body, headers)
-
- resp = conn.getresponse()
- data = resp.read()
-
- if resp.status == 200:
- print >>sys.stderr, "Your results have been submitted successfully!"
- else:
- print >>sys.stderr, "Unable to submit results:"
- print >>sys.stderr, "[http://%s%s] said %i: %s" % (report_host,
- report_url,
- resp.status,
- resp.reason)
- print >>sys.stderr, data
-
-if __name__ == "__main__":
-
- if len(sys.argv) <= 1:
- print "Usage: Report.py [opt] <outputfiles...>"
- print "Where:"
- print "-d : don't submit, just dump XML"
- print "-D : do submit and dump XML"
- sys.exit(1)
-
- submit = True
- dump = False
- files = []
-
- report_server = sys.argv[1]
-
- for a in sys.argv[2:]:
- if a == "-d":
- submit = False
- dump = True
- elif a == "-D":
- dump = True
- submit = True
-
- else:
- if not os.access(a, os.R_OK):
- print "Unable to access file: %s" % a
- sys.exit(1)
- else:
- files.append(a)
-
- report = XmTestReport(files)
-
- xmlout = "<xml>\n%s</xml>\n" % report
-
- if dump:
- print xmlout
-
- if submit:
- postResults(report_server, xmlout)
-
diff --git a/tools/xm-test/lib/XmTestReport/ResultReport.py b/tools/xm-test/lib/XmTestReport/ResultReport.py
deleted file mode 100644
index 03b77c5..0000000
--- a/tools/xm-test/lib/XmTestReport/ResultReport.py
+++ /dev/null
@@ -1,157 +0,0 @@
-#!/usr/bin/python
-
-"""
- ResultReport.py - Handles the gathering and xml-formatting of xm-test
- results
-
- Copyright (C) International Business Machines Corp., 2005
- Author: Dan Smith <danms at us.ibm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-
-import utils
-
-import re
-
-class Test:
-
- def __init__(self, name, state, seq):
- self.vars = {}
- self.vars["name"] = name
- self.vars["state"] = state
- self.vars["log"] = "NO LOG SUPPLIED"
- self.vars["seq"] = str(seq)
-
- def setLog(self, log):
- self.vars["log"] = log
-
- def __str__(self):
- string = "<test>\n"
-
- for k in self.vars.keys():
- string += " " + utils.tagify(k, self.vars[k]) + "\n"
-
- string += "</test>\n"
-
- return string
-
-class TestGroup:
-
- def __init__(self, name):
- self.name = name
- self.tests = []
-
- def addTest(self, test):
- self.tests.append(test)
-
- def __str__(self):
- string = "<group>\n"
- string += " <name>%s</name>\n" % self.name
-
- for t in self.tests:
- string += str(t)
-
- string += "</group>\n"
-
- return string
-
-class ResultSet:
-
- def __init__(self):
- self.groups = []
-
- def addGroup(self, group):
- self.groups.append(group)
-
- def __str__(self):
- string = "<results>\n"
-
- for g in self.groups:
- string += str(g)
-
- string += "</results>\n"
-
- return string
-
-class ResultParser:
-
- def __init__(self):
- self.groups = {}
- self.resultSet = None
-
- def __isImportant(self, line):
-
- if re.search("^[Mm]ak(e|ing)", line):
- return False
- if re.search("^===", line):
- return False
- if re.search("^All [0-9]+ tests", line):
- return False
- if re.search("^[0-9]+ of [0-9]+ tests", line):
- return False
- if re.search("^cp [0-9]+_", line):
- return False
- if re.search("^chmod \+x [0-9]+_", line):
- return False
-
- return True
-
- def parse(self, fileName):
- output = file(fileName);
- contents = output.read()
-
- lines = contents.split("\n")
-
- sequence = 0
- currentLog = ""
- for l in lines:
- match = re.match("^(PASS|FAIL|XPASS|XFAIL|SKIP): ([0-9]+)_([^_]+)_([^\.]+)\.test$", l)
- if match:
- # End of current test; build object
- testStatus = match.group(1)
- testNumber = match.group(2)
- testGroup = match.group(3)
- testName = match.group(4)
-
- if not testGroup in self.groups.keys():
- self.groups[testGroup] = TestGroup(testGroup)
-
- test = Test("%s_%s" % (testNumber, testName), testStatus,
- sequence)
- sequence += 1
- test.setLog(currentLog)
- self.groups[testGroup].addTest(test)
-
- currentLog = ""
-
- else:
- if self.__isImportant(l):
- currentLog += l + "\n"
-
- self.resultSet = ResultSet()
-
- for g in self.groups:
- self.resultSet.addGroup(self.groups[g])
-
- return self.resultSet
-
-if __name__ == "__main__":
-
- import sys
-
- r = ResultParser()
-
- print str(r.parse(sys.argv[1]))
diff --git a/tools/xm-test/lib/XmTestReport/arch.py b/tools/xm-test/lib/XmTestReport/arch.py
deleted file mode 100644
index 920526d..0000000
--- a/tools/xm-test/lib/XmTestReport/arch.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/python
-"""
- arch.py - Encapsulate all logic regarding what type of hardware xen
- is running on to make adding new platforms easier.
-
- Copyright (C) 2006 Tony Breeds IBM Corporation
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-
-import os
-
-"""Convert from uname specification to a more general platform."""
-_uname_to_arch_map = {
- "i386" : "x86",
- "i486" : "x86",
- "i586" : "x86",
- "i686" : "x86",
- "x86_64": "x86_64",
- "ia64" : "ia64",
-}
-
-_arch = _uname_to_arch_map.get(os.uname()[4], "Unknown")
-if _arch == "x86":
- cpuValues = {"model_name" : "Unknown",
- "flags" : "Unknown"}
-elif _arch == "x86_64":
- cpuValues = {"model_name" : "Unknown",
- "flags" : "Unknown"}
-elif _arch == "ia64":
- cpuValues = {"arch" : "Unknown",
- "features" : "Unknown"}
-else:
- raise ValueError, "Unknown architecture!"
diff --git a/tools/xm-test/lib/XmTestReport/utils.py b/tools/xm-test/lib/XmTestReport/utils.py
deleted file mode 100644
index 1d207ef..0000000
--- a/tools/xm-test/lib/XmTestReport/utils.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/python
-
-"""
- utils.py - Utilities for reporting xm-test results
-
- Copyright (C) International Business Machines Corp., 2005
- Author: Dan Smith <danms at us.ibm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-
-from xml.sax.saxutils import escape
-
-def tagify(tag, string):
- return "<%s>%s</%s>" % (tag, escape(string.strip()), tag)
-
-
-
-
diff --git a/tools/xm-test/lib/XmTestReport/xmtest.py.in b/tools/xm-test/lib/XmTestReport/xmtest.py.in
deleted file mode 100644
index 9b7a263..0000000
--- a/tools/xm-test/lib/XmTestReport/xmtest.py.in
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/python
-
-XM_TEST_VERSION = "@PACKAGE_VERSION@"
-
-if __name__ == "__main__":
- import re
-
- match = re.match("^(\d+)\.(\d+)\.(\d+)$", XM_TEST_VERSION)
-
- print "XM_TEST_VERSION=%s" % XM_TEST_VERSION
- if match:
- print "XM_TEST_MAJ=%s" % match.group(1)
- print "XM_TEST_MIN=%s" % match.group(2)
- print "XM_TEST_REV=%s" % match.group(3)
-
diff --git a/tools/xm-test/mergereport b/tools/xm-test/mergereport
deleted file mode 100644
index 98b37de..0000000
--- a/tools/xm-test/mergereport
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-
-# Dan Smith <danms at us.ibm.com> - 16-Sep-2005
-#
-# This script takes all the .report files in the current
-# directory and generates a summary table, showing the
-# number of PASS, FAIL, XPASS, and XFAIL tests in each
-# report
-
-
-echo " Platform | PASS | FAIL | XPASS | XFAIL |"
-echo "---------------------+------+------+-------+-------+"
-
-for r in *.report; do
-
- mach=$(basename $r .report)
- pass=$(cat $r | grep ' PASS' | cut -d : -f 2 | sed 's/ *//')
- fail=$(cat $r | grep ' FAIL' | cut -d : -f 2 | sed 's/ *//')
- xpas=$(cat $r | grep ' XPASS' | cut -d : -f 2 | sed 's/ *//')
- xfal=$(cat $r | grep ' XFAIL' | cut -d : -f 2 | sed 's/ *//')
-
- printf "%20s | %4s | %4s | %5s | %5s |\n" "$mach" "$pass" \
- "$fail" "$xpas" "$xfal"
-
-done
diff --git a/tools/xm-test/mkreport b/tools/xm-test/mkreport
deleted file mode 100644
index 24c4270..0000000
--- a/tools/xm-test/mkreport
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/perl
-
-open(LOG, $ARGV[0]);
- at lines = <LOG>;
-
-foreach $line (@lines) {
- if ($line =~ /^[A-Z]+/) {
- chomp($line);
- ($type, @rest) = split(/:/, $line);
-
- $message = "";
- foreach $chunk (@rest) {
- $message .= $chunk;
- }
-
- if ($type eq "REASON") {
-
- $last_reason = $message ;
-
- } elsif ($type =~ /X?FAIL/) {
-
- $rest[0] =~ /([^\. ]+)\.test/;
- $name = $1;
-
- $passfail = $type;
- $testname = $name;
- $extra = "\n\t$last_reason\n";
-
- $last_reason = "Unknown reason";
-
- } elsif ($type =~ /X?PASS/) {
-
- $rest[0] =~ /([^\. ]+)\.test/;
- $name = $1;
-
- $passfail = $type;
- $testname = $name;
- $extra = "";
-
- $last_reason = "Unknown reason";
-
- } else {
-
- $passfail = $type;
- $testname = "UNKN";
- $extra = "Unknown status type $type!";
-
- $last_reason = "Unknown reason";
-
- }
-
- push(@results, ([$testname, $passfail, $extra]));
-
- }
-
-}
-
-foreach $test (@results) {
-
-
- if ($tests{$test->[0]} eq undef) {
- if ($test->[1] =~ /^X?FAIL/) {
- $fmt = "%5s: %s %s\n";
- printf($fmt, $test->[1], $test->[0], $test->[2]);
- }
- $tests{$test->[0]} = 1;
- }
-
-
-}
-
diff --git a/tools/xm-test/ramdisk/Makefile.am b/tools/xm-test/ramdisk/Makefile.am
deleted file mode 100644
index 8386218..0000000
--- a/tools/xm-test/ramdisk/Makefile.am
+++ /dev/null
@@ -1,126 +0,0 @@
-#
-# make existing:
-#
-# Download a pre-built ramdisk.
-# INITRD = <Directory to download ramdisk from>
-#
-# make initrd.img:
-#
-# Make a ramdisk from scratch.
-# BR_URL = <The URL of the Buildroot source code>
-# BR_SNAPSHOT = 1 Set BR_URL to the upstream Buildroot daily snapshot.
-# BR_ARCH = <The build architecture for the initrd>
-#
-
-INITRD ?= http://xm-test.xensource.com/ramdisks
-
-BR_ARCH ?= $(shell uname -m | sed -e 's/i.86/i386/' -e 's/x86_64/i386/')
-
- at MK@ifdef BR_SNAPSHOT
- at MK@ BR_URL = http://buildroot.uclibc.org/downloads/snapshots/buildroot-snapshot.tar.bz2
- at MK@else
- at MK@ BR_URL = http://xm-test.xensource.com/ramdisks/buildroot-20061023.tar.bz2
- at MK@endif
-BR_TAR = $(notdir $(BR_URL))
-
-BR_SRC = buildroot
-BR_IMG = $(BR_SRC)/rootfs.$(BR_ARCH).ext2
-
-BR_ROOT = build_$(BR_ARCH)/root
-
-EXTRA_DIST = skel configs patches
-
-HVM_SCRIPT = bin/create_disk_image
-
-XMTEST_MAJ_VER = $(shell echo @PACKAGE_VERSION@ | perl -pe 's/(\d+)\.(\d+)\.\d+/\1.\2/')
-XMTEST_VER_IMG = initrd-$(XMTEST_MAJ_VER)-$(BR_ARCH).img
-XMTEST_DL_IMG = $(shell echo $(XMTEST_VER_IMG) | sed -e 's/x86_64/i386/g')
-
-EXTRA_ROOT_DIRS = sys modules
-
-BLKDRV = /lib/modules/$(shell uname -r)/kernel/drivers/xen/blkfront/xenblk.ko
-NETDRV = /lib/modules/$(shell uname -r)/kernel/drivers/xen/netfront/xennet.ko
-PKTDRV = /lib/modules/$(shell uname -r)/kernel/net/packet/af_packet.ko
-
-
-if HVM
-all: initrd.img disk.img
-else
-all: initrd.img
-endif
-
-$(BR_TAR):
- wget $(BR_URL)
-
-$(BR_SRC): $(BR_TAR)
- tar xjf $(BR_TAR)
-
-$(BR_IMG): $(BR_SRC)
- cp configs/buildroot-$(BR_ARCH) $(BR_SRC)/.config
- cp configs/busybox $(BR_SRC)/package/busybox/busybox.config
- cp configs/uClibc $(BR_SRC)/toolchain/uClibc/uClibc.config
- set -e; for i in patches/buildroot/*.patch; do \
- cd $(BR_SRC) && patch -p1 <../$$i && cd ..; done
- cd $(BR_SRC) && make oldconfig && make
-
-$(XMTEST_VER_IMG): $(BR_IMG)
- chmod a+x skel/etc/init.d/rcS
- cd skel && mkdir -p $(EXTRA_ROOT_DIRS)
- -[ -e "$(BLKDRV)" ] && cp $(BLKDRV) skel/modules
- -[ -e "$(NETDRV)" ] && cp $(NETDRV) skel/modules
- -[ -e "$(PKTDRV)" ] && cp $(PKTDRV) skel/modules
- (cd skel && tar cf - .) \
- | (cd $(BR_SRC)/$(BR_ROOT) && tar xvf -)
- cd $(BR_SRC) && make
- cp $(BR_IMG) $(XMTEST_VER_IMG)
-
-initrd.img: $(XMTEST_VER_IMG)
- ln -sf $(XMTEST_VER_IMG) initrd.img
-
-disk.img: existing
- chmod a+x $(HVM_SCRIPT)
- @if test ! "$(HVMKERNEL)" = "no" -a ! "$(DRVDIR)" = "no"; then \
- $(HVM_SCRIPT) -r $(XMTEST_VER_IMG) -k $(HVMKERNEL) \
- -d $(DRVDIR) -n $(NETDRV); \
- elif test "$(HVMKERNEL)" = "no" -a ! "$(DRVDIR)" = "no"; then \
- $(HVM_SCRIPT) -r $(XMTEST_VER_IMG) -d $(DRVDIR) -n $(NETDRV); \
- elif test ! "$(HVMKERNEL)" = "no" -a "$(DRVDIR)" = "no"; then \
- $(HVM_SCRIPT) -r $(XMTEST_VER_IMG) -k $(HVMKERNEL) \
- -n $(NETDRV); \
- else \
- $(HVM_SCRIPT) -r $(XMTEST_VER_IMG) -n $(NETDRV); \
- fi
-
-existing:
- @if [ -n "$(INITRD)" ] && [ ! -f $(XMTEST_VER_IMG) ] ; then \
- if [ ! -f $(XMTEST_DL_IMG) ] ; then \
- wget $(INITRD)/$(XMTEST_DL_IMG); \
- fi; \
- if [ "$(XMTEST_DL_IMG)" != "$(XMTEST_VER_IMG)" ] ; then \
- ln -s $(XMTEST_DL_IMG) $(XMTEST_VER_IMG); \
- fi \
- fi
- @if [ -f $(XMTEST_VER_IMG) ] ; then \
- ln -sf $(XMTEST_VER_IMG) initrd.img; \
- else \
- echo Error, $(XMTEST_VER_IMG) not found; \
- false; \
- fi
-# The newer linux kernels have ext2 disabled by default - but the
-# initrd is ext2.
-# The whole xm-test environment assumes, that the guest system uses
-# the same kernel as the dom0. Therefore the current (dom0's) kernel
-# is checked if ext2 is supported. If not (and ext3 is supported) the
-# initrd will be converted to ext3.
- @cat /proc/filesystems | grep -q ext2 && \
- cat /proc/filesystems | grep -q ext3 || \
- /sbin/tune2fs -j $(XMTEST_DL_IMG) >/dev/null || true
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -Rf buildroot
- rm -f *~
- rm -f initrd.img
- rm -f $(BR_TAR)
- rm -f disk.img
diff --git a/tools/xm-test/ramdisk/README-XenSource-initrd-0.7-img b/tools/xm-test/ramdisk/README-XenSource-initrd-0.7-img
deleted file mode 100644
index 1d2b703..0000000
--- a/tools/xm-test/ramdisk/README-XenSource-initrd-0.7-img
+++ /dev/null
@@ -1,42 +0,0 @@
-XenSource xm-test 0.7 initrd.img
-================================
-
-http://xm-test.xensource.com/ramdisks/initrd-0.7.img is an initrd suitable for
-use with Xen's xm-test regression testing suite. It has been built and
-provided by XenSource, for the convenience of Xen users. xm-test initrds may
-be mixed across minor xm-test versions, but not across major versions; this
-initrd is suitable for all 0.7.x versions of xm-test (as shipped with Xen
-3.0.x).
-
-In order to use this initrd, run "./autogen; ./configure; make existing"
-inside the xm-test directory, and the initrd will be downloaded automatically.
-Alternatively, if you have already downloaded this file, place it into the
-xm-test/ramdisk directory and run the same command. In either case,
-runtest.sh can then be used as normal. See xm-test/README for more details.
-
-This initrd was built using the infrastructure provided by xm-test. It is a
-full guest operating system and filesystem, and as such includes a large
-number of pieces of software. The source code for the majority of these are
-included in full inside the file
-http://xm-test.xensource.com/ramdisks/initrd.0.7.img-buildroot.tar.bz2, or
-alongside this file. Copyright statements and licences are contained therein.
-The remaining source code is included in the Xen distribution, at
-http://www.xensource.com/xen/downloads/archives.html. The configurations used
-for BusyBox, uClibc, and Buildroot are available as
-http://xm-test.xensource.com/ramdisks/initrd-0.7-busybox-config,
-http://xm-test.xensource.com/ramdisks/initrd-0.7-uClibc-config, and
-http://xm-test.xensource.com/ramdisks/initrd-0.7-buildroot-config
-respectively, or alongside this file.
-
-XenSource and the Xen contributors are grateful to the authors of these
-software packages for their contributions to free and open-source software.
-
-
-Buildroot and BusyBox are Copyright (c) Erik Andersen <andersen at codepoet.org>.
-BusyBox is licensed under the GNU General Public License (GPL). A copy of
-this license is available in the file GPL-2,
-http://xm-test.xensource.com/ramdisks/GPL-2, or alongside this file.
-
-uClibc is licensed under the GNU Lesser General Public License (LGPL). A copy
-of this license is available in the file
-http://xm-test.xensource.com/ramdisks/LGPL-2, or alongside this file.
diff --git a/tools/xm-test/ramdisk/README-XenSource-initrd-0.8-img b/tools/xm-test/ramdisk/README-XenSource-initrd-0.8-img
deleted file mode 100644
index b424cb3..0000000
--- a/tools/xm-test/ramdisk/README-XenSource-initrd-0.8-img
+++ /dev/null
@@ -1,42 +0,0 @@
-XenSource xm-test 0.8 initrd.img
-================================
-
-http://xm-test.xensource.com/ramdisks/initrd-0.8.img is an initrd suitable for
-use with Xen's xm-test regression testing suite. It has been built and
-provided by XenSource, for the convenience of Xen users. xm-test initrds may
-be mixed across minor xm-test versions, but not across major versions; this
-initrd is suitable for all 0.8.x versions of xm-test (as shipped with Xen
-3.0.x >3.0.2-3).
-
-In order to use this initrd, run "./autogen; ./configure; make existing"
-inside the xm-test directory, and the initrd will be downloaded automatically.
-Alternatively, if you have already downloaded this file, place it into the
-xm-test/ramdisk directory and run the same command. In either case,
-runtest.sh can then be used as normal. See xm-test/README for more details.
-
-This initrd was built using the infrastructure provided by xm-test. It is a
-full guest operating system and filesystem, and as such includes a large
-number of pieces of software. The source code for the majority of these are
-included in full inside the file
-http://xm-test.xensource.com/ramdisks/initrd-0.8.img-buildroot.tar.bz2, or
-alongside this file. Copyright statements and licences are contained therein.
-The remaining source code is included in the Xen distribution, at
-http://www.xensource.com/xen/downloads/archives.html. The configurations used
-for BusyBox, uClibc, and Buildroot are available as
-http://xm-test.xensource.com/ramdisks/initrd-0.8-busybox-config,
-http://xm-test.xensource.com/ramdisks/initrd-0.8-uClibc-config, and
-http://xm-test.xensource.com/ramdisks/initrd-0.8-buildroot-config
-respectively, or alongside this file.
-
-XenSource and the Xen contributors are grateful to the authors of these
-software packages for their contributions to free and open-source software.
-
-
-Buildroot and BusyBox are Copyright (c) Erik Andersen <andersen at codepoet.org>.
-BusyBox is licensed under the GNU General Public License (GPL). A copy of
-this license is available in the file GPL-2,
-http://xm-test.xensource.com/ramdisks/GPL-2, or alongside this file.
-
-uClibc is licensed under the GNU Lesser General Public License (LGPL). A copy
-of this license is available in the file
-http://xm-test.xensource.com/ramdisks/LGPL-2, or alongside this file.
diff --git a/tools/xm-test/ramdisk/README-XenSource-initrd-1.0-img b/tools/xm-test/ramdisk/README-XenSource-initrd-1.0-img
deleted file mode 100644
index 80ac26b..0000000
--- a/tools/xm-test/ramdisk/README-XenSource-initrd-1.0-img
+++ /dev/null
@@ -1,46 +0,0 @@
-XenSource xm-test 1.0 initrds
-=============================
-
-http://xm-test.xensource.com/ramdisks/initrd-1.0-i386.img and
-http://xm-test.xensource.com/ramdisks/initrd-1.0-powerpc.img are initrds
-suitable for use with Xen's xm-test regression testing suite. They has been
-built and provided by XenSource, for the convenience of Xen users. xm-test
-initrds may be mixed across minor xm-test versions, but not across major
-versions; this initrd is suitable for all 1.0.x versions of xm-test (as
-shipped with the Xen unstable tree for a short while between Xen 3.0.3 and
-Xen 3.0.4).
-
-In order to use one of these initrds, run "./autogen; ./configure; make
-existing" inside the xm-test directory, and the appropriate initrd for your
-architecture will be downloaded automatically. Alternatively, if you have
-already downloaded that file, place it into the xm-test/ramdisk directory and
-run the same command. In either case, runtest.sh can then be used as normal.
-See xm-test/README for more details.
-
-These initrds were built using the infrastructure provided by xm-test. Each
-is a full guest operating system and filesystem, and as such includes a large
-number of pieces of software. The source code for the majority of these are
-included in full inside the file
-http://xm-test.xensource.com/ramdisks/<INITRD>-buildroot.tar.bz2, where
-<INITRD> is either initrd-1.0-i386 or initrd-1.0-powerpc as appropriate, or
-alongside this file. Copyright statements and licences are contained therein.
-The remaining source code is included in the Xen distribution, at
-http://www.xensource.com/xen/downloads/archives.html. The configurations used
-for BusyBox, uClibc, and Buildroot are available as
-http://xm-test.xensource.com/ramdisks/<INITRD>-busybox-config,
-http://xm-test.xensource.com/ramdisks/<INITRD>-uClibc-config, and
-http://xm-test.xensource.com/ramdisks/<INITRD>-buildroot-config respectively,
-or alongside this file.
-
-XenSource and the Xen contributors are grateful to the authors of these
-software packages for their contributions to free and open-source software.
-
-
-Buildroot and BusyBox are Copyright (c) Erik Andersen <andersen at codepoet.org>.
-BusyBox is licensed under the GNU General Public License (GPL). A copy of
-this license is available in the file GPL-2,
-http://xm-test.xensource.com/ramdisks/GPL-2, or alongside this file.
-
-uClibc is licensed under the GNU Lesser General Public License (LGPL). A copy
-of this license is available in the file
-http://xm-test.xensource.com/ramdisks/LGPL-2, or alongside this file.
diff --git a/tools/xm-test/ramdisk/README-XenSource-initrd-1.1-img b/tools/xm-test/ramdisk/README-XenSource-initrd-1.1-img
deleted file mode 100644
index 526c601..0000000
--- a/tools/xm-test/ramdisk/README-XenSource-initrd-1.1-img
+++ /dev/null
@@ -1,45 +0,0 @@
-XenSource xm-test 1.1 initrds
-=============================
-
-http://xm-test.xensource.com/ramdisks/initrd-1.1-i386.img and
-http://xm-test.xensource.com/ramdisks/initrd-1.1-powerpc.img are initrds
-suitable for use with Xen's xm-test regression testing suite. They has been
-built and provided by XenSource, for the convenience of Xen users. xm-test
-initrds may be mixed across minor xm-test versions, but not across major
-versions; this initrd is suitable for all 1.1.x versions of xm-test (as
-shipped with Xen 3.0.4 and the unstable tree leading up to that release).
-
-In order to use one of these initrds, run "./autogen; ./configure; make
-existing" inside the xm-test directory, and the appropriate initrd for your
-architecture will be downloaded automatically. Alternatively, if you have
-already downloaded that file, place it into the xm-test/ramdisk directory and
-run the same command. In either case, runtest.sh can then be used as normal.
-See xm-test/README for more details.
-
-These initrds were built using the infrastructure provided by xm-test. Each
-is a full guest operating system and filesystem, and as such includes a large
-number of pieces of software. The source code for the majority of these are
-included in full inside the file
-http://xm-test.xensource.com/ramdisks/<INITRD>-buildroot.tar.bz2, where
-<INITRD> is either initrd-1.1-i386 or initrd-1.1-powerpc as appropriate, or
-alongside this file. Copyright statements and licences are contained therein.
-The remaining source code is included in the Xen distribution, at
-http://www.xensource.com/xen/downloads/archives.html. The configurations used
-for BusyBox, uClibc, and Buildroot are available as
-http://xm-test.xensource.com/ramdisks/<INITRD>-busybox-config,
-http://xm-test.xensource.com/ramdisks/<INITRD>-uClibc-config, and
-http://xm-test.xensource.com/ramdisks/<INITRD>-buildroot-config respectively,
-or alongside this file.
-
-XenSource and the Xen contributors are grateful to the authors of these
-software packages for their contributions to free and open-source software.
-
-
-Buildroot and BusyBox are Copyright (c) Erik Andersen <andersen at codepoet.org>.
-BusyBox is licensed under the GNU General Public License (GPL). A copy of
-this license is available in the file GPL-2,
-http://xm-test.xensource.com/ramdisks/GPL-2, or alongside this file.
-
-uClibc is licensed under the GNU Lesser General Public License (LGPL). A copy
-of this license is available in the file
-http://xm-test.xensource.com/ramdisks/LGPL-2, or alongside this file.
diff --git a/tools/xm-test/ramdisk/bin/create_disk_image b/tools/xm-test/ramdisk/bin/create_disk_image
deleted file mode 100644
index 6b1bfde..0000000
--- a/tools/xm-test/ramdisk/bin/create_disk_image
+++ /dev/null
@@ -1,384 +0,0 @@
-#!/bin/bash
-###############################################################################
-##
-## Copyright (C) International Business Machines Corp., 2005
-## Author(s): Daniel Stekloff <dsteklof at us.ibm.com>
-##
-## This program is free software; you can redistribute it and/or modify
-## it under the terms of the GNU General Public License as published by
-## the Free Software Foundation; under version 2 of the License.
-##
-## This program is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-## GNU General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with this program; if not, write to the Free Software
-## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-##
-###############################################################################
-function cleanup()
-{
- umount "$MNT"
- rm -Rf "$MNT";
- if [ "$LOOPD" ]; then
- losetup -d $LOOPD
- fi
- if [ "$LOOPP" ]; then
- losetup -d $LOOPP
- fi
- if [ -e "$IMAGE" ]; then
- rm -f "$IMAGE"
- fi
- if [ -e "$LCONF" ]; then
- rm -f "$LCONF"
- fi
-}
-
-function die()
-{
- cleanup
- echo "$@"
- exit 1
-}
-
-function usage()
-{
- cat << EOU
-Command creates a hvm guest disk image for xm-test.
-
-Usage: $0 [OPTIONS]
-
-OPTIONS:
- -d|--dvrdir <name> Directory where to find network driver
- to use for disk image.
- -i|--image <name> Image name to create.
- -k|--kernel <name> Kernel name to use for disk image.
- -n|--netdrv <name> Network driver name to use for disk image.
- -r|--rootfs <image> Rootfs image to use for disk image.
-
-This script defaults to using the 8139too.ko driver for network tests.
-If a dvrdir isn't added on the command-line, it will look in
-/lib/modules/ directory relating to the supplied kernel. If the
-network driver is built into the kernel, you can specify the key word
-"builtin" with the -d option and the script will continue.
-
-Note: Many network drivers rely upon mii.ko. This script will look
-for that module in the same location as the network driver, either
-for the kernel or the location used with the -d option.
-
-EOU
-}
-
-function check_dependencies()
-{
- which lilo > /dev/null 2>&1
- if [ $? -ne 0 ]; then
- die "$PROGNAME requires lilo version 22.7+ to be installed."
- fi
- local pass="$( lilo -V | cut -f3 -d " " | awk -F "." '
- {
- if ($1 >= 22 && $2 >= 7)
- print "true"
- else
- print "false"
- }')"
- if [ $pass = "false" ]; then
- die "$PROGNAME requires lilo version 22.7+ to be installed."
- fi
-}
-
-function initialize_globals()
-{
- PROGNAME="create_disk_image"
- IMAGE="disk.img"
- KERNEL=""
- DRVDIR=""
- NETDRV="8139too.ko"
- LCONF="lilo.conf"
- LOOPD="" # Loop device for entire disk image
- LOOPP="" # Loop device for ext partition
- ROOTFS=""
- MNT="/tmp/$PROGNAME-mnt"
- SIZE=8192
- SECTORS=32
- HEADS=8
- CYLINDERS=$(($SIZE/$SECTORS/$HEADS*2))
- BSIZE=$(($SIZE-$SECTORS))
- OFFSET=$(($SECTORS*512))
-}
-
-function get_options()
-{
- while [ $# -gt 0 ]; do
- case $1 in
- -d|--drvdir)
- shift
- DRVDIR=${1}
- shift
- ;;
- -i|--image)
- shift
- IMAGE=${1}
- shift
- ;;
- -k|--kernel)
- shift
- KERNEL=${1}
- shift
- ;;
- -n|--netdrv)
- shift
- NETDRV=${1}
- shift
- ;;
- -r|--rootfs)
- shift
- ROOTFS=${1}
- shift
- ;;
- *)
- usage
- exit 1
- ;;
- esac
- done
-}
-
-function get_loopd()
-{
- local loop
-
- for i in `seq 0 7`; do
- losetup /dev/loop$i > /dev/null 2>&1
- if [ $? -ne 0 ]; then
- # found one
- echo $i
- return 0
- fi
- done
- die "No free loopback devices."
-}
-
-function losetup_image()
-{
- local loop=$1
- shift
-
- # If offset, then associate with it
- if [ $# -eq 1 ]; then
- losetup -o $1 $loop $IMAGE
- else
- losetup $loop $IMAGE
- fi
-
- if [ $? -ne 0 ]; then
- die "Failed to losetup $IMAGE to $loop."
- fi
-
- echo "Associated $IMAGE with $loop"
-}
-
-function create_disk_image()
-{
- dd bs=1024 count=$SIZE of=$IMAGE if=/dev/zero
-
- fdisk -b 512 -C $CYLINDERS -H $HEADS -S $SECTORS "$IMAGE" > /dev/null 2>&1 << EOF
-n
-p
-1
-1
-
-a
-1
-w
-EOF
-}
-
-function makefs_image()
-{
- mke2fs -N 24 -b 1024 $LOOPP $BSIZE
-
- if [ $? -ne 0 ]; then
- die "mke2fs $LOOPP failed."
- fi
-}
-
-function dd_rootfs_to_image()
-{
- if [ ! "$ROOTFS" ]; then
- die "Must specify rootfs image to use."
- fi
-
- dd if="$ROOTFS" of="$LOOPP" > /dev/null 2>&1
- if [ $? -ne 0 ]; then
- die "Failed to dd $ROOTFS to $LOOPP."
- fi
-
- # Resize fs to use full partition
- e2fsck -f $LOOPP
- resize2fs $LOOPP
- if [ $? -ne 0 ]; then
- die "Failed to resize rootfs on $LOOPP."
- fi
-}
-
-function get_kernel()
-{
- # look in /boot for an existing kernel
- local -a kernels=( `ls /boot | grep vmlinuz` )
- local k
-
- for k in ${kernels[@]}; do
- case "$k" in
- *xen*)
- continue
- ;;
- *)
- KERNEL="/boot/$k"
- echo "Using kernel $KERNEL"
- break
- ;;
- esac
- done
-}
-
-function copy_kernel_to_image()
-{
- if [ ! "$KERNEL" ]; then
- get_kernel || die "Couldn't find a kernel to use."
- fi
-
- mkdir "$MNT/boot"
-
- cp "$KERNEL" "$MNT/boot"
-}
-
-function copy_netdriver_to_image()
-{
- local kernel=`basename $KERNEL`
- local kversion=$( echo $kernel | sed 's/^vmlinuz-//' )
- local fdir="/lib/modules/$kversion/kernel/drivers/net"
-
- mkdir "$MNT/lib/modules"
- if [ -e "$DRVDIR" ]; then
- if [ -e "$DRVDIR/$NETDRV" ]; then
- cp $DRVDIR/mii.ko $MNT/lib/modules
- cp $DRVDIR/$NETDRV $MNT/lib/modules
- else
- die "Failed to find $NETDRV at $DRVDIR."
- fi
- elif [ -e "$fdir/$NETDRV" ]; then
- cp $fdir/mii.ko $MNT/lib/modules
- cp $fdir/$NETDRV $MNT/lib/modules
- else
- die "Xm-test requires at minimum the 8139too.ko driver to run."
- fi
-
- # Make sure that modules will be installed
- if [ -e "$MNT/etc/init.d/rcS" ]; then
- echo "insmod /lib/modules/mii.ko" >> $MNT/etc/init.d/rcS
- echo "insmod /lib/modules/$NETDRV" >> $MNT/etc/init.d/rcS
- else
- die "Failed to add insmod command to rcS file on image."
- fi
-}
-
-function lilo_image()
-{
- local kernel=`basename $KERNEL`
-
- (
- cat <<EOC
-boot=$LOOPD
-delay=10
-geometric
-map=$MNT/boot/map
-disk=$LOOPD
- bios=0x80
- sectors=$SECTORS
- heads=$HEADS
- cylinders=$CYLINDERS
- partition=$LOOPP
- start=$SECTORS
-image=$MNT/boot/$kernel
- append="root=0301 console=tty0 console=ttyS0"
-# append="root=0301"
- label=Linux
- read-only
-EOC
- ) > "/$MNT/boot/$LCONF"
-}
-
-function install_lilo()
-{
- lilo -C "$MNT/boot/$LCONF"
- if [ $? -ne 0 ]; then
- die "Failed to install $MNT/boot/$LCONF."
- fi
-}
-
-function add_getty_to_inittab()
-{
- local itab=$MNT/etc/inittab
-
- if [ -e "$itab" ]; then
- echo "# Start getty on serial line" >> $itab
- echo "S0:12345:respawn:/sbin/getty ttyS0" >> $itab
- fi
-}
-
-
-# Main starts here
-initialize_globals
-check_dependencies
-
-get_options "$@"
-
-create_disk_image
-
-# Get the first free loop device
-ldev=$(get_loopd)
-LOOPD="/dev/loop$ldev"
-losetup_image $LOOPD
-
-# Now associate where the partition will go
-ldev=$(get_loopd)
-LOOPP="/dev/loop$ldev"
-losetup_image $LOOPP $OFFSET
-
-makefs_image
-
-dd_rootfs_to_image
-
-if [ -e "$MNT" ]; then
- rm -Rf "$MNT"
-fi
-
-mkdir "$MNT";
-if [ $? -ne 0 ]; then
- die "Failed to create temporary mount point $MNT."
-fi
-
-mount "$LOOPP" "$MNT";
-if [ $? -ne 0 ]; then
- die "Failed to mount $LOOPP on $MNT."
-fi
-
-copy_kernel_to_image
-if [ ! "$DRVDIR" = "builtin" ]; then
- copy_netdriver_to_image
-fi
-#add_getty_to_inittab
-
-lilo_image
-install_lilo
-
-umount "$MNT"
-rm -Rf "$MNT";
-
-losetup -d $LOOPD
-losetup -d $LOOPP
-
-exit 0
diff --git a/tools/xm-test/ramdisk/configs/buildroot-i386 b/tools/xm-test/ramdisk/configs/buildroot-i386
deleted file mode 100644
index 284f4cf..0000000
--- a/tools/xm-test/ramdisk/configs/buildroot-i386
+++ /dev/null
@@ -1,346 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-BR2_HAVE_DOT_CONFIG=y
-# BR2_alpha is not set
-# BR2_arm is not set
-# BR2_armeb is not set
-# BR2_cris is not set
-BR2_i386=y
-# BR2_m68k is not set
-# BR2_mips is not set
-# BR2_mipsel is not set
-# BR2_nios2 is not set
-# BR2_powerpc is not set
-# BR2_sh is not set
-# BR2_sh64 is not set
-# BR2_sparc is not set
-# BR2_x86_64 is not set
-BR2_x86_i386=y
-# BR2_x86_i486 is not set
-# BR2_x86_i586 is not set
-# BR2_x86_i686 is not set
-BR2_ARCH="i386"
-BR2_ENDIAN="LITTLE"
-
-#
-# Build options
-#
-BR2_WGET="wget --passive-ftp"
-BR2_SVN="svn co"
-BR2_ZCAT="zcat"
-BR2_TAR_OPTIONS=""
-BR2_DL_DIR="$(BASE_DIR)/dl"
-BR2_SOURCEFORGE_MIRROR="easynews"
-BR2_STAGING_DIR="$(BUILD_DIR)/staging_dir"
-BR2_TOPDIR_PREFIX=""
-BR2_TOPDIR_SUFFIX=""
-BR2_GNU_BUILD_SUFFIX="pc-linux-gnu"
-BR2_GNU_TARGET_SUFFIX="linux-uclibc"
-BR2_JLEVEL=1
-
-#
-# Toolchain Options
-#
-
-#
-# Kernel Header Options
-#
-# BR2_KERNEL_HEADERS_2_4_25 is not set
-# BR2_KERNEL_HEADERS_2_4_27 is not set
-# BR2_KERNEL_HEADERS_2_4_29 is not set
-# BR2_KERNEL_HEADERS_2_4_31 is not set
-# BR2_KERNEL_HEADERS_2_6_9 is not set
-# BR2_KERNEL_HEADERS_2_6_11 is not set
-BR2_KERNEL_HEADERS_2_6_12=y
-# BR2_KERNEL_HEADERS_2_6_18 is not set
-BR2_DEFAULT_KERNEL_HEADERS="2.6.12"
-
-#
-# uClibc Options
-#
-# BR2_UCLIBC_VERSION_SNAPSHOT is not set
-# BR2_ENABLE_LOCALE is not set
-# BR2_PTHREADS_NONE is not set
-# BR2_PTHREADS is not set
-BR2_PTHREADS_OLD=y
-# BR2_PTHREADS_NATIVE is not set
-
-#
-# Binutils Options
-#
-# BR2_BINUTILS_VERSION_2_14_90_0_8 is not set
-# BR2_BINUTILS_VERSION_2_15 is not set
-# BR2_BINUTILS_VERSION_2_15_94_0_2_2 is not set
-# BR2_BINUTILS_VERSION_2_16_1 is not set
-# BR2_BINUTILS_VERSION_2_16_90_0_3 is not set
-# BR2_BINUTILS_VERSION_2_16_91_0_5 is not set
-# BR2_BINUTILS_VERSION_2_16_91_0_6 is not set
-BR2_BINUTILS_VERSION_2_16_91_0_7=y
-# BR2_BINUTILS_VERSION_2_17 is not set
-# BR2_BINUTILS_VERSION_2_17_50_0_2 is not set
-# BR2_BINUTILS_VERSION_2_17_50_0_3 is not set
-# BR2_BINUTILS_VERSION_2_17_50_0_4 is not set
-# BR2_BINUTILS_VERSION_2_17_50_0_5 is not set
-# BR2_BINUTILS_VERSION_2_17_50_0_6 is not set
-BR2_BINUTILS_VERSION="2.16.91.0.7"
-BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
-
-#
-# Gcc Options
-#
-# BR2_GCC_VERSION_3_3_5 is not set
-# BR2_GCC_VERSION_3_3_6 is not set
-# BR2_GCC_VERSION_3_4_2 is not set
-# BR2_GCC_VERSION_3_4_3 is not set
-# BR2_GCC_VERSION_3_4_4 is not set
-# BR2_GCC_VERSION_3_4_5 is not set
-BR2_GCC_VERSION_3_4_6=y
-# BR2_GCC_VERSION_4_0_0 is not set
-# BR2_GCC_VERSION_4_0_1 is not set
-# BR2_GCC_VERSION_4_0_2 is not set
-# BR2_GCC_VERSION_4_0_3 is not set
-# BR2_GCC_VERSION_4_1_0 is not set
-# BR2_GCC_VERSION_4_1_1 is not set
-# BR2_GCC_VERSION_4_2 is not set
-# BR2_GCC_IS_SNAP is not set
-BR2_GCC_VERSION="3.4.6"
-# BR2_GCC_USE_SJLJ_EXCEPTIONS is not set
-BR2_EXTRA_GCC_CONFIG_OPTIONS=""
-# BR2_INSTALL_LIBSTDCPP is not set
-# BR2_INSTALL_OBJC is not set
-# BR2_GCC_SHARED_LIBGCC is not set
-
-#
-# Ccache Options
-#
-BR2_CCACHE=y
-
-#
-# Gdb Options
-#
-# BR2_PACKAGE_GDB is not set
-# BR2_PACKAGE_GDB_SERVER is not set
-# BR2_PACKAGE_GDB_HOST is not set
-
-#
-# elf2flt
-#
-# BR2_ELF2FLT is not set
-# BR2_MKLIBS is not set
-
-#
-# Common Toolchain Options
-#
-# BR2_PACKAGE_SSTRIP_TARGET is not set
-# BR2_PACKAGE_SSTRIP_HOST is not set
-BR2_ENABLE_MULTILIB=y
-BR2_LARGEFILE=y
-BR2_TARGET_OPTIMIZATION="-Os -pipe"
-BR2_CROSS_TOOLCHAIN_TARGET_UTILS=y
-
-#
-# Package Selection for the target
-#
-
-#
-# The default minimal system
-#
-BR2_PACKAGE_BUSYBOX=y
-# BR2_PACKAGE_BUSYBOX_SNAPSHOT is not set
-BR2_PACKAGE_BUSYBOX_INSTALL_SYMLINKS=y
-BR2_PACKAGE_BUSYBOX_CONFIG="package/busybox/busybox.config"
-
-#
-# The minimum needed to build a uClibc development system
-#
-# BR2_PACKAGE_BASH is not set
-# BR2_PACKAGE_BZIP2 is not set
-# BR2_PACKAGE_COREUTILS is not set
-# BR2_PACKAGE_DIFFUTILS is not set
-# BR2_PACKAGE_ED is not set
-# BR2_PACKAGE_FINDUTILS is not set
-# BR2_PACKAGE_FLEX is not set
-# BR2_PACKAGE_GAWK is not set
-# BR2_PACKAGE_GCC_TARGET is not set
-# BR2_PACKAGE_CCACHE_TARGET is not set
-# BR2_PACKAGE_GREP is not set
-# BR2_PACKAGE_MAKE is not set
-# BR2_PACKAGE_PATCH is not set
-# BR2_PACKAGE_SED is not set
-# BR2_PACKAGE_TAR is not set
-
-#
-# Other stuff
-#
-# BR2_PACKAGE_ACPID is not set
-# BR2_PACKAGE_ASTERISK is not set
-# BR2_PACKAGE_AT is not set
-# BR2_PACKAGE_AUTOCONF is not set
-# BR2_PACKAGE_AUTOMAKE is not set
-# BR2_PACKAGE_BERKELEYDB is not set
-# BR2_PACKAGE_BIND is not set
-# BR2_PACKAGE_BISON is not set
-# BR2_PACKAGE_BOA is not set
-# BR2_PACKAGE_BRIDGE is not set
-# BR2_PACKAGE_CUSTOMIZE is not set
-# BR2_PACKAGE_ISC_DHCP is not set
-# BR2_PACKAGE_DIALOG is not set
-# BR2_PACKAGE_DIRECTFB is not set
-# BR2_PACKAGE_DISTCC is not set
-# BR2_PACKAGE_DM is not set
-# BR2_PACKAGE_DMRAID is not set
-# BR2_PACKAGE_DNSMASQ is not set
-# BR2_PACKAGE_DROPBEAR is not set
-# BR2_PACKAGE_ETHTOOL is not set
-# BR2_PACKAGE_EXPAT is not set
-# BR2_PACKAGE_E2FSPROGS is not set
-# BR2_PACKAGE_FAKEROOT is not set
-# BR2_PACKAGE_FILE is not set
-# BR2_PACKAGE_FREETYPE is not set
-# BR2_PACKAGE_GETTEXT is not set
-# BR2_PACKAGE_LIBINTL is not set
-# BR2_PACKAGE_GZIP is not set
-# BR2_PACKAGE_HASERL is not set
-# BR2_PACKAGE_HDPARM is not set
-# BR2_PACKAGE_HOSTAP is not set
-# BR2_PACKAGE_HOTPLUG is not set
-# BR2_PACKAGE_IOSTAT is not set
-# BR2_PACKAGE_IPROUTE2 is not set
-# BR2_PACKAGE_IPSEC_TOOLS is not set
-# BR2_PACKAGE_IPTABLES is not set
-# BR2_PACKAGE_JPEG is not set
-# BR2_PACKAGE_LESS is not set
-# BR2_PACKAGE_LIBCGI is not set
-# BR2_PACKAGE_LIBCGICC is not set
-# BR2_PACKAGE_LIBELF is not set
-# BR2_PACKAGE_LIBFLOAT is not set
-# BR2_PACKAGE_LIBGLIB12 is not set
-# BR2_PACKAGE_LIBMAD is not set
-# BR2_PACKAGE_LIBPCAP is not set
-# BR2_PACKAGE_LIBPNG is not set
-# BR2_PACKAGE_LIBSYSFS is not set
-# BR2_PACKAGE_LIBTOOL is not set
-# BR2_PACKAGE_LIBUSB is not set
-# BR2_PACKAGE_LIGHTTPD is not set
-# BR2_PACKAGE_LINKS is not set
-# BR2_PACKAGE_LRZSZ is not set
-# BR2_PACKAGE_LSOF is not set
-# BR2_PACKAGE_LTP-TESTSUITE is not set
-# BR2_PACKAGE_LTT is not set
-# BR2_PACKAGE_LVM2 is not set
-# BR2_PACKAGE_LZO is not set
-# BR2_PACKAGE_LZMA is not set
-# BR2_PACKAGE_M4 is not set
-# BR2_PACKAGE_MDADM is not set
-# BR2_PACKAGE_MEMTESTER is not set
-# BR2_PACKAGE_MICROCOM is not set
-# BR2_PACKAGE_MICROPERL is not set
-# BR2_PACKAGE_MICROWIN is not set
-# BR2_PACKAGE_MKDOSFS is not set
-# BR2_PACKAGE_MODULE_INIT_TOOLS is not set
-# BR2_PACKAGE_MODUTILS is not set
-# BR2_PACKAGE_MPG123 is not set
-# BR2_PACKAGE_MROUTED is not set
-# BR2_PACKAGE_MTD is not set
-# BR2_PACKAGE_NANO is not set
-# BR2_PACKAGE_NBD is not set
-# BR2_PACKAGE_NCURSES is not set
-# BR2_PACKAGE_NETKITBASE is not set
-# BR2_PACKAGE_NETKITTELNET is not set
-# BR2_PACKAGE_NETSNMP is not set
-# BR2_PACKAGE_NEWT is not set
-# BR2_PACKAGE_NTP is not set
-# BR2_PACKAGE_OPENNTPD is not set
-# BR2_PACKAGE_OPENSSH is not set
-# BR2_PACKAGE_OPENSSL is not set
-# BR2_PACKAGE_OPENVPN is not set
-# BR2_PACKAGE_PCIUTILS is not set
-# BR2_PACKAGE_PKGCONFIG is not set
-# BR2_PACKAGE_PORTAGE is not set
-# BR2_PACKAGE_PORTMAP is not set
-# BR2_PACKAGE_PPPD is not set
-# BR2_PACKAGE_PROCPS is not set
-# BR2_PACKAGE_PSMISC is not set
-# BR2_PACKAGE_PYTHON is not set
-# BR2_PACKAGE_QTE is not set
-BR2_QTE_TMAKE_VERSION="1.13"
-# BR2_PACKAGE_RAIDTOOLS is not set
-# BR2_READLINE is not set
-# BR2_PACKAGE_RSYNC is not set
-# BR2_PACKAGE_RUBY is not set
-# BR2_PACKAGE_RXVT is not set
-# BR2_PACKAGE_SDL is not set
-# BR2_PACKAGE_SFDISK is not set
-# BR2_PACKAGE_SLANG is not set
-# BR2_PACKAGE_SMARTMONTOOLS is not set
-# BR2_PACKAGE_SOCAT is not set
-# BR2_PACKAGE_SQLITE is not set
-# BR2_PACKAGE_STRACE is not set
-# BR2_PACKAGE_SUDO is not set
-# BR2_PACKAGE_SYSKLOGD is not set
-# BR2_PACKAGE_SYSVINIT is not set
-# BR2_PACKAGE_TCL is not set
-# BR2_PACKAGE_TCPDUMP is not set
-# BR2_PACKAGE_TFTPD is not set
-# BR2_PACKAGE_THTTPD is not set
-# BR2_PACKAGE_TINYLOGIN is not set
-# BR2_PACKAGE_TINYX is not set
-# BR2_PACKAGE_TN5250 is not set
-# BR2_PACKAGE_TTCP is not set
-# BR2_PACKAGE_UDEV is not set
-# BR2_PACKAGE_UDHCP is not set
-# BR2_PACKAGE_UEMACS is not set
-# BR2_PACKAGE_USBUTILS is not set
-# BR2_PACKAGE_UTIL-LINUX is not set
-# BR2_PACKAGE_VALGRIND is not set
-# BR2_PACKAGE_VTUN is not set
-# BR2_PACKAGE_WGET is not set
-# BR2_PACKAGE_WHICH is not set
-# BR2_PACKAGE_WIPE is not set
-# BR2_PACKAGE_WIRELESS_TOOLS is not set
-# BR2_PACKAGE_XFSPROGS is not set
-# BR2_PACKAGE_ZLIB is not set
-BR2_PACKAGE_HPING=y
-
-#
-# Target Options
-#
-
-#
-# filesystem for target device
-#
-# BR2_TARGET_ROOTFS_CRAMFS is not set
-# BR2_TARGET_ROOTFS_CLOOP is not set
-BR2_TARGET_ROOTFS_EXT2=y
-BR2_TARGET_ROOTFS_EXT2_BLOCKS=0
-BR2_TARGET_ROOTFS_EXT2_INODES=0
-BR2_TARGET_ROOTFS_EXT2_RESBLKS=0
-BR2_TARGET_ROOTFS_EXT2_SQUASH=y
-BR2_TARGET_ROOTFS_EXT2_OUTPUT="$(IMAGE).ext2"
-# BR2_TARGET_ROOTFS_EXT2_GZ is not set
-BR2_TARGET_ROOTFS_EXT2_COPYTO=""
-# BR2_TARGET_ROOTFS_JFFS2 is not set
-# BR2_TARGET_ROOTFS_SQUASHFS is not set
-# BR2_TARGET_ROOTFS_TAR is not set
-# BR2_TARGET_ROOTFS_ISO9660 is not set
-
-#
-# bootloader for target device
-#
-# BR2_TARGET_GRUB is not set
-# BR2_TARGET_SYSLINUX is not set
-
-#
-# Board Support Options
-#
-# BR2_TARGET_SOEKRIS_NET4521 is not set
-# BR2_TARGET_SOEKRIS_NET4801 is not set
-# BR2_TARGET_VIA_EPIA_MII is not set
-
-#
-# Generic System Support
-#
-# BR2_TARGET_GENERIC_ACCESS_POINT is not set
-# BR2_TARGET_GENERIC_FIREWALL is not set
-# BR2_TARGET_GENERIC_DEV_SYSTEM is not set
diff --git a/tools/xm-test/ramdisk/configs/busybox b/tools/xm-test/ramdisk/configs/busybox
deleted file mode 100644
index 480d8f4..0000000
--- a/tools/xm-test/ramdisk/configs/busybox
+++ /dev/null
@@ -1,465 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-HAVE_DOT_CONFIG=y
-
-#
-# General Configuration
-#
-# CONFIG_FEATURE_BUFFERS_USE_MALLOC is not set
-CONFIG_FEATURE_BUFFERS_GO_ON_STACK=y
-# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
-CONFIG_FEATURE_VERBOSE_USAGE=y
-# CONFIG_FEATURE_INSTALLER is not set
-# CONFIG_LOCALE_SUPPORT is not set
-# CONFIG_FEATURE_DEVFS is not set
-CONFIG_FEATURE_DEVPTS=y
-# CONFIG_FEATURE_CLEAN_UP is not set
-CONFIG_FEATURE_SUID=y
-# CONFIG_FEATURE_SUID_CONFIG is not set
-# CONFIG_SELINUX is not set
-
-#
-# Build Options
-#
-# CONFIG_STATIC is not set
-CONFIG_LFS=y
-# USING_CROSS_COMPILER is not set
-EXTRA_CFLAGS_OPTIONS=""
-
-#
-# Installation Options
-#
-# CONFIG_INSTALL_NO_USR is not set
-PREFIX="./_install"
-
-#
-# Archival Utilities
-#
-# CONFIG_AR is not set
-CONFIG_BUNZIP2=y
-# CONFIG_CPIO is not set
-# CONFIG_DPKG is not set
-# CONFIG_DPKG_DEB is not set
-CONFIG_GUNZIP=y
-# CONFIG_FEATURE_GUNZIP_UNCOMPRESS is not set
-CONFIG_GZIP=y
-# CONFIG_RPM2CPIO is not set
-# CONFIG_RPM is not set
-CONFIG_TAR=y
-CONFIG_FEATURE_TAR_CREATE=y
-CONFIG_FEATURE_TAR_BZIP2=y
-# CONFIG_FEATURE_TAR_FROM is not set
-CONFIG_FEATURE_TAR_GZIP=y
-# CONFIG_FEATURE_TAR_COMPRESS is not set
-# CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY is not set
-CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y
-# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set
-# CONFIG_UNCOMPRESS is not set
-CONFIG_UNZIP=y
-
-#
-# Common options for cpio and tar
-#
-# CONFIG_FEATURE_UNARCHIVE_TAPE is not set
-
-#
-# Coreutils
-#
-CONFIG_BASENAME=y
-# CONFIG_CAL is not set
-CONFIG_CAT=y
-CONFIG_CHGRP=y
-CONFIG_CHMOD=y
-CONFIG_CHOWN=y
-CONFIG_CHROOT=y
-CONFIG_CMP=y
-CONFIG_CP=y
-CONFIG_CUT=y
-CONFIG_DATE=y
-CONFIG_FEATURE_DATE_ISOFMT=y
-CONFIG_DD=y
-CONFIG_DF=y
-CONFIG_DIRNAME=y
-CONFIG_DOS2UNIX=y
-CONFIG_UNIX2DOS=y
-CONFIG_DU=y
-CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K=y
-CONFIG_ECHO=y
-CONFIG_FEATURE_FANCY_ECHO=y
-CONFIG_ENV=y
-CONFIG_EXPR=y
-CONFIG_FALSE=y
-# CONFIG_FOLD is not set
-CONFIG_HEAD=y
-# CONFIG_FEATURE_FANCY_HEAD is not set
-CONFIG_HOSTID=y
-CONFIG_ID=y
-CONFIG_INSTALL=y
-# CONFIG_LENGTH is not set
-CONFIG_LN=y
-CONFIG_LOGNAME=y
-CONFIG_LS=y
-CONFIG_FEATURE_LS_FILETYPES=y
-CONFIG_FEATURE_LS_FOLLOWLINKS=y
-CONFIG_FEATURE_LS_RECURSIVE=y
-CONFIG_FEATURE_LS_SORTFILES=y
-CONFIG_FEATURE_LS_TIMESTAMPS=y
-CONFIG_FEATURE_LS_USERNAME=y
-CONFIG_FEATURE_LS_COLOR=n
-CONFIG_MD5SUM=y
-CONFIG_MKDIR=y
-# CONFIG_MKFIFO is not set
-CONFIG_MKNOD=y
-CONFIG_MV=y
-# CONFIG_OD is not set
-# CONFIG_PRINTF is not set
-CONFIG_PWD=y
-# CONFIG_REALPATH is not set
-CONFIG_RM=y
-CONFIG_RMDIR=y
-# CONFIG_SEQ is not set
-CONFIG_SHA1SUM=y
-CONFIG_SLEEP=y
-# CONFIG_FEATURE_FANCY_SLEEP is not set
-CONFIG_SORT=n
-CONFIG_STTY=y
-CONFIG_SYNC=y
-CONFIG_TAIL=y
-CONFIG_FEATURE_FANCY_TAIL=n
-CONFIG_TEE=y
-CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
-CONFIG_TEST=y
-
-#
-# test (forced enabled for use with shell)
-#
-CONFIG_FEATURE_TEST_64=y
-CONFIG_TOUCH=y
-# CONFIG_TR is not set
-CONFIG_TRUE=y
-CONFIG_TTY=y
-CONFIG_UNAME=y
-CONFIG_UNIQ=y
-CONFIG_USLEEP=y
-CONFIG_UUDECODE=n
-CONFIG_UUENCODE=n
-# CONFIG_WATCH is not set
-CONFIG_WC=y
-# CONFIG_WHO is not set
-CONFIG_WHOAMI=y
-CONFIG_YES=y
-
-#
-# Common options for cp and mv
-#
-CONFIG_FEATURE_PRESERVE_HARDLINKS=y
-
-#
-# Common options for ls and more
-#
-CONFIG_FEATURE_AUTOWIDTH=y
-
-#
-# Common options for df, du, ls
-#
-CONFIG_FEATURE_HUMAN_READABLE=y
-
-#
-# Common options for md5sum, sha1sum
-#
-CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y
-
-#
-# Console Utilities
-#
-CONFIG_CHVT=n
-CONFIG_CLEAR=y
-CONFIG_DEALLOCVT=y
-# CONFIG_DUMPKMAP is not set
-# CONFIG_LOADFONT is not set
-# CONFIG_LOADKMAP is not set
-CONFIG_OPENVT=y
-CONFIG_RESET=y
-# CONFIG_SETKEYCODES is not set
-
-#
-# Debian Utilities
-#
-CONFIG_MKTEMP=y
-# CONFIG_PIPE_PROGRESS is not set
-CONFIG_READLINK=y
-CONFIG_RUN_PARTS=n
-CONFIG_START_STOP_DAEMON=n
-CONFIG_WHICH=n
-
-#
-# Editors
-#
-# CONFIG_AWK is not set
-# CONFIG_PATCH is not set
-CONFIG_SED=y
-CONFIG_VI=y
-CONFIG_FEATURE_VI_COLON=y
-CONFIG_FEATURE_VI_YANKMARK=y
-CONFIG_FEATURE_VI_SEARCH=y
-CONFIG_FEATURE_VI_USE_SIGNALS=y
-CONFIG_FEATURE_VI_DOT_CMD=y
-CONFIG_FEATURE_VI_READONLY=y
-CONFIG_FEATURE_VI_SETOPTS=y
-CONFIG_FEATURE_VI_SET=y
-CONFIG_FEATURE_VI_WIN_RESIZE=y
-CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y
-
-#
-# Finding Utilities
-#
-CONFIG_FIND=y
-CONFIG_FEATURE_FIND_MTIME=y
-CONFIG_FEATURE_FIND_PERM=y
-CONFIG_FEATURE_FIND_TYPE=y
-CONFIG_FEATURE_FIND_XDEV=y
-# CONFIG_FEATURE_FIND_NEWER is not set
-# CONFIG_FEATURE_FIND_INUM is not set
-CONFIG_GREP=y
-CONFIG_FEATURE_GREP_EGREP_ALIAS=y
-CONFIG_FEATURE_GREP_FGREP_ALIAS=y
-CONFIG_FEATURE_GREP_CONTEXT=y
-CONFIG_XARGS=y
-# CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION is not set
-CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y
-CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y
-CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y
-
-#
-# Init Utilities
-#
-CONFIG_INIT=y
-CONFIG_FEATURE_USE_INITTAB=y
-CONFIG_FEATURE_INITRD=y
-# CONFIG_FEATURE_INIT_COREDUMPS is not set
-CONFIG_FEATURE_INIT_SWAPON=y
-CONFIG_FEATURE_EXTRA_QUIET=y
-CONFIG_HALT=y
-CONFIG_POWEROFF=y
-CONFIG_REBOOT=y
-# CONFIG_MESG is not set
-
-#
-# Login/Password Management Utilities
-#
-# CONFIG_USE_BB_PWD_GRP is not set
-CONFIG_ADDGROUP=y
-CONFIG_DELGROUP=y
-CONFIG_ADDUSER=y
-CONFIG_DELUSER=y
-CONFIG_GETTY=y
-# CONFIG_FEATURE_UTMP is not set
-# CONFIG_FEATURE_WTMP is not set
-CONFIG_LOGIN=y
-CONFIG_FEATURE_SECURETTY=y
-CONFIG_PASSWD=y
-CONFIG_SU=y
-CONFIG_SULOGIN=y
-CONFIG_VLOCK=y
-
-#
-# Common options for adduser, deluser, login, su
-#
-CONFIG_FEATURE_SHADOWPASSWDS=y
-
-#
-# Miscellaneous Utilities
-#
-# CONFIG_ADJTIMEX is not set
-# CONFIG_CROND is not set
-# CONFIG_CRONTAB is not set
-CONFIG_DC=y
-# CONFIG_DEVFSD is not set
-# CONFIG_LAST is not set
-# CONFIG_HDPARM is not set
-# CONFIG_MAKEDEVS is not set
-CONFIG_MT=y
-# CONFIG_RX is not set
-CONFIG_STRINGS=y
-CONFIG_TIME=y
-# CONFIG_WATCHDOG is not set
-
-#
-# Linux Module Utilities
-#
-CONFIG_INSMOD=y
-CONFIG_FEATURE_2_4_MODULES=y
-CONFIG_FEATURE_2_6_MODULES=y
-# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
-# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
-# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
-# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
-CONFIG_LSMOD=y
-CONFIG_FEATURE_QUERY_MODULE_INTERFACE=y
-CONFIG_MODPROBE=y
-CONFIG_RMMOD=y
-CONFIG_FEATURE_CHECK_TAINTED_MODULE=y
-
-#
-# Networking Utilities
-#
-# CONFIG_FEATURE_IPV6 is not set
-# CONFIG_ARPING is not set
-# CONFIG_FTPGET is not set
-# CONFIG_FTPPUT is not set
-CONFIG_HOSTNAME=y
-# CONFIG_HTTPD is not set
-CONFIG_IFCONFIG=y
-CONFIG_FEATURE_IFCONFIG_STATUS=y
-# CONFIG_FEATURE_IFCONFIG_SLIP is not set
-# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set
-# CONFIG_FEATURE_IFCONFIG_HW is not set
-# CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set
-CONFIG_IFUPDOWN=y
-# CONFIG_FEATURE_IFUPDOWN_IP is not set
-CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN=y
-CONFIG_FEATURE_IFUPDOWN_IPV4=y
-# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set
-# CONFIG_FEATURE_IFUPDOWN_IPX is not set
-# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set
-# CONFIG_INETD is not set
-# CONFIG_IP is not set
-# CONFIG_IPCALC is not set
-# CONFIG_IPADDR is not set
-# CONFIG_IPLINK is not set
-# CONFIG_IPROUTE is not set
-# CONFIG_IPTUNNEL is not set
-# CONFIG_NAMEIF is not set
-# CONFIG_NC is not set
-CONFIG_NETSTAT=y
-CONFIG_NSLOOKUP=y
-CONFIG_PING=y
-CONFIG_FEATURE_FANCY_PING=y
-CONFIG_ROUTE=y
-CONFIG_TELNET=y
-CONFIG_FEATURE_TELNET_TTYPE=y
-# CONFIG_FEATURE_TELNET_AUTOLOGIN is not set
-# CONFIG_TELNETD is not set
-# CONFIG_TFTP is not set
-# CONFIG_TRACEROUTE is not set
-# CONFIG_VCONFIG is not set
-CONFIG_WGET=y
-CONFIG_FEATURE_WGET_STATUSBAR=y
-CONFIG_FEATURE_WGET_AUTHENTICATION=y
-# CONFIG_FEATURE_WGET_IP6_LITERAL is not set
-
-#
-# udhcp Server/Client
-#
-CONFIG_UDHCPD=y
-CONFIG_UDHCPC=y
-CONFIG_DUMPLEASES=y
-CONFIG_FEATURE_UDHCP_SYSLOG=y
-# CONFIG_FEATURE_UDHCP_DEBUG is not set
-
-#
-# Process Utilities
-#
-CONFIG_FREE=y
-CONFIG_KILL=y
-CONFIG_KILLALL=y
-CONFIG_PIDOF=y
-CONFIG_PS=y
-# CONFIG_RENICE is not set
-# CONFIG_TOP is not set
-CONFIG_UPTIME=y
-# CONFIG_SYSCTL is not set
-
-#
-# Another Bourne-like Shell
-#
-CONFIG_FEATURE_SH_IS_ASH=y
-# CONFIG_FEATURE_SH_IS_HUSH is not set
-# CONFIG_FEATURE_SH_IS_LASH is not set
-# CONFIG_FEATURE_SH_IS_MSH is not set
-# CONFIG_FEATURE_SH_IS_NONE is not set
-CONFIG_ASH=y
-
-#
-# Ash Shell Options
-#
-CONFIG_ASH_JOB_CONTROL=y
-CONFIG_ASH_ALIAS=y
-CONFIG_ASH_MATH_SUPPORT=y
-CONFIG_ASH_MATH_SUPPORT_64=y
-# CONFIG_ASH_GETOPTS is not set
-# CONFIG_ASH_CMDCMD is not set
-# CONFIG_ASH_MAIL is not set
-CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
-# CONFIG_ASH_RANDOM_SUPPORT is not set
-# CONFIG_HUSH is not set
-# CONFIG_LASH is not set
-# CONFIG_MSH is not set
-
-#
-# Bourne Shell Options
-#
-# CONFIG_FEATURE_SH_EXTRA_QUIET is not set
-# CONFIG_FEATURE_SH_STANDALONE_SHELL is not set
-CONFIG_FEATURE_COMMAND_EDITING=y
-CONFIG_FEATURE_COMMAND_HISTORY=15
-CONFIG_FEATURE_COMMAND_SAVEHISTORY=y
-CONFIG_FEATURE_COMMAND_TAB_COMPLETION=y
-# CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION is not set
-CONFIG_FEATURE_SH_FANCY_PROMPT=y
-
-#
-# System Logging Utilities
-#
-CONFIG_SYSLOGD=y
-CONFIG_FEATURE_ROTATE_LOGFILE=y
-# CONFIG_FEATURE_REMOTE_LOG is not set
-# CONFIG_FEATURE_IPC_SYSLOG is not set
-CONFIG_KLOGD=y
-CONFIG_LOGGER=y
-
-#
-# Linux System Utilities
-#
-CONFIG_DMESG=y
-# CONFIG_FBSET is not set
-# CONFIG_FDFLUSH is not set
-CONFIG_FDFORMAT=y
-CONFIG_FDISK=y
-FDISK_SUPPORT_LARGE_DISKS=y
-CONFIG_FEATURE_FDISK_WRITABLE=y
-# CONFIG_FEATURE_AIX_LABEL is not set
-# CONFIG_FEATURE_SGI_LABEL is not set
-# CONFIG_FEATURE_SUN_LABEL is not set
-# CONFIG_FEATURE_OSF_LABEL is not set
-# CONFIG_FEATURE_FDISK_ADVANCED is not set
-# CONFIG_FREERAMDISK is not set
-# CONFIG_FSCK_MINIX is not set
-# CONFIG_MKFS_MINIX is not set
-CONFIG_GETOPT=y
-CONFIG_HEXDUMP=y
-CONFIG_HWCLOCK=y
-CONFIG_FEATURE_HWCLOCK_LONGOPTIONS=y
-# CONFIG_LOSETUP is not set
-# CONFIG_MKSWAP is not set
-CONFIG_MORE=y
-CONFIG_FEATURE_USE_TERMIOS=y
-CONFIG_PIVOT_ROOT=y
-CONFIG_RDATE=y
-CONFIG_SWAPONOFF=y
-CONFIG_MOUNT=y
-# CONFIG_NFSMOUNT is not set
-CONFIG_UMOUNT=y
-# CONFIG_FEATURE_MOUNT_FORCE is not set
-
-#
-# Common options for mount/umount
-#
-CONFIG_FEATURE_MOUNT_LOOP=y
-# CONFIG_FEATURE_MTAB_SUPPORT is not set
-
-#
-# Debugging Options
-#
-# CONFIG_DEBUG is not set
diff --git a/tools/xm-test/ramdisk/configs/uClibc b/tools/xm-test/ramdisk/configs/uClibc
deleted file mode 100644
index c6b4203..0000000
--- a/tools/xm-test/ramdisk/configs/uClibc
+++ /dev/null
@@ -1,172 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-# TARGET_alpha is not set
-# TARGET_arm is not set
-# TARGET_bfin is not set
-# TARGET_cris is not set
-# TARGET_e1 is not set
-# TARGET_frv is not set
-# TARGET_h8300 is not set
-TARGET_i386=y
-# TARGET_i960 is not set
-# TARGET_m68k is not set
-# TARGET_microblaze is not set
-# TARGET_mips is not set
-# TARGET_nios is not set
-# TARGET_nios2 is not set
-# TARGET_powerpc is not set
-# TARGET_sh is not set
-# TARGET_sh64 is not set
-# TARGET_sparc is not set
-# TARGET_v850 is not set
-# TARGET_x86_64 is not set
-
-#
-# Target Architecture Features and Options
-#
-HAVE_ELF=y
-ARCH_SUPPORTS_LITTLE_ENDIAN=y
-TARGET_ARCH="i386"
-# CONFIG_GENERIC_386 is not set
-# CONFIG_386 is not set
-# CONFIG_486 is not set
-# CONFIG_586 is not set
-# CONFIG_586MMX is not set
-# CONFIG_686 is not set
-# CONFIG_PENTIUMII is not set
-# CONFIG_PENTIUMIII is not set
-CONFIG_PENTIUM4=y
-# CONFIG_K6 is not set
-# CONFIG_K7 is not set
-# CONFIG_ELAN is not set
-# CONFIG_CRUSOE is not set
-# CONFIG_WINCHIPC6 is not set
-# CONFIG_WINCHIP2 is not set
-# CONFIG_CYRIXIII is not set
-# CONFIG_NEHEMIAH is not set
-ARCH_LITTLE_ENDIAN=y
-# ARCH_BIG_ENDIAN is not set
-# ARCH_HAS_NO_MMU is not set
-ARCH_HAS_MMU=y
-UCLIBC_HAS_FLOATS=y
-HAS_FPU=y
-DO_C99_MATH=y
-KERNEL_SOURCE="/tmp/buildroot/toolchain_build_i386/linux"
-C_SYMBOL_PREFIX=""
-HAVE_DOT_CONFIG=y
-
-#
-# General Library Settings
-#
-# HAVE_NO_PIC is not set
-DOPIC=y
-# HAVE_NO_SHARED is not set
-HAVE_SHARED=y
-# ARCH_HAS_NO_LDSO is not set
-BUILD_UCLIBC_LDSO=y
-# FORCE_SHAREABLE_TEXT_SEGMENTS is not set
-LDSO_LDD_SUPPORT=y
-LDSO_CACHE_SUPPORT=y
-# LDSO_PRELOAD_FILE_SUPPORT is not set
-LDSO_BASE_FILENAME="ld.so"
-# LDSO_RUNPATH is not set
-# DL_FINI_CRT_COMPAT is not set
-UCLIBC_CTOR_DTOR=y
-# HAS_NO_THREADS is not set
-UCLIBC_HAS_THREADS=y
-PTHREADS_DEBUG_SUPPORT=y
-UCLIBC_HAS_LFS=y
-# UCLIBC_STATIC_LDCONFIG is not set
-# MALLOC is not set
-# MALLOC_SIMPLE is not set
-MALLOC_STANDARD=y
-MALLOC_GLIBC_COMPAT=y
-UCLIBC_DYNAMIC_ATEXIT=y
-HAS_SHADOW=y
-# UNIX98PTY_ONLY is not set
-ASSUME_DEVPTS=y
-UCLIBC_HAS_TM_EXTENSIONS=y
-UCLIBC_HAS_TZ_CACHING=y
-UCLIBC_HAS_TZ_FILE=y
-UCLIBC_HAS_TZ_FILE_READ_MANY=y
-UCLIBC_TZ_FILE_PATH="/etc/TZ"
-
-#
-# Networking Support
-#
-UCLIBC_HAS_IPV6=y
-UCLIBC_HAS_RPC=y
-UCLIBC_HAS_FULL_RPC=y
-
-#
-# String and Stdio Support
-#
-UCLIBC_HAS_STRING_GENERIC_OPT=y
-UCLIBC_HAS_STRING_ARCH_OPT=y
-UCLIBC_HAS_CTYPE_TABLES=y
-UCLIBC_HAS_CTYPE_SIGNED=y
-# UCLIBC_HAS_CTYPE_UNSAFE is not set
-UCLIBC_HAS_CTYPE_CHECKED=y
-# UCLIBC_HAS_CTYPE_ENFORCED is not set
-UCLIBC_HAS_WCHAR=y
-# UCLIBC_HAS_LOCALE is not set
-UCLIBC_HAS_HEXADECIMAL_FLOATS=y
-UCLIBC_HAS_GLIBC_CUSTOM_PRINTF=y
-UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS=9
-UCLIBC_HAS_SCANF_GLIBC_A_FLAG=y
-# UCLIBC_HAS_STDIO_BUFSIZ_NONE is not set
-# UCLIBC_HAS_STDIO_BUFSIZ_256 is not set
-# UCLIBC_HAS_STDIO_BUFSIZ_512 is not set
-# UCLIBC_HAS_STDIO_BUFSIZ_1024 is not set
-# UCLIBC_HAS_STDIO_BUFSIZ_2048 is not set
-UCLIBC_HAS_STDIO_BUFSIZ_4096=y
-# UCLIBC_HAS_STDIO_BUFSIZ_8192 is not set
-UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE=y
-# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4 is not set
-# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8 is not set
-# UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT is not set
-UCLIBC_HAS_STDIO_GETC_MACRO=y
-UCLIBC_HAS_STDIO_PUTC_MACRO=y
-UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION=y
-# UCLIBC_HAS_FOPEN_LARGEFILE_MODE is not set
-UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE=y
-UCLIBC_HAS_GLIBC_CUSTOM_STREAMS=y
-UCLIBC_HAS_PRINTF_M_SPEC=y
-UCLIBC_HAS_ERRNO_MESSAGES=y
-# UCLIBC_HAS_SYS_ERRLIST is not set
-UCLIBC_HAS_SIGNUM_MESSAGES=y
-# UCLIBC_HAS_SYS_SIGLIST is not set
-UCLIBC_HAS_GNU_GETOPT=y
-
-#
-# Big and Tall
-#
-UCLIBC_HAS_REGEX=y
-# UCLIBC_HAS_WORDEXP is not set
-UCLIBC_HAS_FTW=y
-UCLIBC_HAS_GLOB=y
-
-#
-# Library Installation Options
-#
-SHARED_LIB_LOADER_PREFIX="/lib"
-RUNTIME_PREFIX="/"
-DEVEL_PREFIX="/usr/"
-
-#
-# uClibc security related options
-#
-# UCLIBC_SECURITY is not set
-
-#
-# uClibc development/debugging options
-#
-CROSS_COMPILER_PREFIX="/tmp/buildroot/build_i386/staging_dir/bin/i386-linux-uclibc-"
-# DODEBUG is not set
-# DODEBUG_PT is not set
-# DOASSERTS is not set
-# SUPPORT_LD_DEBUG is not set
-# SUPPORT_LD_DEBUG_EARLY is not set
-WARNINGS="-Wall"
-# UCLIBC_MJN3_ONLY is not set
diff --git a/tools/xm-test/ramdisk/make-release.sh b/tools/xm-test/ramdisk/make-release.sh
deleted file mode 100644
index 255cf0f..0000000
--- a/tools/xm-test/ramdisk/make-release.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/sh
-
-if [ "$1" = "" ]
-then
- arch=""
-else
- echo "Invalid architecture specified." >&2
- exit 1
-fi
-
-set -eu
-
-tempdir=$(mktemp -d)
-
-dir=$(dirname "$0")
-
-cd $(dirname "$dir")
-
-./autogen
-./configure
-
-cd "$dir"
-
-rm -Rf buildroot
-make $arch initrd.img
-
-initrd=$(readlink "initrd.img")
-prefix=$(basename "$initrd" ".img")
-arch=$(echo "$prefix" | sed -e 's/.*-//')
-
-cp "$initrd" "$tempdir"
-
-cp "buildroot/.config" "$tempdir/$prefix-buildroot-config"
-cp "buildroot/package/busybox/busybox.config" "$tempdir/$prefix-busybox-config"
-cp "buildroot/toolchain/uClibc/uClibc.config" "$tempdir/$prefix-uClibc-config"
-
-mv "buildroot" "$tempdir/buildroot-$arch"
-cd $tempdir
-rm -Rf "buildroot-$arch"/toolchain_build*
-rm -Rf "buildroot-$arch"/build_*
-tar cjf "$prefix-buildroot.tar.bz2" "buildroot-$arch"
-rm -Rf "buildroot-$arch"
-
-echo -e "\n\nYour release is in $tempdir."
diff --git a/tools/xm-test/ramdisk/patches/buildroot/add_xvd_devices.patch b/tools/xm-test/ramdisk/patches/buildroot/add_xvd_devices.patch
deleted file mode 100644
index 25d073d..0000000
--- a/tools/xm-test/ramdisk/patches/buildroot/add_xvd_devices.patch
+++ /dev/null
@@ -1,13 +0,0 @@
---- buildroot/target/generic/device_table.txt~ 2006-10-26 17:38:04.000000000 +1000
-+++ buildroot/target/generic/device_table.txt 2006-10-26 17:37:08.000000000 +1000
-@@ -169,3 +169,10 @@
- #/dev/mcd b 640 0 0 23 0 0 0 -
- #/dev/optcd b 640 0 0 17 0 0 0 -
-
-+# Xen Virtual Block Devices
-+/dev/xvda b 640 0 0 202 0 0 0 -
-+/dev/xvda b 640 0 0 202 1 1 1 4
-+/dev/xvdb b 640 0 0 202 16 0 0 -
-+/dev/xvdb b 640 0 0 202 17 1 1 4
-+/dev/xvdc b 640 0 0 202 32 0 0 -
-+/dev/xvdc b 640 0 0 202 33 1 1 4
diff --git a/tools/xm-test/ramdisk/patches/buildroot/hping.patch b/tools/xm-test/ramdisk/patches/buildroot/hping.patch
deleted file mode 100644
index bcd5cd0..0000000
--- a/tools/xm-test/ramdisk/patches/buildroot/hping.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-diff -Naur buildroot.orig/package/Config.in buildroot/package/Config.in
---- buildroot.orig/package/Config.in 2005-11-15 07:30:21.000000000 -0800
-+++ buildroot/package/Config.in 2005-11-15 07:30:54.000000000 -0800
-@@ -118,6 +118,6 @@
- source "package/wireless-tools/Config.in"
- source "package/xorg/Config.in"
- source "package/zlib/Config.in"
--
-+source "package/hping/Config.in"
-
- endmenu
-diff -Naur buildroot.orig/package/hping/Config.in buildroot/package/hping/Config.in
---- buildroot.orig/package/hping/Config.in 1969-12-31 16:00:00.000000000 -0800
-+++ buildroot/package/hping/Config.in 2005-11-14 14:13:20.000000000 -0800
-@@ -0,0 +1,5 @@
-+config BR2_PACKAGE_HPING
-+ bool "hping"
-+ default y
-+ help
-+ This is the hping package
-diff -Naur buildroot.orig/package/hping/hping.mk buildroot/package/hping/hping.mk
---- buildroot.orig/package/hping/hping.mk 1969-12-31 16:00:00.000000000 -0800
-+++ buildroot/package/hping/hping.mk 2005-11-14 15:11:06.000000000 -0800
-@@ -0,0 +1,43 @@
-+# Taken from the buildroot examples
-+
-+HPING_VERSION = 2.0.0-rc3
-+HPING_TBALL = hping$(HPING_VERSION).tar.gz
-+HPING_URL = http://www.hping.org/$(HPING_TBALL)
-+HPING_DIR = $(BUILD_DIR)/hping2-rc3
-+HPING_TARGET_BINARY = usr/bin/hping
-+HPING_BINARY = hping
-+
-+$(DL_DIR)/$(HPING_TBALL):
-+ $(WGET) -P $(DL_DIR) $(HPING_URL)
-+
-+$(HPING_DIR)/.source: $(DL_DIR)/$(HPING_TBALL)
-+ tar xzf $(DL_DIR)/$(HPING_TBALL) -C $(BUILD_DIR)
-+ touch $(HPING_DIR)/.source
-+
-+$(HPING_DIR)/.configured: $(HPING_DIR)/.source
-+ (cd $(HPING_DIR); \
-+ ./configure; )
-+ cat $(HPING_DIR)/Makefile | grep -v './hping2 -v' > $(HPING_DIR)/foo
-+ mv $(HPING_DIR)/foo $(HPING_DIR)/Makefile
-+ touch $(HPING_DIR)/.configured
-+
-+$(HPING_DIR)/$(HPING_BINARY): $(HPING_DIR)/.configured
-+ $(MAKE) CC=$(TARGET_CC) -C $(HPING_DIR)
-+
-+$(TARGET_DIR)/$(HPING_TARGET_BINARY): $(HPING_DIR)/$(HPING_BINARY)
-+ cp $(HPING_DIR)/hping2 $(TARGET_DIR)/bin
-+
-+hping: $(TARGET_DIR)/$(HPING_TARGET_BINARY)
-+
-+hping-clean:
-+ $(MAKE) prefix=$(TARGET_DIR)/usr -C $(HPING_DIR) uninstall
-+ -$(MAKE) -C $(HPING_DIR) clean
-+
-+hping-dirclean:
-+ rm -Rf $(HPING_DIR)
-+
-+ifeq ($(strip $(BR2_PACKAGE_HPING)),y)
-+TARGETS += hping
-+endif
-+
-+
diff --git a/tools/xm-test/ramdisk/skel/.profile b/tools/xm-test/ramdisk/skel/.profile
deleted file mode 100644
index 290b6ac..0000000
--- a/tools/xm-test/ramdisk/skel/.profile
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-export PS1="@%@%> "
diff --git a/tools/xm-test/ramdisk/skel/etc/init.d/rcS b/tools/xm-test/ramdisk/skel/etc/init.d/rcS
deleted file mode 100644
index 4c294f3..0000000
--- a/tools/xm-test/ramdisk/skel/etc/init.d/rcS
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/sh
-
-mount -a
-
-# If we're running 2.6, make sure /sys is mounted
-if uname -r | grep -q '^2.6'; then
- mount -t sysfs none /sys
-fi
-
-# If the block, net, and packet drivers are modules, we need to load them
-if test -e /modules/xenblk.ko; then
- insmod /modules/xenblk.ko > /dev/null 2>&1
-fi
-if test -e /modules/xennet.ko; then
- insmod /modules/xennet.ko > /dev/null 2>&1
-fi
-if test -e /modules/af_packet.ko; then
- insmod /modules/af_packet.ko > /dev/null 2>&1
-fi
diff --git a/tools/xm-test/ramdisk/skel/etc/inittab b/tools/xm-test/ramdisk/skel/etc/inittab
deleted file mode 100644
index 302e077..0000000
--- a/tools/xm-test/ramdisk/skel/etc/inittab
+++ /dev/null
@@ -1,5 +0,0 @@
-# This is run first except when booting in single-user mode.
-#
-::sysinit:/etc/init.d/rcS
-
-::askfirst:-/bin/sh
diff --git a/tools/xm-test/ramdisk/skel/root/.profile b/tools/xm-test/ramdisk/skel/root/.profile
deleted file mode 100644
index 290b6ac..0000000
--- a/tools/xm-test/ramdisk/skel/root/.profile
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-export PS1="@%@%> "
diff --git a/tools/xm-test/runtest.sh b/tools/xm-test/runtest.sh
deleted file mode 100755
index 73d1a5c..0000000
--- a/tools/xm-test/runtest.sh
+++ /dev/null
@@ -1,337 +0,0 @@
-#!/bin/sh
-
-##
-## Test driver script
-##
-
-usage() {
- echo "Usage: $0 [opts] <report>"
- echo " Where report is a name that will be used for report files"
- echo ""
- echo " Where opts are:"
- echo " -d : do not submit a report for this run"
- echo " -b : do not ask any questions (batch mode)"
- echo " -g <group> : run a group test set"
- echo " available goups are:"
- echo " "`ls grouptest`
- echo " -e <email> : set email address for report"
- echo " -r <url> : url of test results repository to use"
- echo " -s <report> : just submit report <report>"
- echo " -u : unsafe -- do not run the sanity checks before starting"
- echo " -md : all created domains are xend-'managed' domains"
- echo " -h | --help : show this help"
-}
-
-# Just submit the report
-submit_report() {
-
- reportfile=$1
-
- ./lib/XmTestReport/Report.py $reportserver $reportfile
-}
-
-# Generate XML result report from output file
-make_result_report() {
- output=$1
- reportfile=$2
- if ! ./lib/XmTestReport/ResultReport.py $output > $reportfile; then
- echo "Unable to generate clean ResultReport"
- echo "Take a look at $report"
- exit 1
- fi
-}
-
-# Collect environment information for XML report
-make_environment_report() {
- os=$1
- prog=$2
- if ! ./lib/XmTestReport/OSReport.py > $os; then
- echo "Unable to generate clean OSReport"
- echo "Take a look at $os"
- exit 1
- fi
- if ! ./lib/XmTestReport/ProgReport.py > $prog; then
- echo "Unable to generate clean ProgReport"
- echo "Take a look at $prog"
- exit 1
- fi
-}
-
-# Check conditions needed to actually run the tests
-runnable_tests() {
- # Make sure we're root
- uid=$(id -u)
- if [ $uid != 0 ]; then
- echo "ERROR: I must be run as root!"
- exit 1
- fi
-
- # See if the ramdisk has been built
- rdsize=$(stat -Lc %s ramdisk/initrd.img 2>/dev/null)
- if [ -z "$rdsize" ] || [ $rdsize -le 16384 ]; then
- echo "Cannot find a valid ramdisk. You need to run \"make\" or"
- echo "copy in a previously-built ramdisk to the ramdisk/ directory"
- exit 1
- fi
-
- # Figure out the version of the ramdisk link and compare it
- # to what it should be as a cheap way of making sure we're
- # using the right version
- realrd=$(readlink ramdisk/initrd.img)
- eval $(./lib/XmTestReport/xmtest.py)
- ARCH=$(uname -m | sed -e s/i.86/i386/)
- rrdver="initrd-${XM_TEST_MAJ}.${XM_TEST_MIN}-${ARCH}.img"
- exp_flag=0
- realarch=`echo $realrd | awk -F- '{print $3}' | awk -F. '{print $1}'`
- rrdarch=`echo $rrdver | awk -F- '{print $3}' | awk -F. '{print $1}'`
- if [ "$realarch" = "i386" -a "$rrdarch" = "x86_64" ]; then
- exp_flag=1
- fi
- if [ $exp_flag -eq 0 -a "$realrd" != "$rrdver" ]; then
- echo "Error: ramdisk/initrd.img is from an old version, or is not for this "
- echo "architecture ($ARCH)."
- echo "You need to build a ramdisk from at least ${XM_TEST_MAJ}.${XM_TEST_MIN}"
- #exit 1
- fi
-
- # See if xend is running
- if ! xm list >/dev/null 2>&1; then
- echo "'xm list' failed: is xend running?"
- exit 1
- fi
-
- # Run a few sample tests to make sure things are working
- # before we take the plunge
- echo "Running sanity checks..."
- make -C tests/_sanity check 2>&1 | grep REASON
- if [ $? -eq 0 ]; then
- echo "Sanity checks failed"
- exit 1
- fi
-
-}
-
-
-# Get contact info if needed
-get_contact_info() {
-
- if [ ! -f contact_info ]; then
- if [ "$batch" = "yes" ]; then
- echo "Unable to read contact_info!"
- echo "Please run me once interactively before using batch mode!"
- exit 1
- else
- echo "Please provide your email address so that we can "
- echo "contact you if we need further information concerning"
- echo "your results. Any information provided will be"
- echo "kept private. If you wish to remain anonymous, please"
- echo "hit [ENTER] now."
-
- while ! echo "$EMAIL" | grep -q '@'; do
- echo
- echo -n "Your email address: "
- read EMAIL
- if [ -z $EMAIL ]; then
- EMAIL="anonymous at somewhere.com"
- fi
- done
- echo $EMAIL > contact_info
- fi
- fi
-}
-
-# Run the tests
-run_tests() {
- groupentered=$1
- output=$2
- report=$3
- startfile=${report}.start
- stopfile=${report}.stop
-
- date -R > $startfile
- exec < grouptest/$groupentered
- while read casename testlist; do
- echo Running $casename tests...
- echo "*** case $casename from group $groupentered" >> $output
- if [ -z "$testlist" ]; then
- echo "*** Running tests for case $casename" >> $output
- (cd tests/$casename && TEST_VERBOSE=1 make -k check) >> $output 2>&1
- else
- echo "*** Running tests $testlist from case $casename" >> $output
- (cd tests/$casename && TEST_VERBOSE=1 make -k check TESTS="$testlist") >> $output 2>&1
- fi
-
- done
- date -R > $stopfile
-
-}
-
-# Generate some plain-text reports
-make_text_reports() {
- passfail=$1
- failures=$2
- output=$3
- reportfile=$4
- report=$5
- summary=summary.tmp
- startfile=${report}.start
- stopfile=${report}.stop
- echo "Making PASS/FAIL report ($passfail)..."
- cat $OUTPUT | egrep '(REASON|PASS|FAIL|XPASS|XFAIL|SKIP)' | perl -pe 's/^(PASS|FAIL|XPASS|XFAIL)(.+)$/$1$2\n/' > $passfail
-
- echo "Making FAIL report ($failures)..."
- cat $passfail | egrep '(REASON|FAIL)' > $failures
-
- NUMPASS=`grep -c PASS $output`
- NUMFAIL=`grep -c FAIL $output`
- NUMXPASS=`grep -c XPASS $output`
- NUMXFAIL=`grep -c XFAIL $output`
- START=`cat $startfile`
- STOP=`cat $stopfile`
- cat > $summary << EOF
-Xm-test timing summary:
- Run Started : $START
- Run Stoped : $STOP
-Xm-test execution summary:
- PASS: $NUMPASS
- FAIL: $NUMFAIL
- XPASS: $NUMXPASS
- XFAIL: $NUMXFAIL
-EOF
-
- cat $summary > $reportfile
-
- echo -e '\n\nDetails:\n' >> $reportfile
-
- ./mkreport $passfail >> $reportfile
-
- rm $summary
-}
-
-############
-### Main ###
-############
-
-# Defaults
-MAXFAIL=10
-report=yes
-reportserver=${xmtest_repo:-'http://xmtest.dague.org/cgi-bin/report-results'}
-batch=no
-run=yes
-unsafe=no
-GROUPENTERED=default
-
-unset XM_MANAGED_DOMAINS
-
-# Resolve options
-while [ $# -gt 0 ]
- do
- case "$1" in
- -d)
- echo "(Skipping report submission)"
- report=no
- ;;
- -b)
- echo "(Batch mode)"
- batch=yes
- ;;
- -e)
- shift
- echo $1 > contact_info
- echo "(Email set to $1)"
- ;;
- -g)
- shift
- GROUPENTERED=$1
- if [ ! -f grouptest/$GROUPENTERED ]; then
- echo "No file for group $GROUPENTERED"
- exit 1
- fi
- ;;
- -r)
- shift
- reportserver=$1
- ;;
- -s)
- run=no
- ;;
- -u)
- echo "(Unsafe mode)"
- unsafe=yes
- report=no
- ;;
- -md)
- echo "(use managed domains)"
- export XM_MANAGED_DOMAINS=1
- ;;
- -h|--help)
- usage
- exit 0
- ;;
- *)
- REPORT=$1
- break
- ;;
- esac
- shift
-done
-
-# Usage
-if [ -z $REPORT ]; then
- usage
- exit 1
-fi
-
-# Output files
-OSREPORTTEMP=${REPORT}.os.xml
-PROGREPORTTEMP=${REPORT}.prog.xml
-RESULTREPORTTEMP=${REPORT}.result.xml
-XMLREPORT=${REPORT}.xml
-OUTPUT=${REPORT}.output
-SUMMARY=${REPORT}.summary
-PASSFAIL=${REPORT}.passfail
-TXTREPORT=${REPORT}.report
-FAILURES=${REPORT}.failures
-
-# Make sure permissions are correct
-chmod a+x lib/XmTestReport/*
-chmod a+x mkreport mergereport
-
-if [ ! -f contact_info ]; then
- if [ "$batch" = "yes" ]; then
- echo "Unable to read contact_info"
- echo "You must run me interactively once!"
- exit 1
- else
- get_contact_info
- fi
-fi
-
-if [ "$GROUPENTERED" != "default" ]; then
- report=no;
-fi
-
-if [ "$run" != "no" ]; then
- if [ "$unsafe" = "no" ]; then
- runnable_tests
- fi
- rm -f $REPORT"*"
- if [ "$unsafe" = "no" ]; then
- make_environment_report $OSREPORTTEMP $PROGREPORTTEMP
- fi
- run_tests $GROUPENTERED $OUTPUT $REPORT
- make_text_reports $PASSFAIL $FAILURES $OUTPUT $TXTREPORT $REPORT
- if [ "$unsafe" = "no" ]; then
- make_result_report $OUTPUT $RESULTREPORTTEMP
- cat $OSREPORTTEMP $PROGREPORTTEMP $RESULTREPORTTEMP > $XMLREPORT
- rm $OSREPORTTEMP $PROGREPORTTEMP $RESULTREPORTTEMP
- fi
-fi
-
-if [ "$report" = "yes" ]; then
- if [ ! -f "$XMLREPORT" ]; then
- echo "No such file: $XMLREPORT"
- exit 1
- fi
- submit_report $XMLREPORT
-fi
diff --git a/tools/xm-test/tests/Makefile.am b/tools/xm-test/tests/Makefile.am
deleted file mode 100644
index 455f50c..0000000
--- a/tools/xm-test/tests/Makefile.am
+++ /dev/null
@@ -1,43 +0,0 @@
-SUBDIRS = \
- block-create \
- block-list \
- block-destroy \
- block-integrity \
- console \
- create \
- destroy \
- dmesg \
- domid \
- domname \
- help \
- info \
- list \
- memmax \
- memset \
- network \
- network-attach \
- pause \
- reboot \
- sched-credit \
- sedf \
- shutdown \
- sysrq \
- unpause \
- vcpu-disable \
- vcpu-pin \
- enforce_dom0_cpus \
- save restore migrate \
- cpupool
-
-EXTRA_DIST = $(SUBDIRS) Makefile.am.template
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
-
diff --git a/tools/xm-test/tests/Makefile.am.template b/tools/xm-test/tests/Makefile.am.template
deleted file mode 100644
index 24e813a..0000000
--- a/tools/xm-test/tests/Makefile.am.template
+++ /dev/null
@@ -1,21 +0,0 @@
-
-SUBDIRS =
-
-TESTS = 01_mytest.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/_sanity/01_domu_proc.py b/tools/xm-test/tests/_sanity/01_domu_proc.py
deleted file mode 100644
index f283ae6..0000000
--- a/tools/xm-test/tests/_sanity/01_domu_proc.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-#
-# Test that the library and ramdisk are working to the point
-# that we can start a DomU and read /proc
-#
-
-from XmTestLib import *
-
-import re
-
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- FAIL(str(e))
-
-try:
- run = console.runCmd("cat /proc/cpuinfo")
-except ConsoleError, e:
- FAIL(str(e))
-
-if run["return"] != 0:
- FAIL("Unable to read /proc/cpuinfo")
-
-if not re.search("processor", run["output"]):
- print run["output"]
- FAIL("/proc/cpuinfo looks wrong!")
diff --git a/tools/xm-test/tests/_sanity/Makefile.am b/tools/xm-test/tests/_sanity/Makefile.am
deleted file mode 100644
index c1525b3..0000000
--- a/tools/xm-test/tests/_sanity/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-
-SUBDIRS =
-
-TESTS = 01_domu_proc.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/block-create/01_block_attach_device_pos.py b/tools/xm-test/tests/block-create/01_block_attach_device_pos.py
deleted file mode 100644
index 5bbf123..0000000
--- a/tools/xm-test/tests/block-create/01_block_attach_device_pos.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Murillo F. Bernardes <mfb at br.ibm.com>
-
-import re
-
-from XmTestLib import *
-from XmTestLib.block_utils import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-attach not supported for HVM domains")
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-# Attach a console to it
-try:
- console.setHistorySaveCmds(value=True)
- # Run 'ls'
- run = console.runCmd("ls")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-
-block_attach(domain, "phy:ram1", "xvda1")
-
-try:
- run = console.runCmd("cat /proc/partitions")
-except ConsoleError, e:
- FAIL(str(e))
-
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
-
-if not re.search("xvda1",run["output"]):
- FAIL("Device is not actually connected to the domU")
diff --git a/tools/xm-test/tests/block-create/02_block_attach_file_device_pos.py b/tools/xm-test/tests/block-create/02_block_attach_file_device_pos.py
deleted file mode 100644
index e70f583..0000000
--- a/tools/xm-test/tests/block-create/02_block_attach_file_device_pos.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Murillo F. Bernardes <mfb at br.ibm.com>
-
-import re
-
-from XmTestLib import *
-from XmTestLib.block_utils import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-attach not supported for HVM domains")
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-# Set console to save commands and make sure we can run cmds
-try:
- console.setHistorySaveCmds(value=True)
- # Run 'ls'
- run = console.runCmd("ls")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-
-block_attach(domain, "file:/dev/ram1", "xvda1")
-
-try:
- run = console.runCmd("cat /proc/partitions")
-except ConsoleError, e:
- FAIL(str(e))
-
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
-
-if not re.search("xvda1",run["output"]):
- FAIL("Device is not actually connected to the domU")
diff --git a/tools/xm-test/tests/block-create/04_block_attach_device_repeatedly_pos.py b/tools/xm-test/tests/block-create/04_block_attach_device_repeatedly_pos.py
deleted file mode 100644
index 2e25884..0000000
--- a/tools/xm-test/tests/block-create/04_block_attach_device_repeatedly_pos.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Murillo F. Bernardes <mfb at br.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-attach not supported for HVM domains")
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- console.setHistorySaveCmds(value=True)
- # Run 'ls'
- run = console.runCmd("ls")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-for i in range(10):
- status, output = traceCommand("xm block-attach %s phy:ram1 xvda1 w" % domain.getName())
- if i == 0 and status != 0:
- FAIL("xm block attach returned invalid %i != 0" % status)
- if i > 0 and status == 0:
- FAIL("xm block-attach (repeat) returned invalid %i > 0" % status)
- run = console.runCmd("cat /proc/partitions")
- if not re.search("xvda1", run['output']):
- FAIL("Device is not actually attached to domU")
-
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/block-create/05_block_attach_and_dettach_device_repeatedly_pos.py b/tools/xm-test/tests/block-create/05_block_attach_and_dettach_device_repeatedly_pos.py
deleted file mode 100644
index 325e160..0000000
--- a/tools/xm-test/tests/block-create/05_block_attach_and_dettach_device_repeatedly_pos.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Murillo F. Bernardes <mfb at br.ibm.com>
-
-import re
-
-from XmTestLib import *
-from XmTestLib.block_utils import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-attach not supported for HVM domains")
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- console.setHistorySaveCmds(value=True)
- # Run 'ls'
- run = console.runCmd("ls")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-
-for i in range(10):
- block_attach(domain, "phy:ram1", "xvda1")
- run = console.runCmd("cat /proc/partitions")
- if not re.search("xvda1", run["output"]):
- FAIL("Failed to attach block device: /proc/partitions does not show that!")
-
- block_detach(domain, "xvda1")
- run = console.runCmd("cat /proc/partitions")
- if re.search("xvda1", run["output"]):
- FAIL("Failed to dettach block device: /proc/partitions still showing that!")
-
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/block-create/06_block_attach_baddomain_neg.py b/tools/xm-test/tests/block-create/06_block_attach_baddomain_neg.py
deleted file mode 100644
index 958b13e..0000000
--- a/tools/xm-test/tests/block-create/06_block_attach_baddomain_neg.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Murillo F. Bernardes <mfb at br.ibm.com>
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-attach not supported for HVM domains")
-
-status, output = traceCommand("xm block-attach NOT-EXIST phy:ram1 xvda1 w")
-
-eyecatcher = "Error"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm block-attach returned bad status, expected non 0, status is: %i" % status )
-elif where == -1:
- FAIL("xm block-attach returned bad output, expected Error, output is: %s" % output )
diff --git a/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py b/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py
deleted file mode 100644
index 5d435e2..0000000
--- a/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Murillo F. Bernardes <mfb at br.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-attach not supported for HVM domains")
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- console.setHistorySaveCmds(value=True)
- # Run 'ls'
- run = console.runCmd("ls")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-
-status, output = traceCommand("xm block-attach %s phy:NOT-EXIST xvda1 w" % domain.getName())
-eyecatcher = "Error"
-where = re.compile(eyecatcher, re.IGNORECASE).search(output)
-if status == 0:
- FAIL("xm block-attach returned bad status, expected non 0, status is: %i" % status )
-elif where is None:
- FAIL("xm block-attach returned bad output, expected Error, output is: %s" % output )
-
-try:
- run = console.runCmd("cat /proc/partitions")
-except ConsoleError, e:
- FAIL(str(e))
-
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
-
-if re.search("xvda1",run["output"]):
- FAIL("Non existent Device was connected to the domU")
diff --git a/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py b/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py
deleted file mode 100644
index 2fa4824..0000000
--- a/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Murillo F. Bernardes <mfb at br.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-attach not supported for HVM domains")
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- console.setHistorySaveCmds(value=True)
- # Run 'ls'
- run = console.runCmd("ls")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-status, output = traceCommand("xm block-attach %s file:/dev/NOT-EXIST xvda1 w" % domain.getName())
-eyecatcher = "Error"
-where = re.compile(eyecatcher, re.IGNORECASE).search(output)
-if status == 0:
- FAIL("xm block-attach returned bad status, expected non 0, status is: %i" % status )
-elif where is None:
- FAIL("xm block-attach returned bad output, expected Error, output is: %s" % output )
-
-try:
- run = console.runCmd("cat /proc/partitions")
-except ConsoleError, e:
- FAIL(str(e))
-
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
-
-if re.search("xvda1",run["output"]):
- FAIL("Non existent Device was connected to the domU")
diff --git a/tools/xm-test/tests/block-create/09_block_attach_and_dettach_device_check_data_pos.py b/tools/xm-test/tests/block-create/09_block_attach_and_dettach_device_check_data_pos.py
deleted file mode 100644
index 9ac635a..0000000
--- a/tools/xm-test/tests/block-create/09_block_attach_and_dettach_device_check_data_pos.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Copyright (C) flonatel GmbH & Co. KG, 2009
-# Authors: Murillo F. Bernardes <mfb at br.ibm.com>
-# Andreas Florath <xen at flonatel.org>
-
-import re
-
-from XmTestLib import *
-from XmTestLib.block_utils import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-attach not supported for HVM domains")
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain(extraConfig={"extra":"rw"})
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- console.setHistorySaveCmds(value=True)
- # Run 'ls'
- run = console.runCmd("ls")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-s, o = traceCommand("mke2fs -j -q -F /dev/ram1")
-if s != 0:
- FAIL("mke2fs returned %i != 0" % s)
-
-for i in range(10):
- block_attach(domain, "phy:ram1", "xvda1")
- run = console.runCmd("cat /proc/partitions")
- if not re.search("xvda1", run["output"]):
- FAIL("Failed to attach block device: /proc/partitions does not show that!")
-
- console.runCmd("mkdir -p /mnt/xvda1; mount /dev/xvda1 /mnt/xvda1")
-
- if i:
- run = console.runCmd("cat /mnt/xvda1/myfile | grep %s" % (i-1))
- if run['return']:
- FAIL("File created was lost or not updated!")
-
- console.runCmd("echo \"%s\" > /mnt/xvda1/myfile" % i)
- run = console.runCmd("cat /mnt/xvda1/myfile")
- print run['output']
- console.runCmd("umount /mnt/xvda1")
-
- block_detach(domain, "xvda1")
- run = console.runCmd("cat /proc/partitions")
- if re.search("xvda1", run["output"]):
- FAIL("Failed to dettach block device: /proc/partitions still showing that!")
-
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/block-create/10_block_attach_dettach_multiple_devices.py b/tools/xm-test/tests/block-create/10_block_attach_dettach_multiple_devices.py
deleted file mode 100644
index 58c7067..0000000
--- a/tools/xm-test/tests/block-create/10_block_attach_dettach_multiple_devices.py
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Copyright (C) flonatel GmbH & Co. KG, 2009
-# Authors: Murillo F. Bernardes <mfb at br.ibm.com>
-# Andreas Florath <xen at flonatel.org>
-
-# Block devices are by random attached to and detached from the domU.
-
-import re
-import random
-from xen.util import blkif
-
-from os.path import basename
-
-from XmTestLib import *
-from XmTestLib.block_utils import *
-
-def availableRamdisks():
- i=0
- while os.access("/dev/ram%d" % i, os.F_OK):
- i+=1
- return i-1
-
-def attach(phy, devname):
- block_attach(domain, "phy:%s" % phy, devname)
- run = console.runCmd("cat /proc/partitions")
- if not re.search(basename(devname), run["output"]):
- return -2, "Failed to attach block device: " \
- + "/proc/partitions does not show that!"
- return 0, None
-
-
-def detach(devname):
- block_detach(domain, devname)
- run = console.runCmd("cat /proc/partitions")
- if re.search(basename(devname), run["output"]):
- return -2, "Failed to detach block device: " \
- + "/proc/partitions still showing that!"
- return 0, None
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-attach not supported for HVM domains")
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- console.setHistorySaveCmds(value=True)
- # Run 'ls'
- run = console.runCmd("ls")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-ramdisk_cnt = availableRamdisks()
-
-detached = range(0, ramdisk_cnt)
-attached = []
-
-def attach_device():
- n = random.choice(detached)
- status, msg = attach("ram%d" % n, "xvda%d" % n)
- if status:
- FAIL(msg)
- detached.remove(n)
- attached.append(n)
-
-def detach_device():
- n = random.choice(attached)
- status, msg = detach("xvda%d" % n)
- if status:
- FAIL(msg)
- detached.append(n)
- attached.append(n)
-
-# First attach some
-for i in xrange(0, ramdisk_cnt/2):
- attach_device()
-
-for i in xrange(0, ramdisk_cnt*5):
- op = random.randint(0,1) # 1 = attach, 0 = detach
- if op:
- detach_device()
- else:
- attach_device()
-
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/block-create/11_block_attach_shared_dom0.py b/tools/xm-test/tests/block-create/11_block_attach_shared_dom0.py
deleted file mode 100644
index f93b8a1..0000000
--- a/tools/xm-test/tests/block-create/11_block_attach_shared_dom0.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-attach not supported for HVM domains")
-
-# Mount /dev/ram0
-
-s, o = traceCommand("mkfs -j /dev/ram0")
-if s != 0:
- FAIL("Unable to mkfs -j /dev/ram0")
-
-s, o = traceCommand("mkdir -p mnt");
-if s != 0:
- FAIL("Unable to create ./mnt")
-
-s, o = traceCommand("mount /dev/ram0 mnt -o rw")
-if s != 0:
- FAIL("Unable to mount /dev/ram0 on ./mnt")
-
-# Now try to start a DomU with write access to /dev/ram0
-
-config = {"disk":"phy:/dev/ram0,xvda1,w"}
-
-domain = XmTestDomain(extraConfig=config);
-
-try:
- domain.start()
- s, o = traceCommand("umount mnt")
- FAIL("Bug #331: Started a DomU with write access to a rw mounted block device")
-except DomainError, e:
- s, o = traceCommand("umount mnt")
-
-domain.destroy()
diff --git a/tools/xm-test/tests/block-create/12_block_attach_shared_domU.py b/tools/xm-test/tests/block-create/12_block_attach_shared_domU.py
deleted file mode 100644
index 79c9571..0000000
--- a/tools/xm-test/tests/block-create/12_block_attach_shared_domU.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-attach not supported for HVM domains")
-
-config = {"disk":"phy:/dev/ram0,xvda1,w"}
-
-dom1 = XmTestDomain(extraConfig=config)
-dom2 = XmTestDomain(dom1.getName() + "-2",
- extraConfig=config)
-
-try:
- dom1.start()
-except DomainError, e:
- FAIL("Unable to start domain")
-
-try:
- try:
- dom2.start()
- FAIL("Bug #331: Started a DomU with write access to an in-use block device")
- except DomainError, e:
- pass
-finally:
- dom1.destroy()
- dom2.destroy()
diff --git a/tools/xm-test/tests/block-create/Makefile.am b/tools/xm-test/tests/block-create/Makefile.am
deleted file mode 100644
index c9b41f6..0000000
--- a/tools/xm-test/tests/block-create/Makefile.am
+++ /dev/null
@@ -1,29 +0,0 @@
-
-SUBDIRS =
-
-TESTS = 01_block_attach_device_pos.test \
- 02_block_attach_file_device_pos.test \
- 04_block_attach_device_repeatedly_pos.test \
- 05_block_attach_and_dettach_device_repeatedly_pos.test \
- 06_block_attach_baddomain_neg.test \
- 07_block_attach_baddevice_neg.test \
- 08_block_attach_bad_filedevice_neg.test \
- 09_block_attach_and_dettach_device_check_data_pos.test \
- 10_block_attach_dettach_multiple_devices.test \
- 11_block_attach_shared_dom0.test \
- 12_block_attach_shared_domU.test
-
-EXTRA_DIST = $(TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/block-destroy/01_block-destroy_btblock_pos.py b/tools/xm-test/tests/block-destroy/01_block-destroy_btblock_pos.py
deleted file mode 100644
index 1d05684..0000000
--- a/tools/xm-test/tests/block-destroy/01_block-destroy_btblock_pos.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-from XmTestLib.block_utils import block_detach
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-detach not supported for HVM domains")
-
-config = {"disk":"phy:/dev/ram0,xvda1,w"}
-domain = XmTestDomain(extraConfig=config)
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print e.extra
- FAIL("Unable to create domain")
-
-try:
- console.setHistorySaveCmds(value=True)
- run = console.runCmd("cat /proc/partitions | grep xvda1")
- run2 = console.runCmd("cat /proc/partitions")
-except ConsoleError, e:
- FAIL(str(e))
-
-if run["return"] != 0:
- FAIL("block device isn't attached; can't detach!")
-
-block_detach(domain, "xvda1")
-try:
-
- run = console.runCmd("cat /proc/partitions | grep xvda1")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-domain.closeConsole()
-domain.stop()
-
-if run["return"] == 0:
- FAIL("domU reported block device still connected!")
diff --git a/tools/xm-test/tests/block-destroy/02_block-destroy_rtblock_pos.py b/tools/xm-test/tests/block-destroy/02_block-destroy_rtblock_pos.py
deleted file mode 100644
index cf63292..0000000
--- a/tools/xm-test/tests/block-destroy/02_block-destroy_rtblock_pos.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-from XmTestLib.block_utils import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-detach not supported for HVM domains")
-
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print e.extra
- FAIL("Unable to create domain")
-
-block_attach(domain, "phy:/dev/ram0", "xvda1")
-try:
- run = console.runCmd("cat /proc/partitions | grep xvda1")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-if run["return"] != 0:
- FAIL("Failed to verify that block dev is attached")
-
-block_detach(domain, "xvda1")
-try:
- run = console.runCmd("cat /proc/partitions | grep xvda1")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-domain.stop()
-
-if run["return"] == 0:
- FAIL("block-detach failed to detach block device")
diff --git a/tools/xm-test/tests/block-destroy/03_block-destroy_nonexist_neg.py b/tools/xm-test/tests/block-destroy/03_block-destroy_nonexist_neg.py
deleted file mode 100644
index 96fca34..0000000
--- a/tools/xm-test/tests/block-destroy/03_block-destroy_nonexist_neg.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-# Negative Test: attempt removal from non-existent domain
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm block-detach 9999 769")
-eyecatcher = "Error:"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm block-detach returned invalid %i != 0" % status)
-elif where < 0:
- FAIL("xm block-detach failed to report error for non-existent domain")
diff --git a/tools/xm-test/tests/block-destroy/04_block-destroy_nonattached_neg.py b/tools/xm-test/tests/block-destroy/04_block-destroy_nonattached_neg.py
deleted file mode 100644
index d7df7ac..0000000
--- a/tools/xm-test/tests/block-destroy/04_block-destroy_nonattached_neg.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-#Negative Test: attempt removal of non-attached device from live domain
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-detach not supported for HVM domains")
-
-domain = XmTestDomain()
-
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print e.extra
- FAIL("Unable to create domain")
-
-status, output = traceCommand("xm block-detach %s xvda1" % domain.getId())
-
-eyecatcher1 = "Error:"
-eyecatcher2 = "Traceback"
-where1 = output.find(eyecatcher1)
-where2 = output.find(eyecatcher2)
-if status == 0:
- FAIL("xm block-detach returned bad status, expected non 0, status is: %i" % status)
-elif where2 == 0:
- FAIL("xm block-detach returned a stack dump, expected nice error message")
-elif where1 < 0:
- FAIL("xm block-detach returned bad output, expected Error:, output is: %s" % output)
diff --git a/tools/xm-test/tests/block-destroy/05_block-destroy_byname_pos.py b/tools/xm-test/tests/block-destroy/05_block-destroy_byname_pos.py
deleted file mode 100644
index 7e3d990..0000000
--- a/tools/xm-test/tests/block-destroy/05_block-destroy_byname_pos.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-from XmTestLib.block_utils import block_detach
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-detach not supported for HVM domains")
-
-config = {"disk":"phy:/dev/ram0,xvda1,w"}
-domain = XmTestDomain(extraConfig=config)
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print e.extra
- FAIL("Unable to create domain")
-
-try:
- run = console.runCmd("cat /proc/partitions | grep xvda1")
- run2 = console.runCmd("cat /proc/partitions")
-except ConsoleError, e:
- FAIL(str(e))
-
-if run["return"] != 0:
- FAIL("block device isn't attached; can't detach!")
-
-block_detach(domain, "xvda1")
-try:
-
- run = console.runCmd("cat /proc/partitions | grep xvda1")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-domain.closeConsole()
-domain.stop()
-
-if run["return"] == 0:
- FAIL("domU reported block device still connected!" % run["return"])
diff --git a/tools/xm-test/tests/block-destroy/06_block-destroy_check_list_pos.py b/tools/xm-test/tests/block-destroy/06_block-destroy_check_list_pos.py
deleted file mode 100644
index b9fdc06..0000000
--- a/tools/xm-test/tests/block-destroy/06_block-destroy_check_list_pos.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-from XmTestLib.block_utils import *
-
-import re, time
-
-def checkXmLongList(domain):
- s, o = traceCommand("xm list --long %s" % domain.getName())
- if s != 0:
- FAIL("xm list --long <dom> failed")
- if re.search("xvda1", o):
- return True
- else:
- return False
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-detach not supported for HVM domains")
-
-domain = XmTestDomain()
-
-try:
- domain.start()
-except DomainError,e:
- FAIL(str(e))
-
-block_attach(domain, "phy:/dev/ram0", "xvda1")
-
-if not checkXmLongList(domain):
- FAIL("xm long list does not show that xvda1 was attached")
-
-block_detach(domain, "xvda1")
-
-if checkXmLongList(domain):
- # device info is removed by hotplug scripts - give them a chance
- # to fire (they run asynchronously with us).
- time.sleep(1)
- if checkXmLongList(domain):
- FAIL("xm long list does not show that xvda1 was removed")
diff --git a/tools/xm-test/tests/block-destroy/Makefile.am b/tools/xm-test/tests/block-destroy/Makefile.am
deleted file mode 100644
index 78d594e..0000000
--- a/tools/xm-test/tests/block-destroy/Makefile.am
+++ /dev/null
@@ -1,26 +0,0 @@
-
-SUBDIRS =
-
-TESTS = 01_block-destroy_btblock_pos.test \
- 02_block-destroy_rtblock_pos.test \
- 03_block-destroy_nonexist_neg.test \
- 04_block-destroy_nonattached_neg.test \
- 05_block-destroy_byname_pos.test \
- 06_block-destroy_check_list_pos.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/block-integrity/01_block_device_read_verify.py b/tools/xm-test/tests/block-integrity/01_block_device_read_verify.py
deleted file mode 100644
index 28531f1..0000000
--- a/tools/xm-test/tests/block-integrity/01_block_device_read_verify.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: Harry Butterworth <butterwo at uk.ibm.com>
-
-# This test initialises a ram disk in dom0 with data from /dev/urandom and
-# then imports the ram disk device as a physical device into a domU. The md5
-# checksum of the data in the ramdisk is calculated in dom0 and also
-# calculated by the domU reading the data through the blk frontend and
-# backend drivers. The test succeeds if the checksums match indicating that
-# the domU successfully read all the correct data from the device.
-
-import re
-
-from XmTestLib import *
-from XmTestLib.block_utils import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-attach not supported for HVM domains")
-
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- FAIL(str(e))
-
-console.setHistorySaveCmds(value=True)
-
-traceCommand("cat /dev/urandom > /dev/ram1")
-
-s, o = traceCommand("md5sum /dev/ram1")
-
-dom0_md5sum_match = re.search(r"^[\dA-Fa-f]{32}", o, re.M)
-
-block_attach(domain, "phy:ram1", "xvda1")
-
-try:
- run = console.runCmd("md5sum /dev/xvda1")
-except ConsoleError, e:
- FAIL(str(e))
-
-domU_md5sum_match = re.search(r"^[\dA-Fa-f]{32}", run["output"], re.M)
-
-domain.closeConsole()
-
-domain.stop()
-
-if dom0_md5sum_match == None:
- FAIL("Failed to get md5sum of test ram disk in dom0.")
-
-if domU_md5sum_match == None:
- FAIL("Failed to get md5sum of test ram disk in domU.")
-
-if verbose:
- print "md5sum dom0:"
- print dom0_md5sum_match.group()
- print "md5sum domU:"
- print domU_md5sum_match.group()
-
-if dom0_md5sum_match.group() != domU_md5sum_match.group():
- FAIL("MISCOMPARE: data read in domU did not match data provided by domO.")
diff --git a/tools/xm-test/tests/block-integrity/02_block_device_write_verify.py b/tools/xm-test/tests/block-integrity/02_block_device_write_verify.py
deleted file mode 100644
index ed791a0..0000000
--- a/tools/xm-test/tests/block-integrity/02_block_device_write_verify.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: Harry Butterworth <butterwo at uk.ibm.com>
-
-# This test imports a ram disk device as a physical device into a domU.
-# The domU initialises the ram disk with data from /dev/urandom and calculates
-# the md5 checksum of the data (using tee as it is written so as to avoid
-# reading it back from the device which might potentially mask problems).
-# The domU is stopped and the md5 checksum of the data on the device is
-# calculated by dom0. The test succeeds if the checksums match, indicating
-# that all the data written by domU was sucessfully committed to the device.
-
-import re
-
-from XmTestLib import *
-from XmTestLib.block_utils import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-attach not supported for HVM domains")
-
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- FAIL(str(e))
-
-console.setHistorySaveCmds(value=True)
-
-block_attach(domain, "phy:ram1", "xvda1")
-
-console.setTimeout(120)
-
-try:
- run = console.runCmd("dd if=/dev/urandom bs=512 count=`cat /sys/block/xvda1/size` | tee /dev/xvda1 | md5sum")
-except ConsoleError, e:
- FAIL(str(e))
-
-domU_md5sum_match = re.search(r"^[\dA-Fa-f]{32}", run["output"], re.M)
-
-domain.closeConsole()
-
-domain.stop()
-
-s, o = traceCommand("md5sum /dev/ram1")
-
-dom0_md5sum_match = re.search(r"^[\dA-Fa-f]{32}", o, re.M)
-
-if domU_md5sum_match == None:
- FAIL("Failed to get md5sum of data written in domU.")
-
-if dom0_md5sum_match == None:
- FAIL("Failed to get md5sum of data read back in dom0.")
-
-if verbose:
- print "md5sum domU:"
- print domU_md5sum_match.group()
- print "md5sum dom0:"
- print dom0_md5sum_match.group()
-
-if domU_md5sum_match.group() != dom0_md5sum_match.group():
- FAIL("MISCOMPARE: data read in dom0 did not match data written by domU.")
diff --git a/tools/xm-test/tests/block-integrity/Makefile.am b/tools/xm-test/tests/block-integrity/Makefile.am
deleted file mode 100644
index 572812d..0000000
--- a/tools/xm-test/tests/block-integrity/Makefile.am
+++ /dev/null
@@ -1,22 +0,0 @@
-
-SUBDIRS =
-
-TESTS = 01_block_device_read_verify.test \
- 02_block_device_write_verify.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/block-list/01_block-list_pos.py b/tools/xm-test/tests/block-list/01_block-list_pos.py
deleted file mode 100644
index 2b19208..0000000
--- a/tools/xm-test/tests/block-list/01_block-list_pos.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com)
-
-# Positive Test: create domain with block attached at build time, verify list
-
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-list not supported for HVM domains")
-
-config = {"disk":"phy:/dev/ram0,xvda1,w"}
-domain = XmTestDomain(extraConfig=config)
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print e.extra
- FAIL("Unable to create domain")
-
-status, output = traceCommand("xm block-list %s" % domain.getId())
-eyecatcher = "51713"
-where = output.find(eyecatcher)
-if status != 0:
- FAIL("xm block-list returned bad status, expected 0, status is %i" % status)
-elif where < 0:
- FAIL("Fail to list block device")
-
-#Verify the block device on DomainU
-try:
- run = console.runCmd("cat /proc/partitions | grep xvda1")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-domain.stop()
-
-if run["return"] != 0:
- FAIL("Failed to verify that block dev is attached on DomainU")
diff --git a/tools/xm-test/tests/block-list/02_block-list_attachbd_pos.py b/tools/xm-test/tests/block-list/02_block-list_attachbd_pos.py
deleted file mode 100644
index 8ad0df3..0000000
--- a/tools/xm-test/tests/block-list/02_block-list_attachbd_pos.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com)
-
-# Positive Test: create domain, attach block device, verify list
-
-
-from XmTestLib import *
-from XmTestLib.block_utils import block_attach
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-list not supported for HVM domains")
-
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print e.extra
- FAIL("Unable to create domain")
-
-#Attach one virtual block device to domainU
-block_attach(domain, "phy:/dev/ram0", "xvda1")
-
-#Verify block-list on Domain0
-status, output = traceCommand("xm block-list %s" % domain.getId())
-eyecatcher = "51713"
-where = output.find(eyecatcher)
-if status != 0:
- FAIL("xm block-list returned bad status, expected 0, status is %i" % status)
-elif where < 0 :
- FAIL("Fail to list block device")
-
-#Verify attached block device on DomainU
-try:
- run = console.runCmd("cat /proc/partitions | grep xvda1")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-domain.stop()
-
-if run["return"] != 0:
- FAIL("Failed to verify that block dev is attached on DomainU")
diff --git a/tools/xm-test/tests/block-list/03_block-list_anotherbd_pos.py b/tools/xm-test/tests/block-list/03_block-list_anotherbd_pos.py
deleted file mode 100644
index b128ec1..0000000
--- a/tools/xm-test/tests/block-list/03_block-list_anotherbd_pos.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-# Positive Test: create domain with block attach, attach another, verify both in list
-
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-list not supported for HVM domains")
-
-config = {"disk":"phy:/dev/ram0,xvda1,w"}
-domain = XmTestDomain(extraConfig=config)
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print e.extra
- FAIL("Unable to create domain")
-
-status, output = traceCommand("xm block-list %s" % domain.getId())
-if status != 0:
- FAIL("Fail to list block device")
-
-#Add another virtual block device to the domain
-status, output = traceCommand("xm block-attach %s phy:/dev/ram1 xvda2 w" % domain.getId())
-if status != 0:
- FAIL("Fail to attach block device")
-
-#Verify block-list on Domain0
-status, output = traceCommand("xm block-list %s" % domain.getId())
-eyecatcher1 = "51713"
-eyecatcher2 = "51714"
-where1 = output.find(eyecatcher1)
-where2 = output.find(eyecatcher2)
-if status != 0:
- FAIL("xm block-list returned bad status, expected 0, status is %i" % status)
-elif (where1 < 0) and (where2 < 0):
- FAIL("Fail to list all block devices after attaching another block device")
-
-#Verify attached block device on DomainU
-try:
- run = console.runCmd("cat /proc/partitions | grep xvda1;cat /proc/partitions | grep xvda2")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-domain.stop()
-
-if run["return"] != 0:
- FAIL("Failed to verify that block dev is attached on DomainU")
diff --git a/tools/xm-test/tests/block-list/04_block-list_nodb_pos.py b/tools/xm-test/tests/block-list/04_block-list_nodb_pos.py
deleted file mode 100644
index 131eee7..0000000
--- a/tools/xm-test/tests/block-list/04_block-list_nodb_pos.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com)
-
-# Positive Test: attempt list of domain wtih no block devices
-
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-list not supported for HVM domains")
-
-domain = XmTestDomain()
-
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print e.extra
- FAIL("Unable to create domain")
-
-status, output = traceCommand("xm block-list %s" % domain.getId())
-if status != 0:
- FAIL("xm block-list returned bad status, expected 0, status is %i" % status)
-
-if output != "":
- FAIL("xm block-list should not list anything for domain with no block devices")
diff --git a/tools/xm-test/tests/block-list/05_block-list_nonexist_neg.py b/tools/xm-test/tests/block-list/05_block-list_nonexist_neg.py
deleted file mode 100644
index 4b2c9be..0000000
--- a/tools/xm-test/tests/block-list/05_block-list_nonexist_neg.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-# Negative Test: attempt list of non-existent domain
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm block-list 9999")
-eyecatcher = "Error:"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm block-list returned invalid %i != 0" % status)
-elif where < 0:
- FAIL("xm block-list failed to report error for non-existent domain")
-
diff --git a/tools/xm-test/tests/block-list/06_block-list_checkremove_pos.py b/tools/xm-test/tests/block-list/06_block-list_checkremove_pos.py
deleted file mode 100644
index 8d3bf08..0000000
--- a/tools/xm-test/tests/block-list/06_block-list_checkremove_pos.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-from XmTestLib.block_utils import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-list not supported for HVM domains")
-
-domain = XmTestDomain()
-
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- FAIL(str(e))
-
-s, o = traceCommand("xm block-list %s" % domain.getName())
-if s != 0:
- FAIL("block-list returned !0 when no devices attached")
-if o:
- FAIL("block-list without devices reported something!")
-
-block_attach(domain, "phy:/dev/ram0", "xvda1")
-
-s, o = traceCommand("xm block-list %s" % domain.getName())
-if s != 0:
- FAIL("block-list failed")
-if o.find("51713") == -1:
- FAIL("block-list didn't show the block device I just attached!")
-
-block_attach(domain, "phy:/dev/ram1", "xvda2")
-
-s, o = traceCommand("xm block-list %s" % domain.getName())
-if s != 0:
- FAIL("block-list failed")
-if o.find("51714") == -1:
- FAIL("block-list didn't show the other block device I just attached!")
-
-block_detach(domain, "xvda1")
-
-s, o = traceCommand("xm block-list %s" % domain.getName())
-if s != 0:
- FAIL("block-list failed after detaching a device")
-if o.find("51713") != -1:
- FAIL("xvda1 still shown in block-list after detach!")
-if o.find("51714") == -1:
- FAIL("xvda2 not shown after detach of xvda1!")
-
-block_detach(domain, "xvda2")
-
-s, o = traceCommand("xm block-list %s" % domain.getName())
-if s != 0:
- FAIL("block-list failed after detaching another device")
-if o.find("51714") != -1:
- FAIL("xvda2 still shown in block-list after detach!")
-if o:
- FAIL("block-list still shows something after all devices detached!")
-
-domain.stop()
diff --git a/tools/xm-test/tests/block-list/Makefile.am b/tools/xm-test/tests/block-list/Makefile.am
deleted file mode 100644
index 9e303af..0000000
--- a/tools/xm-test/tests/block-list/Makefile.am
+++ /dev/null
@@ -1,26 +0,0 @@
-
-SUBDIRS =
-
-TESTS = 01_block-list_pos.test \
- 02_block-list_attachbd_pos.test \
- 03_block-list_anotherbd_pos.test \
- 04_block-list_nodb_pos.test \
- 05_block-list_nonexist_neg.test \
- 06_block-list_checkremove_pos.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/console/01_console_badopt_neg.py b/tools/xm-test/tests/console/01_console_badopt_neg.py
deleted file mode 100644
index 1c00afe..0000000
--- a/tools/xm-test/tests/console/01_console_badopt_neg.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-# Test Description:
-# Negative Tests:
-# Test console command with non existent option in the command line.
-# Verify fail.
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm console -x")
-eyecatcher = "Error"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm console returned invalid %i != 0" % status)
-elif where == -1:
- FAIL("xm console didn't report error on bad argument")
diff --git a/tools/xm-test/tests/console/02_console_baddom_neg.py b/tools/xm-test/tests/console/02_console_baddom_neg.py
deleted file mode 100644
index 56bf1a0..0000000
--- a/tools/xm-test/tests/console/02_console_baddom_neg.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-# Test Description:
-# Negative Tests:
-# Test for attempting to connect to non existent domname, domid. Verify fail.
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm console 5000")
-eyecatcher = "Error"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm console returned invalid %i != 0" % status)
-elif where == -1:
- FAIL("xm console failed to report error on bad domid")
-
-status, output = traceCommand("xm console NON_EXIST")
-eyecatcher = "Error"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm console returned invalid %i != 0" % status)
-elif where == -1:
- FAIL("xm console failed to report error on bad domname")
diff --git a/tools/xm-test/tests/console/Makefile.am b/tools/xm-test/tests/console/Makefile.am
deleted file mode 100644
index cc48dfd..0000000
--- a/tools/xm-test/tests/console/Makefile.am
+++ /dev/null
@@ -1,22 +0,0 @@
-
-SUBDIRS =
-
-TESTS = 01_console_badopt_neg.test \
- 02_console_baddom_neg.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/cpupool/01_cpupool_basic_pos.py b/tools/xm-test/tests/cpupool/01_cpupool_basic_pos.py
deleted file mode 100644
index 66d1bf7..0000000
--- a/tools/xm-test/tests/cpupool/01_cpupool_basic_pos.py
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/usr/bin/python
-
-import sys
-import re
-import time
-
-from XmTestLib import *
-
-
-#
-# Check output of xm info. It must include field 'free_cpus'
-# The value must be between 0 - nr_cpus
-#
-free_cpus = getInfo("free_cpus")
-if free_cpus == "":
- FAIL("Missing 'free_cpus' entry in xm info output")
-if int(free_cpus) not in range(int(getInfo("nr_cpus")) + 1):
- FAIL("Wrong value of 'free_cpus' (%s)" % int(free_cpus))
-
-
-#
-# Check output of xm list -l. It must contain the key 'pool_name'
-# If XM_USES_API is set, output must also contain 'cpu_pool'.
-#
-status, output = traceCommand("xm list -l Domain-0")
-if status != 0 or "Traceback" in output:
- raise XmError("xm failed", trace=output, status=status)
-if not re.search("pool_name Pool-0", output):
- FAIL("Missing or wrong attribute 'pool_name' in output of 'xm list -l'")
-if os.getenv("XM_USES_API"):
- if not re.search("cpu_pool (.+)", output):
- FAIL("Missing or wrong attribute 'cpu_pool' in output of 'xm list -l'")
-
-#
-# Test pool selection option of xm list.
-#
-status, output = traceCommand("xm list --pool=Pool-0")
-if status != 0 or "Traceback" in output:
- raise XmError("xm failed", trace=output, status=status)
-if not re.search("Domain-0 +0 +", output):
- FAIL("Missing 'Domain-0' in Pool-0")
-
-status, output = traceCommand("xm list --pool=Dummy-Pool")
-if status != 0 or "Traceback" in output:
- raise XmError("xm failed", trace=output, status=status)
-if len(output.splitlines()) != 1:
- FAIL("Wrong pool selection; output must be empty")
-
-
-#
-# Create a Domain without pool specification.
-# Default pool is Pool-0
-#
-name = "TestDomPool-1"
-domain = XmTestDomain(name=name)
-try:
- domain.start(noConsole=True)
-except DomainError, ex:
- FAIL(str(e))
-
-if not isDomainRunning(name):
- FAIL("Couldn't start domain without pool specification")
-
-status, output = traceCommand("xm list -l %s" % name)
-if status != 0 or "Traceback" in output:
- raise XmError("xm failed", trace=output, status=status)
-if not re.search("pool_name Pool-0", output):
- FAIL("Missing or wrong attribute 'pool_name' in output of 'xm list -l %s'" % name)
-
-destroyAllDomUs()
-
-
diff --git a/tools/xm-test/tests/cpupool/02_cpupool_manage_pos.py b/tools/xm-test/tests/cpupool/02_cpupool_manage_pos.py
deleted file mode 100644
index a58cd88..0000000
--- a/tools/xm-test/tests/cpupool/02_cpupool_manage_pos.py
+++ /dev/null
@@ -1,152 +0,0 @@
-#!/usr/bin/python
-
-# Description:
-# Verify commands pool-new and pool-delete.
-#
-import sys
-import re
-import time
-
-from XmTestLib import *
-from pools import *
-
-checkRequirements()
-
-#
-# Check output of xm pool-list (of Pool-0)
-#
-status, output = traceCommand("xm pool-list Pool-0")
-if status != 0:
- FAIL("xm pool-list failed, rc %s" % status)
-lines = output.splitlines()
-if len(lines) != 2:
- FAIL("Wrong output of xm pool-list Pool-0 (%s)" % lines)
-if not re.search("Pool-0 +[0-9]+ +credit +y +[0-9]", lines[1]):
- FAIL("Wrong output of xm pool-list Pool-0 (%s)" % lines)
-
-#
-# Check output of xm pool-list -l (of Pool-0)
-#
-status, output = traceCommand("xm pool-list Pool-0 -l")
-if status != 0:
- FAIL("xm pool-list failed, rc %s" % status)
-if not re.search("name_label Pool-0", output):
- FAIL("Wrong output of xm pool-list Pool-0 -l; missing 'name_label'")
-if not re.search("started_VMs 00000000-0000-0000-0000-000000000000", output):
- FAIL("Wrong output of xm pool-list Pool-0 -l; missing 'started_VMs'")
-if not re.search("started_VM_names Domain-0", output):
- FAIL("Wrong output of xm pool-list Pool-0 -l; missing 'started_VMi_names'")
-
-
-#
-# Create a pool from pool1.cfg
-#
-cmd = "xm pool-new pool1.cfg name=Pool-1"
-status, output = traceCommand(cmd)
-if status != 0:
- FAIL("%s failed, rc %s" % (cmd,status))
-
-status, output = traceCommand("xm pool-list")
-if status != 0:
- FAIL("xm pool-list failed, rc %s" % status)
-if not re.search("Pool-1 +1 +credit", output):
- FAIL("Missing or wrong pool definition for 'Pool-1'")
-
-
-#
-# check persistence of pool; restart xend
-#
-restartXend()
-
-status, output = traceCommand("xm pool-list")
-if status != 0:
- FAIL("xm pool-list failed, rc %s" % status)
-if not re.search("Pool-1 +1 +credit", output):
- FAIL("Missing or wrong pool definition for 'Pool-1'")
-
-
-#
-# Delete pool
-#
-deletePool("Pool-1")
-status, output = traceCommand("xm pool-list")
-if status != 0:
- FAIL("xm pool-list failed, rc %s" % status)
-if re.search("Pool-1 +1 +credit", output):
- FAIL("'Pool-1' not deleted")
-
-
-#
-# create / start / check / destroy / delete a managed pool
-#
-cmd = "xm pool-new pool1.cfg"
-status, output = traceCommand(cmd)
-if status != 0:
- FAIL("%s failed, rc %s" % (cmd,status))
-
-cmd = "xm pool-start Pool-1"
-status, output = traceCommand(cmd)
-if status != 0:
- FAIL("%s failed, rc %s" % (cmd,status))
-
-cmd = "xm pool-list -l Pool-1"
-status, output = traceCommand(cmd)
-if status != 0:
- FAIL("%s failed, rc %s" % (cmd,status))
-if not re.search("host_CPU_numbers +[0-9]", output):
- FAIL("'Pool-1' not activated")
-
-restartXend()
-
-cmd = "xm pool-list -l Pool-1"
-status, output = traceCommand(cmd)
-if status != 0:
- FAIL("%s failed, rc %s" % (cmd,status))
-if not re.search("host_CPU_numbers +[0-9]", output):
- FAIL("'Pool-1' not activated")
-
-destroyPool("Pool-1")
-deletePool("Pool-1")
-
-cmd = "xm pool-list Pool-1"
-status, output = traceCommand(cmd)
-if status != 0:
- FAIL("%s failed, rc %s" % (cmd,status))
-if re.search("Pool-1 +1 +credit", output):
- FAIL("'Pool-1' not deleted")
-
-
-#
-# create / check / destroy a unmanaged pool
-#
-cmd = "xm pool-create pool1.cfg"
-status, output = traceCommand(cmd)
-if status != 0:
- FAIL("%s failed, rc %s" % (cmd,status))
-
-cmd = "xm pool-list -l Pool-1"
-status, output = traceCommand(cmd)
-if status != 0:
- FAIL("%s failed, rc %s" % (cmd,status))
-if not re.search("host_CPU_numbers +[0-9]", output):
- FAIL("'Pool-1' not activated")
-
-restartXend()
-
-cmd = "xm pool-list -l Pool-1"
-status, output = traceCommand(cmd)
-if status != 0:
- FAIL("%s failed, rc %s" % (cmd,status))
-if not re.search("host_CPU_numbers +[0-9]", output):
- FAIL("'Pool-1' not activated")
-
-destroyPool("Pool-1", True)
-
-cmd = "xm pool-list"
-status, output = traceCommand(cmd)
-if status != 0:
- FAIL("%s failed, rc %s" % (cmd,status))
-if re.search("Pool-1", output):
- FAIL("'Pool-1' not deleted")
-
-
diff --git a/tools/xm-test/tests/cpupool/03_cpupool_domain.py b/tools/xm-test/tests/cpupool/03_cpupool_domain.py
deleted file mode 100644
index dcff944..0000000
--- a/tools/xm-test/tests/cpupool/03_cpupool_domain.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/python
-
-import sys
-import re
-import time
-
-from XmTestLib import *
-from pools import *
-
-
-checkRequirements()
-
-#
-# create Pool-1 with 1 CPU and start a VM
-#
-createStdPool()
-name = "TestDomPool-1"
-domain = XmTestDomain(extraConfig={'pool' : 'Pool-1'}, name=name)
-try:
- domain.start(noConsole=True)
-except DomainError, ex:
- FAIL(str(e))
-
-cmd = "xm list --pool=Pool-1"
-status, output = traceCommand(cmd)
-if status != 0:
- FAIL("%s failed, rc %s" % (cmd,status))
-if not re.search(name, output):
- FAIL("%s; missing '%s' in Pool-1" % (cmd,name))
-
-domain.stop()
-waitForDomain(name)
-destroyPool("Pool-1", True)
-
-
-
-#
-# create Pool-1 with 1 CPU, add a second CPU
-# start a VM (with vpcu=3) add a third CPU
-# remove 2 CPUs from pool
-# create Pool-1 with 1 CPU and start a VM
-#
-pool_names = ['Pool-1', 'Pool-2']
-createStdPool({'name' : pool_names[0], 'cpus' : '"1"'})
-name = "TestDomPool-1"
-cmd = "xm pool-cpu-add Pool-1 2"
-status, output = traceCommand(cmd)
-if status != 0:
- FAIL("%s failed, rc %s" % (cmd,status))
-
-domain = XmTestDomain(extraConfig={ 'pool' : 'Pool-1'}, name=name)
-try:
- domain.start(noConsole=True)
-except DomainError, ex:
- FAIL(str(e))
-
-cmd = "xm pool-cpu-add Pool-1 3"
-status, output = traceCommand(cmd)
-if status != 0:
- FAIL("%s failed, rc %s" % (cmd,status))
-
-cmd = "xm pool-cpu-remove Pool-1 2"
-status, output = traceCommand(cmd)
-if status != 0:
- FAIL("%s failed, rc %s" % (cmd,status))
-cmd = "xm pool-cpu-remove Pool-1 3"
-
-status, output = traceCommand(cmd)
-if status != 0:
- FAIL("%s failed, rc %s" % (cmd,status))
-
-
-createStdPool({'name' : pool_names[1]})
-name2 = "TestDomPool-2"
-domain2 = XmTestDomain(extraConfig={ 'pool' : 'Pool-2'}, name=name2)
-try:
- domain2.start(noConsole=True)
-except DomainError, ex:
- FAIL(str(e))
-
-domain2.stop()
-domain.stop()
-
-waitForDomain(name)
-waitForDomain(name2)
-
-for pool in pool_names:
- destroyPool(pool, True)
-
-
-
-#
-# Create 2 pools with 1 cpu per pool.
-# Create three domains in each pool, with 1,2,3 VCPUs
-# Switch a thrid cpu between the pools.
-#
-pool_names = ['Pool-1', 'Pool-2']
-domains = {}
-cpu=3
-
-for pool in pool_names:
- createStdPool({'name' : pool})
- for dom_nr in range(3):
- name = "TestDom%s-%s" % (pool, dom_nr)
- domains[name] = XmTestDomain(extraConfig={'pool' : pool},
- name=name)
- try:
- domains[name].start(noConsole=True)
- except DomainError, ex:
- FAIL(str(ex))
-
-cmd_add_1 = "xm pool-cpu-add Pool-1 %s" % cpu
-cmd_rem_1 = "xm pool-cpu-remove Pool-1 %s" % cpu
-cmd_add_2 = "xm pool-cpu-add Pool-2 %s" % cpu
-cmd_rem_2 = "xm pool-cpu-remove Pool-2 %s" % cpu
-
-for i in range(25):
- traceCommand(cmd_add_1)
- traceCommand(cmd_rem_1)
- traceCommand(cmd_add_2)
- traceCommand(cmd_rem_2)
-
-destroyAllDomUs()
-for pool in pool_names:
- destroyPool(pool, True)
-
diff --git a/tools/xm-test/tests/cpupool/04_cpupool_migrate.py b/tools/xm-test/tests/cpupool/04_cpupool_migrate.py
deleted file mode 100644
index 2eeacd4..0000000
--- a/tools/xm-test/tests/cpupool/04_cpupool_migrate.py
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/usr/bin/python
-
-import sys
-import re
-import time
-
-from XmTestLib import *
-from pools import *
-
-
-
-#
-# Check requirements of test case
-# - min 2 free cpus (not assigned to a pool)
-#
-if int(getInfo("free_cpus")) < 2:
- SKIP("Need at least 2 free cpus")
-
-
-
-#
-# Create 2 pools with one cpu per pool.
-#
-createStdPool({'name' : 'Pool-1'})
-createStdPool({'name' : 'Pool-2'})
-
-
-
-#
-# Create a domain with vcpus=1 in Pool-0.
-# Migrate it to one of the created pools afterwards to the other pool
-#
-name = "TestDomPool-1"
-domain = XmTestDomain(extraConfig={'pool' : 'Pool-0'}, name=name)
-try:
- domain.start(noConsole=True)
-except DomainError, ex:
- FAIL(str(e))
-if not domInPool(name, 'Pool-0'):
- FAIL("missing '%s' in Pool-0" % name)
-
-if not migrateToPool(name, 'Pool-1'):
- FAIL("missing '%s' in Pool-1" % name)
-if not migrateToPool(name, 'Pool-2'):
- FAIL("missing '%s' in Pool-2" % name)
-
-
-
-#
-# Create a domain in Pool-0.
-# Migrate it to one of the created pools afterwards to the other pool
-#
-name = "TestDomPool-2"
-domain = XmTestDomain(extraConfig={'pool' : 'Pool-0'}, name=name)
-try:
- domain.start(noConsole=True)
-except DomainError, ex:
- FAIL(str(e))
-if not domInPool(name, 'Pool-0'):
- FAIL("missing '%s' in Pool-0" % name)
-
-if not migrateToPool(name, 'Pool-1'):
- FAIL("missing '%s' in Pool-1" % name)
-if not migrateToPool(name, 'Pool-2'):
- FAIL("missing '%s' in Pool-2" % name)
-
-
-
-#
-# Migrate other domains between pools
-#
-for cnt in range(10):
- for pool in ['Pool-0', 'Pool-1', 'Pool-2']:
- for domain in getRunningDomains():
- if domain != 'Domain-0':
- if not migrateToPool(domain, pool):
- FAIL("missing '%s' in %s" % (domain, pool))
-
-
-#
-# Cleanup
-#
-cleanupPoolsDomains()
-
diff --git a/tools/xm-test/tests/cpupool/Makefile.am b/tools/xm-test/tests/cpupool/Makefile.am
deleted file mode 100644
index e02aaad..0000000
--- a/tools/xm-test/tests/cpupool/Makefile.am
+++ /dev/null
@@ -1,22 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_cpupool_basic_pos.test \
- 02_cpupool_manage_pos.test \
- 03_cpupool_domain.test \
- 04_cpupool_migrate.test
-
-EXTRA_DIST = $(TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
-
diff --git a/tools/xm-test/tests/cpupool/pool1.cfg b/tools/xm-test/tests/cpupool/pool1.cfg
deleted file mode 100644
index 21c26b7..0000000
--- a/tools/xm-test/tests/cpupool/pool1.cfg
+++ /dev/null
@@ -1 +0,0 @@
-name="Pool-1"
diff --git a/tools/xm-test/tests/cpupool/pools.py b/tools/xm-test/tests/cpupool/pools.py
deleted file mode 100644
index 944104a..0000000
--- a/tools/xm-test/tests/cpupool/pools.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/python
-
-
-from XmTestLib import *
-
-def checkRequirements():
- # - min 4 cpus
- # - only Pool-0 defined
- nr_cpus = int(getInfo("nr_cpus"))
- if nr_cpus < 4:
- SKIP("Need at least 4 cpus for pool tests")
- if len(getPoolList()) > 1:
- SKIP("More than one pool already defined")
-
- # reduce Pool-0 to CPU-0
- traceCommand("xm pool-cpu-add Pool-0 0")
- for i in range(1, nr_cpus):
- traceCommand("xm pool-cpu-remove Pool-0 %s" % i)
-
-def createStdPool(add_param=None):
- cmd = "xm pool-create pool1.cfg "
- if add_param:
- for k,v in add_param.items():
- cmd += "%s=%s " % (k,v)
- status, output = traceCommand(cmd)
- if status != 0 or "Traceback" in output:
- raise XmError("xm failed", trace=output, status=status)
-
-def deletePool(name):
- cmd = "xm pool-delete %s" % name
- status, output = traceCommand(cmd)
- if status != 0 or "Traceback" in output:
- raise XmError("xm failed", trace=output, status=status)
-
-def destroyPool(name, delete_on_xenapi=False):
- cmd = "xm pool-destroy %s" % name
- status, output = traceCommand(cmd)
- if status != 0 or "Traceback" in output:
- raise XmError("xm failed", trace=output, status=status)
- if os.getenv("XM_USES_API") and delete_on_xenapi:
- deletePool(name)
-
-def getPoolList():
- status, output = traceCommand("xm pool-list")
- if status != 0 or "Traceback" in output:
- raise XmError("xm failed", trace=output, status=status)
- lines = output.splitlines()
- pools = []
- for l in lines[1:]:
- elms = l.split(" ", 1)
- pools.append(elms[0]);
- return pools
-
-def domInPool(dom, pool):
- cmd = "xm list --pool=%s" % pool
- status, output = traceCommand(cmd)
- if status != 0 or "Traceback" in output:
- raise XmError("xm failed", trace=output, status=status)
- return re.search(dom, output) != None
-
-def migrateToPool(dom, pool):
- status, output = traceCommand("xm pool-migrate %s %s" % (dom, pool))
- if status != 0 or "Traceback" in output:
- raise XmError("xm failed", trace=output, status=status)
- return domInPool(dom, pool)
-
-def cleanupPoolsDomains():
- destroyAllDomUs()
- for pool in getPoolList():
- if pool != 'Pool-0':
- destroyPool(pool, True)
-
-def waitForDomain(name):
- for i in range(10):
- if not isDomainRunning(name):
- break
- time.sleep(1)
-
diff --git a/tools/xm-test/tests/create/01_create_basic_pos.py b/tools/xm-test/tests/create/01_create_basic_pos.py
deleted file mode 100644
index 20bf533..0000000
--- a/tools/xm-test/tests/create/01_create_basic_pos.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-import sys
-import re
-import time
-
-from XmTestLib import *
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-if int(getInfo("free_memory")) < domain.config.getOpt("memory"):
- SKIP("This test needs %i MB of free memory (%i MB avail)" %
- (domain.config.getOpt("memory"), int(getInfo("free_memory"))))
-
-# Start it
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- # Run 'ls'
- run = console.runCmd("ls")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-# Save a transcript for human review
-saveLog(console.getHistory())
-
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
-
-# Check the output of 'ls'
-
-if not re.search("proc", run["output"]):
- if verbose:
- print run["output"]
- FAIL("'ls' output looks wrong (didn't see /proc)")
diff --git a/tools/xm-test/tests/create/02_create_noparm_neg.py b/tools/xm-test/tests/create/02_create_noparm_neg.py
deleted file mode 100644
index 54f8828..0000000
--- a/tools/xm-test/tests/create/02_create_noparm_neg.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm create")
-eyecatcher = "Error:"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm create returned invalid %i != 0" % status)
-elif where == -1:
- FAIL("xm create failed to report error on missing args")
-
diff --git a/tools/xm-test/tests/create/03_create_badparm_neg.py b/tools/xm-test/tests/create/03_create_badparm_neg.py
deleted file mode 100644
index 2a64cf3..0000000
--- a/tools/xm-test/tests/create/03_create_badparm_neg.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-# Test description:
-# Negative Test:
-# Test for creating domain with non existent option in the command line.
-# Verify fail.
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm create -x")
-eyecatcher = "Error:"
-where = output.find(eyecatcher)
-if where == -1:
- FAIL("xm create failed to report error on bad arg")
diff --git a/tools/xm-test/tests/create/04_create_conflictname_neg.py b/tools/xm-test/tests/create/04_create_conflictname_neg.py
deleted file mode 100644
index 7faa0b2..0000000
--- a/tools/xm-test/tests/create/04_create_conflictname_neg.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-# Test Description:
-# Negative Test:
-# Test for creating domains with same name. Verify fail.
-
-import sys
-import re
-
-from XmTestLib import *
-
-# Create a domain with name "default" (default XmTestDomain, with our ramdisk)
-domain1 = XmTestDomain("default")
-
-#start it
-try:
- domain1.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain1 because:"
- print e.extra
- FAIL(str(e))
-
-# Create second domain with same name "default"
-domain2 = XmTestDomain("default")
-
-#start it
-eyecatcher = "Pass"
-try:
- domain2.start(noConsole=True)
-except DomainError, e:
- eyecatcher = "Fail"
- # Stop the domain1 (nice shutdown)
- domain1.stop()
-
-if eyecatcher != "Fail":
- domain2.stop()
- FAIL("xm create let me create a duplicate-named domain!")
diff --git a/tools/xm-test/tests/create/06_create_mem_neg.py b/tools/xm-test/tests/create/06_create_mem_neg.py
deleted file mode 100644
index 8584b35..0000000
--- a/tools/xm-test/tests/create/06_create_mem_neg.py
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-# Test Description:
-# Negative Tests:
-# Test 1: Test for creating domain with mem=0. Verify fail
-# Test 2: Test for creating domain with mem>sys_mem. Verify fail
-
-import sys
-import re
-import time
-
-from XmTestLib import *
-
-rdpath = os.environ.get("RD_PATH")
-if not rdpath:
- rdpath = "../ramdisk"
-
-# Test 1: create a domain with mem=0
-config1 = {"memory": 0}
-domain1=XmTestDomain(extraConfig=config1)
-
-try:
- domain1.start(noConsole=True)
- eyecatcher1 = "Created"
-except DomainError, e:
- eyecatcher1 = "Fail"
-
-if eyecatcher1 != "Fail":
- domain1.stop()
- FAIL("xm create let me create a domain with 0 memory")
-
-
-# Test 2: create a domain with mem>sys_mem
-
-mem = int(getInfo("total_memory"))
-extreme_mem = mem + 100
-
-config2 = {"memory": extreme_mem}
-domain2=XmTestDomain(extraConfig=config2)
-
-try:
- domain2.start(noConsole=True)
- eyecatcher2 = "Created"
-except DomainError, e:
- eyecatcher2 = "Fail"
-
-if eyecatcher2 != "Fail":
- domain2.stop()
- FAIL("xm create let me create a domain with mem > sys_mem")
-
diff --git a/tools/xm-test/tests/create/07_create_mem64_pos.py b/tools/xm-test/tests/create/07_create_mem64_pos.py
deleted file mode 100644
index f9ed878..0000000
--- a/tools/xm-test/tests/create/07_create_mem64_pos.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-# Test Description:
-# Positive Test
-# Test for creating domain with mem=64.
-
-import sys
-import re
-import time
-
-from XmTestLib import *
-
-rdpath = os.environ.get("RD_PATH")
-if not rdpath:
- rdpath = "../ramdisk"
-
-#get current free memory info
-mem = int(getInfo("free_memory"))
-if mem < 64:
- SKIP("This test needs 64 MB of free memory (%i MB avail)" % mem)
-
-#create a domain with mem=64
-config = {"memory": 64}
-domain_mem64=XmTestDomain(extraConfig=config)
-
-#start it
-try:
- domain_mem64.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain_mem64 because:"
- print e.extra
- FAIL(str(e))
-
-#verify it is running with 64MB mem
-
-eyecatcher1 = str(isDomainRunning(domain_mem64.getName()))
-if eyecatcher1 != "True":
- FAIL("Failed to verify that a 64MB domain started")
-
-eyecatcher2 = getDomMem(domain_mem64.getName())
-if eyecatcher2 not in range(62, 65):
- FAIL("Started domain with 64MB, but it got %i MB" % eyecatcher2)
-
-#stop the domain (nice shutdown)
-domain_mem64.stop()
diff --git a/tools/xm-test/tests/create/08_create_mem128_pos.py b/tools/xm-test/tests/create/08_create_mem128_pos.py
deleted file mode 100644
index f8acd4e..0000000
--- a/tools/xm-test/tests/create/08_create_mem128_pos.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-# Test Description:
-# Positive Test
-# Test for creating domain with mem=.
-
-import sys
-import re
-import time
-
-from XmTestLib import *
-
-rdpath = os.environ.get("RD_PATH")
-if not rdpath:
- rdpath = "../ramdisk"
-
-#get current free memory info
-mem = int(getInfo("free_memory"))
-if mem < 128:
- SKIP("This test needs 128 MB of free memory (%i MB avail)" % mem)
-
-#create a domain with mem=128
-config={"memory": 128}
-domain_mem128=XmTestDomain(extraConfig=config)
-
-#start it
-try:
- domain_mem128.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain_mem128 because:"
- print e.extra
- FAIL(str(e))
-
-#verify it is running with 128MB mem
-
-eyecatcher1 = str(isDomainRunning(domain_mem128.getName()))
-if eyecatcher1 != "True":
- FAIL("Failed to verify that a 128MB domain started")
-
-eyecatcher2 = getDomMem(domain_mem128.getName())
-if eyecatcher2 not in range(126, 129):
- FAIL("Started domain with 128MB, but it got %i MB" % eyecatcher2)
-
-#stop the domain (nice shutdown)
-domain_mem128.stop()
diff --git a/tools/xm-test/tests/create/09_create_mem256_pos.py b/tools/xm-test/tests/create/09_create_mem256_pos.py
deleted file mode 100644
index 71c2e1b..0000000
--- a/tools/xm-test/tests/create/09_create_mem256_pos.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-# Test Description:
-# Positive Test
-# Test for creating domain with mem=256.
-
-import sys
-import re
-import time
-
-from XmTestLib import *
-
-rdpath = os.environ.get("RD_PATH")
-if not rdpath:
- rdpath = "../ramdisk"
-
-#get current free memory info
-mem = int(getInfo("free_memory"))
-if mem < 256:
- SKIP("This test needs 256 MB of free memory (%i MB avail)" % mem)
-
-#create a domain with mem=256
-config = {"memory": 256}
-domain_mem256=XmTestDomain(extraConfig=config)
-
-#start it
-try:
- domain_mem256.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain_mem256 because:"
- print e.extra
- FAIL(str(e))
-
-#verify it is running with 256MB mem
-
-eyecatcher1 = str(isDomainRunning(domain_mem256.getName()))
-if eyecatcher1 != "True":
- FAIL("Failed to verify that a 256MB domain started")
-
-eyecatcher2 = getDomMem(domain_mem256.getName())
-if eyecatcher2 not in range(254, 257):
- FAIL("Started domain with 256MB, but it got %i MB" % eyecatcher2)
-
-#stop the domain (nice shutdown)
-domain_mem256.stop()
diff --git a/tools/xm-test/tests/create/10_create_fastdestroy.py b/tools/xm-test/tests/create/10_create_fastdestroy.py
deleted file mode 100644
index 3f392d2..0000000
--- a/tools/xm-test/tests/create/10_create_fastdestroy.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-
-import re
-
-#
-# Check to see if the output resembles the
-# "No such process error"
-#
-def check_for_NSP_error(output):
- if re.search("XendError.*No such process", output):
- return "Bugzilla bug #234"
- else:
- return None
-
-def check_for_DUP_error(output):
- if re.search("Error.*already exists\!", output):
- return "Xend reported duplicate domain (stale state?)"
- else:
- return None
-
-i = 0
-
-for i in range(0,50):
- domain = XmTestDomain("testdomain")
- try:
- domain.start(noConsole=True)
- except DomainError,e:
- print "Failed: " + e.extra
- NSPerror = check_for_NSP_error(e.extra)
- DUPerror = check_for_DUP_error(e.extra)
- if NSPerror:
- FAIL(NSPerror)
- elif DUPerror:
- FAIL(DUPerror)
- else:
- FAIL("xm create returned invalid status: %i" % e.errorcode)
- domain.destroy()
-
diff --git a/tools/xm-test/tests/create/11_create_concurrent_pos.py b/tools/xm-test/tests/create/11_create_concurrent_pos.py
deleted file mode 100644
index fd8f4dd..0000000
--- a/tools/xm-test/tests/create/11_create_concurrent_pos.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Authors: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-
-import time
-import random
-
-if ENABLE_HVM_SUPPORT:
- MAX_DOMS = getMaxHVMDomains()
- if MAX_DOMS > 50:
- MAX_DOMS = 50
-else:
- MAX_DOMS = 50
-
-MIN_DOMS = 5
-MEM_PER_DOM = minSafeMem()
-
-domains = []
-console = []
-
-free_mem = int(getInfo("free_memory"))
-
-NUM_DOMS = free_mem / MEM_PER_DOM
-
-if NUM_DOMS < MIN_DOMS:
- SKIP("Need %i MB of RAM to start %i@%iMB domains! (%i MB avail)" %
- (MIN_DOMS * MEM_PER_DOM, MIN_DOMS, MEM_PER_DOM,
- free_mem))
-
-if NUM_DOMS > MAX_DOMS:
- if verbose:
- print "*** %i doms is too many: capping at %i" % (NUM_DOMS, MAX_DOMS)
- NUM_DOMS = MAX_DOMS
-
-if verbose:
- print "Watch out! I'm trying to create %i DomUs!" % NUM_DOMS
-
-for d in range(0, NUM_DOMS):
- dom = XmTestDomain(name="11_create_%i" % d,
- extraConfig={"memory":MEM_PER_DOM})
-
- try:
- cons = dom.start()
- except DomainError, e:
- if verbose:
- print str(e)
- FAIL("[%i] Failed to create domain" % d)
-
- try:
- cons.runCmd("ls")
- except ConsoleError, e:
- FAIL("[%i] Failed to attach console to %s" % (d, dom.getName()))
-
- domains.append(dom)
- console.append(cons)
-
- if verbose:
- print "[%i] Started %s" % (d, dom.getName())
-
-
-# If we make it here, we will test several of the DomUs consoles
-
-for i in range(0,5):
- c = random.randint(0, NUM_DOMS-1)
-
- if verbose:
- print "Testing console of %s" % domains[c].getName()
-
- try:
- run = console[c].runCmd("ls")
- except ConsoleError, e:
- FAIL(str(e))
-
- if run["return"] != 0:
- FAIL("'ls' returned invalid %i != 0" % run["return"])
diff --git a/tools/xm-test/tests/create/12_create_concurrent_stress_pos.py b/tools/xm-test/tests/create/12_create_concurrent_stress_pos.py
deleted file mode 100644
index 5235491..0000000
--- a/tools/xm-test/tests/create/12_create_concurrent_stress_pos.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Authors: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-
-import time
-
-DOMS=5
-MEM=minSafeMem()
-DUR=60
-
-domains = []
-
-free_mem = int(getInfo("free_memory"))
-NUM_DOMS = int(free_mem / MEM)
-
-if NUM_DOMS < DOMS:
- SKIP("Need %i MB of RAM to start %i@%iMB domains! (%i MB avail)" %
- (DOMS * MEM, DOMS, MEM, free_mem))
-
-for i in range(0,DOMS):
- dom = XmTestDomain(extraConfig={"memory" : MEM})
-
- try:
- cons = dom.start()
- except DomainError, e:
- if verbose:
- print str(e)
- FAIL("Failed to start %s" % dom.getName())
-
- if verbose:
- print "[%i/%i] Started %s" % (i, DOMS, dom.getName())
-
- domains.append([dom, cons])
-
-# Started DOMS domains, now we put them to work
-
-for d, c in domains:
- if verbose:
- print "Starting task on %s" % d.getName()
- c.sendInput("gzip -c </dev/zero >/dev/null &\n")
-
-if verbose:
- print "Waiting %i seconds..." % DUR
-
-time.sleep(DUR)
-
-for d, c in domains:
-
- if verbose:
- print "Testing domain %s..." % d.getName()
-
- run = c.runCmd("ls")
-
- if run["return"] != 0:
- FAIL("Domain %s didn't survive!" % d.getName())
-
diff --git a/tools/xm-test/tests/create/13_create_multinic_pos.py b/tools/xm-test/tests/create/13_create_multinic_pos.py
deleted file mode 100644
index 585754b..0000000
--- a/tools/xm-test/tests/create/13_create_multinic_pos.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-
-# The device model, qemu-dm, only supports 8 MAX_NICS currently.
-if ENABLE_HVM_SUPPORT:
- MAX_NICS = 8
-else:
- MAX_NICS = 10
-
-for i in range(0,MAX_NICS):
- domain = XmTestNetDomain()
-
- try:
- console = domain.start()
- except DomainError, e:
- FAIL("(%i nics) " % i + str(e))
-
- try:
- console.runCmd("ls")
- except ConsoleError, e:
- FAIL("(%i nics) Console didn't respond: probably crashed!" % i)
-
- domain.destroy()
diff --git a/tools/xm-test/tests/create/14_create_blockroot_pos.py b/tools/xm-test/tests/create/14_create_blockroot_pos.py
deleted file mode 100644
index 79dd622..0000000
--- a/tools/xm-test/tests/create/14_create_blockroot_pos.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Authors: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-
-import os
-import time
-
-rdpath = getRdPath()
-
-# status, output = traceCommand("losetup -f %s" % rdpath)
-# if status != 0:
-# FAIL("Unable to get a free loop device")
-#
-# if verbose:
-# print "Using %s" % output
-
-if ENABLE_HVM_SUPPORT:
- config = None
-else:
- config = {"root" : "/dev/hda1",
- "disk" : "file:%s/initrd.img,hda1,w" % rdpath
- }
-domain = XmTestDomain(name="14_create_blockroot", extraConfig=config)
-
-try:
- console = domain.start()
-except DomainError, e:
- FAIL(str(e))
-
-#waitForBoot()
-
-try:
-# console.debugMe = True
- run = console.runCmd("ls")
-
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-if run["return"] != 0:
- FAIL("DomU 'ls' failed")
diff --git a/tools/xm-test/tests/create/15_create_smallmem_pos.py b/tools/xm-test/tests/create/15_create_smallmem_pos.py
deleted file mode 100644
index d7797c6..0000000
--- a/tools/xm-test/tests/create/15_create_smallmem_pos.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-
-# Create a domain with the minimum memory allocation
-MEM = minSafeMem()
-
-domain = XmTestDomain(extraConfig={"memory": MEM,
- "extra" :"mem=%iM" % MEM})
-
-try:
- console = domain.start()
-except DomainError, e:
- FAIL("Unable to start a domain with %i MB" % MEM)
-
-try:
- console.runCmd("ls")
-except ConsoleError, e:
- if e.reason == RUNAWAY:
- FAIL("Bug #380: Starting a console with %i MB crashed the console daemon" % MEM)
- else:
- FAIL("Starting a console with %i MB failed: domain dies immediately!" % MEM)
-
-domain.destroy()
diff --git a/tools/xm-test/tests/create/16_create_smallmem_neg.py b/tools/xm-test/tests/create/16_create_smallmem_neg.py
deleted file mode 100644
index 6a3f417..0000000
--- a/tools/xm-test/tests/create/16_create_smallmem_neg.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-import re
-from XmTestLib import *
-
-# This is under the default lower limit of 32 and we expect this test
-# to fail. 16MBs isn't enough for the -xen kernel.
-MEM = 16
-
-domain = XmTestDomain(extraConfig={"memory": MEM,
- "extra" :"mem=%iM" % MEM})
-
-try:
- console = domain.start()
- console.runCmd("ls")
-except DomainError, e:
- if not re.search('^Error: Domain memory must be at least \d+ KB', e.extra):
- # PPC gracefully fails like this, rather than crashing.
- FAIL("Unable to start a domain with %i MB" % MEM)
-except ConsoleError, e:
- if e.reason == RUNAWAY:
- print "Domain with %i MB has runaway console as expected" % MEM
-else:
- FAIL("Starting a console with %i MB passed, expected test to fail" % MEM)
-
-print "Starting a domain with %i MB failed as expected" % MEM
-domain.destroy()
diff --git a/tools/xm-test/tests/create/Makefile.am b/tools/xm-test/tests/create/Makefile.am
deleted file mode 100644
index 6dcd6a0..0000000
--- a/tools/xm-test/tests/create/Makefile.am
+++ /dev/null
@@ -1,33 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_create_basic_pos.test \
- 02_create_noparm_neg.test \
- 03_create_badparm_neg.test \
- 04_create_conflictname_neg.test \
- 06_create_mem_neg.test \
- 07_create_mem64_pos.test \
- 08_create_mem128_pos.test \
- 09_create_mem256_pos.test \
- 10_create_fastdestroy.test \
- 11_create_concurrent_pos.test \
- 12_create_concurrent_stress_pos.test \
- 13_create_multinic_pos.test \
- 14_create_blockroot_pos.test \
- 15_create_smallmem_pos.test \
- 16_create_smallmem_neg.test
-
-EXTRA_DIST = $(TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
-
diff --git a/tools/xm-test/tests/destroy/01_destroy_basic_pos.py b/tools/xm-test/tests/destroy/01_destroy_basic_pos.py
deleted file mode 100644
index 02e31d6..0000000
--- a/tools/xm-test/tests/destroy/01_destroy_basic_pos.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-
-import sys
-import re
-import time
-
-from XmTestLib import *
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-# Start it
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- # Run 'ls'
- run = console.runCmd("ls")
-except ConsoleError, e:
- FAIL(str(e))
-
-# Close the console
-domain.closeConsole()
-
-# Check the output of 'ls'
-if not re.search("proc", run["output"]):
- FAIL("'ls' output looks wrong (Didn't see proc)")
-
-# destroy domain - positive test
-status, output = traceCommand("xm destroy %s" % domain.getName())
-if status != 0:
- FAIL("xm destroy returned invalid %i != 0" % status)
diff --git a/tools/xm-test/tests/destroy/02_destroy_noparm_neg.py b/tools/xm-test/tests/destroy/02_destroy_noparm_neg.py
deleted file mode 100644
index 8fadb1e..0000000
--- a/tools/xm-test/tests/destroy/02_destroy_noparm_neg.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm destroy")
-eyecatcher = "Error:"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm destroy returned invalid %i != 0" % status)
-elif where == -1:
- FAIL("xm destroy failed to report error for missing arg")
diff --git a/tools/xm-test/tests/destroy/03_destroy_nonexist_neg.py b/tools/xm-test/tests/destroy/03_destroy_nonexist_neg.py
deleted file mode 100644
index 9520a65..0000000
--- a/tools/xm-test/tests/destroy/03_destroy_nonexist_neg.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm destroy -x")
-eyecatcher = "Error:"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm destroy returned invalid %i != 0" % status)
-elif where == -1:
- FAIL("xm destroy failed to report error for bad arg")
diff --git a/tools/xm-test/tests/destroy/04_destroy_badparm_neg.py b/tools/xm-test/tests/destroy/04_destroy_badparm_neg.py
deleted file mode 100644
index 179b4d0..0000000
--- a/tools/xm-test/tests/destroy/04_destroy_badparm_neg.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm destroy 6666")
-eyecatcher = "Error:"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm destroy returned invalid %i != 0" % status)
-elif where == -1:
- FAIL("xm destroy failed to report error for bad domid")
diff --git a/tools/xm-test/tests/destroy/05_destroy_byid_pos.py b/tools/xm-test/tests/destroy/05_destroy_byid_pos.py
deleted file mode 100644
index 655b7a3..0000000
--- a/tools/xm-test/tests/destroy/05_destroy_byid_pos.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-# Li Ge <lge at us.ibm.com>
-
-# Positive Test:
-# Test Description:
-# 1. Create a domain
-# 2. Destroy the domain by id
-
-import sys
-import re
-import time
-
-from XmTestLib import *
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-# Start it
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-# destroy domain - positive test
-status, output = traceCommand("xm destroy %s" % domain.getId())
-if status != 0:
- FAIL("xm destroy returned invalid %i != 0" % status)
diff --git a/tools/xm-test/tests/destroy/06_destroy_dom0_neg.py b/tools/xm-test/tests/destroy/06_destroy_dom0_neg.py
deleted file mode 100644
index 6ea47f4..0000000
--- a/tools/xm-test/tests/destroy/06_destroy_dom0_neg.py
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm destroy 0")
-if status == 0:
- FAIL("xm destroy returned bad status, expected non 0, status is: %i" % status)
-elif not re.search("Error", output, re.I):
- FAIL("xm destroy returned bad output, expected Error:, output is: %s" % output)
diff --git a/tools/xm-test/tests/destroy/07_destroy_stale_pos.py b/tools/xm-test/tests/destroy/07_destroy_stale_pos.py
deleted file mode 100644
index 83c796a..0000000
--- a/tools/xm-test/tests/destroy/07_destroy_stale_pos.py
+++ /dev/null
@@ -1,133 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-#
-# 10 start a domain
-# 20 destroy it
-# 30 try next xm command
-# 40 goto 10
-
-from XmTestLib import *
-
-import re
-
-def test_mem_set(name):
- status, output = traceCommand("xm mem-set %s 32" % name, logOutput=True)
-
- if status == 0:
- FAIL("mem-set worked after domain destroy!")
- if not re.search("[Ee]rror", output):
- FAIL("mem-set failed to report error after destroy!")
-
-def test_pause(name):
- status, output = traceCommand("xm pause %s" % name, logOutput=True)
-
- if status == 0:
- FAIL("pause worked after domain destroy!")
- if not re.search("[Ee]rror", output):
- FAIL("pause failed to report error after destroy!")
-
-def test_unpause(name):
- status, output = traceCommand("xm unpause %s" % name, logOutput=True)
-
- if status == 0:
- FAIL("unpause worked after domain destroy!")
- if not re.search("[Ee]rror", output):
- FAIL("unpause failed to report error after destroy!")
-
-def test_reboot(name):
- status, output = traceCommand("xm reboot %s" % name, logOutput=True)
-
- if status == 0:
- FAIL("reboot worked after domain destroy!")
- if not re.search("[Ee]rror", output):
- FAIL("reboot failed to report error after destroy!")
-
-def test_save(name):
- status, output = traceCommand("xm save %s /tmp/foo" % name, logOutput=True)
-
- if status == 0:
- FAIL("save worked after domain destroy!")
- if not re.search("[Ee]rror", output):
- FAIL("save failed to report error after destroy!")
-
-def test_block_list(name):
- status, output = traceCommand("xm block-list %s" % name, logOutput=True)
-
- if status == 0:
- FAIL("block-list worked after domain destroy!")
- if not re.search("[Ee]rror", output):
- FAIL("block-list failed to report error after destroy!")
-
-def test_shutdown(name):
- status, output = traceCommand("xm shutdown %s" % name, logOutput=True)
-
- if status == 0:
- FAIL("shutdown worked after domain destroy!")
- if not re.search("[Ee]rror", output):
- FAIL("shutdown failed to report error after destroy!")
-
-def test_domname(name):
- status, output = traceCommand("xm domname %s" % name)
-
- if status == 0:
- FAIL("domname worked after domain destroy!")
- if not re.search("[Ee]rror", output):
- FAIL("domname failed to report error after destroy!")
-
-def test_domid(name):
- status, output = traceCommand("xm domid %s" % name)
-
- if status == 0:
- FAIL("domid worked after domain destroy!")
- if not re.search("[Ee]rror", output):
- FAIL("domid failed to report error after destroy!")
-
-def test_destroy(name):
- status, output = traceCommand("xm destroy %s" % name)
-
- if status == 0:
- FAIL("destroy worked after domain destroy!")
- if not re.search("[Ee]rror", output):
- FAIL("destroy failed to report error after destroy!")
-
-def test_sysrq(name):
- status, output = traceCommand("xm sysrq %s s" % name)
-
- if status == 0:
- FAIL("sysrq worked after domain destroy!")
- if not re.search("[Ee]rror", output):
- FAIL("sysrq failed to report error after destroy!")
-
-def runTests(tests):
- for test in tests:
- domain = XmTestDomain()
-
- # Create a domain
-
- try:
- console = domain.start()
- except DomainError, e:
- FAIL(str(e))
-
- try:
- console.runCmd("ls")
- except ConsoleError, e:
- FAIL(str(e))
-
- # Destroy it
-
- domain.destroy()
-
- # Run test
-
- test(domain.getName())
-
-tests = [test_mem_set, test_pause, test_unpause, test_reboot, test_save,
- test_block_list, test_shutdown, test_domid, test_domname]
-
-if verbose:
- print "Running stale tests"
-runTests(tests)
diff --git a/tools/xm-test/tests/destroy/Makefile.am b/tools/xm-test/tests/destroy/Makefile.am
deleted file mode 100644
index 86088be..0000000
--- a/tools/xm-test/tests/destroy/Makefile.am
+++ /dev/null
@@ -1,27 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_destroy_basic_pos.test \
- 02_destroy_noparm_neg.test \
- 03_destroy_nonexist_neg.test \
- 04_destroy_badparm_neg.test \
- 05_destroy_byid_pos.test \
- 06_destroy_dom0_neg.test \
- 07_destroy_stale_pos.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
-
diff --git a/tools/xm-test/tests/dmesg/01_dmesg_basic_pos.py b/tools/xm-test/tests/dmesg/01_dmesg_basic_pos.py
deleted file mode 100644
index 9930539..0000000
--- a/tools/xm-test/tests/dmesg/01_dmesg_basic_pos.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm dmesg")
-if status != 0:
- FAIL("xm dmesg returned invalid %i != 0" % status)
-elif not re.search("\(XEN\)", output):
- FAIL("xm dmesg didn't output and (XEN) lines")
-
diff --git a/tools/xm-test/tests/dmesg/02_dmesg_basic_neg.py b/tools/xm-test/tests/dmesg/02_dmesg_basic_neg.py
deleted file mode 100644
index e074c0d..0000000
--- a/tools/xm-test/tests/dmesg/02_dmesg_basic_neg.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm dmesg -x")
-eyecatcher = "Error:"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm dmesg returned invalid %i != 0" % status)
-elif where == -1:
- FAIL("xm dmesg failed to report error for bad arg")
-
diff --git a/tools/xm-test/tests/dmesg/Makefile.am b/tools/xm-test/tests/dmesg/Makefile.am
deleted file mode 100644
index 50bcec5..0000000
--- a/tools/xm-test/tests/dmesg/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_dmesg_basic_pos.test 02_dmesg_basic_neg.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
-
diff --git a/tools/xm-test/tests/domid/01_domid_basic_pos.py b/tools/xm-test/tests/domid/01_domid_basic_pos.py
deleted file mode 100644
index 7dea343..0000000
--- a/tools/xm-test/tests/domid/01_domid_basic_pos.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm domid Domain-0")
-if status != 0:
- FAIL("domid(Domain-0) returned invalid %i != 0" % status)
-elif output != "0":
- if verbose:
- print output
- FAIL("domid(Domain-0) failed to report domid 0")
diff --git a/tools/xm-test/tests/domid/02_domid_basic_neg.py b/tools/xm-test/tests/domid/02_domid_basic_neg.py
deleted file mode 100644
index c2a1b01..0000000
--- a/tools/xm-test/tests/domid/02_domid_basic_neg.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm domid non_existent_domain")
-if status == 0:
- FAIL("domid(non_existent_domain) returned invalid %i != 0" % status)
-elif not re.search("Error", output):
- FAIL("domid(non_existent_domain) failed to report error")
-
diff --git a/tools/xm-test/tests/domid/Makefile.am b/tools/xm-test/tests/domid/Makefile.am
deleted file mode 100644
index d45a7f4..0000000
--- a/tools/xm-test/tests/domid/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_domid_basic_pos.test 02_domid_basic_neg.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
-
diff --git a/tools/xm-test/tests/domname/01_domname_basic_pos.py b/tools/xm-test/tests/domname/01_domname_basic_pos.py
deleted file mode 100644
index 61e2672..0000000
--- a/tools/xm-test/tests/domname/01_domname_basic_pos.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm domname 0")
-if status != 0:
- FAIL("domname(0) returned invalid %i != 0" % status)
-elif output != "Domain-0":
- if verbose:
- print output
- FAIL("domname(0) failed to return Domain-0 for domid 0")
-
diff --git a/tools/xm-test/tests/domname/02_domname_basic_neg.py b/tools/xm-test/tests/domname/02_domname_basic_neg.py
deleted file mode 100644
index 567bfcb..0000000
--- a/tools/xm-test/tests/domname/02_domname_basic_neg.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm domname 1492")
-if status == 0:
- FAIL("domname(1492) returned invalid: %i != 0" % status)
-elif not re.search("Error", output):
- FAIL("domname(1492) failed to report error for invalid domid")
-
diff --git a/tools/xm-test/tests/domname/Makefile.am b/tools/xm-test/tests/domname/Makefile.am
deleted file mode 100644
index 9a40e62..0000000
--- a/tools/xm-test/tests/domname/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_domname_basic_pos.test 02_domname_basic_neg.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
-
diff --git a/tools/xm-test/tests/enforce_dom0_cpus/01_enforce_dom0_cpus_basic_pos.py b/tools/xm-test/tests/enforce_dom0_cpus/01_enforce_dom0_cpus_basic_pos.py
deleted file mode 100644
index 86da935..0000000
--- a/tools/xm-test/tests/enforce_dom0_cpus/01_enforce_dom0_cpus_basic_pos.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Authors: Dan Smith <danms at us.ibm.com>
-# Ryan Harper <ryanh at us.ibm.com>
-
-# 1) Make sure we have a multi cpu system and dom0 has at
-# least 2 vcpus online.
-# 2) clone standard config (/etc/xen/xend-config.sxp)
-# 3) modify clone with enforce_dom0_cpus=X
-# 4) restart xend with modified config
-# 5) check /proc/cpuinfo for cpu count
-# 6) check xm info 'VCPUs' field to see that only 'enforce_dom0_cpus'
-# number of cpus are online in dom0
-# 7) Restore initial dom0 vcpu state
-# 8) Restart xend with default config
-
-import sys
-import re
-import time
-import os
-
-# what value should dom0_cpus enforce?
-enforce_dom0_cpus=1
-
-from XmTestLib import *
-
-check_status = 1
-max_tries = 10
-
-def reset_vcpu_count():
- status, output = traceCommand("xm vcpu-set 0 %s"%(dom0_online_vcpus))
- if status != 0:
- print "WARNING!!! Unable to set vcpus back to %s, please set manually"\
- %(dom0_online_vcpus)
-
-# 1) Make sure we have a multi cpu system and dom0 has at least 2 vcpus online.
-
-if smpConcurrencyLevel() <= 1:
- print "*** NOTE: This machine does not have more than one physical"
- print " or logical cpu. The vcpu-disable test cannot be run!"
- SKIP("Host not capable of running test")
-
-# count number of online vcpus in dom0
-dom0_online_vcpus = int(getDomInfo("Domain-0", "VCPUs"))
-if dom0_online_vcpus <= 1:
- print "*** NOTE: DOM0 needs at least 2 VCPUs online to run this test"
- print " Please enable additional vcpus if possible via xm vcpu-set"
- SKIP("Host state not capable of running test")
-
-# 2) clone standard config (/etc/xen/xend-config.sxp)
-# 3) modify clone with enforce_dom0_cpus=1
-old_config="/etc/xen/xend-config.sxp"
-new_config ="/tmp/xend-config.sxp"
-cmd = "sed -e 's,dom0-cpus 0,dom0-cpus %s,' %s > %s" % (enforce_dom0_cpus,
- old_config,
- new_config)
-status, output = traceCommand(cmd)
-if check_status and status != 0:
- FAIL("\"%s\" returned invalid %i != 0" %(cmd,status))
-
-
-# 4) restart xend with new config
-os.putenv("XEND_CONFIG", "/tmp/xend-config.sxp")
-status = restartXend()
-os.unsetenv("XEND_CONFIG")
-if check_status and status != 0:
- ns, no = restartXend()
- if ns != 0:
- FAIL("Restarting xend isn't working: something is WAY broken")
- else:
- FAIL("\"%s\" returned invalid %i != 0" %(cmd,status))
-
-# 5) check /proc/cpuinfo for cpu count
-
-# It takes some time for the CPU count to change, on multi-proc systems, so check the number of procs in a loop for 30 seconds.
-#Sleep inside the loop for a second each time.
-timeout = 30
-starttime = time.time()
-while timeout + starttime > time.time():
-# Check /proc/cpuinfo
- cmd = "grep \"^processor\" /proc/cpuinfo | wc -l"
- status, output = traceCommand(cmd)
- if check_status and status != 0:
- reset_vcpu_count()
- restartXend()
- FAIL("\"%s\" returned invalid %i != 0" %(cmd,status))
-# Has it succeeded? If so, we can leave the loop
- if output == str(enforce_dom0_cpus):
- break
-# Sleep for 1 second before trying again
- time.sleep(1)
-if output != str(enforce_dom0_cpus):
- reset_vcpu_count()
- restartXend()
- FAIL("/proc/cpuinfo says xend didn't enforce dom0_cpus (%s != %s)"%(output,
- enforce_dom0_cpus))
-
-# 6) count number of online cpus and see that it matches enforce value
-num_online = int(getDomInfo("Domain-0", "VCPUs"))
-if num_online != enforce_dom0_cpus:
- reset_vcpu_count()
- restartXend()
- FAIL("xm says xend didn't enforce dom0_cpus (%s != %s)" %(num_online,
- enforce_dom0_cpus))
-
-# 7) restore dead processors
-reset_vcpu_count()
-
-# check restore worked
-# Since this also takes time, we will do it in a loop with a 30 second timeout.
-timeout=30
-starttime=time.time()
-while timeout + starttime > time.time():
- num_online = int(getDomInfo("Domain-0", "VCPUs"))
- if num_online == dom0_online_vcpus:
- break
- time.sleep(1)
-if num_online != dom0_online_vcpus:
- restartXend()
- FAIL("failed to restore dom0's VCPUs")
-
-
-# 8) Restart xend with default config
-restartXend()
-
diff --git a/tools/xm-test/tests/enforce_dom0_cpus/Makefile.am b/tools/xm-test/tests/enforce_dom0_cpus/Makefile.am
deleted file mode 100644
index b08000f..0000000
--- a/tools/xm-test/tests/enforce_dom0_cpus/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-
-SUBDIRS =
-
-TESTS = 01_enforce_dom0_cpus_basic_pos.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/help/01_help_basic_pos.py b/tools/xm-test/tests/help/01_help_basic_pos.py
deleted file mode 100644
index 11b84f0..0000000
--- a/tools/xm-test/tests/help/01_help_basic_pos.py
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm help")
-eyecatcher = "Usage:"
-where = output.find(eyecatcher)
-if where == -1:
- FAIL("xm help: didn't see the usage string")
diff --git a/tools/xm-test/tests/help/02_help_basic_neg.py b/tools/xm-test/tests/help/02_help_basic_neg.py
deleted file mode 100644
index 09116ab..0000000
--- a/tools/xm-test/tests/help/02_help_basic_neg.py
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm")
-eyecatcher = "Usage:"
-where = output.find(eyecatcher)
-if where == -1:
- FAIL("xm: didn't display usage when given no arguments")
diff --git a/tools/xm-test/tests/help/03_help_badparm_neg.py b/tools/xm-test/tests/help/03_help_badparm_neg.py
deleted file mode 100644
index 1064a75..0000000
--- a/tools/xm-test/tests/help/03_help_badparm_neg.py
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm -x")
-eyecatcher = "Error:"
-where = output.find(eyecatcher)
-if where == -1:
- FAIL("xm failed to report error for bad arg")
diff --git a/tools/xm-test/tests/help/04_help_long_pos.py b/tools/xm-test/tests/help/04_help_long_pos.py
deleted file mode 100644
index 9e46b7b..0000000
--- a/tools/xm-test/tests/help/04_help_long_pos.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm help --long")
-#print output
-
-eyecatcher = "xm full list of subcommands:"
-where = output.find(eyecatcher)
-if where == -1:
- FAIL("xm help --long failed to show long listing")
diff --git a/tools/xm-test/tests/help/05_help_nonroot_pos.py b/tools/xm-test/tests/help/05_help_nonroot_pos.py
deleted file mode 100644
index 87a395f..0000000
--- a/tools/xm-test/tests/help/05_help_nonroot_pos.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Copyright (C) XenSource Ltd, 2005
-# Author: Dan Smith <danms at us.ibm.com>
-# Author: Woody Marvel <marvel at us.ibm.com>
-# Author: Ewan Mellor <ewan at xensource.com>
-
-from XmTestLib import *
-
-becomeNonRoot()
-
-status, output = traceCommand("xm help")
-eyecatcher = "Usage:"
-where = output.find(eyecatcher)
-if where == -1:
- FAIL("xm help: didn't see the usage string")
diff --git a/tools/xm-test/tests/help/06_help_allcmds.py b/tools/xm-test/tests/help/06_help_allcmds.py
deleted file mode 100644
index 6fbc0b4..0000000
--- a/tools/xm-test/tests/help/06_help_allcmds.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-
-import re
-
-MAX_ARGS = 10
-
-# These commands aren't suitable for this test, so we
-# ignore them
-skipcommands = ["top", "log"]
-
-status, output = traceCommand("xm help --long")
-
-commands = []
-badcommands = []
-
-lines = output.split("\n")
-for l in lines:
- match = re.match("^ ([a-z][^ ]+).*$", l)
- if match:
- commands.append(match.group(1))
-
-for c in commands:
- if c in skipcommands:
- continue
-
- arglist = ""
- for i in range(0,MAX_ARGS+1):
- if i > 0:
- arglist += "%i " % i
-
- status, output = traceCommand("xm %s %s" % (c, arglist))
-
- if output.find("Traceback") != -1:
- badcommands.append(c + " " + arglist)
- if verbose:
- print "Got Traceback: %s %s" % (c, arglist)
-
-if badcommands:
- FAIL("Got a traceback on: %s" % str(badcommands))
diff --git a/tools/xm-test/tests/help/Makefile.am b/tools/xm-test/tests/help/Makefile.am
deleted file mode 100644
index 7319f37..0000000
--- a/tools/xm-test/tests/help/Makefile.am
+++ /dev/null
@@ -1,26 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_help_basic_pos.test \
- 02_help_basic_neg.test \
- 03_help_badparm_neg.test \
- 04_help_long_pos.test \
- 05_help_nonroot_pos.test \
- 06_help_allcmds.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
-
diff --git a/tools/xm-test/tests/info/01_info_basic_pos.py b/tools/xm-test/tests/info/01_info_basic_pos.py
deleted file mode 100644
index 82867b2..0000000
--- a/tools/xm-test/tests/info/01_info_basic_pos.py
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-
-status, output = traceCommand("xm info")
-
-if status != 0:
- FAIL("xm info returned %i != 0" % status)
diff --git a/tools/xm-test/tests/info/02_info_compiledata_pos.py b/tools/xm-test/tests/info/02_info_compiledata_pos.py
deleted file mode 100644
index 9430ecf..0000000
--- a/tools/xm-test/tests/info/02_info_compiledata_pos.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-import re;
-
-from XmTestLib import *
-
-status, output = traceCommand("xm info")
-
-output = re.sub(" +", " ", output)
-
-lines = output.split("\n")
-
-map = {}
-
-for line in lines:
- pieces = line.split(" : ", 1)
-
- if len(pieces) > 1:
- map[pieces[0]] = pieces[1]
-
-for field in ["cores_per_socket", "threads_per_core", "cpu_mhz",
- "total_memory", "free_memory", "xen_major", "xen_minor",
- "xen_pagesize"]:
- val = map[field]
- if not val.isdigit():
- FAIL("Numeric field %s not all-numbers: %s" % (field, val))
-
-# Check cc_compiler
-if not re.match("gcc version", map["cc_compiler"]):
- FAIL("Bad cc_compiler field: %s" % map["cc_compiler"])
-
-# Check cc_compile_by
-if not re.match("[A-z0-9_]+", map["cc_compile_by"]):
- FAIL("Bad cc_compile_by field: %s" % map["cc_compile_by"])
-
-# Check cc_compile_domain
-# --- What should it look like?
-
-
diff --git a/tools/xm-test/tests/info/Makefile.am b/tools/xm-test/tests/info/Makefile.am
deleted file mode 100644
index bf26c09..0000000
--- a/tools/xm-test/tests/info/Makefile.am
+++ /dev/null
@@ -1,22 +0,0 @@
-
-SUBDIRS =
-
-TESTS = 01_info_basic_pos.test \
- 02_info_compiledata_pos.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/list/01_list_basic_pos.py b/tools/xm-test/tests/list/01_list_basic_pos.py
deleted file mode 100644
index 9a7283f..0000000
--- a/tools/xm-test/tests/list/01_list_basic_pos.py
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm list")
-if status != 0:
- FAIL("xm list returned invalid %i != 0" % status)
-elif not re.search("Domain-0", output):
- FAIL("xm list output invalid; didn't see Domain-0")
diff --git a/tools/xm-test/tests/list/02_list_badparm_neg.py b/tools/xm-test/tests/list/02_list_badparm_neg.py
deleted file mode 100644
index 3adbeb9..0000000
--- a/tools/xm-test/tests/list/02_list_badparm_neg.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm list -x")
-eyecatcher = "Error:"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm list returned invalid %i != 0" % status)
-elif where == -1:
- FAIL("xm list failed to report error for bad arg")
diff --git a/tools/xm-test/tests/list/03_list_nonexist_neg.py b/tools/xm-test/tests/list/03_list_nonexist_neg.py
deleted file mode 100644
index 04acbd6..0000000
--- a/tools/xm-test/tests/list/03_list_nonexist_neg.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm list 6666")
-eyecatcher = "Error:"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm list returned invalid %i != 0" % status)
-elif where == -1:
- FAIL("xm list failed to report error for invalid domid")
-
diff --git a/tools/xm-test/tests/list/04_list_goodparm_pos.py b/tools/xm-test/tests/list/04_list_goodparm_pos.py
deleted file mode 100644
index ec0e1cf..0000000
--- a/tools/xm-test/tests/list/04_list_goodparm_pos.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-import sys
-import re
-import time
-
-from XmTestLib import *
-
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-status, output = traceCommand("xm list %s" % domain.getName())
-
-if status != 0:
- FAIL("`xm list %s' failed with invalid status %i != 0" % (domain.getName(), status))
-
-domain.closeConsole()
-domain.stop()
diff --git a/tools/xm-test/tests/list/05_list_long_pos.py b/tools/xm-test/tests/list/05_list_long_pos.py
deleted file mode 100644
index c3843e5..0000000
--- a/tools/xm-test/tests/list/05_list_long_pos.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-
-import re
-
-status, output = traceCommand("xm list --long")
-
-if status != 0:
- FAIL("xm list --long returned invalid %i != 0" % status)
-
-if not re.search("\(domain", output):
- FAIL("long listing missing any (domain ...) root!")
-
-if not re.search("\(domid 0\)", output):
- FAIL("long listing missing (domid 0)!")
-
-if re.search("Traceback", output):
- FAIL("long listing generated a Traceback!")
diff --git a/tools/xm-test/tests/list/06_list_nonroot.py b/tools/xm-test/tests/list/06_list_nonroot.py
deleted file mode 100644
index db81d2f..0000000
--- a/tools/xm-test/tests/list/06_list_nonroot.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Copyright (C) XenSource Ltd, 2005
-# Author: Ewan Mellor <ewan at xensource.com>
-
-from XmTestLib import *
-
-becomeNonRoot()
-
-status, output = traceCommand("xm list")
-eyecatcher = "Error: Most commands need root access"
-where = output.find(eyecatcher)
-if where == -1:
- FAIL("xm list: didn't see the root hint, saw %s" % output)
diff --git a/tools/xm-test/tests/list/Makefile.am b/tools/xm-test/tests/list/Makefile.am
deleted file mode 100644
index 5b58787..0000000
--- a/tools/xm-test/tests/list/Makefile.am
+++ /dev/null
@@ -1,27 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_list_basic_pos.test \
- 02_list_badparm_neg.test \
- 03_list_nonexist_neg.test \
- 04_list_goodparm_pos.test \
- 05_list_long_pos.test \
- 06_list_nonroot.test
-
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
-
diff --git a/tools/xm-test/tests/memmax/01_memmax_badparm_neg.py b/tools/xm-test/tests/memmax/01_memmax_badparm_neg.py
deleted file mode 100644
index a2d37ec..0000000
--- a/tools/xm-test/tests/memmax/01_memmax_badparm_neg.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-## Description: Test xm memmax bad parameter
-
-import re
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Mem-max not supported for HVM domains")
-
-status, output = traceCommand("xm mem-max")
-eyecatcher = "Error:"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm memmax returned invalid %i == 0" % status)
-elif where < 0:
- FAIL("xm memmax failed to report error for missing arg")
-
-
-status, output = traceCommand("xm mem-max 6666")
-eyecatcher = "Error:"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm memmax returned invalid %i == 0" % status)
-elif where < 0:
- FAIL("xm memmax failed to report error for bad arg")
diff --git a/tools/xm-test/tests/memmax/Makefile.am b/tools/xm-test/tests/memmax/Makefile.am
deleted file mode 100644
index c5b041c..0000000
--- a/tools/xm-test/tests/memmax/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_memmax_badparm_neg.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
-
diff --git a/tools/xm-test/tests/memset/01_memset_basic_pos.py b/tools/xm-test/tests/memset/01_memset_basic_pos.py
deleted file mode 100644
index 7e76930..0000000
--- a/tools/xm-test/tests/memset/01_memset_basic_pos.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-##
-## Description:
-## Tests that verify mem-set output and return code
-## 1) Test for xm mem-set
-## create domain,
-## verify domain and ls output,
-## mem-set in dom0,
-## verify with xm list memory change external,
-## verify with xm list memory change internal,
-##
-## Author: Woody Marvel marvel at us.ibm.com
-##
-
-import sys
-import re
-import time
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Mem-set not supported for HVM domains")
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-# Start it
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- # Make sure it's up an running before we continue
- console.runCmd("ls")
-except ConsoleError, e:
- FAIL(str(e))
-
-xen_mem = XenMemory(console)
-
-origmem = xen_mem.get_mem_from_domU()
-newmem = origmem - 1
-
-# set mem-set for less than default
-cmd = "xm mem-set %s %i" % (domain.getName(), newmem)
-status, output = traceCommand(cmd)
-if status != 0:
- if verbose:
- print "mem-set failed:"
- print output
- FAIL("cmd %s returned invalid %i != 0" % (cmd, status))
-
-for i in [1,2,3,4,5,6,7,8,9,10]:
- mem = getDomMem(domain.getName())
- if mem == newmem:
- break
- time.sleep(1)
-
-# verify memory set externally
-mem = getDomMem(domain.getName())
-if not mem:
- FAIL("Failed to get memory amount for domain %s" % domain.getName())
-elif mem != newmem:
- FAIL("Dom0 failed to verify %i MB; got %i MB" % newmem,mem)
-
-# verify memory set internally
-domUmem = xen_mem.get_mem_from_domU()
-
-if domUmem != newmem:
- FAIL("DomU reported incorrect memory amount: %i MB" % (domUmem))
-
-# quiesce everything
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/memset/02_memset_badparm_neg.py b/tools/xm-test/tests/memset/02_memset_badparm_neg.py
deleted file mode 100644
index 9e8fbaf..0000000
--- a/tools/xm-test/tests/memset/02_memset_badparm_neg.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Woody Marvel <marvel at us.ibm.com>
-##
-## Description:
-## Test xm mem-set output and status
-## Negative Tests:
-## 1) Test xm mem_set (no parm)
-## 2) Test xm list (non existent parm)
-## 3) Test xm list (non existent domain)
-##
-##
-## Author: Woody Marvel marvel at us.ibm.com
-##
-
-import re
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Mem-set not supported for HVM domains")
-
-# destroy no parm input - negative test
-status, output = traceCommand("xm mem-set")
-eyecatcher = "Error:"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm mem-set returned invalid %i == 0" % status)
-elif where == -1:
- FAIL("xm mem-set failed to report error for missing arg")
-
-# destroy non existent parm input - negative test
-status, output = traceCommand("xm mem-set -x")
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm mem-set returned invalid %i == 0" % status)
-elif where == -1:
- FAIL("xm mem-set failed to report error for bad arg")
-
-# destroy non existent domain - negative test
-status, output = traceCommand("xm mem-set 6666")
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm mem-set returned invalid %i == 0" % status)
-elif where == -1:
- FAIL("xm mem-set failed to report error for invalid domid")
-
-# destroy non existent domain and memory - negative test
-status, output = traceCommand("xm mem-set 6666 64")
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm mem-set returned invalid %i == -1" % status)
-elif where == -1:
- FAIL("xm mem-set failed to report error for invalid domid")
-
diff --git a/tools/xm-test/tests/memset/03_memset_random_pos.py b/tools/xm-test/tests/memset/03_memset_random_pos.py
deleted file mode 100644
index 2593701..0000000
--- a/tools/xm-test/tests/memset/03_memset_random_pos.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-import random
-import re
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Mem-set not supported for HVM domains")
-
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to start domain:"
- print e.extra
- FAIL(str(e))
-
-times = random.randint(10,50)
-
-xen_mem = XenMemory(console)
-
-origmem = xen_mem.get_mem_from_domU()
-currmem = origmem
-
-for i in range(0,times):
- amt = random.randint(-10,10)
-
- target = currmem + amt
-
- # Make sure we're not going over or under
- if target < domain.minSafeMem():
- continue
- if target > origmem:
- continue
-
- if verbose:
- print "[%i/%i] Current: %i Target: %i" % (i, times, currmem, target)
-
- cmd = "xm mem-set %s %i" % (domain.getName(), target)
- status, output = traceCommand(cmd)
-
- if status != 0:
- if verbose:
- print "mem-set failed:"
- print output
- FAIL("mem-set from %i to %i failed" % (currmem, target))
-
- domUmem = xen_mem.get_mem_from_domU()
-
- currmem = target
- actual = int(getDomInfo(domain.getName(), "Mem"))
-
- if actual != currmem:
- FAIL("Expected %i MB, xm reported %i MB" % (currmem, actual))
- if domUmem != currmem:
- FAIL("Expected %i MB, domU reported %i MB" % (currmem, domUmem))
-
-
diff --git a/tools/xm-test/tests/memset/04_memset_smallmem_pos.py b/tools/xm-test/tests/memset/04_memset_smallmem_pos.py
deleted file mode 100644
index d2b52fc..0000000
--- a/tools/xm-test/tests/memset/04_memset_smallmem_pos.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Mem-set not supported for HVM domains")
-
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to start domain: "
- print e.extra
- FAIL(str(e))
-
-try:
- # Make sure it's alive before we proceed
- console.runCmd("ls")
-except ConsoleError, e:
- FAIL(str(e))
-
-status, output = traceCommand("xm mem-set %s %i" %
- (domain.getName(), 18))
-
-if status != 0:
- FAIL("xm mem-set %s %i returned invalid %i != 0" %
- (domain.getName(), domain.minSafeMem(), status))
-
-console.setLimit(65536)
-
-try:
- # See if this hits the byte limit
- console.runCmd("ls")
-except ConsoleError, e:
- if e.reason == RUNAWAY:
- # Need to stop the domain before we restart the console daemon
- domain.destroy()
- if isConsoleDead():
- print "*** Attempting restart of xenconsoled"
- s, o = traceCommand("killall xenconsoled")
- s, o = traceCommand("xenconsoled")
- if s != 0:
- print "*** Starting xenconsoled failed: %i" % s
- FAIL("Bug #380: I crashed the console system")
- else:
- FAIL("Bug #145: Ballooning DomU too low caused run-away")
- else:
- FAIL(str(e))
-
-domain.destroy()
diff --git a/tools/xm-test/tests/memset/Makefile.am b/tools/xm-test/tests/memset/Makefile.am
deleted file mode 100644
index 09c3bac..0000000
--- a/tools/xm-test/tests/memset/Makefile.am
+++ /dev/null
@@ -1,24 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_memset_basic_pos.test \
- 02_memset_badparm_neg.test \
- 03_memset_random_pos.test \
- 04_memset_smallmem_pos.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
-
diff --git a/tools/xm-test/tests/migrate/01_migrate_localhost_pos.py b/tools/xm-test/tests/migrate/01_migrate_localhost_pos.py
deleted file mode 100644
index 89c1cc9..0000000
--- a/tools/xm-test/tests/migrate/01_migrate_localhost_pos.py
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Paul Larson <pl at us.ibm.com>
-
-# Description:
-# Positive Tests:
-# Tests for xm migrate
-# 1) Create domain, verify it's up with console
-# 2) live migrate the domain to localhost
-# 3) verify it's migrated, see that it has a new domain ID
-# 4) verify it's still working properly by running a command on it
-
-import re
-import time
-import commands
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Migrate currently not supported for HVM domains")
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-# Start it
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- # Set a variable to check on the other side
- run = console.runCmd("foo=bar")
-except ConsoleError, e:
- FAIL(str(e))
-
-# Close the console
-domain.closeConsole()
-
-old_domid = domid(domain.getName())
-
-# Migrate the domain
-try:
- status, output = traceCommand("xm migrate -l %s localhost" % domain.getName(),
- timeout=90)
-except TimeoutError, e:
- FAIL(str(e))
-
-if status != 0:
- FAIL("xm migrate returned invalid %i != 0" % status)
-
-new_domid = domid(domain.getName())
-
-if (old_domid == new_domid):
- FAIL("xm migrate failed, domain id is still %s" % old_domid)
-
-# Attach a console to it
-try:
- console = domain.getConsole()
- console.debugMe = True
-except ConsoleError, e:
- pass
-
-console.setHistorySaveCmds(value=True)
-console.sendInput("ls")
-
-# Run 'ls'
-try:
- # Check the dmesg output on the domU
- run = console.runCmd("echo xx$foo")
-except ConsoleError, e:
- FAIL(str(e))
-
-if not re.search("bar", run["output"]):
- FAIL("Migrated domain has been reset")
-
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
-
diff --git a/tools/xm-test/tests/migrate/Makefile.am b/tools/xm-test/tests/migrate/Makefile.am
deleted file mode 100644
index 10cd0be..0000000
--- a/tools/xm-test/tests/migrate/Makefile.am
+++ /dev/null
@@ -1,20 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_migrate_localhost_pos.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/network-attach/01_network_attach_pos.py b/tools/xm-test/tests/network-attach/01_network_attach_pos.py
deleted file mode 100644
index d6fdabb..0000000
--- a/tools/xm-test/tests/network-attach/01_network_attach_pos.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Murillo F. Bernardes <mfb at br.ibm.com>
-
-import sys
-
-from XmTestLib import *
-from XmTestLib.network_utils import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Network-attach not supported for HVM domains")
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- # Run 'ls'
- run = console.runCmd("ls")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-## Real test
-status, msg = network_attach(domain.getName(), console)
-if status:
- FAIL(msg)
-
-
-##
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/network-attach/02_network_attach_detach_pos.py b/tools/xm-test/tests/network-attach/02_network_attach_detach_pos.py
deleted file mode 100644
index 43b8e20..0000000
--- a/tools/xm-test/tests/network-attach/02_network_attach_detach_pos.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Murillo F. Bernardes <mfb at br.ibm.com>
-
-import sys
-import re
-import time
-
-from XmTestLib import *
-from XmTestLib.network_utils import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Network-attach not supported for HVM domains")
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- # Run 'ls'
- run = console.runCmd("ls")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-## Real test - attach and detach
-status, msg = network_attach(domain.getName(), console)
-if status:
- FAIL(msg)
-
-status, msg = network_detach(domain.getName(), console)
-if status:
- FAIL(msg)
-
-
-
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/network-attach/03_network_attach_detach_multiple_pos.py b/tools/xm-test/tests/network-attach/03_network_attach_detach_multiple_pos.py
deleted file mode 100644
index a0066d9..0000000
--- a/tools/xm-test/tests/network-attach/03_network_attach_detach_multiple_pos.py
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Murillo F. Bernardes <mfb at br.ibm.com>
-
-import sys
-import re
-import time
-
-from XmTestLib import *
-from XmTestLib.network_utils import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Network-attach not supported for HVM domains")
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-console.debugMe = True
-
-try:
- # Run 'ls'
- run = console.runCmd("ls")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-for i in range(10):
- print "Attaching %d device" % i
- status, msg = network_attach(domain.getName(), console)
- if status:
- FAIL(msg)
-
- print "Detaching %d device" % i
- status, msg = network_detach(domain.getName(), console, i)
- if status:
- FAIL(msg)
-
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/network-attach/04_network_attach_baddomain_neg.py b/tools/xm-test/tests/network-attach/04_network_attach_baddomain_neg.py
deleted file mode 100644
index bcc4c2b..0000000
--- a/tools/xm-test/tests/network-attach/04_network_attach_baddomain_neg.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Murillo F. Bernardes <mfb at br.ibm.com>
-
-from XmTestLib import *
-
-status, output = traceCommand("xm network-attach NOT-EXIST")
-
-eyecatcher = "Error"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm network-attach returned bad status, expected non 0, status is: %i" % status )
-elif where == -1:
- FAIL("xm network-attach returned bad output, expected Error, output is: %s" % output )
diff --git a/tools/xm-test/tests/network-attach/Makefile.am b/tools/xm-test/tests/network-attach/Makefile.am
deleted file mode 100644
index 4edbb7d..0000000
--- a/tools/xm-test/tests/network-attach/Makefile.am
+++ /dev/null
@@ -1,24 +0,0 @@
-
-SUBDIRS =
-
-TESTS = 01_network_attach_pos.test \
- 02_network_attach_detach_pos.test \
- 03_network_attach_detach_multiple_pos.test \
- 04_network_attach_baddomain_neg.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS) network_utils.py
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/network/02_network_local_ping_pos.py b/tools/xm-test/tests/network/02_network_local_ping_pos.py
deleted file mode 100644
index 9029f51..0000000
--- a/tools/xm-test/tests/network/02_network_local_ping_pos.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: <dykman at us.ibm.com>
-
-# Ping tests on local interfaces.
-# - creates a single guest domain
-# - sets up a single NIC
-# - conducts ping tests to the local loopback and IP address.
-
-# ping -c 1 -s $size 127.0.0.1
-# ping -c 1 -s $size $local_IP
-# where $size = 1, 48, 64, 512, 1440, 1500, 1505,
-# 4096, 4192, 32767, 65507, 65508
-
-pingsizes = [ 1, 48, 64, 512, 1440, 1500, 1505, 4096, 4192,
- 32767, 65507 ]
-
-from XmTestLib import *
-rc = 0
-
-# Test creates 1 domain, which requires 2 ips: 1 for the domains and 1 for
-# aliases on dom0
-if xmtest_netconf.canRunNetTest(2) == False:
- SKIP("Don't have enough free configured IPs to run this test")
-
-domain = XmTestDomain()
-domain.newDevice(XenNetDevice, "eth0")
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- console.setHistorySaveCmds(value=True)
-
- # First the loopback pings
- lofails=""
- for size in pingsizes:
- out = console.runCmd("ping -q -c 1 -s " + str(size) + " 127.0.0.1")
- if out["return"]:
- lofails += " " + str(size)
-
- # Next comes eth0
- eth0fails=""
- netdev = domain.getDevice("eth0")
- ip = netdev.getNetDevIP()
- for size in pingsizes:
- out = console.runCmd("ping -q -c 1 -s " + str(size) + " " + ip)
- if out["return"]:
- eth0fails += " " + str(size)
-except ConsoleError, e:
- FAIL(str(e))
-except NetworkError, e:
- FAIL(str(e))
-
-domain.stop()
-
-# Tally up failures
-failures=""
-if len(lofails):
- failures += "ping loopback failed for size" + lofails + ". "
-if len(eth0fails):
- failures += "ping eth0 failed for size" + eth0fails + "."
-if len(failures):
- FAIL(failures)
-
diff --git a/tools/xm-test/tests/network/03_network_local_tcp_pos.py b/tools/xm-test/tests/network/03_network_local_tcp_pos.py
deleted file mode 100644
index b3b0bf1..0000000
--- a/tools/xm-test/tests/network/03_network_local_tcp_pos.py
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: <dykman at us.ibm.com>
-
-# TCP tests on local interfaces.
-# - creates a single guest domain
-# - sets up a single NIC
-# - conducts hping tcp tests to the local loopback and IP address
-
-# hping2 127.0.0.1 -c 1 -d $size
-# hping2 $local_IP -c 1 -d $size
-# where $size = 1, 48, 64, 512, 1440, 1448, 1500, 1505,
-# 4096, 4192, 32767, 65507, 65508
-
-
-trysizes = [ 1, 48, 64, 512, 1440, 1448, 1500, 1505, 4096, 4192,
- 32767, 65495 ]
-
-from XmTestLib import *
-rc = 0
-
-# Test creates 1 domain, which requires 2 ips: 1 for the domains and 1 for
-# aliases on dom0
-if xmtest_netconf.canRunNetTest(2) == False:
- SKIP("Don't have enough free configured IPs to run this test")
-
-# Fire up a guest domain w/1 nic
-domain = XmTestDomain()
-domain.newDevice(XenNetDevice, "eth0")
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- console.setHistorySaveCmds(value=True)
-
- # First do loopback
- lofails=""
- for size in trysizes:
- out = console.runCmd("hping2 127.0.0.1 -E /dev/urandom -q -c 20 "
- + "--fast -d " + str(size) + " -N " + str(size))
- if out["return"]:
- lofails += " " + str(size)
-
- # Next comes eth0
- eth0fails=""
- netdev = domain.getDevice("eth0")
- ip = netdev.getNetDevIP()
- for size in trysizes:
- out = console.runCmd("hping2 " + ip + " -E /dev/urandom -q -c 20 "
- + "--fast -d "+ str(size) + " -N " + str(size))
- if out["return"]:
- eth0fails += " " + str(size)
-except ConsoleError, e:
- FAIL(str(e))
-except NetworkError, e:
- FAIL(str(e))
-
-domain.stop()
-
-# Tally up failures
-failures=""
-if len(lofails):
- failures += "TCP hping2 over loopback failed for size" + lofails + ". "
-if len(eth0fails):
- failures += "TCP hping2 over eth0 failed for size" + eth0fails + "."
-if len(failures):
- FAIL(failures)
-
diff --git a/tools/xm-test/tests/network/04_network_local_udp_pos.py b/tools/xm-test/tests/network/04_network_local_udp_pos.py
deleted file mode 100644
index fcc6807..0000000
--- a/tools/xm-test/tests/network/04_network_local_udp_pos.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: <dykman at us.ibm.com>
-
-# UDP tests on local interfaces.
-# - creates a single guest domain
-# - sets up a single NIC
-# - conducts hping udp tests to the local loopback and IP address
-
-# hping2 127.0.0.1 -2 -c 1 -d $size
-# hping2 $local_IP -2 -c 1 -d $size
-# where $size = 1, 48, 64, 512, 1440, 1448, 1500, 1505,
-# 4096, 4192, 32767, 65507, 65508
-
-
-trysizes = [ 1, 48, 64, 512, 1440, 1448, 1500, 1505, 4096, 4192,
- 32767, 65495 ]
-
-from XmTestLib import *
-rc = 0
-
-# Test creates 1 domain, which requires 2 ips: 1 for the domains and 1 for
-# aliases on dom0
-if xmtest_netconf.canRunNetTest(2) == False:
- SKIP("Don't have enough free configured IPs to run this test")
-
-domain = XmTestDomain()
-domain.newDevice(XenNetDevice, "eth0")
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- console.setHistorySaveCmds(value=True)
-
- # First do loopback
- lofails=""
- for size in trysizes:
- out = console.runCmd("hping2 127.0.0.1 -E /dev/urandom -2 -q -c 20 "
- + "--fast -d " + str(size) + " -N " + str(size))
- if out["return"]:
- lofails += " " + str(size)
- print out["output"]
-
- # Next comes eth0
- eth0fails=""
- netdev = domain.getDevice("eth0")
- ip = netdev.getNetDevIP()
- for size in trysizes:
- out = console.runCmd("hping2 " + ip + " -E /dev/urandom -2 -q -c 20 "
- + "--fast -d " + str(size) + " -N " + str(size))
- if out["return"]:
- eth0fails += " " + str(size)
- print out["output"]
-except ConsoleError, e:
- FAIL(str(e))
-except NetworkError, e:
- FAIL(str(e))
-
-domain.stop()
-
-# Tally up failures
-failures=""
-if len(lofails):
- failures += "UDP hping2 over loopback failed for size" + lofails + ". "
-if len(eth0fails):
- failures += "UDP hping2 over eth0 failed for size" + eth0fails + "."
-if len(failures):
- FAIL(failures)
-
diff --git a/tools/xm-test/tests/network/05_network_dom0_ping_pos.py b/tools/xm-test/tests/network/05_network_dom0_ping_pos.py
deleted file mode 100644
index e86a2b9..0000000
--- a/tools/xm-test/tests/network/05_network_dom0_ping_pos.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: <dykman at us.ibm.com>
-
-# Ping tests to dom0 interface
-# - determines dom0 network
-# - creates a single guest domain
-# - sets up a single NIC on same subnet as dom0
-# - conducts ping tests to the dom0 IP address.
-
-# ping -c 1 -s $size $dom0_IP
-# where $size = 1, 48, 64, 512, 1440, 1500, 1505,
-# 4096, 4192, 32767, 65507, 65508
-
-pingsizes = [ 1, 48, 64, 512, 1440, 1500, 1505, 4096, 4192,
- 32767, 65507 ]
-
-from XmTestLib import *
-rc = 0
-
-# Test creates 1 domain, which requires 2 ips: 1 for the domains and 1 for
-# aliases on dom0
-if xmtest_netconf.canRunNetTest(2) == False:
- SKIP("Don't have enough free configured IPs to run this test")
-
-# Fire up a guest domain w/1 nic
-domain = XmTestDomain()
-domain.newDevice(XenNetDevice, "eth0")
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- # Ping dom0
- fails=""
- netdev = domain.getDevice("eth0")
- dom0ip = netdev.getDom0AliasIP()
- for size in pingsizes:
- out = console.runCmd("ping -q -c 1 -s " + str(size) + " " + dom0ip)
- if out["return"]:
- fails += " " + str(size)
-except ConsoleError, e:
- FAIL(str(e))
-
-domain.stop()
-
-if len(fails):
- FAIL("Ping to dom0 failed for size" + fails + ".")
diff --git a/tools/xm-test/tests/network/06_network_dom0_tcp_pos.py b/tools/xm-test/tests/network/06_network_dom0_tcp_pos.py
deleted file mode 100644
index e36c090..0000000
--- a/tools/xm-test/tests/network/06_network_dom0_tcp_pos.py
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: <dykman at us.ibm.com>
-
-# TCP tests to dom0.
-# - determines dom0 network
-# - creates a single guest domain
-# - sets up a single NIC on same subnet as dom0
-# - conducts hping2 tcp tests to the dom0 IP address
-
-# hping2 $dom0_IP -c 1 -d $size
-# where $size = 1, 48, 64, 512, 1440, 1448, 1500, 1505,
-# 4096, 4192, 32767, 65507, 65508
-
-trysizes = [ 1, 48, 64, 512, 1440, 1500, 1505, 4096, 4192,
- 32767, 65495 ]
-
-from XmTestLib import *
-rc = 0
-
-# Test creates 1 domain, which requires 2 ips: 1 for the domains and 1 for
-# aliases on dom0
-if xmtest_netconf.canRunNetTest(2) == False:
- SKIP("Don't have enough free configured IPs to run this test")
-
-# Fire up a guest domain w/1 nic
-domain = XmTestDomain()
-domain.newDevice(XenNetDevice, "eth0")
-
-try:
- console = domain.start()
- console.setHistorySaveCmds(value=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- # Ping dom0
- fails=""
- netdev = domain.getDevice("eth0")
- dom0ip = netdev.getDom0AliasIP()
- for size in trysizes:
- out = console.runCmd("hping2 " + dom0ip + " -E /dev/urandom -q -c 20 "
- + "--fast -d " + str(size) + " -N " + str(size))
- if out["return"]:
- fails += " " + str(size)
- print out["output"]
-except ConsoleError, e:
- FAIL(str(e))
-
-domain.stop()
-
-if len(fails):
- FAIL("TCP hping2 to dom0 failed for size" + fails + ".")
diff --git a/tools/xm-test/tests/network/07_network_dom0_udp_pos.py b/tools/xm-test/tests/network/07_network_dom0_udp_pos.py
deleted file mode 100644
index f86514f..0000000
--- a/tools/xm-test/tests/network/07_network_dom0_udp_pos.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: <dykman at us.ibm.com>
-
-# UDP tests to dom0.
-# - determines dom0 network
-# - creates a single guest domain
-# - sets up a single NIC on same subnet as dom0
-# - conducts hping2 udp tests to the dom0 IP address
-
-# hping2 $dom0_IP -2 -c 1 -d $size
-# where $size = 1, 48, 64, 512, 1440, 1448, 1500, 1505,
-# 4096, 4192, 32767, 65507, 65508
-
-trysizes = [ 1, 48, 64, 512, 1440, 1500, 1505, 4096, 4192,
- 32767, 65495 ]
-
-from XmTestLib import *
-rc = 0
-
-# Test creates 1 domain, which requires 2 ips: 1 for the domains and 1 for
-# aliases on dom0
-if xmtest_netconf.canRunNetTest(2) == False:
- SKIP("Don't have enough free configured IPs to run this test")
-
-# Fire up a guest domain w/1 nic
-domain = XmTestDomain()
-domain.newDevice(XenNetDevice, "eth0")
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- # Ping dom0
- fails=""
- netdev = domain.getDevice("eth0")
- dom0ip = netdev.getDom0AliasIP()
- for size in trysizes:
- out = console.runCmd("hping2 " + dom0ip + " -E /dev/urandom -2 -q -c 20"
- + " --fast -d " + str(size) + " -N " + str(size))
- if out["return"]:
- fails += " " + str(size)
- print out["output"]
-except ConsoleError, e:
- FAIL(str(e))
-
-domain.stop()
-
-if len(fails):
- FAIL("UDP hping2 to dom0 failed for size" + fails + ".")
diff --git a/tools/xm-test/tests/network/11_network_domU_ping_pos.py b/tools/xm-test/tests/network/11_network_domU_ping_pos.py
deleted file mode 100644
index d4992f1..0000000
--- a/tools/xm-test/tests/network/11_network_domU_ping_pos.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: <dykman at us.ibm.com>
-
-# Ping tests to domU interface
-# - creates two guest domains
-# - sets up a single NIC on each on same subnet
-# - conducts ping tests to the domU IP address.
-
-# ping -c 1 -s $size $domU_IP
-# where $size = 1, 48, 64, 512, 1440, 1500, 1505,
-# 4096, 4192, 32767, 65507, 65508
-
-pingsizes = [ 1, 48, 64, 512, 1440, 1500, 1505, 4096, 4192,
- 32767, 65507 ]
-
-from XmTestLib import *
-
-def netDomain():
-
- dom = XmTestDomain()
- dom.newDevice(XenNetDevice, "eth0")
- try:
- console = dom.start()
- console.setHistorySaveCmds(value=True)
- except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
- return dom
-
-rc = 0
-
-# Test creates 2 domains, which requires 4 ips: 2 for the domains and 2 for
-# aliases on dom0
-if xmtest_netconf.canRunNetTest(4) == False:
- SKIP("Don't have enough free configured IPs to run this test")
-
-# Fire up a pair of guest domains w/1 nic each
-pinger = netDomain()
-pinger_console = pinger.getConsole()
-victim = netDomain()
-
-try:
- # Ping the victim over eth0
- fails=""
- v_netdev = victim.getDevice("eth0")
- ip2 = v_netdev.getNetDevIP()
- for size in pingsizes:
- out = pinger_console.runCmd("ping -q -c 1 -s " + str(size) + " " + ip2)
- if out["return"]:
- fails += " " + str(size)
-except ConsoleError, e:
- FAIL(str(e))
-
-pinger.stop()
-victim.stop()
-
-if len(fails):
- FAIL("Ping failed for size" + fails + ".")
diff --git a/tools/xm-test/tests/network/12_network_domU_tcp_pos.py b/tools/xm-test/tests/network/12_network_domU_tcp_pos.py
deleted file mode 100644
index 50a8a9a..0000000
--- a/tools/xm-test/tests/network/12_network_domU_tcp_pos.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: <dykman at us.ibm.com>
-
-# TCP tests to domU interface
-# - creates two guest domains
-# - sets up a single NIC on each on same subnet
-# - conducts tcp tests to the domU IP address.
-
-# hping2 $domU_IP -c 1 -d $size
-# where $size = 1, 48, 64, 512, 1440, 1500, 1505,
-# 4096, 4192, 32767, 65507, 65508
-
-pingsizes = [ 1, 48, 64, 512, 1440, 1500, 1505, 4096, 4192, 16384, 24567,
- 32767, 65495 ]
-
-from XmTestLib import *
-
-def netDomain():
-
- dom = XmTestDomain()
- dom.newDevice(XenNetDevice, "eth0")
- try:
- console = dom.start()
- console.setHistorySaveCmds(value=True)
- except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
- return dom
-
-rc = 0
-
-# Test creates 2 domains, which requires 4 ips: 2 for the domains and 2 for
-# aliases on dom0
-if xmtest_netconf.canRunNetTest(4) == False:
- SKIP("Don't have enough free configured IPs to run this test")
-
-# Fire up a pair of guest domains w/1 nic each
-src = netDomain()
-src_console = src.getConsole()
-dst = netDomain()
-
-try:
- # Ping the victim over eth0
- fails=""
- dst_netdev = dst.getDevice("eth0")
- ip2 = dst_netdev.getNetDevIP()
- for size in pingsizes:
- out = src_console.runCmd("hping2 " + ip2 + " -E /dev/urandom -q -c 20 "
- + "--fast -d " + str(size) + " -N " + str(size))
- if out["return"]:
- fails += " " + str(size)
- print out["output"]
-except ConsoleError, e:
- FAIL(str(e))
-
-src.stop()
-dst.stop()
-
-if len(fails):
- FAIL("TCP hping2 failed for size" + fails + ".")
diff --git a/tools/xm-test/tests/network/13_network_domU_udp_pos.py b/tools/xm-test/tests/network/13_network_domU_udp_pos.py
deleted file mode 100644
index 140c229..0000000
--- a/tools/xm-test/tests/network/13_network_domU_udp_pos.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Copyright (C) flonatel GmbH & Co. KG, 2009
-# Authors: <dykman at us.ibm.com>
-# Andreas Florath <xen at flonatel.org>
-
-# UDP tests to domU interface
-# - creates two guest domains
-# - sets up a single NIC on each on same subnet
-# - conducts udp tests to the domU IP address.
-
-# hping2 $domU_IP -1 -c 7 -d $size
-# where $size = 1, 48, 64, 512, 1440, 1500, 1505,
-# 4096, 4192, 32767, 65507, 65508
-
-pingsizes = [ 1, 48, 64, 512, 1440, 1500, 1505, 4096, 4192,
- 32767, 65495 ]
-
-from XmTestLib import *
-
-def netDomain():
-
- dom = XmTestDomain()
- dom.newDevice(XenNetDevice, "eth0")
- try:
- console = dom.start()
- console.setHistorySaveCmds(value=True)
- except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
- return dom
-
-fails = ""
-
-# Test creates 2 domains, which requires 4 ips: 2 for the domains and 2 for
-# aliases on dom0
-if xmtest_netconf.canRunNetTest(4) == False:
- SKIP("Don't have enough free configured IPs to run this test")
-
-# Fire up a pair of guest domains w/1 nic each
-guest1 = netDomain()
-guest1_console = guest1.getConsole()
-guest1_netdev = guest1.getDevice("eth0")
-guest1_ip = guest1_netdev.getNetDevIP()
-guest1_dom0_alias_ip = guest1_netdev.dom0_alias_ip
-guest2 = netDomain()
-guest2_console = guest2.getConsole()
-guest2_netdev = guest2.getDevice("eth0")
-guest2_ip = guest2_netdev.getNetDevIP()
-guest2_dom0_alias_ip = guest2_netdev.dom0_alias_ip
-
-def hping_cmd(ip, size):
- return "hping2 " + ip + " -E /dev/urandom -1 -q " \
- + "-c 7 --fast -d " + str(size) + " -N " + str(size)
-
-# Ping everything from guests
-try:
- for size in pingsizes:
- for console in [(guest1_console, "Guest1Console"),
- (guest2_console, "Guest2Console")]:
- for dest_ip in [guest1_ip, guest1_dom0_alias_ip,
- guest2_ip, guest2_dom0_alias_ip ]:
- out = console[0].runCmd(hping_cmd(dest_ip, size))
- if out["return"]:
- fails += " [%d, %s, %s]" % (size, console[1], dest_ip)
-except ConsoleError, e:
- FAIL(str(e))
-
-guest1.stop()
-guest2.stop()
-
-if len(fails):
- FAIL("UDP hping2 failed for size" + fails + ".")
diff --git a/tools/xm-test/tests/network/Makefile.am b/tools/xm-test/tests/network/Makefile.am
deleted file mode 100644
index cb03183..0000000
--- a/tools/xm-test/tests/network/Makefile.am
+++ /dev/null
@@ -1,34 +0,0 @@
-
-SUBDIRS =
-TESTS = \
- 02_network_local_ping_pos.test \
- 03_network_local_tcp_pos.test \
- 04_network_local_udp_pos.test \
- 05_network_dom0_ping_pos.test \
- 06_network_dom0_tcp_pos.test \
- 07_network_dom0_udp_pos.test \
- 11_network_domU_ping_pos.test \
- 12_network_domU_tcp_pos.test \
- 13_network_domU_udp_pos.test
-
-
-
-XFAIL_TESTS = \
- 02_network_local_ping_pos.test \
- 05_network_dom0_ping_pos.test \
- 11_network_domU_ping_pos.test
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/pause/01_pause_basic_pos.py b/tools/xm-test/tests/pause/01_pause_basic_pos.py
deleted file mode 100644
index 083e366..0000000
--- a/tools/xm-test/tests/pause/01_pause_basic_pos.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Paul Larson <pl at us.ibm.com>
-
-# Description:
-# Positive Tests:
-# Tests for xm pause
-# 1) Create domain, verify it's up with console
-# 2) pause the domain
-# 3) verify it's paused by failure to connect console
-
-import time
-import commands
-
-from XmTestLib import *
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-# Start it
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- # Make sure a command succeeds
- run = console.runCmd("ls")
-except ConsoleError, e:
- FAIL(str(e))
-
-# Close the console
-domain.closeConsole()
-
-# Pause the domain
-status, output = traceCommand("xm pause %s" % domain.getName())
-if status != 0:
- FAIL("xm pause returned invalid %i != 0", status)
-
-# Try to attach a console to it
-try:
- console = domain.getConsole()
- console.setHistorySaveCmds(value=True)
- run = console.runCmd("ls")
- #If we get here, console attached to paused domain (unexpected)
- FAIL("console attached to supposedly paused domain")
-except ConsoleError, e:
- pass
-
-# Close the console
-domain.closeConsole()
-
-status, output = traceCommand("xm unpause %s" % domain.getName())
-if status != 0:
- FAIL("xm unpause returned invalid %i != 0", status)
-
-# Stop the domain (nice shutdown)
-domain.stop()
-
diff --git a/tools/xm-test/tests/pause/02_pause_badopt_neg.py b/tools/xm-test/tests/pause/02_pause_badopt_neg.py
deleted file mode 100644
index 82173f1..0000000
--- a/tools/xm-test/tests/pause/02_pause_badopt_neg.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Murillo F. Bernardes <mfb at br.ibm.com>
-
-import time
-import re
-
-from XmTestLib import *
-
-domain = XmTestDomain()
-
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-status, output = traceCommand("xm pause -x %s" % domain.getName())
-
-eyecatcher = "Error"
-where = output.find(eyecatcher)
-if status == 0:
- domain.destroy()
- FAIL("xm pause returned bad status, expected non 0, status is: %i" % status )
-elif where == -1:
- domain.destroy()
- FAIL("xm pause returned bad output, expected Error, output is: %s" % output )
-
-domain.destroy()
diff --git a/tools/xm-test/tests/pause/03_pause_badname_neg.py b/tools/xm-test/tests/pause/03_pause_badname_neg.py
deleted file mode 100644
index 982034c..0000000
--- a/tools/xm-test/tests/pause/03_pause_badname_neg.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Murillo F. Bernardes <mfb at br.ibm.com>
-
-import time
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm pause NOT-EXIST" )
-
-eyecatcher = "Error"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm pause returned bad status, expected non 0, status is: %i" % status )
-elif where == -1:
- FAIL("xm pause returned bad output, expected Error, output is: %s" % output )
diff --git a/tools/xm-test/tests/pause/04_pause_badid_neg.py b/tools/xm-test/tests/pause/04_pause_badid_neg.py
deleted file mode 100644
index ffd1be2..0000000
--- a/tools/xm-test/tests/pause/04_pause_badid_neg.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Murillo F. Bernardes <mfb at br.ibm.com>
-
-import time
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm pause 1246445" )
-
-eyecatcher = "Error"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm pause returned bad status, expected non 0, status is: %i" % status )
-elif where == -1:
- FAIL("xm pause returned bad output, expected Error, output is: %s" % output )
diff --git a/tools/xm-test/tests/pause/Makefile.am b/tools/xm-test/tests/pause/Makefile.am
deleted file mode 100644
index a79ce18..0000000
--- a/tools/xm-test/tests/pause/Makefile.am
+++ /dev/null
@@ -1,22 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_pause_basic_pos.test 02_pause_badopt_neg.test \
- 03_pause_badname_neg.test 04_pause_badid_neg.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
-
diff --git a/tools/xm-test/tests/reboot/01_reboot_basic_pos.py b/tools/xm-test/tests/reboot/01_reboot_basic_pos.py
deleted file mode 100644
index df006c4..0000000
--- a/tools/xm-test/tests/reboot/01_reboot_basic_pos.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-import time
-import re
-
-from XmTestLib import *
-
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-domain.closeConsole()
-
-status, output = traceCommand("xm reboot %s" % domain.getName())
-
-if status != 0:
- FAIL("xm reboot returned %i != 0" % status)
-
-time.sleep(15)
-
-try:
- console = domain.getConsole()
-except ConsoleError, e:
- FAIL(str(e))
-
-try:
- console.sendInput("input")
- run = console.runCmd("uptime")
-except ConsoleError, e:
- FAIL(str(e))
-
-domain.closeConsole()
-
-domain.destroy()
-
-match = re.match("^[^up]*up ([0-9]+).*$", run["output"])
-if match:
- if int(match.group(1)) > 1:
- FAIL("Uptime too large (%i > 1 minutes); domain didn't reboot")
-else:
- FAIL("Invalid uptime string: %s (%s)" % (run["output"], match.group(1)))
-
-
diff --git a/tools/xm-test/tests/reboot/02_reboot_badopt_neg.py b/tools/xm-test/tests/reboot/02_reboot_badopt_neg.py
deleted file mode 100644
index fc60ac2..0000000
--- a/tools/xm-test/tests/reboot/02_reboot_badopt_neg.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-import time
-import re
-
-from XmTestLib import *
-
-domain = XmTestDomain()
-
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-status, output = traceCommand("xm reboot -x %s" % domain.getName())
-
-eyecatcher = "Error"
-where = output.find(eyecatcher)
-if status == 0:
- domain.destroy()
- FAIL("xm reboot returned invalid %i == 0" % status )
-elif where == -1:
- domain.destroy()
- FAIL("xm reboot failed to report error for bad arg")
-
-domain.destroy()
diff --git a/tools/xm-test/tests/reboot/03_reboot_badname_neg.py b/tools/xm-test/tests/reboot/03_reboot_badname_neg.py
deleted file mode 100644
index 480e5dd..0000000
--- a/tools/xm-test/tests/reboot/03_reboot_badname_neg.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-import time
-import re
-
-from XmTestLib import *
-
-status, output = traceCommand("xm reboot NOT-EXIST" )
-
-eyecatcher = "Error"
-where = output.find(eyecatcher)
-if status == 0:
- FAIL("xm reboot returned invalid %i == 0" % status )
-elif where == -1:
- FAIL("xm reboot failed to report error for non-existent domain" )
diff --git a/tools/xm-test/tests/reboot/Makefile.am b/tools/xm-test/tests/reboot/Makefile.am
deleted file mode 100644
index 737e7cc..0000000
--- a/tools/xm-test/tests/reboot/Makefile.am
+++ /dev/null
@@ -1,23 +0,0 @@
-
-SUBDIRS =
-
-TESTS = 01_reboot_basic_pos.test \
- 02_reboot_badopt_neg.test \
- 03_reboot_badname_neg.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/restore/01_restore_basic_pos.py b/tools/xm-test/tests/restore/01_restore_basic_pos.py
deleted file mode 100644
index 4a61c2a..0000000
--- a/tools/xm-test/tests/restore/01_restore_basic_pos.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-# Save a domain and attempt to restore it
-#
-# Since we don't want to depend on the fact that save/01_basic_pos.py
-# ran successfully, we try to save the domain here again
-
-import time
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Restore currently not supported for HVM domains")
-
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-# Make sure the domain isn't DOA
-try:
- console.runCmd("foo=bar")
-except ConsoleError, e:
- FAIL(str(e))
-
-domain.closeConsole()
-
-# Save it out
-try:
- s, o = traceCommand("xm save %s /tmp/test.state" % domain.getName(),
- timeout=30)
-except TimeoutError, e:
- FAIL(str(e))
-
-if s != 0:
- FAIL("save command exited %i != 0" % s)
-
-# FIXME: Give the system some time to update the internal state
-traceCommand("xm list")
-
-# Make sure it's gone
-if isDomainRunning(domain.getName()):
- FAIL("Domain still running after save!")
-
-# Let things settle
-time.sleep(2)
-
-# Restore it in
-status, output = traceCommand("xm restore /tmp/test.state",
- timeout=30)
-if s != 0:
- FAIL("restore command exited %i != 0" % s)
-
-# Make sure it's running
-if not isDomainRunning(domain.getName()):
- FAIL("Restore didn't result in a running %s domain!" % domain.getName())
-
-# Make sure it's alive
-try:
- newConsole = domain.getConsole()
- # Enable debug dumping because this generates a Oops on x86_64
- newConsole.debugMe = True
- newConsole.sendInput("ls")
- run = newConsole.runCmd("echo xx$foo")
- if not re.search("bar", run["output"]):
- FAIL("Restored domain has been reset")
-except ConsoleError, e:
- FAIL("Restored domain is dead (%s)" % str(e))
-
-domain.closeConsole()
-
-# This only works because the domain
-# still has the same name
-domain.stop()
diff --git a/tools/xm-test/tests/restore/02_restore_badparm_neg.py b/tools/xm-test/tests/restore/02_restore_badparm_neg.py
deleted file mode 100644
index e5f2c90..0000000
--- a/tools/xm-test/tests/restore/02_restore_badparm_neg.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-# Test description:
-# Negative Test:
-# Test for restoring domain with non existent option in the command line.
-# Verify fail.
-
-import re
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Restore currently not supported for HVM domains")
-
-status, output = traceCommand("xm restore -x")
-eyecatcher1 = "Error:"
-eyecatcher2 = "Traceback"
-where1 = output.find(eyecatcher1)
-where2 = output.find(eyecatcher2)
-if status == 0:
- FAIL("xm restore returned bad status, expected non 0, status is: %i" % status)
-elif where2 == 0:
- FAIL("xm restore returned a stack dump, expected nice error message")
-elif where1 == -1:
- FAIL("xm restore returned bad output, expected Error:, output is: %s" % output)
diff --git a/tools/xm-test/tests/restore/03_restore_badfilename_neg.py b/tools/xm-test/tests/restore/03_restore_badfilename_neg.py
deleted file mode 100644
index d45c87b..0000000
--- a/tools/xm-test/tests/restore/03_restore_badfilename_neg.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-# Test description:
-# Negative Test:
-# Test for restoring domain with non existent file.
-# Verify fail.
-
-import re
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Restore currently not supported for HVM domains")
-
-status, output = traceCommand("xm restore /tmp/NON_EXIST")
-eyecatcher1 = "Error:"
-eyecatcher2 = "Traceback"
-where1 = output.find(eyecatcher1)
-where2 = output.find(eyecatcher2)
-if status == 0:
- FAIL("xm restore returned bad status, expected non 0, status is: %i" % status)
-elif where2 == 0:
- FAIL("xm restore returned a stack dump, expected nice error message")
-elif where1 == -1:
- FAIL("xm restore returned bad output, expected Error:, output is: %s" % output)
diff --git a/tools/xm-test/tests/restore/04_restore_withdevices_pos.py b/tools/xm-test/tests/restore/04_restore_withdevices_pos.py
deleted file mode 100644
index e9eb29b..0000000
--- a/tools/xm-test/tests/restore/04_restore_withdevices_pos.py
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-
-import re
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Restore currently not supported for HVM domains")
-
-config = {"disk": ["phy:/dev/ram0,xvda1,w", "phy:/dev/ram1,xvdb2,w"],
- "vif": ['', '']}
-domain = XmTestDomain(extraConfig=config)
-
-s, o = traceCommand("mke2fs -j -q /dev/ram0")
-if s != 0:
- FAIL("Unable to mke2fs /dev/ram0 in dom0")
-
-s, o = traceCommand("mke2fs -j -q /dev/ram1")
-if s != 0:
- FAIL("Unable to mke2fs /dev/ram1 in dom0")
-
-try:
- console = domain.start()
-except DomainError, e:
- FAIL(str(e))
-
-try:
- run = console.runCmd("mkdir /mnt/a /mnt/b")
- if run["return"] != 0:
- FAIL("Unable to mkdir /mnt/a /mnt/b")
-
- run = console.runCmd("mount /dev/xvda1 /mnt/a")
- if run["return"] != 0:
- FAIL("Unable to mount /dev/xvda1")
-
- run = console.runCmd("mount /dev/xvdb2 /mnt/b")
- if run["return"] != 0:
- FAIL("Unable to mount /dev/xvdb2")
-
- run = console.runCmd("echo xvda1 > /mnt/a/foo")
- if run["return"] != 0:
- FAIL("Unable to write to block device xvda1!")
-
- run = console.runCmd("echo xvdb2 > /mnt/b/foo")
- if run["return"] != 0:
- FAIL("Unable to write to block device xvdb2!")
-
- run = console.runCmd("ifconfig eth0 172.30.206.1 netmask 255.255.255.240")
- if run["return"] != 0:
- FAIL("Unable to configure DomU's eth0")
-
- run = console.runCmd("ifconfig eth1 172.30.206.17 netmask 255.255.255.240")
- if run["return"] != 0:
- FAIL("Unable to configure DomU's eth1")
-
- run = console.runCmd("ifconfig lo 127.0.0.1")
- if run["return"] != 0:
- FAIL("Unable to configure DomU's lo")
-
-
-except ConsoleError, e:
- FAIL(str(e))
-
-domain.closeConsole()
-
-try:
- s, o = traceCommand("xm save %s /tmp/test.state" % domain.getName(),
- timeout=30)
-except TimeoutError, e:
- FAIL(str(e))
-
-if s != 0:
- FAIL("xm save exited with %i != 0" % s)
-
-# Let things settle
-time.sleep(15)
-
-try:
- s, o = traceCommand("xm restore /tmp/test.state",
- timeout=30)
-except TimeoutError, e:
- FAIL(str(e))
-
-if s != 0:
- FAIL("xm restore exited with %i != 0" % s)
-
-try:
- console = domain.getConsole()
- # Enable debug dumping, as this causes an Oops on x86_64
- console.debugMe = True
-
- # In case the domain is rebooted
- console.sendInput("ls")
-
- run = console.runCmd("ls | grep proc")
- if run["return"] != 0:
- FAIL("ls failed on restored domain")
-
- run = console.runCmd("cat /mnt/a/foo")
- if run["return"] != 0:
- FAIL("Unable to read from block device xvda1")
- if not re.search("xvda1", run["output"]):
- FAIL("Failed to read correct data from xvda1")
-
- run = console.runCmd("cat /mnt/b/foo")
- if run["return"] != 0:
- FAIL("Unable to read from block device xvdb2")
- if not re.search("xvdb2", run["output"]):
- FAIL("Failed to read correct data from xvdb2")
-
- run = console.runCmd("ifconfig")
- if not re.search("eth0", run["output"]):
- FAIL("DomU's eth0 disappeared")
- if not re.search("172.30.206.1", run["output"]):
- FAIL("DomU's eth0 lost its IP")
- if not re.search("eth1", run["output"]):
- FAIL("DomU's eth1 disappeared")
- if not re.search("172.30.206.17", run["output"]):
- FAIL("DomU's eth1 lost its IP")
- if not re.search("Loopback", run["output"]):
- FAIL("DomU's lo disappeared")
- if not re.search("127.0.0.1", run["output"]):
- FAIL("DomU's lo lost its IP")
-
-except ConsoleError, e:
- FAIL(str(e))
-
diff --git a/tools/xm-test/tests/restore/Makefile.am b/tools/xm-test/tests/restore/Makefile.am
deleted file mode 100644
index f690d98..0000000
--- a/tools/xm-test/tests/restore/Makefile.am
+++ /dev/null
@@ -1,24 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_restore_basic_pos.test \
- 02_restore_badparm_neg.test \
- 03_restore_badfilename_neg.test \
- 04_restore_withdevices_pos.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
-
diff --git a/tools/xm-test/tests/save/01_save_basic_pos.py b/tools/xm-test/tests/save/01_save_basic_pos.py
deleted file mode 100644
index 34270fa..0000000
--- a/tools/xm-test/tests/save/01_save_basic_pos.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-import time
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Save currently not supported for HVM domains")
-
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-domain.closeConsole()
-
-# Save it out
-try:
- s, o = traceCommand("xm save %s /tmp/test.state" % domain.getName(),
- timeout=30)
-except TimeoutError, e:
- FAIL(str(e))
-
-if s != 0:
- FAIL("save command exited %i != 0" % s)
-
-# Make sure it's gone
-if isDomainRunning(domain.getName()):
- FAIL("Domain still running after save!")
diff --git a/tools/xm-test/tests/save/02_save_badparm_neg.py b/tools/xm-test/tests/save/02_save_badparm_neg.py
deleted file mode 100644
index 2393c46..0000000
--- a/tools/xm-test/tests/save/02_save_badparm_neg.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-
-# Test description:
-# Negative Test:
-# Test for saving domain with non existent option in the command line.
-# Verify fail.
-
-import re
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Save currently not supported for HVM domains")
-
-status, output = traceCommand("xm save -x")
-eyecatcher1 = "Error:"
-eyecatcher2 = "Traceback"
-where1 = output.find(eyecatcher1)
-where2 = output.find(eyecatcher2)
-if status == 0:
- FAIL("xm save returned bad status, expected non 0, status is: %i" % status)
-elif where2 == 0:
- FAIL("xm save returned a stack dump, expected nice error message")
-elif where1 == -1:
- FAIL("xm save returned bad output, expected Error:, output is: %s" % output)
diff --git a/tools/xm-test/tests/save/03_save_bogusfile_neg.py b/tools/xm-test/tests/save/03_save_bogusfile_neg.py
deleted file mode 100644
index b8b99cd..0000000
--- a/tools/xm-test/tests/save/03_save_bogusfile_neg.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Li Ge <lge at us.ibm.com>
-# Test Description:
-# Negative Test:
-# Create a new domain. Save this domain to bogus file reference. Verify fail.
-
-import time
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Save currently not supported for HVM domains")
-
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-domain.closeConsole()
-
-# Save it out
-status, output = traceCommand("xm save %s /NOWHERE/test.state" % domain.getName())
-eyecatcher1 = "Traceback"
-eyecatcher2 = "Error:"
-where1 = output.find(eyecatcher1)
-where2 = output.find(eyecatcher2)
-if status == 0:
- FAIL("xm save returned bad status, expected non 0, status is: %i" % status)
-elif where1 == 0:
- FAIL("xm save returned a stack dump, expected nice error message")
-elif where2 == -1:
- FAIL("xm save returned bad output, expected Error:, output is: %s" % output)
diff --git a/tools/xm-test/tests/save/Makefile.am b/tools/xm-test/tests/save/Makefile.am
deleted file mode 100644
index 086e8d1..0000000
--- a/tools/xm-test/tests/save/Makefile.am
+++ /dev/null
@@ -1,24 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_save_basic_pos.test \
- 02_save_badparm_neg.test \
- 03_save_bogusfile_neg.test
-
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
-
diff --git a/tools/xm-test/tests/sched-credit/01_sched_credit_weight_cap_pos.py b/tools/xm-test/tests/sched-credit/01_sched_credit_weight_cap_pos.py
deleted file mode 100644
index cdbca0f..0000000
--- a/tools/xm-test/tests/sched-credit/01_sched_credit_weight_cap_pos.py
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/usr/bin/python
-#
-# Sched-credit tests modified from SEDF tests
-#
-
-import re
-
-from XmTestLib import *
-
-paramsRE = re.compile(r'^[^ ]* *[^ ]* *([^ ]*) *([^ ]*)$')
-
-def get_sched_credit_params(domain):
- status, output = traceCommand("xm sched-credit -d %s | tail -1" %
- domain.getName())
-
- if status != 0:
- FAIL("Getting sched-credit parameters return non-zero rv (%d)",
- status)
-
- m = paramsRE.match(output)
- if not m:
- FAIL("xm sched-credit gave bad output")
- weight = int(m.group(1))
- cap = int(m.group(2))
- return (weight, cap)
-
-def set_sched_credit_weight(domain, weight):
- status, output = traceCommand("xm sched-credit -d %s -w %d" %(domain.getName(), weight))
- return status
-
-def set_sched_credit_cap(domain, cap):
- status, output = traceCommand("xm sched-credit -d %s -c %d" %(domain.getName(), cap))
- return status
-
-
-domain = XmTestDomain()
-
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-# check default param values
-(weight, cap) = get_sched_credit_params(domain)
-
-if weight != 256:
- FAIL("default weight is 256 (got %d)", weight)
-if cap != 0:
- FAIL("default cap is 0 (got %d)", cap)
-
-# set new parameters
-status = set_sched_credit_weight(domain, 512)
-if status != 0:
- FAIL("Setting sched-credit weight return non-zero rv (%d)", status)
-
-status = set_sched_credit_cap(domain, 100)
-if status != 0:
- FAIL("Setting sched-credit cap return non-zero rv (%d)", status)
-
-# check new param values
-(weight, cap) = get_sched_credit_params(domain)
-
-if weight != 512:
- FAIL("expected weight of 512 (got %d)", weight)
-if cap != 100:
- FAIL("expected cap of 100 (got %d)", cap)
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/sched-credit/Makefile.am b/tools/xm-test/tests/sched-credit/Makefile.am
deleted file mode 100644
index d37cc64..0000000
--- a/tools/xm-test/tests/sched-credit/Makefile.am
+++ /dev/null
@@ -1,20 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_sched_credit_weight_cap_pos.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/sedf/01_sedf_period_slice_pos.py b/tools/xm-test/tests/sedf/01_sedf_period_slice_pos.py
deleted file mode 100644
index 7339220..0000000
--- a/tools/xm-test/tests/sedf/01_sedf_period_slice_pos.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-# Author: Ryan Harper <ryanh at us.ibm.com>
-
-from XmTestLib import *
-
-def get_sedf_params(domain):
- status, output = traceCommand("xm sched-sedf %s" %(domain.getName()))
- return (status, output.split('\n')[1].split())
-
-
-domain = XmTestDomain(extraConfig = {"sched":"sedf"})
-
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-# get current param values as baseline
-(status, params) = get_sedf_params(domain)
-
-# check rv
-if status != 0:
- FAIL("Getting sedf parameters return non-zero rv (%d)", status)
-
-# parse out current params
-(name, domid, p, s, l, e, w) = params
-
-# NB: setting period requires non-zero slice
-# scale current period in half
-period = str(float(p) / 2)
-slice = str(float(p) / 4)
-
-opts = "%s -p %s -s %s" %(domain.getName(), period, slice)
-(status, output) = traceCommand("xm sched-sedf %s" %(opts))
-
-# check rv
-if status != 0:
- FAIL("Setting sedf parameters return non-zero rv (%d)" % status)
-
-# validate
-(s,params) = get_sedf_params(domain)
-
-# check rv
-if s != 0:
- FAIL("Getting sedf parameters return non-zero rv (%d)" % s)
-
-(name,domid,p1,s1,l1,e1,w1) = params
-
-if p1 != period:
- FAIL("Failed to change domain period from %f to %f" %(p, period))
-
-if s1 != slice:
- FAIL("Failed to change domain slice from %f to %f" %(s, slice))
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/sedf/02_sedf_period_lower_neg.py b/tools/xm-test/tests/sedf/02_sedf_period_lower_neg.py
deleted file mode 100644
index 73bf9f2..0000000
--- a/tools/xm-test/tests/sedf/02_sedf_period_lower_neg.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-# Author: Ryan Harper <ryanh at us.ibm.com>
-#
-# Test if sched-sedf <dom> -p <period> handles lower bound
-
-from XmTestLib import *
-
-def get_sedf_params(domain):
- status, output = traceCommand("xm sched-sedf %s" %(domain.getName()))
- return (status, output.split('\n')[1].split())
-
-
-domain = XmTestDomain(extraConfig = {"sched":"sedf"})
-
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-# pick bogus period
-period = "-1"
-
-# NB: setting period requires non-zero slice
-# scale current period in half
-slice = "5"
-
-opts = "%s -p %s -s %s" %(domain.getName(), period, slice)
-(status, output) = traceCommand("xm sched-sedf %s" %(opts))
-
-# we should see this output from xm
-eyecatcher = "Failed to set sedf parameters"
-
-# check for failure
-if output.find(eyecatcher) >= 0:
- FAIL("sched-sedf let me set bogus period (%s)" %(period))
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/sedf/03_sedf_slice_lower_neg.py b/tools/xm-test/tests/sedf/03_sedf_slice_lower_neg.py
deleted file mode 100644
index f9b07a4..0000000
--- a/tools/xm-test/tests/sedf/03_sedf_slice_lower_neg.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-# Author: Ryan Harper <ryanh at us.ibm.com>
-#
-# Test if sched-sedf <dom> -p <period> handles lower bound
-
-from XmTestLib import *
-
-def get_sedf_params(domain):
- status, output = traceCommand("xm sched-sedf %s" %(domain.getName()))
- return (status, output.split('\n')[1].split())
-
-
-domain = XmTestDomain(extraConfig = {"sched":"sedf"})
-
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-# pick bogus slice
-slice = "0"
-
-opts = "%s -s %s" %(domain.getName(), slice)
-(status, output) = traceCommand("xm sched-sedf %s" %(opts))
-
-# we should see this output from xm
-eyecatcher = "Failed to set sedf parameters"
-
-# check for failure
-if output.find(eyecatcher) >= 0:
- FAIL("sched-sedf let me set bogus slice (%s)" %(slice))
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/sedf/04_sedf_slice_upper_neg.py b/tools/xm-test/tests/sedf/04_sedf_slice_upper_neg.py
deleted file mode 100644
index 0d9d6d4..0000000
--- a/tools/xm-test/tests/sedf/04_sedf_slice_upper_neg.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-# Author: Ryan Harper <ryanh at us.ibm.com>
-
-from XmTestLib import *
-
-def get_sedf_params(domain):
- status, output = traceCommand("xm sched-sedf %s" %(domain.getName()))
- return (status, output.split('\n')[1].split())
-
-
-domain = XmTestDomain(extraConfig = {"sched":"sedf"})
-
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-# get current param values as baseline
-(status, params) = get_sedf_params(domain)
-
-# check rv
-if status != 0:
- FAIL("Getting sedf parameters return non-zero rv (%d)", status)
-
-# parse out current params
-(name, domid, p, s, l, e, w) = params
-
-# set slice > than current period
-slice = str(float(p)+1)
-
-opts = "%s -s %s" %(domain.getName(), slice)
-(status, output) = traceCommand("xm sched-sedf %s" %(opts))
-
-# we should see this output from xm
-eyecatcher = "Failed to set sedf parameters"
-
-# check for failure
-if output.find(eyecatcher) >= 0:
- FAIL("sched-sedf let me set a slice bigger than my period.")
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/sedf/05_sedf_extratime_pos.py b/tools/xm-test/tests/sedf/05_sedf_extratime_pos.py
deleted file mode 100644
index 702d64b..0000000
--- a/tools/xm-test/tests/sedf/05_sedf_extratime_pos.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-# Author: Ryan Harper <ryanh at us.ibm.com>
-
-from XmTestLib import *
-
-def get_sedf_params(domain):
- status, output = traceCommand("xm sched-sedf %s" %(domain.getName()))
- return (status, output.split('\n')[1].split())
-
-
-domain = XmTestDomain(extraConfig = {"sched":"sedf"})
-
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-# get current param values as baseline
-(status, params) = get_sedf_params(domain)
-
-# check rv
-if status != 0:
- FAIL("Getting sedf parameters return non-zero rv (%d)", status)
-
-# parse out current params
-(name, domid, p, s, l, e, w) = params
-
-# toggle extratime value
-extratime = str((int(e)+1)%2)
-
-direction = "disable"
-# NB: when disabling extratime(=0), must pass in a slice
-opts = "%s -e %s" %(domain.getName(), extratime)
-if extratime == "0":
- opts += " -s %s" %( str( (float(p)/2)+1 ) )
- direction = "enable"
-
-(status, output) = traceCommand("xm sched-sedf %s" %(opts))
-
-# check rv
-if status != 0:
- FAIL("Setting sedf parameters return non-zero rv (%d)" % status)
-
-# validate
-(s,params) = get_sedf_params(domain)
-
-# check rv
-if s != 0:
- FAIL("Getting sedf parameters return non-zero rv (%d)" % s)
-
-(name,domid,p1,s1,l1,e1,w1) = params
-
-if e1 != extratime:
- FAIL("Failed to %s extratime" %(direction))
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/sedf/06_sedf_extratime_disable_neg.py b/tools/xm-test/tests/sedf/06_sedf_extratime_disable_neg.py
deleted file mode 100644
index e0a7974..0000000
--- a/tools/xm-test/tests/sedf/06_sedf_extratime_disable_neg.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-# Author: Ryan Harper <ryanh at us.ibm.com>
-
-from XmTestLib import *
-
-def get_sedf_params(domain):
- status, output = traceCommand("xm sched-sedf %s" %(domain.getName()))
- return (status, output.split('\n')[1].split())
-
-
-domain = XmTestDomain(extraConfig = {"sched":"sedf"})
-
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-# get current param values as baseline
-(status, params) = get_sedf_params(domain)
-
-# check rv
-if status != 0:
- FAIL("Getting sedf parameters return non-zero rv (%d)", status)
-
-# parse out current params
-(name, domid, p, s, l, e, w) = params
-
-# if extratime is off, turn it on and drop slice to 0
-if str(e) == "0":
- extratime = 1
- opts = "%s -e %s" %(domain.getName(), extratime)
- (status, output) = traceCommand("xm sched-sedf %s" %(opts))
-
- # check rv
- if status != 0:
- FAIL("Failed to force extratime on (%d)" % status)
-
- # drop slice to 0 now that we are in extratime mode
- slice = 0
-
- opts = "%s -s %s" %(domain.getName(), slice)
- (status, output) = traceCommand("xm sched-sedf %s" %(opts))
-
- # check rv
- if status != 0:
- FAIL("Failed to force slice to 0 (%d)" % status)
-
-
-# ASSERT(extratime=1, slice=0)
-
-# attempt to disable extratime without setting slice
-extratime = "0"
-
-opts = "%s -e %s " %(domain.getName(), extratime)
-(status, output) = traceCommand("xm sched-sedf %s" %(opts))
-
-# we should see this output from xm
-eyecatcher = "Failed to set sedf parameters"
-
-# check for failure
-if output.find(eyecatcher) >= 0:
- FAIL("sched-sedf let me disable extratime without a non-zero slice")
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/sedf/Makefile.am b/tools/xm-test/tests/sedf/Makefile.am
deleted file mode 100644
index 1f9d5c2..0000000
--- a/tools/xm-test/tests/sedf/Makefile.am
+++ /dev/null
@@ -1,25 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_sedf_period_slice_pos.test \
- 02_sedf_period_lower_neg.test \
- 03_sedf_slice_lower_neg.test \
- 04_sedf_slice_upper_neg.test \
- 05_sedf_extratime_pos.test \
- 06_sedf_extratime_disable_neg.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/shutdown/01_shutdown_basic_pos.py b/tools/xm-test/tests/shutdown/01_shutdown_basic_pos.py
deleted file mode 100644
index bfedf65..0000000
--- a/tools/xm-test/tests/shutdown/01_shutdown_basic_pos.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Paul Larson <pl at us.ibm.com>
-
-# Description:
-# Positive Tests:
-# Test for xm shutdown
-# 1) Create domain, verify it's up with console
-# 2) shut down the domain, verify it's down
-
-import time
-import commands
-
-from XmTestLib import *
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-# Start it
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- # Make sure a command succeeds
- run = console.runCmd("ls /bin")
-except ConsoleError, e:
- FAIL(str(e))
-
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-status, output = traceCommand("xm shutdown %s" % domain.getName())
-if status != 0:
- FAIL("good xm shutdown exited with bad %i != 0" % status)
-
-# Verify the domain is gone
-time.sleep(10)
-
-if isDomainRunning(domain.getName()):
-
- traceCommand("xm list")
- if isDomainRunning(domain.getName()):
- FAIL("Guest domain failed to shutdown")
- else:
- FAIL("I had to run an xm list to update xend state!")
-
-
diff --git a/tools/xm-test/tests/shutdown/02_shutdown_badparm_neg.py b/tools/xm-test/tests/shutdown/02_shutdown_badparm_neg.py
deleted file mode 100644
index 6a70ae2..0000000
--- a/tools/xm-test/tests/shutdown/02_shutdown_badparm_neg.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Paul Larson <pl at us.ibm.com>
-
-# Description:
-# Positive Tests:
-# Test for xm shutdown
-# 1) Create domain
-# 2) call xm shutdown with a bad parameter, expect failure
-
-import commands
-
-from XmTestLib import *
-
-eyecatcher = "Error:"
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-# Start it
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-
-ret, output = traceCommand("xm shutdown -x %s" % domain.getName())
-where = output.find(eyecatcher)
-if (ret == 0):
- FAIL("xm shutdown returned invalid %i == 0" % ret)
-elif where == -1:
- FAIL("xm shutdown failed to report error for bad arg")
-
-# Stop the domain (nice shutdown)
-domain.stop()
diff --git a/tools/xm-test/tests/shutdown/03_shutdown_nonexist_neg.py b/tools/xm-test/tests/shutdown/03_shutdown_nonexist_neg.py
deleted file mode 100644
index 4998911..0000000
--- a/tools/xm-test/tests/shutdown/03_shutdown_nonexist_neg.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Paul Larson <pl at us.ibm.com>
-
-# Description:
-# Positive Tests:
-# Test for xm shutdown
-# 1) call xm shutdown with a nonexistant domain, expect failure
-
-import commands
-
-from XmTestLib import *
-
-eyecatcher = "Error:"
-
-ret, output = traceCommand("xm shutdown 9999")
-where = output.find(eyecatcher)
-if (ret == 0):
- FAIL("xm shutdown returned invalid %i == 0" % ret)
-elif where == -1:
- FAIL("xm shutdown failed to report error for bad domid")
diff --git a/tools/xm-test/tests/shutdown/Makefile.am b/tools/xm-test/tests/shutdown/Makefile.am
deleted file mode 100644
index 0fb44f0..0000000
--- a/tools/xm-test/tests/shutdown/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_shutdown_basic_pos.test 02_shutdown_badparm_neg.test 03_shutdown_nonexist_neg.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
-
diff --git a/tools/xm-test/tests/sysrq/01_sysrq_basic_neg.py b/tools/xm-test/tests/sysrq/01_sysrq_basic_neg.py
deleted file mode 100644
index cc42d47..0000000
--- a/tools/xm-test/tests/sysrq/01_sysrq_basic_neg.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-# Check to make sure an invalid sysrq is handled appropriately
-
-import re
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Sysrq not supported for HVM domains")
-
-status, output = traceCommand("xm sysrq does_not_exist s");
-
-if status == 0:
- if verbose:
- print "Bad SysRq output: " + output;
- FAIL("Bad SysRq didn't report error: %i == 0" % status);
diff --git a/tools/xm-test/tests/sysrq/02_sysrq_sync_pos.py b/tools/xm-test/tests/sysrq/02_sysrq_sync_pos.py
deleted file mode 100644
index e6d73fb..0000000
--- a/tools/xm-test/tests/sysrq/02_sysrq_sync_pos.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-import sys
-import re
-import time
-
-from XmTestLib import *
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Sysrq not supported for HVM domains")
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-# Start it
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-status, output = traceCommand("xm sysrq %s s" % domain.getName())
-
-if status != 0:
- FAIL("Good sysrq failed with: %i != 0", status)
-
-# -- CHECK OUTPUT
-
-# Run 'ls'
-try:
- # Check the dmesg output on the domU
- run = console.runCmd("dmesg | grep Emerg\n")
-except ConsoleError, e:
- FAIL(str(e))
-
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
-
-# Save a transcript for human review
-# saveLog(console.getHistory())
-
-# Check dmesg for the sysrq notice
-if not re.search("Emergency", run["output"]):
- FAIL("Sync SysRq not delivered")
diff --git a/tools/xm-test/tests/sysrq/03_sysrq_withreboot_pos.py b/tools/xm-test/tests/sysrq/03_sysrq_withreboot_pos.py
deleted file mode 100644
index d314b40..0000000
--- a/tools/xm-test/tests/sysrq/03_sysrq_withreboot_pos.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-from XmTestLib import *
-
-import time
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Sysrq not supported for HVM domains")
-
-domain = XmTestDomain()
-
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create domain:"
- print e.extra
- FAIL(str(e))
-
-status, output = traceCommand("xm reboot %s" % domain.getName())
-if status != 0:
- FAIL("reboot %s failed with %i != 0" % (domain.getName(), status))
-
-# Wait for the reboot to finish
-time.sleep(20)
-
-status, output = traceCommand("xm sysrq %s s" % domain.getName())
-if status != 0:
- FAIL("sysrq failed with %i != 0" % status)
-
-try:
- run = console.runCmd("dmesg | grep -i reboot")
-except ConsoleError, e:
- FAIL(str(e))
-
-if run == 0:
- FAIL("reboot/sysrq resulted in reboot!")
diff --git a/tools/xm-test/tests/sysrq/Makefile.am b/tools/xm-test/tests/sysrq/Makefile.am
deleted file mode 100644
index 9de15b6..0000000
--- a/tools/xm-test/tests/sysrq/Makefile.am
+++ /dev/null
@@ -1,23 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_sysrq_basic_neg.test \
- 02_sysrq_sync_pos.test \
- 03_sysrq_withreboot_pos.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
-
diff --git a/tools/xm-test/tests/unpause/01_unpause_basic_pos.py b/tools/xm-test/tests/unpause/01_unpause_basic_pos.py
deleted file mode 100644
index e7cfb5f..0000000
--- a/tools/xm-test/tests/unpause/01_unpause_basic_pos.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Paul Larson <pl at us.ibm.com>
-
-# Description:
-# Positive Tests:
-# Tests for xm unpause
-# 1) Create domain, verify it's up with console
-# 2) randomly pause and unpause the domain
-# 3) unpause it one last time
-# 4) verify it's still alive with console
-
-import time
-import commands
-from random import *
-
-from XmTestLib import *
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-domain = XmTestDomain()
-
-# Start it
-try:
- console = domain.start()
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-try:
- # Make sure a command succeeds
- run = console.runCmd("ls")
-except ConsoleError, e:
- FAIL(str(e))
-
-# Close the console
-domain.closeConsole()
-
-seed(time.time())
-
-for i in range(100):
- pauseit = randint(0,1)
- if(pauseit):
- # Pause the domain
- status, output = traceCommand("xm pause %s" % domain.getName())
- if status != 0:
- FAIL("xm pause returned invalid %i != 0", status)
- else:
- # Unpause the domain
- status, output = traceCommand("xm unpause %s" % domain.getName())
- if status != 0:
- FAIL("xm unpause returned invalid %i != 0", status)
-
-# Make sure the domain is unpaused before we finish up
-status, output = traceCommand("xm unpause %s" % domain.getName())
-if status != 0:
- FAIL("xm unpause returned invalid %i != 0", status)
-
-# Are we still alive after all that?
-try:
- console = domain.getConsole()
- run = console.runCmd("ls")
-except ConsoleError, e:
- FAIL(str(e))
-
-# Close the console
-domain.closeConsole()
-
-if run["return"] != 0:
- FAIL("console failed to attach to supposedly unpaused domain")
-
-# Stop the domain (nice shutdown)
-domain.stop()
-
diff --git a/tools/xm-test/tests/unpause/Makefile.am b/tools/xm-test/tests/unpause/Makefile.am
deleted file mode 100644
index b0018b0..0000000
--- a/tools/xm-test/tests/unpause/Makefile.am
+++ /dev/null
@@ -1,20 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_unpause_basic_pos.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/vcpu-disable/01_vcpu-disable_basic_pos.py b/tools/xm-test/tests/vcpu-disable/01_vcpu-disable_basic_pos.py
deleted file mode 100644
index 0869125..0000000
--- a/tools/xm-test/tests/vcpu-disable/01_vcpu-disable_basic_pos.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Authors: Dan Smith <danms at us.ibm.com>
-# Ryan Harper <ryanh at us.ibm.com>
-
-# 1) Make sure we have a multi cpu system
-# 2) Create a test domain with 2 VCPUs
-# 3) Verify that both VCPUs are alive
-# 4) Disable DOM VCPU1 by setting the VCPU count to 1
-# 5) Assert that the VCPU has been disabled
-# 6) Enable DOM VCPU1 (restore VCPU count to 2)
-# 7) Assert that the VCPUs are both alive again
-
-import sys
-import re
-import time
-
-from XmTestLib import *
-
-check_status = 1
-max_tries = 10
-
-def safecmd(cmd):
- i=0
- while i < max_tries:
- status, output = traceCommand(cmd)
- if status == 0:
- break
- i = i+1
- # print "output: [%s]"%(output)
- time.sleep(1)
- return status, output
-
-# Verify that we can run this test on this host
-if smpConcurrencyLevel() <= 1:
- print "*** NOTE: This machine does not have more than one physical"
- print " or logical cpu. The vcpu-disable test cannot be run!"
- SKIP("Host not capable of running test")
-
-# Start a XmTestDomain with 2 VCPUs
-domain = XmTestDomain(extraConfig={"vcpus":2})
-
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-# Disable VCPU 1
-cmd = "xm vcpu-set %s 1" % domain.getName()
-status, output = safecmd(cmd)
-if check_status and status != 0:
- FAIL("\"%s\" returned invalid %i != 0" %(cmd,status))
-
-# Wait for the change to become active
-for i in [1,2,3,4,5,6,7,8,9,10]:
- domUvcpu1 = getVcpuInfo(domain.getName())[1]
- status, output = traceCommand("xm vcpu-list")
- if domUvcpu1 is None:
- break
- time.sleep(1)
-
-if domUvcpu1 is not None:
- print "domUvcpu1: [%s] output: [%s]"%(domUvcpu1, output)
- FAIL("failed to disable VCPU1")
-
-# Enable VCPU 1
-cmd = "xm vcpu-set %s 2" % domain.getName()
-status, output = safecmd(cmd)
-if check_status and status != 0:
- FAIL("\"%s\" returned invalid %i != 0" %(cmd,status))
-
-for i in [1,2,3,4,5,6,7,8,9,10]:
- domUvcpu1 = getVcpuInfo(domain.getName())[1]
- if domUvcpu1 is not None:
- break
- time.sleep(1)
-
-domain.destroy()
diff --git a/tools/xm-test/tests/vcpu-disable/Makefile.am b/tools/xm-test/tests/vcpu-disable/Makefile.am
deleted file mode 100644
index 35da894..0000000
--- a/tools/xm-test/tests/vcpu-disable/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-
-SUBDIRS =
-
-TESTS = 01_vcpu-disable_basic_pos.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/vcpu-pin/01_vcpu-pin_basic_pos.py b/tools/xm-test/tests/vcpu-pin/01_vcpu-pin_basic_pos.py
deleted file mode 100644
index f254401..0000000
--- a/tools/xm-test/tests/vcpu-pin/01_vcpu-pin_basic_pos.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Dan Smith <danms at us.ibm.com>
-
-# 1) Make sure we have a multi cpu system
-# 2) Create a test domain and pin its VCPU0 to CPU 0 and then 1
-
-import sys;
-import re;
-
-from XmTestLib import *
-
-# Verify that we can run this test on this host
-if smpConcurrencyLevel() <= 1:
- print "*** NOTE: This machine does not have more than one physical"
- print " or logical cpu. The vcpu-pin test cannot be run!"
- SKIP("Host not capable of running test")
-
-domain = XmTestDomain()
-
-try:
- domain.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print "Failed to create test domain because:"
- print e.extra
- FAIL(str(e))
-
-status, output = traceCommand("xm vcpu-pin %s 0 0" % domain.getName())
-
-if status != 0:
- FAIL("xm vcpu-pin returned invalid %i != 0" % status)
-
-cpu = getVcpuInfo(domain.getName())[0]
-
-if cpu != 0:
- FAIL("failed to switch VCPU 0 to CPU 0")
-
-status, output = traceCommand("xm vcpu-pin %s 0 1" % domain.getName())
-
-if status != 0:
- FAIL("xm vcpu-pin returned invalid %i != 0" % status)
-
-cpu = getVcpuInfo(domain.getName())[0]
-
-if cpu != 1:
- FAIL("failed to switch VCPU 0 to CPU 1")
-
-domain.stop()
diff --git a/tools/xm-test/tests/vcpu-pin/Makefile.am b/tools/xm-test/tests/vcpu-pin/Makefile.am
deleted file mode 100644
index 9546330..0000000
--- a/tools/xm-test/tests/vcpu-pin/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-
-SUBDIRS =
-
-TESTS = 01_vcpu-pin_basic_pos.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
-
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/xapi/01_xapi-vm_basic.py b/tools/xm-test/tests/xapi/01_xapi-vm_basic.py
deleted file mode 100644
index 6f149a0..0000000
--- a/tools/xm-test/tests/xapi/01_xapi-vm_basic.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: Stefan Berger <stefanb at us.ibm.com>
-
-# Basic VM creation test
-
-from XmTestLib import xapi
-from XmTestLib.XenAPIDomain import XmTestAPIDomain
-from XmTestLib import *
-from xen.xend import XendAPIConstants
-import commands
-import os
-
-try:
- # XmTestAPIDomain tries to establish a connection to XenD
- domain = XmTestAPIDomain()
-except Exception, e:
- SKIP("Skipping test. Error: %s" % str(e))
-vm_uuid = domain.get_uuid()
-
-session = xapi.connect()
-
-domain.start(startpaused=True)
-
-res = session.xenapi.VM.get_power_state(vm_uuid)
-
-if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_PAUSED]:
- FAIL("VM was not started in 'paused' state")
-
-res = session.xenapi.VM.unpause(vm_uuid)
-
-res = session.xenapi.VM.get_power_state(vm_uuid)
-
-if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_RUNNING]:
- FAIL("VM could not be put into 'running' state")
-
-console = domain.getConsole()
-
-try:
- run = console.runCmd("cat /proc/interrupts")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL("Could not access proc-filesystem")
-
-res = session.xenapi.VM.pause(vm_uuid)
-
-res = session.xenapi.VM.get_power_state(vm_uuid)
-
-if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_PAUSED]:
- FAIL("VM could not be put into 'paused' state")
-
-res = session.xenapi.VM.unpause(vm_uuid)
-
-res = session.xenapi.VM.get_power_state(vm_uuid)
-
-if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_RUNNING]:
- FAIL("VM could not be 'unpaused'")
-
-domain.stop()
-domain.destroy()
diff --git a/tools/xm-test/tests/xapi/02_xapi-vbd_basic.py b/tools/xm-test/tests/xapi/02_xapi-vbd_basic.py
deleted file mode 100644
index 7b14702..0000000
--- a/tools/xm-test/tests/xapi/02_xapi-vbd_basic.py
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2007
-# Copyright (C) flonatel GmbH & Co. KG
-# Authors: Stefan Berger <stefanb at us.ibm.com>
-# Andreas Florath <xen at flonatel.org>
-
-# Tests related to SR, VDI, VBD
-#
-# Used methods:
-# SR: get_by_name_label, get_VDIs
-#
-# VDI: create, get_name_label, destroy
-#
-# VBD: create, get_mode, get_VM, get_VDI, get_device
-#
-# VM: get_VBDs
-
-from XmTestLib import xapi
-from XmTestLib.XenAPIDomain import XmTestAPIDomain
-from XmTestLib import *
-from xen.xend import XendAPIConstants
-import commands
-import os
-
-try:
- # XmTestAPIDomain tries to establish a connection to XenD
- domain = XmTestAPIDomain()
-except Exception, e:
- SKIP("Skipping test. Error: %s" % str(e))
-
-vm_uuid = domain.get_uuid()
-
-session = xapi.connect()
-
-# Do something with SR/VDI/VBD
-
-sr_uuid = session.xenapi.SR.get_by_name_label("Local")
-if len(sr_uuid) == 0:
- FAIL("Could not get a handle on SR 'Local'")
-
-vdi_rec = { 'name_label' : "My disk",
- 'SR' : sr_uuid[0],
- 'virtual_size': 1 << 10,
- 'sector_size' : 512,
- 'type' : 0,
- 'shareable' : 0,
- 'read-only' : 0,
- 'other_config': { 'location': "phy:/dev/xg/storage_root" },
-}
-
-vdi_ref = session.xenapi.VDI.create(vdi_rec)
-
-res = session.xenapi.SR.get_VDIs(sr_uuid[0])
-if vdi_ref not in res:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("SR_get_VDI does not show new VDI")
-
-res = session.xenapi.VDI.get_name_label(vdi_ref)
-if res != vdi_rec['name_label']:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("VDI_get_name_label return wrong information")
-
-#MORE method calls to VDI to add here...
-
-
-vbd_rec = { 'VM' : vm_uuid,
- 'VDI' : vdi_ref,
- 'device': "xvda1",
- 'mode' : 1,
- 'driver': 1,
-}
-
-vbd_ref = session.xenapi.VBD.create(vbd_rec)
-
-res = session.xenapi.VBD.get_mode(vbd_ref)
-print "VBD mode: %s" % res
-# FIXME: Check this. Should not have to subtract '1'.
-if res != XendAPIConstants.XEN_API_VBD_MODE[int(vbd_rec['mode']) - 1]:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("VBD_get_mode returned wrong information")
-
-res = session.xenapi.VBD.get_VM(vbd_ref)
-if res != vm_uuid:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("VBD_get_VM returned wrong result")
-
-res = session.xenapi.VBD.get_VDI(vbd_ref)
-if res != vdi_ref:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("VBD_get_VDI returned wrong result")
-
-res = session.xenapi.VBD.get_device(vbd_ref)
-print "VBD device: %s" % res
-if res != vbd_rec['device']:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("VBD_get_device returned wrong result")
-
-res = session.xenapi.VM.get_VBDs(vm_uuid)
-if vbd_ref not in res:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("VM_get_VBDS does not show created VBD")
-
-rc = domain.start()
-
-console = domain.getConsole()
-
-try:
- run = console.runCmd("cat /proc/interrupts")
-except ConsoleError, e:
- saveLog(console.getHistory())
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("Could not access proc-filesystem")
-
-domain.stop()
-domain.destroy()
-
-session.xenapi.VDI.destroy(vdi_ref)
-
-res = session.xenapi.SR.get_VDIs(sr_uuid[0])
-if vdi_ref in res:
- FAIL("SR_get_VDI still shows deleted VDI")
diff --git a/tools/xm-test/tests/xapi/03_xapi-network_pos.py b/tools/xm-test/tests/xapi/03_xapi-network_pos.py
deleted file mode 100644
index 900d487..0000000
--- a/tools/xm-test/tests/xapi/03_xapi-network_pos.py
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/bin/python
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2009 flonatel GmbH & Co. KG
-#============================================================================
-#
-# Author: Andreas Florath <xen at flonatel.org>
-# Loosly based on the original testcase from
-# Tom Wilkie <tom.wilkie at gmail.com>
-#
-# This test case creates two guest systems, creates a (very) private
-# network between them and attaches the ethernet apropriate.
-# Note: in this test case there are some fixed IP and network
-# addresses used. This is not a problem, because those are really
-# used only for local communication.
-#
-
-import sys
-import time
-
-from XmTestLib import *
-from XmTestLib.network_utils import *
-from XmTestLib.XenAPIDomain import XmTestAPIDomain
-
-# Some config for this testcase
-class TCConfig:
- network_name = "xapi-network-xm-test-03"
-
- ip_addr_1 = "172.16.77.70"
- ip_addr_2 = "172.16.77.71"
- default_gateway = "172.16.77.72"
- default_netmask = "255.255.255.0"
-
- @staticmethod
- def remove_network(guest):
- nw = guest.session.xenapi.network.get_all()
- for n in nw:
- name = guest.session.xenapi.network.get_name_label(n)
- if name == TCConfig.network_name:
- guest.session.xenapi.network.destroy(n)
-
-
-# Create two domains (default XmTestDomain, with our ramdisk)
-try:
- guest1 = XmTestAPIDomain()
- console1 = guest1.start()
-# guest1.newDevice(XenNetDevice, "eth0")
-# guest1_netdev = guest1.getDevice("eth0")
- guest2 = XmTestAPIDomain()
- console2 = guest2.start()
-except DomainError, e:
- if verbose:
- print("Failed to create test domain because: %s" % e.extra)
- FAIL(str(e))
-
-# Clean up relicts
-TCConfig.remove_network(guest1)
-
-# Create a network
-network = guest1.session.xenapi.network.create(
- { "name_label": TCConfig.network_name,
- "name_description": "This is a testing network",
- "default_gateway": TCConfig.default_gateway,
- "default_netmask": TCConfig.default_netmask,
- "other_config": {} } )
-
-# Attach two domains to it
-status, msg = network_attach(
- guest1.getName(), console1, bridge=TCConfig.network_name)
-if status:
- FAIL(msg)
-
-status, msg = network_attach(
- guest2.getName(), console2, bridge=TCConfig.network_name)
-if status:
- FAIL(msg)
-
-# Configure IP addresses on two guests
-try:
- run = console1.runCmd(
- "ifconfig eth0 " + TCConfig.ip_addr_1
- + " netmask " + TCConfig.default_netmask + " up")
- run = console2.runCmd(
- "ifconfig eth0 " + TCConfig.ip_addr_2
- + " netmask " + TCConfig.default_netmask + " up")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-# Now ping...
-try:
- run = console1.runCmd("ping -c 4 " + TCConfig.ip_addr_2)
- if run['return'] > 0:
- FAIL("Could not ping other host")
- run = console2.runCmd("ping -c 4 " + TCConfig.ip_addr_1)
- if run['return'] > 0:
- FAIL("Could not pint other host")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-status, msg = network_detach(guest1.getName(), console1)
-status, msg = network_detach(guest2.getName(), console2)
-
-# Clean up
-TCConfig.remove_network(guest1)
-guest1.closeConsole()
-guest1.stop()
-guest2.closeConsole()
-guest2.stop()
-
diff --git a/tools/xm-test/tests/xapi/04_xapi-data_uri_handling.py b/tools/xm-test/tests/xapi/04_xapi-data_uri_handling.py
deleted file mode 100644
index 7d1a39b..0000000
--- a/tools/xm-test/tests/xapi/04_xapi-data_uri_handling.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/python
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2009 flonatel GmbH & Co. KG
-#============================================================================
-#
-# This file contains test cases for checking the data URI
-# functionality:
-# kernel and ramdisk are both checked with original uri,
-# file uri and data uri (in every constallation)
-#
-
-import copy
-
-from xen.util.fileuri import schemes, scheme_data, scheme_file
-
-from XmTestLib import *
-from XmTestLib.network_utils import *
-from XmTestLib.XenAPIDomain import XmTestAPIDomain
-
-kernel_orig_uri = arch.configDefaults['kernel']
-ramdisk_orig_uri = arch.configDefaults['ramdisk']
-kernel_data_uri = scheme_data.create_from_file(kernel_orig_uri)
-ramdisk_data_uri = scheme_data.create_from_file(ramdisk_orig_uri)
-kernel_file_uri = scheme_file.encode(kernel_orig_uri)
-ramdisk_file_uri = scheme_file.encode(ramdisk_orig_uri)
-
-config = copy.copy(arch.configDefaults)
-
-for kernel in (kernel_orig_uri, kernel_data_uri, kernel_file_uri):
- for ramdisk in (ramdisk_orig_uri, ramdisk_data_uri, ramdisk_file_uri):
- config['kernel'] = kernel
- config['ramdisk'] = ramdisk
- print("Using kernel='%s' ramdisk='%s'" % (kernel[:100], ramdisk[:100]))
- try:
- guest = XmTestAPIDomain(baseConfig = config)
- console = guest.start()
- except DomainError, e:
- if verbose:
- print("Failed to create test domain because: %s" % e.extra)
- FAIL(str(e))
-
- try:
- run = console.runCmd("ls /")
- if run['return'] > 0:
- FAIL("Could not start host")
- except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
- guest.closeConsole()
- guest.stop()
-
diff --git a/tools/xm-test/tests/xapi/20_xapi-cpu_pool_basic.py b/tools/xm-test/tests/xapi/20_xapi-cpu_pool_basic.py
deleted file mode 100644
index 0476412..0000000
--- a/tools/xm-test/tests/xapi/20_xapi-cpu_pool_basic.py
+++ /dev/null
@@ -1,157 +0,0 @@
-#!/usr/bin/python
-
-
-# Basic Pool creation tests
-
-from XmTestLib import xapi
-from XmTestLib import *
-
-
-session = xapi.connect()
-host_ref = session.xenapi.host.get_all()[0]
-pools = session.xenapi.host.get_resident_cpu_pools(host_ref)
-if len(pools) != 1:
- SKIP("Only Pool-0 have to be created for this test")
-
-
-# check extension of host object
-host_recs = session.xenapi.host.get_all_records()
-host_rec = host_recs[host_recs.keys()[0]]
-if len(host_recs.keys()) != 1 or not host_rec.has_key("resident_cpu_pools") or \
- len(host_rec["resident_cpu_pools"]) != 1:
- FAIL("Missing or wrong field 'resident_cpu_pools' in host record")
-
-
-# check extension of host_cpu object
-host_cpu_recs = session.xenapi.host_cpu.get_all_records()
-assigned_cpus = [ cpu for cpu in host_cpu_recs.values() if len(cpu["cpu_pool"]) > 0 ]
-unassigned_cpus = session.xenapi.host_cpu.get_unassigned_cpus()
-if len(host_cpu_recs) - len(assigned_cpus) != len(unassigned_cpus):
- FAIL("Wrong host_cpu count values; CPUS total: %d, CPUS ass: %d, CPUS unass: %d" % (
- len(host_cpu_recs), len(assigned_cpus), len(unassigned_cpus)))
-
-for cpu_rec in host_cpu_recs.values():
- cpu_pool = session.xenapi.host_cpu.get_cpu_pool(cpu_rec['uuid'])
- if cpu_pool != cpu_rec['cpu_pool']:
- FAIL("Inconsistency of cpu_pool ref between host_cpu record (%s) "
- "and get_cpu_pool (%s)" % (cpu_rec['cpu_pool'], cpu_pool))
-
-
-# create / modify / remove managed cpu pools
-pool1_cfg = { 'name_label' : 'Pool-1',
- 'name_description' : 'new pool',
- 'auto_power_on' : False,
- 'ncpu' : '3',
- 'sched_policy' : 'credit',
- 'proposed_CPUs' : ['1','2'],
- 'other_config' : { 'xmtest' : True },
- }
-pool1 = session.xenapi.cpu_pool.create(pool1_cfg)
-pool1_rec = session.xenapi.cpu_pool.get_record(pool1)
-for k in pool1_cfg.keys():
- if pool1_rec[k] != pool1_cfg[k]:
- FAIL("Create error Pool-1 (create config %s, current config: %s, key: %s)" % (
- pool1_cfg, pool1_rec, k))
-
-pool_all = session.xenapi.cpu_pool.get_all()
-if len(pool_all) != 2:
- FAIL("cpu_pool.get_all() returns '%d', expected '2'" % len(pool_all))
-
-pool_all = session.xenapi.cpu_pool.get_all_records()
-if len(pool_all) != 2:
- FAIL("cpu_pool.get_all_records() returns '%d', expected '2'" % len(pool_all))
-
-if pool1 != session.xenapi.cpu_pool.get_by_name_label(pool1_cfg['name_label'])[0]:
- FAIL("cpu_pool.get_by_name_label() returns wrong value")
-
-if pool1 != session.xenapi.cpu_pool.get_by_uuid(pool1):
- FAIL("cpu_pool.get_by_uuid() returns wrong value")
-
-if session.xenapi.cpu_pool.get_activated(pool1):
- FAIL("cpu_pool.get_activated() returns 'true' instead of 'false'")
-
-if pool1_cfg['auto_power_on'] != session.xenapi.cpu_pool.get_auto_power_on(pool1):
- FAIL("cpu_pool.get_auto_power_on() returns wrong value")
-
-if len(session.xenapi.cpu_pool.get_host_CPUs(pool1)) != 0:
- FAIL("cpu_pool.get_host_CPUs has to return an empty list")
-
-if pool1_cfg['name_label'] != session.xenapi.cpu_pool.get_name_label(pool1):
- FAIL("cpu_pool.get_name_label() returns wrong value")
-
-if pool1_cfg['name_description'] != session.xenapi.cpu_pool.get_name_description(pool1):
- FAIL("cpu_pool.get_name_description() returns wrong value")
-
-if pool1_cfg['ncpu'] != session.xenapi.cpu_pool.get_ncpu(pool1):
- FAIL("cpu_pool.get_ncpu() returns wrong value")
-
-cfg_len = len(pool1_cfg['proposed_CPUs'])
-api_len = len(session.xenapi.cpu_pool.get_proposed_CPUs(pool1))
-if cfg_len != api_len:
- FAIL("cpu_pool.get_proposed_CPUs() returns wrong value; cfg_cnt: %s, api_cnt:%s" % (cfg_len, api_len))
-
-other_config = session.xenapi.cpu_pool.get_other_config(pool1)
-if pool1_cfg['other_config']['xmtest'] != other_config.get('xmtest'):
- FAIL("cpu_pool.get_other_config() returns wrong value")
-
-if session.xenapi.cpu_pool.get_resident_on(pool1) != session.xenapi.host.get_all()[0]:
- FAIL("cpu_pool.get_resident_on() returns wrong value")
-
-if pool1_cfg['sched_policy'] != session.xenapi.cpu_pool.get_sched_policy(pool1):
- FAIL("cpu_pool.get_sched_policy() returns wrong value")
-
-if len(session.xenapi.cpu_pool.get_started_VMs(pool1)) != 0:
- FAIL("cpu_pool.get_started_VMs() returns wrong value")
-
-if pool1 != session.xenapi.cpu_pool.get_uuid(pool1):
- FAIL("cpu_pool.get_uuid() returns wrong value")
-
-session.xenapi.cpu_pool.set_auto_power_on(pool1, True)
-if not session.xenapi.cpu_pool.get_auto_power_on(pool1):
- FAIL("cpu_pool.get_auto_power_on() returns wrong value")
-
-session.xenapi.cpu_pool.set_proposed_CPUs(pool1, [4])
-if '4' not in session.xenapi.cpu_pool.get_proposed_CPUs(pool1):
- FAIL("cpu_pool.get_proposed_CPUs() returns wrong value; (set_proposed_CPUs)")
-
-session.xenapi.cpu_pool.add_to_proposed_CPUs(pool1, 5)
-val = session.xenapi.cpu_pool.get_proposed_CPUs(pool1)
-if '5' not in val:
- FAIL("cpu_pool.get_proposed_CPUs() returns wrong value; %s not in %s" % ('5',val))
-
-session.xenapi.cpu_pool.remove_from_proposed_CPUs(pool1, 5)
-val = session.xenapi.cpu_pool.get_proposed_CPUs(pool1)
-if '5' in val:
- FAIL("cpu_pool.get_proposed_CPUs() returns wrong value; %s in %s" % ('5',val))
-
-session.xenapi.cpu_pool.set_name_label(pool1, 'New-Pool-1')
-if 'New-Pool-1' != session.xenapi.cpu_pool.get_name_label(pool1):
- FAIL("cpu_pool.get_name_label() returns wrong value")
-
-session.xenapi.cpu_pool.set_ncpu(pool1, 4)
-if '4' != session.xenapi.cpu_pool.get_ncpu(pool1):
- FAIL("cpu_pool.get_ncpu() returns wrong value")
-
-session.xenapi.cpu_pool.set_other_config(pool1, {'test' : 'ok'})
-other_config = session.xenapi.cpu_pool.get_other_config(pool1)
-if other_config.get('test') != 'ok':
- FAIL("cpu_pool.get_other_config() returns wrong value")
-
-session.xenapi.cpu_pool.add_to_other_config(pool1, 'new_entry', 'added')
-other_config = session.xenapi.cpu_pool.get_other_config(pool1)
-if other_config.get('new_entry') != 'added':
- FAIL("cpu_pool.get_other_config() returns wrong value")
-
-session.xenapi.cpu_pool.remove_from_other_config(pool1, 'new_entry')
-other_config = session.xenapi.cpu_pool.get_other_config(pool1)
-if other_config.get('new_entry') != None:
- FAIL("cpu_pool.get_other_config() returns wrong value")
-
-session.xenapi.cpu_pool.set_sched_policy(pool1, 'credit')
-if 'credit' != session.xenapi.cpu_pool.get_sched_policy(pool1):
- FAIL("cpu_pool.get_sched_policy() returns wrong value")
-
-session.xenapi.cpu_pool.destroy(pool1)
-if pool1 in session.xenapi.cpu_pool.get_all():
- FAIL("cpu_pool.destroy() has not removed pool")
-
diff --git a/tools/xm-test/tests/xapi/Makefile.am b/tools/xm-test/tests/xapi/Makefile.am
deleted file mode 100644
index 36aac45..0000000
--- a/tools/xm-test/tests/xapi/Makefile.am
+++ /dev/null
@@ -1,23 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_xapi-vm_basic.test \
- 02_xapi-vbd_basic.test \
- 03_xapi-network_pos.test \
- 04_xapi-data_uri_handling.test \
- 20_xapi-cpu_pool_basic.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS) xapi_utils.py
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/xen/Makefile b/xen/Makefile
index 134a8bd..72c1313 100644
--- a/xen/Makefile
+++ b/xen/Makefile
@@ -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 = 4
-export XEN_SUBVERSION = 4
-export XEN_EXTRAVERSION ?= .1$(XEN_VENDORVERSION)
+export XEN_SUBVERSION = 5
+export XEN_EXTRAVERSION ?= .0-rc$(XEN_VENDORVERSION)
export XEN_FULLVERSION = $(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION)
-include xen-version
@@ -12,7 +12,7 @@ export XEN_DOMAIN ?= $(shell ([ -x /bin/dnsdomainname ] && /bin/dnsdomainname) |
export BASEDIR := $(CURDIR)
export XEN_ROOT := $(BASEDIR)/..
-EFI_MOUNTPOINT ?= /boot/efi
+EFI_MOUNTPOINT ?= $(BOOT_DIR)/efi
.PHONY: default
default: build
@@ -36,12 +36,12 @@ _install: D=$(DESTDIR)
_install: T=$(notdir $(TARGET))
_install: Z=$(CONFIG_XEN_INSTALL_SUFFIX)
_install: $(TARGET)$(CONFIG_XEN_INSTALL_SUFFIX)
- [ -d $(D)/boot ] || $(INSTALL_DIR) $(D)/boot
- $(INSTALL_DATA) $(TARGET)$(Z) $(D)/boot/$(T)-$(XEN_FULLVERSION)$(Z)
- ln -f -s $(T)-$(XEN_FULLVERSION)$(Z) $(D)/boot/$(T)-$(XEN_VERSION).$(XEN_SUBVERSION)$(Z)
- ln -f -s $(T)-$(XEN_FULLVERSION)$(Z) $(D)/boot/$(T)-$(XEN_VERSION)$(Z)
- ln -f -s $(T)-$(XEN_FULLVERSION)$(Z) $(D)/boot/$(T)$(Z)
- $(INSTALL_DATA) $(TARGET)-syms $(D)/boot/$(T)-syms-$(XEN_FULLVERSION)
+ [ -d $(D)$(BOOT_DIR) ] || $(INSTALL_DIR) $(D)$(BOOT_DIR)
+ $(INSTALL_DATA) $(TARGET)$(Z) $(D)$(BOOT_DIR)/$(T)-$(XEN_FULLVERSION)$(Z)
+ ln -f -s $(T)-$(XEN_FULLVERSION)$(Z) $(D)$(BOOT_DIR)/$(T)-$(XEN_VERSION).$(XEN_SUBVERSION)$(Z)
+ ln -f -s $(T)-$(XEN_FULLVERSION)$(Z) $(D)$(BOOT_DIR)/$(T)-$(XEN_VERSION)$(Z)
+ ln -f -s $(T)-$(XEN_FULLVERSION)$(Z) $(D)$(BOOT_DIR)/$(T)$(Z)
+ $(INSTALL_DATA) $(TARGET)-syms $(D)$(BOOT_DIR)/$(T)-syms-$(XEN_FULLVERSION)
if [ -r $(TARGET).efi -a -n '$(EFI_DIR)' ]; then \
[ -d $(D)$(EFI_DIR) ] || $(INSTALL_DIR) $(D)$(EFI_DIR); \
$(INSTALL_DATA) $(TARGET).efi $(D)$(EFI_DIR)/$(T)-$(XEN_FULLVERSION).efi; \
@@ -60,11 +60,11 @@ _uninstall: D=$(DESTDIR)
_uninstall: T=$(notdir $(TARGET))
_uninstall: Z=$(CONFIG_XEN_INSTALL_SUFFIX)
_uninstall:
- rm -f $(D)/boot/$(T)-$(XEN_FULLVERSION)$(Z)
- rm -f $(D)/boot/$(T)-$(XEN_VERSION).$(XEN_SUBVERSION)$(Z)
- rm -f $(D)/boot/$(T)-$(XEN_VERSION)$(Z)
- rm -f $(D)/boot/$(T)$(Z)
- rm -f $(D)/boot/$(T)-syms-$(XEN_FULLVERSION)
+ rm -f $(D)$(BOOT_DIR)/$(T)-$(XEN_FULLVERSION)$(Z)
+ rm -f $(D)$(BOOT_DIR)/$(T)-$(XEN_VERSION).$(XEN_SUBVERSION)$(Z)
+ rm -f $(D)$(BOOT_DIR)/$(T)-$(XEN_VERSION)$(Z)
+ rm -f $(D)$(BOOT_DIR)/$(T)$(Z)
+ rm -f $(D)$(BOOT_DIR)/$(T)-syms-$(XEN_FULLVERSION)
rm -f $(D)$(EFI_DIR)/$(T)-$(XEN_FULLVERSION).efi
rm -f $(D)$(EFI_DIR)/$(T)-$(XEN_VERSION).$(XEN_SUBVERSION).efi
rm -f $(D)$(EFI_DIR)/$(T)-$(XEN_VERSION).efi
@@ -84,7 +84,7 @@ _clean: delete-unfresh-files
$(MAKE) -f $(BASEDIR)/Rules.mk -C xsm clean
$(MAKE) -f $(BASEDIR)/Rules.mk -C crypto clean
$(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) clean
- rm -f include/asm *.o $(TARGET) $(TARGET).gz $(TARGET)-syms *~ core
+ rm -f include/asm *.o $(TARGET) $(TARGET).gz $(TARGET).efi $(TARGET)-syms *~ core
rm -f include/asm-*/asm-offsets.h
rm -f .banner
@@ -100,6 +100,9 @@ $(TARGET): delete-unfresh-files
$(MAKE) -C tools
$(MAKE) -f $(BASEDIR)/Rules.mk include/xen/compile.h
[ -e include/asm ] || ln -sf asm-$(TARGET_ARCH) include/asm
+ [ -e arch/$(TARGET_ARCH)/efi ] && for f in boot.c runtime.c compat.c efi.h;\
+ do ln -nsf ../../../common/efi/$$f arch/$(TARGET_ARCH)/efi/; done;\
+ true
$(MAKE) -f $(BASEDIR)/Rules.mk -C include
$(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) asm-offsets.s
$(MAKE) -f $(BASEDIR)/Rules.mk include/asm-$(TARGET_ARCH)/asm-offsets.h
@@ -150,7 +153,7 @@ include/asm-$(TARGET_ARCH)/asm-offsets.h: arch/$(TARGET_ARCH)/asm-offsets.s
echo "#ifndef __ASM_OFFSETS_H__"; \
echo "#define __ASM_OFFSETS_H__"; \
echo ""; \
- sed -ne "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"; \
+ sed -rne "/==>/{s:.*==>(.*)<==.*:\1:; s: [\$$#]: :; p;}"; \
echo ""; \
echo "#endif") <$< >$@
diff --git a/xen/Rules.mk b/xen/Rules.mk
index 3a6cec5..a97405c 100644
--- a/xen/Rules.mk
+++ b/xen/Rules.mk
@@ -47,8 +47,7 @@ CFLAGS += -pipe -g -D__XEN__ -include $(BASEDIR)/include/xen/config.h
CFLAGS += -nostdinc
CFLAGS-$(XSM_ENABLE) += -DXSM_ENABLE
-CFLAGS-$(FLASK_ENABLE) += -DFLASK_ENABLE -DXSM_MAGIC=0xf97cff8c
-CFLAGS-$(FLASK_ENABLE) += -DFLASK_DEVELOP -DFLASK_BOOTPARAM -DFLASK_AVC_STATS
+CFLAGS-$(FLASK_ENABLE) += -DFLASK_ENABLE
CFLAGS-$(verbose) += -DVERBOSE
CFLAGS-$(crash_debug) += -DCRASH_DEBUG
CFLAGS-$(perfc) += -DPERF_COUNTERS
@@ -58,8 +57,12 @@ CFLAGS-$(HAS_ACPI) += -DHAS_ACPI
CFLAGS-$(HAS_GDBSX) += -DHAS_GDBSX
CFLAGS-$(HAS_PASSTHROUGH) += -DHAS_PASSTHROUGH
CFLAGS-$(HAS_DEVICE_TREE) += -DHAS_DEVICE_TREE
+CFLAGS-$(HAS_MEM_ACCESS) += -DHAS_MEM_ACCESS
+CFLAGS-$(HAS_MEM_PAGING) += -DHAS_MEM_PAGING
+CFLAGS-$(HAS_MEM_SHARING) += -DHAS_MEM_SHARING
CFLAGS-$(HAS_PCI) += -DHAS_PCI
CFLAGS-$(HAS_IOPORTS) += -DHAS_IOPORTS
+CFLAGS-$(HAS_PDX) += -DHAS_PDX
CFLAGS-$(frame_pointer) += -fno-omit-frame-pointer -DCONFIG_FRAME_POINTER
ifneq ($(max_phys_cpus),)
@@ -168,11 +171,12 @@ _clean_%/: FORCE
$(CC) $(AFLAGS) -c $< -o $@
SPECIAL_DATA_SECTIONS := rodata $(foreach n,1 2 4 8,rodata.str1.$(n)) \
- $(foreach r,rel rel.ro,data.$(r) data.$(r).local)
+ $(foreach r,rel rel.ro,data.$(r).local)
$(filter %.init.o,$(obj-y) $(obj-bin-y) $(extra-y)): %.init.o: %.o Makefile
- $(OBJDUMP) -h $< | sed -n '/[0-9]/{s,00*,0,g;p}' | while read idx name sz rest; do \
+ $(OBJDUMP) -h $< | sed -n '/[0-9]/{s,00*,0,g;p;}' | while read idx name sz rest; do \
case "$$name" in \
+ .*.local) ;; \
.text|.text.*|.data|.data.*|.bss) \
test $$sz != 0 || continue; \
echo "Error: size of $<:$$name is 0x$$sz" >&2; \
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index d70f6d5..41aba2e 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -1,6 +1,7 @@
subdir-$(arm32) += arm32
subdir-$(arm64) += arm64
subdir-y += platforms
+subdir-$(arm64) += efi
obj-$(EARLY_PRINTK) += early_printk.o
obj-y += cpu.o
@@ -10,7 +11,8 @@ obj-y += vpsci.o
obj-y += domctl.o
obj-y += sysctl.o
obj-y += domain_build.o
-obj-y += gic.o
+obj-y += gic.o gic-v2.o
+obj-$(CONFIG_ARM_64) += gic-v3.o
obj-y += io.o
obj-y += irq.o
obj-y += kernel.o
@@ -21,17 +23,21 @@ obj-y += guestcopy.o
obj-y += physdev.o
obj-y += platform.o
obj-y += setup.o
+obj-y += bootfdt.o
obj-y += time.o
obj-y += smpboot.o
obj-y += smp.o
obj-y += shutdown.o
obj-y += traps.o
-obj-y += vgic.o
+obj-y += vgic.o vgic-v2.o
+obj-$(CONFIG_ARM_64) += vgic-v3.o
obj-y += vtimer.o
obj-y += vuart.o
obj-y += hvm.o
obj-y += device.o
obj-y += decode.o
+obj-y += processor.o
+obj-y += smc.o
#obj-bin-y += ....o
@@ -44,6 +50,9 @@ ALL_OBJS := $(TARGET_SUBARCH)/head.o $(ALL_OBJS)
$(TARGET): $(TARGET)-syms $(TARGET).axf
$(OBJCOPY) -O binary -S $< $@
+ifeq (arm64,$(XEN_TARGET_ARCH))
+ ln -sf $(notdir $@) ../../$(notdir $@).efi
+endif
$(TARGET).axf: $(TARGET)-syms
# XXX: VE model loads by VMA so instead of
@@ -95,3 +104,4 @@ clean::
rm -f asm-offsets.s xen.lds
rm -f $(BASEDIR)/.xen-syms.[0-9]*
rm -f $(TARGET).axf
+ rm -f $(TARGET).efi
diff --git a/xen/arch/arm/README.LinuxPrimitives b/xen/arch/arm/README.LinuxPrimitives
new file mode 100644
index 0000000..7f33fc7
--- /dev/null
+++ b/xen/arch/arm/README.LinuxPrimitives
@@ -0,0 +1,163 @@
+Xen on ARM uses various low level assembly primitives from the Linux
+kernel. This file tracks what files have been imported and when they
+were last updated.
+
+=====================================================================
+arm64:
+=====================================================================
+
+bitops: last sync @ v3.16-rc6 (last commit: 8715466b6027)
+
+linux/arch/arm64/lib/bitops.S xen/arch/arm/arm64/lib/bitops.S
+linux/arch/arm64/include/asm/bitops.h xen/include/asm-arm/arm64/bitops.h
+
+---------------------------------------------------------------------
+
+cmpxchg: last sync @ v3.16-rc6 (last commit: e1dfda9ced9b)
+
+linux/arch/arm64/include/asm/cmpxchg.h xen/include/asm-arm/arm64/cmpxchg.h
+
+---------------------------------------------------------------------
+
+atomics: last sync @ v3.16-rc6 (last commit: 8715466b6027)
+
+linux/arch/arm64/include/asm/atomic.h xen/include/asm-arm/arm64/atomic.h
+
+---------------------------------------------------------------------
+
+spinlocks: last sync @ v3.16-rc6 (last commit: 95c4189689f9)
+
+linux/arch/arm64/include/asm/spinlock.h xen/include/asm-arm/arm64/spinlock.h
+
+Skipped:
+ 5686b06 arm64: lockref: add support for lockless lockrefs using cmpxchg
+ 52ea2a5 arm64: locks: introduce ticket-based spinlock implementation
+
+---------------------------------------------------------------------
+
+mem*: last sync @ v3.16-rc6 (last commit: d875c9b37240)
+
+linux/arch/arm64/lib/memchr.S xen/arch/arm/arm64/lib/memchr.S
+linux/arch/arm64/lib/memcmp.S xen/arch/arm/arm64/lib/memcmp.S
+linux/arch/arm64/lib/memcpy.S xen/arch/arm/arm64/lib/memcpy.S
+linux/arch/arm64/lib/memmove.S xen/arch/arm/arm64/lib/memmove.S
+linux/arch/arm64/lib/memset.S xen/arch/arm/arm64/lib/memset.S
+
+for i in memchr.S memcmp.S memcpy.S memmove.S memset.S ; do
+ diff -u linux/arch/arm64/lib/$i xen/arch/arm/arm64/lib/$i
+done
+
+---------------------------------------------------------------------
+
+str*: last sync @ v3.16-rc6 (last commit: 0a42cb0a6fa6)
+
+linux/arch/arm64/lib/strchr.S xen/arch/arm/arm64/lib/strchr.S
+linux/arch/arm64/lib/strcmp.S xen/arch/arm/arm64/lib/strcmp.S
+linux/arch/arm64/lib/strlen.S xen/arch/arm/arm64/lib/strlen.S
+linux/arch/arm64/lib/strncmp.S xen/arch/arm/arm64/lib/strncmp.S
+linux/arch/arm64/lib/strnlen.S xen/arch/arm/arm64/lib/strnlen.S
+linux/arch/arm64/lib/strrchr.S xen/arch/arm/arm64/lib/strrchr.S
+
+for i in strchr.S strcmp.S strlen.S strncmp.S strnlen.S strrchr.S ; do
+ diff -u linux/arch/arm64/lib/$i xen/arch/arm/arm64/lib/$i
+done
+
+---------------------------------------------------------------------
+
+{clear,copy}_page: last sync @ v3.16-rc6 (last commit: f27bb139c387)
+
+linux/arch/arm64/lib/clear_page.S xen/arch/arm/arm64/lib/clear_page.S
+linux/arch/arm64/lib/copy_page.S unused in Xen
+
+=====================================================================
+arm32
+=====================================================================
+
+bitops: last sync @ v3.16-rc6 (last commit: c32ffce0f66e)
+
+linux/arch/arm/lib/bitops.h xen/arch/arm/arm32/lib/bitops.h
+linux/arch/arm/lib/changebit.S xen/arch/arm/arm32/lib/changebit.S
+linux/arch/arm/lib/clearbit.S xen/arch/arm/arm32/lib/clearbit.S
+linux/arch/arm/lib/findbit.S xen/arch/arm/arm32/lib/findbit.S
+linux/arch/arm/lib/setbit.S xen/arch/arm/arm32/lib/setbit.S
+linux/arch/arm/lib/testchangebit.S xen/arch/arm/arm32/lib/testchangebit.S
+linux/arch/arm/lib/testclearbit.S xen/arch/arm/arm32/lib/testclearbit.S
+linux/arch/arm/lib/testsetbit.S xen/arch/arm/arm32/lib/testsetbit.S
+
+for i in bitops.h changebit.S clearbit.S findbit.S setbit.S testchangebit.S \
+ testclearbit.S testsetbit.S; do
+ diff -u ../linux/arch/arm/lib/$i xen/arch/arm/arm32/lib/$i;
+done
+
+---------------------------------------------------------------------
+
+cmpxchg: last sync @ v3.16-rc6 (last commit: c32ffce0f66e)
+
+linux/arch/arm/include/asm/cmpxchg.h xen/include/asm-arm/arm32/cmpxchg.h
+
+---------------------------------------------------------------------
+
+atomics: last sync @ v3.16-rc6 (last commit: 030d0178bdbd)
+
+linux/arch/arm/include/asm/atomic.h xen/include/asm-arm/arm32/atomic.h
+
+---------------------------------------------------------------------
+
+spinlocks: last sync: 15e7e5c1ebf5
+
+linux/arch/arm/include/asm/spinlock.h xen/include/asm-arm/arm32/spinlock.h
+
+*** Linux has switched to ticket locks but we still use bitlocks.
+
+resync to v3.14-rc7:
+
+ 7c8746a ARM: 7955/1: spinlock: ensure we have a compiler barrier before sev
+ 0cbad9c ARM: 7854/1: lockref: add support for lockless lockrefs using cmpxchg64
+ 9bb17be ARM: locks: prefetch the destination word for write prior to strex
+ 27a8479 ARM: smp_on_up: move inline asm ALT_SMP patching macro out of spinlock.
+ 00efaa0 ARM: 7812/1: rwlocks: retry trylock operation if strex fails on free lo
+ afa31d8 ARM: 7811/1: locks: use early clobber in arch_spin_trylock
+ 73a6fdc ARM: spinlock: use inner-shareable dsb variant prior to sev instruction
+
+---------------------------------------------------------------------
+
+mem*: last sync @ v3.16-rc6 (last commit: d98b90ea22b0)
+
+linux/arch/arm/lib/copy_template.S xen/arch/arm/arm32/lib/copy_template.S
+linux/arch/arm/lib/memchr.S xen/arch/arm/arm32/lib/memchr.S
+linux/arch/arm/lib/memcpy.S xen/arch/arm/arm32/lib/memcpy.S
+linux/arch/arm/lib/memmove.S xen/arch/arm/arm32/lib/memmove.S
+linux/arch/arm/lib/memset.S xen/arch/arm/arm32/lib/memset.S
+linux/arch/arm/lib/memzero.S xen/arch/arm/arm32/lib/memzero.S
+
+for i in copy_template.S memchr.S memcpy.S memmove.S memset.S \
+ memzero.S ; do
+ diff -u linux/arch/arm/lib/$i xen/arch/arm/arm32/lib/$i
+done
+
+---------------------------------------------------------------------
+
+str*: last sync @ v3.16-rc6 (last commit: d98b90ea22b0)
+
+linux/arch/arm/lib/strchr.S xen/arch/arm/arm32/lib/strchr.S
+linux/arch/arm/lib/strrchr.S xen/arch/arm/arm32/lib/strrchr.S
+
+---------------------------------------------------------------------
+
+{clear,copy}_page: last sync: Never
+
+linux/arch/arm/lib/copy_page.S unused in Xen
+
+clear_page == memset
+
+---------------------------------------------------------------------
+
+libgcc: last sync @ v3.16-rc6 (last commit: 01885bc)
+
+linux/arch/arm/lib/lib1funcs.S xen/arch/arm/arm32/lib/lib1funcs.S
+linux/arch/arm/lib/lshrdi3.S xen/arch/arm/arm32/lib/lshrdi3.S
+linux/arch/arm/lib/div64.S xen/arch/arm/arm32/lib/div64.S
+
+for i in lib1funcs.S lshrdi3.S div64.S ; do
+ diff -u linux/arch/arm/lib/$i xen/arch/arm/arm32/lib/$i
+done
diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk
index 2db39ad..4ee51a9 100644
--- a/xen/arch/arm/Rules.mk
+++ b/xen/arch/arm/Rules.mk
@@ -9,6 +9,8 @@
HAS_DEVICE_TREE := y
HAS_VIDEO := y
HAS_ARM_HDLCD := y
+HAS_PASSTHROUGH := y
+HAS_PDX := y
CFLAGS += -I$(BASEDIR)/include
@@ -43,7 +45,6 @@ ifeq ($(debug),y)
# Early printk for versatile express
ifeq ($(CONFIG_EARLY_PRINTK), vexpress)
EARLY_PRINTK_INC := pl011
-EARLY_PRINTK_BAUD := 38400
EARLY_UART_BASE_ADDRESS := 0x1c090000
endif
ifeq ($(CONFIG_EARLY_PRINTK), fastmodel)
@@ -54,13 +55,10 @@ EARLY_UART_BASE_ADDRESS := 0x1c090000
endif
ifeq ($(CONFIG_EARLY_PRINTK), exynos5250)
EARLY_PRINTK_INC := exynos4210
-EARLY_PRINTK_INIT_UART := y
-EARLY_PRINTK_BAUD := 115200
EARLY_UART_BASE_ADDRESS := 0x12c20000
endif
ifeq ($(CONFIG_EARLY_PRINTK), midway)
EARLY_PRINTK_INC := pl011
-EARLY_PRINTK_BAUD := 115200
EARLY_UART_BASE_ADDRESS := 0xfff36000
endif
ifeq ($(CONFIG_EARLY_PRINTK), omap5432)
@@ -68,6 +66,11 @@ EARLY_PRINTK_INC := 8250
EARLY_UART_BASE_ADDRESS := 0x48020000
EARLY_UART_REG_SHIFT := 2
endif
+ifeq ($(CONFIG_EARLY_PRINTK), dra7)
+EARLY_PRINTK_INC := 8250
+EARLY_UART_BASE_ADDRESS := 0x4806A000
+EARLY_UART_REG_SHIFT := 2
+endif
ifeq ($(CONFIG_EARLY_PRINTK), sun6i)
EARLY_PRINTK_INC := 8250
EARLY_UART_BASE_ADDRESS := 0x01c28000
@@ -80,21 +83,38 @@ EARLY_UART_REG_SHIFT := 2
endif
ifeq ($(CONFIG_EARLY_PRINTK), brcm)
EARLY_PRINTK_INC := 8250
-EARLY_UART_BASE_ADDRESS := 0xF0406B00
+EARLY_UART_BASE_ADDRESS := 0xF040AB00
EARLY_UART_REG_SHIFT := 2
endif
ifeq ($(CONFIG_EARLY_PRINTK), xgene-storm)
EARLY_PRINTK_INC := 8250
-EARLY_PRINTK_BAUD := 115200
EARLY_UART_BASE_ADDRESS := 0x1c020000
EARLY_UART_REG_SHIFT := 2
endif
+ifeq ($(CONFIG_EARLY_PRINTK), xgene-mcdivitt)
+EARLY_PRINTK_INC := 8250
+EARLY_UART_BASE_ADDRESS := 0x1c021000
+EARLY_UART_REG_SHIFT := 2
+endif
+ifeq ($(CONFIG_EARLY_PRINTK), juno)
+EARLY_PRINTK_INC := pl011
+EARLY_UART_BASE_ADDRESS := 0x7ff80000
+endif
+ifeq ($(CONFIG_EARLY_PRINTK), hip04-d01)
+EARLY_PRINTK_INC := 8250
+EARLY_UART_BASE_ADDRESS := 0xE4007000
+EARLY_UART_REG_SHIFT := 2
+endif
+ifeq ($(CONFIG_EARLY_PRINTK), seattle)
+EARLY_PRINTK_INC := pl011
+EARLY_UART_BASE_ADDRESS := 0xe1010000
+endif
ifneq ($(EARLY_PRINTK_INC),)
EARLY_PRINTK := y
endif
-CFLAGS-$(EARLY_PRINTK) += -DEARLY_PRINTK
+CFLAGS-$(EARLY_PRINTK) += -DCONFIG_EARLY_PRINTK
CFLAGS-$(EARLY_PRINTK_INIT_UART) += -DEARLY_PRINTK_INIT_UART
CFLAGS-$(EARLY_PRINTK) += -DEARLY_PRINTK_INC=\"debug-$(EARLY_PRINTK_INC).inc\"
CFLAGS-$(EARLY_PRINTK) += -DEARLY_PRINTK_BAUD=$(EARLY_PRINTK_BAUD)
diff --git a/xen/arch/arm/arm32/Makefile b/xen/arch/arm/arm32/Makefile
index 65ecff4..df0e7de 100644
--- a/xen/arch/arm/arm32/Makefile
+++ b/xen/arch/arm/arm32/Makefile
@@ -1,7 +1,7 @@
subdir-y += lib
obj-y += entry.o
-obj-y += proc-v7.o
+obj-y += proc-v7.o proc-caxx.o
obj-y += traps.o
obj-y += domain.o
diff --git a/xen/arch/arm/arm32/asm-offsets.c b/xen/arch/arm/arm32/asm-offsets.c
index ac628c0..cd1dff7 100644
--- a/xen/arch/arm/arm32/asm-offsets.c
+++ b/xen/arch/arm/arm32/asm-offsets.c
@@ -13,11 +13,12 @@
#include <asm/current.h>
#include <asm/procinfo.h>
-#define DEFINE(_sym, _val) \
- __asm__ __volatile__ ( "\n->" #_sym " %0 " #_val : : "i" (_val) )
-#define BLANK() \
- __asm__ __volatile__ ( "\n->" : : )
-#define OFFSET(_sym, _str, _mem) \
+#define DEFINE(_sym, _val) \
+ asm volatile ("\n.ascii\"==>#define " #_sym " %0 /* " #_val " */<==\"" \
+ : : "i" (_val) )
+#define BLANK() \
+ asm volatile ( "\n.ascii\"==><==\"" : : )
+#define OFFSET(_sym, _str, _mem) \
DEFINE(_sym, offsetof(_str, _mem));
void __dummy__(void)
diff --git a/xen/arch/arm/arm32/debug-exynos4210.inc b/xen/arch/arm/arm32/debug-exynos4210.inc
index 39f2db3..752942d 100644
--- a/xen/arch/arm/arm32/debug-exynos4210.inc
+++ b/xen/arch/arm/arm32/debug-exynos4210.inc
@@ -18,38 +18,6 @@
#include <asm/exynos4210-uart.h>
-/* Exynos 5 UART initialization
- * rb: register which contains the UART base address
- * rc: scratch register 1
- * rd: scratch register 2 */
-.macro early_uart_init rb rc rd
- /* init clock */
- ldr \rc, =0x10020000
- /* select MPLL (800MHz) source clock */
- ldr \rd, [\rc, #0x250]
- and \rd, \rd, #(~(0xf<<8))
- orr \rd, \rd, #(0x6<<8)
- str \rd, [\rc, #0x250]
- /* ratio 800/(7+1) */
- ldr \rd, [\rc, #0x558]
- and \rd, \rd, #(~(0xf<<8))
- orr \rd, \rd, #(0x7<<8)
- str \rd, [\rc, #0x558]
-
- mov \rc, #(100000000 / EARLY_PRINTK_BAUD % 16)
- str \rc, [\rb, #UFRACVAL] /* -> UFRACVAL (Baud divisor fraction) */
- mov \rc, #(100000000 / EARLY_PRINTK_BAUD / 16 - 1)
- str \rc, [\rb, #UBRDIV] /* -> UBRDIV (Baud divisor integer) */
- mov \rc, #3 /* 8n1 */
- str \rc, [\rb, #ULCON] /* -> (Line control) */
- ldr \rc, =UCON_TX_IRQ /* TX IRQMODE */
- str \rc, [\rb, #UCON] /* -> (Control Register) */
- mov \rc, #0x0
- str \rc, [\rb, #UFCON] /* disable FIFO */
- mov \rc, #0x0
- str \rc, [\rb, #UMCON] /* no auto flow control */
-.endm
-
/* Exynos 5 UART wait UART to be ready to transmit
* rb: register which contains the UART base address
* rc: scratch register */
diff --git a/xen/arch/arm/arm32/head.S b/xen/arch/arm/arm32/head.S
index 5bc23cc..5c0263e 100644
--- a/xen/arch/arm/arm32/head.S
+++ b/xen/arch/arm/arm32/head.S
@@ -19,22 +19,21 @@
#include <asm/config.h>
#include <asm/page.h>
-#include <asm/processor-ca15.h>
-#include <asm/processor-ca7.h>
#include <asm/asm_defns.h>
#include <asm/early_printk.h>
#define ZIMAGE_MAGIC_NUMBER 0x016f2818
-#define PT_PT 0xe7f /* nG=1 AF=1 SH=10 AP=01 NS=1 ATTR=111 T=1 P=1 */
-#define PT_MEM 0xe7d /* nG=1 AF=1 SH=10 AP=01 NS=1 ATTR=111 T=0 P=1 */
+#define PT_PT 0xf7f /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=1 P=1 */
+#define PT_MEM 0xf7d /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=0 P=1 */
+#define PT_MEM_L3 0xf7f /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=1 P=1 */
#define PT_DEV 0xe71 /* nG=1 AF=1 SH=10 AP=01 NS=1 ATTR=100 T=0 P=1 */
#define PT_DEV_L3 0xe73 /* nG=1 AF=1 SH=10 AP=01 NS=1 ATTR=100 T=1 P=1 */
#define PT_UPPER(x) (PT_##x & 0xf00)
#define PT_LOWER(x) (PT_##x & 0x0ff)
-#if (defined (EARLY_PRINTK)) && (defined (EARLY_PRINTK_INC))
+#if (defined (CONFIG_EARLY_PRINTK)) && (defined (EARLY_PRINTK_INC))
#include EARLY_PRINTK_INC
#endif
@@ -46,7 +45,7 @@
* r3 -
* r4 -
* r5 -
- * r6 -
+ * r6 - identity map in place
* r7 - CPUID
* r8 - DTB address (boot CPU only)
* r9 - paddr(start)
@@ -59,7 +58,7 @@
*/
/* Macro to print a string to the UART, if there is one.
* Clobbers r0-r3. */
-#ifdef EARLY_PRINTK
+#ifdef CONFIG_EARLY_PRINTK
#define PRINT(_s) \
adr r0, 98f ; \
bl puts ; \
@@ -67,18 +66,17 @@
98: .asciz _s ; \
.align 2 ; \
99:
-#else /* EARLY_PRINTK */
+#else /* CONFIG_EARLY_PRINTK */
#define PRINT(s)
-#endif /* !EARLY_PRINTK */
+#endif /* !CONFIG_EARLY_PRINTK */
.arm
/* This must be the very first address in the loaded image.
* It should be linked at XEN_VIRT_START, and loaded at any
- * 2MB-aligned address. All of text+data+bss must fit in 2MB,
+ * 4K-aligned address. All of text+data+bss must fit in 2MB,
* or the initial pagetable code below will need adjustment. */
- .global start
-start:
+GLOBAL(start)
/* zImage magic header, see:
* http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html#d0e309
*/
@@ -149,7 +147,7 @@ common_start:
b 2b
1:
-#ifdef EARLY_PRINTK
+#ifdef CONFIG_EARLY_PRINTK
ldr r11, =EARLY_UART_BASE_ADDRESS /* r11 := UART base address */
teq r12, #0 /* Boot CPU sets up the UART too */
bleq init_uart
@@ -200,26 +198,16 @@ skip_bss:
PRINT("- Setting up control registers -\r\n")
/* Get processor specific proc info into r1 */
- mrc CP32(r0, MIDR) /* r0 := our cpu id */
- ldr r1, = __proc_info_start
- add r1, r1, r10 /* r1 := paddr of table (start) */
- ldr r2, = __proc_info_end
- add r2, r2, r10 /* r2 := paddr of table (end) */
-1: ldr r3, [r1, #PROCINFO_cpu_mask]
- and r4, r0, r3 /* r4 := our cpu id with mask */
- ldr r3, [r1, #PROCINFO_cpu_val] /* r3 := cpu val in current proc info */
- teq r4, r3
- beq 2f /* Match => exit, or try next proc info */
- add r1, r1, #PROCINFO_sizeof
- cmp r1, r2
- blo 1b
+ bl __lookup_processor_type
+ teq r1, #0
+ bne 1f
mov r4, r0
PRINT("- Missing processor info: ")
mov r0, r4
bl putn
PRINT(" -\r\n")
b fail
-2:
+1:
/* Jump to cpu_init */
ldr r1, [r1, #PROCINFO_cpu_init] /* r1 := vaddr(init func) */
@@ -236,10 +224,10 @@ cpu_init_done:
mcr CP32(r1, HMAIR1)
/* Set up the HTCR:
- * PT walks use Outer-Shareable accesses,
+ * PT walks use Inner-Shareable accesses,
* PT walks are write-back, write-allocate in both cache levels,
* Full 32-bit address space goes through this table. */
- ldr r0, =0x80002500
+ ldr r0, =(TCR_RES1|TCR_SH0_IS|TCR_ORGN0_WBWA|TCR_IRGN0_WBWA|TCR_T0SZ(0))
mcr CP32(r0, HTCR)
/* Set up the HSCTLR:
@@ -261,6 +249,14 @@ cpu_init_done:
* mapping. So each CPU must rebuild the page tables here with
* the 1:1 in place. */
+ /* If Xen is loaded at exactly XEN_VIRT_START then we don't
+ * need an additional 1:1 mapping, the virtual mapping will
+ * suffice.
+ */
+ cmp r9, #XEN_VIRT_START
+ moveq r6, #1 /* r6 := identity map now in place */
+ movne r6, #0 /* r6 := identity map not yet in place */
+
/* Write Xen's PT's paddr into the HTTBR */
ldr r4, =boot_pgtable
add r4, r4, r10 /* r4 := paddr (boot_pagetable) */
@@ -270,52 +266,87 @@ cpu_init_done:
/* Setup boot_pgtable: */
ldr r1, =boot_second
add r1, r1, r10 /* r1 := paddr (boot_second) */
- mov r3, #0x0
/* ... map boot_second in boot_pgtable[0] */
orr r2, r1, #PT_UPPER(PT) /* r2:r3 := table map of boot_second */
orr r2, r2, #PT_LOWER(PT) /* (+ rights for linear PT) */
+ mov r3, #0x0
strd r2, r3, [r4, #0] /* Map it in slot 0 */
/* ... map of paddr(start) in boot_pgtable */
- lsrs r1, r9, #30 /* Offset of base paddr in boot_pgtable */
+ lsrs r1, r9, #FIRST_SHIFT /* Offset of base paddr in boot_pgtable */
beq 1f /* If it is in slot 0 then map in boot_second
* later on */
- lsl r2, r1, #30 /* Base address for 1GB mapping */
+ lsl r2, r1, #FIRST_SHIFT /* Base address for 1GB mapping */
orr r2, r2, #PT_UPPER(MEM) /* r2:r3 := section map */
orr r2, r2, #PT_LOWER(MEM)
lsl r1, r1, #3 /* r1 := Slot offset */
strd r2, r3, [r4, r1] /* Mapping of paddr(start) */
+ mov r6, #1 /* r6 := identity map now in place */
1: /* Setup boot_second: */
ldr r4, =boot_second
- add r4, r4, r10 /* r1 := paddr (boot_second) */
+ add r4, r4, r10 /* r4 := paddr (boot_second) */
+
+ ldr r1, =boot_third
+ add r1, r1, r10 /* r1 := paddr (boot_third) */
- lsr r2, r9, #20 /* Base address for 2MB mapping */
- lsl r2, r2, #20
+ /* ... map boot_third in boot_second[1] */
+ orr r2, r1, #PT_UPPER(PT) /* r2:r3 := table map of boot_third */
+ orr r2, r2, #PT_LOWER(PT) /* (+ rights for linear PT) */
+ mov r3, #0x0
+ strd r2, r3, [r4, #8] /* Map it in slot 1 */
+
+ /* ... map of paddr(start) in boot_second */
+ cmp r6, #1 /* r6 is set if already created */
+ beq 1f
+ lsr r2, r9, #SECOND_SHIFT /* Offset of base paddr in boot_second */
+ ldr r3, =LPAE_ENTRY_MASK
+ and r1, r2, r3
+ cmp r1, #1
+ beq virtphys_clash /* It's in slot 1, which we cannot handle */
+
+ lsl r2, r2, #SECOND_SHIFT /* Base address for 2MB mapping */
orr r2, r2, #PT_UPPER(MEM) /* r2:r3 := section map */
orr r2, r2, #PT_LOWER(MEM)
+ mov r3, #0x0
+ lsl r1, r1, #3 /* r1 := Slot offset */
+ strd r2, r3, [r4, r1] /* Mapping of paddr(start) */
+ mov r6, #1 /* r6 := identity map now in place */
- /* ... map of vaddr(start) in boot_second */
- ldr r1, =start
- lsr r1, #18 /* Slot for vaddr(start) */
- strd r2, r3, [r4, r1] /* Map vaddr(start) */
+ /* Setup boot_third: */
+1: ldr r4, =boot_third
+ add r4, r4, r10 /* r4 := paddr (boot_third) */
- /* ... map of paddr(start) in boot_second */
- lsrs r1, r9, #30 /* Base paddr */
- bne 1f /* If paddr(start) is not in slot 0
- * then the mapping was done in
- * boot_pgtable above */
+ lsr r2, r9, #THIRD_SHIFT /* Base address for 4K mapping */
+ lsl r2, r2, #THIRD_SHIFT
+ orr r2, r2, #PT_UPPER(MEM_L3) /* r2:r3 := map */
+ orr r2, r2, #PT_LOWER(MEM_L3)
+ mov r3, #0x0
- mov r1, r9, lsr #18 /* Slot for paddr(start) */
- strd r2, r3, [r4, r1] /* Map Xen there */
-1:
+ /* ... map of vaddr(start) in boot_third */
+ mov r1, #0
+1: strd r2, r3, [r4, r1] /* Map vaddr(start) */
+ add r2, r2, #PAGE_SIZE /* Next page */
+ add r1, r1, #8 /* Next slot */
+ cmp r1, #(LPAE_ENTRIES<<3) /* 512*8-byte entries per page */
+ blo 1b
/* Defer fixmap and dtb mapping until after paging enabled, to
* avoid them clashing with the 1:1 mapping. */
/* boot pagetable setup complete */
+ cmp r6, #1 /* Did we manage to create an identity mapping ? */
+ beq 1f
+ PRINT("Unable to build boot page tables - Failed to identity map Xen.\r\n")
+ b fail
+virtphys_clash:
+ /* Identity map clashes with boot_third, which we cannot handle yet */
+ PRINT("- Unable to build boot page tables - virt and phys addresses clash. -\r\n")
+ b fail
+
+1:
PRINT("- Turning on paging -\r\n")
ldr r1, =paging /* Explicit vaddr, not RIP-relative */
@@ -330,30 +361,30 @@ paging:
/* Now we can install the fixmap and dtb mappings, since we
* don't need the 1:1 map any more */
dsb
-#if defined(EARLY_PRINTK) /* Fixmap is only used by early printk */
+#if defined(CONFIG_EARLY_PRINTK) /* Fixmap is only used by early printk */
/* Non-boot CPUs don't need to rebuild the fixmap itself, just
- * the mapping from boot_second to xen_fixmap */
+ * the mapping from boot_second to xen_fixmap */
teq r12, #0
bne 1f
/* Add UART to the fixmap table */
ldr r1, =xen_fixmap /* r1 := vaddr (xen_fixmap) */
mov r3, #0
- lsr r2, r11, #12
- lsl r2, r2, #12 /* 4K aligned paddr of UART */
+ lsr r2, r11, #THIRD_SHIFT
+ lsl r2, r2, #THIRD_SHIFT /* 4K aligned paddr of UART */
orr r2, r2, #PT_UPPER(DEV_L3)
orr r2, r2, #PT_LOWER(DEV_L3) /* r2:r3 := 4K dev map including UART */
strd r2, r3, [r1, #(FIXMAP_CONSOLE*8)] /* Map it in the first fixmap's slot */
1:
/* Map fixmap into boot_second */
- ldr r1, =boot_second /* r1 := vaddr (xen_fixmap) */
+ ldr r1, =boot_second /* r1 := vaddr (boot_second) */
ldr r2, =xen_fixmap
add r2, r2, r10 /* r2 := paddr (xen_fixmap) */
orr r2, r2, #PT_UPPER(PT)
orr r2, r2, #PT_LOWER(PT) /* r2:r3 := table map of xen_fixmap */
ldr r4, =FIXMAP_ADDR(0)
- mov r4, r4, lsr #18 /* r4 := Slot for FIXMAP(0) */
+ mov r4, r4, lsr #(SECOND_SHIFT - 3) /* r4 := Slot for FIXMAP(0) */
strd r2, r3, [r1, r4] /* Map it in the fixmap's slot */
/* Use a virtual address to access the UART. */
@@ -365,12 +396,12 @@ paging:
ldr r1, =boot_second
mov r3, #0x0
- lsr r2, r8, #21
- lsl r2, r2, #21 /* r2: 2MB-aligned paddr of DTB */
+ lsr r2, r8, #SECOND_SHIFT
+ lsl r2, r2, #SECOND_SHIFT /* r2: 2MB-aligned paddr of DTB */
orr r2, r2, #PT_UPPER(MEM)
orr r2, r2, #PT_LOWER(MEM) /* r2:r3 := 2MB RAM incl. DTB */
ldr r4, =BOOT_FDT_VIRT_START
- mov r4, r4, lsr #18 /* Slot for BOOT_FDT_VIRT_START */
+ mov r4, r4, lsr #(SECOND_SHIFT - 3) /* Slot for BOOT_FDT_VIRT_START */
strd r2, r3, [r1, r4] /* Map it in the early fdt slot */
1:
@@ -420,12 +451,13 @@ launch:
beq start_xen /* and disappear into the land of C */
b start_secondary /* (to the appropriate entry point) */
-/* Fail-stop
- * r0: string explaining why */
+/* Fail-stop */
fail: PRINT("- Boot failed -\r\n")
1: wfe
b 1b
+GLOBAL(_end_boot)
+
/* Copy Xen to new location and switch TTBR
* r1:r0 ttbr
* r2 source address
@@ -503,7 +535,7 @@ ENTRY(relocate_xen)
mov pc, lr
-#ifdef EARLY_PRINTK
+#ifdef CONFIG_EARLY_PRINTK
/* Bring up the UART.
* r11: Early UART base address
* Clobbers r0-r2 */
@@ -548,15 +580,53 @@ putn:
hex: .ascii "0123456789abcdef"
.align 2
-#else /* EARLY_PRINTK */
+#else /* CONFIG_EARLY_PRINTK */
+ENTRY(early_puts)
init_uart:
-.global early_puts
-early_puts:
puts:
putn: mov pc, lr
-#endif /* !EARLY_PRINTK */
+#endif /* !CONFIG_EARLY_PRINTK */
+
+/* This provides a C-API version of __lookup_processor_type */
+ENTRY(lookup_processor_type)
+ stmfd sp!, {r4, r10, lr}
+ mov r10, #0 /* r10 := offset between virt&phys */
+ bl __lookup_processor_type
+ mov r0, r1
+ ldmfd sp!, {r4, r10, pc}
+
+/* Read processor ID register (CP#15, CR0), and Look up in the linker-built
+ * supported processor list. Note that we can't use the absolute addresses for
+ * the __proc_info lists since we aren't running with the MMU on (and therefore,
+ * we are not in correct address space). We have to calculate the offset.
+ *
+ * r10: offset between virt&phys
+ *
+ * Returns:
+ * r0: CPUID
+ * r1: proc_info pointer
+ * Clobbers r2-r4
+ */
+__lookup_processor_type:
+ mrc CP32(r0, MIDR) /* r0 := our cpu id */
+ ldr r1, = __proc_info_start
+ add r1, r1, r10 /* r1 := paddr of table (start) */
+ ldr r2, = __proc_info_end
+ add r2, r2, r10 /* r2 := paddr of table (end) */
+1: ldr r3, [r1, #PROCINFO_cpu_mask]
+ and r4, r0, r3 /* r4 := our cpu id with mask */
+ ldr r3, [r1, #PROCINFO_cpu_val] /* r3 := cpu val in current proc info */
+ teq r4, r3
+ beq 2f /* Match => exit, or try next proc info */
+ add r1, r1, #PROCINFO_sizeof
+ cmp r1, r2
+ blo 1b
+ /* We failed to find the proc_info, return NULL */
+ mov r1, #0
+2:
+ mov pc, lr
/*
* Local variables:
diff --git a/xen/arch/arm/arm32/lib/Makefile b/xen/arch/arm/arm32/lib/Makefile
index 4cf41f4..e9fbc59 100644
--- a/xen/arch/arm/arm32/lib/Makefile
+++ b/xen/arch/arm/arm32/lib/Makefile
@@ -1,5 +1,6 @@
-obj-y += memcpy.o memmove.o memset.o memzero.o
+obj-y += memcpy.o memmove.o memset.o memchr.o memzero.o
obj-y += findbit.o setbit.o
obj-y += setbit.o clearbit.o changebit.o
obj-y += testsetbit.o testclearbit.o testchangebit.o
+obj-y += strchr.o strrchr.o
obj-y += lib1funcs.o lshrdi3.o div64.o
diff --git a/xen/arch/arm/arm32/lib/assembler.h b/xen/arch/arm/arm32/lib/assembler.h
index f8d4b3a..6de2638 100644
--- a/xen/arch/arm/arm32/lib/assembler.h
+++ b/xen/arch/arm/arm32/lib/assembler.h
@@ -36,8 +36,8 @@
* Endian independent macros for shifting bytes within registers.
*/
#ifndef __ARMEB__
-#define pull lsr
-#define push lsl
+#define lspull lsr
+#define lspush lsl
#define get_byte_0 lsl #0
#define get_byte_1 lsr #8
#define get_byte_2 lsr #16
@@ -47,8 +47,8 @@
#define put_byte_2 lsl #16
#define put_byte_3 lsl #24
#else
-#define pull lsl
-#define push lsr
+#define lspull lsl
+#define lspush lsr
#define get_byte_0 lsr #24
#define get_byte_1 lsr #16
#define get_byte_2 lsr #8
diff --git a/xen/arch/arm/arm32/lib/bitops.h b/xen/arch/arm/arm32/lib/bitops.h
index 689f2e8..a167c2d 100644
--- a/xen/arch/arm/arm32/lib/bitops.h
+++ b/xen/arch/arm/arm32/lib/bitops.h
@@ -1,13 +1,20 @@
#include <xen/config.h>
#if __LINUX_ARM_ARCH__ >= 6
- .macro bitop, instr
+ .macro bitop, name, instr
+ENTRY( \name )
+UNWIND( .fnstart )
ands ip, r1, #3
strneb r1, [ip] @ assert word-aligned
mov r2, #1
and r3, r0, #31 @ Get bit offset
mov r0, r0, lsr #5
add r1, r1, r0, lsl #2 @ Get word offset
+#if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
+ .arch_extension mp
+ ALT_SMP(W(pldw) [r1])
+ ALT_UP(W(nop))
+#endif
mov r3, r2, lsl r3
1: ldrex r2, [r1]
\instr r2, r2, r3
@@ -15,9 +22,13 @@
cmp r0, #0
bne 1b
bx lr
+UNWIND( .fnend )
+ENDPROC(\name )
.endm
- .macro testop, instr, store
+ .macro testop, name, instr, store
+ENTRY( \name )
+UNWIND( .fnstart )
ands ip, r1, #3
strneb r1, [ip] @ assert word-aligned
mov r2, #1
@@ -26,6 +37,11 @@
add r1, r1, r0, lsl #2 @ Get word offset
mov r3, r2, lsl r3 @ create mask
smp_dmb
+#if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
+ .arch_extension mp
+ ALT_SMP(W(pldw) [r1])
+ ALT_UP(W(nop))
+#endif
1: ldrex r2, [r1]
ands r0, r2, r3 @ save old value of bit
\instr r2, r2, r3 @ toggle bit
@@ -36,6 +52,8 @@
cmp r0, #0
movne r0, #1
2: bx lr
+UNWIND( .fnend )
+ENDPROC(\name )
.endm
#else
.macro bitop, name, instr
diff --git a/xen/arch/arm/arm32/lib/changebit.S b/xen/arch/arm/arm32/lib/changebit.S
index 62954bc..11f41d2 100644
--- a/xen/arch/arm/arm32/lib/changebit.S
+++ b/xen/arch/arm/arm32/lib/changebit.S
@@ -13,6 +13,4 @@
#include "bitops.h"
.text
-ENTRY(_change_bit)
- bitop eor
-ENDPROC(_change_bit)
+bitop _change_bit, eor
diff --git a/xen/arch/arm/arm32/lib/clearbit.S b/xen/arch/arm/arm32/lib/clearbit.S
index 42ce416..1b6a569 100644
--- a/xen/arch/arm/arm32/lib/clearbit.S
+++ b/xen/arch/arm/arm32/lib/clearbit.S
@@ -14,6 +14,4 @@
#include "bitops.h"
.text
-ENTRY(_clear_bit)
- bitop bic
-ENDPROC(_clear_bit)
+bitop _clear_bit, bic
diff --git a/xen/arch/arm/arm32/lib/copy_template.S b/xen/arch/arm/arm32/lib/copy_template.S
index 805e3f8..3bc8eb8 100644
--- a/xen/arch/arm/arm32/lib/copy_template.S
+++ b/xen/arch/arm/arm32/lib/copy_template.S
@@ -197,24 +197,24 @@
12: PLD( pld [r1, #124] )
13: ldr4w r1, r4, r5, r6, r7, abort=19f
- mov r3, lr, pull #\pull
+ mov r3, lr, lspull #\pull
subs r2, r2, #32
ldr4w r1, r8, r9, ip, lr, abort=19f
- orr r3, r3, r4, push #\push
- mov r4, r4, pull #\pull
- orr r4, r4, r5, push #\push
- mov r5, r5, pull #\pull
- orr r5, r5, r6, push #\push
- mov r6, r6, pull #\pull
- orr r6, r6, r7, push #\push
- mov r7, r7, pull #\pull
- orr r7, r7, r8, push #\push
- mov r8, r8, pull #\pull
- orr r8, r8, r9, push #\push
- mov r9, r9, pull #\pull
- orr r9, r9, ip, push #\push
- mov ip, ip, pull #\pull
- orr ip, ip, lr, push #\push
+ orr r3, r3, r4, lspush #\push
+ mov r4, r4, lspull #\pull
+ orr r4, r4, r5, lspush #\push
+ mov r5, r5, lspull #\pull
+ orr r5, r5, r6, lspush #\push
+ mov r6, r6, lspull #\pull
+ orr r6, r6, r7, lspush #\push
+ mov r7, r7, lspull #\pull
+ orr r7, r7, r8, lspush #\push
+ mov r8, r8, lspull #\pull
+ orr r8, r8, r9, lspush #\push
+ mov r9, r9, lspull #\pull
+ orr r9, r9, ip, lspush #\push
+ mov ip, ip, lspull #\pull
+ orr ip, ip, lr, lspush #\push
str8w r0, r3, r4, r5, r6, r7, r8, r9, ip, , abort=19f
bge 12b
PLD( cmn r2, #96 )
@@ -225,10 +225,10 @@
14: ands ip, r2, #28
beq 16f
-15: mov r3, lr, pull #\pull
+15: mov r3, lr, lspull #\pull
ldr1w r1, lr, abort=21f
subs ip, ip, #4
- orr r3, r3, lr, push #\push
+ orr r3, r3, lr, lspush #\push
str1w r0, r3, abort=21f
bgt 15b
CALGN( cmp r2, #0 )
diff --git a/xen/arch/arm/arm32/lib/memchr.S b/xen/arch/arm/arm32/lib/memchr.S
new file mode 100644
index 0000000..fd64ed8
--- /dev/null
+++ b/xen/arch/arm/arm32/lib/memchr.S
@@ -0,0 +1,28 @@
+/*
+ * linux/arch/arm/lib/memchr.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ASM optimised string functions
+ */
+
+#include <xen/config.h>
+
+#include "assembler.h"
+
+ .text
+ .align 5
+ENTRY(memchr)
+1: subs r2, r2, #1
+ bmi 2f
+ ldrb r3, [r0], #1
+ teq r3, r1
+ bne 1b
+ sub r0, r0, #1
+2: movne r0, #0
+ mov pc, lr
+ENDPROC(memchr)
diff --git a/xen/arch/arm/arm32/lib/memmove.S b/xen/arch/arm/arm32/lib/memmove.S
index 4e142b8..18634c3 100644
--- a/xen/arch/arm/arm32/lib/memmove.S
+++ b/xen/arch/arm/arm32/lib/memmove.S
@@ -148,24 +148,24 @@ ENTRY(memmove)
12: PLD( pld [r1, #-128] )
13: ldmdb r1!, {r7, r8, r9, ip}
- mov lr, r3, push #\push
+ mov lr, r3, lspush #\push
subs r2, r2, #32
ldmdb r1!, {r3, r4, r5, r6}
- orr lr, lr, ip, pull #\pull
- mov ip, ip, push #\push
- orr ip, ip, r9, pull #\pull
- mov r9, r9, push #\push
- orr r9, r9, r8, pull #\pull
- mov r8, r8, push #\push
- orr r8, r8, r7, pull #\pull
- mov r7, r7, push #\push
- orr r7, r7, r6, pull #\pull
- mov r6, r6, push #\push
- orr r6, r6, r5, pull #\pull
- mov r5, r5, push #\push
- orr r5, r5, r4, pull #\pull
- mov r4, r4, push #\push
- orr r4, r4, r3, pull #\pull
+ orr lr, lr, ip, lspull #\pull
+ mov ip, ip, lspush #\push
+ orr ip, ip, r9, lspull #\pull
+ mov r9, r9, lspush #\push
+ orr r9, r9, r8, lspull #\pull
+ mov r8, r8, lspush #\push
+ orr r8, r8, r7, lspull #\pull
+ mov r7, r7, lspush #\push
+ orr r7, r7, r6, lspull #\pull
+ mov r6, r6, lspush #\push
+ orr r6, r6, r5, lspull #\pull
+ mov r5, r5, lspush #\push
+ orr r5, r5, r4, lspull #\pull
+ mov r4, r4, lspush #\push
+ orr r4, r4, r3, lspull #\pull
stmdb r0!, {r4 - r9, ip, lr}
bge 12b
PLD( cmn r2, #96 )
@@ -176,10 +176,10 @@ ENTRY(memmove)
14: ands ip, r2, #28
beq 16f
-15: mov lr, r3, push #\push
+15: mov lr, r3, lspush #\push
ldr r3, [r1, #-4]!
subs ip, ip, #4
- orr lr, lr, r3, pull #\pull
+ orr lr, lr, r3, lspull #\pull
str lr, [r0, #-4]!
bgt 15b
CALGN( cmp r2, #0 )
diff --git a/xen/arch/arm/arm32/lib/memset.S b/xen/arch/arm/arm32/lib/memset.S
index d2937a3..c8ab257 100644
--- a/xen/arch/arm/arm32/lib/memset.S
+++ b/xen/arch/arm/arm32/lib/memset.S
@@ -16,27 +16,15 @@
.text
.align 5
- .word 0
-
-1: subs r2, r2, #4 @ 1 do we have enough
- blt 5f @ 1 bytes to align with?
- cmp r3, #2 @ 1
- strltb r1, [r0], #1 @ 1
- strleb r1, [r0], #1 @ 1
- strb r1, [r0], #1 @ 1
- add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
-/*
- * The pointer is now aligned and the length is adjusted. Try doing the
- * memset again.
- */
ENTRY(memset)
ands r3, r0, #3 @ 1 unaligned?
- bne 1b @ 1
+ mov ip, r0 @ preserve r0 as return value
+ bne 6f @ 1
/*
- * we know that the pointer in r0 is aligned to a word boundary.
+ * we know that the pointer in ip is aligned to a word boundary.
*/
- orr r1, r1, r1, lsl #8
+1: orr r1, r1, r1, lsl #8
orr r1, r1, r1, lsl #16
mov r3, r1
cmp r2, #16
@@ -45,29 +33,28 @@ ENTRY(memset)
#if ! CALGN(1)+0
/*
- * We need an extra register for this loop - save the return address and
- * use the LR
+ * We need 2 extra registers for this loop - use r8 and the LR
*/
- str lr, [sp, #-4]!
- mov ip, r1
+ stmfd sp!, {r8, lr}
+ mov r8, r1
mov lr, r1
2: subs r2, r2, #64
- stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time.
- stmgeia r0!, {r1, r3, ip, lr}
- stmgeia r0!, {r1, r3, ip, lr}
- stmgeia r0!, {r1, r3, ip, lr}
+ stmgeia ip!, {r1, r3, r8, lr} @ 64 bytes at a time.
+ stmgeia ip!, {r1, r3, r8, lr}
+ stmgeia ip!, {r1, r3, r8, lr}
+ stmgeia ip!, {r1, r3, r8, lr}
bgt 2b
- ldmeqfd sp!, {pc} @ Now <64 bytes to go.
+ ldmeqfd sp!, {r8, pc} @ Now <64 bytes to go.
/*
* No need to correct the count; we're only testing bits from now on
*/
tst r2, #32
- stmneia r0!, {r1, r3, ip, lr}
- stmneia r0!, {r1, r3, ip, lr}
+ stmneia ip!, {r1, r3, r8, lr}
+ stmneia ip!, {r1, r3, r8, lr}
tst r2, #16
- stmneia r0!, {r1, r3, ip, lr}
- ldr lr, [sp], #4
+ stmneia ip!, {r1, r3, r8, lr}
+ ldmfd sp!, {r8, lr}
#else
@@ -76,54 +63,63 @@ ENTRY(memset)
* whole cache lines at once.
*/
- stmfd sp!, {r4-r7, lr}
+ stmfd sp!, {r4-r8, lr}
mov r4, r1
mov r5, r1
mov r6, r1
mov r7, r1
- mov ip, r1
+ mov r8, r1
mov lr, r1
cmp r2, #96
- tstgt r0, #31
+ tstgt ip, #31
ble 3f
- and ip, r0, #31
- rsb ip, ip, #32
- sub r2, r2, ip
- movs ip, ip, lsl #(32 - 4)
- stmcsia r0!, {r4, r5, r6, r7}
- stmmiia r0!, {r4, r5}
- tst ip, #(1 << 30)
- mov ip, r1
- strne r1, [r0], #4
+ and r8, ip, #31
+ rsb r8, r8, #32
+ sub r2, r2, r8
+ movs r8, r8, lsl #(32 - 4)
+ stmcsia ip!, {r4, r5, r6, r7}
+ stmmiia ip!, {r4, r5}
+ tst r8, #(1 << 30)
+ mov r8, r1
+ strne r1, [ip], #4
3: subs r2, r2, #64
- stmgeia r0!, {r1, r3-r7, ip, lr}
- stmgeia r0!, {r1, r3-r7, ip, lr}
+ stmgeia ip!, {r1, r3-r8, lr}
+ stmgeia ip!, {r1, r3-r8, lr}
bgt 3b
- ldmeqfd sp!, {r4-r7, pc}
+ ldmeqfd sp!, {r4-r8, pc}
tst r2, #32
- stmneia r0!, {r1, r3-r7, ip, lr}
+ stmneia ip!, {r1, r3-r8, lr}
tst r2, #16
- stmneia r0!, {r4-r7}
- ldmfd sp!, {r4-r7, lr}
+ stmneia ip!, {r4-r7}
+ ldmfd sp!, {r4-r8, lr}
#endif
4: tst r2, #8
- stmneia r0!, {r1, r3}
+ stmneia ip!, {r1, r3}
tst r2, #4
- strne r1, [r0], #4
+ strne r1, [ip], #4
/*
* When we get here, we've got less than 4 bytes to zero. We
* may have an unaligned pointer as well.
*/
5: tst r2, #2
- strneb r1, [r0], #1
- strneb r1, [r0], #1
+ strneb r1, [ip], #1
+ strneb r1, [ip], #1
tst r2, #1
- strneb r1, [r0], #1
+ strneb r1, [ip], #1
mov pc, lr
+
+6: subs r2, r2, #4 @ 1 do we have enough
+ blt 5b @ 1 bytes to align with?
+ cmp r3, #2 @ 1
+ strltb r1, [ip], #1 @ 1
+ strleb r1, [ip], #1 @ 1
+ strb r1, [ip], #1 @ 1
+ add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
+ b 1b
ENDPROC(memset)
diff --git a/xen/arch/arm/arm32/lib/setbit.S b/xen/arch/arm/arm32/lib/setbit.S
index c828851..1f4ef56 100644
--- a/xen/arch/arm/arm32/lib/setbit.S
+++ b/xen/arch/arm/arm32/lib/setbit.S
@@ -13,6 +13,4 @@
#include "bitops.h"
.text
-ENTRY(_set_bit)
- bitop orr
-ENDPROC(_set_bit)
+bitop _set_bit, orr
diff --git a/xen/arch/arm/arm32/lib/strchr.S b/xen/arch/arm/arm32/lib/strchr.S
new file mode 100644
index 0000000..2f89c01
--- /dev/null
+++ b/xen/arch/arm/arm32/lib/strchr.S
@@ -0,0 +1,29 @@
+/*
+ * linux/arch/arm/lib/strchr.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ASM optimised string functions
+ */
+
+#include <xen/config.h>
+
+#include "assembler.h"
+
+ .text
+ .align 5
+ENTRY(strchr)
+ and r1, r1, #0xff
+1: ldrb r2, [r0], #1
+ teq r2, r1
+ teqne r2, #0
+ bne 1b
+ teq r2, r1
+ movne r0, #0
+ subeq r0, r0, #1
+ mov pc, lr
+ENDPROC(strchr)
diff --git a/xen/arch/arm/arm32/lib/strrchr.S b/xen/arch/arm/arm32/lib/strrchr.S
new file mode 100644
index 0000000..7d534b1
--- /dev/null
+++ b/xen/arch/arm/arm32/lib/strrchr.S
@@ -0,0 +1,28 @@
+/*
+ * linux/arch/arm/lib/strrchr.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ASM optimised string functions
+ */
+
+#include <xen/config.h>
+
+#include "assembler.h"
+
+ .text
+ .align 5
+ENTRY(strrchr)
+ mov r3, #0
+1: ldrb r2, [r0], #1
+ teq r2, r1
+ subeq r3, r0, #1
+ teq r2, #0
+ bne 1b
+ mov r0, r3
+ mov pc, lr
+ENDPROC(strrchr)
diff --git a/xen/arch/arm/arm32/lib/testchangebit.S b/xen/arch/arm/arm32/lib/testchangebit.S
index a7f527c..7f4635c 100644
--- a/xen/arch/arm/arm32/lib/testchangebit.S
+++ b/xen/arch/arm/arm32/lib/testchangebit.S
@@ -13,6 +13,4 @@
#include "bitops.h"
.text
-ENTRY(_test_and_change_bit)
- testop eor, str
-ENDPROC(_test_and_change_bit)
+testop _test_and_change_bit, eor, str
diff --git a/xen/arch/arm/arm32/lib/testclearbit.S b/xen/arch/arm/arm32/lib/testclearbit.S
index 8f39c72..4d4152f 100644
--- a/xen/arch/arm/arm32/lib/testclearbit.S
+++ b/xen/arch/arm/arm32/lib/testclearbit.S
@@ -13,6 +13,4 @@
#include "bitops.h"
.text
-ENTRY(_test_and_clear_bit)
- testop bicne, strne
-ENDPROC(_test_and_clear_bit)
+testop _test_and_clear_bit, bicne, strne
diff --git a/xen/arch/arm/arm32/lib/testsetbit.S b/xen/arch/arm/arm32/lib/testsetbit.S
index 1b8d273..54f48f9 100644
--- a/xen/arch/arm/arm32/lib/testsetbit.S
+++ b/xen/arch/arm/arm32/lib/testsetbit.S
@@ -13,6 +13,4 @@
#include "bitops.h"
.text
-ENTRY(_test_and_set_bit)
- testop orreq, streq
-ENDPROC(_test_and_set_bit)
+testop _test_and_set_bit, orreq, streq
diff --git a/xen/arch/arm/arm32/proc-caxx.c b/xen/arch/arm/arm32/proc-caxx.c
new file mode 100644
index 0000000..9166a1d
--- /dev/null
+++ b/xen/arch/arm/arm32/proc-caxx.c
@@ -0,0 +1,35 @@
+/*
+ * xen/arch/arm/arm32/proc-caxx.c
+ *
+ * arm V7 Cortex A15 and A7 initialisation
+ *
+ * Julien Grall <julien.grall at linaro.org>
+ * Copyright (c) 2014 Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <asm/procinfo.h>
+#include <asm/processor.h>
+
+#define ACTLR_SMP (1 << 6)
+
+static void caxx_vcpu_initialise(struct vcpu *v)
+{
+ /* If the guest has more 1 VCPU, enable the SMP bit in ACTLR */
+ if ( v->domain->max_vcpus > 1 )
+ v->arch.actlr |= ACTLR_SMP;
+ else
+ v->arch.actlr &= ~ACTLR_SMP;
+}
+
+const struct processor caxx_processor = {
+ .vcpu_initialise = caxx_vcpu_initialise,
+};
diff --git a/xen/arch/arm/arm32/proc-v7.S b/xen/arch/arm/arm32/proc-v7.S
index 2c8cb9c..2f3ff1e 100644
--- a/xen/arch/arm/arm32/proc-v7.S
+++ b/xen/arch/arm/arm32/proc-v7.S
@@ -20,10 +20,12 @@
#include <asm/asm_defns.h>
#include <asm/arm32/processor.h>
-v7_init:
+ca15mp_init:
+ca7mp_init:
+brahma15mp_init:
/* Set up the SMP bit in ACTLR */
mrc CP32(r0, ACTLR)
- orr r0, r0, #(ACTLR_V7_SMP) /* enable SMP bit */
+ orr r0, r0, #(ACTLR_CAXX_SMP) /* enable SMP bit */
mcr CP32(r0, ACTLR)
mov pc, lr
@@ -32,7 +34,8 @@ v7_init:
__v7_ca15mp_proc_info:
.long 0x410FC0F0 /* Cortex-A15 */
.long 0xFF0FFFF0 /* Mask */
- .long v7_init
+ .long ca15mp_init
+ .long caxx_processor
.size __v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info
.section ".init.proc.info", #alloc, #execinstr
@@ -40,15 +43,17 @@ __v7_ca15mp_proc_info:
__v7_ca7mp_proc_info:
.long 0x410FC070 /* Cortex-A7 */
.long 0xFF0FFFF0 /* Mask */
- .long v7_init
+ .long ca7mp_init
+ .long caxx_processor
.size __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info
.section ".init.proc.info", #alloc, #execinstr
.type __v7_brahma15mp_proc_info, #object
__v7_brahma15mp_proc_info:
- .long 0x420F00F2 /* Broadcom Brahma-B15 */
- .long 0xFF0FFFFF /* Mask */
- .long v7_init
+ .long 0x420F00F0 /* Broadcom Brahma-B15 */
+ .long 0xFF0FFFF0 /* Mask */
+ .long brahma15mp_init
+ .long caxx_processor
.size __v7_brahma15mp_proc_info, . - __v7_brahma15mp_proc_info
/*
diff --git a/xen/arch/arm/arm32/traps.c b/xen/arch/arm/arm32/traps.c
index ff0b945..f8cf864 100644
--- a/xen/arch/arm/arm32/traps.c
+++ b/xen/arch/arm/arm32/traps.c
@@ -18,6 +18,7 @@
#include <xen/config.h>
#include <xen/lib.h>
+#include <xen/kernel.h>
#include <public/xen.h>
@@ -25,6 +26,28 @@
asmlinkage void do_trap_undefined_instruction(struct cpu_user_regs *regs)
{
+ uint32_t pc = regs->pc;
+ uint32_t instr;
+
+ if ( !is_kernel_text(pc) &&
+ (system_state >= SYS_STATE_active || !is_kernel_inittext(pc)) )
+ goto die;
+
+ /* PC should be always a multiple of 4, as Xen is using ARM instruction set */
+ if ( regs->pc & 0x3 )
+ goto die;
+
+ instr = *((uint32_t *)pc);
+ if ( instr != BUG_OPCODE )
+ goto die;
+
+ if ( do_bug_frame(regs, pc) )
+ goto die;
+
+ regs->pc += 4;
+ return;
+
+die:
do_unexpected_trap("Undefined Instruction", regs);
}
diff --git a/xen/arch/arm/arm64/Makefile b/xen/arch/arm/arm64/Makefile
index d2d5875..c7243f5 100644
--- a/xen/arch/arm/arm64/Makefile
+++ b/xen/arch/arm/arm64/Makefile
@@ -7,5 +7,6 @@ obj-y += domain.o
obj-y += vfp.o
obj-y += smpboot.o
obj-y += domctl.o
+obj-y += cache.o
obj-$(EARLY_PRINTK) += debug.o
diff --git a/xen/arch/arm/arm64/asm-offsets.c b/xen/arch/arm/arm64/asm-offsets.c
index d7572fa..a3ce816 100644
--- a/xen/arch/arm/arm64/asm-offsets.c
+++ b/xen/arch/arm/arm64/asm-offsets.c
@@ -12,11 +12,12 @@
#include <public/xen.h>
#include <asm/current.h>
-#define DEFINE(_sym, _val) \
- __asm__ __volatile__ ( "\n->" #_sym " %0 " #_val : : "i" (_val) )
-#define BLANK() \
- __asm__ __volatile__ ( "\n->" : : )
-#define OFFSET(_sym, _str, _mem) \
+#define DEFINE(_sym, _val) \
+ asm volatile ("\n.ascii\"==>#define " #_sym " %0 /* " #_val " */<==\"" \
+ : : "i" (_val) )
+#define BLANK() \
+ asm volatile ( "\n.ascii\"==><==\"" : : )
+#define OFFSET(_sym, _str, _mem) \
DEFINE(_sym, offsetof(_str, _mem));
void __dummy__(void)
diff --git a/xen/arch/arm/arm64/cache.S b/xen/arch/arm/arm64/cache.S
new file mode 100644
index 0000000..eff4e16
--- /dev/null
+++ b/xen/arch/arm/arm64/cache.S
@@ -0,0 +1,52 @@
+/*
+ * Cache maintenance
+ *
+ * Copyright (C) 2001 Deep Blue Solutions Ltd.
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 1996-2000 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * dcache_line_size - get the minimum D-cache line size from the CTR register.
+ */
+ .macro dcache_line_size, reg, tmp
+ mrs \tmp, ctr_el0 // read CTR
+ ubfm \tmp, \tmp, #16, #19 // cache line size encoding
+ mov \reg, #4 // bytes per word
+ lsl \reg, \reg, \tmp // actual cache line size
+ .endm
+
+/*
+ * __flush_dcache_area(kaddr, size)
+ *
+ * Ensure that the data held in the page kaddr is written back to the
+ * page in question.
+ *
+ * - kaddr - kernel address
+ * - size - size in question
+ */
+ENTRY(__flush_dcache_area)
+ dcache_line_size x2, x3
+ add x1, x0, x1
+ sub x3, x2, #1
+ bic x0, x0, x3
+1: dc civac, x0 // clean & invalidate D line / unified line
+ add x0, x0, x2
+ cmp x0, x1
+ b.lo 1b
+ dsb sy
+ ret
+ENDPROC(__flush_dcache_area)
diff --git a/xen/arch/arm/arm64/domain.c b/xen/arch/arm/arm64/domain.c
index 6990a7b..ccba21f 100644
--- a/xen/arch/arm/arm64/domain.c
+++ b/xen/arch/arm/arm64/domain.c
@@ -29,7 +29,7 @@ void vcpu_regs_hyp_to_user(const struct vcpu *vcpu,
{
#define C(hyp,user) regs->user = vcpu->arch.cpu_info->guest_cpu_user_regs.hyp
ALLREGS;
- if ( is_pv32_domain(vcpu->domain) )
+ if ( is_32bit_domain(vcpu->domain) )
{
ALLREGS32;
}
@@ -45,7 +45,7 @@ void vcpu_regs_user_to_hyp(struct vcpu *vcpu,
{
#define C(hyp,user) vcpu->arch.cpu_info->guest_cpu_user_regs.hyp = regs->user
ALLREGS;
- if ( is_pv32_domain(vcpu->domain) )
+ if ( is_32bit_domain(vcpu->domain) )
{
ALLREGS32;
}
diff --git a/xen/arch/arm/arm64/domctl.c b/xen/arch/arm/arm64/domctl.c
index e2b4617..c0ff248 100644
--- a/xen/arch/arm/arm64/domctl.c
+++ b/xen/arch/arm/arm64/domctl.c
@@ -11,6 +11,7 @@
#include <xen/sched.h>
#include <xen/hypercall.h>
#include <public/domctl.h>
+#include <asm/cpufeature.h>
static long switch_mode(struct domain *d, enum domain_type type)
{
@@ -35,9 +36,11 @@ long subarch_do_domctl(struct xen_domctl *domctl, struct domain *d,
switch ( domctl->u.address_size.size )
{
case 32:
- return switch_mode(d, DOMAIN_PV32);
+ if ( !cpu_has_el1_32 )
+ return -EINVAL;
+ return switch_mode(d, DOMAIN_32BIT);
case 64:
- return switch_mode(d, DOMAIN_PV64);
+ return switch_mode(d, DOMAIN_64BIT);
default:
return -EINVAL;
}
diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S
index be44f67..75b7ee1 100644
--- a/xen/arch/arm/arm64/head.S
+++ b/xen/arch/arm/arm64/head.S
@@ -24,13 +24,16 @@
#include <asm/page.h>
#include <asm/asm_defns.h>
#include <asm/early_printk.h>
+#include <efi/efierr.h>
+#include <asm/arm64/efibind.h>
-#define PT_PT 0xe7f /* nG=1 AF=1 SH=10 AP=01 NS=1 ATTR=111 T=1 P=1 */
-#define PT_MEM 0xe7d /* nG=1 AF=1 SH=10 AP=01 NS=1 ATTR=111 T=0 P=1 */
+#define PT_PT 0xf7f /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=1 P=1 */
+#define PT_MEM 0xf7d /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=0 P=1 */
+#define PT_MEM_L3 0xf7f /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=1 P=1 */
#define PT_DEV 0xe71 /* nG=1 AF=1 SH=10 AP=01 NS=1 ATTR=100 T=0 P=1 */
#define PT_DEV_L3 0xe73 /* nG=1 AF=1 SH=10 AP=01 NS=1 ATTR=100 T=1 P=1 */
-#if (defined (EARLY_PRINTK)) && (defined (EARLY_PRINTK_INC))
+#if (defined (CONFIG_EARLY_PRINTK)) && (defined (EARLY_PRINTK_INC))
#include EARLY_PRINTK_INC
#endif
@@ -61,7 +64,7 @@
* x22 - is_secondary_cpu
* x23 - UART address
* x24 - cpuid
- * x25 -
+ * x25 - identity map in place
* x26 -
* x27 -
* x28 -
@@ -71,7 +74,7 @@
/* Macro to print a string to the UART, if there is one.
* Clobbers x0-x3. */
-#ifdef EARLY_PRINTK
+#ifdef CONFIG_EARLY_PRINTK
#define PRINT(_s) \
adr x0, 98f ; \
bl puts ; \
@@ -79,9 +82,9 @@
98: .asciz _s ; \
.align 2 ; \
99:
-#else /* EARLY_PRINTK */
+#else /* CONFIG_EARLY_PRINTK */
#define PRINT(s)
-#endif /* !EARLY_PRINTK */
+#endif /* !CONFIG_EARLY_PRINTK */
/*.aarch64*/
@@ -95,17 +98,22 @@
*
* This must be the very first address in the loaded image.
* It should be linked at XEN_VIRT_START, and loaded at any
- * 2MB-aligned address. All of text+data+bss must fit in 2MB,
+ * 4K-aligned address. All of text+data+bss must fit in 2MB,
* or the initial pagetable code below will need adjustment.
*/
- .global start
-start:
+GLOBAL(start)
/*
* DO NOT MODIFY. Image header expected by Linux boot-loaders.
*/
- b real_start /* branch to kernel start, magic */
- .long 0 /* reserved */
+efi_head:
+ /*
+ * This add instruction has no meaningful effect except that
+ * its opcode forms the magic "MZ" signature of a PE/COFF file
+ * that is required for UEFI applications.
+ */
+ add x13, x18, #0x16
+ b real_start /* branch to kernel start */
.quad 0 /* Image load offset from start of RAM */
.quad 0 /* reserved */
.quad 0 /* reserved */
@@ -116,8 +124,113 @@ start:
.byte 0x52
.byte 0x4d
.byte 0x64
- .word 0 /* reserved */
+ .long pe_header - efi_head /* Offset to the PE header. */
+ /*
+ * Add the PE/COFF header to the file. The address of this header
+ * is at offset 0x3c in the file, and is part of Linux "Image"
+ * header. The arm64 Linux Image format is designed to support
+ * being both an 'Image' format binary and a PE/COFF binary.
+ * The PE/COFF format is defined by Microsoft, and is available
+ * from: http://msdn.microsoft.com/en-us/gg463119.aspx
+ * Version 8.3 adds support for arm64 and UEFI usage.
+ */
+
+ .align 3
+pe_header:
+ .ascii "PE"
+ .short 0
+coff_header:
+ .short 0xaa64 /* AArch64 */
+ .short 2 /* nr_sections */
+ .long 0 /* TimeDateStamp */
+ .long 0 /* PointerToSymbolTable */
+ .long 1 /* NumberOfSymbols */
+ .short section_table - optional_header /* SizeOfOptionalHeader */
+ .short 0x206 /* Characteristics. */
+ /* IMAGE_FILE_DEBUG_STRIPPED | */
+ /* IMAGE_FILE_EXECUTABLE_IMAGE | */
+ /* IMAGE_FILE_LINE_NUMS_STRIPPED */
+optional_header:
+ .short 0x20b /* PE32+ format */
+ .byte 0x02 /* MajorLinkerVersion */
+ .byte 0x14 /* MinorLinkerVersion */
+ .long _end - real_start /* SizeOfCode */
+ .long 0 /* SizeOfInitializedData */
+ .long 0 /* SizeOfUninitializedData */
+ .long efi_start - efi_head /* AddressOfEntryPoint */
+ .long real_start - efi_head /* BaseOfCode */
+
+extra_header_fields:
+ .quad 0 /* ImageBase */
+ .long 0x1000 /* SectionAlignment (4 KByte) */
+ .long 0x8 /* FileAlignment */
+ .short 0 /* MajorOperatingSystemVersion */
+ .short 0 /* MinorOperatingSystemVersion */
+ .short 0 /* MajorImageVersion */
+ .short 0 /* MinorImageVersion */
+ .short 0 /* MajorSubsystemVersion */
+ .short 0 /* MinorSubsystemVersion */
+ .long 0 /* Win32VersionValue */
+
+ .long _end - efi_head /* SizeOfImage */
+
+ /* Everything before the kernel image is considered part of the header */
+ .long real_start - efi_head /* SizeOfHeaders */
+ .long 0 /* CheckSum */
+ .short 0xa /* Subsystem (EFI application) */
+ .short 0 /* DllCharacteristics */
+ .quad 0 /* SizeOfStackReserve */
+ .quad 0 /* SizeOfStackCommit */
+ .quad 0 /* SizeOfHeapReserve */
+ .quad 0 /* SizeOfHeapCommit */
+ .long 0 /* LoaderFlags */
+ .long 0x6 /* NumberOfRvaAndSizes */
+
+ .quad 0 /* ExportTable */
+ .quad 0 /* ImportTable */
+ .quad 0 /* ResourceTable */
+ .quad 0 /* ExceptionTable */
+ .quad 0 /* CertificationTable */
+ .quad 0 /* BaseRelocationTable */
+
+ /* Section table */
+section_table:
+
+ /*
+ * The EFI application loader requires a relocation section
+ * because EFI applications must be relocatable. This is a
+ * dummy section as far as we are concerned.
+ */
+ .ascii ".reloc"
+ .byte 0
+ .byte 0 /* end of 0 padding of section name */
+ .long 0
+ .long 0
+ .long 0 /* SizeOfRawData */
+ .long 0 /* PointerToRawData */
+ .long 0 /* PointerToRelocations */
+ .long 0 /* PointerToLineNumbers */
+ .short 0 /* NumberOfRelocations */
+ .short 0 /* NumberOfLineNumbers */
+ .long 0x42100040 /* Characteristics (section flags) */
+
+
+ .ascii ".text"
+ .byte 0
+ .byte 0
+ .byte 0 /* end of 0 padding of section name */
+ .long _end - real_start /* VirtualSize */
+ .long real_start - efi_head /* VirtualAddress */
+ .long __init_end_efi - real_start /* SizeOfRawData */
+ .long real_start - efi_head /* PointerToRawData */
+
+ .long 0 /* PointerToRelocations (0 for executables) */
+ .long 0 /* PointerToLineNumbers (0 for executables) */
+ .short 0 /* NumberOfRelocations (0 for executables) */
+ .short 0 /* NumberOfLineNumbers (0 for executables) */
+ .long 0xe0500020 /* Characteristics (section flags) */
+ .align 5
real_start:
msr DAIFSet, 0xf /* Disable all interrupts */
@@ -174,7 +287,7 @@ common_start:
b 2b
1:
-#ifdef EARLY_PRINTK
+#ifdef CONFIG_EARLY_PRINTK
ldr x23, =EARLY_UART_BASE_ADDRESS /* x23 := UART base address */
cbnz x22, 1f
bl init_uart /* Boot CPU sets up the UART too */
@@ -224,13 +337,17 @@ skip_bss:
ldr x0, =MAIRVAL
msr mair_el2, x0
- /* Set up the HTCR:
- * PASize -- 40 bits / 1TB
+ /* Set up TCR_EL2:
+ * PS -- Based on ID_AA64MMFR0_EL1.PARange
* Top byte is used
- * PT walks use Outer-Shareable accesses,
+ * PT walks use Inner-Shareable accesses,
* PT walks are write-back, write-allocate in both cache levels,
* Full 64-bit address space goes through this table. */
- ldr x0, =0x80822500
+ ldr x0, =(TCR_RES1|TCR_SH0_IS|TCR_ORGN0_WBWA|TCR_IRGN0_WBWA|TCR_T0SZ(0))
+ /* ID_AA64MMFR0_EL1[3:0] (PARange) corresponds to TCR_EL2[18:16] (PS) */
+ mrs x1, ID_AA64MMFR0_EL1
+ bfi x0, x1, #16, #3
+
msr tcr_el2, x0
/* Set up the SCTLR_EL2:
@@ -239,9 +356,9 @@ skip_bss:
* Write-implies-XN disabled (for now),
* D-cache disabled (for now),
* I-cache enabled,
- * Alignment checking enabled,
+ * Alignment checking disabled,
* MMU translation disabled (for now). */
- ldr x0, =(HSCTLR_BASE|SCTLR_A)
+ ldr x0, =(HSCTLR_BASE)
msr SCTLR_EL2, x0
/* Rebuild the boot pagetable's first-level entries. The structure
@@ -252,6 +369,13 @@ skip_bss:
* mapping. So each CPU must rebuild the page tables here with
* the 1:1 in place. */
+ /* If Xen is loaded at exactly XEN_VIRT_START then we don't
+ * need an additional 1:1 mapping, the virtual mapping will
+ * suffice.
+ */
+ cmp x19, #XEN_VIRT_START
+ cset x25, eq /* x25 := identity map in place, or not */
+
/* Write Xen's PT's paddr into TTBR0_EL2 */
ldr x4, =boot_pgtable
add x4, x4, x20 /* x4 := paddr (boot_pagetable) */
@@ -266,16 +390,33 @@ skip_bss:
orr x2, x1, x3 /* + rights for linear PT */
str x2, [x4, #0] /* Map it in slot 0 */
- /* ... map of paddr(start) in boot_pgtable */
- lsr x1, x19, #39 /* Offset of base paddr in boot_pgtable */
+ /* ... map of paddr(start) in boot_pgtable+boot_first_id */
+ lsr x1, x19, #ZEROETH_SHIFT/* Offset of base paddr in boot_pgtable */
cbz x1, 1f /* It's in slot 0, map in boot_first
* or boot_second later on */
- lsl x2, x1, #39 /* Base address for 512GB mapping */
- mov x3, #PT_MEM /* x2 := Section mapping */
- orr x2, x2, x3
+ /* Level zero does not support superpage mappings, so we have
+ * to use an extra first level page in which we create a 1GB mapping.
+ */
+ ldr x2, =boot_first_id
+ add x2, x2, x20 /* x2 := paddr (boot_first_id) */
+
+ mov x3, #PT_PT /* x2 := table map of boot_first_id */
+ orr x2, x2, x3 /* + rights for linear PT */
lsl x1, x1, #3 /* x1 := Slot offset */
- str x2, [x4, x1] /* Mapping of paddr(start)*/
+ str x2, [x4, x1]
+
+ ldr x4, =boot_first_id /* Next level into boot_first_id */
+ add x4, x4, x20 /* x4 := paddr(boot_first_id) */
+
+ lsr x1, x19, #FIRST_SHIFT /* x1 := Offset of base paddr in boot_first_id */
+ lsl x2, x1, #FIRST_SHIFT /* x2 := Base address for 1GB mapping */
+ mov x3, #PT_MEM /* x2 := Section map */
+ orr x2, x2, x3
+ and x1, x1, #LPAE_ENTRY_MASK /* x1 := Slot offset */
+ lsl x1, x1, #3
+ str x2, [x4, x1] /* Mapping of paddr(start) */
+ mov x25, #1 /* x25 := identity map now in place */
1: /* Setup boot_first: */
ldr x4, =boot_first /* Next level into boot_first */
@@ -284,50 +425,79 @@ skip_bss:
/* ... map boot_second in boot_first[0] */
ldr x1, =boot_second
add x1, x1, x20 /* x1 := paddr(boot_second) */
- mov x3, #PT_PT /* x2 := table map of boot_first */
+ mov x3, #PT_PT /* x2 := table map of boot_second */
orr x2, x1, x3 /* + rights for linear PT */
str x2, [x4, #0] /* Map it in slot 0 */
/* ... map of paddr(start) in boot_first */
- lsr x2, x19, #30 /* x2 := Offset of base paddr in boot_first */
- and x1, x2, 0x1ff /* x1 := Slot to use */
+ cbnz x25, 1f /* x25 is set if already created */
+ lsr x2, x19, #FIRST_SHIFT /* x2 := Offset of base paddr in boot_first */
+ and x1, x2, #LPAE_ENTRY_MASK /* x1 := Slot to use */
cbz x1, 1f /* It's in slot 0, map in boot_second */
- lsl x2, x2, #30 /* Base address for 1GB mapping */
+ lsl x2, x2, #FIRST_SHIFT /* Base address for 1GB mapping */
mov x3, #PT_MEM /* x2 := Section map */
orr x2, x2, x3
lsl x1, x1, #3 /* x1 := Slot offset */
str x2, [x4, x1] /* Create mapping of paddr(start)*/
+ mov x25, #1 /* x25 := identity map now in place */
1: /* Setup boot_second: */
- ldr x4, =boot_second
- add x4, x4, x20 /* x4 := paddr (boot_second) */
+ ldr x4, =boot_second /* Next level into boot_second */
+ add x4, x4, x20 /* x4 := paddr(boot_second) */
- lsr x2, x19, #20 /* Base address for 2MB mapping */
- lsl x2, x2, #20
+ /* ... map boot_third in boot_second[1] */
+ ldr x1, =boot_third
+ add x1, x1, x20 /* x1 := paddr(boot_third) */
+ mov x3, #PT_PT /* x2 := table map of boot_third */
+ orr x2, x1, x3 /* + rights for linear PT */
+ str x2, [x4, #8] /* Map it in slot 1 */
+
+ /* ... map of paddr(start) in boot_second */
+ cbnz x25, 1f /* x25 is set if already created */
+ lsr x2, x19, #SECOND_SHIFT /* x2 := Offset of base paddr in boot_second */
+ and x1, x2, #LPAE_ENTRY_MASK /* x1 := Slot to use */
+ cmp x1, #1
+ b.eq virtphys_clash /* It's in slot 1, which we cannot handle */
+
+ lsl x2, x2, #SECOND_SHIFT /* Base address for 2MB mapping */
mov x3, #PT_MEM /* x2 := Section map */
orr x2, x2, x3
+ lsl x1, x1, #3 /* x1 := Slot offset */
+ str x2, [x4, x1] /* Create mapping of paddr(start)*/
+ mov x25, #1 /* x25 := identity map now in place */
- /* ... map of vaddr(start) in boot_second */
- ldr x1, =start
- lsr x1, x1, #18 /* Slot for vaddr(start) */
- str x2, [x4, x1] /* Map vaddr(start) */
+1: /* Setup boot_third: */
+ ldr x4, =boot_third
+ add x4, x4, x20 /* x4 := paddr (boot_third) */
- /* ... map of paddr(start) in boot_second */
- lsr x1, x19, #30 /* Base paddr */
- cbnz x1, 1f /* If paddr(start) is not in slot 0
- * then the mapping was done in
- * boot_pgtable or boot_first above */
+ lsr x2, x19, #THIRD_SHIFT /* Base address for 4K mapping */
+ lsl x2, x2, #THIRD_SHIFT
+ mov x3, #PT_MEM_L3 /* x2 := Section map */
+ orr x2, x2, x3
- lsr x1, x19, #18 /* Slot for paddr(start) */
- str x2, [x4, x1] /* Map Xen there */
-1:
+ /* ... map of vaddr(start) in boot_third */
+ mov x1, xzr
+1: str x2, [x4, x1] /* Map vaddr(start) */
+ add x2, x2, #PAGE_SIZE /* Next page */
+ add x1, x1, #8 /* Next slot */
+ cmp x1, #(LPAE_ENTRIES<<3) /* 512 entries per page */
+ b.lt 1b
/* Defer fixmap and dtb mapping until after paging enabled, to
* avoid them clashing with the 1:1 mapping. */
/* boot pagetable setup complete */
+ cbnz x25, 1f /* Did we manage to create an identity mapping ? */
+ PRINT("Unable to build boot page tables - Failed to identity map Xen.\r\n")
+ b fail
+virtphys_clash:
+ /* Identity map clashes with boot_third, which we cannot handle yet */
+ PRINT("- Unable to build boot page tables - virt and phys addresses clash. -\r\n")
+ b fail
+
+1:
PRINT("- Turning on paging -\r\n")
ldr x1, =paging /* Explicit vaddr, not RIP-relative */
@@ -343,16 +513,16 @@ paging:
/* Now we can install the fixmap and dtb mappings, since we
* don't need the 1:1 map any more */
dsb sy
-#if defined(EARLY_PRINTK) /* Fixmap is only used by early printk */
+#if defined(CONFIG_EARLY_PRINTK) /* Fixmap is only used by early printk */
/* Non-boot CPUs don't need to rebuild the fixmap itself, just
- * the mapping from boot_second to xen_fixmap */
+ * the mapping from boot_second to xen_fixmap */
cbnz x22, 1f
/* Add UART to the fixmap table */
ldr x1, =xen_fixmap
add x1, x1, x20 /* x1 := paddr (xen_fixmap) */
- lsr x2, x23, #12
- lsl x2, x2, #12 /* 4K aligned paddr of UART */
+ lsr x2, x23, #THIRD_SHIFT
+ lsl x2, x2, #THIRD_SHIFT /* 4K aligned paddr of UART */
mov x3, #PT_DEV_L3
orr x2, x2, x3 /* x2 := 4K dev map including UART */
str x2, [x1, #(FIXMAP_CONSOLE*8)] /* Map it in the first fixmap's slot */
@@ -365,7 +535,7 @@ paging:
mov x3, #PT_PT
orr x2, x2, x3 /* x2 := table map of xen_fixmap */
ldr x1, =FIXMAP_ADDR(0)
- lsr x1, x1, #18 /* x1 := Slot for FIXMAP(0) */
+ lsr x1, x1, #(SECOND_SHIFT - 3) /* x1 := Slot for FIXMAP(0) */
str x2, [x4, x1] /* Map it in the fixmap's slot */
/* Use a virtual address to access the UART. */
@@ -375,12 +545,13 @@ paging:
/* Map the DTB in the boot misc slot */
cbnz x22, 1f /* Only on boot CPU */
- lsr x2, x21, #21
- lsl x2, x2, #21 /* x2 := 2MB-aligned paddr of DTB */
+ ldr x4, =boot_second /* x4 := vaddr (boot_second) */
+ lsr x2, x21, #SECOND_SHIFT
+ lsl x2, x2, #SECOND_SHIFT /* x2 := 2MB-aligned paddr of DTB */
mov x3, #PT_MEM /* x2 := 2MB RAM incl. DTB */
orr x2, x2, x3
ldr x1, =BOOT_FDT_VIRT_START
- lsr x1, x1, #18 /* x4 := Slot for BOOT_FDT_VIRT_START */
+ lsr x1, x1, #(SECOND_SHIFT - 3) /* x4 := Slot for BOOT_FDT_VIRT_START */
str x2, [x4, x1] /* Map it in the early fdt slot */
1:
@@ -428,12 +599,13 @@ launch:
cbz x22, start_xen /* and disappear into the land of C */
b start_secondary /* (to the appropriate entry point) */
-/* Fail-stop
- * r0: string explaining why */
+/* Fail-stop */
fail: PRINT("- Boot failed -\r\n")
1: wfe
b 1b
+GLOBAL(_end_boot)
+
/* Copy Xen to new location and switch TTBR
* x0 ttbr
* x1 source address
@@ -500,7 +672,7 @@ ENTRY(relocate_xen)
ret
-#ifdef EARLY_PRINTK
+#ifdef CONFIG_EARLY_PRINTK
/* Bring up the UART.
* x23: Early UART base address
* Clobbers x0-x1 */
@@ -547,15 +719,71 @@ putn:
hex: .ascii "0123456789abcdef"
.align 2
-#else /* EARLY_PRINTK */
+#else /* CONFIG_EARLY_PRINTK */
+ENTRY(early_puts)
init_uart:
-.global early_puts
-early_puts:
puts:
putn: ret
-#endif /* EARLY_PRINTK */
+#endif /* !CONFIG_EARLY_PRINTK */
+
+/* This provides a C-API version of __lookup_processor_type
+ * TODO: For now, the implementation return NULL every time
+ */
+ENTRY(lookup_processor_type)
+ mov x0, #0
+ ret
+/*
+ * Function to transition from EFI loader in C, to Xen entry point.
+ * void noreturn efi_xen_start(void *fdt_ptr, uint32_t fdt_size);
+ */
+ENTRY(efi_xen_start)
+ /*
+ * Preserve x0 (fdt pointer) across call to __flush_dcache_area,
+ * restore for entry into Xen.
+ */
+ mov x20, x0
+
+ /* flush dcache covering the FDT updated by EFI boot code */
+ bl __flush_dcache_area
+
+ /*
+ * Flush dcache covering current runtime addresses
+ * of xen text/data. Then flush all of icache.
+ */
+ adrp x1, _start
+ add x1, x1, #:lo12:_start
+ mov x0, x1
+ adrp x2, _end
+ add x2, x2, #:lo12:_end
+ sub x1, x2, x1
+
+ bl __flush_dcache_area
+ ic ialluis
+ tlbi alle2
+
+ /*
+ * Turn off cache and MMU as Xen expects. EFI enables them, but also
+ * mandates a 1:1 (unity) VA->PA mapping, so we can turn off the
+ * MMU while executing EFI code before entering Xen.
+ * The EFI loader calls this to start Xen.
+ */
+
+ /* Turn off Dcache and MMU */
+ mrs x0, sctlr_el2
+ bic x0, x0, #1 << 0 /* clear SCTLR.M */
+ bic x0, x0, #1 << 2 /* clear SCTLR.C */
+ msr sctlr_el2, x0
+ isb
+
+ /* Jump to Xen entry point */
+ mov x0, x20
+ mov x1, xzr
+ mov x2, xzr
+ mov x3, xzr
+ b real_start
+ENDPROC(efi_xen_start)
/*
* Local variables:
diff --git a/xen/arch/arm/arm64/lib/Makefile b/xen/arch/arm/arm64/lib/Makefile
index 32c02c4..1b9c7a9 100644
--- a/xen/arch/arm/arm64/lib/Makefile
+++ b/xen/arch/arm/arm64/lib/Makefile
@@ -1 +1,4 @@
+obj-y += memcpy.o memcmp.o memmove.o memset.o memchr.o
+obj-y += clear_page.o
obj-y += bitops.o find_next_bit.o
+obj-y += strchr.o strcmp.o strlen.o strncmp.o strnlen.o strrchr.o
diff --git a/xen/arch/arm/arm64/lib/assembler.h b/xen/arch/arm/arm64/lib/assembler.h
new file mode 100644
index 0000000..3f9c0dc
--- /dev/null
+++ b/xen/arch/arm/arm64/lib/assembler.h
@@ -0,0 +1,12 @@
+#ifndef __ASM_ASSEMBLER_H__
+#define __ASM_ASSEMBLER_H__
+
+#ifndef __ASSEMBLY__
+#error "Only include this from assembly code"
+#endif
+
+/* Only LE support so far */
+#define CPU_BE(x...)
+#define CPU_LE(x...) x
+
+#endif /* __ASM_ASSEMBLER_H__ */
diff --git a/xen/arch/arm/arm64/lib/bitops.S b/xen/arch/arm/arm64/lib/bitops.S
index 80cc903..e1ad239 100644
--- a/xen/arch/arm/arm64/lib/bitops.S
+++ b/xen/arch/arm/arm64/lib/bitops.S
@@ -46,11 +46,12 @@ ENTRY( \name )
mov x2, #1
add x1, x1, x0, lsr #3 // Get word offset
lsl x4, x2, x3 // Create mask
-1: ldaxr w2, [x1]
+1: ldxr w2, [x1]
lsr w0, w2, w3 // Save old value of bit
\instr w2, w2, w4 // toggle bit
stlxr w5, w2, [x1]
cbnz w5, 1b
+ dmb ish
and w0, w0, #1
3: ret
ENDPROC(\name )
diff --git a/xen/arch/arm/arm64/lib/clear_page.S b/xen/arch/arm/arm64/lib/clear_page.S
new file mode 100644
index 0000000..8d5cadb
--- /dev/null
+++ b/xen/arch/arm/arm64/lib/clear_page.S
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/config.h>
+
+/*
+ * Clear page @dest
+ *
+ * Parameters:
+ * x0 - dest
+ */
+ENTRY(clear_page)
+ mrs x1, dczid_el0
+ and w1, w1, #0xf
+ mov x2, #4
+ lsl x1, x2, x1
+
+1: dc zva, x0
+ add x0, x0, x1
+ tst x0, #(PAGE_SIZE - 1)
+ b.ne 1b
+ ret
+ENDPROC(clear_page)
diff --git a/xen/arch/arm/arm64/lib/memchr.S b/xen/arch/arm/arm64/lib/memchr.S
new file mode 100644
index 0000000..b04590c
--- /dev/null
+++ b/xen/arch/arm/arm64/lib/memchr.S
@@ -0,0 +1,44 @@
+/*
+ * Based on arch/arm/lib/memchr.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ * Copyright (C) 2013 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/config.h>
+#include "assembler.h"
+
+/*
+ * Find a character in an area of memory.
+ *
+ * Parameters:
+ * x0 - buf
+ * x1 - c
+ * x2 - n
+ * Returns:
+ * x0 - address of first occurrence of 'c' or 0
+ */
+ENTRY(memchr)
+ and w1, w1, #0xff
+1: subs x2, x2, #1
+ b.mi 2f
+ ldrb w3, [x0], #1
+ cmp w3, w1
+ b.ne 1b
+ sub x0, x0, #1
+ ret
+2: mov x0, #0
+ ret
+ENDPROC(memchr)
diff --git a/xen/arch/arm/arm64/lib/memcmp.S b/xen/arch/arm/arm64/lib/memcmp.S
new file mode 100644
index 0000000..9aad925
--- /dev/null
+++ b/xen/arch/arm/arm64/lib/memcmp.S
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2013 ARM Ltd.
+ * Copyright (C) 2013 Linaro.
+ *
+ * This code is based on glibc cortex strings work originally authored by Linaro
+ * and re-licensed under GPLv2 for the Linux kernel. The original code can
+ * be found @
+ *
+ * http://bazaar.launchpad.net/~linaro-toolchain-dev/cortex-strings/trunk/
+ * files/head:/src/aarch64/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/config.h>
+#include "assembler.h"
+
+/*
+* compare memory areas(when two memory areas' offset are different,
+* alignment handled by the hardware)
+*
+* Parameters:
+* x0 - const memory area 1 pointer
+* x1 - const memory area 2 pointer
+* x2 - the maximal compare byte length
+* Returns:
+* x0 - a compare result, maybe less than, equal to, or greater than ZERO
+*/
+
+/* Parameters and result. */
+src1 .req x0
+src2 .req x1
+limit .req x2
+result .req x0
+
+/* Internal variables. */
+data1 .req x3
+data1w .req w3
+data2 .req x4
+data2w .req w4
+has_nul .req x5
+diff .req x6
+endloop .req x7
+tmp1 .req x8
+tmp2 .req x9
+tmp3 .req x10
+pos .req x11
+limit_wd .req x12
+mask .req x13
+
+ENTRY(memcmp)
+ cbz limit, .Lret0
+ eor tmp1, src1, src2
+ tst tmp1, #7
+ b.ne .Lmisaligned8
+ ands tmp1, src1, #7
+ b.ne .Lmutual_align
+ sub limit_wd, limit, #1 /* limit != 0, so no underflow. */
+ lsr limit_wd, limit_wd, #3 /* Convert to Dwords. */
+ /*
+ * The input source addresses are at alignment boundary.
+ * Directly compare eight bytes each time.
+ */
+.Lloop_aligned:
+ ldr data1, [src1], #8
+ ldr data2, [src2], #8
+.Lstart_realigned:
+ subs limit_wd, limit_wd, #1
+ eor diff, data1, data2 /* Non-zero if differences found. */
+ csinv endloop, diff, xzr, cs /* Last Dword or differences. */
+ cbz endloop, .Lloop_aligned
+
+ /* Not reached the limit, must have found a diff. */
+ tbz limit_wd, #63, .Lnot_limit
+
+ /* Limit % 8 == 0 => the diff is in the last 8 bytes. */
+ ands limit, limit, #7
+ b.eq .Lnot_limit
+ /*
+ * The remained bytes less than 8. It is needed to extract valid data
+ * from last eight bytes of the intended memory range.
+ */
+ lsl limit, limit, #3 /* bytes-> bits. */
+ mov mask, #~0
+CPU_BE( lsr mask, mask, limit )
+CPU_LE( lsl mask, mask, limit )
+ bic data1, data1, mask
+ bic data2, data2, mask
+
+ orr diff, diff, mask
+ b .Lnot_limit
+
+.Lmutual_align:
+ /*
+ * Sources are mutually aligned, but are not currently at an
+ * alignment boundary. Round down the addresses and then mask off
+ * the bytes that precede the start point.
+ */
+ bic src1, src1, #7
+ bic src2, src2, #7
+ ldr data1, [src1], #8
+ ldr data2, [src2], #8
+ /*
+ * We can not add limit with alignment offset(tmp1) here. Since the
+ * addition probably make the limit overflown.
+ */
+ sub limit_wd, limit, #1/*limit != 0, so no underflow.*/
+ and tmp3, limit_wd, #7
+ lsr limit_wd, limit_wd, #3
+ add tmp3, tmp3, tmp1
+ add limit_wd, limit_wd, tmp3, lsr #3
+ add limit, limit, tmp1/* Adjust the limit for the extra. */
+
+ lsl tmp1, tmp1, #3/* Bytes beyond alignment -> bits.*/
+ neg tmp1, tmp1/* Bits to alignment -64. */
+ mov tmp2, #~0
+ /*mask off the non-intended bytes before the start address.*/
+CPU_BE( lsl tmp2, tmp2, tmp1 )/*Big-endian.Early bytes are at MSB*/
+ /* Little-endian. Early bytes are at LSB. */
+CPU_LE( lsr tmp2, tmp2, tmp1 )
+
+ orr data1, data1, tmp2
+ orr data2, data2, tmp2
+ b .Lstart_realigned
+
+ /*src1 and src2 have different alignment offset.*/
+.Lmisaligned8:
+ cmp limit, #8
+ b.lo .Ltiny8proc /*limit < 8: compare byte by byte*/
+
+ and tmp1, src1, #7
+ neg tmp1, tmp1
+ add tmp1, tmp1, #8/*valid length in the first 8 bytes of src1*/
+ and tmp2, src2, #7
+ neg tmp2, tmp2
+ add tmp2, tmp2, #8/*valid length in the first 8 bytes of src2*/
+ subs tmp3, tmp1, tmp2
+ csel pos, tmp1, tmp2, hi /*Choose the maximum.*/
+
+ sub limit, limit, pos
+ /*compare the proceeding bytes in the first 8 byte segment.*/
+.Ltinycmp:
+ ldrb data1w, [src1], #1
+ ldrb data2w, [src2], #1
+ subs pos, pos, #1
+ ccmp data1w, data2w, #0, ne /* NZCV = 0b0000. */
+ b.eq .Ltinycmp
+ cbnz pos, 1f /*diff occurred before the last byte.*/
+ cmp data1w, data2w
+ b.eq .Lstart_align
+1:
+ sub result, data1, data2
+ ret
+
+.Lstart_align:
+ lsr limit_wd, limit, #3
+ cbz limit_wd, .Lremain8
+
+ ands xzr, src1, #7
+ b.eq .Lrecal_offset
+ /*process more leading bytes to make src1 aligned...*/
+ add src1, src1, tmp3 /*backwards src1 to alignment boundary*/
+ add src2, src2, tmp3
+ sub limit, limit, tmp3
+ lsr limit_wd, limit, #3
+ cbz limit_wd, .Lremain8
+ /*load 8 bytes from aligned SRC1..*/
+ ldr data1, [src1], #8
+ ldr data2, [src2], #8
+
+ subs limit_wd, limit_wd, #1
+ eor diff, data1, data2 /*Non-zero if differences found.*/
+ csinv endloop, diff, xzr, ne
+ cbnz endloop, .Lunequal_proc
+ /*How far is the current SRC2 from the alignment boundary...*/
+ and tmp3, tmp3, #7
+
+.Lrecal_offset:/*src1 is aligned now..*/
+ neg pos, tmp3
+.Lloopcmp_proc:
+ /*
+ * Divide the eight bytes into two parts. First,backwards the src2
+ * to an alignment boundary,load eight bytes and compare from
+ * the SRC2 alignment boundary. If all 8 bytes are equal,then start
+ * the second part's comparison. Otherwise finish the comparison.
+ * This special handle can garantee all the accesses are in the
+ * thread/task space in avoid to overrange access.
+ */
+ ldr data1, [src1,pos]
+ ldr data2, [src2,pos]
+ eor diff, data1, data2 /* Non-zero if differences found. */
+ cbnz diff, .Lnot_limit
+
+ /*The second part process*/
+ ldr data1, [src1], #8
+ ldr data2, [src2], #8
+ eor diff, data1, data2 /* Non-zero if differences found. */
+ subs limit_wd, limit_wd, #1
+ csinv endloop, diff, xzr, ne/*if limit_wd is 0,will finish the cmp*/
+ cbz endloop, .Lloopcmp_proc
+.Lunequal_proc:
+ cbz diff, .Lremain8
+
+/*There is differnence occured in the latest comparison.*/
+.Lnot_limit:
+/*
+* For little endian,reverse the low significant equal bits into MSB,then
+* following CLZ can find how many equal bits exist.
+*/
+CPU_LE( rev diff, diff )
+CPU_LE( rev data1, data1 )
+CPU_LE( rev data2, data2 )
+
+ /*
+ * The MS-non-zero bit of DIFF marks either the first bit
+ * that is different, or the end of the significant data.
+ * Shifting left now will bring the critical information into the
+ * top bits.
+ */
+ clz pos, diff
+ lsl data1, data1, pos
+ lsl data2, data2, pos
+ /*
+ * We need to zero-extend (char is unsigned) the value and then
+ * perform a signed subtraction.
+ */
+ lsr data1, data1, #56
+ sub result, data1, data2, lsr #56
+ ret
+
+.Lremain8:
+ /* Limit % 8 == 0 =>. all data are equal.*/
+ ands limit, limit, #7
+ b.eq .Lret0
+
+.Ltiny8proc:
+ ldrb data1w, [src1], #1
+ ldrb data2w, [src2], #1
+ subs limit, limit, #1
+
+ ccmp data1w, data2w, #0, ne /* NZCV = 0b0000. */
+ b.eq .Ltiny8proc
+ sub result, data1, data2
+ ret
+.Lret0:
+ mov result, #0
+ ret
+ENDPROC(memcmp)
diff --git a/xen/arch/arm/arm64/lib/memcpy.S b/xen/arch/arm/arm64/lib/memcpy.S
new file mode 100644
index 0000000..7cc885d
--- /dev/null
+++ b/xen/arch/arm/arm64/lib/memcpy.S
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2013 ARM Ltd.
+ * Copyright (C) 2013 Linaro.
+ *
+ * This code is based on glibc cortex strings work originally authored by Linaro
+ * and re-licensed under GPLv2 for the Linux kernel. The original code can
+ * be found @
+ *
+ * http://bazaar.launchpad.net/~linaro-toolchain-dev/cortex-strings/trunk/
+ * files/head:/src/aarch64/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/config.h>
+#include <asm/cache.h>
+#include "assembler.h"
+
+/*
+ * Copy a buffer from src to dest (alignment handled by the hardware)
+ *
+ * Parameters:
+ * x0 - dest
+ * x1 - src
+ * x2 - n
+ * Returns:
+ * x0 - dest
+ */
+dstin .req x0
+src .req x1
+count .req x2
+tmp1 .req x3
+tmp1w .req w3
+tmp2 .req x4
+tmp2w .req w4
+tmp3 .req x5
+tmp3w .req w5
+dst .req x6
+
+A_l .req x7
+A_h .req x8
+B_l .req x9
+B_h .req x10
+C_l .req x11
+C_h .req x12
+D_l .req x13
+D_h .req x14
+
+ENTRY(memcpy)
+ mov dst, dstin
+ cmp count, #16
+ /*When memory length is less than 16, the accessed are not aligned.*/
+ b.lo .Ltiny15
+
+ neg tmp2, src
+ ands tmp2, tmp2, #15/* Bytes to reach alignment. */
+ b.eq .LSrcAligned
+ sub count, count, tmp2
+ /*
+ * Copy the leading memory data from src to dst in an increasing
+ * address order.By this way,the risk of overwritting the source
+ * memory data is eliminated when the distance between src and
+ * dst is less than 16. The memory accesses here are alignment.
+ */
+ tbz tmp2, #0, 1f
+ ldrb tmp1w, [src], #1
+ strb tmp1w, [dst], #1
+1:
+ tbz tmp2, #1, 2f
+ ldrh tmp1w, [src], #2
+ strh tmp1w, [dst], #2
+2:
+ tbz tmp2, #2, 3f
+ ldr tmp1w, [src], #4
+ str tmp1w, [dst], #4
+3:
+ tbz tmp2, #3, .LSrcAligned
+ ldr tmp1, [src],#8
+ str tmp1, [dst],#8
+
+.LSrcAligned:
+ cmp count, #64
+ b.ge .Lcpy_over64
+ /*
+ * Deal with small copies quickly by dropping straight into the
+ * exit block.
+ */
+.Ltail63:
+ /*
+ * Copy up to 48 bytes of data. At this point we only need the
+ * bottom 6 bits of count to be accurate.
+ */
+ ands tmp1, count, #0x30
+ b.eq .Ltiny15
+ cmp tmp1w, #0x20
+ b.eq 1f
+ b.lt 2f
+ ldp A_l, A_h, [src], #16
+ stp A_l, A_h, [dst], #16
+1:
+ ldp A_l, A_h, [src], #16
+ stp A_l, A_h, [dst], #16
+2:
+ ldp A_l, A_h, [src], #16
+ stp A_l, A_h, [dst], #16
+.Ltiny15:
+ /*
+ * Prefer to break one ldp/stp into several load/store to access
+ * memory in an increasing address order,rather than to load/store 16
+ * bytes from (src-16) to (dst-16) and to backward the src to aligned
+ * address,which way is used in original cortex memcpy. If keeping
+ * the original memcpy process here, memmove need to satisfy the
+ * precondition that src address is at least 16 bytes bigger than dst
+ * address,otherwise some source data will be overwritten when memove
+ * call memcpy directly. To make memmove simpler and decouple the
+ * memcpy's dependency on memmove, withdrew the original process.
+ */
+ tbz count, #3, 1f
+ ldr tmp1, [src], #8
+ str tmp1, [dst], #8
+1:
+ tbz count, #2, 2f
+ ldr tmp1w, [src], #4
+ str tmp1w, [dst], #4
+2:
+ tbz count, #1, 3f
+ ldrh tmp1w, [src], #2
+ strh tmp1w, [dst], #2
+3:
+ tbz count, #0, .Lexitfunc
+ ldrb tmp1w, [src]
+ strb tmp1w, [dst]
+
+.Lexitfunc:
+ ret
+
+.Lcpy_over64:
+ subs count, count, #128
+ b.ge .Lcpy_body_large
+ /*
+ * Less than 128 bytes to copy, so handle 64 here and then jump
+ * to the tail.
+ */
+ ldp A_l, A_h, [src],#16
+ stp A_l, A_h, [dst],#16
+ ldp B_l, B_h, [src],#16
+ ldp C_l, C_h, [src],#16
+ stp B_l, B_h, [dst],#16
+ stp C_l, C_h, [dst],#16
+ ldp D_l, D_h, [src],#16
+ stp D_l, D_h, [dst],#16
+
+ tst count, #0x3f
+ b.ne .Ltail63
+ ret
+
+ /*
+ * Critical loop. Start at a new cache line boundary. Assuming
+ * 64 bytes per line this ensures the entire loop is in one line.
+ */
+ .p2align L1_CACHE_SHIFT
+.Lcpy_body_large:
+ /* pre-get 64 bytes data. */
+ ldp A_l, A_h, [src],#16
+ ldp B_l, B_h, [src],#16
+ ldp C_l, C_h, [src],#16
+ ldp D_l, D_h, [src],#16
+1:
+ /*
+ * interlace the load of next 64 bytes data block with store of the last
+ * loaded 64 bytes data.
+ */
+ stp A_l, A_h, [dst],#16
+ ldp A_l, A_h, [src],#16
+ stp B_l, B_h, [dst],#16
+ ldp B_l, B_h, [src],#16
+ stp C_l, C_h, [dst],#16
+ ldp C_l, C_h, [src],#16
+ stp D_l, D_h, [dst],#16
+ ldp D_l, D_h, [src],#16
+ subs count, count, #64
+ b.ge 1b
+ stp A_l, A_h, [dst],#16
+ stp B_l, B_h, [dst],#16
+ stp C_l, C_h, [dst],#16
+ stp D_l, D_h, [dst],#16
+
+ tst count, #0x3f
+ b.ne .Ltail63
+ ret
+ENDPROC(memcpy)
diff --git a/xen/arch/arm/arm64/lib/memmove.S b/xen/arch/arm/arm64/lib/memmove.S
new file mode 100644
index 0000000..f4065b9
--- /dev/null
+++ b/xen/arch/arm/arm64/lib/memmove.S
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2013 ARM Ltd.
+ * Copyright (C) 2013 Linaro.
+ *
+ * This code is based on glibc cortex strings work originally authored by Linaro
+ * and re-licensed under GPLv2 for the Linux kernel. The original code can
+ * be found @
+ *
+ * http://bazaar.launchpad.net/~linaro-toolchain-dev/cortex-strings/trunk/
+ * files/head:/src/aarch64/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/config.h>
+#include <asm/cache.h>
+#include "assembler.h"
+
+/*
+ * Move a buffer from src to test (alignment handled by the hardware).
+ * If dest <= src, call memcpy, otherwise copy in reverse order.
+ *
+ * Parameters:
+ * x0 - dest
+ * x1 - src
+ * x2 - n
+ * Returns:
+ * x0 - dest
+ */
+dstin .req x0
+src .req x1
+count .req x2
+tmp1 .req x3
+tmp1w .req w3
+tmp2 .req x4
+tmp2w .req w4
+tmp3 .req x5
+tmp3w .req w5
+dst .req x6
+
+A_l .req x7
+A_h .req x8
+B_l .req x9
+B_h .req x10
+C_l .req x11
+C_h .req x12
+D_l .req x13
+D_h .req x14
+
+ENTRY(memmove)
+ cmp dstin, src
+ b.lo memcpy
+ add tmp1, src, count
+ cmp dstin, tmp1
+ b.hs memcpy /* No overlap. */
+
+ add dst, dstin, count
+ add src, src, count
+ cmp count, #16
+ b.lo .Ltail15 /*probably non-alignment accesses.*/
+
+ ands tmp2, src, #15 /* Bytes to reach alignment. */
+ b.eq .LSrcAligned
+ sub count, count, tmp2
+ /*
+ * process the aligned offset length to make the src aligned firstly.
+ * those extra instructions' cost is acceptable. It also make the
+ * coming accesses are based on aligned address.
+ */
+ tbz tmp2, #0, 1f
+ ldrb tmp1w, [src, #-1]!
+ strb tmp1w, [dst, #-1]!
+1:
+ tbz tmp2, #1, 2f
+ ldrh tmp1w, [src, #-2]!
+ strh tmp1w, [dst, #-2]!
+2:
+ tbz tmp2, #2, 3f
+ ldr tmp1w, [src, #-4]!
+ str tmp1w, [dst, #-4]!
+3:
+ tbz tmp2, #3, .LSrcAligned
+ ldr tmp1, [src, #-8]!
+ str tmp1, [dst, #-8]!
+
+.LSrcAligned:
+ cmp count, #64
+ b.ge .Lcpy_over64
+
+ /*
+ * Deal with small copies quickly by dropping straight into the
+ * exit block.
+ */
+.Ltail63:
+ /*
+ * Copy up to 48 bytes of data. At this point we only need the
+ * bottom 6 bits of count to be accurate.
+ */
+ ands tmp1, count, #0x30
+ b.eq .Ltail15
+ cmp tmp1w, #0x20
+ b.eq 1f
+ b.lt 2f
+ ldp A_l, A_h, [src, #-16]!
+ stp A_l, A_h, [dst, #-16]!
+1:
+ ldp A_l, A_h, [src, #-16]!
+ stp A_l, A_h, [dst, #-16]!
+2:
+ ldp A_l, A_h, [src, #-16]!
+ stp A_l, A_h, [dst, #-16]!
+
+.Ltail15:
+ tbz count, #3, 1f
+ ldr tmp1, [src, #-8]!
+ str tmp1, [dst, #-8]!
+1:
+ tbz count, #2, 2f
+ ldr tmp1w, [src, #-4]!
+ str tmp1w, [dst, #-4]!
+2:
+ tbz count, #1, 3f
+ ldrh tmp1w, [src, #-2]!
+ strh tmp1w, [dst, #-2]!
+3:
+ tbz count, #0, .Lexitfunc
+ ldrb tmp1w, [src, #-1]
+ strb tmp1w, [dst, #-1]
+
+.Lexitfunc:
+ ret
+
+.Lcpy_over64:
+ subs count, count, #128
+ b.ge .Lcpy_body_large
+ /*
+ * Less than 128 bytes to copy, so handle 64 bytes here and then jump
+ * to the tail.
+ */
+ ldp A_l, A_h, [src, #-16]
+ stp A_l, A_h, [dst, #-16]
+ ldp B_l, B_h, [src, #-32]
+ ldp C_l, C_h, [src, #-48]
+ stp B_l, B_h, [dst, #-32]
+ stp C_l, C_h, [dst, #-48]
+ ldp D_l, D_h, [src, #-64]!
+ stp D_l, D_h, [dst, #-64]!
+
+ tst count, #0x3f
+ b.ne .Ltail63
+ ret
+
+ /*
+ * Critical loop. Start at a new cache line boundary. Assuming
+ * 64 bytes per line this ensures the entire loop is in one line.
+ */
+ .p2align L1_CACHE_SHIFT
+.Lcpy_body_large:
+ /* pre-load 64 bytes data. */
+ ldp A_l, A_h, [src, #-16]
+ ldp B_l, B_h, [src, #-32]
+ ldp C_l, C_h, [src, #-48]
+ ldp D_l, D_h, [src, #-64]!
+1:
+ /*
+ * interlace the load of next 64 bytes data block with store of the last
+ * loaded 64 bytes data.
+ */
+ stp A_l, A_h, [dst, #-16]
+ ldp A_l, A_h, [src, #-16]
+ stp B_l, B_h, [dst, #-32]
+ ldp B_l, B_h, [src, #-32]
+ stp C_l, C_h, [dst, #-48]
+ ldp C_l, C_h, [src, #-48]
+ stp D_l, D_h, [dst, #-64]!
+ ldp D_l, D_h, [src, #-64]!
+ subs count, count, #64
+ b.ge 1b
+ stp A_l, A_h, [dst, #-16]
+ stp B_l, B_h, [dst, #-32]
+ stp C_l, C_h, [dst, #-48]
+ stp D_l, D_h, [dst, #-64]!
+
+ tst count, #0x3f
+ b.ne .Ltail63
+ ret
+ENDPROC(memmove)
diff --git a/xen/arch/arm/arm64/lib/memset.S b/xen/arch/arm/arm64/lib/memset.S
new file mode 100644
index 0000000..4ee714d
--- /dev/null
+++ b/xen/arch/arm/arm64/lib/memset.S
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2013 ARM Ltd.
+ * Copyright (C) 2013 Linaro.
+ *
+ * This code is based on glibc cortex strings work originally authored by Linaro
+ * and re-licensed under GPLv2 for the Linux kernel. The original code can
+ * be found @
+ *
+ * http://bazaar.launchpad.net/~linaro-toolchain-dev/cortex-strings/trunk/
+ * files/head:/src/aarch64/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/config.h>
+#include <asm/cache.h>
+#include "assembler.h"
+
+/*
+ * Fill in the buffer with character c (alignment handled by the hardware)
+ *
+ * Parameters:
+ * x0 - buf
+ * x1 - c
+ * x2 - n
+ * Returns:
+ * x0 - buf
+ */
+
+dstin .req x0
+val .req w1
+count .req x2
+tmp1 .req x3
+tmp1w .req w3
+tmp2 .req x4
+tmp2w .req w4
+zva_len_x .req x5
+zva_len .req w5
+zva_bits_x .req x6
+
+A_l .req x7
+A_lw .req w7
+dst .req x8
+tmp3w .req w9
+tmp3 .req x9
+
+ENTRY(memset)
+ mov dst, dstin /* Preserve return value. */
+ and A_lw, val, #255
+ orr A_lw, A_lw, A_lw, lsl #8
+ orr A_lw, A_lw, A_lw, lsl #16
+ orr A_l, A_l, A_l, lsl #32
+
+ cmp count, #15
+ b.hi .Lover16_proc
+ /*All store maybe are non-aligned..*/
+ tbz count, #3, 1f
+ str A_l, [dst], #8
+1:
+ tbz count, #2, 2f
+ str A_lw, [dst], #4
+2:
+ tbz count, #1, 3f
+ strh A_lw, [dst], #2
+3:
+ tbz count, #0, 4f
+ strb A_lw, [dst]
+4:
+ ret
+
+.Lover16_proc:
+ /*Whether the start address is aligned with 16.*/
+ neg tmp2, dst
+ ands tmp2, tmp2, #15
+ b.eq .Laligned
+/*
+* The count is not less than 16, we can use stp to store the start 16 bytes,
+* then adjust the dst aligned with 16.This process will make the current
+* memory address at alignment boundary.
+*/
+ stp A_l, A_l, [dst] /*non-aligned store..*/
+ /*make the dst aligned..*/
+ sub count, count, tmp2
+ add dst, dst, tmp2
+
+.Laligned:
+ cbz A_l, .Lzero_mem
+
+.Ltail_maybe_long:
+ cmp count, #64
+ b.ge .Lnot_short
+.Ltail63:
+ ands tmp1, count, #0x30
+ b.eq 3f
+ cmp tmp1w, #0x20
+ b.eq 1f
+ b.lt 2f
+ stp A_l, A_l, [dst], #16
+1:
+ stp A_l, A_l, [dst], #16
+2:
+ stp A_l, A_l, [dst], #16
+/*
+* The last store length is less than 16,use stp to write last 16 bytes.
+* It will lead some bytes written twice and the access is non-aligned.
+*/
+3:
+ ands count, count, #15
+ cbz count, 4f
+ add dst, dst, count
+ stp A_l, A_l, [dst, #-16] /* Repeat some/all of last store. */
+4:
+ ret
+
+ /*
+ * Critical loop. Start at a new cache line boundary. Assuming
+ * 64 bytes per line, this ensures the entire loop is in one line.
+ */
+ .p2align L1_CACHE_SHIFT
+.Lnot_short:
+ sub dst, dst, #16/* Pre-bias. */
+ sub count, count, #64
+1:
+ stp A_l, A_l, [dst, #16]
+ stp A_l, A_l, [dst, #32]
+ stp A_l, A_l, [dst, #48]
+ stp A_l, A_l, [dst, #64]!
+ subs count, count, #64
+ b.ge 1b
+ tst count, #0x3f
+ add dst, dst, #16
+ b.ne .Ltail63
+.Lexitfunc:
+ ret
+
+ /*
+ * For zeroing memory, check to see if we can use the ZVA feature to
+ * zero entire 'cache' lines.
+ */
+.Lzero_mem:
+ cmp count, #63
+ b.le .Ltail63
+ /*
+ * For zeroing small amounts of memory, it's not worth setting up
+ * the line-clear code.
+ */
+ cmp count, #128
+ b.lt .Lnot_short /*count is at least 128 bytes*/
+
+ mrs tmp1, dczid_el0
+ tbnz tmp1, #4, .Lnot_short
+ mov tmp3w, #4
+ and zva_len, tmp1w, #15 /* Safety: other bits reserved. */
+ lsl zva_len, tmp3w, zva_len
+
+ ands tmp3w, zva_len, #63
+ /*
+ * ensure the zva_len is not less than 64.
+ * It is not meaningful to use ZVA if the block size is less than 64.
+ */
+ b.ne .Lnot_short
+.Lzero_by_line:
+ /*
+ * Compute how far we need to go to become suitably aligned. We're
+ * already at quad-word alignment.
+ */
+ cmp count, zva_len_x
+ b.lt .Lnot_short /* Not enough to reach alignment. */
+ sub zva_bits_x, zva_len_x, #1
+ neg tmp2, dst
+ ands tmp2, tmp2, zva_bits_x
+ b.eq 2f /* Already aligned. */
+ /* Not aligned, check that there's enough to copy after alignment.*/
+ sub tmp1, count, tmp2
+ /*
+ * grantee the remain length to be ZVA is bigger than 64,
+ * avoid to make the 2f's process over mem range.*/
+ cmp tmp1, #64
+ ccmp tmp1, zva_len_x, #8, ge /* NZCV=0b1000 */
+ b.lt .Lnot_short
+ /*
+ * We know that there's at least 64 bytes to zero and that it's safe
+ * to overrun by 64 bytes.
+ */
+ mov count, tmp1
+1:
+ stp A_l, A_l, [dst]
+ stp A_l, A_l, [dst, #16]
+ stp A_l, A_l, [dst, #32]
+ subs tmp2, tmp2, #64
+ stp A_l, A_l, [dst, #48]
+ add dst, dst, #64
+ b.ge 1b
+ /* We've overrun a bit, so adjust dst downwards.*/
+ add dst, dst, tmp2
+2:
+ sub count, count, zva_len_x
+3:
+ dc zva, dst
+ add dst, dst, zva_len_x
+ subs count, count, zva_len_x
+ b.ge 3b
+ ands count, count, zva_bits_x
+ b.ne .Ltail_maybe_long
+ ret
+ENDPROC(memset)
diff --git a/xen/arch/arm/arm64/lib/strchr.S b/xen/arch/arm/arm64/lib/strchr.S
new file mode 100644
index 0000000..9e265e4
--- /dev/null
+++ b/xen/arch/arm/arm64/lib/strchr.S
@@ -0,0 +1,41 @@
+/*
+ * Based on arch/arm/lib/strchr.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ * Copyright (C) 2013 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/config.h>
+
+/*
+ * Find the first occurrence of a character in a string.
+ *
+ * Parameters:
+ * x0 - str
+ * x1 - c
+ * Returns:
+ * x0 - address of first occurrence of 'c' or 0
+ */
+ENTRY(strchr)
+ and w1, w1, #0xff
+1: ldrb w2, [x0], #1
+ cmp w2, w1
+ ccmp w2, wzr, #4, ne
+ b.ne 1b
+ sub x0, x0, #1
+ cmp w2, w1
+ csel x0, x0, xzr, eq
+ ret
+ENDPROC(strchr)
diff --git a/xen/arch/arm/arm64/lib/strcmp.S b/xen/arch/arm/arm64/lib/strcmp.S
new file mode 100644
index 0000000..bdcf7b0
--- /dev/null
+++ b/xen/arch/arm/arm64/lib/strcmp.S
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2013 ARM Ltd.
+ * Copyright (C) 2013 Linaro.
+ *
+ * This code is based on glibc cortex strings work originally authored by Linaro
+ * and re-licensed under GPLv2 for the Linux kernel. The original code can
+ * be found @
+ *
+ * http://bazaar.launchpad.net/~linaro-toolchain-dev/cortex-strings/trunk/
+ * files/head:/src/aarch64/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/config.h>
+
+#include "assembler.h"
+
+/*
+ * compare two strings
+ *
+ * Parameters:
+ * x0 - const string 1 pointer
+ * x1 - const string 2 pointer
+ * Returns:
+ * x0 - an integer less than, equal to, or greater than zero
+ * if s1 is found, respectively, to be less than, to match,
+ * or be greater than s2.
+ */
+
+#define REP8_01 0x0101010101010101
+#define REP8_7f 0x7f7f7f7f7f7f7f7f
+#define REP8_80 0x8080808080808080
+
+/* Parameters and result. */
+src1 .req x0
+src2 .req x1
+result .req x0
+
+/* Internal variables. */
+data1 .req x2
+data1w .req w2
+data2 .req x3
+data2w .req w3
+has_nul .req x4
+diff .req x5
+syndrome .req x6
+tmp1 .req x7
+tmp2 .req x8
+tmp3 .req x9
+zeroones .req x10
+pos .req x11
+
+ENTRY(strcmp)
+ eor tmp1, src1, src2
+ mov zeroones, #REP8_01
+ tst tmp1, #7
+ b.ne .Lmisaligned8
+ ands tmp1, src1, #7
+ b.ne .Lmutual_align
+
+ /*
+ * NUL detection works on the principle that (X - 1) & (~X) & 0x80
+ * (=> (X - 1) & ~(X | 0x7f)) is non-zero iff a byte is zero, and
+ * can be done in parallel across the entire word.
+ */
+.Lloop_aligned:
+ ldr data1, [src1], #8
+ ldr data2, [src2], #8
+.Lstart_realigned:
+ sub tmp1, data1, zeroones
+ orr tmp2, data1, #REP8_7f
+ eor diff, data1, data2 /* Non-zero if differences found. */
+ bic has_nul, tmp1, tmp2 /* Non-zero if NUL terminator. */
+ orr syndrome, diff, has_nul
+ cbz syndrome, .Lloop_aligned
+ b .Lcal_cmpresult
+
+.Lmutual_align:
+ /*
+ * Sources are mutually aligned, but are not currently at an
+ * alignment boundary. Round down the addresses and then mask off
+ * the bytes that preceed the start point.
+ */
+ bic src1, src1, #7
+ bic src2, src2, #7
+ lsl tmp1, tmp1, #3 /* Bytes beyond alignment -> bits. */
+ ldr data1, [src1], #8
+ neg tmp1, tmp1 /* Bits to alignment -64. */
+ ldr data2, [src2], #8
+ mov tmp2, #~0
+ /* Big-endian. Early bytes are at MSB. */
+CPU_BE( lsl tmp2, tmp2, tmp1 ) /* Shift (tmp1 & 63). */
+ /* Little-endian. Early bytes are at LSB. */
+CPU_LE( lsr tmp2, tmp2, tmp1 ) /* Shift (tmp1 & 63). */
+
+ orr data1, data1, tmp2
+ orr data2, data2, tmp2
+ b .Lstart_realigned
+
+.Lmisaligned8:
+ /*
+ * Get the align offset length to compare per byte first.
+ * After this process, one string's address will be aligned.
+ */
+ and tmp1, src1, #7
+ neg tmp1, tmp1
+ add tmp1, tmp1, #8
+ and tmp2, src2, #7
+ neg tmp2, tmp2
+ add tmp2, tmp2, #8
+ subs tmp3, tmp1, tmp2
+ csel pos, tmp1, tmp2, hi /*Choose the maximum. */
+.Ltinycmp:
+ ldrb data1w, [src1], #1
+ ldrb data2w, [src2], #1
+ subs pos, pos, #1
+ ccmp data1w, #1, #0, ne /* NZCV = 0b0000. */
+ ccmp data1w, data2w, #0, cs /* NZCV = 0b0000. */
+ b.eq .Ltinycmp
+ cbnz pos, 1f /*find the null or unequal...*/
+ cmp data1w, #1
+ ccmp data1w, data2w, #0, cs
+ b.eq .Lstart_align /*the last bytes are equal....*/
+1:
+ sub result, data1, data2
+ ret
+
+.Lstart_align:
+ ands xzr, src1, #7
+ b.eq .Lrecal_offset
+ /*process more leading bytes to make str1 aligned...*/
+ add src1, src1, tmp3
+ add src2, src2, tmp3
+ /*load 8 bytes from aligned str1 and non-aligned str2..*/
+ ldr data1, [src1], #8
+ ldr data2, [src2], #8
+
+ sub tmp1, data1, zeroones
+ orr tmp2, data1, #REP8_7f
+ bic has_nul, tmp1, tmp2
+ eor diff, data1, data2 /* Non-zero if differences found. */
+ orr syndrome, diff, has_nul
+ cbnz syndrome, .Lcal_cmpresult
+ /*How far is the current str2 from the alignment boundary...*/
+ and tmp3, tmp3, #7
+.Lrecal_offset:
+ neg pos, tmp3
+.Lloopcmp_proc:
+ /*
+ * Divide the eight bytes into two parts. First,backwards the src2
+ * to an alignment boundary,load eight bytes from the SRC2 alignment
+ * boundary,then compare with the relative bytes from SRC1.
+ * If all 8 bytes are equal,then start the second part's comparison.
+ * Otherwise finish the comparison.
+ * This special handle can garantee all the accesses are in the
+ * thread/task space in avoid to overrange access.
+ */
+ ldr data1, [src1,pos]
+ ldr data2, [src2,pos]
+ sub tmp1, data1, zeroones
+ orr tmp2, data1, #REP8_7f
+ bic has_nul, tmp1, tmp2
+ eor diff, data1, data2 /* Non-zero if differences found. */
+ orr syndrome, diff, has_nul
+ cbnz syndrome, .Lcal_cmpresult
+
+ /*The second part process*/
+ ldr data1, [src1], #8
+ ldr data2, [src2], #8
+ sub tmp1, data1, zeroones
+ orr tmp2, data1, #REP8_7f
+ bic has_nul, tmp1, tmp2
+ eor diff, data1, data2 /* Non-zero if differences found. */
+ orr syndrome, diff, has_nul
+ cbz syndrome, .Lloopcmp_proc
+
+.Lcal_cmpresult:
+ /*
+ * reversed the byte-order as big-endian,then CLZ can find the most
+ * significant zero bits.
+ */
+CPU_LE( rev syndrome, syndrome )
+CPU_LE( rev data1, data1 )
+CPU_LE( rev data2, data2 )
+
+ /*
+ * For big-endian we cannot use the trick with the syndrome value
+ * as carry-propagation can corrupt the upper bits if the trailing
+ * bytes in the string contain 0x01.
+ * However, if there is no NUL byte in the dword, we can generate
+ * the result directly. We ca not just subtract the bytes as the
+ * MSB might be significant.
+ */
+CPU_BE( cbnz has_nul, 1f )
+CPU_BE( cmp data1, data2 )
+CPU_BE( cset result, ne )
+CPU_BE( cneg result, result, lo )
+CPU_BE( ret )
+CPU_BE( 1: )
+ /*Re-compute the NUL-byte detection, using a byte-reversed value. */
+CPU_BE( rev tmp3, data1 )
+CPU_BE( sub tmp1, tmp3, zeroones )
+CPU_BE( orr tmp2, tmp3, #REP8_7f )
+CPU_BE( bic has_nul, tmp1, tmp2 )
+CPU_BE( rev has_nul, has_nul )
+CPU_BE( orr syndrome, diff, has_nul )
+
+ clz pos, syndrome
+ /*
+ * The MS-non-zero bit of the syndrome marks either the first bit
+ * that is different, or the top bit of the first zero byte.
+ * Shifting left now will bring the critical information into the
+ * top bits.
+ */
+ lsl data1, data1, pos
+ lsl data2, data2, pos
+ /*
+ * But we need to zero-extend (char is unsigned) the value and then
+ * perform a signed 32-bit subtraction.
+ */
+ lsr data1, data1, #56
+ sub result, data1, data2, lsr #56
+ ret
+ENDPROC(strcmp)
diff --git a/xen/arch/arm/arm64/lib/strlen.S b/xen/arch/arm/arm64/lib/strlen.S
new file mode 100644
index 0000000..ee055a2
--- /dev/null
+++ b/xen/arch/arm/arm64/lib/strlen.S
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2013 ARM Ltd.
+ * Copyright (C) 2013 Linaro.
+ *
+ * This code is based on glibc cortex strings work originally authored by Linaro
+ * and re-licensed under GPLv2 for the Linux kernel. The original code can
+ * be found @
+ *
+ * http://bazaar.launchpad.net/~linaro-toolchain-dev/cortex-strings/trunk/
+ * files/head:/src/aarch64/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/config.h>
+
+#include "assembler.h"
+
+
+/*
+ * calculate the length of a string
+ *
+ * Parameters:
+ * x0 - const string pointer
+ * Returns:
+ * x0 - the return length of specific string
+ */
+
+/* Arguments and results. */
+srcin .req x0
+len .req x0
+
+/* Locals and temporaries. */
+src .req x1
+data1 .req x2
+data2 .req x3
+data2a .req x4
+has_nul1 .req x5
+has_nul2 .req x6
+tmp1 .req x7
+tmp2 .req x8
+tmp3 .req x9
+tmp4 .req x10
+zeroones .req x11
+pos .req x12
+
+#define REP8_01 0x0101010101010101
+#define REP8_7f 0x7f7f7f7f7f7f7f7f
+#define REP8_80 0x8080808080808080
+
+ENTRY(strlen)
+ mov zeroones, #REP8_01
+ bic src, srcin, #15
+ ands tmp1, srcin, #15
+ b.ne .Lmisaligned
+ /*
+ * NUL detection works on the principle that (X - 1) & (~X) & 0x80
+ * (=> (X - 1) & ~(X | 0x7f)) is non-zero iff a byte is zero, and
+ * can be done in parallel across the entire word.
+ */
+ /*
+ * The inner loop deals with two Dwords at a time. This has a
+ * slightly higher start-up cost, but we should win quite quickly,
+ * especially on cores with a high number of issue slots per
+ * cycle, as we get much better parallelism out of the operations.
+ */
+.Lloop:
+ ldp data1, data2, [src], #16
+.Lrealigned:
+ sub tmp1, data1, zeroones
+ orr tmp2, data1, #REP8_7f
+ sub tmp3, data2, zeroones
+ orr tmp4, data2, #REP8_7f
+ bic has_nul1, tmp1, tmp2
+ bics has_nul2, tmp3, tmp4
+ ccmp has_nul1, #0, #0, eq /* NZCV = 0000 */
+ b.eq .Lloop
+
+ sub len, src, srcin
+ cbz has_nul1, .Lnul_in_data2
+CPU_BE( mov data2, data1 ) /*prepare data to re-calculate the syndrome*/
+ sub len, len, #8
+ mov has_nul2, has_nul1
+.Lnul_in_data2:
+ /*
+ * For big-endian, carry propagation (if the final byte in the
+ * string is 0x01) means we cannot use has_nul directly. The
+ * easiest way to get the correct byte is to byte-swap the data
+ * and calculate the syndrome a second time.
+ */
+CPU_BE( rev data2, data2 )
+CPU_BE( sub tmp1, data2, zeroones )
+CPU_BE( orr tmp2, data2, #REP8_7f )
+CPU_BE( bic has_nul2, tmp1, tmp2 )
+
+ sub len, len, #8
+ rev has_nul2, has_nul2
+ clz pos, has_nul2
+ add len, len, pos, lsr #3 /* Bits to bytes. */
+ ret
+
+.Lmisaligned:
+ cmp tmp1, #8
+ neg tmp1, tmp1
+ ldp data1, data2, [src], #16
+ lsl tmp1, tmp1, #3 /* Bytes beyond alignment -> bits. */
+ mov tmp2, #~0
+ /* Big-endian. Early bytes are at MSB. */
+CPU_BE( lsl tmp2, tmp2, tmp1 ) /* Shift (tmp1 & 63). */
+ /* Little-endian. Early bytes are at LSB. */
+CPU_LE( lsr tmp2, tmp2, tmp1 ) /* Shift (tmp1 & 63). */
+
+ orr data1, data1, tmp2
+ orr data2a, data2, tmp2
+ csinv data1, data1, xzr, le
+ csel data2, data2, data2a, le
+ b .Lrealigned
+ENDPROC(strlen)
diff --git a/xen/arch/arm/arm64/lib/strncmp.S b/xen/arch/arm/arm64/lib/strncmp.S
new file mode 100644
index 0000000..ca2e4a6
--- /dev/null
+++ b/xen/arch/arm/arm64/lib/strncmp.S
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2013 ARM Ltd.
+ * Copyright (C) 2013 Linaro.
+ *
+ * This code is based on glibc cortex strings work originally authored by Linaro
+ * and re-licensed under GPLv2 for the Linux kernel. The original code can
+ * be found @
+ *
+ * http://bazaar.launchpad.net/~linaro-toolchain-dev/cortex-strings/trunk/
+ * files/head:/src/aarch64/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/config.h>
+
+#include "assembler.h"
+
+/*
+ * compare two strings
+ *
+ * Parameters:
+ * x0 - const string 1 pointer
+ * x1 - const string 2 pointer
+ * x2 - the maximal length to be compared
+ * Returns:
+ * x0 - an integer less than, equal to, or greater than zero if s1 is found,
+ * respectively, to be less than, to match, or be greater than s2.
+ */
+
+#define REP8_01 0x0101010101010101
+#define REP8_7f 0x7f7f7f7f7f7f7f7f
+#define REP8_80 0x8080808080808080
+
+/* Parameters and result. */
+src1 .req x0
+src2 .req x1
+limit .req x2
+result .req x0
+
+/* Internal variables. */
+data1 .req x3
+data1w .req w3
+data2 .req x4
+data2w .req w4
+has_nul .req x5
+diff .req x6
+syndrome .req x7
+tmp1 .req x8
+tmp2 .req x9
+tmp3 .req x10
+zeroones .req x11
+pos .req x12
+limit_wd .req x13
+mask .req x14
+endloop .req x15
+
+ENTRY(strncmp)
+ cbz limit, .Lret0
+ eor tmp1, src1, src2
+ mov zeroones, #REP8_01
+ tst tmp1, #7
+ b.ne .Lmisaligned8
+ ands tmp1, src1, #7
+ b.ne .Lmutual_align
+ /* Calculate the number of full and partial words -1. */
+ /*
+ * when limit is mulitply of 8, if not sub 1,
+ * the judgement of last dword will wrong.
+ */
+ sub limit_wd, limit, #1 /* limit != 0, so no underflow. */
+ lsr limit_wd, limit_wd, #3 /* Convert to Dwords. */
+
+ /*
+ * NUL detection works on the principle that (X - 1) & (~X) & 0x80
+ * (=> (X - 1) & ~(X | 0x7f)) is non-zero iff a byte is zero, and
+ * can be done in parallel across the entire word.
+ */
+.Lloop_aligned:
+ ldr data1, [src1], #8
+ ldr data2, [src2], #8
+.Lstart_realigned:
+ subs limit_wd, limit_wd, #1
+ sub tmp1, data1, zeroones
+ orr tmp2, data1, #REP8_7f
+ eor diff, data1, data2 /* Non-zero if differences found. */
+ csinv endloop, diff, xzr, pl /* Last Dword or differences.*/
+ bics has_nul, tmp1, tmp2 /* Non-zero if NUL terminator. */
+ ccmp endloop, #0, #0, eq
+ b.eq .Lloop_aligned
+
+ /*Not reached the limit, must have found the end or a diff. */
+ tbz limit_wd, #63, .Lnot_limit
+
+ /* Limit % 8 == 0 => all bytes significant. */
+ ands limit, limit, #7
+ b.eq .Lnot_limit
+
+ lsl limit, limit, #3 /* Bits -> bytes. */
+ mov mask, #~0
+CPU_BE( lsr mask, mask, limit )
+CPU_LE( lsl mask, mask, limit )
+ bic data1, data1, mask
+ bic data2, data2, mask
+
+ /* Make sure that the NUL byte is marked in the syndrome. */
+ orr has_nul, has_nul, mask
+
+.Lnot_limit:
+ orr syndrome, diff, has_nul
+ b .Lcal_cmpresult
+
+.Lmutual_align:
+ /*
+ * Sources are mutually aligned, but are not currently at an
+ * alignment boundary. Round down the addresses and then mask off
+ * the bytes that precede the start point.
+ * We also need to adjust the limit calculations, but without
+ * overflowing if the limit is near ULONG_MAX.
+ */
+ bic src1, src1, #7
+ bic src2, src2, #7
+ ldr data1, [src1], #8
+ neg tmp3, tmp1, lsl #3 /* 64 - bits(bytes beyond align). */
+ ldr data2, [src2], #8
+ mov tmp2, #~0
+ sub limit_wd, limit, #1 /* limit != 0, so no underflow. */
+ /* Big-endian. Early bytes are at MSB. */
+CPU_BE( lsl tmp2, tmp2, tmp3 ) /* Shift (tmp1 & 63). */
+ /* Little-endian. Early bytes are at LSB. */
+CPU_LE( lsr tmp2, tmp2, tmp3 ) /* Shift (tmp1 & 63). */
+
+ and tmp3, limit_wd, #7
+ lsr limit_wd, limit_wd, #3
+ /* Adjust the limit. Only low 3 bits used, so overflow irrelevant.*/
+ add limit, limit, tmp1
+ add tmp3, tmp3, tmp1
+ orr data1, data1, tmp2
+ orr data2, data2, tmp2
+ add limit_wd, limit_wd, tmp3, lsr #3
+ b .Lstart_realigned
+
+/*when src1 offset is not equal to src2 offset...*/
+.Lmisaligned8:
+ cmp limit, #8
+ b.lo .Ltiny8proc /*limit < 8... */
+ /*
+ * Get the align offset length to compare per byte first.
+ * After this process, one string's address will be aligned.*/
+ and tmp1, src1, #7
+ neg tmp1, tmp1
+ add tmp1, tmp1, #8
+ and tmp2, src2, #7
+ neg tmp2, tmp2
+ add tmp2, tmp2, #8
+ subs tmp3, tmp1, tmp2
+ csel pos, tmp1, tmp2, hi /*Choose the maximum. */
+ /*
+ * Here, limit is not less than 8, so directly run .Ltinycmp
+ * without checking the limit.*/
+ sub limit, limit, pos
+.Ltinycmp:
+ ldrb data1w, [src1], #1
+ ldrb data2w, [src2], #1
+ subs pos, pos, #1
+ ccmp data1w, #1, #0, ne /* NZCV = 0b0000. */
+ ccmp data1w, data2w, #0, cs /* NZCV = 0b0000. */
+ b.eq .Ltinycmp
+ cbnz pos, 1f /*find the null or unequal...*/
+ cmp data1w, #1
+ ccmp data1w, data2w, #0, cs
+ b.eq .Lstart_align /*the last bytes are equal....*/
+1:
+ sub result, data1, data2
+ ret
+
+.Lstart_align:
+ lsr limit_wd, limit, #3
+ cbz limit_wd, .Lremain8
+ /*process more leading bytes to make str1 aligned...*/
+ ands xzr, src1, #7
+ b.eq .Lrecal_offset
+ add src1, src1, tmp3 /*tmp3 is positive in this branch.*/
+ add src2, src2, tmp3
+ ldr data1, [src1], #8
+ ldr data2, [src2], #8
+
+ sub limit, limit, tmp3
+ lsr limit_wd, limit, #3
+ subs limit_wd, limit_wd, #1
+
+ sub tmp1, data1, zeroones
+ orr tmp2, data1, #REP8_7f
+ eor diff, data1, data2 /* Non-zero if differences found. */
+ csinv endloop, diff, xzr, ne/*if limit_wd is 0,will finish the cmp*/
+ bics has_nul, tmp1, tmp2
+ ccmp endloop, #0, #0, eq /*has_null is ZERO: no null byte*/
+ b.ne .Lunequal_proc
+ /*How far is the current str2 from the alignment boundary...*/
+ and tmp3, tmp3, #7
+.Lrecal_offset:
+ neg pos, tmp3
+.Lloopcmp_proc:
+ /*
+ * Divide the eight bytes into two parts. First,backwards the src2
+ * to an alignment boundary,load eight bytes from the SRC2 alignment
+ * boundary,then compare with the relative bytes from SRC1.
+ * If all 8 bytes are equal,then start the second part's comparison.
+ * Otherwise finish the comparison.
+ * This special handle can garantee all the accesses are in the
+ * thread/task space in avoid to overrange access.
+ */
+ ldr data1, [src1,pos]
+ ldr data2, [src2,pos]
+ sub tmp1, data1, zeroones
+ orr tmp2, data1, #REP8_7f
+ bics has_nul, tmp1, tmp2 /* Non-zero if NUL terminator. */
+ eor diff, data1, data2 /* Non-zero if differences found. */
+ csinv endloop, diff, xzr, eq
+ cbnz endloop, .Lunequal_proc
+
+ /*The second part process*/
+ ldr data1, [src1], #8
+ ldr data2, [src2], #8
+ subs limit_wd, limit_wd, #1
+ sub tmp1, data1, zeroones
+ orr tmp2, data1, #REP8_7f
+ eor diff, data1, data2 /* Non-zero if differences found. */
+ csinv endloop, diff, xzr, ne/*if limit_wd is 0,will finish the cmp*/
+ bics has_nul, tmp1, tmp2
+ ccmp endloop, #0, #0, eq /*has_null is ZERO: no null byte*/
+ b.eq .Lloopcmp_proc
+
+.Lunequal_proc:
+ orr syndrome, diff, has_nul
+ cbz syndrome, .Lremain8
+.Lcal_cmpresult:
+ /*
+ * reversed the byte-order as big-endian,then CLZ can find the most
+ * significant zero bits.
+ */
+CPU_LE( rev syndrome, syndrome )
+CPU_LE( rev data1, data1 )
+CPU_LE( rev data2, data2 )
+ /*
+ * For big-endian we cannot use the trick with the syndrome value
+ * as carry-propagation can corrupt the upper bits if the trailing
+ * bytes in the string contain 0x01.
+ * However, if there is no NUL byte in the dword, we can generate
+ * the result directly. We can't just subtract the bytes as the
+ * MSB might be significant.
+ */
+CPU_BE( cbnz has_nul, 1f )
+CPU_BE( cmp data1, data2 )
+CPU_BE( cset result, ne )
+CPU_BE( cneg result, result, lo )
+CPU_BE( ret )
+CPU_BE( 1: )
+ /* Re-compute the NUL-byte detection, using a byte-reversed value.*/
+CPU_BE( rev tmp3, data1 )
+CPU_BE( sub tmp1, tmp3, zeroones )
+CPU_BE( orr tmp2, tmp3, #REP8_7f )
+CPU_BE( bic has_nul, tmp1, tmp2 )
+CPU_BE( rev has_nul, has_nul )
+CPU_BE( orr syndrome, diff, has_nul )
+ /*
+ * The MS-non-zero bit of the syndrome marks either the first bit
+ * that is different, or the top bit of the first zero byte.
+ * Shifting left now will bring the critical information into the
+ * top bits.
+ */
+ clz pos, syndrome
+ lsl data1, data1, pos
+ lsl data2, data2, pos
+ /*
+ * But we need to zero-extend (char is unsigned) the value and then
+ * perform a signed 32-bit subtraction.
+ */
+ lsr data1, data1, #56
+ sub result, data1, data2, lsr #56
+ ret
+
+.Lremain8:
+ /* Limit % 8 == 0 => all bytes significant. */
+ ands limit, limit, #7
+ b.eq .Lret0
+.Ltiny8proc:
+ ldrb data1w, [src1], #1
+ ldrb data2w, [src2], #1
+ subs limit, limit, #1
+
+ ccmp data1w, #1, #0, ne /* NZCV = 0b0000. */
+ ccmp data1w, data2w, #0, cs /* NZCV = 0b0000. */
+ b.eq .Ltiny8proc
+ sub result, data1, data2
+ ret
+
+.Lret0:
+ mov result, #0
+ ret
+ENDPROC(strncmp)
diff --git a/xen/arch/arm/arm64/lib/strnlen.S b/xen/arch/arm/arm64/lib/strnlen.S
new file mode 100644
index 0000000..8aa5bbf
--- /dev/null
+++ b/xen/arch/arm/arm64/lib/strnlen.S
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2013 ARM Ltd.
+ * Copyright (C) 2013 Linaro.
+ *
+ * This code is based on glibc cortex strings work originally authored by Linaro
+ * and re-licensed under GPLv2 for the Linux kernel. The original code can
+ * be found @
+ *
+ * http://bazaar.launchpad.net/~linaro-toolchain-dev/cortex-strings/trunk/
+ * files/head:/src/aarch64/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/config.h>
+
+#include "assembler.h"
+
+/*
+ * determine the length of a fixed-size string
+ *
+ * Parameters:
+ * x0 - const string pointer
+ * x1 - maximal string length
+ * Returns:
+ * x0 - the return length of specific string
+ */
+
+/* Arguments and results. */
+srcin .req x0
+len .req x0
+limit .req x1
+
+/* Locals and temporaries. */
+src .req x2
+data1 .req x3
+data2 .req x4
+data2a .req x5
+has_nul1 .req x6
+has_nul2 .req x7
+tmp1 .req x8
+tmp2 .req x9
+tmp3 .req x10
+tmp4 .req x11
+zeroones .req x12
+pos .req x13
+limit_wd .req x14
+
+#define REP8_01 0x0101010101010101
+#define REP8_7f 0x7f7f7f7f7f7f7f7f
+#define REP8_80 0x8080808080808080
+
+ENTRY(strnlen)
+ cbz limit, .Lhit_limit
+ mov zeroones, #REP8_01
+ bic src, srcin, #15
+ ands tmp1, srcin, #15
+ b.ne .Lmisaligned
+ /* Calculate the number of full and partial words -1. */
+ sub limit_wd, limit, #1 /* Limit != 0, so no underflow. */
+ lsr limit_wd, limit_wd, #4 /* Convert to Qwords. */
+
+ /*
+ * NUL detection works on the principle that (X - 1) & (~X) & 0x80
+ * (=> (X - 1) & ~(X | 0x7f)) is non-zero iff a byte is zero, and
+ * can be done in parallel across the entire word.
+ */
+ /*
+ * The inner loop deals with two Dwords at a time. This has a
+ * slightly higher start-up cost, but we should win quite quickly,
+ * especially on cores with a high number of issue slots per
+ * cycle, as we get much better parallelism out of the operations.
+ */
+.Lloop:
+ ldp data1, data2, [src], #16
+.Lrealigned:
+ sub tmp1, data1, zeroones
+ orr tmp2, data1, #REP8_7f
+ sub tmp3, data2, zeroones
+ orr tmp4, data2, #REP8_7f
+ bic has_nul1, tmp1, tmp2
+ bic has_nul2, tmp3, tmp4
+ subs limit_wd, limit_wd, #1
+ orr tmp1, has_nul1, has_nul2
+ ccmp tmp1, #0, #0, pl /* NZCV = 0000 */
+ b.eq .Lloop
+
+ cbz tmp1, .Lhit_limit /* No null in final Qword. */
+
+ /*
+ * We know there's a null in the final Qword. The easiest thing
+ * to do now is work out the length of the string and return
+ * MIN (len, limit).
+ */
+ sub len, src, srcin
+ cbz has_nul1, .Lnul_in_data2
+CPU_BE( mov data2, data1 ) /*perpare data to re-calculate the syndrome*/
+
+ sub len, len, #8
+ mov has_nul2, has_nul1
+.Lnul_in_data2:
+ /*
+ * For big-endian, carry propagation (if the final byte in the
+ * string is 0x01) means we cannot use has_nul directly. The
+ * easiest way to get the correct byte is to byte-swap the data
+ * and calculate the syndrome a second time.
+ */
+CPU_BE( rev data2, data2 )
+CPU_BE( sub tmp1, data2, zeroones )
+CPU_BE( orr tmp2, data2, #REP8_7f )
+CPU_BE( bic has_nul2, tmp1, tmp2 )
+
+ sub len, len, #8
+ rev has_nul2, has_nul2
+ clz pos, has_nul2
+ add len, len, pos, lsr #3 /* Bits to bytes. */
+ cmp len, limit
+ csel len, len, limit, ls /* Return the lower value. */
+ ret
+
+.Lmisaligned:
+ /*
+ * Deal with a partial first word.
+ * We're doing two things in parallel here;
+ * 1) Calculate the number of words (but avoiding overflow if
+ * limit is near ULONG_MAX) - to do this we need to work out
+ * limit + tmp1 - 1 as a 65-bit value before shifting it;
+ * 2) Load and mask the initial data words - we force the bytes
+ * before the ones we are interested in to 0xff - this ensures
+ * early bytes will not hit any zero detection.
+ */
+ ldp data1, data2, [src], #16
+
+ sub limit_wd, limit, #1
+ and tmp3, limit_wd, #15
+ lsr limit_wd, limit_wd, #4
+
+ add tmp3, tmp3, tmp1
+ add limit_wd, limit_wd, tmp3, lsr #4
+
+ neg tmp4, tmp1
+ lsl tmp4, tmp4, #3 /* Bytes beyond alignment -> bits. */
+
+ mov tmp2, #~0
+ /* Big-endian. Early bytes are at MSB. */
+CPU_BE( lsl tmp2, tmp2, tmp4 ) /* Shift (tmp1 & 63). */
+ /* Little-endian. Early bytes are at LSB. */
+CPU_LE( lsr tmp2, tmp2, tmp4 ) /* Shift (tmp1 & 63). */
+
+ cmp tmp1, #8
+
+ orr data1, data1, tmp2
+ orr data2a, data2, tmp2
+
+ csinv data1, data1, xzr, le
+ csel data2, data2, data2a, le
+ b .Lrealigned
+
+.Lhit_limit:
+ mov len, limit
+ ret
+ENDPROC(strnlen)
diff --git a/xen/arch/arm/arm64/lib/strrchr.S b/xen/arch/arm/arm64/lib/strrchr.S
new file mode 100644
index 0000000..3791754
--- /dev/null
+++ b/xen/arch/arm/arm64/lib/strrchr.S
@@ -0,0 +1,42 @@
+/*
+ * Based on arch/arm/lib/strrchr.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ * Copyright (C) 2013 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/config.h>
+
+/*
+ * Find the last occurrence of a character in a string.
+ *
+ * Parameters:
+ * x0 - str
+ * x1 - c
+ * Returns:
+ * x0 - address of last occurrence of 'c' or 0
+ */
+ENTRY(strrchr)
+ mov x3, #0
+ and w1, w1, #0xff
+1: ldrb w2, [x0], #1
+ cbz w2, 2f
+ cmp w2, w1
+ b.ne 1b
+ sub x3, x0, #1
+ b 1b
+2: mov x0, x3
+ ret
+ENDPROC(strrchr)
diff --git a/xen/arch/arm/arm64/smpboot.c b/xen/arch/arm/arm64/smpboot.c
index 1287c72..341cc77 100644
--- a/xen/arch/arm/arm64/smpboot.c
+++ b/xen/arch/arm/arm64/smpboot.c
@@ -32,8 +32,7 @@ static int __init smp_spin_table_cpu_up(int cpu)
return -EFAULT;
}
- release[0] = __pa(init_secondary);
- flush_xen_data_tlb_range_va((vaddr_t)release, sizeof(*release));
+ writeq(__pa(init_secondary), release);
iounmap(release);
@@ -55,7 +54,7 @@ static void __init smp_spin_table_init(int cpu, struct dt_device_node *dn)
static int __init smp_psci_init(int cpu)
{
- if ( !psci_available )
+ if ( !psci_ver )
{
printk("CPU%d asks for PSCI, but DTB has no PSCI node\n", cpu);
return -ENODEV;
diff --git a/xen/arch/arm/arm64/vfp.c b/xen/arch/arm/arm64/vfp.c
index 3cd2b1b..999a0d5 100644
--- a/xen/arch/arm/arm64/vfp.c
+++ b/xen/arch/arm/arm64/vfp.c
@@ -28,7 +28,8 @@ void vfp_save_state(struct vcpu *v)
v->arch.vfp.fpsr = READ_SYSREG32(FPSR);
v->arch.vfp.fpcr = READ_SYSREG32(FPCR);
- v->arch.vfp.fpexc32_el2 = READ_SYSREG32(FPEXC32_EL2);
+ if ( is_32bit_domain(v->domain) )
+ v->arch.vfp.fpexc32_el2 = READ_SYSREG32(FPEXC32_EL2);
}
void vfp_restore_state(struct vcpu *v)
@@ -56,5 +57,6 @@ void vfp_restore_state(struct vcpu *v)
WRITE_SYSREG32(v->arch.vfp.fpsr, FPSR);
WRITE_SYSREG32(v->arch.vfp.fpcr, FPCR);
- WRITE_SYSREG32(v->arch.vfp.fpexc32_el2, FPEXC32_EL2);
+ if ( is_32bit_domain(v->domain) )
+ WRITE_SYSREG32(v->arch.vfp.fpexc32_el2, FPEXC32_EL2);
}
diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
new file mode 100644
index 0000000..e100233
--- /dev/null
+++ b/xen/arch/arm/bootfdt.c
@@ -0,0 +1,370 @@
+/*
+ * Early Device Tree
+ *
+ * Copyright (C) 2012-2014 Citrix Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/lib.h>
+#include <xen/kernel.h>
+#include <xen/init.h>
+#include <xen/device_tree.h>
+#include <xen/libfdt/libfdt.h>
+#include <asm/setup.h>
+
+static bool_t __init device_tree_node_matches(const void *fdt, int node,
+ const char *match)
+{
+ const char *name;
+ size_t match_len;
+
+ name = fdt_get_name(fdt, node, NULL);
+ match_len = strlen(match);
+
+ /* Match both "match" and "match at ..." patterns but not
+ "match-foo". */
+ return strncmp(name, match, match_len) == 0
+ && (name[match_len] == '@' || name[match_len] == '\0');
+}
+
+static bool_t __init device_tree_node_compatible(const void *fdt, int node,
+ const char *match)
+{
+ int len, l;
+ int mlen;
+ const void *prop;
+
+ mlen = strlen(match);
+
+ prop = fdt_getprop(fdt, node, "compatible", &len);
+ if ( prop == NULL )
+ return 0;
+
+ while ( len > 0 ) {
+ if ( !dt_compat_cmp(prop, match) )
+ return 1;
+ l = strlen(prop) + 1;
+ prop += l;
+ len -= l;
+ }
+
+ return 0;
+}
+
+static void __init device_tree_get_reg(const __be32 **cell, u32 address_cells,
+ u32 size_cells, u64 *start, u64 *size)
+{
+ *start = dt_next_cell(address_cells, cell);
+ *size = dt_next_cell(size_cells, cell);
+}
+
+static u32 __init device_tree_get_u32(const void *fdt, int node,
+ const char *prop_name, u32 dflt)
+{
+ const struct fdt_property *prop;
+
+ prop = fdt_get_property(fdt, node, prop_name, NULL);
+ if ( !prop || prop->len < sizeof(u32) )
+ return dflt;
+
+ return fdt32_to_cpu(*(uint32_t*)prop->data);
+}
+
+/**
+ * device_tree_for_each_node - iterate over all device tree nodes
+ * @fdt: flat device tree.
+ * @func: function to call for each node.
+ * @data: data to pass to @func.
+ *
+ * Any nodes nested at DEVICE_TREE_MAX_DEPTH or deeper are ignored.
+ *
+ * Returns 0 if all nodes were iterated over successfully. If @func
+ * returns a value different from 0, that value is returned immediately.
+ */
+static int __init device_tree_for_each_node(const void *fdt,
+ device_tree_node_func func,
+ void *data)
+{
+ int node;
+ int depth;
+ u32 address_cells[DEVICE_TREE_MAX_DEPTH];
+ u32 size_cells[DEVICE_TREE_MAX_DEPTH];
+ int ret;
+
+ for ( node = 0, depth = 0;
+ node >=0 && depth >= 0;
+ node = fdt_next_node(fdt, node, &depth) )
+ {
+ const char *name = fdt_get_name(fdt, node, NULL);
+
+ if ( depth >= DEVICE_TREE_MAX_DEPTH )
+ {
+ printk("Warning: device tree node `%s' is nested too deep\n",
+ name);
+ continue;
+ }
+
+ address_cells[depth] = device_tree_get_u32(fdt, node, "#address-cells",
+ depth > 0 ? address_cells[depth-1] : 0);
+ size_cells[depth] = device_tree_get_u32(fdt, node, "#size-cells",
+ depth > 0 ? size_cells[depth-1] : 0);
+
+
+ ret = func(fdt, node, name, depth,
+ address_cells[depth-1], size_cells[depth-1], data);
+ if ( ret != 0 )
+ return ret;
+ }
+ return 0;
+}
+
+static void __init process_memory_node(const void *fdt, int node,
+ const char *name,
+ u32 address_cells, u32 size_cells)
+{
+ const struct fdt_property *prop;
+ int i;
+ int banks;
+ const __be32 *cell;
+ paddr_t start, size;
+ u32 reg_cells = address_cells + size_cells;
+
+ if ( address_cells < 1 || size_cells < 1 )
+ {
+ printk("fdt: node `%s': invalid #address-cells or #size-cells",
+ name);
+ return;
+ }
+
+ prop = fdt_get_property(fdt, node, "reg", NULL);
+ if ( !prop )
+ {
+ printk("fdt: node `%s': missing `reg' property\n", name);
+ return;
+ }
+
+ cell = (const __be32 *)prop->data;
+ banks = fdt32_to_cpu(prop->len) / (reg_cells * sizeof (u32));
+
+ for ( i = 0; i < banks && bootinfo.mem.nr_banks < NR_MEM_BANKS; i++ )
+ {
+ device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
+ if ( !size )
+ continue;
+ bootinfo.mem.bank[bootinfo.mem.nr_banks].start = start;
+ bootinfo.mem.bank[bootinfo.mem.nr_banks].size = size;
+ bootinfo.mem.nr_banks++;
+ }
+}
+
+static void __init process_multiboot_node(const void *fdt, int node,
+ const char *name,
+ u32 address_cells, u32 size_cells)
+{
+ static int kind_guess = 0;
+ const struct fdt_property *prop;
+ const __be32 *cell;
+ bootmodule_kind kind;
+ paddr_t start, size;
+ const char *cmdline;
+ int len;
+
+ if ( fdt_node_check_compatible(fdt, node, "xen,linux-zimage") == 0 ||
+ fdt_node_check_compatible(fdt, node, "multiboot,kernel") == 0 )
+ kind = BOOTMOD_KERNEL;
+ else if ( fdt_node_check_compatible(fdt, node, "xen,linux-initrd") == 0 ||
+ fdt_node_check_compatible(fdt, node, "multiboot,ramdisk") == 0 )
+ kind = BOOTMOD_RAMDISK;
+ else if ( fdt_node_check_compatible(fdt, node, "xen,xsm-policy") == 0 )
+ kind = BOOTMOD_XSM;
+ else
+ kind = BOOTMOD_UNKNOWN;
+
+ /* Guess that first two unknown are kernel and ramdisk respectively. */
+ if ( kind == BOOTMOD_UNKNOWN )
+ {
+ switch ( kind_guess++ )
+ {
+ case 0: kind = BOOTMOD_KERNEL; break;
+ case 1: kind = BOOTMOD_RAMDISK; break;
+ default: break;
+ }
+ }
+
+ prop = fdt_get_property(fdt, node, "reg", &len);
+ if ( !prop )
+ panic("node %s missing `reg' property\n", name);
+
+ if ( len < dt_cells_to_size(address_cells + size_cells) )
+ panic("fdt: node `%s': `reg` property length is too short\n",
+ name);
+
+ cell = (const __be32 *)prop->data;
+ device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
+
+ prop = fdt_get_property(fdt, node, "bootargs", &len);
+ if ( prop )
+ {
+ if ( len > BOOTMOD_MAX_CMDLINE )
+ panic("module %s command line too long\n", name);
+ cmdline = prop->data;
+ }
+ else
+ cmdline = NULL;
+
+ add_boot_module(kind, start, size, cmdline);
+}
+
+static void __init process_chosen_node(const void *fdt, int node,
+ const char *name,
+ u32 address_cells, u32 size_cells)
+{
+ const struct fdt_property *prop;
+ paddr_t start, end;
+ int len;
+
+ printk("Checking for initrd in /chosen\n");
+
+ prop = fdt_get_property(fdt, node, "linux,initrd-start", &len);
+ if ( !prop )
+ /* No initrd present. */
+ return;
+ if ( len != sizeof(u32) && len != sizeof(u64) )
+ {
+ printk("linux,initrd-start property has invalid length %d\n", len);
+ return;
+ }
+ start = dt_read_number((void *)&prop->data, dt_size_to_cells(len));
+
+ prop = fdt_get_property(fdt, node, "linux,initrd-end", &len);
+ if ( !prop )
+ {
+ printk("linux,initrd-end not present but -start was\n");
+ return;
+ }
+ if ( len != sizeof(u32) && len != sizeof(u64) )
+ {
+ printk("linux,initrd-end property has invalid length %d\n", len);
+ return;
+ }
+ end = dt_read_number((void *)&prop->data, dt_size_to_cells(len));
+
+ if ( start >= end )
+ {
+ printk("linux,initrd limits invalid: %"PRIpaddr" >= %"PRIpaddr"\n",
+ start, end);
+ return;
+ }
+
+ printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end);
+
+ add_boot_module(BOOTMOD_RAMDISK, start, end-start, NULL);
+}
+
+static int __init early_scan_node(const void *fdt,
+ int node, const char *name, int depth,
+ u32 address_cells, u32 size_cells,
+ void *data)
+{
+ if ( device_tree_node_matches(fdt, node, "memory") )
+ process_memory_node(fdt, node, name, address_cells, size_cells);
+ else if ( device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) ||
+ device_tree_node_compatible(fdt, node, "multiboot,module" ))
+ process_multiboot_node(fdt, node, name, address_cells, size_cells);
+ else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") )
+ process_chosen_node(fdt, node, name, address_cells, size_cells);
+
+ return 0;
+}
+
+static void __init early_print_info(void)
+{
+ struct meminfo *mi = &bootinfo.mem;
+ struct bootmodules *mods = &bootinfo.modules;
+ int i, nr_rsvd;
+
+ for ( i = 0; i < mi->nr_banks; i++ )
+ printk("RAM: %"PRIpaddr" - %"PRIpaddr"\n",
+ mi->bank[i].start,
+ mi->bank[i].start + mi->bank[i].size - 1);
+ printk("\n");
+ for ( i = 0 ; i < mods->nr_mods; i++ )
+ printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s %s\n",
+ i,
+ mods->module[i].start,
+ mods->module[i].start + mods->module[i].size,
+ boot_module_kind_as_string(mods->module[i].kind),
+ mods->module[i].cmdline);
+ nr_rsvd = fdt_num_mem_rsv(device_tree_flattened);
+ for ( i = 0; i < nr_rsvd; i++ )
+ {
+ paddr_t s, e;
+ if ( fdt_get_mem_rsv(device_tree_flattened, i, &s, &e) < 0 )
+ continue;
+ /* fdt_get_mem_rsv returns length */
+ e += s;
+ printk(" RESVD[%d]: %"PRIpaddr" - %"PRIpaddr"\n",
+ i, s, e);
+ }
+ printk("\n");
+}
+
+/**
+ * boot_fdt_info - initialize bootinfo from a DTB
+ * @fdt: flattened device tree binary
+ *
+ * Returns the size of the DTB.
+ */
+size_t __init boot_fdt_info(const void *fdt, paddr_t paddr)
+{
+ int ret;
+
+ ret = fdt_check_header(fdt);
+ if ( ret < 0 )
+ panic("No valid device tree\n");
+
+ add_boot_module(BOOTMOD_FDT, paddr, fdt_totalsize(fdt), NULL);
+
+ device_tree_for_each_node((void *)fdt, early_scan_node, NULL);
+ early_print_info();
+
+ return fdt_totalsize(fdt);
+}
+
+const char *boot_fdt_cmdline(const void *fdt)
+{
+ int node;
+ const struct fdt_property *prop;
+
+ node = fdt_path_offset(fdt, "/chosen");
+ if ( node < 0 )
+ return NULL;
+
+ prop = fdt_get_property(fdt, node, "xen,xen-bootargs", NULL);
+ if ( prop == NULL )
+ {
+ struct bootmodule *dom0_mod =
+ boot_module_find_by_kind(BOOTMOD_KERNEL);
+
+ if (fdt_get_property(fdt, node, "xen,dom0-bootargs", NULL) ||
+ ( dom0_mod && dom0_mod->cmdline[0] ) )
+ prop = fdt_get_property(fdt, node, "bootargs", NULL);
+ }
+ if ( prop == NULL )
+ return NULL;
+
+ return prop->data;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/decode.c b/xen/arch/arm/decode.c
index 8880c39..9d237f8 100644
--- a/xen/arch/arm/decode.c
+++ b/xen/arch/arm/decode.c
@@ -151,7 +151,7 @@ bad_thumb:
int decode_instruction(const struct cpu_user_regs *regs, struct hsr_dabt *dabt)
{
- if ( is_pv32_domain(current->domain) && regs->cpsr & PSR_THUMB )
+ if ( is_32bit_domain(current->domain) && regs->cpsr & PSR_THUMB )
return decode_thumb(regs->pc, dabt);
/* TODO: Handle ARM instruction */
diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
index f86b2e3..59e94c0 100644
--- a/xen/arch/arm/device.c
+++ b/xen/arch/arm/device.c
@@ -67,6 +67,21 @@ int __init device_init(struct dt_device_node *dev, enum device_type type,
return -EBADF;
}
+enum device_type device_get_type(const struct dt_device_node *dev)
+{
+ const struct device_desc *desc;
+
+ ASSERT(dev != NULL);
+
+ for ( desc = _sdevice; desc != _edevice; desc++ )
+ {
+ if ( device_is_compatible(desc, dev) )
+ return desc->type;
+ }
+
+ return DEVICE_UNKNOWN;
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 67de12a..7221bc8 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -28,9 +28,10 @@
#include <asm/irq.h>
#include <asm/cpufeature.h>
#include <asm/vfp.h>
-#include <asm/processor-ca15.h>
+#include <asm/procinfo.h>
#include <asm/gic.h>
+#include <asm/vgic.h>
#include <asm/platform.h>
#include "vtimer.h"
#include "vuart.h"
@@ -47,7 +48,7 @@ void idle_loop(void)
local_irq_disable();
if ( cpu_is_haltable(smp_processor_id()) )
{
- dsb();
+ dsb(sy);
wfi();
}
local_irq_enable();
@@ -59,6 +60,12 @@ void idle_loop(void)
static void ctxt_switch_from(struct vcpu *p)
{
+ /* When the idle VCPU is running, Xen will always stay in hypervisor
+ * mode. Therefore we don't need to save the context of an idle VCPU.
+ */
+ if ( is_idle_vcpu(p) )
+ goto end_context;
+
p2m_save_state(p);
/* CP 15 */
@@ -76,7 +83,7 @@ static void ctxt_switch_from(struct vcpu *p)
p->arch.cntkctl = READ_SYSREG32(CNTKCTL_EL1);
virt_timer_save(p);
- if ( is_pv32_domain(p->domain) && cpu_has_thumbee )
+ if ( is_32bit_domain(p->domain) && cpu_has_thumbee )
{
p->arch.teecr = READ_SYSREG32(TEECR32_EL1);
p->arch.teehbr = READ_SYSREG32(TEEHBR32_EL1);
@@ -94,7 +101,7 @@ static void ctxt_switch_from(struct vcpu *p)
p->arch.ttbcr = READ_SYSREG(TCR_EL1);
p->arch.ttbr0 = READ_SYSREG64(TTBR0_EL1);
p->arch.ttbr1 = READ_SYSREG64(TTBR1_EL1);
- if ( is_pv32_domain(p->domain) )
+ if ( is_32bit_domain(p->domain) )
p->arch.dacr = READ_SYSREG(DACR32_EL2);
p->arch.par = READ_SYSREG64(PAR_EL1);
#if defined(CONFIG_ARM_32)
@@ -117,7 +124,7 @@ static void ctxt_switch_from(struct vcpu *p)
p->arch.esr = READ_SYSREG64(ESR_EL1);
#endif
- if ( is_pv32_domain(p->domain) )
+ if ( is_32bit_domain(p->domain) )
p->arch.ifsr = READ_SYSREG(IFSR32_EL2);
p->arch.afsr0 = READ_SYSREG(AFSR0_EL1);
p->arch.afsr1 = READ_SYSREG(AFSR1_EL1);
@@ -131,11 +138,19 @@ static void ctxt_switch_from(struct vcpu *p)
gic_save_state(p);
isb();
+
+end_context:
context_saved(p);
}
static void ctxt_switch_to(struct vcpu *n)
{
+ /* When the idle VCPU is running, Xen will always stay in hypervisor
+ * mode. Therefore we don't need to restore the context of an idle VCPU.
+ */
+ if ( is_idle_vcpu(n) )
+ return;
+
p2m_restore_state(n);
WRITE_SYSREG32(n->domain->arch.vpidr, VPIDR_EL2);
@@ -159,7 +174,7 @@ static void ctxt_switch_to(struct vcpu *n)
WRITE_SYSREG64(n->arch.esr, ESR_EL1);
#endif
- if ( is_pv32_domain(n->domain) )
+ if ( is_32bit_domain(n->domain) )
WRITE_SYSREG(n->arch.ifsr, IFSR32_EL2);
WRITE_SYSREG(n->arch.afsr0, AFSR0_EL1);
WRITE_SYSREG(n->arch.afsr1, AFSR1_EL1);
@@ -169,7 +184,7 @@ static void ctxt_switch_to(struct vcpu *n)
WRITE_SYSREG(n->arch.ttbcr, TCR_EL1);
WRITE_SYSREG64(n->arch.ttbr0, TTBR0_EL1);
WRITE_SYSREG64(n->arch.ttbr1, TTBR1_EL1);
- if ( is_pv32_domain(n->domain) )
+ if ( is_32bit_domain(n->domain) )
WRITE_SYSREG(n->arch.dacr, DACR32_EL2);
WRITE_SYSREG64(n->arch.par, PAR_EL1);
#if defined(CONFIG_ARM_32)
@@ -191,7 +206,7 @@ static void ctxt_switch_to(struct vcpu *n)
WRITE_SYSREG(n->arch.tpidrro_el0, TPIDRRO_EL0);
WRITE_SYSREG(n->arch.tpidr_el1, TPIDR_EL1);
- if ( is_pv32_domain(n->domain) && cpu_has_thumbee )
+ if ( is_32bit_domain(n->domain) && cpu_has_thumbee )
{
WRITE_SYSREG32(n->arch.teecr, TEECR32_EL1);
WRITE_SYSREG32(n->arch.teehbr, TEEHBR32_EL1);
@@ -244,7 +259,7 @@ static void continue_new_vcpu(struct vcpu *prev)
if ( is_idle_vcpu(current) )
reset_stack_and_jump(idle_loop);
- else if is_pv32_domain(current->domain)
+ else if ( is_32bit_domain(current->domain) )
/* check_wakeup_from_wait(); */
reset_stack_and_jump(return_to_new_vcpu32);
else
@@ -394,7 +409,7 @@ struct domain *alloc_domain_struct(void)
return NULL;
clear_page(d);
- d->arch.grant_table_gpfn = xzalloc_array(xen_pfn_t, max_nr_grant_frames);
+ d->arch.grant_table_gpfn = xzalloc_array(xen_pfn_t, max_grant_frames);
return d;
}
@@ -467,24 +482,25 @@ int vcpu_initialise(struct vcpu *v)
v->arch.actlr = READ_SYSREG32(ACTLR_EL1);
- /* XXX: Handle other than CA15 cpus */
- if ( v->domain->max_vcpus > 1 )
- v->arch.actlr |= ACTLR_CA15_SMP;
- else
- v->arch.actlr &= ~ACTLR_CA15_SMP;
+ processor_vcpu_initialise(v);
if ( (rc = vcpu_vgic_init(v)) != 0 )
- return rc;
+ goto fail;
if ( (rc = vcpu_vtimer_init(v)) != 0 )
- return rc;
+ goto fail;
return rc;
+
+fail:
+ vcpu_destroy(v);
+ return rc;
}
void vcpu_destroy(struct vcpu *v)
{
vcpu_timer_destroy(v);
+ vcpu_vgic_free(v);
free_xenheap_pages(v->arch.stack, STACK_ORDER);
}
@@ -512,6 +528,9 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
share_xen_page_with_guest(
virt_to_page(d->shared_info), d, XENSHARE_writable);
+ if ( (rc = domain_io_init(d)) != 0 )
+ goto fail;
+
if ( (rc = p2m_alloc_table(d)) != 0 )
goto fail;
@@ -521,7 +540,7 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
if ( (rc = domain_vgic_init(d)) != 0 )
goto fail;
- if ( (rc = vcpu_domain_init(d)) != 0 )
+ if ( (rc = domain_vtimer_init(d)) != 0 )
goto fail;
if ( d->domain_id )
@@ -531,10 +550,13 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
/*
* Virtual UART is only used by linux early printk and decompress code.
- * Only use it for dom0 because the linux kernel may not support
- * multi-platform.
+ * Only use it for the hardware domain because the linux kernel may not
+ * support multi-platform.
*/
- if ( (d->domain_id == 0) && (rc = domain_vuart_init(d)) )
+ if ( is_hardware_domain(d) && (rc = domain_vuart_init(d)) )
+ goto fail;
+
+ if ( (rc = iommu_domain_init(d)) != 0 )
goto fail;
return 0;
@@ -548,12 +570,28 @@ fail:
void arch_domain_destroy(struct domain *d)
{
+ /* IOMMU page table is shared with P2M, always call
+ * iommu_domain_destroy() before p2m_teardown().
+ */
+ iommu_domain_destroy(d);
p2m_teardown(d);
domain_vgic_free(d);
domain_vuart_free(d);
free_xenheap_page(d->shared_info);
}
+void arch_domain_shutdown(struct domain *d)
+{
+}
+
+void arch_domain_pause(struct domain *d)
+{
+}
+
+void arch_domain_unpause(struct domain *d)
+{
+}
+
static int is_guest_pv32_psr(uint32_t psr)
{
switch (psr & PSR_MODE_MASK)
@@ -607,7 +645,7 @@ int arch_set_info_guest(
struct vcpu_guest_context *ctxt = c.nat;
struct vcpu_guest_core_regs *regs = &c.nat->user_regs;
- if ( is_pv32_domain(v->domain) )
+ if ( is_32bit_domain(v->domain) )
{
if ( !is_guest_pv32_psr(regs->cpsr) )
return -EINVAL;
@@ -679,7 +717,7 @@ static int relinquish_memory(struct domain *d, struct page_list_head *list)
if ( hypercall_preempt_check() )
{
- ret = -EAGAIN;
+ ret = -ERESTART;
goto out;
}
}
@@ -735,12 +773,7 @@ int domain_relinquish_resources(struct domain *d)
void arch_dump_domain_info(struct domain *d)
{
- struct vcpu *v;
-
- for_each_vcpu ( d, v )
- {
- gic_dump_info(v);
- }
+ p2m_dump_info(d);
}
@@ -763,6 +796,7 @@ long arch_do_vcpu_op(int cmd, struct vcpu *v, XEN_GUEST_HANDLE_PARAM(void) arg)
void arch_dump_vcpu_info(struct vcpu *v)
{
+ gic_dump_info(v);
}
void vcpu_mark_events_pending(struct vcpu *v)
@@ -773,7 +807,20 @@ void vcpu_mark_events_pending(struct vcpu *v)
if ( already_pending )
return;
- vgic_vcpu_inject_irq(v, v->domain->arch.evtchn_irq, 1);
+ vgic_vcpu_inject_irq(v, v->domain->arch.evtchn_irq);
+}
+
+/* The ARM spec declares that even if local irqs are masked in
+ * the CPSR register, an irq should wake up a cpu from WFI anyway.
+ * For this reason we need to check for irqs that need delivery,
+ * ignoring the CPSR register, *after* calling SCHEDOP_block to
+ * avoid races with vgic_vcpu_inject_irq.
+ */
+void vcpu_block_unless_event_pending(struct vcpu *v)
+{
+ vcpu_block();
+ if ( local_events_need_delivery_nomask() )
+ vcpu_unblock(current);
}
/*
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 8cbd776..de180d8 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -11,9 +11,13 @@
#include <xen/device_tree.h>
#include <xen/libfdt/libfdt.h>
#include <xen/guest_access.h>
+#include <xen/iocap.h>
+#include <asm/device.h>
#include <asm/setup.h>
#include <asm/platform.h>
#include <asm/psci.h>
+#include <asm/setup.h>
+#include <asm/cpufeature.h>
#include <asm/gic.h>
#include <xen/irq.h>
@@ -43,6 +47,13 @@ custom_param("dom0_mem", parse_dom0_mem);
# define DPRINT(fmt, args...) do {} while ( 0 )
#endif
+//#define DEBUG_11_ALLOCATION
+#ifdef DEBUG_11_ALLOCATION
+# define D11PRINT(fmt, args...) printk(XENLOG_DEBUG fmt, ##args)
+#else
+# define D11PRINT(fmt, args...) do {} while ( 0 )
+#endif
+
/*
* Amount of extra space required to dom0's device tree. No new nodes
* are added (yet) but one terminating reserve map entry (16 bytes) is
@@ -50,7 +61,7 @@ custom_param("dom0_mem", parse_dom0_mem);
*/
#define DOM0_FDT_EXTRA_SIZE (128 + sizeof(struct fdt_reserve_entry))
-struct vcpu *__init alloc_dom0_vcpu0(void)
+struct vcpu *__init alloc_dom0_vcpu0(struct domain *dom0)
{
if ( opt_dom0_max_vcpus == 0 )
opt_dom0_max_vcpus = num_online_cpus();
@@ -65,43 +76,276 @@ struct vcpu *__init alloc_dom0_vcpu0(void)
return alloc_vcpu(dom0, 0, 0);
}
-static void allocate_memory_11(struct domain *d, struct kernel_info *kinfo)
+static unsigned int get_11_allocation_size(paddr_t size)
{
- paddr_t start;
- paddr_t size;
- struct page_info *pg = NULL;
- unsigned int order = get_order_from_bytes(dom0_mem);
- int res;
+ /*
+ * get_order_from_bytes returns the order greater than or equal to
+ * the given size, but we need less than or equal. Adding one to
+ * the size pushes an evenly aligned size into the next order, so
+ * we can then unconditionally subtract 1 from the order which is
+ * returned.
+ */
+ return get_order_from_bytes(size + 1) - 1;
+}
+
+/*
+ * Insert the given pages into a memory bank, banks are ordered by address.
+ *
+ * Returns false if the memory would be below bank 0 or we have run
+ * out of banks. In this case it will free the pages.
+ */
+static bool_t insert_11_bank(struct domain *d,
+ struct kernel_info *kinfo,
+ struct page_info *pg,
+ unsigned int order)
+{
+ int res, i;
paddr_t spfn;
+ paddr_t start, size;
+
+ spfn = page_to_mfn(pg);
+ start = pfn_to_paddr(spfn);
+ size = pfn_to_paddr((1 << order));
+
+ D11PRINT("Allocated %#"PRIpaddr"-%#"PRIpaddr" (%ldMB/%ldMB, order %d)\n",
+ start, start + size,
+ 1UL << (order+PAGE_SHIFT-20),
+ /* Don't want format this as PRIpaddr (16 digit hex) */
+ (unsigned long)(kinfo->unassigned_mem >> 20),
+ order);
+
+ if ( kinfo->mem.nr_banks > 0 &&
+ size < MB(128) &&
+ start + size < kinfo->mem.bank[0].start )
+ {
+ D11PRINT("Allocation below bank 0 is too small, not using\n");
+ goto fail;
+ }
+
+ res = guest_physmap_add_page(d, spfn, spfn, order);
+ if ( res )
+ panic("Failed map pages to DOM0: %d", res);
+
+ kinfo->unassigned_mem -= size;
+
+ if ( kinfo->mem.nr_banks == 0 )
+ {
+ kinfo->mem.bank[0].start = start;
+ kinfo->mem.bank[0].size = size;
+ kinfo->mem.nr_banks = 1;
+ return true;
+ }
+
+ for( i = 0; i < kinfo->mem.nr_banks; i++ )
+ {
+ struct membank *bank = &kinfo->mem.bank[i];
+
+ /* If possible merge new memory into the start of the bank */
+ if ( bank->start == start+size )
+ {
+ bank->start = start;
+ bank->size += size;
+ return true;
+ }
+
+ /* If possible merge new memory onto the end of the bank */
+ if ( start == bank->start + bank->size )
+ {
+ bank->size += size;
+ return true;
+ }
+
+ /*
+ * Otherwise if it is below this bank insert new memory in a
+ * new bank before this one. If there was a lower bank we
+ * could have inserted the memory into/before we would already
+ * have done so, so this must be the right place.
+ */
+ if ( start + size < bank->start && kinfo->mem.nr_banks < NR_MEM_BANKS )
+ {
+ memmove(bank + 1, bank, sizeof(*bank)*(kinfo->mem.nr_banks - i));
+ kinfo->mem.nr_banks++;
+ bank->start = start;
+ bank->size = size;
+ return true;
+ }
+ }
+
+ if ( i == kinfo->mem.nr_banks && kinfo->mem.nr_banks < NR_MEM_BANKS )
+ {
+ struct membank *bank = &kinfo->mem.bank[kinfo->mem.nr_banks];
+
+ bank->start = start;
+ bank->size = size;
+ kinfo->mem.nr_banks++;
+ return true;
+ }
+
+ /* If we get here then there are no more banks to fill. */
+
+fail:
+ free_domheap_pages(pg, order);
+ return false;
+}
+
+/*
+ * This is all pretty horrible.
+ *
+ * Requirements:
+ *
+ * 1. The dom0 kernel should be loaded within the first 128MB of RAM. This
+ * is necessary at least for Linux zImage kernels, which are all we
+ * support today.
+ * 2. We want to put the dom0 kernel, ramdisk and DTB in the same
+ * bank. Partly this is just easier for us to deal with, but also
+ * the ramdisk and DTB must be placed within a certain proximity of
+ * the kernel within RAM.
+ * 3. For 32-bit dom0 we want to place as much of the RAM as we
+ * reasonably can below 4GB, so that it can be used by non-LPAE
+ * enabled kernels.
+ * 4. For 32-bit dom0 the kernel must be located below 4GB.
+ * 5. We want to have a few largers banks rather than many smaller ones.
+ *
+ * For the first two requirements we need to make sure that the lowest
+ * bank is sufficiently large.
+ *
+ * For convenience we also sort the banks by physical address.
+ *
+ * The memory allocator does not really give us the flexibility to
+ * meet these requirements directly. So instead of proceed as follows:
+ *
+ * We first allocate the largest allocation we can as low as we
+ * can. This then becomes the first bank. This bank must be at least
+ * 128MB (or dom0_mem if that is smaller).
+ *
+ * Then we start allocating more memory, trying to allocate the
+ * largest possible size and trying smaller sizes until we
+ * successfully allocate something.
+ *
+ * We then try and insert this memory in to the list of banks. If it
+ * can be merged into an existing bank then this is trivial.
+ *
+ * If the new memory is before the first bank (and cannot be merged into it)
+ * and is at least 128M then we allow it, otherwise we give up. Since the
+ * allocator prefers to allocate high addresses first and the first bank has
+ * already been allocated to be as low as possible this likely means we
+ * wouldn't have been able to allocate much more memory anyway.
+ *
+ * Otherwise we insert a new bank. If we've reached MAX_NR_BANKS then
+ * we give up.
+ *
+ * For 32-bit domain we require that the initial allocation for the
+ * first bank is under 4G. Then for the subsequent allocations we
+ * initially allocate memory only from below 4GB. Once that runs out
+ * (as described above) we allow higher allocations and continue until
+ * that runs out (or we have allocated sufficient dom0 memory).
+ */
+static void allocate_memory_11(struct domain *d, struct kernel_info *kinfo)
+{
+ const unsigned int min_low_order =
+ get_order_from_bytes(min_t(paddr_t, dom0_mem, MB(128)));
+ const unsigned int min_order = get_order_from_bytes(MB(4));
+ struct page_info *pg;
+ unsigned int order = get_11_allocation_size(kinfo->unassigned_mem);
+ int i;
+
+ bool_t lowmem = is_32bit_domain(d);
unsigned int bits;
- for ( bits = PAGE_SHIFT + 1; bits < PADDR_BITS; bits++ )
+ printk("Allocating 1:1 mappings totalling %ldMB for dom0:\n",
+ /* Don't want format this as PRIpaddr (16 digit hex) */
+ (unsigned long)(kinfo->unassigned_mem >> 20));
+
+ kinfo->mem.nr_banks = 0;
+
+ /*
+ * First try and allocate the largest thing we can as low as
+ * possible to be bank 0.
+ */
+ while ( order >= min_low_order )
{
- pg = alloc_domheap_pages(d, order, MEMF_bits(bits));
- if ( pg != NULL )
- break;
+ for ( bits = order ; bits <= (lowmem ? 32 : PADDR_BITS); bits++ )
+ {
+ pg = alloc_domheap_pages(d, order, MEMF_bits(bits));
+ if ( pg != NULL )
+ goto got_bank0;
+ }
+ order--;
}
- if ( !pg )
- panic("Failed to allocate contiguous memory for dom0");
+ panic("Unable to allocate first memory bank");
- spfn = page_to_mfn(pg);
- start = pfn_to_paddr(spfn);
- size = pfn_to_paddr((1 << order));
+ got_bank0:
- // 1:1 mapping
- printk("Populate P2M %#"PRIx64"->%#"PRIx64" (1:1 mapping for dom0)\n",
- start, start + size);
- res = guest_physmap_add_page(d, spfn, spfn, order);
+ if ( !insert_11_bank(d, kinfo, pg, order) )
+ BUG(); /* Cannot fail for first bank */
- if ( res )
- panic("Unable to add pages in DOM0: %d", res);
+ /* Now allocate more memory and fill in additional banks */
- kinfo->mem.bank[0].start = start;
- kinfo->mem.bank[0].size = size;
- kinfo->mem.nr_banks = 1;
+ order = get_11_allocation_size(kinfo->unassigned_mem);
+ while ( kinfo->unassigned_mem && kinfo->mem.nr_banks < NR_MEM_BANKS )
+ {
+ pg = alloc_domheap_pages(d, order, lowmem ? MEMF_bits(32) : 0);
+ if ( !pg )
+ {
+ order --;
- kinfo->unassigned_mem -= size;
+ if ( lowmem && order < min_low_order)
+ {
+ D11PRINT("Failed at min_low_order, allow high allocations\n");
+ order = get_11_allocation_size(kinfo->unassigned_mem);
+ lowmem = false;
+ continue;
+ }
+ if ( order >= min_order )
+ continue;
+
+ /* No more we can do */
+ break;
+ }
+
+ if ( !insert_11_bank(d, kinfo, pg, order) )
+ {
+ if ( kinfo->mem.nr_banks == NR_MEM_BANKS )
+ /* Nothing more we can do. */
+ break;
+
+ if ( lowmem )
+ {
+ D11PRINT("Allocation below bank 0, allow high allocations\n");
+ order = get_11_allocation_size(kinfo->unassigned_mem);
+ lowmem = false;
+ continue;
+ }
+ else
+ {
+ D11PRINT("Allocation below bank 0\n");
+ break;
+ }
+ }
+
+ /*
+ * Success, next time around try again to get the largest order
+ * allocation possible.
+ */
+ order = get_11_allocation_size(kinfo->unassigned_mem);
+ }
+
+ if ( kinfo->unassigned_mem )
+ printk("WARNING: Failed to allocate requested dom0 memory."
+ /* Don't want format this as PRIpaddr (16 digit hex) */
+ " %ldMB unallocated\n",
+ (unsigned long)kinfo->unassigned_mem >> 20);
+
+ for( i = 0; i < kinfo->mem.nr_banks; i++ )
+ {
+ printk("BANK[%d] %#"PRIpaddr"-%#"PRIpaddr" (%ldMB)\n",
+ i,
+ kinfo->mem.bank[i].start,
+ kinfo->mem.bank[i].start + kinfo->mem.bank[i].size,
+ /* Don't want format this as PRIpaddr (16 digit hex) */
+ (unsigned long)(kinfo->mem.bank[i].size >> 20));
+ }
}
static void allocate_memory(struct domain *d, struct kernel_info *kinfo)
@@ -162,9 +406,10 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo,
int res = 0;
int had_dom0_bootargs = 0;
- if ( early_info.modules.nr_mods >= MOD_KERNEL &&
- early_info.modules.module[MOD_KERNEL].cmdline[0] )
- bootargs = &early_info.modules.module[MOD_KERNEL].cmdline[0];
+ const struct bootmodule *mod = kinfo->kernel_bootmodule;
+
+ if ( mod && mod->cmdline[0] )
+ bootargs = &mod->cmdline[0];
dt_for_each_property_node (node, prop)
{
@@ -179,12 +424,21 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo,
* bootargs (from module #1, above).
* * remove bootargs, xen,dom0-bootargs, xen,xen-bootargs,
* linux,initrd-start and linux,initrd-end.
+ * * remove bootargs, linux,uefi-system-table,
+ * linux,uefi-mmap-start, linux,uefi-mmap-size,
+ * linux,uefi-mmap-desc-size, and linux,uefi-mmap-desc-ver
+ * (since EFI boot is not currently supported in dom0).
*/
if ( dt_node_path_is_equal(node, "/chosen") )
{
if ( dt_property_name_is_equal(prop, "xen,xen-bootargs") ||
dt_property_name_is_equal(prop, "linux,initrd-start") ||
- dt_property_name_is_equal(prop, "linux,initrd-end") )
+ dt_property_name_is_equal(prop, "linux,initrd-end") ||
+ dt_property_name_is_equal(prop, "linux,uefi-system-table") ||
+ dt_property_name_is_equal(prop, "linux,uefi-mmap-start") ||
+ dt_property_name_is_equal(prop, "linux,uefi-mmap-size") ||
+ dt_property_name_is_equal(prop, "linux,uefi-mmap-desc-size") ||
+ dt_property_name_is_equal(prop, "linux,uefi-mmap-desc-ver"))
continue;
if ( dt_property_name_is_equal(prop, "xen,dom0-bootargs") )
@@ -211,6 +465,8 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo,
if ( dt_node_path_is_equal(node, "/chosen") )
{
+ const struct bootmodule *mod = kinfo->initrd_bootmodule;
+
if ( bootargs )
{
res = fdt_property(kinfo->fdt, "bootargs", bootargs,
@@ -223,7 +479,7 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo,
* If the bootloader provides an initrd, we must create a placeholder
* for the initrd properties. The values will be replaced later.
*/
- if ( early_info.modules.module[MOD_INITRD].size )
+ if ( mod && mod->size )
{
u64 a = 0;
res = fdt_property(kinfo->fdt, "linux,initrd-start", &a, sizeof(a));
@@ -391,6 +647,9 @@ static int make_hypervisor_node(struct domain *d,
static int make_psci_node(void *fdt, const struct dt_device_node *parent)
{
int res;
+ const char compat[] =
+ "arm,psci-0.2""\0"
+ "arm,psci";
DPRINT("Create PSCI node\n");
@@ -399,7 +658,7 @@ static int make_psci_node(void *fdt, const struct dt_device_node *parent)
if ( res )
return res;
- res = fdt_property_string(fdt, "compatible", "arm,psci");
+ res = fdt_property(fdt, "compatible", compat, sizeof(compat));
if ( res )
return res;
@@ -507,7 +766,7 @@ static int make_cpus_node(const struct domain *d, void *fdt,
return res;
}
- if ( is_pv64_domain(d) )
+ if ( is_64bit_domain(d) )
{
res = fdt_property_string(fdt, "enable-method", "psci");
if ( res )
@@ -528,10 +787,9 @@ static int make_gic_node(const struct domain *d, void *fdt,
const struct dt_device_node *node)
{
const struct dt_device_node *gic = dt_interrupt_controller;
- const void *compatible = NULL;
- u32 len;
- __be32 *new_cells, *tmp;
int res = 0;
+ const void *addrcells;
+ u32 addrcells_len;
/*
* Xen currently supports only a single GIC. Discard any secondary
@@ -545,48 +803,7 @@ static int make_gic_node(const struct domain *d, void *fdt,
DPRINT("Create gic node\n");
- compatible = dt_get_property(gic, "compatible", &len);
- if ( !compatible )
- {
- dprintk(XENLOG_ERR, "Can't find compatible property for the gic node\n");
- return -FDT_ERR_XEN(ENOENT);
- }
-
- res = fdt_begin_node(fdt, "interrupt-controller");
- if ( res )
- return res;
-
- res = fdt_property(fdt, "compatible", compatible, len);
- if ( res )
- return res;
-
- res = fdt_property_cell(fdt, "#interrupt-cells", 3);
- if ( res )
- return res;
-
- res = fdt_property(fdt, "interrupt-controller", NULL, 0);
-
- if ( res )
- return res;
-
- len = dt_cells_to_size(dt_n_addr_cells(node) + dt_n_size_cells(node));
- len *= 2; /* GIC has two memory regions: Distributor + CPU interface */
- new_cells = xzalloc_bytes(len);
- if ( new_cells == NULL )
- return -FDT_ERR_XEN(ENOMEM);
-
- tmp = new_cells;
- DPRINT(" Set Distributor Base 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
- d->arch.vgic.dbase, d->arch.vgic.dbase + PAGE_SIZE - 1);
- dt_set_range(&tmp, node, d->arch.vgic.dbase, PAGE_SIZE);
-
- DPRINT(" Set Cpu Base 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
- d->arch.vgic.cbase, d->arch.vgic.cbase + (PAGE_SIZE * 2) - 1);
- dt_set_range(&tmp, node, d->arch.vgic.cbase, PAGE_SIZE * 2);
-
- res = fdt_property(fdt, "reg", new_cells, len);
- xfree(new_cells);
-
+ res = gic_make_node(d, node, fdt);
if ( res )
return res;
@@ -602,6 +819,14 @@ static int make_gic_node(const struct domain *d, void *fdt,
return res;
}
+ addrcells = dt_get_property(gic, "#address-cells", &addrcells_len);
+ if ( addrcells )
+ {
+ res = fdt_property(fdt, "#address-cells", addrcells, addrcells_len);
+ if ( res )
+ return res;
+ }
+
res = fdt_end_node(fdt);
return res;
@@ -620,8 +845,10 @@ static int make_timer_node(const struct domain *d, void *fdt,
u32 len;
const void *compatible;
int res;
- const struct dt_irq *irq;
+ unsigned int irq;
gic_interrupt_t intrs[3];
+ u32 clock_frequency;
+ bool_t clock_valid;
DPRINT("Create timer node\n");
@@ -647,35 +874,47 @@ static int make_timer_node(const struct domain *d, void *fdt,
if ( res )
return res;
- irq = timer_dt_irq(TIMER_PHYS_SECURE_PPI);
- DPRINT(" Secure interrupt %u\n", irq->irq);
- set_interrupt_ppi(intrs[0], irq->irq, 0xf, irq->type);
+ /* The timer IRQ is emulated by Xen. It always exposes an active-low
+ * level-sensitive interrupt */
+
+ irq = timer_get_irq(TIMER_PHYS_SECURE_PPI);
+ DPRINT(" Secure interrupt %u\n", irq);
+ set_interrupt_ppi(intrs[0], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
- irq = timer_dt_irq(TIMER_PHYS_NONSECURE_PPI);
- DPRINT(" Non secure interrupt %u\n", irq->irq);
- set_interrupt_ppi(intrs[1], irq->irq, 0xf, irq->type);
+ irq = timer_get_irq(TIMER_PHYS_NONSECURE_PPI);
+ DPRINT(" Non secure interrupt %u\n", irq);
+ set_interrupt_ppi(intrs[1], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
- irq = timer_dt_irq(TIMER_VIRT_PPI);
- DPRINT(" Virt interrupt %u\n", irq->irq);
- set_interrupt_ppi(intrs[2], irq->irq, 0xf, irq->type);
+ irq = timer_get_irq(TIMER_VIRT_PPI);
+ DPRINT(" Virt interrupt %u\n", irq);
+ set_interrupt_ppi(intrs[2], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
res = fdt_property_interrupts(fdt, intrs, 3);
if ( res )
return res;
+ clock_valid = dt_property_read_u32(dev, "clock-frequency",
+ &clock_frequency);
+ if ( clock_valid )
+ {
+ res = fdt_property_cell(fdt, "clock-frequency", clock_frequency);
+ if ( res )
+ return res;
+ }
+
res = fdt_end_node(fdt);
return res;
}
/* Map the device in the domain */
-static int map_device(struct domain *d, const struct dt_device_node *dev)
+static int map_device(struct domain *d, struct dt_device_node *dev)
{
unsigned int nirq;
unsigned int naddr;
unsigned int i;
int res;
- struct dt_irq irq;
+ unsigned int irq;
struct dt_raw_irq rirq;
u64 addr, size;
@@ -684,6 +923,18 @@ static int map_device(struct domain *d, const struct dt_device_node *dev)
DPRINT("%s nirq = %d naddr = %u\n", dt_node_full_name(dev), nirq, naddr);
+ if ( dt_device_is_protected(dev) )
+ {
+ DPRINT("%s setup iommu\n", dt_node_full_name(dev));
+ res = iommu_assign_dt_device(d, dev);
+ if ( res )
+ {
+ printk(XENLOG_ERR "Failed to setup the IOMMU for %s\n",
+ dt_node_full_name(dev));
+ return res;
+ }
+ }
+
/* Map IRQs */
for ( i = 0; i < nirq; i++ )
{
@@ -706,17 +957,24 @@ static int map_device(struct domain *d, const struct dt_device_node *dev)
continue;
}
- res = dt_irq_translate(&rirq, &irq);
- if ( res )
+ res = platform_get_irq(dev, i);
+ if ( res < 0 )
{
- printk(XENLOG_ERR "Unable to translate irq %u for %s\n",
+ printk(XENLOG_ERR "Unable to get irq %u for %s\n",
i, dt_node_full_name(dev));
return res;
}
- DPRINT("irq %u = %u type = 0x%x\n", i, irq.irq, irq.type);
- /* Don't check return because the IRQ can be use by multiple device */
- gic_route_irq_to_guest(d, &irq, dt_node_name(dev));
+ irq = res;
+
+ DPRINT("irq %u = %u\n", i, irq);
+ res = route_irq_to_guest(d, irq, dt_node_name(dev));
+ if ( res )
+ {
+ printk(XENLOG_ERR "Unable to route IRQ %u to domain %u\n",
+ irq, d->domain_id);
+ return res;
+ }
}
/* Map the address ranges */
@@ -733,28 +991,41 @@ static int map_device(struct domain *d, const struct dt_device_node *dev)
DPRINT("addr %u = 0x%"PRIx64" - 0x%"PRIx64"\n",
i, addr, addr + size - 1);
- res = map_mmio_regions(d, addr & PAGE_MASK,
- PAGE_ALIGN(addr + size) - 1,
- addr & PAGE_MASK);
+ res = iomem_permit_access(d, paddr_to_pfn(addr & PAGE_MASK),
+ paddr_to_pfn(PAGE_ALIGN(addr + size - 1)));
if ( res )
{
- printk(XENLOG_ERR "Unable to map 0x%"PRIx64
- " - 0x%"PRIx64" in dom0\n",
+ printk(XENLOG_ERR "Unable to permit to dom%d access to"
+ " 0x%"PRIx64" - 0x%"PRIx64"\n",
+ d->domain_id,
addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1);
return res;
}
+ res = map_mmio_regions(d,
+ paddr_to_pfn(addr & PAGE_MASK),
+ DIV_ROUND_UP(size, PAGE_SIZE),
+ paddr_to_pfn(addr & PAGE_MASK));
+ if ( res )
+ {
+ printk(XENLOG_ERR "Unable to map 0x%"PRIx64
+ " - 0x%"PRIx64" in domain %d\n",
+ addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1,
+ d->domain_id);
+ return res;
+ }
}
return 0;
}
static int handle_node(struct domain *d, struct kernel_info *kinfo,
- const struct dt_device_node *node)
+ struct dt_device_node *node)
{
static const struct dt_device_match skip_matches[] __initconst =
{
DT_MATCH_COMPATIBLE("xen,xen"),
DT_MATCH_COMPATIBLE("xen,multiboot-module"),
+ DT_MATCH_COMPATIBLE("multiboot,module"),
DT_MATCH_COMPATIBLE("arm,psci"),
DT_MATCH_PATH("/cpus"),
DT_MATCH_TYPE("memory"),
@@ -762,7 +1033,8 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
};
static const struct dt_device_match gic_matches[] __initconst =
{
- DT_MATCH_GIC,
+ DT_MATCH_GIC_V2,
+ DT_MATCH_GIC_V3,
{ /* sentinel */ },
};
static const struct dt_device_match timer_matches[] __initconst =
@@ -770,7 +1042,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
DT_MATCH_TIMER,
{ /* sentinel */ },
};
- const struct dt_device_node *child;
+ struct dt_device_node *child;
int res;
const char *name;
const char *path;
@@ -805,6 +1077,15 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
return 0;
}
+ /* Even if the IOMMU device is not used by Xen, it should not be
+ * passthrough to DOM0
+ */
+ if ( device_get_type(node) == DEVICE_IOMMU )
+ {
+ DPRINT(" IOMMU, skip it\n");
+ return 0;
+ }
+
/*
* Some device doesn't need to be mapped in Xen:
* - Memory: the guest will see a different view of memory. It will
@@ -924,18 +1205,21 @@ static void dtb_load(struct kernel_info *kinfo)
static void initrd_load(struct kernel_info *kinfo)
{
+ const struct bootmodule *mod = kinfo->initrd_bootmodule;
paddr_t load_addr = kinfo->initrd_paddr;
- paddr_t paddr = early_info.modules.module[MOD_INITRD].start;
- paddr_t len = early_info.modules.module[MOD_INITRD].size;
+ paddr_t paddr, len;
unsigned long offs;
int node;
int res;
__be32 val[2];
__be32 *cellp;
- if ( !len )
+ if ( !mod || !mod->size )
return;
+ paddr = mod->start;
+ len = mod->size;
+
printk("Loading dom0 initrd from %"PRIpaddr" to 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
paddr, load_addr, load_addr + len);
@@ -976,7 +1260,7 @@ static void initrd_load(struct kernel_info *kinfo)
dst = map_domain_page(ma>>PAGE_SHIFT);
- copy_from_paddr(dst + s, paddr + offs, l, BUFFERABLE);
+ copy_from_paddr(dst + s, paddr + offs, l);
unmap_domain_page(dst);
offs += l;
@@ -999,20 +1283,28 @@ int construct_dom0(struct domain *d)
printk("*** LOADING DOMAIN 0 ***\n");
+ iommu_hwdom_init(d);
+
d->max_pages = ~0U;
kinfo.unassigned_mem = dom0_mem;
- allocate_memory(d, &kinfo);
-
- rc = kernel_prepare(&kinfo);
+ rc = kernel_probe(&kinfo);
if ( rc < 0 )
return rc;
#ifdef CONFIG_ARM_64
+ /* if aarch32 mode is not supported at EL1 do not allow 32-bit domain */
+ if ( !(cpu_has_el1_32) && kinfo.type == DOMAIN_32BIT )
+ {
+ printk("Platform does not support 32-bit domain\n");
+ return -EINVAL;
+ }
d->arch.type = kinfo.type;
#endif
+ allocate_memory(d, &kinfo);
+
rc = prepare_dtb(d, &kinfo);
if ( rc < 0 )
return rc;
@@ -1030,8 +1322,8 @@ int construct_dom0(struct domain *d)
set_current(v);
/*
- * kernel_load will determine the placement of the initrd & fdt in
- * RAM, so call it first.
+ * kernel_load will determine the placement of the kernel as well
+ * as the initrd & fdt in RAM, so call it first.
*/
kernel_load(&kinfo);
/* initrd_load will fix up the fdt, so call it before dtb_load */
@@ -1051,7 +1343,7 @@ int construct_dom0(struct domain *d)
regs->pc = (register_t)kinfo.entry;
- if ( is_pv32_domain(d) )
+ if ( is_32bit_domain(d) )
{
regs->cpsr = PSR_GUEST32_INIT;
diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
index 45974e7..d246e84 100644
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -10,6 +10,8 @@
#include <xen/errno.h>
#include <xen/sched.h>
#include <xen/hypercall.h>
+#include <asm/gic.h>
+#include <xen/guest_access.h>
#include <public/domctl.h>
long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
@@ -30,6 +32,39 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
return p2m_cache_flush(d, s, e);
}
+ case XEN_DOMCTL_arm_configure_domain:
+ {
+ uint8_t gic_version;
+
+ /*
+ * Currently the vGIC is emulating the same version of the
+ * hardware GIC. Only the value XEN_DOMCTL_CONFIG_GIC_DEFAULT
+ * is allowed. The DOMCTL will return the actual version of the
+ * GIC.
+ */
+ if ( domctl->u.configuredomain.gic_version != XEN_DOMCTL_CONFIG_GIC_DEFAULT )
+ return -EOPNOTSUPP;
+
+ switch ( gic_hw_version() )
+ {
+ case GIC_V3:
+ gic_version = XEN_DOMCTL_CONFIG_GIC_V3;
+ break;
+ case GIC_V2:
+ gic_version = XEN_DOMCTL_CONFIG_GIC_V2;
+ break;
+ default:
+ BUG();
+ }
+
+ domctl->u.configuredomain.gic_version = gic_version;
+
+ /* TODO: Make the copy generic for all ARCH domctl */
+ if ( __copy_to_guest(u_domctl, domctl, 1) )
+ return -EFAULT;
+
+ return 0;
+ }
default:
return subarch_do_domctl(domctl, d, u_domctl);
diff --git a/xen/arch/arm/early_printk.c b/xen/arch/arm/early_printk.c
index 41938bb..c85db69 100644
--- a/xen/arch/arm/early_printk.c
+++ b/xen/arch/arm/early_printk.c
@@ -13,15 +13,12 @@
#include <xen/lib.h>
#include <xen/stdarg.h>
#include <xen/string.h>
-#include <asm/early_printk.h>
+#include <xen/early_printk.h>
void early_putch(char c);
void early_flush(void);
-/* Early printk buffer */
-static char __initdata buf[512];
-
-static void __init early_puts(const char *s)
+void early_puts(const char *s)
{
while (*s != '\0') {
if (*s == '\n')
@@ -29,12 +26,6 @@ static void __init early_puts(const char *s)
early_putch(*s);
s++;
}
-}
-
-static void __init early_vprintk(const char *fmt, va_list args)
-{
- vsnprintf(buf, sizeof(buf), fmt, args);
- early_puts(buf);
/*
* Wait the UART has finished to transfer all characters before
@@ -42,26 +33,3 @@ static void __init early_vprintk(const char *fmt, va_list args)
*/
early_flush();
}
-
-void __init early_printk(const char *fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- early_vprintk(fmt, args);
- va_end(args);
-}
-
-void __attribute__((noreturn)) __init
-early_panic(const char *fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- early_vprintk(fmt, args);
- va_end(args);
-
- early_printk("\n\nEarly Panic: Stopping\n");
-
- while(1);
-}
diff --git a/xen/arch/arm/efi/Makefile b/xen/arch/arm/efi/Makefile
new file mode 100644
index 0000000..729e53e
--- /dev/null
+++ b/xen/arch/arm/efi/Makefile
@@ -0,0 +1,3 @@
+CFLAGS += -fshort-wchar
+
+obj-y += boot.init.o runtime.o
diff --git a/xen/arch/arm/efi/efi-boot.h b/xen/arch/arm/efi/efi-boot.h
new file mode 100644
index 0000000..639942d
--- /dev/null
+++ b/xen/arch/arm/efi/efi-boot.h
@@ -0,0 +1,576 @@
+/*
+ * Architecture specific implementation for EFI boot code. This file
+ * is intended to be included by common/efi/boot.c _only_, and
+ * therefore can define arch specific global variables.
+ */
+#include <xen/device_tree.h>
+#include <xen/libfdt/libfdt.h>
+#include <asm/setup.h>
+
+void noreturn efi_xen_start(void *fdt_ptr, uint32_t fdt_size);
+
+#define DEVICE_TREE_GUID \
+{0xb1b621d5, 0xf19c, 0x41a5, {0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0}}
+
+static struct file __initdata dtbfile;
+static void __initdata *fdt;
+static void __initdata *memmap;
+
+static int __init setup_chosen_node(void *fdt, int *addr_cells, int *size_cells)
+{
+ int node;
+ const struct fdt_property *prop;
+ int len;
+ uint32_t val;
+
+ if ( !fdt || !addr_cells || !size_cells )
+ return -1;
+
+ /* locate chosen node, which is where we add Xen module info. */
+ node = fdt_subnode_offset(fdt, 0, "chosen");
+ if ( node < 0 )
+ {
+ node = fdt_add_subnode(fdt, 0, "chosen");
+ if ( node < 0 )
+ return node;
+ }
+
+ /* Get or set #address-cells and #size-cells */
+ prop = fdt_get_property(fdt, node, "#address-cells", &len);
+ if ( !prop )
+ {
+ val = cpu_to_fdt32(2);
+ if ( fdt_setprop(fdt, node, "#address-cells", &val, sizeof(val)) )
+ return -1;
+ *addr_cells = 2;
+ }
+ else
+ *addr_cells = fdt32_to_cpu(*((uint32_t *)prop->data));
+
+ prop = fdt_get_property(fdt, node, "#size-cells", &len);
+ if ( !prop )
+ {
+ val = cpu_to_fdt32(2);
+ if ( fdt_setprop(fdt, node, "#size-cells", &val, sizeof(val)) )
+ return -1;
+ *size_cells = 2;
+ }
+ else
+ *size_cells = fdt32_to_cpu(*((uint32_t *)prop->data));
+
+ /*
+ * Make sure ranges is empty if it exists, otherwise create empty ranges
+ * property.
+ */
+ prop = fdt_get_property(fdt, node, "ranges", &len);
+ if ( !prop )
+ {
+ val = cpu_to_fdt32(0);
+ if ( fdt_setprop(fdt, node, "ranges", &val, 0) )
+ return -1;
+ }
+ else if ( fdt32_to_cpu(prop->len) )
+ return -1; /* Non-empty ranges property */
+ return node;
+}
+
+/*
+ * Set a single 'reg' property taking into account the
+ * configured addr and size cell sizes.
+ */
+static int __init fdt_set_reg(void *fdt, int node, int addr_cells,
+ int size_cells, uint64_t addr, uint64_t len)
+{
+ __be32 val[4]; /* At most 2 64 bit values to be stored */
+ __be32 *cellp;
+
+ /*
+ * Make sure that the values provided can be represented in
+ * the reg property, and sizes are valid.
+ */
+ if ( addr_cells < 1 || addr_cells > 2 || size_cells < 1 || size_cells > 2 )
+ return -1;
+ if ( addr_cells == 1 && (addr >> 32) )
+ return -1;
+ if ( size_cells == 1 && (len >> 32) )
+ return -1;
+
+ cellp = (__be32 *)val;
+ dt_set_cell(&cellp, addr_cells, addr);
+ dt_set_cell(&cellp, size_cells, len);
+
+ return(fdt_setprop(fdt, node, "reg", val, sizeof(*cellp) * (cellp - val)));
+}
+
+static void __init *lookup_fdt_config_table(EFI_SYSTEM_TABLE *sys_table)
+{
+ const EFI_GUID fdt_guid = DEVICE_TREE_GUID;
+ EFI_CONFIGURATION_TABLE *tables;
+ void *fdt = NULL;
+ int i;
+
+ tables = sys_table->ConfigurationTable;
+ for ( i = 0; i < sys_table->NumberOfTableEntries; i++ )
+ {
+ if ( match_guid(&tables[i].VendorGuid, &fdt_guid) )
+ {
+ fdt = tables[i].VendorTable;
+ break;
+ }
+ }
+ return fdt;
+}
+
+static EFI_STATUS __init efi_process_memory_map_bootinfo(EFI_MEMORY_DESCRIPTOR *map,
+ UINTN mmap_size,
+ UINTN desc_size)
+{
+ int Index;
+ int i = 0;
+ EFI_MEMORY_DESCRIPTOR *desc_ptr = map;
+
+ for ( Index = 0; Index < (mmap_size / desc_size); Index++ )
+ {
+ if ( desc_ptr->Type == EfiConventionalMemory
+ || desc_ptr->Type == EfiBootServicesCode
+ || desc_ptr->Type == EfiBootServicesData )
+ {
+ bootinfo.mem.bank[i].start = desc_ptr->PhysicalStart;
+ bootinfo.mem.bank[i].size = desc_ptr->NumberOfPages * EFI_PAGE_SIZE;
+ if ( ++i >= NR_MEM_BANKS )
+ {
+ PrintStr(L"Warning: All ");
+ DisplayUint(NR_MEM_BANKS, -1);
+ PrintStr(L" bootinfo mem banks exhausted.\r\n");
+ break;
+ }
+ }
+ desc_ptr = NextMemoryDescriptor(desc_ptr, desc_size);
+ }
+
+ bootinfo.mem.nr_banks = i;
+ return EFI_SUCCESS;
+}
+
+/*
+ * Add the FDT nodes for the standard EFI information, which consist
+ * of the System table address, the address of the final EFI memory map,
+ * and memory map information.
+ */
+EFI_STATUS __init fdt_add_uefi_nodes(EFI_SYSTEM_TABLE *sys_table,
+ void *fdt,
+ EFI_MEMORY_DESCRIPTOR *memory_map,
+ UINTN map_size,
+ UINTN desc_size,
+ UINT32 desc_ver)
+{
+ int node;
+ int status;
+ u32 fdt_val32;
+ u64 fdt_val64;
+ int prev;
+ int num_rsv;
+
+ /*
+ * Delete any memory nodes present. The EFI memory map is the only
+ * memory description provided to Xen.
+ */
+ prev = 0;
+ for (;;)
+ {
+ const char *type;
+ int len;
+
+ node = fdt_next_node(fdt, prev, NULL);
+ if ( node < 0 )
+ break;
+
+ type = fdt_getprop(fdt, node, "device_type", &len);
+ if ( type && strncmp(type, "memory", len) == 0 )
+ {
+ fdt_del_node(fdt, node);
+ continue;
+ }
+
+ prev = node;
+ }
+
+ /*
+ * Delete all memory reserve map entries. When booting via UEFI,
+ * kernel will use the UEFI memory map to find reserved regions.
+ */
+ num_rsv = fdt_num_mem_rsv(fdt);
+ while ( num_rsv-- > 0 )
+ fdt_del_mem_rsv(fdt, num_rsv);
+
+ /* Add FDT entries for EFI runtime services in chosen node. */
+ node = fdt_subnode_offset(fdt, 0, "chosen");
+ if ( node < 0 )
+ {
+ node = fdt_add_subnode(fdt, 0, "chosen");
+ if ( node < 0 )
+ {
+ status = node; /* node is error code when negative */
+ goto fdt_set_fail;
+ }
+ }
+
+ fdt_val64 = cpu_to_fdt64((u64)(uintptr_t)sys_table);
+ status = fdt_setprop(fdt, node, "linux,uefi-system-table",
+ &fdt_val64, sizeof(fdt_val64));
+ if ( status )
+ goto fdt_set_fail;
+
+ fdt_val64 = cpu_to_fdt64((u64)(uintptr_t)memory_map);
+ status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
+ &fdt_val64, sizeof(fdt_val64));
+ if ( status )
+ goto fdt_set_fail;
+
+ fdt_val32 = cpu_to_fdt32(map_size);
+ status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
+ &fdt_val32, sizeof(fdt_val32));
+ if ( status )
+ goto fdt_set_fail;
+
+ fdt_val32 = cpu_to_fdt32(desc_size);
+ status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
+ &fdt_val32, sizeof(fdt_val32));
+ if ( status )
+ goto fdt_set_fail;
+
+ fdt_val32 = cpu_to_fdt32(desc_ver);
+ status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
+ &fdt_val32, sizeof(fdt_val32));
+ if ( status )
+ goto fdt_set_fail;
+
+ return EFI_SUCCESS;
+
+fdt_set_fail:
+ if ( status == -FDT_ERR_NOSPACE )
+ return EFI_BUFFER_TOO_SMALL;
+
+ return EFI_LOAD_ERROR;
+}
+
+/*
+ * Allocates new memory for a larger FDT, and frees existing memory if
+ * struct file size is non-zero. Updates file struct with new memory
+ * address/size for later freeing. If fdtfile.ptr is NULL, an empty FDT
+ * is created.
+ */
+static void __init *fdt_increase_size(struct file *fdtfile, int add_size)
+{
+ EFI_STATUS status;
+ EFI_PHYSICAL_ADDRESS fdt_addr;
+ int fdt_size;
+ int pages;
+ void *new_fdt;
+
+ if ( fdtfile->ptr )
+ fdt_size = fdt_totalsize(fdtfile->ptr);
+ else
+ fdt_size = 0;
+
+ pages = PFN_UP(fdt_size + add_size);
+ status = efi_bs->AllocatePages(AllocateAnyPages, EfiLoaderData,
+ pages, &fdt_addr);
+
+ if ( status != EFI_SUCCESS )
+ return NULL;
+
+ new_fdt = (void *)fdt_addr;
+
+ if ( fdt_size )
+ {
+ if ( fdt_open_into(dtbfile.ptr, new_fdt, pages * EFI_PAGE_SIZE) )
+ return NULL;
+ }
+ else
+ {
+ /*
+ * Create an empty FDT if not provided one, which is the expected case
+ * when booted from the UEFI shell on an ACPI only system. We will use
+ * the FDT to pass the EFI information to Xen, as well as nodes for
+ * any modules the stub loads. The ACPI tables are part of the UEFI
+ * system table that is passed in the FDT.
+ */
+ if ( fdt_create_empty_tree(new_fdt, pages * EFI_PAGE_SIZE) )
+ return NULL;
+ }
+
+ /*
+ * Now that we have the new FDT allocated and copied, free the
+ * original and update the struct file so that the error handling
+ * code will free it. If the original FDT came from a configuration
+ * table, we don't own that memory and can't free it.
+ */
+ if ( dtbfile.size )
+ efi_bs->FreePages(dtbfile.addr, PFN_UP(dtbfile.size));
+
+ /* Update 'file' info for new memory so we clean it up on error exits */
+ dtbfile.addr = fdt_addr;
+ dtbfile.size = pages * EFI_PAGE_SIZE;
+ return new_fdt;
+}
+
+static void __init efi_arch_relocate_image(unsigned long delta)
+{
+}
+
+static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
+ void *map,
+ UINTN map_size,
+ UINTN desc_size,
+ UINT32 desc_ver)
+{
+ EFI_STATUS status;
+
+ status = efi_process_memory_map_bootinfo(map, map_size, desc_size);
+ if ( EFI_ERROR(status) )
+ blexit(L"EFI memory map processing failed");
+
+ status = fdt_add_uefi_nodes(SystemTable, fdt, map, map_size, desc_size,
+ desc_ver);
+ if ( EFI_ERROR(status) )
+ PrintErrMesg(L"Updating FDT failed\r\n", status);
+}
+
+static void __init efi_arch_pre_exit_boot(void)
+{
+}
+
+static void __init efi_arch_post_exit_boot(void)
+{
+ efi_xen_start(fdt, fdt_totalsize(fdt));
+}
+
+static void __init efi_arch_cfg_file_early(EFI_FILE_HANDLE dir_handle, char *section)
+{
+ union string name;
+
+ /*
+ * The DTB must be processed before any other entries in the configuration
+ * file, as the DTB is updated as modules are loaded.
+ */
+ name.s = get_value(&cfg, section, "dtb");
+ if ( name.s )
+ {
+ split_string(name.s);
+ read_file(dir_handle, s2w(&name), &dtbfile, NULL);
+ efi_bs->FreePool(name.w);
+ }
+ fdt = fdt_increase_size(&dtbfile, cfg.size + EFI_PAGE_SIZE);
+ if ( !fdt )
+ blexit(L"Unable to create new FDT");
+}
+
+static void __init efi_arch_cfg_file_late(EFI_FILE_HANDLE dir_handle, char *section)
+{
+}
+
+static void *__init efi_arch_allocate_mmap_buffer(UINTN *map_size)
+{
+ void *ptr;
+ EFI_STATUS status;
+ UINTN map_size_alloc = *map_size + EFI_PAGE_SIZE;
+
+ status = efi_bs->AllocatePool(EfiLoaderData, map_size_alloc, &ptr);
+ if ( status != EFI_SUCCESS )
+ return NULL;
+ *map_size = map_size_alloc;
+ return ptr;
+}
+
+static void __init efi_arch_edd(void)
+{
+}
+
+static void __init efi_arch_memory_setup(void)
+{
+}
+
+static void __init efi_arch_handle_cmdline(CHAR16 *image_name,
+ CHAR16 *cmdline_options,
+ char *cfgfile_options)
+{
+ union string name;
+ char *buf;
+ EFI_STATUS status;
+ int prop_len;
+ int chosen;
+
+ /* locate chosen node, which is where we add Xen module info. */
+ chosen = fdt_subnode_offset(fdt, 0, "chosen");
+ if ( chosen < 0 )
+ blexit(L"Unable to find chosen node");
+
+ status = efi_bs->AllocatePool(EfiBootServicesData, EFI_PAGE_SIZE, (void **)&buf);
+ if ( EFI_ERROR(status) )
+ PrintErrMesg(L"Unable to allocate string buffer\r\n", status);
+
+ if ( image_name )
+ {
+ name.w = image_name;
+ w2s(&name);
+ }
+ else
+ name.s = "xen";
+
+ prop_len = 0;
+ prop_len += snprintf(buf + prop_len,
+ EFI_PAGE_SIZE - prop_len, "%s", name.s);
+ if ( prop_len >= EFI_PAGE_SIZE )
+ blexit(L"FDT string overflow");
+
+ if ( cfgfile_options )
+ {
+ prop_len += snprintf(buf + prop_len,
+ EFI_PAGE_SIZE - prop_len, " %s", cfgfile_options);
+ if ( prop_len >= EFI_PAGE_SIZE )
+ blexit(L"FDT string overflow");
+ }
+
+ if ( cmdline_options )
+ {
+ name.w = cmdline_options;
+ w2s(&name);
+ }
+ else
+ name.s = NULL;
+
+ if ( name.s )
+ {
+ prop_len += snprintf(buf + prop_len,
+ EFI_PAGE_SIZE - prop_len, " %s", name.s);
+ if ( prop_len >= EFI_PAGE_SIZE )
+ blexit(L"FDT string overflow");
+ }
+
+ if ( fdt_setprop_string(fdt, chosen, "xen,xen-bootargs", buf) < 0 )
+ blexit(L"Unable to set xen,xen-bootargs property.");
+
+ efi_bs->FreePool(buf);
+}
+
+static void __init efi_arch_handle_module(struct file *file, const CHAR16 *name,
+ char *options)
+{
+ int node;
+ int chosen;
+ int addr_len, size_len;
+
+ if ( file == &dtbfile )
+ return;
+ chosen = setup_chosen_node(fdt, &addr_len, &size_len);
+ if ( chosen < 0 )
+ blexit(L"Unable to setup chosen node");
+
+ if ( file == &ramdisk )
+ {
+ char ramdisk_compat[] = "multiboot,ramdisk\0multiboot,module";
+ node = fdt_add_subnode(fdt, chosen, "ramdisk");
+ if ( node < 0 )
+ blexit(L"Unable to add ramdisk FDT node.");
+ if ( fdt_setprop(fdt, node, "compatible", ramdisk_compat,
+ sizeof(ramdisk_compat)) < 0 )
+ blexit(L"Unable to set compatible property.");
+ if ( fdt_set_reg(fdt, node, addr_len, size_len, ramdisk.addr,
+ ramdisk.size) < 0 )
+ blexit(L"Unable to set reg property.");
+ }
+ else if ( file == &xsm )
+ {
+ char xsm_compat[] = "xen,xsm-policy\0multiboot,module";
+ node = fdt_add_subnode(fdt, chosen, "xsm");
+ if ( node < 0 )
+ blexit(L"Unable to add xsm FDT node.");
+ if ( fdt_setprop(fdt, node, "compatible", xsm_compat,
+ sizeof(xsm_compat)) < 0 )
+ blexit(L"Unable to set compatible property.");
+ if ( fdt_set_reg(fdt, node, addr_len, size_len, xsm.addr,
+ xsm.size) < 0 )
+ blexit(L"Unable to set reg property.");
+ }
+ else if ( file == &kernel )
+ {
+ char kernel_compat[] = "multiboot,kernel\0multiboot,module";
+ node = fdt_add_subnode(fdt, chosen, "kernel");
+ if ( node < 0 )
+ blexit(L"Unable to add dom0 FDT node.");
+ if ( fdt_setprop(fdt, node, "compatible", kernel_compat,
+ sizeof(kernel_compat)) < 0 )
+ blexit(L"Unable to set compatible property.");
+ if ( options && fdt_setprop_string(fdt, node, "bootargs", options) < 0 )
+ blexit(L"Unable to set bootargs property.");
+ if ( fdt_set_reg(fdt, node, addr_len, size_len, kernel.addr,
+ kernel.size) < 0 )
+ blexit(L"Unable to set reg property.");
+ }
+ else
+ blexit(L"Unknown module type");
+}
+
+static void __init efi_arch_cpu(void)
+{
+}
+
+static void __init efi_arch_blexit(void)
+{
+ if ( dtbfile.addr && dtbfile.size )
+ efi_bs->FreePages(dtbfile.addr, PFN_UP(dtbfile.size));
+ if ( memmap )
+ efi_bs->FreePool(memmap);
+}
+
+static void __init efi_arch_load_addr_check(EFI_LOADED_IMAGE *loaded_image)
+{
+ if ( (unsigned long)loaded_image->ImageBase & ((1 << 12) - 1) )
+ blexit(L"Xen must be loaded at a 4 KByte boundary.");
+}
+
+static bool_t __init efi_arch_use_config_file(EFI_SYSTEM_TABLE *SystemTable)
+{
+ /*
+ * For arm, we may get a device tree from GRUB (or other bootloader)
+ * that contains modules that have already been loaded into memory. In
+ * this case, we do not use a configuration file, and rely on the
+ * bootloader to have loaded all required modules and appropriate
+ * options.
+ */
+
+ fdt = lookup_fdt_config_table(SystemTable);
+ dtbfile.ptr = fdt;
+ dtbfile.size = 0; /* Config table memory can't be freed, so set size to 0 */
+ if ( !fdt || fdt_node_offset_by_compatible(fdt, 0, "multiboot,module") < 0 )
+ {
+ /*
+ * We either have no FDT, or one without modules, so we must have a
+ * Xen EFI configuration file to specify modules. (dom0 required)
+ */
+ return 1;
+ }
+ PrintStr(L"Using modules provided by bootloader in FDT\r\n");
+ /* We have modules already defined in fdt, just add space. */
+ fdt = fdt_increase_size(&dtbfile, EFI_PAGE_SIZE);
+ return 0;
+}
+
+static void __init efi_arch_console_init(UINTN cols, UINTN rows)
+{
+}
+
+static void __init efi_arch_video_init(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
+ UINTN info_size,
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info)
+{
+}
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/efi/runtime.h b/xen/arch/arm/efi/runtime.h
new file mode 100644
index 0000000..25afceb
--- /dev/null
+++ b/xen/arch/arm/efi/runtime.h
@@ -0,0 +1 @@
+/* Placeholder for ARM-specific runtime include/declarations */
diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
new file mode 100644
index 0000000..faad1ff
--- /dev/null
+++ b/xen/arch/arm/gic-v2.c
@@ -0,0 +1,787 @@
+/*
+ * xen/arch/arm/gic-v2.c
+ *
+ * ARM Generic Interrupt Controller support v2
+ *
+ * Tim Deegan <tim at xen.org>
+ * Copyright (c) 2011 Citrix Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/irq.h>
+#include <xen/sched.h>
+#include <xen/errno.h>
+#include <xen/softirq.h>
+#include <xen/list.h>
+#include <xen/device_tree.h>
+#include <xen/libfdt/libfdt.h>
+#include <asm/p2m.h>
+#include <asm/domain.h>
+#include <asm/platform.h>
+#include <asm/device.h>
+
+#include <asm/io.h>
+#include <asm/gic.h>
+
+/*
+ * LR register definitions are GIC v2 specific.
+ * Moved these definitions from header file to here
+ */
+#define GICH_V2_LR_VIRTUAL_MASK 0x3ff
+#define GICH_V2_LR_VIRTUAL_SHIFT 0
+#define GICH_V2_LR_PHYSICAL_MASK 0x3ff
+#define GICH_V2_LR_PHYSICAL_SHIFT 10
+#define GICH_V2_LR_STATE_MASK 0x3
+#define GICH_V2_LR_STATE_SHIFT 28
+#define GICH_V2_LR_PRIORITY_SHIFT 23
+#define GICH_V2_LR_PRIORITY_MASK 0x1f
+#define GICH_V2_LR_HW_SHIFT 31
+#define GICH_V2_LR_HW_MASK 0x1
+#define GICH_V2_LR_GRP_SHIFT 30
+#define GICH_V2_LR_GRP_MASK 0x1
+#define GICH_V2_LR_MAINTENANCE_IRQ (1<<19)
+#define GICH_V2_LR_GRP1 (1<<30)
+#define GICH_V2_LR_HW (1<<31)
+#define GICH_V2_LR_CPUID_SHIFT 9
+#define GICH_V2_VTR_NRLRGS 0x3f
+
+#define GICH_V2_VMCR_PRIORITY_MASK 0x1f
+#define GICH_V2_VMCR_PRIORITY_SHIFT 27
+
+/* Global state */
+static struct {
+ paddr_t dbase; /* Address of distributor registers */
+ void __iomem * map_dbase; /* IO mapped Address of distributor registers */
+ paddr_t cbase; /* Address of CPU interface registers */
+ void __iomem * map_cbase[2]; /* IO mapped Address of CPU interface registers */
+ paddr_t hbase; /* Address of virtual interface registers */
+ void __iomem * map_hbase; /* IO Address of virtual interface registers */
+ paddr_t vbase; /* Address of virtual cpu interface registers */
+ spinlock_t lock;
+} gicv2;
+
+static struct gic_info gicv2_info;
+
+/* The GIC mapping of CPU interfaces does not necessarily match the
+ * logical CPU numbering. Let's use mapping as returned by the GIC
+ * itself
+ */
+static DEFINE_PER_CPU(u8, gic_cpu_id);
+
+/* Maximum cpu interface per GIC */
+#define NR_GIC_CPU_IF 8
+
+static inline void writeb_gicd(uint8_t val, unsigned int offset)
+{
+ writeb_relaxed(val, gicv2.map_dbase + offset);
+}
+
+static inline void writel_gicd(uint32_t val, unsigned int offset)
+{
+ writel_relaxed(val, gicv2.map_dbase + offset);
+}
+
+static inline uint32_t readl_gicd(unsigned int offset)
+{
+ return readl_relaxed(gicv2.map_dbase + offset);
+}
+
+static inline void writel_gicc(uint32_t val, unsigned int offset)
+{
+ unsigned int page = offset >> PAGE_SHIFT;
+ offset &= ~PAGE_MASK;
+ writel_relaxed(val, gicv2.map_cbase[page] + offset);
+}
+
+static inline uint32_t readl_gicc(unsigned int offset)
+{
+ unsigned int page = offset >> PAGE_SHIFT;
+ offset &= ~PAGE_MASK;
+ return readl_relaxed(gicv2.map_cbase[page] + offset);
+}
+
+static inline void writel_gich(uint32_t val, unsigned int offset)
+{
+ writel_relaxed(val, gicv2.map_hbase + offset);
+}
+
+static inline uint32_t readl_gich(int unsigned offset)
+{
+ return readl_relaxed(gicv2.map_hbase + offset);
+}
+
+static unsigned int gicv2_cpu_mask(const cpumask_t *cpumask)
+{
+ unsigned int cpu;
+ unsigned int mask = 0;
+ cpumask_t possible_mask;
+
+ cpumask_and(&possible_mask, cpumask, &cpu_possible_map);
+ for_each_cpu( cpu, &possible_mask )
+ {
+ ASSERT(cpu < NR_GIC_CPU_IF);
+ mask |= per_cpu(gic_cpu_id, cpu);
+ }
+
+ return mask;
+}
+
+static void gicv2_save_state(struct vcpu *v)
+{
+ int i;
+
+ /* No need for spinlocks here because interrupts are disabled around
+ * this call and it only accesses struct vcpu fields that cannot be
+ * accessed simultaneously by another pCPU.
+ */
+ for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+ v->arch.gic.v2.lr[i] = readl_gich(GICH_LR + i * 4);
+
+ v->arch.gic.v2.apr = readl_gich(GICH_APR);
+ v->arch.gic.v2.vmcr = readl_gich(GICH_VMCR);
+ /* Disable until next VCPU scheduled */
+ writel_gich(0, GICH_HCR);
+}
+
+static void gicv2_restore_state(const struct vcpu *v)
+{
+ int i;
+
+ for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+ writel_gich(v->arch.gic.v2.lr[i], GICH_LR + i * 4);
+
+ writel_gich(v->arch.gic.v2.apr, GICH_APR);
+ writel_gich(v->arch.gic.v2.vmcr, GICH_VMCR);
+ writel_gich(GICH_HCR_EN, GICH_HCR);
+}
+
+static void gicv2_dump_state(const struct vcpu *v)
+{
+ int i;
+
+ if ( v == current )
+ {
+ for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+ printk(" HW_LR[%d]=%x\n", i,
+ readl_gich(GICH_LR + i * 4));
+ }
+ else
+ {
+ for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+ printk(" VCPU_LR[%d]=%x\n", i, v->arch.gic.v2.lr[i]);
+ }
+}
+
+static void gicv2_eoi_irq(struct irq_desc *irqd)
+{
+ int irq = irqd->irq;
+ /* Lower the priority */
+ writel_gicc(irq, GICC_EOIR);
+}
+
+static void gicv2_dir_irq(struct irq_desc *irqd)
+{
+ /* Deactivate */
+ writel_gicc(irqd->irq, GICC_DIR);
+}
+
+static unsigned int gicv2_read_irq(void)
+{
+ return (readl_gicc(GICC_IAR) & GICC_IA_IRQ);
+}
+
+/*
+ * needs to be called with a valid cpu_mask, ie each cpu in the mask has
+ * already called gic_cpu_init
+ */
+static void gicv2_set_irq_properties(struct irq_desc *desc,
+ const cpumask_t *cpu_mask,
+ unsigned int priority)
+{
+ uint32_t cfg, edgebit;
+ unsigned int mask = gicv2_cpu_mask(cpu_mask);
+ unsigned int irq = desc->irq;
+ unsigned int type = desc->arch.type;
+
+ ASSERT(type != DT_IRQ_TYPE_INVALID);
+ ASSERT(spin_is_locked(&desc->lock));
+
+ spin_lock(&gicv2.lock);
+ /* Set edge / level */
+ cfg = readl_gicd(GICD_ICFGR + (irq / 16) * 4);
+ edgebit = 2u << (2 * (irq % 16));
+ if ( type & DT_IRQ_TYPE_LEVEL_MASK )
+ cfg &= ~edgebit;
+ else if ( type & DT_IRQ_TYPE_EDGE_BOTH )
+ cfg |= edgebit;
+ writel_gicd(cfg, GICD_ICFGR + (irq / 16) * 4);
+
+ /* Set target CPU mask (RAZ/WI on uniprocessor) */
+ writeb_gicd(mask, GICD_ITARGETSR + irq);
+ /* Set priority */
+ writeb_gicd(priority, GICD_IPRIORITYR + irq);
+
+ spin_unlock(&gicv2.lock);
+}
+
+static void __init gicv2_dist_init(void)
+{
+ uint32_t type;
+ uint32_t cpumask;
+ uint32_t gic_cpus;
+ int i;
+
+ cpumask = readl_gicd(GICD_ITARGETSR) & 0xff;
+ cpumask |= cpumask << 8;
+ cpumask |= cpumask << 16;
+
+ /* Disable the distributor */
+ writel_gicd(0, GICD_CTLR);
+
+ type = readl_gicd(GICD_TYPER);
+ gicv2_info.nr_lines = 32 * ((type & GICD_TYPE_LINES) + 1);
+ gic_cpus = 1 + ((type & GICD_TYPE_CPUS) >> 5);
+ printk("GICv2: %d lines, %d cpu%s%s (IID %8.8x).\n",
+ gicv2_info.nr_lines, gic_cpus, (gic_cpus == 1) ? "" : "s",
+ (type & GICD_TYPE_SEC) ? ", secure" : "",
+ readl_gicd(GICD_IIDR));
+
+ /* Default all global IRQs to level, active low */
+ for ( i = 32; i < gicv2_info.nr_lines; i += 16 )
+ writel_gicd(0x0, GICD_ICFGR + (i / 16) * 4);
+
+ /* Route all global IRQs to this CPU */
+ for ( i = 32; i < gicv2_info.nr_lines; i += 4 )
+ writel_gicd(cpumask, GICD_ITARGETSR + (i / 4) * 4);
+
+ /* Default priority for global interrupts */
+ for ( i = 32; i < gicv2_info.nr_lines; i += 4 )
+ writel_gicd(GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 |
+ GIC_PRI_IRQ << 8 | GIC_PRI_IRQ,
+ GICD_IPRIORITYR + (i / 4) * 4);
+
+ /* Disable all global interrupts */
+ for ( i = 32; i < gicv2_info.nr_lines; i += 32 )
+ writel_gicd(~0x0, GICD_ICENABLER + (i / 32) * 4);
+
+ /* Turn on the distributor */
+ writel_gicd(GICD_CTL_ENABLE, GICD_CTLR);
+}
+
+static void __cpuinit gicv2_cpu_init(void)
+{
+ int i;
+
+ this_cpu(gic_cpu_id) = readl_gicd(GICD_ITARGETSR) & 0xff;
+
+ /* The first 32 interrupts (PPI and SGI) are banked per-cpu, so
+ * even though they are controlled with GICD registers, they must
+ * be set up here with the other per-cpu state. */
+ writel_gicd(0xffff0000, GICD_ICENABLER); /* Disable all PPI */
+ writel_gicd(0x0000ffff, GICD_ISENABLER); /* Enable all SGI */
+
+ /* Set SGI priorities */
+ for ( i = 0; i < 16; i += 4 )
+ writel_gicd(GIC_PRI_IPI << 24 | GIC_PRI_IPI << 16 |
+ GIC_PRI_IPI << 8 | GIC_PRI_IPI,
+ GICD_IPRIORITYR + (i / 4) * 4);
+
+ /* Set PPI priorities */
+ for ( i = 16; i < 32; i += 4 )
+ writel_gicd(GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 |
+ GIC_PRI_IRQ << 8 | GIC_PRI_IRQ,
+ GICD_IPRIORITYR + (i / 4) * 4);
+
+ /* Local settings: interface controller */
+ /* Don't mask by priority */
+ writel_gicc(0xff, GICC_PMR);
+ /* Finest granularity of priority */
+ writel_gicc(0x0, GICC_BPR);
+ /* Turn on delivery */
+ writel_gicc(GICC_CTL_ENABLE|GICC_CTL_EOI, GICC_CTLR);
+}
+
+static void gicv2_cpu_disable(void)
+{
+ writel_gicc(0x0, GICC_CTLR);
+}
+
+static void __cpuinit gicv2_hyp_init(void)
+{
+ uint32_t vtr;
+ uint8_t nr_lrs;
+
+ vtr = readl_gich(GICH_VTR);
+ nr_lrs = (vtr & GICH_V2_VTR_NRLRGS) + 1;
+ gicv2_info.nr_lrs = nr_lrs;
+
+ writel_gich(GICH_MISR_EOI, GICH_MISR);
+}
+
+static void __cpuinit gicv2_hyp_disable(void)
+{
+ writel_gich(0, GICH_HCR);
+}
+
+static int gicv2_secondary_cpu_init(void)
+{
+ spin_lock(&gicv2.lock);
+
+ gicv2_cpu_init();
+ gicv2_hyp_init();
+
+ spin_unlock(&gicv2.lock);
+
+ return 0;
+}
+
+static void gicv2_send_SGI(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
+ const cpumask_t *cpu_mask)
+{
+ unsigned int mask = 0;
+ cpumask_t online_mask;
+
+ switch ( irqmode )
+ {
+ case SGI_TARGET_OTHERS:
+ writel_gicd(GICD_SGI_TARGET_OTHERS | sgi, GICD_SGIR);
+ break;
+ case SGI_TARGET_SELF:
+ writel_gicd(GICD_SGI_TARGET_SELF | sgi, GICD_SGIR);
+ break;
+ case SGI_TARGET_LIST:
+ cpumask_and(&online_mask, cpu_mask, &cpu_online_map);
+ mask = gicv2_cpu_mask(&online_mask);
+ writel_gicd(GICD_SGI_TARGET_LIST |
+ (mask << GICD_SGI_TARGET_SHIFT) | sgi,
+ GICD_SGIR);
+ break;
+ default:
+ BUG();
+ }
+}
+
+/* Shut down the per-CPU GIC interface */
+static void gicv2_disable_interface(void)
+{
+ spin_lock(&gicv2.lock);
+ gicv2_cpu_disable();
+ gicv2_hyp_disable();
+ spin_unlock(&gicv2.lock);
+}
+
+static void gicv2_update_lr(int lr, const struct pending_irq *p,
+ unsigned int state)
+{
+ uint32_t lr_reg;
+
+ BUG_ON(lr >= gicv2_info.nr_lrs);
+ BUG_ON(lr < 0);
+
+ lr_reg = (((state & GICH_V2_LR_STATE_MASK) << GICH_V2_LR_STATE_SHIFT) |
+ ((GIC_PRI_TO_GUEST(p->priority) & GICH_V2_LR_PRIORITY_MASK)
+ << GICH_V2_LR_PRIORITY_SHIFT) |
+ ((p->irq & GICH_V2_LR_VIRTUAL_MASK) << GICH_V2_LR_VIRTUAL_SHIFT));
+
+ if ( p->desc != NULL )
+ {
+ if ( platform_has_quirk(PLATFORM_QUIRK_GUEST_PIRQ_NEED_EOI) )
+ lr_reg |= GICH_V2_LR_MAINTENANCE_IRQ;
+ else
+ lr_reg |= GICH_V2_LR_HW | ((p->desc->irq & GICH_V2_LR_PHYSICAL_MASK )
+ << GICH_V2_LR_PHYSICAL_SHIFT);
+ }
+
+ writel_gich(lr_reg, GICH_LR + lr * 4);
+}
+
+static void gicv2_clear_lr(int lr)
+{
+ writel_gich(0, GICH_LR + lr * 4);
+}
+
+static int gicv2v_setup(struct domain *d)
+{
+ int ret;
+
+ /*
+ * The hardware domain gets the hardware address.
+ * Guests get the virtual platform layout.
+ */
+ if ( is_hardware_domain(d) )
+ {
+ d->arch.vgic.dbase = gicv2.dbase;
+ d->arch.vgic.cbase = gicv2.cbase;
+ }
+ else
+ {
+ d->arch.vgic.dbase = GUEST_GICD_BASE;
+ d->arch.vgic.cbase = GUEST_GICC_BASE;
+ }
+
+ d->arch.vgic.nr_lines = 0;
+
+ /*
+ * Map the gic virtual cpu interface in the gic cpu interface
+ * region of the guest.
+ *
+ * The second page is always mapped at +4K irrespective of the
+ * GIC_64K_STRIDE quirk. The DTB passed to the guest reflects this.
+ */
+ ret = map_mmio_regions(d, paddr_to_pfn(d->arch.vgic.cbase), 1,
+ paddr_to_pfn(gicv2.vbase));
+ if ( ret )
+ return ret;
+
+ if ( !platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
+ ret = map_mmio_regions(d, paddr_to_pfn(d->arch.vgic.cbase + PAGE_SIZE),
+ 2, paddr_to_pfn(gicv2.vbase + PAGE_SIZE));
+ else
+ ret = map_mmio_regions(d, paddr_to_pfn(d->arch.vgic.cbase + PAGE_SIZE),
+ 2, paddr_to_pfn(gicv2.vbase + 16*PAGE_SIZE));
+
+ return ret;
+}
+
+static void gicv2_read_lr(int lr, struct gic_lr *lr_reg)
+{
+ uint32_t lrv;
+
+ lrv = readl_gich(GICH_LR + lr * 4);
+ lr_reg->pirq = (lrv >> GICH_V2_LR_PHYSICAL_SHIFT) & GICH_V2_LR_PHYSICAL_MASK;
+ lr_reg->virq = (lrv >> GICH_V2_LR_VIRTUAL_SHIFT) & GICH_V2_LR_VIRTUAL_MASK;
+ lr_reg->priority = (lrv >> GICH_V2_LR_PRIORITY_SHIFT) & GICH_V2_LR_PRIORITY_MASK;
+ lr_reg->state = (lrv >> GICH_V2_LR_STATE_SHIFT) & GICH_V2_LR_STATE_MASK;
+ lr_reg->hw_status = (lrv >> GICH_V2_LR_HW_SHIFT) & GICH_V2_LR_HW_MASK;
+ lr_reg->grp = (lrv >> GICH_V2_LR_GRP_SHIFT) & GICH_V2_LR_GRP_MASK;
+}
+
+static void gicv2_write_lr(int lr, const struct gic_lr *lr_reg)
+{
+ uint32_t lrv = 0;
+
+ lrv = ( ((lr_reg->pirq & GICH_V2_LR_PHYSICAL_MASK) << GICH_V2_LR_PHYSICAL_SHIFT) |
+ ((lr_reg->virq & GICH_V2_LR_VIRTUAL_MASK) << GICH_V2_LR_VIRTUAL_SHIFT) |
+ ((uint32_t)(lr_reg->priority & GICH_V2_LR_PRIORITY_MASK)
+ << GICH_V2_LR_PRIORITY_SHIFT) |
+ ((uint32_t)(lr_reg->state & GICH_V2_LR_STATE_MASK)
+ << GICH_V2_LR_STATE_SHIFT) |
+ ((uint32_t)(lr_reg->hw_status & GICH_V2_LR_HW_MASK)
+ << GICH_V2_LR_HW_SHIFT) |
+ ((uint32_t)(lr_reg->grp & GICH_V2_LR_GRP_MASK) << GICH_V2_LR_GRP_SHIFT) );
+
+ writel_gich(lrv, GICH_LR + lr * 4);
+}
+
+static void gicv2_hcr_status(uint32_t flag, bool_t status)
+{
+ uint32_t hcr = readl_gich(GICH_HCR);
+
+ if ( status )
+ hcr |= flag;
+ else
+ hcr &= (~flag);
+
+ writel_gich(hcr, GICH_HCR);
+}
+
+static unsigned int gicv2_read_vmcr_priority(void)
+{
+ return ((readl_gich(GICH_VMCR) >> GICH_V2_VMCR_PRIORITY_SHIFT)
+ & GICH_V2_VMCR_PRIORITY_MASK);
+}
+
+static unsigned int gicv2_read_apr(int apr_reg)
+{
+ return readl_gich(GICH_APR);
+}
+
+static void gicv2_irq_enable(struct irq_desc *desc)
+{
+ unsigned long flags;
+ int irq = desc->irq;
+
+ ASSERT(spin_is_locked(&desc->lock));
+
+ spin_lock_irqsave(&gicv2.lock, flags);
+ clear_bit(_IRQ_DISABLED, &desc->status);
+ dsb(sy);
+ /* Enable routing */
+ writel_gicd((1u << (irq % 32)), GICD_ISENABLER + (irq / 32) * 4);
+ spin_unlock_irqrestore(&gicv2.lock, flags);
+}
+
+static void gicv2_irq_disable(struct irq_desc *desc)
+{
+ unsigned long flags;
+ int irq = desc->irq;
+
+ ASSERT(spin_is_locked(&desc->lock));
+
+ spin_lock_irqsave(&gicv2.lock, flags);
+ /* Disable routing */
+ writel_gicd(1u << (irq % 32), GICD_ICENABLER + (irq / 32) * 4);
+ set_bit(_IRQ_DISABLED, &desc->status);
+ spin_unlock_irqrestore(&gicv2.lock, flags);
+}
+
+static unsigned int gicv2_irq_startup(struct irq_desc *desc)
+{
+ gicv2_irq_enable(desc);
+
+ return 0;
+}
+
+static void gicv2_irq_shutdown(struct irq_desc *desc)
+{
+ gicv2_irq_disable(desc);
+}
+
+static void gicv2_irq_ack(struct irq_desc *desc)
+{
+ /* No ACK -- reading IAR has done this for us */
+}
+
+static void gicv2_host_irq_end(struct irq_desc *desc)
+{
+ /* Lower the priority */
+ gicv2_eoi_irq(desc);
+ /* Deactivate */
+ gicv2_dir_irq(desc);
+}
+
+static void gicv2_guest_irq_end(struct irq_desc *desc)
+{
+ /* Lower the priority of the IRQ */
+ gicv2_eoi_irq(desc);
+ /* Deactivation happens in maintenance interrupt / via GICV */
+}
+
+static void gicv2_irq_set_affinity(struct irq_desc *desc, const cpumask_t *cpu_mask)
+{
+ unsigned int mask;
+
+ ASSERT(!cpumask_empty(cpu_mask));
+
+ spin_lock(&gicv2.lock);
+
+ mask = gicv2_cpu_mask(cpu_mask);
+
+ /* Set target CPU mask (RAZ/WI on uniprocessor) */
+ writeb_gicd(mask, GICD_ITARGETSR + desc->irq);
+
+ spin_unlock(&gicv2.lock);
+}
+
+static int gicv2_make_dt_node(const struct domain *d,
+ const struct dt_device_node *node, void *fdt)
+{
+ const struct dt_device_node *gic = dt_interrupt_controller;
+ const void *compatible = NULL;
+ u32 len;
+ __be32 *new_cells, *tmp;
+ int res = 0;
+
+ compatible = dt_get_property(gic, "compatible", &len);
+ if ( !compatible )
+ {
+ dprintk(XENLOG_ERR, "Can't find compatible property for the gic node\n");
+ return -FDT_ERR_XEN(ENOENT);
+ }
+
+ res = fdt_begin_node(fdt, "interrupt-controller");
+ if ( res )
+ return res;
+
+ res = fdt_property(fdt, "compatible", compatible, len);
+ if ( res )
+ return res;
+
+ res = fdt_property_cell(fdt, "#interrupt-cells", 3);
+ if ( res )
+ return res;
+
+ res = fdt_property(fdt, "interrupt-controller", NULL, 0);
+
+ if ( res )
+ return res;
+
+ len = dt_cells_to_size(dt_n_addr_cells(node) + dt_n_size_cells(node));
+ len *= 2; /* GIC has two memory regions: Distributor + CPU interface */
+ new_cells = xzalloc_bytes(len);
+ if ( new_cells == NULL )
+ return -FDT_ERR_XEN(ENOMEM);
+
+ tmp = new_cells;
+ dt_set_range(&tmp, node, d->arch.vgic.dbase, PAGE_SIZE);
+ dt_set_range(&tmp, node, d->arch.vgic.cbase, PAGE_SIZE * 2);
+
+ res = fdt_property(fdt, "reg", new_cells, len);
+ xfree(new_cells);
+
+ return res;
+}
+
+/* XXX different for level vs edge */
+static hw_irq_controller gicv2_host_irq_type = {
+ .typename = "gic-v2",
+ .startup = gicv2_irq_startup,
+ .shutdown = gicv2_irq_shutdown,
+ .enable = gicv2_irq_enable,
+ .disable = gicv2_irq_disable,
+ .ack = gicv2_irq_ack,
+ .end = gicv2_host_irq_end,
+ .set_affinity = gicv2_irq_set_affinity,
+};
+
+static hw_irq_controller gicv2_guest_irq_type = {
+ .typename = "gic-v2",
+ .startup = gicv2_irq_startup,
+ .shutdown = gicv2_irq_shutdown,
+ .enable = gicv2_irq_enable,
+ .disable = gicv2_irq_disable,
+ .ack = gicv2_irq_ack,
+ .end = gicv2_guest_irq_end,
+ .set_affinity = gicv2_irq_set_affinity,
+};
+
+const static struct gic_hw_operations gicv2_ops = {
+ .info = &gicv2_info,
+ .secondary_init = gicv2_secondary_cpu_init,
+ .save_state = gicv2_save_state,
+ .restore_state = gicv2_restore_state,
+ .dump_state = gicv2_dump_state,
+ .gicv_setup = gicv2v_setup,
+ .gic_host_irq_type = &gicv2_host_irq_type,
+ .gic_guest_irq_type = &gicv2_guest_irq_type,
+ .eoi_irq = gicv2_eoi_irq,
+ .deactivate_irq = gicv2_dir_irq,
+ .read_irq = gicv2_read_irq,
+ .set_irq_properties = gicv2_set_irq_properties,
+ .send_SGI = gicv2_send_SGI,
+ .disable_interface = gicv2_disable_interface,
+ .update_lr = gicv2_update_lr,
+ .update_hcr_status = gicv2_hcr_status,
+ .clear_lr = gicv2_clear_lr,
+ .read_lr = gicv2_read_lr,
+ .write_lr = gicv2_write_lr,
+ .read_vmcr_priority = gicv2_read_vmcr_priority,
+ .read_apr = gicv2_read_apr,
+ .make_dt_node = gicv2_make_dt_node,
+};
+
+/* Set up the GIC */
+static int __init gicv2_init(struct dt_device_node *node, const void *data)
+{
+ int res;
+
+ dt_device_set_used_by(node, DOMID_XEN);
+
+ res = dt_device_get_address(node, 0, &gicv2.dbase, NULL);
+ if ( res || !gicv2.dbase || (gicv2.dbase & ~PAGE_MASK) )
+ panic("GICv2: Cannot find a valid address for the distributor");
+
+ res = dt_device_get_address(node, 1, &gicv2.cbase, NULL);
+ if ( res || !gicv2.cbase || (gicv2.cbase & ~PAGE_MASK) )
+ panic("GICv2: Cannot find a valid address for the CPU");
+
+ res = dt_device_get_address(node, 2, &gicv2.hbase, NULL);
+ if ( res || !gicv2.hbase || (gicv2.hbase & ~PAGE_MASK) )
+ panic("GICv2: Cannot find a valid address for the hypervisor");
+
+ res = dt_device_get_address(node, 3, &gicv2.vbase, NULL);
+ if ( res || !gicv2.vbase || (gicv2.vbase & ~PAGE_MASK) )
+ panic("GICv2: Cannot find a valid address for the virtual CPU");
+
+ res = platform_get_irq(node, 0);
+ if ( res < 0 )
+ panic("GICv2: Cannot find the maintenance IRQ");
+ gicv2_info.maintenance_irq = res;
+
+ /* Set the GIC as the primary interrupt controller */
+ dt_interrupt_controller = node;
+
+ /* TODO: Add check on distributor, cpu size */
+
+ printk("GICv2 initialization:\n"
+ " gic_dist_addr=%"PRIpaddr"\n"
+ " gic_cpu_addr=%"PRIpaddr"\n"
+ " gic_hyp_addr=%"PRIpaddr"\n"
+ " gic_vcpu_addr=%"PRIpaddr"\n"
+ " gic_maintenance_irq=%u\n",
+ gicv2.dbase, gicv2.cbase, gicv2.hbase, gicv2.vbase,
+ gicv2_info.maintenance_irq);
+
+ if ( (gicv2.dbase & ~PAGE_MASK) || (gicv2.cbase & ~PAGE_MASK) ||
+ (gicv2.hbase & ~PAGE_MASK) || (gicv2.vbase & ~PAGE_MASK) )
+ panic("GICv2 interfaces not page aligned");
+
+ gicv2.map_dbase = ioremap_nocache(gicv2.dbase, PAGE_SIZE);
+ if ( !gicv2.map_dbase )
+ panic("GICv2: Failed to ioremap for GIC distributor\n");
+
+ gicv2.map_cbase[0] = ioremap_nocache(gicv2.cbase, PAGE_SIZE);
+
+ if ( platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
+ gicv2.map_cbase[1] = ioremap_nocache(gicv2.cbase + PAGE_SIZE * 0x10,
+ PAGE_SIZE);
+ else
+ gicv2.map_cbase[1] = ioremap_nocache(gicv2.cbase + PAGE_SIZE, PAGE_SIZE);
+
+ if ( !gicv2.map_cbase[0] || !gicv2.map_cbase[1] )
+ panic("GICv2: Failed to ioremap for GIC CPU interface\n");
+
+ gicv2.map_hbase = ioremap_nocache(gicv2.hbase, PAGE_SIZE);
+ if ( !gicv2.map_hbase )
+ panic("GICv2: Failed to ioremap for GIC Virtual interface\n");
+
+ /* Global settings: interrupt distributor */
+ spin_lock_init(&gicv2.lock);
+ spin_lock(&gicv2.lock);
+
+ gicv2_dist_init();
+ gicv2_cpu_init();
+ gicv2_hyp_init();
+
+ spin_unlock(&gicv2.lock);
+
+ gicv2_info.hw_version = GIC_V2;
+ register_gic_ops(&gicv2_ops);
+
+ return 0;
+}
+
+static const char * const gicv2_dt_compat[] __initconst =
+{
+ DT_COMPAT_GIC_CORTEX_A15,
+ DT_COMPAT_GIC_CORTEX_A7,
+ DT_COMPAT_GIC_400,
+ NULL
+};
+
+DT_DEVICE_START(gicv2, "GICv2:", DEVICE_GIC)
+ .compatible = gicv2_dt_compat,
+ .init = gicv2_init,
+DT_DEVICE_END
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
new file mode 100644
index 0000000..076aa62
--- /dev/null
+++ b/xen/arch/arm/gic-v3.c
@@ -0,0 +1,1299 @@
+/*
+ * xen/arch/arm/gic-v3.c
+ *
+ * ARM Generic Interrupt Controller support v3 version
+ * based on xen/arch/arm/gic-v2.c and kernel GICv3 driver
+ *
+ * Copyright (C) 2012,2013 - ARM Ltd
+ * Marc Zyngier <marc.zyngier at arm.com>
+ *
+ * Vijaya Kumar K <vijaya.kumar at caviumnetworks.com>, Cavium Inc
+ * ported to Xen
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/init.h>
+#include <xen/cpu.h>
+#include <xen/mm.h>
+#include <xen/irq.h>
+#include <xen/sched.h>
+#include <xen/errno.h>
+#include <xen/delay.h>
+#include <xen/device_tree.h>
+#include <xen/sizes.h>
+#include <xen/libfdt/libfdt.h>
+#include <asm/p2m.h>
+#include <asm/domain.h>
+#include <asm/io.h>
+#include <asm/device.h>
+#include <asm/gic.h>
+#include <asm/gic_v3_defs.h>
+#include <asm/cpufeature.h>
+
+struct rdist_region {
+ paddr_t base;
+ paddr_t size;
+ void __iomem *map_base;
+};
+
+/* Global state */
+static struct {
+ paddr_t dbase; /* Address of distributor registers */
+ paddr_t dbase_size;
+ void __iomem *map_dbase; /* Mapped address of distributor registers */
+ struct rdist_region *rdist_regions;
+ uint32_t rdist_stride;
+ unsigned int rdist_count; /* Number of rdist regions count */
+ unsigned int nr_priorities;
+ spinlock_t lock;
+} gicv3;
+
+static struct gic_info gicv3_info;
+
+/* per-cpu re-distributor base */
+static DEFINE_PER_CPU(void __iomem*, rbase);
+
+#define GICD (gicv3.map_dbase)
+#define GICD_RDIST_BASE (this_cpu(rbase))
+#define GICD_RDIST_SGI_BASE (GICD_RDIST_BASE + SZ_64K)
+
+/*
+ * Saves all 16(Max) LR registers. Though number of LRs implemented
+ * is implementation specific.
+ */
+static inline void gicv3_save_lrs(struct vcpu *v)
+{
+ /* Fall through for all the cases */
+ switch ( gicv3_info.nr_lrs )
+ {
+ case 16:
+ v->arch.gic.v3.lr[15] = READ_SYSREG(ICH_LR15_EL2);
+ case 15:
+ v->arch.gic.v3.lr[14] = READ_SYSREG(ICH_LR14_EL2);
+ case 14:
+ v->arch.gic.v3.lr[13] = READ_SYSREG(ICH_LR13_EL2);
+ case 13:
+ v->arch.gic.v3.lr[12] = READ_SYSREG(ICH_LR12_EL2);
+ case 12:
+ v->arch.gic.v3.lr[11] = READ_SYSREG(ICH_LR11_EL2);
+ case 11:
+ v->arch.gic.v3.lr[10] = READ_SYSREG(ICH_LR10_EL2);
+ case 10:
+ v->arch.gic.v3.lr[9] = READ_SYSREG(ICH_LR9_EL2);
+ case 9:
+ v->arch.gic.v3.lr[8] = READ_SYSREG(ICH_LR8_EL2);
+ case 8:
+ v->arch.gic.v3.lr[7] = READ_SYSREG(ICH_LR7_EL2);
+ case 7:
+ v->arch.gic.v3.lr[6] = READ_SYSREG(ICH_LR6_EL2);
+ case 6:
+ v->arch.gic.v3.lr[5] = READ_SYSREG(ICH_LR5_EL2);
+ case 5:
+ v->arch.gic.v3.lr[4] = READ_SYSREG(ICH_LR4_EL2);
+ case 4:
+ v->arch.gic.v3.lr[3] = READ_SYSREG(ICH_LR3_EL2);
+ case 3:
+ v->arch.gic.v3.lr[2] = READ_SYSREG(ICH_LR2_EL2);
+ case 2:
+ v->arch.gic.v3.lr[1] = READ_SYSREG(ICH_LR1_EL2);
+ case 1:
+ v->arch.gic.v3.lr[0] = READ_SYSREG(ICH_LR0_EL2);
+ break;
+ default:
+ BUG();
+ }
+}
+
+/*
+ * Restores all 16(Max) LR registers. Though number of LRs implemented
+ * is implementation specific.
+ */
+static inline void gicv3_restore_lrs(const struct vcpu *v)
+{
+ /* Fall through for all the cases */
+ switch ( gicv3_info.nr_lrs )
+ {
+ case 16:
+ WRITE_SYSREG(v->arch.gic.v3.lr[15], ICH_LR15_EL2);
+ case 15:
+ WRITE_SYSREG(v->arch.gic.v3.lr[14], ICH_LR14_EL2);
+ case 14:
+ WRITE_SYSREG(v->arch.gic.v3.lr[13], ICH_LR13_EL2);
+ case 13:
+ WRITE_SYSREG(v->arch.gic.v3.lr[12], ICH_LR12_EL2);
+ case 12:
+ WRITE_SYSREG(v->arch.gic.v3.lr[11], ICH_LR11_EL2);
+ case 11:
+ WRITE_SYSREG(v->arch.gic.v3.lr[10], ICH_LR10_EL2);
+ case 10:
+ WRITE_SYSREG(v->arch.gic.v3.lr[9], ICH_LR9_EL2);
+ case 9:
+ WRITE_SYSREG(v->arch.gic.v3.lr[8], ICH_LR8_EL2);
+ case 8:
+ WRITE_SYSREG(v->arch.gic.v3.lr[7], ICH_LR7_EL2);
+ case 7:
+ WRITE_SYSREG(v->arch.gic.v3.lr[6], ICH_LR6_EL2);
+ case 6:
+ WRITE_SYSREG(v->arch.gic.v3.lr[5], ICH_LR5_EL2);
+ case 5:
+ WRITE_SYSREG(v->arch.gic.v3.lr[4], ICH_LR4_EL2);
+ case 4:
+ WRITE_SYSREG(v->arch.gic.v3.lr[3], ICH_LR3_EL2);
+ case 3:
+ WRITE_SYSREG(v->arch.gic.v3.lr[2], ICH_LR2_EL2);
+ case 2:
+ WRITE_SYSREG(v->arch.gic.v3.lr[1], ICH_LR1_EL2);
+ case 1:
+ WRITE_SYSREG(v->arch.gic.v3.lr[0], ICH_LR0_EL2);
+ break;
+ default:
+ BUG();
+ }
+}
+
+static uint64_t gicv3_ich_read_lr(int lr)
+{
+ switch ( lr )
+ {
+ case 0: return READ_SYSREG(ICH_LR0_EL2);
+ case 1: return READ_SYSREG(ICH_LR1_EL2);
+ case 2: return READ_SYSREG(ICH_LR2_EL2);
+ case 3: return READ_SYSREG(ICH_LR3_EL2);
+ case 4: return READ_SYSREG(ICH_LR4_EL2);
+ case 5: return READ_SYSREG(ICH_LR5_EL2);
+ case 6: return READ_SYSREG(ICH_LR6_EL2);
+ case 7: return READ_SYSREG(ICH_LR7_EL2);
+ case 8: return READ_SYSREG(ICH_LR8_EL2);
+ case 9: return READ_SYSREG(ICH_LR9_EL2);
+ case 10: return READ_SYSREG(ICH_LR10_EL2);
+ case 11: return READ_SYSREG(ICH_LR11_EL2);
+ case 12: return READ_SYSREG(ICH_LR12_EL2);
+ case 13: return READ_SYSREG(ICH_LR13_EL2);
+ case 14: return READ_SYSREG(ICH_LR14_EL2);
+ case 15: return READ_SYSREG(ICH_LR15_EL2);
+ default:
+ BUG();
+ }
+}
+
+static void gicv3_ich_write_lr(int lr, uint64_t val)
+{
+ switch ( lr )
+ {
+ case 0:
+ WRITE_SYSREG(val, ICH_LR0_EL2);
+ break;
+ case 1:
+ WRITE_SYSREG(val, ICH_LR1_EL2);
+ break;
+ case 2:
+ WRITE_SYSREG(val, ICH_LR2_EL2);
+ break;
+ case 3:
+ WRITE_SYSREG(val, ICH_LR3_EL2);
+ break;
+ case 4:
+ WRITE_SYSREG(val, ICH_LR4_EL2);
+ break;
+ case 5:
+ WRITE_SYSREG(val, ICH_LR5_EL2);
+ break;
+ case 6:
+ WRITE_SYSREG(val, ICH_LR6_EL2);
+ break;
+ case 7:
+ WRITE_SYSREG(val, ICH_LR7_EL2);
+ break;
+ case 8:
+ WRITE_SYSREG(val, ICH_LR8_EL2);
+ break;
+ case 9:
+ WRITE_SYSREG(val, ICH_LR9_EL2);
+ break;
+ case 10:
+ WRITE_SYSREG(val, ICH_LR10_EL2);
+ break;
+ case 11:
+ WRITE_SYSREG(val, ICH_LR11_EL2);
+ break;
+ case 12:
+ WRITE_SYSREG(val, ICH_LR12_EL2);
+ break;
+ case 13:
+ WRITE_SYSREG(val, ICH_LR13_EL2);
+ break;
+ case 14:
+ WRITE_SYSREG(val, ICH_LR14_EL2);
+ break;
+ case 15:
+ WRITE_SYSREG(val, ICH_LR15_EL2);
+ break;
+ default:
+ return;
+ }
+ isb();
+}
+
+/*
+ * System Register Enable (SRE). Enable to access CPU & Virtual
+ * interface registers as system registers in EL2
+ */
+static void gicv3_enable_sre(void)
+{
+ uint32_t val;
+
+ val = READ_SYSREG32(ICC_SRE_EL2);
+ val |= GICC_SRE_EL2_SRE | GICC_SRE_EL2_ENEL1;
+
+ WRITE_SYSREG32(val, ICC_SRE_EL2);
+ isb();
+}
+
+/* Wait for completion of a distributor change */
+static void gicv3_do_wait_for_rwp(void __iomem *base)
+{
+ uint32_t val;
+ bool_t timeout = 0;
+ s_time_t deadline = NOW() + MILLISECS(1000);
+
+ do {
+ val = readl_relaxed(base + GICD_CTLR);
+ if ( !(val & GICD_CTLR_RWP) )
+ break;
+ if ( NOW() > deadline )
+ {
+ timeout = 1;
+ break;
+ }
+ cpu_relax();
+ udelay(1);
+ } while ( 1 );
+
+ if ( timeout )
+ dprintk(XENLOG_ERR, "RWP timeout\n");
+}
+
+static void gicv3_dist_wait_for_rwp(void)
+{
+ gicv3_do_wait_for_rwp(GICD);
+}
+
+static void gicv3_redist_wait_for_rwp(void)
+{
+ gicv3_do_wait_for_rwp(GICD_RDIST_BASE);
+}
+
+static void gicv3_wait_for_rwp(int irq)
+{
+ if ( irq < NR_LOCAL_IRQS )
+ gicv3_redist_wait_for_rwp();
+ else
+ gicv3_dist_wait_for_rwp();
+}
+
+static unsigned int gicv3_get_cpu_from_mask(const cpumask_t *cpumask)
+{
+ unsigned int cpu;
+ cpumask_t possible_mask;
+
+ cpumask_and(&possible_mask, cpumask, &cpu_possible_map);
+ cpu = cpumask_any(&possible_mask);
+
+ return cpu;
+}
+
+static void restore_aprn_regs(const union gic_state_data *d)
+{
+ /* Write APRn register based on number of priorities
+ platform has implemented */
+ switch ( gicv3.nr_priorities )
+ {
+ case 7:
+ WRITE_SYSREG32(d->v3.apr0[2], ICH_AP0R2_EL2);
+ WRITE_SYSREG32(d->v3.apr1[2], ICH_AP1R2_EL2);
+ /* Fall through */
+ case 6:
+ WRITE_SYSREG32(d->v3.apr0[1], ICH_AP0R1_EL2);
+ WRITE_SYSREG32(d->v3.apr1[1], ICH_AP1R1_EL2);
+ /* Fall through */
+ case 5:
+ WRITE_SYSREG32(d->v3.apr0[0], ICH_AP0R0_EL2);
+ WRITE_SYSREG32(d->v3.apr1[0], ICH_AP1R0_EL2);
+ break;
+ default:
+ BUG();
+ }
+}
+
+static void save_aprn_regs(union gic_state_data *d)
+{
+ /* Read APRn register based on number of priorities
+ platform has implemented */
+ switch ( gicv3.nr_priorities )
+ {
+ case 7:
+ d->v3.apr0[2] = READ_SYSREG32(ICH_AP0R2_EL2);
+ d->v3.apr1[2] = READ_SYSREG32(ICH_AP1R2_EL2);
+ /* Fall through */
+ case 6:
+ d->v3.apr0[1] = READ_SYSREG32(ICH_AP0R1_EL2);
+ d->v3.apr1[1] = READ_SYSREG32(ICH_AP1R1_EL2);
+ /* Fall through */
+ case 5:
+ d->v3.apr0[0] = READ_SYSREG32(ICH_AP0R0_EL2);
+ d->v3.apr1[0] = READ_SYSREG32(ICH_AP1R0_EL2);
+ break;
+ default:
+ BUG();
+ }
+}
+
+/*
+ * As per section 4.8.17 of the GICv3 spec following
+ * registers are save and restored on guest swap
+ */
+static void gicv3_save_state(struct vcpu *v)
+{
+
+ /* No need for spinlocks here because interrupts are disabled around
+ * this call and it only accesses struct vcpu fields that cannot be
+ * accessed simultaneously by another pCPU.
+ *
+ * Make sure all stores to the GIC via the memory mapped interface
+ * are now visible to the system register interface
+ */
+ dsb(sy);
+ gicv3_save_lrs(v);
+ save_aprn_regs(&v->arch.gic);
+ v->arch.gic.v3.vmcr = READ_SYSREG32(ICH_VMCR_EL2);
+ v->arch.gic.v3.sre_el1 = READ_SYSREG32(ICC_SRE_EL1);
+}
+
+static void gicv3_restore_state(const struct vcpu *v)
+{
+ WRITE_SYSREG32(v->arch.gic.v3.sre_el1, ICC_SRE_EL1);
+ WRITE_SYSREG32(v->arch.gic.v3.vmcr, ICH_VMCR_EL2);
+ restore_aprn_regs(&v->arch.gic);
+ gicv3_restore_lrs(v);
+
+ /*
+ * Make sure all stores are visible the GIC
+ */
+ dsb(sy);
+}
+
+static void gicv3_dump_state(const struct vcpu *v)
+{
+ int i;
+
+ if ( v == current )
+ {
+ for ( i = 0; i < gicv3_info.nr_lrs; i++ )
+ printk(" HW_LR[%d]=%lx\n", i, gicv3_ich_read_lr(i));
+ }
+ else
+ {
+ for ( i = 0; i < gicv3_info.nr_lrs; i++ )
+ printk(" VCPU_LR[%d]=%lx\n", i, v->arch.gic.v3.lr[i]);
+ }
+}
+
+static void gicv3_poke_irq(struct irq_desc *irqd, u32 offset)
+{
+ u32 mask = 1 << (irqd->irq % 32);
+ void __iomem *base;
+
+ if ( irqd->irq < NR_GIC_LOCAL_IRQS )
+ base = GICD_RDIST_SGI_BASE;
+ else
+ base = GICD;
+
+ writel_relaxed(mask, base + offset + (irqd->irq / 32) * 4);
+ gicv3_wait_for_rwp(irqd->irq);
+}
+
+static void gicv3_unmask_irq(struct irq_desc *irqd)
+{
+ gicv3_poke_irq(irqd, GICD_ISENABLER);
+}
+
+static void gicv3_mask_irq(struct irq_desc *irqd)
+{
+ gicv3_poke_irq(irqd, GICD_ICENABLER);
+}
+
+static void gicv3_eoi_irq(struct irq_desc *irqd)
+{
+ /* Lower the priority */
+ WRITE_SYSREG32(irqd->irq, ICC_EOIR1_EL1);
+ isb();
+}
+
+static void gicv3_dir_irq(struct irq_desc *irqd)
+{
+ /* Deactivate */
+ WRITE_SYSREG32(irqd->irq, ICC_DIR_EL1);
+ isb();
+}
+
+static unsigned int gicv3_read_irq(void)
+{
+ return READ_SYSREG32(ICC_IAR1_EL1);
+}
+
+static inline uint64_t gicv3_mpidr_to_affinity(int cpu)
+{
+ uint64_t mpidr = cpu_logical_map(cpu);
+ return (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 32 |
+ MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
+ MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
+ MPIDR_AFFINITY_LEVEL(mpidr, 0));
+}
+
+static void gicv3_set_irq_properties(struct irq_desc *desc,
+ const cpumask_t *cpu_mask,
+ unsigned int priority)
+{
+ uint32_t cfg, edgebit;
+ uint64_t affinity;
+ void __iomem *base;
+ unsigned int cpu = gicv3_get_cpu_from_mask(cpu_mask);
+ unsigned int irq = desc->irq;
+ unsigned int type = desc->arch.type;
+
+ /* SGI's are always edge-triggered not need to call GICD_ICFGR0 */
+ ASSERT(irq >= NR_GIC_SGI);
+
+ spin_lock(&gicv3.lock);
+
+ if ( irq >= NR_GIC_LOCAL_IRQS)
+ base = GICD + GICD_ICFGR + (irq / 16) * 4;
+ else
+ base = GICD_RDIST_SGI_BASE + GICR_ICFGR1;
+
+ cfg = readl_relaxed(base);
+
+ edgebit = 2u << (2 * (irq % 16));
+ if ( type & DT_IRQ_TYPE_LEVEL_MASK )
+ cfg &= ~edgebit;
+ else if ( type & DT_IRQ_TYPE_EDGE_BOTH )
+ cfg |= edgebit;
+
+ writel_relaxed(cfg, base);
+
+ affinity = gicv3_mpidr_to_affinity(cpu);
+ /* Make sure we don't broadcast the interrupt */
+ affinity &= ~GICD_IROUTER_SPI_MODE_ANY;
+
+ if ( irq >= NR_GIC_LOCAL_IRQS )
+ writeq_relaxed(affinity, (GICD + GICD_IROUTER + irq * 8));
+
+ /* Set priority */
+ if ( irq < NR_GIC_LOCAL_IRQS )
+ writeb_relaxed(priority, GICD_RDIST_SGI_BASE + GICR_IPRIORITYR0 + irq);
+ else
+ writeb_relaxed(priority, GICD + GICD_IPRIORITYR + irq);
+
+ spin_unlock(&gicv3.lock);
+}
+
+static void __init gicv3_dist_init(void)
+{
+ uint32_t type;
+ uint32_t priority;
+ uint64_t affinity;
+ int i;
+
+ /* Disable the distributor */
+ writel_relaxed(0, GICD + GICD_CTLR);
+
+ type = readl_relaxed(GICD + GICD_TYPER);
+ gicv3_info.nr_lines = 32 * ((type & GICD_TYPE_LINES) + 1);
+
+ printk("GICv3: %d lines, (IID %8.8x).\n",
+ gicv3_info.nr_lines, readl_relaxed(GICD + GICD_IIDR));
+
+ /* Default all global IRQs to level, active low */
+ for ( i = NR_GIC_LOCAL_IRQS; i < gicv3_info.nr_lines; i += 16 )
+ writel_relaxed(0, GICD + GICD_ICFGR + (i / 16) * 4);
+
+ /* Default priority for global interrupts */
+ for ( i = NR_GIC_LOCAL_IRQS; i < gicv3_info.nr_lines; i += 4 )
+ {
+ priority = (GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 |
+ GIC_PRI_IRQ << 8 | GIC_PRI_IRQ);
+ writel_relaxed(priority, GICD + GICD_IPRIORITYR + (i / 4) * 4);
+ }
+
+ /* Disable all global interrupts */
+ for ( i = NR_GIC_LOCAL_IRQS; i < gicv3_info.nr_lines; i += 32 )
+ writel_relaxed(0xffffffff, GICD + GICD_ICENABLER + (i / 32) * 4);
+
+ gicv3_dist_wait_for_rwp();
+
+ /* Turn on the distributor */
+ writel_relaxed(GICD_CTL_ENABLE | GICD_CTLR_ARE_NS |
+ GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1, GICD + GICD_CTLR);
+
+ /* Route all global IRQs to this CPU */
+ affinity = gicv3_mpidr_to_affinity(smp_processor_id());
+ /* Make sure we don't broadcast the interrupt */
+ affinity &= ~GICD_IROUTER_SPI_MODE_ANY;
+
+ for ( i = NR_GIC_LOCAL_IRQS; i < gicv3_info.nr_lines; i++ )
+ writeq_relaxed(affinity, GICD + GICD_IROUTER + i * 8);
+}
+
+static int gicv3_enable_redist(void)
+{
+ uint32_t val;
+ bool_t timeout = 0;
+ s_time_t deadline = NOW() + MILLISECS(1000);
+
+ /* Wake up this CPU redistributor */
+ val = readl_relaxed(GICD_RDIST_BASE + GICR_WAKER);
+ val &= ~GICR_WAKER_ProcessorSleep;
+ writel_relaxed(val, GICD_RDIST_BASE + GICR_WAKER);
+
+ do {
+ val = readl_relaxed(GICD_RDIST_BASE + GICR_WAKER);
+ if ( !(val & GICR_WAKER_ChildrenAsleep) )
+ break;
+ if ( NOW() > deadline )
+ {
+ timeout = 1;
+ break;
+ }
+ cpu_relax();
+ udelay(1);
+ } while ( timeout );
+
+ if ( timeout )
+ {
+ dprintk(XENLOG_ERR, "GICv3: Redist enable RWP timeout\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int __init gicv3_populate_rdist(void)
+{
+ int i;
+ uint32_t aff;
+ uint32_t reg;
+ uint64_t typer;
+ uint64_t mpidr = cpu_logical_map(smp_processor_id());
+
+ /*
+ * If we ever get a cluster of more than 16 CPUs, just scream.
+ */
+ if ( (mpidr & 0xff) >= 16 )
+ dprintk(XENLOG_WARNING, "GICv3:Cluster with more than 16's cpus\n");
+
+ /*
+ * Convert affinity to a 32bit value that can be matched to GICR_TYPER
+ * bits [63:32]
+ */
+ aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 |
+ MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
+ MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
+ MPIDR_AFFINITY_LEVEL(mpidr, 0));
+
+ for ( i = 0; i < gicv3.rdist_count; i++ )
+ {
+ void __iomem *ptr = gicv3.rdist_regions[i].map_base;
+
+ reg = readl_relaxed(ptr + GICR_PIDR2) & GICR_PIDR2_ARCH_REV_MASK;
+ if ( (reg >> GICR_PIDR2_ARCH_REV_SHIFT) != GICR_PIDR2_ARCH_GICV3 )
+ {
+ dprintk(XENLOG_ERR,
+ "GICv3: No redistributor present @%"PRIpaddr"\n",
+ gicv3.rdist_regions[i].base);
+ break;
+ }
+
+ do {
+ typer = readq_relaxed(ptr + GICR_TYPER);
+
+ if ( (typer >> 32) == aff )
+ {
+ this_cpu(rbase) = ptr;
+ printk("GICv3: CPU%d: Found redistributor in region %d @%p\n",
+ smp_processor_id(), i, ptr);
+ return 0;
+ }
+ if ( gicv3.rdist_stride )
+ ptr += gicv3.rdist_stride;
+ else
+ {
+ ptr += SZ_64K * 2;
+ if ( typer & GICR_TYPER_VLPIS )
+ ptr += SZ_64K * 2; /* Skip VLPI_base + reserved page */
+ }
+
+ } while ( !(typer & GICR_TYPER_LAST) );
+ }
+
+ dprintk(XENLOG_ERR, "GICv3: CPU%d: mpidr 0x%x has no re-distributor!\n",
+ smp_processor_id(), cpu_logical_map(smp_processor_id()));
+
+ return -ENODEV;
+}
+
+static int __cpuinit gicv3_cpu_init(void)
+{
+ int i;
+ uint32_t priority;
+
+ /* Register ourselves with the rest of the world */
+ if ( gicv3_populate_rdist() )
+ return -ENODEV;
+
+ if ( gicv3_enable_redist() )
+ return -ENODEV;
+
+ /* Set priority on PPI and SGI interrupts */
+ priority = (GIC_PRI_IPI << 24 | GIC_PRI_IPI << 16 | GIC_PRI_IPI << 8 |
+ GIC_PRI_IPI);
+ for (i = 0; i < NR_GIC_SGI; i += 4)
+ writel_relaxed(priority,
+ GICD_RDIST_SGI_BASE + GICR_IPRIORITYR0 + (i / 4) * 4);
+
+ priority = (GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 | GIC_PRI_IRQ << 8 |
+ GIC_PRI_IRQ);
+ for (i = NR_GIC_SGI; i < NR_GIC_LOCAL_IRQS; i += 4)
+ writel_relaxed(priority,
+ GICD_RDIST_SGI_BASE + GICR_IPRIORITYR0 + (i / 4) * 4);
+
+ /*
+ * Disable all PPI interrupts, ensure all SGI interrupts are
+ * enabled.
+ */
+ writel_relaxed(0xffff0000, GICD_RDIST_SGI_BASE + GICR_ICENABLER0);
+ writel_relaxed(0x0000ffff, GICD_RDIST_SGI_BASE + GICR_ISENABLER0);
+
+ gicv3_redist_wait_for_rwp();
+
+ /* Enable system registers */
+ gicv3_enable_sre();
+
+ /* No priority grouping */
+ WRITE_SYSREG32(0, ICC_BPR1_EL1);
+
+ /* Set priority mask register */
+ WRITE_SYSREG32(DEFAULT_PMR_VALUE, ICC_PMR_EL1);
+
+ /* EOI drops priority too (mode 0) */
+ WRITE_SYSREG32(GICC_CTLR_EL1_EOImode_drop, ICC_CTLR_EL1);
+
+ /* Enable Group1 interrupts */
+ WRITE_SYSREG32(1, ICC_IGRPEN1_EL1);
+
+ /* Sync at once at the end of cpu interface configuration */
+ isb();
+
+ return 0;
+}
+
+static void gicv3_cpu_disable(void)
+{
+ WRITE_SYSREG32(0, ICC_CTLR_EL1);
+ isb();
+}
+
+static void __cpuinit gicv3_hyp_init(void)
+{
+ uint32_t vtr;
+
+ vtr = READ_SYSREG32(ICH_VTR_EL2);
+ gicv3_info.nr_lrs = (vtr & GICH_VTR_NRLRGS) + 1;
+ gicv3.nr_priorities = ((vtr >> GICH_VTR_PRIBITS_SHIFT) &
+ GICH_VTR_PRIBITS_MASK) + 1;
+
+ if ( !((gicv3.nr_priorities > 4) && (gicv3.nr_priorities < 8)) )
+ panic("GICv3: Invalid number of priority bits\n");
+
+ WRITE_SYSREG32(GICH_VMCR_EOI | GICH_VMCR_VENG1, ICH_VMCR_EL2);
+ WRITE_SYSREG32(GICH_HCR_EN, ICH_HCR_EL2);
+}
+
+/* Set up the per-CPU parts of the GIC for a secondary CPU */
+static int gicv3_secondary_cpu_init(void)
+{
+ int res;
+
+ spin_lock(&gicv3.lock);
+
+ res = gicv3_cpu_init();
+ gicv3_hyp_init();
+
+ spin_unlock(&gicv3.lock);
+
+ return res;
+}
+
+static void __cpuinit gicv3_hyp_disable(void)
+{
+ uint32_t hcr;
+
+ hcr = READ_SYSREG32(ICH_HCR_EL2);
+ hcr &= ~GICH_HCR_EN;
+ WRITE_SYSREG32(hcr, ICH_HCR_EL2);
+ isb();
+}
+
+static u16 gicv3_compute_target_list(int *base_cpu, const struct cpumask *mask,
+ uint64_t cluster_id)
+{
+ int cpu = *base_cpu;
+ uint64_t mpidr = cpu_logical_map(cpu);
+ u16 tlist = 0;
+
+ while ( cpu < nr_cpu_ids )
+ {
+ /*
+ * Assume that each cluster does not have more than 16 CPU's.
+ * Check is made during GICv3 initialization (gicv3_populate_rdist())
+ * on mpidr value for this. So skip this check here.
+ */
+ tlist |= 1 << (mpidr & 0xf);
+
+ cpu = cpumask_next(cpu, mask);
+ if ( cpu == nr_cpu_ids )
+ {
+ cpu--;
+ goto out;
+ }
+
+ mpidr = cpu_logical_map(cpu);
+ if ( cluster_id != (mpidr & ~MPIDR_AFF0_MASK) ) {
+ cpu--;
+ goto out;
+ }
+ }
+out:
+ *base_cpu = cpu;
+
+ return tlist;
+}
+
+static void gicv3_send_sgi(enum gic_sgi sgi, enum gic_sgi_mode mode,
+ const cpumask_t *cpumask)
+{
+ int cpu = 0;
+ uint64_t val;
+
+ for_each_cpu(cpu, cpumask)
+ {
+ /* Mask lower 8 bits. It represent cpu in affinity level 0 */
+ uint64_t cluster_id = cpu_logical_map(cpu) & ~MPIDR_AFF0_MASK;
+ u16 tlist;
+
+ /* Get targetlist for the cluster to send SGI */
+ tlist = gicv3_compute_target_list(&cpu, cpumask, cluster_id);
+
+ /*
+ * Prepare affinity path of the cluster for which SGI is generated
+ * along with SGI number
+ */
+ val = (MPIDR_AFFINITY_LEVEL(cluster_id, 3) << 48 |
+ MPIDR_AFFINITY_LEVEL(cluster_id, 2) << 32 |
+ sgi << 24 |
+ MPIDR_AFFINITY_LEVEL(cluster_id, 1) << 16 |
+ tlist);
+
+ WRITE_SYSREG(val, ICC_SGI1R_EL1);
+ }
+ /* Force above writes to ICC_SGI1R_EL1 */
+ isb();
+}
+
+/* Shut down the per-CPU GIC interface */
+static void gicv3_disable_interface(void)
+{
+ spin_lock(&gicv3.lock);
+
+ gicv3_cpu_disable();
+ gicv3_hyp_disable();
+
+ spin_unlock(&gicv3.lock);
+}
+
+static void gicv3_update_lr(int lr, const struct pending_irq *p,
+ unsigned int state)
+{
+ uint64_t grp = GICH_LR_GRP1;
+ uint64_t val = 0;
+
+ BUG_ON(lr >= gicv3_info.nr_lrs);
+ BUG_ON(lr < 0);
+
+ val = (((uint64_t)state & 0x3) << GICH_LR_STATE_SHIFT) | grp;
+ val |= ((uint64_t)p->priority & 0xff) << GICH_LR_PRIORITY_SHIFT;
+ val |= ((uint64_t)p->irq & GICH_LR_VIRTUAL_MASK) << GICH_LR_VIRTUAL_SHIFT;
+
+ if ( p->desc != NULL )
+ val |= GICH_LR_HW | (((uint64_t)p->desc->irq & GICH_LR_PHYSICAL_MASK)
+ << GICH_LR_PHYSICAL_SHIFT);
+
+ gicv3_ich_write_lr(lr, val);
+}
+
+static void gicv3_clear_lr(int lr)
+{
+ gicv3_ich_write_lr(lr, 0);
+}
+
+static void gicv3_read_lr(int lr, struct gic_lr *lr_reg)
+{
+ uint64_t lrv;
+
+ lrv = gicv3_ich_read_lr(lr);
+
+ lr_reg->pirq = (lrv >> GICH_LR_PHYSICAL_SHIFT) & GICH_LR_PHYSICAL_MASK;
+ lr_reg->virq = (lrv >> GICH_LR_VIRTUAL_SHIFT) & GICH_LR_VIRTUAL_MASK;
+
+ lr_reg->priority = (lrv >> GICH_LR_PRIORITY_SHIFT) & GICH_LR_PRIORITY_MASK;
+ lr_reg->state = (lrv >> GICH_LR_STATE_SHIFT) & GICH_LR_STATE_MASK;
+ lr_reg->hw_status = (lrv >> GICH_LR_HW_SHIFT) & GICH_LR_HW_MASK;
+ lr_reg->grp = (lrv >> GICH_LR_GRP_SHIFT) & GICH_LR_GRP_MASK;
+}
+
+static void gicv3_write_lr(int lr_reg, const struct gic_lr *lr)
+{
+ uint64_t lrv = 0;
+
+ lrv = ( ((u64)(lr->pirq & GICH_LR_PHYSICAL_MASK) << GICH_LR_PHYSICAL_SHIFT)|
+ ((u64)(lr->virq & GICH_LR_VIRTUAL_MASK) << GICH_LR_VIRTUAL_SHIFT) |
+ ((u64)(lr->priority & GICH_LR_PRIORITY_MASK) << GICH_LR_PRIORITY_SHIFT)|
+ ((u64)(lr->state & GICH_LR_STATE_MASK) << GICH_LR_STATE_SHIFT) |
+ ((u64)(lr->hw_status & GICH_LR_HW_MASK) << GICH_LR_HW_SHIFT) |
+ ((u64)(lr->grp & GICH_LR_GRP_MASK) << GICH_LR_GRP_SHIFT) );
+
+ gicv3_ich_write_lr(lr_reg, lrv);
+}
+
+static int gicv_v3_init(struct domain *d)
+{
+ int i;
+
+ /*
+ * Domain 0 gets the hardware address.
+ * Guests get the virtual platform layout.
+ */
+ if ( is_hardware_domain(d) )
+ {
+ d->arch.vgic.dbase = gicv3.dbase;
+ d->arch.vgic.dbase_size = gicv3.dbase_size;
+ for ( i = 0; i < gicv3.rdist_count; i++ )
+ {
+ d->arch.vgic.rbase[i] = gicv3.rdist_regions[i].base;
+ d->arch.vgic.rbase_size[i] = gicv3.rdist_regions[i].size;
+ }
+ d->arch.vgic.rdist_stride = gicv3.rdist_stride;
+ d->arch.vgic.rdist_count = gicv3.rdist_count;
+ }
+ else
+ {
+ d->arch.vgic.dbase = GUEST_GICV3_GICD_BASE;
+ d->arch.vgic.dbase_size = GUEST_GICV3_GICD_SIZE;
+
+ /* XXX: Only one Re-distributor region mapped for the guest */
+ BUILD_BUG_ON(GUEST_GICV3_RDIST_REGIONS != 1);
+
+ d->arch.vgic.rdist_count = GUEST_GICV3_RDIST_REGIONS;
+ d->arch.vgic.rdist_stride = GUEST_GICV3_RDIST_STRIDE;
+
+ /* The first redistributor should contain enough space for all CPUs */
+ BUILD_BUG_ON((GUEST_GICV3_GICR0_SIZE / GUEST_GICV3_RDIST_STRIDE) < MAX_VIRT_CPUS);
+ d->arch.vgic.rbase[0] = GUEST_GICV3_GICR0_BASE;
+ d->arch.vgic.rbase_size[0] = GUEST_GICV3_GICR0_SIZE;
+ }
+
+ d->arch.vgic.nr_lines = 0;
+
+ return 0;
+}
+
+static void gicv3_hcr_status(uint32_t flag, bool_t status)
+{
+ uint32_t hcr;
+
+ hcr = READ_SYSREG32(ICH_HCR_EL2);
+ if ( status )
+ WRITE_SYSREG32(hcr | flag, ICH_HCR_EL2);
+ else
+ WRITE_SYSREG32(hcr & (~flag), ICH_HCR_EL2);
+ isb();
+}
+
+static unsigned int gicv3_read_vmcr_priority(void)
+{
+ return ((READ_SYSREG32(ICH_VMCR_EL2) >> GICH_VMCR_PRIORITY_SHIFT) &
+ GICH_VMCR_PRIORITY_MASK);
+}
+
+/* Only support reading GRP1 APRn registers */
+static unsigned int gicv3_read_apr(int apr_reg)
+{
+ switch ( apr_reg )
+ {
+ case 0:
+ ASSERT(gicv3.nr_priorities > 4 && gicv3.nr_priorities < 8);
+ return READ_SYSREG32(ICH_AP1R0_EL2);
+ case 1:
+ ASSERT(gicv3.nr_priorities > 5 && gicv3.nr_priorities < 8);
+ return READ_SYSREG32(ICH_AP1R1_EL2);
+ case 2:
+ ASSERT(gicv3.nr_priorities > 6 && gicv3.nr_priorities < 8);
+ return READ_SYSREG32(ICH_AP1R2_EL2);
+ default:
+ BUG();
+ }
+}
+
+static void gicv3_irq_enable(struct irq_desc *desc)
+{
+ unsigned long flags;
+
+ ASSERT(spin_is_locked(&desc->lock));
+
+ spin_lock_irqsave(&gicv3.lock, flags);
+ clear_bit(_IRQ_DISABLED, &desc->status);
+ dsb(sy);
+ /* Enable routing */
+ gicv3_unmask_irq(desc);
+ spin_unlock_irqrestore(&gicv3.lock, flags);
+}
+
+static void gicv3_irq_disable(struct irq_desc *desc)
+{
+ unsigned long flags;
+
+ ASSERT(spin_is_locked(&desc->lock));
+
+ spin_lock_irqsave(&gicv3.lock, flags);
+ /* Disable routing */
+ gicv3_mask_irq(desc);
+ set_bit(_IRQ_DISABLED, &desc->status);
+ spin_unlock_irqrestore(&gicv3.lock, flags);
+}
+
+static unsigned int gicv3_irq_startup(struct irq_desc *desc)
+{
+ gicv3_irq_enable(desc);
+
+ return 0;
+}
+
+static void gicv3_irq_shutdown(struct irq_desc *desc)
+{
+ gicv3_irq_disable(desc);
+}
+
+static void gicv3_irq_ack(struct irq_desc *desc)
+{
+ /* No ACK -- reading IAR has done this for us */
+}
+
+static void gicv3_host_irq_end(struct irq_desc *desc)
+{
+ /* Lower the priority */
+ gicv3_eoi_irq(desc);
+ /* Deactivate */
+ gicv3_dir_irq(desc);
+}
+
+static void gicv3_guest_irq_end(struct irq_desc *desc)
+{
+ /* Lower the priority of the IRQ */
+ gicv3_eoi_irq(desc);
+ /* Deactivation happens in maintenance interrupt / via GICV */
+}
+
+static void gicv3_irq_set_affinity(struct irq_desc *desc, const cpumask_t *mask)
+{
+ unsigned int cpu;
+ uint64_t affinity;
+
+ ASSERT(!cpumask_empty(mask));
+
+ spin_lock(&gicv3.lock);
+
+ cpu = gicv3_get_cpu_from_mask(mask);
+ affinity = gicv3_mpidr_to_affinity(cpu);
+ /* Make sure we don't broadcast the interrupt */
+ affinity &= ~GICD_IROUTER_SPI_MODE_ANY;
+
+ if ( desc->irq >= NR_GIC_LOCAL_IRQS )
+ writeq_relaxed(affinity, (GICD + GICD_IROUTER + desc->irq * 8));
+
+ spin_unlock(&gicv3.lock);
+}
+
+static int gicv3_make_dt_node(const struct domain *d,
+ const struct dt_device_node *node, void *fdt)
+{
+ const struct dt_device_node *gic = dt_interrupt_controller;
+ const void *compatible = NULL;
+ uint32_t len;
+ __be32 *new_cells, *tmp;
+ uint32_t rd_stride = 0;
+ uint32_t rd_count = 0;
+
+ int i, res = 0;
+
+ compatible = dt_get_property(gic, "compatible", &len);
+ if ( !compatible )
+ {
+ dprintk(XENLOG_ERR, "Can't find compatible property for the gic node\n");
+ return -FDT_ERR_XEN(ENOENT);
+ }
+
+ res = fdt_begin_node(fdt, "interrupt-controller");
+ if ( res )
+ return res;
+
+ res = fdt_property(fdt, "compatible", compatible, len);
+ if ( res )
+ return res;
+
+ res = fdt_property_cell(fdt, "#interrupt-cells", 3);
+ if ( res )
+ return res;
+
+ res = fdt_property(fdt, "interrupt-controller", NULL, 0);
+ if ( res )
+ return res;
+
+ res = dt_property_read_u32(gic, "redistributor-stride", &rd_stride);
+ if ( !res )
+ rd_stride = 0;
+
+ res = dt_property_read_u32(gic, "#redistributor-regions", &rd_count);
+ if ( !res )
+ rd_count = 1;
+
+ res = fdt_property_cell(fdt, "redistributor-stride", rd_stride);
+ if ( res )
+ return res;
+
+ res = fdt_property_cell(fdt, "#redistributor-regions", rd_count);
+ if ( res )
+ return res;
+
+ len = dt_cells_to_size(dt_n_addr_cells(node) + dt_n_size_cells(node));
+ /*
+ * GIC has two memory regions: Distributor + rdist regions
+ * CPU interface and virtual cpu interfaces accessesed as System registers
+ * So cells are created only for Distributor and rdist regions
+ */
+ len = len * (d->arch.vgic.rdist_count + 1);
+ new_cells = xzalloc_bytes(len);
+ if ( new_cells == NULL )
+ return -FDT_ERR_XEN(ENOMEM);
+
+ tmp = new_cells;
+
+ dt_set_range(&tmp, node, d->arch.vgic.dbase, d->arch.vgic.dbase_size);
+
+ for ( i = 0; i < d->arch.vgic.rdist_count; i++ )
+ dt_set_range(&tmp, node, d->arch.vgic.rbase[i],
+ d->arch.vgic.rbase_size[i]);
+
+ res = fdt_property(fdt, "reg", new_cells, len);
+ xfree(new_cells);
+
+ return res;
+}
+
+static const hw_irq_controller gicv3_host_irq_type = {
+ .typename = "gic-v3",
+ .startup = gicv3_irq_startup,
+ .shutdown = gicv3_irq_shutdown,
+ .enable = gicv3_irq_enable,
+ .disable = gicv3_irq_disable,
+ .ack = gicv3_irq_ack,
+ .end = gicv3_host_irq_end,
+ .set_affinity = gicv3_irq_set_affinity,
+};
+
+static const hw_irq_controller gicv3_guest_irq_type = {
+ .typename = "gic-v3",
+ .startup = gicv3_irq_startup,
+ .shutdown = gicv3_irq_shutdown,
+ .enable = gicv3_irq_enable,
+ .disable = gicv3_irq_disable,
+ .ack = gicv3_irq_ack,
+ .end = gicv3_guest_irq_end,
+ .set_affinity = gicv3_irq_set_affinity,
+};
+
+static const struct gic_hw_operations gicv3_ops = {
+ .info = &gicv3_info,
+ .save_state = gicv3_save_state,
+ .restore_state = gicv3_restore_state,
+ .dump_state = gicv3_dump_state,
+ .gicv_setup = gicv_v3_init,
+ .gic_host_irq_type = &gicv3_host_irq_type,
+ .gic_guest_irq_type = &gicv3_guest_irq_type,
+ .eoi_irq = gicv3_eoi_irq,
+ .deactivate_irq = gicv3_dir_irq,
+ .read_irq = gicv3_read_irq,
+ .set_irq_properties = gicv3_set_irq_properties,
+ .send_SGI = gicv3_send_sgi,
+ .disable_interface = gicv3_disable_interface,
+ .update_lr = gicv3_update_lr,
+ .update_hcr_status = gicv3_hcr_status,
+ .clear_lr = gicv3_clear_lr,
+ .read_lr = gicv3_read_lr,
+ .write_lr = gicv3_write_lr,
+ .read_vmcr_priority = gicv3_read_vmcr_priority,
+ .read_apr = gicv3_read_apr,
+ .secondary_init = gicv3_secondary_cpu_init,
+ .make_dt_node = gicv3_make_dt_node,
+};
+
+/* Set up the GIC */
+static int __init gicv3_init(struct dt_device_node *node, const void *data)
+{
+ struct rdist_region *rdist_regs;
+ int res, i;
+ uint32_t reg;
+
+ if ( !cpu_has_gicv3 )
+ {
+ dprintk(XENLOG_ERR, "GICv3: driver requires system register support\n");
+ return -ENODEV;
+ }
+
+ dt_device_set_used_by(node, DOMID_XEN);
+
+ res = dt_device_get_address(node, 0, &gicv3.dbase, &gicv3.dbase_size);
+ if ( res || !gicv3.dbase )
+ panic("GICv3: Cannot find a valid distributor address");
+
+ if ( (gicv3.dbase & ~PAGE_MASK) || (gicv3.dbase_size & ~PAGE_MASK) )
+ panic("GICv3: Found unaligned distributor address %"PRIpaddr"",
+ gicv3.dbase);
+
+ gicv3.map_dbase = ioremap_nocache(gicv3.dbase, gicv3.dbase_size);
+ if ( !gicv3.map_dbase )
+ panic("GICv3: Failed to ioremap for GIC distributor\n");
+
+ reg = readl_relaxed(GICD + GICD_PIDR2) & GICD_PIDR2_ARCH_REV_MASK;
+ if ( ((reg >> GICD_PIDR2_ARCH_REV_SHIFT) != GICD_PIDR2_ARCH_GICV3) )
+ panic("GICv3: no distributor detected\n");
+
+ if ( !dt_property_read_u32(node, "#redistributor-regions",
+ &gicv3.rdist_count) )
+ gicv3.rdist_count = 1;
+
+ if ( gicv3.rdist_count > MAX_RDIST_COUNT )
+ panic("GICv3: Number of redistributor regions is more than"
+ "%d (Increase MAX_RDIST_COUNT!!)\n", MAX_RDIST_COUNT);
+
+ rdist_regs = xzalloc_array(struct rdist_region, gicv3.rdist_count);
+ if ( !rdist_regs )
+ panic("GICv3: Failed to allocate memory for rdist regions\n");
+
+ for ( i = 0; i < gicv3.rdist_count; i++ )
+ {
+ uint64_t rdist_base, rdist_size;
+
+ res = dt_device_get_address(node, 1 + i, &rdist_base, &rdist_size);
+ if ( res || !rdist_base )
+ panic("GICv3: No rdist base found for region %d\n", i);
+
+ rdist_regs[i].base = rdist_base;
+ rdist_regs[i].size = rdist_size;
+ }
+
+ /* If stride is not set in dt. Set default to 2 * SZ_64K */
+ if ( !dt_property_read_u32(node, "redistributor-stride", &gicv3.rdist_stride) )
+ gicv3.rdist_stride = 0;
+
+ gicv3.rdist_regions= rdist_regs;
+
+ res = platform_get_irq(node, 0);
+ if ( res < 0 )
+ panic("GICv3: Cannot find the maintenance IRQ");
+ gicv3_info.maintenance_irq = res;
+
+ /* Set the GIC as the primary interrupt controller */
+ dt_interrupt_controller = node;
+
+ for ( i = 0; i < gicv3.rdist_count; i++ )
+ {
+ /* map dbase & rdist regions */
+ gicv3.rdist_regions[i].map_base =
+ ioremap_nocache(gicv3.rdist_regions[i].base,
+ gicv3.rdist_regions[i].size);
+
+ if ( !gicv3.rdist_regions[i].map_base )
+ panic("GICv3: Failed to ioremap rdist region for region %d\n", i);
+ }
+
+ printk("GICv3 initialization:\n"
+ " gic_dist_addr=%"PRIpaddr"\n"
+ " gic_dist_size=%"PRIpaddr"\n"
+ " gic_dist_mapaddr=%p\n"
+ " gic_rdist_regions=%d\n"
+ " gic_rdist_stride=%x\n"
+ " gic_rdist_base=%"PRIpaddr"\n"
+ " gic_rdist_base_size=%"PRIpaddr"\n"
+ " gic_rdist_base_mapaddr=%p\n"
+ " gic_maintenance_irq=%u\n",
+ gicv3.dbase, gicv3.dbase_size, gicv3.map_dbase, gicv3.rdist_count,
+ gicv3.rdist_stride, gicv3.rdist_regions[0].base,
+ gicv3.rdist_regions[0].size, gicv3.rdist_regions[0].map_base,
+ gicv3_info.maintenance_irq);
+
+ spin_lock_init(&gicv3.lock);
+
+ spin_lock(&gicv3.lock);
+
+ gicv3_dist_init();
+ res = gicv3_cpu_init();
+ gicv3_hyp_init();
+
+ gicv3_info.hw_version = GIC_V3;
+ /* Register hw ops*/
+ register_gic_ops(&gicv3_ops);
+
+ spin_unlock(&gicv3.lock);
+
+ return res;
+}
+
+static const char * const gicv3_dt_compat[] __initconst =
+{
+ DT_COMPAT_GIC_V3,
+ NULL
+};
+
+DT_DEVICE_START(gicv3, "GICv3", DEVICE_GIC)
+ .compatible = gicv3_dt_compat,
+ .init = gicv3_init,
+DT_DEVICE_END
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 074624e..e7a1af5 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -24,354 +24,123 @@
#include <xen/irq.h>
#include <xen/sched.h>
#include <xen/errno.h>
-#include <xen/serial.h>
#include <xen/softirq.h>
#include <xen/list.h>
#include <xen/device_tree.h>
#include <asm/p2m.h>
#include <asm/domain.h>
#include <asm/platform.h>
-
+#include <asm/device.h>
+#include <asm/io.h>
#include <asm/gic.h>
+#include <asm/vgic.h>
-/* Access to the GIC Distributor registers through the fixmap */
-#define GICD ((volatile uint32_t *) FIXMAP_ADDR(FIXMAP_GICD))
-#define GICC ((volatile uint32_t *) FIXMAP_ADDR(FIXMAP_GICC1))
-#define GICH ((volatile uint32_t *) FIXMAP_ADDR(FIXMAP_GICH))
static void gic_restore_pending_irqs(struct vcpu *v);
-/* Global state */
-static struct {
- paddr_t dbase; /* Address of distributor registers */
- paddr_t cbase; /* Address of CPU interface registers */
- paddr_t hbase; /* Address of virtual interface registers */
- paddr_t vbase; /* Address of virtual cpu interface registers */
- unsigned int lines; /* Number of interrupts (SPIs + PPIs + SGIs) */
- struct dt_irq maintenance; /* IRQ maintenance */
- unsigned int cpus;
- spinlock_t lock;
-} gic;
-
-static irq_desc_t irq_desc[NR_IRQS];
-static DEFINE_PER_CPU(irq_desc_t[NR_LOCAL_IRQS], local_irq_desc);
static DEFINE_PER_CPU(uint64_t, lr_mask);
-static unsigned nr_lrs;
+#define lr_all_full() (this_cpu(lr_mask) == ((1 << gic_hw_ops->info->nr_lrs) - 1))
-/* The GIC mapping of CPU interfaces does not necessarily match the
- * logical CPU numbering. Let's use mapping as returned by the GIC
- * itself
- */
-static DEFINE_PER_CPU(u8, gic_cpu_id);
+#undef GIC_DEBUG
-/* Maximum cpu interface per GIC */
-#define NR_GIC_CPU_IF 8
+static void gic_update_one_lr(struct vcpu *v, int i);
-static unsigned int gic_cpu_mask(const cpumask_t *cpumask)
-{
- unsigned int cpu;
- unsigned int mask = 0;
- cpumask_t possible_mask;
+static const struct gic_hw_operations *gic_hw_ops;
- cpumask_and(&possible_mask, cpumask, &cpu_possible_map);
- for_each_cpu(cpu, &possible_mask)
- {
- ASSERT(cpu < NR_GIC_CPU_IF);
- mask |= per_cpu(gic_cpu_id, cpu);
- }
+void register_gic_ops(const struct gic_hw_operations *ops)
+{
+ gic_hw_ops = ops;
+}
- return mask;
+static void clear_cpu_lr_mask(void)
+{
+ this_cpu(lr_mask) = 0ULL;
}
-unsigned int gic_number_lines(void)
+enum gic_version gic_hw_version(void)
{
- return gic.lines;
+ return gic_hw_ops->info->hw_version;
}
-irq_desc_t *__irq_to_desc(int irq)
+unsigned int gic_number_lines(void)
{
- if (irq < NR_LOCAL_IRQS) return &this_cpu(local_irq_desc)[irq];
- return &irq_desc[irq-NR_LOCAL_IRQS];
+ return gic_hw_ops->info->nr_lines;
}
void gic_save_state(struct vcpu *v)
{
- int i;
ASSERT(!local_irq_is_enabled());
+ ASSERT(!is_idle_vcpu(v));
/* No need for spinlocks here because interrupts are disabled around
* this call and it only accesses struct vcpu fields that cannot be
* accessed simultaneously by another pCPU.
*/
- for ( i=0; i<nr_lrs; i++)
- v->arch.gic_lr[i] = GICH[GICH_LR + i];
v->arch.lr_mask = this_cpu(lr_mask);
- v->arch.gic_apr = GICH[GICH_APR];
- v->arch.gic_vmcr = GICH[GICH_VMCR];
- /* Disable until next VCPU scheduled */
- GICH[GICH_HCR] = 0;
+ gic_hw_ops->save_state(v);
isb();
}
void gic_restore_state(struct vcpu *v)
{
- int i;
-
- if ( is_idle_vcpu(v) )
- return;
+ ASSERT(!local_irq_is_enabled());
+ ASSERT(!is_idle_vcpu(v));
this_cpu(lr_mask) = v->arch.lr_mask;
- for ( i=0; i<nr_lrs; i++)
- GICH[GICH_LR + i] = v->arch.gic_lr[i];
- GICH[GICH_APR] = v->arch.gic_apr;
- GICH[GICH_VMCR] = v->arch.gic_vmcr;
- GICH[GICH_HCR] = GICH_HCR_EN;
+ gic_hw_ops->restore_state(v);
+
isb();
gic_restore_pending_irqs(v);
}
-static void gic_irq_enable(struct irq_desc *desc)
-{
- int irq = desc->irq;
- unsigned long flags;
-
- spin_lock_irqsave(&desc->lock, flags);
- spin_lock(&gic.lock);
- desc->status &= ~IRQ_DISABLED;
- dsb();
- /* Enable routing */
- GICD[GICD_ISENABLER + irq / 32] = (1u << (irq % 32));
- spin_unlock(&gic.lock);
- spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-static void gic_irq_disable(struct irq_desc *desc)
-{
- int irq = desc->irq;
- unsigned long flags;
-
- spin_lock_irqsave(&desc->lock, flags);
- spin_lock(&gic.lock);
- /* Disable routing */
- GICD[GICD_ICENABLER + irq / 32] = (1u << (irq % 32));
- desc->status |= IRQ_DISABLED;
- spin_unlock(&gic.lock);
- spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-static unsigned int gic_irq_startup(struct irq_desc *desc)
-{
- gic_irq_enable(desc);
- return 0;
-}
-
-static void gic_irq_shutdown(struct irq_desc *desc)
-{
- gic_irq_disable(desc);
-}
-
-static void gic_irq_ack(struct irq_desc *desc)
-{
- /* No ACK -- reading IAR has done this for us */
-}
-
-static void gic_host_irq_end(struct irq_desc *desc)
-{
- int irq = desc->irq;
- /* Lower the priority */
- GICC[GICC_EOIR] = irq;
- /* Deactivate */
- GICC[GICC_DIR] = irq;
-}
-
-static void gic_guest_irq_end(struct irq_desc *desc)
-{
- int irq = desc->irq;
- /* Lower the priority of the IRQ */
- GICC[GICC_EOIR] = irq;
- /* Deactivation happens in maintenance interrupt / via GICV */
-}
-
-static void gic_irq_set_affinity(struct irq_desc *desc, const cpumask_t *mask)
-{
- BUG();
-}
-
-/* XXX different for level vs edge */
-static hw_irq_controller gic_host_irq_type = {
- .typename = "gic",
- .startup = gic_irq_startup,
- .shutdown = gic_irq_shutdown,
- .enable = gic_irq_enable,
- .disable = gic_irq_disable,
- .ack = gic_irq_ack,
- .end = gic_host_irq_end,
- .set_affinity = gic_irq_set_affinity,
-};
-static hw_irq_controller gic_guest_irq_type = {
- .typename = "gic",
- .startup = gic_irq_startup,
- .shutdown = gic_irq_shutdown,
- .enable = gic_irq_enable,
- .disable = gic_irq_disable,
- .ack = gic_irq_ack,
- .end = gic_guest_irq_end,
- .set_affinity = gic_irq_set_affinity,
-};
-
/*
- * - needs to be called with gic.lock held
- * - needs to be called with a valid cpu_mask, ie each cpu in the mask has
+ * needs to be called with a valid cpu_mask, ie each cpu in the mask has
* already called gic_cpu_init
+ * - desc.lock must be held
+ * - arch.type must be valid (i.e != DT_IRQ_TYPE_INVALID)
*/
-static void gic_set_irq_properties(unsigned int irq, bool_t level,
+static void gic_set_irq_properties(struct irq_desc *desc,
const cpumask_t *cpu_mask,
unsigned int priority)
{
- volatile unsigned char *bytereg;
- uint32_t cfg, edgebit;
- unsigned int mask = gic_cpu_mask(cpu_mask);
-
- /* Set edge / level */
- cfg = GICD[GICD_ICFGR + irq / 16];
- edgebit = 2u << (2 * (irq % 16));
- if ( level )
- cfg &= ~edgebit;
- else
- cfg |= edgebit;
- GICD[GICD_ICFGR + irq / 16] = cfg;
-
- /* Set target CPU mask (RAZ/WI on uniprocessor) */
- bytereg = (unsigned char *) (GICD + GICD_ITARGETSR);
- bytereg[irq] = mask;
-
- /* Set priority */
- bytereg = (unsigned char *) (GICD + GICD_IPRIORITYR);
- bytereg[irq] = priority;
-
+ gic_hw_ops->set_irq_properties(desc, cpu_mask, priority);
}
-/* Program the GIC to route an interrupt */
-static int gic_route_irq(unsigned int irq, bool_t level,
- const cpumask_t *cpu_mask, unsigned int priority)
+/* Program the GIC to route an interrupt to the host (i.e. Xen)
+ * - needs to be called with desc.lock held
+ */
+void gic_route_irq_to_xen(struct irq_desc *desc, const cpumask_t *cpu_mask,
+ unsigned int priority)
{
- struct irq_desc *desc = irq_to_desc(irq);
- unsigned long flags;
-
ASSERT(priority <= 0xff); /* Only 8 bits of priority */
- ASSERT(irq < gic.lines); /* Can't route interrupts that don't exist */
-
- if ( desc->action != NULL )
- return -EBUSY;
-
- /* Disable interrupt */
- desc->handler->shutdown(desc);
-
- spin_lock_irqsave(&desc->lock, flags);
-
- desc->handler = &gic_host_irq_type;
+ ASSERT(desc->irq < gic_number_lines());/* Can't route interrupts that don't exist */
+ ASSERT(test_bit(_IRQ_DISABLED, &desc->status));
+ ASSERT(spin_is_locked(&desc->lock));
- spin_lock(&gic.lock);
- gic_set_irq_properties(irq, level, cpu_mask, priority);
- spin_unlock(&gic.lock);
+ desc->handler = gic_hw_ops->gic_host_irq_type;
- spin_unlock_irqrestore(&desc->lock, flags);
- return 0;
-}
-
-/* Program the GIC to route an interrupt with a dt_irq */
-void gic_route_dt_irq(const struct dt_irq *irq, const cpumask_t *cpu_mask,
- unsigned int priority)
-{
- bool_t level;
-
- level = dt_irq_is_level_triggered(irq);
-
- gic_route_irq(irq->irq, level, cpu_mask, priority);
-}
-
-static void __init gic_dist_init(void)
-{
- uint32_t type;
- uint32_t cpumask;
- int i;
-
- cpumask = GICD[GICD_ITARGETSR] & 0xff;
- cpumask |= cpumask << 8;
- cpumask |= cpumask << 16;
-
- /* Disable the distributor */
- GICD[GICD_CTLR] = 0;
-
- type = GICD[GICD_TYPER];
- gic.lines = 32 * ((type & GICD_TYPE_LINES) + 1);
- gic.cpus = 1 + ((type & GICD_TYPE_CPUS) >> 5);
- printk("GIC: %d lines, %d cpu%s%s (IID %8.8x).\n",
- gic.lines, gic.cpus, (gic.cpus == 1) ? "" : "s",
- (type & GICD_TYPE_SEC) ? ", secure" : "",
- GICD[GICD_IIDR]);
-
- /* Default all global IRQs to level, active low */
- for ( i = 32; i < gic.lines; i += 16 )
- GICD[GICD_ICFGR + i / 16] = 0x0;
-
- /* Route all global IRQs to this CPU */
- for ( i = 32; i < gic.lines; i += 4 )
- GICD[GICD_ITARGETSR + i / 4] = cpumask;
-
- /* Default priority for global interrupts */
- for ( i = 32; i < gic.lines; i += 4 )
- GICD[GICD_IPRIORITYR + i / 4] = 0xa0a0a0a0;
-
- /* Disable all global interrupts */
- for ( i = 32; i < gic.lines; i += 32 )
- GICD[GICD_ICENABLER + i / 32] = (uint32_t)~0ul;
-
- /* Turn on the distributor */
- GICD[GICD_CTLR] = GICD_CTL_ENABLE;
+ gic_set_irq_properties(desc, cpu_mask, priority);
}
-static void __cpuinit gic_cpu_init(void)
-{
- int i;
-
- this_cpu(gic_cpu_id) = GICD[GICD_ITARGETSR] & 0xff;
-
- /* The first 32 interrupts (PPI and SGI) are banked per-cpu, so
- * even though they are controlled with GICD registers, they must
- * be set up here with the other per-cpu state. */
- GICD[GICD_ICENABLER] = 0xffff0000; /* Disable all PPI */
- GICD[GICD_ISENABLER] = 0x0000ffff; /* Enable all SGI */
- /* Set PPI and SGI priorities */
- for (i = 0; i < 32; i += 4)
- GICD[GICD_IPRIORITYR + i / 4] = 0xa0a0a0a0;
-
- /* Local settings: interface controller */
- GICC[GICC_PMR] = 0xff; /* Don't mask by priority */
- GICC[GICC_BPR] = 0; /* Finest granularity of priority */
- GICC[GICC_CTLR] = GICC_CTL_ENABLE|GICC_CTL_EOI; /* Turn on delivery */
-}
-
-static void gic_cpu_disable(void)
+/* Program the GIC to route an interrupt to a guest
+ * - desc.lock must be held
+ */
+void gic_route_irq_to_guest(struct domain *d, struct irq_desc *desc,
+ const cpumask_t *cpu_mask, unsigned int priority)
{
- GICC[GICC_CTLR] = 0;
-}
+ struct pending_irq *p;
+ ASSERT(spin_is_locked(&desc->lock));
-static void __cpuinit gic_hyp_init(void)
-{
- uint32_t vtr;
+ desc->handler = gic_hw_ops->gic_guest_irq_type;
+ set_bit(_IRQ_GUEST, &desc->status);
- vtr = GICH[GICH_VTR];
- nr_lrs = (vtr & GICH_VTR_NRLRGS) + 1;
+ gic_set_irq_properties(desc, cpumask_of(smp_processor_id()), GIC_PRI_IRQ);
- GICH[GICH_MISR] = GICH_MISR_EOI;
- this_cpu(lr_mask) = 0ULL;
-}
-
-static void __cpuinit gic_hyp_disable(void)
-{
- GICH[GICH_HCR] = 0;
+ /* Use vcpu0 to retrieve the pending_irq struct. Given that we only
+ * route SPIs to guests, it doesn't make any difference. */
+ p = irq_to_pending(d->vcpu[0], desc->irq);
+ p->desc = desc;
}
int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
@@ -397,99 +166,43 @@ int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
/* Set up the GIC */
void __init gic_init(void)
{
- static const struct dt_device_match gic_ids[] __initconst =
- {
- DT_MATCH_GIC,
- { /* sentinel */ },
- };
+ int rc;
struct dt_device_node *node;
- int res;
-
- node = dt_find_interrupt_controller(gic_ids);
- if ( !node )
- panic("Unable to find compatible GIC in the device tree");
-
- dt_device_set_used_by(node, DOMID_XEN);
-
- res = dt_device_get_address(node, 0, &gic.dbase, NULL);
- if ( res || !gic.dbase || (gic.dbase & ~PAGE_MASK) )
- panic("GIC: Cannot find a valid address for the distributor");
-
- res = dt_device_get_address(node, 1, &gic.cbase, NULL);
- if ( res || !gic.cbase || (gic.cbase & ~PAGE_MASK) )
- panic("GIC: Cannot find a valid address for the CPU");
+ uint8_t num_gics = 0;
- res = dt_device_get_address(node, 2, &gic.hbase, NULL);
- if ( res || !gic.hbase || (gic.hbase & ~PAGE_MASK) )
- panic("GIC: Cannot find a valid address for the hypervisor");
-
- res = dt_device_get_address(node, 3, &gic.vbase, NULL);
- if ( res || !gic.vbase || (gic.vbase & ~PAGE_MASK) )
- panic("GIC: Cannot find a valid address for the virtual CPU");
-
- res = dt_device_get_irq(node, 0, &gic.maintenance);
- if ( res )
- panic("GIC: Cannot find the maintenance IRQ");
-
- /* Set the GIC as the primary interrupt controller */
- dt_interrupt_controller = node;
-
- /* TODO: Add check on distributor, cpu size */
-
- printk("GIC initialization:\n"
- " gic_dist_addr=%"PRIpaddr"\n"
- " gic_cpu_addr=%"PRIpaddr"\n"
- " gic_hyp_addr=%"PRIpaddr"\n"
- " gic_vcpu_addr=%"PRIpaddr"\n"
- " gic_maintenance_irq=%u\n",
- gic.dbase, gic.cbase, gic.hbase, gic.vbase,
- gic.maintenance.irq);
-
- if ( (gic.dbase & ~PAGE_MASK) || (gic.cbase & ~PAGE_MASK) ||
- (gic.hbase & ~PAGE_MASK) || (gic.vbase & ~PAGE_MASK) )
- panic("GIC interfaces not page aligned");
-
- set_fixmap(FIXMAP_GICD, gic.dbase >> PAGE_SHIFT, DEV_SHARED);
- BUILD_BUG_ON(FIXMAP_ADDR(FIXMAP_GICC1) !=
- FIXMAP_ADDR(FIXMAP_GICC2)-PAGE_SIZE);
- set_fixmap(FIXMAP_GICC1, gic.cbase >> PAGE_SHIFT, DEV_SHARED);
- if ( platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
- set_fixmap(FIXMAP_GICC2, (gic.cbase >> PAGE_SHIFT) + 0x10, DEV_SHARED);
- else
- set_fixmap(FIXMAP_GICC2, (gic.cbase >> PAGE_SHIFT) + 0x1, DEV_SHARED);
- set_fixmap(FIXMAP_GICH, gic.hbase >> PAGE_SHIFT, DEV_SHARED);
+ dt_for_each_device_node( dt_host, node )
+ {
+ if ( !dt_get_property(node, "interrupt-controller", NULL) )
+ continue;
- /* Global settings: interrupt distributor */
- spin_lock_init(&gic.lock);
- spin_lock(&gic.lock);
+ if ( !dt_get_parent(node) )
+ continue;
- gic_dist_init();
- gic_cpu_init();
- gic_hyp_init();
+ rc = device_init(node, DEVICE_GIC, NULL);
+ if ( !rc )
+ {
+ /* NOTE: Only one GIC is supported */
+ num_gics = 1;
+ break;
+ }
+ }
+ if ( !num_gics )
+ panic("Unable to find compatible GIC in the device tree");
- spin_unlock(&gic.lock);
+ /* Clear LR mask for cpu0 */
+ clear_cpu_lr_mask();
}
void send_SGI_mask(const cpumask_t *cpumask, enum gic_sgi sgi)
{
- unsigned int mask = 0;
- cpumask_t online_mask;
-
ASSERT(sgi < 16); /* There are only 16 SGIs */
- cpumask_and(&online_mask, cpumask, &cpu_online_map);
- mask = gic_cpu_mask(&online_mask);
-
- dsb();
-
- GICD[GICD_SGIR] = GICD_SGI_TARGET_LIST
- | (mask<<GICD_SGI_TARGET_SHIFT)
- | sgi;
+ dsb(sy);
+ gic_hw_ops->send_SGI(sgi, SGI_TARGET_LIST, cpumask);
}
void send_SGI_one(unsigned int cpu, enum gic_sgi sgi)
{
- ASSERT(cpu < NR_GIC_CPU_IF); /* Targets bitmap only supports 8 CPUs */
send_SGI_mask(cpumask_of(cpu), sgi);
}
@@ -497,20 +210,16 @@ void send_SGI_self(enum gic_sgi sgi)
{
ASSERT(sgi < 16); /* There are only 16 SGIs */
- dsb();
-
- GICD[GICD_SGIR] = GICD_SGI_TARGET_SELF
- | sgi;
+ dsb(sy);
+ gic_hw_ops->send_SGI(sgi, SGI_TARGET_SELF, NULL);
}
void send_SGI_allbutself(enum gic_sgi sgi)
{
ASSERT(sgi < 16); /* There are only 16 SGIs */
- dsb();
-
- GICD[GICD_SGIR] = GICD_SGI_TARGET_OTHERS
- | sgi;
+ dsb(sy);
+ gic_hw_ops->send_SGI(sgi, SGI_TARGET_OTHERS, NULL);
}
void smp_send_state_dump(unsigned int cpu)
@@ -521,10 +230,9 @@ void smp_send_state_dump(unsigned int cpu)
/* Set up the per-CPU parts of the GIC for a secondary CPU */
void __cpuinit gic_init_secondary_cpu(void)
{
- spin_lock(&gic.lock);
- gic_cpu_init();
- gic_hyp_init();
- spin_unlock(&gic.lock);
+ gic_hw_ops->secondary_init();
+ /* Clear LR mask for secondary cpus */
+ clear_cpu_lr_mask();
}
/* Shut down the per-CPU GIC interface */
@@ -532,118 +240,33 @@ void gic_disable_cpu(void)
{
ASSERT(!local_irq_is_enabled());
- spin_lock(&gic.lock);
- gic_cpu_disable();
- gic_hyp_disable();
- spin_unlock(&gic.lock);
-}
-
-void gic_route_ppis(void)
-{
- /* GIC maintenance */
- gic_route_dt_irq(&gic.maintenance, cpumask_of(smp_processor_id()), 0xa0);
- /* Route timer interrupt */
- route_timer_interrupt();
-}
-
-void gic_route_spis(void)
-{
- int seridx;
- const struct dt_irq *irq;
-
- for ( seridx = 0; seridx <= SERHND_IDX; seridx++ )
- {
- if ( (irq = serial_dt_irq(seridx)) == NULL )
- continue;
-
- gic_route_dt_irq(irq, cpumask_of(smp_processor_id()), 0xa0);
- }
-}
-
-void __init release_irq(unsigned int irq)
-{
- struct irq_desc *desc;
- unsigned long flags;
- struct irqaction *action;
-
- desc = irq_to_desc(irq);
-
- desc->handler->shutdown(desc);
-
- spin_lock_irqsave(&desc->lock,flags);
- action = desc->action;
- desc->action = NULL;
- desc->status &= ~IRQ_GUEST;
-
- spin_unlock_irqrestore(&desc->lock,flags);
-
- /* Wait to make sure it's not being used on another CPU */
- do { smp_mb(); } while ( desc->status & IRQ_INPROGRESS );
-
- if (action && action->free_on_release)
- xfree(action);
-}
-
-static int __setup_irq(struct irq_desc *desc, unsigned int irq,
- struct irqaction *new)
-{
- if ( desc->action != NULL )
- return -EBUSY;
-
- desc->action = new;
- dsb();
-
- return 0;
-}
-
-int __init setup_dt_irq(const struct dt_irq *irq, struct irqaction *new)
-{
- int rc;
- unsigned long flags;
- struct irq_desc *desc;
-
- desc = irq_to_desc(irq->irq);
-
- spin_lock_irqsave(&desc->lock, flags);
- rc = __setup_irq(desc, irq->irq, new);
- spin_unlock_irqrestore(&desc->lock, flags);
-
- desc->handler->startup(desc);
-
-
- return rc;
+ gic_hw_ops->disable_interface();
}
-static inline void gic_set_lr(int lr, unsigned int virtual_irq,
- unsigned int state, unsigned int priority)
+static inline void gic_set_lr(int lr, struct pending_irq *p,
+ unsigned int state)
{
- int maintenance_int = GICH_LR_MAINTENANCE_IRQ;
- struct pending_irq *p = irq_to_pending(current, virtual_irq);
-
- BUG_ON(lr >= nr_lrs);
- BUG_ON(lr < 0);
- BUG_ON(state & ~(GICH_LR_STATE_MASK<<GICH_LR_STATE_SHIFT));
+ ASSERT(!local_irq_is_enabled());
- GICH[GICH_LR + lr] = state |
- maintenance_int |
- ((priority >> 3) << GICH_LR_PRIORITY_SHIFT) |
- ((virtual_irq & GICH_LR_VIRTUAL_MASK) << GICH_LR_VIRTUAL_SHIFT);
+ gic_hw_ops->update_lr(lr, p, state);
set_bit(GIC_IRQ_GUEST_VISIBLE, &p->status);
- clear_bit(GIC_IRQ_GUEST_PENDING, &p->status);
+ clear_bit(GIC_IRQ_GUEST_QUEUED, &p->status);
+ p->lr = lr;
}
-static inline void gic_add_to_lr_pending(struct vcpu *v, unsigned int irq,
- unsigned int priority)
+static inline void gic_add_to_lr_pending(struct vcpu *v, struct pending_irq *n)
{
- struct pending_irq *iter, *n = irq_to_pending(v, irq);
+ struct pending_irq *iter;
+
+ ASSERT(spin_is_locked(&v->arch.vgic.lock));
if ( !list_empty(&n->lr_queue) )
return;
list_for_each_entry ( iter, &v->arch.vgic.lr_pending, lr_queue )
{
- if ( iter->priority > priority )
+ if ( iter->priority > n->priority )
{
list_add_tail(&n->lr_queue, &iter->lr_queue);
return;
@@ -657,152 +280,264 @@ void gic_remove_from_queues(struct vcpu *v, unsigned int virtual_irq)
struct pending_irq *p = irq_to_pending(v, virtual_irq);
unsigned long flags;
- spin_lock_irqsave(&gic.lock, flags);
+ spin_lock_irqsave(&v->arch.vgic.lock, flags);
if ( !list_empty(&p->lr_queue) )
list_del_init(&p->lr_queue);
- spin_unlock_irqrestore(&gic.lock, flags);
+ spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
}
-void gic_set_guest_irq(struct vcpu *v, unsigned int virtual_irq,
- unsigned int state, unsigned int priority)
+void gic_raise_inflight_irq(struct vcpu *v, unsigned int virtual_irq)
+{
+ struct pending_irq *n = irq_to_pending(v, virtual_irq);
+
+ ASSERT(spin_is_locked(&v->arch.vgic.lock));
+
+ if ( list_empty(&n->lr_queue) )
+ {
+ if ( v == current )
+ gic_update_one_lr(v, n->lr);
+ }
+#ifdef GIC_DEBUG
+ else
+ gdprintk(XENLOG_DEBUG, "trying to inject irq=%u into d%dv%d, when it is still lr_pending\n",
+ virtual_irq, v->domain->domain_id, v->vcpu_id);
+#endif
+}
+
+void gic_raise_guest_irq(struct vcpu *v, unsigned int virtual_irq,
+ unsigned int priority)
{
int i;
- unsigned long flags;
+ unsigned int nr_lrs = gic_hw_ops->info->nr_lrs;
- spin_lock_irqsave(&gic.lock, flags);
+ ASSERT(spin_is_locked(&v->arch.vgic.lock));
if ( v == current && list_empty(&v->arch.vgic.lr_pending) )
{
i = find_first_zero_bit(&this_cpu(lr_mask), nr_lrs);
if (i < nr_lrs) {
set_bit(i, &this_cpu(lr_mask));
- gic_set_lr(i, virtual_irq, state, priority);
- goto out;
+ gic_set_lr(i, irq_to_pending(v, virtual_irq), GICH_LR_PENDING);
+ return;
}
}
- gic_add_to_lr_pending(v, virtual_irq, priority);
+ gic_add_to_lr_pending(v, irq_to_pending(v, virtual_irq));
+}
+
+static void gic_update_one_lr(struct vcpu *v, int i)
+{
+ struct pending_irq *p;
+ int irq;
+ struct gic_lr lr_val;
-out:
- spin_unlock_irqrestore(&gic.lock, flags);
- return;
+ ASSERT(spin_is_locked(&v->arch.vgic.lock));
+ ASSERT(!local_irq_is_enabled());
+
+ gic_hw_ops->read_lr(i, &lr_val);
+ irq = lr_val.virq;
+ p = irq_to_pending(v, irq);
+ if ( lr_val.state & GICH_LR_ACTIVE )
+ {
+ set_bit(GIC_IRQ_GUEST_ACTIVE, &p->status);
+ if ( test_bit(GIC_IRQ_GUEST_ENABLED, &p->status) &&
+ test_and_clear_bit(GIC_IRQ_GUEST_QUEUED, &p->status) )
+ {
+ if ( p->desc == NULL )
+ {
+ lr_val.state |= GICH_LR_PENDING;
+ gic_hw_ops->write_lr(i, &lr_val);
+ }
+ else
+ gdprintk(XENLOG_WARNING, "unable to inject hw irq=%d into d%dv%d: already active in LR%d\n",
+ irq, v->domain->domain_id, v->vcpu_id, i);
+ }
+ }
+ else if ( lr_val.state & GICH_LR_PENDING )
+ {
+ int q __attribute__ ((unused)) = test_and_clear_bit(GIC_IRQ_GUEST_QUEUED, &p->status);
+#ifdef GIC_DEBUG
+ if ( q )
+ gdprintk(XENLOG_DEBUG, "trying to inject irq=%d into d%dv%d, when it is already pending in LR%d\n",
+ irq, v->domain->domain_id, v->vcpu_id, i);
+#endif
+ }
+ else
+ {
+ gic_hw_ops->clear_lr(i);
+ clear_bit(i, &this_cpu(lr_mask));
+
+ if ( p->desc != NULL )
+ {
+ clear_bit(_IRQ_INPROGRESS, &p->desc->status);
+ if ( platform_has_quirk(PLATFORM_QUIRK_GUEST_PIRQ_NEED_EOI) )
+ gic_hw_ops->deactivate_irq(p->desc);
+ }
+ clear_bit(GIC_IRQ_GUEST_VISIBLE, &p->status);
+ clear_bit(GIC_IRQ_GUEST_ACTIVE, &p->status);
+ p->lr = GIC_INVALID_LR;
+ if ( test_bit(GIC_IRQ_GUEST_ENABLED, &p->status) &&
+ test_bit(GIC_IRQ_GUEST_QUEUED, &p->status) &&
+ !test_bit(GIC_IRQ_GUEST_MIGRATING, &p->status) )
+ gic_raise_guest_irq(v, irq, p->priority);
+ else {
+ list_del_init(&p->inflight);
+ if ( test_and_clear_bit(GIC_IRQ_GUEST_MIGRATING, &p->status) )
+ {
+ struct vcpu *v_target = vgic_get_target_vcpu(v, irq);
+ irq_set_affinity(p->desc, cpumask_of(v_target->processor));
+ }
+ }
+ }
}
-static void gic_restore_pending_irqs(struct vcpu *v)
+void gic_clear_lrs(struct vcpu *v)
{
- int i;
- struct pending_irq *p, *t;
+ int i = 0;
unsigned long flags;
+ unsigned int nr_lrs = gic_hw_ops->info->nr_lrs;
- list_for_each_entry_safe ( p, t, &v->arch.vgic.lr_pending, lr_queue )
- {
- i = find_first_zero_bit(&this_cpu(lr_mask), nr_lrs);
- if ( i >= nr_lrs ) return;
+ /* The idle domain has no LRs to be cleared. Since gic_restore_state
+ * doesn't write any LR registers for the idle domain they could be
+ * non-zero. */
+ if ( is_idle_vcpu(v) )
+ return;
- spin_lock_irqsave(&gic.lock, flags);
- gic_set_lr(i, p->irq, GICH_LR_PENDING, p->priority);
- list_del_init(&p->lr_queue);
- set_bit(i, &this_cpu(lr_mask));
- spin_unlock_irqrestore(&gic.lock, flags);
+ gic_hw_ops->update_hcr_status(GICH_HCR_UIE, 0);
+
+ spin_lock_irqsave(&v->arch.vgic.lock, flags);
+
+ while ((i = find_next_bit((const unsigned long *) &this_cpu(lr_mask),
+ nr_lrs, i)) < nr_lrs ) {
+ gic_update_one_lr(v, i);
+ i++;
}
+ spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
}
-void gic_clear_pending_irqs(struct vcpu *v)
+static void gic_restore_pending_irqs(struct vcpu *v)
{
- struct pending_irq *p, *t;
+ int lr = 0;
+ struct pending_irq *p, *t, *p_r;
+ struct list_head *inflight_r;
unsigned long flags;
+ unsigned int nr_lrs = gic_hw_ops->info->nr_lrs;
+ int lrs = nr_lrs;
- spin_lock_irqsave(&gic.lock, flags);
- v->arch.lr_mask = 0;
+ spin_lock_irqsave(&v->arch.vgic.lock, flags);
+
+ if ( list_empty(&v->arch.vgic.lr_pending) )
+ goto out;
+
+ inflight_r = &v->arch.vgic.inflight_irqs;
list_for_each_entry_safe ( p, t, &v->arch.vgic.lr_pending, lr_queue )
- list_del_init(&p->lr_queue);
- spin_unlock_irqrestore(&gic.lock, flags);
-}
+ {
+ lr = find_next_zero_bit(&this_cpu(lr_mask), nr_lrs, lr);
+ if ( lr >= nr_lrs )
+ {
+ /* No more free LRs: find a lower priority irq to evict */
+ list_for_each_entry_reverse( p_r, inflight_r, inflight )
+ {
+ if ( p_r->priority == p->priority )
+ goto out;
+ if ( test_bit(GIC_IRQ_GUEST_VISIBLE, &p_r->status) &&
+ !test_bit(GIC_IRQ_GUEST_ACTIVE, &p_r->status) )
+ goto found;
+ }
+ /* We didn't find a victim this time, and we won't next
+ * time, so quit */
+ goto out;
-static void gic_inject_irq_start(void)
-{
- register_t hcr = READ_SYSREG(HCR_EL2);
- WRITE_SYSREG(hcr | HCR_VI, HCR_EL2);
- isb();
-}
+found:
+ lr = p_r->lr;
+ p_r->lr = GIC_INVALID_LR;
+ set_bit(GIC_IRQ_GUEST_QUEUED, &p_r->status);
+ clear_bit(GIC_IRQ_GUEST_VISIBLE, &p_r->status);
+ gic_add_to_lr_pending(v, p_r);
+ inflight_r = &p_r->inflight;
+ }
-static void gic_inject_irq_stop(void)
-{
- register_t hcr = READ_SYSREG(HCR_EL2);
- if (hcr & HCR_VI) {
- WRITE_SYSREG(hcr & ~HCR_VI, HCR_EL2);
- isb();
+ gic_set_lr(lr, p, GICH_LR_PENDING);
+ list_del_init(&p->lr_queue);
+ set_bit(lr, &this_cpu(lr_mask));
+
+ /* We can only evict nr_lrs entries */
+ lrs--;
+ if ( lrs == 0 )
+ break;
}
-}
-int gic_events_need_delivery(void)
-{
- return (!list_empty(¤t->arch.vgic.lr_pending) ||
- this_cpu(lr_mask));
+out:
+ spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
}
-void gic_inject(void)
+void gic_clear_pending_irqs(struct vcpu *v)
{
- if ( vcpu_info(current, evtchn_upcall_pending) )
- vgic_vcpu_inject_irq(current, current->domain->arch.evtchn_irq, 1);
+ struct pending_irq *p, *t;
- gic_restore_pending_irqs(current);
- if (!gic_events_need_delivery())
- gic_inject_irq_stop();
- else
- gic_inject_irq_start();
+ ASSERT(spin_is_locked(&v->arch.vgic.lock));
+
+ v->arch.lr_mask = 0;
+ list_for_each_entry_safe ( p, t, &v->arch.vgic.lr_pending, lr_queue )
+ list_del_init(&p->lr_queue);
}
-int gic_route_irq_to_guest(struct domain *d, const struct dt_irq *irq,
- const char * devname)
+int gic_events_need_delivery(void)
{
- struct irqaction *action;
- struct irq_desc *desc = irq_to_desc(irq->irq);
- unsigned long flags;
- int retval;
- bool_t level;
+ struct vcpu *v = current;
struct pending_irq *p;
+ unsigned long flags;
+ const unsigned long apr = gic_hw_ops->read_apr(0);
+ int mask_priority;
+ int active_priority;
+ int rc = 0;
- action = xmalloc(struct irqaction);
- if (!action)
- return -ENOMEM;
-
- action->dev_id = d;
- action->name = devname;
- action->free_on_release = 1;
+ mask_priority = gic_hw_ops->read_vmcr_priority();
+ active_priority = find_next_bit(&apr, 32, 0);
- spin_lock_irqsave(&desc->lock, flags);
- spin_lock(&gic.lock);
+ spin_lock_irqsave(&v->arch.vgic.lock, flags);
- desc->handler = &gic_guest_irq_type;
- desc->status |= IRQ_GUEST;
+ /* TODO: We order the guest irqs by priority, but we don't change
+ * the priority of host irqs. */
- level = dt_irq_is_level_triggered(irq);
+ /* find the first enabled non-active irq, the queue is already
+ * ordered by priority */
+ list_for_each_entry( p, &v->arch.vgic.inflight_irqs, inflight )
+ {
+ if ( GIC_PRI_TO_GUEST(p->priority) >= mask_priority )
+ goto out;
+ if ( GIC_PRI_TO_GUEST(p->priority) >= active_priority )
+ goto out;
+ if ( test_bit(GIC_IRQ_GUEST_ENABLED, &p->status) )
+ {
+ rc = 1;
+ goto out;
+ }
+ }
- gic_set_irq_properties(irq->irq, level, cpumask_of(smp_processor_id()),
- 0xa0);
+out:
+ spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
+ return rc;
+}
- retval = __setup_irq(desc, irq->irq, action);
- if (retval) {
- xfree(action);
- goto out;
- }
+void gic_inject(void)
+{
+ ASSERT(!local_irq_is_enabled());
- /* TODO: do not assume delivery to vcpu0 */
- p = irq_to_pending(d->vcpu[0], irq->irq);
- p->desc = desc;
+ gic_restore_pending_irqs(current);
-out:
- spin_unlock(&gic.lock);
- spin_unlock_irqrestore(&desc->lock, flags);
- return retval;
+ if ( !list_empty(¤t->arch.vgic.lr_pending) && lr_all_full() )
+ gic_hw_ops->update_hcr_status(GICH_HCR_UIE, 1);
}
-static void do_sgi(struct cpu_user_regs *regs, int othercpu, enum gic_sgi sgi)
+static void do_sgi(struct cpu_user_regs *regs, enum gic_sgi sgi)
{
/* Lower the priority */
- GICC[GICC_EOIR] = sgi;
+ struct irq_desc *desc = irq_to_desc(sgi);
+
+ /* Lower the priority */
+ gic_hw_ops->eoi_irq(desc);
switch (sgi)
{
@@ -821,19 +556,17 @@ static void do_sgi(struct cpu_user_regs *regs, int othercpu, enum gic_sgi sgi)
}
/* Deactivate */
- GICC[GICC_DIR] = sgi;
+ gic_hw_ops->deactivate_irq(desc);
}
/* Accept an interrupt from the GIC and dispatch its handler */
void gic_interrupt(struct cpu_user_regs *regs, int is_fiq)
{
- uint32_t intack;
unsigned int irq;
-
do {
- intack = GICC[GICC_IAR];
- irq = intack & GICC_IA_IRQ;
+ /* Reading IRQ will ACK it */
+ irq = gic_hw_ops->read_irq();
if ( likely(irq >= 16 && irq < 1021) )
{
@@ -843,8 +576,7 @@ void gic_interrupt(struct cpu_user_regs *regs, int is_fiq)
}
else if (unlikely(irq < 16))
{
- unsigned int cpu = (intack & GICC_IA_CPU_MASK) >> GICC_IA_CPU_SHIFT;
- do_sgi(regs, cpu, irq);
+ do_sgi(regs, irq);
}
else
{
@@ -856,155 +588,52 @@ void gic_interrupt(struct cpu_user_regs *regs, int is_fiq)
int gicv_setup(struct domain *d)
{
- int ret;
-
- /*
- * Domain 0 gets the hardware address.
- * Guests get the virtual platform layout.
- */
- if ( d->domain_id == 0 )
- {
- d->arch.vgic.dbase = gic.dbase;
- d->arch.vgic.cbase = gic.cbase;
- }
- else
- {
- d->arch.vgic.dbase = GUEST_GICD_BASE;
- d->arch.vgic.cbase = GUEST_GICC_BASE;
- }
-
- d->arch.vgic.nr_lines = 0;
-
- /*
- * Map the gic virtual cpu interface in the gic cpu interface
- * region of the guest.
- *
- * The second page is always mapped at +4K irrespective of the
- * GIC_64K_STRIDE quirk. The DTB passed to the guest reflects this.
- */
- ret = map_mmio_regions(d, d->arch.vgic.cbase,
- d->arch.vgic.cbase + PAGE_SIZE - 1,
- gic.vbase);
- if (ret)
- return ret;
-
- if ( !platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
- ret = map_mmio_regions(d, d->arch.vgic.cbase + PAGE_SIZE,
- d->arch.vgic.cbase + (2 * PAGE_SIZE) - 1,
- gic.vbase + PAGE_SIZE);
- else
- ret = map_mmio_regions(d, d->arch.vgic.cbase + PAGE_SIZE,
- d->arch.vgic.cbase + (2 * PAGE_SIZE) - 1,
- gic.vbase + 16*PAGE_SIZE);
-
- return ret;
-
-}
-
-static void gic_irq_eoi(void *info)
-{
- int virq = (uintptr_t) info;
- GICC[GICC_DIR] = virq;
+ return gic_hw_ops->gicv_setup(d);
}
static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
{
- int i = 0, virq, pirq = -1;
- uint32_t lr;
- struct vcpu *v = current;
- uint64_t eisr = GICH[GICH_EISR0] | (((uint64_t) GICH[GICH_EISR1]) << 32);
-
- while ((i = find_next_bit((const long unsigned int *) &eisr,
- 64, i)) < 64) {
- struct pending_irq *p, *p2;
- int cpu;
- bool_t inflight;
-
- cpu = -1;
- inflight = 0;
-
- spin_lock_irq(&gic.lock);
- lr = GICH[GICH_LR + i];
- virq = lr & GICH_LR_VIRTUAL_MASK;
- GICH[GICH_LR + i] = 0;
- clear_bit(i, &this_cpu(lr_mask));
-
- p = irq_to_pending(v, virq);
- if ( p->desc != NULL ) {
- p->desc->status &= ~IRQ_INPROGRESS;
- /* Assume only one pcpu needs to EOI the irq */
- cpu = p->desc->arch.eoi_cpu;
- pirq = p->desc->irq;
- }
- if ( test_bit(GIC_IRQ_GUEST_PENDING, &p->status) &&
- test_bit(GIC_IRQ_GUEST_ENABLED, &p->status))
- {
- inflight = 1;
- gic_add_to_lr_pending(v, virq, p->priority);
- }
-
- clear_bit(GIC_IRQ_GUEST_VISIBLE, &p->status);
-
- if ( !list_empty(&v->arch.vgic.lr_pending) ) {
- p2 = list_entry(v->arch.vgic.lr_pending.next, typeof(*p2), lr_queue);
- gic_set_lr(i, p2->irq, GICH_LR_PENDING, p2->priority);
- list_del_init(&p2->lr_queue);
- set_bit(i, &this_cpu(lr_mask));
- }
- spin_unlock_irq(&gic.lock);
-
- if ( !inflight )
- {
- spin_lock_irq(&v->arch.vgic.lock);
- list_del_init(&p->inflight);
- spin_unlock_irq(&v->arch.vgic.lock);
- }
-
- if ( p->desc != NULL ) {
- /* this is not racy because we can't receive another irq of the
- * same type until we EOI it. */
- if ( cpu == smp_processor_id() )
- gic_irq_eoi((void*)(uintptr_t)pirq);
- else
- on_selected_cpus(cpumask_of(cpu),
- gic_irq_eoi, (void*)(uintptr_t)pirq, 0);
- }
-
- i++;
- }
+ /*
+ * This is a dummy interrupt handler.
+ * Receiving the interrupt is going to cause gic_inject to be called
+ * on return to guest that is going to clear the old LRs and inject
+ * new interrupts.
+ *
+ * Do not add code here: maintenance interrupts caused by setting
+ * GICH_HCR_UIE, might read as spurious interrupts (1023) because
+ * GICH_HCR_UIE is cleared before reading GICC_IAR. As a consequence
+ * this handler is not called.
+ */
}
void gic_dump_info(struct vcpu *v)
{
- int i;
struct pending_irq *p;
printk("GICH_LRs (vcpu %d) mask=%"PRIx64"\n", v->vcpu_id, v->arch.lr_mask);
- if ( v == current )
- {
- for ( i = 0; i < nr_lrs; i++ )
- printk(" HW_LR[%d]=%x\n", i, GICH[GICH_LR + i]);
- } else {
- for ( i = 0; i < nr_lrs; i++ )
- printk(" VCPU_LR[%d]=%x\n", i, v->arch.gic_lr[i]);
- }
+ gic_hw_ops->dump_state(v);
list_for_each_entry ( p, &v->arch.vgic.inflight_irqs, inflight )
{
- printk("Inflight irq=%d\n", p->irq);
+ printk("Inflight irq=%d lr=%u\n", p->irq, p->lr);
}
list_for_each_entry( p, &v->arch.vgic.lr_pending, lr_queue )
{
printk("Pending irq=%d\n", p->irq);
}
-
}
void __cpuinit init_maintenance_interrupt(void)
{
- request_dt_irq(&gic.maintenance, maintenance_interrupt,
- "irq-maintenance", NULL);
+ request_irq(gic_hw_ops->info->maintenance_irq, 0, maintenance_interrupt,
+ "irq-maintenance", NULL);
+}
+
+int gic_make_node(const struct domain *d,const struct dt_device_node *node,
+ void *fdt)
+{
+ return gic_hw_ops->make_dt_node(d, node, fdt);
}
/*
diff --git a/xen/arch/arm/guestcopy.c b/xen/arch/arm/guestcopy.c
index 0173597..7dbaeca 100644
--- a/xen/arch/arm/guestcopy.c
+++ b/xen/arch/arm/guestcopy.c
@@ -27,7 +27,7 @@ static unsigned long raw_copy_to_guest_helper(void *to, const void *from,
p += offset;
memcpy(p, from, size);
if ( flush_dcache )
- clean_xen_dcache_va_range(p, size);
+ clean_dcache_va_range(p, size);
unmap_domain_page(p - offset);
put_page(page);
diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index a6db00b..8e55d49 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -1,5 +1,5 @@
/*
- * xen/arch/arm/io.h
+ * xen/arch/arm/io.c
*
* ARM I/O handlers
*
@@ -18,30 +18,61 @@
#include <xen/config.h>
#include <xen/lib.h>
+#include <xen/spinlock.h>
+#include <xen/sched.h>
#include <asm/current.h>
-
-#include "io.h"
-
-static const struct mmio_handler *const mmio_handlers[] =
-{
- &vgic_distr_mmio_handler,
- &vuart_mmio_handler,
-};
-#define MMIO_HANDLER_NR ARRAY_SIZE(mmio_handlers)
+#include <asm/mmio.h>
int handle_mmio(mmio_info_t *info)
{
struct vcpu *v = current;
int i;
+ const struct mmio_handler *mmio_handler;
+ const struct io_handler *io_handlers = &v->domain->arch.io_handlers;
+
+ for ( i = 0; i < io_handlers->num_entries; i++ )
+ {
+ mmio_handler = &io_handlers->mmio_handlers[i];
- for ( i = 0; i < MMIO_HANDLER_NR; i++ )
- if ( mmio_handlers[i]->check_handler(v, info->gpa) )
+ if ( (info->gpa >= mmio_handler->addr) &&
+ (info->gpa < (mmio_handler->addr + mmio_handler->size)) )
+ {
return info->dabt.write ?
- mmio_handlers[i]->write_handler(v, info) :
- mmio_handlers[i]->read_handler(v, info);
+ mmio_handler->mmio_handler_ops->write_handler(v, info) :
+ mmio_handler->mmio_handler_ops->read_handler(v, info);
+ }
+ }
return 0;
}
+
+void register_mmio_handler(struct domain *d,
+ const struct mmio_handler_ops *handle,
+ paddr_t addr, paddr_t size)
+{
+ struct io_handler *handler = &d->arch.io_handlers;
+
+ BUG_ON(handler->num_entries >= MAX_IO_HANDLER);
+
+ spin_lock(&handler->lock);
+
+ handler->mmio_handlers[handler->num_entries].mmio_handler_ops = handle;
+ handler->mmio_handlers[handler->num_entries].addr = addr;
+ handler->mmio_handlers[handler->num_entries].size = size;
+ dsb(ish);
+ handler->num_entries++;
+
+ spin_unlock(&handler->lock);
+}
+
+int domain_io_init(struct domain *d)
+{
+ spin_lock_init(&d->arch.io_handlers.lock);
+ d->arch.io_handlers.num_entries = 0;
+
+ return 0;
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/arm/io.h b/xen/arch/arm/io.h
deleted file mode 100644
index 8d252c0..0000000
--- a/xen/arch/arm/io.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * xen/arch/arm/io.h
- *
- * ARM I/O handlers
- *
- * Copyright (c) 2011 Citrix Systems.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ARCH_ARM_IO_H__
-#define __ARCH_ARM_IO_H__
-
-#include <xen/lib.h>
-#include <asm/processor.h>
-#include <asm/regs.h>
-
-typedef struct
-{
- struct hsr_dabt dabt;
- vaddr_t gva;
- paddr_t gpa;
-} mmio_info_t;
-
-typedef int (*mmio_read_t)(struct vcpu *v, mmio_info_t *info);
-typedef int (*mmio_write_t)(struct vcpu *v, mmio_info_t *info);
-typedef int (*mmio_check_t)(struct vcpu *v, paddr_t addr);
-
-struct mmio_handler {
- mmio_check_t check_handler;
- mmio_read_t read_handler;
- mmio_write_t write_handler;
-};
-
-extern const struct mmio_handler vgic_distr_mmio_handler;
-extern const struct mmio_handler vuart_mmio_handler;
-
-extern int handle_mmio(mmio_info_t *info);
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index 3e326b0..25ecf1d 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -26,30 +26,40 @@
#include <xen/sched.h>
#include <asm/gic.h>
+#include <asm/vgic.h>
+
+static unsigned int local_irqs_type[NR_LOCAL_IRQS];
+static DEFINE_SPINLOCK(local_irqs_type_lock);
-static void enable_none(struct irq_desc *irq) { }
-static unsigned int startup_none(struct irq_desc *irq) { return 0; }
-static void disable_none(struct irq_desc *irq) { }
static void ack_none(struct irq_desc *irq)
{
printk("unexpected IRQ trap at irq %02x\n", irq->irq);
}
-#define shutdown_none disable_none
-#define end_none enable_none
+static void end_none(struct irq_desc *irq) { }
hw_irq_controller no_irq_type = {
.typename = "none",
- .startup = startup_none,
- .shutdown = shutdown_none,
- .enable = enable_none,
- .disable = disable_none,
+ .startup = irq_startup_none,
+ .shutdown = irq_shutdown_none,
+ .enable = irq_enable_none,
+ .disable = irq_disable_none,
.ack = ack_none,
.end = end_none
};
+static irq_desc_t irq_desc[NR_IRQS];
+static DEFINE_PER_CPU(irq_desc_t[NR_LOCAL_IRQS], local_irq_desc);
+
+irq_desc_t *__irq_to_desc(int irq)
+{
+ if (irq < NR_LOCAL_IRQS) return &this_cpu(local_irq_desc)[irq];
+ return &irq_desc[irq-NR_LOCAL_IRQS];
+}
+
int __init arch_init_one_irq_desc(struct irq_desc *desc)
{
+ desc->arch.type = DT_IRQ_TYPE_INVALID;
return 0;
}
@@ -72,18 +82,37 @@ static int __cpuinit init_local_irq_data(void)
{
int irq;
+ spin_lock(&local_irqs_type_lock);
+
for (irq = 0; irq < NR_LOCAL_IRQS; irq++) {
struct irq_desc *desc = irq_to_desc(irq);
init_one_irq_desc(desc);
desc->irq = irq;
desc->action = NULL;
+
+ /* PPIs are included in local_irqs, we copy the IRQ type from
+ * local_irqs_type when bringing up local IRQ for this CPU in
+ * order to pick up any configuration done before this CPU came
+ * up. For interrupts configured after this point this is done in
+ * irq_set_type.
+ */
+ desc->arch.type = local_irqs_type[irq];
}
+ spin_unlock(&local_irqs_type_lock);
+
return 0;
}
void __init init_IRQ(void)
{
+ int irq;
+
+ spin_lock(&local_irqs_type_lock);
+ for ( irq = 0; irq < NR_LOCAL_IRQS; irq++ )
+ local_irqs_type[irq] = DT_IRQ_TYPE_INVALID;
+ spin_unlock(&local_irqs_type_lock);
+
BUG_ON(init_local_irq_data() < 0);
BUG_ON(init_irq_data() < 0);
}
@@ -93,9 +122,27 @@ void __cpuinit init_secondary_IRQ(void)
BUG_ON(init_local_irq_data() < 0);
}
-int __init request_dt_irq(const struct dt_irq *irq,
- void (*handler)(int, void *, struct cpu_user_regs *),
- const char *devname, void *dev_id)
+static inline struct domain *irq_get_domain(struct irq_desc *desc)
+{
+ ASSERT(spin_is_locked(&desc->lock));
+
+ if ( !test_bit(_IRQ_GUEST, &desc->status) )
+ return dom_xen;
+
+ ASSERT(desc->action != NULL);
+
+ return desc->action->dev_id;
+}
+
+void irq_set_affinity(struct irq_desc *desc, const cpumask_t *cpu_mask)
+{
+ if ( desc != NULL )
+ desc->handler->set_affinity(desc, cpu_mask);
+}
+
+int request_irq(unsigned int irq, unsigned int irqflags,
+ void (*handler)(int, void *, struct cpu_user_regs *),
+ const char *devname, void *dev_id)
{
struct irqaction *action;
int retval;
@@ -106,13 +153,13 @@ int __init request_dt_irq(const struct dt_irq *irq,
* which interrupt is which (messes up the interrupt freeing
* logic etc).
*/
- if (irq->irq >= nr_irqs)
+ if ( irq >= nr_irqs )
return -EINVAL;
- if (!handler)
+ if ( !handler )
return -EINVAL;
action = xmalloc(struct irqaction);
- if (!action)
+ if ( !action )
return -ENOMEM;
action->handler = handler;
@@ -120,8 +167,8 @@ int __init request_dt_irq(const struct dt_irq *irq,
action->dev_id = dev_id;
action->free_on_release = 1;
- retval = setup_dt_irq(irq, action);
- if (retval)
+ retval = setup_irq(irq, irqflags, action);
+ if ( retval )
xfree(action);
return retval;
@@ -131,7 +178,6 @@ int __init request_dt_irq(const struct dt_irq *irq,
void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq)
{
struct irq_desc *desc = irq_to_desc(irq);
- struct irqaction *action = desc->action;
/* TODO: perfc_incr(irqs); */
@@ -142,48 +188,59 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq)
spin_lock(&desc->lock);
desc->handler->ack(desc);
- if ( action == NULL )
+ if ( !desc->action )
{
printk("Unknown %s %#3.3x\n",
is_fiq ? "FIQ" : "IRQ", irq);
goto out;
}
- if ( desc->status & IRQ_GUEST )
+ if ( test_bit(_IRQ_GUEST, &desc->status) )
{
- struct domain *d = action->dev_id;
+ struct domain *d = irq_get_domain(desc);
desc->handler->end(desc);
- desc->status |= IRQ_INPROGRESS;
+ set_bit(_IRQ_INPROGRESS, &desc->status);
desc->arch.eoi_cpu = smp_processor_id();
- /* XXX: inject irq into all guest vcpus */
- vgic_vcpu_inject_irq(d->vcpu[0], irq, 0);
+ /* the irq cannot be a PPI, we only support delivery of SPIs to
+ * guests */
+ vgic_vcpu_inject_spi(d, irq);
goto out_no_end;
}
- desc->status |= IRQ_PENDING;
+ set_bit(_IRQ_PENDING, &desc->status);
/*
* Since we set PENDING, if another processor is handling a different
* instance of this same irq, the other processor will take care of it.
*/
- if ( desc->status & (IRQ_DISABLED | IRQ_INPROGRESS) )
+ if ( test_bit(_IRQ_DISABLED, &desc->status) ||
+ test_bit(_IRQ_INPROGRESS, &desc->status) )
goto out;
- desc->status |= IRQ_INPROGRESS;
+ set_bit(_IRQ_INPROGRESS, &desc->status);
- action = desc->action;
- while ( desc->status & IRQ_PENDING )
+ while ( test_bit(_IRQ_PENDING, &desc->status) )
{
- desc->status &= ~IRQ_PENDING;
+ struct irqaction *action;
+
+ clear_bit(_IRQ_PENDING, &desc->status);
+ action = desc->action;
+
spin_unlock_irq(&desc->lock);
- action->handler(irq, action->dev_id, regs);
+
+ do
+ {
+ action->handler(irq, action->dev_id, regs);
+ action = action->next;
+ } while ( action );
+
spin_lock_irq(&desc->lock);
}
- desc->status &= ~IRQ_INPROGRESS;
+ clear_bit(_IRQ_INPROGRESS, &desc->status);
out:
desc->handler->end(desc);
@@ -192,6 +249,182 @@ out_no_end:
irq_exit();
}
+void release_irq(unsigned int irq, const void *dev_id)
+{
+ struct irq_desc *desc;
+ unsigned long flags;
+ struct irqaction *action, **action_ptr;
+
+ desc = irq_to_desc(irq);
+
+ spin_lock_irqsave(&desc->lock,flags);
+
+ action_ptr = &desc->action;
+ for ( ;; )
+ {
+ action = *action_ptr;
+ if ( !action )
+ {
+ printk(XENLOG_WARNING "Trying to free already-free IRQ %u\n", irq);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ return;
+ }
+
+ if ( action->dev_id == dev_id )
+ break;
+
+ action_ptr = &action->next;
+ }
+
+ /* Found it - remove it from the action list */
+ *action_ptr = action->next;
+
+ /* If this was the last action, shut down the IRQ */
+ if ( !desc->action )
+ {
+ desc->handler->shutdown(desc);
+ clear_bit(_IRQ_GUEST, &desc->status);
+ }
+
+ spin_unlock_irqrestore(&desc->lock,flags);
+
+ /* Wait to make sure it's not being used on another CPU */
+ do { smp_mb(); } while ( test_bit(_IRQ_INPROGRESS, &desc->status) );
+
+ if ( action->free_on_release )
+ xfree(action);
+}
+
+static int __setup_irq(struct irq_desc *desc, unsigned int irqflags,
+ struct irqaction *new)
+{
+ bool_t shared = !!(irqflags & IRQF_SHARED);
+
+ ASSERT(new != NULL);
+
+ /* Sanity checks:
+ * - if the IRQ is marked as shared
+ * - dev_id is not NULL when IRQF_SHARED is set
+ */
+ if ( desc->action != NULL && (!test_bit(_IRQF_SHARED, &desc->status) || !shared) )
+ return -EINVAL;
+ if ( shared && new->dev_id == NULL )
+ return -EINVAL;
+
+ if ( shared )
+ set_bit(_IRQF_SHARED, &desc->status);
+
+ new->next = desc->action;
+ dsb(ish);
+ desc->action = new;
+ dsb(ish);
+
+ return 0;
+}
+
+int setup_irq(unsigned int irq, unsigned int irqflags, struct irqaction *new)
+{
+ int rc;
+ unsigned long flags;
+ struct irq_desc *desc;
+ bool_t disabled;
+
+ desc = irq_to_desc(irq);
+
+ spin_lock_irqsave(&desc->lock, flags);
+
+ if ( test_bit(_IRQ_GUEST, &desc->status) )
+ {
+ struct domain *d = irq_get_domain(desc);
+
+ spin_unlock_irqrestore(&desc->lock, flags);
+ printk(XENLOG_ERR "ERROR: IRQ %u is already in use by the domain %u\n",
+ irq, d->domain_id);
+ return -EBUSY;
+ }
+
+ disabled = (desc->action == NULL);
+
+ rc = __setup_irq(desc, irqflags, new);
+ if ( rc )
+ goto err;
+
+ /* First time the IRQ is setup */
+ if ( disabled )
+ {
+ /* It's fine to use smp_processor_id() because:
+ * For PPI: irq_desc is banked
+ * For SPI: we don't care for now which CPU will receive the
+ * interrupt
+ * TODO: Handle case where SPI is setup on different CPU than
+ * the targeted CPU and the priority.
+ */
+ gic_route_irq_to_xen(desc, cpumask_of(smp_processor_id()),
+ GIC_PRI_IRQ);
+ desc->handler->startup(desc);
+ }
+
+err:
+ spin_unlock_irqrestore(&desc->lock, flags);
+
+ return rc;
+}
+
+int route_irq_to_guest(struct domain *d, unsigned int irq,
+ const char * devname)
+{
+ struct irqaction *action;
+ struct irq_desc *desc = irq_to_desc(irq);
+ unsigned long flags;
+ int retval = 0;
+
+ action = xmalloc(struct irqaction);
+ if (!action)
+ return -ENOMEM;
+
+ action->dev_id = d;
+ action->name = devname;
+ action->free_on_release = 1;
+
+ spin_lock_irqsave(&desc->lock, flags);
+
+ /* If the IRQ is already used by someone
+ * - If it's the same domain -> Xen doesn't need to update the IRQ desc
+ * - Otherwise -> For now, don't allow the IRQ to be shared between
+ * Xen and domains.
+ */
+ if ( desc->action != NULL )
+ {
+ struct domain *ad = irq_get_domain(desc);
+
+ if ( test_bit(_IRQ_GUEST, &desc->status) && d == ad )
+ goto out;
+
+ if ( test_bit(_IRQ_GUEST, &desc->status) )
+ printk(XENLOG_ERR "ERROR: IRQ %u is already used by domain %u\n",
+ irq, ad->domain_id);
+ else
+ printk(XENLOG_ERR "ERROR: IRQ %u is already used by Xen\n", irq);
+ retval = -EBUSY;
+ goto out;
+ }
+
+ retval = __setup_irq(desc, 0, action);
+ if ( retval )
+ goto out;
+
+ gic_route_irq_to_guest(d, desc, cpumask_of(smp_processor_id()),
+ GIC_PRI_IRQ);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ return 0;
+
+out:
+ spin_unlock_irqrestore(&desc->lock, flags);
+ xfree(action);
+
+ return retval;
+}
+
/*
* pirq event channels. We don't use these on ARM, instead we use the
* features of the GIC to inject virtualised normal interrupts.
@@ -221,6 +454,97 @@ void pirq_set_affinity(struct domain *d, int pirq, const cpumask_t *mask)
BUG();
}
+static bool_t irq_validate_new_type(unsigned int curr, unsigned new)
+{
+ return (curr == DT_IRQ_TYPE_INVALID || curr == new );
+}
+
+int irq_set_spi_type(unsigned int spi, unsigned int type)
+{
+ unsigned long flags;
+ struct irq_desc *desc = irq_to_desc(spi);
+ int ret = -EBUSY;
+
+ /* This function should not be used for other than SPIs */
+ if ( spi < NR_LOCAL_IRQS )
+ return -EINVAL;
+
+ spin_lock_irqsave(&desc->lock, flags);
+
+ if ( !irq_validate_new_type(desc->arch.type, type) )
+ goto err;
+
+ desc->arch.type = type;
+
+ ret = 0;
+
+err:
+ spin_unlock_irqrestore(&desc->lock, flags);
+ return ret;
+}
+
+static int irq_local_set_type(unsigned int irq, unsigned int type)
+{
+ unsigned int cpu;
+ unsigned int old_type;
+ unsigned long flags;
+ int ret = -EBUSY;
+ struct irq_desc *desc;
+
+ ASSERT(irq < NR_LOCAL_IRQS);
+
+ spin_lock(&local_irqs_type_lock);
+
+ old_type = local_irqs_type[irq];
+
+ if ( !irq_validate_new_type(old_type, type) )
+ goto unlock;
+
+ ret = 0;
+ /* We don't need to reconfigure if the type is correctly set */
+ if ( old_type == type )
+ goto unlock;
+
+ local_irqs_type[irq] = type;
+
+ for_each_cpu( cpu, &cpu_online_map )
+ {
+ desc = &per_cpu(local_irq_desc, cpu)[irq];
+ spin_lock_irqsave(&desc->lock, flags);
+ desc->arch.type = type;
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+
+unlock:
+ spin_unlock(&local_irqs_type_lock);
+ return ret;
+}
+
+int platform_get_irq(const struct dt_device_node *device, int index)
+{
+ struct dt_irq dt_irq;
+ unsigned int type, irq;
+ int res;
+
+ res = dt_device_get_irq(device, index, &dt_irq);
+ if ( res )
+ return -1;
+
+ irq = dt_irq.irq;
+ type = dt_irq.type;
+
+ /* Setup the IRQ type */
+ if ( irq < NR_LOCAL_IRQS )
+ res = irq_local_set_type(irq, type);
+ else
+ res = irq_set_spi_type(irq, type);
+
+ if ( res )
+ return -1;
+
+ return irq;
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
index 69c7d43..209c3dd 100644
--- a/xen/arch/arm/kernel.c
+++ b/xen/arch/arm/kernel.c
@@ -16,9 +16,8 @@
#include "kernel.h"
-/* Store kernel in first 8M of flash */
-#define KERNEL_FLASH_ADDRESS 0x00000000UL
-#define KERNEL_FLASH_SIZE 0x00800000UL
+#define UIMAGE_MAGIC 0x27051956
+#define UIMAGE_NMLEN 32
#define ZIMAGE32_MAGIC_OFFSET 0x24
#define ZIMAGE32_START_OFFSET 0x28
@@ -44,7 +43,7 @@ struct minimal_dtb_header {
* @paddr: source physical address
* @len: length to copy
*/
-void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len, int attrindx)
+void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len)
{
void *src = (void *)FIXMAP_ADDR(FIXMAP_MISC);
@@ -56,9 +55,9 @@ void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len, int attrindx)
s = paddr & (PAGE_SIZE-1);
l = min(PAGE_SIZE - s, len);
- set_fixmap(FIXMAP_MISC, p, attrindx);
+ set_fixmap(FIXMAP_MISC, p, BUFFERABLE);
memcpy(dst, src + s, l);
- clean_xen_dcache_va_range(dst, l);
+ clean_dcache_va_range(dst, l);
paddr += l;
dst += l;
@@ -69,25 +68,25 @@ void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len, int attrindx)
}
static void place_modules(struct kernel_info *info,
- paddr_t kernel_start,
- paddr_t kernel_end)
+ paddr_t kernbase, paddr_t kernend)
{
/* Align DTB and initrd size to 2Mb. Linux only requires 4 byte alignment */
- const paddr_t initrd_len =
- ROUNDUP(early_info.modules.module[MOD_INITRD].size, MB(2));
+ const struct bootmodule *mod = info->initrd_bootmodule;
+ const paddr_t initrd_len = ROUNDUP(mod ? mod->size : 0, MB(2));
const paddr_t dtb_len = ROUNDUP(fdt_totalsize(info->fdt), MB(2));
- const paddr_t total = initrd_len + dtb_len;
+ const paddr_t modsize = initrd_len + dtb_len;
/* Convenient */
- const paddr_t mem_start = info->mem.bank[0].start;
- const paddr_t mem_size = info->mem.bank[0].size;
- const paddr_t mem_end = mem_start + mem_size;
- const paddr_t kernel_size = kernel_end - kernel_start;
+ const paddr_t rambase = info->mem.bank[0].start;
+ const paddr_t ramsize = info->mem.bank[0].size;
+ const paddr_t ramend = rambase + ramsize;
+ const paddr_t kernsize = ROUNDUP(kernend, MB(2)) - kernbase;
+ const paddr_t ram128mb = rambase + MB(128);
- paddr_t addr;
+ paddr_t modbase;
- if ( total + kernel_size > mem_size )
- panic("Not enough memory in the first bank for the dtb+initrd");
+ if ( modsize + kernsize > ramsize )
+ panic("Not enough memory in the first bank for the kernel+dtb+initrd");
/*
* DTB must be loaded such that it does not conflict with the
@@ -99,35 +98,70 @@ static void place_modules(struct kernel_info *info,
* If the bootloader provides an initrd, it will be loaded just
* after the DTB.
*
- * We try to place dtb+initrd at 128MB, (or, if we have less RAM,
- * as high as possible). If there is no space then fallback to
- * just after the kernel, if there is room, otherwise just before.
+ * We try to place dtb+initrd at 128MB or if we have less RAM
+ * as high as possible. If there is no space then fallback to
+ * just before the kernel.
+ *
+ * If changing this then consider
+ * tools/libxc/xc_dom_arm.c:arch_setup_meminit as well.
*/
-
- if ( kernel_end < MIN(mem_start + MB(128), mem_end - total) )
- addr = MIN(mem_start + MB(128), mem_end - total);
- else if ( mem_end - ROUNDUP(kernel_end, MB(2)) >= total )
- addr = ROUNDUP(kernel_end, MB(2));
- else if ( kernel_start - mem_start >= total )
- addr = kernel_start - total;
+ if ( ramend >= ram128mb + modsize && kernend < ram128mb )
+ modbase = ram128mb;
+ else if ( ramend - modsize > ROUNDUP(kernend, MB(2)) )
+ modbase = ramend - modsize;
+ else if ( kernbase - rambase > modsize )
+ modbase = kernbase - modsize;
else
{
panic("Unable to find suitable location for dtb+initrd");
return;
}
- info->dtb_paddr = addr;
+ info->dtb_paddr = modbase;
info->initrd_paddr = info->dtb_paddr + dtb_len;
}
+static paddr_t kernel_zimage_place(struct kernel_info *info)
+{
+ paddr_t load_addr;
+
+#ifdef CONFIG_ARM_64
+ if ( info->type == DOMAIN_64BIT )
+ return info->mem.bank[0].start + info->zimage.text_offset;
+#endif
+
+ /*
+ * If start is zero, the zImage is position independent, in this
+ * case Documentation/arm/Booting recommends loading below 128MiB
+ * and above 32MiB. Load it as high as possible within these
+ * constraints, while also avoiding the DTB.
+ */
+ if ( info->zimage.start == 0 )
+ {
+ paddr_t load_end;
+
+ load_end = info->mem.bank[0].start + info->mem.bank[0].size;
+ load_end = MIN(info->mem.bank[0].start + MB(128), load_end);
+
+ load_addr = load_end - info->zimage.len;
+ /* Align to 2MB */
+ load_addr &= ~((2 << 20) - 1);
+ }
+ else
+ load_addr = info->zimage.start;
+
+ return load_addr;
+}
+
static void kernel_zimage_load(struct kernel_info *info)
{
- paddr_t load_addr = info->zimage.load_addr;
+ paddr_t load_addr = kernel_zimage_place(info);
paddr_t paddr = info->zimage.kernel_addr;
- paddr_t attr = info->load_attr;
paddr_t len = info->zimage.len;
unsigned long offs;
+ info->entry = load_addr;
+
place_modules(info, load_addr, load_addr + len);
printk("Loading zImage from %"PRIpaddr" to %"PRIpaddr"-%"PRIpaddr"\n",
@@ -150,19 +184,85 @@ static void kernel_zimage_load(struct kernel_info *info)
dst = map_domain_page(ma>>PAGE_SHIFT);
- copy_from_paddr(dst + s, paddr + offs, l, attr);
+ copy_from_paddr(dst + s, paddr + offs, l);
unmap_domain_page(dst);
offs += l;
}
}
+/*
+ * Uimage CPU Architecture Codes
+ */
+#define IH_ARCH_ARM 2 /* ARM */
+#define IH_ARCH_ARM64 22 /* ARM64 */
+
+/*
+ * Check if the image is a uImage and setup kernel_info
+ */
+static int kernel_uimage_probe(struct kernel_info *info,
+ paddr_t addr, paddr_t size)
+{
+ struct {
+ __be32 magic; /* Image Header Magic Number */
+ __be32 hcrc; /* Image Header CRC Checksum */
+ __be32 time; /* Image Creation Timestamp */
+ __be32 size; /* Image Data Size */
+ __be32 load; /* Data Load Address */
+ __be32 ep; /* Entry Point Address */
+ __be32 dcrc; /* Image Data CRC Checksum */
+ uint8_t os; /* Operating System */
+ uint8_t arch; /* CPU architecture */
+ uint8_t type; /* Image Type */
+ uint8_t comp; /* Compression Type */
+ uint8_t name[UIMAGE_NMLEN]; /* Image Name */
+ } uimage;
+
+ uint32_t len;
+
+ if ( size < sizeof(uimage) )
+ return -EINVAL;
+
+ copy_from_paddr(&uimage, addr, sizeof(uimage));
+
+ if ( be32_to_cpu(uimage.magic) != UIMAGE_MAGIC )
+ return -EINVAL;
+
+ len = be32_to_cpu(uimage.size);
+
+ if ( len > size - sizeof(uimage) )
+ return -EINVAL;
+
+ info->zimage.kernel_addr = addr + sizeof(uimage);
+ info->zimage.len = len;
+
+ info->entry = info->zimage.start;
+ info->load = kernel_zimage_load;
+
+#ifdef CONFIG_ARM_64
+ switch ( uimage.arch )
+ {
+ case IH_ARCH_ARM:
+ info->type = DOMAIN_32BIT;
+ break;
+ case IH_ARCH_ARM64:
+ info->type = DOMAIN_64BIT;
+ break;
+ default:
+ printk(XENLOG_ERR "Unsupported uImage arch type %d\n", uimage.arch);
+ return -EINVAL;
+ }
+#endif
+
+ return 0;
+}
+
#ifdef CONFIG_ARM_64
/*
- * Check if the image is a 64-bit zImage and setup kernel_info
+ * Check if the image is a 64-bit Image.
*/
-static int kernel_try_zimage64_prepare(struct kernel_info *info,
- paddr_t addr, paddr_t size)
+static int kernel_zimage64_probe(struct kernel_info *info,
+ paddr_t addr, paddr_t size)
{
/* linux/Documentation/arm64/booting.txt */
struct {
@@ -183,7 +283,7 @@ static int kernel_try_zimage64_prepare(struct kernel_info *info,
if ( size < sizeof(zimage) )
return -EINVAL;
- copy_from_paddr(&zimage, addr, sizeof(zimage), DEV_SHARED);
+ copy_from_paddr(&zimage, addr, sizeof(zimage));
if ( zimage.magic0 != ZIMAGE64_MAGIC_V0 &&
zimage.magic1 != ZIMAGE64_MAGIC_V1 )
@@ -201,15 +301,12 @@ static int kernel_try_zimage64_prepare(struct kernel_info *info,
return -EINVAL;
info->zimage.kernel_addr = addr;
-
- info->zimage.load_addr = info->mem.bank[0].start
- + zimage.text_offset;
info->zimage.len = end - start;
+ info->zimage.text_offset = zimage.text_offset;
- info->entry = info->zimage.load_addr;
info->load = kernel_zimage_load;
- info->type = DOMAIN_PV64;
+ info->type = DOMAIN_64BIT;
return 0;
}
@@ -218,8 +315,8 @@ static int kernel_try_zimage64_prepare(struct kernel_info *info,
/*
* Check if the image is a 32-bit zImage and setup kernel_info
*/
-static int kernel_try_zimage32_prepare(struct kernel_info *info,
- paddr_t addr, paddr_t size)
+static int kernel_zimage32_probe(struct kernel_info *info,
+ paddr_t addr, paddr_t size)
{
uint32_t zimage[ZIMAGE32_HEADER_LEN/4];
uint32_t start, end;
@@ -228,7 +325,7 @@ static int kernel_try_zimage32_prepare(struct kernel_info *info,
if ( size < ZIMAGE32_HEADER_LEN )
return -EINVAL;
- copy_from_paddr(zimage, addr, sizeof(zimage), DEV_SHARED);
+ copy_from_paddr(zimage, addr, sizeof(zimage));
if (zimage[ZIMAGE32_MAGIC_OFFSET/4] != ZIMAGE32_MAGIC)
return -EINVAL;
@@ -244,8 +341,7 @@ static int kernel_try_zimage32_prepare(struct kernel_info *info,
*/
if ( addr + end - start + sizeof(dtb_hdr) <= size )
{
- copy_from_paddr(&dtb_hdr, addr + end - start,
- sizeof(dtb_hdr), DEV_SHARED);
+ copy_from_paddr(&dtb_hdr, addr + end - start, sizeof(dtb_hdr));
if (be32_to_cpu(dtb_hdr.magic) == DTB_MAGIC) {
end += be32_to_cpu(dtb_hdr.total_size);
@@ -256,32 +352,13 @@ static int kernel_try_zimage32_prepare(struct kernel_info *info,
info->zimage.kernel_addr = addr;
- /*
- * If start is zero, the zImage is position independent, in this
- * case Documentation/arm/Booting recommends loading below 128MiB
- * and above 32MiB. Load it as high as possible within these
- * constraints, while also avoiding the DTB.
- */
- if (start == 0)
- {
- paddr_t load_end;
-
- load_end = info->mem.bank[0].start + info->mem.bank[0].size;
- load_end = MIN(info->mem.bank[0].start + MB(128), load_end);
-
- info->zimage.load_addr = load_end - end;
- /* Align to 2MB */
- info->zimage.load_addr &= ~((2 << 20) - 1);
- }
- else
- info->zimage.load_addr = start;
+ info->zimage.start = start;
info->zimage.len = end - start;
- info->entry = info->zimage.load_addr;
info->load = kernel_zimage_load;
#ifdef CONFIG_ARM_64
- info->type = DOMAIN_PV32;
+ info->type = DOMAIN_32BIT;
#endif
return 0;
@@ -289,6 +366,12 @@ static int kernel_try_zimage32_prepare(struct kernel_info *info,
static void kernel_elf_load(struct kernel_info *info)
{
+ /*
+ * TODO: can the ELF header be used to find the physical address
+ * to load the image to? Instead of assuming virt == phys.
+ */
+ info->entry = info->elf.parms.virt_entry;
+
place_modules(info,
info->elf.parms.virt_kstart,
info->elf.parms.virt_kend);
@@ -301,24 +384,24 @@ static void kernel_elf_load(struct kernel_info *info)
elf_load_binary(&info->elf.elf);
printk("Free temporary kernel buffer\n");
- free_xenheap_pages(info->kernel_img, info->kernel_order);
+ free_xenheap_pages(info->elf.kernel_img, info->elf.kernel_order);
}
-static int kernel_try_elf_prepare(struct kernel_info *info,
- paddr_t addr, paddr_t size)
+static int kernel_elf_probe(struct kernel_info *info,
+ paddr_t addr, paddr_t size)
{
int rc;
memset(&info->elf.elf, 0, sizeof(info->elf.elf));
- info->kernel_order = get_order_from_bytes(size);
- info->kernel_img = alloc_xenheap_pages(info->kernel_order, 0);
- if ( info->kernel_img == NULL )
+ info->elf.kernel_order = get_order_from_bytes(size);
+ info->elf.kernel_img = alloc_xenheap_pages(info->elf.kernel_order, 0);
+ if ( info->elf.kernel_img == NULL )
panic("Cannot allocate temporary buffer for kernel");
- copy_from_paddr(info->kernel_img, addr, size, info->load_attr);
+ copy_from_paddr(info->elf.kernel_img, addr, size);
- if ( (rc = elf_init(&info->elf.elf, info->kernel_img, size )) != 0 )
+ if ( (rc = elf_init(&info->elf.elf, info->elf.kernel_img, size )) != 0 )
goto err;
#ifdef VERBOSE
elf_set_verbose(&info->elf.elf);
@@ -329,9 +412,9 @@ static int kernel_try_elf_prepare(struct kernel_info *info,
#ifdef CONFIG_ARM_64
if ( elf_32bit(&info->elf.elf) )
- info->type = DOMAIN_PV32;
+ info->type = DOMAIN_32BIT;
else if ( elf_64bit(&info->elf.elf) )
- info->type = DOMAIN_PV64;
+ info->type = DOMAIN_64BIT;
else
{
printk("Unknown ELF class\n");
@@ -340,11 +423,6 @@ static int kernel_try_elf_prepare(struct kernel_info *info,
}
#endif
- /*
- * TODO: can the ELF header be used to find the physical address
- * to load the image to? Instead of assuming virt == phys.
- */
- info->entry = info->elf.parms.virt_entry;
info->load = kernel_elf_load;
if ( elf_check_broken(&info->elf.elf) )
@@ -357,38 +435,43 @@ err:
printk("Xen: ELF kernel broken: %s\n",
elf_check_broken(&info->elf.elf));
- free_xenheap_pages(info->kernel_img, info->kernel_order);
+ free_xenheap_pages(info->elf.kernel_img, info->elf.kernel_order);
return rc;
}
-int kernel_prepare(struct kernel_info *info)
+int kernel_probe(struct kernel_info *info)
{
+ struct bootmodule *mod = boot_module_find_by_kind(BOOTMOD_KERNEL);
int rc;
paddr_t start, size;
- if ( early_info.modules.nr_mods < MOD_KERNEL )
- {
- printk("No boot modules found, trying flash\n");
- start = KERNEL_FLASH_ADDRESS;
- size = KERNEL_FLASH_SIZE;
- info->load_attr = DEV_SHARED;
- }
- else
+ if ( !mod || !mod->size )
{
- printk("Loading kernel from boot module %d\n", MOD_KERNEL);
- start = early_info.modules.module[MOD_KERNEL].start;
- size = early_info.modules.module[MOD_KERNEL].size;
- info->load_attr = BUFFERABLE;
+ printk(XENLOG_ERR "Missing kernel boot module?\n");
+ return -ENOENT;
}
+ info->kernel_bootmodule = mod;
+ start = mod->start;
+ size = mod->size;
+
+ printk("Loading kernel from boot module @ %"PRIpaddr"\n", start);
+
+ info->initrd_bootmodule = boot_module_find_by_kind(BOOTMOD_RAMDISK);
+ if ( info->initrd_bootmodule )
+ printk("Loading ramdisk from boot module @ %"PRIpaddr"\n",
+ info->initrd_bootmodule->start);
+
#ifdef CONFIG_ARM_64
- rc = kernel_try_zimage64_prepare(info, start, size);
+ rc = kernel_zimage64_probe(info, start, size);
if (rc < 0)
#endif
- rc = kernel_try_zimage32_prepare(info, start, size);
+ rc = kernel_uimage_probe(info, start, size);
+ if (rc < 0)
+ rc = kernel_zimage32_probe(info, start, size);
if (rc < 0)
- rc = kernel_try_elf_prepare(info, start, size);
+ rc = kernel_elf_probe(info, start, size);
return rc;
}
diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
index b48c2c9..0050dfb 100644
--- a/xen/arch/arm/kernel.h
+++ b/xen/arch/arm/kernel.h
@@ -8,6 +8,7 @@
#include <xen/libelf.h>
#include <xen/device_tree.h>
+#include <asm/setup.h>
struct kernel_info {
#ifdef CONFIG_ARM_64
@@ -16,34 +17,59 @@ struct kernel_info {
void *fdt; /* flat device tree */
paddr_t unassigned_mem; /* RAM not (yet) assigned to a bank */
- struct dt_mem_info mem;
+ struct meminfo mem;
- paddr_t dtb_paddr;
+ /* kernel entry point */
paddr_t entry;
+ /* boot blob load addresses */
+ const struct bootmodule *kernel_bootmodule, *initrd_bootmodule;
+ paddr_t dtb_paddr;
paddr_t initrd_paddr;
- void *kernel_img;
- unsigned kernel_order;
-
+ /* loader to use for this kernel */
+ void (*load)(struct kernel_info *info);
+ /* loader specific state */
union {
struct {
paddr_t kernel_addr;
- paddr_t load_addr;
paddr_t len;
+#ifdef CONFIG_ARM_64
+ paddr_t text_offset; /* 64-bit Image only */
+#endif
+ paddr_t start; /* 32-bit zImage only */
} zimage;
struct {
struct elf_binary elf;
struct elf_dom_parms parms;
+ unsigned kernel_order;
+ void *kernel_img;
} elf;
};
-
- void (*load)(struct kernel_info *info);
- int load_attr;
};
-int kernel_prepare(struct kernel_info *info);
+/*
+ * Probe the kernel to detemine its type and select a loader.
+ *
+ * Sets in info:
+ * ->type
+ * ->load hook, and sets loader specific variables ->{zimage,elf}
+ */
+int kernel_probe(struct kernel_info *info);
+
+/*
+ * Loads the kernel into guest RAM.
+ *
+ * Expects to be set in info when called:
+ * ->mem
+ * ->fdt
+ *
+ * Sets in info:
+ * ->entry
+ * ->dtb_paddr
+ * ->initrd_paddr
+ */
void kernel_load(struct kernel_info *info);
#endif /* #ifdef __ARCH_ARM_KERNEL_H__ */
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 308a798..7d4ba0c 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -37,7 +37,6 @@
#include <public/memory.h>
#include <xen/sched.h>
#include <xen/vmap.h>
-#include <asm/early_printk.h>
#include <xsm/xsm.h>
#include <xen/pfn.h>
@@ -48,8 +47,9 @@ struct domain *dom_xen, *dom_io, *dom_cow;
* to the CPUs own pagetables.
*
* These pagetables have a very simple structure. They include:
- * - a 2MB mapping of xen at XEN_VIRT_START, boot_first and
- * boot_second are used to populate the trie down to that mapping.
+ * - 2MB worth of 4K mappings of xen at XEN_VIRT_START, boot_first and
+ * boot_second are used to populate the tables down to boot_third
+ * which contains the actual mapping.
* - a 1:1 mapping of xen at its current physical address. This uses a
* section mapping at whichever of boot_{pgtable,first,second}
* covers that physical address.
@@ -68,8 +68,10 @@ struct domain *dom_xen, *dom_io, *dom_cow;
lpae_t boot_pgtable[LPAE_ENTRIES] __attribute__((__aligned__(4096)));
#ifdef CONFIG_ARM_64
lpae_t boot_first[LPAE_ENTRIES] __attribute__((__aligned__(4096)));
+lpae_t boot_first_id[LPAE_ENTRIES] __attribute__((__aligned__(4096)));
#endif
lpae_t boot_second[LPAE_ENTRIES] __attribute__((__aligned__(4096)));
+lpae_t boot_third[LPAE_ENTRIES] __attribute__((__aligned__(4096)));
/* Main runtime page tables */
@@ -82,10 +84,12 @@ lpae_t boot_second[LPAE_ENTRIES] __attribute__((__aligned__(4096)));
*/
#ifdef CONFIG_ARM_64
+#define HYP_PT_ROOT_LEVEL 0
lpae_t xen_pgtable[LPAE_ENTRIES] __attribute__((__aligned__(4096)));
lpae_t xen_first[LPAE_ENTRIES] __attribute__((__aligned__(4096)));
#define THIS_CPU_PGTABLE xen_pgtable
#else
+#define HYP_PT_ROOT_LEVEL 1
/* Per-CPU pagetable pages */
/* xen_pgtable == root of the trie (zeroeth level on 64-bit, first on 32-bit) */
static DEFINE_PER_CPU(lpae_t *, xen_pgtable);
@@ -134,9 +138,12 @@ static paddr_t phys_offset;
/* Limits of the Xen heap */
unsigned long xenheap_mfn_start __read_mostly = ~0UL;
unsigned long xenheap_mfn_end __read_mostly;
-unsigned long xenheap_virt_end __read_mostly;
+vaddr_t xenheap_virt_end __read_mostly;
+#ifdef CONFIG_ARM_64
+vaddr_t xenheap_virt_start __read_mostly;
+#endif
-unsigned long frametable_base_mfn __read_mostly;
+unsigned long frametable_base_pdx __read_mostly;
unsigned long frametable_virt_end __read_mostly;
unsigned long max_page;
@@ -151,7 +158,11 @@ static inline void check_memory_layout_alignment_constraints(void) {
BUILD_BUG_ON(FIXMAP_ADDR(0) & ~SECOND_MASK);
BUILD_BUG_ON(BOOT_RELOC_VIRT_START & ~SECOND_MASK);
/* 1GB aligned regions */
+#ifdef CONFIG_ARM_32
BUILD_BUG_ON(XENHEAP_VIRT_START & ~FIRST_MASK);
+#else
+ BUILD_BUG_ON(DIRECTMAP_VIRT_START & ~FIRST_MASK);
+#endif
/* Page table structure constraints */
#ifdef CONFIG_ARM_64
BUILD_BUG_ON(zeroeth_table_offset(XEN_VIRT_START));
@@ -163,34 +174,66 @@ static inline void check_memory_layout_alignment_constraints(void) {
#endif
}
-void dump_pt_walk(lpae_t *first, paddr_t addr)
+void dump_pt_walk(paddr_t ttbr, paddr_t addr,
+ unsigned int root_level,
+ unsigned int nr_root_tables)
{
- lpae_t *second = NULL, *third = NULL;
+ static const char *level_strs[4] = { "0TH", "1ST", "2ND", "3RD" };
+ const unsigned long root_pfn = paddr_to_pfn(ttbr);
+ const unsigned int offsets[4] = {
+ zeroeth_table_offset(addr),
+ first_table_offset(addr),
+ second_table_offset(addr),
+ third_table_offset(addr)
+ };
+ lpae_t pte, *mapping;
+ unsigned int level, root_table;
- if ( first_table_offset(addr) >= LPAE_ENTRIES )
- return;
+#ifdef CONFIG_ARM_32
+ BUG_ON(root_level < 1);
+#endif
+ BUG_ON(root_level > 3);
+
+ if ( nr_root_tables > 1 )
+ {
+ /*
+ * Concatenated root-level tables. The table number will be
+ * the offset at the previous level. It is not possible to
+ * concatenate a level-0 root.
+ */
+ BUG_ON(root_level == 0);
+ root_table = offsets[root_level - 1];
+ printk("Using concatenated root table %u\n", root_table);
+ if ( root_table >= nr_root_tables )
+ {
+ printk("Invalid root table offset\n");
+ return;
+ }
+ }
+ else
+ root_table = 0;
- printk("1ST[0x%x] = 0x%"PRIpaddr"\n", first_table_offset(addr),
- first[first_table_offset(addr)].bits);
- if ( !first[first_table_offset(addr)].walk.valid ||
- !first[first_table_offset(addr)].walk.table )
- goto done;
+ mapping = map_domain_page(root_pfn + root_table);
- second = map_domain_page(first[first_table_offset(addr)].walk.base);
- printk("2ND[0x%x] = 0x%"PRIpaddr"\n", second_table_offset(addr),
- second[second_table_offset(addr)].bits);
- if ( !second[second_table_offset(addr)].walk.valid ||
- !second[second_table_offset(addr)].walk.table )
- goto done;
+ for ( level = root_level; ; level++ )
+ {
+ if ( offsets[level] > LPAE_ENTRIES )
+ break;
+
+ pte = mapping[offsets[level]];
- third = map_domain_page(second[second_table_offset(addr)].walk.base);
- printk("3RD[0x%x] = 0x%"PRIpaddr"\n", third_table_offset(addr),
- third[third_table_offset(addr)].bits);
+ printk("%s[0x%x] = 0x%"PRIpaddr"\n",
+ level_strs[level], offsets[level], pte.bits);
-done:
- if (third) unmap_domain_page(third);
- if (second) unmap_domain_page(second);
+ if ( level == 3 || !pte.walk.valid || !pte.walk.table )
+ break;
+ /* For next iteration */
+ unmap_domain_page(mapping);
+ mapping = map_domain_page(pte.walk.base);
+ }
+
+ unmap_domain_page(mapping);
}
void dump_hyp_walk(vaddr_t addr)
@@ -206,15 +249,14 @@ void dump_hyp_walk(vaddr_t addr)
BUG_ON( (lpae_t *)(unsigned long)(ttbr - phys_offset) != pgtable );
else
BUG_ON( virt_to_maddr(pgtable) != ttbr );
- dump_pt_walk(pgtable, addr);
+ dump_pt_walk(ttbr, addr, HYP_PT_ROOT_LEVEL, 1);
}
/* Map a 4k page in a fixmap entry */
void set_fixmap(unsigned map, unsigned long mfn, unsigned attributes)
{
- lpae_t pte = mfn_to_xen_entry(mfn);
+ lpae_t pte = mfn_to_xen_entry(mfn, attributes);
pte.pt.table = 1; /* 4k mappings always have this bit set */
- pte.pt.ai = attributes;
pte.pt.xn = 1;
write_pte(xen_fixmap + third_table_offset(FIXMAP_ADDR(map)), pte);
flush_xen_data_tlb_range_va(FIXMAP_ADDR(map), PAGE_SIZE);
@@ -270,7 +312,7 @@ void *map_domain_page(unsigned long mfn)
else if ( map[slot].pt.avail == 0 )
{
/* Commandeer this 2MB slot */
- pte = mfn_to_xen_entry(slot_mfn);
+ pte = mfn_to_xen_entry(slot_mfn, WRITEALLOC);
pte.pt.avail = 1;
write_pte(map + slot, pte);
break;
@@ -303,7 +345,7 @@ void *map_domain_page(unsigned long mfn)
* We may not have flushed this specific subpage at map time,
* since we only flush the 4k page not the superpage
*/
- flush_xen_data_tlb_range_va(va, PAGE_SIZE);
+ flush_xen_data_tlb_range_va_local(va, PAGE_SIZE);
return (void *)va;
}
@@ -344,13 +386,9 @@ unsigned long domain_page_map_to_mfn(const void *ptr)
void flush_page_to_ram(unsigned long mfn)
{
- void *p, *v = map_domain_page(mfn);
-
- dsb(); /* So the CPU issues all writes to the range */
- for ( p = v; p < v + PAGE_SIZE ; p += cacheline_bytes )
- asm volatile (__clean_and_invalidate_xen_dcache_one(0) : : "r" (p));
- dsb(); /* So we know the flushes happen before continuing */
+ void *v = map_domain_page(mfn);
+ clean_and_invalidate_dcache_va_range(v, PAGE_SIZE);
unmap_domain_page(v);
}
@@ -380,28 +418,11 @@ void __init arch_init_memory(void)
BUG_ON(IS_ERR(dom_cow));
}
-void __cpuinit setup_virt_paging(void)
-{
- /* Setup Stage 2 address translation */
- /* SH0=00, ORGN0=IRGN0=01
- * SL0=01 (Level-1)
- * ARVv7: T0SZ=(1)1000 = -8 (32-(-8) = 40 bit physical addresses)
- * ARMv8: T0SZ=01 1000 = 24 (64-24 = 40 bit physical addresses)
- * PS=010 == 40 bits
- */
-#ifdef CONFIG_ARM_32
- WRITE_SYSREG32(0x80002558, VTCR_EL2);
-#else
- WRITE_SYSREG32(0x80022558, VTCR_EL2);
-#endif
- isb();
-}
-
static inline lpae_t pte_of_xenaddr(vaddr_t va)
{
paddr_t ma = va + phys_offset;
unsigned long mfn = ma >> PAGE_SHIFT;
- return mfn_to_xen_entry(mfn);
+ return mfn_to_xen_entry(mfn, WRITEALLOC);
}
void __init remove_early_mappings(void)
@@ -422,6 +443,12 @@ void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
lpae_t pte, *p;
int i;
+ /* Map the destination in the boot misc area. */
+ dest_va = BOOT_RELOC_VIRT_START;
+ pte = mfn_to_xen_entry(xen_paddr >> PAGE_SHIFT, WRITEALLOC);
+ write_pte(xen_second + second_table_offset(dest_va), pte);
+ flush_xen_data_tlb_range_va_local(dest_va, SECOND_SIZE);
+
/* Calculate virt-to-phys offset for the new location */
phys_offset = xen_paddr - (unsigned long) _start;
@@ -455,7 +482,7 @@ void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
/* Initialise xen second level entries ... */
/* ... Xen's text etc */
- pte = mfn_to_xen_entry(xen_paddr>>PAGE_SHIFT);
+ pte = mfn_to_xen_entry(xen_paddr>>PAGE_SHIFT, WRITEALLOC);
pte.pt.xn = 0;/* Contains our text mapping! */
xen_second[second_table_offset(XEN_VIRT_START)] = pte;
@@ -470,9 +497,9 @@ void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
/* Map the destination in the boot misc area. */
dest_va = BOOT_RELOC_VIRT_START;
- pte = mfn_to_xen_entry(xen_paddr >> PAGE_SHIFT);
+ pte = mfn_to_xen_entry(xen_paddr >> PAGE_SHIFT, WRITEALLOC);
write_pte(boot_second + second_table_offset(dest_va), pte);
- flush_xen_data_tlb_range_va(dest_va, SECOND_SIZE);
+ flush_xen_data_tlb_range_va_local(dest_va, SECOND_SIZE);
#ifdef CONFIG_ARM_64
ttbr = (uintptr_t) xen_pgtable + phys_offset;
#else
@@ -484,13 +511,17 @@ void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
/* Clear the copy of the boot pagetables. Each secondary CPU
* rebuilds these itself (see head.S) */
memset(boot_pgtable, 0x0, PAGE_SIZE);
- clean_xen_dcache(boot_pgtable);
+ clean_and_invalidate_dcache(boot_pgtable);
#ifdef CONFIG_ARM_64
memset(boot_first, 0x0, PAGE_SIZE);
- clean_xen_dcache(boot_first);
+ clean_and_invalidate_dcache(boot_first);
+ memset(boot_first_id, 0x0, PAGE_SIZE);
+ clean_and_invalidate_dcache(boot_first_id);
#endif
memset(boot_second, 0x0, PAGE_SIZE);
- clean_xen_dcache(boot_second);
+ clean_and_invalidate_dcache(boot_second);
+ memset(boot_third, 0x0, PAGE_SIZE);
+ clean_and_invalidate_dcache(boot_third);
/* Break up the Xen mapping into 4k pages and protect them separately. */
for ( i = 0; i < LPAE_ENTRIES; i++ )
@@ -499,7 +530,7 @@ void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
unsigned long va = XEN_VIRT_START + (i << PAGE_SHIFT);
if ( !is_kernel(va) )
break;
- pte = mfn_to_xen_entry(mfn);
+ pte = mfn_to_xen_entry(mfn, WRITEALLOC);
pte.pt.table = 1; /* 4k mappings always have this bit set */
if ( is_kernel_text(va) || is_kernel_inittext(va) )
{
@@ -520,7 +551,7 @@ void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
/* From now on, no mapping may be both writable and executable. */
WRITE_SYSREG32(READ_SYSREG32(SCTLR_EL2) | SCTLR_WXN, SCTLR_EL2);
/* Flush everything after setting WXN bit. */
- flush_xen_text_tlb();
+ flush_xen_text_tlb_local();
#ifdef CONFIG_ARM_32
per_cpu(xen_pgtable, 0) = cpu0_pgtable;
@@ -528,7 +559,7 @@ void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
/* Make sure it is clear */
memset(this_cpu(xen_dommap), 0, DOMHEAP_SECOND_PAGES*PAGE_SIZE);
- clean_xen_dcache_va_range(this_cpu(xen_dommap),
+ clean_dcache_va_range(this_cpu(xen_dommap),
DOMHEAP_SECOND_PAGES*PAGE_SIZE);
#endif
}
@@ -539,7 +570,7 @@ int init_secondary_pagetables(int cpu)
/* Set init_ttbr for this CPU coming up. All CPus share a single setof
* pagetables, but rewrite it each time for consistency with 32 bit. */
init_ttbr = (uintptr_t) xen_pgtable + phys_offset;
- clean_xen_dcache(init_ttbr);
+ clean_dcache(init_ttbr);
return 0;
}
#else
@@ -569,20 +600,20 @@ int init_secondary_pagetables(int cpu)
* domheap mapping pages. */
for ( i = 0; i < DOMHEAP_SECOND_PAGES; i++ )
{
- pte = mfn_to_xen_entry(virt_to_mfn(domheap+i*LPAE_ENTRIES));
+ pte = mfn_to_xen_entry(virt_to_mfn(domheap+i*LPAE_ENTRIES), WRITEALLOC);
pte.pt.table = 1;
write_pte(&first[first_table_offset(DOMHEAP_VIRT_START+i*FIRST_SIZE)], pte);
}
- clean_xen_dcache_va_range(first, PAGE_SIZE);
- clean_xen_dcache_va_range(domheap, DOMHEAP_SECOND_PAGES*PAGE_SIZE);
+ clean_dcache_va_range(first, PAGE_SIZE);
+ clean_dcache_va_range(domheap, DOMHEAP_SECOND_PAGES*PAGE_SIZE);
per_cpu(xen_pgtable, cpu) = first;
per_cpu(xen_dommap, cpu) = domheap;
/* Set init_ttbr for this CPU coming up */
init_ttbr = __pa(first);
- clean_xen_dcache(init_ttbr);
+ clean_dcache(init_ttbr);
return 0;
}
@@ -593,7 +624,7 @@ void __cpuinit mmu_init_secondary_cpu(void)
{
/* From now on, no mapping may be both writable and executable. */
WRITE_SYSREG32(READ_SYSREG32(SCTLR_EL2) | SCTLR_WXN, SCTLR_EL2);
- flush_xen_text_tlb();
+ flush_xen_text_tlb_local();
}
/* Create Xen's mappings of memory.
@@ -614,14 +645,14 @@ static void __init create_32mb_mappings(lpae_t *second,
count = nr_mfns / LPAE_ENTRIES;
p = second + second_linear_offset(virt_offset);
- pte = mfn_to_xen_entry(base_mfn);
+ pte = mfn_to_xen_entry(base_mfn, WRITEALLOC);
pte.pt.contig = 1; /* These maps are in 16-entry contiguous chunks. */
for ( i = 0; i < count; i++ )
{
write_pte(p + i, pte);
pte.pt.base += 1 << LPAE_SHIFT;
}
- flush_xen_data_tlb();
+ flush_xen_data_tlb_local();
}
#ifdef CONFIG_ARM_32
@@ -641,26 +672,33 @@ void __init setup_xenheap_mappings(unsigned long base_mfn,
unsigned long nr_mfns)
{
lpae_t *first, pte;
- unsigned long offset, end_mfn;
+ unsigned long mfn, end_mfn;
vaddr_t vaddr;
- /* First call sets the xenheap physical offset. */
+ /* Align to previous 1GB boundary */
+ mfn = base_mfn & ~((FIRST_SIZE>>PAGE_SHIFT)-1);
+
+ /* First call sets the xenheap physical and virtual offset. */
if ( xenheap_mfn_start == ~0UL )
+ {
xenheap_mfn_start = base_mfn;
+ xenheap_virt_start = DIRECTMAP_VIRT_START +
+ (base_mfn - mfn) * PAGE_SIZE;
+ }
if ( base_mfn < xenheap_mfn_start )
- early_panic("cannot add xenheap mapping at %lx below heap start %lx",
- base_mfn, xenheap_mfn_start);
+ panic("cannot add xenheap mapping at %lx below heap start %lx",
+ base_mfn, xenheap_mfn_start);
end_mfn = base_mfn + nr_mfns;
- /* Align to previous 1GB boundary */
- base_mfn &= ~((FIRST_SIZE>>PAGE_SHIFT)-1);
-
- offset = base_mfn - xenheap_mfn_start;
- vaddr = DIRECTMAP_VIRT_START + offset*PAGE_SIZE;
+ /*
+ * Virtual address aligned to previous 1GB to match physical
+ * address alignment done above.
+ */
+ vaddr = (vaddr_t)mfn_to_virt(base_mfn) & FIRST_MASK;
- while ( base_mfn < end_mfn )
+ while ( mfn < end_mfn )
{
int slot = zeroeth_table_offset(vaddr);
lpae_t *p = &xen_pgtable[slot];
@@ -686,21 +724,21 @@ void __init setup_xenheap_mappings(unsigned long base_mfn,
else
{
unsigned long first_mfn = alloc_boot_pages(1, 1);
- pte = mfn_to_xen_entry(first_mfn);
+ pte = mfn_to_xen_entry(first_mfn, WRITEALLOC);
pte.pt.table = 1;
write_pte(p, pte);
first = mfn_to_virt(first_mfn);
}
- pte = mfn_to_xen_entry(base_mfn);
+ pte = mfn_to_xen_entry(mfn, WRITEALLOC);
/* TODO: Set pte.pt.contig when appropriate. */
write_pte(&first[first_table_offset(vaddr)], pte);
- base_mfn += FIRST_SIZE>>PAGE_SHIFT;
+ mfn += FIRST_SIZE>>PAGE_SHIFT;
vaddr += FIRST_SIZE;
}
- flush_xen_data_tlb();
+ flush_xen_data_tlb_local();
}
#endif
@@ -708,7 +746,8 @@ void __init setup_xenheap_mappings(unsigned long base_mfn,
void __init setup_frametable_mappings(paddr_t ps, paddr_t pe)
{
unsigned long nr_pages = (pe - ps) >> PAGE_SHIFT;
- unsigned long frametable_size = nr_pages * sizeof(struct page_info);
+ unsigned long nr_pdxs = pfn_to_pdx(nr_pages);
+ unsigned long frametable_size = nr_pdxs * sizeof(struct page_info);
unsigned long base_mfn;
#ifdef CONFIG_ARM_64
lpae_t *second, pte;
@@ -716,7 +755,7 @@ void __init setup_frametable_mappings(paddr_t ps, paddr_t pe)
int i;
#endif
- frametable_base_mfn = ps >> PAGE_SHIFT;
+ frametable_base_pdx = pfn_to_pdx(ps >> PAGE_SHIFT);
/* Round up to 32M boundary */
frametable_size = (frametable_size + 0x1ffffff) & ~0x1ffffff;
@@ -728,7 +767,7 @@ void __init setup_frametable_mappings(paddr_t ps, paddr_t pe)
second = mfn_to_virt(second_base);
for ( i = 0; i < nr_second; i++ )
{
- pte = mfn_to_xen_entry(second_base + i);
+ pte = mfn_to_xen_entry(second_base + i, WRITEALLOC);
pte.pt.table = 1;
write_pte(&xen_first[first_table_offset(FRAMETABLE_VIRT_START)+i], pte);
}
@@ -737,11 +776,11 @@ void __init setup_frametable_mappings(paddr_t ps, paddr_t pe)
create_32mb_mappings(xen_second, FRAMETABLE_VIRT_START, base_mfn, frametable_size >> PAGE_SHIFT);
#endif
- memset(&frame_table[0], 0, nr_pages * sizeof(struct page_info));
- memset(&frame_table[nr_pages], -1,
- frametable_size - (nr_pages * sizeof(struct page_info)));
+ memset(&frame_table[0], 0, nr_pdxs * sizeof(struct page_info));
+ memset(&frame_table[nr_pdxs], -1,
+ frametable_size - (nr_pdxs * sizeof(struct page_info)));
- frametable_virt_end = FRAMETABLE_VIRT_START + (nr_pages * sizeof(struct page_info));
+ frametable_virt_end = FRAMETABLE_VIRT_START + (nr_pdxs * sizeof(struct page_info));
}
void *__init arch_vmap_virt_end(void)
@@ -780,7 +819,7 @@ static int create_xen_table(lpae_t *entry)
if ( p == NULL )
return -ENOMEM;
clear_page(p);
- pte = mfn_to_xen_entry(virt_to_mfn(p));
+ pte = mfn_to_xen_entry(virt_to_mfn(p), WRITEALLOC);
pte.pt.table = 1;
write_pte(entry, pte);
return 0;
@@ -826,9 +865,8 @@ static int create_xen_entries(enum xenmap_operation op,
addr, mfn);
return -EINVAL;
}
- pte = mfn_to_xen_entry(mfn);
+ pte = mfn_to_xen_entry(mfn, ai);
pte.pt.table = 1;
- pte.pt.ai = ai;
write_pte(&third[third_table_offset(addr)], pte);
break;
case REMOVE:
@@ -908,7 +946,7 @@ static void set_pte_flags_on_range(const char *p, unsigned long l, enum mg mg)
}
write_pte(xen_xenmap + i, pte);
}
- flush_xen_text_tlb();
+ flush_xen_text_tlb_local();
}
/* Release all __init and __initdata ranges to be reused */
@@ -963,7 +1001,7 @@ void share_xen_page_with_guest(struct page_info *page,
page->u.inuse.type_info |= PGT_validated | 1;
page_set_owner(page, d);
- wmb(); /* install valid domain ptr before updating refcnt. */
+ smp_wmb(); /* install valid domain ptr before updating refcnt. */
ASSERT((page->count_info & ~PGC_xen_heap) == 0);
/* Only add to the allocation list if the domain isn't dying. */
@@ -994,6 +1032,7 @@ int xenmem_add_to_physmap_one(
unsigned long mfn = 0;
int rc;
p2m_type_t t;
+ struct page_info *page = NULL;
switch ( space )
{
@@ -1015,7 +1054,7 @@ int xenmem_add_to_physmap_one(
else
{
if ( (idx >= nr_grant_frames(d->grant_table)) &&
- (idx < max_nr_grant_frames) )
+ (idx < max_grant_frames) )
gnttab_grow_table(d, idx + 1);
if ( idx < nr_grant_frames(d->grant_table) )
@@ -1041,7 +1080,6 @@ int xenmem_add_to_physmap_one(
case XENMAPSPACE_gmfn_foreign:
{
struct domain *od;
- struct page_info *page;
p2m_type_t p2mt;
od = rcu_lock_domain_by_any_id(foreign_domid);
if ( od == NULL )
@@ -1091,6 +1129,14 @@ int xenmem_add_to_physmap_one(
/* Map at new location. */
rc = guest_physmap_add_entry(d, gpfn, mfn, 0, t);
+ /* If we fail to add the mapping, we need to drop the reference we
+ * took earlier on foreign pages */
+ if ( rc && space == XENMAPSPACE_gmfn_foreign )
+ {
+ ASSERT(page != NULL);
+ put_page(page);
+ }
+
return rc;
}
@@ -1235,6 +1281,16 @@ int is_iomem_page(unsigned long mfn)
return 1;
return 0;
}
+
+void clear_and_clean_page(struct page_info *page)
+{
+ void *p = __map_domain_page(page);
+
+ clear_page(p);
+ clean_dcache_va_range(p, PAGE_SIZE);
+ unmap_domain_page(p);
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index bc81b67..8809f5a 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -1,6 +1,7 @@
#include <xen/config.h>
#include <xen/sched.h>
#include <xen/lib.h>
+#include <xen/stdbool.h>
#include <xen/errno.h>
#include <xen/domain_page.h>
#include <xen/bitops.h>
@@ -10,32 +11,69 @@
#include <asm/hardirq.h>
#include <asm/page.h>
-/* First level P2M is 2 consecutive pages */
-#define P2M_FIRST_ORDER 1
-#define P2M_FIRST_ENTRIES (LPAE_ENTRIES<<P2M_FIRST_ORDER)
+#ifdef CONFIG_ARM_64
+static unsigned int __read_mostly p2m_root_order;
+static unsigned int __read_mostly p2m_root_level;
+#define P2M_ROOT_ORDER p2m_root_order
+#define P2M_ROOT_LEVEL p2m_root_level
+#else
+/* First level P2M is alway 2 consecutive pages */
+#define P2M_ROOT_LEVEL 1
+#define P2M_ROOT_ORDER 1
+#endif
+
+#define P2M_ROOT_PAGES (1<<P2M_ROOT_ORDER)
+
+static bool_t p2m_valid(lpae_t pte)
+{
+ return pte.p2m.valid;
+}
+/* These two can only be used on L0..L2 ptes because L3 mappings set
+ * the table bit and therefore these would return the opposite to what
+ * you would expect. */
+static bool_t p2m_table(lpae_t pte)
+{
+ return p2m_valid(pte) && pte.p2m.table;
+}
+static bool_t p2m_mapping(lpae_t pte)
+{
+ return p2m_valid(pte) && !pte.p2m.table;
+}
+
+void p2m_dump_info(struct domain *d)
+{
+ struct p2m_domain *p2m = &d->arch.p2m;
+
+ spin_lock(&p2m->lock);
+ printk("p2m mappings for domain %d (vmid %d):\n",
+ d->domain_id, p2m->vmid);
+ BUG_ON(p2m->stats.mappings[0] || p2m->stats.shattered[0]);
+ printk(" 1G mappings: %ld (shattered %ld)\n",
+ p2m->stats.mappings[1], p2m->stats.shattered[1]);
+ printk(" 2M mappings: %ld (shattered %ld)\n",
+ p2m->stats.mappings[2], p2m->stats.shattered[2]);
+ printk(" 4K mappings: %ld\n", p2m->stats.mappings[3]);
+ spin_unlock(&p2m->lock);
+}
+
+void memory_type_changed(struct domain *d)
+{
+}
void dump_p2m_lookup(struct domain *d, paddr_t addr)
{
struct p2m_domain *p2m = &d->arch.p2m;
- lpae_t *first;
printk("dom%d IPA 0x%"PRIpaddr"\n", d->domain_id, addr);
- if ( first_linear_offset(addr) > LPAE_ENTRIES )
- {
- printk("Cannot dump addresses in second of first level pages...\n");
- return;
- }
-
printk("P2M @ %p mfn:0x%lx\n",
- p2m->first_level, page_to_mfn(p2m->first_level));
+ p2m->root, page_to_mfn(p2m->root));
- first = __map_domain_page(p2m->first_level);
- dump_pt_walk(first, addr);
- unmap_domain_page(first);
+ dump_pt_walk(page_to_maddr(p2m->root), addr,
+ P2M_ROOT_LEVEL, P2M_ROOT_PAGES);
}
-void p2m_load_VTTBR(struct domain *d)
+static void p2m_load_VTTBR(struct domain *d)
{
if ( is_idle_domain(d) )
return;
@@ -60,7 +98,7 @@ void p2m_restore_state(struct vcpu *n)
p2m_load_VTTBR(n->domain);
isb();
- if ( is_pv32_domain(n->domain) )
+ if ( is_32bit_domain(n->domain) )
hcr &= ~HCR_RW;
else
hcr |= HCR_RW;
@@ -72,29 +110,27 @@ void p2m_restore_state(struct vcpu *n)
isb();
}
-static int p2m_first_level_index(paddr_t addr)
-{
- /*
- * 1st pages are concatenated so zeroeth offset gives us the
- * index of the 1st page
- */
- return zeroeth_table_offset(addr);
-}
-
-/*
- * Map whichever of the first pages contain addr. The caller should
- * then use first_table_offset as an index.
- */
-static lpae_t *p2m_map_first(struct p2m_domain *p2m, paddr_t addr)
+void flush_tlb_domain(struct domain *d)
{
- struct page_info *page;
+ unsigned long flags = 0;
- if ( first_linear_offset(addr) >= P2M_FIRST_ENTRIES )
- return NULL;
+ /* Update the VTTBR if necessary with the domain d. In this case,
+ * it's only necessary to flush TLBs on every CPUs with the current VMID
+ * (our domain).
+ */
+ if ( d != current->domain )
+ {
+ local_irq_save(flags);
+ p2m_load_VTTBR(d);
+ }
- page = p2m->first_level + p2m_first_level_index(addr);
+ flush_tlb();
- return __map_domain_page(page);
+ if ( d != current->domain )
+ {
+ p2m_load_VTTBR(current->domain);
+ local_irq_restore(flags);
+ }
}
/*
@@ -106,52 +142,81 @@ static lpae_t *p2m_map_first(struct p2m_domain *p2m, paddr_t addr)
paddr_t p2m_lookup(struct domain *d, paddr_t paddr, p2m_type_t *t)
{
struct p2m_domain *p2m = &d->arch.p2m;
- lpae_t pte, *first = NULL, *second = NULL, *third = NULL;
+ const unsigned int offsets[4] = {
+ zeroeth_table_offset(paddr),
+ first_table_offset(paddr),
+ second_table_offset(paddr),
+ third_table_offset(paddr)
+ };
+ const paddr_t masks[4] = {
+ ZEROETH_MASK, FIRST_MASK, SECOND_MASK, THIRD_MASK
+ };
+ lpae_t pte, *map;
paddr_t maddr = INVALID_PADDR;
+ paddr_t mask = 0;
p2m_type_t _t;
+ unsigned int level, root_table;
+
+ BUILD_BUG_ON(THIRD_MASK != PAGE_MASK);
/* Allow t to be NULL */
t = t ?: &_t;
*t = p2m_invalid;
+ if ( P2M_ROOT_PAGES > 1 )
+ {
+ /*
+ * Concatenated root-level tables. The table number will be
+ * the offset at the previous level. It is not possible to
+ * concatenate a level-0 root.
+ */
+ ASSERT(P2M_ROOT_LEVEL > 0);
+ root_table = offsets[P2M_ROOT_LEVEL - 1];
+ if ( root_table >= P2M_ROOT_PAGES )
+ goto err;
+ }
+ else
+ root_table = 0;
+
spin_lock(&p2m->lock);
- first = p2m_map_first(p2m, paddr);
- if ( !first )
- goto err;
+ map = __map_domain_page(p2m->root + root_table);
- pte = first[first_table_offset(paddr)];
- if ( !pte.p2m.valid || !pte.p2m.table )
- goto done;
+ ASSERT(P2M_ROOT_LEVEL < 4);
+
+ for ( level = P2M_ROOT_LEVEL ; level < 4 ; level++ )
+ {
+ mask = masks[level];
- second = map_domain_page(pte.p2m.base);
- pte = second[second_table_offset(paddr)];
- if ( !pte.p2m.valid || !pte.p2m.table )
- goto done;
+ pte = map[offsets[level]];
- third = map_domain_page(pte.p2m.base);
- pte = third[third_table_offset(paddr)];
+ if ( level == 3 && !p2m_table(pte) )
+ /* Invalid, clobber the pte */
+ pte.bits = 0;
+ if ( level == 3 || !p2m_table(pte) )
+ /* Done */
+ break;
- /* This bit must be one in the level 3 entry */
- if ( !pte.p2m.table )
- pte.bits = 0;
+ ASSERT(level < 3);
-done:
- if ( pte.p2m.valid )
+ /* Map for next level */
+ unmap_domain_page(map);
+ map = map_domain_page(pte.p2m.base);
+ }
+
+ unmap_domain_page(map);
+
+ if ( p2m_valid(pte) )
{
+ ASSERT(mask);
ASSERT(pte.p2m.type != p2m_invalid);
- maddr = (pte.bits & PADDR_MASK & PAGE_MASK) | (paddr & ~PAGE_MASK);
+ maddr = (pte.bits & PADDR_MASK & mask) | (paddr & ~mask);
*t = pte.p2m.type;
}
- if (third) unmap_domain_page(third);
- if (second) unmap_domain_page(second);
- if (first) unmap_domain_page(first);
-
-err:
spin_unlock(&p2m->lock);
-
+err:
return maddr;
}
@@ -169,14 +234,84 @@ int p2m_pod_decrease_reservation(struct domain *d,
return -ENOSYS;
}
+static void p2m_set_permission(lpae_t *e, p2m_type_t t, p2m_access_t a)
+{
+ /* First apply type permissions */
+ switch ( t )
+ {
+ case p2m_ram_rw:
+ e->p2m.xn = 0;
+ e->p2m.write = 1;
+ break;
+
+ case p2m_ram_ro:
+ e->p2m.xn = 0;
+ e->p2m.write = 0;
+ break;
+
+ case p2m_iommu_map_rw:
+ case p2m_map_foreign:
+ case p2m_grant_map_rw:
+ case p2m_mmio_direct:
+ e->p2m.xn = 1;
+ e->p2m.write = 1;
+ break;
+
+ case p2m_iommu_map_ro:
+ case p2m_grant_map_ro:
+ case p2m_invalid:
+ e->p2m.xn = 1;
+ e->p2m.write = 0;
+ break;
+
+ case p2m_max_real_type:
+ BUG();
+ break;
+ }
+
+ /* Then restrict with access permissions */
+ switch ( a )
+ {
+ case p2m_access_rwx:
+ break;
+ case p2m_access_wx:
+ e->p2m.read = 0;
+ break;
+ case p2m_access_rw:
+ e->p2m.xn = 1;
+ break;
+ case p2m_access_w:
+ e->p2m.read = 0;
+ e->p2m.xn = 1;
+ break;
+ case p2m_access_rx:
+ case p2m_access_rx2rw:
+ e->p2m.write = 0;
+ break;
+ case p2m_access_x:
+ e->p2m.write = 0;
+ e->p2m.read = 0;
+ break;
+ case p2m_access_r:
+ e->p2m.write = 0;
+ e->p2m.xn = 1;
+ break;
+ case p2m_access_n:
+ case p2m_access_n2rwx:
+ e->p2m.read = e->p2m.write = 0;
+ e->p2m.xn = 1;
+ break;
+ }
+}
+
static lpae_t mfn_to_p2m_entry(unsigned long mfn, unsigned int mattr,
p2m_type_t t)
{
paddr_t pa = ((paddr_t) mfn) << PAGE_SHIFT;
- /* xn and write bit will be defined in the switch */
+ /* sh, xn and write bit will be defined in the following switches
+ * based on mattr and t. */
lpae_t e = (lpae_t) {
.p2m.af = 1,
- .p2m.sh = LPAE_SH_OUTER,
.p2m.read = 1,
.p2m.mattr = mattr,
.p2m.table = 1,
@@ -186,36 +321,23 @@ static lpae_t mfn_to_p2m_entry(unsigned long mfn, unsigned int mattr,
BUILD_BUG_ON(p2m_max_real_type > (1 << 4));
- switch (t)
+ switch (mattr)
{
- case p2m_ram_rw:
- e.p2m.xn = 0;
- e.p2m.write = 1;
- break;
-
- case p2m_ram_ro:
- e.p2m.xn = 0;
- e.p2m.write = 0;
- break;
-
- case p2m_map_foreign:
- case p2m_grant_map_rw:
- case p2m_mmio_direct:
- e.p2m.xn = 1;
- e.p2m.write = 1;
+ case MATTR_MEM:
+ e.p2m.sh = LPAE_SH_INNER;
break;
- case p2m_grant_map_ro:
- case p2m_invalid:
- e.p2m.xn = 1;
- e.p2m.write = 0;
+ case MATTR_DEV:
+ e.p2m.sh = LPAE_SH_OUTER;
break;
-
- case p2m_max_real_type:
+ default:
BUG();
break;
}
+ /* We pass p2m_access_rwx as a placeholder for now. */
+ p2m_set_permission(&e, t, p2m_access_rwx);
+
ASSERT(!(pa & ~PAGE_MASK));
ASSERT(!(pa & ~PADDR_MASK));
@@ -224,16 +346,33 @@ static lpae_t mfn_to_p2m_entry(unsigned long mfn, unsigned int mattr,
return e;
}
-/* Allocate a new page table page and hook it in via the given entry */
-static int p2m_create_table(struct domain *d,
- lpae_t *entry)
+static inline void p2m_write_pte(lpae_t *p, lpae_t pte, bool_t flush_cache)
+{
+ write_pte(p, pte);
+ if ( flush_cache )
+ clean_dcache(*p);
+}
+
+/*
+ * Allocate a new page table page and hook it in via the given entry.
+ * apply_one_level relies on this returning 0 on success
+ * and -ve on failure.
+ *
+ * If the existing entry is present then it must be a mapping and not
+ * a table and it will be shattered into the next level down.
+ *
+ * level_shift is the number of bits at the level we want to create.
+ */
+static int p2m_create_table(struct domain *d, lpae_t *entry,
+ int level_shift, bool_t flush_cache)
{
struct p2m_domain *p2m = &d->arch.p2m;
struct page_info *page;
- void *p;
+ lpae_t *p;
lpae_t pte;
+ int splitting = p2m_valid(*entry);
- BUG_ON(entry->p2m.valid);
+ BUG_ON(p2m_table(*entry));
page = alloc_domheap_page(NULL, 0);
if ( page == NULL )
@@ -242,12 +381,42 @@ static int p2m_create_table(struct domain *d,
page_list_add(page, &p2m->pages);
p = __map_domain_page(page);
- clear_page(p);
+ if ( splitting )
+ {
+ p2m_type_t t = entry->p2m.type;
+ unsigned long base_pfn = entry->p2m.base;
+ int i;
+
+ /*
+ * We are either splitting a first level 1G page into 512 second level
+ * 2M pages, or a second level 2M page into 512 third level 4K pages.
+ */
+ for ( i=0 ; i < LPAE_ENTRIES; i++ )
+ {
+ pte = mfn_to_p2m_entry(base_pfn + (i<<(level_shift-LPAE_SHIFT)),
+ MATTR_MEM, t);
+
+ /*
+ * First and second level super pages set p2m.table = 0, but
+ * third level entries set table = 1.
+ */
+ if ( level_shift - LPAE_SHIFT )
+ pte.p2m.table = 0;
+
+ write_pte(&p[i], pte);
+ }
+ }
+ else
+ clear_page(p);
+
+ if ( flush_cache )
+ clean_dcache_va_range(p, PAGE_SIZE);
+
unmap_domain_page(p);
pte = mfn_to_p2m_entry(page_to_mfn(page), MATTR_MEM, p2m_invalid);
- write_pte(entry, pte);
+ p2m_write_pte(entry, pte, flush_cache);
return 0;
}
@@ -260,192 +429,472 @@ enum p2m_operation {
CACHEFLUSH,
};
-static int apply_p2m_changes(struct domain *d,
- enum p2m_operation op,
- paddr_t start_gpaddr,
- paddr_t end_gpaddr,
- paddr_t maddr,
- int mattr,
- p2m_type_t t)
+/* Put any references on the single 4K page referenced by pte. TODO:
+ * Handle superpages, for now we only take special references for leaf
+ * pages (specifically foreign ones, which can't be super mapped today).
+ */
+static void p2m_put_l3_page(const lpae_t pte)
{
- int rc;
+ ASSERT(p2m_valid(pte));
+
+ /* TODO: Handle other p2m types
+ *
+ * It's safe to do the put_page here because page_alloc will
+ * flush the TLBs if the page is reallocated before the end of
+ * this loop.
+ */
+ if ( p2m_is_foreign(pte.p2m.type) )
+ {
+ unsigned long mfn = pte.p2m.base;
+
+ ASSERT(mfn_valid(mfn));
+ put_page(mfn_to_page(mfn));
+ }
+}
+
+/*
+ * Returns true if start_gpaddr..end_gpaddr contains at least one
+ * suitably aligned level_size mappping of maddr.
+ *
+ * So long as the range is large enough the end_gpaddr need not be
+ * aligned (callers should create one superpage mapping based on this
+ * result and then call this again on the new range, eventually the
+ * slop at the end will cause this function to return false).
+ */
+static bool_t is_mapping_aligned(const paddr_t start_gpaddr,
+ const paddr_t end_gpaddr,
+ const paddr_t maddr,
+ const paddr_t level_size)
+{
+ const paddr_t level_mask = level_size - 1;
+
+ /* No hardware superpages at level 0 */
+ if ( level_size == ZEROETH_SIZE )
+ return false;
+
+ /*
+ * A range smaller than the size of a superpage at this level
+ * cannot be superpage aligned.
+ */
+ if ( ( end_gpaddr - start_gpaddr ) < level_size - 1 )
+ return false;
+
+ /* Both the gpaddr and maddr must be aligned */
+ if ( start_gpaddr & level_mask )
+ return false;
+ if ( maddr & level_mask )
+ return false;
+ return true;
+}
+
+#define P2M_ONE_DESCEND 0
+#define P2M_ONE_PROGRESS_NOP 0x1
+#define P2M_ONE_PROGRESS 0x10
+
+/* Helpers to lookup the properties of each level */
+static const paddr_t level_sizes[] =
+ { ZEROETH_SIZE, FIRST_SIZE, SECOND_SIZE, THIRD_SIZE };
+static const paddr_t level_masks[] =
+ { ZEROETH_MASK, FIRST_MASK, SECOND_MASK, THIRD_MASK };
+static const paddr_t level_shifts[] =
+ { ZEROETH_SHIFT, FIRST_SHIFT, SECOND_SHIFT, THIRD_SHIFT };
+
+static int p2m_shatter_page(struct domain *d,
+ lpae_t *entry,
+ unsigned int level,
+ bool_t flush_cache)
+{
+ const paddr_t level_shift = level_shifts[level];
+ int rc = p2m_create_table(d, entry,
+ level_shift - PAGE_SHIFT, flush_cache);
+
+ if ( !rc )
+ {
+ struct p2m_domain *p2m = &d->arch.p2m;
+ p2m->stats.shattered[level]++;
+ p2m->stats.mappings[level]--;
+ p2m->stats.mappings[level+1] += LPAE_ENTRIES;
+ }
+
+ return rc;
+}
+
+/*
+ * 0 == (P2M_ONE_DESCEND) continue to descend the tree
+ * +ve == (P2M_ONE_PROGRESS_*) handled at this level, continue, flush,
+ * entry, addr and maddr updated. Return value is an
+ * indication of the amount of work done (for preemption).
+ * -ve == (-Exxx) error.
+ */
+static int apply_one_level(struct domain *d,
+ lpae_t *entry,
+ unsigned int level,
+ bool_t flush_cache,
+ enum p2m_operation op,
+ paddr_t start_gpaddr,
+ paddr_t end_gpaddr,
+ paddr_t *addr,
+ paddr_t *maddr,
+ bool_t *flush,
+ int mattr,
+ p2m_type_t t)
+{
+ const paddr_t level_size = level_sizes[level];
+ const paddr_t level_mask = level_masks[level];
+ const paddr_t level_shift = level_shifts[level];
+
struct p2m_domain *p2m = &d->arch.p2m;
- lpae_t *first = NULL, *second = NULL, *third = NULL;
- paddr_t addr;
- unsigned long cur_first_page = ~0,
- cur_first_offset = ~0,
- cur_second_offset = ~0;
- unsigned long count = 0;
- unsigned int flush = 0;
- bool_t populate = (op == INSERT || op == ALLOCATE);
lpae_t pte;
+ const lpae_t orig_pte = *entry;
+ int rc;
- spin_lock(&p2m->lock);
+ BUG_ON(level > 3);
- if ( d != current->domain )
- p2m_load_VTTBR(d);
-
- addr = start_gpaddr;
- while ( addr < end_gpaddr )
+ switch ( op )
{
- if ( cur_first_page != p2m_first_level_index(addr) )
+ case ALLOCATE:
+ ASSERT(level < 3 || !p2m_valid(orig_pte));
+ ASSERT(*maddr == 0);
+
+ if ( p2m_valid(orig_pte) )
+ return P2M_ONE_DESCEND;
+
+ if ( is_mapping_aligned(*addr, end_gpaddr, 0, level_size) )
{
- if ( first ) unmap_domain_page(first);
- first = p2m_map_first(p2m, addr);
- if ( !first )
+ struct page_info *page;
+
+ page = alloc_domheap_pages(d, level_shift - PAGE_SHIFT, 0);
+ if ( page )
{
- rc = -EINVAL;
- goto out;
+ pte = mfn_to_p2m_entry(page_to_mfn(page), mattr, t);
+ if ( level < 3 )
+ pte.p2m.table = 0;
+ p2m_write_pte(entry, pte, flush_cache);
+ p2m->stats.mappings[level]++;
+
+ *addr += level_size;
+
+ return P2M_ONE_PROGRESS;
}
- cur_first_page = p2m_first_level_index(addr);
+ else if ( level == 3 )
+ return -ENOMEM;
}
- if ( !first[first_table_offset(addr)].p2m.valid )
+ /* L3 is always suitably aligned for mapping (handled, above) */
+ BUG_ON(level == 3);
+
+ /*
+ * If we get here then we failed to allocate a sufficiently
+ * large contiguous region for this level (which can't be
+ * L3). Create a page table and continue to descend so we try
+ * smaller allocations.
+ */
+ rc = p2m_create_table(d, entry, 0, flush_cache);
+ if ( rc < 0 )
+ return rc;
+
+ return P2M_ONE_DESCEND;
+
+ case INSERT:
+ if ( is_mapping_aligned(*addr, end_gpaddr, *maddr, level_size) &&
+ /* We do not handle replacing an existing table with a superpage */
+ (level == 3 || !p2m_table(orig_pte)) )
{
- if ( !populate )
+ /* New mapping is superpage aligned, make it */
+ pte = mfn_to_p2m_entry(*maddr >> PAGE_SHIFT, mattr, t);
+ if ( level < 3 )
+ pte.p2m.table = 0; /* Superpage entry */
+
+ p2m_write_pte(entry, pte, flush_cache);
+
+ *flush |= p2m_valid(orig_pte);
+
+ *addr += level_size;
+ *maddr += level_size;
+
+ if ( p2m_valid(orig_pte) )
{
- addr = (addr + FIRST_SIZE) & FIRST_MASK;
- continue;
+ /*
+ * We can't currently get here for an existing table
+ * mapping, since we don't handle replacing an
+ * existing table with a superpage. If we did we would
+ * need to handle freeing (and accounting) for the bit
+ * of the p2m tree which we would be about to lop off.
+ */
+ BUG_ON(level < 3 && p2m_table(orig_pte));
+ if ( level == 3 )
+ p2m_put_l3_page(orig_pte);
}
+ else /* New mapping */
+ p2m->stats.mappings[level]++;
+
+ return P2M_ONE_PROGRESS;
+ }
+ else
+ {
+ /* New mapping is not superpage aligned, create a new table entry */
- rc = p2m_create_table(d, &first[first_table_offset(addr)]);
- if ( rc < 0 )
+ /* L3 is always suitably aligned for mapping (handled, above) */
+ BUG_ON(level == 3);
+
+ /* Not present -> create table entry and descend */
+ if ( !p2m_valid(orig_pte) )
{
- printk("p2m_populate_ram: L1 failed\n");
- goto out;
+ rc = p2m_create_table(d, entry, 0, flush_cache);
+ if ( rc < 0 )
+ return rc;
+ return P2M_ONE_DESCEND;
}
+
+ /* Existing superpage mapping -> shatter and descend */
+ if ( p2m_mapping(orig_pte) )
+ {
+ *flush = true;
+ rc = p2m_shatter_page(d, entry, level, flush_cache);
+ if ( rc < 0 )
+ return rc;
+ } /* else: an existing table mapping -> descend */
+
+ BUG_ON(!p2m_table(*entry));
+
+ return P2M_ONE_DESCEND;
}
- BUG_ON(!first[first_table_offset(addr)].p2m.valid);
+ break;
- if ( cur_first_offset != first_table_offset(addr) )
+ case RELINQUISH:
+ case REMOVE:
+ if ( !p2m_valid(orig_pte) )
{
- if (second) unmap_domain_page(second);
- second = map_domain_page(first[first_table_offset(addr)].p2m.base);
- cur_first_offset = first_table_offset(addr);
+ /* Progress up to next boundary */
+ *addr = (*addr + level_size) & level_mask;
+ *maddr = (*maddr + level_size) & level_mask;
+ return P2M_ONE_PROGRESS_NOP;
}
- /* else: second already valid */
- if ( !second[second_table_offset(addr)].p2m.valid )
+ if ( level < 3 )
{
- if ( !populate )
- {
- addr = (addr + SECOND_SIZE) & SECOND_MASK;
- continue;
- }
+ if ( p2m_table(orig_pte) )
+ return P2M_ONE_DESCEND;
- rc = p2m_create_table(d, &second[second_table_offset(addr)]);
- if ( rc < 0 ) {
- printk("p2m_populate_ram: L2 failed\n");
- goto out;
+ if ( op == REMOVE &&
+ !is_mapping_aligned(*addr, end_gpaddr,
+ 0, /* maddr doesn't matter for remove */
+ level_size) )
+ {
+ /*
+ * Removing a mapping from the middle of a superpage. Shatter
+ * and descend.
+ */
+ *flush = true;
+ rc = p2m_shatter_page(d, entry, level, flush_cache);
+ if ( rc < 0 )
+ return rc;
+
+ return P2M_ONE_DESCEND;
}
}
- BUG_ON(!second[second_table_offset(addr)].p2m.valid);
+ /*
+ * Ensure that the guest address addr currently being
+ * handled (that is in the range given as argument to
+ * this function) is actually mapped to the corresponding
+ * machine address in the specified range. maddr here is
+ * the machine address given to the function, while
+ * orig_pte.p2m.base is the machine frame number actually
+ * mapped to the guest address: check if the two correspond.
+ */
+ if ( op == REMOVE &&
+ pfn_to_paddr(orig_pte.p2m.base) != *maddr )
+ printk(XENLOG_G_WARNING
+ "p2m_remove dom%d: mapping at %"PRIpaddr" is of maddr %"PRIpaddr" not %"PRIpaddr" as expected\n",
+ d->domain_id, *addr, pfn_to_paddr(orig_pte.p2m.base),
+ *maddr);
+
+ *flush = true;
+
+ memset(&pte, 0x00, sizeof(pte));
+ p2m_write_pte(entry, pte, flush_cache);
+
+ *addr += level_size;
+ *maddr += level_size;
+
+ p2m->stats.mappings[level]--;
+
+ if ( level == 3 )
+ p2m_put_l3_page(orig_pte);
+
+ /*
+ * This is still a single pte write, no matter the level, so no need to
+ * scale.
+ */
+ return P2M_ONE_PROGRESS;
- if ( cur_second_offset != second_table_offset(addr) )
+ case CACHEFLUSH:
+ if ( !p2m_valid(orig_pte) )
{
- /* map third level */
- if (third) unmap_domain_page(third);
- third = map_domain_page(second[second_table_offset(addr)].p2m.base);
- cur_second_offset = second_table_offset(addr);
+ *addr = (*addr + level_size) & level_mask;
+ return P2M_ONE_PROGRESS_NOP;
}
- pte = third[third_table_offset(addr)];
-
- flush |= pte.p2m.valid;
+ if ( level < 3 && p2m_table(orig_pte) )
+ return P2M_ONE_DESCEND;
- /* TODO: Handle other p2m type
- *
- * It's safe to do the put_page here because page_alloc will
- * flush the TLBs if the page is reallocated before the end of
- * this loop.
+ /*
+ * could flush up to the next superpage boundary, but would
+ * need to be careful about preemption, so just do one 4K page
+ * now and return P2M_ONE_PROGRESS{,_NOP} so that the caller will
+ * continue to loop over the rest of the range.
*/
- if ( pte.p2m.valid && p2m_is_foreign(pte.p2m.type) )
+ if ( p2m_is_ram(orig_pte.p2m.type) )
{
- unsigned long mfn = pte.p2m.base;
+ unsigned long offset = paddr_to_pfn(*addr & ~level_mask);
+ flush_page_to_ram(orig_pte.p2m.base + offset);
- ASSERT(mfn_valid(mfn));
- put_page(mfn_to_page(mfn));
+ *addr += PAGE_SIZE;
+ return P2M_ONE_PROGRESS;
}
-
- /* Allocate a new RAM page and attach */
- switch (op) {
- case ALLOCATE:
- {
- struct page_info *page;
-
- ASSERT(!pte.p2m.valid);
- rc = -ENOMEM;
- page = alloc_domheap_page(d, 0);
- if ( page == NULL ) {
- printk("p2m_populate_ram: failed to allocate page\n");
- goto out;
- }
-
- pte = mfn_to_p2m_entry(page_to_mfn(page), mattr, t);
-
- write_pte(&third[third_table_offset(addr)], pte);
- }
- break;
- case INSERT:
- {
- pte = mfn_to_p2m_entry(maddr >> PAGE_SHIFT, mattr, t);
- write_pte(&third[third_table_offset(addr)], pte);
- maddr += PAGE_SIZE;
- }
- break;
- case RELINQUISH:
- case REMOVE:
- {
- if ( !pte.p2m.valid )
- {
- count++;
- break;
- }
-
- count += 0x10;
-
- memset(&pte, 0x00, sizeof(pte));
- write_pte(&third[third_table_offset(addr)], pte);
- count++;
- }
- break;
-
- case CACHEFLUSH:
- {
- if ( !pte.p2m.valid || !p2m_is_ram(pte.p2m.type) )
- break;
-
- flush_page_to_ram(pte.p2m.base);
- }
- break;
+ else
+ {
+ *addr += PAGE_SIZE;
+ return P2M_ONE_PROGRESS_NOP;
}
+ }
+
+ BUG(); /* Should never get here */
+}
+
+static int apply_p2m_changes(struct domain *d,
+ enum p2m_operation op,
+ paddr_t start_gpaddr,
+ paddr_t end_gpaddr,
+ paddr_t maddr,
+ int mattr,
+ p2m_type_t t)
+{
+ int rc, ret;
+ struct p2m_domain *p2m = &d->arch.p2m;
+ lpae_t *mappings[4] = { NULL, NULL, NULL, NULL };
+ paddr_t addr, orig_maddr = maddr;
+ unsigned int level = 0;
+ unsigned int cur_root_table = ~0;
+ unsigned int cur_offset[4] = { ~0, ~0, ~0, ~0 };
+ unsigned int count = 0;
+ bool_t flush = false;
+ bool_t flush_pt;
+
+ /* Some IOMMU don't support coherent PT walk. When the p2m is
+ * shared with the CPU, Xen has to make sure that the PT changes have
+ * reached the memory
+ */
+ flush_pt = iommu_enabled && !iommu_has_feature(d, IOMMU_FEAT_COHERENT_WALK);
+
+ spin_lock(&p2m->lock);
+
+ /* Static mapping. P2M_ROOT_PAGES > 1 are handled below */
+ if ( P2M_ROOT_PAGES == 1 )
+ mappings[P2M_ROOT_LEVEL] = __map_domain_page(p2m->root);
+
+ addr = start_gpaddr;
+ while ( addr < end_gpaddr )
+ {
+ int root_table;
+ const unsigned int offsets[4] = {
+ zeroeth_table_offset(addr),
+ first_table_offset(addr),
+ second_table_offset(addr),
+ third_table_offset(addr)
+ };
+
+ /*
+ * Arbitrarily, preempt every 512 operations or 8192 nops.
+ * 512*P2M_ONE_PROGRESS == 8192*P2M_ONE_PROGRESS_NOP == 0x2000
+ *
+ * count is initialised to 0 above, so we are guaranteed to
+ * always make at least one pass.
+ */
- /* Preempt every 2MiB (mapped) or 32 MiB (unmapped) - arbitrary */
if ( op == RELINQUISH && count >= 0x2000 )
{
if ( hypercall_preempt_check() )
{
p2m->lowest_mapped_gfn = addr >> PAGE_SHIFT;
- rc = -EAGAIN;
+ rc = -ERESTART;
goto out;
}
count = 0;
}
- /* Got the next page */
- addr += PAGE_SIZE;
+ if ( P2M_ROOT_PAGES > 1 )
+ {
+ int i;
+ /*
+ * Concatenated root-level tables. The table number will be the
+ * offset at the previous level. It is not possible to concatenate
+ * a level-0 root.
+ */
+ ASSERT(P2M_ROOT_LEVEL > 0);
+ root_table = offsets[P2M_ROOT_LEVEL - 1];
+ if ( root_table >= P2M_ROOT_PAGES )
+ {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if ( cur_root_table != root_table )
+ {
+ if ( mappings[P2M_ROOT_LEVEL] )
+ unmap_domain_page(mappings[P2M_ROOT_LEVEL]);
+ mappings[P2M_ROOT_LEVEL] =
+ __map_domain_page(p2m->root + root_table);
+ cur_root_table = root_table;
+ /* Any mapping further down is now invalid */
+ for ( i = P2M_ROOT_LEVEL; i < 4; i++ )
+ cur_offset[i] = ~0;
+ }
+ }
+
+ for ( level = P2M_ROOT_LEVEL; level < 4; level++ )
+ {
+ unsigned offset = offsets[level];
+ lpae_t *entry = &mappings[level][offset];
+
+ ret = apply_one_level(d, entry,
+ level, flush_pt, op,
+ start_gpaddr, end_gpaddr,
+ &addr, &maddr, &flush,
+ mattr, t);
+ if ( ret < 0 ) { rc = ret ; goto out; }
+ count += ret;
+ /* L3 had better have done something! We cannot descend any further */
+ BUG_ON(level == 3 && ret == P2M_ONE_DESCEND);
+ if ( ret != P2M_ONE_DESCEND ) break;
+
+ BUG_ON(!p2m_valid(*entry));
+
+ if ( cur_offset[level] != offset )
+ {
+ /* Update mapping for next level */
+ int i;
+ if ( mappings[level+1] )
+ unmap_domain_page(mappings[level+1]);
+ mappings[level+1] = map_domain_page(entry->p2m.base);
+ cur_offset[level] = offset;
+ /* Any mapping further down is now invalid */
+ for ( i = level+1; i < 4; i++ )
+ cur_offset[i] = ~0;
+ }
+ /* else: next level already valid */
+ }
}
if ( flush )
{
- /* At the beginning of the function, Xen is updating VTTBR
- * with the domain where the mappings are created. In this
- * case it's only necessary to flush TLBs on every CPUs with
- * the current VMID (our domain).
- */
- flush_tlb();
+ unsigned long sgfn = paddr_to_pfn(start_gpaddr);
+ unsigned long egfn = paddr_to_pfn(end_gpaddr);
+
+ flush_tlb_domain(d);
+ iommu_iotlb_flush(d, sgfn, egfn - sgfn);
}
if ( op == ALLOCATE || op == INSERT )
@@ -453,19 +902,33 @@ static int apply_p2m_changes(struct domain *d,
unsigned long sgfn = paddr_to_pfn(start_gpaddr);
unsigned long egfn = paddr_to_pfn(end_gpaddr);
- p2m->max_mapped_gfn = MAX(p2m->max_mapped_gfn, egfn);
- p2m->lowest_mapped_gfn = MIN(p2m->lowest_mapped_gfn, sgfn);
+ p2m->max_mapped_gfn = max(p2m->max_mapped_gfn, egfn);
+ p2m->lowest_mapped_gfn = min(p2m->lowest_mapped_gfn, sgfn);
}
rc = 0;
out:
- if (third) unmap_domain_page(third);
- if (second) unmap_domain_page(second);
- if (first) unmap_domain_page(first);
+ if ( rc < 0 && ( op == INSERT || op == ALLOCATE ) &&
+ addr != start_gpaddr )
+ {
+ BUG_ON(addr == end_gpaddr);
+ /*
+ * addr keeps the address of the last successfully-inserted mapping,
+ * while apply_p2m_changes() considers an address range which is
+ * exclusive of end_gpaddr: add level_size to addr to obtain the
+ * right end of the range
+ */
+ apply_p2m_changes(d, REMOVE,
+ start_gpaddr, addr + level_sizes[level], orig_maddr,
+ mattr, p2m_invalid);
+ }
- if ( d != current->domain )
- p2m_load_VTTBR(current->domain);
+ for ( level = P2M_ROOT_LEVEL; level < 4; level ++ )
+ {
+ if ( mappings[level] )
+ unmap_domain_page(mappings[level]);
+ }
spin_unlock(&p2m->lock);
@@ -481,12 +944,27 @@ int p2m_populate_ram(struct domain *d,
}
int map_mmio_regions(struct domain *d,
- paddr_t start_gaddr,
- paddr_t end_gaddr,
- paddr_t maddr)
+ unsigned long start_gfn,
+ unsigned long nr,
+ unsigned long mfn)
+{
+ return apply_p2m_changes(d, INSERT,
+ pfn_to_paddr(start_gfn),
+ pfn_to_paddr(start_gfn + nr),
+ pfn_to_paddr(mfn),
+ MATTR_DEV, p2m_mmio_direct);
+}
+
+int unmap_mmio_regions(struct domain *d,
+ unsigned long start_gfn,
+ unsigned long nr,
+ unsigned long mfn)
{
- return apply_p2m_changes(d, INSERT, start_gaddr, end_gaddr,
- maddr, MATTR_DEV, p2m_mmio_direct);
+ return apply_p2m_changes(d, REMOVE,
+ pfn_to_paddr(start_gfn),
+ pfn_to_paddr(start_gfn + nr),
+ pfn_to_paddr(mfn),
+ MATTR_DEV, p2m_invalid);
}
int guest_physmap_add_entry(struct domain *d,
@@ -515,36 +993,27 @@ int p2m_alloc_table(struct domain *d)
{
struct p2m_domain *p2m = &d->arch.p2m;
struct page_info *page;
- void *p;
+ unsigned int i;
- page = alloc_domheap_pages(NULL, P2M_FIRST_ORDER, 0);
+ page = alloc_domheap_pages(NULL, P2M_ROOT_ORDER, 0);
if ( page == NULL )
return -ENOMEM;
spin_lock(&p2m->lock);
/* Clear both first level pages */
- p = __map_domain_page(page);
- clear_page(p);
- unmap_domain_page(p);
+ for ( i = 0; i < P2M_ROOT_PAGES; i++ )
+ clear_and_clean_page(page + i);
- p = __map_domain_page(page + 1);
- clear_page(p);
- unmap_domain_page(p);
-
- p2m->first_level = page;
+ p2m->root = page;
- d->arch.vttbr = page_to_maddr(p2m->first_level)
+ d->arch.vttbr = page_to_maddr(p2m->root)
| ((uint64_t)p2m->vmid&0xff)<<48;
- p2m_load_VTTBR(d);
-
/* Make sure that all TLBs corresponding to the new VMID are flushed
* before using it
*/
- flush_tlb();
-
- p2m_load_VTTBR(current->domain);
+ flush_tlb_domain(d);
spin_unlock(&p2m->lock);
@@ -615,9 +1084,9 @@ void p2m_teardown(struct domain *d)
while ( (pg = page_list_remove_head(&p2m->pages)) )
free_domheap_page(pg);
- free_domheap_pages(p2m->first_level, P2M_FIRST_ORDER);
+ free_domheap_pages(p2m->root, P2M_ROOT_ORDER);
- p2m->first_level = NULL;
+ p2m->root = NULL;
p2m_free_vmid(d);
@@ -641,7 +1110,7 @@ int p2m_init(struct domain *d)
d->arch.vttbr = 0;
- p2m->first_level = NULL;
+ p2m->root = NULL;
p2m->max_mapped_gfn = 0;
p2m->lowest_mapped_gfn = ULONG_MAX;
@@ -688,13 +1157,29 @@ struct page_info *get_page_from_gva(struct domain *d, vaddr_t va,
{
struct p2m_domain *p2m = &d->arch.p2m;
struct page_info *page = NULL;
- paddr_t maddr;
-
- ASSERT(d == current->domain);
+ paddr_t maddr = 0;
+ int rc;
spin_lock(&p2m->lock);
- if ( gvirt_to_maddr(va, &maddr, flags) )
+ if ( unlikely(d != current->domain) )
+ {
+ unsigned long irq_flags;
+
+ local_irq_save(irq_flags);
+ p2m_load_VTTBR(d);
+
+ rc = gvirt_to_maddr(va, &maddr, flags);
+
+ p2m_load_VTTBR(current->domain);
+ local_irq_restore(irq_flags);
+ }
+ else
+ {
+ rc = gvirt_to_maddr(va, &maddr, flags);
+ }
+
+ if ( rc )
goto err;
if ( !mfn_valid(maddr >> PAGE_SHIFT) )
@@ -711,6 +1196,75 @@ err:
return page;
}
+static void __init setup_virt_paging_one(void *data)
+{
+ unsigned long val = (unsigned long)data;
+ WRITE_SYSREG32(val, VTCR_EL2);
+ isb();
+}
+
+void __init setup_virt_paging(void)
+{
+ /* Setup Stage 2 address translation */
+ unsigned long val = VTCR_RES1|VTCR_SH0_IS|VTCR_ORGN0_WBWA|VTCR_IRGN0_WBWA;
+
+#ifdef CONFIG_ARM_32
+ printk("P2M: 40-bit IPA\n");
+ val |= VTCR_T0SZ(0x18); /* 40 bit IPA */
+ val |= VTCR_SL0(0x1); /* P2M starts at first level */
+#else /* CONFIG_ARM_64 */
+ const struct {
+ unsigned int pabits; /* Physical Address Size */
+ unsigned int t0sz; /* Desired T0SZ, minimum in comment */
+ unsigned int root_order; /* Page order of the root of the p2m */
+ unsigned int sl0; /* Desired SL0, maximum in comment */
+ } pa_range_info[] = {
+ /* T0SZ minimum and SL0 maximum from ARM DDI 0487A.b Table D4-5 */
+ /* PA size, t0sz(min), root-order, sl0(max) */
+ [0] = { 32, 32/*32*/, 0, 1 },
+ [1] = { 36, 28/*28*/, 0, 1 },
+ [2] = { 40, 24/*24*/, 1, 1 },
+ [3] = { 42, 24/*22*/, 1, 1 },
+ [4] = { 44, 20/*20*/, 0, 2 },
+ [5] = { 48, 16/*16*/, 0, 2 },
+ [6] = { 0 }, /* Invalid */
+ [7] = { 0 } /* Invalid */
+ };
+
+ unsigned int cpu;
+ unsigned int pa_range = 0x10; /* Larger than any possible value */
+
+ for_each_online_cpu ( cpu )
+ {
+ const struct cpuinfo_arm *info = &cpu_data[cpu];
+ if ( info->mm64.pa_range < pa_range )
+ pa_range = info->mm64.pa_range;
+ }
+
+ /* pa_range is 4 bits, but the defined encodings are only 3 bits */
+ if ( pa_range&0x8 || !pa_range_info[pa_range].pabits )
+ panic("Unknown encoding of ID_AA64MMFR0_EL1.PARange %x\n", pa_range);
+
+ val |= VTCR_PS(pa_range);
+ val |= VTCR_TG0_4K;
+ val |= VTCR_SL0(pa_range_info[pa_range].sl0);
+ val |= VTCR_T0SZ(pa_range_info[pa_range].t0sz);
+
+ p2m_root_order = pa_range_info[pa_range].root_order;
+ p2m_root_level = 2 - pa_range_info[pa_range].sl0;
+
+ printk("P2M: %d-bit IPA with %d-bit PA\n",
+ 64 - pa_range_info[pa_range].t0sz,
+ pa_range_info[pa_range].pabits);
+#endif
+ printk("P2M: %d levels with order-%d root, VTCR 0x%lx\n",
+ 4 - P2M_ROOT_LEVEL, P2M_ROOT_ORDER, val);
+ /* It is not allowed to concatenate a level zero root */
+ BUG_ON( P2M_ROOT_LEVEL == 0 && P2M_ROOT_ORDER > 0 );
+ setup_virt_paging_one((void *)val);
+ smp_call_function(setup_virt_paging_one, (void *)val, 1);
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/arm/platform.c b/xen/arch/arm/platform.c
index 74c3328..cb4cda8 100644
--- a/xen/arch/arm/platform.c
+++ b/xen/arch/arm/platform.c
@@ -110,7 +110,7 @@ int __init platform_specific_mapping(struct domain *d)
#ifdef CONFIG_ARM_32
int __init platform_cpu_up(int cpu)
{
- if ( psci_available )
+ if ( psci_ver )
return call_psci_cpu_on(cpu);
if ( platform && platform->cpu_up )
diff --git a/xen/arch/arm/platforms/Makefile b/xen/arch/arm/platforms/Makefile
index 680364f..8f47c16 100644
--- a/xen/arch/arm/platforms/Makefile
+++ b/xen/arch/arm/platforms/Makefile
@@ -1,6 +1,8 @@
obj-y += vexpress.o
+obj-$(CONFIG_ARM_32) += brcm.o
obj-$(CONFIG_ARM_32) += exynos5.o
obj-$(CONFIG_ARM_32) += midway.o
obj-$(CONFIG_ARM_32) += omap5.o
obj-$(CONFIG_ARM_32) += sunxi.o
+obj-$(CONFIG_ARM_64) += seattle.o
obj-$(CONFIG_ARM_64) += xgene-storm.o
diff --git a/xen/arch/arm/platforms/brcm.c b/xen/arch/arm/platforms/brcm.c
new file mode 100644
index 0000000..a10de22
--- /dev/null
+++ b/xen/arch/arm/platforms/brcm.c
@@ -0,0 +1,294 @@
+/*
+ * xen/arch/arm/platforms/brcm.c
+ *
+ * Broadcom Platform startup.
+ *
+ * Jon Fraser <jfraser at broadcom.com>
+ * Copyright (c) 2013-2014 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/platform.h>
+#include <xen/mm.h>
+#include <xen/vmap.h>
+#include <asm/io.h>
+#include <xen/delay.h>
+
+struct brcm_plat_regs {
+ uint32_t hif_mask;
+ uint32_t hif_cpu_reset_config;
+ uint32_t hif_boot_continuation;
+ uint32_t cpu0_pwr_zone_ctrl;
+ uint32_t scratch_reg;
+};
+
+static u32 brcm_boot_continuation_pc;
+
+static struct brcm_plat_regs regs;
+
+static __init int brcm_get_dt_node(char *compat_str,
+ const struct dt_device_node **dn,
+ u32 *reg_base)
+{
+ const struct dt_device_node *node;
+ u64 reg_base_64;
+ int rc;
+
+ node = dt_find_compatible_node(NULL, NULL, compat_str);
+ if ( !node )
+ {
+ dprintk(XENLOG_ERR, "%s: missing \"%s\" node\n", __func__, compat_str);
+ return -ENOENT;
+ }
+
+ rc = dt_device_get_address(node, 0, ®_base_64, NULL);
+ if ( rc )
+ {
+ dprintk(XENLOG_ERR, "%s: missing \"reg\" prop\n", __func__);
+ return rc;
+ }
+
+ if ( dn )
+ *dn = node;
+
+ if ( reg_base )
+ *reg_base = reg_base_64;
+
+ return 0;
+}
+
+static __init int brcm_populate_plat_regs(void)
+{
+ int rc;
+ const struct dt_device_node *node;
+ u32 reg_base;
+ u32 val;
+
+ rc = brcm_get_dt_node("brcm,brcmstb-cpu-biu-ctrl", &node, ®_base);
+ if ( rc )
+ return rc;
+
+ if ( !dt_property_read_u32(node, "cpu-reset-config-reg", &val) )
+ {
+ dprintk(XENLOG_ERR, "Missing property \"cpu-reset-config-reg\"\n");
+ return -ENOENT;
+ }
+ regs.hif_cpu_reset_config = reg_base + val;
+
+ if ( !dt_property_read_u32(node, "cpu0-pwr-zone-ctrl-reg", &val) )
+ {
+ dprintk(XENLOG_ERR, "Missing property \"cpu0-pwr-zone-ctrl-reg\"\n");
+ return -ENOENT;
+ }
+ regs.cpu0_pwr_zone_ctrl = reg_base + val;
+
+ if ( !dt_property_read_u32(node, "scratch-reg", &val) )
+ {
+ dprintk(XENLOG_ERR, "Missing property \"scratch-reg\"\n");
+ return -ENOENT;
+ }
+ regs.scratch_reg = reg_base + val;
+
+ rc = brcm_get_dt_node("brcm,brcmstb-hif-continuation", NULL, ®_base);
+ if ( rc )
+ return rc;
+
+ regs.hif_boot_continuation = reg_base;
+
+ dprintk(XENLOG_INFO, "hif_cpu_reset_config : %08xh\n",
+ regs.hif_cpu_reset_config);
+ dprintk(XENLOG_INFO, "cpu0_pwr_zone_ctrl : %08xh\n",
+ regs.cpu0_pwr_zone_ctrl);
+ dprintk(XENLOG_INFO, "hif_boot_continuation : %08xh\n",
+ regs.hif_boot_continuation);
+ dprintk(XENLOG_INFO, "scratch_reg : %08xh\n",
+ regs.scratch_reg);
+
+ return 0;
+}
+
+#define ZONE_PWR_UP_REQ (1 << 10)
+#define ZONE_PWR_ON_STATE (1 << 26)
+
+static int brcm_cpu_power_on(int cpu)
+{
+ u32 tmp;
+ void __iomem *pwr_ctl;
+ unsigned int timeout;
+
+ dprintk(XENLOG_ERR, "%s: Power on cpu %d\n", __func__, cpu);
+
+ pwr_ctl = ioremap_nocache(regs.cpu0_pwr_zone_ctrl + (cpu * sizeof(u32)),
+ sizeof(u32));
+
+ if ( !pwr_ctl )
+ {
+ dprintk(XENLOG_ERR, "%s: Unable to map \"cpu0_pwr_zone_ctrl\"\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ /* request core power on */
+ tmp = readl(pwr_ctl);
+ tmp |= ZONE_PWR_UP_REQ;
+ writel(tmp, pwr_ctl);
+
+ /*
+ * Wait for the cpu to power on.
+ * Wait a max of 10 msec.
+ */
+ timeout = 10;
+ tmp = readl(pwr_ctl);
+
+ while ( !(tmp & ZONE_PWR_ON_STATE) )
+ {
+ if ( timeout-- == 0 )
+ break;
+
+ mdelay(1);
+ tmp = readl(pwr_ctl);
+ }
+
+ iounmap(pwr_ctl);
+
+ if ( timeout == 0 )
+ {
+ dprintk(XENLOG_ERR, "CPU%d power enable failed", cpu);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int brcm_cpu_release(u32 cpu)
+{
+ u32 tmp;
+ u32 __iomem *reg;
+
+ dprintk(XENLOG_INFO, "%s: Taking cpu %d out of reset \n", __func__, cpu);
+
+ reg = ioremap_nocache(regs.hif_cpu_reset_config, sizeof(u32));
+ if ( !reg )
+ {
+ dprintk(XENLOG_ERR, "%s: Unable to map \"hif_cpu_reset_config\"\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ /* now take the cpu out of reset */
+ tmp = readl(reg);
+ tmp &= ~(1 << cpu);
+ writel(tmp, reg);
+
+ iounmap(reg);
+
+ return 0;
+}
+
+static int brcm_set_boot_continuation(u32 cpu, u32 pc)
+{
+ u32 __iomem *reg;
+ dprintk(XENLOG_INFO, "%s: cpu %d pc 0x%x\n", __func__, cpu, pc);
+
+ reg = ioremap_nocache(regs.hif_boot_continuation + (cpu * 2 * sizeof(u32)),
+ 2 * sizeof(u32));
+ if ( !reg )
+ {
+ dprintk(XENLOG_ERR, "%s: Unable to map \"hif_boot_continuation\"\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ writel(0, reg);
+ writel(pc, reg + 1);
+
+ iounmap(reg);
+
+ return 0;
+}
+
+static int brcm_cpu_up(int cpu)
+{
+ int rc;
+
+ rc = brcm_cpu_power_on(cpu);
+ if ( rc )
+ return rc;
+
+ rc = brcm_set_boot_continuation(cpu, brcm_boot_continuation_pc);
+ if ( rc )
+ return rc;
+
+ return brcm_cpu_release(cpu);
+}
+
+static int __init brcm_smp_init(void)
+{
+ u32 __iomem *scratch;
+ u32 target_pc;
+
+ scratch = ioremap_nocache(regs.scratch_reg, sizeof(u32));
+
+ if ( !scratch )
+ {
+ dprintk(XENLOG_ERR, "%s: Unable to map \"scratch_reg\"\n", __func__);
+ return -EFAULT;
+ }
+ /*
+ * The HIF CPU BIU CTRL Scratch Register is used to pass
+ * addresses between this code in xen and the boot helper.
+ * The helper puts its own entry point in the scratch register.
+ * That address is written to the cpu boot continuation registers.
+ * The helper expects xen to put xen's entry point back in the register.
+ * The helper will jump to that address.
+ * The helper is in SRAM, which will always be a 32 bit address.
+ */
+
+ brcm_boot_continuation_pc = readl(scratch);
+
+ target_pc = __pa(init_secondary);
+ writel(target_pc, scratch);
+
+ iounmap(scratch);
+
+ dprintk(XENLOG_INFO, "%s: target_pc 0x%x boot continuation pc 0x%x\n",
+ __func__, target_pc, brcm_boot_continuation_pc);
+
+ return 0;
+}
+
+static __init int brcm_init(void)
+{
+ return brcm_populate_plat_regs();
+}
+
+static const char const *brcm_dt_compat[] __initconst =
+{
+ "brcm,bcm7445d0",
+ NULL
+};
+
+PLATFORM_START(brcm, "Broadcom B15")
+ .compatible = brcm_dt_compat,
+ .init = brcm_init,
+ .smp_init = brcm_smp_init,
+ .cpu_up = brcm_cpu_up,
+PLATFORM_END
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/platforms/exynos5.c b/xen/arch/arm/platforms/exynos5.c
index 65e584f..79e3a5f 100644
--- a/xen/arch/arm/platforms/exynos5.c
+++ b/xen/arch/arm/platforms/exynos5.c
@@ -23,18 +23,47 @@
#include <xen/domain_page.h>
#include <xen/mm.h>
#include <xen/vmap.h>
+#include <xen/delay.h>
#include <asm/platforms/exynos5.h>
#include <asm/platform.h>
#include <asm/io.h>
+static bool_t secure_firmware;
+
+#define EXYNOS_ARM_CORE0_CONFIG 0x2000
+#define EXYNOS_ARM_CORE_CONFIG(_nr) (EXYNOS_ARM_CORE0_CONFIG + (0x80 * (_nr)))
+#define EXYNOS_ARM_CORE_STATUS(_nr) (EXYNOS_ARM_CORE_CONFIG(_nr) + 0x4)
+#define S5P_CORE_LOCAL_PWR_EN 0x3
+
+#define SMC_CMD_CPU1BOOT (-4)
+
static int exynos5_init_time(void)
{
uint32_t reg;
void __iomem *mct;
+ int rc;
+ struct dt_device_node *node;
+ u64 mct_base_addr;
+ u64 size;
+
+ node = dt_find_compatible_node(NULL, NULL, "samsung,exynos4210-mct");
+ if ( !node )
+ {
+ dprintk(XENLOG_ERR, "samsung,exynos4210-mct missing in DT\n");
+ return -ENXIO;
+ }
- BUILD_BUG_ON(EXYNOS5_MCT_G_TCON >= PAGE_SIZE);
+ rc = dt_device_get_address(node, 0, &mct_base_addr, &size);
+ if ( rc )
+ {
+ dprintk(XENLOG_ERR, "Error in \"samsung,exynos4210-mct\"\n");
+ return -ENXIO;
+ }
+
+ dprintk(XENLOG_INFO, "mct_base_addr: %016llx size: %016llx\n",
+ mct_base_addr, size);
- mct = ioremap_attr(EXYNOS5_MCT_BASE, PAGE_SIZE, PAGE_HYPERVISOR_NOCACHE);
+ mct = ioremap_attr(mct_base_addr, size, PAGE_HYPERVISOR_NOCACHE);
if ( !mct )
{
dprintk(XENLOG_ERR, "Unable to map MCT\n");
@@ -51,25 +80,62 @@ static int exynos5_init_time(void)
}
/* Additional mappings for dom0 (Not in the DTS) */
-static int exynos5_specific_mapping(struct domain *d)
+static int exynos5250_specific_mapping(struct domain *d)
{
/* Map the chip ID */
- map_mmio_regions(d, EXYNOS5_PA_CHIPID, EXYNOS5_PA_CHIPID + PAGE_SIZE - 1,
- EXYNOS5_PA_CHIPID);
+ map_mmio_regions(d, paddr_to_pfn(EXYNOS5_PA_CHIPID), 1,
+ paddr_to_pfn(EXYNOS5_PA_CHIPID));
/* Map the PWM region */
- map_mmio_regions(d, EXYNOS5_PA_TIMER,
- EXYNOS5_PA_TIMER + (PAGE_SIZE * 2) - 1,
- EXYNOS5_PA_TIMER);
+ map_mmio_regions(d, paddr_to_pfn(EXYNOS5_PA_TIMER), 2,
+ paddr_to_pfn(EXYNOS5_PA_TIMER));
return 0;
}
static int __init exynos5_smp_init(void)
{
+ struct dt_device_node *node;
void __iomem *sysram;
+ char *compatible;
+ u64 sysram_addr;
+ u64 size;
+ u64 sysram_offset;
+ int rc;
- sysram = ioremap_nocache(S5P_PA_SYSRAM, PAGE_SIZE);
+ node = dt_find_compatible_node(NULL, NULL, "samsung,secure-firmware");
+ if ( node )
+ {
+ /* Have to use sysram_ns_base_addr + 0x1c for boot address */
+ compatible = "samsung,exynos4210-sysram-ns";
+ sysram_offset = 0x1c;
+ secure_firmware = 1;
+ printk("Running under secure firmware.\n");
+ }
+ else
+ {
+ /* Have to use sysram_base_addr + offset 0 for boot address */
+ compatible = "samsung,exynos4210-sysram";
+ sysram_offset = 0;
+ }
+
+ node = dt_find_compatible_node(NULL, NULL, compatible);
+ if ( !node )
+ {
+ dprintk(XENLOG_ERR, "%s missing in DT\n", compatible);
+ return -ENXIO;
+ }
+
+ rc = dt_device_get_address(node, 0, &sysram_addr, &size);
+ if ( rc )
+ {
+ dprintk(XENLOG_ERR, "Error in %s\n", compatible);
+ return -ENXIO;
+ }
+ dprintk(XENLOG_INFO, "sysram_addr: %016llx size: %016llx offset: %016llx\n",
+ sysram_addr, size, sysram_offset);
+
+ sysram = ioremap_nocache(sysram_addr, size);
if ( !sysram )
{
dprintk(XENLOG_ERR, "Unable to map exynos5 MMIO\n");
@@ -78,20 +144,129 @@ static int __init exynos5_smp_init(void)
printk("Set SYSRAM to %"PRIpaddr" (%p)\n",
__pa(init_secondary), init_secondary);
- writel(__pa(init_secondary), sysram);
+ writel(__pa(init_secondary), sysram + sysram_offset);
iounmap(sysram);
return 0;
}
+static int exynos_cpu_power_state(void __iomem *power, int cpu)
+{
+ return __raw_readl(power + EXYNOS_ARM_CORE_STATUS(cpu)) &
+ S5P_CORE_LOCAL_PWR_EN;
+}
+
+static void exynos_cpu_power_up(void __iomem *power, int cpu)
+{
+ __raw_writel(S5P_CORE_LOCAL_PWR_EN,
+ power + EXYNOS_ARM_CORE_CONFIG(cpu));
+}
+
+static int exynos5_cpu_power_up(void __iomem *power, int cpu)
+{
+ unsigned int timeout;
+
+ if ( !exynos_cpu_power_state(power, cpu) )
+ {
+ exynos_cpu_power_up(power, cpu);
+ timeout = 10;
+
+ /* wait max 10 ms until cpu is on */
+ while ( exynos_cpu_power_state(power, cpu) != S5P_CORE_LOCAL_PWR_EN )
+ {
+ if ( timeout-- == 0 )
+ break;
+
+ mdelay(1);
+ }
+
+ if ( timeout == 0 )
+ {
+ dprintk(XENLOG_ERR, "CPU%d power enable failed", cpu);
+ return -ETIMEDOUT;
+ }
+ }
+ return 0;
+}
+
+static int exynos5_get_pmu_baseandsize(u64 *power_base_addr, u64 *size)
+{
+ struct dt_device_node *node;
+ int rc;
+ static const struct dt_device_match exynos_dt_pmu_matches[] =
+ {
+ DT_MATCH_COMPATIBLE("samsung,exynos5250-pmu"),
+ DT_MATCH_COMPATIBLE("samsung,exynos5410-pmu"),
+ DT_MATCH_COMPATIBLE("samsung,exynos5420-pmu"),
+ { /*sentinel*/ },
+ };
+
+ node = dt_find_matching_node(NULL, exynos_dt_pmu_matches);
+ if ( !node )
+ {
+ dprintk(XENLOG_ERR, "samsung,exynos5XXX-pmu missing in DT\n");
+ return -ENXIO;
+ }
+
+ rc = dt_device_get_address(node, 0, power_base_addr, size);
+ if ( rc )
+ {
+ dprintk(XENLOG_ERR, "Error in \"samsung,exynos5XXX-pmu\"\n");
+ return -ENXIO;
+ }
+
+ dprintk(XENLOG_DEBUG, "power_base_addr: %016llx size: %016llx\n",
+ *power_base_addr, *size);
+
+ return 0;
+}
+
+static int exynos5_cpu_up(int cpu)
+{
+ u64 power_base_addr;
+ u64 size;
+ void __iomem *power;
+ int rc;
+
+ rc = exynos5_get_pmu_baseandsize(&power_base_addr, &size);
+ if ( rc )
+ return rc;
+
+ power = ioremap_nocache(power_base_addr, size);
+ if ( !power )
+ {
+ dprintk(XENLOG_ERR, "Unable to map power MMIO\n");
+ return -EFAULT;
+ }
+
+ rc = exynos5_cpu_power_up(power, cpu);
+ if ( rc )
+ {
+ iounmap(power);
+ return -ETIMEDOUT;
+ }
+
+ iounmap(power);
+
+ if ( secure_firmware )
+ call_smc(SMC_CMD_CPU1BOOT, cpu, 0, 0);
+
+ return cpu_up_send_sgi(cpu);
+}
+
static void exynos5_reset(void)
{
+ u64 power_base_addr;
+ u64 size;
void __iomem *pmu;
+ int rc;
- BUILD_BUG_ON(EXYNOS5_SWRESET >= PAGE_SIZE);
+ rc = exynos5_get_pmu_baseandsize(&power_base_addr, &size);
+ if ( rc )
+ return;
- pmu = ioremap_nocache(EXYNOS5_PA_PMU, PAGE_SIZE);
+ pmu = ioremap_nocache(power_base_addr, size);
if ( !pmu )
{
dprintk(XENLOG_ERR, "Unable to map PMU\n");
@@ -99,15 +274,10 @@ static void exynos5_reset(void)
}
writel(1, pmu + EXYNOS5_SWRESET);
+
iounmap(pmu);
}
-static const char * const exynos5_dt_compat[] __initconst =
-{
- "samsung,exynos5250",
- NULL
-};
-
static const struct dt_device_match exynos5_blacklist_dev[] __initconst =
{
/* Multi core Timer
@@ -115,15 +285,37 @@ static const struct dt_device_match exynos5_blacklist_dev[] __initconst =
* This is result to random freeze.
*/
DT_MATCH_COMPATIBLE("samsung,exynos4210-mct"),
+ DT_MATCH_COMPATIBLE("samsung,secure-firmware"),
{ /* sentinel */ },
};
+static const char * const exynos5250_dt_compat[] __initconst =
+{
+ "samsung,exynos5250",
+ NULL
+};
+
+static const char * const exynos5_dt_compat[] __initconst =
+{
+ "samsung,exynos5410",
+ NULL
+};
+
+PLATFORM_START(exynos5250, "SAMSUNG EXYNOS5250")
+ .compatible = exynos5250_dt_compat,
+ .init_time = exynos5_init_time,
+ .specific_mapping = exynos5250_specific_mapping,
+ .smp_init = exynos5_smp_init,
+ .cpu_up = cpu_up_send_sgi,
+ .reset = exynos5_reset,
+ .blacklist_dev = exynos5_blacklist_dev,
+PLATFORM_END
+
PLATFORM_START(exynos5, "SAMSUNG EXYNOS5")
.compatible = exynos5_dt_compat,
.init_time = exynos5_init_time,
- .specific_mapping = exynos5_specific_mapping,
.smp_init = exynos5_smp_init,
- .cpu_up = cpu_up_send_sgi,
+ .cpu_up = exynos5_cpu_up,
.reset = exynos5_reset,
.blacklist_dev = exynos5_blacklist_dev,
PLATFORM_END
diff --git a/xen/arch/arm/platforms/omap5.c b/xen/arch/arm/platforms/omap5.c
index 76d4d9b..9d6e504 100644
--- a/xen/arch/arm/platforms/omap5.c
+++ b/xen/arch/arm/platforms/omap5.c
@@ -102,21 +102,20 @@ static int omap5_init_time(void)
static int omap5_specific_mapping(struct domain *d)
{
/* Map the PRM module */
- map_mmio_regions(d, OMAP5_PRM_BASE, OMAP5_PRM_BASE + (PAGE_SIZE * 2) - 1,
- OMAP5_PRM_BASE);
+ map_mmio_regions(d, paddr_to_pfn(OMAP5_PRM_BASE), 2,
+ paddr_to_pfn(OMAP5_PRM_BASE));
/* Map the PRM_MPU */
- map_mmio_regions(d, OMAP5_PRCM_MPU_BASE,
- OMAP5_PRCM_MPU_BASE + PAGE_SIZE - 1,
- OMAP5_PRCM_MPU_BASE);
+ map_mmio_regions(d, paddr_to_pfn(OMAP5_PRCM_MPU_BASE), 1,
+ paddr_to_pfn(OMAP5_PRCM_MPU_BASE));
/* Map the Wakeup Gen */
- map_mmio_regions(d, OMAP5_WKUPGEN_BASE, OMAP5_WKUPGEN_BASE + PAGE_SIZE - 1,
- OMAP5_WKUPGEN_BASE);
+ map_mmio_regions(d, paddr_to_pfn(OMAP5_WKUPGEN_BASE), 1,
+ paddr_to_pfn(OMAP5_WKUPGEN_BASE));
/* Map the on-chip SRAM */
- map_mmio_regions(d, OMAP5_SRAM_PA, OMAP5_SRAM_PA + (PAGE_SIZE * 32) - 1,
- OMAP5_SRAM_PA);
+ map_mmio_regions(d, paddr_to_pfn(OMAP5_SRAM_PA), 32,
+ paddr_to_pfn(OMAP5_SRAM_PA));
return 0;
}
@@ -144,12 +143,29 @@ static int __init omap5_smp_init(void)
return 0;
}
-static const char const *omap5_dt_compat[] __initconst =
+static const char * const omap5_dt_compat[] __initconst =
{
"ti,omap5",
NULL
};
+static const char * const dra7_dt_compat[] __initconst =
+{
+ "ti,dra7",
+ NULL
+};
+
+static const struct dt_device_match dra7_blacklist_dev[] __initconst =
+{
+ /* OMAP Linux kernel handles devices with status "disabled" in a
+ * weird manner - tries to reset them. While their memory ranges
+ * are not mapped, this leads to data aborts, so skip these devices
+ * from DT for dom0.
+ */
+ DT_MATCH_NOT_AVAILABLE(),
+ { /* sentinel */ },
+};
+
PLATFORM_START(omap5, "TI OMAP5")
.compatible = omap5_dt_compat,
.init_time = omap5_init_time,
@@ -161,6 +177,17 @@ PLATFORM_START(omap5, "TI OMAP5")
.dom0_gnttab_size = 0x20000,
PLATFORM_END
+PLATFORM_START(dra7, "TI DRA7")
+ .compatible = dra7_dt_compat,
+ .init_time = omap5_init_time,
+ .cpu_up = cpu_up_send_sgi,
+ .smp_init = omap5_smp_init,
+
+ .dom0_gnttab_start = 0x4b000000,
+ .dom0_gnttab_size = 0x20000,
+ .blacklist_dev = dra7_blacklist_dev,
+PLATFORM_END
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/arm/platforms/seattle.c b/xen/arch/arm/platforms/seattle.c
new file mode 100644
index 0000000..6cc5362
--- /dev/null
+++ b/xen/arch/arm/platforms/seattle.c
@@ -0,0 +1,60 @@
+/*
+ * xen/arch/arm/seattle.c
+ *
+ * AMD Seattle specific settings
+ *
+ * Suravee Suthikulpanit <suravee.suthikulpanit at amd.com>
+ * Copyright (c) 2014 Advance Micro Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/platform.h>
+#include <asm/psci.h>
+
+static const char * const seattle_dt_compat[] __initconst =
+{
+ "amd,seattle",
+ NULL
+};
+
+/* Seattle firmware only implements PSCI handler for
+ * system off and system reset at this point.
+ * This is temporary until full PSCI-0.2 is supported.
+ * Then, these function will be removed.
+ */
+static void seattle_system_reset(void)
+{
+ call_smc(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
+}
+
+static void seattle_system_off(void)
+{
+ call_smc(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
+}
+
+PLATFORM_START(seattle, "SEATTLE")
+ .compatible = seattle_dt_compat,
+ .reset = seattle_system_reset,
+ .poweroff = seattle_system_off,
+
+ .dom0_gnttab_start = 0xe1700000,
+ .dom0_gnttab_size = 0x20000,
+PLATFORM_END
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/platforms/sunxi.c b/xen/arch/arm/platforms/sunxi.c
index fb12801..89d8290 100644
--- a/xen/arch/arm/platforms/sunxi.c
+++ b/xen/arch/arm/platforms/sunxi.c
@@ -16,7 +16,38 @@
* GNU General Public License for more details.
*/
+#include <xen/mm.h>
+#include <xen/vmap.h>
#include <asm/platform.h>
+#include <asm/io.h>
+
+/* Watchdog constants: */
+#define SUNXI_WDT_BASE 0x01c20c90
+#define SUNXI_WDT_MODE 0x04
+#define SUNXI_WDT_MODEADDR (SUNXI_WDT_BASE + SUNXI_WDT_MODE)
+#define SUNXI_WDT_MODE_EN (1 << 0)
+#define SUNXI_WDT_MODE_RST_EN (1 << 1)
+
+
+static void sunxi_reset(void)
+{
+ void __iomem *wdt;
+
+ wdt = ioremap_nocache(SUNXI_WDT_MODEADDR & PAGE_MASK, PAGE_SIZE);
+ if ( !wdt )
+ {
+ dprintk(XENLOG_ERR, "Unable to map watchdog register!\n");
+ return;
+ }
+
+ /* Enable watchdog to trigger a reset after 500 ms: */
+ writel(SUNXI_WDT_MODE_EN | SUNXI_WDT_MODE_RST_EN,
+ wdt + (SUNXI_WDT_MODEADDR & ~PAGE_MASK));
+ iounmap(wdt);
+
+ for (;;)
+ wfi();
+}
static const char * const sunxi_dt_compat[] __initconst =
{
@@ -37,6 +68,7 @@ static const struct dt_device_match sunxi_blacklist_dev[] __initconst =
PLATFORM_START(sunxi, "Allwinner A20")
.compatible = sunxi_dt_compat,
.blacklist_dev = sunxi_blacklist_dev,
+ .reset = sunxi_reset,
.dom0_gnttab_start = 0x01d00000,
.dom0_gnttab_size = 0x20000,
diff --git a/xen/arch/arm/platforms/vexpress.c b/xen/arch/arm/platforms/vexpress.c
index 6132056..ce66935 100644
--- a/xen/arch/arm/platforms/vexpress.c
+++ b/xen/arch/arm/platforms/vexpress.c
@@ -48,7 +48,7 @@ static inline int vexpress_ctrl_start(uint32_t *syscfg, int write,
/* wait for complete flag to be set */
do {
stat = syscfg[V2M_SYS_CFGSTAT/4];
- dsb();
+ dsb(sy);
} while ( !(stat & V2M_SYS_CFG_COMPLETE) );
/* check error status and return error flag if set */
@@ -113,10 +113,10 @@ static void vexpress_reset(void)
/* switch to slow mode */
writel(0x3, sp810);
- dsb(); isb();
+ dsb(sy); isb();
/* writing any value to SCSYSSTAT reg will reset the system */
writel(0x1, sp810 + 4);
- dsb(); isb();
+ dsb(sy); isb();
iounmap(sp810);
}
@@ -176,6 +176,8 @@ PLATFORM_START(vexpress, "VERSATILE EXPRESS")
#endif
.reset = vexpress_reset,
.blacklist_dev = vexpress_blacklist_dev,
+ .dom0_gnttab_start = 0x10000000,
+ .dom0_gnttab_size = 0x20000,
PLATFORM_END
/*
diff --git a/xen/arch/arm/platforms/xgene-storm.c b/xen/arch/arm/platforms/xgene-storm.c
index af3b71c..0b3492d 100644
--- a/xen/arch/arm/platforms/xgene-storm.c
+++ b/xen/arch/arm/platforms/xgene-storm.c
@@ -37,19 +37,19 @@ static bool reset_vals_valid = false;
static uint32_t xgene_storm_quirks(void)
{
- return PLATFORM_QUIRK_GIC_64K_STRIDE;
+ return PLATFORM_QUIRK_GIC_64K_STRIDE|PLATFORM_QUIRK_GUEST_PIRQ_NEED_EOI;
}
static int map_one_mmio(struct domain *d, const char *what,
- paddr_t start, paddr_t end)
+ unsigned long start, unsigned long end)
{
int ret;
- printk("Additional MMIO %"PRIpaddr"-%"PRIpaddr" (%s)\n",
+ printk("Additional MMIO %lx-%lx (%s)\n",
start, end, what);
- ret = map_mmio_regions(d, start, end, start);
+ ret = map_mmio_regions(d, start, end - start, start);
if ( ret )
- printk("Failed to map %s @ %"PRIpaddr" to dom%d\n",
+ printk("Failed to map %s @ %lx to dom%d\n",
what, start, d->domain_id);
return ret;
}
@@ -57,61 +57,56 @@ static int map_one_mmio(struct domain *d, const char *what,
static int map_one_spi(struct domain *d, const char *what,
unsigned int spi, unsigned int type)
{
- struct dt_irq irq;
+ unsigned int irq;
int ret;
- irq.type = type;
+ irq = spi + 32; /* SPIs start at IRQ 32 */
- irq.irq = spi + 32; /* SPIs start at IRQ 32 */
+ ret = irq_set_spi_type(irq, type);
+ if ( ret )
+ {
+ printk("Failed to set the type for IRQ%u\n", irq);
+ return ret;
+ }
- printk("Additional IRQ %u (%s)\n", irq.irq, what);
+ printk("Additional IRQ %u (%s)\n", irq, what);
- ret = gic_route_irq_to_guest(d, &irq, what);
+ ret = route_irq_to_guest(d, irq, what);
if ( ret )
printk("Failed to route %s to dom%d\n", what, d->domain_id);
return ret;
}
-/*
- * Xen does not currently support mapping MMIO regions and interrupt
- * for bus child devices (referenced via the "ranges" and
- * "interrupt-map" properties to domain 0). Instead for now map the
- * necessary resources manually.
- */
-static int xgene_storm_specific_mapping(struct domain *d)
+/* Creates MMIO mappings base..end as well as 4 SPIs from the given base. */
+static int xgene_storm_pcie_specific_mapping(struct domain *d,
+ const struct dt_device_node *node,
+ paddr_t base, paddr_t end,
+ int base_spi)
{
int ret;
- /* Map the PCIe bus resources */
- ret = map_one_mmio(d, "PCI MEM REGION", 0xe000000000UL, 0xe010000000UL);
- if ( ret )
- goto err;
+ printk("Mapping additional regions for PCIe device %s\n",
+ dt_node_full_name(node));
- ret = map_one_mmio(d, "PCI IO REGION", 0xe080000000UL, 0xe080010000UL);
- if ( ret )
- goto err;
-
- ret = map_one_mmio(d, "PCI CFG REGION", 0xe0d0000000UL, 0xe0d0200000UL);
- if ( ret )
- goto err;
- ret = map_one_mmio(d, "PCI MSI REGION", 0xe010000000UL, 0xe010800000UL);
+ /* Map the PCIe bus resources */
+ ret = map_one_mmio(d, "PCI MEMORY", paddr_to_pfn(base), paddr_to_pfn(end));
if ( ret )
goto err;
- ret = map_one_spi(d, "PCI#INTA", 0xc2, DT_IRQ_TYPE_LEVEL_HIGH);
+ ret = map_one_spi(d, "PCI#INTA", base_spi+0, DT_IRQ_TYPE_LEVEL_HIGH);
if ( ret )
goto err;
- ret = map_one_spi(d, "PCI#INTB", 0xc3, DT_IRQ_TYPE_LEVEL_HIGH);
+ ret = map_one_spi(d, "PCI#INTB", base_spi+1, DT_IRQ_TYPE_LEVEL_HIGH);
if ( ret )
goto err;
- ret = map_one_spi(d, "PCI#INTC", 0xc4, DT_IRQ_TYPE_LEVEL_HIGH);
+ ret = map_one_spi(d, "PCI#INTC", base_spi+2, DT_IRQ_TYPE_LEVEL_HIGH);
if ( ret )
goto err;
- ret = map_one_spi(d, "PCI#INTD", 0xc5, DT_IRQ_TYPE_LEVEL_HIGH);
+ ret = map_one_spi(d, "PCI#INTD", base_spi+3, DT_IRQ_TYPE_LEVEL_HIGH);
if ( ret )
goto err;
@@ -120,6 +115,69 @@ err:
return ret;
}
+/*
+ * Xen does not currently support mapping MMIO regions and interrupt
+ * for bus child devices (referenced via the "ranges" and
+ * "interrupt-map" properties to domain 0). Instead for now map the
+ * necessary resources manually.
+ */
+static int xgene_storm_specific_mapping(struct domain *d)
+{
+ struct dt_device_node *node = NULL;
+ int ret;
+
+ while ( (node = dt_find_compatible_node(node, "pci", "apm,xgene-pcie")) )
+ {
+ u64 addr;
+
+ /* Identify the bus via it's control register address */
+ ret = dt_device_get_address(node, 0, &addr, NULL);
+ if ( ret < 0 )
+ return ret;
+
+ if ( !dt_device_is_available(node) )
+ continue;
+
+ switch ( addr )
+ {
+ case 0x1f2b0000: /* PCIe0 */
+ ret = xgene_storm_pcie_specific_mapping(d,
+ node,
+ 0x0e000000000UL, 0x10000000000UL, 0xc2);
+ break;
+ case 0x1f2c0000: /* PCIe1 */
+ ret = xgene_storm_pcie_specific_mapping(d,
+ node,
+ 0x0d000000000UL, 0x0e000000000UL, 0xc8);
+ break;
+ case 0x1f2d0000: /* PCIe2 */
+ ret = xgene_storm_pcie_specific_mapping(d,
+ node,
+ 0x09000000000UL, 0x0a000000000UL, 0xce);
+ break;
+ case 0x1f500000: /* PCIe3 */
+ ret = xgene_storm_pcie_specific_mapping(d,
+ node,
+ 0x0a000000000UL, 0x0c000000000UL, 0xd4);
+ break;
+ case 0x1f510000: /* PCIe4 */
+ ret = xgene_storm_pcie_specific_mapping(d,
+ node,
+ 0x0c000000000UL, 0x0d000000000UL, 0xda);
+ break;
+
+ default:
+ printk("Ignoring unknown PCI bus %s\n", dt_node_full_name(node));
+ continue;
+ }
+
+ if ( ret < 0 )
+ return ret;
+ }
+
+ return 0;
+}
+
static void xgene_storm_reset(void)
{
void __iomem *addr;
diff --git a/xen/arch/arm/processor.c b/xen/arch/arm/processor.c
new file mode 100644
index 0000000..8c425ce
--- /dev/null
+++ b/xen/arch/arm/processor.c
@@ -0,0 +1,49 @@
+/*
+ * xen/arch/arm/processor.c
+ *
+ * Helpers to execute processor specific code.
+ *
+ * Julien Grall <julien.grall at linaro.org>
+ * Copyright (C) 2014 Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <asm/procinfo.h>
+
+static const struct processor *processor = NULL;
+
+void __init processor_setup(void)
+{
+ const struct proc_info_list *procinfo;
+
+ procinfo = lookup_processor_type();
+ if ( !procinfo )
+ return;
+
+ processor = procinfo->processor;
+}
+
+void processor_vcpu_initialise(struct vcpu *v)
+{
+ if ( !processor || !processor->vcpu_initialise )
+ return;
+
+ processor->vcpu_initialise(v);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/psci.c b/xen/arch/arm/psci.c
index b6360d5..4066309 100644
--- a/xen/arch/arm/psci.c
+++ b/xen/arch/arm/psci.c
@@ -23,51 +23,32 @@
#include <xen/smp.h>
#include <asm/psci.h>
-bool_t psci_available;
-
-#ifdef CONFIG_ARM_32
-#define REG_PREFIX "r"
-#else
-#define REG_PREFIX "x"
-#endif
-
-static noinline int __invoke_psci_fn_smc(register_t function_id,
- register_t arg0,
- register_t arg1,
- register_t arg2)
-{
- asm volatile(
- __asmeq("%0", REG_PREFIX"0")
- __asmeq("%1", REG_PREFIX"1")
- __asmeq("%2", REG_PREFIX"2")
- __asmeq("%3", REG_PREFIX"3")
- "smc #0"
- : "+r" (function_id)
- : "r" (arg0), "r" (arg1), "r" (arg2));
-
- return function_id;
-}
-
-#undef REG_PREFIX
+uint32_t psci_ver;
static uint32_t psci_cpu_on_nr;
int call_psci_cpu_on(int cpu)
{
- return __invoke_psci_fn_smc(psci_cpu_on_nr,
- cpu_logical_map(cpu), __pa(init_secondary), 0);
+ return call_smc(psci_cpu_on_nr, cpu_logical_map(cpu), __pa(init_secondary), 0);
}
-int __init psci_init(void)
+void call_psci_system_off(void)
+{
+ if ( psci_ver > XEN_PSCI_V_0_1 )
+ call_smc(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
+}
+
+void call_psci_system_reset(void)
+{
+ if ( psci_ver > XEN_PSCI_V_0_1 )
+ call_smc(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
+}
+
+int __init psci_is_smc_method(const struct dt_device_node *psci)
{
- const struct dt_device_node *psci;
int ret;
const char *prop_str;
- psci = dt_find_compatible_node(NULL, NULL, "arm,psci");
- if ( !psci )
- return -ENODEV;
-
ret = dt_property_read_string(psci, "method", &prop_str);
if ( ret )
{
@@ -85,19 +66,74 @@ int __init psci_init(void)
return -EINVAL;
}
+ return 0;
+}
+
+int __init psci_init_0_1(void)
+{
+ int ret;
+ const struct dt_device_node *psci;
+
+ psci = dt_find_compatible_node(NULL, NULL, "arm,psci");
+ if ( !psci )
+ return -EOPNOTSUPP;
+
+ ret = psci_is_smc_method(psci);
+ if ( ret )
+ return -EINVAL;
+
if ( !dt_property_read_u32(psci, "cpu_on", &psci_cpu_on_nr) )
{
printk("/psci node is missing the \"cpu_on\" property\n");
return -ENOENT;
}
- psci_available = 1;
+ psci_ver = XEN_PSCI_V_0_1;
- printk(XENLOG_INFO "Using PSCI for SMP bringup\n");
+ printk(XENLOG_INFO "Using PSCI-0.1 for SMP bringup\n");
return 0;
}
+int __init psci_init_0_2(void)
+{
+ int ret;
+ const struct dt_device_node *psci;
+
+ psci = dt_find_compatible_node(NULL, NULL, "arm,psci-0.2");
+ if ( !psci )
+ return -EOPNOTSUPP;
+
+ ret = psci_is_smc_method(psci);
+ if ( ret )
+ return -EINVAL;
+
+ psci_ver = call_smc(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
+
+ if ( psci_ver != XEN_PSCI_V_0_2 )
+ {
+ printk("Error: PSCI version %#x is not supported.\n", psci_ver);
+ return -EOPNOTSUPP;
+ }
+
+ psci_cpu_on_nr = PSCI_0_2_FN_CPU_ON;
+
+ printk(XENLOG_INFO "Using PSCI-0.2 for SMP bringup\n");
+
+ return 0;
+}
+
+int __init psci_init(void)
+{
+ int ret;
+
+ ret = psci_init_0_2();
+ if ( ret )
+ ret = psci_init_0_1();
+
+ return ret;
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 9480f42..d2dcc3a 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -39,10 +39,14 @@
#include <asm/page.h>
#include <asm/current.h>
#include <asm/setup.h>
-#include <asm/early_printk.h>
#include <asm/gic.h>
#include <asm/cpufeature.h>
#include <asm/platform.h>
+#include <asm/procinfo.h>
+#include <asm/setup.h>
+#include <xsm/xsm.h>
+
+struct bootinfo __initdata bootinfo;
struct cpuinfo_arm __read_mostly boot_cpu_data;
@@ -99,9 +103,10 @@ static void __init processor_id(void)
cpu_has_el2_32 ? "64+32" : cpu_has_el2_64 ? "64" : "No",
cpu_has_el1_32 ? "64+32" : cpu_has_el1_64 ? "64" : "No",
cpu_has_el0_32 ? "64+32" : cpu_has_el0_64 ? "64" : "No");
- printk(" Extensions:%s%s\n",
+ printk(" Extensions:%s%s%s\n",
cpu_has_fp ? " FloatingPoint" : "",
- cpu_has_simd ? " AdvancedSIMD" : "");
+ cpu_has_simd ? " AdvancedSIMD" : "",
+ cpu_has_gicv3 ? " GICv3-SysReg" : "");
printk(" Debug Features: %016"PRIx64" %016"PRIx64"\n",
boot_cpu_data.dbg64.bits[0], boot_cpu_data.dbg64.bits[1]);
@@ -122,8 +127,9 @@ static void __init processor_id(void)
printk("32-bit Execution:\n");
printk(" Processor Features: %08"PRIx32":%08"PRIx32"\n",
boot_cpu_data.pfr32.bits[0], boot_cpu_data.pfr32.bits[1]);
- printk(" Instruction Sets:%s%s%s%s%s\n",
+ printk(" Instruction Sets:%s%s%s%s%s%s\n",
cpu_has_aarch32 ? " AArch32" : "",
+ cpu_has_arm ? " A32" : "",
cpu_has_thumb ? " Thumb" : "",
cpu_has_thumb2 ? " Thumb-2" : "",
cpu_has_thumbee ? " ThumbEE" : "",
@@ -149,6 +155,8 @@ static void __init processor_id(void)
{
printk("32-bit Execution: Unsupported\n");
}
+
+ processor_setup();
}
static void dt_unreserved_regions(paddr_t s, paddr_t e,
@@ -177,16 +185,76 @@ static void dt_unreserved_regions(paddr_t s, paddr_t e,
cb(s, e);
}
+struct bootmodule *add_boot_module(bootmodule_kind kind,
+ paddr_t start, paddr_t size,
+ const char *cmdline)
+{
+ struct bootmodules *mods = &bootinfo.modules;
+ struct bootmodule *mod;
+
+ if ( mods->nr_mods == MAX_MODULES )
+ {
+ printk("Ignoring %s boot module at %"PRIpaddr"-%"PRIpaddr" (too many)\n",
+ boot_module_kind_as_string(kind), start, start + size);
+ return NULL;
+ }
+
+ mod = &mods->module[mods->nr_mods++];
+ mod->kind = kind;
+ mod->start = start;
+ mod->size = size;
+ if ( cmdline )
+ safe_strcpy(mod->cmdline, cmdline);
+ else
+ mod->cmdline[0] = 0;
+
+ return mod;
+}
+
+struct bootmodule * __init boot_module_find_by_kind(bootmodule_kind kind)
+{
+ struct bootmodules *mods = &bootinfo.modules;
+ struct bootmodule *mod;
+ int i;
+ for (i = 0 ; i < mods->nr_mods ; i++ )
+ {
+ mod = &mods->module[i];
+ if ( mod->kind == kind )
+ return mod;
+ }
+ return NULL;
+}
+
+const char * __init boot_module_kind_as_string(bootmodule_kind kind)
+{
+ switch ( kind )
+ {
+ case BOOTMOD_XEN: return "Xen";
+ case BOOTMOD_FDT: return "Device Tree";
+ case BOOTMOD_KERNEL: return "Kernel";
+ case BOOTMOD_RAMDISK: return "Ramdisk";
+ case BOOTMOD_XSM: return "XSM";
+ case BOOTMOD_UNKNOWN: return "Unknown";
+ default: BUG();
+ }
+}
+
void __init discard_initial_modules(void)
{
- struct dt_module_info *mi = &early_info.modules;
+ struct bootmodules *mi = &bootinfo.modules;
int i;
- for ( i = MOD_DISCARD_FIRST; i <= mi->nr_mods; i++ )
+ for ( i = 0; i <= mi->nr_mods; i++ )
{
paddr_t s = mi->module[i].start;
paddr_t e = s + PAGE_ALIGN(mi->module[i].size);
+ if ( mi->module[i].kind == BOOTMOD_XEN )
+ continue;
+
+ if ( !mfn_valid(paddr_to_pfn(s)) || !mfn_valid(paddr_to_pfn(e)))
+ continue;
+
dt_unreserved_regions(s, e, init_domheap_pages, 0);
}
@@ -207,7 +275,7 @@ static paddr_t __init consider_modules(paddr_t s, paddr_t e,
uint32_t size, paddr_t align,
int first_mod)
{
- const struct dt_module_info *mi = &early_info.modules;
+ const struct bootmodules *mi = &bootinfo.modules;
int i;
int nr_rsvd;
@@ -272,7 +340,7 @@ static paddr_t __init consider_modules(paddr_t s, paddr_t e,
*/
static paddr_t __init next_module(paddr_t s, paddr_t *end)
{
- struct dt_module_info *mi = &early_info.modules;
+ struct bootmodules *mi = &bootinfo.modules;
paddr_t lowest = ~(paddr_t)0;
int i;
@@ -281,6 +349,9 @@ static paddr_t __init next_module(paddr_t s, paddr_t *end)
paddr_t mod_s = mi->module[i].start;
paddr_t mod_e = mod_s + mi->module[i].size;
+ if ( !mi->module[i].size )
+ continue;
+
if ( mod_s < s )
continue;
if ( mod_s > lowest )
@@ -302,7 +373,7 @@ static paddr_t __init next_module(paddr_t s, paddr_t *end)
*/
static paddr_t __init get_xen_paddr(void)
{
- struct dt_mem_info *mi = &early_info.mem;
+ struct meminfo *mi = &bootinfo.mem;
paddr_t min_size;
paddr_t paddr = 0, last_end;
int i;
@@ -326,7 +397,7 @@ static paddr_t __init get_xen_paddr(void)
if ( bank->size >= min_size )
{
e = consider_modules(bank->start, bank->start + bank->size,
- min_size, XEN_PADDR_ALIGN, 1);
+ min_size, XEN_PADDR_ALIGN, 0);
if ( !e )
continue;
@@ -346,22 +417,55 @@ static paddr_t __init get_xen_paddr(void)
}
if ( !paddr )
- early_panic("Not enough memory to relocate Xen");
-
- early_printk("Placing Xen at 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
- paddr, paddr + min_size);
+ panic("Not enough memory to relocate Xen");
- early_info.modules.module[MOD_XEN].start = paddr;
- early_info.modules.module[MOD_XEN].size = min_size;
+ printk("Placing Xen at 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
+ paddr, paddr + min_size);
return paddr;
}
+static void init_pdx(void)
+{
+ paddr_t bank_start, bank_size, bank_end;
+
+ u64 mask = pdx_init_mask(bootinfo.mem.bank[0].start);
+ int bank;
+
+ for ( bank = 0 ; bank < bootinfo.mem.nr_banks; bank++ )
+ {
+ bank_start = bootinfo.mem.bank[bank].start;
+ bank_size = bootinfo.mem.bank[bank].size;
+
+ mask |= bank_start | pdx_region_mask(bank_start, bank_size);
+ }
+
+ for ( bank = 0 ; bank < bootinfo.mem.nr_banks; bank++ )
+ {
+ bank_start = bootinfo.mem.bank[bank].start;
+ bank_size = bootinfo.mem.bank[bank].size;
+
+ if (~mask & pdx_region_mask(bank_start, bank_size))
+ mask = 0;
+ }
+
+ pfn_pdx_hole_setup(mask >> PAGE_SHIFT);
+
+ for ( bank = 0 ; bank < bootinfo.mem.nr_banks; bank++ )
+ {
+ bank_start = bootinfo.mem.bank[bank].start;
+ bank_size = bootinfo.mem.bank[bank].size;
+ bank_end = bank_start + bank_size;
+
+ set_pdx_range(paddr_to_pfn(bank_start),
+ paddr_to_pfn(bank_end));
+ }
+}
+
#ifdef CONFIG_ARM_32
static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
{
paddr_t ram_start, ram_end, ram_size;
- paddr_t contig_start, contig_end;
paddr_t s, e;
unsigned long ram_pages;
unsigned long heap_pages, xenheap_pages, domheap_pages;
@@ -370,69 +474,24 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
int i;
void *fdt;
- if ( !early_info.mem.nr_banks )
- early_panic("No memory bank");
+ if ( !bootinfo.mem.nr_banks )
+ panic("No memory bank");
- /*
- * We are going to accumulate two regions here.
- *
- * The first is the bounds of the initial memory region which is
- * contiguous with the first bank. For simplicity the xenheap is
- * always allocated from this region.
- *
- * The second is the complete bounds of the regions containing RAM
- * (ie. from the lowest RAM address to the highest), which
- * includes any holes.
- *
- * We also track the number of actual RAM pages (i.e. not counting
- * the holes).
- */
- ram_size = early_info.mem.bank[0].size;
+ init_pdx();
- contig_start = ram_start = early_info.mem.bank[0].start;
- contig_end = ram_end = ram_start + ram_size;
+ ram_start = bootinfo.mem.bank[0].start;
+ ram_size = bootinfo.mem.bank[0].size;
+ ram_end = ram_start + ram_size;
- for ( i = 1; i < early_info.mem.nr_banks; i++ )
+ for ( i = 1; i < bootinfo.mem.nr_banks; i++ )
{
- paddr_t bank_start = early_info.mem.bank[i].start;
- paddr_t bank_size = early_info.mem.bank[i].size;
+ paddr_t bank_start = bootinfo.mem.bank[i].start;
+ paddr_t bank_size = bootinfo.mem.bank[i].size;
paddr_t bank_end = bank_start + bank_size;
- paddr_t new_ram_size = ram_size + bank_size;
- paddr_t new_ram_start = min(ram_start,bank_start);
- paddr_t new_ram_end = max(ram_end,bank_end);
-
- /*
- * If the new bank is contiguous with the initial contiguous
- * region then incorporate it into the contiguous region.
- *
- * Otherwise we allow non-contigious regions so long as at
- * least half of the total RAM region actually contains
- * RAM. We actually fudge this slightly and require that
- * adding the current bank does not cause us to violate this
- * restriction.
- *
- * This restriction ensures that the frametable (which is not
- * currently sparse) does not consume all available RAM.
- */
- if ( bank_start == contig_end )
- contig_end = bank_end;
- else if ( bank_end == contig_start )
- contig_start = bank_start;
- else if ( 2 * new_ram_size < new_ram_end - new_ram_start )
- /* Would create memory map which is too sparse, so stop here. */
- break;
-
- ram_size = new_ram_size;
- ram_start = new_ram_start;
- ram_end = new_ram_end;
- }
-
- if ( i != early_info.mem.nr_banks )
- {
- early_printk("WARNING: only using %d out of %d memory banks\n",
- i, early_info.mem.nr_banks);
- early_info.mem.nr_banks = i;
+ ram_size = ram_size + bank_size;
+ ram_start = min(ram_start,bank_start);
+ ram_end = max(ram_end,bank_end);
}
total_pages = ram_pages = ram_size >> PAGE_SHIFT;
@@ -442,7 +501,7 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
*
* - must be 32 MiB aligned
* - must not include Xen itself or the boot modules
- * - must be at most 1/8 the total RAM in the system
+ * - must be at most 1GB or 1/8 the total RAM in the system if less
* - must be at least 128M
*
* We try to allocate the largest xenheap possible within these
@@ -451,11 +510,11 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
heap_pages = ram_pages;
xenheap_pages = (heap_pages/8 + 0x1fffUL) & ~0x1fffUL;
xenheap_pages = max(xenheap_pages, 128UL<<(20-PAGE_SHIFT));
+ xenheap_pages = min(xenheap_pages, 1UL<<(30-PAGE_SHIFT));
do
{
- /* xenheap is always in the initial contiguous region */
- e = consider_modules(contig_start, contig_end,
+ e = consider_modules(ram_start, ram_end,
pfn_to_paddr(xenheap_pages),
32<<20, 0);
if ( e )
@@ -465,14 +524,13 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
} while ( xenheap_pages > 128<<(20-PAGE_SHIFT) );
if ( ! e )
- early_panic("Not not enough space for xenheap");
+ panic("Not not enough space for xenheap");
domheap_pages = heap_pages - xenheap_pages;
- early_printk("Xen heap: %"PRIpaddr"-%"PRIpaddr" (%lu pages)\n",
- e - (pfn_to_paddr(xenheap_pages)), e,
- xenheap_pages);
- early_printk("Dom heap: %lu pages\n", domheap_pages);
+ printk("Xen heap: %"PRIpaddr"-%"PRIpaddr" (%lu pages)\n",
+ e - (pfn_to_paddr(xenheap_pages)), e, xenheap_pages);
+ printk("Dom heap: %lu pages\n", domheap_pages);
setup_xenheap_mappings((e >> PAGE_SHIFT) - xenheap_pages, xenheap_pages);
@@ -488,14 +546,14 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
/* Copy the DTB. */
fdt = mfn_to_virt(alloc_boot_pages(dtb_pages, 1));
- copy_from_paddr(fdt, dtb_paddr, dtb_size, BUFFERABLE);
+ copy_from_paddr(fdt, dtb_paddr, dtb_size);
device_tree_flattened = fdt;
/* Add non-xenheap memory */
- for ( i = 0; i < early_info.mem.nr_banks; i++ )
+ for ( i = 0; i < bootinfo.mem.nr_banks; i++ )
{
- paddr_t bank_start = early_info.mem.bank[i].start;
- paddr_t bank_end = bank_start + early_info.mem.bank[i].size;
+ paddr_t bank_start = bootinfo.mem.bank[i].start;
+ paddr_t bank_end = bank_start + bootinfo.mem.bank[i].size;
s = bank_start;
while ( s < bank_end )
@@ -551,34 +609,19 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
unsigned long dtb_pages;
void *fdt;
+ init_pdx();
+
total_pages = 0;
- for ( bank = 0 ; bank < early_info.mem.nr_banks; bank++ )
+ for ( bank = 0 ; bank < bootinfo.mem.nr_banks; bank++ )
{
- paddr_t bank_start = early_info.mem.bank[bank].start;
- paddr_t bank_size = early_info.mem.bank[bank].size;
+ paddr_t bank_start = bootinfo.mem.bank[bank].start;
+ paddr_t bank_size = bootinfo.mem.bank[bank].size;
paddr_t bank_end = bank_start + bank_size;
paddr_t s, e;
- paddr_t new_ram_size = ram_size + bank_size;
- paddr_t new_ram_start = min(ram_start,bank_start);
- paddr_t new_ram_end = max(ram_end,bank_end);
-
- /*
- * We allow non-contigious regions so long as at least half of
- * the total RAM region actually contains RAM. We actually
- * fudge this slightly and require that adding the current
- * bank does not cause us to violate this restriction.
- *
- * This restriction ensures that the frametable (which is not
- * currently sparse) does not consume all available RAM.
- */
- if ( bank > 0 && 2 * new_ram_size < new_ram_end - new_ram_start )
- /* Would create memory map which is too sparse, so stop here. */
- break;
-
- ram_start = new_ram_start;
- ram_end = new_ram_end;
- ram_size = new_ram_size;
+ ram_size = ram_size + bank_size;
+ ram_start = min(ram_start,bank_start);
+ ram_end = max(ram_end,bank_end);
setup_xenheap_mappings(bank_start>>PAGE_SHIFT, bank_size>>PAGE_SHIFT);
@@ -604,13 +647,6 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
}
}
- if ( bank != early_info.mem.nr_banks )
- {
- early_printk("WARNING: only using %d out of %d memory banks\n",
- bank, early_info.mem.nr_banks);
- early_info.mem.nr_banks = bank;
- }
-
total_pages += ram_size >> PAGE_SHIFT;
xenheap_virt_end = XENHEAP_VIRT_START + ram_end - ram_start;
@@ -625,7 +661,7 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
/* Copy the DTB. */
fdt = mfn_to_virt(alloc_boot_pages(dtb_pages, 1));
- copy_from_paddr(fdt, dtb_paddr, dtb_size, BUFFERABLE);
+ copy_from_paddr(fdt, dtb_paddr, dtb_size);
device_tree_flattened = fdt;
setup_frametable_mappings(ram_start, ram_end);
@@ -657,31 +693,56 @@ void __init start_xen(unsigned long boot_phys_offset,
{
size_t fdt_size;
int cpus, i;
+ paddr_t xen_paddr;
const char *cmdline;
+ struct bootmodule *xen_bootmodule;
+ struct domain *dom0;
setup_cache();
percpu_init_areas();
set_processor_id(0); /* needed early, for smp_processor_id() */
+ set_current((struct vcpu *)0xfffff000); /* debug sanity */
+ idle_vcpu[0] = current;
+
+ /* Initialize traps early allow us to get backtrace when an error occurred */
+ init_traps();
+
smp_clear_cpu_maps();
/* This is mapped by head.S */
device_tree_flattened = (void *)BOOT_FDT_VIRT_START
+ (fdt_paddr & ((1 << SECOND_SHIFT) - 1));
- fdt_size = device_tree_early_init(device_tree_flattened, fdt_paddr);
+ fdt_size = boot_fdt_info(device_tree_flattened, fdt_paddr);
- cmdline = device_tree_bootargs(device_tree_flattened);
- early_printk("Command line: %s\n", cmdline);
+ cmdline = boot_fdt_cmdline(device_tree_flattened);
+ printk("Command line: %s\n", cmdline);
cmdline_parse(cmdline);
- setup_pagetables(boot_phys_offset, get_xen_paddr());
+ /* Register Xen's load address as a boot module. */
+ xen_bootmodule = add_boot_module(BOOTMOD_XEN,
+ (paddr_t)(uintptr_t)(_start + boot_phys_offset),
+ (paddr_t)(uintptr_t)(_end - _start + 1), NULL);
+ BUG_ON(!xen_bootmodule);
+
+ xen_paddr = get_xen_paddr();
+ setup_pagetables(boot_phys_offset, xen_paddr);
+
+ /* Update Xen's address now that we have relocated. */
+ printk("Update BOOTMOD_XEN from %"PRIpaddr"-%"PRIpaddr" => %"PRIpaddr"-%"PRIpaddr"\n",
+ xen_bootmodule->start, xen_bootmodule->start + xen_bootmodule->size,
+ xen_paddr, xen_paddr + xen_bootmodule->size);
+ xen_bootmodule->start = xen_paddr;
+
setup_mm(fdt_paddr, fdt_size);
vm_init();
dt_unflatten_host_device_tree();
dt_irq_xlate = gic_irq_xlate;
+ init_IRQ();
+
dt_uart_init();
console_init_preirq();
@@ -698,23 +759,14 @@ void __init start_xen(unsigned long boot_phys_offset,
gic_init();
- set_current((struct vcpu *)0xfffff000); /* debug sanity */
- idle_vcpu[0] = current;
-
- init_traps();
-
- setup_virt_paging();
-
p2m_vmid_allocator_init();
softirq_init();
tasklet_subsys_init();
- init_IRQ();
- gic_route_ppis();
- gic_route_spis();
+ xsm_dt_init();
init_maintenance_interrupt();
init_timer_interrupt();
@@ -730,6 +782,8 @@ void __init start_xen(unsigned long boot_phys_offset,
local_irq_enable();
local_abort_enable();
+ iommu_setup();
+
smp_prepare_cpus(cpus);
initialize_keytable();
@@ -751,11 +805,13 @@ void __init start_xen(unsigned long boot_phys_offset,
printk("Brought up %ld CPUs\n", (long)num_online_cpus());
/* TODO: smp_cpus_done(); */
+ setup_virt_paging();
+
do_initcalls();
/* Create initial domain 0. */
dom0 = domain_create(0, 0, 0);
- if ( IS_ERR(dom0) || (alloc_dom0_vcpu0() == NULL) )
+ if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
panic("Error creating domain 0");
dom0->is_privileged = 1;
@@ -797,8 +853,11 @@ void arch_get_xen_caps(xen_capabilities_info_t *info)
snprintf(s, sizeof(s), "xen-%d.%d-aarch64 ", major, minor);
safe_strcat(*info, s);
#endif
- snprintf(s, sizeof(s), "xen-%d.%d-armv7l ", major, minor);
- safe_strcat(*info, s);
+ if ( cpu_has_aarch32 )
+ {
+ snprintf(s, sizeof(s), "xen-%d.%d-armv7l ", major, minor);
+ safe_strcat(*info, s);
+ }
}
/*
diff --git a/xen/arch/arm/shutdown.c b/xen/arch/arm/shutdown.c
index 767cc12..4988b03 100644
--- a/xen/arch/arm/shutdown.c
+++ b/xen/arch/arm/shutdown.c
@@ -5,23 +5,32 @@
#include <xen/lib.h>
#include <xen/smp.h>
#include <asm/platform.h>
+#include <asm/psci.h>
-static void raw_machine_reset(void)
-{
- platform_reset();
-}
-
-static void halt_this_cpu(void *arg)
+static void noreturn halt_this_cpu(void *arg)
{
stop_cpu();
}
void machine_halt(void)
{
+ int timeout = 10;
+
watchdog_disable();
console_start_sync();
local_irq_enable();
smp_call_function(halt_this_cpu, NULL, 0);
+ local_irq_disable();
+
+ /* Wait at most another 10ms for all other CPUs to go offline. */
+ while ( (num_online_cpus() > 1) && (timeout-- > 0) )
+ mdelay(1);
+
+ /* This is mainly for PSCI-0.2, which does not return if success. */
+ call_psci_system_off();
+
+ /* Alternative halt procedure */
+ platform_poweroff();
halt_this_cpu(NULL);
}
@@ -39,9 +48,13 @@ void machine_restart(unsigned int delay_millisecs)
while ( (num_online_cpus() > 1) && (timeout-- > 0) )
mdelay(1);
+ /* This is mainly for PSCI-0.2, which does not return if success. */
+ call_psci_system_reset();
+
+ /* Alternative reset procedure */
while ( 1 )
{
- raw_machine_reset();
+ platform_reset();
mdelay(100);
}
}
diff --git a/xen/arch/arm/smc.S b/xen/arch/arm/smc.S
new file mode 100644
index 0000000..b8f1822
--- /dev/null
+++ b/xen/arch/arm/smc.S
@@ -0,0 +1,21 @@
+/*
+ * xen/arch/arm/smc.S
+ *
+ * Wrapper for Secure Monitors Calls
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/macros.h>
+
+ENTRY(call_smc)
+ smc #0
+ ret
diff --git a/xen/arch/arm/smp.c b/xen/arch/arm/smp.c
index 30203b8..917d490 100644
--- a/xen/arch/arm/smp.c
+++ b/xen/arch/arm/smp.c
@@ -19,7 +19,18 @@ void smp_send_event_check_mask(const cpumask_t *mask)
void smp_send_call_function_mask(const cpumask_t *mask)
{
- send_SGI_mask(mask, GIC_SGI_CALL_FUNCTION);
+ cpumask_t target_mask;
+
+ cpumask_andnot(&target_mask, mask, cpumask_of(smp_processor_id()));
+
+ send_SGI_mask(&target_mask, GIC_SGI_CALL_FUNCTION);
+
+ if ( cpumask_test_cpu(smp_processor_id(), mask) )
+ {
+ local_irq_disable();
+ smp_call_function_interrupt();
+ local_irq_enable();
+ }
}
/*
diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c
index a829957..14054ae 100644
--- a/xen/arch/arm/smpboot.c
+++ b/xen/arch/arm/smpboot.c
@@ -279,16 +279,12 @@ void __cpuinit start_secondary(unsigned long boot_phys_offset,
init_traps();
- setup_virt_paging();
-
mmu_init_secondary_cpu();
gic_init_secondary_cpu();
init_secondary_IRQ();
- gic_route_ppis();
-
init_maintenance_interrupt();
init_timer_interrupt();
@@ -298,12 +294,12 @@ void __cpuinit start_secondary(unsigned long boot_phys_offset,
/* Run local notifiers */
notify_cpu_starting(cpuid);
- wmb();
+ smp_wmb();
/* Now report this CPU is up */
smp_up_cpu = MPIDR_INVALID;
cpumask_set_cpu(cpuid, &cpu_online_map);
- wmb();
+ smp_wmb();
local_irq_enable();
local_abort_enable();
@@ -330,7 +326,7 @@ void __cpu_disable(void)
if ( cpu_disable_scheduler(cpu) )
BUG();
- mb();
+ smp_mb();
/* Return to caller; eventually the IPI mechanism will unwind and the
* scheduler will drop to the idle loop, which will call stop_cpu(). */
@@ -341,7 +337,7 @@ void stop_cpu(void)
local_irq_disable();
cpu_is_dead = 1;
/* Make sure the write happens before we sleep forever */
- dsb();
+ dsb(sy);
isb();
while ( 1 )
wfi();
@@ -378,7 +374,7 @@ int __cpu_up(unsigned int cpu)
/* Open the gate for this CPU */
smp_up_cpu = cpu_logical_map(cpu);
- clean_xen_dcache(smp_up_cpu);
+ clean_dcache(smp_up_cpu);
rc = arch_cpu_up(cpu);
@@ -411,10 +407,10 @@ void __cpu_die(unsigned int cpu)
process_pending_softirqs();
if ( (++i % 10) == 0 )
printk(KERN_ERR "CPU %u still not dead...\n", cpu);
- mb();
+ smp_mb();
}
cpu_is_dead = 0;
- mb();
+ smp_mb();
}
/*
diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
index 5374bf7..a6436f1 100644
--- a/xen/arch/arm/time.c
+++ b/xen/arch/arm/time.c
@@ -32,29 +32,23 @@
#include <asm/system.h>
#include <asm/time.h>
#include <asm/gic.h>
+#include <asm/vgic.h>
#include <asm/cpufeature.h>
#include <asm/platform.h>
-/*
- * Unfortunately the hypervisor timer interrupt appears to be buggy in
- * some versions of the model. Disable this to use the physical timer
- * instead.
- */
-#define USE_HYP_TIMER 1
-
uint64_t __read_mostly boot_count;
/* For fine-grained timekeeping, we use the ARM "Generic Timer", a
* register-mapped time source in the SoC. */
unsigned long __read_mostly cpu_khz; /* CPU clock frequency in kHz. */
-static struct dt_irq timer_irq[MAX_TIMER_PPI];
+static unsigned int timer_irq[MAX_TIMER_PPI];
-const struct dt_irq *timer_dt_irq(enum timer_ppi ppi)
+unsigned int timer_get_irq(enum timer_ppi ppi)
{
ASSERT(ppi >= TIMER_PHYS_SECURE_PPI && ppi < MAX_TIMER_PPI);
- return &timer_irq[ppi];
+ return timer_irq[ppi];
}
/*static inline*/ s_time_t ticks_to_ns(uint64_t ticks)
@@ -67,37 +61,6 @@ const struct dt_irq *timer_dt_irq(enum timer_ppi ppi)
return muldiv64(ns, 1000 * cpu_khz, SECONDS(1));
}
-/* TODO: On a real system the firmware would have set the frequency in
- the CNTFRQ register. Also we'd need to use devicetree to find
- the RTC. When we've seen some real systems, we can delete this.
-static uint32_t calibrate_timer(void)
-{
- uint32_t sec;
- uint64_t start, end;
- paddr_t rtc_base = 0x1C170000ull;
- volatile uint32_t *rtc;
-
- ASSERT(!local_irq_is_enabled());
- set_fixmap(FIXMAP_MISC, rtc_base >> PAGE_SHIFT, DEV_SHARED);
- rtc = (uint32_t *) FIXMAP_ADDR(FIXMAP_MISC);
-
- printk("Calibrating timer against RTC...");
- // Turn on the RTC
- rtc[3] = 1;
- // Wait for an edge
- sec = rtc[0] + 1;
- do {} while ( rtc[0] != sec );
- // Now time a few seconds
- start = READ_SYSREG64(CNTPCT_EL0);
- do {} while ( rtc[0] < sec + 32 );
- end = READ_SYSREG64(CNTPCT_EL0);
- printk("done.\n");
-
- clear_fixmap(FIXMAP_MISC);
- return (end - start) / 32;
-}
-*/
-
/* Set up the timer on the boot CPU */
int __init init_xen_time(void)
{
@@ -120,15 +83,17 @@ int __init init_xen_time(void)
/* Retrieve all IRQs for the timer */
for ( i = TIMER_PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++ )
{
- res = dt_device_get_irq(dev, i, &timer_irq[i]);
- if ( res )
+ res = platform_get_irq(dev, i);
+
+ if ( res < 0 )
panic("Timer: Unable to retrieve IRQ %u from the device tree", i);
+ timer_irq[i] = res;
}
printk("Generic Timer IRQ: phys=%u hyp=%u virt=%u\n",
- timer_irq[TIMER_PHYS_NONSECURE_PPI].irq,
- timer_irq[TIMER_HYP_PPI].irq,
- timer_irq[TIMER_VIRT_PPI].irq);
+ timer_irq[TIMER_PHYS_NONSECURE_PPI],
+ timer_irq[TIMER_HYP_PPI],
+ timer_irq[TIMER_VIRT_PPI]);
res = platform_init_time();
if ( res )
@@ -166,22 +131,13 @@ int reprogram_timer(s_time_t timeout)
if ( timeout == 0 )
{
-#if USE_HYP_TIMER
WRITE_SYSREG32(0, CNTHP_CTL_EL2);
-#else
- WRITE_SYSREG32(0, CNTP_CTL_EL0);
-#endif
return 1;
}
deadline = ns_to_ticks(timeout) + boot_count;
-#if USE_HYP_TIMER
WRITE_SYSREG64(deadline, CNTHP_CVAL_EL2);
WRITE_SYSREG32(CNTx_CTL_ENABLE, CNTHP_CTL_EL2);
-#else
- WRITE_SYSREG64(deadline, CNTP_CVAL_EL0);
- WRITE_SYSREG32(CNTx_CTL_ENABLE, CNTP_CTL_EL0);
-#endif
isb();
/* No need to check for timers in the past; the Generic Timer fires
@@ -192,7 +148,7 @@ int reprogram_timer(s_time_t timeout)
/* Handle the firing timer */
static void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
{
- if ( irq == (timer_irq[TIMER_HYP_PPI].irq) &&
+ if ( irq == (timer_irq[TIMER_HYP_PPI]) &&
READ_SYSREG32(CNTHP_CTL_EL2) & CNTx_CTL_PENDING )
{
/* Signal the generic timer code to do its work */
@@ -201,7 +157,7 @@ static void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
WRITE_SYSREG32(0, CNTHP_CTL_EL2);
}
- if ( irq == (timer_irq[TIMER_PHYS_NONSECURE_PPI].irq) &&
+ if ( irq == (timer_irq[TIMER_PHYS_NONSECURE_PPI]) &&
READ_SYSREG32(CNTP_CTL_EL0) & CNTx_CTL_PENDING )
{
/* Signal the generic timer code to do its work */
@@ -215,18 +171,7 @@ static void vtimer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
{
current->arch.virt_timer.ctl = READ_SYSREG32(CNTV_CTL_EL0);
WRITE_SYSREG32(current->arch.virt_timer.ctl | CNTx_CTL_MASK, CNTV_CTL_EL0);
- vgic_vcpu_inject_irq(current, current->arch.virt_timer.irq, 1);
-}
-
-/* Route timer's IRQ on this CPU */
-void __cpuinit route_timer_interrupt(void)
-{
- gic_route_dt_irq(&timer_irq[TIMER_PHYS_NONSECURE_PPI],
- cpumask_of(smp_processor_id()), 0xa0);
- gic_route_dt_irq(&timer_irq[TIMER_HYP_PPI],
- cpumask_of(smp_processor_id()), 0xa0);
- gic_route_dt_irq(&timer_irq[TIMER_VIRT_PPI],
- cpumask_of(smp_processor_id()), 0xa0);
+ vgic_vcpu_inject_irq(current, current->arch.virt_timer.irq);
}
/* Set up the timer interrupt on this CPU */
@@ -234,23 +179,18 @@ void __cpuinit init_timer_interrupt(void)
{
/* Sensible defaults */
WRITE_SYSREG64(0, CNTVOFF_EL2); /* No VM-specific offset */
-#if USE_HYP_TIMER
/* Do not let the VMs program the physical timer, only read the physical counter */
WRITE_SYSREG32(CNTHCTL_PA, CNTHCTL_EL2);
-#else
- /* Cannot let VMs access physical counter if we are using it */
- WRITE_SYSREG32(0, CNTHCTL_EL2);
-#endif
WRITE_SYSREG32(0, CNTP_CTL_EL0); /* Physical timer disabled */
WRITE_SYSREG32(0, CNTHP_CTL_EL2); /* Hypervisor's timer disabled */
isb();
- request_dt_irq(&timer_irq[TIMER_HYP_PPI], timer_interrupt,
- "hyptimer", NULL);
- request_dt_irq(&timer_irq[TIMER_VIRT_PPI], vtimer_interrupt,
+ request_irq(timer_irq[TIMER_HYP_PPI], 0, timer_interrupt,
+ "hyptimer", NULL);
+ request_irq(timer_irq[TIMER_VIRT_PPI], 0, vtimer_interrupt,
"virtimer", NULL);
- request_dt_irq(&timer_irq[TIMER_PHYS_NONSECURE_PPI], timer_interrupt,
- "phytimer", NULL);
+ request_irq(timer_irq[TIMER_PHYS_NONSECURE_PPI], 0, timer_interrupt,
+ "phytimer", NULL);
}
/* Wait a set number of microseconds */
@@ -259,7 +199,7 @@ void udelay(unsigned long usecs)
s_time_t deadline = get_s_time() + 1000 * (s_time_t) usecs;
while ( get_s_time() - deadline < 0 )
;
- dsb();
+ dsb(sy);
isb();
}
@@ -281,7 +221,7 @@ void domain_set_time_offset(struct domain *d, int32_t time_offset_seconds)
/* XXX update guest visible wallclock time */
}
-struct tm wallclock_time(void)
+struct tm wallclock_time(uint64_t *ns)
{
return (struct tm) { 0 };
}
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 4c910c8..4c93250 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -32,15 +32,18 @@
#include <xen/domain_page.h>
#include <public/sched.h>
#include <public/xen.h>
+#include <asm/debugger.h>
#include <asm/event.h>
#include <asm/regs.h>
#include <asm/cpregs.h>
#include <asm/psci.h>
+#include <asm/mmio.h>
+#include <asm/cpufeature.h>
#include "decode.h"
-#include "io.h"
#include "vtimer.h"
#include <asm/gic.h>
+#include <asm/vgic.h>
/* The base of the stack must always be double-word aligned, which means
* that both the kernel half of struct cpu_user_regs (which is pushed in
@@ -89,8 +92,8 @@ void __cpuinit init_traps(void)
CPTR_EL2);
/* Setup hypervisor traps */
- WRITE_SYSREG(HCR_PTW|HCR_BSU_OUTER|HCR_AMO|HCR_IMO|HCR_FMO|HCR_VM|
- HCR_TWI|HCR_TSC|HCR_TAC|HCR_SWIO|HCR_TIDCP, HCR_EL2);
+ WRITE_SYSREG(HCR_PTW|HCR_BSU_INNER|HCR_AMO|HCR_IMO|HCR_FMO|HCR_VM|
+ HCR_TWE|HCR_TWI|HCR_TSC|HCR_TAC|HCR_SWIO|HCR_TIDCP, HCR_EL2);
isb();
}
@@ -308,7 +311,7 @@ static void inject_undef32_exception(struct cpu_user_regs *regs)
/* Saved PC points to the instruction past the faulting instruction. */
uint32_t return_offset = is_thumb ? 2 : 4;
- BUG_ON( !is_pv32_domain(current->domain) );
+ BUG_ON( !is_32bit_domain(current->domain) );
/* Update processor mode */
cpsr_switch_mode(regs, PSR_MODE_UND);
@@ -336,7 +339,7 @@ static void inject_abt32_exception(struct cpu_user_regs *regs,
uint32_t return_offset = is_thumb ? 4 : 0;
register_t fsr;
- BUG_ON( !is_pv32_domain(current->domain) );
+ BUG_ON( !is_32bit_domain(current->domain) );
cpsr_switch_mode(regs, PSR_MODE_ABT);
@@ -425,7 +428,7 @@ static void inject_undef64_exception(struct cpu_user_regs *regs, int instr_len)
.ec = HSR_EC_UNKNOWN,
};
- BUG_ON( is_pv32_domain(current->domain) );
+ BUG_ON( is_32bit_domain(current->domain) );
handler = exception_handler64(regs, VECTOR64_SYNC_OFFSET);
@@ -465,7 +468,7 @@ static void inject_abt64_exception(struct cpu_user_regs *regs,
esr.ec = prefetch
? HSR_EC_INSTR_ABORT_CURR_EL : HSR_EC_DATA_ABORT_CURR_EL;
- BUG_ON( is_pv32_domain(current->domain) );
+ BUG_ON( is_32bit_domain(current->domain) );
handler = exception_handler64(regs, VECTOR64_SYNC_OFFSET);
@@ -499,7 +502,7 @@ static void inject_iabt64_exception(struct cpu_user_regs *regs,
static void inject_undef_exception(struct cpu_user_regs *regs,
int instr_len)
{
- if ( is_pv32_domain(current->domain) )
+ if ( is_32bit_domain(current->domain) )
inject_undef32_exception(regs);
#ifdef CONFIG_ARM_64
else
@@ -511,7 +514,7 @@ static void inject_iabt_exception(struct cpu_user_regs *regs,
register_t addr,
int instr_len)
{
- if ( is_pv32_domain(current->domain) )
+ if ( is_32bit_domain(current->domain) )
inject_pabt32_exception(regs, addr);
#ifdef CONFIG_ARM_64
else
@@ -523,7 +526,7 @@ static void inject_dabt_exception(struct cpu_user_regs *regs,
register_t addr,
int instr_len)
{
- if ( is_pv32_domain(current->domain) )
+ if ( is_32bit_domain(current->domain) )
inject_dabt32_exception(regs, addr);
#ifdef CONFIG_ARM_64
else
@@ -728,10 +731,10 @@ static void _show_registers(struct cpu_user_regs *regs,
if ( guest_mode )
{
- if ( is_pv32_domain(v->domain) )
+ if ( is_32bit_domain(v->domain) )
show_registers_32(regs, ctxt, guest_mode, v);
#ifdef CONFIG_ARM_64
- else if ( is_pv64_domain(v->domain) )
+ else if ( is_64bit_domain(v->domain) )
{
if ( psr_mode_is_32bit(regs->cpsr) )
{
@@ -788,7 +791,8 @@ void show_registers(struct cpu_user_regs *regs)
#else
ctxt.far = READ_SYSREG(FAR_EL1);
ctxt.esr_el1 = READ_SYSREG(ESR_EL1);
- ctxt.ifsr32_el2 = READ_SYSREG(IFSR32_EL2);
+ if ( guest_mode(regs) && is_32bit_domain(current->domain) )
+ ctxt.ifsr32_el2 = READ_SYSREG(IFSR32_EL2);
#endif
ctxt.vttbr_el2 = READ_SYSREG64(VTTBR_EL2);
@@ -888,7 +892,7 @@ static void show_guest_stack(struct vcpu *v, struct cpu_user_regs *regs)
return;
}
- page = get_page_from_gva(current->domain, sp, GV2M_READ);
+ page = get_page_from_gva(v->domain, sp, GV2M_READ);
if ( page == NULL )
{
printk("Failed to convert stack to physical address\n");
@@ -1047,6 +1051,102 @@ void do_unexpected_trap(const char *msg, struct cpu_user_regs *regs)
panic("CPU%d: Unexpected Trap: %s\n", smp_processor_id(), msg);
}
+int do_bug_frame(struct cpu_user_regs *regs, vaddr_t pc)
+{
+ const struct bug_frame *bug;
+ const char *prefix = "", *filename, *predicate;
+ unsigned long fixup;
+ int id, lineno;
+ static const struct bug_frame *const stop_frames[] = {
+ __stop_bug_frames_0,
+ __stop_bug_frames_1,
+ __stop_bug_frames_2,
+ NULL
+ };
+
+ for ( bug = __start_bug_frames, id = 0; stop_frames[id]; ++bug )
+ {
+ while ( unlikely(bug == stop_frames[id]) )
+ ++id;
+
+ if ( ((vaddr_t)bug_loc(bug)) == pc )
+ break;
+ }
+
+ if ( !stop_frames[id] )
+ return -ENOENT;
+
+ /* WARN, BUG or ASSERT: decode the filename pointer and line number. */
+ filename = bug_file(bug);
+ if ( !is_kernel(filename) )
+ return -EINVAL;
+ fixup = strlen(filename);
+ if ( fixup > 50 )
+ {
+ filename += fixup - 47;
+ prefix = "...";
+ }
+ lineno = bug_line(bug);
+
+ switch ( id )
+ {
+ case BUGFRAME_warn:
+ printk("Xen WARN at %s%s:%d\n", prefix, filename, lineno);
+ show_execution_state(regs);
+ return 0;
+
+ case BUGFRAME_bug:
+ printk("Xen BUG at %s%s:%d\n", prefix, filename, lineno);
+
+ if ( debugger_trap_fatal(TRAP_invalid_op, regs) )
+ return 0;
+
+ show_execution_state(regs);
+ panic("Xen BUG at %s%s:%d", prefix, filename, lineno);
+
+ case BUGFRAME_assert:
+ /* ASSERT: decode the predicate string pointer. */
+ predicate = bug_msg(bug);
+ if ( !is_kernel(predicate) )
+ predicate = "<unknown>";
+
+ printk("Assertion '%s' failed at %s%s:%d\n",
+ predicate, prefix, filename, lineno);
+ if ( debugger_trap_fatal(TRAP_invalid_op, regs) )
+ return 0;
+ show_execution_state(regs);
+ panic("Assertion '%s' failed at %s%s:%d",
+ predicate, prefix, filename, lineno);
+ }
+
+ return -EINVAL;
+}
+
+#ifdef CONFIG_ARM_64
+static void do_trap_brk(struct cpu_user_regs *regs, union hsr hsr)
+{
+ /* HCR_EL2.TGE and MDCR_EL2.TDE are not set so we never receive
+ * software breakpoint exception for EL1 and EL0 here.
+ */
+ BUG_ON(!hyp_mode(regs));
+
+ switch (hsr.brk.comment)
+ {
+ case BRK_BUG_FRAME:
+ if ( do_bug_frame(regs, regs->pc) )
+ goto die;
+
+ regs->pc += 4;
+
+ break;
+
+ default:
+die:
+ do_unexpected_trap("Undefined Breakpoint Value", regs);
+ }
+}
+#endif
+
typedef register_t (*arm_hypercall_fn_t)(
register_t, register_t, register_t, register_t, register_t);
@@ -1072,6 +1172,7 @@ static arm_hypercall_t arm_hypercall_table[] = {
HYPERCALL(sched_op, 2),
HYPERCALL(console_io, 3),
HYPERCALL(xen_version, 2),
+ HYPERCALL(xsm_op, 1),
HYPERCALL(event_channel_op, 2),
HYPERCALL(physdev_op, 2),
HYPERCALL(sysctl, 2),
@@ -1081,24 +1182,6 @@ static arm_hypercall_t arm_hypercall_table[] = {
HYPERCALL_ARM(vcpu_op, 3),
};
-typedef int (*arm_psci_fn_t)(uint32_t, register_t);
-
-typedef struct {
- arm_psci_fn_t fn;
- int nr_args;
-} arm_psci_t;
-
-#define PSCI(_name, _nr_args) \
- [ PSCI_ ## _name ] = { \
- .fn = (arm_psci_fn_t) &do_psci_ ## _name, \
- .nr_args = _nr_args, \
- }
-
-static arm_psci_t arm_psci_table[] = {
- PSCI(cpu_off, 1),
- PSCI(cpu_on, 2),
-};
-
#ifndef NDEBUG
static void do_debug_trap(struct cpu_user_regs *regs, unsigned int code)
{
@@ -1131,33 +1214,108 @@ static void do_debug_trap(struct cpu_user_regs *regs, unsigned int code)
#endif
#ifdef CONFIG_ARM_64
-#define PSCI_OP_REG(r) (r)->x0
-#define PSCI_RESULT_REG(r) (r)->x0
-#define PSCI_ARGS(r) (r)->x1, (r)->x2
+#define PSCI_RESULT_REG(reg) (reg)->x0
+#define PSCI_ARG(reg,n) (reg)->x##n
+#define PSCI_ARG32(reg,n) (uint32_t)( (reg)->x##n & 0x00000000FFFFFFFF )
#else
-#define PSCI_OP_REG(r) (r)->r0
-#define PSCI_RESULT_REG(r) (r)->r0
-#define PSCI_ARGS(r) (r)->r1, (r)->r2
+#define PSCI_RESULT_REG(reg) (reg)->r0
+#define PSCI_ARG(reg,n) (reg)->r##n
+#define PSCI_ARG32(reg,n) PSCI_ARG(reg,n)
#endif
-static void do_trap_psci(struct cpu_user_regs *regs)
+/* helper function for checking arm mode 32/64 bit */
+static inline int psci_mode_check(struct domain *d, register_t fid)
{
- arm_psci_fn_t psci_call = NULL;
+ return !( is_64bit_domain(d)^( (fid & PSCI_0_2_64BIT) >> 30 ) );
+}
- if ( PSCI_OP_REG(regs) >= ARRAY_SIZE(arm_psci_table) )
- {
- domain_crash_synchronous();
- return;
- }
+static void do_trap_psci(struct cpu_user_regs *regs)
+{
+ register_t fid = PSCI_ARG(regs,0);
- psci_call = arm_psci_table[PSCI_OP_REG(regs)].fn;
- if ( psci_call == NULL )
+ /* preloading in case psci_mode_check fails */
+ PSCI_RESULT_REG(regs) = PSCI_INVALID_PARAMETERS;
+ switch( fid )
{
+ case PSCI_cpu_off:
+ {
+ uint32_t pstate = PSCI_ARG32(regs,1);
+ PSCI_RESULT_REG(regs) = do_psci_cpu_off(pstate);
+ }
+ break;
+ case PSCI_cpu_on:
+ {
+ uint32_t vcpuid = PSCI_ARG32(regs,1);
+ register_t epoint = PSCI_ARG(regs,2);
+ PSCI_RESULT_REG(regs) = do_psci_cpu_on(vcpuid, epoint);
+ }
+ break;
+ case PSCI_0_2_FN_PSCI_VERSION:
+ PSCI_RESULT_REG(regs) = do_psci_0_2_version();
+ break;
+ case PSCI_0_2_FN_CPU_OFF:
+ PSCI_RESULT_REG(regs) = do_psci_0_2_cpu_off();
+ break;
+ case PSCI_0_2_FN_MIGRATE_INFO_TYPE:
+ PSCI_RESULT_REG(regs) = do_psci_0_2_migrate_info_type();
+ break;
+ case PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
+ case PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
+ if ( psci_mode_check(current->domain, fid) )
+ PSCI_RESULT_REG(regs) = do_psci_0_2_migrate_info_up_cpu();
+ break;
+ case PSCI_0_2_FN_SYSTEM_OFF:
+ do_psci_0_2_system_off();
+ PSCI_RESULT_REG(regs) = PSCI_INTERNAL_FAILURE;
+ break;
+ case PSCI_0_2_FN_SYSTEM_RESET:
+ do_psci_0_2_system_reset();
+ PSCI_RESULT_REG(regs) = PSCI_INTERNAL_FAILURE;
+ break;
+ case PSCI_0_2_FN_CPU_ON:
+ case PSCI_0_2_FN64_CPU_ON:
+ if ( psci_mode_check(current->domain, fid) )
+ {
+ register_t vcpuid = PSCI_ARG(regs,1);
+ register_t epoint = PSCI_ARG(regs,2);
+ register_t cid = PSCI_ARG(regs,3);
+ PSCI_RESULT_REG(regs) =
+ do_psci_0_2_cpu_on(vcpuid, epoint, cid);
+ }
+ break;
+ case PSCI_0_2_FN_CPU_SUSPEND:
+ case PSCI_0_2_FN64_CPU_SUSPEND:
+ if ( psci_mode_check(current->domain, fid) )
+ {
+ uint32_t pstate = PSCI_ARG32(regs,1);
+ register_t epoint = PSCI_ARG(regs,2);
+ register_t cid = PSCI_ARG(regs,3);
+ PSCI_RESULT_REG(regs) =
+ do_psci_0_2_cpu_suspend(pstate, epoint, cid);
+ }
+ break;
+ case PSCI_0_2_FN_AFFINITY_INFO:
+ case PSCI_0_2_FN64_AFFINITY_INFO:
+ if ( psci_mode_check(current->domain, fid) )
+ {
+ register_t taff = PSCI_ARG(regs,1);
+ uint32_t laff = PSCI_ARG32(regs,2);
+ PSCI_RESULT_REG(regs) =
+ do_psci_0_2_affinity_info(taff, laff);
+ }
+ break;
+ case PSCI_0_2_FN_MIGRATE:
+ case PSCI_0_2_FN64_MIGRATE:
+ if ( psci_mode_check(current->domain, fid) )
+ {
+ uint32_t tcpu = PSCI_ARG32(regs,1);
+ PSCI_RESULT_REG(regs) = do_psci_0_2_migrate(tcpu);
+ }
+ break;
+ default:
domain_crash_synchronous();
return;
}
-
- PSCI_RESULT_REG(regs) = psci_call(PSCI_ARGS(regs));
}
#ifdef CONFIG_ARM_64
@@ -1260,7 +1418,7 @@ void do_multicall_call(struct multicall_entry *multi)
return;
}
- if ( is_pv32_domain(current->domain) &&
+ if ( is_32bit_domain(current->domain) &&
!check_multicall_32bit_clean(multi) )
return;
@@ -1319,7 +1477,7 @@ static int check_conditional_instr(struct cpu_user_regs *regs, union hsr hsr)
{
unsigned long it;
- BUG_ON( !is_pv32_domain(current->domain) || !(cpsr&PSR_THUMB) );
+ BUG_ON( !is_32bit_domain(current->domain) || !(cpsr&PSR_THUMB) );
it = ( (cpsr >> (10-2)) & 0xfc) | ((cpsr >> 25) & 0x3 );
@@ -1344,10 +1502,10 @@ static void advance_pc(struct cpu_user_regs *regs, union hsr hsr)
unsigned long itbits, cond, cpsr = regs->cpsr;
/* PSR_IT_MASK bits can only be set for 32-bit processors in Thumb mode. */
- BUG_ON( (!is_pv32_domain(current->domain)||!(cpsr&PSR_THUMB))
+ BUG_ON( (!is_32bit_domain(current->domain)||!(cpsr&PSR_THUMB))
&& (cpsr&PSR_IT_MASK) );
- if ( is_pv32_domain(current->domain) && (cpsr&PSR_IT_MASK) )
+ if ( is_32bit_domain(current->domain) && (cpsr&PSR_IT_MASK) )
{
/* The ITSTATE[7:0] block is contained in CPSR[15:10],CPSR[26:25]
*
@@ -1590,23 +1748,43 @@ bad_cp:
static void do_cp14_dbg(struct cpu_user_regs *regs, union hsr hsr)
{
+#ifndef NDEBUG
+ struct hsr_cp64 cp64 = hsr.cp64;
+#endif
+
if ( !check_conditional_instr(regs, hsr) )
{
advance_pc(regs, hsr);
return;
}
+#ifndef NDEBUG
+ gdprintk(XENLOG_ERR,
+ "%s p14, %d, r%d, r%d, cr%d @ 0x%"PRIregister"\n",
+ cp64.read ? "mrrc" : "mcrr",
+ cp64.op1, cp64.reg1, cp64.reg2, cp64.crm, regs->pc);
+ gdprintk(XENLOG_ERR, "unhandled 64-bit CP14 access %#x\n",
+ hsr.bits & HSR_CP64_REGS_MASK);
+#endif
inject_undef_exception(regs, hsr.len);
}
static void do_cp(struct cpu_user_regs *regs, union hsr hsr)
{
+#ifndef NDEBUG
+ struct hsr_cp cp = hsr.cp;
+#endif
+
if ( !check_conditional_instr(regs, hsr) )
{
advance_pc(regs, hsr);
return;
}
+#ifndef NDEBUG
+ ASSERT(!cp.tas); /* We don't trap SIMD instruction */
+ gdprintk(XENLOG_ERR, "unhandled CP%d access\n", cp.coproc);
+#endif
inject_undef_exception(regs, hsr.len);
}
@@ -1665,6 +1843,20 @@ static void do_sysreg(struct cpu_user_regs *regs,
domain_crash_synchronous();
}
break;
+ case HSR_SYSREG_ICC_SGI1R_EL1:
+ if ( !vgic_emulate(regs, hsr) )
+ {
+ dprintk(XENLOG_WARNING,
+ "failed emulation of sysreg ICC_SGI1R_EL1 access\n");
+ inject_undef64_exception(regs, hsr.len);
+ }
+ break;
+ case HSR_SYSREG_ICC_SGI0R_EL1:
+ case HSR_SYSREG_ICC_ASGI1R_EL1:
+ /* TBD: Implement to support secure grp0/1 SGI forwarding */
+ dprintk(XENLOG_WARNING,
+ "Emulation of sysreg ICC_SGI0R_EL1/ASGI1R_EL1 not supported\n");
+ inject_undef64_exception(regs, hsr.len);
default:
bad_sysreg:
{
@@ -1809,16 +2001,25 @@ bad_data_abort:
inject_dabt_exception(regs, info.gva, hsr.len);
}
+static void enter_hypervisor_head(struct cpu_user_regs *regs)
+{
+ if ( guest_mode(regs) )
+ gic_clear_lrs(current);
+}
+
asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
{
union hsr hsr = { .bits = READ_SYSREG32(ESR_EL2) };
+ enter_hypervisor_head(regs);
+
/*
* We currently do not handle 32-bit userspace on 64-bit kernels
* correctly (See XSA-102). Until that is resolved we treat any
* trap from 32-bit userspace on 64-bit kernel as undefined.
*/
- if ( is_pv64_domain(current->domain) && psr_mode_is_32bit(regs->cpsr) )
+ if ( !hyp_mode(regs) && is_64bit_domain(current->domain) &&
+ psr_mode_is_32bit(regs->cpsr) )
{
inject_undef_exception(regs, hsr.len);
return;
@@ -1831,40 +2032,37 @@ asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
advance_pc(regs, hsr);
return;
}
- /* at the moment we only trap WFI */
- vcpu_block();
- /* The ARM spec declares that even if local irqs are masked in
- * the CPSR register, an irq should wake up a cpu from WFI anyway.
- * For this reason we need to check for irqs that need delivery,
- * ignoring the CPSR register, *after* calling SCHEDOP_block to
- * avoid races with vgic_vcpu_inject_irq.
- */
- if ( local_events_need_delivery_nomask() )
- vcpu_unblock(current);
+ if ( hsr.wfi_wfe.ti ) {
+ /* Yield the VCPU for WFE */
+ vcpu_yield();
+ } else {
+ /* Block the VCPU for WFI */
+ vcpu_block_unless_event_pending(current);
+ }
advance_pc(regs, hsr);
break;
case HSR_EC_CP15_32:
- if ( ! is_pv32_domain(current->domain) )
+ if ( !is_32bit_domain(current->domain) )
goto bad_trap;
do_cp15_32(regs, hsr);
break;
case HSR_EC_CP15_64:
- if ( ! is_pv32_domain(current->domain) )
+ if ( !is_32bit_domain(current->domain) )
goto bad_trap;
do_cp15_64(regs, hsr);
break;
case HSR_EC_CP14_32:
- if ( !is_pv32_domain(current->domain) )
+ if ( !is_32bit_domain(current->domain) )
goto bad_trap;
do_cp14_32(regs, hsr);
break;
case HSR_EC_CP14_DBG:
- if ( !is_pv32_domain(current->domain) )
+ if ( !is_32bit_domain(current->domain) )
goto bad_trap;
do_cp14_dbg(regs, hsr);
break;
case HSR_EC_CP:
- if ( !is_pv32_domain(current->domain) )
+ if ( !is_32bit_domain(current->domain) )
goto bad_trap;
do_cp(regs, hsr);
break;
@@ -1894,7 +2092,7 @@ asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
inject_undef64_exception(regs, hsr.len);
break;
case HSR_EC_SYSREG:
- if ( is_pv32_domain(current->domain) )
+ if ( is_32bit_domain(current->domain) )
goto bad_trap;
do_sysreg(regs, hsr);
break;
@@ -1906,9 +2104,16 @@ asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
case HSR_EC_DATA_ABORT_LOWER_EL:
do_trap_data_abort_guest(regs, hsr);
break;
+
+#ifdef CONFIG_ARM_64
+ case HSR_EC_BRK:
+ do_trap_brk(regs, hsr);
+ break;
+#endif
+
default:
bad_trap:
- printk("Hypervisor Trap. HSR=0x%x EC=0x%x IL=%x Syndrome=%"PRIx32"\n",
+ printk("Hypervisor Trap. HSR=0x%x EC=0x%x IL=%x Syndrome=0x%"PRIx32"\n",
hsr.bits, hsr.ec, hsr.len, hsr.iss);
do_unexpected_trap("Hypervisor", regs);
}
@@ -1916,11 +2121,13 @@ asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
asmlinkage void do_trap_irq(struct cpu_user_regs *regs)
{
+ enter_hypervisor_head(regs);
gic_interrupt(regs, 0);
}
asmlinkage void do_trap_fiq(struct cpu_user_regs *regs)
{
+ enter_hypervisor_head(regs);
gic_interrupt(regs, 1);
}
diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
new file mode 100644
index 0000000..1369f78
--- /dev/null
+++ b/xen/arch/arm/vgic-v2.c
@@ -0,0 +1,589 @@
+/*
+ * xen/arch/arm/vgic-v2.c
+ *
+ * ARM Virtual Generic Interrupt Controller support v2
+ *
+ * Ian Campbell <ian.campbell at citrix.com>
+ * Copyright (c) 2011 Citrix Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <xen/bitops.h>
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/init.h>
+#include <xen/softirq.h>
+#include <xen/irq.h>
+#include <xen/sched.h>
+
+#include <asm/current.h>
+#include <asm/device.h>
+
+#include <asm/mmio.h>
+#include <asm/gic.h>
+#include <asm/vgic.h>
+
+static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
+{
+ struct hsr_dabt dabt = info->dabt;
+ struct cpu_user_regs *regs = guest_cpu_user_regs();
+ register_t *r = select_user_reg(regs, dabt.reg);
+ struct vgic_irq_rank *rank;
+ int gicd_reg = (int)(info->gpa - v->domain->arch.vgic.dbase);
+ unsigned long flags;
+
+ switch ( gicd_reg )
+ {
+ case GICD_CTLR:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ vgic_lock(v);
+ *r = v->domain->arch.vgic.ctlr;
+ vgic_unlock(v);
+ return 1;
+ case GICD_TYPER:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ /* No secure world support for guests. */
+ vgic_lock(v);
+ *r = ( (v->domain->max_vcpus << 5) & GICD_TYPE_CPUS )
+ |( ((v->domain->arch.vgic.nr_lines / 32)) & GICD_TYPE_LINES );
+ vgic_unlock(v);
+ return 1;
+ case GICD_IIDR:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ /*
+ * XXX Do we need a JEP106 manufacturer ID?
+ * Just use the physical h/w value for now
+ */
+ *r = 0x0000043b;
+ return 1;
+
+ /* Implementation defined -- read as zero */
+ case 0x020 ... 0x03c:
+ goto read_as_zero;
+
+ case GICD_IGROUPR ... GICD_IGROUPRN:
+ /* We do not implement security extensions for guests, read zero */
+ goto read_as_zero;
+
+ case GICD_ISENABLER ... GICD_ISENABLERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER, DABT_WORD);
+ if ( rank == NULL) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = rank->ienable;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_ICENABLER ... GICD_ICENABLERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER, DABT_WORD);
+ if ( rank == NULL) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = rank->ienable;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_ISPENDR ... GICD_ISPENDRN:
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISPENDR, DABT_WORD);
+ if ( rank == NULL) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = vgic_byte_read(rank->ipend, dabt.sign, gicd_reg);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_ICPENDR ... GICD_ICPENDRN:
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICPENDR, DABT_WORD);
+ if ( rank == NULL) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = vgic_byte_read(rank->ipend, dabt.sign, gicd_reg);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_ISACTIVER ... GICD_ISACTIVERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISACTIVER, DABT_WORD);
+ if ( rank == NULL) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = rank->iactive;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_ICACTIVER ... GICD_ICACTIVERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICACTIVER, DABT_WORD);
+ if ( rank == NULL) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = rank->iactive;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_ITARGETSR ... GICD_ITARGETSRN:
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 8, gicd_reg - GICD_ITARGETSR, DABT_WORD);
+ if ( rank == NULL) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = rank->v2.itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR,
+ DABT_WORD)];
+ if ( dabt.size == DABT_BYTE )
+ *r = vgic_byte_read(*r, dabt.sign, gicd_reg);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR, DABT_WORD);
+ if ( rank == NULL) goto read_as_zero;
+
+ vgic_lock_rank(v, rank, flags);
+ *r = rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR,
+ DABT_WORD)];
+ if ( dabt.size == DABT_BYTE )
+ *r = vgic_byte_read(*r, dabt.sign, gicd_reg);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_ICFGR ... GICD_ICFGRN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 2, gicd_reg - GICD_ICFGR, DABT_WORD);
+ if ( rank == NULL) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR, DABT_WORD)];
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_NSACR ... GICD_NSACRN:
+ /* We do not implement security extensions for guests, read zero */
+ goto read_as_zero;
+
+ case GICD_SGIR:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ /* Write only -- read unknown */
+ *r = 0xdeadbeef;
+ return 1;
+
+ case GICD_CPENDSGIR ... GICD_CPENDSGIRN:
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicd_reg - GICD_CPENDSGIR, DABT_WORD);
+ if ( rank == NULL) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = vgic_byte_read(rank->pendsgi, dabt.sign, gicd_reg);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_SPENDSGIR ... GICD_SPENDSGIRN:
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicd_reg - GICD_SPENDSGIR, DABT_WORD);
+ if ( rank == NULL) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = vgic_byte_read(rank->pendsgi, dabt.sign, gicd_reg);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ /* Implementation defined -- read as zero */
+ case 0xfd0 ... 0xfe4:
+ goto read_as_zero;
+
+ case GICD_ICPIDR2:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ printk("vGICD: unhandled read from ICPIDR2\n");
+ return 0;
+
+ /* Implementation defined -- read as zero */
+ case 0xfec ... 0xffc:
+ goto read_as_zero;
+
+ /* Reserved -- read as zero */
+ case 0x00c ... 0x01c:
+ case 0x040 ... 0x07c:
+ case 0x7fc:
+ case 0xbfc:
+ case 0xf04 ... 0xf0c:
+ case 0xf30 ... 0xfcc:
+ goto read_as_zero;
+
+ default:
+ printk("vGICD: unhandled read r%d offset %#08x\n",
+ dabt.reg, gicd_reg);
+ return 0;
+ }
+
+bad_width:
+ printk("vGICD: bad read width %d r%d offset %#08x\n",
+ dabt.size, dabt.reg, gicd_reg);
+ domain_crash_synchronous();
+ return 0;
+
+read_as_zero:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ *r = 0;
+ return 1;
+}
+
+static int vgic_v2_to_sgi(struct vcpu *v, register_t sgir)
+{
+
+ int virq;
+ int irqmode;
+ enum gic_sgi_mode sgi_mode;
+ unsigned long vcpu_mask = 0;
+
+ irqmode = (sgir & GICD_SGI_TARGET_LIST_MASK) >> GICD_SGI_TARGET_LIST_SHIFT;
+ virq = (sgir & GICD_SGI_INTID_MASK);
+ vcpu_mask = (sgir & GICD_SGI_TARGET_MASK) >> GICD_SGI_TARGET_SHIFT;
+
+ /* Map GIC sgi value to enum value */
+ switch ( irqmode )
+ {
+ case GICD_SGI_TARGET_LIST_VAL:
+ sgi_mode = SGI_TARGET_LIST;
+ break;
+ case GICD_SGI_TARGET_OTHERS_VAL:
+ sgi_mode = SGI_TARGET_OTHERS;
+ break;
+ case GICD_SGI_TARGET_SELF_VAL:
+ sgi_mode = SGI_TARGET_SELF;
+ break;
+ default:
+ BUG();
+ }
+
+ return vgic_to_sgi(v, sgir, sgi_mode, virq, vcpu_mask);
+}
+
+static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
+{
+ struct hsr_dabt dabt = info->dabt;
+ struct cpu_user_regs *regs = guest_cpu_user_regs();
+ register_t *r = select_user_reg(regs, dabt.reg);
+ struct vgic_irq_rank *rank;
+ int gicd_reg = (int)(info->gpa - v->domain->arch.vgic.dbase);
+ uint32_t tr;
+ unsigned long flags;
+
+ switch ( gicd_reg )
+ {
+ case GICD_CTLR:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ /* Ignore all but the enable bit */
+ v->domain->arch.vgic.ctlr = (*r) & GICD_CTL_ENABLE;
+ return 1;
+
+ /* R/O -- write ignored */
+ case GICD_TYPER:
+ case GICD_IIDR:
+ goto write_ignore;
+
+ /* Implementation defined -- write ignored */
+ case 0x020 ... 0x03c:
+ goto write_ignore;
+
+ case GICD_IGROUPR ... GICD_IGROUPRN:
+ /* We do not implement security extensions for guests, write ignore */
+ goto write_ignore;
+
+ case GICD_ISENABLER ... GICD_ISENABLERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER, DABT_WORD);
+ if ( rank == NULL) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ tr = rank->ienable;
+ rank->ienable |= *r;
+ /* The virtual irq is derived from register offset.
+ * The register difference is word difference. So divide by 2(DABT_WORD)
+ * to get Virtual irq number */
+ vgic_enable_irqs(v, (*r) & (~tr),
+ (gicd_reg - GICD_ISENABLER) >> DABT_WORD);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_ICENABLER ... GICD_ICENABLERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER, DABT_WORD);
+ if ( rank == NULL) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ tr = rank->ienable;
+ rank->ienable &= ~*r;
+ /* The virtual irq is derived from register offset.
+ * The register difference is word difference. So divide by 2(DABT_WORD)
+ * to get Virtual irq number */
+ vgic_disable_irqs(v, (*r) & tr,
+ (gicd_reg - GICD_ICENABLER) >> DABT_WORD);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_ISPENDR ... GICD_ISPENDRN:
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ printk("vGICD: unhandled %s write %#"PRIregister" to ISPENDR%d\n",
+ dabt.size ? "word" : "byte", *r, gicd_reg - GICD_ISPENDR);
+ return 0;
+
+ case GICD_ICPENDR ... GICD_ICPENDRN:
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ printk("vGICD: unhandled %s write %#"PRIregister" to ICPENDR%d\n",
+ dabt.size ? "word" : "byte", *r, gicd_reg - GICD_ICPENDR);
+ return 0;
+
+ case GICD_ISACTIVER ... GICD_ISACTIVERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISACTIVER, DABT_WORD);
+ if ( rank == NULL) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ rank->iactive &= ~*r;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_ICACTIVER ... GICD_ICACTIVERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICACTIVER, DABT_WORD);
+ if ( rank == NULL) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ rank->iactive &= ~*r;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_ITARGETSR ... GICD_ITARGETSR + 7:
+ /* SGI/PPI target is read only */
+ goto write_ignore;
+
+ case GICD_ITARGETSR + 8 ... GICD_ITARGETSRN:
+ {
+ /* unsigned long needed for find_next_bit */
+ unsigned long target;
+ int i;
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 8, gicd_reg - GICD_ITARGETSR, DABT_WORD);
+ if ( rank == NULL) goto write_ignore;
+ /* 8-bit vcpu mask for this domain */
+ BUG_ON(v->domain->max_vcpus > 8);
+ target = (1 << v->domain->max_vcpus) - 1;
+ if ( dabt.size == 2 )
+ target = target | (target << 8) | (target << 16) | (target << 24);
+ else
+ target = (target << (8 * (gicd_reg & 0x3)));
+ target &= *r;
+ /* ignore zero writes */
+ if ( !target )
+ goto write_ignore;
+ /* For word reads ignore writes where any single byte is zero */
+ if ( dabt.size == 2 &&
+ !((target & 0xff) && (target & (0xff << 8)) &&
+ (target & (0xff << 16)) && (target & (0xff << 24))))
+ goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ i = 0;
+ while ( (i = find_next_bit(&target, 32, i)) < 32 )
+ {
+ unsigned int irq, new_target, old_target;
+ unsigned long old_target_mask;
+ struct vcpu *v_target, *v_old;
+
+ new_target = i % 8;
+ old_target_mask = vgic_byte_read(rank->v2.itargets[REG_RANK_INDEX(8,
+ gicd_reg - GICD_ITARGETSR, DABT_WORD)], 0, i/8);
+ old_target = find_first_bit(&old_target_mask, 8);
+
+ if ( new_target != old_target )
+ {
+ irq = gicd_reg - GICD_ITARGETSR + (i / 8);
+ v_target = v->domain->vcpu[new_target];
+ v_old = v->domain->vcpu[old_target];
+ vgic_migrate_irq(v_old, v_target, irq);
+ }
+ i += 8 - new_target;
+ }
+ if ( dabt.size == DABT_WORD )
+ rank->v2.itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR,
+ DABT_WORD)] = target;
+ else
+ vgic_byte_write(&rank->v2.itargets[REG_RANK_INDEX(8,
+ gicd_reg - GICD_ITARGETSR, DABT_WORD)], target, gicd_reg);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ }
+
+ case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR, DABT_WORD);
+ if ( rank == NULL) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ if ( dabt.size == DABT_WORD )
+ rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR,
+ DABT_WORD)] = *r;
+ else
+ vgic_byte_write(&rank->ipriority[REG_RANK_INDEX(8,
+ gicd_reg - GICD_IPRIORITYR, DABT_WORD)], *r, gicd_reg);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_ICFGR: /* SGIs */
+ goto write_ignore;
+ case GICD_ICFGR + 1: /* PPIs */
+ /* It is implementation defined if these are writeable. We chose not */
+ goto write_ignore;
+ case GICD_ICFGR + 2 ... GICD_ICFGRN: /* SPIs */
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 2, gicd_reg - GICD_ICFGR, DABT_WORD);
+ if ( rank == NULL) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR, DABT_WORD)] = *r;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+
+ case GICD_NSACR ... GICD_NSACRN:
+ /* We do not implement security extensions for guests, write ignore */
+ goto write_ignore;
+
+ case GICD_SGIR:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ return vgic_v2_to_sgi(v, *r);
+
+ case GICD_CPENDSGIR ... GICD_CPENDSGIRN:
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ printk("vGICD: unhandled %s write %#"PRIregister" to ICPENDSGIR%d\n",
+ dabt.size ? "word" : "byte", *r, gicd_reg - GICD_CPENDSGIR);
+ return 0;
+
+ case GICD_SPENDSGIR ... GICD_SPENDSGIRN:
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ printk("vGICD: unhandled %s write %#"PRIregister" to ISPENDSGIR%d\n",
+ dabt.size ? "word" : "byte", *r, gicd_reg - GICD_SPENDSGIR);
+ return 0;
+
+ /* Implementation defined -- write ignored */
+ case 0xfd0 ... 0xfe4:
+ goto write_ignore;
+
+ /* R/O -- write ignore */
+ case GICD_ICPIDR2:
+ goto write_ignore;
+
+ /* Implementation defined -- write ignored */
+ case 0xfec ... 0xffc:
+ goto write_ignore;
+
+ /* Reserved -- write ignored */
+ case 0x00c ... 0x01c:
+ case 0x040 ... 0x07c:
+ case 0x7fc:
+ case 0xbfc:
+ case 0xf04 ... 0xf0c:
+ case 0xf30 ... 0xfcc:
+ goto write_ignore;
+
+ default:
+ printk("vGICD: unhandled write r%d=%"PRIregister" offset %#08x\n",
+ dabt.reg, *r, gicd_reg);
+ return 0;
+ }
+
+bad_width:
+ printk("vGICD: bad write width %d r%d=%"PRIregister" offset %#08x\n",
+ dabt.size, dabt.reg, *r, gicd_reg);
+ domain_crash_synchronous();
+ return 0;
+
+write_ignore:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ return 1;
+}
+
+static const struct mmio_handler_ops vgic_v2_distr_mmio_handler = {
+ .read_handler = vgic_v2_distr_mmio_read,
+ .write_handler = vgic_v2_distr_mmio_write,
+};
+
+static struct vcpu *vgic_v2_get_target_vcpu(struct vcpu *v, unsigned int irq)
+{
+ unsigned long target;
+ struct vcpu *v_target;
+ struct vgic_irq_rank *rank = vgic_rank_irq(v, irq);
+ ASSERT(spin_is_locked(&rank->lock));
+
+ target = vgic_byte_read(rank->v2.itargets[REG_RANK_INDEX(8,
+ irq, DABT_WORD)], 0, irq & 0x3);
+
+ /* 1-N SPI should be delivered as pending to all the vcpus in the
+ * mask, but here we just return the first vcpu for simplicity and
+ * because it would be too slow to do otherwise. */
+ target = find_first_bit(&target, 8);
+ ASSERT(target >= 0 && target < v->domain->max_vcpus);
+ v_target = v->domain->vcpu[target];
+ return v_target;
+}
+
+static int vgic_v2_get_irq_priority(struct vcpu *v, unsigned int irq)
+{
+ int priority;
+ struct vgic_irq_rank *rank = vgic_rank_irq(v, irq);
+
+ ASSERT(spin_is_locked(&rank->lock));
+ priority = vgic_byte_read(rank->ipriority[REG_RANK_INDEX(8,
+ irq, DABT_WORD)], 0, irq & 0x3);
+
+ return priority;
+}
+
+static int vgic_v2_vcpu_init(struct vcpu *v)
+{
+ int i;
+
+ /* For SGI and PPI the target is always this CPU */
+ for ( i = 0 ; i < 8 ; i++ )
+ v->arch.vgic.private_irqs->v2.itargets[i] =
+ (1<<(v->vcpu_id+0))
+ | (1<<(v->vcpu_id+8))
+ | (1<<(v->vcpu_id+16))
+ | (1<<(v->vcpu_id+24));
+
+ return 0;
+}
+
+static int vgic_v2_domain_init(struct domain *d)
+{
+ int i;
+
+ /* By default deliver to CPU0 */
+ for ( i = 0; i < DOMAIN_NR_RANKS(d); i++ )
+ memset(d->arch.vgic.shared_irqs[i].v2.itargets, 0x1,
+ sizeof(d->arch.vgic.shared_irqs[i].v2.itargets));
+
+ /* We rely on gicv_setup() to initialize dbase(vGIC distributor base) */
+ register_mmio_handler(d, &vgic_v2_distr_mmio_handler, d->arch.vgic.dbase,
+ PAGE_SIZE);
+
+ return 0;
+}
+
+static const struct vgic_ops vgic_v2_ops = {
+ .vcpu_init = vgic_v2_vcpu_init,
+ .domain_init = vgic_v2_domain_init,
+ .get_irq_priority = vgic_v2_get_irq_priority,
+ .get_target_vcpu = vgic_v2_get_target_vcpu,
+};
+
+int vgic_v2_init(struct domain *d)
+{
+ register_vgic_ops(d, &vgic_v2_ops);
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
new file mode 100644
index 0000000..ff99e50
--- /dev/null
+++ b/xen/arch/arm/vgic-v3.c
@@ -0,0 +1,1086 @@
+/*
+ * xen/arch/arm/vgic-v3.c
+ *
+ * ARM Virtual Generic Interrupt Controller v3 support
+ * based on xen/arch/arm/vgic.c
+ *
+ * Vijaya Kumar K <vijaya.kumar at caviumnetworks.com>
+ * Copyright (c) 2014 Cavium Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <xen/bitops.h>
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/init.h>
+#include <xen/softirq.h>
+#include <xen/irq.h>
+#include <xen/sched.h>
+#include <xen/sizes.h>
+#include <asm/current.h>
+#include <asm/device.h>
+#include <asm/mmio.h>
+#include <asm/gic_v3_defs.h>
+#include <asm/gic.h>
+#include <asm/vgic.h>
+
+/* GICD_PIDRn register values for ARM implementations */
+#define GICV3_GICD_PIDR0 0x92
+#define GICV3_GICD_PIDR1 0xb4
+#define GICV3_GICD_PIDR2 0x3b
+#define GICV3_GICD_PIDR4 0x04
+
+/* GICR_PIDRn register values for ARM implementations */
+#define GICV3_GICR_PIDR0 0x93
+#define GICV3_GICR_PIDR1 GICV3_GICD_PIDR1
+#define GICV3_GICR_PIDR2 GICV3_GICD_PIDR2
+#define GICV3_GICR_PIDR4 GICV3_GICD_PIDR4
+
+static struct vcpu *vgic_v3_irouter_to_vcpu(struct vcpu *v, uint64_t irouter)
+{
+ irouter &= ~(GICD_IROUTER_SPI_MODE_ANY);
+ irouter = irouter & MPIDR_AFF0_MASK;
+
+ return v->domain->vcpu[irouter];
+}
+
+static uint64_t vgic_v3_vcpu_to_irouter(struct vcpu *v,
+ unsigned int vcpu_id)
+{
+ uint64_t irq_affinity;
+ struct vcpu *v_target;
+
+ v_target = v->domain->vcpu[vcpu_id];
+ irq_affinity = (MPIDR_AFFINITY_LEVEL(v_target->arch.vmpidr, 3) << 32 |
+ MPIDR_AFFINITY_LEVEL(v_target->arch.vmpidr, 2) << 16 |
+ MPIDR_AFFINITY_LEVEL(v_target->arch.vmpidr, 1) << 8 |
+ MPIDR_AFFINITY_LEVEL(v_target->arch.vmpidr, 0));
+
+ return irq_affinity;
+}
+
+static struct vcpu *vgic_v3_get_target_vcpu(struct vcpu *v, unsigned int irq)
+{
+ uint64_t target;
+ struct vgic_irq_rank *rank = vgic_rank_irq(v, irq);
+
+ ASSERT(spin_is_locked(&rank->lock));
+
+ target = rank->v3.irouter[irq % 32];
+ target &= ~(GICD_IROUTER_SPI_MODE_ANY);
+ target &= MPIDR_AFF0_MASK;
+ ASSERT(target >= 0 && target < v->domain->max_vcpus);
+
+ return v->domain->vcpu[target];
+}
+
+static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, mmio_info_t *info,
+ uint32_t gicr_reg)
+{
+ struct hsr_dabt dabt = info->dabt;
+ struct cpu_user_regs *regs = guest_cpu_user_regs();
+ register_t *r = select_user_reg(regs, dabt.reg);
+ uint64_t aff;
+
+ switch ( gicr_reg )
+ {
+ case GICR_CTLR:
+ /* We have not implemented LPI's, read zero */
+ goto read_as_zero;
+ case GICR_IIDR:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ *r = GICV3_GICR_IIDR_VAL;
+ return 1;
+ case GICR_TYPER:
+ if ( dabt.size != DABT_DOUBLE_WORD ) goto bad_width;
+ /* TBD: Update processor id in [23:8] when ITS support is added */
+ aff = (MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 3) << 56 |
+ MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 2) << 48 |
+ MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 1) << 40 |
+ MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 0) << 32);
+ *r = aff;
+ return 1;
+ case GICR_STATUSR:
+ /* Not implemented */
+ goto read_as_zero;
+ case GICR_WAKER:
+ /* Power management is not implemented */
+ goto read_as_zero;
+ case GICR_SETLPIR:
+ /* WO. Read as zero */
+ goto read_as_zero_64;
+ case GICR_CLRLPIR:
+ /* WO. Read as zero */
+ goto read_as_zero_64;
+ case GICR_PROPBASER:
+ /* LPI's not implemented */
+ goto read_as_zero_64;
+ case GICR_PENDBASER:
+ /* LPI's not implemented */
+ goto read_as_zero_64;
+ case GICR_INVLPIR:
+ /* WO. Read as zero */
+ goto read_as_zero_64;
+ case GICR_INVALLR:
+ /* WO. Read as zero */
+ goto read_as_zero_64;
+ return 0;
+ case GICR_SYNCR:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ /* RO . But when read it always returns busy bito bit[0] */
+ *r = GICR_SYNCR_NOT_BUSY;
+ return 1;
+ case GICR_MOVLPIR:
+ /* WO Read as zero */
+ goto read_as_zero_64;
+ case GICR_MOVALLR:
+ /* WO Read as zero */
+ goto read_as_zero_64;
+ case GICR_PIDR0:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ *r = GICV3_GICR_PIDR0;
+ return 1;
+ case GICR_PIDR1:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ *r = GICV3_GICR_PIDR1;
+ return 1;
+ case GICR_PIDR2:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ *r = GICV3_GICR_PIDR2;
+ return 1;
+ case GICR_PIDR3:
+ /* Manufacture/customer defined */
+ goto read_as_zero;
+ case GICR_PIDR4:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ *r = GICV3_GICR_PIDR4;
+ return 1;
+ case GICR_PIDR5 ... GICR_PIDR7:
+ /* Reserved0 */
+ goto read_as_zero;
+ default:
+ printk("vGICv3: vGICR: read r%d offset %#08x\n not found",
+ dabt.reg, gicr_reg);
+ return 0;
+ }
+bad_width:
+ printk("vGICv3: vGICR: bad read width %d r%d offset %#08x\n",
+ dabt.size, dabt.reg, gicr_reg);
+ domain_crash_synchronous();
+ return 0;
+
+read_as_zero_64:
+ if ( dabt.size != DABT_DOUBLE_WORD ) goto bad_width;
+ *r = 0;
+ return 1;
+
+read_as_zero:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ *r = 0;
+ return 1;
+}
+
+static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, mmio_info_t *info,
+ uint32_t gicr_reg)
+{
+ struct hsr_dabt dabt = info->dabt;
+ struct cpu_user_regs *regs = guest_cpu_user_regs();
+ register_t *r = select_user_reg(regs, dabt.reg);
+
+ switch ( gicr_reg )
+ {
+ case GICR_CTLR:
+ /* LPI's not implemented */
+ goto write_ignore;
+ case GICR_IIDR:
+ /* RO */
+ goto write_ignore;
+ case GICR_TYPER:
+ /* RO */
+ goto write_ignore_64;
+ case GICR_STATUSR:
+ /* Not implemented */
+ goto write_ignore;
+ case GICR_WAKER:
+ /* Power mgmt not implemented */
+ goto write_ignore;
+ case GICR_SETLPIR:
+ /* LPI is not implemented */
+ goto write_ignore_64;
+ case GICR_CLRLPIR:
+ /* LPI is not implemented */
+ goto write_ignore_64;
+ case GICR_PROPBASER:
+ /* LPI is not implemented */
+ goto write_ignore_64;
+ case GICR_PENDBASER:
+ /* LPI is not implemented */
+ goto write_ignore_64;
+ case GICR_INVLPIR:
+ /* LPI is not implemented */
+ goto write_ignore_64;
+ case GICR_INVALLR:
+ /* LPI is not implemented */
+ goto write_ignore_64;
+ case GICR_SYNCR:
+ /* RO */
+ goto write_ignore;
+ case GICR_MOVLPIR:
+ /* LPI is not implemented */
+ goto write_ignore_64;
+ case GICR_MOVALLR:
+ /* LPI is not implemented */
+ goto write_ignore_64;
+ case GICR_PIDR7... GICR_PIDR0:
+ /* RO */
+ goto write_ignore;
+ default:
+ printk("vGICR: write r%d offset %#08x\n not found", dabt.reg, gicr_reg);
+ return 0;
+ }
+bad_width:
+ printk("vGICR: bad write width %d r%d=%"PRIregister" offset %#08x\n",
+ dabt.size, dabt.reg, *r, gicr_reg);
+ domain_crash_synchronous();
+ return 0;
+
+write_ignore_64:
+ if ( dabt.size != DABT_DOUBLE_WORD ) goto bad_width;
+ return 1;
+
+write_ignore:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ return 1;
+}
+
+static int __vgic_v3_distr_common_mmio_read(struct vcpu *v, mmio_info_t *info,
+ uint32_t reg)
+{
+ struct hsr_dabt dabt = info->dabt;
+ struct cpu_user_regs *regs = guest_cpu_user_regs();
+ register_t *r = select_user_reg(regs, dabt.reg);
+ struct vgic_irq_rank *rank;
+ unsigned long flags;
+
+ switch ( reg )
+ {
+ case GICD_IGROUPR ... GICD_IGROUPRN:
+ /* We do not implement security extensions for guests, read zero */
+ goto read_as_zero;
+ case GICD_ISENABLER ... GICD_ISENABLERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, reg - GICD_ISENABLER, DABT_WORD);
+ if ( rank == NULL ) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = rank->ienable;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_ICENABLER ... GICD_ICENABLERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, reg - GICD_ICENABLER, DABT_WORD);
+ if ( rank == NULL ) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = rank->ienable;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_ISPENDR ... GICD_ISPENDRN:
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, reg - GICD_ISPENDR, DABT_WORD);
+ if ( rank == NULL ) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = vgic_byte_read(rank->ipend, dabt.sign, reg);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_ICPENDR ... GICD_ICPENDRN:
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, reg - GICD_ICPENDR, DABT_WORD);
+ if ( rank == NULL ) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = vgic_byte_read(rank->ipend, dabt.sign, reg);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_ISACTIVER ... GICD_ISACTIVERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, reg - GICD_ISACTIVER, DABT_WORD);
+ if ( rank == NULL ) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = rank->iactive;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_ICACTIVER ... GICD_ICACTIVERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, reg - GICD_ICACTIVER, DABT_WORD);
+ if ( rank == NULL ) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = rank->iactive;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 8, reg - GICD_IPRIORITYR, DABT_WORD);
+ if ( rank == NULL ) goto read_as_zero;
+
+ vgic_lock_rank(v, rank, flags);
+ *r = rank->ipriority[REG_RANK_INDEX(8, reg - GICD_IPRIORITYR,
+ DABT_WORD)];
+ if ( dabt.size == DABT_BYTE )
+ *r = vgic_byte_read(*r, dabt.sign, reg);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_ICFGR ... GICD_ICFGRN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 2, reg - GICD_ICFGR, DABT_WORD);
+ if ( rank == NULL ) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = rank->icfg[REG_RANK_INDEX(2, reg - GICD_ICFGR, DABT_WORD)];
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ default:
+ printk("vGICv3: vGICD/vGICR: unhandled read r%d offset %#08x\n",
+ dabt.reg, reg);
+ return 0;
+ }
+
+bad_width:
+ dprintk(XENLOG_ERR,
+ "vGICv3: vGICD/vGICR: bad read width %d r%d offset %#08x\n",
+ dabt.size, dabt.reg, reg);
+ domain_crash_synchronous();
+ return 0;
+
+read_as_zero:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ *r = 0;
+ return 1;
+}
+
+static int __vgic_v3_distr_common_mmio_write(struct vcpu *v, mmio_info_t *info,
+ uint32_t reg)
+{
+ struct hsr_dabt dabt = info->dabt;
+ struct cpu_user_regs *regs = guest_cpu_user_regs();
+ register_t *r = select_user_reg(regs, dabt.reg);
+ struct vgic_irq_rank *rank;
+ uint32_t tr;
+ unsigned long flags;
+
+ switch ( reg )
+ {
+ case GICD_IGROUPR ... GICD_IGROUPRN:
+ /* We do not implement security extensions for guests, write ignore */
+ goto write_ignore;
+ case GICD_ISENABLER ... GICD_ISENABLERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, reg - GICD_ISENABLER, DABT_WORD);
+ if ( rank == NULL ) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ tr = rank->ienable;
+ rank->ienable |= *r;
+ /* The irq number is extracted from offset. so shift by register size */
+ vgic_enable_irqs(v, (*r) & (~tr), (reg - GICD_ISENABLER) >> DABT_WORD);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_ICENABLER ... GICD_ICENABLERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, reg - GICD_ICENABLER, DABT_WORD);
+ if ( rank == NULL ) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ tr = rank->ienable;
+ rank->ienable &= ~*r;
+ /* The irq number is extracted from offset. so shift by register size */
+ vgic_disable_irqs(v, (*r) & tr, (reg - GICD_ICENABLER) >> DABT_WORD);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_ISPENDR ... GICD_ISPENDRN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, reg - GICD_ISPENDR, DABT_WORD);
+ if ( rank == NULL ) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ rank->ipend = *r;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_ICPENDR ... GICD_ICPENDRN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, reg - GICD_ICPENDR, DABT_WORD);
+ if ( rank == NULL ) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ rank->ipend &= ~*r;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_ISACTIVER ... GICD_ISACTIVERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, reg - GICD_ISACTIVER, DABT_WORD);
+ if ( rank == NULL ) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ rank->iactive &= ~*r;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_ICACTIVER ... GICD_ICACTIVERN:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, reg - GICD_ICACTIVER, DABT_WORD);
+ if ( rank == NULL ) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ rank->iactive &= ~*r;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
+ if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 8, reg - GICD_IPRIORITYR, DABT_WORD);
+ if ( rank == NULL ) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ if ( dabt.size == DABT_WORD )
+ rank->ipriority[REG_RANK_INDEX(8, reg - GICD_IPRIORITYR,
+ DABT_WORD)] = *r;
+ else
+ vgic_byte_write(&rank->ipriority[REG_RANK_INDEX(8,
+ reg - GICD_IPRIORITYR, DABT_WORD)], *r, reg);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_ICFGR: /* Restricted to configure SGIs */
+ goto write_ignore;
+ case GICD_ICFGR + 4 ... GICD_ICFGRN: /* PPI + SPIs */
+ /* ICFGR1 for PPI's, which is implementation defined
+ if ICFGR1 is programmable or not. We chose to program */
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 2, reg - GICD_ICFGR, DABT_WORD);
+ if ( rank == NULL ) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ rank->icfg[REG_RANK_INDEX(2, reg - GICD_ICFGR, DABT_WORD)] = *r;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ default:
+ printk("vGICv3: vGICD/vGICR: unhandled write r%d "
+ "=%"PRIregister" offset %#08x\n", dabt.reg, *r, reg);
+ return 0;
+ }
+
+bad_width:
+ dprintk(XENLOG_ERR,
+ "vGICv3: vGICD/vGICR: bad write width %d r%d=%"PRIregister" "
+ "offset %#08x\n", dabt.size, dabt.reg, *r, reg);
+ domain_crash_synchronous();
+ return 0;
+
+write_ignore:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ return 1;
+}
+
+static int vgic_v3_rdistr_sgi_mmio_read(struct vcpu *v, mmio_info_t *info,
+ uint32_t gicr_reg)
+{
+ struct hsr_dabt dabt = info->dabt;
+ struct cpu_user_regs *regs = guest_cpu_user_regs();
+ register_t *r = select_user_reg(regs, dabt.reg);
+ struct vgic_irq_rank *rank;
+ unsigned long flags;
+
+ switch ( gicr_reg )
+ {
+ case GICR_IGRPMODR0:
+ /* We do not implement security extensions for guests, read zero */
+ goto read_as_zero;
+ case GICR_IGROUPR0:
+ case GICR_ISENABLER0:
+ case GICR_ICENABLER0:
+ case GICR_ISACTIVER0:
+ case GICR_ICACTIVER0:
+ case GICR_IPRIORITYR0...GICR_IPRIORITYR7:
+ case GICR_ICFGR0... GICR_ICFGR1:
+ /*
+ * Above registers offset are common with GICD.
+ * So handle in common with GICD handling
+ */
+ return __vgic_v3_distr_common_mmio_read(v, info, gicr_reg);
+ case GICR_ISPENDR0:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicr_reg - GICR_ISPENDR0, DABT_WORD);
+ if ( rank == NULL ) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = rank->pendsgi;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICR_ICPENDR0:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicr_reg - GICR_ICPENDR0, DABT_WORD);
+ if ( rank == NULL ) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ *r = rank->pendsgi;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICR_NSACR:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ return 1;
+ default:
+ printk("vGICv3: vGICR: read r%d offset %#08x\n not found",
+ dabt.reg, gicr_reg);
+ return 0;
+ }
+bad_width:
+ printk("vGICv3: vGICR: bad read width %d r%d offset %#08x\n",
+ dabt.size, dabt.reg, gicr_reg);
+ domain_crash_synchronous();
+ return 0;
+
+read_as_zero:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ *r = 0;
+ return 1;
+}
+
+static int vgic_v3_rdistr_sgi_mmio_write(struct vcpu *v, mmio_info_t *info,
+ uint32_t gicr_reg)
+{
+ struct hsr_dabt dabt = info->dabt;
+ struct cpu_user_regs *regs = guest_cpu_user_regs();
+ register_t *r = select_user_reg(regs, dabt.reg);
+ struct vgic_irq_rank *rank;
+ unsigned long flags;
+
+ switch ( gicr_reg )
+ {
+ case GICR_IGRPMODR0:
+ /* We do not implement security extensions for guests, write ignore */
+ goto write_ignore;
+ case GICR_IGROUPR0:
+ case GICR_ISENABLER0:
+ case GICR_ICENABLER0:
+ case GICR_ISACTIVER0:
+ case GICR_ICACTIVER0:
+ case GICR_ICFGR1:
+ case GICR_IPRIORITYR0...GICR_IPRIORITYR7:
+ /*
+ * Above registers offset are common with GICD.
+ * So handle common with GICD handling
+ */
+ return __vgic_v3_distr_common_mmio_write(v, info, gicr_reg);
+ case GICR_ISPENDR0:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicr_reg - GICR_ISACTIVER0, DABT_WORD);
+ if ( rank == NULL ) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ /* TODO: we just store the SGI pending status. Handle it properly */
+ rank->pendsgi |= *r;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICR_ICPENDR0:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 1, gicr_reg - GICR_ISACTIVER0, DABT_WORD);
+ if ( rank == NULL ) goto write_ignore;
+ vgic_lock_rank(v, rank, flags);
+ /* TODO: we just store the SGI pending status. Handle it properly */
+ rank->pendsgi &= ~*r;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICR_NSACR:
+ /* We do not implement security extensions for guests, write ignore */
+ goto write_ignore;
+ default:
+ printk("vGICv3: vGICR SGI: write r%d offset %#08x\n not found",
+ dabt.reg, gicr_reg);
+ return 0;
+ }
+
+bad_width:
+ printk("vGICR SGI: bad write width %d r%d=%"PRIregister" offset %#08x\n",
+ dabt.size, dabt.reg, *r, gicr_reg);
+ domain_crash_synchronous();
+ return 0;
+
+write_ignore:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ return 1;
+}
+
+static int vgic_v3_rdistr_mmio_read(struct vcpu *v, mmio_info_t *info)
+{
+ uint32_t offset;
+
+ if ( v->domain->arch.vgic.rdist_stride != 0 )
+ offset = info->gpa & (v->domain->arch.vgic.rdist_stride - 1);
+ else
+ /* If stride is not set. Default 128K */
+ offset = info->gpa & (SZ_128K - 1);
+
+ if ( offset < SZ_64K )
+ return __vgic_v3_rdistr_rd_mmio_read(v, info, offset);
+ else if ( (offset >= SZ_64K) && (offset < 2 * SZ_64K) )
+ return vgic_v3_rdistr_sgi_mmio_read(v, info, (offset - SZ_64K));
+ else
+ gdprintk(XENLOG_WARNING,
+ "vGICv3: vGICR: unknown gpa read address %"PRIpaddr"\n",
+ info->gpa);
+
+ return 0;
+}
+
+static int vgic_v3_rdistr_mmio_write(struct vcpu *v, mmio_info_t *info)
+{
+ uint32_t offset;
+
+ if ( v->domain->arch.vgic.rdist_stride != 0 )
+ offset = info->gpa & (v->domain->arch.vgic.rdist_stride - 1);
+ else
+ /* If stride is not set. Default 128K */
+ offset = info->gpa & (SZ_128K - 1);
+
+ if ( offset < SZ_64K )
+ return __vgic_v3_rdistr_rd_mmio_write(v, info, offset);
+ else if ( (offset >= SZ_64K) && (offset < 2 * SZ_64K) )
+ return vgic_v3_rdistr_sgi_mmio_write(v, info, (offset - SZ_64K));
+ else
+ gdprintk(XENLOG_WARNING,
+ "vGICV3: vGICR: unknown gpa write address %"PRIpaddr"\n",
+ info->gpa);
+
+ return 0;
+}
+
+static int vgic_v3_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
+{
+ struct hsr_dabt dabt = info->dabt;
+ struct cpu_user_regs *regs = guest_cpu_user_regs();
+ register_t *r = select_user_reg(regs, dabt.reg);
+ struct vgic_irq_rank *rank;
+ unsigned long flags;
+ uint64_t irouter;
+ unsigned int vcpu_id;
+ int gicd_reg = (int)(info->gpa - v->domain->arch.vgic.dbase);
+
+ switch ( gicd_reg )
+ {
+ case GICD_CTLR:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ vgic_lock(v);
+ *r = v->domain->arch.vgic.ctlr;
+ vgic_unlock(v);
+ return 1;
+ case GICD_TYPER:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ /* No secure world support for guests. */
+ *r = (((v->domain->max_vcpus << 5) & GICD_TYPE_CPUS ) |
+ ((v->domain->arch.vgic.nr_lines / 32) & GICD_TYPE_LINES));
+ return 1;
+ case GICD_STATUSR:
+ /*
+ * Optional, Not implemented for now.
+ * Update to support guest debugging.
+ */
+ goto read_as_zero;
+ case GICD_IIDR:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ *r = GICV3_GICD_IIDR_VAL;
+ return 1;
+ case 0x020 ... 0x03c:
+ case 0xc000 ... 0xffcc:
+ /* Implementation defined -- read as zero */
+ goto read_as_zero;
+ case GICD_IGROUPR ... GICD_IGROUPRN:
+ case GICD_ISENABLER ... GICD_ISENABLERN:
+ case GICD_ICENABLER ... GICD_ICENABLERN:
+ case GICD_ISPENDR ... GICD_ISPENDRN:
+ case GICD_ICPENDR ... GICD_ICPENDRN:
+ case GICD_ISACTIVER ... GICD_ISACTIVERN:
+ case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
+ case GICD_ICFGR ... GICD_ICFGRN:
+ /*
+ * Above all register are common with GICR and GICD
+ * Manage in common
+ */
+ return __vgic_v3_distr_common_mmio_read(v, info, gicd_reg);
+ case GICD_IROUTER ... GICD_IROUTER31:
+ /* SGI/PPI is RES0 */
+ goto read_as_zero_64;
+ case GICD_IROUTER32 ... GICD_IROUTERN:
+ if ( dabt.size != DABT_DOUBLE_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 64, gicd_reg - GICD_IROUTER,
+ DABT_DOUBLE_WORD);
+ if ( rank == NULL ) goto read_as_zero;
+ vgic_lock_rank(v, rank, flags);
+ irouter = rank->v3.irouter[REG_RANK_INDEX(64,
+ (gicd_reg - GICD_IROUTER), DABT_DOUBLE_WORD)];
+ /* XXX: bit[31] stores IRQ mode. Just return */
+ if ( irouter & GICD_IROUTER_SPI_MODE_ANY )
+ {
+ *r = GICD_IROUTER_SPI_MODE_ANY;
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ }
+ vcpu_id = irouter;
+ *r = vgic_v3_vcpu_to_irouter(v, vcpu_id);
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_NSACR ... GICD_NSACRN:
+ /* We do not implement security extensions for guests, read zero */
+ goto read_as_zero;
+ case GICD_SGIR:
+ /* Read as ICH_SGIR system register with SRE set. So ignore */
+ goto read_as_zero;
+ case GICD_CPENDSGIR ... GICD_CPENDSGIRN:
+ /* Replaced with GICR_ICPENDR0. So ignore write */
+ goto read_as_zero;
+ case GICD_SPENDSGIR ... GICD_SPENDSGIRN:
+ /* Replaced with GICR_ISPENDR0. So ignore write */
+ goto read_as_zero;
+ case GICD_PIDR0:
+ /* GICv3 identification value */
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ *r = GICV3_GICD_PIDR0;
+ return 1;
+ case GICD_PIDR1:
+ /* GICv3 identification value */
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ *r = GICV3_GICD_PIDR1;
+ return 1;
+ case GICD_PIDR2:
+ /* GICv3 identification value */
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ *r = GICV3_GICD_PIDR2;
+ return 1;
+ case GICD_PIDR3:
+ /* GICv3 identification value. Manufacturer/Customer defined */
+ goto read_as_zero;
+ case GICD_PIDR4:
+ /* GICv3 identification value */
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ *r = GICV3_GICD_PIDR4;
+ return 1;
+ case GICD_PIDR5 ... GICD_PIDR7:
+ /* Reserved0 */
+ goto read_as_zero;
+ case 0x00c:
+ case 0x044:
+ case 0x04c:
+ case 0x05c ... 0x07c:
+ case 0xf30 ... 0x5fcc:
+ case 0x8000 ... 0xbfcc:
+ /* These are reserved register addresses */
+ printk("vGICv3: vGICD: read unknown 0x00c .. 0xfcc r%d offset %#08x\n",
+ dabt.reg, gicd_reg);
+ goto read_as_zero;
+ default:
+ printk("vGICv3: vGICD: unhandled read r%d offset %#08x\n",
+ dabt.reg, gicd_reg);
+ return 0;
+ }
+
+bad_width:
+ dprintk(XENLOG_ERR, "vGICv3: vGICD: bad read width %d r%d offset %#08x\n",
+ dabt.size, dabt.reg, gicd_reg);
+ domain_crash_synchronous();
+ return 0;
+
+read_as_zero_64:
+ if ( dabt.size != DABT_DOUBLE_WORD ) goto bad_width;
+ *r = 0;
+ return 1;
+
+read_as_zero:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ *r = 0;
+ return 1;
+}
+
+static int vgic_v3_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
+{
+ struct hsr_dabt dabt = info->dabt;
+ struct cpu_user_regs *regs = guest_cpu_user_regs();
+ register_t *r = select_user_reg(regs, dabt.reg);
+ struct vgic_irq_rank *rank;
+ unsigned long flags;
+ uint64_t new_irouter, new_target, old_target;
+ struct vcpu *old_vcpu, *new_vcpu;
+ int gicd_reg = (int)(info->gpa - v->domain->arch.vgic.dbase);
+
+ switch ( gicd_reg )
+ {
+ case GICD_CTLR:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ /* Ignore all but the enable bit */
+ v->domain->arch.vgic.ctlr = (*r) & GICD_CTL_ENABLE;
+ return 1;
+ case GICD_TYPER:
+ /* RO -- write ignored */
+ goto write_ignore;
+ case GICD_IIDR:
+ /* RO -- write ignored */
+ goto write_ignore;
+ case GICD_STATUSR:
+ /* RO -- write ignored */
+ goto write_ignore;
+ case GICD_SETSPI_NSR:
+ /* Message based SPI is not implemented */
+ goto write_ignore;
+ case GICD_CLRSPI_NSR:
+ /* Message based SPI is not implemented */
+ goto write_ignore;
+ case GICD_SETSPI_SR:
+ /* Message based SPI is not implemented */
+ goto write_ignore;
+ case GICD_CLRSPI_SR:
+ /* Message based SPI is not implemented */
+ goto write_ignore;
+ case 0x020 ... 0x03c:
+ case 0xc000 ... 0xffcc:
+ /* Implementation defined -- write ignored */
+ printk("vGICv3: vGICD: write unknown 0x020 - 0x03c r%d offset %#08x\n",
+ dabt.reg, gicd_reg);
+ goto write_ignore;
+ case GICD_IGROUPR ... GICD_IGROUPRN:
+ case GICD_ISENABLER ... GICD_ISENABLERN:
+ case GICD_ICENABLER ... GICD_ICENABLERN:
+ case GICD_ISPENDR ... GICD_ISPENDRN:
+ case GICD_ICPENDR ... GICD_ICPENDRN:
+ case GICD_ISACTIVER ... GICD_ISACTIVERN:
+ case GICD_ICACTIVER ... GICD_ICACTIVERN:
+ case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
+ case GICD_ICFGR ... GICD_ICFGRN:
+ /* Above registers are common with GICR and GICD
+ * Manage in common */
+ return __vgic_v3_distr_common_mmio_write(v, info, gicd_reg);
+ case GICD_IROUTER ... GICD_IROUTER31:
+ /* SGI/PPI is RES0 */
+ goto write_ignore_64;
+ case GICD_IROUTER32 ... GICD_IROUTERN:
+ if ( dabt.size != DABT_DOUBLE_WORD ) goto bad_width;
+ rank = vgic_rank_offset(v, 64, gicd_reg - GICD_IROUTER,
+ DABT_DOUBLE_WORD);
+ if ( rank == NULL ) goto write_ignore_64;
+ BUG_ON(v->domain->max_vcpus > 8);
+ new_irouter = *r;
+ vgic_lock_rank(v, rank, flags);
+
+ old_target = rank->v3.irouter[REG_RANK_INDEX(64,
+ (gicd_reg - GICD_IROUTER), DABT_DOUBLE_WORD)];
+ old_target &= ~(GICD_IROUTER_SPI_MODE_ANY);
+ if ( new_irouter & GICD_IROUTER_SPI_MODE_ANY )
+ {
+ /*
+ * IRQ routing mode set. Route any one processor in the entire
+ * system. We chose vcpu 0 and set IRQ mode bit[31] in irouter.
+ */
+ new_target = 0;
+ new_vcpu = v->domain->vcpu[0];
+ new_irouter = GICD_IROUTER_SPI_MODE_ANY;
+ }
+ else
+ {
+ new_target = new_irouter & MPIDR_AFF0_MASK;
+ if ( new_target >= v->domain->max_vcpus )
+ {
+ printk("vGICv3: vGICD: wrong irouter at offset %#08x\n val 0x%lx vcpu %x",
+ gicd_reg, new_target, v->domain->max_vcpus);
+ vgic_unlock_rank(v, rank, flags);
+ return 0;
+ }
+ new_vcpu = vgic_v3_irouter_to_vcpu(v, new_irouter);
+ }
+
+ rank->v3.irouter[REG_RANK_INDEX(64, (gicd_reg - GICD_IROUTER),
+ DABT_DOUBLE_WORD)] = new_irouter;
+ if ( old_target != new_target )
+ {
+ old_vcpu = v->domain->vcpu[old_target];
+ vgic_migrate_irq(old_vcpu, new_vcpu, (gicd_reg - GICD_IROUTER)/8);
+ }
+ vgic_unlock_rank(v, rank, flags);
+ return 1;
+ case GICD_NSACR ... GICD_NSACRN:
+ /* We do not implement security extensions for guests, write ignore */
+ goto write_ignore;
+ case GICD_SGIR:
+ /* it is accessed as system register in GICv3 */
+ goto write_ignore;
+ case GICD_CPENDSGIR ... GICD_CPENDSGIRN:
+ /* Replaced with GICR_ICPENDR0. So ignore write */
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ return 0;
+ case GICD_SPENDSGIR ... GICD_SPENDSGIRN:
+ /* Replaced with GICR_ISPENDR0. So ignore write */
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ return 0;
+ case GICD_PIDR7... GICD_PIDR0:
+ /* RO -- write ignore */
+ goto write_ignore;
+ case 0x00c:
+ case 0x044:
+ case 0x04c:
+ case 0x05c ... 0x07c:
+ case 0xf30 ... 0x5fcc:
+ case 0x8000 ... 0xbfcc:
+ /* Reserved register addresses */
+ printk("vGICv3: vGICD: write unknown 0x00c 0xfcc r%d offset %#08x\n",
+ dabt.reg, gicd_reg);
+ goto write_ignore;
+ default:
+ printk("vGICv3: vGICD: unhandled write r%d=%"PRIregister" "
+ "offset %#08x\n", dabt.reg, *r, gicd_reg);
+ return 0;
+ }
+
+bad_width:
+ dprintk(XENLOG_ERR,
+ "VGICv3: vGICD: bad write width %d r%d=%"PRIregister" "
+ "offset %#08x\n", dabt.size, dabt.reg, *r, gicd_reg);
+ domain_crash_synchronous();
+ return 0;
+
+write_ignore:
+ if ( dabt.size != DABT_WORD ) goto bad_width;
+ return 1;
+
+write_ignore_64:
+ if ( dabt.size != DABT_DOUBLE_WORD ) goto bad_width;
+ return 1;
+}
+
+static int vgic_v3_to_sgi(struct vcpu *v, register_t sgir)
+{
+ int virq;
+ int irqmode;
+ enum gic_sgi_mode sgi_mode;
+ unsigned long vcpu_mask = 0;
+
+ irqmode = (sgir >> ICH_SGI_IRQMODE_SHIFT) & ICH_SGI_IRQMODE_MASK;
+ virq = (sgir >> ICH_SGI_IRQ_SHIFT ) & ICH_SGI_IRQ_MASK;
+ /* SGI's are injected at Rdist level 0. ignoring affinity 1, 2, 3 */
+ vcpu_mask = sgir & ICH_SGI_TARGETLIST_MASK;
+
+ /* Map GIC sgi value to enum value */
+ switch ( irqmode )
+ {
+ case ICH_SGI_TARGET_LIST:
+ sgi_mode = SGI_TARGET_LIST;
+ break;
+ case ICH_SGI_TARGET_OTHERS:
+ sgi_mode = SGI_TARGET_OTHERS;
+ break;
+ default:
+ gdprintk(XENLOG_WARNING, "Wrong irq mode in SGI1R_EL1 register\n");
+ return 0;
+ }
+
+ return vgic_to_sgi(v, sgir, sgi_mode, virq, vcpu_mask);
+}
+
+static int vgic_v3_emulate_sysreg(struct cpu_user_regs *regs, union hsr hsr)
+{
+ struct vcpu *v = current;
+ struct hsr_sysreg sysreg = hsr.sysreg;
+ register_t *r = select_user_reg(regs, sysreg.reg);
+
+ ASSERT (hsr.ec == HSR_EC_SYSREG);
+
+ switch ( hsr.bits & HSR_SYSREG_REGS_MASK )
+ {
+ case HSR_SYSREG_ICC_SGI1R_EL1:
+ /* WO */
+ if ( !sysreg.read )
+ return vgic_v3_to_sgi(v, *r);
+ else
+ {
+ gdprintk(XENLOG_WARNING, "Reading SGI1R_EL1 - WO register\n");
+ return 0;
+ }
+ default:
+ return 0;
+ }
+}
+
+static const struct mmio_handler_ops vgic_rdistr_mmio_handler = {
+ .read_handler = vgic_v3_rdistr_mmio_read,
+ .write_handler = vgic_v3_rdistr_mmio_write,
+};
+
+static const struct mmio_handler_ops vgic_distr_mmio_handler = {
+ .read_handler = vgic_v3_distr_mmio_read,
+ .write_handler = vgic_v3_distr_mmio_write,
+};
+
+static int vgic_v3_get_irq_priority(struct vcpu *v, unsigned int irq)
+{
+ int priority;
+ struct vgic_irq_rank *rank = vgic_rank_irq(v, irq);
+
+ ASSERT(spin_is_locked(&rank->lock));
+ priority = vgic_byte_read(rank->ipriority[REG_RANK_INDEX(8,
+ irq, DABT_WORD)], 0, irq & 0x3);
+
+ return priority;
+}
+
+static int vgic_v3_vcpu_init(struct vcpu *v)
+{
+ int i;
+ uint64_t affinity;
+
+ /* For SGI and PPI the target is always this CPU */
+ affinity = (MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 3) << 32 |
+ MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 2) << 16 |
+ MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 1) << 8 |
+ MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 0));
+
+ for ( i = 0 ; i < 32 ; i++ )
+ v->arch.vgic.private_irqs->v3.irouter[i] = affinity;
+
+ return 0;
+}
+
+static int vgic_v3_domain_init(struct domain *d)
+{
+ int i, idx;
+
+ /* By default deliver to CPU0 */
+ for ( i = 0; i < DOMAIN_NR_RANKS(d); i++ )
+ {
+ for ( idx = 0; idx < 32; idx++ )
+ d->arch.vgic.shared_irqs[i].v3.irouter[idx] = 0;
+ }
+ /* We rely on gicv init to get dbase and size */
+ register_mmio_handler(d, &vgic_distr_mmio_handler, d->arch.vgic.dbase,
+ d->arch.vgic.dbase_size);
+
+ /*
+ * Register mmio handler per redistributor region but not for
+ * every sgi rdist region which is per core.
+ * The redistributor region encompasses per core sgi region.
+ */
+ for ( i = 0; i < d->arch.vgic.rdist_count; i++ )
+ register_mmio_handler(d, &vgic_rdistr_mmio_handler,
+ d->arch.vgic.rbase[i], d->arch.vgic.rbase_size[i]);
+
+ return 0;
+}
+
+static const struct vgic_ops v3_ops = {
+ .vcpu_init = vgic_v3_vcpu_init,
+ .domain_init = vgic_v3_domain_init,
+ .get_irq_priority = vgic_v3_get_irq_priority,
+ .get_target_vcpu = vgic_v3_get_target_vcpu,
+ .emulate_sysreg = vgic_v3_emulate_sysreg,
+};
+
+int vgic_v3_init(struct domain *d)
+{
+ register_vgic_ops(d, &v3_ops);
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 850006c..97061ce 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -27,50 +27,37 @@
#include <asm/current.h>
-#include "io.h"
+#include <asm/mmio.h>
#include <asm/gic.h>
+#include <asm/vgic.h>
-#define REG(n) (n/4)
-
-/* Number of ranks of interrupt registers for a domain */
-#define DOMAIN_NR_RANKS(d) (((d)->arch.vgic.nr_lines+31)/32)
-
-/*
- * Rank containing GICD_<FOO><n> for GICD_<FOO> with
- * <b>-bits-per-interrupt
- */
-static inline int REG_RANK_NR(int b, uint32_t n)
+static inline struct vgic_irq_rank *vgic_get_rank(struct vcpu *v, int rank)
{
- switch ( b )
- {
- case 8: return n >> 3;
- case 4: return n >> 2;
- case 2: return n >> 1;
- case 1: return n;
- default: BUG();
- }
+ if ( rank == 0 )
+ return v->arch.vgic.private_irqs;
+ else if ( rank <= DOMAIN_NR_RANKS(v->domain) )
+ return &v->domain->arch.vgic.shared_irqs[rank - 1];
+ else
+ return NULL;
}
/*
- * Offset of GICD_<FOO><n> with its rank, for GICD_<FOO> with
- * <b>-bits-per-interrupt.
- */
-#define REG_RANK_INDEX(b, n) ((n) & ((b)-1))
-
-/*
* Returns rank corresponding to a GICD_<FOO><n> register for
* GICD_<FOO> with <b>-bits-per-interrupt.
*/
-static struct vgic_irq_rank *vgic_irq_rank(struct vcpu *v, int b, int n)
+struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n,
+ int s)
{
- int rank = REG_RANK_NR(b, n);
+ int rank = REG_RANK_NR(b, (n >> s));
- if ( rank == 0 )
- return &v->arch.vgic.private_irqs;
- else if ( rank <= DOMAIN_NR_RANKS(v->domain) )
- return &v->domain->arch.vgic.shared_irqs[rank - 1];
- else
- return NULL;
+ return vgic_get_rank(v, rank);
+}
+
+struct vgic_irq_rank *vgic_rank_irq(struct vcpu *v, unsigned int irq)
+{
+ int rank = irq/32;
+
+ return vgic_get_rank(v, rank);
}
int domain_vgic_init(struct domain *d)
@@ -82,11 +69,27 @@ int domain_vgic_init(struct domain *d)
/* Currently nr_lines in vgic and gic doesn't have the same meanings
* Here nr_lines = number of SPIs
*/
- if ( d->domain_id == 0 )
+ if ( is_hardware_domain(d) )
d->arch.vgic.nr_lines = gic_number_lines() - 32;
else
d->arch.vgic.nr_lines = 0; /* We don't need SPIs for the guest */
+ switch ( gic_hw_version() )
+ {
+#ifdef CONFIG_ARM_64
+ case GIC_V3:
+ if ( vgic_v3_init(d) )
+ return -ENODEV;
+ break;
+#endif
+ case GIC_V2:
+ if ( vgic_v2_init(d) )
+ return -ENODEV;
+ break;
+ default:
+ return -ENODEV;
+ }
+
d->arch.vgic.shared_irqs =
xzalloc_array(struct vgic_irq_rank, DOMAIN_NR_RANKS(d));
if ( d->arch.vgic.shared_irqs == NULL )
@@ -95,10 +98,7 @@ int domain_vgic_init(struct domain *d)
d->arch.vgic.pending_irqs =
xzalloc_array(struct pending_irq, d->arch.vgic.nr_lines);
if ( d->arch.vgic.pending_irqs == NULL )
- {
- xfree(d->arch.vgic.shared_irqs);
return -ENOMEM;
- }
for (i=0; i<d->arch.vgic.nr_lines; i++)
{
@@ -107,9 +107,17 @@ int domain_vgic_init(struct domain *d)
}
for (i=0; i<DOMAIN_NR_RANKS(d); i++)
spin_lock_init(&d->arch.vgic.shared_irqs[i].lock);
+
+ d->arch.vgic.handler->domain_init(d);
+
return 0;
}
+void register_vgic_ops(struct domain *d, const struct vgic_ops *ops)
+{
+ d->arch.vgic.handler = ops;
+}
+
void domain_vgic_free(struct domain *d)
{
xfree(d->arch.vgic.shared_irqs);
@@ -119,9 +127,14 @@ void domain_vgic_free(struct domain *d)
int vcpu_vgic_init(struct vcpu *v)
{
int i;
- memset(&v->arch.vgic.private_irqs, 0, sizeof(v->arch.vgic.private_irqs));
- spin_lock_init(&v->arch.vgic.private_irqs.lock);
+ v->arch.vgic.private_irqs = xzalloc(struct vgic_irq_rank);
+ if ( v->arch.vgic.private_irqs == NULL )
+ return -ENOMEM;
+
+ spin_lock_init(&v->arch.vgic.private_irqs->lock);
+
+ v->domain->arch.vgic.handler->vcpu_init(v);
memset(&v->arch.vgic.pending_irqs, 0, sizeof(v->arch.vgic.pending_irqs));
for (i = 0; i < 32; i++)
@@ -130,13 +143,6 @@ int vcpu_vgic_init(struct vcpu *v)
INIT_LIST_HEAD(&v->arch.vgic.pending_irqs[i].lr_queue);
}
- /* For SGI and PPI the target is always this CPU */
- for ( i = 0 ; i < 8 ; i++ )
- v->arch.vgic.private_irqs.itargets[i] =
- (1<<(v->vcpu_id+0))
- | (1<<(v->vcpu_id+8))
- | (1<<(v->vcpu_id+16))
- | (1<<(v->vcpu_id+24));
INIT_LIST_HEAD(&v->arch.vgic.inflight_irqs);
INIT_LIST_HEAD(&v->arch.vgic.lr_pending);
spin_lock_init(&v->arch.vgic.lock);
@@ -144,532 +150,197 @@ int vcpu_vgic_init(struct vcpu *v)
return 0;
}
-#define vgic_lock(v) spin_lock_irq(&(v)->domain->arch.vgic.lock)
-#define vgic_unlock(v) spin_unlock_irq(&(v)->domain->arch.vgic.lock)
-
-#define vgic_lock_rank(v, r) spin_lock(&(r)->lock)
-#define vgic_unlock_rank(v, r) spin_unlock(&(r)->lock)
-
-static uint32_t byte_read(uint32_t val, int sign, int offset)
+int vcpu_vgic_free(struct vcpu *v)
{
- int byte = offset & 0x3;
-
- val = val >> (8*byte);
- if ( sign && (val & 0x80) )
- val |= 0xffffff00;
- else
- val &= 0x000000ff;
- return val;
+ xfree(v->arch.vgic.private_irqs);
+ return 0;
}
-static void byte_write(uint32_t *reg, uint32_t var, int offset)
+/* takes the rank lock */
+struct vcpu *vgic_get_target_vcpu(struct vcpu *v, unsigned int irq)
{
- int byte = offset & 0x3;
-
- var &= (0xff << (8*byte));
+ struct domain *d = v->domain;
+ struct vcpu *v_target;
+ struct vgic_irq_rank *rank = vgic_rank_irq(v, irq);
+ unsigned long flags;
- *reg &= ~(0xff << (8*byte));
- *reg |= var;
+ vgic_lock_rank(v, rank, flags);
+ v_target = d->arch.vgic.handler->get_target_vcpu(v, irq);
+ vgic_unlock_rank(v, rank, flags);
+ return v_target;
}
-static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
+void vgic_migrate_irq(struct vcpu *old, struct vcpu *new, unsigned int irq)
{
- struct hsr_dabt dabt = info->dabt;
- struct cpu_user_regs *regs = guest_cpu_user_regs();
- register_t *r = select_user_reg(regs, dabt.reg);
- struct vgic_irq_rank *rank;
- int offset = (int)(info->gpa - v->domain->arch.vgic.dbase);
- int gicd_reg = REG(offset);
-
- switch ( gicd_reg )
- {
- case GICD_CTLR:
- if ( dabt.size != 2 ) goto bad_width;
- vgic_lock(v);
- *r = v->domain->arch.vgic.ctlr;
- vgic_unlock(v);
- return 1;
- case GICD_TYPER:
- if ( dabt.size != 2 ) goto bad_width;
- /* No secure world support for guests. */
- vgic_lock(v);
- *r = ( (v->domain->max_vcpus<<5) & GICD_TYPE_CPUS )
- |( ((v->domain->arch.vgic.nr_lines/32)) & GICD_TYPE_LINES );
- vgic_unlock(v);
- return 1;
- case GICD_IIDR:
- if ( dabt.size != 2 ) goto bad_width;
- /*
- * XXX Do we need a JEP106 manufacturer ID?
- * Just use the physical h/w value for now
- */
- *r = 0x0000043b;
- return 1;
-
- /* Implementation defined -- read as zero */
- case REG(0x020) ... REG(0x03c):
- goto read_as_zero;
-
- case GICD_IGROUPR ... GICD_IGROUPRN:
- /* We do not implement security extensions for guests, read zero */
- goto read_as_zero;
-
- case GICD_ISENABLER ... GICD_ISENABLERN:
- if ( dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 1, gicd_reg - GICD_ISENABLER);
- if ( rank == NULL) goto read_as_zero;
- vgic_lock_rank(v, rank);
- *r = rank->ienable;
- vgic_unlock_rank(v, rank);
- return 1;
-
- case GICD_ICENABLER ... GICD_ICENABLERN:
- if ( dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 1, gicd_reg - GICD_ICENABLER);
- if ( rank == NULL) goto read_as_zero;
- vgic_lock_rank(v, rank);
- *r = rank->ienable;
- vgic_unlock_rank(v, rank);
- return 1;
-
- case GICD_ISPENDR ... GICD_ISPENDRN:
- if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 1, gicd_reg - GICD_ISPENDR);
- if ( rank == NULL) goto read_as_zero;
- vgic_lock_rank(v, rank);
- *r = byte_read(rank->ipend, dabt.sign, offset);
- vgic_unlock_rank(v, rank);
- return 1;
-
- case GICD_ICPENDR ... GICD_ICPENDRN:
- if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 1, gicd_reg - GICD_ICPENDR);
- if ( rank == NULL) goto read_as_zero;
- vgic_lock_rank(v, rank);
- *r = byte_read(rank->ipend, dabt.sign, offset);
- vgic_unlock_rank(v, rank);
- return 1;
-
- case GICD_ISACTIVER ... GICD_ISACTIVERN:
- if ( dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 1, gicd_reg - GICD_ISACTIVER);
- if ( rank == NULL) goto read_as_zero;
- vgic_lock_rank(v, rank);
- *r = rank->iactive;
- vgic_unlock_rank(v, rank);
- return 1;
-
- case GICD_ICACTIVER ... GICD_ICACTIVERN:
- if ( dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 1, gicd_reg - GICD_ICACTIVER);
- if ( rank == NULL) goto read_as_zero;
- vgic_lock_rank(v, rank);
- *r = rank->iactive;
- vgic_unlock_rank(v, rank);
- return 1;
-
- case GICD_ITARGETSR ... GICD_ITARGETSRN:
- if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 8, gicd_reg - GICD_ITARGETSR);
- if ( rank == NULL) goto read_as_zero;
-
- vgic_lock_rank(v, rank);
- *r = rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR)];
- if ( dabt.size == 0 )
- *r = byte_read(*r, dabt.sign, offset);
- vgic_unlock_rank(v, rank);
- return 1;
-
- case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
- if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 8, gicd_reg - GICD_IPRIORITYR);
- if ( rank == NULL) goto read_as_zero;
-
- vgic_lock_rank(v, rank);
- *r = rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR)];
- if ( dabt.size == 0 )
- *r = byte_read(*r, dabt.sign, offset);
- vgic_unlock_rank(v, rank);
- return 1;
-
- case GICD_ICFGR ... GICD_ICFGRN:
- if ( dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 2, gicd_reg - GICD_ICFGR);
- if ( rank == NULL) goto read_as_zero;
- vgic_lock_rank(v, rank);
- *r = rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR)];
- vgic_unlock_rank(v, rank);
- return 1;
-
- case GICD_NSACR ... GICD_NSACRN:
- /* We do not implement security extensions for guests, read zero */
- goto read_as_zero;
-
- case GICD_SGIR:
- if ( dabt.size != 2 ) goto bad_width;
- /* Write only -- read unknown */
- *r = 0xdeadbeef;
- return 1;
-
- case GICD_CPENDSGIR ... GICD_CPENDSGIRN:
- if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 1, gicd_reg - GICD_CPENDSGIR);
- if ( rank == NULL) goto read_as_zero;
- vgic_lock_rank(v, rank);
- *r = byte_read(rank->pendsgi, dabt.sign, offset);
- vgic_unlock_rank(v, rank);
- return 1;
-
- case GICD_SPENDSGIR ... GICD_SPENDSGIRN:
- if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 1, gicd_reg - GICD_SPENDSGIR);
- if ( rank == NULL) goto read_as_zero;
- vgic_lock_rank(v, rank);
- *r = byte_read(rank->pendsgi, dabt.sign, offset);
- vgic_unlock_rank(v, rank);
- return 1;
-
- /* Implementation defined -- read as zero */
- case REG(0xfd0) ... REG(0xfe4):
- goto read_as_zero;
-
- case GICD_ICPIDR2:
- if ( dabt.size != 2 ) goto bad_width;
- printk("vGICD: unhandled read from ICPIDR2\n");
- return 0;
+ unsigned long flags;
+ struct pending_irq *p = irq_to_pending(old, irq);
- /* Implementation defined -- read as zero */
- case REG(0xfec) ... REG(0xffc):
- goto read_as_zero;
+ /* nothing to do for virtual interrupts */
+ if ( p->desc == NULL )
+ return;
- /* Reserved -- read as zero */
- case REG(0x00c) ... REG(0x01c):
- case REG(0x040) ... REG(0x07c):
- case REG(0x7fc):
- case REG(0xbfc):
- case REG(0xf04) ... REG(0xf0c):
- case REG(0xf30) ... REG(0xfcc):
- goto read_as_zero;
+ /* migration already in progress, no need to do anything */
+ if ( test_bit(GIC_IRQ_GUEST_MIGRATING, &p->status) )
+ return;
- default:
- printk("vGICD: unhandled read r%d offset %#08x\n",
- dabt.reg, offset);
- return 0;
+ spin_lock_irqsave(&old->arch.vgic.lock, flags);
+
+ if ( list_empty(&p->inflight) )
+ {
+ irq_set_affinity(p->desc, cpumask_of(new->processor));
+ spin_unlock_irqrestore(&old->arch.vgic.lock, flags);
+ return;
+ }
+ /* If the IRQ is still lr_pending, re-inject it to the new vcpu */
+ if ( !list_empty(&p->lr_queue) )
+ {
+ clear_bit(GIC_IRQ_GUEST_QUEUED, &p->status);
+ list_del_init(&p->lr_queue);
+ list_del_init(&p->inflight);
+ irq_set_affinity(p->desc, cpumask_of(new->processor));
+ spin_unlock_irqrestore(&old->arch.vgic.lock, flags);
+ vgic_vcpu_inject_irq(new, irq);
+ return;
}
+ /* if the IRQ is in a GICH_LR register, set GIC_IRQ_GUEST_MIGRATING
+ * and wait for the EOI */
+ if ( !list_empty(&p->inflight) )
+ set_bit(GIC_IRQ_GUEST_MIGRATING, &p->status);
-bad_width:
- printk("vGICD: bad read width %d r%d offset %#08x\n",
- dabt.size, dabt.reg, offset);
- domain_crash_synchronous();
- return 0;
+ spin_unlock_irqrestore(&old->arch.vgic.lock, flags);
+}
-read_as_zero:
- if ( dabt.size != 2 ) goto bad_width;
- *r = 0;
- return 1;
+void arch_move_irqs(struct vcpu *v)
+{
+ const cpumask_t *cpu_mask = cpumask_of(v->processor);
+ struct domain *d = v->domain;
+ struct pending_irq *p;
+ struct vcpu *v_target;
+ int i;
+
+ for ( i = 32; i < (d->arch.vgic.nr_lines + 32); i++ )
+ {
+ v_target = vgic_get_target_vcpu(v, i);
+ p = irq_to_pending(v_target, i);
+
+ if ( v_target == v && !test_bit(GIC_IRQ_GUEST_MIGRATING, &p->status) )
+ irq_set_affinity(p->desc, cpu_mask);
+ }
}
-static void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n)
+void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n)
{
+ struct domain *d = v->domain;
const unsigned long mask = r;
struct pending_irq *p;
unsigned int irq;
+ unsigned long flags;
int i = 0;
+ struct vcpu *v_target;
while ( (i = find_next_bit(&mask, 32, i)) < 32 ) {
irq = i + (32 * n);
- p = irq_to_pending(v, irq);
+ v_target = d->arch.vgic.handler->get_target_vcpu(v, irq);
+ p = irq_to_pending(v_target, irq);
clear_bit(GIC_IRQ_GUEST_ENABLED, &p->status);
- gic_remove_from_queues(v, irq);
+ gic_remove_from_queues(v_target, irq);
if ( p->desc != NULL )
+ {
+ spin_lock_irqsave(&p->desc->lock, flags);
p->desc->handler->disable(p->desc);
+ spin_unlock_irqrestore(&p->desc->lock, flags);
+ }
i++;
}
}
-static void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
+void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
{
+ struct domain *d = v->domain;
const unsigned long mask = r;
struct pending_irq *p;
unsigned int irq;
+ unsigned long flags;
int i = 0;
+ struct vcpu *v_target;
while ( (i = find_next_bit(&mask, 32, i)) < 32 ) {
irq = i + (32 * n);
- p = irq_to_pending(v, irq);
+ v_target = d->arch.vgic.handler->get_target_vcpu(v, irq);
+ p = irq_to_pending(v_target, irq);
set_bit(GIC_IRQ_GUEST_ENABLED, &p->status);
+ spin_lock_irqsave(&v_target->arch.vgic.lock, flags);
if ( !list_empty(&p->inflight) && !test_bit(GIC_IRQ_GUEST_VISIBLE, &p->status) )
- gic_set_guest_irq(v, irq, GICH_LR_PENDING, p->priority);
+ gic_raise_guest_irq(v_target, irq, p->priority);
+ spin_unlock_irqrestore(&v_target->arch.vgic.lock, flags);
if ( p->desc != NULL )
+ {
+ irq_set_affinity(p->desc, cpumask_of(v_target->processor));
+ spin_lock_irqsave(&p->desc->lock, flags);
p->desc->handler->enable(p->desc);
+ spin_unlock_irqrestore(&p->desc->lock, flags);
+ }
i++;
}
}
-static inline int is_vcpu_running(struct domain *d, int vcpuid)
-{
- struct vcpu *v;
-
- if ( vcpuid >= d->max_vcpus )
- return 0;
-
- v = d->vcpu[vcpuid];
- if ( v == NULL )
- return 0;
- if (test_bit(_VPF_down, &v->pause_flags) )
- return 0;
-
- return 1;
-}
-
-static int vgic_to_sgi(struct vcpu *v, register_t sgir)
+/* TODO: unsigned long is used to fit vcpu_mask.*/
+int vgic_to_sgi(struct vcpu *v, register_t sgir, enum gic_sgi_mode irqmode, int virq,
+ unsigned long vcpu_mask)
{
struct domain *d = v->domain;
- int virtual_irq;
- int filter;
int vcpuid;
int i;
- unsigned long vcpu_mask = 0;
ASSERT(d->max_vcpus < 8*sizeof(vcpu_mask));
- filter = (sgir & GICD_SGI_TARGET_LIST_MASK);
- virtual_irq = (sgir & GICD_SGI_INTID_MASK);
- ASSERT( virtual_irq < 16 );
+ ASSERT( virq < 16 );
- switch ( filter )
+ switch ( irqmode )
{
- case GICD_SGI_TARGET_LIST:
- vcpu_mask = (sgir & GICD_SGI_TARGET_MASK) >> GICD_SGI_TARGET_SHIFT;
- break;
- case GICD_SGI_TARGET_OTHERS:
- for ( i = 0; i < d->max_vcpus; i++ )
- {
- if ( i != current->vcpu_id && is_vcpu_running(d, i) )
- set_bit(i, &vcpu_mask);
- }
- break;
- case GICD_SGI_TARGET_SELF:
- set_bit(current->vcpu_id, &vcpu_mask);
- break;
- default:
- gdprintk(XENLOG_WARNING, "vGICD: unhandled GICD_SGIR write %"PRIregister" with wrong TargetListFilter field\n",
- sgir);
- return 0;
+ case SGI_TARGET_LIST:
+ break;
+ case SGI_TARGET_OTHERS:
+ /*
+ * We expect vcpu_mask to be 0 for SGI_TARGET_OTHERS and
+ * SGI_TARGET_SELF mode. So Force vcpu_mask to 0
+ */
+ vcpu_mask = 0;
+ for ( i = 0; i < d->max_vcpus; i++ )
+ {
+ if ( i != current->vcpu_id && d->vcpu[i] != NULL &&
+ is_vcpu_online(d->vcpu[i]) )
+ set_bit(i, &vcpu_mask);
+ }
+ break;
+ case SGI_TARGET_SELF:
+ /*
+ * We expect vcpu_mask to be 0 for SGI_TARGET_OTHERS and
+ * SGI_TARGET_SELF mode. So Force vcpu_mask to 0
+ */
+ vcpu_mask = 0;
+ set_bit(current->vcpu_id, &vcpu_mask);
+ break;
+ default:
+ gdprintk(XENLOG_WARNING,
+ "vGICD:unhandled GICD_SGIR write %"PRIregister" \
+ with wrong mode\n", sgir);
+ return 0;
}
for_each_set_bit( vcpuid, &vcpu_mask, d->max_vcpus )
{
- if ( !is_vcpu_running(d, vcpuid) )
+ if ( d->vcpu[vcpuid] != NULL && !is_vcpu_online(d->vcpu[vcpuid]) )
{
- gdprintk(XENLOG_WARNING, "vGICD: GICD_SGIR write r=%"PRIregister" vcpu_mask=%lx, wrong CPUTargetList\n",
- sgir, vcpu_mask);
+ gdprintk(XENLOG_WARNING, "VGIC: write r=%"PRIregister" \
+ vcpu_mask=%lx, wrong CPUTargetList\n", sgir, vcpu_mask);
continue;
}
- vgic_vcpu_inject_irq(d->vcpu[vcpuid], virtual_irq, 1);
- }
- return 1;
-}
-
-static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
-{
- struct hsr_dabt dabt = info->dabt;
- struct cpu_user_regs *regs = guest_cpu_user_regs();
- register_t *r = select_user_reg(regs, dabt.reg);
- struct vgic_irq_rank *rank;
- int offset = (int)(info->gpa - v->domain->arch.vgic.dbase);
- int gicd_reg = REG(offset);
- uint32_t tr;
-
- switch ( gicd_reg )
- {
- case GICD_CTLR:
- if ( dabt.size != 2 ) goto bad_width;
- /* Ignore all but the enable bit */
- v->domain->arch.vgic.ctlr = (*r) & GICD_CTL_ENABLE;
- return 1;
-
- /* R/O -- write ignored */
- case GICD_TYPER:
- case GICD_IIDR:
- goto write_ignore;
-
- /* Implementation defined -- write ignored */
- case REG(0x020) ... REG(0x03c):
- goto write_ignore;
-
- case GICD_IGROUPR ... GICD_IGROUPRN:
- /* We do not implement security extensions for guests, write ignore */
- goto write_ignore;
-
- case GICD_ISENABLER ... GICD_ISENABLERN:
- if ( dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 1, gicd_reg - GICD_ISENABLER);
- if ( rank == NULL) goto write_ignore;
- vgic_lock_rank(v, rank);
- tr = rank->ienable;
- rank->ienable |= *r;
- vgic_unlock_rank(v, rank);
- vgic_enable_irqs(v, (*r) & (~tr), gicd_reg - GICD_ISENABLER);
- return 1;
-
- case GICD_ICENABLER ... GICD_ICENABLERN:
- if ( dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 1, gicd_reg - GICD_ICENABLER);
- if ( rank == NULL) goto write_ignore;
- vgic_lock_rank(v, rank);
- tr = rank->ienable;
- rank->ienable &= ~*r;
- vgic_unlock_rank(v, rank);
- vgic_disable_irqs(v, (*r) & tr, gicd_reg - GICD_ICENABLER);
- return 1;
-
- case GICD_ISPENDR ... GICD_ISPENDRN:
- if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
- printk("vGICD: unhandled %s write %#"PRIregister" to ISPENDR%d\n",
- dabt.size ? "word" : "byte", *r, gicd_reg - GICD_ISPENDR);
- return 0;
-
- case GICD_ICPENDR ... GICD_ICPENDRN:
- if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
- printk("vGICD: unhandled %s write %#"PRIregister" to ICPENDR%d\n",
- dabt.size ? "word" : "byte", *r, gicd_reg - GICD_ICPENDR);
- return 0;
-
- case GICD_ISACTIVER ... GICD_ISACTIVERN:
- if ( dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 1, gicd_reg - GICD_ISACTIVER);
- if ( rank == NULL) goto write_ignore;
- vgic_lock_rank(v, rank);
- rank->iactive &= ~*r;
- vgic_unlock_rank(v, rank);
- return 1;
-
- case GICD_ICACTIVER ... GICD_ICACTIVERN:
- if ( dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 1, gicd_reg - GICD_ICACTIVER);
- if ( rank == NULL) goto write_ignore;
- vgic_lock_rank(v, rank);
- rank->iactive &= ~*r;
- vgic_unlock_rank(v, rank);
- return 1;
-
- case GICD_ITARGETSR ... GICD_ITARGETSR + 7:
- /* SGI/PPI target is read only */
- goto write_ignore;
-
- case GICD_ITARGETSR + 8 ... GICD_ITARGETSRN:
- if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 8, gicd_reg - GICD_ITARGETSR);
- if ( rank == NULL) goto write_ignore;
- vgic_lock_rank(v, rank);
- if ( dabt.size == 2 )
- rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR)] = *r;
- else
- byte_write(&rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR)],
- *r, offset);
- vgic_unlock_rank(v, rank);
- return 1;
-
- case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
- if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 8, gicd_reg - GICD_IPRIORITYR);
- if ( rank == NULL) goto write_ignore;
- vgic_lock_rank(v, rank);
- if ( dabt.size == 2 )
- rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR)] = *r;
- else
- byte_write(&rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR)],
- *r, offset);
- vgic_unlock_rank(v, rank);
- return 1;
-
- case GICD_ICFGR: /* SGIs */
- goto write_ignore;
- case GICD_ICFGR + 1: /* PPIs */
- /* It is implementation defined if these are writeable. We chose not */
- goto write_ignore;
- case GICD_ICFGR + 2 ... GICD_ICFGRN: /* SPIs */
- if ( dabt.size != 2 ) goto bad_width;
- rank = vgic_irq_rank(v, 2, gicd_reg - GICD_ICFGR);
- if ( rank == NULL) goto write_ignore;
- vgic_lock_rank(v, rank);
- rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR)] = *r;
- vgic_unlock_rank(v, rank);
- return 1;
-
- case GICD_NSACR ... GICD_NSACRN:
- /* We do not implement security extensions for guests, write ignore */
- goto write_ignore;
-
- case GICD_SGIR:
- if ( dabt.size != 2 )
- goto bad_width;
- return vgic_to_sgi(v, *r);
-
- case GICD_CPENDSGIR ... GICD_CPENDSGIRN:
- if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
- printk("vGICD: unhandled %s write %#"PRIregister" to ICPENDSGIR%d\n",
- dabt.size ? "word" : "byte", *r, gicd_reg - GICD_CPENDSGIR);
- return 0;
-
- case GICD_SPENDSGIR ... GICD_SPENDSGIRN:
- if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
- printk("vGICD: unhandled %s write %#"PRIregister" to ISPENDSGIR%d\n",
- dabt.size ? "word" : "byte", *r, gicd_reg - GICD_SPENDSGIR);
- return 0;
-
- /* Implementation defined -- write ignored */
- case REG(0xfd0) ... REG(0xfe4):
- goto write_ignore;
-
- /* R/O -- write ignore */
- case GICD_ICPIDR2:
- goto write_ignore;
-
- /* Implementation defined -- write ignored */
- case REG(0xfec) ... REG(0xffc):
- goto write_ignore;
-
- /* Reserved -- write ignored */
- case REG(0x00c) ... REG(0x01c):
- case REG(0x040) ... REG(0x07c):
- case REG(0x7fc):
- case REG(0xbfc):
- case REG(0xf04) ... REG(0xf0c):
- case REG(0xf30) ... REG(0xfcc):
- goto write_ignore;
-
- default:
- printk("vGICD: unhandled write r%d=%"PRIregister" offset %#08x\n",
- dabt.reg, *r, offset);
- return 0;
+ vgic_vcpu_inject_irq(d->vcpu[vcpuid], virq);
}
-
-bad_width:
- printk("vGICD: bad write width %d r%d=%"PRIregister" offset %#08x\n",
- dabt.size, dabt.reg, *r, offset);
- domain_crash_synchronous();
- return 0;
-
-write_ignore:
- if ( dabt.size != 2 ) goto bad_width;
return 1;
}
-static int vgic_distr_mmio_check(struct vcpu *v, paddr_t addr)
-{
- struct domain *d = v->domain;
-
- return (addr >= (d->arch.vgic.dbase)) && (addr < (d->arch.vgic.dbase + PAGE_SIZE));
-}
-
-const struct mmio_handler vgic_distr_mmio_handler = {
- .check_handler = vgic_distr_mmio_check,
- .read_handler = vgic_distr_mmio_read,
- .write_handler = vgic_distr_mmio_write,
-};
-
struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq)
{
struct pending_irq *n;
@@ -694,25 +365,19 @@ void vgic_clear_pending_irqs(struct vcpu *v)
spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
}
-void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq, int virtual)
+void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq)
{
- int idx = irq >> 2, byte = irq & 0x3;
uint8_t priority;
- struct vgic_irq_rank *rank = vgic_irq_rank(v, 8, idx);
+ struct vgic_irq_rank *rank = vgic_rank_irq(v, irq);
struct pending_irq *iter, *n = irq_to_pending(v, irq);
unsigned long flags;
bool_t running;
- spin_lock_irqsave(&v->arch.vgic.lock, flags);
+ vgic_lock_rank(v, rank, flags);
+ priority = v->domain->arch.vgic.handler->get_irq_priority(v, irq);
+ vgic_unlock_rank(v, rank, flags);
- if ( !list_empty(&n->inflight) )
- {
- if ( (irq != current->domain->arch.evtchn_irq) ||
- (!test_bit(GIC_IRQ_GUEST_VISIBLE, &n->status)) )
- set_bit(GIC_IRQ_GUEST_PENDING, &n->status);
- spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
- return;
- }
+ spin_lock_irqsave(&v->arch.vgic.lock, flags);
/* vcpu offline */
if ( test_bit(_VPF_down, &v->pause_flags) )
@@ -721,15 +386,20 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq, int virtual)
return;
}
- priority = byte_read(rank->ipriority[REG_RANK_INDEX(8, idx)], 0, byte);
+ set_bit(GIC_IRQ_GUEST_QUEUED, &n->status);
+
+ if ( !list_empty(&n->inflight) )
+ {
+ gic_raise_inflight_irq(v, irq);
+ goto out;
+ }
n->irq = irq;
- set_bit(GIC_IRQ_GUEST_PENDING, &n->status);
n->priority = priority;
/* the irq is enabled */
if ( test_bit(GIC_IRQ_GUEST_ENABLED, &n->status) )
- gic_set_guest_irq(v, irq, GICH_LR_PENDING, priority);
+ gic_raise_guest_irq(v, irq, priority);
list_for_each_entry ( iter, &v->arch.vgic.inflight_irqs, inflight )
{
@@ -749,6 +419,31 @@ out:
smp_send_event_check_mask(cpumask_of(v->processor));
}
+void vgic_vcpu_inject_spi(struct domain *d, unsigned int irq)
+{
+ struct vcpu *v;
+
+ /* the IRQ needs to be an SPI */
+ ASSERT(irq >= 32 && irq <= gic_number_lines());
+
+ v = vgic_get_target_vcpu(d->vcpu[0], irq);
+ vgic_vcpu_inject_irq(v, irq);
+}
+
+void arch_evtchn_inject(struct vcpu *v)
+{
+ vgic_vcpu_inject_irq(v, v->domain->arch.evtchn_irq);
+}
+
+int vgic_emulate(struct cpu_user_regs *regs, union hsr hsr)
+{
+ struct vcpu *v = current;
+
+ ASSERT(v->domain->arch.vgic.handler->emulate_sysreg != NULL);
+
+ return v->domain->arch.vgic.handler->emulate_sysreg(regs, hsr);
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/arm/vpsci.c b/xen/arch/arm/vpsci.c
index c82884f..3f2a482 100644
--- a/xen/arch/arm/vpsci.c
+++ b/xen/arch/arm/vpsci.c
@@ -16,25 +16,40 @@
#include <asm/current.h>
#include <asm/gic.h>
+#include <asm/vgic.h>
#include <asm/psci.h>
+#include <asm/event.h>
-int do_psci_cpu_on(uint32_t vcpuid, register_t entry_point)
+#include <public/sched.h>
+
+static int do_common_cpu_on(register_t target_cpu, register_t entry_point,
+ register_t context_id,int ver)
{
struct vcpu *v;
struct domain *d = current->domain;
struct vcpu_guest_context *ctxt;
int rc;
int is_thumb = entry_point & 1;
+ register_t vcpuid;
+
+ if( ver == XEN_PSCI_V_0_2 )
+ vcpuid = (target_cpu & MPIDR_HWID_MASK);
+ else
+ vcpuid = target_cpu;
if ( (vcpuid < 0) || (vcpuid >= MAX_VIRT_CPUS) )
- return PSCI_EINVAL;
+ return PSCI_INVALID_PARAMETERS;
if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
- return PSCI_EINVAL;
+ return PSCI_INVALID_PARAMETERS;
/* THUMB set is not allowed with 64-bit domain */
- if ( is_pv64_domain(d) && is_thumb )
- return PSCI_EINVAL;
+ if ( is_64bit_domain(d) && is_thumb )
+ return PSCI_INVALID_PARAMETERS;
+
+ if( ( ver == XEN_PSCI_V_0_2 ) &&
+ ( !test_bit(_VPF_down, &v->pause_flags) ) )
+ return PSCI_ALREADY_ON;
if ( (ctxt = alloc_vcpu_guest_context()) == NULL )
return PSCI_DENIED;
@@ -47,11 +62,19 @@ int do_psci_cpu_on(uint32_t vcpuid, register_t entry_point)
ctxt->ttbr0 = 0;
ctxt->ttbr1 = 0;
ctxt->ttbcr = 0; /* Defined Reset Value */
- if ( is_pv32_domain(d) )
+ if ( is_32bit_domain(d) )
+ {
ctxt->user_regs.cpsr = PSR_GUEST32_INIT;
+ if( ver == XEN_PSCI_V_0_2 )
+ ctxt->user_regs.r0_usr = context_id;
+ }
#ifdef CONFIG_ARM_64
else
+ {
ctxt->user_regs.cpsr = PSR_GUEST64_INIT;
+ if( ver == XEN_PSCI_V_0_2 )
+ ctxt->user_regs.x0 = context_id;
+ }
#endif
/* Start the VCPU with THUMB set if it's requested by the kernel */
@@ -75,7 +98,12 @@ int do_psci_cpu_on(uint32_t vcpuid, register_t entry_point)
return PSCI_SUCCESS;
}
-int do_psci_cpu_off(uint32_t power_state)
+int32_t do_psci_cpu_on(uint32_t vcpuid, register_t entry_point)
+{
+ return do_common_cpu_on(vcpuid,entry_point,0,XEN_PSCI_V_0_1);
+}
+
+int32_t do_psci_cpu_off(uint32_t power_state)
{
struct vcpu *v = current;
if ( !test_and_set_bit(_VPF_down, &v->pause_flags) )
@@ -83,6 +111,100 @@ int do_psci_cpu_off(uint32_t power_state)
return PSCI_SUCCESS;
}
+uint32_t do_psci_0_2_version(void)
+{
+ return XEN_PSCI_V_0_2;
+}
+
+register_t do_psci_0_2_cpu_suspend(uint32_t power_state, register_t entry_point,
+ register_t context_id)
+{
+ struct vcpu *v = current;
+
+ /*
+ * Power off requests are treated as performing standby
+ * as this simplifies Xen implementation.
+ */
+
+ vcpu_block_unless_event_pending(v);
+ return PSCI_SUCCESS;
+}
+
+int32_t do_psci_0_2_cpu_off(void)
+{
+ return do_psci_cpu_off(0);
+}
+
+int32_t do_psci_0_2_cpu_on(register_t target_cpu, register_t entry_point,
+ register_t context_id)
+{
+ return do_common_cpu_on(target_cpu,entry_point,context_id,XEN_PSCI_V_0_2);
+}
+
+static const unsigned long target_affinity_mask[] = {
+ ( MPIDR_HWID_MASK & AFFINITY_MASK( 0 ) ),
+ ( MPIDR_HWID_MASK & AFFINITY_MASK( 1 ) ),
+ ( MPIDR_HWID_MASK & AFFINITY_MASK( 2 ) )
+#ifdef CONFIG_ARM_64
+ ,( MPIDR_HWID_MASK & AFFINITY_MASK( 3 ) )
+#endif
+};
+
+int32_t do_psci_0_2_affinity_info(register_t target_affinity,
+ uint32_t lowest_affinity_level)
+{
+ struct domain *d = current->domain;
+ struct vcpu *v;
+ uint32_t vcpuid;
+ unsigned long tmask;
+
+ if ( lowest_affinity_level < ARRAY_SIZE(target_affinity_mask) )
+ {
+ tmask = target_affinity_mask[lowest_affinity_level];
+ target_affinity &= tmask;
+ }
+ else
+ return PSCI_INVALID_PARAMETERS;
+
+ for ( vcpuid = 0; vcpuid < d->max_vcpus; vcpuid++ )
+ {
+ v = d->vcpu[vcpuid];
+
+ if ( ( ( v->arch.vmpidr & tmask ) == target_affinity )
+ && ( !test_bit(_VPF_down, &v->pause_flags) ) )
+ return PSCI_0_2_AFFINITY_LEVEL_ON;
+ }
+
+ return PSCI_0_2_AFFINITY_LEVEL_OFF;
+}
+
+int32_t do_psci_0_2_migrate(uint32_t target_cpu)
+{
+ return PSCI_NOT_SUPPORTED;
+}
+
+uint32_t do_psci_0_2_migrate_info_type(void)
+{
+ return PSCI_0_2_TOS_MP_OR_NOT_PRESENT;
+}
+
+register_t do_psci_0_2_migrate_info_up_cpu(void)
+{
+ return PSCI_NOT_SUPPORTED;
+}
+
+void do_psci_0_2_system_off( void )
+{
+ struct domain *d = current->domain;
+ domain_shutdown(d,SHUTDOWN_poweroff);
+}
+
+void do_psci_0_2_system_reset(void)
+{
+ struct domain *d = current->domain;
+ domain_shutdown(d,SHUTDOWN_reboot);
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/arm/vtimer.c b/xen/arch/arm/vtimer.c
index e325f78..2e95ceb 100644
--- a/xen/arch/arm/vtimer.c
+++ b/xen/arch/arm/vtimer.c
@@ -24,6 +24,7 @@
#include <asm/irq.h>
#include <asm/time.h>
#include <asm/gic.h>
+#include <asm/vgic.h>
#include <asm/regs.h>
extern s_time_t ticks_to_ns(uint64_t ticks);
@@ -34,17 +35,17 @@ static void phys_timer_expired(void *data)
struct vtimer *t = data;
t->ctl |= CNTx_CTL_PENDING;
if ( !(t->ctl & CNTx_CTL_MASK) )
- vgic_vcpu_inject_irq(t->v, t->irq, 1);
+ vgic_vcpu_inject_irq(t->v, t->irq);
}
static void virt_timer_expired(void *data)
{
struct vtimer *t = data;
t->ctl |= CNTx_CTL_MASK;
- vgic_vcpu_inject_irq(t->v, t->irq, 1);
+ vgic_vcpu_inject_irq(t->v, t->irq);
}
-int vcpu_domain_init(struct domain *d)
+int domain_vtimer_init(struct domain *d)
{
d->arch.phys_timer_base.offset = NOW();
d->arch.virt_timer_base.offset = READ_SYSREG64(CNTPCT_EL0);
@@ -54,17 +55,18 @@ int vcpu_domain_init(struct domain *d)
int vcpu_vtimer_init(struct vcpu *v)
{
struct vtimer *t = &v->arch.phys_timer;
- bool_t d0 = (v->domain == dom0);
+ bool_t d0 = is_hardware_domain(v->domain);
/*
- * Domain 0 uses the hardware interrupts, guests get the virtual platform.
+ * Hardware domain uses the hardware interrupts, guests get the virtual
+ * platform.
*/
init_timer(&t->timer, phys_timer_expired, t, v->processor);
t->ctl = 0;
t->cval = NOW();
t->irq = d0
- ? timer_dt_irq(TIMER_PHYS_NONSECURE_PPI)->irq
+ ? timer_get_irq(TIMER_PHYS_NONSECURE_PPI)
: GUEST_TIMER_PHYS_NS_PPI;
t->v = v;
@@ -72,23 +74,27 @@ int vcpu_vtimer_init(struct vcpu *v)
init_timer(&t->timer, virt_timer_expired, t, v->processor);
t->ctl = 0;
t->irq = d0
- ? timer_dt_irq(TIMER_VIRT_PPI)->irq
+ ? timer_get_irq(TIMER_VIRT_PPI)
: GUEST_TIMER_VIRT_PPI;
t->v = v;
+ v->arch.vtimer_initialized = 1;
+
return 0;
}
void vcpu_timer_destroy(struct vcpu *v)
{
+ if ( !v->arch.vtimer_initialized )
+ return;
+
kill_timer(&v->arch.virt_timer.timer);
kill_timer(&v->arch.phys_timer.timer);
}
int virt_timer_save(struct vcpu *v)
{
- if ( is_idle_domain(v->domain) )
- return 0;
+ ASSERT(!is_idle_vcpu(v));
v->arch.virt_timer.ctl = READ_SYSREG32(CNTV_CTL_EL0);
WRITE_SYSREG32(v->arch.virt_timer.ctl & ~CNTx_CTL_ENABLE, CNTV_CTL_EL0);
@@ -104,8 +110,7 @@ int virt_timer_save(struct vcpu *v)
int virt_timer_restore(struct vcpu *v)
{
- if ( is_idle_domain(v->domain) )
- return 0;
+ ASSERT(!is_idle_vcpu(v));
stop_timer(&v->arch.virt_timer.timer);
migrate_timer(&v->arch.virt_timer.timer, v->processor);
@@ -266,16 +271,16 @@ int vtimer_emulate(struct cpu_user_regs *regs, union hsr hsr)
switch (hsr.ec) {
case HSR_EC_CP15_32:
- if ( !is_pv32_domain(current->domain) )
+ if ( !is_32bit_domain(current->domain) )
return 0;
return vtimer_emulate_cp32(regs, hsr);
case HSR_EC_CP15_64:
- if ( !is_pv32_domain(current->domain) )
+ if ( !is_32bit_domain(current->domain) )
return 0;
return vtimer_emulate_cp64(regs, hsr);
#ifdef CONFIG_ARM_64
case HSR_EC_SYSREG:
- if ( is_pv32_domain(current->domain) )
+ if ( is_32bit_domain(current->domain) )
return 0;
return vtimer_emulate_sysreg(regs, hsr);
#endif
diff --git a/xen/arch/arm/vtimer.h b/xen/arch/arm/vtimer.h
index bcf910e..6d2e46e 100644
--- a/xen/arch/arm/vtimer.h
+++ b/xen/arch/arm/vtimer.h
@@ -20,7 +20,7 @@
#ifndef __ARCH_ARM_VTIMER_H__
#define __ARCH_ARM_VTIMER_H__
-extern int vcpu_domain_init(struct domain *d);
+extern int domain_vtimer_init(struct domain *d);
extern int vcpu_vtimer_init(struct vcpu *v);
extern int vtimer_emulate(struct cpu_user_regs *regs, union hsr hsr);
extern int virt_timer_save(struct vcpu *v);
diff --git a/xen/arch/arm/vuart.c b/xen/arch/arm/vuart.c
index b9d3ced..e327c15 100644
--- a/xen/arch/arm/vuart.c
+++ b/xen/arch/arm/vuart.c
@@ -38,15 +38,23 @@
#include <xen/errno.h>
#include <xen/ctype.h>
#include <xen/serial.h>
+#include <asm/mmio.h>
#include "vuart.h"
-#include "io.h"
#define domain_has_vuart(d) ((d)->arch.vuart.info != NULL)
+static int vuart_mmio_read(struct vcpu *v, mmio_info_t *info);
+static int vuart_mmio_write(struct vcpu *v, mmio_info_t *info);
+
+static const struct mmio_handler_ops vuart_mmio_handler = {
+ .read_handler = vuart_mmio_read,
+ .write_handler = vuart_mmio_write,
+};
+
int domain_vuart_init(struct domain *d)
{
- ASSERT( !d->domain_id );
+ ASSERT( is_hardware_domain(d) );
d->arch.vuart.info = serial_vuart_info(SERHND_DTUART);
if ( !d->arch.vuart.info )
@@ -59,6 +67,10 @@ int domain_vuart_init(struct domain *d)
if ( !d->arch.vuart.buf )
return -ENOMEM;
+ register_mmio_handler(d, &vuart_mmio_handler,
+ d->arch.vuart.info->base_addr,
+ d->arch.vuart.info->size);
+
return 0;
}
@@ -92,14 +104,6 @@ static void vuart_print_char(struct vcpu *v, char c)
spin_unlock(&uart->lock);
}
-static int vuart_mmio_check(struct vcpu *v, paddr_t addr)
-{
- const struct vuart_info *info = v->domain->arch.vuart.info;
-
- return (domain_has_vuart(v->domain) && addr >= info->base_addr &&
- addr <= (info->base_addr + info->size));
-}
-
static int vuart_mmio_read(struct vcpu *v, mmio_info_t *info)
{
struct domain *d = v->domain;
@@ -133,12 +137,6 @@ static int vuart_mmio_write(struct vcpu *v, mmio_info_t *info)
return 1;
}
-const struct mmio_handler vuart_mmio_handler = {
- .check_handler = vuart_mmio_check,
- .read_handler = vuart_mmio_read,
- .write_handler = vuart_mmio_write,
-};
-
/*
* Local variables:
* mode: C
diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
index e8b4f47..0488f37 100644
--- a/xen/arch/arm/xen.lds.S
+++ b/xen/arch/arm/xen.lds.S
@@ -30,6 +30,8 @@ SECTIONS
.text : /* XXX should be AT ( XEN_PHYS_START ) */ {
_stext = .; /* Text section */
*(.text)
+ *(.text.cold)
+ *(.text.unlikely)
*(.fixup)
*(.gnu.warning)
_etext = .; /* End of text section */
@@ -38,6 +40,14 @@ SECTIONS
. = ALIGN(PAGE_SIZE);
.rodata : {
_srodata = .; /* Read-only data */
+ /* Bug frames table */
+ __start_bug_frames = .;
+ *(.bug_frames.0)
+ __stop_bug_frames_0 = .;
+ *(.bug_frames.1)
+ __stop_bug_frames_1 = .;
+ *(.bug_frames.2)
+ __stop_bug_frames_2 = .;
*(.rodata)
*(.rodata.*)
_erodata = .; /* End of read-only data */
@@ -133,6 +143,7 @@ SECTIONS
*(.xsm_initcall.init)
__xsm_initcall_end = .;
} :text
+ __init_end_efi = .;
. = ALIGN(STACK_SIZE);
__init_end = .;
@@ -176,3 +187,9 @@ SECTIONS
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
}
+
+/*
+ * We require that Xen is loaded at a 4K boundary, so this ensures that any
+ * code running on the boot time identity map cannot cross a section boundary.
+ */
+ASSERT( _end_boot - start <= PAGE_SIZE, "Boot code is larger than 4K")
diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index d502bdf..86ca5f8 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -7,6 +7,7 @@ subdir-y += oprofile
subdir-$(x86_64) += x86_64
+obj-bin-y += alternative.init.o
obj-y += apic.o
obj-y += bitops.o
obj-bin-y += bzimage.init.o
@@ -41,6 +42,7 @@ obj-y += numa.o
obj-y += pci.o
obj-y += percpu.o
obj-y += physdev.o
+obj-y += psr.o
obj-y += setup.o
obj-y += shutdown.o
obj-y += smp.o
diff --git a/xen/arch/x86/Rules.mk b/xen/arch/x86/Rules.mk
index 576985e..6775cb5 100644
--- a/xen/arch/x86/Rules.mk
+++ b/xen/arch/x86/Rules.mk
@@ -12,6 +12,7 @@ HAS_NS16550 := y
HAS_EHCI := y
HAS_KEXEC := y
HAS_GDBSX := y
+HAS_PDX := y
xenoprof := y
#
diff --git a/xen/arch/x86/acpi/boot.c b/xen/arch/x86/acpi/boot.c
index 05de536..903830b 100644
--- a/xen/arch/x86/acpi/boot.c
+++ b/xen/arch/x86/acpi/boot.c
@@ -56,7 +56,9 @@ bool_t __initdata acpi_ht = 1; /* enable HT */
bool_t __initdata acpi_lapic;
bool_t __initdata acpi_ioapic;
-bool_t acpi_skip_timer_override __initdata;
+/* acpi_skip_timer_override: Skip IRQ0 overrides. */
+static bool_t acpi_skip_timer_override __initdata;
+boolean_param("acpi_skip_timer_override", acpi_skip_timer_override);
#ifdef CONFIG_X86_LOCAL_APIC
static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
@@ -402,11 +404,15 @@ acpi_fadt_parse_sleep_info(struct acpi_table_fadt *fadt)
acpi_fadt_copy_address(pm1b_evt, pm1b_event, pm1_event);
printk(KERN_INFO PREFIX
- "SLEEP INFO: pm1x_cnt[%"PRIx64",%"PRIx64"], "
- "pm1x_evt[%"PRIx64",%"PRIx64"]\n",
+ "SLEEP INFO: pm1x_cnt[%d:%"PRIx64",%d:%"PRIx64"], "
+ "pm1x_evt[%d:%"PRIx64",%d:%"PRIx64"]\n",
+ acpi_sinfo.pm1a_cnt_blk.space_id,
acpi_sinfo.pm1a_cnt_blk.address,
+ acpi_sinfo.pm1b_cnt_blk.space_id,
acpi_sinfo.pm1b_cnt_blk.address,
+ acpi_sinfo.pm1a_evt_blk.space_id,
acpi_sinfo.pm1a_evt_blk.address,
+ acpi_sinfo.pm1b_evt_blk.space_id,
acpi_sinfo.pm1b_evt_blk.address);
/* Now FACS... */
diff --git a/xen/arch/x86/acpi/cpu_idle.c b/xen/arch/x86/acpi/cpu_idle.c
index 6aaa7ab..2b2bcc6 100644
--- a/xen/arch/x86/acpi/cpu_idle.c
+++ b/xen/arch/x86/acpi/cpu_idle.c
@@ -62,13 +62,17 @@
#define GET_HW_RES_IN_NS(msr, val) \
do { rdmsrl(msr, val); val = tsc_ticks2ns(val); } while( 0 )
-#define GET_PC2_RES(val) GET_HW_RES_IN_NS(0x60D, val) /* SNB only */
+#define GET_PC2_RES(val) GET_HW_RES_IN_NS(0x60D, val) /* SNB onwards */
#define GET_PC3_RES(val) GET_HW_RES_IN_NS(0x3F8, val)
#define GET_PC6_RES(val) GET_HW_RES_IN_NS(0x3F9, val)
#define GET_PC7_RES(val) GET_HW_RES_IN_NS(0x3FA, val)
+#define GET_PC8_RES(val) GET_HW_RES_IN_NS(0x630, val) /* some Haswells only */
+#define GET_PC9_RES(val) GET_HW_RES_IN_NS(0x631, val) /* some Haswells only */
+#define GET_PC10_RES(val) GET_HW_RES_IN_NS(0x632, val) /* some Haswells only */
+#define GET_CC1_RES(val) GET_HW_RES_IN_NS(0x660, val) /* Silvermont only */
#define GET_CC3_RES(val) GET_HW_RES_IN_NS(0x3FC, val)
#define GET_CC6_RES(val) GET_HW_RES_IN_NS(0x3FD, val)
-#define GET_CC7_RES(val) GET_HW_RES_IN_NS(0x3FE, val) /* SNB only */
+#define GET_CC7_RES(val) GET_HW_RES_IN_NS(0x3FE, val) /* SNB onwards */
static void lapic_timer_nop(void) { }
void (*__read_mostly lapic_timer_off)(void);
@@ -111,8 +115,13 @@ struct hw_residencies
{
uint64_t pc2;
uint64_t pc3;
+ uint64_t pc4;
uint64_t pc6;
uint64_t pc7;
+ uint64_t pc8;
+ uint64_t pc9;
+ uint64_t pc10;
+ uint64_t cc1;
uint64_t cc3;
uint64_t cc6;
uint64_t cc7;
@@ -128,6 +137,12 @@ static void do_get_hw_residencies(void *arg)
switch ( c->x86_model )
{
+ /* 4th generation Intel Core (Haswell) */
+ case 0x45:
+ GET_PC8_RES(hw_res->pc8);
+ GET_PC9_RES(hw_res->pc9);
+ GET_PC10_RES(hw_res->pc10);
+ /* fall through */
/* Sandy bridge */
case 0x2A:
case 0x2D:
@@ -137,7 +152,6 @@ static void do_get_hw_residencies(void *arg)
/* Haswell */
case 0x3C:
case 0x3F:
- case 0x45:
case 0x46:
/* future */
case 0x3D:
@@ -160,6 +174,22 @@ static void do_get_hw_residencies(void *arg)
GET_CC3_RES(hw_res->cc3);
GET_CC6_RES(hw_res->cc6);
break;
+ /* various Atoms */
+ case 0x27:
+ GET_PC3_RES(hw_res->pc2); /* abusing GET_PC3_RES */
+ GET_PC6_RES(hw_res->pc4); /* abusing GET_PC6_RES */
+ GET_PC7_RES(hw_res->pc6); /* abusing GET_PC7_RES */
+ break;
+ /* Silvermont */
+ case 0x37:
+ case 0x4A:
+ case 0x4D:
+ case 0x5A:
+ case 0x5D:
+ GET_PC7_RES(hw_res->pc6); /* abusing GET_PC7_RES */
+ GET_CC1_RES(hw_res->cc1);
+ GET_CC6_RES(hw_res->cc6);
+ break;
}
}
@@ -179,10 +209,16 @@ static void print_hw_residencies(uint32_t cpu)
get_hw_residencies(cpu, &hw_res);
- printk("PC2[%"PRId64"] PC3[%"PRId64"] PC6[%"PRId64"] PC7[%"PRId64"]\n",
- hw_res.pc2, hw_res.pc3, hw_res.pc6, hw_res.pc7);
- printk("CC3[%"PRId64"] CC6[%"PRId64"] CC7[%"PRId64"]\n",
- hw_res.cc3, hw_res.cc6,hw_res.cc7);
+ printk("PC2[%"PRIu64"] PC%d[%"PRIu64"] PC6[%"PRIu64"] PC7[%"PRIu64"]\n",
+ hw_res.pc2,
+ hw_res.pc4 ? 4 : 3, hw_res.pc4 ?: hw_res.pc3,
+ hw_res.pc6, hw_res.pc7);
+ if ( hw_res.pc8 | hw_res.pc9 | hw_res.pc10 )
+ printk("PC8[%"PRIu64"] PC9[%"PRIu64"] PC10[%"PRIu64"]\n",
+ hw_res.pc8, hw_res.pc9, hw_res.pc10);
+ printk("CC%d[%"PRIu64"] CC6[%"PRIu64"] CC7[%"PRIu64"]\n",
+ hw_res.cc1 ? 1 : 3, hw_res.cc1 ?: hw_res.cc3,
+ hw_res.cc6, hw_res.cc7);
}
static char* acpi_cstate_method_name[] =
@@ -294,13 +330,27 @@ void cpuidle_wakeup_mwait(cpumask_t *mask)
cpumask_andnot(mask, mask, &target);
}
+bool_t arch_skip_send_event_check(unsigned int cpu)
+{
+ /*
+ * This relies on softirq_pending() and mwait_wakeup() to access data
+ * on the same cache line.
+ */
+ smp_mb();
+ return !!cpumask_test_cpu(cpu, &cpuidle_mwait_flags);
+}
+
void mwait_idle_with_hints(unsigned int eax, unsigned int ecx)
{
unsigned int cpu = smp_processor_id();
s_time_t expires = per_cpu(timer_deadline, cpu);
if ( boot_cpu_has(X86_FEATURE_CLFLUSH_MONITOR) )
+ {
+ mb();
clflush((void *)&mwait_wakeup(cpu));
+ mb();
+ }
__monitor((void *)&mwait_wakeup(cpu), 0, 0);
smp_mb();
@@ -309,7 +359,7 @@ void mwait_idle_with_hints(unsigned int eax, unsigned int ecx)
* Timer deadline passing is the event on which we will be woken via
* cpuidle_mwait_wakeup. So check it now that the location is armed.
*/
- if ( expires > NOW() || expires == 0 )
+ if ( (expires > NOW() || expires == 0) && !softirq_pending(cpu) )
{
cpumask_set_cpu(cpu, &cpuidle_mwait_flags);
__mwait(eax, ecx);
@@ -936,7 +986,7 @@ static void set_cx(
cx->entry_method = ACPI_CSTATE_EM_HALT;
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
- if ( ioports_deny_access(dom0, cx->address, cx->address) )
+ if ( ioports_deny_access(hardware_domain, cx->address, cx->address) )
printk(XENLOG_WARNING "Could not deny access to port %04x\n",
cx->address);
cx->entry_method = ACPI_CSTATE_EM_SYSIO;
@@ -950,7 +1000,7 @@ static void set_cx(
cx->target_residency = cx->latency * latency_factor;
smp_wmb();
- acpi_power->count++;
+ acpi_power->count += (cx->type != ACPI_STATE_C1);
if ( cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2 )
acpi_power->safe_state = cx;
}
@@ -1100,19 +1150,21 @@ int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat)
struct acpi_processor_power *power = processor_powers[cpuid];
uint64_t idle_usage = 0, idle_res = 0;
uint64_t usage[ACPI_PROCESSOR_MAX_POWER], res[ACPI_PROCESSOR_MAX_POWER];
- int i;
- struct hw_residencies hw_res;
+ unsigned int i, nr, nr_pc = 0, nr_cc = 0;
if ( power == NULL )
{
stat->last = 0;
stat->nr = 0;
stat->idle_time = 0;
+ stat->nr_pc = 0;
+ stat->nr_cc = 0;
return 0;
}
stat->last = power->last_state ? power->last_state->idx : 0;
stat->idle_time = get_cpu_idle_time(cpuid);
+ nr = min(stat->nr, power->count);
/* mimic the stat when detail info hasn't been registered by dom0 */
if ( pm_idle_save == NULL )
@@ -1121,14 +1173,14 @@ int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat)
usage[1] = idle_usage = 1;
res[1] = idle_res = stat->idle_time;
-
- memset(&hw_res, 0, sizeof(hw_res));
}
else
{
+ struct hw_residencies hw_res;
+
stat->nr = power->count;
- for ( i = 1; i < power->count; i++ )
+ for ( i = 1; i < nr; i++ )
{
spin_lock_irq(&power->stat_lock);
usage[i] = power->states[i].usage;
@@ -1140,22 +1192,42 @@ int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat)
}
get_hw_residencies(cpuid, &hw_res);
+
+#define PUT_xC(what, n) do { \
+ if ( stat->nr_##what >= n && \
+ copy_to_guest_offset(stat->what, n - 1, &hw_res.what##n, 1) ) \
+ return -EFAULT; \
+ if ( hw_res.what##n ) \
+ nr_##what = n; \
+ } while ( 0 )
+#define PUT_PC(n) PUT_xC(pc, n)
+ PUT_PC(2);
+ PUT_PC(3);
+ PUT_PC(4);
+ PUT_PC(6);
+ PUT_PC(7);
+ PUT_PC(8);
+ PUT_PC(9);
+ PUT_PC(10);
+#undef PUT_PC
+#define PUT_CC(n) PUT_xC(cc, n)
+ PUT_CC(1);
+ PUT_CC(3);
+ PUT_CC(6);
+ PUT_CC(7);
+#undef PUT_CC
+#undef PUT_xC
}
usage[0] = idle_usage;
res[0] = NOW() - idle_res;
- if ( copy_to_guest(stat->triggers, usage, stat->nr) ||
- copy_to_guest(stat->residencies, res, stat->nr) )
+ if ( copy_to_guest(stat->triggers, usage, nr) ||
+ copy_to_guest(stat->residencies, res, nr) )
return -EFAULT;
- stat->pc2 = hw_res.pc2;
- stat->pc3 = hw_res.pc3;
- stat->pc6 = hw_res.pc6;
- stat->pc7 = hw_res.pc7;
- stat->cc3 = hw_res.cc3;
- stat->cc6 = hw_res.cc6;
- stat->cc7 = hw_res.cc7;
+ stat->nr_pc = nr_pc;
+ stat->nr_cc = nr_cc;
return 0;
}
diff --git a/xen/arch/x86/acpi/cpufreq/cpufreq.c b/xen/arch/x86/acpi/cpufreq/cpufreq.c
index 4a6aeb3..fa3678d 100644
--- a/xen/arch/x86/acpi/cpufreq/cpufreq.c
+++ b/xen/arch/x86/acpi/cpufreq/cpufreq.c
@@ -57,8 +57,8 @@ struct acpi_cpufreq_data *cpufreq_drv_data[NR_CPUS];
static struct cpufreq_driver acpi_cpufreq_driver;
-static unsigned int __read_mostly acpi_pstate_strict;
-integer_param("acpi_pstate_strict", acpi_pstate_strict);
+static bool_t __read_mostly acpi_pstate_strict;
+boolean_param("acpi_pstate_strict", acpi_pstate_strict);
static int check_est_cpu(unsigned int cpuid)
{
diff --git a/xen/arch/x86/acpi/cpuidle_menu.c b/xen/arch/x86/acpi/cpuidle_menu.c
index 6952776..4afaa8d 100644
--- a/xen/arch/x86/acpi/cpuidle_menu.c
+++ b/xen/arch/x86/acpi/cpuidle_menu.c
@@ -36,6 +36,7 @@
#define RESOLUTION 1024
#define DECAY 4
#define MAX_INTERESTING 50000
+#define LATENCY_MULTIPLIER 10
/*
* Concepts and ideas behind the menu governor
@@ -88,6 +89,9 @@
* the average interrupt interval is, the smaller C state latency should be
* and thus the less likely a busy CPU will hit such a deep C state.
*
+ * As an additional rule to reduce the performance impact, menu tries to
+ * limit the exit latency duration to be no more than 10% of the decaying
+ * measured idle time.
*/
struct perf_factor{
@@ -102,6 +106,7 @@ struct menu_device
int last_state_idx;
unsigned int expected_us;
u64 predicted_us;
+ u64 latency_factor;
unsigned int measured_us;
unsigned int exit_us;
unsigned int bucket;
@@ -199,6 +204,10 @@ static int menu_select(struct acpi_processor_power *power)
io_interval = avg_intr_interval_us();
+ data->latency_factor = DIV_ROUND(
+ data->latency_factor * (DECAY - 1) + data->measured_us,
+ DECAY);
+
/*
* if the correction factor is 0 (eg first time init or cpu hotplug
* etc), we actually want to start out with a unity factor.
@@ -220,6 +229,8 @@ static int menu_select(struct acpi_processor_power *power)
break;
if (s->latency * IO_MULTIPLIER > io_interval)
break;
+ if (s->latency * LATENCY_MULTIPLIER > data->latency_factor)
+ break;
/* TBD: we need to check the QoS requirment in future */
data->exit_us = s->latency;
data->last_state_idx = i;
@@ -231,18 +242,16 @@ static int menu_select(struct acpi_processor_power *power)
static void menu_reflect(struct acpi_processor_power *power)
{
struct menu_device *data = &__get_cpu_var(menu_devices);
- unsigned int last_idle_us = power->last_residency;
- unsigned int measured_us;
u64 new_factor;
- measured_us = last_idle_us;
+ data->measured_us = power->last_residency;
/*
* We correct for the exit latency; we are assuming here that the
* exit latency happens after the event that we're interested in.
*/
- if (measured_us > data->exit_us)
- measured_us -= data->exit_us;
+ if (data->measured_us > data->exit_us)
+ data->measured_us -= data->exit_us;
/* update our correction ratio */
@@ -250,7 +259,7 @@ static void menu_reflect(struct acpi_processor_power *power)
* (DECAY - 1) / DECAY;
if (data->expected_us > 0 && data->measured_us < MAX_INTERESTING)
- new_factor += RESOLUTION * measured_us / data->expected_us;
+ new_factor += RESOLUTION * data->measured_us / data->expected_us;
else
/*
* we were idle so long that we count it as a perfect
diff --git a/xen/arch/x86/acpi/suspend.c b/xen/arch/x86/acpi/suspend.c
index 1718930..1d8344c 100644
--- a/xen/arch/x86/acpi/suspend.c
+++ b/xen/arch/x86/acpi/suspend.c
@@ -9,6 +9,7 @@
#include <xen/smp.h>
#include <asm/processor.h>
#include <asm/msr.h>
+#include <asm/debugreg.h>
#include <asm/flushtlb.h>
#include <asm/hvm/hvm.h>
#include <asm/hvm/support.h>
@@ -55,10 +56,7 @@ void restore_rest_processor_state(void)
wrmsrl(MSR_LSTAR, saved_lstar);
wrmsrl(MSR_CSTAR, saved_cstar);
wrmsr(MSR_STAR, 0, (FLAT_RING3_CS32<<16) | __HYPERVISOR_CS);
- wrmsr(MSR_SYSCALL_MASK,
- X86_EFLAGS_VM|X86_EFLAGS_RF|X86_EFLAGS_NT|
- X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_TF,
- 0U);
+ wrmsr(MSR_SYSCALL_MASK, XEN_SYSCALL_MASK, 0U);
wrfsbase(saved_fs_base);
wrgsbase(saved_gs_base);
diff --git a/xen/arch/x86/alternative.c b/xen/arch/x86/alternative.c
new file mode 100644
index 0000000..2743792
--- /dev/null
+++ b/xen/arch/x86/alternative.c
@@ -0,0 +1,213 @@
+/******************************************************************************
+ * alternative.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <xen/types.h>
+#include <asm/processor.h>
+#include <asm/alternative.h>
+#include <xen/init.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/nmi.h>
+
+#define MAX_PATCH_LEN (255-1)
+
+extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
+
+#ifdef K8_NOP1
+static const unsigned char k8nops[] __initconst = {
+ K8_NOP1,
+ K8_NOP2,
+ K8_NOP3,
+ K8_NOP4,
+ K8_NOP5,
+ K8_NOP6,
+ K8_NOP7,
+ K8_NOP8
+};
+static const unsigned char * const k8_nops[ASM_NOP_MAX+1] = {
+ NULL,
+ k8nops,
+ k8nops + 1,
+ k8nops + 1 + 2,
+ k8nops + 1 + 2 + 3,
+ k8nops + 1 + 2 + 3 + 4,
+ k8nops + 1 + 2 + 3 + 4 + 5,
+ k8nops + 1 + 2 + 3 + 4 + 5 + 6,
+ k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7
+};
+#endif
+
+#ifdef P6_NOP1
+static const unsigned char p6nops[] __initconst = {
+ P6_NOP1,
+ P6_NOP2,
+ P6_NOP3,
+ P6_NOP4,
+ P6_NOP5,
+ P6_NOP6,
+ P6_NOP7,
+ P6_NOP8
+};
+static const unsigned char * const p6_nops[ASM_NOP_MAX+1] = {
+ NULL,
+ p6nops,
+ p6nops + 1,
+ p6nops + 1 + 2,
+ p6nops + 1 + 2 + 3,
+ p6nops + 1 + 2 + 3 + 4,
+ p6nops + 1 + 2 + 3 + 4 + 5,
+ p6nops + 1 + 2 + 3 + 4 + 5 + 6,
+ p6nops + 1 + 2 + 3 + 4 + 5 + 6 + 7
+};
+#endif
+
+static const unsigned char * const *ideal_nops __initdata = k8_nops;
+
+static int __init mask_nmi_callback(const struct cpu_user_regs *regs, int cpu)
+{
+ return 1;
+}
+
+static void __init arch_init_ideal_nops(void)
+{
+ /*
+ * Due to a decoder implementation quirk, some
+ * specific Intel CPUs actually perform better with
+ * the "k8_nops" than with the SDM-recommended NOPs.
+ */
+ if ( (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
+ !(boot_cpu_data.x86 == 6 &&
+ boot_cpu_data.x86_model >= 0x0f &&
+ boot_cpu_data.x86_model != 0x1c &&
+ boot_cpu_data.x86_model != 0x26 &&
+ boot_cpu_data.x86_model != 0x27 &&
+ boot_cpu_data.x86_model < 0x30) )
+ ideal_nops = p6_nops;
+}
+
+/* Use this to add nops to a buffer, then text_poke the whole buffer. */
+static void __init add_nops(void *insns, unsigned int len)
+{
+ while ( len > 0 )
+ {
+ unsigned int noplen = len;
+ if ( noplen > ASM_NOP_MAX )
+ noplen = ASM_NOP_MAX;
+ memcpy(insns, ideal_nops[noplen], noplen);
+ insns += noplen;
+ len -= noplen;
+ }
+}
+
+/*
+ * text_poke_early - Update instructions on a live kernel at boot time
+ * @addr: address to modify
+ * @opcode: source of the copy
+ * @len: length to copy
+ *
+ * When you use this code to patch more than one byte of an instruction
+ * you need to make sure that other CPUs cannot execute this code in parallel.
+ * Also no thread must be currently preempted in the middle of these
+ * instructions. And on the local CPU you need to be protected again NMI or MCE
+ * handlers seeing an inconsistent instruction while you patch.
+ *
+ * This routine is called with local interrupt disabled.
+ */
+static void *__init text_poke_early(void *addr, const void *opcode, size_t len)
+{
+ memcpy(addr, opcode, len);
+ sync_core();
+
+ return addr;
+}
+
+/*
+ * Replace instructions with better alternatives for this CPU type.
+ * This runs before SMP is initialized to avoid SMP problems with
+ * self modifying code. This implies that asymmetric systems where
+ * APs have less capabilities than the boot processor are not handled.
+ * Tough. Make sure you disable such features by hand.
+ */
+static void __init apply_alternatives(struct alt_instr *start, struct alt_instr *end)
+{
+ struct alt_instr *a;
+ u8 *instr, *replacement;
+ u8 insnbuf[MAX_PATCH_LEN];
+
+ ASSERT(!local_irq_is_enabled());
+
+ printk(KERN_INFO "alt table %p -> %p\n", start, end);
+
+ /*
+ * The scan order should be from start to end. A later scanned
+ * alternative code can overwrite a previous scanned alternative code.
+ * Some kernel functions (e.g. memcpy, memset, etc) use this order to
+ * patch code.
+ *
+ * So be careful if you want to change the scan order to any other
+ * order.
+ */
+ for ( a = start; a < end; a++ )
+ {
+ instr = (u8 *)&a->instr_offset + a->instr_offset;
+ replacement = (u8 *)&a->repl_offset + a->repl_offset;
+ BUG_ON(a->replacementlen > a->instrlen);
+ BUG_ON(a->instrlen > sizeof(insnbuf));
+ BUG_ON(a->cpuid >= NCAPINTS * 32);
+ if ( !boot_cpu_has(a->cpuid) )
+ continue;
+
+ memcpy(insnbuf, replacement, a->replacementlen);
+
+ /* 0xe8/0xe9 are relative branches; fix the offset. */
+ if ( (*insnbuf & 0xfe) == 0xe8 && a->replacementlen == 5 )
+ *(s32 *)(insnbuf + 1) += replacement - instr;
+
+ add_nops(insnbuf + a->replacementlen,
+ a->instrlen - a->replacementlen);
+ text_poke_early(instr, insnbuf, a->instrlen);
+ }
+}
+
+void __init alternative_instructions(void)
+{
+ nmi_callback_t saved_nmi_callback;
+
+ arch_init_ideal_nops();
+
+ /*
+ * The patching is not fully atomic, so try to avoid local interruptions
+ * that might execute the to be patched code.
+ * Other CPUs are not running.
+ */
+ saved_nmi_callback = set_nmi_callback(mask_nmi_callback);
+
+ /*
+ * Don't stop machine check exceptions while patching.
+ * MCEs only happen when something got corrupted and in this
+ * case we must do something about the corruption.
+ * Ignoring it is worse than a unlikely patching race.
+ * Also machine checks tend to be broadcast and if one CPU
+ * goes into machine check the others follow quickly, so we don't
+ * expect a machine check to cause undue problems during to code
+ * patching.
+ */
+ apply_alternatives(__alt_instructions, __alt_instructions_end);
+
+ set_nmi_callback(saved_nmi_callback);
+}
diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c
index 0e5e302..1de693f 100644
--- a/xen/arch/x86/apic.c
+++ b/xen/arch/x86/apic.c
@@ -145,13 +145,9 @@ int get_physical_broadcast(void)
int get_maxlvt(void)
{
- unsigned int v, ver, maxlvt;
+ unsigned int v = apic_read(APIC_LVR);
- v = apic_read(APIC_LVR);
- ver = GET_APIC_VERSION(v);
- /* 82489DXs do not report # of LVT entries. */
- maxlvt = APIC_INTEGRATED(ver) ? GET_APIC_MAXLVT(v) : 2;
- return maxlvt;
+ return GET_APIC_MAXLVT(v);
}
void clear_local_APIC(void)
@@ -217,12 +213,9 @@ void clear_local_APIC(void)
if (maxlvt >= 6)
apic_write_around(APIC_CMCI, APIC_LVT_MASKED);
- v = GET_APIC_VERSION(apic_read(APIC_LVR));
- if (APIC_INTEGRATED(v)) { /* !82489DX */
- if (maxlvt > 3) /* Due to Pentium errata 3AP and 11AP. */
- apic_write(APIC_ESR, 0);
- apic_read(APIC_ESR);
- }
+ if (maxlvt > 3) /* Due to Pentium errata 3AP and 11AP. */
+ apic_write(APIC_ESR, 0);
+ apic_read(APIC_ESR);
}
void __init connect_bsp_APIC(void)
@@ -314,7 +307,7 @@ void disable_local_APIC(void)
~(MSR_IA32_APICBASE_ENABLE|MSR_IA32_APICBASE_EXTD));
}
- if ( kexecing )
+ if ( kexecing && (current_local_apic_mode() != apic_boot_mode) )
{
uint64_t msr_content;
rdmsrl(MSR_IA32_APICBASE, msr_content);
@@ -330,7 +323,9 @@ void disable_local_APIC(void)
wrmsrl(MSR_IA32_APICBASE, msr_content);
break;
case APIC_MODE_X2APIC:
- msr_content |= (MSR_IA32_APICBASE_ENABLE|MSR_IA32_APICBASE_EXTD);
+ msr_content |= MSR_IA32_APICBASE_ENABLE;
+ wrmsrl(MSR_IA32_APICBASE, msr_content);
+ msr_content |= MSR_IA32_APICBASE_EXTD;
wrmsrl(MSR_IA32_APICBASE, msr_content);
break;
default:
@@ -475,10 +470,7 @@ void __init init_bsp_APIC(void)
* Set up the virtual wire mode.
*/
apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
- value = APIC_DM_NMI;
- if (!APIC_INTEGRATED(ver)) /* 82489DX */
- value |= APIC_LVT_LEVEL_TRIGGER;
- apic_write_around(APIC_LVT1, value);
+ apic_write_around(APIC_LVT1, APIC_DM_NMI);
}
static void apic_pm_activate(void)
@@ -553,7 +545,7 @@ void __devinit setup_local_APIC(void)
/*
* Double-check whether this APIC is really registered.
*/
- if (!apic_id_registered())
+ if (!APIC_INTEGRATED(ver) || !apic_id_registered())
BUG();
/*
@@ -669,11 +661,9 @@ void __devinit setup_local_APIC(void)
value = APIC_DM_NMI;
else
value = APIC_DM_NMI | APIC_LVT_MASKED;
- if (!APIC_INTEGRATED(ver)) /* 82489DX */
- value |= APIC_LVT_LEVEL_TRIGGER;
apic_write_around(APIC_LVT1, value);
- if (APIC_INTEGRATED(ver) && !esr_disable) { /* !82489DX */
+ if (!esr_disable) {
maxlvt = get_maxlvt();
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
apic_write(APIC_ESR, 0);
@@ -692,16 +682,13 @@ void __devinit setup_local_APIC(void)
"vector: %#lx after: %#lx\n",
oldvalue, value);
} else {
- if (esr_disable)
- /*
- * Something untraceble is creating bad interrupts on
- * secondary quads ... for the moment, just leave the
- * ESR disabled - we can't do anything useful with the
- * errors anyway - mbligh
- */
- printk("Leaving ESR disabled.\n");
- else
- printk("No ESR for 82489DX.\n");
+ /*
+ * Something untraceble is creating bad interrupts on
+ * secondary quads ... for the moment, just leave the
+ * ESR disabled - we can't do anything useful with the
+ * errors anyway - mbligh
+ */
+ printk("Leaving ESR disabled.\n");
}
if (nmi_watchdog == NMI_LOCAL_APIC)
@@ -813,12 +800,7 @@ static void __init lapic_disable(char *str)
setup_clear_cpu_cap(X86_FEATURE_APIC);
}
custom_param("nolapic", lapic_disable);
-
-static void __init lapic_enable(char *str)
-{
- enable_local_apic = 1;
-}
-custom_param("lapic", lapic_enable);
+boolean_param("lapic", enable_local_apic);
static void __init apic_set_verbosity(char *str)
{
@@ -1099,13 +1081,10 @@ static void __init wait_8254_wraparound(void)
static void __setup_APIC_LVTT(unsigned int clocks)
{
- unsigned int lvtt_value, tmp_value, ver;
+ unsigned int lvtt_value, tmp_value;
- ver = GET_APIC_VERSION(apic_read(APIC_LVR));
/* NB. Xen uses local APIC timer in one-shot mode. */
lvtt_value = /*APIC_TIMER_MODE_PERIODIC |*/ LOCAL_TIMER_VECTOR;
- if (!APIC_INTEGRATED(ver))
- lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
if ( tdt_enabled )
{
diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile
index 13f4a66..5fdb5ae 100644
--- a/xen/arch/x86/boot/Makefile
+++ b/xen/arch/x86/boot/Makefile
@@ -1,8 +1,8 @@
obj-bin-y += head.o
-head.o: reloc.S
+RELOC_DEPS = $(BASEDIR)/include/asm-x86/config.h $(BASEDIR)/include/xen/multiboot.h
-%.S: %.c
- $(MAKE) -f build32.mk $@
+head.o: reloc.S
-reloc.S: head.S
+reloc.S: reloc.c $(RELOC_DEPS)
+ $(MAKE) -f build32.mk $@ RELOC_DEPS="$(RELOC_DEPS)"
diff --git a/xen/arch/x86/boot/build32.mk b/xen/arch/x86/boot/build32.mk
index a2d4b34..c208249 100644
--- a/xen/arch/x86/boot/build32.mk
+++ b/xen/arch/x86/boot/build32.mk
@@ -20,7 +20,7 @@ CFLAGS := $(filter-out -flto,$(CFLAGS))
%.o: %.c
$(CC) $(CFLAGS) -c -fpic $< -o $@
- $(OBJDUMP) -h $@ | sed -n '/[0-9]/{s,00*,0,g;p}' |\
+ $(OBJDUMP) -h $@ | sed -n '/[0-9]/{s,00*,0,g;p;}' |\
while read idx name sz rest; do \
case "$$name" in \
.data|.data.*|.rodata|.rodata.*|.bss|.bss.*) \
@@ -30,5 +30,6 @@ CFLAGS := $(filter-out -flto,$(CFLAGS))
esac; \
done
-reloc.o: $(BASEDIR)/include/asm-x86/config.h
+reloc.o: reloc.c $(RELOC_DEPS)
+
.PRECIOUS: %.bin %.lnk
diff --git a/xen/arch/x86/boot/cmdline.S b/xen/arch/x86/boot/cmdline.S
index e1f4595..00687eb 100644
--- a/xen/arch/x86/boot/cmdline.S
+++ b/xen/arch/x86/boot/cmdline.S
@@ -329,6 +329,8 @@ cmdline_parse_early:
popa
ret
+ .pushsection .init.rodata, "a", @progbits
+
.Lvga_text_modes: /* rows, mode_number */
.word 25,VIDEO_80x25
.word 50,VIDEO_80x50
@@ -361,3 +363,5 @@ cmdline_parse_early:
.asciz "no"
.Ledd_opt:
.asciz "edd"
+
+ .popsection
diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index b12eefb..c99f739 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -6,6 +6,7 @@
#include <asm/fixmap.h>
#include <asm/page.h>
#include <asm/msr.h>
+#include <asm/cpufeature.h>
.text
.code32
@@ -32,11 +33,19 @@ ENTRY(start)
/* Checksum: must be the negated sum of the first two fields. */
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
- .section .init.text, "ax"
+ .section .init.rodata, "a", @progbits
+ .align 4
+
+ .word 0
+gdt_boot_descr:
+ .word 6*8-1
+ .long sym_phys(trampoline_gdt)
.Lbad_cpu_msg: .asciz "ERR: Not a 64-bit CPU!"
.Lbad_ldr_msg: .asciz "ERR: Not a Multiboot bootloader!"
+ .section .init.text, "ax", @progbits
+
bad_cpu:
mov $(sym_phys(.Lbad_cpu_msg)),%esi # Error message
jmp print_err
@@ -46,11 +55,11 @@ print_err:
mov $0xB8000,%edi # VGA framebuffer
1: mov (%esi),%bl
test %bl,%bl # Terminate on '\0' sentinel
-2: je 2b
+ je .Lhalt
mov $0x3f8+5,%dx # UART Line Status Register
-3: in %dx,%al
+2: in %dx,%al
test $0x20,%al # Test THR Empty flag
- je 3b
+ je 2b
mov $0x3f8+0,%dx # UART Transmit Holding Register
mov %bl,%al
out %al,%dx # Send a character over the serial line
@@ -58,10 +67,8 @@ print_err:
mov $7,%al
stosb # Write an attribute to the VGA framebuffer
jmp 1b
-
-gdt_boot_descr:
- .word 6*8-1
- .long sym_phys(trampoline_gdt)
+.Lhalt: hlt
+ jmp .Lhalt
__start:
cld
@@ -75,7 +82,7 @@ __start:
mov %ecx,%ss
/* Check for Multiboot bootloader */
- cmp $0x2BADB002,%eax
+ cmp $MULTIBOOT_BOOTLOADER_MAGIC,%eax
jne not_multiboot
/* Set up trampoline segment 64k below EBDA */
@@ -94,7 +101,7 @@ __start:
*/
testb $MBI_MEMLIMITS,(%ebx)
jz 2f /* not available? BDA value will be fine */
- mov 4(%ebx),%edx
+ mov MB_mem_lower(%ebx),%edx
cmp $0x100,%edx /* is the multiboot value too small? */
jb 2f /* if so, do not use it */
shl $10-4,%edx
@@ -131,11 +138,17 @@ __start:
mov $0x80000001,%eax
cpuid
1: mov %edx,sym_phys(cpuid_ext_features)
- mov %edx,sym_phys(boot_cpu_data)+CPUINFO86_ext_features
+ mov %edx,sym_phys(boot_cpu_data)+CPUINFO_FEATURE_OFFSET(X86_FEATURE_LM)
/* Check for availability of long mode. */
- bt $29,%edx
+ bt $X86_FEATURE_LM & 0x1f,%edx
jnc bad_cpu
+
+ /* Stash TSC to calculate a good approximation of time-since-boot */
+ rdtsc
+ mov %eax,sym_phys(boot_tsc_stamp)
+ mov %edx,sym_phys(boot_tsc_stamp+4)
+
/* Initialise L2 boot-map page table entries (16MB). */
mov $sym_phys(l2_bootmap),%edx
mov $PAGE_HYPERVISOR|_PAGE_PSE,%eax
diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c
index fa0fb6b..f971920 100644
--- a/xen/arch/x86/boot/reloc.c
+++ b/xen/arch/x86/boot/reloc.c
@@ -1,11 +1,11 @@
-/******************************************************************************
+/*
* reloc.c
- *
+ *
* 32-bit flat memory-map routines for relocating Multiboot structures
* and modules. This is most easily done early with paging disabled.
- *
+ *
* Copyright (c) 2009, Citrix Systems, Inc.
- *
+ *
* Authors:
* Keir Fraser <keir at xen.org>
*/
@@ -21,8 +21,9 @@ asm (
" jmp reloc \n"
);
-/* This is our data. Because the code must be relocatable, no BSS is
- * allowed. All data is accessed PC-relative with inline assembly.
+/*
+ * This is our data. Because the code must be relocatable, no BSS is
+ * allowed. All data is accessed PC-relative with inline assembly.
*/
asm (
"alloc: \n"
@@ -45,7 +46,7 @@ static void *reloc_mbi_struct(void *old, unsigned int bytes)
" mov %0,%%edi \n"
" rep movsb \n"
: "=&r" (new), "+c" (bytes), "+S" (old)
- : : "edx", "edi");
+ : : "edx", "edi", "memory");
return new;
}
diff --git a/xen/arch/x86/boot/trampoline.S b/xen/arch/x86/boot/trampoline.S
index 4f5f8d7..ccb40fb 100644
--- a/xen/arch/x86/boot/trampoline.S
+++ b/xen/arch/x86/boot/trampoline.S
@@ -109,12 +109,9 @@ trampoline_protmode_entry:
.code64
start64:
/* Jump to high mappings. */
- mov high_start(%rip),%rax
+ movabs $__high_start,%rax
jmpq *%rax
-high_start:
- .quad __high_start
-
.code32
trampoline_boot_cpu_entry:
cmpb $0,bootsym_rel(skip_realmode,5)
diff --git a/xen/arch/x86/boot/wakeup.S b/xen/arch/x86/boot/wakeup.S
index a3883c1..08ea9b2 100644
--- a/xen/arch/x86/boot/wakeup.S
+++ b/xen/arch/x86/boot/wakeup.S
@@ -166,12 +166,9 @@ wakeup_32:
.code64
wakeup_64:
/* Jump to high mappings and the higher-level wakeup code. */
- movq ret_point(%rip), %rbx
+ movabs $__ret_point, %rbx
jmp *%rbx
-ret_point:
- .quad __ret_point
-
bogus_saved_magic:
movw $0x0e00 + 'S', 0xb8014
jmp bogus_saved_magic
diff --git a/xen/arch/x86/boot/x86_64.S b/xen/arch/x86/boot/x86_64.S
index 8f92402..bfbafd2 100644
--- a/xen/arch/x86/boot/x86_64.S
+++ b/xen/arch/x86/boot/x86_64.S
@@ -9,8 +9,8 @@
mov %ecx,%gs
mov %ecx,%ss
- /* Enable full CR4 features. */
- mov mmu_cr4_features(%rip),%rcx
+ /* Enable minimal CR4 features. */
+ mov $XEN_MINIMAL_CR4,%rcx
mov %rcx,%cr4
mov stack_start(%rip),%rsp
@@ -25,57 +25,15 @@
leaq 1f(%rip),%rax
pushq %rax
lretq
-1: lidt idt_descr(%rip)
-
+1:
test %ebx,%ebx
jnz start_secondary
- /* Initialise IDT with simple error defaults. */
- leaq ignore_int(%rip),%rcx
- movl %ecx,%eax
- andl $0xFFFF0000,%eax
- orl $0x00008E00,%eax
- shlq $32,%rax
- movl %ecx,%edx
- andl $0x0000FFFF,%edx
- orl $(__HYPERVISOR_CS64<<16),%edx
- orq %rdx,%rax
- shrq $32,%rcx
- movl %ecx,%edx
- leaq idt_table(%rip),%rdi
- movl $256,%ecx
-1: movq %rax,(%rdi)
- movq %rdx,8(%rdi)
- addq $16,%rdi
- loop 1b
-
/* Pass off the Multiboot info structure to C land. */
mov multiboot_ptr(%rip),%edi
call __start_xen
ud2 /* Force a panic (invalid opcode). */
-/* This is the default interrupt handler. */
-int_msg:
- .asciz "Unknown interrupt (cr2=%016lx)\n"
-hex_msg:
- .asciz " %016lx"
-ignore_int:
- SAVE_ALL
- movq %cr2,%rsi
- leaq int_msg(%rip),%rdi
- xorl %eax,%eax
- call printk
- movq %rsp,%rbp
-0: movq (%rbp),%rsi
- addq $8,%rbp
- leaq hex_msg(%rip),%rdi
- xorl %eax,%eax
- call printk
- testq $0xff8,%rbp
- jnz 0b
-1: jmp 1b
-
-
/*** DESCRIPTOR TABLES ***/
.data
@@ -88,11 +46,6 @@ GLOBAL(gdt_descr)
.word LAST_RESERVED_GDT_BYTE
.quad boot_cpu_gdt_table - FIRST_RESERVED_GDT_BYTE
- .word 0,0,0
-GLOBAL(idt_descr)
- .word 256*16-1
- .quad idt_table
-
GLOBAL(stack_start)
.quad cpu0_stack
diff --git a/xen/arch/x86/bzimage.c b/xen/arch/x86/bzimage.c
index d72b832..c86c39e 100644
--- a/xen/arch/x86/bzimage.c
+++ b/xen/arch/x86/bzimage.c
@@ -146,7 +146,7 @@ static __init int perform_gunzip(char *output, char *image, unsigned long image_
return rc;
}
-struct setup_header {
+struct __packed setup_header {
uint8_t _pad0[0x1f1]; /* skip uninteresting stuff */
uint8_t setup_sects;
uint16_t root_flags;
@@ -183,7 +183,7 @@ struct setup_header {
uint64_t hardware_subarch_data;
uint32_t payload_offset;
uint32_t payload_length;
- } __attribute__((packed));
+ };
static __init int bzimage_check(struct setup_header *hdr, unsigned long len)
{
diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index 46c1e48..566cdac 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -30,24 +30,21 @@
* "fam_10_rev_c"
* "fam_11_rev_b"
*/
-static char opt_famrev[14];
+static char __initdata opt_famrev[14];
string_param("cpuid_mask_cpu", opt_famrev);
+static unsigned int __initdata opt_cpuid_mask_l7s0_eax = ~0u;
+integer_param("cpuid_mask_l7s0_eax", opt_cpuid_mask_l7s0_eax);
+static unsigned int __initdata opt_cpuid_mask_l7s0_ebx = ~0u;
+integer_param("cpuid_mask_l7s0_ebx", opt_cpuid_mask_l7s0_ebx);
+
+static unsigned int __initdata opt_cpuid_mask_thermal_ecx = ~0u;
+integer_param("cpuid_mask_thermal_ecx", opt_cpuid_mask_thermal_ecx);
+
/* 1 = allow, 0 = don't allow guest creation, -1 = don't allow boot */
s8 __read_mostly opt_allow_unsafe;
boolean_param("allow_unsafe", opt_allow_unsafe);
-static inline void wrmsr_amd(unsigned int index, unsigned int lo,
- unsigned int hi)
-{
- asm volatile (
- "wrmsr"
- : /* No outputs */
- : "c" (index), "a" (lo),
- "d" (hi), "D" (0x9c5a203a)
- );
-}
-
static inline int rdmsr_amd_safe(unsigned int msr, unsigned int *lo,
unsigned int *hi)
{
@@ -83,6 +80,51 @@ static inline int wrmsr_amd_safe(unsigned int msr, unsigned int lo,
return err;
}
+static const struct cpuidmask {
+ uint16_t fam;
+ char rev[2];
+ unsigned int ecx, edx, ext_ecx, ext_edx;
+} pre_canned[] __initconst = {
+#define CAN(fam, id, rev) { \
+ fam, #rev, \
+ AMD_FEATURES_##id##_REV_##rev##_ECX, \
+ AMD_FEATURES_##id##_REV_##rev##_EDX, \
+ AMD_EXTFEATURES_##id##_REV_##rev##_ECX, \
+ AMD_EXTFEATURES_##id##_REV_##rev##_EDX \
+ }
+#define CAN_FAM(fam, rev) CAN(0x##fam, FAM##fam##h, rev)
+#define CAN_K8(rev) CAN(0x0f, K8, rev)
+ CAN_FAM(11, B),
+ CAN_FAM(10, C),
+ CAN_FAM(10, B),
+ CAN_K8(G),
+ CAN_K8(F),
+ CAN_K8(E),
+ CAN_K8(D),
+ CAN_K8(C)
+#undef CAN
+};
+
+static const struct cpuidmask *__init noinline get_cpuidmask(const char *opt)
+{
+ unsigned long fam;
+ char rev;
+ unsigned int i;
+
+ if (strncmp(opt, "fam_", 4))
+ return NULL;
+ fam = simple_strtoul(opt + 4, &opt, 16);
+ if (strncmp(opt, "_rev_", 5) || !opt[5] || opt[6])
+ return NULL;
+ rev = toupper(opt[5]);
+
+ for (i = 0; i < ARRAY_SIZE(pre_canned); ++i)
+ if (fam == pre_canned[i].fam && rev == *pre_canned[i].rev)
+ return &pre_canned[i];
+
+ return NULL;
+}
+
/*
* Mask the features and extended features returned by CPUID. Parameters are
* set from the boot line via two methods:
@@ -96,7 +138,12 @@ static void __devinit set_cpuidmask(const struct cpuinfo_x86 *c)
{
static unsigned int feat_ecx, feat_edx;
static unsigned int extfeat_ecx, extfeat_edx;
+ static unsigned int l7s0_eax, l7s0_ebx;
+ static unsigned int thermal_ecx;
+ static bool_t skip_feat, skip_extfeat;
+ static bool_t skip_l7s0_eax_ebx, skip_thermal_ecx;
static enum { not_parsed, no_mask, set_mask } status;
+ unsigned int eax, ebx, ecx, edx;
if (status == no_mask)
return;
@@ -104,7 +151,7 @@ static void __devinit set_cpuidmask(const struct cpuinfo_x86 *c)
if (status == set_mask)
goto setmask;
- ASSERT((status == not_parsed) && (smp_processor_id() == 0));
+ ASSERT((status == not_parsed) && (c == &boot_cpu_data));
status = no_mask;
/* Fam11 doesn't support masking at all. */
@@ -112,57 +159,30 @@ static void __devinit set_cpuidmask(const struct cpuinfo_x86 *c)
return;
if (~(opt_cpuid_mask_ecx & opt_cpuid_mask_edx &
- opt_cpuid_mask_ext_ecx & opt_cpuid_mask_ext_edx)) {
+ opt_cpuid_mask_ext_ecx & opt_cpuid_mask_ext_edx &
+ opt_cpuid_mask_l7s0_eax & opt_cpuid_mask_l7s0_ebx &
+ opt_cpuid_mask_thermal_ecx)) {
feat_ecx = opt_cpuid_mask_ecx;
feat_edx = opt_cpuid_mask_edx;
extfeat_ecx = opt_cpuid_mask_ext_ecx;
extfeat_edx = opt_cpuid_mask_ext_edx;
+ l7s0_eax = opt_cpuid_mask_l7s0_eax;
+ l7s0_ebx = opt_cpuid_mask_l7s0_ebx;
+ thermal_ecx = opt_cpuid_mask_thermal_ecx;
} else if (*opt_famrev == '\0') {
return;
- } else if (!strcmp(opt_famrev, "fam_0f_rev_c")) {
- feat_ecx = AMD_FEATURES_K8_REV_C_ECX;
- feat_edx = AMD_FEATURES_K8_REV_C_EDX;
- extfeat_ecx = AMD_EXTFEATURES_K8_REV_C_ECX;
- extfeat_edx = AMD_EXTFEATURES_K8_REV_C_EDX;
- } else if (!strcmp(opt_famrev, "fam_0f_rev_d")) {
- feat_ecx = AMD_FEATURES_K8_REV_D_ECX;
- feat_edx = AMD_FEATURES_K8_REV_D_EDX;
- extfeat_ecx = AMD_EXTFEATURES_K8_REV_D_ECX;
- extfeat_edx = AMD_EXTFEATURES_K8_REV_D_EDX;
- } else if (!strcmp(opt_famrev, "fam_0f_rev_e")) {
- feat_ecx = AMD_FEATURES_K8_REV_E_ECX;
- feat_edx = AMD_FEATURES_K8_REV_E_EDX;
- extfeat_ecx = AMD_EXTFEATURES_K8_REV_E_ECX;
- extfeat_edx = AMD_EXTFEATURES_K8_REV_E_EDX;
- } else if (!strcmp(opt_famrev, "fam_0f_rev_f")) {
- feat_ecx = AMD_FEATURES_K8_REV_F_ECX;
- feat_edx = AMD_FEATURES_K8_REV_F_EDX;
- extfeat_ecx = AMD_EXTFEATURES_K8_REV_F_ECX;
- extfeat_edx = AMD_EXTFEATURES_K8_REV_F_EDX;
- } else if (!strcmp(opt_famrev, "fam_0f_rev_g")) {
- feat_ecx = AMD_FEATURES_K8_REV_G_ECX;
- feat_edx = AMD_FEATURES_K8_REV_G_EDX;
- extfeat_ecx = AMD_EXTFEATURES_K8_REV_G_ECX;
- extfeat_edx = AMD_EXTFEATURES_K8_REV_G_EDX;
- } else if (!strcmp(opt_famrev, "fam_10_rev_b")) {
- feat_ecx = AMD_FEATURES_FAM10h_REV_B_ECX;
- feat_edx = AMD_FEATURES_FAM10h_REV_B_EDX;
- extfeat_ecx = AMD_EXTFEATURES_FAM10h_REV_B_ECX;
- extfeat_edx = AMD_EXTFEATURES_FAM10h_REV_B_EDX;
- } else if (!strcmp(opt_famrev, "fam_10_rev_c")) {
- feat_ecx = AMD_FEATURES_FAM10h_REV_C_ECX;
- feat_edx = AMD_FEATURES_FAM10h_REV_C_EDX;
- extfeat_ecx = AMD_EXTFEATURES_FAM10h_REV_C_ECX;
- extfeat_edx = AMD_EXTFEATURES_FAM10h_REV_C_EDX;
- } else if (!strcmp(opt_famrev, "fam_11_rev_b")) {
- feat_ecx = AMD_FEATURES_FAM11h_REV_B_ECX;
- feat_edx = AMD_FEATURES_FAM11h_REV_B_EDX;
- extfeat_ecx = AMD_EXTFEATURES_FAM11h_REV_B_ECX;
- extfeat_edx = AMD_EXTFEATURES_FAM11h_REV_B_EDX;
} else {
- printk("Invalid processor string: %s\n", opt_famrev);
- printk("CPUID will not be masked\n");
- return;
+ const struct cpuidmask *m = get_cpuidmask(opt_famrev);
+
+ if (!m) {
+ printk("Invalid processor string: %s\n", opt_famrev);
+ printk("CPUID will not be masked\n");
+ return;
+ }
+ feat_ecx = m->ecx;
+ feat_edx = m->edx;
+ extfeat_ecx = m->ext_ecx;
+ extfeat_edx = m->ext_edx;
}
/* Setting bits in the CPUID mask MSR that are not set in the
@@ -179,14 +199,53 @@ static void __devinit set_cpuidmask(const struct cpuinfo_x86 *c)
printk("Writing CPUID extended feature mask ECX:EDX -> %08Xh:%08Xh\n",
extfeat_ecx, extfeat_edx);
+ if (c->cpuid_level >= 7)
+ cpuid_count(7, 0, &eax, &ebx, &ecx, &edx);
+ else
+ ebx = eax = 0;
+ if ((eax | ebx) && ~(l7s0_eax & l7s0_ebx)) {
+ if (l7s0_eax > eax)
+ l7s0_eax = eax;
+ l7s0_ebx &= ebx;
+ printk("Writing CPUID leaf 7 subleaf 0 feature mask EAX:EBX -> %08Xh:%08Xh\n",
+ l7s0_eax, l7s0_ebx);
+ } else
+ skip_l7s0_eax_ebx = 1;
+
+ /* Only Fam15 has the respective MSR. */
+ ecx = c->x86 == 0x15 && c->cpuid_level >= 6 ? cpuid_ecx(6) : 0;
+ if (ecx && ~thermal_ecx) {
+ thermal_ecx &= ecx;
+ printk("Writing CPUID thermal/power feature mask ECX -> %08Xh\n",
+ thermal_ecx);
+ } else
+ skip_thermal_ecx = 1;
+
setmask:
/* AMD processors prior to family 10h required a 32-bit password */
- if (c->x86 >= 0x10) {
- wrmsr(MSR_K8_FEATURE_MASK, feat_edx, feat_ecx);
- wrmsr(MSR_K8_EXT_FEATURE_MASK, extfeat_edx, extfeat_ecx);
- } else {
- wrmsr_amd(MSR_K8_FEATURE_MASK, feat_edx, feat_ecx);
- wrmsr_amd(MSR_K8_EXT_FEATURE_MASK, extfeat_edx, extfeat_ecx);
+ if (!skip_feat &&
+ wrmsr_amd_safe(MSR_K8_FEATURE_MASK, feat_edx, feat_ecx)) {
+ skip_feat = 1;
+ printk("Failed to set CPUID feature mask\n");
+ }
+
+ if (!skip_extfeat &&
+ wrmsr_amd_safe(MSR_K8_EXT_FEATURE_MASK, extfeat_edx, extfeat_ecx)) {
+ skip_extfeat = 1;
+ printk("Failed to set CPUID extended feature mask\n");
+ }
+
+ if (!skip_l7s0_eax_ebx &&
+ wrmsr_amd_safe(MSR_AMD_L7S0_FEATURE_MASK, l7s0_ebx, l7s0_eax)) {
+ skip_l7s0_eax_ebx = 1;
+ printk("Failed to set CPUID leaf 7 subleaf 0 feature mask\n");
+ }
+
+ if (!skip_thermal_ecx &&
+ (rdmsr_amd_safe(MSR_AMD_THRM_FEATURE_MASK, &eax, &edx) ||
+ wrmsr_amd_safe(MSR_AMD_THRM_FEATURE_MASK, thermal_ecx, edx))){
+ skip_thermal_ecx = 1;
+ printk("Failed to set CPUID thermal/power feature mask\n");
}
}
@@ -326,7 +385,6 @@ static void check_syscfg_dram_mod_en(void)
static void __devinit amd_get_topology(struct cpuinfo_x86 *c)
{
-#ifdef CONFIG_X86_HT
int cpu;
unsigned bits;
@@ -364,7 +422,6 @@ static void __devinit amd_get_topology(struct cpuinfo_x86 *c)
"Core",
cpu_has(c, X86_FEATURE_TOPOEXT) ? c->compute_unit_id :
c->cpu_core_id);
-#endif
}
static void __devinit init_amd(struct cpuinfo_x86 *c)
@@ -402,13 +459,9 @@ static void __devinit init_amd(struct cpuinfo_x86 *c)
* revision D (model = 0x14) and later actually support it.
* (AMD Erratum #110, docId: 25759).
*/
- unsigned int lo, hi;
-
clear_bit(X86_FEATURE_LAHF_LM, c->x86_capability);
- if (!rdmsr_amd_safe(0xc001100d, &lo, &hi)) {
- hi &= ~1;
- wrmsr_amd_safe(0xc001100d, lo, hi);
- }
+ if (!rdmsr_amd_safe(0xc001100d, &l, &h))
+ wrmsr_amd_safe(0xc001100d, l, h & ~1);
}
switch(c->x86)
@@ -422,11 +475,11 @@ static void __devinit init_amd(struct cpuinfo_x86 *c)
display_cacheinfo(c);
- if (cpuid_eax(0x80000000) >= 0x80000008) {
+ if (c->extended_cpuid_level >= 0x80000008) {
c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
}
- if (cpuid_eax(0x80000000) >= 0x80000007) {
+ if (c->extended_cpuid_level >= 0x80000007) {
c->x86_power = cpuid_edx(0x80000007);
if (c->x86_power & (1<<8)) {
set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c
index 4221826..5c8d3c2 100644
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -74,7 +74,7 @@ int __cpuinit get_model_name(struct cpuinfo_x86 *c)
unsigned int *v;
char *p, *q;
- if (cpuid_eax(0x80000000) < 0x80000004)
+ if (c->extended_cpuid_level < 0x80000004)
return 0;
v = (unsigned int *) c->x86_model_id;
@@ -101,11 +101,9 @@ int __cpuinit get_model_name(struct cpuinfo_x86 *c)
void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
{
- unsigned int n, dummy, ecx, edx, l2size;
+ unsigned int dummy, ecx, edx, l2size;
- n = cpuid_eax(0x80000000);
-
- if (n >= 0x80000005) {
+ if (c->extended_cpuid_level >= 0x80000005) {
cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
if (opt_cpu_info)
printk("CPU: L1 I cache %dK (%d bytes/line),"
@@ -114,7 +112,7 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
c->x86_cache_size=(ecx>>24)+(edx>>24);
}
- if (n < 0x80000006) /* Some chips just has a large L1. */
+ if (c->extended_cpuid_level < 0x80000006) /* Some chips just has a large L1. */
return;
ecx = cpuid_ecx(0x80000006);
@@ -154,6 +152,22 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
this_cpu = &default_cpu;
}
+static inline u32 _phys_pkg_id(u32 cpuid_apic, int index_msb)
+{
+ return cpuid_apic >> index_msb;
+}
+
+/*
+ * cpuid returns the value latched in the HW at reset, not the APIC ID
+ * register's value. For any box whose BIOS changes APIC IDs, like
+ * clustered APIC systems, we must use hard_smp_processor_id.
+ *
+ * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID.
+ */
+static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb)
+{
+ return _phys_pkg_id(hard_smp_processor_id(), index_msb);
+}
/* Do minimum CPU detection early.
Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
@@ -195,7 +209,7 @@ static void __init early_cpu_detect(void)
static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
{
- u32 tfms, xlvl, capability, excap, ebx;
+ u32 tfms, capability, excap, ebx;
/* Get vendor name */
cpuid(0x00000000, &c->cpuid_level,
@@ -218,19 +232,21 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
if (c->x86 >= 0x6)
c->x86_model += ((tfms >> 16) & 0xF) << 4;
c->x86_mask = tfms & 15;
+ c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
+ c->phys_proc_id = c->apicid;
if ( cpu_has(c, X86_FEATURE_CLFLSH) )
c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8;
/* AMD-defined flags: level 0x80000001 */
- xlvl = cpuid_eax(0x80000000);
- if ( (xlvl & 0xffff0000) == 0x80000000 ) {
- if ( xlvl >= 0x80000001 ) {
+ c->extended_cpuid_level = cpuid_eax(0x80000000);
+ if ( (c->extended_cpuid_level & 0xffff0000) == 0x80000000 ) {
+ if ( c->extended_cpuid_level >= 0x80000001 ) {
c->x86_capability[1] = cpuid_edx(0x80000001);
c->x86_capability[6] = cpuid_ecx(0x80000001);
}
- if ( xlvl >= 0x80000004 )
+ if ( c->extended_cpuid_level >= 0x80000004 )
get_model_name(c); /* Default name */
- if ( xlvl >= 0x80000008 )
+ if ( c->extended_cpuid_level >= 0x80000008 )
paddr_bits = cpuid_eax(0x80000008) & 0xff;
}
@@ -243,10 +259,6 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
cpuid_count(0x00000007, 0, &dummy, &ebx, &dummy, &dummy);
c->x86_capability[X86_FEATURE_FSGSBASE / 32] = ebx;
}
-
-#ifdef CONFIG_X86_HT
- c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
-#endif
}
/*
@@ -273,23 +285,12 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
generic_identify(c);
#ifdef NOISY_CAPS
- printk(KERN_DEBUG "CPU: After generic identify, caps:");
+ printk(KERN_DEBUG "CPU: After vendor identify, caps:");
for (i = 0; i < NCAPINTS; i++)
printk(" %08x", c->x86_capability[i]);
printk("\n");
#endif
- if (this_cpu->c_identify) {
- this_cpu->c_identify(c);
-
-#ifdef NOISY_CAPS
- printk(KERN_DEBUG "CPU: After vendor identify, caps:");
- for (i = 0; i < NCAPINTS; i++)
- printk(" %08x", c->x86_capability[i]);
- printk("\n");
-#endif
- }
-
/*
* Vendor-specific initialization. In this section we
* canonicalize the feature flags, meaning if there are
@@ -353,17 +354,6 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
}
}
-/* cpuid returns the value latched in the HW at reset, not the APIC ID
- * register's value. For any box whose BIOS changes APIC IDs, like
- * clustered APIC systems, we must use hard_smp_processor_id.
- *
- * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID.
- */
-static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb)
-{
- return hard_smp_processor_id() >> index_msb;
-}
-
/* leaf 0xb SMT level */
#define SMT_LEVEL 0
@@ -437,32 +427,22 @@ void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c)
}
}
-#ifdef CONFIG_X86_HT
void __cpuinit detect_ht(struct cpuinfo_x86 *c)
{
u32 eax, ebx, ecx, edx;
int index_msb, core_bits;
- cpuid(1, &eax, &ebx, &ecx, &edx);
-
- c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
-
- if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)
- || cpu_has(c, X86_FEATURE_XTOPOLOGY))
+ if (!cpu_has(c, X86_FEATURE_HT) ||
+ cpu_has(c, X86_FEATURE_CMP_LEGACY) ||
+ cpu_has(c, X86_FEATURE_XTOPOLOGY))
return;
+ cpuid(1, &eax, &ebx, &ecx, &edx);
c->x86_num_siblings = (ebx & 0xff0000) >> 16;
if (c->x86_num_siblings == 1) {
printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
} else if (c->x86_num_siblings > 1 ) {
-
- if (c->x86_num_siblings > nr_cpu_ids) {
- printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", c->x86_num_siblings);
- c->x86_num_siblings = 1;
- return;
- }
-
index_msb = get_count_order(c->x86_num_siblings);
c->phys_proc_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
@@ -484,7 +464,43 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
c->cpu_core_id);
}
}
-#endif
+
+unsigned int __init apicid_to_socket(unsigned int apicid)
+{
+ unsigned int dummy;
+
+ if (boot_cpu_has(X86_FEATURE_XTOPOLOGY)) {
+ unsigned int eax, ecx, sub_index = 1, core_plus_mask_width;
+
+ cpuid_count(0xb, SMT_LEVEL, &eax, &dummy, &dummy, &dummy);
+ core_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
+ do {
+ cpuid_count(0xb, sub_index, &eax, &dummy, &ecx,
+ &dummy);
+
+ if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) {
+ core_plus_mask_width =
+ BITS_SHIFT_NEXT_LEVEL(eax);
+ break;
+ }
+
+ sub_index++;
+ } while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE);
+
+ return _phys_pkg_id(apicid, core_plus_mask_width);
+ }
+
+ if (boot_cpu_has(X86_FEATURE_HT) &&
+ !boot_cpu_has(X86_FEATURE_CMP_LEGACY)) {
+ unsigned int num_siblings = (cpuid_ebx(1) & 0xff0000) >> 16;
+
+ if (num_siblings)
+ return _phys_pkg_id(apicid,
+ get_count_order(num_siblings));
+ }
+
+ return apicid;
+}
void __cpuinit print_cpu_info(unsigned int cpu)
{
@@ -529,6 +545,61 @@ void __init early_cpu_init(void)
centaur_init_cpu();
early_cpu_detect();
}
+
+/*
+ * Sets up system tables and descriptors.
+ *
+ * - Sets up TSS with stack pointers, including ISTs
+ * - Inserts TSS selector into regular and compat GDTs
+ * - Loads GDT, IDT, TR then null LDT
+ */
+void __cpuinit load_system_tables(void)
+{
+ unsigned int cpu = smp_processor_id();
+ unsigned long stack_bottom = get_stack_bottom(),
+ stack_top = stack_bottom & ~(STACK_SIZE - 1);
+
+ struct tss_struct *tss = &this_cpu(init_tss);
+ struct desc_struct *gdt =
+ this_cpu(gdt_table) - FIRST_RESERVED_GDT_ENTRY;
+ struct desc_struct *compat_gdt =
+ this_cpu(compat_gdt_table) - FIRST_RESERVED_GDT_ENTRY;
+
+ const struct desc_ptr gdtr = {
+ .base = (unsigned long)gdt,
+ .limit = LAST_RESERVED_GDT_BYTE,
+ };
+ const struct desc_ptr idtr = {
+ .base = (unsigned long)idt_tables[cpu],
+ .limit = (IDT_ENTRIES * sizeof(idt_entry_t)) - 1,
+ };
+
+ /* Main stack for interrupts/exceptions. */
+ tss->rsp0 = stack_bottom;
+ tss->bitmap = IOBMP_INVALID_OFFSET;
+
+ /* MCE, NMI and Double Fault handlers get their own stacks. */
+ tss->ist[IST_MCE - 1] = stack_top + IST_MCE * PAGE_SIZE;
+ tss->ist[IST_DF - 1] = stack_top + IST_DF * PAGE_SIZE;
+ tss->ist[IST_NMI - 1] = stack_top + IST_NMI * PAGE_SIZE;
+
+ _set_tssldt_desc(
+ gdt + TSS_ENTRY,
+ (unsigned long)tss,
+ offsetof(struct tss_struct, __cacheline_filler) - 1,
+ SYS_DESC_tss_avail);
+ _set_tssldt_desc(
+ compat_gdt + TSS_ENTRY,
+ (unsigned long)tss,
+ offsetof(struct tss_struct, __cacheline_filler) - 1,
+ SYS_DESC_tss_busy);
+
+ asm volatile ("lgdt %0" : : "m" (gdtr) );
+ asm volatile ("lidt %0" : : "m" (idtr) );
+ asm volatile ("ltr %w0" : : "rm" (TSS_ENTRY << 3) );
+ asm volatile ("lldt %w0" : : "rm" (0) );
+}
+
/*
* cpu_init() initializes state that is per-CPU. Some data is already
* initialized (naturally) in the bootstrap process, such as the GDT
@@ -538,11 +609,6 @@ void __init early_cpu_init(void)
void __cpuinit cpu_init(void)
{
int cpu = smp_processor_id();
- struct tss_struct *t = &this_cpu(init_tss);
- struct desc_ptr gdt_desc = {
- .base = (unsigned long)(this_cpu(gdt_table) - FIRST_RESERVED_GDT_ENTRY),
- .limit = LAST_RESERVED_GDT_BYTE
- };
if (cpumask_test_and_set_cpu(cpu, &cpu_initialized)) {
printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
@@ -557,22 +623,9 @@ void __cpuinit cpu_init(void)
/* Install correct page table. */
write_ptbase(current);
- asm volatile ( "lgdt %0" : : "m" (gdt_desc) );
-
- /* No nested task. */
- asm volatile ("pushf ; andw $0xbfff,(%"__OP"sp) ; popf" );
-
/* Ensure FPU gets initialised for each domain. */
stts();
- /* Set up and load the per-CPU TSS and LDT. */
- t->bitmap = IOBMP_INVALID_OFFSET;
- /* Bottom-of-stack must be 16-byte aligned! */
- BUG_ON((get_stack_bottom() & 15) != 0);
- t->rsp0 = get_stack_bottom();
- load_TR();
- asm volatile ( "lldt %%ax" : : "a" (0) );
-
/* Clear all 6 debug registers: */
#define CD(register) asm volatile ( "mov %0,%%db" #register : : "r"(0UL) );
CD(0); CD(1); CD(2); CD(3); /* no db4 and db5 */; CD(6); CD(7);
diff --git a/xen/arch/x86/cpu/cpu.h b/xen/arch/x86/cpu/cpu.h
index a7b7421..68563bb 100644
--- a/xen/arch/x86/cpu/cpu.h
+++ b/xen/arch/x86/cpu/cpu.h
@@ -6,7 +6,6 @@ struct cpu_dev {
char * c_ident[2];
void (*c_init)(struct cpuinfo_x86 * c);
- void (*c_identify)(struct cpuinfo_x86 * c);
};
extern struct cpu_dev * cpu_devs [X86_VENDOR_NUM];
diff --git a/xen/arch/x86/cpu/intel.c b/xen/arch/x86/cpu/intel.c
index 992650f..9868cd5 100644
--- a/xen/arch/x86/cpu/intel.c
+++ b/xen/arch/x86/cpu/intel.c
@@ -21,7 +21,8 @@
static unsigned int probe_intel_cpuid_faulting(void)
{
uint64_t x;
- return !rdmsr_safe(MSR_INTEL_PLATFORM_INFO, x) && (x & (1u<<31));
+ return !rdmsr_safe(MSR_INTEL_PLATFORM_INFO, x) &&
+ (x & MSR_PLATFORM_INFO_CPUID_FAULTING);
}
static DEFINE_PER_CPU(bool_t, cpuid_faulting_enabled);
@@ -34,9 +35,9 @@ void set_cpuid_faulting(bool_t enable)
return;
rdmsr(MSR_INTEL_MISC_FEATURES_ENABLES, lo, hi);
- lo &= ~1;
+ lo &= ~MSR_MISC_FEATURES_CPUID_FAULTING;
if (enable)
- lo |= 1;
+ lo |= MSR_MISC_FEATURES_CPUID_FAULTING;
wrmsr(MSR_INTEL_MISC_FEATURES_ENABLES, lo, hi);
this_cpu(cpuid_faulting_enabled) = enable;
@@ -50,68 +51,109 @@ void set_cpuid_faulting(bool_t enable)
*/
static void __devinit set_cpuidmask(const struct cpuinfo_x86 *c)
{
- u32 eax, edx;
- const char *extra = "";
+ static unsigned int msr_basic, msr_ext, msr_xsave;
+ static enum { not_parsed, no_mask, set_mask } status;
+ u64 msr_val;
+
+ if (status == no_mask)
+ return;
+
+ if (status == set_mask)
+ goto setmask;
+
+ ASSERT((status == not_parsed) && (c == &boot_cpu_data));
+ status = no_mask;
if (!~(opt_cpuid_mask_ecx & opt_cpuid_mask_edx &
opt_cpuid_mask_ext_ecx & opt_cpuid_mask_ext_edx &
- opt_cpuid_mask_xsave_eax))
+ opt_cpuid_mask_xsave_eax))
return;
- /* Only family 6 supports this feature */
- switch ((c->x86 == 6) * c->x86_model) {
- case 0x17:
- if ((c->x86_mask & 0x0f) < 4)
- break;
- /* fall through */
- case 0x1d:
- wrmsr(MSR_INTEL_CPUID_FEATURE_MASK,
- opt_cpuid_mask_ecx,
- opt_cpuid_mask_edx);
- if (~(opt_cpuid_mask_ext_ecx & opt_cpuid_mask_ext_edx))
- extra = "extended ";
- else if (~opt_cpuid_mask_xsave_eax)
- extra = "xsave ";
- else
- return;
+ /* Only family 6 supports this feature. */
+ if (c->x86 != 6) {
+ printk("No CPUID feature masking support available\n");
+ return;
+ }
+
+ switch (c->x86_model) {
+ case 0x17: /* Yorkfield, Wolfdale, Penryn, Harpertown(DP) */
+ case 0x1d: /* Dunnington(MP) */
+ msr_basic = MSR_INTEL_MASK_V1_CPUID1;
break;
-/*
- * CPU supports this feature if the processor signature meets the following:
- * (CPUID.(EAX=01h):EAX) > 000106A2h, or
- * (CPUID.(EAX=01h):EAX) == 000106Exh, 0002065xh, 000206Cxh, 000206Exh, or 000206Fxh
- *
- */
- case 0x1a:
- if ((c->x86_mask & 0x0f) <= 2)
- break;
- /* fall through */
- case 0x1e: case 0x1f:
- case 0x25: case 0x2c: case 0x2e: case 0x2f:
- wrmsr(MSR_INTEL_CPUID1_FEATURE_MASK,
- opt_cpuid_mask_ecx,
- opt_cpuid_mask_edx);
- wrmsr(MSR_INTEL_CPUID80000001_FEATURE_MASK,
- opt_cpuid_mask_ext_ecx,
- opt_cpuid_mask_ext_edx);
- if (!~opt_cpuid_mask_xsave_eax)
- return;
- extra = "xsave ";
+
+ case 0x1a: /* Bloomfield, Nehalem-EP(Gainestown) */
+ case 0x1e: /* Clarksfield, Lynnfield, Jasper Forest */
+ case 0x1f: /* Something Nehalem-based - perhaps Auburndale/Havendale? */
+ case 0x25: /* Arrandale, Clarksdale */
+ case 0x2c: /* Gulftown, Westmere-EP */
+ case 0x2e: /* Nehalem-EX(Beckton) */
+ case 0x2f: /* Westmere-EX */
+ msr_basic = MSR_INTEL_MASK_V2_CPUID1;
+ msr_ext = MSR_INTEL_MASK_V2_CPUID80000001;
+ break;
+
+ case 0x2a: /* SandyBridge */
+ case 0x2d: /* SandyBridge-E, SandyBridge-EN, SandyBridge-EP */
+ msr_basic = MSR_INTEL_MASK_V3_CPUID1;
+ msr_ext = MSR_INTEL_MASK_V3_CPUID80000001;
+ msr_xsave = MSR_INTEL_MASK_V3_CPUIDD_01;
break;
- case 0x2a: case 0x2d:
- wrmsr(MSR_INTEL_CPUID1_FEATURE_MASK_V2,
- opt_cpuid_mask_ecx,
- opt_cpuid_mask_edx);
- rdmsr(MSR_INTEL_CPUIDD_01_FEATURE_MASK, eax, edx);
- wrmsr(MSR_INTEL_CPUIDD_01_FEATURE_MASK,
- opt_cpuid_mask_xsave_eax, edx);
- wrmsr(MSR_INTEL_CPUID80000001_FEATURE_MASK_V2,
- opt_cpuid_mask_ext_ecx,
- opt_cpuid_mask_ext_edx);
- return;
}
- printk(XENLOG_ERR "Cannot set CPU %sfeature mask on CPU#%d\n",
- extra, smp_processor_id());
+ status = set_mask;
+
+ if (~(opt_cpuid_mask_ecx & opt_cpuid_mask_edx)) {
+ if (msr_basic)
+ printk("Writing CPUID feature mask ecx:edx -> %08x:%08x\n",
+ opt_cpuid_mask_ecx, opt_cpuid_mask_edx);
+ else
+ printk("No CPUID feature mask available\n");
+ }
+ else
+ msr_basic = 0;
+
+ if (~(opt_cpuid_mask_ext_ecx & opt_cpuid_mask_ext_edx)) {
+ if (msr_ext)
+ printk("Writing CPUID extended feature mask ecx:edx -> %08x:%08x\n",
+ opt_cpuid_mask_ext_ecx, opt_cpuid_mask_ext_edx);
+ else
+ printk("No CPUID extended feature mask available\n");
+ }
+ else
+ msr_ext = 0;
+
+ if (~opt_cpuid_mask_xsave_eax) {
+ if (msr_xsave)
+ printk("Writing CPUID xsave feature mask eax -> %08x\n",
+ opt_cpuid_mask_xsave_eax);
+ else
+ printk("No CPUID xsave feature mask available\n");
+ }
+ else
+ msr_xsave = 0;
+
+ setmask:
+ if (msr_basic &&
+ wrmsr_safe(msr_basic,
+ ((u64)opt_cpuid_mask_edx << 32) | opt_cpuid_mask_ecx)){
+ msr_basic = 0;
+ printk("Failed to set CPUID feature mask\n");
+ }
+
+ if (msr_ext &&
+ wrmsr_safe(msr_ext,
+ ((u64)opt_cpuid_mask_ext_edx << 32) | opt_cpuid_mask_ext_ecx)){
+ msr_ext = 0;
+ printk("Failed to set CPUID extended feature mask\n");
+ }
+
+ if (msr_xsave &&
+ (rdmsr_safe(msr_xsave, msr_val) ||
+ wrmsr_safe(msr_xsave,
+ (msr_val & (~0ULL << 32)) | opt_cpuid_mask_xsave_eax))){
+ msr_xsave = 0;
+ printk("Failed to set CPUID xsave feature mask\n");
+ }
}
void __devinit early_intel_workaround(struct cpuinfo_x86 *c)
@@ -221,6 +263,11 @@ static void __devinit init_intel(struct cpuinfo_x86 *c)
if (!cpu_has_cpuid_faulting)
set_cpuidmask(c);
+ else if ((c == &boot_cpu_data) &&
+ (~(opt_cpuid_mask_ecx & opt_cpuid_mask_edx &
+ opt_cpuid_mask_ext_ecx & opt_cpuid_mask_ext_edx &
+ opt_cpuid_mask_xsave_eax)))
+ printk("No CPUID feature masking support available\n");
/* Work around errata */
Intel_errata_workarounds(c);
diff --git a/xen/arch/x86/cpu/intel_cacheinfo.c b/xen/arch/x86/cpu/intel_cacheinfo.c
index 430f939..48970c0 100644
--- a/xen/arch/x86/cpu/intel_cacheinfo.c
+++ b/xen/arch/x86/cpu/intel_cacheinfo.c
@@ -81,54 +81,9 @@ static struct _cache_table cache_table[] __cpuinitdata =
{ 0x00, 0, 0}
};
-
-enum _cache_type
-{
- CACHE_TYPE_NULL = 0,
- CACHE_TYPE_DATA = 1,
- CACHE_TYPE_INST = 2,
- CACHE_TYPE_UNIFIED = 3
-};
-
-union _cpuid4_leaf_eax {
- struct {
- enum _cache_type type:5;
- unsigned int level:3;
- unsigned int is_self_initializing:1;
- unsigned int is_fully_associative:1;
- unsigned int reserved:4;
- unsigned int num_threads_sharing:12;
- unsigned int num_cores_on_die:6;
- } split;
- u32 full;
-};
-
-union _cpuid4_leaf_ebx {
- struct {
- unsigned int coherency_line_size:12;
- unsigned int physical_line_partition:10;
- unsigned int ways_of_associativity:10;
- } split;
- u32 full;
-};
-
-union _cpuid4_leaf_ecx {
- struct {
- unsigned int number_of_sets:32;
- } split;
- u32 full;
-};
-
-struct _cpuid4_info {
- union _cpuid4_leaf_eax eax;
- union _cpuid4_leaf_ebx ebx;
- union _cpuid4_leaf_ecx ecx;
- unsigned long size;
-};
-
unsigned short num_cache_leaves;
-static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
+int cpuid4_cache_lookup(int index, struct cpuid4_info *this_leaf)
{
union _cpuid4_leaf_eax eax;
union _cpuid4_leaf_ebx ebx;
@@ -185,7 +140,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
* parameters cpuid leaf to find the cache details
*/
for (i = 0; i < num_cache_leaves; i++) {
- struct _cpuid4_info this_leaf;
+ struct cpuid4_info this_leaf;
int retval;
diff --git a/xen/arch/x86/cpu/mcheck/Makefile b/xen/arch/x86/cpu/mcheck/Makefile
index c8cd5f9..0d63ff9 100644
--- a/xen/arch/x86/cpu/mcheck/Makefile
+++ b/xen/arch/x86/cpu/mcheck/Makefile
@@ -1,6 +1,4 @@
obj-y += amd_nonfatal.o
-obj-y += amd_k8.o
-obj-y += amd_f10.o
obj-y += mce_amd.o
obj-y += mcaction.o
obj-y += barrier.o
diff --git a/xen/arch/x86/cpu/mcheck/amd_f10.c b/xen/arch/x86/cpu/mcheck/amd_f10.c
deleted file mode 100644
index 61319dc..0000000
--- a/xen/arch/x86/cpu/mcheck/amd_f10.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * MCA implementation for AMD Family10 CPUs
- * Copyright (c) 2007 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/* K8 common MCA documentation published at
- *
- * AMD64 Architecture Programmer's Manual Volume 2:
- * System Programming
- * Publication # 24593 Revision: 3.12
- * Issue Date: September 2006
- */
-
-/* Family10 MCA documentation published at
- *
- * BIOS and Kernel Developer's Guide
- * For AMD Family 10h Processors
- * Publication # 31116 Revision: 1.08
- * Isse Date: June 10, 2007
- */
-
-
-#include <xen/init.h>
-#include <xen/types.h>
-
-#include <asm/msr.h>
-
-#include "mce.h"
-#include "mce_quirks.h"
-#include "x86_mca.h"
-#include "mce_amd.h"
-#include "mcaction.h"
-
-static struct mcinfo_extended *
-amd_f10_handler(struct mc_info *mi, uint16_t bank, uint64_t status)
-{
- struct mcinfo_extended *mc_ext;
-
- /* Family 0x10 introduced additional MSR that belong to the
- * northbridge bank (4). */
- if (mi == NULL || bank != 4)
- return NULL;
-
- if (!(status & MCi_STATUS_VAL))
- return NULL;
-
- if (!(status & MCi_STATUS_MISCV))
- return NULL;
-
- mc_ext = x86_mcinfo_reserve(mi, sizeof(*mc_ext));
- if (!mc_ext)
- {
- mi->flags |= MCINFO_FLAGS_UNCOMPLETE;
- return NULL;
- }
-
- mc_ext->common.type = MC_TYPE_EXTENDED;
- mc_ext->common.size = sizeof(*mc_ext);
- mc_ext->mc_msrs = 3;
-
- mc_ext->mc_msr[0].reg = MSR_F10_MC4_MISC1;
- mc_ext->mc_msr[1].reg = MSR_F10_MC4_MISC2;
- mc_ext->mc_msr[2].reg = MSR_F10_MC4_MISC3;
-
- mc_ext->mc_msr[0].value = mca_rdmsr(MSR_F10_MC4_MISC1);
- mc_ext->mc_msr[1].value = mca_rdmsr(MSR_F10_MC4_MISC2);
- mc_ext->mc_msr[2].value = mca_rdmsr(MSR_F10_MC4_MISC3);
-
- return mc_ext;
-}
-
-/* AMD Family10 machine check */
-enum mcheck_type amd_f10_mcheck_init(struct cpuinfo_x86 *c)
-{
- enum mcequirk_amd_flags quirkflag = mcequirk_lookup_amd_quirkdata(c);
-
- if (amd_k8_mcheck_init(c) == mcheck_none)
- return mcheck_none;
-
- if (quirkflag == MCEQUIRK_F10_GART)
- mcequirk_amd_apply(quirkflag);
-
- x86_mce_callback_register(amd_f10_handler);
- mce_recoverable_register(mc_amd_recoverable_scan);
- mce_register_addrcheck(mc_amd_addrcheck);
-
- return mcheck_amd_famXX;
-}
-
-/* amd specific MCA MSR */
-int vmce_amd_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val)
-{
- switch (msr) {
- case MSR_F10_MC4_MISC1: /* DRAM error type */
- v->arch.vmce.bank[1].mci_misc = val;
- mce_printk(MCE_VERBOSE, "MCE: wr msr %#"PRIx64"\n", val);
- break;
- case MSR_F10_MC4_MISC2: /* Link error type */
- case MSR_F10_MC4_MISC3: /* L3 cache error type */
- /* ignore write: we do not emulate link and l3 cache errors
- * to the guest.
- */
- mce_printk(MCE_VERBOSE, "MCE: wr msr %#"PRIx64"\n", val);
- break;
- default:
- return 0;
- }
-
- return 1;
-}
-
-int vmce_amd_rdmsr(const struct vcpu *v, uint32_t msr, uint64_t *val)
-{
- switch (msr) {
- case MSR_F10_MC4_MISC1: /* DRAM error type */
- *val = v->arch.vmce.bank[1].mci_misc;
- mce_printk(MCE_VERBOSE, "MCE: rd msr %#"PRIx64"\n", *val);
- break;
- case MSR_F10_MC4_MISC2: /* Link error type */
- case MSR_F10_MC4_MISC3: /* L3 cache error type */
- /* we do not emulate link and l3 cache
- * errors to the guest.
- */
- *val = 0;
- mce_printk(MCE_VERBOSE, "MCE: rd msr %#"PRIx64"\n", *val);
- break;
- default:
- return 0;
- }
-
- return 1;
-}
diff --git a/xen/arch/x86/cpu/mcheck/amd_k8.c b/xen/arch/x86/cpu/mcheck/amd_k8.c
deleted file mode 100644
index 8ff359c..0000000
--- a/xen/arch/x86/cpu/mcheck/amd_k8.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * MCA implementation for AMD K8 CPUs
- * Copyright (c) 2007 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/* K8 common MCA documentation published at
- *
- * AMD64 Architecture Programmer's Manual Volume 2:
- * System Programming
- * Publication # 24593 Revision: 3.12
- * Issue Date: September 2006
- *
- * URL:
- * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24593.pdf
- */
-
-/* The related documentation for K8 Revisions A - E is:
- *
- * BIOS and Kernel Developer's Guide for
- * AMD Athlon 64 and AMD Opteron Processors
- * Publication # 26094 Revision: 3.30
- * Issue Date: February 2006
- *
- * URL:
- * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/26094.PDF
- */
-
-/* The related documentation for K8 Revisions F - G is:
- *
- * BIOS and Kernel Developer's Guide for
- * AMD NPT Family 0Fh Processors
- * Publication # 32559 Revision: 3.04
- * Issue Date: December 2006
- *
- * URL:
- * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf
- */
-
-
-#include <xen/config.h>
-#include <xen/init.h>
-#include <xen/types.h>
-#include <xen/kernel.h>
-#include <xen/smp.h>
-#include <xen/sched.h>
-#include <xen/sched-if.h>
-#include <xen/softirq.h>
-
-#include <asm/processor.h>
-#include <asm/shared.h>
-#include <asm/system.h>
-#include <asm/msr.h>
-
-#include "mce.h"
-#include "mce_quirks.h"
-
-/* Machine Check Handler for AMD K8 family series */
-static void k8_machine_check(struct cpu_user_regs *regs, long error_code)
-{
- mcheck_cmn_handler(regs, error_code, mca_allbanks,
- __get_cpu_var(mce_clear_banks));
-}
-
-static int k8_need_clearbank_scan(enum mca_source who, uint64_t status)
-{
- if (who != MCA_MCE_SCAN)
- return 1;
-
- /*
- * For fatal error, it shouldn't be cleared so that sticky bank
- * have a chance to be handled after reboot by polling.
- */
- if ((status & MCi_STATUS_UC) && (status & MCi_STATUS_PCC))
- return 0;
-
- return 1;
-}
-
-/* AMD K8 machine check */
-enum mcheck_type amd_k8_mcheck_init(struct cpuinfo_x86 *c)
-{
- uint32_t i;
- enum mcequirk_amd_flags quirkflag;
-
- quirkflag = mcequirk_lookup_amd_quirkdata(c);
-
- mce_handler_init();
- x86_mce_vector_register(k8_machine_check);
- mce_need_clearbank_register(k8_need_clearbank_scan);
-
- for (i = 0; i < nr_mce_banks; i++) {
- if (quirkflag == MCEQUIRK_K8_GART && i == 4) {
- mcequirk_amd_apply(quirkflag);
- } else {
- /* Enable error reporting of all errors */
- wrmsrl(MSR_IA32_MCx_CTL(i), 0xffffffffffffffffULL);
- wrmsrl(MSR_IA32_MCx_STATUS(i), 0x0ULL);
- }
- }
-
- return mcheck_amd_k8;
-}
diff --git a/xen/arch/x86/cpu/mcheck/mcaction.c b/xen/arch/x86/cpu/mcheck/mcaction.c
index adf2ded..9cf2499 100644
--- a/xen/arch/x86/cpu/mcheck/mcaction.c
+++ b/xen/arch/x86/cpu/mcheck/mcaction.c
@@ -38,7 +38,7 @@ void mce_register_addrcheck(mce_check_addr_t cbfunc)
void
mc_memerr_dhandler(struct mca_binfo *binfo,
enum mce_result *result,
- struct cpu_user_regs *regs)
+ const struct cpu_user_regs *regs)
{
struct mcinfo_bank *bank = binfo->mib;
struct mcinfo_global *global = binfo->mig;
diff --git a/xen/arch/x86/cpu/mcheck/mcaction.h b/xen/arch/x86/cpu/mcheck/mcaction.h
index 0f70a24..c6044d5 100644
--- a/xen/arch/x86/cpu/mcheck/mcaction.h
+++ b/xen/arch/x86/cpu/mcheck/mcaction.h
@@ -7,7 +7,7 @@
void
mc_memerr_dhandler(struct mca_binfo *binfo,
enum mce_result *result,
- struct cpu_user_regs *regs);
+ const struct cpu_user_regs *regs);
#define MC_ADDR_PHYSICAL 0
#define MC_ADDR_VIRTUAL 1
diff --git a/xen/arch/x86/cpu/mcheck/mce-apei.c b/xen/arch/x86/cpu/mcheck/mce-apei.c
index 3370341..08f6401 100644
--- a/xen/arch/x86/cpu/mcheck/mce-apei.c
+++ b/xen/arch/x86/cpu/mcheck/mce-apei.c
@@ -44,18 +44,15 @@
UUID_LE(0xfe08ffbe, 0x95e4, 0x4be7, 0xbc, 0x73, 0x40, 0x96, \
0x04, 0x4a, 0x38, 0xfc)
-#pragma pack(1)
/*
* CPER specification (in UEFI specification 2.3 appendix N) requires
* byte-packed.
*/
-struct cper_mce_record {
+struct __packed cper_mce_record {
struct cper_record_header hdr;
struct cper_section_descriptor sec_hdr;
struct mce mce;
-} __packed;
-/* Reset to default packing */
-#pragma pack()
+};
int apei_write_mce(struct mce *m)
{
@@ -92,10 +89,12 @@ int apei_write_mce(struct mce *m)
return erst_write(&rcd.hdr);
}
-size_t apei_read_mce(struct mce *m, u64 *record_id)
+#ifndef NDEBUG /* currently dead code */
+
+ssize_t apei_read_mce(struct mce *m, u64 *record_id)
{
struct cper_mce_record rcd;
- size_t len;
+ ssize_t len;
if (!m || !record_id)
return -EINVAL;
@@ -118,12 +117,14 @@ size_t apei_read_mce(struct mce *m, u64 *record_id)
}
/* Check whether there is record in ERST */
-int apei_check_mce(void)
+bool_t apei_check_mce(void)
{
- return erst_get_record_count();
+ return erst_get_record_count() > 0;
}
int apei_clear_mce(u64 record_id)
{
return erst_clear(record_id);
}
+
+#endif /* currently dead code */
diff --git a/xen/arch/x86/cpu/mcheck/mce.c b/xen/arch/x86/cpu/mcheck/mce.c
index af6f0be..05a86fb 100644
--- a/xen/arch/x86/cpu/mcheck/mce.c
+++ b/xen/arch/x86/cpu/mcheck/mce.c
@@ -70,10 +70,11 @@ static void __init mce_set_verbosity(char *str)
custom_param("mce_verbosity", mce_set_verbosity);
/* Handle unconfigured int18 (should never happen) */
-static void unexpected_machine_check(struct cpu_user_regs *regs, long error_code)
+static void unexpected_machine_check(const struct cpu_user_regs *regs)
{
- printk(XENLOG_ERR "CPU#%d: Unexpected int18 (Machine Check).\n",
- smp_processor_id());
+ console_force_unlock();
+ printk("Unexpected Machine Check Exception\n");
+ fatal_trap(regs);
}
@@ -87,9 +88,9 @@ void x86_mce_vector_register(x86_mce_vector_t hdlr)
/* Call the installed machine check handler for this CPU setup. */
-void machine_check_vector(struct cpu_user_regs *regs, long error_code)
+void do_machine_check(const struct cpu_user_regs *regs)
{
- _machine_check_vector(regs, error_code);
+ _machine_check_vector(regs);
}
/* Init machine check callback handler
@@ -423,7 +424,7 @@ static void mce_spin_unlock(spinlock_t *lk)
spin_unlock(lk);
}
-static enum mce_result mce_action(struct cpu_user_regs *regs,
+static enum mce_result mce_action(const struct cpu_user_regs *regs,
mctelem_cookie_t mctc);
/*
@@ -431,7 +432,7 @@ static enum mce_result mce_action(struct cpu_user_regs *regs,
* -1: if system can't be recovered
* 0: Continue to next step
*/
-static int mce_urgent_action(struct cpu_user_regs *regs,
+static int mce_urgent_action(const struct cpu_user_regs *regs,
mctelem_cookie_t mctc)
{
uint64_t gstatus;
@@ -458,9 +459,10 @@ static int mce_urgent_action(struct cpu_user_regs *regs,
}
/* Shared #MC handler. */
-void mcheck_cmn_handler(struct cpu_user_regs *regs, long error_code,
- struct mca_banks *bankmask, struct mca_banks *clear_bank)
+void mcheck_cmn_handler(const struct cpu_user_regs *regs)
{
+ struct mca_banks *bankmask = mca_allbanks;
+ struct mca_banks *clear_bank = __get_cpu_var(mce_clear_banks);
uint64_t gstatus;
mctelem_cookie_t mctc = NULL;
struct mca_summary bs;
@@ -775,13 +777,15 @@ void mcheck_init(struct cpuinfo_x86 *c, bool_t bsp)
intpose_init();
- mctelem_init(sizeof(struct mc_info));
+ if ( bsp )
+ {
+ mctelem_init(sizeof(struct mc_info));
+ register_cpu_notifier(&cpu_nfb);
+ }
/* Turn on MCE now */
set_in_cr4(X86_CR4_MCE);
- if ( bsp )
- register_cpu_notifier(&cpu_nfb);
set_poll_bankmask(c);
return;
@@ -1567,7 +1571,7 @@ void mc_panic(char *s)
*/
/* Maybe called in MCE context, no lock, no printk */
-static enum mce_result mce_action(struct cpu_user_regs *regs,
+static enum mce_result mce_action(const struct cpu_user_regs *regs,
mctelem_cookie_t mctc)
{
struct mc_info *local_mi;
diff --git a/xen/arch/x86/cpu/mcheck/mce.h b/xen/arch/x86/cpu/mcheck/mce.h
index cbd123d..e83d431 100644
--- a/xen/arch/x86/cpu/mcheck/mce.h
+++ b/xen/arch/x86/cpu/mcheck/mce.h
@@ -57,18 +57,17 @@ int mce_available(struct cpuinfo_x86 *c);
unsigned int mce_firstbank(struct cpuinfo_x86 *c);
/* Helper functions used for collecting error telemetry */
struct mc_info *x86_mcinfo_getptr(void);
-void mc_panic(char *s);
+void noreturn mc_panic(char *s);
void x86_mc_get_cpu_info(unsigned, uint32_t *, uint16_t *, uint16_t *,
uint32_t *, uint32_t *, uint32_t *, uint32_t *);
/* Register a handler for machine check exceptions. */
-typedef void (*x86_mce_vector_t)(struct cpu_user_regs *, long);
+typedef void (*x86_mce_vector_t)(const struct cpu_user_regs *regs);
extern void x86_mce_vector_register(x86_mce_vector_t);
/* Common generic MCE handler that implementations may nominate
* via x86_mce_vector_register. */
-extern void mcheck_cmn_handler(struct cpu_user_regs *, long,
- struct mca_banks *, struct mca_banks *);
+extern void mcheck_cmn_handler(const struct cpu_user_regs *regs);
/* Register a handler for judging whether mce is recoverable. */
typedef int (*mce_recoverable_t)(uint64_t status);
diff --git a/xen/arch/x86/cpu/mcheck/mce_amd.c b/xen/arch/x86/cpu/mcheck/mce_amd.c
index 74ee115..4e8ad38 100644
--- a/xen/arch/x86/cpu/mcheck/mce_amd.c
+++ b/xen/arch/x86/cpu/mcheck/mce_amd.c
@@ -1,6 +1,6 @@
/*
* common MCA implementation for AMD CPUs.
- * Copyright (c) 2012 Advanced Micro Devices, Inc.
+ * Copyright (c) 2012-2014 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,6 +17,50 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/* K8 common MCA documentation published at
+ *
+ * AMD64 Architecture Programmer's Manual Volume 2:
+ * System Programming
+ * Publication # 24593 Revision: 3.24
+ * Issue Date: October 2013
+ *
+ * URL:
+ * http://support.amd.com/TechDocs/24593.pdf
+ */
+
+/* The related documentation for K8 Revisions A - E is:
+ *
+ * BIOS and Kernel Developer's Guide for
+ * AMD Athlon 64 and AMD Opteron Processors
+ * Publication # 26094 Revision: 3.30
+ * Issue Date: February 2006
+ *
+ * URL:
+ * http://support.amd.com/TechDocs/26094.PDF
+ */
+
+/* The related documentation for K8 Revisions F - G is:
+ *
+ * BIOS and Kernel Developer's Guide for
+ * AMD NPT Family 0Fh Processors
+ * Publication # 32559 Revision: 3.08
+ * Issue Date: July 2007
+ *
+ * URL:
+ * http://support.amd.com/TechDocs/32559.pdf
+ */
+
+/* Family10 MCA documentation published at
+ *
+ * BIOS and Kernel Developer's Guide
+ * For AMD Family 10h Processors
+ * Publication # 31116 Revision: 3.62
+ * Isse Date: January 11, 2013
+ *
+ * URL:
+ * http://support.amd.com/TechDocs/31116.pdf
+ */
+
#include <xen/init.h>
#include <xen/types.h>
@@ -27,8 +71,8 @@
#include "x86_mca.h"
#include "mce_amd.h"
#include "mcaction.h"
-
#include "mce_quirks.h"
+#include "vmce.h"
#define ANY -1
@@ -98,7 +142,8 @@ mc_amd_addrcheck(uint64_t status, uint64_t misc, int addrtype)
errorcode = status & (MCi_STATUS_MCA | MCi_STATUS_MSEC);
ectype = mc_ec2type(errorcode);
- switch (ectype) {
+ switch ( ectype )
+ {
case MC_EC_BUS_TYPE: /* value in addr MSR is physical */
case MC_EC_MEM_TYPE: /* value in addr MSR is physical */
return (addrtype == MC_ADDR_PHYSICAL);
@@ -158,24 +203,107 @@ int mcequirk_amd_apply(enum mcequirk_amd_flags flags)
return 0;
}
+static struct mcinfo_extended *
+amd_f10_handler(struct mc_info *mi, uint16_t bank, uint64_t status)
+{
+ struct mcinfo_extended *mc_ext;
+
+ /* Family 0x10 introduced additional MSR that belong to the
+ * northbridge bank (4). */
+ if ( mi == NULL || bank != 4 )
+ return NULL;
+
+ if ( !(status & MCi_STATUS_VAL) )
+ return NULL;
+
+ if ( !(status & MCi_STATUS_MISCV) )
+ return NULL;
+
+ mc_ext = x86_mcinfo_reserve(mi, sizeof(*mc_ext));
+ if ( !mc_ext )
+ {
+ mi->flags |= MCINFO_FLAGS_UNCOMPLETE;
+ return NULL;
+ }
+
+ mc_ext->common.type = MC_TYPE_EXTENDED;
+ mc_ext->common.size = sizeof(*mc_ext);
+ mc_ext->mc_msrs = 3;
+
+ mc_ext->mc_msr[0].reg = MSR_F10_MC4_MISC1;
+ mc_ext->mc_msr[1].reg = MSR_F10_MC4_MISC2;
+ mc_ext->mc_msr[2].reg = MSR_F10_MC4_MISC3;
+
+ mc_ext->mc_msr[0].value = mca_rdmsr(MSR_F10_MC4_MISC1);
+ mc_ext->mc_msr[1].value = mca_rdmsr(MSR_F10_MC4_MISC2);
+ mc_ext->mc_msr[2].value = mca_rdmsr(MSR_F10_MC4_MISC3);
+
+ return mc_ext;
+}
+
+static int amd_need_clearbank_scan(enum mca_source who, uint64_t status)
+{
+ if ( who != MCA_MCE_SCAN )
+ return 1;
+
+ /*
+ * For fatal error, it shouldn't be cleared so that sticky bank
+ * have a chance to be handled after reboot by polling.
+ */
+ if ( (status & MCi_STATUS_UC) && (status & MCi_STATUS_PCC) )
+ return 0;
+
+ return 1;
+}
+
+/* AMD specific MCA MSR */
+int vmce_amd_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val)
+{
+ /* Do nothing as we don't emulate this MC bank currently */
+ mce_printk(MCE_VERBOSE, "MCE: wr msr %#"PRIx64"\n", val);
+ return 1;
+}
+
+int vmce_amd_rdmsr(const struct vcpu *v, uint32_t msr, uint64_t *val)
+{
+ /* Assign '0' as we don't emulate this MC bank currently */
+ *val = 0;
+ return 1;
+}
+
enum mcheck_type
amd_mcheck_init(struct cpuinfo_x86 *ci)
{
- enum mcheck_type rc = mcheck_none;
+ uint32_t i;
+ enum mcequirk_amd_flags quirkflag = mcequirk_lookup_amd_quirkdata(ci);
- switch ( ci->x86 )
- {
- default:
- /* Assume that machine check support is available.
- * The minimum provided support is at least the K8. */
- case 0xf:
- rc = amd_k8_mcheck_init(ci);
- break;
+ /* Assume that machine check support is available.
+ * The minimum provided support is at least the K8. */
+ mce_handler_init();
+ x86_mce_vector_register(mcheck_cmn_handler);
+ mce_need_clearbank_register(amd_need_clearbank_scan);
- case 0x10 ... 0x17:
- rc = amd_f10_mcheck_init(ci);
- break;
+ for ( i = 0; i < nr_mce_banks; i++ )
+ {
+ if ( quirkflag == MCEQUIRK_K8_GART && i == 4 )
+ mcequirk_amd_apply(quirkflag);
+ else
+ {
+ /* Enable error reporting of all errors */
+ wrmsrl(MSR_IA32_MCx_CTL(i), 0xffffffffffffffffULL);
+ wrmsrl(MSR_IA32_MCx_STATUS(i), 0x0ULL);
+ }
}
- return rc;
+ if ( ci->x86 == 0xf )
+ return mcheck_amd_k8;
+
+ if ( quirkflag == MCEQUIRK_F10_GART )
+ mcequirk_amd_apply(quirkflag);
+
+ x86_mce_callback_register(amd_f10_handler);
+ mce_recoverable_register(mc_amd_recoverable_scan);
+ mce_register_addrcheck(mc_amd_addrcheck);
+
+ return mcheck_amd_famXX;
}
diff --git a/xen/arch/x86/cpu/mcheck/mce_amd.h b/xen/arch/x86/cpu/mcheck/mce_amd.h
index 5d047e7..de5fc48 100644
--- a/xen/arch/x86/cpu/mcheck/mce_amd.h
+++ b/xen/arch/x86/cpu/mcheck/mce_amd.h
@@ -1,9 +1,6 @@
#ifndef _MCHECK_AMD_H
#define _MCHECK_AMD_H
-enum mcheck_type amd_k8_mcheck_init(struct cpuinfo_x86 *c);
-enum mcheck_type amd_f10_mcheck_init(struct cpuinfo_x86 *c);
-
int mc_amd_recoverable_scan(uint64_t status);
int mc_amd_addrcheck(uint64_t status, uint64_t misc, int addrtype);
diff --git a/xen/arch/x86/cpu/mcheck/mce_intel.c b/xen/arch/x86/cpu/mcheck/mce_intel.c
index 5b93870..94db396 100644
--- a/xen/arch/x86/cpu/mcheck/mce_intel.c
+++ b/xen/arch/x86/cpu/mcheck/mce_intel.c
@@ -266,7 +266,7 @@ static enum intel_mce_type intel_check_mce_type(uint64_t status)
static void intel_memerr_dhandler(
struct mca_binfo *binfo,
enum mce_result *result,
- struct cpu_user_regs *regs)
+ const struct cpu_user_regs *regs)
{
mce_printk(MCE_VERBOSE, "MCE: Enter UCR recovery action\n");
mc_memerr_dhandler(binfo, result, regs);
@@ -293,7 +293,7 @@ static int intel_checkaddr(uint64_t status, uint64_t misc, int addrtype)
static void intel_srar_dhandler(
struct mca_binfo *binfo,
enum mce_result *result,
- struct cpu_user_regs *regs)
+ const struct cpu_user_regs *regs)
{
uint64_t status = binfo->mib->mc_status;
@@ -319,7 +319,7 @@ static int intel_srao_check(uint64_t status)
static void intel_srao_dhandler(
struct mca_binfo *binfo,
enum mce_result *result,
- struct cpu_user_regs *regs)
+ const struct cpu_user_regs *regs)
{
uint64_t status = binfo->mib->mc_status;
@@ -348,7 +348,7 @@ static int intel_default_check(uint64_t status)
static void intel_default_mce_dhandler(
struct mca_binfo *binfo,
enum mce_result *result,
- struct cpu_user_regs * regs)
+ const struct cpu_user_regs * regs)
{
uint64_t status = binfo->mib->mc_status;
enum intel_mce_type type;
@@ -370,7 +370,7 @@ static const struct mca_error_handler intel_mce_dhandlers[] = {
static void intel_default_mce_uhandler(
struct mca_binfo *binfo,
enum mce_result *result,
- struct cpu_user_regs *regs)
+ const struct cpu_user_regs *regs)
{
uint64_t status = binfo->mib->mc_status;
enum intel_mce_type type;
@@ -392,12 +392,6 @@ static const struct mca_error_handler intel_mce_uhandlers[] = {
{intel_default_check, intel_default_mce_uhandler}
};
-static void intel_machine_check(struct cpu_user_regs * regs, long error_code)
-{
- mcheck_cmn_handler(regs, error_code, mca_allbanks,
- __get_cpu_var(mce_clear_banks));
-}
-
/* According to MCA OS writer guide, CMCI handler need to clear bank when
* 1) CE (UC = 0)
* 2) ser_support = 1, Superious error, OVER = 0, EN = 0, [UC = 1]
@@ -780,7 +774,7 @@ static void intel_init_mce(void)
if (firstbank) /* if cmci enabled, firstbank = 0 */
wrmsrl(MSR_IA32_MC0_STATUS, 0x0ULL);
- x86_mce_vector_register(intel_machine_check);
+ x86_mce_vector_register(mcheck_cmn_handler);
mce_recoverable_register(intel_recoverable_scan);
mce_need_clearbank_register(intel_need_clearbank_scan);
mce_register_addrcheck(intel_checkaddr);
diff --git a/xen/arch/x86/cpu/mcheck/mctelem.c b/xen/arch/x86/cpu/mcheck/mctelem.c
index ed8e8d2..b8da465 100644
--- a/xen/arch/x86/cpu/mcheck/mctelem.c
+++ b/xen/arch/x86/cpu/mcheck/mctelem.c
@@ -248,25 +248,14 @@ static void mctelem_processing_release(struct mctelem_ent *tep)
}
}
-void mctelem_init(int reqdatasz)
+void __init mctelem_init(unsigned int datasz)
{
- static int called = 0;
- static int datasz = 0, realdatasz = 0;
char *datarr;
- int i;
+ unsigned int i;
- BUG_ON(MC_URGENT != 0 || MC_NONURGENT != 1 || MC_NCLASSES != 2);
-
- /* Called from mcheck_init for all processors; initialize for the
- * first call only (no race here since the boot cpu completes
- * init before others start up). */
- if (++called == 1) {
- realdatasz = reqdatasz;
- datasz = (reqdatasz & ~0xf) + 0x10; /* 16 byte roundup */
- } else {
- BUG_ON(reqdatasz != realdatasz);
- return;
- }
+ BUILD_BUG_ON(MC_URGENT != 0 || MC_NONURGENT != 1 || MC_NCLASSES != 2);
+
+ datasz = (datasz & ~0xf) + 0x10; /* 16 byte roundup */
if ((mctctl.mctc_elems = xmalloc_array(struct mctelem_ent,
MC_NENT)) == NULL ||
diff --git a/xen/arch/x86/cpu/mcheck/mctelem.h b/xen/arch/x86/cpu/mcheck/mctelem.h
index e5514d9..4947b57 100644
--- a/xen/arch/x86/cpu/mcheck/mctelem.h
+++ b/xen/arch/x86/cpu/mcheck/mctelem.h
@@ -59,7 +59,7 @@ typedef enum mctelem_class {
MC_NONURGENT
} mctelem_class_t;
-extern void mctelem_init(int);
+extern void mctelem_init(unsigned int);
extern mctelem_cookie_t mctelem_reserve(mctelem_class_t);
extern void *mctelem_dataptr(mctelem_cookie_t);
extern void mctelem_commit(mctelem_cookie_t);
diff --git a/xen/arch/x86/cpu/mcheck/vmce.c b/xen/arch/x86/cpu/mcheck/vmce.c
index dcfe97e..ba1693c 100644
--- a/xen/arch/x86/cpu/mcheck/vmce.c
+++ b/xen/arch/x86/cpu/mcheck/vmce.c
@@ -82,10 +82,9 @@ int vmce_restore_vcpu(struct vcpu *v, const struct hvm_vmce_vcpu *ctxt)
if ( ctxt->caps & ~guest_mcg_cap & ~MCG_CAP_COUNT & ~MCG_CTL_P )
{
dprintk(XENLOG_G_ERR, "%s restore: unsupported MCA capabilities"
- " %#" PRIx64 " for d%d:v%u (supported: %#Lx)\n",
+ " %#" PRIx64 " for %pv (supported: %#Lx)\n",
has_hvm_container_vcpu(v) ? "HVM" : "PV", ctxt->caps,
- v->domain->domain_id, v->vcpu_id,
- guest_mcg_cap & ~MCG_CAP_COUNT);
+ v, guest_mcg_cap & ~MCG_CAP_COUNT);
return -EPERM;
}
@@ -107,7 +106,7 @@ static int bank_mce_rdmsr(const struct vcpu *v, uint32_t msr, uint64_t *val)
*val = 0;
- switch ( msr & (MSR_IA32_MC0_CTL | 3) )
+ switch ( msr & (-MSR_IA32_MC0_CTL | 3) )
{
case MSR_IA32_MC0_CTL:
/* stick all 1's to MCi_CTL */
@@ -210,7 +209,7 @@ static int bank_mce_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val)
int ret = 1;
unsigned int bank = (msr - MSR_IA32_MC0_CTL) / 4;
- switch ( msr & (MSR_IA32_MC0_CTL | 3) )
+ switch ( msr & (-MSR_IA32_MC0_CTL | 3) )
{
case MSR_IA32_MC0_CTL:
/*
@@ -365,15 +364,13 @@ int inject_vmce(struct domain *d, int vcpu)
guest_has_trap_callback(d, v->vcpu_id, TRAP_machine_check)) &&
!test_and_set_bool(v->mce_pending) )
{
- mce_printk(MCE_VERBOSE, "MCE: inject vMCE to d%d:v%d\n",
- d->domain_id, v->vcpu_id);
+ mce_printk(MCE_VERBOSE, "MCE: inject vMCE to %pv\n", v);
vcpu_kick(v);
ret = 0;
}
else
{
- mce_printk(MCE_QUIET, "Failed to inject vMCE to d%d:v%d\n",
- d->domain_id, v->vcpu_id);
+ mce_printk(MCE_QUIET, "Failed to inject vMCE to %pv\n", v);
ret = -EBUSY;
break;
}
@@ -437,7 +434,7 @@ int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn)
int rc;
/* Always trust dom0's MCE handler will prevent future access */
- if ( d == dom0 )
+ if ( is_hardware_domain(d) )
return 0;
if (!mfn_valid(mfn_x(mfn)))
@@ -451,8 +448,7 @@ int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn)
if ( p2m_to_mask(pt) & P2M_UNMAP_TYPES)
{
ASSERT(mfn_x(r_mfn) == mfn_x(mfn));
- p2m_change_type(d, gfn, pt, p2m_ram_broken);
- rc = 0;
+ rc = p2m_change_type_one(d, gfn, pt, p2m_ram_broken);
}
put_gfn(d, gfn);
diff --git a/xen/arch/x86/cpu/mcheck/vmce.h b/xen/arch/x86/cpu/mcheck/vmce.h
index 6b2c95a..163ce3c 100644
--- a/xen/arch/x86/cpu/mcheck/vmce.h
+++ b/xen/arch/x86/cpu/mcheck/vmce.h
@@ -5,8 +5,9 @@
int vmce_init(struct cpuinfo_x86 *c);
-#define dom0_vmce_enabled() (dom0 && dom0->max_vcpus && dom0->vcpu[0] \
- && guest_enabled_event(dom0->vcpu[0], VIRQ_MCA))
+#define dom0_vmce_enabled() (hardware_domain && hardware_domain->max_vcpus \
+ && hardware_domain->vcpu[0] \
+ && guest_enabled_event(hardware_domain->vcpu[0], VIRQ_MCA))
int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn);
diff --git a/xen/arch/x86/cpu/mcheck/x86_mca.h b/xen/arch/x86/cpu/mcheck/x86_mca.h
index ca5dfff..a2cd37e 100644
--- a/xen/arch/x86/cpu/mcheck/x86_mca.h
+++ b/xen/arch/x86/cpu/mcheck/x86_mca.h
@@ -152,7 +152,7 @@ struct mca_error_handler
*/
int (*owned_error)(uint64_t status);
void (*recovery_handler)(struct mca_binfo *binfo,
- enum mce_result *result, struct cpu_user_regs *regs);
+ enum mce_result *result, const struct cpu_user_regs *regs);
};
/* Global variables */
diff --git a/xen/arch/x86/cpu/mtrr/generic.c b/xen/arch/x86/cpu/mtrr/generic.c
index aa5399b..493830b 100644
--- a/xen/arch/x86/cpu/mtrr/generic.c
+++ b/xen/arch/x86/cpu/mtrr/generic.c
@@ -11,15 +11,13 @@
#include <asm/cpufeature.h>
#include "mtrr.h"
-struct fixed_range_block {
- int base_msr; /* start address of an MTRR block */
- int ranges; /* number of MTRRs in this block */
-};
-
-static struct fixed_range_block fixed_range_blocks[] = {
- { MTRRfix64K_00000_MSR, 1 }, /* one 64k MTRR */
- { MTRRfix16K_80000_MSR, 2 }, /* two 16k MTRRs */
- { MTRRfix4K_C0000_MSR, 8 }, /* eight 4k MTRRs */
+static const struct fixed_range_block {
+ uint32_t base_msr; /* start address of an MTRR block */
+ unsigned int ranges; /* number of MTRRs in this block */
+} fixed_range_blocks[] = {
+ { MSR_MTRRfix64K_00000, (0x80000 - 0x00000) >> (16 + 3) },
+ { MSR_MTRRfix16K_80000, (0xC0000 - 0x80000) >> (14 + 3) },
+ { MSR_MTRRfix4K_C0000, (0x100000 - 0xC0000) >> (12 + 3) },
{}
};
@@ -30,28 +28,30 @@ struct mtrr_state mtrr_state = {};
static void
get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr)
{
- rdmsrl(MTRRphysBase_MSR(index), vr->base);
- rdmsrl(MTRRphysMask_MSR(index), vr->mask);
+ rdmsrl(MSR_IA32_MTRR_PHYSBASE(index), vr->base);
+ rdmsrl(MSR_IA32_MTRR_PHYSMASK(index), vr->mask);
}
static void
get_fixed_ranges(mtrr_type * frs)
{
uint64_t *p = (uint64_t *) frs;
- int i;
+ const struct fixed_range_block *block;
- rdmsrl(MTRRfix64K_00000_MSR, p[0]);
+ if (!mtrr_state.have_fixed)
+ return;
- for (i = 0; i < 2; i++)
- rdmsrl(MTRRfix16K_80000_MSR + i, p[1 + i]);
- for (i = 0; i < 8; i++)
- rdmsrl(MTRRfix4K_C0000_MSR + i, p[3 + i]);
+ for (block = fixed_range_blocks; block->ranges; ++block) {
+ unsigned int i;
+
+ for (i = 0; i < block->ranges; ++i, ++p)
+ rdmsrl(block->base_msr + i, *p);
+ }
}
void mtrr_save_fixed_ranges(void *info)
{
- if (cpu_has_mtrr)
- get_fixed_ranges(mtrr_state.fixed_ranges);
+ get_fixed_ranges(mtrr_state.fixed_ranges);
}
/* Grab all of the MTRR state for this CPU into *state */
@@ -69,20 +69,119 @@ void __init get_mtrr_state(void)
}
vrs = mtrr_state.var_ranges;
- rdmsrl(MTRRcap_MSR, msr_content);
+ rdmsrl(MSR_MTRRcap, msr_content);
mtrr_state.have_fixed = (msr_content >> 8) & 1;
for (i = 0; i < num_var_ranges; i++)
get_mtrr_var_range(i, &vrs[i]);
- if (mtrr_state.have_fixed)
- get_fixed_ranges(mtrr_state.fixed_ranges);
+ get_fixed_ranges(mtrr_state.fixed_ranges);
- rdmsrl(MTRRdefType_MSR, msr_content);
+ rdmsrl(MSR_MTRRdefType, msr_content);
mtrr_state.def_type = (msr_content & 0xff);
mtrr_state.enabled = (msr_content & 0xc00) >> 10;
/* Store mtrr_cap for HVM MTRR virtualisation. */
- rdmsrl(MTRRcap_MSR, mtrr_state.mtrr_cap);
+ rdmsrl(MSR_MTRRcap, mtrr_state.mtrr_cap);
+}
+
+static bool_t __initdata mtrr_show;
+boolean_param("mtrr.show", mtrr_show);
+
+static const char *__init mtrr_attrib_to_str(mtrr_type x)
+{
+ static const char __initconst strings[MTRR_NUM_TYPES][16] =
+ {
+ [0 ... MTRR_NUM_TYPES - 1] = "?",
+ [MTRR_TYPE_UNCACHABLE] = "uncachable",
+ [MTRR_TYPE_WRCOMB] = "write-combining",
+ [MTRR_TYPE_WRTHROUGH] = "write-through",
+ [MTRR_TYPE_WRPROT] = "write-protect",
+ [MTRR_TYPE_WRBACK] = "write-back",
+ };
+
+ return x < MTRR_NUM_TYPES ? strings[x] : "?";
+}
+
+static unsigned int __initdata last_fixed_start;
+static unsigned int __initdata last_fixed_end;
+static mtrr_type __initdata last_fixed_type;
+
+static void __init print_fixed_last(const char *level)
+{
+ if (!last_fixed_end)
+ return;
+
+ printk("%s %05x-%05x %s\n", level, last_fixed_start,
+ last_fixed_end - 1, mtrr_attrib_to_str(last_fixed_type));
+
+ last_fixed_end = 0;
+}
+
+static void __init update_fixed_last(unsigned int base, unsigned int end,
+ mtrr_type type)
+{
+ last_fixed_start = base;
+ last_fixed_end = end;
+ last_fixed_type = type;
+}
+
+static void __init print_fixed(unsigned int base, unsigned int step,
+ const mtrr_type *types, const char *level)
+{
+ unsigned i;
+
+ for (i = 0; i < 8; ++i, ++types, base += step) {
+ if (last_fixed_end == 0) {
+ update_fixed_last(base, base + step, *types);
+ continue;
+ }
+ if (last_fixed_end == base && last_fixed_type == *types) {
+ last_fixed_end = base + step;
+ continue;
+ }
+ /* new segments: gap or different type */
+ print_fixed_last(level);
+ update_fixed_last(base, base + step, *types);
+ }
+}
+
+static void __init print_mtrr_state(const char *level)
+{
+ unsigned int i;
+ int width;
+
+ printk("%sMTRR default type: %s\n", level,
+ mtrr_attrib_to_str(mtrr_state.def_type));
+ if (mtrr_state.have_fixed) {
+ const mtrr_type *fr = mtrr_state.fixed_ranges;
+ const struct fixed_range_block *block = fixed_range_blocks;
+ unsigned int base = 0, step = 0x10000;
+
+ printk("%sMTRR fixed ranges %sabled:\n", level,
+ mtrr_state.enabled & 1 ? "en" : "dis");
+ for (; block->ranges; ++block, step >>= 2) {
+ for (i = 0; i < block->ranges; ++i, fr += 8) {
+ print_fixed(base, step, fr, level);
+ base += 8 * step;
+ }
+ }
+ print_fixed_last(level);
+ }
+ printk("%sMTRR variable ranges %sabled:\n", level,
+ mtrr_state.enabled & 2 ? "en" : "dis");
+ width = (paddr_bits - PAGE_SHIFT + 3) / 4;
+
+ for (i = 0; i < num_var_ranges; ++i) {
+ if (mtrr_state.var_ranges[i].mask & MTRR_PHYSMASK_VALID)
+ printk("%s %u base %0*"PRIx64"000 mask %0*"PRIx64"000 %s\n",
+ level, i,
+ width, mtrr_state.var_ranges[i].base >> 12,
+ width, mtrr_state.var_ranges[i].mask >> 12,
+ mtrr_attrib_to_str(mtrr_state.var_ranges[i].base &
+ MTRR_PHYSBASE_TYPE_MASK));
+ else
+ printk("%s %u disabled\n", level, i);
+ }
}
/* Some BIOS's are fucked and don't set all MTRRs the same! */
@@ -90,6 +189,8 @@ void __init mtrr_state_warn(void)
{
unsigned long mask = smp_changes_mask;
+ if (mtrr_show)
+ print_mtrr_state(mask ? KERN_WARNING : "");
if (!mask)
return;
if (mask & MTRR_CHANGE_MASK_FIXED)
@@ -100,6 +201,8 @@ void __init mtrr_state_warn(void)
printk(KERN_WARNING "mtrr: your CPUs had inconsistent MTRRdefType settings\n");
printk(KERN_INFO "mtrr: probably your BIOS does not setup all CPUs.\n");
printk(KERN_INFO "mtrr: corrected configuration.\n");
+ if (!mtrr_show)
+ print_mtrr_state(KERN_INFO);
}
/* Doesn't attempt to pass an error out to MTRR users
@@ -163,8 +266,8 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base,
{
uint64_t _mask, _base;
- rdmsrl(MTRRphysMask_MSR(reg), _mask);
- if ((_mask & 0x800) == 0) {
+ rdmsrl(MSR_IA32_MTRR_PHYSMASK(reg), _mask);
+ if (!(_mask & MTRR_PHYSMASK_VALID)) {
/* Invalid (i.e. free) range */
*base = 0;
*size = 0;
@@ -172,7 +275,7 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base,
return;
}
- rdmsrl(MTRRphysBase_MSR(reg), _base);
+ rdmsrl(MSR_IA32_MTRR_PHYSBASE(reg), _base);
/* Work out the shifted address mask. */
_mask = size_or_mask | (_mask >> PAGE_SHIFT);
@@ -210,7 +313,7 @@ static int set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr)
uint64_t msr_content;
int changed = FALSE;
- rdmsrl(MTRRphysBase_MSR(index), msr_content);
+ rdmsrl(MSR_IA32_MTRR_PHYSBASE(index), msr_content);
lo = (uint32_t)msr_content;
hi = (uint32_t)(msr_content >> 32);
base_lo = (uint32_t)vr->base;
@@ -222,11 +325,11 @@ static int set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr)
base_hi &= size_and_mask >> (32 - PAGE_SHIFT);
if ((base_lo != lo) || (base_hi != hi)) {
- mtrr_wrmsr(MTRRphysBase_MSR(index), vr->base);
+ mtrr_wrmsr(MSR_IA32_MTRR_PHYSBASE(index), vr->base);
changed = TRUE;
}
- rdmsrl(MTRRphysMask_MSR(index), msr_content);
+ rdmsrl(MSR_IA32_MTRR_PHYSMASK(index), msr_content);
lo = (uint32_t)msr_content;
hi = (uint32_t)(msr_content >> 32);
mask_lo = (uint32_t)vr->mask;
@@ -238,7 +341,7 @@ static int set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr)
mask_hi &= size_and_mask >> (32 - PAGE_SHIFT);
if ((mask_lo != lo) || (mask_hi != hi)) {
- mtrr_wrmsr(MTRRphysMask_MSR(index), vr->mask);
+ mtrr_wrmsr(MSR_IA32_MTRR_PHYSMASK(index), vr->mask);
changed = TRUE;
}
return changed;
@@ -311,10 +414,10 @@ static void prepare_set(void)
flush_tlb_local();
/* Save MTRR state */
- rdmsrl(MTRRdefType_MSR, deftype);
+ rdmsrl(MSR_MTRRdefType, deftype);
/* Disable MTRRs, and set the default type to uncached */
- mtrr_wrmsr(MTRRdefType_MSR, deftype & ~0xcff);
+ mtrr_wrmsr(MSR_MTRRdefType, deftype & ~0xcff);
}
static void post_set(void)
@@ -323,7 +426,7 @@ static void post_set(void)
flush_tlb_local();
/* Intel (P6) standard MTRRs */
- mtrr_wrmsr(MTRRdefType_MSR, deftype);
+ mtrr_wrmsr(MSR_MTRRdefType, deftype);
/* Enable caches */
write_cr0(read_cr0() & 0xbfffffff);
@@ -380,20 +483,20 @@ static void generic_set_mtrr(unsigned int reg, unsigned long base,
if (size == 0) {
/* The invalid bit is kept in the mask, so we simply clear the
relevant mask register to disable a range. */
- mtrr_wrmsr(MTRRphysMask_MSR(reg), 0);
+ mtrr_wrmsr(MSR_IA32_MTRR_PHYSMASK(reg), 0);
memset(vr, 0, sizeof(struct mtrr_var_range));
} else {
uint32_t base_lo, base_hi, mask_lo, mask_hi;
base_lo = base << PAGE_SHIFT | type;
base_hi = (base & size_and_mask) >> (32 - PAGE_SHIFT);
- mask_lo = -size << PAGE_SHIFT | 0x800;
+ mask_lo = (-size << PAGE_SHIFT) | MTRR_PHYSMASK_VALID;
mask_hi = (-size & size_and_mask) >> (32 - PAGE_SHIFT);
vr->base = ((uint64_t)base_hi << 32) | base_lo;
vr->mask = ((uint64_t)mask_hi << 32) | mask_lo;
- mtrr_wrmsr(MTRRphysBase_MSR(reg), vr->base);
- mtrr_wrmsr(MTRRphysMask_MSR(reg), vr->mask);
+ mtrr_wrmsr(MSR_IA32_MTRR_PHYSBASE(reg), vr->base);
+ mtrr_wrmsr(MSR_IA32_MTRR_PHYSMASK(reg), vr->mask);
}
post_set();
@@ -438,7 +541,7 @@ int generic_validate_add_page(unsigned long base, unsigned long size, unsigned i
static int generic_have_wrcomb(void)
{
unsigned long config;
- rdmsrl(MTRRcap_MSR, config);
+ rdmsrl(MSR_MTRRcap, config);
return (config & (1ULL << 10));
}
diff --git a/xen/arch/x86/cpu/mtrr/main.c b/xen/arch/x86/cpu/mtrr/main.c
index f7fc0a6..f5d5317 100644
--- a/xen/arch/x86/cpu/mtrr/main.c
+++ b/xen/arch/x86/cpu/mtrr/main.c
@@ -91,7 +91,7 @@ static void __init set_num_var_ranges(void)
unsigned long config = 0;
if (use_intel()) {
- rdmsrl(MTRRcap_MSR, config);
+ rdmsrl(MSR_MTRRcap, config);
} else if (is_cpu(AMD))
config = 2;
else if (is_cpu(CYRIX) || is_cpu(CENTAUR))
diff --git a/xen/arch/x86/cpu/mtrr/mtrr.h b/xen/arch/x86/cpu/mtrr/mtrr.h
index a0ecdba..a9d6dcd 100644
--- a/xen/arch/x86/cpu/mtrr/mtrr.h
+++ b/xen/arch/x86/cpu/mtrr/mtrr.h
@@ -7,24 +7,6 @@
#define FALSE 0
#endif
-#define MTRRcap_MSR 0x0fe
-#define MTRRdefType_MSR 0x2ff
-
-#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
-#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
-
-#define MTRRfix64K_00000_MSR 0x250
-#define MTRRfix16K_80000_MSR 0x258
-#define MTRRfix16K_A0000_MSR 0x259
-#define MTRRfix4K_C0000_MSR 0x268
-#define MTRRfix4K_C8000_MSR 0x269
-#define MTRRfix4K_D0000_MSR 0x26a
-#define MTRRfix4K_D8000_MSR 0x26b
-#define MTRRfix4K_E0000_MSR 0x26c
-#define MTRRfix4K_E8000_MSR 0x26d
-#define MTRRfix4K_F0000_MSR 0x26e
-#define MTRRfix4K_F8000_MSR 0x26f
-
#define MTRR_CHANGE_MASK_FIXED 0x01
#define MTRR_CHANGE_MASK_VARIABLE 0x02
#define MTRR_CHANGE_MASK_DEFTYPE 0x04
diff --git a/xen/arch/x86/cpu/mwait-idle.c b/xen/arch/x86/cpu/mwait-idle.c
index 65ea7b3..6dd5822 100644
--- a/xen/arch/x86/cpu/mwait-idle.c
+++ b/xen/arch/x86/cpu/mwait-idle.c
@@ -1,7 +1,7 @@
/*
* mwait_idle.c - native hardware idle loop for modern processors
*
- * Copyright (c) 2010, Intel Corporation.
+ * Copyright (c) 2013, Intel Corporation.
* Len Brown <len.brown at intel.com>
*
* This program is free software; you can redistribute it and/or modify it
@@ -88,6 +88,7 @@ struct idle_cpu {
* Indicate which enable bits to clear here.
*/
unsigned long auto_demotion_disable_flags;
+ bool_t byt_auto_demotion_disable_flag;
bool_t disable_promotion_to_c1e;
};
@@ -187,6 +188,46 @@ static const struct cpuidle_state snb_cstates[] = {
{}
};
+static const struct cpuidle_state byt_cstates[] = {
+ {
+ .name = "C1-BYT",
+ .flags = MWAIT2flg(0x00),
+ .exit_latency = 1,
+ .target_residency = 1,
+ },
+ {
+ .name = "C1E-BYT",
+ .flags = MWAIT2flg(0x01),
+ .exit_latency = 15,
+ .target_residency = 30,
+ },
+ {
+ .name = "C6N-BYT",
+ .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 40,
+ .target_residency = 275,
+ },
+ {
+ .name = "C6S-BYT",
+ .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 140,
+ .target_residency = 560,
+ },
+ {
+ .name = "C7-BYT",
+ .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 1200,
+ .target_residency = 1500,
+ },
+ {
+ .name = "C7S-BYT",
+ .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 10000,
+ .target_residency = 20000,
+ },
+ {}
+};
+
static const struct cpuidle_state ivb_cstates[] = {
{
.name = "C1-IVB",
@@ -221,6 +262,90 @@ static const struct cpuidle_state ivb_cstates[] = {
{}
};
+static const struct cpuidle_state ivt_cstates[] = {
+ {
+ .name = "C1-IVT",
+ .flags = MWAIT2flg(0x00),
+ .exit_latency = 1,
+ .target_residency = 1,
+ },
+ {
+ .name = "C1E-IVT",
+ .flags = MWAIT2flg(0x01),
+ .exit_latency = 10,
+ .target_residency = 80,
+ },
+ {
+ .name = "C3-IVT",
+ .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 59,
+ .target_residency = 156,
+ },
+ {
+ .name = "C6-IVT",
+ .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 82,
+ .target_residency = 300,
+ },
+ {}
+};
+
+static const struct cpuidle_state ivt_cstates_4s[] = {
+ {
+ .name = "C1-IVT-4S",
+ .flags = MWAIT2flg(0x00),
+ .exit_latency = 1,
+ .target_residency = 1,
+ },
+ {
+ .name = "C1E-IVT-4S",
+ .flags = MWAIT2flg(0x01),
+ .exit_latency = 10,
+ .target_residency = 250,
+ },
+ {
+ .name = "C3-IVT-4S",
+ .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 59,
+ .target_residency = 300,
+ },
+ {
+ .name = "C6-IVT-4S",
+ .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 84,
+ .target_residency = 400,
+ },
+ {}
+};
+
+static const struct cpuidle_state ivt_cstates_8s[] = {
+ {
+ .name = "C1-IVT-8S",
+ .flags = MWAIT2flg(0x00),
+ .exit_latency = 1,
+ .target_residency = 1,
+ },
+ {
+ .name = "C1E-IVT-8S",
+ .flags = MWAIT2flg(0x01),
+ .exit_latency = 10,
+ .target_residency = 500,
+ },
+ {
+ .name = "C3-IVT-8S",
+ .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 59,
+ .target_residency = 600,
+ },
+ {
+ .name = "C6-IVT-8S",
+ .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 88,
+ .target_residency = 700,
+ },
+ {}
+};
+
static const struct cpuidle_state hsw_cstates[] = {
{
.name = "C1-HSW",
@@ -273,6 +398,58 @@ static const struct cpuidle_state hsw_cstates[] = {
{}
};
+static const struct cpuidle_state bdw_cstates[] = {
+ {
+ .name = "C1-BDW",
+ .flags = MWAIT2flg(0x00),
+ .exit_latency = 2,
+ .target_residency = 2,
+ },
+ {
+ .name = "C1E-BDW",
+ .flags = MWAIT2flg(0x01),
+ .exit_latency = 10,
+ .target_residency = 20,
+ },
+ {
+ .name = "C3-BDW",
+ .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 40,
+ .target_residency = 100,
+ },
+ {
+ .name = "C6-BDW",
+ .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 133,
+ .target_residency = 400,
+ },
+ {
+ .name = "C7s-BDW",
+ .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 166,
+ .target_residency = 500,
+ },
+ {
+ .name = "C8-BDW",
+ .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 300,
+ .target_residency = 900,
+ },
+ {
+ .name = "C9-BDW",
+ .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 600,
+ .target_residency = 1800,
+ },
+ {
+ .name = "C10-BDW",
+ .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 2600,
+ .target_residency = 7700,
+ },
+ {}
+};
+
static const struct cpuidle_state atom_cstates[] = {
{
.name = "C1E-ATM",
@@ -301,6 +478,22 @@ static const struct cpuidle_state atom_cstates[] = {
{}
};
+static const struct cpuidle_state avn_cstates[] = {
+ {
+ .name = "C1-AVN",
+ .flags = MWAIT2flg(0x00),
+ .exit_latency = 2,
+ .target_residency = 2,
+ },
+ {
+ .name = "C6-AVN",
+ .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 15,
+ .target_residency = 45,
+ },
+ {}
+};
+
static void mwait_idle(void)
{
unsigned int cpu = smp_processor_id();
@@ -397,6 +590,12 @@ static void auto_demotion_disable(void *dummy)
wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
}
+static void byt_auto_demotion_disable(void *dummy)
+{
+ wrmsrl(MSR_CC6_DEMOTION_POLICY_CONFIG, 0);
+ wrmsrl(MSR_MC6_DEMOTION_POLICY_CONFIG, 0);
+}
+
static void c1e_promotion_disable(void *dummy)
{
u64 msr_bits;
@@ -426,16 +625,37 @@ static const struct idle_cpu idle_cpu_snb = {
.disable_promotion_to_c1e = 1,
};
+static const struct idle_cpu idle_cpu_byt = {
+ .state_table = byt_cstates,
+ .disable_promotion_to_c1e = 1,
+ .byt_auto_demotion_disable_flag = 1,
+};
+
static const struct idle_cpu idle_cpu_ivb = {
.state_table = ivb_cstates,
.disable_promotion_to_c1e = 1,
};
+static const struct idle_cpu idle_cpu_ivt = {
+ .state_table = ivt_cstates,
+ .disable_promotion_to_c1e = 1,
+};
+
static const struct idle_cpu idle_cpu_hsw = {
.state_table = hsw_cstates,
.disable_promotion_to_c1e = 1,
};
+static const struct idle_cpu idle_cpu_bdw = {
+ .state_table = bdw_cstates,
+ .disable_promotion_to_c1e = 1,
+};
+
+static const struct idle_cpu idle_cpu_avn = {
+ .state_table = avn_cstates,
+ .disable_promotion_to_c1e = 1,
+};
+
#define ICPU(model, cpu) { 6, model, &idle_cpu_##cpu }
static struct intel_idle_id {
@@ -453,15 +673,52 @@ static struct intel_idle_id {
ICPU(0x26, lincroft),
ICPU(0x2a, snb),
ICPU(0x2d, snb),
+ ICPU(0x36, atom),
+ ICPU(0x37, byt),
ICPU(0x3a, ivb),
- ICPU(0x3e, ivb),
+ ICPU(0x3e, ivt),
ICPU(0x3c, hsw),
ICPU(0x3f, hsw),
ICPU(0x45, hsw),
ICPU(0x46, hsw),
+ ICPU(0x4d, avn),
+ ICPU(0x3d, bdw),
+ ICPU(0x4f, bdw),
+ ICPU(0x56, bdw),
{}
};
+/*
+ * mwait_idle_state_table_update()
+ *
+ * Update the default state_table for this CPU-id
+ *
+ * Currently used to access tuned IVT multi-socket targets
+ * Assumption: num_sockets == (max_package_num + 1)
+ */
+static void __init mwait_idle_state_table_update(void)
+{
+ /* IVT uses a different table for 1-2, 3-4, and > 4 sockets */
+ if (boot_cpu_data.x86_model == 0x3e) { /* IVT */
+ unsigned int cpu, max_apicid = boot_cpu_physical_apicid;
+
+ for_each_present_cpu(cpu)
+ if (max_apicid < x86_cpu_to_apicid[cpu])
+ max_apicid = x86_cpu_to_apicid[cpu];
+ switch (apicid_to_socket(max_apicid)) {
+ case 0: case 1:
+ /* 1 and 2 socket systems use default ivt_cstates */
+ break;
+ case 2: case 3:
+ cpuidle_state_table = ivt_cstates_4s;
+ break;
+ default:
+ cpuidle_state_table = ivt_cstates_8s;
+ break;
+ }
+ }
+}
+
static int __init mwait_idle_probe(void)
{
unsigned int eax, ebx, ecx;
@@ -507,6 +764,9 @@ static int __init mwait_idle_probe(void)
pr_debug(PREFIX "lapic_timer_reliable_states %#x\n",
lapic_timer_reliable_states);
+
+ mwait_idle_state_table_update();
+
return 0;
}
@@ -533,23 +793,22 @@ static int mwait_idle_cpu_init(struct notifier_block *nfb,
dev->count = 1;
for (cstate = 0; cpuidle_state_table[cstate].target_residency; ++cstate) {
- unsigned int num_substates, hint, state, substate;
+ unsigned int num_substates, hint, state;
struct acpi_processor_cx *cx;
hint = flg2MWAIT(cpuidle_state_table[cstate].flags);
state = MWAIT_HINT2CSTATE(hint) + 1;
- substate = MWAIT_HINT2SUBSTATE(hint);
if (state > max_cstate) {
printk(PREFIX "max C-state %u reached\n", max_cstate);
break;
}
- /* Does the state exist in CPUID.MWAIT? */
+ /* Number of sub-states for this state in CPUID.MWAIT. */
num_substates = (mwait_substates >> (state * 4))
& MWAIT_SUBSTATE_MASK;
- /* if sub-state in table is not enumerated by CPUID */
- if (substate >= num_substates)
+ /* If NO sub-states for this state in CPUID, skip it. */
+ if (num_substates == 0)
continue;
if (dev->count >= ACPI_PROCESSOR_MAX_POWER) {
@@ -576,6 +835,9 @@ static int mwait_idle_cpu_init(struct notifier_block *nfb,
if (icpu->auto_demotion_disable_flags)
on_selected_cpus(cpumask_of(cpu), auto_demotion_disable, NULL, 1);
+ if (icpu->byt_auto_demotion_disable_flag)
+ on_selected_cpus(cpumask_of(cpu), byt_auto_demotion_disable, NULL, 1);
+
if (icpu->disable_promotion_to_c1e)
on_selected_cpus(cpumask_of(cpu), c1e_promotion_disable, NULL, 1);
diff --git a/xen/arch/x86/crash.c b/xen/arch/x86/crash.c
index 01fd906..c0b83df 100644
--- a/xen/arch/x86/crash.c
+++ b/xen/arch/x86/crash.c
@@ -36,7 +36,7 @@ static unsigned int crashing_cpu;
static DEFINE_PER_CPU_READ_MOSTLY(bool_t, crash_save_done);
/* This becomes the NMI handler for non-crashing CPUs, when Xen is crashing. */
-void __attribute__((noreturn)) do_nmi_crash(struct cpu_user_regs *regs)
+void do_nmi_crash(struct cpu_user_regs *regs)
{
int cpu = smp_processor_id();
@@ -113,6 +113,7 @@ void __attribute__((noreturn)) do_nmi_crash(struct cpu_user_regs *regs)
halt();
}
+void nmi_crash(void);
static void nmi_shootdown_cpus(void)
{
unsigned long msecs;
@@ -148,7 +149,8 @@ static void nmi_shootdown_cpus(void)
* This update is safe from a security point of view, as this pcpu
* is never going to try to sysret back to a PV vcpu.
*/
- _set_gate_lower(&idt_tables[i][TRAP_nmi], 14, 0, &trap_nop);
+ _set_gate_lower(&idt_tables[i][TRAP_nmi],
+ SYS_DESC_irq_gate, 0, &trap_nop);
set_ist(&idt_tables[i][TRAP_machine_check], IST_NONE);
}
else
@@ -204,7 +206,7 @@ void machine_crash_shutdown(void)
info = kexec_crash_save_info();
info->xen_phys_start = xen_phys_start;
info->dom0_pfn_to_mfn_frame_list_list =
- arch_get_pfn_to_mfn_frame_list_list(dom0);
+ arch_get_pfn_to_mfn_frame_list_list(hardware_domain);
}
/*
diff --git a/xen/arch/x86/dmi_scan.c b/xen/arch/x86/dmi_scan.c
index 9d4348b..500133a 100644
--- a/xen/arch/x86/dmi_scan.c
+++ b/xen/arch/x86/dmi_scan.c
@@ -18,16 +18,16 @@
#define memcpy_fromio memcpy
#define alloc_bootmem(l) xmalloc_bytes(l)
-struct dmi_eps {
+struct __packed dmi_eps {
char anchor[5]; /* "_DMI_" */
u8 checksum;
u16 size;
u32 address;
u16 num_structures;
u8 revision;
-} __attribute__((packed));
+};
-struct smbios_eps {
+struct __packed smbios_eps {
char anchor[4]; /* "_SM_" */
u8 checksum;
u8 length;
@@ -36,7 +36,7 @@ struct smbios_eps {
u8 revision;
u8 _rsrvd_[5];
struct dmi_eps dmi;
-} __attribute__((packed));
+};
struct dmi_header
{
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 195b07f..11c7d9f 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -51,6 +51,7 @@
#include <asm/fixmap.h>
#include <asm/hvm/hvm.h>
#include <asm/hvm/support.h>
+#include <asm/hvm/viridian.h>
#include <asm/debugreg.h>
#include <asm/msr.h>
#include <asm/traps.h>
@@ -60,6 +61,7 @@
#include <xen/numa.h>
#include <xen/iommu.h>
#include <compat/vcpu.h>
+#include <asm/psr.h>
DEFINE_PER_CPU(struct vcpu *, curr_vcpu);
DEFINE_PER_CPU(unsigned long, cr4);
@@ -133,12 +135,12 @@ void startup_cpu_idle_loop(void)
reset_stack_and_jump(idle_loop);
}
-static void continue_idle_domain(struct vcpu *v)
+static void noreturn continue_idle_domain(struct vcpu *v)
{
reset_stack_and_jump(idle_loop);
}
-static void continue_nonidle_domain(struct vcpu *v)
+static void noreturn continue_nonidle_domain(struct vcpu *v)
{
check_wakeup_from_wait();
mark_regs_dirty(guest_cpu_user_regs());
@@ -151,15 +153,29 @@ void dump_pageframe_info(struct domain *d)
printk("Memory pages belonging to domain %u:\n", d->domain_id);
- if ( d->tot_pages >= 10 )
+ if ( d->tot_pages >= 10 && d->is_dying < DOMDYING_dead )
{
printk(" DomPage list too long to display\n");
}
else
{
+ unsigned long total[MASK_EXTR(PGT_type_mask, PGT_type_mask) + 1] = {};
+
spin_lock(&d->page_alloc_lock);
page_list_for_each ( page, &d->page_list )
{
+ unsigned int index = MASK_EXTR(page->u.inuse.type_info,
+ PGT_type_mask);
+
+ if ( ++total[index] > 16 )
+ {
+ switch ( page->u.inuse.type_info & PGT_type_mask )
+ {
+ case PGT_none:
+ case PGT_writable_page:
+ continue;
+ }
+ }
printk(" DomPage %p: caf=%08lx, taf=%" PRtype_info "\n",
_p(page_to_mfn(page)),
page->count_info, page->u.inuse.type_info);
@@ -180,6 +196,14 @@ void dump_pageframe_info(struct domain *d)
spin_unlock(&d->page_alloc_lock);
}
+smap_check_policy_t smap_policy_change(struct vcpu *v,
+ smap_check_policy_t new_policy)
+{
+ smap_check_policy_t old_policy = v->arch.smap_check_policy;
+ v->arch.smap_check_policy = new_policy;
+ return old_policy;
+}
+
/*
* The hole may be at or above the 44-bit boundary, so we need to determine
* the total bit count until reaching 32 significant (not squashed out) bits
@@ -407,6 +431,9 @@ int vcpu_initialise(struct vcpu *v)
v->arch.flags = TF_kernel_mode;
+ /* By default, do not emulate */
+ v->arch.mem_event.emulate_flags = 0;
+
rc = mapcache_vcpu_init(v);
if ( rc )
return rc;
@@ -636,6 +663,26 @@ void arch_domain_destroy(struct domain *d)
free_xenheap_page(d->shared_info);
cleanup_domain_irq_mapping(d);
+
+ psr_free_rmid(d);
+}
+
+void arch_domain_shutdown(struct domain *d)
+{
+ if ( has_viridian_time_ref_count(d) )
+ viridian_time_ref_count_freeze(d);
+}
+
+void arch_domain_pause(struct domain *d)
+{
+ if ( has_viridian_time_ref_count(d) )
+ viridian_time_ref_count_freeze(d);
+}
+
+void arch_domain_unpause(struct domain *d)
+{
+ if ( has_viridian_time_ref_count(d) )
+ viridian_time_ref_count_thaw(d);
}
unsigned long pv_guest_cr4_fixup(const struct vcpu *v, unsigned long guest_cr4)
@@ -651,9 +698,9 @@ unsigned long pv_guest_cr4_fixup(const struct vcpu *v, unsigned long guest_cr4)
hv_cr4_mask &= ~X86_CR4_OSXSAVE;
if ( (guest_cr4 & hv_cr4_mask) != (hv_cr4 & hv_cr4_mask) )
- gdprintk(XENLOG_WARNING,
- "Attempt to change CR4 flags %08lx -> %08lx\n",
- hv_cr4, guest_cr4);
+ printk(XENLOG_G_WARNING
+ "d%d attempted to change %pv's CR4 flags %08lx -> %08lx\n",
+ current->domain->domain_id, v, hv_cr4, guest_cr4);
return (hv_cr4 & hv_cr4_mask) | (guest_cr4 & ~hv_cr4_mask);
}
@@ -929,8 +976,8 @@ int arch_set_info_guest(
switch ( rc )
{
case -EINTR:
- rc = -EAGAIN;
- case -EAGAIN:
+ rc = -ERESTART;
+ case -ERESTART:
case 0:
break;
default:
@@ -957,8 +1004,8 @@ int arch_set_info_guest(
switch ( rc )
{
case -EINTR:
- rc = -EAGAIN;
- case -EAGAIN:
+ rc = -ERESTART;
+ case -ERESTART:
v->arch.old_guest_table =
pagetable_get_page(v->arch.guest_table);
v->arch.guest_table = pagetable_null();
@@ -1341,14 +1388,7 @@ static void paravirt_ctxt_switch_to(struct vcpu *v)
write_cr4(cr4);
if ( unlikely(v->arch.debugreg[7] & DR7_ACTIVE_MASK) )
- {
- write_debugreg(0, v->arch.debugreg[0]);
- write_debugreg(1, v->arch.debugreg[1]);
- write_debugreg(2, v->arch.debugreg[2]);
- write_debugreg(3, v->arch.debugreg[3]);
- write_debugreg(6, v->arch.debugreg[6]);
- write_debugreg(7, v->arch.debugreg[7]);
- }
+ activate_debugregs(v);
if ( (v->domain->arch.tsc_mode == TSC_MODE_PVRDTSCP) &&
boot_cpu_has(X86_FEATURE_RDTSCP) )
@@ -1356,22 +1396,31 @@ static void paravirt_ctxt_switch_to(struct vcpu *v)
}
/* Update per-VCPU guest runstate shared memory area (if registered). */
-bool_t update_runstate_area(const struct vcpu *v)
+bool_t update_runstate_area(struct vcpu *v)
{
+ bool_t rc;
+ smap_check_policy_t smap_policy;
+
if ( guest_handle_is_null(runstate_guest(v)) )
return 1;
+ smap_policy = smap_policy_change(v, SMAP_CHECK_ENABLED);
+
if ( has_32bit_shinfo(v->domain) )
{
struct compat_vcpu_runstate_info info;
XLAT_vcpu_runstate_info(&info, &v->runstate);
__copy_to_guest(v->runstate_guest.compat, &info, 1);
- return 1;
+ rc = 1;
}
+ else
+ rc = __copy_to_guest(runstate_guest(v), &v->runstate, 1) !=
+ sizeof(v->runstate);
+
+ smap_policy_change(v, smap_policy);
- return __copy_to_guest(runstate_guest(v), &v->runstate, 1) !=
- sizeof(v->runstate);
+ return rc;
}
static void _update_runstate_area(struct vcpu *v)
@@ -1402,6 +1451,8 @@ static void __context_switch(void)
{
memcpy(&p->arch.user_regs, stack_regs, CTXT_SWITCH_STACK_BYTES);
vcpu_save_fpu(p);
+ if ( psr_cmt_enabled() )
+ psr_assoc_rmid(0);
p->arch.ctxt_switch_from(p);
}
@@ -1426,6 +1477,9 @@ static void __context_switch(void)
}
vcpu_restore_fpu_eager(n);
n->arch.ctxt_switch_to(n);
+
+ if ( psr_cmt_enabled() && n->domain->arch.psr_rmid > 0 )
+ psr_assoc_rmid(n->domain->arch.psr_rmid);
}
gdt = !is_pv_32on64_vcpu(n) ? per_cpu(gdt_table, cpu) :
@@ -1529,7 +1583,8 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
}
set_cpuid_faulting(is_pv_vcpu(next) &&
- (next->domain->domain_id != 0));
+ !is_control_domain(next->domain) &&
+ !is_hardware_domain(next->domain));
}
if (is_hvm_vcpu(next) && (prev != next) )
@@ -1545,13 +1600,11 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
update_vcpu_system_time(next);
schedule_tail(next);
- BUG();
}
void continue_running(struct vcpu *same)
{
schedule_tail(same);
- BUG();
}
int __sync_local_execstate(void)
@@ -1697,7 +1750,8 @@ unsigned long hypercall_create_continuation(
return op;
}
-int hypercall_xlat_continuation(unsigned int *id, unsigned int mask, ...)
+int hypercall_xlat_continuation(unsigned int *id, unsigned int nr,
+ unsigned int mask, ...)
{
int rc = 0;
struct mc_state *mcs = ¤t->mc_state;
@@ -1706,7 +1760,10 @@ int hypercall_xlat_continuation(unsigned int *id, unsigned int mask, ...)
unsigned long nval = 0;
va_list args;
- BUG_ON(id && *id > 5);
+ ASSERT(nr <= ARRAY_SIZE(mcs->call.args));
+ ASSERT(!(mask >> nr));
+
+ BUG_ON(id && *id >= nr);
BUG_ON(id && (mask & (1U << *id)));
va_start(args, mask);
@@ -1719,7 +1776,7 @@ int hypercall_xlat_continuation(unsigned int *id, unsigned int mask, ...)
return 0;
}
- for ( i = 0; i < 6; ++i, mask >>= 1 )
+ for ( i = 0; i < nr; ++i, mask >>= 1 )
{
if ( mask & 1 )
{
@@ -1747,7 +1804,7 @@ int hypercall_xlat_continuation(unsigned int *id, unsigned int mask, ...)
else
{
regs = guest_cpu_user_regs();
- for ( i = 0; i < 6; ++i, mask >>= 1 )
+ for ( i = 0; i < nr; ++i, mask >>= 1 )
{
unsigned long *reg;
@@ -1816,9 +1873,9 @@ static int relinquish_memory(
{
case 0:
break;
- case -EAGAIN:
+ case -ERESTART:
case -EINTR:
- ret = -EAGAIN;
+ ret = -ERESTART;
page_list_add(page, list);
set_bit(_PGT_pinned, &page->u.inuse.type_info);
put_page(page);
@@ -1863,9 +1920,9 @@ static int relinquish_memory(
if ( x & PGT_partial )
put_page(page);
put_page(page);
- ret = -EAGAIN;
+ ret = -ERESTART;
goto out;
- case -EAGAIN:
+ case -ERESTART:
page_list_add(page, list);
page->u.inuse.type_info |= PGT_partial;
if ( x & PGT_partial )
@@ -1889,7 +1946,7 @@ static int relinquish_memory(
if ( hypercall_preempt_check() )
{
- ret = -EAGAIN;
+ ret = -ERESTART;
goto out;
}
}
@@ -1912,10 +1969,14 @@ int domain_relinquish_resources(struct domain *d)
switch ( d->arch.relmem )
{
case RELMEM_not_started:
- pci_release_devices(d);
+ ret = pci_release_devices(d);
+ if ( ret )
+ return ret;
/* Tear down paging-assistance stuff. */
- paging_teardown(d);
+ ret = paging_teardown(d);
+ if ( ret )
+ return ret;
/* Drop the in-use references to page-table bases. */
for_each_vcpu ( d, v )
@@ -1936,15 +1997,14 @@ int domain_relinquish_resources(struct domain *d)
*/
destroy_gdt(v);
}
+ }
- if ( d->arch.pv_domain.pirq_eoi_map != NULL )
- {
- unmap_domain_page_global(d->arch.pv_domain.pirq_eoi_map);
- put_page_and_type(
- mfn_to_page(d->arch.pv_domain.pirq_eoi_map_mfn));
- d->arch.pv_domain.pirq_eoi_map = NULL;
- d->arch.pv_domain.auto_unmask = 0;
- }
+ if ( d->arch.pirq_eoi_map != NULL )
+ {
+ unmap_domain_page_global(d->arch.pirq_eoi_map);
+ put_page_and_type(mfn_to_page(d->arch.pirq_eoi_map_mfn));
+ d->arch.pirq_eoi_map = NULL;
+ d->arch.auto_unmask = 0;
}
d->arch.relmem = RELMEM_shared;
diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
index 84ce392..7a6afea 100644
--- a/xen/arch/x86/domain_build.c
+++ b/xen/arch/x86/domain_build.c
@@ -35,6 +35,7 @@
#include <asm/setup.h>
#include <asm/bzimage.h> /* for bzimage_parse */
#include <asm/io_apic.h>
+#include <asm/hap.h>
#include <public/version.h>
@@ -100,7 +101,7 @@ static void __init parse_dom0_max_vcpus(const char *s)
}
custom_param("dom0_max_vcpus", parse_dom0_max_vcpus);
-struct vcpu *__init alloc_dom0_vcpu0(void)
+struct vcpu *__init alloc_dom0_vcpu0(struct domain *dom0)
{
unsigned max_vcpus;
@@ -269,7 +270,7 @@ static unsigned long __init compute_dom0_nr_pages(
return nr_pages;
}
-static void __init process_dom0_ioports_disable(void)
+static void __init process_dom0_ioports_disable(struct domain *dom0)
{
unsigned long io_from, io_to;
char *t, *s = opt_dom0_ioports_disable;
@@ -307,6 +308,447 @@ static void __init process_dom0_ioports_disable(void)
}
}
+static __init void pvh_add_mem_mapping(struct domain *d, unsigned long gfn,
+ unsigned long mfn, unsigned long nr_mfns)
+{
+ unsigned long i;
+ int rc;
+
+ for ( i = 0; i < nr_mfns; i++ )
+ {
+ if ( (rc = set_mmio_p2m_entry(d, gfn + i, _mfn(mfn + i))) )
+ panic("pvh_add_mem_mapping: gfn:%lx mfn:%lx i:%ld rc:%d\n",
+ gfn, mfn, i, rc);
+ if ( !(i & 0xfffff) )
+ process_pending_softirqs();
+ }
+}
+
+/*
+ * Set the 1:1 map for all non-RAM regions for dom 0. Thus, dom0 will have
+ * the entire io region mapped in the EPT/NPT.
+ *
+ * pvh fixme: The following doesn't map MMIO ranges when they sit above the
+ * highest E820 covered address.
+ */
+static __init void pvh_map_all_iomem(struct domain *d, unsigned long nr_pages)
+{
+ unsigned long start_pfn, end_pfn, end = 0, start = 0;
+ const struct e820entry *entry;
+ unsigned long nump, nmap, navail, mfn, nr_holes = 0;
+ unsigned int i;
+ struct page_info *page;
+ int rc;
+
+ for ( i = 0, entry = e820.map; i < e820.nr_map; i++, entry++ )
+ {
+ end = entry->addr + entry->size;
+
+ if ( entry->type == E820_RAM || entry->type == E820_UNUSABLE ||
+ i == e820.nr_map - 1 )
+ {
+ start_pfn = PFN_DOWN(start);
+
+ /* Unused RAM areas are marked UNUSABLE, so skip them too */
+ if ( entry->type == E820_RAM || entry->type == E820_UNUSABLE )
+ end_pfn = PFN_UP(entry->addr);
+ else
+ end_pfn = PFN_UP(end);
+
+ if ( start_pfn < end_pfn )
+ {
+ nump = end_pfn - start_pfn;
+ /* Add pages to the mapping */
+ pvh_add_mem_mapping(d, start_pfn, start_pfn, nump);
+ if ( start_pfn < nr_pages )
+ nr_holes += (end_pfn < nr_pages) ?
+ nump : (nr_pages - start_pfn);
+ }
+ start = end;
+ }
+ }
+
+ /*
+ * Some BIOSes may not report io space above ram that is less than 4GB. So
+ * we map any non-ram upto 4GB.
+ */
+ if ( end < GB(4) )
+ {
+ start_pfn = PFN_UP(end);
+ end_pfn = (GB(4)) >> PAGE_SHIFT;
+ nump = end_pfn - start_pfn;
+ pvh_add_mem_mapping(d, start_pfn, start_pfn, nump);
+ }
+
+ /*
+ * Add the memory removed by the holes at the end of the
+ * memory map.
+ */
+ page = page_list_first(&d->page_list);
+ for ( i = 0, entry = e820.map; i < e820.nr_map && nr_holes > 0;
+ i++, entry++ )
+ {
+ if ( entry->type != E820_RAM )
+ continue;
+
+ end_pfn = PFN_UP(entry->addr + entry->size);
+ if ( end_pfn <= nr_pages )
+ continue;
+
+ navail = end_pfn - nr_pages;
+ nmap = min(navail, nr_holes);
+ nr_holes -= nmap;
+ start_pfn = max_t(unsigned long, nr_pages, PFN_DOWN(entry->addr));
+ /*
+ * Populate this memory region using the pages
+ * previously removed by the MMIO holes.
+ */
+ do
+ {
+ mfn = page_to_mfn(page);
+ if ( get_gpfn_from_mfn(mfn) != INVALID_M2P_ENTRY )
+ continue;
+
+ rc = guest_physmap_add_page(d, start_pfn, mfn, 0);
+ if ( rc != 0 )
+ panic("Unable to add gpfn %#lx mfn %#lx to Dom0 physmap: %d",
+ start_pfn, mfn, rc);
+ start_pfn++;
+ nmap--;
+ if ( !(nmap & 0xfffff) )
+ process_pending_softirqs();
+ } while ( ((page = page_list_next(page, &d->page_list)) != NULL)
+ && nmap );
+ ASSERT(nmap == 0);
+ if ( page == NULL )
+ break;
+ }
+
+ ASSERT(nr_holes == 0);
+}
+
+static __init void pvh_setup_e820(struct domain *d, unsigned long nr_pages)
+{
+ struct e820entry *entry, *entry_guest;
+ unsigned int i;
+ unsigned long pages, cur_pages = 0;
+
+ /*
+ * Craft the e820 memory map for Dom0 based on the hardware e820 map.
+ */
+ d->arch.e820 = xzalloc_array(struct e820entry, e820.nr_map);
+ if ( !d->arch.e820 )
+ panic("Unable to allocate memory for Dom0 e820 map");
+ entry_guest = d->arch.e820;
+
+ /* Clamp e820 memory map to match the memory assigned to Dom0 */
+ for ( i = 0, entry = e820.map; i < e820.nr_map; i++, entry++ )
+ {
+ if ( entry->type != E820_RAM )
+ {
+ *entry_guest = *entry;
+ goto next;
+ }
+
+ if ( nr_pages == cur_pages )
+ {
+ /*
+ * We already have all the assigned memory,
+ * skip this entry
+ */
+ continue;
+ }
+
+ *entry_guest = *entry;
+ pages = PFN_UP(entry_guest->size);
+ if ( (cur_pages + pages) > nr_pages )
+ {
+ /* Truncate region */
+ entry_guest->size = (nr_pages - cur_pages) << PAGE_SHIFT;
+ cur_pages = nr_pages;
+ }
+ else
+ {
+ cur_pages += pages;
+ }
+ next:
+ d->arch.nr_e820++;
+ entry_guest++;
+ }
+ ASSERT(cur_pages == nr_pages);
+ ASSERT(d->arch.nr_e820 <= e820.nr_map);
+}
+
+static __init void dom0_update_physmap(struct domain *d, unsigned long pfn,
+ unsigned long mfn, unsigned long vphysmap_s)
+{
+ if ( is_pvh_domain(d) )
+ {
+ int rc = guest_physmap_add_page(d, pfn, mfn, 0);
+ BUG_ON(rc);
+ return;
+ }
+ if ( !is_pv_32on64_domain(d) )
+ ((unsigned long *)vphysmap_s)[pfn] = mfn;
+ else
+ ((unsigned int *)vphysmap_s)[pfn] = mfn;
+
+ set_gpfn_from_mfn(mfn, pfn);
+}
+
+/* Replace mfns with pfns in dom0 page tables */
+static __init void pvh_fixup_page_tables_for_hap(struct vcpu *v,
+ unsigned long v_start,
+ unsigned long v_end)
+{
+ int i, j, k;
+ l4_pgentry_t *pl4e, *l4start;
+ l3_pgentry_t *pl3e;
+ l2_pgentry_t *pl2e;
+ l1_pgentry_t *pl1e;
+ unsigned long cr3_pfn;
+
+ ASSERT(paging_mode_enabled(v->domain));
+
+ l4start = map_domain_page(pagetable_get_pfn(v->arch.guest_table));
+
+ /* Clear entries prior to guest L4 start */
+ pl4e = l4start + l4_table_offset(v_start);
+ memset(l4start, 0, (unsigned long)pl4e - (unsigned long)l4start);
+
+ for ( ; pl4e <= l4start + l4_table_offset(v_end - 1); pl4e++ )
+ {
+ pl3e = map_l3t_from_l4e(*pl4e);
+ for ( i = 0; i < PAGE_SIZE / sizeof(*pl3e); i++, pl3e++ )
+ {
+ if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
+ continue;
+
+ pl2e = map_l2t_from_l3e(*pl3e);
+ for ( j = 0; j < PAGE_SIZE / sizeof(*pl2e); j++, pl2e++ )
+ {
+ if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
+ continue;
+
+ pl1e = map_l1t_from_l2e(*pl2e);
+ for ( k = 0; k < PAGE_SIZE / sizeof(*pl1e); k++, pl1e++ )
+ {
+ if ( !(l1e_get_flags(*pl1e) & _PAGE_PRESENT) )
+ continue;
+
+ *pl1e = l1e_from_pfn(get_gpfn_from_mfn(l1e_get_pfn(*pl1e)),
+ l1e_get_flags(*pl1e));
+ }
+ unmap_domain_page(pl1e);
+ *pl2e = l2e_from_pfn(get_gpfn_from_mfn(l2e_get_pfn(*pl2e)),
+ l2e_get_flags(*pl2e));
+ }
+ unmap_domain_page(pl2e);
+ *pl3e = l3e_from_pfn(get_gpfn_from_mfn(l3e_get_pfn(*pl3e)),
+ l3e_get_flags(*pl3e));
+ }
+ unmap_domain_page(pl3e);
+ *pl4e = l4e_from_pfn(get_gpfn_from_mfn(l4e_get_pfn(*pl4e)),
+ l4e_get_flags(*pl4e));
+ }
+
+ /* Clear entries post guest L4. */
+ if ( (unsigned long)pl4e & (PAGE_SIZE - 1) )
+ memset(pl4e, 0, PAGE_SIZE - ((unsigned long)pl4e & (PAGE_SIZE - 1)));
+
+ unmap_domain_page(l4start);
+
+ cr3_pfn = get_gpfn_from_mfn(paddr_to_pfn(v->arch.cr3));
+ v->arch.hvm_vcpu.guest_cr[3] = pfn_to_paddr(cr3_pfn);
+
+ /*
+ * Finally, we update the paging modes (hap_update_paging_modes). This will
+ * create monitor_table for us, update v->arch.cr3, and update vmcs.cr3.
+ */
+ paging_update_paging_modes(v);
+}
+
+static __init void mark_pv_pt_pages_rdonly(struct domain *d,
+ l4_pgentry_t *l4start,
+ unsigned long vpt_start,
+ unsigned long nr_pt_pages)
+{
+ unsigned long count;
+ struct page_info *page;
+ l4_pgentry_t *pl4e;
+ l3_pgentry_t *pl3e;
+ l2_pgentry_t *pl2e;
+ l1_pgentry_t *pl1e;
+
+ pl4e = l4start + l4_table_offset(vpt_start);
+ pl3e = l4e_to_l3e(*pl4e);
+ pl3e += l3_table_offset(vpt_start);
+ pl2e = l3e_to_l2e(*pl3e);
+ pl2e += l2_table_offset(vpt_start);
+ pl1e = l2e_to_l1e(*pl2e);
+ pl1e += l1_table_offset(vpt_start);
+ for ( count = 0; count < nr_pt_pages; count++ )
+ {
+ l1e_remove_flags(*pl1e, _PAGE_RW);
+ page = mfn_to_page(l1e_get_pfn(*pl1e));
+
+ /* Read-only mapping + PGC_allocated + page-table page. */
+ page->count_info = PGC_allocated | 3;
+ page->u.inuse.type_info |= PGT_validated | 1;
+
+ /* Top-level p.t. is pinned. */
+ if ( (page->u.inuse.type_info & PGT_type_mask) ==
+ (!is_pv_32on64_domain(d) ?
+ PGT_l4_page_table : PGT_l3_page_table) )
+ {
+ page->count_info += 1;
+ page->u.inuse.type_info += 1 | PGT_pinned;
+ }
+
+ /* Iterate. */
+ if ( !((unsigned long)++pl1e & (PAGE_SIZE - 1)) )
+ {
+ if ( !((unsigned long)++pl2e & (PAGE_SIZE - 1)) )
+ {
+ if ( !((unsigned long)++pl3e & (PAGE_SIZE - 1)) )
+ pl3e = l4e_to_l3e(*++pl4e);
+ pl2e = l3e_to_l2e(*pl3e);
+ }
+ pl1e = l2e_to_l1e(*pl2e);
+ }
+ }
+}
+
+static __init void setup_pv_physmap(struct domain *d, unsigned long pgtbl_pfn,
+ unsigned long v_start, unsigned long v_end,
+ unsigned long vphysmap_start,
+ unsigned long vphysmap_end,
+ unsigned long nr_pages)
+{
+ struct page_info *page = NULL;
+ l4_pgentry_t *pl4e, *l4start = map_domain_page(pgtbl_pfn);
+ l3_pgentry_t *pl3e = NULL;
+ l2_pgentry_t *pl2e = NULL;
+ l1_pgentry_t *pl1e = NULL;
+
+ if ( v_start <= vphysmap_end && vphysmap_start <= v_end )
+ panic("DOM0 P->M table overlaps initial mapping");
+
+ while ( vphysmap_start < vphysmap_end )
+ {
+ if ( d->tot_pages + ((round_pgup(vphysmap_end) - vphysmap_start)
+ >> PAGE_SHIFT) + 3 > nr_pages )
+ panic("Dom0 allocation too small for initial P->M table");
+
+ if ( pl1e )
+ {
+ unmap_domain_page(pl1e);
+ pl1e = NULL;
+ }
+ if ( pl2e )
+ {
+ unmap_domain_page(pl2e);
+ pl2e = NULL;
+ }
+ if ( pl3e )
+ {
+ unmap_domain_page(pl3e);
+ pl3e = NULL;
+ }
+ pl4e = l4start + l4_table_offset(vphysmap_start);
+ if ( !l4e_get_intpte(*pl4e) )
+ {
+ page = alloc_domheap_page(d, 0);
+ if ( !page )
+ break;
+
+ /* No mapping, PGC_allocated + page-table page. */
+ page->count_info = PGC_allocated | 2;
+ page->u.inuse.type_info = PGT_l3_page_table | PGT_validated | 1;
+ pl3e = __map_domain_page(page);
+ clear_page(pl3e);
+ *pl4e = l4e_from_page(page, L4_PROT);
+ } else
+ pl3e = map_domain_page(l4e_get_pfn(*pl4e));
+
+ pl3e += l3_table_offset(vphysmap_start);
+ if ( !l3e_get_intpte(*pl3e) )
+ {
+ if ( cpu_has_page1gb &&
+ !(vphysmap_start & ((1UL << L3_PAGETABLE_SHIFT) - 1)) &&
+ vphysmap_end >= vphysmap_start + (1UL << L3_PAGETABLE_SHIFT) &&
+ (page = alloc_domheap_pages(d,
+ L3_PAGETABLE_SHIFT - PAGE_SHIFT,
+ 0)) != NULL )
+ {
+ *pl3e = l3e_from_page(page, L1_PROT|_PAGE_DIRTY|_PAGE_PSE);
+ vphysmap_start += 1UL << L3_PAGETABLE_SHIFT;
+ continue;
+ }
+ if ( (page = alloc_domheap_page(d, 0)) == NULL )
+ break;
+
+ /* No mapping, PGC_allocated + page-table page. */
+ page->count_info = PGC_allocated | 2;
+ page->u.inuse.type_info = PGT_l2_page_table | PGT_validated | 1;
+ pl2e = __map_domain_page(page);
+ clear_page(pl2e);
+ *pl3e = l3e_from_page(page, L3_PROT);
+ }
+ else
+ pl2e = map_domain_page(l3e_get_pfn(*pl3e));
+
+ pl2e += l2_table_offset(vphysmap_start);
+ if ( !l2e_get_intpte(*pl2e) )
+ {
+ if ( !(vphysmap_start & ((1UL << L2_PAGETABLE_SHIFT) - 1)) &&
+ vphysmap_end >= vphysmap_start + (1UL << L2_PAGETABLE_SHIFT) &&
+ (page = alloc_domheap_pages(d,
+ L2_PAGETABLE_SHIFT - PAGE_SHIFT,
+ 0)) != NULL )
+ {
+ *pl2e = l2e_from_page(page, L1_PROT|_PAGE_DIRTY|_PAGE_PSE);
+ if ( opt_allow_superpage )
+ get_superpage(page_to_mfn(page), d);
+ vphysmap_start += 1UL << L2_PAGETABLE_SHIFT;
+ continue;
+ }
+ if ( (page = alloc_domheap_page(d, 0)) == NULL )
+ break;
+
+ /* No mapping, PGC_allocated + page-table page. */
+ page->count_info = PGC_allocated | 2;
+ page->u.inuse.type_info = PGT_l1_page_table | PGT_validated | 1;
+ pl1e = __map_domain_page(page);
+ clear_page(pl1e);
+ *pl2e = l2e_from_page(page, L2_PROT);
+ }
+ else
+ pl1e = map_domain_page(l2e_get_pfn(*pl2e));
+
+ pl1e += l1_table_offset(vphysmap_start);
+ BUG_ON(l1e_get_intpte(*pl1e));
+ page = alloc_domheap_page(d, 0);
+ if ( !page )
+ break;
+
+ *pl1e = l1e_from_page(page, L1_PROT|_PAGE_DIRTY);
+ vphysmap_start += PAGE_SIZE;
+ vphysmap_start &= PAGE_MASK;
+ }
+ if ( !page )
+ panic("Not enough RAM for DOM0 P->M table");
+
+ if ( pl1e )
+ unmap_domain_page(pl1e);
+ if ( pl2e )
+ unmap_domain_page(pl2e);
+ if ( pl3e )
+ unmap_domain_page(pl3e);
+
+ unmap_domain_page(l4start);
+}
+
int __init construct_dom0(
struct domain *d,
const module_t *image, unsigned long image_headroom,
@@ -335,6 +777,8 @@ int __init construct_dom0(
l3_pgentry_t *l3tab = NULL, *l3start = NULL;
l2_pgentry_t *l2tab = NULL, *l2start = NULL;
l1_pgentry_t *l1tab = NULL, *l1start = NULL;
+ paddr_t shared_info_paddr = 0;
+ u32 save_pvh_pg_mode = 0;
/*
* This fully describes the memory layout of the initial domain. All
@@ -412,12 +856,21 @@ int __init construct_dom0(
goto out;
}
- if ( parms.elf_notes[XEN_ELFNOTE_SUPPORTED_FEATURES].type != XEN_ENT_NONE &&
- !test_bit(XENFEAT_dom0, parms.f_supported) )
+ if ( parms.elf_notes[XEN_ELFNOTE_SUPPORTED_FEATURES].type != XEN_ENT_NONE )
{
- printk("Kernel does not support Dom0 operation\n");
- rc = -EINVAL;
- goto out;
+ if ( !test_bit(XENFEAT_dom0, parms.f_supported) )
+ {
+ printk("Kernel does not support Dom0 operation\n");
+ rc = -EINVAL;
+ goto out;
+ }
+ if ( is_pvh_domain(d) &&
+ !test_bit(XENFEAT_hvm_callback_vector, parms.f_supported) )
+ {
+ printk("Kernel does not support PVH mode\n");
+ rc = -EINVAL;
+ goto out;
+ }
}
if ( compat32 )
@@ -482,6 +935,13 @@ int __init construct_dom0(
vstartinfo_end = (vstartinfo_start +
sizeof(struct start_info) +
sizeof(struct dom0_vga_console_info));
+
+ if ( is_pvh_domain(d) )
+ {
+ shared_info_paddr = round_pgup(vstartinfo_end) - v_start;
+ vstartinfo_end += PAGE_SIZE;
+ }
+
vpt_start = round_pgup(vstartinfo_end);
for ( nr_pt_pages = 2; ; nr_pt_pages++ )
{
@@ -677,10 +1137,13 @@ int __init construct_dom0(
L1_PROT : COMPAT_L1_PROT));
l1tab++;
- page = mfn_to_page(mfn);
- if ( (page->u.inuse.type_info == 0) &&
- !get_page_and_type(page, d, PGT_writable_page) )
- BUG();
+ if ( !paging_mode_translate(d) )
+ {
+ page = mfn_to_page(mfn);
+ if ( !page->u.inuse.type_info &&
+ !get_page_and_type(page, d, PGT_writable_page) )
+ BUG();
+ }
}
if ( is_pv_32on64_domain(d) )
@@ -706,43 +1169,8 @@ int __init construct_dom0(
}
/* Pages that are part of page tables must be read only. */
- l4tab = l4start + l4_table_offset(vpt_start);
- l3start = l3tab = l4e_to_l3e(*l4tab);
- l3tab += l3_table_offset(vpt_start);
- l2start = l2tab = l3e_to_l2e(*l3tab);
- l2tab += l2_table_offset(vpt_start);
- l1start = l1tab = l2e_to_l1e(*l2tab);
- l1tab += l1_table_offset(vpt_start);
- for ( count = 0; count < nr_pt_pages; count++ )
- {
- l1e_remove_flags(*l1tab, _PAGE_RW);
- page = mfn_to_page(l1e_get_pfn(*l1tab));
-
- /* Read-only mapping + PGC_allocated + page-table page. */
- page->count_info = PGC_allocated | 3;
- page->u.inuse.type_info |= PGT_validated | 1;
-
- /* Top-level p.t. is pinned. */
- if ( (page->u.inuse.type_info & PGT_type_mask) ==
- (!is_pv_32on64_domain(d) ?
- PGT_l4_page_table : PGT_l3_page_table) )
- {
- page->count_info += 1;
- page->u.inuse.type_info += 1 | PGT_pinned;
- }
-
- /* Iterate. */
- if ( !((unsigned long)++l1tab & (PAGE_SIZE - 1)) )
- {
- if ( !((unsigned long)++l2tab & (PAGE_SIZE - 1)) )
- {
- if ( !((unsigned long)++l3tab & (PAGE_SIZE - 1)) )
- l3start = l3tab = l4e_to_l3e(*++l4tab);
- l2start = l2tab = l3e_to_l2e(*l3tab);
- }
- l1start = l1tab = l2e_to_l1e(*l2tab);
- }
- }
+ if ( is_pv_domain(d) )
+ mark_pv_pt_pages_rdonly(d, l4start, vpt_start, nr_pt_pages);
/* Mask all upcalls... */
for ( i = 0; i < XEN_LEGACY_MAX_VCPUS; i++ )
@@ -757,6 +1185,13 @@ int __init construct_dom0(
(void)alloc_vcpu(d, i, cpu);
}
+ /*
+ * pvh: we temporarily disable d->arch.paging.mode so that we can build cr3
+ * needed to run on dom0's page tables.
+ */
+ save_pvh_pg_mode = d->arch.paging.mode;
+ d->arch.paging.mode = 0;
+
/* Set up CR3 value for write_ptbase */
if ( paging_mode_enabled(d) )
paging_update_paging_modes(v);
@@ -814,131 +1249,30 @@ int __init construct_dom0(
elf_64bit(&elf) ? 64 : 32, parms.pae ? "p" : "");
count = d->tot_pages;
- l4start = map_domain_page(pagetable_get_pfn(v->arch.guest_table));
- l3tab = NULL;
- l2tab = NULL;
- l1tab = NULL;
+
/* Set up the phys->machine table if not part of the initial mapping. */
- if ( parms.p2m_base != UNSET_ADDR )
+ if ( is_pv_domain(d) && parms.p2m_base != UNSET_ADDR )
{
- unsigned long va = vphysmap_start;
-
- if ( v_start <= vphysmap_end && vphysmap_start <= v_end )
- panic("DOM0 P->M table overlaps initial mapping");
+ pfn = pagetable_get_pfn(v->arch.guest_table);
+ setup_pv_physmap(d, pfn, v_start, v_end, vphysmap_start, vphysmap_end,
+ nr_pages);
+ }
- while ( va < vphysmap_end )
- {
- if ( d->tot_pages + ((round_pgup(vphysmap_end) - va)
- >> PAGE_SHIFT) + 3 > nr_pages )
- panic("Dom0 allocation too small for initial P->M table");
+ if ( is_pvh_domain(d) )
+ {
+ unsigned long hap_pages, memkb = nr_pages * (PAGE_SIZE / 1024);
- if ( l1tab )
- {
- unmap_domain_page(l1tab);
- l1tab = NULL;
- }
- if ( l2tab )
- {
- unmap_domain_page(l2tab);
- l2tab = NULL;
- }
- if ( l3tab )
- {
- unmap_domain_page(l3tab);
- l3tab = NULL;
- }
- l4tab = l4start + l4_table_offset(va);
- if ( !l4e_get_intpte(*l4tab) )
- {
- page = alloc_domheap_page(d, 0);
- if ( !page )
- break;
- /* No mapping, PGC_allocated + page-table page. */
- page->count_info = PGC_allocated | 2;
- page->u.inuse.type_info =
- PGT_l3_page_table | PGT_validated | 1;
- l3tab = __map_domain_page(page);
- clear_page(l3tab);
- *l4tab = l4e_from_page(page, L4_PROT);
- } else
- l3tab = map_domain_page(l4e_get_pfn(*l4tab));
- l3tab += l3_table_offset(va);
- if ( !l3e_get_intpte(*l3tab) )
- {
- if ( cpu_has_page1gb &&
- !(va & ((1UL << L3_PAGETABLE_SHIFT) - 1)) &&
- vphysmap_end >= va + (1UL << L3_PAGETABLE_SHIFT) &&
- (page = alloc_domheap_pages(d,
- L3_PAGETABLE_SHIFT -
- PAGE_SHIFT,
- 0)) != NULL )
- {
- *l3tab = l3e_from_page(page,
- L1_PROT|_PAGE_DIRTY|_PAGE_PSE);
- va += 1UL << L3_PAGETABLE_SHIFT;
- continue;
- }
- if ( (page = alloc_domheap_page(d, 0)) == NULL )
- break;
- /* No mapping, PGC_allocated + page-table page. */
- page->count_info = PGC_allocated | 2;
- page->u.inuse.type_info =
- PGT_l2_page_table | PGT_validated | 1;
- l2tab = __map_domain_page(page);
- clear_page(l2tab);
- *l3tab = l3e_from_page(page, L3_PROT);
- }
- else
- l2tab = map_domain_page(l3e_get_pfn(*l3tab));
- l2tab += l2_table_offset(va);
- if ( !l2e_get_intpte(*l2tab) )
- {
- if ( !(va & ((1UL << L2_PAGETABLE_SHIFT) - 1)) &&
- vphysmap_end >= va + (1UL << L2_PAGETABLE_SHIFT) &&
- (page = alloc_domheap_pages(d,
- L2_PAGETABLE_SHIFT -
- PAGE_SHIFT,
- 0)) != NULL )
- {
- *l2tab = l2e_from_page(page,
- L1_PROT|_PAGE_DIRTY|_PAGE_PSE);
- if ( opt_allow_superpage )
- get_superpage(page_to_mfn(page), d);
- va += 1UL << L2_PAGETABLE_SHIFT;
- continue;
- }
- if ( (page = alloc_domheap_page(d, 0)) == NULL )
- break;
- /* No mapping, PGC_allocated + page-table page. */
- page->count_info = PGC_allocated | 2;
- page->u.inuse.type_info =
- PGT_l1_page_table | PGT_validated | 1;
- l1tab = __map_domain_page(page);
- clear_page(l1tab);
- *l2tab = l2e_from_page(page, L2_PROT);
- }
- else
- l1tab = map_domain_page(l2e_get_pfn(*l2tab));
- l1tab += l1_table_offset(va);
- BUG_ON(l1e_get_intpte(*l1tab));
- page = alloc_domheap_page(d, 0);
- if ( !page )
- break;
- *l1tab = l1e_from_page(page, L1_PROT|_PAGE_DIRTY);
- va += PAGE_SIZE;
- va &= PAGE_MASK;
- }
- if ( !page )
- panic("Not enough RAM for DOM0 P->M table");
+ /* Copied from: libxl_get_required_shadow_memory() */
+ memkb = 4 * (256 * d->max_vcpus + 2 * (memkb / 1024));
+ hap_pages = ( (memkb + 1023) / 1024) << (20 - PAGE_SHIFT);
+ hap_set_alloc_for_pvh_dom0(d, hap_pages);
}
- if ( l1tab )
- unmap_domain_page(l1tab);
- if ( l2tab )
- unmap_domain_page(l2tab);
- if ( l3tab )
- unmap_domain_page(l3tab);
- unmap_domain_page(l4start);
+ /*
+ * We enable paging mode again so guest_physmap_add_page will do the
+ * right thing for us.
+ */
+ d->arch.paging.mode = save_pvh_pg_mode;
/* Write the phys->machine and machine->phys table entries. */
for ( pfn = 0; pfn < count; pfn++ )
@@ -956,11 +1290,7 @@ int __init construct_dom0(
if ( pfn > REVERSE_START && (vinitrd_start || pfn < initrd_pfn) )
mfn = alloc_epfn - (pfn - REVERSE_START);
#endif
- if ( !is_pv_32on64_domain(d) )
- ((unsigned long *)vphysmap_start)[pfn] = mfn;
- else
- ((unsigned int *)vphysmap_start)[pfn] = mfn;
- set_gpfn_from_mfn(mfn, pfn);
+ dom0_update_physmap(d, pfn, mfn, vphysmap_start);
if (!(pfn & 0xfffff))
process_pending_softirqs();
}
@@ -973,11 +1303,11 @@ int __init construct_dom0(
if ( get_gpfn_from_mfn(mfn) >= count )
{
BUG_ON(is_pv_32bit_domain(d));
- if ( !page->u.inuse.type_info &&
+ if ( !paging_mode_translate(d) && !page->u.inuse.type_info &&
!get_page_and_type(page, d, PGT_writable_page) )
BUG();
- ((unsigned long *)vphysmap_start)[pfn] = mfn;
- set_gpfn_from_mfn(mfn, pfn);
+
+ dom0_update_physmap(d, pfn, mfn, vphysmap_start);
++pfn;
if (!(pfn & 0xfffff))
process_pending_softirqs();
@@ -997,11 +1327,7 @@ int __init construct_dom0(
#ifndef NDEBUG
#define pfn (nr_pages - 1 - (pfn - (alloc_epfn - alloc_spfn)))
#endif
- if ( !is_pv_32on64_domain(d) )
- ((unsigned long *)vphysmap_start)[pfn] = mfn;
- else
- ((unsigned int *)vphysmap_start)[pfn] = mfn;
- set_gpfn_from_mfn(mfn, pfn);
+ dom0_update_physmap(d, pfn, mfn, vphysmap_start);
#undef pfn
page++; pfn++;
if (!(pfn & 0xfffff))
@@ -1025,6 +1351,15 @@ int __init construct_dom0(
si->console.dom0.info_size = sizeof(struct dom0_vga_console_info);
}
+ /*
+ * PVH: We need to update si->shared_info while we are on dom0 page tables,
+ * but need to defer the p2m update until after we have fixed up the
+ * page tables for PVH so that the m2p for the si pte entry returns
+ * correct pfn.
+ */
+ if ( is_pvh_domain(d) )
+ si->shared_info = shared_info_paddr;
+
if ( is_pv_32on64_domain(d) )
xlat_start_info(si, XLAT_start_info_console_dom0);
@@ -1058,8 +1393,15 @@ int __init construct_dom0(
regs->eflags = X86_EFLAGS_IF;
if ( opt_dom0_shadow )
+ {
+ if ( is_pvh_domain(d) )
+ {
+ printk("Unsupported option dom0_shadow for PVH\n");
+ return -EINVAL;
+ }
if ( paging_enable(d, PG_SH_enable) == 0 )
paging_update_paging_modes(v);
+ }
if ( supervisor_mode_kernel )
{
@@ -1082,29 +1424,29 @@ int __init construct_dom0(
rc = 0;
- /* DOM0 is permitted full I/O capabilities. */
- rc |= ioports_permit_access(dom0, 0, 0xFFFF);
- rc |= iomem_permit_access(dom0, 0UL, ~0UL);
- rc |= irqs_permit_access(dom0, 1, nr_irqs_gsi - 1);
+ /* The hardware domain is initially permitted full I/O capabilities. */
+ rc |= ioports_permit_access(d, 0, 0xFFFF);
+ rc |= iomem_permit_access(d, 0UL, ~0UL);
+ rc |= irqs_permit_access(d, 1, nr_irqs_gsi - 1);
/*
* Modify I/O port access permissions.
*/
/* Master Interrupt Controller (PIC). */
- rc |= ioports_deny_access(dom0, 0x20, 0x21);
+ rc |= ioports_deny_access(d, 0x20, 0x21);
/* Slave Interrupt Controller (PIC). */
- rc |= ioports_deny_access(dom0, 0xA0, 0xA1);
+ rc |= ioports_deny_access(d, 0xA0, 0xA1);
/* Interval Timer (PIT). */
- rc |= ioports_deny_access(dom0, 0x40, 0x43);
+ rc |= ioports_deny_access(d, 0x40, 0x43);
/* PIT Channel 2 / PC Speaker Control. */
- rc |= ioports_deny_access(dom0, 0x61, 0x61);
+ rc |= ioports_deny_access(d, 0x61, 0x61);
/* ACPI PM Timer. */
if ( pmtmr_ioport )
- rc |= ioports_deny_access(dom0, pmtmr_ioport, pmtmr_ioport + 3);
+ rc |= ioports_deny_access(d, pmtmr_ioport, pmtmr_ioport + 3);
/* PCI configuration space (NB. 0xcf8 has special treatment). */
- rc |= ioports_deny_access(dom0, 0xcfc, 0xcff);
+ rc |= ioports_deny_access(d, 0xcfc, 0xcff);
/* Command-line I/O ranges. */
- process_dom0_ioports_disable();
+ process_dom0_ioports_disable(d);
/*
* Modify I/O memory access permissions.
@@ -1113,22 +1455,22 @@ int __init construct_dom0(
if ( mp_lapic_addr != 0 )
{
mfn = paddr_to_pfn(mp_lapic_addr);
- rc |= iomem_deny_access(dom0, mfn, mfn);
+ rc |= iomem_deny_access(d, mfn, mfn);
}
/* I/O APICs. */
for ( i = 0; i < nr_ioapics; i++ )
{
mfn = paddr_to_pfn(mp_ioapics[i].mpc_apicaddr);
if ( !rangeset_contains_singleton(mmio_ro_ranges, mfn) )
- rc |= iomem_deny_access(dom0, mfn, mfn);
+ rc |= iomem_deny_access(d, mfn, mfn);
}
/* MSI range. */
- rc |= iomem_deny_access(dom0, paddr_to_pfn(MSI_ADDR_BASE_LO),
+ rc |= iomem_deny_access(d, paddr_to_pfn(MSI_ADDR_BASE_LO),
paddr_to_pfn(MSI_ADDR_BASE_LO +
MSI_ADDR_DEST_ID_MASK));
/* HyperTransport range. */
if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
- rc |= iomem_deny_access(dom0, paddr_to_pfn(0xfdULL << 32),
+ rc |= iomem_deny_access(d, paddr_to_pfn(0xfdULL << 32),
paddr_to_pfn((1ULL << 40) - 1));
/* Remove access to E820_UNUSABLE I/O regions above 1MB. */
@@ -1140,7 +1482,7 @@ int __init construct_dom0(
if ( (e820.map[i].type == E820_UNUSABLE) &&
(e820.map[i].size != 0) &&
(sfn <= efn) )
- rc |= iomem_deny_access(dom0, sfn, efn);
+ rc |= iomem_deny_access(d, sfn, efn);
}
BUG_ON(rc != 0);
@@ -1149,7 +1491,23 @@ int __init construct_dom0(
printk(" Xen warning: dom0 kernel broken ELF: %s\n",
elf_check_broken(&elf));
- iommu_dom0_init(dom0);
+ if ( is_pvh_domain(d) )
+ {
+ /* finally, fixup the page table, replacing mfns with pfns */
+ pvh_fixup_page_tables_for_hap(v, v_start, v_end);
+
+ /* the pt has correct pfn for si, now update the mfn in the p2m */
+ mfn = virt_to_mfn(d->shared_info);
+ pfn = shared_info_paddr >> PAGE_SHIFT;
+ dom0_update_physmap(d, pfn, mfn, 0);
+
+ pvh_map_all_iomem(d, nr_pages);
+ pvh_setup_e820(d, nr_pages);
+ }
+
+ if ( d->domain_id == hardware_domid )
+ iommu_hwdom_init(d);
+
return 0;
out:
diff --git a/xen/arch/x86/domain_page.c b/xen/arch/x86/domain_page.c
index 3903952..158a164 100644
--- a/xen/arch/x86/domain_page.c
+++ b/xen/arch/x86/domain_page.c
@@ -7,6 +7,7 @@
*/
#include <xen/domain_page.h>
+#include <xen/efi.h>
#include <xen/mm.h>
#include <xen/perfc.h>
#include <xen/pfn.h>
@@ -37,11 +38,14 @@ static inline struct vcpu *mapcache_current_vcpu(void)
*/
if ( unlikely(pagetable_is_null(v->arch.guest_table)) && is_pv_vcpu(v) )
{
+ unsigned long cr3;
+
/* If we really are idling, perform lazy context switch now. */
if ( (v = idle_vcpu[smp_processor_id()]) == current )
sync_local_execstate();
/* We must now be running on the idle page table. */
- ASSERT(read_cr3() == __pa(idle_pg_table));
+ ASSERT((cr3 = read_cr3()) == __pa(idle_pg_table) ||
+ (efi_enabled && cr3 == efi_rs_page_table()));
}
return v;
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index a967b65..82365a4 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -30,11 +30,12 @@
#include <xen/hypercall.h> /* for arch_do_domctl */
#include <xsm/xsm.h>
#include <xen/iommu.h>
-#include <asm/mem_event.h>
+#include <xen/mem_event.h>
#include <public/mem_event.h>
#include <asm/mem_sharing.h>
#include <asm/xstate.h>
#include <asm/debugger.h>
+#include <asm/psr.h>
static int gdbsx_guest_mem_io(
domid_t domid, struct xen_domctl_gdbsx_memio *iop)
@@ -46,21 +47,26 @@ static int gdbsx_guest_mem_io(
return (iop->remain ? -EFAULT : 0);
}
+#define MAX_IOPORTS 0x10000
+
long arch_do_domctl(
struct xen_domctl *domctl, struct domain *d,
XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
{
long ret = 0;
bool_t copyback = 0;
+ unsigned long i;
switch ( domctl->cmd )
{
case XEN_DOMCTL_shadow_op:
{
- ret = paging_domctl(d,
- &domctl->u.shadow_op,
- guest_handle_cast(u_domctl, void));
+ ret = paging_domctl(d, &domctl->u.shadow_op,
+ guest_handle_cast(u_domctl, void), 0);
+ if ( ret == -ERESTART )
+ return hypercall_create_continuation(__HYPERVISOR_arch_1,
+ "h", u_domctl);
copyback = 1;
}
break;
@@ -71,18 +77,18 @@ long arch_do_domctl(
unsigned int np = domctl->u.ioport_permission.nr_ports;
int allow = domctl->u.ioport_permission.allow_access;
- ret = -EINVAL;
- if ( (fp + np) > 65536 )
- break;
-
- if ( np == 0 )
- ret = 0;
- else if ( xsm_ioport_permission(XSM_HOOK, d, fp, fp + np - 1, allow) )
+ if ( (fp + np) <= fp || (fp + np) > MAX_IOPORTS )
+ ret = -EINVAL;
+ else if ( !ioports_access_permitted(current->domain,
+ fp, fp + np - 1) ||
+ xsm_ioport_permission(XSM_HOOK, d, fp, fp + np - 1, allow) )
ret = -EPERM;
else if ( allow )
ret = ioports_permit_access(d, fp, fp + np - 1);
else
ret = ioports_deny_access(d, fp, fp + np - 1);
+ if ( !ret )
+ memory_type_changed(d);
}
break;
@@ -319,7 +325,6 @@ long arch_do_domctl(
case XEN_DOMCTL_getmemlist:
{
- int i;
unsigned long max_pfns = domctl->u.getmemlist.max_pfns;
uint64_t mfn;
struct page_info *page;
@@ -639,79 +644,8 @@ long arch_do_domctl(
}
break;
- case XEN_DOMCTL_memory_mapping:
- {
- unsigned long gfn = domctl->u.memory_mapping.first_gfn;
- unsigned long mfn = domctl->u.memory_mapping.first_mfn;
- unsigned long nr_mfns = domctl->u.memory_mapping.nr_mfns;
- int add = domctl->u.memory_mapping.add_mapping;
- unsigned long i;
-
- ret = -EINVAL;
- if ( (mfn + nr_mfns - 1) < mfn || /* wrap? */
- ((mfn | (mfn + nr_mfns - 1)) >> (paddr_bits - PAGE_SHIFT)) ||
- (gfn + nr_mfns - 1) < gfn ) /* wrap? */
- break;
-
- ret = -EPERM;
- if ( !iomem_access_permitted(current->domain, mfn, mfn + nr_mfns - 1) )
- break;
-
- ret = xsm_iomem_mapping(XSM_HOOK, d, mfn, mfn + nr_mfns - 1, add);
- if ( ret )
- break;
-
- if ( add )
- {
- printk(XENLOG_G_INFO
- "memory_map:add: dom%d gfn=%lx mfn=%lx nr=%lx\n",
- d->domain_id, gfn, mfn, nr_mfns);
-
- ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
- if ( !ret && paging_mode_translate(d) )
- {
- for ( i = 0; !ret && i < nr_mfns; i++ )
- if ( !set_mmio_p2m_entry(d, gfn + i, _mfn(mfn + i)) )
- ret = -EIO;
- if ( ret )
- {
- printk(XENLOG_G_WARNING
- "memory_map:fail: dom%d gfn=%lx mfn=%lx\n",
- d->domain_id, gfn + i, mfn + i);
- while ( i-- )
- clear_mmio_p2m_entry(d, gfn + i);
- if ( iomem_deny_access(d, mfn, mfn + nr_mfns - 1) &&
- is_hardware_domain(current->domain) )
- printk(XENLOG_ERR
- "memory_map: failed to deny dom%d access to [%lx,%lx]\n",
- d->domain_id, mfn, mfn + nr_mfns - 1);
- }
- }
- }
- else
- {
- printk(XENLOG_G_INFO
- "memory_map:remove: dom%d gfn=%lx mfn=%lx nr=%lx\n",
- d->domain_id, gfn, mfn, nr_mfns);
-
- if ( paging_mode_translate(d) )
- for ( i = 0; i < nr_mfns; i++ )
- add |= !clear_mmio_p2m_entry(d, gfn + i);
- ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
- if ( !ret && add )
- ret = -EIO;
- if ( ret && is_hardware_domain(current->domain) )
- printk(XENLOG_ERR
- "memory_map: error %ld %s dom%d access to [%lx,%lx]\n",
- ret, add ? "removing" : "denying", d->domain_id,
- mfn, mfn + nr_mfns - 1);
- }
- }
- break;
-
case XEN_DOMCTL_ioport_mapping:
{
-#define MAX_IOPORTS 0x10000
struct hvm_iommu *hd;
unsigned int fgp = domctl->u.ioport_mapping.first_gport;
unsigned int fmp = domctl->u.ioport_mapping.first_mport;
@@ -745,7 +679,7 @@ long arch_do_domctl(
"ioport_map:add: dom%d gport=%x mport=%x nr=%x\n",
d->domain_id, fgp, fmp, np);
- list_for_each_entry(g2m_ioport, &hd->g2m_ioport_list, list)
+ list_for_each_entry(g2m_ioport, &hd->arch.g2m_ioport_list, list)
if (g2m_ioport->mport == fmp )
{
g2m_ioport->gport = fgp;
@@ -764,7 +698,7 @@ long arch_do_domctl(
g2m_ioport->gport = fgp;
g2m_ioport->mport = fmp;
g2m_ioport->np = np;
- list_add_tail(&g2m_ioport->list, &hd->g2m_ioport_list);
+ list_add_tail(&g2m_ioport->list, &hd->arch.g2m_ioport_list);
}
if ( !ret )
ret = ioports_permit_access(d, fmp, fmp + np - 1);
@@ -779,7 +713,7 @@ long arch_do_domctl(
printk(XENLOG_G_INFO
"ioport_map:remove: dom%d gport=%x mport=%x nr=%x\n",
d->domain_id, fgp, fmp, np);
- list_for_each_entry(g2m_ioport, &hd->g2m_ioport_list, list)
+ list_for_each_entry(g2m_ioport, &hd->arch.g2m_ioport_list, list)
if ( g2m_ioport->mport == fmp )
{
list_del(&g2m_ioport->list);
@@ -792,6 +726,8 @@ long arch_do_domctl(
"ioport_map: error %ld denying dom%d access to [%x,%x]\n",
ret, d->domain_id, fmp, fmp + np - 1);
}
+ if ( !ret )
+ memory_type_changed(d);
}
break;
@@ -921,7 +857,6 @@ long arch_do_domctl(
{
xen_domctl_cpuid_t *ctl = &domctl->u.cpuid;
cpuid_input_t *cpuid, *unused = NULL;
- int i;
for ( i = 0; i < MAX_CPUID_INPUT; i++ )
{
@@ -1022,11 +957,10 @@ long arch_do_domctl(
if ( !d->controller_pause_count )
break;
ret = -EINVAL;
- if ( domctl->u.gdbsx_pauseunp_vcpu.vcpu >= MAX_VIRT_CPUS ||
+ if ( domctl->u.gdbsx_pauseunp_vcpu.vcpu >= d->max_vcpus ||
(v = d->vcpu[domctl->u.gdbsx_pauseunp_vcpu.vcpu]) == NULL )
break;
- vcpu_pause(v);
- ret = 0;
+ ret = vcpu_pause_by_systemcontroller(v);
}
break;
@@ -1038,13 +972,14 @@ long arch_do_domctl(
if ( !d->controller_pause_count )
break;
ret = -EINVAL;
- if ( domctl->u.gdbsx_pauseunp_vcpu.vcpu >= MAX_VIRT_CPUS ||
+ if ( domctl->u.gdbsx_pauseunp_vcpu.vcpu >= d->max_vcpus ||
(v = d->vcpu[domctl->u.gdbsx_pauseunp_vcpu.vcpu]) == NULL )
break;
- if ( !atomic_read(&v->pause_count) )
- printk("WARN: Unpausing vcpu:%d which is not paused\n", v->vcpu_id);
- vcpu_unpause(v);
- ret = 0;
+ ret = vcpu_unpause_by_systemcontroller(v);
+ if ( ret == -EINVAL )
+ printk(XENLOG_G_WARNING
+ "WARN: d%d attempting to unpause %pv which is not paused\n",
+ current->domain->domain_id, v);
}
break;
@@ -1166,8 +1101,7 @@ long arch_do_domctl(
{
if ( evc->size >= 2 * sizeof(uint64_t) + XSTATE_AREA_MIN_SIZE )
ret = validate_xstate(_xcr0, _xcr0_accum,
- _xsave_area->xsave_hdr.xstate_bv,
- evc->xfeature_mask);
+ _xsave_area->xsave_hdr.xstate_bv);
}
else if ( !_xcr0 )
ret = 0;
@@ -1200,14 +1134,6 @@ long arch_do_domctl(
}
break;
- case XEN_DOMCTL_mem_event_op:
- {
- ret = mem_event_domctl(d, &domctl->u.mem_event_op,
- guest_handle_cast(u_domctl, void));
- copyback = 1;
- }
- break;
-
case XEN_DOMCTL_mem_sharing_op:
{
ret = mem_sharing_domctl(d, &domctl->u.mem_sharing_op);
@@ -1232,34 +1158,176 @@ long arch_do_domctl(
break;
#endif /* P2M_AUDIT */
- case XEN_DOMCTL_set_access_required:
- {
- struct p2m_domain* p2m;
-
- ret = -EPERM;
- if ( current->domain == d )
- break;
-
- ret = 0;
- p2m = p2m_get_hostp2m(d);
- p2m->access_required = domctl->u.access_required.access_required;
- }
- break;
-
case XEN_DOMCTL_set_broken_page_p2m:
{
p2m_type_t pt;
unsigned long pfn = domctl->u.set_broken_page_p2m.pfn;
mfn_t mfn = get_gfn_query(d, pfn, &pt);
- if ( unlikely(!mfn_valid(mfn_x(mfn)) || !p2m_is_ram(pt) ||
- (p2m_change_type(d, pfn, pt, p2m_ram_broken) != pt)) )
+ if ( unlikely(!mfn_valid(mfn_x(mfn))) || unlikely(!p2m_is_ram(pt)) )
ret = -EINVAL;
+ else
+ ret = p2m_change_type_one(d, pfn, pt, p2m_ram_broken);
put_gfn(d, pfn);
}
break;
+ case XEN_DOMCTL_get_vcpu_msrs:
+ case XEN_DOMCTL_set_vcpu_msrs:
+ {
+ struct xen_domctl_vcpu_msrs *vmsrs = &domctl->u.vcpu_msrs;
+ struct xen_domctl_vcpu_msr msr;
+ struct vcpu *v;
+ uint32_t nr_msrs = 0;
+
+ ret = -ESRCH;
+ if ( (vmsrs->vcpu >= d->max_vcpus) ||
+ ((v = d->vcpu[vmsrs->vcpu]) == NULL) )
+ break;
+
+ ret = -EINVAL;
+ if ( (v == current) || /* no vcpu_pause() */
+ !is_pv_domain(d) )
+ break;
+
+ /* Count maximum number of optional msrs. */
+ if ( boot_cpu_has(X86_FEATURE_DBEXT) )
+ nr_msrs += 4;
+
+ if ( domctl->cmd == XEN_DOMCTL_get_vcpu_msrs )
+ {
+ ret = 0; copyback = 1;
+
+ /* NULL guest handle is a request for max size. */
+ if ( guest_handle_is_null(vmsrs->msrs) )
+ vmsrs->msr_count = nr_msrs;
+ else
+ {
+ i = 0;
+
+ vcpu_pause(v);
+
+ if ( boot_cpu_has(X86_FEATURE_DBEXT) )
+ {
+ unsigned int j;
+
+ if ( v->arch.pv_vcpu.dr_mask[0] )
+ {
+ if ( i < vmsrs->msr_count && !ret )
+ {
+ msr.index = MSR_AMD64_DR0_ADDRESS_MASK;
+ msr.reserved = 0;
+ msr.value = v->arch.pv_vcpu.dr_mask[0];
+ if ( copy_to_guest_offset(vmsrs->msrs, i, &msr, 1) )
+ ret = -EFAULT;
+ }
+ ++i;
+ }
+
+ for ( j = 0; j < 3; ++j )
+ {
+ if ( !v->arch.pv_vcpu.dr_mask[1 + j] )
+ continue;
+ if ( i < vmsrs->msr_count && !ret )
+ {
+ msr.index = MSR_AMD64_DR1_ADDRESS_MASK + j;
+ msr.reserved = 0;
+ msr.value = v->arch.pv_vcpu.dr_mask[1 + j];
+ if ( copy_to_guest_offset(vmsrs->msrs, i, &msr, 1) )
+ ret = -EFAULT;
+ }
+ ++i;
+ }
+ }
+
+ vcpu_unpause(v);
+
+ if ( i > vmsrs->msr_count && !ret )
+ ret = -ENOBUFS;
+ vmsrs->msr_count = i;
+ }
+ }
+ else
+ {
+ ret = -EINVAL;
+ if ( vmsrs->msr_count > nr_msrs )
+ break;
+
+ vcpu_pause(v);
+
+ for ( i = 0; i < vmsrs->msr_count; ++i )
+ {
+ ret = -EFAULT;
+ if ( copy_from_guest_offset(&msr, vmsrs->msrs, i, 1) )
+ break;
+
+ ret = -EINVAL;
+ if ( msr.reserved )
+ break;
+
+ switch ( msr.index )
+ {
+ case MSR_AMD64_DR0_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) ||
+ (msr.value >> 32) )
+ break;
+ v->arch.pv_vcpu.dr_mask[0] = msr.value;
+ continue;
+
+ case MSR_AMD64_DR1_ADDRESS_MASK ...
+ MSR_AMD64_DR3_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) ||
+ (msr.value >> 32) )
+ break;
+ msr.index -= MSR_AMD64_DR1_ADDRESS_MASK - 1;
+ v->arch.pv_vcpu.dr_mask[msr.index] = msr.value;
+ continue;
+ }
+ break;
+ }
+
+ vcpu_unpause(v);
+
+ if ( i == vmsrs->msr_count )
+ ret = 0;
+ else
+ {
+ vmsrs->msr_count = i;
+ copyback = 1;
+ }
+ }
+ }
+ break;
+
+ case XEN_DOMCTL_psr_cmt_op:
+ if ( !psr_cmt_enabled() )
+ {
+ ret = -ENODEV;
+ break;
+ }
+
+ switch ( domctl->u.psr_cmt_op.cmd )
+ {
+ case XEN_DOMCTL_PSR_CMT_OP_ATTACH:
+ ret = psr_alloc_rmid(d);
+ break;
+ case XEN_DOMCTL_PSR_CMT_OP_DETACH:
+ if ( d->arch.psr_rmid > 0 )
+ psr_free_rmid(d);
+ else
+ ret = -ENOENT;
+ break;
+ case XEN_DOMCTL_PSR_CMT_OP_QUERY_RMID:
+ domctl->u.psr_cmt_op.data = d->arch.psr_rmid;
+ copyback = 1;
+ break;
+ default:
+ ret = -ENOSYS;
+ break;
+ }
+ break;
+
default:
ret = iommu_do_domctl(domctl, d, u_domctl);
break;
diff --git a/xen/arch/x86/e820.c b/xen/arch/x86/e820.c
index 55fe0d6..bf84bae 100644
--- a/xen/arch/x86/e820.c
+++ b/xen/arch/x86/e820.c
@@ -89,9 +89,9 @@ static void __init add_memory_region(unsigned long long start,
}
} /* add_memory_region */
-static void __init print_e820_memory_map(struct e820entry *map, int entries)
+static void __init print_e820_memory_map(struct e820entry *map, unsigned int entries)
{
- int i;
+ unsigned int i;
for (i = 0; i < entries; i++) {
printk(" %016Lx - %016Lx ",
@@ -512,7 +512,7 @@ static void __init reserve_dmi_region(void)
}
static void __init machine_specific_memory_setup(
- struct e820entry *raw, int *raw_nr)
+ struct e820entry *raw, unsigned int *raw_nr)
{
unsigned long mpt_limit, ro_mpt_limit;
uint64_t top_of_ram, size;
@@ -695,7 +695,7 @@ int __init reserve_e820_ram(struct e820map *e820, uint64_t s, uint64_t e)
}
unsigned long __init init_e820(
- const char *str, struct e820entry *raw, int *raw_nr)
+ const char *str, struct e820entry *raw, unsigned int *raw_nr)
{
if ( e820_verbose )
{
diff --git a/xen/arch/x86/efi/boot.c b/xen/arch/x86/efi/boot.c
deleted file mode 100644
index 0dd935c..0000000
--- a/xen/arch/x86/efi/boot.c
+++ /dev/null
@@ -1,1723 +0,0 @@
-#include "efi.h"
-#include <efi/efiprot.h>
-#include <efi/efipciio.h>
-#include <public/xen.h>
-#include <xen/compile.h>
-#include <xen/ctype.h>
-#include <xen/dmi.h>
-#include <xen/init.h>
-#include <xen/keyhandler.h>
-#include <xen/lib.h>
-#include <xen/mm.h>
-#include <xen/multiboot.h>
-#include <xen/pci_regs.h>
-#include <xen/pfn.h>
-#if EFI_PAGE_SIZE != PAGE_SIZE
-# error Cannot use xen/pfn.h here!
-#endif
-#include <xen/string.h>
-#include <xen/stringify.h>
-#include <xen/vga.h>
-#include <asm/e820.h>
-#include <asm/edd.h>
-#define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */
-#include <asm/fixmap.h>
-#undef __ASSEMBLY__
-#include <asm/msr.h>
-#include <asm/processor.h>
-
-/* Using SetVirtualAddressMap() is incompatible with kexec: */
-#undef USE_SET_VIRTUAL_ADDRESS_MAP
-
-#define SHIM_LOCK_PROTOCOL_GUID \
- { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
-
-typedef EFI_STATUS
-(/* _not_ EFIAPI */ *EFI_SHIM_LOCK_VERIFY) (
- IN VOID *Buffer,
- IN UINT32 Size);
-
-typedef struct {
- EFI_SHIM_LOCK_VERIFY Verify;
-} EFI_SHIM_LOCK_PROTOCOL;
-
-extern char start[];
-extern u32 cpuid_ext_features;
-
-union string {
- CHAR16 *w;
- char *s;
- const char *cs;
-};
-
-struct file {
- UINTN size;
- union {
- EFI_PHYSICAL_ADDRESS addr;
- void *ptr;
- };
-};
-
-static EFI_BOOT_SERVICES *__initdata efi_bs;
-static EFI_HANDLE __initdata efi_ih;
-
-static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdOut;
-static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdErr;
-
-static UINT32 __initdata mdesc_ver;
-
-static struct file __initdata cfg;
-static struct file __initdata kernel;
-static struct file __initdata ramdisk;
-static struct file __initdata ucode;
-static struct file __initdata xsm;
-
-static multiboot_info_t __initdata mbi = {
- .flags = MBI_MODULES | MBI_LOADERNAME
-};
-static module_t __initdata mb_modules[3];
-
-static CHAR16 __initdata newline[] = L"\r\n";
-
-#define PrintStr(s) StdOut->OutputString(StdOut, s)
-#define PrintErr(s) StdErr->OutputString(StdErr, s)
-
-static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer)
-{
- if ( Val >= 10 )
- Buffer = FormatDec(Val / 10, Buffer);
- *Buffer = (CHAR16)(L'0' + Val % 10);
- return Buffer + 1;
-}
-
-static CHAR16 *__init FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer)
-{
- if ( Width > 1 || Val >= 0x10 )
- Buffer = FormatHex(Val >> 4, Width ? Width - 1 : 0, Buffer);
- *Buffer = (CHAR16)((Val &= 0xf) < 10 ? L'0' + Val : L'a' + Val - 10);
- return Buffer + 1;
-}
-
-static void __init DisplayUint(UINT64 Val, INTN Width)
-{
- CHAR16 PrintString[32], *end;
-
- if (Width < 0)
- end = FormatDec(Val, PrintString);
- else
- {
- PrintStr(L"0x");
- end = FormatHex(Val, Width, PrintString);
- }
- *end = 0;
- PrintStr(PrintString);
-}
-
-static CHAR16 *__init wstrcpy(CHAR16 *d, const CHAR16 *s)
-{
- CHAR16 *r = d;
-
- while ( (*d++ = *s++) != 0 )
- ;
- return r;
-}
-
-static int __init wstrcmp(const CHAR16 *s1, const CHAR16 *s2)
-{
- while ( *s1 && *s1 == *s2 )
- {
- ++s1;
- ++s2;
- }
- return *s1 - *s2;
-}
-
-static int __init wstrncmp(const CHAR16 *s1, const CHAR16 *s2, UINTN n)
-{
- while ( n && *s1 && *s1 == *s2 )
- {
- --n;
- ++s1;
- ++s2;
- }
- return n ? *s1 - *s2 : 0;
-}
-
-static CHAR16 *__init s2w(union string *str)
-{
- const char *s = str->s;
- CHAR16 *w;
- void *ptr;
-
- if ( efi_bs->AllocatePool(EfiLoaderData, (strlen(s) + 1) * sizeof(*w),
- &ptr) != EFI_SUCCESS )
- return NULL;
-
- w = str->w = ptr;
- do {
- *w = *s++;
- } while ( *w++ );
-
- return str->w;
-}
-
-static char *__init w2s(const union string *str)
-{
- const CHAR16 *w = str->w;
- char *s = str->s;
-
- do {
- if ( *w > 0x007f )
- return NULL;
- *s = *w++;
- } while ( *s++ );
-
- return str->s;
-}
-
-static bool_t __init match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2)
-{
- return guid1->Data1 == guid2->Data1 &&
- guid1->Data2 == guid2->Data2 &&
- guid1->Data3 == guid2->Data3 &&
- !memcmp(guid1->Data4, guid2->Data4, sizeof(guid1->Data4));
-}
-
-static void __init __attribute__((__noreturn__)) blexit(const CHAR16 *str)
-{
- if ( str )
- PrintStr((CHAR16 *)str);
- PrintStr(newline);
-
- if ( cfg.addr )
- efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
- if ( kernel.addr )
- efi_bs->FreePages(kernel.addr, PFN_UP(kernel.size));
- if ( ramdisk.addr )
- efi_bs->FreePages(ramdisk.addr, PFN_UP(ramdisk.size));
- if ( ucode.addr )
- efi_bs->FreePages(ucode.addr, PFN_UP(ucode.size));
- if ( xsm.addr )
- efi_bs->FreePages(xsm.addr, PFN_UP(xsm.size));
-
- efi_bs->Exit(efi_ih, EFI_SUCCESS, 0, NULL);
- for( ; ; ); /* not reached */
-}
-
-/* generic routine for printing error messages */
-static void __init PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode)
-{
- StdOut = StdErr;
- PrintErr((CHAR16 *)mesg);
- PrintErr(L": ");
-
- switch (ErrCode)
- {
- case EFI_NOT_FOUND:
- mesg = L"Not found";
- break;
- case EFI_NO_MEDIA:
- mesg = L"The device has no media";
- break;
- case EFI_MEDIA_CHANGED:
- mesg = L"Media changed";
- break;
- case EFI_DEVICE_ERROR:
- mesg = L"Device error";
- break;
- case EFI_VOLUME_CORRUPTED:
- mesg = L"Volume corrupted";
- break;
- case EFI_ACCESS_DENIED:
- mesg = L"Access denied";
- break;
- case EFI_OUT_OF_RESOURCES:
- mesg = L"Out of resources";
- break;
- case EFI_VOLUME_FULL:
- mesg = L"Volume is full";
- break;
- case EFI_SECURITY_VIOLATION:
- mesg = L"Security violation";
- break;
- case EFI_CRC_ERROR:
- mesg = L"CRC error";
- break;
- case EFI_COMPROMISED_DATA:
- mesg = L"Compromised data";
- break;
- default:
- PrintErr(L"ErrCode: ");
- DisplayUint(ErrCode, 0);
- mesg = NULL;
- break;
- }
- blexit(mesg);
-}
-
-static void __init place_string(u32 *addr, const char *s)
-{
- static char *__initdata alloc = start;
-
- if ( s && *s )
- {
- size_t len1 = strlen(s) + 1;
- const char *old = (char *)(long)*addr;
- size_t len2 = *addr ? strlen(old) + 1 : 0;
-
- alloc -= len1 + len2;
- /*
- * Insert new string before already existing one. This is needed
- * for options passed on the command line to override options from
- * the configuration file.
- */
- memcpy(alloc, s, len1);
- if ( *addr )
- {
- alloc[len1 - 1] = ' ';
- memcpy(alloc + len1, old, len2);
- }
- }
- *addr = (long)alloc;
-}
-
-static unsigned int __init get_argv(unsigned int argc, CHAR16 **argv,
- CHAR16 *cmdline, UINTN cmdsize)
-{
- CHAR16 *ptr = (CHAR16 *)(argv + argc + 1), *prev = NULL;
- bool_t prev_sep = TRUE;
-
- for ( ; cmdsize > sizeof(*cmdline) && *cmdline;
- cmdsize -= sizeof(*cmdline), ++cmdline )
- {
- bool_t cur_sep = *cmdline == L' ' || *cmdline == L'\t';
-
- if ( !prev_sep )
- {
- if ( cur_sep )
- ++ptr;
- else if ( argv )
- {
- *ptr = *cmdline;
- *++ptr = 0;
- }
- }
- else if ( !cur_sep )
- {
- if ( !argv )
- ++argc;
- else if ( prev && wstrcmp(prev, L"--") == 0 )
- {
- union string rest = { .w = cmdline };
-
- --argv;
- place_string(&mbi.cmdline, w2s(&rest));
- break;
- }
- else
- {
- *argv++ = prev = ptr;
- *ptr = *cmdline;
- *++ptr = 0;
- }
- }
- prev_sep = cur_sep;
- }
- if ( argv )
- *argv = NULL;
- return argc;
-}
-
-static EFI_FILE_HANDLE __init get_parent_handle(EFI_LOADED_IMAGE *loaded_image,
- CHAR16 **leaf)
-{
- static EFI_GUID __initdata fs_protocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
- EFI_FILE_HANDLE dir_handle;
- EFI_DEVICE_PATH *dp;
- CHAR16 *pathend, *ptr;
- EFI_STATUS ret;
-
- do {
- EFI_FILE_IO_INTERFACE *fio;
-
- /* Get the file system interface. */
- ret = efi_bs->HandleProtocol(loaded_image->DeviceHandle,
- &fs_protocol, (void **)&fio);
- if ( EFI_ERROR(ret) )
- blexit(L"Couldn't obtain the File System Protocol Interface");
- ret = fio->OpenVolume(fio, &dir_handle);
- } while ( ret == EFI_MEDIA_CHANGED );
- if ( ret != EFI_SUCCESS )
- blexit(L"OpenVolume failure");
-
-#define buffer ((CHAR16 *)keyhandler_scratch)
-#define BUFFERSIZE sizeof(keyhandler_scratch)
- for ( dp = loaded_image->FilePath, *buffer = 0;
- DevicePathType(dp) != END_DEVICE_PATH_TYPE;
- dp = (void *)dp + DevicePathNodeLength(dp) )
- {
- FILEPATH_DEVICE_PATH *fp;
-
- if ( DevicePathType(dp) != MEDIA_DEVICE_PATH ||
- DevicePathSubType(dp) != MEDIA_FILEPATH_DP )
- blexit(L"Unsupported device path component");
-
- if ( *buffer )
- {
- EFI_FILE_HANDLE new_handle;
-
- ret = dir_handle->Open(dir_handle, &new_handle, buffer,
- EFI_FILE_MODE_READ, 0);
- if ( ret != EFI_SUCCESS )
- {
- PrintErr(L"Open failed for ");
- PrintErrMesg(buffer, ret);
- }
- dir_handle->Close(dir_handle);
- dir_handle = new_handle;
- }
- fp = (void *)dp;
- if ( BUFFERSIZE < DevicePathNodeLength(dp) -
- sizeof(*dp) + sizeof(*buffer) )
- blexit(L"Increase BUFFERSIZE");
- memcpy(buffer, fp->PathName, DevicePathNodeLength(dp) - sizeof(*dp));
- buffer[(DevicePathNodeLength(dp) - sizeof(*dp)) / sizeof(*buffer)] = 0;
- }
- for ( ptr = buffer, pathend = NULL; *ptr; ++ptr )
- if ( *ptr == L'\\' )
- pathend = ptr;
- if ( pathend )
- {
- *pathend = 0;
- *leaf = pathend + 1;
- if ( *buffer )
- {
- EFI_FILE_HANDLE new_handle;
-
- ret = dir_handle->Open(dir_handle, &new_handle, buffer,
- EFI_FILE_MODE_READ, 0);
- if ( ret != EFI_SUCCESS ) {
- PrintErr(L"Open failed for ");
- PrintErrMesg(buffer, ret);
- }
- dir_handle->Close(dir_handle);
- dir_handle = new_handle;
- }
- }
- else
- *leaf = buffer;
-#undef BUFFERSIZE
-#undef buffer
-
- return dir_handle;
-}
-
-static CHAR16 *__init point_tail(CHAR16 *fn)
-{
- CHAR16 *tail = NULL;
-
- for ( ; ; ++fn )
- switch ( *fn )
- {
- case 0:
- return tail;
- case L'.':
- case L'-':
- case L'_':
- tail = fn;
- break;
- }
-}
-
-static bool_t __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
- struct file *file)
-{
- EFI_FILE_HANDLE FileHandle = NULL;
- UINT64 size;
- EFI_STATUS ret;
- CHAR16 *what = NULL;
-
- if ( !name )
- PrintErrMesg(L"No filename", EFI_OUT_OF_RESOURCES);
- ret = dir_handle->Open(dir_handle, &FileHandle, name,
- EFI_FILE_MODE_READ, 0);
- if ( file == &cfg && ret == EFI_NOT_FOUND )
- return 0;
- if ( EFI_ERROR(ret) )
- what = L"Open";
- else
- ret = FileHandle->SetPosition(FileHandle, -1);
- if ( EFI_ERROR(ret) )
- what = what ?: L"Seek";
- else
- ret = FileHandle->GetPosition(FileHandle, &size);
- if ( EFI_ERROR(ret) )
- what = what ?: L"Get size";
- else
- ret = FileHandle->SetPosition(FileHandle, 0);
- if ( EFI_ERROR(ret) )
- what = what ?: L"Seek";
- else
- {
- file->addr = min(1UL << (32 + PAGE_SHIFT),
- HYPERVISOR_VIRT_END - DIRECTMAP_VIRT_START);
- ret = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
- PFN_UP(size), &file->addr);
- }
- if ( EFI_ERROR(ret) )
- {
- file->addr = 0;
- what = what ?: L"Allocation";
- }
- else
- {
- if ( file != &cfg )
- {
- PrintStr(name);
- PrintStr(L": ");
- DisplayUint(file->addr, 2 * sizeof(file->addr));
- PrintStr(L"-");
- DisplayUint(file->addr + size, 2 * sizeof(file->addr));
- PrintStr(newline);
- mb_modules[mbi.mods_count].mod_start = file->addr >> PAGE_SHIFT;
- mb_modules[mbi.mods_count].mod_end = size;
- ++mbi.mods_count;
- }
-
- file->size = size;
- ret = FileHandle->Read(FileHandle, &file->size, file->ptr);
- if ( !EFI_ERROR(ret) && file->size != size )
- ret = EFI_ABORTED;
- if ( EFI_ERROR(ret) )
- what = L"Read";
- }
-
- if ( FileHandle )
- FileHandle->Close(FileHandle);
-
- if ( what )
- {
- PrintErr(what);
- PrintErr(L" failed for ");
- PrintErrMesg(name, ret);
- }
-
- return 1;
-}
-
-static void __init pre_parse(const struct file *cfg)
-{
- char *ptr = cfg->ptr, *end = ptr + cfg->size;
- bool_t start = 1, comment = 0;
-
- for ( ; ptr < end; ++ptr )
- {
- if ( iscntrl(*ptr) )
- {
- comment = 0;
- start = 1;
- *ptr = 0;
- }
- else if ( comment || (start && isspace(*ptr)) )
- *ptr = 0;
- else if ( *ptr == '#' || (start && *ptr == ';') )
- {
- comment = 1;
- *ptr = 0;
- }
- else
- start = 0;
- }
- if ( cfg->size && end[-1] )
- PrintStr(L"No newline at end of config file,"
- " last line will be ignored.\r\n");
-}
-
-static char *__init get_value(const struct file *cfg, const char *section,
- const char *item)
-{
- char *ptr = cfg->ptr, *end = ptr + cfg->size;
- size_t slen = section ? strlen(section) : 0, ilen = strlen(item);
- bool_t match = !slen;
-
- for ( ; ptr < end; ++ptr )
- {
- switch ( *ptr )
- {
- case 0:
- continue;
- case '[':
- if ( !slen )
- break;
- if ( match )
- return NULL;
- match = strncmp(++ptr, section, slen) == 0 && ptr[slen] == ']';
- break;
- default:
- if ( match && strncmp(ptr, item, ilen) == 0 && ptr[ilen] == '=' )
- return ptr + ilen + 1;
- break;
- }
- ptr += strlen(ptr);
- }
- return NULL;
-}
-
-static void __init split_value(char *s)
-{
- while ( *s && isspace(*s) )
- ++s;
- place_string(&mb_modules[mbi.mods_count].string, s);
- while ( *s && !isspace(*s) )
- ++s;
- *s = 0;
-}
-
-static void __init edd_put_string(u8 *dst, size_t n, const char *src)
-{
- while ( n-- && *src )
- *dst++ = *src++;
- if ( *src )
- PrintErrMesg(L"Internal error populating EDD info",
- EFI_BUFFER_TOO_SMALL);
- while ( n-- )
- *dst++ = ' ';
-}
-#define edd_put_string(d, s) edd_put_string(d, ARRAY_SIZE(d), s)
-
-static void __init setup_efi_pci(void)
-{
- EFI_STATUS status;
- EFI_HANDLE *handles;
- static EFI_GUID __initdata pci_guid = EFI_PCI_IO_PROTOCOL;
- UINTN i, nr_pci, size = 0;
- struct efi_pci_rom *last = NULL;
-
- status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size, NULL);
- if ( status == EFI_BUFFER_TOO_SMALL )
- status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
- if ( !EFI_ERROR(status) )
- status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size,
- handles);
- if ( EFI_ERROR(status) )
- size = 0;
-
- nr_pci = size / sizeof(*handles);
- for ( i = 0; i < nr_pci; ++i )
- {
- EFI_PCI_IO *pci = NULL;
- u64 attributes;
- struct efi_pci_rom *rom, *va;
- UINTN segment, bus, device, function;
-
- status = efi_bs->HandleProtocol(handles[i], &pci_guid, (void **)&pci);
- if ( EFI_ERROR(status) || !pci || !pci->RomImage || !pci->RomSize )
- continue;
-
- status = pci->Attributes(pci, EfiPciIoAttributeOperationGet, 0,
- &attributes);
- if ( EFI_ERROR(status) ||
- !(attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) ||
- EFI_ERROR(pci->GetLocation(pci, &segment, &bus, &device,
- &function)) )
- continue;
-
- DisplayUint(segment, 4);
- PrintStr(L":");
- DisplayUint(bus, 2);
- PrintStr(L":");
- DisplayUint(device, 2);
- PrintStr(L".");
- DisplayUint(function, 1);
- PrintStr(L": ROM: ");
- DisplayUint(pci->RomSize, 0);
- PrintStr(L" bytes at ");
- DisplayUint((UINTN)pci->RomImage, 0);
- PrintStr(newline);
-
- size = pci->RomSize + sizeof(*rom);
- status = efi_bs->AllocatePool(EfiRuntimeServicesData, size,
- (void **)&rom);
- if ( EFI_ERROR(status) )
- continue;
-
- rom->next = NULL;
- rom->size = pci->RomSize;
-
- status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_VENDOR_ID, 1,
- &rom->vendor);
- if ( !EFI_ERROR(status) )
- status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_DEVICE_ID, 1,
- &rom->devid);
- if ( EFI_ERROR(status) )
- {
- efi_bs->FreePool(rom);
- continue;
- }
-
- rom->segment = segment;
- rom->bus = bus;
- rom->devfn = (device << 3) | function;
- memcpy(rom->data, pci->RomImage, pci->RomSize);
-
- va = (void *)rom + DIRECTMAP_VIRT_START;
- if ( last )
- last->next = va;
- else
- efi_pci_roms = va;
- last = rom;
- }
-
- efi_bs->FreePool(handles);
-}
-
-static int __init set_color(u32 mask, int bpp, u8 *pos, u8 *sz)
-{
- if ( bpp < 0 )
- return bpp;
- if ( !mask )
- return -EINVAL;
- for ( *pos = 0; !(mask & 1); ++*pos )
- mask >>= 1;
- for ( *sz = 0; mask & 1; ++sz)
- mask >>= 1;
- if ( mask )
- return -EINVAL;
- return max(*pos + *sz, bpp);
-}
-
-extern const intpte_t __page_tables_start[], __page_tables_end[];
-#define in_page_tables(v) ((intpte_t *)(v) >= __page_tables_start && \
- (intpte_t *)(v) < __page_tables_end)
-
-#define PE_BASE_RELOC_ABS 0
-#define PE_BASE_RELOC_HIGHLOW 3
-#define PE_BASE_RELOC_DIR64 10
-
-extern const struct pe_base_relocs {
- u32 rva;
- u32 size;
- u16 entries[];
-} __base_relocs_start[], __base_relocs_end[];
-
-static void __init relocate_image(unsigned long delta)
-{
- const struct pe_base_relocs *base_relocs;
-
- for ( base_relocs = __base_relocs_start; base_relocs < __base_relocs_end; )
- {
- unsigned int i, n;
-
- n = (base_relocs->size - sizeof(*base_relocs)) /
- sizeof(*base_relocs->entries);
- for ( i = 0; i < n; ++i )
- {
- unsigned long addr = xen_phys_start + base_relocs->rva +
- (base_relocs->entries[i] & 0xfff);
-
- switch ( base_relocs->entries[i] >> 12 )
- {
- case PE_BASE_RELOC_ABS:
- break;
- case PE_BASE_RELOC_HIGHLOW:
- if ( delta )
- {
- *(u32 *)addr += delta;
- if ( in_page_tables(addr) )
- *(u32 *)addr += xen_phys_start;
- }
- break;
- case PE_BASE_RELOC_DIR64:
- if ( delta )
- {
- *(u64 *)addr += delta;
- if ( in_page_tables(addr) )
- *(intpte_t *)addr += xen_phys_start;
- }
- break;
- default:
- blexit(L"Unsupported relocation type");
- }
- }
- base_relocs = (const void *)(base_relocs->entries + i + (i & 1));
- }
-}
-
-extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[];
-extern const s32 __trampoline_seg_start[], __trampoline_seg_stop[];
-
-static void __init relocate_trampoline(unsigned long phys)
-{
- const s32 *trampoline_ptr;
-
- trampoline_phys = phys;
- /* Apply relocations to trampoline. */
- for ( trampoline_ptr = __trampoline_rel_start;
- trampoline_ptr < __trampoline_rel_stop;
- ++trampoline_ptr )
- *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += phys;
- for ( trampoline_ptr = __trampoline_seg_start;
- trampoline_ptr < __trampoline_seg_stop;
- ++trampoline_ptr )
- *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4;
-}
-
-void EFIAPI __init __attribute__((__noreturn__))
-efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
-{
- static EFI_GUID __initdata loaded_image_guid = LOADED_IMAGE_PROTOCOL;
- static EFI_GUID __initdata gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
- static EFI_GUID __initdata bio_guid = BLOCK_IO_PROTOCOL;
- static EFI_GUID __initdata devp_guid = DEVICE_PATH_PROTOCOL;
- static EFI_GUID __initdata shim_lock_guid = SHIM_LOCK_PROTOCOL_GUID;
- EFI_LOADED_IMAGE *loaded_image;
- EFI_STATUS status;
- unsigned int i, argc;
- CHAR16 **argv, *file_name, *cfg_file_name = NULL;
- UINTN cols, rows, depth, size, map_key, info_size, gop_mode = ~0;
- EFI_HANDLE *handles = NULL;
- EFI_SHIM_LOCK_PROTOCOL *shim_lock;
- EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
- EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
- EFI_FILE_HANDLE dir_handle;
- union string section = { NULL }, name;
- struct e820entry *e;
- u64 efer;
- bool_t base_video = 0;
-
- efi_ih = ImageHandle;
- efi_bs = SystemTable->BootServices;
- efi_rs = SystemTable->RuntimeServices;
- efi_ct = SystemTable->ConfigurationTable;
- efi_num_ct = SystemTable->NumberOfTableEntries;
- efi_version = SystemTable->Hdr.Revision;
- efi_fw_vendor = SystemTable->FirmwareVendor;
- efi_fw_revision = SystemTable->FirmwareRevision;
-
- StdOut = SystemTable->ConOut;
- StdErr = SystemTable->StdErr ?: StdOut;
-
- status = efi_bs->HandleProtocol(ImageHandle, &loaded_image_guid,
- (void **)&loaded_image);
- if ( status != EFI_SUCCESS )
- PrintErrMesg(L"No Loaded Image Protocol", status);
-
- xen_phys_start = (UINTN)loaded_image->ImageBase;
- if ( (xen_phys_start + loaded_image->ImageSize - 1) >> 32 )
- blexit(L"Xen must be loaded below 4Gb.");
- if ( xen_phys_start & ((1 << L2_PAGETABLE_SHIFT) - 1) )
- blexit(L"Xen must be loaded at a 2Mb boundary.");
- trampoline_xen_phys_start = xen_phys_start;
-
- /* Get the file system interface. */
- dir_handle = get_parent_handle(loaded_image, &file_name);
-
- argc = get_argv(0, NULL, loaded_image->LoadOptions,
- loaded_image->LoadOptionsSize);
- if ( argc > 0 &&
- efi_bs->AllocatePool(EfiLoaderData,
- (argc + 1) * sizeof(*argv) +
- loaded_image->LoadOptionsSize,
- (void **)&argv) == EFI_SUCCESS )
- get_argv(argc, argv, loaded_image->LoadOptions,
- loaded_image->LoadOptionsSize);
- else
- argc = 0;
- for ( i = 1; i < argc; ++i )
- {
- CHAR16 *ptr = argv[i];
-
- if ( !ptr )
- break;
- if ( *ptr == L'/' || *ptr == L'-' )
- {
- if ( wstrcmp(ptr + 1, L"basevideo") == 0 )
- base_video = 1;
- else if ( wstrncmp(ptr + 1, L"cfg=", 4) == 0 )
- cfg_file_name = ptr + 5;
- else if ( i + 1 < argc && wstrcmp(ptr + 1, L"cfg") == 0 )
- cfg_file_name = argv[++i];
- else if ( wstrcmp(ptr + 1, L"help") == 0 ||
- (ptr[1] == L'?' && !ptr[2]) )
- {
- PrintStr(L"Xen EFI Loader options:\r\n");
- PrintStr(L"-basevideo retain current video mode\r\n");
- PrintStr(L"-cfg=<file> specify configuration file\r\n");
- PrintStr(L"-help, -? display this help\r\n");
- blexit(NULL);
- }
- else
- {
- PrintStr(L"WARNING: Unknown command line option '");
- PrintStr(ptr);
- PrintStr(L"' ignored\r\n");
- }
- }
- else
- section.w = ptr;
- }
-
- if ( !base_video )
- {
- unsigned int best;
-
- for ( i = 0, size = 0, best = StdOut->Mode->Mode;
- i < StdOut->Mode->MaxMode; ++i )
- {
- if ( StdOut->QueryMode(StdOut, i, &cols, &rows) == EFI_SUCCESS &&
- cols * rows > size )
- {
- size = cols * rows;
- best = i;
- }
- }
- if ( best != StdOut->Mode->Mode )
- StdOut->SetMode(StdOut, best);
- }
-
- PrintStr(L"Xen " __stringify(XEN_VERSION) "." __stringify(XEN_SUBVERSION)
- XEN_EXTRAVERSION " (c/s " XEN_CHANGESET ") EFI loader\r\n");
-
- relocate_image(0);
-
- if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
- &cols, &rows) == EFI_SUCCESS )
- {
- vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3;
- vga_console_info.u.text_mode_3.columns = cols;
- vga_console_info.u.text_mode_3.rows = rows;
- vga_console_info.u.text_mode_3.font_height = 16;
- }
-
- size = 0;
- status = efi_bs->LocateHandle(ByProtocol, &gop_guid, NULL, &size, NULL);
- if ( status == EFI_BUFFER_TOO_SMALL )
- status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
- if ( !EFI_ERROR(status) )
- status = efi_bs->LocateHandle(ByProtocol, &gop_guid, NULL, &size,
- handles);
- if ( EFI_ERROR(status) )
- size = 0;
- for ( i = 0; i < size / sizeof(*handles); ++i )
- {
- status = efi_bs->HandleProtocol(handles[i], &gop_guid, (void **)&gop);
- if ( EFI_ERROR(status) )
- continue;
- status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info);
- if ( !EFI_ERROR(status) )
- break;
- }
- if ( handles )
- efi_bs->FreePool(handles);
- if ( EFI_ERROR(status) )
- gop = NULL;
-
- /* Read and parse the config file. */
- if ( !cfg_file_name )
- {
- CHAR16 *tail;
-
- while ( (tail = point_tail(file_name)) != NULL )
- {
- wstrcpy(tail, L".cfg");
- if ( read_file(dir_handle, file_name, &cfg) )
- break;
- *tail = 0;
- }
- if ( !tail )
- blexit(L"No configuration file found.");
- PrintStr(L"Using configuration file '");
- PrintStr(file_name);
- PrintStr(L"'\r\n");
- }
- else if ( !read_file(dir_handle, cfg_file_name, &cfg) )
- blexit(L"Configuration file not found.");
- pre_parse(&cfg);
-
- if ( section.w )
- w2s(§ion);
- else
- section.s = get_value(&cfg, "global", "default");
-
- for ( ; ; )
- {
- name.s = get_value(&cfg, section.s, "kernel");
- if ( name.s )
- break;
- name.s = get_value(&cfg, "global", "chain");
- if ( !name.s )
- break;
- efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
- cfg.addr = 0;
- if ( !read_file(dir_handle, s2w(&name), &cfg) )
- {
- PrintStr(L"Chained configuration file '");
- PrintStr(name.w);
- efi_bs->FreePool(name.w);
- blexit(L"'not found.");
- }
- pre_parse(&cfg);
- efi_bs->FreePool(name.w);
- }
- if ( !name.s )
- blexit(L"No Dom0 kernel image specified.");
- split_value(name.s);
- read_file(dir_handle, s2w(&name), &kernel);
- efi_bs->FreePool(name.w);
-
- if ( !EFI_ERROR(efi_bs->LocateProtocol(&shim_lock_guid, NULL,
- (void **)&shim_lock)) &&
- shim_lock->Verify(kernel.ptr, kernel.size) != EFI_SUCCESS )
- blexit(L"Dom0 kernel image could not be verified.");
-
- name.s = get_value(&cfg, section.s, "ramdisk");
- if ( name.s )
- {
- split_value(name.s);
- read_file(dir_handle, s2w(&name), &ramdisk);
- efi_bs->FreePool(name.w);
- }
-
- name.s = get_value(&cfg, section.s, "ucode");
- if ( !name.s )
- name.s = get_value(&cfg, "global", "ucode");
- if ( name.s )
- {
- microcode_set_module(mbi.mods_count);
- split_value(name.s);
- read_file(dir_handle, s2w(&name), &ucode);
- efi_bs->FreePool(name.w);
- }
-
- name.s = get_value(&cfg, section.s, "xsm");
- if ( name.s )
- {
- split_value(name.s);
- read_file(dir_handle, s2w(&name), &xsm);
- efi_bs->FreePool(name.w);
- }
-
- name.s = get_value(&cfg, section.s, "options");
- if ( name.s )
- place_string(&mbi.cmdline, name.s);
- /* Insert image name last, as it gets prefixed to the other options. */
- if ( argc )
- {
- name.w = *argv;
- w2s(&name);
- }
- else
- name.s = "xen";
- place_string(&mbi.cmdline, name.s);
-
- cols = rows = depth = 0;
- if ( !base_video )
- {
- name.cs = get_value(&cfg, section.s, "video");
- if ( !name.cs )
- name.cs = get_value(&cfg, "global", "video");
- if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
- {
- cols = simple_strtoul(name.cs + 4, &name.cs, 10);
- if ( *name.cs == 'x' )
- rows = simple_strtoul(name.cs + 1, &name.cs, 10);
- if ( *name.cs == 'x' )
- depth = simple_strtoul(name.cs + 1, &name.cs, 10);
- if ( *name.cs )
- cols = rows = depth = 0;
- }
- }
-
- efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
- cfg.addr = 0;
-
- dir_handle->Close(dir_handle);
-
- if ( gop && !base_video )
- {
- for ( i = size = 0; i < gop->Mode->MaxMode; ++i )
- {
- unsigned int bpp = 0;
-
- status = gop->QueryMode(gop, i, &info_size, &mode_info);
- if ( EFI_ERROR(status) )
- continue;
- switch ( mode_info->PixelFormat )
- {
- case PixelBitMask:
- bpp = hweight32(mode_info->PixelInformation.RedMask |
- mode_info->PixelInformation.GreenMask |
- mode_info->PixelInformation.BlueMask);
- break;
- case PixelRedGreenBlueReserved8BitPerColor:
- case PixelBlueGreenRedReserved8BitPerColor:
- bpp = 24;
- break;
- default:
- continue;
- }
- if ( cols == mode_info->HorizontalResolution &&
- rows == mode_info->VerticalResolution &&
- (!depth || bpp == depth) )
- {
- gop_mode = i;
- break;
- }
- if ( !cols && !rows &&
- mode_info->HorizontalResolution *
- mode_info->VerticalResolution > size )
- {
- size = mode_info->HorizontalResolution *
- mode_info->VerticalResolution;
- gop_mode = i;
- }
- }
- }
-
- if ( mbi.cmdline )
- mbi.flags |= MBI_CMDLINE;
- /*
- * These must not be initialized statically, since the value must
- * not get relocated when processing base relocations below.
- */
- mbi.boot_loader_name = (long)"EFI";
- mbi.mods_addr = (long)mb_modules;
-
- place_string(&mbi.mem_upper, NULL);
-
- /* Collect EDD info. */
- BUILD_BUG_ON(offsetof(struct edd_info, edd_device_params) != EDDEXTSIZE);
- BUILD_BUG_ON(sizeof(struct edd_device_params) != EDDPARMSIZE);
- size = 0;
- status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size, NULL);
- if ( status == EFI_BUFFER_TOO_SMALL )
- status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
- if ( !EFI_ERROR(status) )
- status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size,
- handles);
- if ( EFI_ERROR(status) )
- size = 0;
- for ( i = 0; i < size / sizeof(*handles); ++i )
- {
- EFI_BLOCK_IO *bio;
- EFI_DEV_PATH_PTR devp;
- struct edd_info *info = boot_edd_info + boot_edd_info_nr;
- struct edd_device_params *params = &info->edd_device_params;
- enum { root, acpi, pci, ctrlr } state = root;
-
- status = efi_bs->HandleProtocol(handles[i], &bio_guid, (void **)&bio);
- if ( EFI_ERROR(status) ||
- bio->Media->RemovableMedia ||
- bio->Media->LogicalPartition )
- continue;
- if ( boot_edd_info_nr < EDD_INFO_MAX )
- {
- info->device = 0x80 + boot_edd_info_nr; /* fake */
- info->version = 0x11;
- params->length = offsetof(struct edd_device_params, dpte_ptr);
- params->number_of_sectors = bio->Media->LastBlock + 1;
- params->bytes_per_sector = bio->Media->BlockSize;
- params->dpte_ptr = ~0;
- }
- ++boot_edd_info_nr;
- status = efi_bs->HandleProtocol(handles[i], &devp_guid,
- (void **)&devp);
- if ( EFI_ERROR(status) )
- continue;
- for ( ; !IsDevicePathEnd(devp.DevPath);
- devp.DevPath = NextDevicePathNode(devp.DevPath) )
- {
- switch ( DevicePathType(devp.DevPath) )
- {
- const u8 *p;
-
- case ACPI_DEVICE_PATH:
- if ( state != root || boot_edd_info_nr > EDD_INFO_MAX )
- break;
- switch ( DevicePathSubType(devp.DevPath) )
- {
- case ACPI_DP:
- if ( devp.Acpi->HID != EISA_PNP_ID(0xA03) &&
- devp.Acpi->HID != EISA_PNP_ID(0xA08) )
- break;
- params->interface_path.pci.bus = devp.Acpi->UID;
- state = acpi;
- break;
- case EXPANDED_ACPI_DP:
- /* XXX */
- break;
- }
- break;
- case HARDWARE_DEVICE_PATH:
- if ( state != acpi ||
- DevicePathSubType(devp.DevPath) != HW_PCI_DP ||
- boot_edd_info_nr > EDD_INFO_MAX )
- break;
- state = pci;
- edd_put_string(params->host_bus_type, "PCI");
- params->interface_path.pci.slot = devp.Pci->Device;
- params->interface_path.pci.function = devp.Pci->Function;
- break;
- case MESSAGING_DEVICE_PATH:
- if ( state != pci || boot_edd_info_nr > EDD_INFO_MAX )
- break;
- state = ctrlr;
- switch ( DevicePathSubType(devp.DevPath) )
- {
- case MSG_ATAPI_DP:
- edd_put_string(params->interface_type, "ATAPI");
- params->interface_path.pci.channel =
- devp.Atapi->PrimarySecondary;
- params->device_path.atapi.device = devp.Atapi->SlaveMaster;
- params->device_path.atapi.lun = devp.Atapi->Lun;
- break;
- case MSG_SCSI_DP:
- edd_put_string(params->interface_type, "SCSI");
- params->device_path.scsi.id = devp.Scsi->Pun;
- params->device_path.scsi.lun = devp.Scsi->Lun;
- break;
- case MSG_FIBRECHANNEL_DP:
- edd_put_string(params->interface_type, "FIBRE");
- params->device_path.fibre.wwid = devp.FibreChannel->WWN;
- params->device_path.fibre.lun = devp.FibreChannel->Lun;
- break;
- case MSG_1394_DP:
- edd_put_string(params->interface_type, "1394");
- params->device_path.i1394.eui = devp.F1394->Guid;
- break;
- case MSG_USB_DP:
- case MSG_USB_CLASS_DP:
- edd_put_string(params->interface_type, "USB");
- break;
- case MSG_I2O_DP:
- edd_put_string(params->interface_type, "I2O");
- params->device_path.i2o.identity_tag = devp.I2O->Tid;
- break;
- default:
- continue;
- }
- info->version = 0x30;
- params->length = sizeof(struct edd_device_params);
- params->key = 0xbedd;
- params->device_path_info_length =
- sizeof(struct edd_device_params) -
- offsetof(struct edd_device_params, key);
- for ( p = (const u8 *)¶ms->key; p < ¶ms->checksum; ++p )
- params->checksum -= *p;
- break;
- case MEDIA_DEVICE_PATH:
- if ( DevicePathSubType(devp.DevPath) == MEDIA_HARDDRIVE_DP &&
- devp.HardDrive->MBRType == MBR_TYPE_PCAT &&
- boot_mbr_signature_nr < EDD_MBR_SIG_MAX )
- {
- struct mbr_signature *sig = boot_mbr_signature +
- boot_mbr_signature_nr;
-
- sig->device = 0x80 + boot_edd_info_nr; /* fake */
- memcpy(&sig->signature, devp.HardDrive->Signature,
- sizeof(sig->signature));
- ++boot_mbr_signature_nr;
- }
- break;
- }
- }
- }
- if ( handles )
- efi_bs->FreePool(handles);
- if ( boot_edd_info_nr > EDD_INFO_MAX )
- boot_edd_info_nr = EDD_INFO_MAX;
-
- /* XXX Collect EDID info. */
-
- if ( cpuid_eax(0x80000000) > 0x80000000 )
- {
- cpuid_ext_features = cpuid_edx(0x80000001);
- boot_cpu_data.x86_capability[1] = cpuid_ext_features;
- }
-
- /* Obtain basic table pointers. */
- for ( i = 0; i < efi_num_ct; ++i )
- {
- static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID;
- static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID;
- static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID;
- static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID;
-
- if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) )
- efi.acpi20 = (long)efi_ct[i].VendorTable;
- if ( match_guid(&acpi_guid, &efi_ct[i].VendorGuid) )
- efi.acpi = (long)efi_ct[i].VendorTable;
- if ( match_guid(&mps_guid, &efi_ct[i].VendorGuid) )
- efi.mps = (long)efi_ct[i].VendorTable;
- if ( match_guid(&smbios_guid, &efi_ct[i].VendorGuid) )
- efi.smbios = (long)efi_ct[i].VendorTable;
- }
-
- if (efi.smbios != EFI_INVALID_TABLE_ADDR)
- dmi_efi_get_table((void *)(long)efi.smbios);
-
- /* Collect PCI ROM contents. */
- setup_efi_pci();
-
- /* Get snapshot of variable store parameters. */
- status = (efi_rs->Hdr.Revision >> 16) >= 2 ?
- efi_rs->QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
- &efi_boot_max_var_store_size,
- &efi_boot_remain_var_store_size,
- &efi_boot_max_var_size) :
- EFI_INCOMPATIBLE_VERSION;
- if ( EFI_ERROR(status) )
- {
- efi_boot_max_var_store_size = 0;
- efi_boot_remain_var_store_size = 0;
- efi_boot_max_var_size = status;
- PrintStr(L"Warning: Could not query variable store: ");
- DisplayUint(status, 0);
- PrintStr(newline);
- }
-
- /* Allocate space for trampoline (in first Mb). */
- cfg.addr = 0x100000;
- cfg.size = trampoline_end - trampoline_start;
- status = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
- PFN_UP(cfg.size), &cfg.addr);
- if ( status == EFI_SUCCESS )
- relocate_trampoline(cfg.addr);
- else
- {
- cfg.addr = 0;
- PrintStr(L"Trampoline space cannot be allocated; will try fallback.\r\n");
- }
-
- /* Initialise L2 identity-map and boot-map page table entries (16MB). */
- for ( i = 0; i < 8; ++i )
- {
- unsigned int slot = (xen_phys_start >> L2_PAGETABLE_SHIFT) + i;
- paddr_t addr = slot << L2_PAGETABLE_SHIFT;
-
- l2_identmap[slot] = l2e_from_paddr(addr, PAGE_HYPERVISOR|_PAGE_PSE);
- slot &= L2_PAGETABLE_ENTRIES - 1;
- l2_bootmap[slot] = l2e_from_paddr(addr, __PAGE_HYPERVISOR|_PAGE_PSE);
- }
- /* Initialise L3 boot-map page directory entries. */
- l3_bootmap[l3_table_offset(xen_phys_start)] =
- l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
- l3_bootmap[l3_table_offset(xen_phys_start + (8 << L2_PAGETABLE_SHIFT) - 1)] =
- l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
-
- if ( gop )
- {
- int bpp = 0;
-
- /* Set graphics mode. */
- if ( gop_mode < gop->Mode->MaxMode && gop_mode != gop->Mode->Mode )
- gop->SetMode(gop, gop_mode);
-
- /* Get graphics and frame buffer info. */
- status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info);
- if ( !EFI_ERROR(status) )
- switch ( mode_info->PixelFormat )
- {
- case PixelRedGreenBlueReserved8BitPerColor:
- vga_console_info.u.vesa_lfb.red_pos = 0;
- vga_console_info.u.vesa_lfb.red_size = 8;
- vga_console_info.u.vesa_lfb.green_pos = 8;
- vga_console_info.u.vesa_lfb.green_size = 8;
- vga_console_info.u.vesa_lfb.blue_pos = 16;
- vga_console_info.u.vesa_lfb.blue_size = 8;
- vga_console_info.u.vesa_lfb.rsvd_pos = 24;
- vga_console_info.u.vesa_lfb.rsvd_size = 8;
- bpp = 32;
- break;
- case PixelBlueGreenRedReserved8BitPerColor:
- vga_console_info.u.vesa_lfb.red_pos = 16;
- vga_console_info.u.vesa_lfb.red_size = 8;
- vga_console_info.u.vesa_lfb.green_pos = 8;
- vga_console_info.u.vesa_lfb.green_size = 8;
- vga_console_info.u.vesa_lfb.blue_pos = 0;
- vga_console_info.u.vesa_lfb.blue_size = 8;
- vga_console_info.u.vesa_lfb.rsvd_pos = 24;
- vga_console_info.u.vesa_lfb.rsvd_size = 8;
- bpp = 32;
- break;
- case PixelBitMask:
- bpp = set_color(mode_info->PixelInformation.RedMask, bpp,
- &vga_console_info.u.vesa_lfb.red_pos,
- &vga_console_info.u.vesa_lfb.red_size);
- bpp = set_color(mode_info->PixelInformation.GreenMask, bpp,
- &vga_console_info.u.vesa_lfb.green_pos,
- &vga_console_info.u.vesa_lfb.green_size);
- bpp = set_color(mode_info->PixelInformation.BlueMask, bpp,
- &vga_console_info.u.vesa_lfb.blue_pos,
- &vga_console_info.u.vesa_lfb.blue_size);
- bpp = set_color(mode_info->PixelInformation.ReservedMask, bpp,
- &vga_console_info.u.vesa_lfb.rsvd_pos,
- &vga_console_info.u.vesa_lfb.rsvd_size);
- if ( bpp > 0 )
- break;
- /* fall through */
- default:
- PrintErr(L"Current graphics mode is unsupported!");
- status = EFI_UNSUPPORTED;
- break;
- }
- if ( !EFI_ERROR(status) )
- {
- vga_console_info.video_type = XEN_VGATYPE_EFI_LFB;
- vga_console_info.u.vesa_lfb.gbl_caps = 2; /* possibly non-VGA */
- vga_console_info.u.vesa_lfb.width =
- mode_info->HorizontalResolution;
- vga_console_info.u.vesa_lfb.height = mode_info->VerticalResolution;
- vga_console_info.u.vesa_lfb.bits_per_pixel = bpp;
- vga_console_info.u.vesa_lfb.bytes_per_line =
- (mode_info->PixelsPerScanLine * bpp + 7) >> 3;
- vga_console_info.u.vesa_lfb.lfb_base = gop->Mode->FrameBufferBase;
- vga_console_info.u.vesa_lfb.lfb_size =
- (gop->Mode->FrameBufferSize + 0xffff) >> 16;
- }
- }
-
- status = efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key,
- &efi_mdesc_size, &mdesc_ver);
- mbi.mem_upper -= efi_memmap_size;
- mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
- if ( mbi.mem_upper < xen_phys_start )
- blexit(L"Out of static memory");
- efi_memmap = (void *)(long)mbi.mem_upper;
- status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key,
- &efi_mdesc_size, &mdesc_ver);
- if ( EFI_ERROR(status) )
- blexit(L"Cannot obtain memory map");
-
- /* Populate E820 table and check trampoline area availability. */
- e = e820map - 1;
- for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
- {
- EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
- u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
- u32 type;
-
- switch ( desc->Type )
- {
- default:
- type = E820_RESERVED;
- break;
- case EfiConventionalMemory:
- case EfiBootServicesCode:
- case EfiBootServicesData:
- if ( !trampoline_phys && desc->PhysicalStart + len <= 0x100000 &&
- len >= cfg.size && desc->PhysicalStart + len > cfg.addr )
- cfg.addr = (desc->PhysicalStart + len - cfg.size) & PAGE_MASK;
- /* fall through */
- case EfiLoaderCode:
- case EfiLoaderData:
- if ( desc->Attribute & EFI_MEMORY_WB )
- type = E820_RAM;
- else
- case EfiUnusableMemory:
- type = E820_UNUSABLE;
- break;
- case EfiACPIReclaimMemory:
- type = E820_ACPI;
- break;
- case EfiACPIMemoryNVS:
- type = E820_NVS;
- break;
- }
- if ( e820nr && type == e->type &&
- desc->PhysicalStart == e->addr + e->size )
- e->size += len;
- else if ( !len || e820nr >= E820MAX )
- continue;
- else
- {
- ++e;
- e->addr = desc->PhysicalStart;
- e->size = len;
- e->type = type;
- ++e820nr;
- }
- }
- if ( !trampoline_phys )
- {
- if ( !cfg.addr )
- blexit(L"No memory for trampoline");
- relocate_trampoline(cfg.addr);
- }
-
- status = efi_bs->ExitBootServices(ImageHandle, map_key);
- if ( EFI_ERROR(status) )
- PrintErrMesg(L"Cannot exit boot services", status);
-
- /* Adjust pointers into EFI. */
- efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
-#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
- efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START;
-#endif
- efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
- efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
-
- relocate_image(__XEN_VIRT_START - xen_phys_start);
- memcpy((void *)trampoline_phys, trampoline_start, cfg.size);
-
- /* Set system registers and transfer control. */
- asm volatile("pushq $0\n\tpopfq");
- rdmsrl(MSR_EFER, efer);
- efer |= EFER_SCE;
- if ( cpuid_ext_features & (1 << (X86_FEATURE_NX & 0x1f)) )
- efer |= EFER_NX;
- wrmsrl(MSR_EFER, efer);
- write_cr0(X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP |
- X86_CR0_AM | X86_CR0_PG);
- asm volatile ( "mov %[cr4], %%cr4\n\t"
- "mov %[cr3], %%cr3\n\t"
- "movabs $__start_xen, %[rip]\n\t"
- "lidt idt_descr(%%rip)\n\t"
- "lgdt gdt_descr(%%rip)\n\t"
- "mov stack_start(%%rip), %%rsp\n\t"
- "mov %[ds], %%ss\n\t"
- "mov %[ds], %%ds\n\t"
- "mov %[ds], %%es\n\t"
- "mov %[ds], %%fs\n\t"
- "mov %[ds], %%gs\n\t"
- "movl %[cs], 8(%%rsp)\n\t"
- "mov %[rip], (%%rsp)\n\t"
- "lretq %[stkoff]-16"
- : [rip] "=&r" (efer/* any dead 64-bit variable */)
- : [cr3] "r" (idle_pg_table),
- [cr4] "r" (mmu_cr4_features),
- [cs] "ir" (__HYPERVISOR_CS),
- [ds] "r" (__HYPERVISOR_DS),
- [stkoff] "i" (STACK_SIZE - sizeof(struct cpu_info)),
- "D" (&mbi)
- : "memory" );
- for( ; ; ); /* not reached */
-}
-
-#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
-static __init void copy_mapping(unsigned long mfn, unsigned long end,
- bool_t (*is_valid)(unsigned long smfn,
- unsigned long emfn))
-{
- unsigned long next;
-
- for ( ; mfn < end; mfn = next )
- {
- l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)];
- l3_pgentry_t *l3src, *l3dst;
- unsigned long va = (unsigned long)mfn_to_virt(mfn);
-
- next = mfn + (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT));
- if ( !is_valid(mfn, min(next, end)) )
- continue;
- if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
- {
- l3dst = alloc_xen_pagetable();
- BUG_ON(!l3dst);
- clear_page(l3dst);
- efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)] =
- l4e_from_paddr(virt_to_maddr(l3dst), __PAGE_HYPERVISOR);
- }
- else
- l3dst = l4e_to_l3e(l4e);
- l3src = l4e_to_l3e(idle_pg_table[l4_table_offset(va)]);
- l3dst[l3_table_offset(mfn << PAGE_SHIFT)] = l3src[l3_table_offset(va)];
- }
-}
-
-static bool_t __init ram_range_valid(unsigned long smfn, unsigned long emfn)
-{
- unsigned long sz = pfn_to_pdx(emfn - 1) / PDX_GROUP_COUNT + 1;
-
- return !(smfn & pfn_hole_mask) &&
- find_next_bit(pdx_group_valid, sz,
- pfn_to_pdx(smfn) / PDX_GROUP_COUNT) < sz;
-}
-
-static bool_t __init rt_range_valid(unsigned long smfn, unsigned long emfn)
-{
- return 1;
-}
-#endif
-
-#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \
- (EFI_PAGE_SHIFT + BITS_PER_LONG - 32))
-
-void __init efi_init_memory(void)
-{
- unsigned int i;
-#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
- struct rt_extra {
- struct rt_extra *next;
- unsigned long smfn, emfn;
- unsigned int prot;
- } *extra, *extra_head = NULL;
-#endif
-
- printk(XENLOG_INFO "EFI memory map:\n");
- for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
- {
- EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
- u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
- unsigned long smfn, emfn;
- unsigned int prot = PAGE_HYPERVISOR;
-
- printk(XENLOG_INFO " %013" PRIx64 "-%013" PRIx64
- " type=%u attr=%016" PRIx64 "\n",
- desc->PhysicalStart, desc->PhysicalStart + len - 1,
- desc->Type, desc->Attribute);
-
- if ( !(desc->Attribute & EFI_MEMORY_RUNTIME) )
- continue;
-
- desc->VirtualStart = INVALID_VIRTUAL_ADDRESS;
-
- smfn = PFN_DOWN(desc->PhysicalStart);
- emfn = PFN_UP(desc->PhysicalStart + len);
-
- if ( desc->Attribute & EFI_MEMORY_WB )
- /* nothing */;
- else if ( desc->Attribute & EFI_MEMORY_WT )
- prot |= _PAGE_PWT | MAP_SMALL_PAGES;
- else if ( desc->Attribute & EFI_MEMORY_WC )
- prot |= _PAGE_PAT | MAP_SMALL_PAGES;
- else if ( desc->Attribute & (EFI_MEMORY_UC | EFI_MEMORY_UCE) )
- prot |= _PAGE_PWT | _PAGE_PCD | MAP_SMALL_PAGES;
- else
- {
- printk(XENLOG_ERR "Unknown cachability for MFNs %#lx-%#lx\n",
- smfn, emfn - 1);
- continue;
- }
-
- if ( desc->Attribute & EFI_MEMORY_WP )
- prot &= _PAGE_RW;
- if ( desc->Attribute & EFI_MEMORY_XP )
- prot |= _PAGE_NX_BIT;
-
- if ( pfn_to_pdx(emfn - 1) < (DIRECTMAP_SIZE >> PAGE_SHIFT) &&
- !(smfn & pfn_hole_mask) &&
- !((smfn ^ (emfn - 1)) & ~pfn_pdx_bottom_mask) )
- {
- if ( (unsigned long)mfn_to_virt(emfn - 1) >= HYPERVISOR_VIRT_END )
- prot &= ~_PAGE_GLOBAL;
- if ( map_pages_to_xen((unsigned long)mfn_to_virt(smfn),
- smfn, emfn - smfn, prot) == 0 )
- desc->VirtualStart =
- (unsigned long)maddr_to_virt(desc->PhysicalStart);
- else
- printk(XENLOG_ERR "Could not map MFNs %#lx-%#lx\n",
- smfn, emfn - 1);
- }
-#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
- else if ( !((desc->PhysicalStart + len - 1) >> (VADDR_BITS - 1)) &&
- (extra = xmalloc(struct rt_extra)) != NULL )
- {
- extra->smfn = smfn;
- extra->emfn = emfn;
- extra->prot = prot & ~_PAGE_GLOBAL;
- extra->next = extra_head;
- extra_head = extra;
- desc->VirtualStart = desc->PhysicalStart;
- }
-#endif
- else
- {
-#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
- /* XXX allocate e.g. down from FIXADDR_START */
-#endif
- printk(XENLOG_ERR "No mapping for MFNs %#lx-%#lx\n",
- smfn, emfn - 1);
- }
- }
-
-#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
- efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size,
- mdesc_ver, efi_memmap);
-#else
- /* Set up 1:1 page tables to do runtime calls in "physical" mode. */
- efi_l4_pgtable = alloc_xen_pagetable();
- BUG_ON(!efi_l4_pgtable);
- clear_page(efi_l4_pgtable);
-
- copy_mapping(0, max_page, ram_range_valid);
-
- /* Insert non-RAM runtime mappings inside the direct map. */
- for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
- {
- const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
-
- if ( (desc->Attribute & EFI_MEMORY_RUNTIME) &&
- desc->VirtualStart != INVALID_VIRTUAL_ADDRESS &&
- desc->VirtualStart != desc->PhysicalStart )
- copy_mapping(PFN_DOWN(desc->PhysicalStart),
- PFN_UP(desc->PhysicalStart +
- (desc->NumberOfPages << EFI_PAGE_SHIFT)),
- rt_range_valid);
- }
-
- /* Insert non-RAM runtime mappings outside of the direct map. */
- while ( (extra = extra_head) != NULL )
- {
- unsigned long addr = extra->smfn << PAGE_SHIFT;
- l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(addr)];
- l3_pgentry_t *pl3e;
- l2_pgentry_t *pl2e;
- l1_pgentry_t *l1t;
-
- if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
- {
- pl3e = alloc_xen_pagetable();
- BUG_ON(!pl3e);
- clear_page(pl3e);
- efi_l4_pgtable[l4_table_offset(addr)] =
- l4e_from_paddr(virt_to_maddr(pl3e), __PAGE_HYPERVISOR);
- }
- else
- pl3e = l4e_to_l3e(l4e);
- pl3e += l3_table_offset(addr);
- if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
- {
- pl2e = alloc_xen_pagetable();
- BUG_ON(!pl2e);
- clear_page(pl2e);
- *pl3e = l3e_from_paddr(virt_to_maddr(pl2e), __PAGE_HYPERVISOR);
- }
- else
- {
- BUG_ON(l3e_get_flags(*pl3e) & _PAGE_PSE);
- pl2e = l3e_to_l2e(*pl3e);
- }
- pl2e += l2_table_offset(addr);
- if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
- {
- l1t = alloc_xen_pagetable();
- BUG_ON(!l1t);
- clear_page(l1t);
- *pl2e = l2e_from_paddr(virt_to_maddr(l1t), __PAGE_HYPERVISOR);
- }
- else
- {
- BUG_ON(l2e_get_flags(*pl2e) & _PAGE_PSE);
- l1t = l2e_to_l1e(*pl2e);
- }
- for ( i = l1_table_offset(addr);
- i < L1_PAGETABLE_ENTRIES && extra->smfn < extra->emfn;
- ++i, ++extra->smfn )
- l1t[i] = l1e_from_pfn(extra->smfn, extra->prot);
-
- if ( extra->smfn == extra->emfn )
- {
- extra_head = extra->next;
- xfree(extra);
- }
- }
-
- /* Insert Xen mappings. */
- for ( i = l4_table_offset(HYPERVISOR_VIRT_START);
- i < l4_table_offset(DIRECTMAP_VIRT_END); ++i )
- efi_l4_pgtable[i] = idle_pg_table[i];
-#endif
-}
diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h
new file mode 100644
index 0000000..3a3b4fe
--- /dev/null
+++ b/xen/arch/x86/efi/efi-boot.h
@@ -0,0 +1,639 @@
+/*
+ * Architecture specific implementation for EFI boot code. This file
+ * is intended to be included by common/efi/boot.c _only_, and
+ * therefore can define arch specific global variables.
+ */
+#include <xen/vga.h>
+#include <asm/e820.h>
+#include <asm/edd.h>
+#include <asm/msr.h>
+#include <asm/processor.h>
+
+static struct file __initdata ucode;
+static multiboot_info_t __initdata mbi = {
+ .flags = MBI_MODULES | MBI_LOADERNAME
+};
+static module_t __initdata mb_modules[3];
+
+static void __init edd_put_string(u8 *dst, size_t n, const char *src)
+{
+ while ( n-- && *src )
+ *dst++ = *src++;
+ if ( *src )
+ PrintErrMesg(L"Internal error populating EDD info",
+ EFI_BUFFER_TOO_SMALL);
+ while ( n-- )
+ *dst++ = ' ';
+}
+#define edd_put_string(d, s) edd_put_string(d, ARRAY_SIZE(d), s)
+
+extern const intpte_t __page_tables_start[], __page_tables_end[];
+#define in_page_tables(v) ((intpte_t *)(v) >= __page_tables_start && \
+ (intpte_t *)(v) < __page_tables_end)
+
+#define PE_BASE_RELOC_ABS 0
+#define PE_BASE_RELOC_HIGHLOW 3
+#define PE_BASE_RELOC_DIR64 10
+
+extern const struct pe_base_relocs {
+ u32 rva;
+ u32 size;
+ u16 entries[];
+} __base_relocs_start[], __base_relocs_end[];
+
+static void __init efi_arch_relocate_image(unsigned long delta)
+{
+ const struct pe_base_relocs *base_relocs;
+
+ for ( base_relocs = __base_relocs_start; base_relocs < __base_relocs_end; )
+ {
+ unsigned int i, n;
+
+ n = (base_relocs->size - sizeof(*base_relocs)) /
+ sizeof(*base_relocs->entries);
+ for ( i = 0; i < n; ++i )
+ {
+ unsigned long addr = xen_phys_start + base_relocs->rva +
+ (base_relocs->entries[i] & 0xfff);
+
+ switch ( base_relocs->entries[i] >> 12 )
+ {
+ case PE_BASE_RELOC_ABS:
+ break;
+ case PE_BASE_RELOC_HIGHLOW:
+ if ( delta )
+ {
+ *(u32 *)addr += delta;
+ if ( in_page_tables(addr) )
+ *(u32 *)addr += xen_phys_start;
+ }
+ break;
+ case PE_BASE_RELOC_DIR64:
+ if ( delta )
+ {
+ *(u64 *)addr += delta;
+ if ( in_page_tables(addr) )
+ *(intpte_t *)addr += xen_phys_start;
+ }
+ break;
+ default:
+ blexit(L"Unsupported relocation type");
+ }
+ }
+ base_relocs = (const void *)(base_relocs->entries + i + (i & 1));
+ }
+}
+
+extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[];
+extern const s32 __trampoline_seg_start[], __trampoline_seg_stop[];
+
+static void __init relocate_trampoline(unsigned long phys)
+{
+ const s32 *trampoline_ptr;
+
+ trampoline_phys = phys;
+ /* Apply relocations to trampoline. */
+ for ( trampoline_ptr = __trampoline_rel_start;
+ trampoline_ptr < __trampoline_rel_stop;
+ ++trampoline_ptr )
+ *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += phys;
+ for ( trampoline_ptr = __trampoline_seg_start;
+ trampoline_ptr < __trampoline_seg_stop;
+ ++trampoline_ptr )
+ *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4;
+}
+
+static void __init place_string(u32 *addr, const char *s)
+{
+ static char *__initdata alloc = start;
+
+ if ( s && *s )
+ {
+ size_t len1 = strlen(s) + 1;
+ const char *old = (char *)(long)*addr;
+ size_t len2 = *addr ? strlen(old) + 1 : 0;
+
+ alloc -= len1 + len2;
+ /*
+ * Insert new string before already existing one. This is needed
+ * for options passed on the command line to override options from
+ * the configuration file.
+ */
+ memcpy(alloc, s, len1);
+ if ( *addr )
+ {
+ alloc[len1 - 1] = ' ';
+ memcpy(alloc + len1, old, len2);
+ }
+ }
+ *addr = (long)alloc;
+}
+
+static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
+ void *map,
+ UINTN map_size,
+ UINTN desc_size,
+ UINT32 desc_ver)
+{
+ struct e820entry *e;
+ unsigned int i;
+
+ /* Populate E820 table and check trampoline area availability. */
+ e = e820map - 1;
+ for ( e820nr = i = 0; i < map_size; i += desc_size )
+ {
+ EFI_MEMORY_DESCRIPTOR *desc = map + i;
+ u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
+ u32 type;
+
+ switch ( desc->Type )
+ {
+ default:
+ type = E820_RESERVED;
+ break;
+ case EfiConventionalMemory:
+ case EfiBootServicesCode:
+ case EfiBootServicesData:
+ if ( !trampoline_phys && desc->PhysicalStart + len <= 0x100000 &&
+ len >= cfg.size && desc->PhysicalStart + len > cfg.addr )
+ cfg.addr = (desc->PhysicalStart + len - cfg.size) & PAGE_MASK;
+ /* fall through */
+ case EfiLoaderCode:
+ case EfiLoaderData:
+ if ( desc->Attribute & EFI_MEMORY_WB )
+ type = E820_RAM;
+ else
+ case EfiUnusableMemory:
+ type = E820_UNUSABLE;
+ break;
+ case EfiACPIReclaimMemory:
+ type = E820_ACPI;
+ break;
+ case EfiACPIMemoryNVS:
+ type = E820_NVS;
+ break;
+ }
+ if ( e820nr && type == e->type &&
+ desc->PhysicalStart == e->addr + e->size )
+ e->size += len;
+ else if ( !len || e820nr >= E820MAX )
+ continue;
+ else
+ {
+ ++e;
+ e->addr = desc->PhysicalStart;
+ e->size = len;
+ e->type = type;
+ ++e820nr;
+ }
+ }
+
+}
+
+static void *__init efi_arch_allocate_mmap_buffer(UINTN *map_size)
+{
+ place_string(&mbi.mem_upper, NULL);
+ mbi.mem_upper -= *map_size;
+ mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
+ if ( mbi.mem_upper < xen_phys_start )
+ return NULL;
+ return (void *)(long)mbi.mem_upper;
+}
+
+static void __init efi_arch_pre_exit_boot(void)
+{
+ if ( !trampoline_phys )
+ {
+ if ( !cfg.addr )
+ blexit(L"No memory for trampoline");
+ relocate_trampoline(cfg.addr);
+ }
+}
+
+static void __init noreturn efi_arch_post_exit_boot(void)
+{
+ u64 efer;
+
+ efi_arch_relocate_image(__XEN_VIRT_START - xen_phys_start);
+ memcpy((void *)trampoline_phys, trampoline_start, cfg.size);
+
+ /* Set system registers and transfer control. */
+ asm volatile("pushq $0\n\tpopfq");
+ rdmsrl(MSR_EFER, efer);
+ efer |= EFER_SCE;
+ if ( cpuid_ext_features & (1 << (X86_FEATURE_NX & 0x1f)) )
+ efer |= EFER_NX;
+ wrmsrl(MSR_EFER, efer);
+ write_cr0(X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP |
+ X86_CR0_AM | X86_CR0_PG);
+ asm volatile ( "mov %[cr4], %%cr4\n\t"
+ "mov %[cr3], %%cr3\n\t"
+ "movabs $__start_xen, %[rip]\n\t"
+ "lgdt gdt_descr(%%rip)\n\t"
+ "mov stack_start(%%rip), %%rsp\n\t"
+ "mov %[ds], %%ss\n\t"
+ "mov %[ds], %%ds\n\t"
+ "mov %[ds], %%es\n\t"
+ "mov %[ds], %%fs\n\t"
+ "mov %[ds], %%gs\n\t"
+ "movl %[cs], 8(%%rsp)\n\t"
+ "mov %[rip], (%%rsp)\n\t"
+ "lretq %[stkoff]-16"
+ : [rip] "=&r" (efer/* any dead 64-bit variable */)
+ : [cr3] "r" (idle_pg_table),
+ [cr4] "r" (mmu_cr4_features),
+ [cs] "ir" (__HYPERVISOR_CS),
+ [ds] "r" (__HYPERVISOR_DS),
+ [stkoff] "i" (STACK_SIZE - sizeof(struct cpu_info)),
+ "D" (&mbi)
+ : "memory" );
+ for( ; ; ); /* not reached */
+}
+
+static void __init efi_arch_cfg_file_early(EFI_FILE_HANDLE dir_handle, char *section)
+{
+}
+
+static void __init efi_arch_cfg_file_late(EFI_FILE_HANDLE dir_handle, char *section)
+{
+ union string name;
+
+ name.s = get_value(&cfg, section, "ucode");
+ if ( !name.s )
+ name.s = get_value(&cfg, "global", "ucode");
+ if ( name.s )
+ {
+ microcode_set_module(mbi.mods_count);
+ split_string(name.s);
+ read_file(dir_handle, s2w(&name), &ucode, NULL);
+ efi_bs->FreePool(name.w);
+ }
+}
+
+static void __init efi_arch_handle_cmdline(CHAR16 *image_name,
+ CHAR16 *cmdline_options,
+ char *cfgfile_options)
+{
+ union string name;
+
+ if ( cmdline_options )
+ {
+ name.w = cmdline_options;
+ w2s(&name);
+ place_string(&mbi.cmdline, name.s);
+ }
+ if ( cfgfile_options )
+ place_string(&mbi.cmdline, cfgfile_options);
+ /* Insert image name last, as it gets prefixed to the other options. */
+ if ( image_name )
+ {
+ name.w = image_name;
+ w2s(&name);
+ }
+ else
+ name.s = "xen";
+ place_string(&mbi.cmdline, name.s);
+
+ if ( mbi.cmdline )
+ mbi.flags |= MBI_CMDLINE;
+ /*
+ * These must not be initialized statically, since the value must
+ * not get relocated when processing base relocations later.
+ */
+ mbi.boot_loader_name = (long)"EFI";
+ mbi.mods_addr = (long)mb_modules;
+}
+
+static void __init efi_arch_edd(void)
+{
+ static EFI_GUID __initdata bio_guid = BLOCK_IO_PROTOCOL;
+ static EFI_GUID __initdata devp_guid = DEVICE_PATH_PROTOCOL;
+ EFI_HANDLE *handles = NULL;
+ unsigned int i;
+ UINTN size;
+ EFI_STATUS status;
+
+ /* Collect EDD info. */
+ BUILD_BUG_ON(offsetof(struct edd_info, edd_device_params) != EDDEXTSIZE);
+ BUILD_BUG_ON(sizeof(struct edd_device_params) != EDDPARMSIZE);
+ size = 0;
+ status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size, NULL);
+ if ( status == EFI_BUFFER_TOO_SMALL )
+ status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
+ if ( !EFI_ERROR(status) )
+ status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size,
+ handles);
+ if ( EFI_ERROR(status) )
+ size = 0;
+ for ( i = 0; i < size / sizeof(*handles); ++i )
+ {
+ EFI_BLOCK_IO *bio;
+ EFI_DEV_PATH_PTR devp;
+ struct edd_info *info = boot_edd_info + boot_edd_info_nr;
+ struct edd_device_params *params = &info->edd_device_params;
+ enum { root, acpi, pci, ctrlr } state = root;
+
+ status = efi_bs->HandleProtocol(handles[i], &bio_guid, (void **)&bio);
+ if ( EFI_ERROR(status) ||
+ bio->Media->RemovableMedia ||
+ bio->Media->LogicalPartition )
+ continue;
+ if ( boot_edd_info_nr < EDD_INFO_MAX )
+ {
+ info->device = 0x80 + boot_edd_info_nr; /* fake */
+ info->version = 0x11;
+ params->length = offsetof(struct edd_device_params, dpte_ptr);
+ params->number_of_sectors = bio->Media->LastBlock + 1;
+ params->bytes_per_sector = bio->Media->BlockSize;
+ params->dpte_ptr = ~0;
+ }
+ ++boot_edd_info_nr;
+ status = efi_bs->HandleProtocol(handles[i], &devp_guid,
+ (void **)&devp);
+ if ( EFI_ERROR(status) )
+ continue;
+ for ( ; !IsDevicePathEnd(devp.DevPath);
+ devp.DevPath = NextDevicePathNode(devp.DevPath) )
+ {
+ switch ( DevicePathType(devp.DevPath) )
+ {
+ const u8 *p;
+
+ case ACPI_DEVICE_PATH:
+ if ( state != root || boot_edd_info_nr > EDD_INFO_MAX )
+ break;
+ switch ( DevicePathSubType(devp.DevPath) )
+ {
+ case ACPI_DP:
+ if ( devp.Acpi->HID != EISA_PNP_ID(0xA03) &&
+ devp.Acpi->HID != EISA_PNP_ID(0xA08) )
+ break;
+ params->interface_path.pci.bus = devp.Acpi->UID;
+ state = acpi;
+ break;
+ case EXPANDED_ACPI_DP:
+ /* XXX */
+ break;
+ }
+ break;
+ case HARDWARE_DEVICE_PATH:
+ if ( state != acpi ||
+ DevicePathSubType(devp.DevPath) != HW_PCI_DP ||
+ boot_edd_info_nr > EDD_INFO_MAX )
+ break;
+ state = pci;
+ edd_put_string(params->host_bus_type, "PCI");
+ params->interface_path.pci.slot = devp.Pci->Device;
+ params->interface_path.pci.function = devp.Pci->Function;
+ break;
+ case MESSAGING_DEVICE_PATH:
+ if ( state != pci || boot_edd_info_nr > EDD_INFO_MAX )
+ break;
+ state = ctrlr;
+ switch ( DevicePathSubType(devp.DevPath) )
+ {
+ case MSG_ATAPI_DP:
+ edd_put_string(params->interface_type, "ATAPI");
+ params->interface_path.pci.channel =
+ devp.Atapi->PrimarySecondary;
+ params->device_path.atapi.device = devp.Atapi->SlaveMaster;
+ params->device_path.atapi.lun = devp.Atapi->Lun;
+ break;
+ case MSG_SCSI_DP:
+ edd_put_string(params->interface_type, "SCSI");
+ params->device_path.scsi.id = devp.Scsi->Pun;
+ params->device_path.scsi.lun = devp.Scsi->Lun;
+ break;
+ case MSG_FIBRECHANNEL_DP:
+ edd_put_string(params->interface_type, "FIBRE");
+ params->device_path.fibre.wwid = devp.FibreChannel->WWN;
+ params->device_path.fibre.lun = devp.FibreChannel->Lun;
+ break;
+ case MSG_1394_DP:
+ edd_put_string(params->interface_type, "1394");
+ params->device_path.i1394.eui = devp.F1394->Guid;
+ break;
+ case MSG_USB_DP:
+ case MSG_USB_CLASS_DP:
+ edd_put_string(params->interface_type, "USB");
+ break;
+ case MSG_I2O_DP:
+ edd_put_string(params->interface_type, "I2O");
+ params->device_path.i2o.identity_tag = devp.I2O->Tid;
+ break;
+ default:
+ continue;
+ }
+ info->version = 0x30;
+ params->length = sizeof(struct edd_device_params);
+ params->key = 0xbedd;
+ params->device_path_info_length =
+ sizeof(struct edd_device_params) -
+ offsetof(struct edd_device_params, key);
+ for ( p = (const u8 *)¶ms->key; p < ¶ms->checksum; ++p )
+ params->checksum -= *p;
+ break;
+ case MEDIA_DEVICE_PATH:
+ if ( DevicePathSubType(devp.DevPath) == MEDIA_HARDDRIVE_DP &&
+ devp.HardDrive->MBRType == MBR_TYPE_PCAT &&
+ boot_mbr_signature_nr < EDD_MBR_SIG_MAX )
+ {
+ struct mbr_signature *sig = boot_mbr_signature +
+ boot_mbr_signature_nr;
+
+ sig->device = 0x80 + boot_edd_info_nr; /* fake */
+ memcpy(&sig->signature, devp.HardDrive->Signature,
+ sizeof(sig->signature));
+ ++boot_mbr_signature_nr;
+ }
+ break;
+ }
+ }
+ }
+ if ( handles )
+ efi_bs->FreePool(handles);
+ if ( boot_edd_info_nr > EDD_INFO_MAX )
+ boot_edd_info_nr = EDD_INFO_MAX;
+}
+
+static void __init efi_arch_console_init(UINTN cols, UINTN rows)
+{
+ vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3;
+ vga_console_info.u.text_mode_3.columns = cols;
+ vga_console_info.u.text_mode_3.rows = rows;
+ vga_console_info.u.text_mode_3.font_height = 16;
+}
+
+static void __init efi_arch_video_init(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
+ UINTN info_size,
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info)
+{
+ int bpp = 0;
+
+ switch ( mode_info->PixelFormat )
+ {
+ case PixelRedGreenBlueReserved8BitPerColor:
+ vga_console_info.u.vesa_lfb.red_pos = 0;
+ vga_console_info.u.vesa_lfb.red_size = 8;
+ vga_console_info.u.vesa_lfb.green_pos = 8;
+ vga_console_info.u.vesa_lfb.green_size = 8;
+ vga_console_info.u.vesa_lfb.blue_pos = 16;
+ vga_console_info.u.vesa_lfb.blue_size = 8;
+ vga_console_info.u.vesa_lfb.rsvd_pos = 24;
+ vga_console_info.u.vesa_lfb.rsvd_size = 8;
+ bpp = 32;
+ break;
+ case PixelBlueGreenRedReserved8BitPerColor:
+ vga_console_info.u.vesa_lfb.red_pos = 16;
+ vga_console_info.u.vesa_lfb.red_size = 8;
+ vga_console_info.u.vesa_lfb.green_pos = 8;
+ vga_console_info.u.vesa_lfb.green_size = 8;
+ vga_console_info.u.vesa_lfb.blue_pos = 0;
+ vga_console_info.u.vesa_lfb.blue_size = 8;
+ vga_console_info.u.vesa_lfb.rsvd_pos = 24;
+ vga_console_info.u.vesa_lfb.rsvd_size = 8;
+ bpp = 32;
+ break;
+ case PixelBitMask:
+ bpp = set_color(mode_info->PixelInformation.RedMask, bpp,
+ &vga_console_info.u.vesa_lfb.red_pos,
+ &vga_console_info.u.vesa_lfb.red_size);
+ bpp = set_color(mode_info->PixelInformation.GreenMask, bpp,
+ &vga_console_info.u.vesa_lfb.green_pos,
+ &vga_console_info.u.vesa_lfb.green_size);
+ bpp = set_color(mode_info->PixelInformation.BlueMask, bpp,
+ &vga_console_info.u.vesa_lfb.blue_pos,
+ &vga_console_info.u.vesa_lfb.blue_size);
+ bpp = set_color(mode_info->PixelInformation.ReservedMask, bpp,
+ &vga_console_info.u.vesa_lfb.rsvd_pos,
+ &vga_console_info.u.vesa_lfb.rsvd_size);
+ if ( bpp > 0 )
+ break;
+ /* fall through */
+ default:
+ PrintErr(L"Current graphics mode is unsupported!\r\n");
+ bpp = 0;
+ break;
+ }
+ if ( bpp > 0 )
+ {
+ vga_console_info.video_type = XEN_VGATYPE_EFI_LFB;
+ vga_console_info.u.vesa_lfb.gbl_caps = 2; /* possibly non-VGA */
+ vga_console_info.u.vesa_lfb.width =
+ mode_info->HorizontalResolution;
+ vga_console_info.u.vesa_lfb.height = mode_info->VerticalResolution;
+ vga_console_info.u.vesa_lfb.bits_per_pixel = bpp;
+ vga_console_info.u.vesa_lfb.bytes_per_line =
+ (mode_info->PixelsPerScanLine * bpp + 7) >> 3;
+ vga_console_info.u.vesa_lfb.lfb_base = gop->Mode->FrameBufferBase;
+ vga_console_info.u.vesa_lfb.lfb_size =
+ (gop->Mode->FrameBufferSize + 0xffff) >> 16;
+ }
+}
+
+static void __init efi_arch_memory_setup(void)
+{
+ unsigned int i;
+ EFI_STATUS status;
+
+ /* Allocate space for trampoline (in first Mb). */
+ cfg.addr = 0x100000;
+ cfg.size = trampoline_end - trampoline_start;
+ status = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
+ PFN_UP(cfg.size), &cfg.addr);
+ if ( status == EFI_SUCCESS )
+ relocate_trampoline(cfg.addr);
+ else
+ {
+ cfg.addr = 0;
+ PrintStr(L"Trampoline space cannot be allocated; will try fallback.\r\n");
+ }
+
+ /* Initialise L2 identity-map and boot-map page table entries (16MB). */
+ for ( i = 0; i < 8; ++i )
+ {
+ unsigned int slot = (xen_phys_start >> L2_PAGETABLE_SHIFT) + i;
+ paddr_t addr = slot << L2_PAGETABLE_SHIFT;
+
+ l2_identmap[slot] = l2e_from_paddr(addr, PAGE_HYPERVISOR|_PAGE_PSE);
+ slot &= L2_PAGETABLE_ENTRIES - 1;
+ l2_bootmap[slot] = l2e_from_paddr(addr, __PAGE_HYPERVISOR|_PAGE_PSE);
+ }
+ /* Initialise L3 boot-map page directory entries. */
+ l3_bootmap[l3_table_offset(xen_phys_start)] =
+ l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
+ l3_bootmap[l3_table_offset(xen_phys_start + (8 << L2_PAGETABLE_SHIFT) - 1)] =
+ l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
+}
+
+static void __init efi_arch_handle_module(struct file *file, const CHAR16 *name,
+ char *options)
+{
+ union string local_name;
+ void *ptr;
+
+ /*
+ * Make a copy, as conversion is destructive, and caller still wants
+ * wide string available after this call returns.
+ */
+ if ( efi_bs->AllocatePool(EfiLoaderData, (wstrlen(name) + 1) * sizeof(*name),
+ &ptr) != EFI_SUCCESS )
+ blexit(L"Unable to allocate string buffer");
+
+ local_name.w = ptr;
+ wstrcpy(local_name.w, name);
+ w2s(&local_name);
+
+ /*
+ * If options are provided, put them in
+ * mb_modules[mbi.mods_count].string after the filename, with a space
+ * separating them. place_string() prepends strings and adds separating
+ * spaces, so the call order is reversed.
+ */
+ if ( options )
+ place_string(&mb_modules[mbi.mods_count].string, options);
+ place_string(&mb_modules[mbi.mods_count].string, local_name.s);
+ mb_modules[mbi.mods_count].mod_start = file->addr >> PAGE_SHIFT;
+ mb_modules[mbi.mods_count].mod_end = file->size;
+ ++mbi.mods_count;
+ efi_bs->FreePool(ptr);
+}
+
+static void __init efi_arch_cpu(void)
+{
+ if ( cpuid_eax(0x80000000) > 0x80000000 )
+ {
+ cpuid_ext_features = cpuid_edx(0x80000001);
+ boot_cpu_data.x86_capability[1] = cpuid_ext_features;
+ }
+}
+
+static void __init efi_arch_blexit(void)
+{
+ if ( ucode.addr )
+ efi_bs->FreePages(ucode.addr, PFN_UP(ucode.size));
+}
+
+static void __init efi_arch_load_addr_check(EFI_LOADED_IMAGE *loaded_image)
+{
+ xen_phys_start = (UINTN)loaded_image->ImageBase;
+ if ( (xen_phys_start + loaded_image->ImageSize - 1) >> 32 )
+ blexit(L"Xen must be loaded below 4Gb.");
+ if ( xen_phys_start & ((1 << L2_PAGETABLE_SHIFT) - 1) )
+ blexit(L"Xen must be loaded at a 2Mb boundary.");
+ trampoline_xen_phys_start = xen_phys_start;
+}
+
+static bool_t __init efi_arch_use_config_file(EFI_SYSTEM_TABLE *SystemTable)
+{
+ return 1; /* x86 always uses a config file */
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/efi/efi.h b/xen/arch/x86/efi/efi.h
deleted file mode 100644
index a80d5f1..0000000
--- a/xen/arch/x86/efi/efi.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#include <asm/efibind.h>
-#include <efi/efidef.h>
-#include <efi/efierr.h>
-#include <efi/eficon.h>
-#include <efi/efidevp.h>
-#include <efi/eficapsule.h>
-#include <efi/efiapi.h>
-#include <xen/efi.h>
-#include <xen/spinlock.h>
-#include <asm/page.h>
-
-struct efi_pci_rom {
- const struct efi_pci_rom *next;
- u16 vendor, devid, segment;
- u8 bus, devfn;
- unsigned long size;
- unsigned char data[];
-};
-
-extern unsigned int efi_num_ct;
-extern EFI_CONFIGURATION_TABLE *efi_ct;
-
-extern unsigned int efi_version, efi_fw_revision;
-extern const CHAR16 *efi_fw_vendor;
-
-extern EFI_RUNTIME_SERVICES *efi_rs;
-
-extern UINTN efi_memmap_size, efi_mdesc_size;
-extern void *efi_memmap;
-
-extern l4_pgentry_t *efi_l4_pgtable;
-
-extern const struct efi_pci_rom *efi_pci_roms;
-
-extern UINT64 efi_boot_max_var_store_size, efi_boot_remain_var_store_size,
- efi_boot_max_var_size;
-
-unsigned long efi_rs_enter(void);
-void efi_rs_leave(unsigned long);
diff --git a/xen/arch/x86/efi/runtime.c b/xen/arch/x86/efi/runtime.c
deleted file mode 100644
index 166852d..0000000
--- a/xen/arch/x86/efi/runtime.c
+++ /dev/null
@@ -1,547 +0,0 @@
-#include "efi.h"
-#include <xen/cache.h>
-#include <xen/errno.h>
-#include <xen/guest_access.h>
-#include <xen/irq.h>
-#include <xen/time.h>
-#include <asm/mc146818rtc.h>
-
-DEFINE_XEN_GUEST_HANDLE(CHAR16);
-
-#ifndef COMPAT
-
-# include <asm/i387.h>
-# include <asm/xstate.h>
-# include <public/platform.h>
-
-const bool_t efi_enabled = 1;
-
-unsigned int __read_mostly efi_num_ct;
-EFI_CONFIGURATION_TABLE *__read_mostly efi_ct;
-
-unsigned int __read_mostly efi_version;
-unsigned int __read_mostly efi_fw_revision;
-const CHAR16 *__read_mostly efi_fw_vendor;
-
-EFI_RUNTIME_SERVICES *__read_mostly efi_rs;
-static DEFINE_SPINLOCK(efi_rs_lock);
-
-UINTN __read_mostly efi_memmap_size;
-UINTN __read_mostly efi_mdesc_size;
-void *__read_mostly efi_memmap;
-
-UINT64 __read_mostly efi_boot_max_var_store_size;
-UINT64 __read_mostly efi_boot_remain_var_store_size;
-UINT64 __read_mostly efi_boot_max_var_size;
-
-struct efi __read_mostly efi = {
- .acpi = EFI_INVALID_TABLE_ADDR,
- .acpi20 = EFI_INVALID_TABLE_ADDR,
- .mps = EFI_INVALID_TABLE_ADDR,
- .smbios = EFI_INVALID_TABLE_ADDR,
-};
-
-l4_pgentry_t *__read_mostly efi_l4_pgtable;
-
-const struct efi_pci_rom *__read_mostly efi_pci_roms;
-
-unsigned long efi_rs_enter(void)
-{
- static const u16 fcw = FCW_DEFAULT;
- static const u32 mxcsr = MXCSR_DEFAULT;
- unsigned long cr3 = read_cr3();
-
- save_fpu_enable();
- asm volatile ( "fldcw %0" :: "m" (fcw) );
- asm volatile ( "ldmxcsr %0" :: "m" (mxcsr) );
-
- spin_lock(&efi_rs_lock);
-
- /* prevent fixup_page_fault() from doing anything */
- irq_enter();
-
- if ( is_pv_vcpu(current) && !is_idle_vcpu(current) )
- {
- struct desc_ptr gdt_desc = {
- .limit = LAST_RESERVED_GDT_BYTE,
- .base = (unsigned long)(per_cpu(gdt_table, smp_processor_id()) -
- FIRST_RESERVED_GDT_ENTRY)
- };
-
- asm volatile ( "lgdt %0" : : "m" (gdt_desc) );
- }
-
- write_cr3(virt_to_maddr(efi_l4_pgtable));
-
- return cr3;
-}
-
-void efi_rs_leave(unsigned long cr3)
-{
- write_cr3(cr3);
- if ( is_pv_vcpu(current) && !is_idle_vcpu(current) )
- {
- struct desc_ptr gdt_desc = {
- .limit = LAST_RESERVED_GDT_BYTE,
- .base = GDT_VIRT_START(current)
- };
-
- asm volatile ( "lgdt %0" : : "m" (gdt_desc) );
- }
- irq_exit();
- spin_unlock(&efi_rs_lock);
- stts();
-}
-
-unsigned long efi_get_time(void)
-{
- EFI_TIME time;
- EFI_STATUS status;
- unsigned long cr3 = efi_rs_enter(), flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- status = efi_rs->GetTime(&time, NULL);
- spin_unlock_irqrestore(&rtc_lock, flags);
- efi_rs_leave(cr3);
-
- if ( EFI_ERROR(status) )
- return 0;
-
- return mktime(time.Year, time.Month, time.Day,
- time.Hour, time.Minute, time.Second);
-}
-
-void efi_halt_system(void)
-{
- EFI_STATUS status;
- unsigned long cr3 = efi_rs_enter();
-
- status = efi_rs->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
- efi_rs_leave(cr3);
-
- printk(XENLOG_WARNING "EFI: could not halt system (%#lx)\n", status);
-}
-
-void efi_reset_system(bool_t warm)
-{
- EFI_STATUS status;
- unsigned long cr3 = efi_rs_enter();
-
- status = efi_rs->ResetSystem(warm ? EfiResetWarm : EfiResetCold,
- EFI_SUCCESS, 0, NULL);
- efi_rs_leave(cr3);
-
- printk(XENLOG_WARNING "EFI: could not reset system (%#lx)\n", status);
-}
-
-#endif
-
-int efi_get_info(uint32_t idx, union xenpf_efi_info *info)
-{
- unsigned int i, n;
-
- switch ( idx )
- {
- case XEN_FW_EFI_VERSION:
- info->version = efi_version;
- break;
- case XEN_FW_EFI_RT_VERSION:
- {
- unsigned long cr3 = efi_rs_enter();
-
- info->version = efi_rs->Hdr.Revision;
- efi_rs_leave(cr3);
- break;
- }
- case XEN_FW_EFI_CONFIG_TABLE:
- info->cfg.addr = __pa(efi_ct);
- info->cfg.nent = efi_num_ct;
- break;
- case XEN_FW_EFI_VENDOR:
- info->vendor.revision = efi_fw_revision;
- n = info->vendor.bufsz / sizeof(*efi_fw_vendor);
- if ( !guest_handle_okay(guest_handle_cast(info->vendor.name,
- CHAR16), n) )
- return -EFAULT;
- for ( i = 0; i < n; ++i )
- {
- if ( __copy_to_guest_offset(info->vendor.name, i,
- efi_fw_vendor + i, 1) )
- return -EFAULT;
- if ( !efi_fw_vendor[i] )
- break;
- }
- break;
- case XEN_FW_EFI_MEM_INFO:
- for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
- {
- EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
- u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
-
- if ( info->mem.addr >= desc->PhysicalStart &&
- info->mem.addr < desc->PhysicalStart + len )
- {
- info->mem.type = desc->Type;
- info->mem.attr = desc->Attribute;
- if ( info->mem.addr + info->mem.size < info->mem.addr ||
- info->mem.addr + info->mem.size >
- desc->PhysicalStart + len )
- info->mem.size = desc->PhysicalStart + len -
- info->mem.addr;
- return 0;
- }
- }
- return -ESRCH;
- case XEN_FW_EFI_PCI_ROM: {
- const struct efi_pci_rom *ent;
-
- for ( ent = efi_pci_roms; ent; ent = ent->next )
- if ( info->pci_rom.segment == ent->segment &&
- info->pci_rom.bus == ent->bus &&
- info->pci_rom.devfn == ent->devfn &&
- info->pci_rom.vendor == ent->vendor &&
- info->pci_rom.devid == ent->devid )
- {
- info->pci_rom.address = __pa(ent->data);
- info->pci_rom.size = ent->size;
- return 0;
- }
- return -ESRCH;
- }
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static long gwstrlen(XEN_GUEST_HANDLE_PARAM(CHAR16) str)
-{
- unsigned long len;
-
- for ( len = 0; ; ++len )
- {
- CHAR16 c;
-
- if ( copy_from_guest_offset(&c, str, len, 1) )
- return -EFAULT;
- if ( !c )
- break;
- }
-
- return len;
-}
-
-static inline EFI_TIME *cast_time(struct xenpf_efi_time *time)
-{
-#define chk_fld(F, f) \
- BUILD_BUG_ON(sizeof(cast_time(NULL)->F) != sizeof(time->f) || \
- offsetof(EFI_TIME, F) != offsetof(struct xenpf_efi_time, f))
- chk_fld(Year, year);
- chk_fld(Month, month);
- chk_fld(Day, day);
- chk_fld(Hour, hour);
- chk_fld(Minute, min);
- chk_fld(Second, sec);
- chk_fld(Nanosecond, ns);
- chk_fld(TimeZone, tz);
- chk_fld(Daylight, daylight);
-#undef chk_fld
- return (void *)time;
-}
-
-static inline EFI_GUID *cast_guid(struct xenpf_efi_guid *guid)
-{
-#define chk_fld(n) \
- BUILD_BUG_ON(sizeof(cast_guid(NULL)->Data##n) != sizeof(guid->data##n) || \
- offsetof(EFI_GUID, Data##n) != \
- offsetof(struct xenpf_efi_guid, data##n))
- chk_fld(1);
- chk_fld(2);
- chk_fld(3);
- chk_fld(4);
-#undef chk_fld
- return (void *)guid;
-}
-
-int efi_runtime_call(struct xenpf_efi_runtime_call *op)
-{
- unsigned long cr3, flags;
- EFI_STATUS status = EFI_NOT_STARTED;
- int rc = 0;
-
- switch ( op->function )
- {
- case XEN_EFI_get_time:
- {
- EFI_TIME_CAPABILITIES caps;
-
- if ( op->misc )
- return -EINVAL;
-
- cr3 = efi_rs_enter();
- spin_lock_irqsave(&rtc_lock, flags);
- status = efi_rs->GetTime(cast_time(&op->u.get_time.time), &caps);
- spin_unlock_irqrestore(&rtc_lock, flags);
- efi_rs_leave(cr3);
-
- if ( !EFI_ERROR(status) )
- {
- op->u.get_time.resolution = caps.Resolution;
- op->u.get_time.accuracy = caps.Accuracy;
- if ( caps.SetsToZero )
- op->misc = XEN_EFI_GET_TIME_SET_CLEARS_NS;
- }
- }
- break;
-
- case XEN_EFI_set_time:
- if ( op->misc )
- return -EINVAL;
-
- cr3 = efi_rs_enter();
- spin_lock_irqsave(&rtc_lock, flags);
- status = efi_rs->SetTime(cast_time(&op->u.set_time));
- spin_unlock_irqrestore(&rtc_lock, flags);
- efi_rs_leave(cr3);
- break;
-
- case XEN_EFI_get_wakeup_time:
- {
- BOOLEAN enabled, pending;
-
- if ( op->misc )
- return -EINVAL;
-
- cr3 = efi_rs_enter();
- spin_lock_irqsave(&rtc_lock, flags);
- status = efi_rs->GetWakeupTime(&enabled, &pending,
- cast_time(&op->u.get_wakeup_time));
- spin_unlock_irqrestore(&rtc_lock, flags);
- efi_rs_leave(cr3);
-
- if ( !EFI_ERROR(status) )
- {
- if ( enabled )
- op->misc |= XEN_EFI_GET_WAKEUP_TIME_ENABLED;
- if ( pending )
- op->misc |= XEN_EFI_GET_WAKEUP_TIME_PENDING;
- }
- }
- break;
-
- case XEN_EFI_set_wakeup_time:
- if ( op->misc & ~(XEN_EFI_SET_WAKEUP_TIME_ENABLE |
- XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY) )
- return -EINVAL;
-
- cr3 = efi_rs_enter();
- spin_lock_irqsave(&rtc_lock, flags);
- status = efi_rs->SetWakeupTime(!!(op->misc &
- XEN_EFI_SET_WAKEUP_TIME_ENABLE),
- (op->misc &
- XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY) ?
- NULL :
- cast_time(&op->u.set_wakeup_time));
- spin_unlock_irqrestore(&rtc_lock, flags);
- efi_rs_leave(cr3);
-
- op->misc = 0;
- break;
-
- case XEN_EFI_get_next_high_monotonic_count:
- if ( op->misc )
- return -EINVAL;
-
- cr3 = efi_rs_enter();
- status = efi_rs->GetNextHighMonotonicCount(&op->misc);
- efi_rs_leave(cr3);
- break;
-
- case XEN_EFI_get_variable:
- {
- CHAR16 *name;
- long len;
- unsigned char *data;
- UINTN size;
-
- if ( op->misc )
- return -EINVAL;
-
- len = gwstrlen(guest_handle_cast(op->u.get_variable.name, CHAR16));
- if ( len < 0 )
- return len;
- name = xmalloc_array(CHAR16, ++len);
- if ( !name )
- return -ENOMEM;
- __copy_from_guest(name, op->u.get_variable.name, len);
-
- size = op->u.get_variable.size;
- if ( size )
- {
- data = xmalloc_bytes(size);
- if ( !data )
- {
- xfree(name);
- return -ENOMEM;
- }
- }
- else
- data = NULL;
-
- cr3 = efi_rs_enter();
- status = efi_rs->GetVariable(
- name, cast_guid(&op->u.get_variable.vendor_guid),
- &op->misc, &size, data);
- efi_rs_leave(cr3);
-
- if ( !EFI_ERROR(status) &&
- copy_to_guest(op->u.get_variable.data, data, size) )
- rc = -EFAULT;
- op->u.get_variable.size = size;
-
- xfree(data);
- xfree(name);
- }
- break;
-
- case XEN_EFI_set_variable:
- {
- CHAR16 *name;
- long len;
- unsigned char *data;
-
- len = gwstrlen(guest_handle_cast(op->u.set_variable.name, CHAR16));
- if ( len < 0 )
- return len;
- name = xmalloc_array(CHAR16, ++len);
- if ( !name )
- return -ENOMEM;
- __copy_from_guest(name, op->u.set_variable.name, len);
-
- data = xmalloc_bytes(op->u.set_variable.size);
- if ( !data )
- rc = -ENOMEM;
- else if ( copy_from_guest(data, op->u.set_variable.data,
- op->u.set_variable.size) )
- rc = -EFAULT;
- else
- {
- cr3 = efi_rs_enter();
- status = efi_rs->SetVariable(
- name, cast_guid(&op->u.set_variable.vendor_guid),
- op->misc, op->u.set_variable.size, data);
- efi_rs_leave(cr3);
- }
-
- xfree(data);
- xfree(name);
- }
- break;
-
- case XEN_EFI_get_next_variable_name:
- {
- union {
- CHAR16 *str;
- unsigned char *raw;
- } name;
- UINTN size;
-
- if ( op->misc )
- return -EINVAL;
-
- size = op->u.get_next_variable_name.size;
- name.raw = xmalloc_bytes(size);
- if ( !name.raw )
- return -ENOMEM;
- if ( copy_from_guest(name.raw, op->u.get_next_variable_name.name,
- size) )
- {
- xfree(name.raw);
- return -EFAULT;
- }
-
- cr3 = efi_rs_enter();
- status = efi_rs->GetNextVariableName(
- &size, name.str,
- cast_guid(&op->u.get_next_variable_name.vendor_guid));
- efi_rs_leave(cr3);
-
- if ( !EFI_ERROR(status) &&
- copy_to_guest(op->u.get_next_variable_name.name, name.raw, size) )
- rc = -EFAULT;
- op->u.get_next_variable_name.size = size;
-
- xfree(name.raw);
- }
- break;
-
- case XEN_EFI_query_variable_info:
- if ( op->misc & ~XEN_EFI_VARINFO_BOOT_SNAPSHOT )
- return -EINVAL;
-
- if ( op->misc & XEN_EFI_VARINFO_BOOT_SNAPSHOT )
- {
- if ( (op->u.query_variable_info.attr
- & ~EFI_VARIABLE_APPEND_WRITE) !=
- (EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS) )
- return -EINVAL;
-
- op->u.query_variable_info.max_store_size =
- efi_boot_max_var_store_size;
- op->u.query_variable_info.remain_store_size =
- efi_boot_remain_var_store_size;
- if ( efi_boot_max_var_store_size )
- {
- op->u.query_variable_info.max_size = efi_boot_max_var_size;
- status = EFI_SUCCESS;
- }
- else
- {
- op->u.query_variable_info.max_size = 0;
- status = efi_boot_max_var_size;
- }
- break;
- }
-
- cr3 = efi_rs_enter();
- if ( (efi_rs->Hdr.Revision >> 16) < 2 )
- {
- efi_rs_leave(cr3);
- return -EOPNOTSUPP;
- }
- status = efi_rs->QueryVariableInfo(
- op->u.query_variable_info.attr,
- &op->u.query_variable_info.max_store_size,
- &op->u.query_variable_info.remain_store_size,
- &op->u.query_variable_info.max_size);
- efi_rs_leave(cr3);
- break;
-
- case XEN_EFI_query_capsule_capabilities:
- case XEN_EFI_update_capsule:
- if ( op->misc )
- return -EINVAL;
-
- cr3 = efi_rs_enter();
- if ( (efi_rs->Hdr.Revision >> 16) < 2 )
- {
- efi_rs_leave(cr3);
- return -EOPNOTSUPP;
- }
- efi_rs_leave(cr3);
- /* XXX fall through for now */
- default:
- return -ENOSYS;
- }
-
-#ifndef COMPAT
- op->status = status;
-#else
- op->status = (status & 0x3fffffff) | ((status >> 32) & 0xc0000000);
-#endif
-
- return rc;
-}
diff --git a/xen/arch/x86/efi/runtime.h b/xen/arch/x86/efi/runtime.h
new file mode 100644
index 0000000..0eb2fb9
--- /dev/null
+++ b/xen/arch/x86/efi/runtime.h
@@ -0,0 +1,5 @@
+#include <asm/mc146818rtc.h>
+
+#ifndef COMPAT
+l4_pgentry_t *__read_mostly efi_l4_pgtable;
+#endif
diff --git a/xen/arch/x86/efi/stub.c b/xen/arch/x86/efi/stub.c
index 8916a2e..b8f49f8 100644
--- a/xen/arch/x86/efi/stub.c
+++ b/xen/arch/x86/efi/stub.c
@@ -9,6 +9,12 @@ const bool_t efi_enabled = 0;
void __init efi_init_memory(void) { }
+paddr_t efi_rs_page_table(void)
+{
+ BUG();
+ return 0;
+}
+
unsigned long efi_get_time(void)
{
BUG();
diff --git a/xen/arch/x86/flushtlb.c b/xen/arch/x86/flushtlb.c
index 1b75652..5d5d79c 100644
--- a/xen/arch/x86/flushtlb.c
+++ b/xen/arch/x86/flushtlb.c
@@ -72,7 +72,7 @@ static void post_flush(u32 t)
void write_cr3(unsigned long cr3)
{
- unsigned long flags;
+ unsigned long flags, cr4 = read_cr4();
u32 t;
/* This non-reentrant function is sometimes called in interrupt context. */
@@ -82,16 +82,9 @@ void write_cr3(unsigned long cr3)
hvm_flush_guest_tlbs();
-#ifdef USER_MAPPINGS_ARE_GLOBAL
- {
- unsigned long cr4 = read_cr4();
- write_cr4(cr4 & ~X86_CR4_PGE);
- asm volatile ( "mov %0, %%cr3" : : "r" (cr3) : "memory" );
- write_cr4(cr4);
- }
-#else
+ write_cr4(cr4 & ~X86_CR4_PGE);
asm volatile ( "mov %0, %%cr3" : : "r" (cr3) : "memory" );
-#endif
+ write_cr4(cr4);
post_flush(t);
@@ -123,23 +116,13 @@ void flush_area_local(const void *va, unsigned int flags)
else
{
u32 t = pre_flush();
+ unsigned long cr4 = read_cr4();
hvm_flush_guest_tlbs();
-#ifndef USER_MAPPINGS_ARE_GLOBAL
- if ( !(flags & FLUSH_TLB_GLOBAL) || !(read_cr4() & X86_CR4_PGE) )
- {
- asm volatile ( "mov %0, %%cr3"
- : : "r" (read_cr3()) : "memory" );
- }
- else
-#endif
- {
- unsigned long cr4 = read_cr4();
- write_cr4(cr4 & ~X86_CR4_PGE);
- barrier();
- write_cr4(cr4);
- }
+ write_cr4(cr4 & ~X86_CR4_PGE);
+ barrier();
+ write_cr4(cr4);
post_flush(t);
}
diff --git a/xen/arch/x86/genapic/x2apic.c b/xen/arch/x86/genapic/x2apic.c
index b2cab03..9a3cfd9 100644
--- a/xen/arch/x86/genapic/x2apic.c
+++ b/xen/arch/x86/genapic/x2apic.c
@@ -92,6 +92,11 @@ static unsigned int cpu_mask_to_apicid_x2apic_cluster(const cpumask_t *cpumask)
return dest;
}
+static void send_IPI_self_x2apic(uint8_t vector)
+{
+ apic_wrmsr(APIC_SELF_IPI, vector);
+}
+
static void send_IPI_mask_x2apic_phys(const cpumask_t *cpumask, int vector)
{
unsigned int cpu;
diff --git a/xen/arch/x86/hpet.c b/xen/arch/x86/hpet.c
index 3a4f7e8..0b13f52 100644
--- a/xen/arch/x86/hpet.c
+++ b/xen/arch/x86/hpet.c
@@ -355,7 +355,7 @@ static int __init hpet_setup_msi_irq(struct hpet_event_channel *ch)
hpet_write32(cfg, HPET_Tn_CFG(ch->idx));
desc->handler = &hpet_msi_type;
- ret = request_irq(ch->msi.irq, hpet_interrupt_handler, "HPET", ch);
+ ret = request_irq(ch->msi.irq, 0, hpet_interrupt_handler, "HPET", ch);
if ( ret >= 0 )
ret = __hpet_setup_msi_irq(desc);
if ( ret < 0 )
diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index 868aa1d..14c1847 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -21,6 +21,7 @@
#include <asm/hvm/hvm.h>
#include <asm/hvm/trace.h>
#include <asm/hvm/support.h>
+#include <asm/hvm/svm/svm.h>
static void hvmtrace_io_assist(int is_mmio, ioreq_t *p)
{
@@ -53,28 +54,21 @@ static int hvmemul_do_io(
int is_mmio, paddr_t addr, unsigned long *reps, int size,
paddr_t ram_gpa, int dir, int df, void *p_data)
{
- paddr_t value = ram_gpa;
- int value_is_ptr = (p_data == NULL);
struct vcpu *curr = current;
struct hvm_vcpu_io *vio;
- ioreq_t *p = get_ioreq(curr);
- ioreq_t _ioreq;
+ ioreq_t p = {
+ .type = is_mmio ? IOREQ_TYPE_COPY : IOREQ_TYPE_PIO,
+ .addr = addr,
+ .size = size,
+ .dir = dir,
+ .df = df,
+ .data = ram_gpa,
+ .data_is_ptr = (p_data == NULL),
+ };
unsigned long ram_gfn = paddr_to_pfn(ram_gpa);
p2m_type_t p2mt;
struct page_info *ram_page;
int rc;
- bool_t has_dm = 1;
-
- /*
- * Domains without a backing DM, don't have an ioreq page. Just
- * point to a struct on the stack, initialising the state as needed.
- */
- if ( !p )
- {
- has_dm = 0;
- p = &_ioreq;
- p->state = STATE_IOREQ_NONE;
- }
/* Check for paged out page */
ram_page = get_page_from_gfn(curr->domain, ram_gfn, &p2mt, P2M_UNSHARE);
@@ -107,15 +101,15 @@ static int hvmemul_do_io(
return X86EMUL_UNHANDLEABLE;
}
- if ( (p_data != NULL) && (dir == IOREQ_WRITE) )
+ if ( !p.data_is_ptr && (dir == IOREQ_WRITE) )
{
- memcpy(&value, p_data, size);
+ memcpy(&p.data, p_data, size);
p_data = NULL;
}
vio = &curr->arch.hvm_vcpu.hvm_io;
- if ( is_mmio && !value_is_ptr )
+ if ( is_mmio && !p.data_is_ptr )
{
/* Part of a multi-cycle read or write? */
if ( dir == IOREQ_WRITE )
@@ -159,7 +153,7 @@ static int hvmemul_do_io(
goto finish_access;
case HVMIO_dispatched:
/* May have to wait for previous cycle of a multi-write to complete. */
- if ( is_mmio && !value_is_ptr && (dir == IOREQ_WRITE) &&
+ if ( is_mmio && !p.data_is_ptr && (dir == IOREQ_WRITE) &&
(addr == (vio->mmio_large_write_pa +
vio->mmio_large_write_bytes)) )
{
@@ -173,10 +167,9 @@ static int hvmemul_do_io(
return X86EMUL_UNHANDLEABLE;
}
- if ( p->state != STATE_IOREQ_NONE )
+ if ( hvm_io_pending(curr) )
{
- gdprintk(XENLOG_WARNING, "WARNING: io already pending (%d)?\n",
- p->state);
+ gdprintk(XENLOG_WARNING, "WARNING: io already pending?\n");
if ( ram_page )
put_page(ram_page);
return X86EMUL_UNHANDLEABLE;
@@ -193,38 +186,31 @@ static int hvmemul_do_io(
if ( vio->mmio_retrying )
*reps = 1;
- p->dir = dir;
- p->data_is_ptr = value_is_ptr;
- p->type = is_mmio ? IOREQ_TYPE_COPY : IOREQ_TYPE_PIO;
- p->size = size;
- p->addr = addr;
- p->count = *reps;
- p->df = df;
- p->data = value;
+ p.count = *reps;
if ( dir == IOREQ_WRITE )
- hvmtrace_io_assist(is_mmio, p);
+ hvmtrace_io_assist(is_mmio, &p);
if ( is_mmio )
{
- rc = hvm_mmio_intercept(p);
+ rc = hvm_mmio_intercept(&p);
if ( rc == X86EMUL_UNHANDLEABLE )
- rc = hvm_buffered_io_intercept(p);
+ rc = hvm_buffered_io_intercept(&p);
}
else
{
- rc = hvm_portio_intercept(p);
+ rc = hvm_portio_intercept(&p);
}
switch ( rc )
{
case X86EMUL_OKAY:
case X86EMUL_RETRY:
- *reps = p->count;
- p->state = STATE_IORESP_READY;
+ *reps = p.count;
+ p.state = STATE_IORESP_READY;
if ( !vio->mmio_retry )
{
- hvm_io_assist(p);
+ hvm_io_assist(&p);
vio->io_state = HVMIO_none;
}
else
@@ -233,7 +219,7 @@ static int hvmemul_do_io(
break;
case X86EMUL_UNHANDLEABLE:
/* If there is no backing DM, just ignore accesses */
- if ( !has_dm )
+ if ( !hvm_has_dm(curr->domain) )
{
rc = X86EMUL_OKAY;
vio->io_state = HVMIO_none;
@@ -241,7 +227,7 @@ static int hvmemul_do_io(
else
{
rc = X86EMUL_RETRY;
- if ( !hvm_send_assist_req(curr) )
+ if ( !hvm_send_assist_req(&p) )
vio->io_state = HVMIO_none;
else if ( p_data == NULL )
rc = X86EMUL_OKAY;
@@ -260,12 +246,12 @@ static int hvmemul_do_io(
finish_access:
if ( dir == IOREQ_READ )
- hvmtrace_io_assist(is_mmio, p);
+ hvmtrace_io_assist(is_mmio, &p);
if ( p_data != NULL )
memcpy(p_data, &vio->io_data, size);
- if ( is_mmio && !value_is_ptr )
+ if ( is_mmio && !p.data_is_ptr )
{
/* Part of a multi-cycle read or write? */
if ( dir == IOREQ_WRITE )
@@ -420,8 +406,13 @@ static int hvmemul_virtual_to_linear(
* Clip repetitions to avoid overflow when multiplying by @bytes_per_rep.
* The chosen maximum is very conservative but it's what we use in
* hvmemul_linear_to_phys() so there is no point in using a larger value.
+ * If introspection has been enabled for this domain, *reps should be
+ * at most 1, since optimization might otherwise cause a single mem_event
+ * being triggered for repeated writes to a whole page.
*/
- *reps = min_t(unsigned long, *reps, 4096);
+ *reps = min_t(unsigned long, *reps,
+ unlikely(current->domain->arch.hvm_domain.introspection_enabled)
+ ? 1 : 4096);
reg = hvmemul_get_seg_reg(seg, hvmemul_ctxt);
@@ -456,9 +447,10 @@ static int hvmemul_virtual_to_linear(
/* This is a singleton operation: fail it with an exception. */
hvmemul_ctxt->exn_pending = 1;
- hvmemul_ctxt->exn_vector = TRAP_gp_fault;
- hvmemul_ctxt->exn_error_code = 0;
- hvmemul_ctxt->exn_insn_len = 0;
+ hvmemul_ctxt->trap.vector = TRAP_gp_fault;
+ hvmemul_ctxt->trap.type = X86_EVENTTYPE_HW_EXCEPTION;
+ hvmemul_ctxt->trap.error_code = 0;
+ hvmemul_ctxt->trap.insn_len = 0;
return X86EMUL_EXCEPTION;
}
@@ -496,10 +488,11 @@ static int __hvmemul_read(
while ( off & (chunk - 1) )
chunk >>= 1;
- if ( unlikely(vio->mmio_gva == (addr & PAGE_MASK)) && vio->mmio_gva )
+ if ( ((access_type != hvm_access_insn_fetch
+ ? vio->mmio_access.read_access
+ : vio->mmio_access.insn_fetch)) &&
+ (vio->mmio_gva == (addr & PAGE_MASK)) )
{
- if ( access_type == hvm_access_insn_fetch )
- return X86EMUL_UNHANDLEABLE;
gpa = (((paddr_t)vio->mmio_gpfn << PAGE_SHIFT) | off);
while ( (off + chunk) <= PAGE_SIZE )
{
@@ -639,7 +632,8 @@ static int hvmemul_write(
while ( off & (chunk - 1) )
chunk >>= 1;
- if ( unlikely(vio->mmio_gva == (addr & PAGE_MASK)) && vio->mmio_gva )
+ if ( vio->mmio_access.write_access &&
+ (vio->mmio_gva == (addr & PAGE_MASK)) )
{
gpa = (((paddr_t)vio->mmio_gpfn << PAGE_SHIFT) | off);
while ( (off + chunk) <= PAGE_SIZE )
@@ -703,6 +697,94 @@ static int hvmemul_write(
return X86EMUL_OKAY;
}
+static int hvmemul_write_discard(
+ enum x86_segment seg,
+ unsigned long offset,
+ void *p_data,
+ unsigned int bytes,
+ struct x86_emulate_ctxt *ctxt)
+{
+ /* Discarding the write. */
+ return X86EMUL_OKAY;
+}
+
+static int hvmemul_rep_ins_discard(
+ uint16_t src_port,
+ enum x86_segment dst_seg,
+ unsigned long dst_offset,
+ unsigned int bytes_per_rep,
+ unsigned long *reps,
+ struct x86_emulate_ctxt *ctxt)
+{
+ return X86EMUL_OKAY;
+}
+
+static int hvmemul_rep_movs_discard(
+ enum x86_segment src_seg,
+ unsigned long src_offset,
+ enum x86_segment dst_seg,
+ unsigned long dst_offset,
+ unsigned int bytes_per_rep,
+ unsigned long *reps,
+ struct x86_emulate_ctxt *ctxt)
+{
+ return X86EMUL_OKAY;
+}
+
+static int hvmemul_rep_outs_discard(
+ enum x86_segment src_seg,
+ unsigned long src_offset,
+ uint16_t dst_port,
+ unsigned int bytes_per_rep,
+ unsigned long *reps,
+ struct x86_emulate_ctxt *ctxt)
+{
+ return X86EMUL_OKAY;
+}
+
+static int hvmemul_cmpxchg_discard(
+ enum x86_segment seg,
+ unsigned long offset,
+ void *p_old,
+ void *p_new,
+ unsigned int bytes,
+ struct x86_emulate_ctxt *ctxt)
+{
+ return X86EMUL_OKAY;
+}
+
+static int hvmemul_read_io_discard(
+ unsigned int port,
+ unsigned int bytes,
+ unsigned long *val,
+ struct x86_emulate_ctxt *ctxt)
+{
+ return X86EMUL_OKAY;
+}
+
+static int hvmemul_write_io_discard(
+ unsigned int port,
+ unsigned int bytes,
+ unsigned long val,
+ struct x86_emulate_ctxt *ctxt)
+{
+ return X86EMUL_OKAY;
+}
+
+static int hvmemul_write_msr_discard(
+ unsigned long reg,
+ uint64_t val,
+ struct x86_emulate_ctxt *ctxt)
+{
+ return X86EMUL_OKAY;
+}
+
+static int hvmemul_wbinvd_discard(
+ struct x86_emulate_ctxt *ctxt)
+{
+ return X86EMUL_OKAY;
+}
+
static int hvmemul_cmpxchg(
enum x86_segment seg,
unsigned long offset,
@@ -1036,14 +1118,16 @@ static int hvmemul_inject_hw_exception(
container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
hvmemul_ctxt->exn_pending = 1;
- hvmemul_ctxt->exn_vector = vector;
- hvmemul_ctxt->exn_error_code = error_code;
- hvmemul_ctxt->exn_insn_len = 0;
+ hvmemul_ctxt->trap.vector = vector;
+ hvmemul_ctxt->trap.type = X86_EVENTTYPE_HW_EXCEPTION;
+ hvmemul_ctxt->trap.error_code = error_code;
+ hvmemul_ctxt->trap.insn_len = 0;
return X86EMUL_OKAY;
}
static int hvmemul_inject_sw_interrupt(
+ enum x86_swint_type type,
uint8_t vector,
uint8_t insn_len,
struct x86_emulate_ctxt *ctxt)
@@ -1051,10 +1135,29 @@ static int hvmemul_inject_sw_interrupt(
struct hvm_emulate_ctxt *hvmemul_ctxt =
container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
+ switch ( type )
+ {
+ case x86_swint_icebp:
+ hvmemul_ctxt->trap.type = X86_EVENTTYPE_PRI_SW_EXCEPTION;
+ break;
+
+ case x86_swint_int3:
+ case x86_swint_into:
+ hvmemul_ctxt->trap.type = X86_EVENTTYPE_SW_EXCEPTION;
+ break;
+
+ case x86_swint_int:
+ hvmemul_ctxt->trap.type = X86_EVENTTYPE_SW_INTERRUPT;
+ break;
+
+ default:
+ return X86EMUL_UNHANDLEABLE;
+ }
+
hvmemul_ctxt->exn_pending = 1;
- hvmemul_ctxt->exn_vector = vector;
- hvmemul_ctxt->exn_error_code = -1;
- hvmemul_ctxt->exn_insn_len = insn_len;
+ hvmemul_ctxt->trap.vector = vector;
+ hvmemul_ctxt->trap.error_code = HVM_DELIVER_NO_ERROR_CODE;
+ hvmemul_ctxt->trap.insn_len = insn_len;
return X86EMUL_OKAY;
}
@@ -1153,8 +1256,33 @@ static const struct x86_emulate_ops hvm_emulate_ops = {
.invlpg = hvmemul_invlpg
};
-int hvm_emulate_one(
- struct hvm_emulate_ctxt *hvmemul_ctxt)
+static const struct x86_emulate_ops hvm_emulate_ops_no_write = {
+ .read = hvmemul_read,
+ .insn_fetch = hvmemul_insn_fetch,
+ .write = hvmemul_write_discard,
+ .cmpxchg = hvmemul_cmpxchg_discard,
+ .rep_ins = hvmemul_rep_ins_discard,
+ .rep_outs = hvmemul_rep_outs_discard,
+ .rep_movs = hvmemul_rep_movs_discard,
+ .read_segment = hvmemul_read_segment,
+ .write_segment = hvmemul_write_segment,
+ .read_io = hvmemul_read_io_discard,
+ .write_io = hvmemul_write_io_discard,
+ .read_cr = hvmemul_read_cr,
+ .write_cr = hvmemul_write_cr,
+ .read_msr = hvmemul_read_msr,
+ .write_msr = hvmemul_write_msr_discard,
+ .wbinvd = hvmemul_wbinvd_discard,
+ .cpuid = hvmemul_cpuid,
+ .inject_hw_exception = hvmemul_inject_hw_exception,
+ .inject_sw_interrupt = hvmemul_inject_sw_interrupt,
+ .get_fpu = hvmemul_get_fpu,
+ .put_fpu = hvmemul_put_fpu,
+ .invlpg = hvmemul_invlpg
+};
+
+static int _hvm_emulate_one(struct hvm_emulate_ctxt *hvmemul_ctxt,
+ const struct x86_emulate_ops *ops)
{
struct cpu_user_regs *regs = hvmemul_ctxt->ctxt.regs;
struct vcpu *curr = current;
@@ -1206,7 +1334,14 @@ int hvm_emulate_one(
vio->mmio_retrying = vio->mmio_retry;
vio->mmio_retry = 0;
- rc = x86_emulate(&hvmemul_ctxt->ctxt, &hvm_emulate_ops);
+ if ( cpu_has_vmx )
+ hvmemul_ctxt->ctxt.swint_emulate = x86_swint_emulate_none;
+ else if ( cpu_has_svm_nrips )
+ hvmemul_ctxt->ctxt.swint_emulate = x86_swint_emulate_icebp;
+ else
+ hvmemul_ctxt->ctxt.swint_emulate = x86_swint_emulate_all;
+
+ rc = x86_emulate(&hvmemul_ctxt->ctxt, ops);
if ( rc == X86EMUL_OKAY && vio->mmio_retry )
rc = X86EMUL_RETRY;
@@ -1254,6 +1389,54 @@ int hvm_emulate_one(
return X86EMUL_OKAY;
}
+int hvm_emulate_one(
+ struct hvm_emulate_ctxt *hvmemul_ctxt)
+{
+ return _hvm_emulate_one(hvmemul_ctxt, &hvm_emulate_ops);
+}
+
+int hvm_emulate_one_no_write(
+ struct hvm_emulate_ctxt *hvmemul_ctxt)
+{
+ return _hvm_emulate_one(hvmemul_ctxt, &hvm_emulate_ops_no_write);
+}
+
+void hvm_mem_event_emulate_one(bool_t nowrite, unsigned int trapnr,
+ unsigned int errcode)
+{
+ struct hvm_emulate_ctxt ctx = {{ 0 }};
+ int rc;
+
+ hvm_emulate_prepare(&ctx, guest_cpu_user_regs());
+
+ if ( nowrite )
+ rc = hvm_emulate_one_no_write(&ctx);
+ else
+ rc = hvm_emulate_one(&ctx);
+
+ switch ( rc )
+ {
+ case X86EMUL_RETRY:
+ /*
+ * This function is called when handling an EPT-related mem_event
+ * reply. As such, nothing else needs to be done here, since simply
+ * returning makes the current instruction cause a page fault again,
+ * consistent with X86EMUL_RETRY.
+ */
+ return;
+ case X86EMUL_UNHANDLEABLE:
+ hvm_dump_emulation_state(XENLOG_G_DEBUG "Mem event", &ctx);
+ hvm_inject_hw_exception(trapnr, errcode);
+ break;
+ case X86EMUL_EXCEPTION:
+ if ( ctx.exn_pending )
+ hvm_inject_trap(&ctx.trap);
+ break;
+ }
+
+ hvm_emulate_writeback(&ctx);
+}
+
void hvm_emulate_prepare(
struct hvm_emulate_ctxt *hvmemul_ctxt,
struct cpu_user_regs *regs)
@@ -1292,3 +1475,39 @@ struct segment_register *hvmemul_get_seg_reg(
hvm_get_segment_register(current, seg, &hvmemul_ctxt->seg_reg[seg]);
return &hvmemul_ctxt->seg_reg[seg];
}
+
+static const char *guest_x86_mode_to_str(int mode)
+{
+ switch ( mode )
+ {
+ case 0: return "Real";
+ case 1: return "v86";
+ case 2: return "16bit";
+ case 4: return "32bit";
+ case 8: return "64bit";
+ default: return "Unknown";
+ }
+}
+
+void hvm_dump_emulation_state(const char *prefix,
+ struct hvm_emulate_ctxt *hvmemul_ctxt)
+{
+ struct vcpu *curr = current;
+ const char *mode_str = guest_x86_mode_to_str(hvm_guest_x86_mode(curr));
+ const struct segment_register *cs =
+ hvmemul_get_seg_reg(x86_seg_cs, hvmemul_ctxt);
+
+ printk("%s emulation failed: %pv %s @ %04x:%08lx -> %*ph\n",
+ prefix, curr, mode_str, cs->sel, hvmemul_ctxt->insn_buf_eip,
+ hvmemul_ctxt->insn_buf_bytes, hvmemul_ctxt->insn_buf);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c
index 4324b52..bdfc6fc 100644
--- a/xen/arch/x86/hvm/hpet.c
+++ b/xen/arch/x86/hvm/hpet.c
@@ -20,10 +20,12 @@
#include <asm/hvm/vpt.h>
#include <asm/hvm/io.h>
#include <asm/hvm/support.h>
+#include <asm/hvm/trace.h>
#include <asm/current.h>
#include <asm/hpet.h>
#include <xen/sched.h>
#include <xen/event.h>
+#include <xen/trace.h>
#define domain_vhpet(x) (&(x)->arch.hvm_domain.pl_time.vhpet)
#define vcpu_vhpet(x) (domain_vhpet((x)->domain))
@@ -73,31 +75,37 @@
((timer_config(h, n) & HPET_TN_INT_ROUTE_CAP_MASK) \
>> HPET_TN_INT_ROUTE_CAP_SHIFT)
-static inline uint64_t hpet_read_maincounter(HPETState *h)
+static inline uint64_t hpet_read_maincounter(HPETState *h, uint64_t guest_time)
{
- ASSERT(spin_is_locked(&h->lock));
+ ASSERT(rw_is_locked(&h->lock));
if ( hpet_enabled(h) )
- return guest_time_hpet(h) + h->mc_offset;
+ return guest_time + h->mc_offset;
else
return h->hpet.mc64;
}
-static uint64_t hpet_get_comparator(HPETState *h, unsigned int tn)
+static uint64_t hpet_get_comparator(HPETState *h, unsigned int tn,
+ uint64_t guest_time)
{
uint64_t comparator;
uint64_t elapsed;
+ ASSERT(rw_is_write_locked(&h->lock));
+
comparator = h->hpet.comparator64[tn];
- if ( timer_is_periodic(h, tn) )
+ if ( hpet_enabled(h) && timer_is_periodic(h, tn) )
{
/* update comparator by number of periods elapsed since last update */
uint64_t period = h->hpet.period[tn];
if (period)
{
- elapsed = hpet_read_maincounter(h) + period - 1 - comparator;
- comparator += (elapsed / period) * period;
- h->hpet.comparator64[tn] = comparator;
+ elapsed = hpet_read_maincounter(h, guest_time) - comparator;
+ if ( (int64_t)elapsed >= 0 )
+ {
+ comparator += ((elapsed + period) / period) * period;
+ h->hpet.comparator64[tn] = comparator;
+ }
}
}
@@ -107,7 +115,8 @@ static uint64_t hpet_get_comparator(HPETState *h, unsigned int tn)
h->hpet.timers[tn].cmp = comparator;
return comparator;
}
-static inline uint64_t hpet_read64(HPETState *h, unsigned long addr)
+static inline uint64_t hpet_read64(HPETState *h, unsigned long addr,
+ uint64_t guest_time)
{
addr &= ~7;
@@ -120,7 +129,7 @@ static inline uint64_t hpet_read64(HPETState *h, unsigned long addr)
case HPET_STATUS:
return h->hpet.isr;
case HPET_COUNTER:
- return hpet_read_maincounter(h);
+ return hpet_read_maincounter(h, guest_time);
case HPET_Tn_CFG(0):
case HPET_Tn_CFG(1):
case HPET_Tn_CFG(2):
@@ -128,7 +137,7 @@ static inline uint64_t hpet_read64(HPETState *h, unsigned long addr)
case HPET_Tn_CMP(0):
case HPET_Tn_CMP(1):
case HPET_Tn_CMP(2):
- return hpet_get_comparator(h, HPET_TN(CMP, addr));
+ return hpet_get_comparator(h, HPET_TN(CMP, addr), guest_time);
case HPET_Tn_ROUTE(0):
case HPET_Tn_ROUTE(1):
case HPET_Tn_ROUTE(2):
@@ -172,43 +181,54 @@ static int hpet_read(
goto out;
}
- spin_lock(&h->lock);
+ result = addr < HPET_Tn_CMP(0) ||
+ ((addr - HPET_Tn_CMP(0)) % (HPET_Tn_CMP(1) - HPET_Tn_CMP(0))) > 7;
+ if ( result )
+ read_lock(&h->lock);
+ else
+ write_lock(&h->lock);
+
+ val = hpet_read64(h, addr, guest_time_hpet(h));
- val = hpet_read64(h, addr);
+ if ( result )
+ read_unlock(&h->lock);
+ else
+ write_unlock(&h->lock);
result = val;
if ( length != 8 )
result = (val >> ((addr & 7) * 8)) & ((1ULL << (length * 8)) - 1);
- spin_unlock(&h->lock);
-
out:
*pval = result;
return X86EMUL_OKAY;
}
-static void hpet_stop_timer(HPETState *h, unsigned int tn)
+static void hpet_stop_timer(HPETState *h, unsigned int tn,
+ uint64_t guest_time)
{
ASSERT(tn < HPET_TIMER_NUM);
- ASSERT(spin_is_locked(&h->lock));
+ ASSERT(rw_is_write_locked(&h->lock));
+ TRACE_1D(TRC_HVM_EMUL_HPET_STOP_TIMER, tn);
destroy_periodic_time(&h->pt[tn]);
/* read the comparator to get it updated so a read while stopped will
* return the expected value. */
- hpet_get_comparator(h, tn);
+ hpet_get_comparator(h, tn, guest_time);
}
/* the number of HPET tick that stands for
* 1/(2^10) second, namely, 0.9765625 milliseconds */
#define HPET_TINY_TIME_SPAN ((h->stime_freq >> 10) / STIME_PER_HPET_TICK)
-static void hpet_set_timer(HPETState *h, unsigned int tn)
+static void hpet_set_timer(HPETState *h, unsigned int tn,
+ uint64_t guest_time)
{
uint64_t tn_cmp, cur_tick, diff;
unsigned int irq;
unsigned int oneshot;
ASSERT(tn < HPET_TIMER_NUM);
- ASSERT(spin_is_locked(&h->lock));
+ ASSERT(rw_is_write_locked(&h->lock));
if ( (tn == 0) && (h->hpet.config & HPET_CFG_LEGACY) )
{
@@ -220,8 +240,8 @@ static void hpet_set_timer(HPETState *h, unsigned int tn)
if ( !timer_enabled(h, tn) )
return;
- tn_cmp = hpet_get_comparator(h, tn);
- cur_tick = hpet_read_maincounter(h);
+ tn_cmp = hpet_get_comparator(h, tn, guest_time);
+ cur_tick = hpet_read_maincounter(h, guest_time);
if ( timer_is_32bit(h, tn) )
{
tn_cmp = (uint32_t)tn_cmp;
@@ -255,6 +275,10 @@ static void hpet_set_timer(HPETState *h, unsigned int tn)
* being enabled (now).
*/
oneshot = !timer_is_periodic(h, tn);
+ TRACE_2_LONG_4D(TRC_HVM_EMUL_HPET_START_TIMER, tn, irq,
+ TRC_PAR_LONG(hpet_tick_to_ns(h, diff)),
+ TRC_PAR_LONG(oneshot ? 0LL :
+ hpet_tick_to_ns(h, h->hpet.period[tn])));
create_periodic_time(vhpet_vcpu(h), &h->pt[tn],
hpet_tick_to_ns(h, diff),
oneshot ? 0 : hpet_tick_to_ns(h, h->hpet.period[tn]),
@@ -275,6 +299,7 @@ static int hpet_write(
{
HPETState *h = vcpu_vhpet(v);
uint64_t old_val, new_val;
+ uint64_t guest_time;
int tn, i;
/* Acculumate a bit mask of timers whos state is changed by this write. */
@@ -289,9 +314,10 @@ static int hpet_write(
if ( hpet_check_access_length(addr, length) != 0 )
goto out;
- spin_lock(&h->lock);
+ write_lock(&h->lock);
- old_val = hpet_read64(h, addr);
+ guest_time = guest_time_hpet(h);
+ old_val = hpet_read64(h, addr, guest_time);
new_val = val;
if ( length != 8 )
new_val = hpet_fixup_reg(
@@ -306,7 +332,7 @@ static int hpet_write(
if ( !(old_val & HPET_CFG_ENABLE) && (new_val & HPET_CFG_ENABLE) )
{
/* Enable main counter and interrupt generation. */
- h->mc_offset = h->hpet.mc64 - guest_time_hpet(h);
+ h->mc_offset = h->hpet.mc64 - guest_time;
for ( i = 0; i < HPET_TIMER_NUM; i++ )
{
h->hpet.comparator64[i] =
@@ -320,7 +346,7 @@ static int hpet_write(
else if ( (old_val & HPET_CFG_ENABLE) && !(new_val & HPET_CFG_ENABLE) )
{
/* Halt main counter and disable interrupt generation. */
- h->hpet.mc64 = h->mc_offset + guest_time_hpet(h);
+ h->hpet.mc64 = h->mc_offset + guest_time;
for ( i = 0; i < HPET_TIMER_NUM; i++ )
if ( timer_enabled(h, i) )
set_stop_timer(i);
@@ -387,21 +413,11 @@ static int hpet_write(
case HPET_Tn_CMP(1):
case HPET_Tn_CMP(2):
tn = HPET_TN(CMP, addr);
- if ( timer_is_32bit(h, tn) )
- new_val = (uint32_t)new_val;
- h->hpet.timers[tn].cmp = new_val;
- if ( h->hpet.timers[tn].config & HPET_TN_SETVAL )
- /*
- * When SETVAL is one, software is able to "directly set a periodic
- * timer's accumulator." That is, set the comparator without
- * adjusting the period. Much the same as just setting the
- * comparator on an enabled one-shot timer.
- *
- * This configuration bit clears when the comparator is written.
- */
- h->hpet.timers[tn].config &= ~HPET_TN_SETVAL;
- else if ( timer_is_periodic(h, tn) )
+ if ( timer_is_periodic(h, tn) &&
+ !(h->hpet.timers[tn].config & HPET_TN_SETVAL) )
{
+ uint64_t max_period = (timer_is_32bit(h, tn) ? ~0u : ~0ull) >> 1;
+
/*
* Clamp period to reasonable min/max values:
* - minimum is 100us, same as timers controlled by vpt.c
@@ -409,10 +425,29 @@ static int hpet_write(
*/
if ( hpet_tick_to_ns(h, new_val) < MICROSECS(100) )
new_val = (MICROSECS(100) << 10) / h->hpet_to_ns_scale;
- new_val &= (timer_is_32bit(h, tn) ? ~0u : ~0ull) >> 1;
+ if ( new_val > max_period )
+ new_val = max_period;
h->hpet.period[tn] = new_val;
}
- h->hpet.comparator64[tn] = new_val;
+ else
+ {
+ /*
+ * When SETVAL is one, software is able to "directly set
+ * a periodic timer's accumulator." That is, set the
+ * comparator without adjusting the period. Much the
+ * same as just setting the comparator on an enabled
+ * one-shot timer.
+ *
+ * This configuration bit clears when the comparator is
+ * written.
+ */
+ h->hpet.timers[tn].config &= ~HPET_TN_SETVAL;
+ h->hpet.comparator64[tn] = new_val;
+ /* truncate if timer is in 32 bit mode */
+ if ( timer_is_32bit(h, tn) )
+ new_val = (uint32_t)new_val;
+ h->hpet.timers[tn].cmp = new_val;
+ }
if ( hpet_enabled(h) && timer_enabled(h, tn) )
set_restart_timer(tn);
break;
@@ -434,21 +469,21 @@ static int hpet_write(
{
i = find_first_set_bit(stop_timers);
__clear_bit(i, &stop_timers);
- hpet_stop_timer(h, i);
+ hpet_stop_timer(h, i, guest_time);
}
while (start_timers)
{
i = find_first_set_bit(start_timers);
__clear_bit(i, &start_timers);
- hpet_set_timer(h, i);
+ hpet_set_timer(h, i, guest_time);
}
#undef set_stop_timer
#undef set_start_timer
#undef set_restart_timer
- spin_unlock(&h->lock);
+ write_unlock(&h->lock);
out:
return X86EMUL_OKAY;
@@ -472,11 +507,14 @@ static int hpet_save(struct domain *d, hvm_domain_context_t *h)
{
HPETState *hp = domain_vhpet(d);
int rc;
+ uint64_t guest_time;
- spin_lock(&hp->lock);
+ write_lock(&hp->lock);
+ guest_time = guest_time_hpet(hp);
/* Write the proper value into the main counter */
- hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp);
+ if ( hpet_enabled(hp) )
+ hp->hpet.mc64 = hp->mc_offset + guest_time;
/* Save the HPET registers */
rc = _hvm_init_entry(h, HVM_SAVE_CODE(HPET), 0, HVM_SAVE_LENGTH(HPET));
@@ -500,14 +538,24 @@ static int hpet_save(struct domain *d, hvm_domain_context_t *h)
C(period[1]);
C(period[2]);
#undef C
- /* save the 64 bit comparator in the 64 bit timer[n].cmp field
- * regardless of whether or not the timer is in 32 bit mode. */
+ /*
+ * read the comparator to get it updated so hpet_save will
+ * return the expected value.
+ */
+ hpet_get_comparator(hp, 0, guest_time);
+ hpet_get_comparator(hp, 1, guest_time);
+ hpet_get_comparator(hp, 2, guest_time);
+ /*
+ * save the 64 bit comparator in the 64 bit timer[n].cmp
+ * field regardless of whether or not the timer is in 32 bit
+ * mode.
+ */
rec->timers[0].cmp = hp->hpet.comparator64[0];
rec->timers[1].cmp = hp->hpet.comparator64[1];
rec->timers[2].cmp = hp->hpet.comparator64[2];
}
- spin_unlock(&hp->lock);
+ write_unlock(&hp->lock);
return rc;
}
@@ -517,14 +565,15 @@ static int hpet_load(struct domain *d, hvm_domain_context_t *h)
HPETState *hp = domain_vhpet(d);
struct hvm_hw_hpet *rec;
uint64_t cmp;
+ uint64_t guest_time;
int i;
- spin_lock(&hp->lock);
+ write_lock(&hp->lock);
/* Reload the HPET registers */
if ( _hvm_check_entry(h, HVM_SAVE_CODE(HPET), HVM_SAVE_LENGTH(HPET), 1) )
{
- spin_unlock(&hp->lock);
+ write_unlock(&hp->lock);
return -EINVAL;
}
@@ -555,30 +604,31 @@ static int hpet_load(struct domain *d, hvm_domain_context_t *h)
#undef C
/* Recalculate the offset between the main counter and guest time */
- hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp);
+ guest_time = guest_time_hpet(hp);
+ hp->mc_offset = hp->hpet.mc64 - guest_time;
/* restart all timers */
if ( hpet_enabled(hp) )
for ( i = 0; i < HPET_TIMER_NUM; i++ )
if ( timer_enabled(hp, i) )
- hpet_set_timer(hp, i);
+ hpet_set_timer(hp, i, guest_time);
- spin_unlock(&hp->lock);
+ write_unlock(&hp->lock);
return 0;
}
HVM_REGISTER_SAVE_RESTORE(HPET, hpet_save, hpet_load, 1, HVMSR_PER_DOM);
-void hpet_init(struct vcpu *v)
+void hpet_init(struct domain *d)
{
- HPETState *h = vcpu_vhpet(v);
+ HPETState *h = domain_vhpet(d);
int i;
memset(h, 0, sizeof(HPETState));
- spin_lock_init(&h->lock);
+ rwlock_init(&h->lock);
h->stime_freq = S_TO_NS;
@@ -598,6 +648,7 @@ void hpet_init(struct vcpu *v)
h->hpet.timers[i].config =
HPET_TN_INT_ROUTE_CAP | HPET_TN_64BIT_CAP | HPET_TN_PERIODIC_CAP;
h->hpet.timers[i].cmp = ~0ULL;
+ h->hpet.comparator64[i] = ~0ULL;
h->pt[i].source = PTSRC_isa;
}
}
@@ -607,18 +658,31 @@ void hpet_deinit(struct domain *d)
int i;
HPETState *h = domain_vhpet(d);
- spin_lock(&h->lock);
+ write_lock(&h->lock);
if ( hpet_enabled(h) )
+ {
+ uint64_t guest_time = guest_time_hpet(h);
+
for ( i = 0; i < HPET_TIMER_NUM; i++ )
if ( timer_enabled(h, i) )
- hpet_stop_timer(h, i);
+ hpet_stop_timer(h, i, guest_time);
+ }
- spin_unlock(&h->lock);
+ write_unlock(&h->lock);
}
void hpet_reset(struct domain *d)
{
hpet_deinit(d);
- hpet_init(d->vcpu[0]);
+ hpet_init(d);
}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index be1a2d3..51ffc90 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -35,6 +35,9 @@
#include <xen/paging.h>
#include <xen/cpu.h>
#include <xen/wait.h>
+#include <xen/mem_event.h>
+#include <xen/mem_access.h>
+#include <xen/rangeset.h>
#include <asm/shadow.h>
#include <asm/hap.h>
#include <asm/current.h>
@@ -63,14 +66,15 @@
#include <public/hvm/ioreq.h>
#include <public/version.h>
#include <public/memory.h>
-#include <asm/mem_event.h>
-#include <asm/mem_access.h>
#include <public/mem_event.h>
+#include <public/arch-x86/cpuid.h>
bool_t __read_mostly hvm_enabled;
+#ifdef DBG_LEVEL_0
unsigned int opt_hvm_debug_level __read_mostly;
integer_param("hvm_debug", opt_hvm_debug_level);
+#endif
struct hvm_function_table hvm_funcs __read_mostly;
@@ -82,6 +86,11 @@ unsigned long __attribute__ ((__section__ (".bss.page_aligned")))
static bool_t __initdata opt_hap_enabled = 1;
boolean_param("hap", opt_hap_enabled);
+#ifndef opt_hvm_fep
+bool_t opt_hvm_fep;
+boolean_param("hvm_fep", opt_hvm_fep);
+#endif
+
static int cpu_callback(
struct notifier_block *nfb, unsigned long action, void *hcpu)
{
@@ -235,9 +244,16 @@ int hvm_set_guest_pat(struct vcpu *v, u64 guest_pat)
uint8_t *value = (uint8_t *)&guest_pat;
for ( i = 0; i < 8; i++ )
- if ( unlikely(!(value[i] == 0 || value[i] == 1 ||
- value[i] == 4 || value[i] == 5 ||
- value[i] == 6 || value[i] == 7)) ) {
+ switch ( value[i] )
+ {
+ case PAT_TYPE_UC_MINUS:
+ case PAT_TYPE_UNCACHABLE:
+ case PAT_TYPE_WRBACK:
+ case PAT_TYPE_WRCOMB:
+ case PAT_TYPE_WRPROT:
+ case PAT_TYPE_WRTHROUGH:
+ break;
+ default:
HVM_DBG_LOG(DBG_LEVEL_MSR, "invalid guest PAT: %"PRIx64"\n",
guest_pat);
return 0;
@@ -245,19 +261,24 @@ int hvm_set_guest_pat(struct vcpu *v, u64 guest_pat)
if ( !hvm_funcs.set_guest_pat(v, guest_pat) )
v->arch.hvm_vcpu.pat_cr = guest_pat;
+
return 1;
}
-void hvm_set_guest_tsc(struct vcpu *v, u64 guest_tsc)
+void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc)
{
uint64_t tsc;
uint64_t delta_tsc;
if ( v->domain->arch.vtsc )
{
- tsc = hvm_get_guest_time(v);
+ tsc = hvm_get_guest_time_fixed(v, at_tsc);
tsc = gtime_to_gtsc(v->domain, tsc);
}
+ else if ( at_tsc )
+ {
+ tsc = at_tsc;
+ }
else
{
rdtscll(tsc);
@@ -268,27 +289,31 @@ void hvm_set_guest_tsc(struct vcpu *v, u64 guest_tsc)
- v->arch.hvm_vcpu.cache_tsc_offset;
v->arch.hvm_vcpu.cache_tsc_offset = delta_tsc;
- hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset);
+ hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset, at_tsc);
}
void hvm_set_guest_tsc_adjust(struct vcpu *v, u64 tsc_adjust)
{
v->arch.hvm_vcpu.cache_tsc_offset += tsc_adjust
- v->arch.hvm_vcpu.msr_tsc_adjust;
- hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset);
+ hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset, 0);
v->arch.hvm_vcpu.msr_tsc_adjust = tsc_adjust;
}
-u64 hvm_get_guest_tsc(struct vcpu *v)
+u64 hvm_get_guest_tsc_fixed(struct vcpu *v, uint64_t at_tsc)
{
uint64_t tsc;
if ( v->domain->arch.vtsc )
{
- tsc = hvm_get_guest_time(v);
+ tsc = hvm_get_guest_time_fixed(v, at_tsc);
tsc = gtime_to_gtsc(v->domain, tsc);
v->domain->arch.vtsc_kerncount++;
}
+ else if ( at_tsc )
+ {
+ tsc = at_tsc;
+ }
else
{
rdtscll(tsc);
@@ -345,40 +370,91 @@ void hvm_migrate_pirqs(struct vcpu *v)
spin_unlock(&d->event_lock);
}
-void hvm_do_resume(struct vcpu *v)
+static ioreq_t *get_ioreq(struct hvm_ioreq_server *s, struct vcpu *v)
{
- ioreq_t *p;
+ shared_iopage_t *p = s->ioreq.va;
- check_wakeup_from_wait();
+ ASSERT((v == current) || !vcpu_runnable(v));
+ ASSERT(p != NULL);
- if ( is_hvm_vcpu(v) )
- pt_restore_timer(v);
+ return &p->vcpu_ioreq[v->vcpu_id];
+}
- /* NB. Optimised for common case (p->state == STATE_IOREQ_NONE). */
- if ( !(p = get_ioreq(v)) )
- goto check_inject_trap;
+bool_t hvm_io_pending(struct vcpu *v)
+{
+ struct domain *d = v->domain;
+ struct hvm_ioreq_server *s;
+
+ list_for_each_entry ( s,
+ &d->arch.hvm_domain.ioreq_server.list,
+ list_entry )
+ {
+ ioreq_t *p = get_ioreq(s, v);
+
+ if ( p->state != STATE_IOREQ_NONE )
+ return 1;
+ }
+ return 0;
+}
+
+static bool_t hvm_wait_for_io(struct hvm_ioreq_vcpu *sv, ioreq_t *p)
+{
+ /* NB. Optimised for common case (p->state == STATE_IOREQ_NONE). */
while ( p->state != STATE_IOREQ_NONE )
{
switch ( p->state )
{
case STATE_IORESP_READY: /* IORESP_READY -> NONE */
+ rmb(); /* see IORESP_READY /then/ read contents of ioreq */
hvm_io_assist(p);
break;
case STATE_IOREQ_READY: /* IOREQ_{READY,INPROCESS} -> IORESP_READY */
case STATE_IOREQ_INPROCESS:
- wait_on_xen_event_channel(v->arch.hvm_vcpu.xen_port,
+ wait_on_xen_event_channel(sv->ioreq_evtchn,
(p->state != STATE_IOREQ_READY) &&
(p->state != STATE_IOREQ_INPROCESS));
break;
default:
gdprintk(XENLOG_ERR, "Weird HVM iorequest state %d.\n", p->state);
- domain_crash(v->domain);
- return; /* bail */
+ domain_crash(sv->vcpu->domain);
+ return 0; /* bail */
+ }
+ }
+
+ return 1;
+}
+
+void hvm_do_resume(struct vcpu *v)
+{
+ struct domain *d = v->domain;
+ struct hvm_ioreq_server *s;
+
+ check_wakeup_from_wait();
+
+ if ( is_hvm_vcpu(v) )
+ pt_restore_timer(v);
+
+ list_for_each_entry ( s,
+ &d->arch.hvm_domain.ioreq_server.list,
+ list_entry )
+ {
+ struct hvm_ioreq_vcpu *sv;
+
+ list_for_each_entry ( sv,
+ &s->ioreq_vcpu_list,
+ list_entry )
+ {
+ if ( sv->vcpu == v )
+ {
+ if ( !hvm_wait_for_io(sv, get_ioreq(s, v)) )
+ return;
+
+ break;
+ }
}
}
- check_inject_trap:
/* Inject pending hw/sw trap */
if ( v->arch.hvm_vcpu.inject_trap.vector != -1 )
{
@@ -387,150 +463,936 @@ void hvm_do_resume(struct vcpu *v)
}
}
-static void hvm_init_ioreq_page(
- struct domain *d, struct hvm_ioreq_page *iorp)
-{
- memset(iorp, 0, sizeof(*iorp));
- spin_lock_init(&iorp->lock);
- domain_pause(d);
-}
-
-void destroy_ring_for_helper(
- void **_va, struct page_info *page)
+static int hvm_alloc_ioreq_gmfn(struct domain *d, unsigned long *gmfn)
{
- void *va = *_va;
+ unsigned int i;
+ int rc;
- if ( va != NULL )
+ rc = -ENOMEM;
+ for ( i = 0; i < sizeof(d->arch.hvm_domain.ioreq_gmfn.mask) * 8; i++ )
{
- unmap_domain_page_global(va);
- put_page_and_type(page);
- *_va = NULL;
+ if ( test_and_clear_bit(i, &d->arch.hvm_domain.ioreq_gmfn.mask) )
+ {
+ *gmfn = d->arch.hvm_domain.ioreq_gmfn.base + i;
+ rc = 0;
+ break;
+ }
}
+
+ return rc;
}
-static void hvm_destroy_ioreq_page(
- struct domain *d, struct hvm_ioreq_page *iorp)
+static void hvm_free_ioreq_gmfn(struct domain *d, unsigned long gmfn)
{
- spin_lock(&iorp->lock);
+ unsigned int i = gmfn - d->arch.hvm_domain.ioreq_gmfn.base;
- ASSERT(d->is_dying);
+ clear_bit(i, &d->arch.hvm_domain.ioreq_gmfn.mask);
+}
- destroy_ring_for_helper(&iorp->va, iorp->page);
+static void hvm_unmap_ioreq_page(struct hvm_ioreq_server *s, bool_t buf)
+{
+ struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
- spin_unlock(&iorp->lock);
+ destroy_ring_for_helper(&iorp->va, iorp->page);
}
-int prepare_ring_for_helper(
- struct domain *d, unsigned long gmfn, struct page_info **_page,
- void **_va)
+static int hvm_map_ioreq_page(
+ struct hvm_ioreq_server *s, bool_t buf, unsigned long gmfn)
{
+ struct domain *d = s->domain;
+ struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
struct page_info *page;
- p2m_type_t p2mt;
void *va;
+ int rc;
- page = get_page_from_gfn(d, gmfn, &p2mt, P2M_UNSHARE);
- if ( p2m_is_paging(p2mt) )
+ if ( (rc = prepare_ring_for_helper(d, gmfn, &page, &va)) )
+ return rc;
+
+ if ( (iorp->va != NULL) || d->is_dying )
{
- if ( page )
- put_page(page);
- p2m_mem_paging_populate(d, gmfn);
- return -ENOENT;
+ destroy_ring_for_helper(&va, page);
+ return -EINVAL;
}
- if ( p2m_is_shared(p2mt) )
+
+ iorp->va = va;
+ iorp->page = page;
+ iorp->gmfn = gmfn;
+
+ return 0;
+}
+
+static void hvm_remove_ioreq_gmfn(
+ struct domain *d, struct hvm_ioreq_page *iorp)
+{
+ guest_physmap_remove_page(d, iorp->gmfn,
+ page_to_mfn(iorp->page), 0);
+ clear_page(iorp->va);
+}
+
+static int hvm_add_ioreq_gmfn(
+ struct domain *d, struct hvm_ioreq_page *iorp)
+{
+ clear_page(iorp->va);
+ return guest_physmap_add_page(d, iorp->gmfn,
+ page_to_mfn(iorp->page), 0);
+}
+
+static int hvm_print_line(
+ int dir, uint32_t port, uint32_t bytes, uint32_t *val)
+{
+ struct domain *cd = current->domain;
+ char c = *val;
+
+ BUG_ON(bytes != 1);
+
+ /* Accept only printable characters, newline, and horizontal tab. */
+ if ( !isprint(c) && (c != '\n') && (c != '\t') )
+ return X86EMUL_OKAY;
+
+ spin_lock(&cd->pbuf_lock);
+ if ( c != '\n' )
+ cd->pbuf[cd->pbuf_idx++] = c;
+ if ( (cd->pbuf_idx == (DOMAIN_PBUF_SIZE - 1)) || (c == '\n') )
{
- if ( page )
- put_page(page);
- return -ENOENT;
+ cd->pbuf[cd->pbuf_idx] = '\0';
+ guest_printk(cd, XENLOG_G_DEBUG "%s\n", cd->pbuf);
+ cd->pbuf_idx = 0;
}
- if ( !page )
- return -EINVAL;
+ spin_unlock(&cd->pbuf_lock);
+
+ return X86EMUL_OKAY;
+}
+
+static int hvm_access_cf8(
+ int dir, uint32_t port, uint32_t bytes, uint32_t *val)
+{
+ struct domain *d = current->domain;
+
+ if ( dir == IOREQ_WRITE && bytes == 4 )
+ d->arch.hvm_domain.pci_cf8 = *val;
+
+ /* We always need to fall through to the catch all emulator */
+ return X86EMUL_UNHANDLEABLE;
+}
+
+static int handle_pvh_io(
+ int dir, uint32_t port, uint32_t bytes, uint32_t *val)
+{
+ struct vcpu *curr = current;
+ struct cpu_user_regs *regs = guest_cpu_user_regs();
+
+ if ( dir == IOREQ_WRITE )
+ guest_io_write(port, bytes, *val, curr, regs);
+ else
+ *val = guest_io_read(port, bytes, curr, regs);
+
+ return X86EMUL_OKAY;
+}
+
+static void hvm_update_ioreq_evtchn(struct hvm_ioreq_server *s,
+ struct hvm_ioreq_vcpu *sv)
+{
+ ASSERT(spin_is_locked(&s->lock));
- if ( !get_page_type(page, PGT_writable_page) )
+ if ( s->ioreq.va != NULL )
{
- put_page(page);
- return -EINVAL;
+ ioreq_t *p = get_ioreq(s, sv->vcpu);
+
+ p->vp_eport = sv->ioreq_evtchn;
}
+}
+
+static int hvm_ioreq_server_add_vcpu(struct hvm_ioreq_server *s,
+ bool_t is_default, struct vcpu *v)
+{
+ struct hvm_ioreq_vcpu *sv;
+ int rc;
+
+ sv = xzalloc(struct hvm_ioreq_vcpu);
+
+ rc = -ENOMEM;
+ if ( !sv )
+ goto fail1;
+
+ spin_lock(&s->lock);
+
+ rc = alloc_unbound_xen_event_channel(v, s->domid, NULL);
+ if ( rc < 0 )
+ goto fail2;
- va = __map_domain_page_global(page);
- if ( va == NULL )
+ sv->ioreq_evtchn = rc;
+
+ if ( v->vcpu_id == 0 && s->bufioreq.va != NULL )
{
- put_page_and_type(page);
- return -ENOMEM;
+ struct domain *d = s->domain;
+
+ rc = alloc_unbound_xen_event_channel(v, s->domid, NULL);
+ if ( rc < 0 )
+ goto fail3;
+
+ s->bufioreq_evtchn = rc;
+ if ( is_default )
+ d->arch.hvm_domain.params[HVM_PARAM_BUFIOREQ_EVTCHN] =
+ s->bufioreq_evtchn;
}
- *_va = va;
- *_page = page;
+ sv->vcpu = v;
+ list_add(&sv->list_entry, &s->ioreq_vcpu_list);
+
+ if ( s->enabled )
+ hvm_update_ioreq_evtchn(s, sv);
+
+ spin_unlock(&s->lock);
return 0;
+
+ fail3:
+ free_xen_event_channel(v, sv->ioreq_evtchn);
+
+ fail2:
+ spin_unlock(&s->lock);
+ xfree(sv);
+
+ fail1:
+ return rc;
}
-static int hvm_set_ioreq_page(
- struct domain *d, struct hvm_ioreq_page *iorp, unsigned long gmfn)
+static void hvm_ioreq_server_remove_vcpu(struct hvm_ioreq_server *s,
+ struct vcpu *v)
{
- struct page_info *page;
- void *va;
- int rc;
+ struct hvm_ioreq_vcpu *sv;
- if ( (rc = prepare_ring_for_helper(d, gmfn, &page, &va)) )
- return rc;
+ spin_lock(&s->lock);
+
+ list_for_each_entry ( sv,
+ &s->ioreq_vcpu_list,
+ list_entry )
+ {
+ if ( sv->vcpu != v )
+ continue;
- spin_lock(&iorp->lock);
+ list_del(&sv->list_entry);
- if ( (iorp->va != NULL) || d->is_dying )
+ if ( v->vcpu_id == 0 && s->bufioreq.va != NULL )
+ free_xen_event_channel(v, s->bufioreq_evtchn);
+
+ free_xen_event_channel(v, sv->ioreq_evtchn);
+
+ xfree(sv);
+ break;
+ }
+
+ spin_unlock(&s->lock);
+}
+
+static void hvm_ioreq_server_remove_all_vcpus(struct hvm_ioreq_server *s)
+{
+ struct hvm_ioreq_vcpu *sv, *next;
+
+ spin_lock(&s->lock);
+
+ list_for_each_entry_safe ( sv,
+ next,
+ &s->ioreq_vcpu_list,
+ list_entry )
{
- destroy_ring_for_helper(&va, page);
- spin_unlock(&iorp->lock);
- return -EINVAL;
+ struct vcpu *v = sv->vcpu;
+
+ list_del(&sv->list_entry);
+
+ if ( v->vcpu_id == 0 && s->bufioreq.va != NULL )
+ free_xen_event_channel(v, s->bufioreq_evtchn);
+
+ free_xen_event_channel(v, sv->ioreq_evtchn);
+
+ xfree(sv);
}
- iorp->va = va;
- iorp->page = page;
+ spin_unlock(&s->lock);
+}
- spin_unlock(&iorp->lock);
+static int hvm_ioreq_server_map_pages(struct hvm_ioreq_server *s,
+ bool_t is_default, bool_t handle_bufioreq)
+{
+ struct domain *d = s->domain;
+ unsigned long ioreq_pfn, bufioreq_pfn;
+ int rc;
- domain_unpause(d);
+ if ( is_default )
+ {
+ ioreq_pfn = d->arch.hvm_domain.params[HVM_PARAM_IOREQ_PFN];
+
+ /*
+ * The default ioreq server must handle buffered ioreqs, for
+ * backwards compatibility.
+ */
+ ASSERT(handle_bufioreq);
+ bufioreq_pfn = d->arch.hvm_domain.params[HVM_PARAM_BUFIOREQ_PFN];
+ }
+ else
+ {
+ rc = hvm_alloc_ioreq_gmfn(d, &ioreq_pfn);
+ if ( rc )
+ goto fail1;
+
+ if ( handle_bufioreq )
+ {
+ rc = hvm_alloc_ioreq_gmfn(d, &bufioreq_pfn);
+ if ( rc )
+ goto fail2;
+ }
+ }
+
+ rc = hvm_map_ioreq_page(s, 0, ioreq_pfn);
+ if ( rc )
+ goto fail3;
+
+ if ( handle_bufioreq )
+ {
+ rc = hvm_map_ioreq_page(s, 1, bufioreq_pfn);
+ if ( rc )
+ goto fail4;
+ }
return 0;
+
+fail4:
+ hvm_unmap_ioreq_page(s, 0);
+
+fail3:
+ if ( !is_default && handle_bufioreq )
+ hvm_free_ioreq_gmfn(d, bufioreq_pfn);
+
+fail2:
+ if ( !is_default )
+ hvm_free_ioreq_gmfn(d, ioreq_pfn);
+
+fail1:
+ return rc;
}
-static int hvm_print_line(
- int dir, uint32_t port, uint32_t bytes, uint32_t *val)
+static void hvm_ioreq_server_unmap_pages(struct hvm_ioreq_server *s,
+ bool_t is_default)
{
- struct domain *cd = current->domain;
- char c = *val;
+ struct domain *d = s->domain;
+ bool_t handle_bufioreq = ( s->bufioreq.va != NULL );
- BUG_ON(bytes != 1);
+ if ( handle_bufioreq )
+ hvm_unmap_ioreq_page(s, 1);
+
+ hvm_unmap_ioreq_page(s, 0);
+
+ if ( !is_default )
+ {
+ if ( handle_bufioreq )
+ hvm_free_ioreq_gmfn(d, s->bufioreq.gmfn);
+
+ hvm_free_ioreq_gmfn(d, s->ioreq.gmfn);
+ }
+}
+
+static void hvm_ioreq_server_free_rangesets(struct hvm_ioreq_server *s,
+ bool_t is_default)
+{
+ unsigned int i;
+
+ if ( is_default )
+ return;
+
+ for ( i = 0; i < NR_IO_RANGE_TYPES; i++ )
+ rangeset_destroy(s->range[i]);
+}
+
+static int hvm_ioreq_server_alloc_rangesets(struct hvm_ioreq_server *s,
+ bool_t is_default)
+{
+ unsigned int i;
+ int rc;
+
+ if ( is_default )
+ goto done;
+
+ for ( i = 0; i < NR_IO_RANGE_TYPES; i++ )
+ {
+ char *name;
+
+ rc = asprintf(&name, "ioreq_server %d %s", s->id,
+ (i == HVMOP_IO_RANGE_PORT) ? "port" :
+ (i == HVMOP_IO_RANGE_MEMORY) ? "memory" :
+ (i == HVMOP_IO_RANGE_PCI) ? "pci" :
+ "");
+ if ( rc )
+ goto fail;
+
+ s->range[i] = rangeset_new(s->domain, name,
+ RANGESETF_prettyprint_hex);
+
+ xfree(name);
+
+ rc = -ENOMEM;
+ if ( !s->range[i] )
+ goto fail;
+
+ rangeset_limit(s->range[i], MAX_NR_IO_RANGES);
+ }
+
+ done:
+ return 0;
+
+ fail:
+ hvm_ioreq_server_free_rangesets(s, 0);
+
+ return rc;
+}
+
+static void hvm_ioreq_server_enable(struct hvm_ioreq_server *s,
+ bool_t is_default)
+{
+ struct domain *d = s->domain;
+ struct hvm_ioreq_vcpu *sv;
+ bool_t handle_bufioreq = ( s->bufioreq.va != NULL );
+
+ spin_lock(&s->lock);
+
+ if ( s->enabled )
+ goto done;
+
+ if ( !is_default )
+ {
+ hvm_remove_ioreq_gmfn(d, &s->ioreq);
+
+ if ( handle_bufioreq )
+ hvm_remove_ioreq_gmfn(d, &s->bufioreq);
+ }
+
+ s->enabled = 1;
+
+ list_for_each_entry ( sv,
+ &s->ioreq_vcpu_list,
+ list_entry )
+ hvm_update_ioreq_evtchn(s, sv);
+
+ done:
+ spin_unlock(&s->lock);
+}
+
+static void hvm_ioreq_server_disable(struct hvm_ioreq_server *s,
+ bool_t is_default)
+{
+ struct domain *d = s->domain;
+ bool_t handle_bufioreq = ( s->bufioreq.va != NULL );
+
+ spin_lock(&s->lock);
+
+ if ( !s->enabled )
+ goto done;
+
+ if ( !is_default )
+ {
+ if ( handle_bufioreq )
+ hvm_add_ioreq_gmfn(d, &s->bufioreq);
+
+ hvm_add_ioreq_gmfn(d, &s->ioreq);
+ }
+
+ s->enabled = 0;
+
+ done:
+ spin_unlock(&s->lock);
+}
+
+static int hvm_ioreq_server_init(struct hvm_ioreq_server *s, struct domain *d,
+ domid_t domid, bool_t is_default,
+ bool_t handle_bufioreq, ioservid_t id)
+{
+ struct vcpu *v;
+ int rc;
+
+ s->id = id;
+ s->domain = d;
+ s->domid = domid;
+
+ spin_lock_init(&s->lock);
+ INIT_LIST_HEAD(&s->ioreq_vcpu_list);
+ spin_lock_init(&s->bufioreq_lock);
+
+ rc = hvm_ioreq_server_alloc_rangesets(s, is_default);
+ if ( rc )
+ return rc;
+
+ rc = hvm_ioreq_server_map_pages(s, is_default, handle_bufioreq);
+ if ( rc )
+ goto fail_map;
+
+ for_each_vcpu ( d, v )
+ {
+ rc = hvm_ioreq_server_add_vcpu(s, is_default, v);
+ if ( rc )
+ goto fail_add;
+ }
+
+ return 0;
+
+ fail_add:
+ hvm_ioreq_server_remove_all_vcpus(s);
+ hvm_ioreq_server_unmap_pages(s, is_default);
+
+ fail_map:
+ hvm_ioreq_server_free_rangesets(s, is_default);
+
+ return rc;
+}
+
+static void hvm_ioreq_server_deinit(struct hvm_ioreq_server *s,
+ bool_t is_default)
+{
+ hvm_ioreq_server_remove_all_vcpus(s);
+ hvm_ioreq_server_unmap_pages(s, is_default);
+ hvm_ioreq_server_free_rangesets(s, is_default);
+}
+
+static ioservid_t next_ioservid(struct domain *d)
+{
+ struct hvm_ioreq_server *s;
+ ioservid_t id;
+
+ ASSERT(spin_is_locked(&d->arch.hvm_domain.ioreq_server.lock));
+
+ id = d->arch.hvm_domain.ioreq_server.id;
+
+ again:
+ id++;
+
+ /* Check for uniqueness */
+ list_for_each_entry ( s,
+ &d->arch.hvm_domain.ioreq_server.list,
+ list_entry )
+ {
+ if ( id == s->id )
+ goto again;
+ }
+
+ d->arch.hvm_domain.ioreq_server.id = id;
+
+ return id;
+}
+
+static int hvm_create_ioreq_server(struct domain *d, domid_t domid,
+ bool_t is_default, bool_t handle_bufioreq,
+ ioservid_t *id)
+{
+ struct hvm_ioreq_server *s;
+ int rc;
+
+ rc = -ENOMEM;
+ s = xzalloc(struct hvm_ioreq_server);
+ if ( !s )
+ goto fail1;
+
+ domain_pause(d);
+ spin_lock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ rc = -EEXIST;
+ if ( is_default && d->arch.hvm_domain.default_ioreq_server != NULL )
+ goto fail2;
+
+ rc = hvm_ioreq_server_init(s, d, domid, is_default, handle_bufioreq,
+ next_ioservid(d));
+ if ( rc )
+ goto fail3;
+
+ list_add(&s->list_entry,
+ &d->arch.hvm_domain.ioreq_server.list);
+
+ if ( is_default )
+ {
+ d->arch.hvm_domain.default_ioreq_server = s;
+ hvm_ioreq_server_enable(s, 1);
+ }
+
+ if ( id )
+ *id = s->id;
+
+ spin_unlock(&d->arch.hvm_domain.ioreq_server.lock);
+ domain_unpause(d);
+
+ return 0;
+
+ fail3:
+ fail2:
+ spin_unlock(&d->arch.hvm_domain.ioreq_server.lock);
+ domain_unpause(d);
+
+ xfree(s);
+ fail1:
+ return rc;
+}
+
+static int hvm_destroy_ioreq_server(struct domain *d, ioservid_t id)
+{
+ struct hvm_ioreq_server *s;
+ int rc;
+
+ spin_lock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ rc = -ENOENT;
+ list_for_each_entry ( s,
+ &d->arch.hvm_domain.ioreq_server.list,
+ list_entry )
+ {
+ if ( s == d->arch.hvm_domain.default_ioreq_server )
+ continue;
+
+ if ( s->id != id )
+ continue;
+
+ domain_pause(d);
+
+ list_del(&s->list_entry);
+
+ hvm_ioreq_server_deinit(s, 0);
+
+ domain_unpause(d);
+
+ xfree(s);
+
+ rc = 0;
+ break;
+ }
+
+ spin_unlock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ return rc;
+}
+
+static int hvm_get_ioreq_server_info(struct domain *d, ioservid_t id,
+ unsigned long *ioreq_pfn,
+ unsigned long *bufioreq_pfn,
+ evtchn_port_t *bufioreq_port)
+{
+ struct hvm_ioreq_server *s;
+ int rc;
+
+ spin_lock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ rc = -ENOENT;
+ list_for_each_entry ( s,
+ &d->arch.hvm_domain.ioreq_server.list,
+ list_entry )
+ {
+ if ( s == d->arch.hvm_domain.default_ioreq_server )
+ continue;
+
+ if ( s->id != id )
+ continue;
+
+ *ioreq_pfn = s->ioreq.gmfn;
+
+ if ( s->bufioreq.va != NULL )
+ {
+ *bufioreq_pfn = s->bufioreq.gmfn;
+ *bufioreq_port = s->bufioreq_evtchn;
+ }
+
+ rc = 0;
+ break;
+ }
+
+ spin_unlock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ return rc;
+}
+
+static int hvm_map_io_range_to_ioreq_server(struct domain *d, ioservid_t id,
+ uint32_t type, uint64_t start, uint64_t end)
+{
+ struct hvm_ioreq_server *s;
+ int rc;
+
+ spin_lock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ rc = -ENOENT;
+ list_for_each_entry ( s,
+ &d->arch.hvm_domain.ioreq_server.list,
+ list_entry )
+ {
+ if ( s == d->arch.hvm_domain.default_ioreq_server )
+ continue;
+
+ if ( s->id == id )
+ {
+ struct rangeset *r;
+
+ switch ( type )
+ {
+ case HVMOP_IO_RANGE_PORT:
+ case HVMOP_IO_RANGE_MEMORY:
+ case HVMOP_IO_RANGE_PCI:
+ r = s->range[type];
+ break;
+
+ default:
+ r = NULL;
+ break;
+ }
+
+ rc = -EINVAL;
+ if ( !r )
+ break;
+
+ rc = -EEXIST;
+ if ( rangeset_overlaps_range(r, start, end) )
+ break;
+
+ rc = rangeset_add_range(r, start, end);
+ break;
+ }
+ }
+
+ spin_unlock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ return rc;
+}
+
+static int hvm_unmap_io_range_from_ioreq_server(struct domain *d, ioservid_t id,
+ uint32_t type, uint64_t start, uint64_t end)
+{
+ struct hvm_ioreq_server *s;
+ int rc;
+
+ spin_lock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ rc = -ENOENT;
+ list_for_each_entry ( s,
+ &d->arch.hvm_domain.ioreq_server.list,
+ list_entry )
+ {
+ if ( s == d->arch.hvm_domain.default_ioreq_server )
+ continue;
+
+ if ( s->id == id )
+ {
+ struct rangeset *r;
+
+ switch ( type )
+ {
+ case HVMOP_IO_RANGE_PORT:
+ case HVMOP_IO_RANGE_MEMORY:
+ case HVMOP_IO_RANGE_PCI:
+ r = s->range[type];
+ break;
+
+ default:
+ r = NULL;
+ break;
+ }
+
+ rc = -EINVAL;
+ if ( !r )
+ break;
+
+ rc = -ENOENT;
+ if ( !rangeset_contains_range(r, start, end) )
+ break;
+
+ rc = rangeset_remove_range(r, start, end);
+ break;
+ }
+ }
+
+ spin_unlock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ return rc;
+}
+
+static int hvm_set_ioreq_server_state(struct domain *d, ioservid_t id,
+ bool_t enabled)
+{
+ struct list_head *entry;
+ int rc;
+
+ spin_lock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ rc = -ENOENT;
+ list_for_each ( entry,
+ &d->arch.hvm_domain.ioreq_server.list )
+ {
+ struct hvm_ioreq_server *s = list_entry(entry,
+ struct hvm_ioreq_server,
+ list_entry);
+
+ if ( s == d->arch.hvm_domain.default_ioreq_server )
+ continue;
+
+ if ( s->id != id )
+ continue;
+
+ domain_pause(d);
+
+ if ( enabled )
+ hvm_ioreq_server_enable(s, 0);
+ else
+ hvm_ioreq_server_disable(s, 0);
+
+ domain_unpause(d);
+
+ rc = 0;
+ break;
+ }
+
+ spin_unlock(&d->arch.hvm_domain.ioreq_server.lock);
+ return rc;
+}
+
+static int hvm_all_ioreq_servers_add_vcpu(struct domain *d, struct vcpu *v)
+{
+ struct hvm_ioreq_server *s;
+ int rc;
+
+ spin_lock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ list_for_each_entry ( s,
+ &d->arch.hvm_domain.ioreq_server.list,
+ list_entry )
+ {
+ bool_t is_default = (s == d->arch.hvm_domain.default_ioreq_server);
+
+ rc = hvm_ioreq_server_add_vcpu(s, is_default, v);
+ if ( rc )
+ goto fail;
+ }
+
+ spin_unlock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ return 0;
+
+ fail:
+ list_for_each_entry ( s,
+ &d->arch.hvm_domain.ioreq_server.list,
+ list_entry )
+ hvm_ioreq_server_remove_vcpu(s, v);
+
+ spin_unlock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ return rc;
+}
+
+static void hvm_all_ioreq_servers_remove_vcpu(struct domain *d, struct vcpu *v)
+{
+ struct hvm_ioreq_server *s;
+
+ spin_lock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ list_for_each_entry ( s,
+ &d->arch.hvm_domain.ioreq_server.list,
+ list_entry )
+ hvm_ioreq_server_remove_vcpu(s, v);
+
+ spin_unlock(&d->arch.hvm_domain.ioreq_server.lock);
+}
+
+static void hvm_destroy_all_ioreq_servers(struct domain *d)
+{
+ struct hvm_ioreq_server *s, *next;
+
+ spin_lock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ /* No need to domain_pause() as the domain is being torn down */
+
+ list_for_each_entry_safe ( s,
+ next,
+ &d->arch.hvm_domain.ioreq_server.list,
+ list_entry )
+ {
+ bool_t is_default = (s == d->arch.hvm_domain.default_ioreq_server);
+
+ if ( is_default )
+ {
+ hvm_ioreq_server_disable(s, 1);
+ d->arch.hvm_domain.default_ioreq_server = NULL;
+ }
+
+ list_del(&s->list_entry);
+
+ hvm_ioreq_server_deinit(s, is_default);
+
+ xfree(s);
+ }
+
+ spin_unlock(&d->arch.hvm_domain.ioreq_server.lock);
+}
+
+static int hvm_replace_event_channel(struct vcpu *v, domid_t remote_domid,
+ evtchn_port_t *p_port)
+{
+ int old_port, new_port;
+
+ new_port = alloc_unbound_xen_event_channel(v, remote_domid, NULL);
+ if ( new_port < 0 )
+ return new_port;
+
+ /* xchg() ensures that only we call free_xen_event_channel(). */
+ old_port = xchg(p_port, new_port);
+ free_xen_event_channel(v, old_port);
+ return 0;
+}
+
+static int hvm_set_dm_domain(struct domain *d, domid_t domid)
+{
+ struct hvm_ioreq_server *s;
+ int rc = 0;
+
+ spin_lock(&d->arch.hvm_domain.ioreq_server.lock);
+
+ /*
+ * Lack of ioreq server is not a failure. HVM_PARAM_DM_DOMAIN will
+ * still be set and thus, when the server is created, it will have
+ * the correct domid.
+ */
+ s = d->arch.hvm_domain.default_ioreq_server;
+ if ( !s )
+ goto done;
+
+ domain_pause(d);
+ spin_lock(&s->lock);
+
+ if ( s->domid != domid )
+ {
+ struct hvm_ioreq_vcpu *sv;
+
+ list_for_each_entry ( sv,
+ &s->ioreq_vcpu_list,
+ list_entry )
+ {
+ struct vcpu *v = sv->vcpu;
+
+ if ( v->vcpu_id == 0 )
+ {
+ rc = hvm_replace_event_channel(v, domid,
+ &s->bufioreq_evtchn);
+ if ( rc )
+ break;
- /* Accept only printable characters, newline, and horizontal tab. */
- if ( !isprint(c) && (c != '\n') && (c != '\t') )
- return X86EMUL_OKAY;
+ d->arch.hvm_domain.params[HVM_PARAM_BUFIOREQ_EVTCHN] =
+ s->bufioreq_evtchn;
+ }
- spin_lock(&cd->pbuf_lock);
- if ( c != '\n' )
- cd->pbuf[cd->pbuf_idx++] = c;
- if ( (cd->pbuf_idx == (DOMAIN_PBUF_SIZE - 1)) || (c == '\n') )
- {
- cd->pbuf[cd->pbuf_idx] = '\0';
- guest_printk(cd, XENLOG_G_DEBUG "%s\n", cd->pbuf);
- cd->pbuf_idx = 0;
- }
- spin_unlock(&cd->pbuf_lock);
+ rc = hvm_replace_event_channel(v, domid, &sv->ioreq_evtchn);
+ if ( rc )
+ break;
- return X86EMUL_OKAY;
-}
+ hvm_update_ioreq_evtchn(s, sv);
+ }
-static int handle_pvh_io(
- int dir, uint32_t port, uint32_t bytes, uint32_t *val)
-{
- struct vcpu *curr = current;
- struct cpu_user_regs *regs = guest_cpu_user_regs();
+ s->domid = domid;
+ }
- if ( dir == IOREQ_WRITE )
- guest_io_write(port, bytes, *val, curr, regs);
- else
- *val = guest_io_read(port, bytes, curr, regs);
+ spin_unlock(&s->lock);
+ domain_unpause(d);
- return X86EMUL_OKAY;
+ done:
+ spin_unlock(&d->arch.hvm_domain.ioreq_server.lock);
+ return rc;
}
int hvm_domain_initialise(struct domain *d)
@@ -560,6 +1422,8 @@ int hvm_domain_initialise(struct domain *d)
}
+ spin_lock_init(&d->arch.hvm_domain.ioreq_server.lock);
+ INIT_LIST_HEAD(&d->arch.hvm_domain.ioreq_server.list);
spin_lock_init(&d->arch.hvm_domain.irq_lock);
spin_lock_init(&d->arch.hvm_domain.uc_lock);
@@ -600,10 +1464,8 @@ int hvm_domain_initialise(struct domain *d)
rtc_init(d);
- hvm_init_ioreq_page(d, &d->arch.hvm_domain.ioreq);
- hvm_init_ioreq_page(d, &d->arch.hvm_domain.buf_ioreq);
-
register_portio_handler(d, 0xe9, 1, hvm_print_line);
+ register_portio_handler(d, 0xcf8, 4, hvm_access_cf8);
rc = hvm_funcs.domain_initialise(d);
if ( rc != 0 )
@@ -634,8 +1496,7 @@ void hvm_domain_relinquish_resources(struct domain *d)
if ( hvm_funcs.nhvm_domain_relinquish_resources )
hvm_funcs.nhvm_domain_relinquish_resources(d);
- hvm_destroy_ioreq_page(d, &d->arch.hvm_domain.ioreq);
- hvm_destroy_ioreq_page(d, &d->arch.hvm_domain.buf_ioreq);
+ hvm_destroy_all_ioreq_servers(d);
msixtbl_pt_cleanup(d);
@@ -827,6 +1688,75 @@ static bool_t hvm_efer_valid(struct domain *d,
((value & (EFER_LME|EFER_LMA)) == EFER_LMA));
}
+/* These reserved bits in lower 32 remain 0 after any load of CR0 */
+#define HVM_CR0_GUEST_RESERVED_BITS \
+ (~((unsigned long) \
+ (X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | \
+ X86_CR0_TS | X86_CR0_ET | X86_CR0_NE | \
+ X86_CR0_WP | X86_CR0_AM | X86_CR0_NW | \
+ X86_CR0_CD | X86_CR0_PG)))
+
+/* These bits in CR4 cannot be set by the guest. */
+static unsigned long hvm_cr4_guest_reserved_bits(const struct vcpu *v,
+ bool_t restore)
+{
+ unsigned int leaf1_ecx = 0, leaf1_edx = 0;
+ unsigned int leaf7_0_ebx = 0, leaf7_0_ecx = 0;
+
+ if ( !restore && !is_hardware_domain(v->domain) )
+ {
+ unsigned int level;
+
+ ASSERT(v == current);
+ hvm_cpuid(0, &level, NULL, NULL, NULL);
+ if ( level >= 1 )
+ hvm_cpuid(1, NULL, NULL, &leaf1_ecx, &leaf1_edx);
+ if ( level >= 7 )
+ hvm_cpuid(7, NULL, &leaf7_0_ebx, &leaf7_0_ecx, NULL);
+ }
+ else
+ {
+ leaf1_edx = boot_cpu_data.x86_capability[X86_FEATURE_VME / 32];
+ leaf1_ecx = boot_cpu_data.x86_capability[X86_FEATURE_PCID / 32];
+ leaf7_0_ebx = boot_cpu_data.x86_capability[X86_FEATURE_FSGSBASE / 32];
+ }
+
+ return ~(unsigned long)
+ ((leaf1_edx & cpufeat_mask(X86_FEATURE_VME) ?
+ X86_CR4_VME | X86_CR4_PVI : 0) |
+ (leaf1_edx & cpufeat_mask(X86_FEATURE_TSC) ?
+ X86_CR4_TSD : 0) |
+ (leaf1_edx & cpufeat_mask(X86_FEATURE_DE) ?
+ X86_CR4_DE : 0) |
+ (leaf1_edx & cpufeat_mask(X86_FEATURE_PSE) ?
+ X86_CR4_PSE : 0) |
+ (leaf1_edx & cpufeat_mask(X86_FEATURE_PAE) ?
+ X86_CR4_PAE : 0) |
+ (leaf1_edx & (cpufeat_mask(X86_FEATURE_MCE) |
+ cpufeat_mask(X86_FEATURE_MCA)) ?
+ X86_CR4_MCE : 0) |
+ (leaf1_edx & cpufeat_mask(X86_FEATURE_PGE) ?
+ X86_CR4_PGE : 0) |
+ X86_CR4_PCE |
+ (leaf1_edx & cpufeat_mask(X86_FEATURE_FXSR) ?
+ X86_CR4_OSFXSR : 0) |
+ (leaf1_edx & cpufeat_mask(X86_FEATURE_XMM) ?
+ X86_CR4_OSXMMEXCPT : 0) |
+ ((restore || nestedhvm_enabled(v->domain)) &&
+ (leaf1_ecx & cpufeat_mask(X86_FEATURE_VMXE)) ?
+ X86_CR4_VMXE : 0) |
+ (leaf7_0_ebx & cpufeat_mask(X86_FEATURE_FSGSBASE) ?
+ X86_CR4_FSGSBASE : 0) |
+ (leaf1_ecx & cpufeat_mask(X86_FEATURE_PCID) ?
+ X86_CR4_PCIDE : 0) |
+ (leaf1_ecx & cpufeat_mask(X86_FEATURE_XSAVE) ?
+ X86_CR4_OSXSAVE : 0) |
+ (leaf7_0_ebx & cpufeat_mask(X86_FEATURE_SMEP) ?
+ X86_CR4_SMEP : 0) |
+ (leaf7_0_ebx & cpufeat_mask(X86_FEATURE_SMAP) ?
+ X86_CR4_SMAP : 0));
+}
+
static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
{
int vcpuid;
@@ -857,7 +1787,7 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
return -EINVAL;
}
- if ( ctxt.cr4 & HVM_CR4_GUEST_RESERVED_BITS(v, 1) )
+ if ( ctxt.cr4 & hvm_cr4_guest_reserved_bits(v, 1) )
{
printk(XENLOG_G_ERR "HVM%d restore: bad CR4 %#" PRIx64 "\n",
d->domain_id, ctxt.cr4);
@@ -1041,6 +1971,7 @@ static int hvm_load_cpu_xsave_states(struct domain *d, hvm_domain_context_t *h)
struct vcpu *v;
struct hvm_hw_cpu_xsave *ctxt;
struct hvm_save_descriptor *desc;
+ unsigned int i, desc_start;
/* Which vcpu is this? */
vcpuid = hvm_load_instance(h);
@@ -1081,22 +2012,14 @@ static int hvm_load_cpu_xsave_states(struct domain *d, hvm_domain_context_t *h)
save_area) + XSTATE_AREA_MIN_SIZE);
return -EINVAL;
}
- size = HVM_CPU_XSAVE_SIZE(xfeature_mask);
- if ( desc->length > size )
- {
- printk(XENLOG_G_WARNING
- "HVM%d.%d restore mismatch: xsave length %u > %u\n",
- d->domain_id, vcpuid, desc->length, size);
- return -EOPNOTSUPP;
- }
h->cur += sizeof (*desc);
+ desc_start = h->cur;
ctxt = (struct hvm_hw_cpu_xsave *)&h->data[h->cur];
h->cur += desc->length;
err = validate_xstate(ctxt->xcr0, ctxt->xcr0_accum,
- ctxt->save_area.xsave_hdr.xstate_bv,
- ctxt->xfeature_mask);
+ ctxt->save_area.xsave_hdr.xstate_bv);
if ( err )
{
printk(XENLOG_G_WARNING
@@ -1109,10 +2032,24 @@ static int hvm_load_cpu_xsave_states(struct domain *d, hvm_domain_context_t *h)
size = HVM_CPU_XSAVE_SIZE(ctxt->xcr0_accum);
if ( desc->length > size )
{
+ /*
+ * Xen 4.3.0, 4.2.3 and older used to send longer-than-needed
+ * xsave regions. Permit loading the record if the extra data
+ * is all zero.
+ */
+ for ( i = size; i < desc->length; i++ )
+ {
+ if ( h->data[desc_start + i] )
+ {
+ printk(XENLOG_G_WARNING
+ "HVM%d.%u restore mismatch: xsave length %#x > %#x (non-zero data at %#x)\n",
+ d->domain_id, vcpuid, desc->length, size, i);
+ return -EOPNOTSUPP;
+ }
+ }
printk(XENLOG_G_WARNING
- "HVM%d.%d restore mismatch: xsave length %u > %u\n",
+ "HVM%d.%u restore mismatch: xsave length %#x > %#x\n",
d->domain_id, vcpuid, desc->length, size);
- return -EOPNOTSUPP;
}
/* Checking finished */
@@ -1121,15 +2058,125 @@ static int hvm_load_cpu_xsave_states(struct domain *d, hvm_domain_context_t *h)
if ( ctxt->xcr0_accum & XSTATE_NONLAZY )
v->arch.nonlazy_xstate_used = 1;
memcpy(v->arch.xsave_area, &ctxt->save_area,
- desc->length - offsetof(struct hvm_hw_cpu_xsave, save_area));
+ min(desc->length, size) - offsetof(struct hvm_hw_cpu_xsave,
+ save_area));
+
+ return 0;
+}
+
+#define HVM_CPU_MSR_SIZE(cnt) offsetof(struct hvm_msr, msr[cnt])
+static unsigned int __read_mostly msr_count_max;
+
+static int hvm_save_cpu_msrs(struct domain *d, hvm_domain_context_t *h)
+{
+ struct vcpu *v;
+
+ for_each_vcpu ( d, v )
+ {
+ struct hvm_msr *ctxt;
+ unsigned int i;
+
+ if ( _hvm_init_entry(h, CPU_MSR_CODE, v->vcpu_id,
+ HVM_CPU_MSR_SIZE(msr_count_max)) )
+ return 1;
+ ctxt = (struct hvm_msr *)&h->data[h->cur];
+ ctxt->count = 0;
+
+ if ( hvm_funcs.save_msr )
+ hvm_funcs.save_msr(v, ctxt);
+
+ ASSERT(ctxt->count <= msr_count_max);
+
+ for ( i = 0; i < ctxt->count; ++i )
+ ctxt->msr[i]._rsvd = 0;
+
+ if ( ctxt->count )
+ h->cur += HVM_CPU_MSR_SIZE(ctxt->count);
+ else
+ h->cur -= sizeof(struct hvm_save_descriptor);
+ }
return 0;
}
-/* We need variable length data chunk for xsave area, hence customized
- * declaration other than HVM_REGISTER_SAVE_RESTORE.
+static int hvm_load_cpu_msrs(struct domain *d, hvm_domain_context_t *h)
+{
+ unsigned int i, vcpuid = hvm_load_instance(h);
+ struct vcpu *v;
+ const struct hvm_save_descriptor *desc;
+ struct hvm_msr *ctxt;
+ int err = 0;
+
+ if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
+ {
+ dprintk(XENLOG_G_ERR, "HVM restore: dom%d has no vcpu%u\n",
+ d->domain_id, vcpuid);
+ return -EINVAL;
+ }
+
+ /* Customized checking for entry since our entry is of variable length */
+ desc = (struct hvm_save_descriptor *)&h->data[h->cur];
+ if ( sizeof (*desc) > h->size - h->cur)
+ {
+ printk(XENLOG_G_WARNING
+ "HVM%d.%d restore: not enough data left to read MSR descriptor\n",
+ d->domain_id, vcpuid);
+ return -ENODATA;
+ }
+ if ( desc->length + sizeof (*desc) > h->size - h->cur)
+ {
+ printk(XENLOG_G_WARNING
+ "HVM%d.%d restore: not enough data left to read %u MSR bytes\n",
+ d->domain_id, vcpuid, desc->length);
+ return -ENODATA;
+ }
+ if ( desc->length < HVM_CPU_MSR_SIZE(1) )
+ {
+ printk(XENLOG_G_WARNING
+ "HVM%d.%d restore mismatch: MSR length %u < %zu\n",
+ d->domain_id, vcpuid, desc->length, HVM_CPU_MSR_SIZE(1));
+ return -EINVAL;
+ }
+
+ h->cur += sizeof(*desc);
+ ctxt = (struct hvm_msr *)&h->data[h->cur];
+ h->cur += desc->length;
+
+ if ( desc->length != HVM_CPU_MSR_SIZE(ctxt->count) )
+ {
+ printk(XENLOG_G_WARNING
+ "HVM%d.%d restore mismatch: MSR length %u != %zu\n",
+ d->domain_id, vcpuid, desc->length,
+ HVM_CPU_MSR_SIZE(ctxt->count));
+ return -EOPNOTSUPP;
+ }
+
+ for ( i = 0; i < ctxt->count; ++i )
+ if ( ctxt->msr[i]._rsvd )
+ return -EOPNOTSUPP;
+ /* Checking finished */
+
+ if ( hvm_funcs.load_msr )
+ err = hvm_funcs.load_msr(v, ctxt);
+
+ for ( i = 0; !err && i < ctxt->count; ++i )
+ {
+ switch ( ctxt->msr[i].index )
+ {
+ default:
+ if ( !ctxt->msr[i]._rsvd )
+ err = -ENXIO;
+ break;
+ }
+ }
+
+ return err;
+}
+
+/* We need variable length data chunks for XSAVE area and MSRs, hence
+ * a custom declaration rather than HVM_REGISTER_SAVE_RESTORE.
*/
-static int __init __hvm_register_CPU_XSAVE_save_and_restore(void)
+static int __init hvm_register_CPU_save_and_restore(void)
{
hvm_register_savevm(CPU_XSAVE_CODE,
"CPU_XSAVE",
@@ -1138,15 +2185,27 @@ static int __init __hvm_register_CPU_XSAVE_save_and_restore(void)
HVM_CPU_XSAVE_SIZE(xfeature_mask) +
sizeof(struct hvm_save_descriptor),
HVMSR_PER_VCPU);
+
+ if ( hvm_funcs.init_msr )
+ msr_count_max += hvm_funcs.init_msr();
+
+ if ( msr_count_max )
+ hvm_register_savevm(CPU_MSR_CODE,
+ "CPU_MSR",
+ hvm_save_cpu_msrs,
+ hvm_load_cpu_msrs,
+ HVM_CPU_MSR_SIZE(msr_count_max) +
+ sizeof(struct hvm_save_descriptor),
+ HVMSR_PER_VCPU);
+
return 0;
}
-__initcall(__hvm_register_CPU_XSAVE_save_and_restore);
+__initcall(hvm_register_CPU_save_and_restore);
int hvm_vcpu_initialise(struct vcpu *v)
{
int rc;
struct domain *d = v->domain;
- domid_t dm_domid;
hvm_asid_flush_vcpu(v);
@@ -1158,8 +2217,7 @@ int hvm_vcpu_initialise(struct vcpu *v)
goto fail1;
/* NB: vlapic_init must be called before hvm_funcs.vcpu_initialise */
- if ( is_hvm_vcpu(v) )
- rc = vlapic_init(v);
+ rc = vlapic_init(v);
if ( rc != 0 ) /* teardown: vlapic_destroy */
goto fail2;
@@ -1177,7 +2235,7 @@ int hvm_vcpu_initialise(struct vcpu *v)
{
v->arch.hvm_vcpu.hcall_64bit = 1; /* PVH 32bitfixme. */
/* This is for hvm_long_mode_enabled(v). */
- v->arch.hvm_vcpu.guest_efer = EFER_SCE | EFER_LMA | EFER_LME;
+ v->arch.hvm_vcpu.guest_efer = EFER_LMA | EFER_LME;
return 0;
}
@@ -1189,35 +2247,15 @@ int hvm_vcpu_initialise(struct vcpu *v)
&& (rc = nestedhvm_vcpu_initialise(v)) < 0 ) /* teardown: nestedhvm_vcpu_destroy */
goto fail5;
- dm_domid = d->arch.hvm_domain.params[HVM_PARAM_DM_DOMAIN];
-
- /* Create ioreq event channel. */
- rc = alloc_unbound_xen_event_channel(v, dm_domid, NULL); /* teardown: none */
- if ( rc < 0 )
+ rc = hvm_all_ioreq_servers_add_vcpu(d, v);
+ if ( rc != 0 )
goto fail6;
- /* Register ioreq event channel. */
- v->arch.hvm_vcpu.xen_port = rc;
-
- if ( v->vcpu_id == 0 )
- {
- /* Create bufioreq event channel. */
- rc = alloc_unbound_xen_event_channel(v, dm_domid, NULL); /* teardown: none */
- if ( rc < 0 )
- goto fail6;
- d->arch.hvm_domain.params[HVM_PARAM_BUFIOREQ_EVTCHN] = rc;
- }
-
- spin_lock(&d->arch.hvm_domain.ioreq.lock);
- if ( d->arch.hvm_domain.ioreq.va != NULL )
- get_ioreq(v)->vp_eport = v->arch.hvm_vcpu.xen_port;
- spin_unlock(&d->arch.hvm_domain.ioreq.lock);
-
if ( v->vcpu_id == 0 )
{
/* NB. All these really belong in hvm_domain_initialise(). */
pmtimer_init(v);
- hpet_init(v);
+ hpet_init(d);
/* Init guest TSC to start from zero. */
hvm_set_guest_tsc(v, 0);
@@ -1245,6 +2283,10 @@ int hvm_vcpu_initialise(struct vcpu *v)
void hvm_vcpu_destroy(struct vcpu *v)
{
+ struct domain *d = v->domain;
+
+ hvm_all_ioreq_servers_remove_vcpu(d, v);
+
nestedhvm_vcpu_destroy(v);
free_compat_arg_xlat(v);
@@ -1256,9 +2298,6 @@ void hvm_vcpu_destroy(struct vcpu *v)
vlapic_destroy(v);
hvm_funcs.vcpu_destroy(v);
-
- /* Event channel is already freed by evtchn_destroy(). */
- /*free_xen_event_channel(v, v->arch.hvm_vcpu.xen_port);*/
}
void hvm_vcpu_down(struct vcpu *v)
@@ -1277,42 +2316,312 @@ void hvm_vcpu_down(struct vcpu *v)
online_count++;
domain_unlock(d);
- /* ... Shut down the domain if not. */
- if ( online_count == 0 )
+ /* ... Shut down the domain if not. */
+ if ( online_count == 0 )
+ {
+ gdprintk(XENLOG_INFO, "All CPUs offline -- powering off.\n");
+ domain_shutdown(d, SHUTDOWN_poweroff);
+ }
+}
+
+static struct hvm_ioreq_server *hvm_select_ioreq_server(struct domain *d,
+ ioreq_t *p)
+{
+#define CF8_BDF(cf8) (((cf8) & 0x00ffff00) >> 8)
+#define CF8_ADDR_LO(cf8) ((cf8) & 0x000000fc)
+#define CF8_ADDR_HI(cf8) (((cf8) & 0x0f000000) >> 16)
+#define CF8_ENABLED(cf8) (!!((cf8) & 0x80000000))
+
+ struct hvm_ioreq_server *s;
+ uint32_t cf8;
+ uint8_t type;
+ uint64_t addr;
+
+ if ( list_empty(&d->arch.hvm_domain.ioreq_server.list) )
+ return NULL;
+
+ if ( p->type != IOREQ_TYPE_COPY && p->type != IOREQ_TYPE_PIO )
+ return d->arch.hvm_domain.default_ioreq_server;
+
+ cf8 = d->arch.hvm_domain.pci_cf8;
+
+ if ( p->type == IOREQ_TYPE_PIO &&
+ (p->addr & ~3) == 0xcfc &&
+ CF8_ENABLED(cf8) )
+ {
+ uint32_t sbdf;
+
+ /* PCI config data cycle */
+
+ sbdf = HVMOP_PCI_SBDF(0,
+ PCI_BUS(CF8_BDF(cf8)),
+ PCI_SLOT(CF8_BDF(cf8)),
+ PCI_FUNC(CF8_BDF(cf8)));
+
+ type = IOREQ_TYPE_PCI_CONFIG;
+ addr = ((uint64_t)sbdf << 32) |
+ CF8_ADDR_HI(cf8) |
+ CF8_ADDR_LO(cf8) |
+ (p->addr & 3);
+ }
+ else
+ {
+ type = p->type;
+ addr = p->addr;
+ }
+
+ list_for_each_entry ( s,
+ &d->arch.hvm_domain.ioreq_server.list,
+ list_entry )
+ {
+ struct rangeset *r;
+
+ if ( s == d->arch.hvm_domain.default_ioreq_server )
+ continue;
+
+ if ( !s->enabled )
+ continue;
+
+ BUILD_BUG_ON(IOREQ_TYPE_PIO != HVMOP_IO_RANGE_PORT);
+ BUILD_BUG_ON(IOREQ_TYPE_COPY != HVMOP_IO_RANGE_MEMORY);
+ BUILD_BUG_ON(IOREQ_TYPE_PCI_CONFIG != HVMOP_IO_RANGE_PCI);
+ r = s->range[type];
+
+ switch ( type )
+ {
+ unsigned long end;
+
+ case IOREQ_TYPE_PIO:
+ end = addr + p->size - 1;
+ if ( rangeset_contains_range(r, addr, end) )
+ return s;
+
+ break;
+ case IOREQ_TYPE_COPY:
+ end = addr + (p->size * p->count) - 1;
+ if ( rangeset_contains_range(r, addr, end) )
+ return s;
+
+ break;
+ case IOREQ_TYPE_PCI_CONFIG:
+ if ( rangeset_contains_singleton(r, addr >> 32) )
+ {
+ p->type = type;
+ p->addr = addr;
+ return s;
+ }
+
+ break;
+ }
+ }
+
+ return d->arch.hvm_domain.default_ioreq_server;
+
+#undef CF8_ADDR_ENABLED
+#undef CF8_ADDR_HI
+#undef CF8_ADDR_LO
+#undef CF8_BDF
+}
+
+int hvm_buffered_io_send(ioreq_t *p)
+{
+ struct domain *d = current->domain;
+ struct hvm_ioreq_server *s = hvm_select_ioreq_server(d, p);
+ struct hvm_ioreq_page *iorp;
+ buffered_iopage_t *pg;
+ buf_ioreq_t bp = { .data = p->data,
+ .addr = p->addr,
+ .type = p->type,
+ .dir = p->dir };
+ /* Timeoffset sends 64b data, but no address. Use two consecutive slots. */
+ int qw = 0;
+
+ /* Ensure buffered_iopage fits in a page */
+ BUILD_BUG_ON(sizeof(buffered_iopage_t) > PAGE_SIZE);
+
+ if ( !s )
+ return 0;
+
+ iorp = &s->bufioreq;
+ pg = iorp->va;
+
+ if ( !pg )
+ return 0;
+
+ /*
+ * Return 0 for the cases we can't deal with:
+ * - 'addr' is only a 20-bit field, so we cannot address beyond 1MB
+ * - we cannot buffer accesses to guest memory buffers, as the guest
+ * may expect the memory buffer to be synchronously accessed
+ * - the count field is usually used with data_is_ptr and since we don't
+ * support data_is_ptr we do not waste space for the count field either
+ */
+ if ( (p->addr > 0xffffful) || p->data_is_ptr || (p->count != 1) )
+ return 0;
+
+ switch ( p->size )
+ {
+ case 1:
+ bp.size = 0;
+ break;
+ case 2:
+ bp.size = 1;
+ break;
+ case 4:
+ bp.size = 2;
+ break;
+ case 8:
+ bp.size = 3;
+ qw = 1;
+ break;
+ default:
+ gdprintk(XENLOG_WARNING, "unexpected ioreq size: %u\n", p->size);
+ return 0;
+ }
+
+ spin_lock(&s->bufioreq_lock);
+
+ if ( (pg->write_pointer - pg->read_pointer) >=
+ (IOREQ_BUFFER_SLOT_NUM - qw) )
+ {
+ /* The queue is full: send the iopacket through the normal path. */
+ spin_unlock(&s->bufioreq_lock);
+ return 0;
+ }
+
+ pg->buf_ioreq[pg->write_pointer % IOREQ_BUFFER_SLOT_NUM] = bp;
+
+ if ( qw )
+ {
+ bp.data = p->data >> 32;
+ pg->buf_ioreq[(pg->write_pointer+1) % IOREQ_BUFFER_SLOT_NUM] = bp;
+ }
+
+ /* Make the ioreq_t visible /before/ write_pointer. */
+ wmb();
+ pg->write_pointer += qw ? 2 : 1;
+
+ notify_via_xen_event_channel(d, s->bufioreq_evtchn);
+ spin_unlock(&s->bufioreq_lock);
+
+ return 1;
+}
+
+bool_t hvm_has_dm(struct domain *d)
+{
+ return !list_empty(&d->arch.hvm_domain.ioreq_server.list);
+}
+
+bool_t hvm_send_assist_req_to_ioreq_server(struct hvm_ioreq_server *s,
+ ioreq_t *proto_p)
+{
+ struct vcpu *curr = current;
+ struct domain *d = curr->domain;
+ struct hvm_ioreq_vcpu *sv;
+
+ if ( unlikely(!vcpu_start_shutdown_deferral(curr)) )
+ return 0; /* implicitly bins the i/o operation */
+
+ list_for_each_entry ( sv,
+ &s->ioreq_vcpu_list,
+ list_entry )
+ {
+ if ( sv->vcpu == curr )
+ {
+ evtchn_port_t port = sv->ioreq_evtchn;
+ ioreq_t *p = get_ioreq(s, curr);
+
+ if ( unlikely(p->state != STATE_IOREQ_NONE) )
+ {
+ gdprintk(XENLOG_ERR,
+ "Device model set bad IO state %d.\n",
+ p->state);
+ goto crash;
+ }
+
+ if ( unlikely(p->vp_eport != port) )
+ {
+ gdprintk(XENLOG_ERR,
+ "Device model set bad event channel %d.\n",
+ p->vp_eport);
+ goto crash;
+ }
+
+ proto_p->state = STATE_IOREQ_NONE;
+ proto_p->vp_eport = port;
+ *p = *proto_p;
+
+ prepare_wait_on_xen_event_channel(port);
+
+ /*
+ * Following happens /after/ blocking and setting up ioreq
+ * contents. prepare_wait_on_xen_event_channel() is an implicit
+ * barrier.
+ */
+ p->state = STATE_IOREQ_READY;
+ notify_via_xen_event_channel(d, port);
+ break;
+ }
+ }
+
+ return 1;
+
+ crash:
+ domain_crash(d);
+ return 0;
+}
+
+static bool_t hvm_complete_assist_req(ioreq_t *p)
+{
+ switch ( p->type )
{
- gdprintk(XENLOG_INFO, "All CPUs offline -- powering off.\n");
- domain_shutdown(d, SHUTDOWN_poweroff);
+ case IOREQ_TYPE_COPY:
+ case IOREQ_TYPE_PIO:
+ if ( p->dir == IOREQ_READ )
+ {
+ if ( !p->data_is_ptr )
+ p->data = ~0ul;
+ else
+ {
+ int i, step = p->df ? -p->size : p->size;
+ uint32_t data = ~0;
+
+ for ( i = 0; i < p->count; i++ )
+ hvm_copy_to_guest_phys(p->data + step * i, &data,
+ p->size);
+ }
+ }
+ /* FALLTHRU */
+ default:
+ p->state = STATE_IORESP_READY;
+ hvm_io_assist(p);
+ break;
}
+
+ return 1;
}
-bool_t hvm_send_assist_req(struct vcpu *v)
+bool_t hvm_send_assist_req(ioreq_t *p)
{
- ioreq_t *p;
-
- if ( unlikely(!vcpu_start_shutdown_deferral(v)) )
- return 0; /* implicitly bins the i/o operation */
+ struct hvm_ioreq_server *s = hvm_select_ioreq_server(current->domain, p);
- if ( !(p = get_ioreq(v)) )
- return 0;
+ if ( !s )
+ return hvm_complete_assist_req(p);
- if ( unlikely(p->state != STATE_IOREQ_NONE) )
- {
- /* This indicates a bug in the device model. Crash the domain. */
- gdprintk(XENLOG_ERR, "Device model set bad IO state %d.\n", p->state);
- domain_crash(v->domain);
- return 0;
- }
+ return hvm_send_assist_req_to_ioreq_server(s, p);
+}
- prepare_wait_on_xen_event_channel(v->arch.hvm_vcpu.xen_port);
+void hvm_broadcast_assist_req(ioreq_t *p)
+{
+ struct domain *d = current->domain;
+ struct hvm_ioreq_server *s;
- /*
- * Following happens /after/ blocking and setting up ioreq contents.
- * prepare_wait_on_xen_event_channel() is an implicit barrier.
- */
- p->state = STATE_IOREQ_READY;
- notify_via_xen_event_channel(v->domain, v->arch.hvm_vcpu.xen_port);
+ ASSERT(p->type == IOREQ_TYPE_INVALIDATE);
- return 1;
+ list_for_each_entry ( s,
+ &d->arch.hvm_domain.ioreq_server.list,
+ list_entry )
+ (void) hvm_send_assist_req_to_ioreq_server(s, p);
}
void hvm_hlt(unsigned long rflags)
@@ -1397,12 +2706,8 @@ void hvm_inject_page_fault(int errcode, unsigned long cr2)
hvm_inject_trap(&trap);
}
-int hvm_hap_nested_page_fault(paddr_t gpa,
- bool_t gla_valid,
- unsigned long gla,
- bool_t access_r,
- bool_t access_w,
- bool_t access_x)
+int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
+ struct npfec npfec)
{
unsigned long gfn = gpa >> PAGE_SHIFT;
p2m_type_t p2mt;
@@ -1431,8 +2736,11 @@ int hvm_hap_nested_page_fault(paddr_t gpa,
* into l1 guest if not fixable. The algorithm is
* the same as for shadow paging.
*/
- rv = nestedhvm_hap_nested_page_fault(v, &gpa,
- access_r, access_w, access_x);
+
+ rv = nestedhvm_hap_nested_page_fault(v, &gpa,
+ npfec.read_access,
+ npfec.write_access,
+ npfec.insn_fetch);
switch (rv) {
case NESTEDHVM_PAGEFAULT_DONE:
case NESTEDHVM_PAGEFAULT_RETRY:
@@ -1454,13 +2762,16 @@ int hvm_hap_nested_page_fault(paddr_t gpa,
}
}
- /* For the benefit of 32-bit WinXP (& older Windows) on AMD CPUs,
- * a fast path for LAPIC accesses, skipping the p2m lookup. */
+ /*
+ * No need to do the P2M lookup for internally handled MMIO, benefiting
+ * - 32-bit WinXP (& older Windows) on AMD CPUs for LAPIC accesses,
+ * - newer Windows (like Server 2012) for HPET accesses.
+ */
if ( !nestedhvm_vcpu_in_guestmode(v)
&& is_hvm_vcpu(v)
- && gfn == PFN_DOWN(vlapic_base_address(vcpu_vlapic(v))) )
+ && hvm_mmio_internal(gpa) )
{
- if ( !handle_mmio() )
+ if ( !handle_mmio_with_translation(gla, gpa >> PAGE_SHIFT, npfec) )
hvm_inject_hw_exception(TRAP_gp_fault, 0);
rc = 1;
goto out;
@@ -1468,47 +2779,49 @@ int hvm_hap_nested_page_fault(paddr_t gpa,
p2m = p2m_get_hostp2m(v->domain);
mfn = get_gfn_type_access(p2m, gfn, &p2mt, &p2ma,
- P2M_ALLOC | (access_w ? P2M_UNSHARE : 0), NULL);
+ P2M_ALLOC | (npfec.write_access ? P2M_UNSHARE : 0),
+ NULL);
/* Check access permissions first, then handle faults */
if ( mfn_x(mfn) != INVALID_MFN )
{
- int violation = 0;
+ bool_t violation;
+
/* If the access is against the permissions, then send to mem_event */
- switch (p2ma)
+ switch (p2ma)
{
case p2m_access_n:
case p2m_access_n2rwx:
default:
- violation = access_r || access_w || access_x;
+ violation = npfec.read_access || npfec.write_access || npfec.insn_fetch;
break;
case p2m_access_r:
- violation = access_w || access_x;
+ violation = npfec.write_access || npfec.insn_fetch;
break;
case p2m_access_w:
- violation = access_r || access_x;
+ violation = npfec.read_access || npfec.insn_fetch;
break;
case p2m_access_x:
- violation = access_r || access_w;
+ violation = npfec.read_access || npfec.write_access;
break;
case p2m_access_rx:
case p2m_access_rx2rw:
- violation = access_w;
+ violation = npfec.write_access;
break;
case p2m_access_wx:
- violation = access_r;
+ violation = npfec.read_access;
break;
case p2m_access_rw:
- violation = access_x;
+ violation = npfec.insn_fetch;
break;
case p2m_access_rwx:
+ violation = 0;
break;
}
if ( violation )
{
- if ( p2m_mem_access_check(gpa, gla_valid, gla, access_r,
- access_w, access_x, &req_ptr) )
+ if ( p2m_mem_access_check(gpa, gla, npfec, &req_ptr) )
{
fall_through = 1;
} else {
@@ -1524,7 +2837,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa,
* to the mmio handler.
*/
if ( (p2mt == p2m_mmio_dm) ||
- (access_w && (p2mt == p2m_ram_ro)) )
+ (npfec.write_access && (p2mt == p2m_ram_ro)) )
{
put_gfn(p2m->domain, gfn);
@@ -1532,7 +2845,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa,
if ( unlikely(is_pvh_vcpu(v)) )
goto out;
- if ( !handle_mmio() )
+ if ( !handle_mmio_with_translation(gla, gpa >> PAGE_SHIFT, npfec) )
hvm_inject_hw_exception(TRAP_gp_fault, 0);
rc = 1;
goto out;
@@ -1543,7 +2856,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa,
paged = 1;
/* Mem sharing: unshare the page and try again */
- if ( access_w && (p2mt == p2m_ram_shared) )
+ if ( npfec.write_access && (p2mt == p2m_ram_shared) )
{
ASSERT(!p2m_is_nestedp2m(p2m));
sharing_enomem =
@@ -1560,17 +2873,17 @@ int hvm_hap_nested_page_fault(paddr_t gpa,
* a large page, we do not change other pages type within that large
* page.
*/
- if ( access_w )
+ if ( npfec.write_access )
{
paging_mark_dirty(v->domain, mfn_x(mfn));
- p2m_change_type(v->domain, gfn, p2m_ram_logdirty, p2m_ram_rw);
+ p2m_change_type_one(v->domain, gfn, p2m_ram_logdirty, p2m_ram_rw);
}
rc = 1;
goto out_put_gfn;
}
/* Shouldn't happen: Maybe the guest was writing to a r/o grant mapping? */
- if ( access_w && (p2mt == p2m_grant_map_ro) )
+ if ( npfec.write_access && (p2mt == p2m_grant_map_ro) )
{
gdprintk(XENLOG_WARNING,
"trying to write to read-only grant mapping\n");
@@ -1688,11 +3001,6 @@ static bool_t domain_exit_uc_mode(struct vcpu *v)
return 1;
}
-static void local_flush_cache(void *info)
-{
- wbinvd();
-}
-
static void hvm_set_uc_mode(struct vcpu *v, bool_t is_in_uc_mode)
{
v->domain->arch.hvm_domain.is_in_uc_mode = is_in_uc_mode;
@@ -1792,7 +3100,7 @@ void hvm_shadow_handle_cd(struct vcpu *v, unsigned long value)
domain_pause_nosync(v->domain);
/* Flush physical caches. */
- on_each_cpu(local_flush_cache, NULL, 1);
+ flush_all(FLUSH_CACHE);
hvm_set_uc_mode(v, 1);
domain_unpause(v->domain);
@@ -1823,6 +3131,7 @@ static void hvm_update_cr(struct vcpu *v, unsigned int cr, unsigned long value)
int hvm_set_cr0(unsigned long value)
{
struct vcpu *v = current;
+ struct domain *d = v->domain;
unsigned long gfn, old_value = v->arch.hvm_vcpu.guest_cr[0];
struct page_info *page;
@@ -1846,8 +3155,8 @@ int hvm_set_cr0(unsigned long value)
goto gpf;
/* A pvh is not expected to change to real mode. */
- if ( is_pvh_vcpu(v)
- && (value & (X86_CR0_PE | X86_CR0_PG)) != (X86_CR0_PG | X86_CR0_PE) )
+ if ( is_pvh_domain(d) &&
+ (value & (X86_CR0_PE | X86_CR0_PG)) != (X86_CR0_PG | X86_CR0_PE) )
{
printk(XENLOG_G_WARNING
"PVH attempting to turn off PE/PG. CR0:%lx\n", value);
@@ -1869,16 +3178,16 @@ int hvm_set_cr0(unsigned long value)
hvm_update_guest_efer(v);
}
- if ( !paging_mode_hap(v->domain) )
+ if ( !paging_mode_hap(d) )
{
/* The guest CR3 must be pointing to the guest physical. */
gfn = v->arch.hvm_vcpu.guest_cr[3]>>PAGE_SHIFT;
- page = get_page_from_gfn(v->domain, gfn, NULL, P2M_ALLOC);
+ page = get_page_from_gfn(d, gfn, NULL, P2M_ALLOC);
if ( !page )
{
gdprintk(XENLOG_ERR, "Invalid CR3 value = %lx\n",
v->arch.hvm_vcpu.guest_cr[3]);
- domain_crash(v->domain);
+ domain_crash(d);
return X86EMUL_UNHANDLEABLE;
}
@@ -1905,24 +3214,18 @@ int hvm_set_cr0(unsigned long value)
hvm_update_guest_efer(v);
}
- if ( !paging_mode_hap(v->domain) )
+ if ( !paging_mode_hap(d) )
{
put_page(pagetable_get_page(v->arch.guest_table));
v->arch.guest_table = pagetable_null();
}
}
- /*
- * When cr0.cd setting
- * 1. For guest w/o VT-d, and for guest with VT-d but snooped, Xen need not
- * do anything, since hardware snoop mechanism has ensured cache coherency;
- * 2. For guest with VT-d but non-snooped, cache coherency cannot be
- * guaranteed by h/w so need emulate UC memory type to guest.
- */
if ( ((value ^ old_value) & X86_CR0_CD) &&
- has_arch_pdevs(v->domain) &&
- iommu_enabled && !iommu_snoop &&
- hvm_funcs.handle_cd )
+ iommu_enabled && hvm_funcs.handle_cd &&
+ (!rangeset_is_empty(d->iomem_caps) ||
+ !rangeset_is_empty(d->arch.ioport_caps) ||
+ has_arch_pdevs(d)) )
hvm_funcs.handle_cd(v, value);
hvm_update_cr(v, 0, value);
@@ -1981,7 +3284,7 @@ int hvm_set_cr4(unsigned long value)
struct vcpu *v = current;
unsigned long old_cr;
- if ( value & HVM_CR4_GUEST_RESERVED_BITS(v, 0) )
+ if ( value & hvm_cr4_guest_reserved_bits(v, 0) )
{
HVM_DBG_LOG(DBG_LEVEL_1,
"Guest attempts to set reserved bit in CR4: %lx",
@@ -2577,7 +3880,9 @@ static enum hvm_copy_result __hvm_copy(
while ( todo > 0 )
{
- count = min_t(int, PAGE_SIZE - (addr & ~PAGE_MASK), todo);
+ paddr_t gpa = addr & ~PAGE_MASK;
+
+ count = min_t(int, PAGE_SIZE - gpa, todo);
if ( flags & HVMCOPY_virt )
{
@@ -2592,16 +3897,22 @@ static enum hvm_copy_result __hvm_copy(
hvm_inject_page_fault(pfec, addr);
return HVMCOPY_bad_gva_to_gfn;
}
+ gpa |= (paddr_t)gfn << PAGE_SHIFT;
}
else
{
gfn = addr >> PAGE_SHIFT;
+ gpa = addr;
}
- /* For the benefit of 32-bit WinXP (& older Windows) on AMD CPUs,
- * a fast path for LAPIC accesses, skipping the p2m lookup. */
+ /*
+ * No need to do the P2M lookup for internally handled MMIO, benefiting
+ * - 32-bit WinXP (& older Windows) on AMD CPUs for LAPIC accesses,
+ * - newer Windows (like Server 2012) for HPET accesses.
+ */
if ( !nestedhvm_vcpu_in_guestmode(curr)
- && gfn == PFN_DOWN(vlapic_base_address(vcpu_vlapic(curr))) )
+ && is_hvm_vcpu(curr)
+ && hvm_mmio_internal(gpa) )
return HVMCOPY_bad_gfn_to_mfn;
page = get_page_from_gfn(curr->domain, gfn, &p2mt, P2M_UNSHARE);
@@ -2862,6 +4173,24 @@ unsigned long copy_from_user_hvm(void *to, const void *from, unsigned len)
return rc ? len : 0; /* fake a copy_from_user() return code */
}
+void hvm_hypervisor_cpuid_leaf(uint32_t sub_idx,
+ uint32_t *eax, uint32_t *ebx,
+ uint32_t *ecx, uint32_t *edx)
+{
+ *eax = *ebx = *ecx = *edx = 0;
+ if ( hvm_funcs.hypervisor_cpuid_leaf )
+ hvm_funcs.hypervisor_cpuid_leaf(sub_idx, eax, ebx, ecx, edx);
+
+ if ( sub_idx == 0 )
+ {
+ /*
+ * Indicate that memory mapped from other domains (either grants or
+ * foreign pages) has valid IOMMU entries.
+ */
+ *eax |= XEN_HVM_CPUID_IOMMU_MAPPINGS;
+ }
+}
+
void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
{
@@ -2915,6 +4244,15 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
if ( (count == 0) && !cpu_has_smep )
*ebx &= ~cpufeat_mask(X86_FEATURE_SMEP);
+ if ( (count == 0) && !cpu_has_smap )
+ *ebx &= ~cpufeat_mask(X86_FEATURE_SMAP);
+
+ /* Don't expose MPX to hvm when VMX support is not available */
+ if ( (count == 0) &&
+ (!(vmx_vmexit_control & VM_EXIT_CLEAR_BNDCFGS) ||
+ !(vmx_vmentry_control & VM_ENTRY_LOAD_BNDCFGS)) )
+ *ebx &= ~cpufeat_mask(X86_FEATURE_MPX);
+
/* Don't expose INVPCID to non-hap hvm. */
if ( (count == 0) && !hap_enabled(d) )
*ebx &= ~cpufeat_mask(X86_FEATURE_INVPCID);
@@ -2953,6 +4291,9 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
/* Only provide PSE36 when guest runs in 32bit PAE or in long mode */
if ( !(hvm_pae_enabled(v) || hvm_long_mode_enabled(v)) )
*edx &= ~cpufeat_mask(X86_FEATURE_PSE36);
+ /* Hide data breakpoint extensions if the hardware has no support. */
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) )
+ *ecx &= ~cpufeat_mask(X86_FEATURE_DBEXT);
break;
case 0x80000008:
@@ -3064,10 +4405,10 @@ int hvm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
index = msr - MSR_MTRRfix4K_C0000;
*msr_content = fixed_range_base[index + 3];
break;
- case MSR_IA32_MTRR_PHYSBASE0...MSR_IA32_MTRR_PHYSMASK7:
+ case MSR_IA32_MTRR_PHYSBASE(0)...MSR_IA32_MTRR_PHYSMASK(MTRR_VCNT-1):
if ( !mtrr )
goto gp_fault;
- index = msr - MSR_IA32_MTRR_PHYSBASE0;
+ index = msr - MSR_IA32_MTRR_PHYSBASE(0);
*msr_content = var_range_base[index];
break;
@@ -3141,7 +4482,9 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
break;
case MSR_IA32_APICBASE:
- vlapic_msr_set(vcpu_vlapic(v), msr_content);
+ if ( unlikely(is_pvh_vcpu(v)) ||
+ !vlapic_msr_set(vcpu_vlapic(v), msr_content) )
+ goto gp_fault;
break;
case MSR_IA32_TSC_DEADLINE:
@@ -3165,13 +4508,15 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
case MSR_MTRRdefType:
if ( !mtrr )
goto gp_fault;
- if ( !mtrr_def_type_msr_set(&v->arch.hvm_vcpu.mtrr, msr_content) )
+ if ( !mtrr_def_type_msr_set(v->domain, &v->arch.hvm_vcpu.mtrr,
+ msr_content) )
goto gp_fault;
break;
case MSR_MTRRfix64K_00000:
if ( !mtrr )
goto gp_fault;
- if ( !mtrr_fix_range_msr_set(&v->arch.hvm_vcpu.mtrr, 0, msr_content) )
+ if ( !mtrr_fix_range_msr_set(v->domain, &v->arch.hvm_vcpu.mtrr, 0,
+ msr_content) )
goto gp_fault;
break;
case MSR_MTRRfix16K_80000:
@@ -3179,7 +4524,7 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
if ( !mtrr )
goto gp_fault;
index = msr - MSR_MTRRfix16K_80000 + 1;
- if ( !mtrr_fix_range_msr_set(&v->arch.hvm_vcpu.mtrr,
+ if ( !mtrr_fix_range_msr_set(v->domain, &v->arch.hvm_vcpu.mtrr,
index, msr_content) )
goto gp_fault;
break;
@@ -3187,11 +4532,11 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
if ( !mtrr )
goto gp_fault;
index = msr - MSR_MTRRfix4K_C0000 + 3;
- if ( !mtrr_fix_range_msr_set(&v->arch.hvm_vcpu.mtrr,
+ if ( !mtrr_fix_range_msr_set(v->domain, &v->arch.hvm_vcpu.mtrr,
index, msr_content) )
goto gp_fault;
break;
- case MSR_IA32_MTRR_PHYSBASE0...MSR_IA32_MTRR_PHYSMASK7:
+ case MSR_IA32_MTRR_PHYSBASE(0)...MSR_IA32_MTRR_PHYSMASK(MTRR_VCNT-1):
if ( !mtrr )
goto gp_fault;
if ( !mtrr_var_range_msr_set(v->domain, &v->arch.hvm_vcpu.mtrr,
@@ -3315,12 +4660,6 @@ static long hvm_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
case PHYSDEVOP_irq_status_query:
case PHYSDEVOP_get_free_pirq:
return do_physdev_op(cmd, arg);
-
- /* pvh fixme: coming soon */
- case PHYSDEVOP_pirq_eoi_gmfn_v1:
- case PHYSDEVOP_pirq_eoi_gmfn_v2:
- return -ENOSYS;
-
}
}
@@ -3440,7 +4779,8 @@ static hvm_hypercall_t *const hvm_hypercall64_table[NR_hypercalls] = {
HYPERCALL(hvm_op),
HYPERCALL(sysctl),
HYPERCALL(domctl),
- HYPERCALL(tmem_op)
+ HYPERCALL(tmem_op),
+ [ __HYPERVISOR_arch_1 ] = (hvm_hypercall_t *)paging_domctl_continuation
};
#define COMPAT_CALL(x) \
@@ -3460,7 +4800,8 @@ static hvm_hypercall_t *const hvm_hypercall32_table[NR_hypercalls] = {
HYPERCALL(hvm_op),
HYPERCALL(sysctl),
HYPERCALL(domctl),
- HYPERCALL(tmem_op)
+ HYPERCALL(tmem_op),
+ [ __HYPERVISOR_arch_1 ] = (hvm_hypercall_t *)paging_domctl_continuation
};
/* PVH 32bitfixme. */
@@ -3478,7 +4819,8 @@ static hvm_hypercall_t *const pvh_hypercall64_table[NR_hypercalls] = {
[ __HYPERVISOR_physdev_op ] = (hvm_hypercall_t *)hvm_physdev_op,
HYPERCALL(hvm_op),
HYPERCALL(sysctl),
- HYPERCALL(domctl)
+ HYPERCALL(domctl),
+ [ __HYPERVISOR_arch_1 ] = (hvm_hypercall_t *)paging_domctl_continuation
};
int hvm_do_hypercall(struct cpu_user_regs *regs)
@@ -3534,10 +4876,10 @@ int hvm_do_hypercall(struct cpu_user_regs *regs)
regs->r8, regs->r9);
curr->arch.hvm_vcpu.hcall_64bit = 0;
}
+ else if ( unlikely(is_pvh_vcpu(curr)) )
+ regs->_eax = -ENOSYS; /* PVH 32bitfixme. */
else
{
- ASSERT(!is_pvh_vcpu(curr)); /* PVH 32bitfixme. */
-
HVM_DBG_LOG(DBG_LEVEL_HCALL, "hcall%u(%x, %x, %x, %x, %x, %x)", eax,
(uint32_t)regs->ebx, (uint32_t)regs->ecx,
(uint32_t)regs->edx, (uint32_t)regs->esi,
@@ -3717,7 +5059,8 @@ void hvm_vcpu_reset_state(struct vcpu *v, uint16_t cs, uint16_t ip)
/* Sync AP's TSC with BSP's. */
v->arch.hvm_vcpu.cache_tsc_offset =
v->domain->vcpu[0]->arch.hvm_vcpu.cache_tsc_offset;
- hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset);
+ hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset,
+ d->arch.hvm_domain.sync_tsc);
v->arch.hvm_vcpu.msr_tsc_adjust = 0;
@@ -3779,19 +5122,234 @@ static void hvm_s3_resume(struct domain *d)
}
}
-static int hvmop_set_isa_irq_level(
- XEN_GUEST_HANDLE_PARAM(xen_hvm_set_isa_irq_level_t) uop)
+static int hvmop_set_isa_irq_level(
+ XEN_GUEST_HANDLE_PARAM(xen_hvm_set_isa_irq_level_t) uop)
+{
+ struct xen_hvm_set_isa_irq_level op;
+ struct domain *d;
+ int rc;
+
+ if ( copy_from_guest(&op, uop, 1) )
+ return -EFAULT;
+
+ if ( op.isa_irq > 15 )
+ return -EINVAL;
+
+ rc = rcu_lock_remote_domain_by_id(op.domid, &d);
+ if ( rc != 0 )
+ return rc;
+
+ rc = -EINVAL;
+ if ( !is_hvm_domain(d) )
+ goto out;
+
+ rc = xsm_hvm_set_isa_irq_level(XSM_DM_PRIV, d);
+ if ( rc )
+ goto out;
+
+ rc = 0;
+ switch ( op.level )
+ {
+ case 0:
+ hvm_isa_irq_deassert(d, op.isa_irq);
+ break;
+ case 1:
+ hvm_isa_irq_assert(d, op.isa_irq);
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ out:
+ rcu_unlock_domain(d);
+ return rc;
+}
+
+static int hvmop_set_pci_link_route(
+ XEN_GUEST_HANDLE_PARAM(xen_hvm_set_pci_link_route_t) uop)
+{
+ struct xen_hvm_set_pci_link_route op;
+ struct domain *d;
+ int rc;
+
+ if ( copy_from_guest(&op, uop, 1) )
+ return -EFAULT;
+
+ if ( (op.link > 3) || (op.isa_irq > 15) )
+ return -EINVAL;
+
+ rc = rcu_lock_remote_domain_by_id(op.domid, &d);
+ if ( rc != 0 )
+ return rc;
+
+ rc = -EINVAL;
+ if ( !is_hvm_domain(d) )
+ goto out;
+
+ rc = xsm_hvm_set_pci_link_route(XSM_DM_PRIV, d);
+ if ( rc )
+ goto out;
+
+ rc = 0;
+ hvm_set_pci_link_route(d, op.link, op.isa_irq);
+
+ out:
+ rcu_unlock_domain(d);
+ return rc;
+}
+
+static int hvmop_inject_msi(
+ XEN_GUEST_HANDLE_PARAM(xen_hvm_inject_msi_t) uop)
+{
+ struct xen_hvm_inject_msi op;
+ struct domain *d;
+ int rc;
+
+ if ( copy_from_guest(&op, uop, 1) )
+ return -EFAULT;
+
+ rc = rcu_lock_remote_domain_by_id(op.domid, &d);
+ if ( rc != 0 )
+ return rc;
+
+ rc = -EINVAL;
+ if ( !is_hvm_domain(d) )
+ goto out;
+
+ rc = xsm_hvm_inject_msi(XSM_DM_PRIV, d);
+ if ( rc )
+ goto out;
+
+ rc = hvm_inject_msi(d, op.addr, op.data);
+
+ out:
+ rcu_unlock_domain(d);
+ return rc;
+}
+
+static int hvmop_flush_tlb_all(void)
+{
+ struct domain *d = current->domain;
+ struct vcpu *v;
+
+ if ( !is_hvm_domain(d) )
+ return -EINVAL;
+
+ /* Avoid deadlock if more than one vcpu tries this at the same time. */
+ if ( !spin_trylock(&d->hypercall_deadlock_mutex) )
+ return -ERESTART;
+
+ /* Pause all other vcpus. */
+ for_each_vcpu ( d, v )
+ if ( v != current )
+ vcpu_pause_nosync(v);
+
+ /* Now that all VCPUs are signalled to deschedule, we wait... */
+ for_each_vcpu ( d, v )
+ if ( v != current )
+ while ( !vcpu_runnable(v) && v->is_running )
+ cpu_relax();
+
+ /* All other vcpus are paused, safe to unlock now. */
+ spin_unlock(&d->hypercall_deadlock_mutex);
+
+ /* Flush paging-mode soft state (e.g., va->gfn cache; PAE PDPE cache). */
+ for_each_vcpu ( d, v )
+ paging_update_cr3(v);
+
+ /* Flush all dirty TLBs. */
+ flush_tlb_mask(d->domain_dirty_cpumask);
+
+ /* Done. */
+ for_each_vcpu ( d, v )
+ if ( v != current )
+ vcpu_unpause(v);
+
+ return 0;
+}
+
+static int hvmop_create_ioreq_server(
+ XEN_GUEST_HANDLE_PARAM(xen_hvm_create_ioreq_server_t) uop)
+{
+ struct domain *curr_d = current->domain;
+ xen_hvm_create_ioreq_server_t op;
+ struct domain *d;
+ int rc;
+
+ if ( copy_from_guest(&op, uop, 1) )
+ return -EFAULT;
+
+ rc = rcu_lock_remote_domain_by_id(op.domid, &d);
+ if ( rc != 0 )
+ return rc;
+
+ rc = -EINVAL;
+ if ( !is_hvm_domain(d) )
+ goto out;
+
+ rc = xsm_hvm_ioreq_server(XSM_DM_PRIV, d, HVMOP_create_ioreq_server);
+ if ( rc != 0 )
+ goto out;
+
+ rc = hvm_create_ioreq_server(d, curr_d->domain_id, 0,
+ !!op.handle_bufioreq, &op.id);
+ if ( rc != 0 )
+ goto out;
+
+ rc = copy_to_guest(uop, &op, 1) ? -EFAULT : 0;
+
+ out:
+ rcu_unlock_domain(d);
+ return rc;
+}
+
+static int hvmop_get_ioreq_server_info(
+ XEN_GUEST_HANDLE_PARAM(xen_hvm_get_ioreq_server_info_t) uop)
+{
+ xen_hvm_get_ioreq_server_info_t op;
+ struct domain *d;
+ int rc;
+
+ if ( copy_from_guest(&op, uop, 1) )
+ return -EFAULT;
+
+ rc = rcu_lock_remote_domain_by_id(op.domid, &d);
+ if ( rc != 0 )
+ return rc;
+
+ rc = -EINVAL;
+ if ( !is_hvm_domain(d) )
+ goto out;
+
+ rc = xsm_hvm_ioreq_server(XSM_DM_PRIV, d, HVMOP_get_ioreq_server_info);
+ if ( rc != 0 )
+ goto out;
+
+ rc = hvm_get_ioreq_server_info(d, op.id,
+ &op.ioreq_pfn,
+ &op.bufioreq_pfn,
+ &op.bufioreq_port);
+ if ( rc != 0 )
+ goto out;
+
+ rc = copy_to_guest(uop, &op, 1) ? -EFAULT : 0;
+
+ out:
+ rcu_unlock_domain(d);
+ return rc;
+}
+
+static int hvmop_map_io_range_to_ioreq_server(
+ XEN_GUEST_HANDLE_PARAM(xen_hvm_io_range_t) uop)
{
- struct xen_hvm_set_isa_irq_level op;
+ xen_hvm_io_range_t op;
struct domain *d;
int rc;
if ( copy_from_guest(&op, uop, 1) )
return -EFAULT;
- if ( op.isa_irq > 15 )
- return -EINVAL;
-
rc = rcu_lock_remote_domain_by_id(op.domid, &d);
if ( rc != 0 )
return rc;
@@ -3800,42 +5358,28 @@ static int hvmop_set_isa_irq_level(
if ( !is_hvm_domain(d) )
goto out;
- rc = xsm_hvm_set_isa_irq_level(XSM_DM_PRIV, d);
- if ( rc )
+ rc = xsm_hvm_ioreq_server(XSM_DM_PRIV, d, HVMOP_map_io_range_to_ioreq_server);
+ if ( rc != 0 )
goto out;
- rc = 0;
- switch ( op.level )
- {
- case 0:
- hvm_isa_irq_deassert(d, op.isa_irq);
- break;
- case 1:
- hvm_isa_irq_assert(d, op.isa_irq);
- break;
- default:
- rc = -EINVAL;
- break;
- }
+ rc = hvm_map_io_range_to_ioreq_server(d, op.id, op.type,
+ op.start, op.end);
out:
rcu_unlock_domain(d);
return rc;
}
-static int hvmop_set_pci_link_route(
- XEN_GUEST_HANDLE_PARAM(xen_hvm_set_pci_link_route_t) uop)
+static int hvmop_unmap_io_range_from_ioreq_server(
+ XEN_GUEST_HANDLE_PARAM(xen_hvm_io_range_t) uop)
{
- struct xen_hvm_set_pci_link_route op;
+ xen_hvm_io_range_t op;
struct domain *d;
int rc;
if ( copy_from_guest(&op, uop, 1) )
return -EFAULT;
- if ( (op.link > 3) || (op.isa_irq > 15) )
- return -EINVAL;
-
rc = rcu_lock_remote_domain_by_id(op.domid, &d);
if ( rc != 0 )
return rc;
@@ -3844,22 +5388,22 @@ static int hvmop_set_pci_link_route(
if ( !is_hvm_domain(d) )
goto out;
- rc = xsm_hvm_set_pci_link_route(XSM_DM_PRIV, d);
- if ( rc )
+ rc = xsm_hvm_ioreq_server(XSM_DM_PRIV, d, HVMOP_unmap_io_range_from_ioreq_server);
+ if ( rc != 0 )
goto out;
- rc = 0;
- hvm_set_pci_link_route(d, op.link, op.isa_irq);
-
+ rc = hvm_unmap_io_range_from_ioreq_server(d, op.id, op.type,
+ op.start, op.end);
+
out:
rcu_unlock_domain(d);
return rc;
}
-static int hvmop_inject_msi(
- XEN_GUEST_HANDLE_PARAM(xen_hvm_inject_msi_t) uop)
+static int hvmop_set_ioreq_server_state(
+ XEN_GUEST_HANDLE_PARAM(xen_hvm_set_ioreq_server_state_t) uop)
{
- struct xen_hvm_inject_msi op;
+ xen_hvm_set_ioreq_server_state_t op;
struct domain *d;
int rc;
@@ -3874,86 +5418,91 @@ static int hvmop_inject_msi(
if ( !is_hvm_domain(d) )
goto out;
- rc = xsm_hvm_inject_msi(XSM_DM_PRIV, d);
- if ( rc )
+ rc = xsm_hvm_ioreq_server(XSM_DM_PRIV, d, HVMOP_set_ioreq_server_state);
+ if ( rc != 0 )
goto out;
- hvm_inject_msi(d, op.addr, op.data);
+ rc = hvm_set_ioreq_server_state(d, op.id, !!op.enabled);
out:
rcu_unlock_domain(d);
return rc;
}
-static int hvmop_flush_tlb_all(void)
+static int hvmop_destroy_ioreq_server(
+ XEN_GUEST_HANDLE_PARAM(xen_hvm_destroy_ioreq_server_t) uop)
{
- struct domain *d = current->domain;
- struct vcpu *v;
-
- if ( !is_hvm_domain(d) )
- return -EINVAL;
-
- /* Avoid deadlock if more than one vcpu tries this at the same time. */
- if ( !spin_trylock(&d->hypercall_deadlock_mutex) )
- return -EAGAIN;
-
- /* Pause all other vcpus. */
- for_each_vcpu ( d, v )
- if ( v != current )
- vcpu_pause_nosync(v);
+ xen_hvm_destroy_ioreq_server_t op;
+ struct domain *d;
+ int rc;
- /* Now that all VCPUs are signalled to deschedule, we wait... */
- for_each_vcpu ( d, v )
- if ( v != current )
- while ( !vcpu_runnable(v) && v->is_running )
- cpu_relax();
+ if ( copy_from_guest(&op, uop, 1) )
+ return -EFAULT;
- /* All other vcpus are paused, safe to unlock now. */
- spin_unlock(&d->hypercall_deadlock_mutex);
+ rc = rcu_lock_remote_domain_by_id(op.domid, &d);
+ if ( rc != 0 )
+ return rc;
- /* Flush paging-mode soft state (e.g., va->gfn cache; PAE PDPE cache). */
- for_each_vcpu ( d, v )
- paging_update_cr3(v);
+ rc = -EINVAL;
+ if ( !is_hvm_domain(d) )
+ goto out;
- /* Flush all dirty TLBs. */
- flush_tlb_mask(d->domain_dirty_cpumask);
+ rc = xsm_hvm_ioreq_server(XSM_DM_PRIV, d, HVMOP_destroy_ioreq_server);
+ if ( rc != 0 )
+ goto out;
- /* Done. */
- for_each_vcpu ( d, v )
- if ( v != current )
- vcpu_unpause(v);
+ rc = hvm_destroy_ioreq_server(d, op.id);
- return 0;
+ out:
+ rcu_unlock_domain(d);
+ return rc;
}
-static int hvm_replace_event_channel(struct vcpu *v, domid_t remote_domid,
- int *p_port)
-{
- int old_port, new_port;
-
- new_port = alloc_unbound_xen_event_channel(v, remote_domid, NULL);
- if ( new_port < 0 )
- return new_port;
-
- /* xchg() ensures that only we call free_xen_event_channel(). */
- old_port = xchg(p_port, new_port);
- free_xen_event_channel(v, old_port);
- return 0;
-}
+#define HVMOP_op_mask 0xff
long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
{
struct domain *curr_d = current->domain;
+ unsigned long start_iter = op & ~HVMOP_op_mask;
long rc = 0;
- switch ( op )
+ switch ( op &= HVMOP_op_mask )
{
+ case HVMOP_create_ioreq_server:
+ rc = hvmop_create_ioreq_server(
+ guest_handle_cast(arg, xen_hvm_create_ioreq_server_t));
+ break;
+
+ case HVMOP_get_ioreq_server_info:
+ rc = hvmop_get_ioreq_server_info(
+ guest_handle_cast(arg, xen_hvm_get_ioreq_server_info_t));
+ break;
+
+ case HVMOP_map_io_range_to_ioreq_server:
+ rc = hvmop_map_io_range_to_ioreq_server(
+ guest_handle_cast(arg, xen_hvm_io_range_t));
+ break;
+
+ case HVMOP_unmap_io_range_from_ioreq_server:
+ rc = hvmop_unmap_io_range_from_ioreq_server(
+ guest_handle_cast(arg, xen_hvm_io_range_t));
+ break;
+
+ case HVMOP_set_ioreq_server_state:
+ rc = hvmop_set_ioreq_server_state(
+ guest_handle_cast(arg, xen_hvm_set_ioreq_server_state_t));
+ break;
+
+ case HVMOP_destroy_ioreq_server:
+ rc = hvmop_destroy_ioreq_server(
+ guest_handle_cast(arg, xen_hvm_destroy_ioreq_server_t));
+ break;
+
case HVMOP_set_param:
case HVMOP_get_param:
{
struct xen_hvm_param a;
- struct hvm_ioreq_page *iorp;
struct domain *d;
struct vcpu *v;
@@ -3985,21 +5534,6 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
switch ( a.index )
{
- case HVM_PARAM_IOREQ_PFN:
- iorp = &d->arch.hvm_domain.ioreq;
- if ( (rc = hvm_set_ioreq_page(d, iorp, a.value)) != 0 )
- break;
- spin_lock(&iorp->lock);
- if ( iorp->va != NULL )
- /* Initialise evtchn port info if VCPUs already created. */
- for_each_vcpu ( d, v )
- get_ioreq(v)->vp_eport = v->arch.hvm_vcpu.xen_port;
- spin_unlock(&iorp->lock);
- break;
- case HVM_PARAM_BUFIOREQ_PFN:
- iorp = &d->arch.hvm_domain.buf_ioreq;
- rc = hvm_set_ioreq_page(d, iorp, a.value);
- break;
case HVM_PARAM_CALLBACK_IRQ:
hvm_set_callback_via(d, a.value);
hvm_latch_shinfo_size(d);
@@ -4009,8 +5543,24 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
rc = -EINVAL;
break;
case HVM_PARAM_VIRIDIAN:
- if ( a.value > 1 )
+ /* This should only ever be set once by the tools and read by the guest. */
+ rc = -EPERM;
+ if ( curr_d == d )
+ break;
+
+ if ( a.value != d->arch.hvm_domain.params[a.index] )
+ {
+ rc = -EEXIST;
+ if ( d->arch.hvm_domain.params[a.index] != 0 )
+ break;
+
rc = -EINVAL;
+ if ( (a.value & ~HVMPV_feature_mask) ||
+ !(a.value & HVMPV_base_freq) )
+ break;
+ }
+
+ rc = 0;
break;
case HVM_PARAM_IDENT_PT:
/* Not reflexive, as we must domain_pause(). */
@@ -4031,7 +5581,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
* All foreign updates to guest state must synchronise on
* the domctl_lock.
*/
- rc = -EAGAIN;
+ rc = -ERESTART;
if ( !domctl_lock_acquire() )
break;
@@ -4045,7 +5595,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
domctl_lock_release();
break;
case HVM_PARAM_DM_DOMAIN:
- /* Not reflexive, as we must domain_pause(). */
+ /* Not reflexive, as we may need to domain_pause(). */
rc = -EPERM;
if ( curr_d == d )
break;
@@ -4053,31 +5603,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
if ( a.value == DOMID_SELF )
a.value = curr_d->domain_id;
- rc = 0;
- domain_pause(d); /* safe to change per-vcpu xen_port */
- if ( d->vcpu[0] )
- rc = hvm_replace_event_channel(d->vcpu[0], a.value,
- (int *)&d->vcpu[0]->domain->arch.hvm_domain.params
- [HVM_PARAM_BUFIOREQ_EVTCHN]);
- if ( rc )
- {
- domain_unpause(d);
- break;
- }
- iorp = &d->arch.hvm_domain.ioreq;
- for_each_vcpu ( d, v )
- {
- rc = hvm_replace_event_channel(v, a.value,
- &v->arch.hvm_vcpu.xen_port);
- if ( rc )
- break;
-
- spin_lock(&iorp->lock);
- if ( iorp->va != NULL )
- get_ioreq(v)->vp_eport = v->arch.hvm_vcpu.xen_port;
- spin_unlock(&iorp->lock);
- }
- domain_unpause(d);
+ rc = hvm_set_dm_domain(d, a.value);
break;
case HVM_PARAM_ACPI_S_STATE:
/* Not reflexive, as we must domain_pause(). */
@@ -4142,6 +5668,34 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
if ( a.value > SHUTDOWN_MAX )
rc = -EINVAL;
break;
+ case HVM_PARAM_IOREQ_SERVER_PFN:
+ if ( d == current->domain )
+ {
+ rc = -EPERM;
+ break;
+ }
+ d->arch.hvm_domain.ioreq_gmfn.base = a.value;
+ break;
+ case HVM_PARAM_NR_IOREQ_SERVER_PAGES:
+ {
+ unsigned int i;
+
+ if ( d == current->domain )
+ {
+ rc = -EPERM;
+ break;
+ }
+ if ( a.value == 0 ||
+ a.value > sizeof(d->arch.hvm_domain.ioreq_gmfn.mask) * 8 )
+ {
+ rc = -EINVAL;
+ break;
+ }
+ for ( i = 0; i < a.value; i++ )
+ set_bit(i, &d->arch.hvm_domain.ioreq_gmfn.mask);
+
+ break;
+ }
}
if ( rc == 0 )
@@ -4175,11 +5729,30 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
case HVM_PARAM_ACPI_S_STATE:
a.value = d->arch.hvm_domain.is_s3_suspended ? 3 : 0;
break;
+ case HVM_PARAM_IOREQ_SERVER_PFN:
+ case HVM_PARAM_NR_IOREQ_SERVER_PAGES:
+ if ( d == current->domain )
+ {
+ rc = -EPERM;
+ break;
+ }
+ case HVM_PARAM_IOREQ_PFN:
+ case HVM_PARAM_BUFIOREQ_PFN:
+ case HVM_PARAM_BUFIOREQ_EVTCHN: {
+ domid_t domid;
+
+ /* May need to create server */
+ domid = d->arch.hvm_domain.params[HVM_PARAM_DM_DOMAIN];
+ rc = hvm_create_ioreq_server(d, domid, 1, 1, NULL);
+ if ( rc != 0 && rc != -EEXIST )
+ goto param_fail;
+ /*FALLTHRU*/
+ }
default:
a.value = d->arch.hvm_domain.params[a.index];
break;
}
- rc = copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
+ rc = __copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
}
HVM_DBG_LOG(DBG_LEVEL_HCALL, "%s param %u = %"PRIx64,
@@ -4234,7 +5807,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
if ( a.nr > GB(1) >> PAGE_SHIFT )
goto param_fail2;
- rc = xsm_hvm_param(XSM_TARGET, d, op);
+ rc = xsm_hvm_control(XSM_DM_PRIV, d, op);
if ( rc )
goto param_fail2;
@@ -4272,12 +5845,12 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
if ( !is_hvm_domain(d) )
goto param_fail3;
- rc = xsm_hvm_param(XSM_TARGET, d, op);
+ rc = xsm_hvm_control(XSM_DM_PRIV, d, op);
if ( rc )
goto param_fail3;
rc = -EINVAL;
- if ( (a.first_pfn > domain_get_maximum_gpfn(d)) ||
+ if ( a.nr < start_iter ||
((a.first_pfn + a.nr - 1) < a.first_pfn) ||
((a.first_pfn + a.nr - 1) > domain_get_maximum_gpfn(d)) )
goto param_fail3;
@@ -4286,9 +5859,9 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
if ( !paging_mode_log_dirty(d) )
goto param_fail3;
- while ( a.nr > 0 )
+ while ( a.nr > start_iter )
{
- unsigned long pfn = a.first_pfn;
+ unsigned long pfn = a.first_pfn + start_iter;
struct page_info *page;
page = get_page_from_gfn(d, pfn, NULL, P2M_UNSHARE);
@@ -4301,16 +5874,11 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
put_page(page);
}
- a.first_pfn++;
- a.nr--;
-
/* Check for continuation if it's not the last interation */
- if ( a.nr > 0 && hypercall_preempt_check() )
+ if ( a.nr > ++start_iter && !(start_iter & HVMOP_op_mask) &&
+ hypercall_preempt_check() )
{
- if ( copy_to_guest(arg, &a, 1) )
- rc = -EFAULT;
- else
- rc = -EAGAIN;
+ rc = -ERESTART;
break;
}
}
@@ -4356,7 +5924,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
a.mem_type = HVMMEM_ram_rw;
else
a.mem_type = HVMMEM_mmio_dm;
- rc = copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
+ rc = __copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
}
param_fail_getmemtype:
@@ -4387,12 +5955,12 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
if ( !is_hvm_domain(d) )
goto param_fail4;
- rc = xsm_hvm_param(XSM_TARGET, d, op);
+ rc = xsm_hvm_control(XSM_DM_PRIV, d, op);
if ( rc )
goto param_fail4;
rc = -EINVAL;
- if ( (a.first_pfn > domain_get_maximum_gpfn(d)) ||
+ if ( a.nr < start_iter ||
((a.first_pfn + a.nr - 1) < a.first_pfn) ||
((a.first_pfn + a.nr - 1) > domain_get_maximum_gpfn(d)) )
goto param_fail4;
@@ -4400,57 +5968,42 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
if ( a.hvmmem_type >= ARRAY_SIZE(memtype) )
goto param_fail4;
- while ( a.nr )
+ while ( a.nr > start_iter )
{
- unsigned long pfn = a.first_pfn;
+ unsigned long pfn = a.first_pfn + start_iter;
p2m_type_t t;
- p2m_type_t nt;
- mfn_t mfn;
- mfn = get_gfn_unshare(d, pfn, &t);
+
+ get_gfn_unshare(d, pfn, &t);
if ( p2m_is_paging(t) )
{
put_gfn(d, pfn);
p2m_mem_paging_populate(d, pfn);
- rc = -EINVAL;
+ rc = -EAGAIN;
goto param_fail4;
}
if ( p2m_is_shared(t) )
{
put_gfn(d, pfn);
- rc = -EINVAL;
+ rc = -EAGAIN;
goto param_fail4;
- }
+ }
if ( !p2m_is_ram(t) &&
(!p2m_is_hole(t) || a.hvmmem_type != HVMMEM_mmio_dm) )
{
put_gfn(d, pfn);
goto param_fail4;
}
- else
- {
- nt = p2m_change_type(d, pfn, t, memtype[a.hvmmem_type]);
- if ( nt != t )
- {
- put_gfn(d, pfn);
- gdprintk(XENLOG_WARNING,
- "type of pfn %#lx changed from %d to %d while "
- "we were trying to change it to %d\n",
- pfn, t, nt, memtype[a.hvmmem_type]);
- goto param_fail4;
- }
- }
- put_gfn(d, pfn);
- a.first_pfn++;
- a.nr--;
+ rc = p2m_change_type_one(d, pfn, t, memtype[a.hvmmem_type]);
+ put_gfn(d, pfn);
+ if ( rc )
+ goto param_fail4;
/* Check for continuation if it's not the last interation */
- if ( a.nr > 0 && hypercall_preempt_check() )
+ if ( a.nr > ++start_iter && !(start_iter & HVMOP_op_mask) &&
+ hypercall_preempt_check() )
{
- if ( copy_to_guest(arg, &a, 1) )
- rc = -EFAULT;
- else
- rc = -EAGAIN;
+ rc = -ERESTART;
goto param_fail4;
}
}
@@ -4462,86 +6015,6 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
break;
}
- case HVMOP_set_mem_access:
- {
- struct xen_hvm_set_mem_access a;
- struct domain *d;
-
- if ( copy_from_guest(&a, arg, 1) )
- return -EFAULT;
-
- rc = rcu_lock_remote_domain_by_id(a.domid, &d);
- if ( rc != 0 )
- return rc;
-
- rc = -EINVAL;
- if ( !is_hvm_domain(d) )
- goto param_fail5;
-
- rc = xsm_hvm_param(XSM_TARGET, d, op);
- if ( rc )
- goto param_fail5;
-
- rc = -EINVAL;
- if ( (a.first_pfn != ~0ull) &&
- ((a.first_pfn > domain_get_maximum_gpfn(d)) ||
- ((a.first_pfn + a.nr - 1) < a.first_pfn) ||
- ((a.first_pfn + a.nr - 1) > domain_get_maximum_gpfn(d))) )
- goto param_fail5;
-
- rc = p2m_set_mem_access(d, a.first_pfn, a.nr, a.hvmmem_access);
- if ( rc > 0 )
- {
- a.first_pfn += a.nr - rc;
- a.nr = rc;
- if ( __copy_to_guest(arg, &a, 1) )
- rc = -EFAULT;
- else
- rc = -EAGAIN;
- }
-
- param_fail5:
- rcu_unlock_domain(d);
- break;
- }
-
- case HVMOP_get_mem_access:
- {
- struct xen_hvm_get_mem_access a;
- struct domain *d;
- hvmmem_access_t access;
-
- if ( copy_from_guest(&a, arg, 1) )
- return -EFAULT;
-
- rc = rcu_lock_remote_domain_by_id(a.domid, &d);
- if ( rc != 0 )
- return rc;
-
- rc = -EINVAL;
- if ( !is_hvm_domain(d) )
- goto param_fail6;
-
- rc = xsm_hvm_param(XSM_TARGET, d, op);
- if ( rc )
- goto param_fail6;
-
- rc = -EINVAL;
- if ( (a.pfn > domain_get_maximum_gpfn(d)) && a.pfn != ~0ull )
- goto param_fail6;
-
- rc = p2m_get_mem_access(d, a.pfn, &access);
- if ( rc != 0 )
- goto param_fail6;
-
- a.hvmmem_access = access;
- rc = copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
-
- param_fail6:
- rcu_unlock_domain(d);
- break;
- }
-
case HVMOP_pagetable_dying:
{
struct xen_hvm_pagetable_dying a;
@@ -4612,7 +6085,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
if ( !is_hvm_domain(d) )
goto param_fail8;
- rc = xsm_hvm_param(XSM_TARGET, d, op);
+ rc = xsm_hvm_control(XSM_DM_PRIV, d, op);
if ( rc )
goto param_fail8;
@@ -4645,9 +6118,12 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
}
}
- if ( rc == -EAGAIN )
- rc = hypercall_create_continuation(
- __HYPERVISOR_hvm_op, "lh", op, arg);
+ if ( rc == -ERESTART )
+ {
+ ASSERT(!(start_iter & HVMOP_op_mask));
+ rc = hypercall_create_continuation(__HYPERVISOR_hvm_op, "lh",
+ op | start_iter, arg);
+ }
return rc;
}
@@ -4677,6 +6153,38 @@ int hvm_debug_op(struct vcpu *v, int32_t op)
return rc;
}
+static void hvm_mem_event_fill_regs(mem_event_request_t *req)
+{
+ const struct cpu_user_regs *regs = guest_cpu_user_regs();
+ const struct vcpu *curr = current;
+
+ req->x86_regs.rax = regs->eax;
+ req->x86_regs.rcx = regs->ecx;
+ req->x86_regs.rdx = regs->edx;
+ req->x86_regs.rbx = regs->ebx;
+ req->x86_regs.rsp = regs->esp;
+ req->x86_regs.rbp = regs->ebp;
+ req->x86_regs.rsi = regs->esi;
+ req->x86_regs.rdi = regs->edi;
+
+ req->x86_regs.r8 = regs->r8;
+ req->x86_regs.r9 = regs->r9;
+ req->x86_regs.r10 = regs->r10;
+ req->x86_regs.r11 = regs->r11;
+ req->x86_regs.r12 = regs->r12;
+ req->x86_regs.r13 = regs->r13;
+ req->x86_regs.r14 = regs->r14;
+ req->x86_regs.r15 = regs->r15;
+
+ req->x86_regs.rflags = regs->eflags;
+ req->x86_regs.rip = regs->eip;
+
+ req->x86_regs.msr_efer = curr->arch.hvm_vcpu.guest_efer;
+ req->x86_regs.cr0 = curr->arch.hvm_vcpu.guest_cr[0];
+ req->x86_regs.cr3 = curr->arch.hvm_vcpu.guest_cr[3];
+ req->x86_regs.cr4 = curr->arch.hvm_vcpu.guest_cr[4];
+}
+
static int hvm_memory_event_traps(long p, uint32_t reason,
unsigned long value, unsigned long old,
bool_t gla_valid, unsigned long gla)
@@ -4716,7 +6224,12 @@ static int hvm_memory_event_traps(long p, uint32_t reason,
req.gla = gla;
req.gla_valid = 1;
}
+ else
+ {
+ req.gla = old;
+ }
+ hvm_mem_event_fill_regs(&req);
mem_event_put_request(d, &d->mem_event->access, &req);
return 1;
diff --git a/xen/arch/x86/hvm/i8254.c b/xen/arch/x86/hvm/i8254.c
index f7493b8..3ec01c0 100644
--- a/xen/arch/x86/hvm/i8254.c
+++ b/xen/arch/x86/hvm/i8254.c
@@ -31,6 +31,7 @@
#include <xen/lib.h>
#include <xen/errno.h>
#include <xen/sched.h>
+#include <xen/trace.h>
#include <asm/time.h>
#include <asm/hvm/hvm.h>
#include <asm/hvm/io.h>
@@ -159,6 +160,7 @@ static int pit_get_gate(PITState *pit, int channel)
static void pit_time_fired(struct vcpu *v, void *priv)
{
uint64_t *count_load_time = priv;
+ TRACE_0D(TRC_HVM_EMUL_PIT_TIMER_CB);
*count_load_time = get_guest_time(v);
}
@@ -188,16 +190,19 @@ static void pit_load_count(PITState *pit, int channel, int val)
case 2:
case 3:
/* Periodic timer. */
+ TRACE_2D(TRC_HVM_EMUL_PIT_START_TIMER, period, period);
create_periodic_time(v, &pit->pt0, period, period, 0, pit_time_fired,
&pit->count_load_time[channel]);
break;
case 1:
case 4:
/* One-shot timer. */
+ TRACE_2D(TRC_HVM_EMUL_PIT_START_TIMER, period, 0);
create_periodic_time(v, &pit->pt0, period, 0, 0, pit_time_fired,
&pit->count_load_time[channel]);
break;
default:
+ TRACE_0D(TRC_HVM_EMUL_PIT_STOP_TIMER);
destroy_periodic_time(&pit->pt0);
break;
}
@@ -377,6 +382,7 @@ static uint32_t pit_ioport_read(struct PITState *pit, uint32_t addr)
void pit_stop_channel0_irq(PITState *pit)
{
+ TRACE_0D(TRC_HVM_EMUL_PIT_STOP_TIMER);
spin_lock(&pit->lock);
destroy_periodic_time(&pit->pt0);
spin_unlock(&pit->lock);
@@ -431,6 +437,7 @@ void pit_reset(struct domain *d)
struct hvm_hw_pit_channel *s;
int i;
+ TRACE_0D(TRC_HVM_EMUL_PIT_STOP_TIMER);
destroy_periodic_time(&pit->pt0);
pit->pt0.source = PTSRC_isa;
@@ -465,6 +472,8 @@ void pit_init(struct domain *d, unsigned long cpu_khz)
void pit_deinit(struct domain *d)
{
PITState *pit = domain_vpit(d);
+
+ TRACE_0D(TRC_HVM_EMUL_PIT_STOP_TIMER);
destroy_periodic_time(&pit->pt0);
}
@@ -540,7 +549,7 @@ int pv_pit_handler(int port, int data, int write)
.data = data
};
- if ( (current->domain->domain_id == 0) && dom0_pit_access(&ioreq) )
+ if ( is_hardware_domain(current->domain) && hwdom_pit_access(&ioreq) )
{
/* nothing to do */;
}
@@ -556,3 +565,12 @@ int pv_pit_handler(int port, int data, int write)
return !write ? ioreq.data : 0;
}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c
index 7cc13b5..d52a48c 100644
--- a/xen/arch/x86/hvm/intercept.c
+++ b/xen/arch/x86/hvm/intercept.c
@@ -163,17 +163,42 @@ static int hvm_mmio_access(struct vcpu *v,
return rc;
}
+bool_t hvm_mmio_internal(paddr_t gpa)
+{
+ struct vcpu *curr = current;
+ unsigned int i;
+
+ for ( i = 0; i < HVM_MMIO_HANDLER_NR; ++i )
+ if ( hvm_mmio_handlers[i]->check_handler(curr, gpa) )
+ return 1;
+
+ return 0;
+}
+
int hvm_mmio_intercept(ioreq_t *p)
{
struct vcpu *v = current;
int i;
for ( i = 0; i < HVM_MMIO_HANDLER_NR; i++ )
- if ( hvm_mmio_handlers[i]->check_handler(v, p->addr) )
+ {
+ hvm_mmio_check_t check_handler =
+ hvm_mmio_handlers[i]->check_handler;
+
+ if ( check_handler(v, p->addr) )
+ {
+ if ( unlikely(p->count > 1) &&
+ !check_handler(v, unlikely(p->df)
+ ? p->addr - (p->count - 1L) * p->size
+ : p->addr + (p->count - 1L) * p->size) )
+ p->count = 1;
+
return hvm_mmio_access(
v, p,
hvm_mmio_handlers[i]->read_handler,
hvm_mmio_handlers[i]->write_handler);
+ }
+ }
return X86EMUL_UNHANDLEABLE;
}
@@ -330,6 +355,13 @@ int hvm_io_intercept(ioreq_t *p, int type)
if ( type == HVM_PORTIO )
return process_portio_intercept(
handler->hdl_list[i].action.portio, p);
+
+ if ( unlikely(p->count > 1) &&
+ (unlikely(p->df)
+ ? p->addr - (p->count - 1L) * p->size < addr
+ : p->addr + p->count * 1L * p->size - 1 >= addr + size) )
+ p->count = 1;
+
return handler->hdl_list[i].action.mmio(p);
}
}
diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
index 247fb7e..68fb890 100644
--- a/xen/arch/x86/hvm/io.c
+++ b/xen/arch/x86/hvm/io.c
@@ -46,129 +46,35 @@
#include <xen/iocap.h>
#include <public/hvm/ioreq.h>
-int hvm_buffered_io_send(ioreq_t *p)
-{
- struct vcpu *v = current;
- struct hvm_ioreq_page *iorp = &v->domain->arch.hvm_domain.buf_ioreq;
- buffered_iopage_t *pg = iorp->va;
- buf_ioreq_t bp;
- /* Timeoffset sends 64b data, but no address. Use two consecutive slots. */
- int qw = 0;
-
- /* Ensure buffered_iopage fits in a page */
- BUILD_BUG_ON(sizeof(buffered_iopage_t) > PAGE_SIZE);
-
- /*
- * Return 0 for the cases we can't deal with:
- * - 'addr' is only a 20-bit field, so we cannot address beyond 1MB
- * - we cannot buffer accesses to guest memory buffers, as the guest
- * may expect the memory buffer to be synchronously accessed
- * - the count field is usually used with data_is_ptr and since we don't
- * support data_is_ptr we do not waste space for the count field either
- */
- if ( (p->addr > 0xffffful) || p->data_is_ptr || (p->count != 1) )
- return 0;
-
- bp.type = p->type;
- bp.dir = p->dir;
- switch ( p->size )
- {
- case 1:
- bp.size = 0;
- break;
- case 2:
- bp.size = 1;
- break;
- case 4:
- bp.size = 2;
- break;
- case 8:
- bp.size = 3;
- qw = 1;
- break;
- default:
- gdprintk(XENLOG_WARNING, "unexpected ioreq size: %u\n", p->size);
- return 0;
- }
-
- bp.data = p->data;
- bp.addr = p->addr;
-
- spin_lock(&iorp->lock);
-
- if ( (pg->write_pointer - pg->read_pointer) >=
- (IOREQ_BUFFER_SLOT_NUM - qw) )
- {
- /* The queue is full: send the iopacket through the normal path. */
- spin_unlock(&iorp->lock);
- return 0;
- }
-
- memcpy(&pg->buf_ioreq[pg->write_pointer % IOREQ_BUFFER_SLOT_NUM],
- &bp, sizeof(bp));
-
- if ( qw )
- {
- bp.data = p->data >> 32;
- memcpy(&pg->buf_ioreq[(pg->write_pointer+1) % IOREQ_BUFFER_SLOT_NUM],
- &bp, sizeof(bp));
- }
-
- /* Make the ioreq_t visible /before/ write_pointer. */
- wmb();
- pg->write_pointer += qw ? 2 : 1;
-
- notify_via_xen_event_channel(v->domain,
- v->domain->arch.hvm_domain.params[HVM_PARAM_BUFIOREQ_EVTCHN]);
- spin_unlock(&iorp->lock);
-
- return 1;
-}
-
void send_timeoffset_req(unsigned long timeoff)
{
- ioreq_t p[1];
+ ioreq_t p = {
+ .type = IOREQ_TYPE_TIMEOFFSET,
+ .size = 8,
+ .count = 1,
+ .dir = IOREQ_WRITE,
+ .data = timeoff,
+ .state = STATE_IOREQ_READY,
+ };
if ( timeoff == 0 )
return;
- memset(p, 0, sizeof(*p));
-
- p->type = IOREQ_TYPE_TIMEOFFSET;
- p->size = 8;
- p->count = 1;
- p->dir = IOREQ_WRITE;
- p->data = timeoff;
-
- p->state = STATE_IOREQ_READY;
-
- if ( !hvm_buffered_io_send(p) )
+ if ( !hvm_buffered_io_send(&p) )
printk("Unsuccessful timeoffset update\n");
}
/* Ask ioemu mapcache to invalidate mappings. */
void send_invalidate_req(void)
{
- struct vcpu *v = current;
- ioreq_t *p = get_ioreq(v);
-
- if ( !p )
- return;
-
- if ( p->state != STATE_IOREQ_NONE )
- {
- gdprintk(XENLOG_ERR, "WARNING: send invalidate req with something "
- "already pending (%d)?\n", p->state);
- domain_crash(v->domain);
- return;
- }
-
- p->type = IOREQ_TYPE_INVALIDATE;
- p->size = 4;
- p->dir = IOREQ_WRITE;
- p->data = ~0UL; /* flush all */
-
- (void)hvm_send_assist_req(v);
+ ioreq_t p = {
+ .type = IOREQ_TYPE_INVALIDATE,
+ .size = 4,
+ .dir = IOREQ_WRITE,
+ .data = ~0UL, /* flush all */
+ };
+
+ hvm_broadcast_assist_req(&p);
}
int handle_mmio(void)
@@ -189,25 +95,16 @@ int handle_mmio(void)
if ( vio->io_state == HVMIO_awaiting_completion )
vio->io_state = HVMIO_handle_mmio_awaiting_completion;
else
- vio->mmio_gva = 0;
+ vio->mmio_access = (struct npfec){};
switch ( rc )
{
case X86EMUL_UNHANDLEABLE:
- gdprintk(XENLOG_WARNING,
- "MMIO emulation failed @ %04x:%lx: "
- "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
- hvmemul_get_seg_reg(x86_seg_cs, &ctxt)->sel,
- ctxt.insn_buf_eip,
- ctxt.insn_buf[0], ctxt.insn_buf[1],
- ctxt.insn_buf[2], ctxt.insn_buf[3],
- ctxt.insn_buf[4], ctxt.insn_buf[5],
- ctxt.insn_buf[6], ctxt.insn_buf[7],
- ctxt.insn_buf[8], ctxt.insn_buf[9]);
+ hvm_dump_emulation_state(XENLOG_G_WARNING "MMIO", &ctxt);
return 0;
case X86EMUL_EXCEPTION:
if ( ctxt.exn_pending )
- hvm_inject_hw_exception(ctxt.exn_vector, ctxt.exn_error_code);
+ hvm_inject_trap(&ctxt.trap);
break;
default:
break;
@@ -218,9 +115,14 @@ int handle_mmio(void)
return 1;
}
-int handle_mmio_with_translation(unsigned long gva, unsigned long gpfn)
+int handle_mmio_with_translation(unsigned long gva, unsigned long gpfn,
+ struct npfec access)
{
struct hvm_vcpu_io *vio = ¤t->arch.hvm_vcpu.hvm_io;
+
+ vio->mmio_access = access.gla_valid &&
+ access.kind == npfec_kind_with_gla
+ ? access : (struct npfec){};
vio->mmio_gva = gva & PAGE_MASK;
vio->mmio_gpfn = gpfn;
return handle_mmio();
@@ -273,8 +175,6 @@ void hvm_io_assist(ioreq_t *p)
struct hvm_vcpu_io *vio = &curr->arch.hvm_vcpu.hvm_io;
enum hvm_io_state io_state;
- rmb(); /* see IORESP_READY /then/ read contents of ioreq */
-
p->state = STATE_IOREQ_NONE;
io_state = vio->io_state;
@@ -453,7 +353,7 @@ int dpci_ioport_intercept(ioreq_t *p)
unsigned int s = 0, e = 0;
int rc;
- list_for_each_entry( g2m_ioport, &hd->g2m_ioport_list, list )
+ list_for_each_entry( g2m_ioport, &hd->arch.g2m_ioport_list, list )
{
s = g2m_ioport->gport;
e = s + g2m_ioport->np;
diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c
index 5048c29..35f4f94 100644
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -270,7 +270,7 @@ void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq)
d->domain_id, link, old_isa_irq, isa_irq);
}
-void hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data)
+int hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data)
{
uint32_t tmp = (uint32_t) addr;
uint8_t dest = (tmp & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
@@ -283,7 +283,8 @@ void hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data)
if ( !vector )
{
- int pirq = ((addr >> 32) & 0xffffff00) | ((addr >> 12) & 0xff);
+ int pirq = ((addr >> 32) & 0xffffff00) | dest;
+
if ( pirq > 0 )
{
struct pirq *info = pirq_info(d, pirq);
@@ -291,20 +292,26 @@ void hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data)
/* if it is the first time, allocate the pirq */
if ( !info || info->arch.hvm.emuirq == IRQ_UNBOUND )
{
+ int rc;
+
spin_lock(&d->event_lock);
- map_domain_emuirq_pirq(d, pirq, IRQ_MSI_EMU);
+ rc = map_domain_emuirq_pirq(d, pirq, IRQ_MSI_EMU);
spin_unlock(&d->event_lock);
+ if ( rc )
+ return rc;
info = pirq_info(d, pirq);
if ( !info )
- return;
- } else if (info->arch.hvm.emuirq != IRQ_MSI_EMU)
- return;
+ return -EBUSY;
+ }
+ else if ( info->arch.hvm.emuirq != IRQ_MSI_EMU )
+ return -EINVAL;
send_guest_pirq(d, info);
- return;
+ return 0;
}
+ return -ERANGE;
}
- vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
+ return vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
}
void hvm_set_callback_via(struct domain *d, uint64_t via)
@@ -461,6 +468,12 @@ int hvm_local_events_need_delivery(struct vcpu *v)
return !hvm_interrupt_blocked(v, intack);
}
+void arch_evtchn_inject(struct vcpu *v)
+{
+ if ( has_hvm_container_vcpu(v) )
+ hvm_assert_evtchn_irq(v);
+}
+
static void irq_dump(struct domain *d)
{
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
diff --git a/xen/arch/x86/hvm/mtrr.c b/xen/arch/x86/hvm/mtrr.c
index e13647c..ee18553 100644
--- a/xen/arch/x86/hvm/mtrr.c
+++ b/xen/arch/x86/hvm/mtrr.c
@@ -20,6 +20,7 @@
#include <public/hvm/e820.h>
#include <xen/types.h>
#include <asm/e820.h>
+#include <asm/iocap.h>
#include <asm/mm.h>
#include <asm/paging.h>
#include <asm/p2m.h>
@@ -42,32 +43,42 @@ static const uint8_t pat_entry_2_pte_flags[8] = {
/* Effective mm type lookup table, according to MTRR and PAT. */
static const uint8_t mm_type_tbl[MTRR_NUM_TYPES][PAT_TYPE_NUMS] = {
-/********PAT(UC,WC,RS,RS,WT,WP,WB,UC-)*/
-/* RS means reserved type(2,3), and type is hardcoded here */
- /*MTRR(UC):(UC,WC,RS,RS,UC,UC,UC,UC)*/
- {0, 1, 2, 2, 0, 0, 0, 0},
- /*MTRR(WC):(UC,WC,RS,RS,UC,UC,WC,WC)*/
- {0, 1, 2, 2, 0, 0, 1, 1},
- /*MTRR(RS):(RS,RS,RS,RS,RS,RS,RS,RS)*/
- {2, 2, 2, 2, 2, 2, 2, 2},
- /*MTRR(RS):(RS,RS,RS,RS,RS,RS,RS,RS)*/
- {2, 2, 2, 2, 2, 2, 2, 2},
- /*MTRR(WT):(UC,WC,RS,RS,WT,WP,WT,UC)*/
- {0, 1, 2, 2, 4, 5, 4, 0},
- /*MTRR(WP):(UC,WC,RS,RS,WT,WP,WP,WC)*/
- {0, 1, 2, 2, 4, 5, 5, 1},
- /*MTRR(WB):(UC,WC,RS,RS,WT,WP,WB,UC)*/
- {0, 1, 2, 2, 4, 5, 6, 0}
+#define RS MEMORY_NUM_TYPES
+#define UC MTRR_TYPE_UNCACHABLE
+#define WB MTRR_TYPE_WRBACK
+#define WC MTRR_TYPE_WRCOMB
+#define WP MTRR_TYPE_WRPROT
+#define WT MTRR_TYPE_WRTHROUGH
+
+/* PAT(UC, WC, RS, RS, WT, WP, WB, UC-) */
+/* MTRR(UC) */ {UC, WC, RS, RS, UC, UC, UC, UC},
+/* MTRR(WC) */ {UC, WC, RS, RS, UC, UC, WC, WC},
+/* MTRR(RS) */ {RS, RS, RS, RS, RS, RS, RS, RS},
+/* MTRR(RS) */ {RS, RS, RS, RS, RS, RS, RS, RS},
+/* MTRR(WT) */ {UC, WC, RS, RS, WT, WP, WT, UC},
+/* MTRR(WP) */ {UC, WC, RS, RS, WT, WP, WP, WC},
+/* MTRR(WB) */ {UC, WC, RS, RS, WT, WP, WB, UC}
+
+#undef UC
+#undef WC
+#undef WT
+#undef WP
+#undef WB
+#undef RS
};
/*
* Reverse lookup table, to find a pat type according to MTRR and effective
* memory type. This table is dynamically generated.
*/
-static uint8_t mtrr_epat_tbl[MTRR_NUM_TYPES][MEMORY_NUM_TYPES];
+static uint8_t __read_mostly mtrr_epat_tbl[MTRR_NUM_TYPES][MEMORY_NUM_TYPES] =
+ { [0 ... MTRR_NUM_TYPES-1] =
+ { [0 ... MEMORY_NUM_TYPES-1] = INVALID_MEM_TYPE }
+ };
/* Lookup table for PAT entry of a given PAT value in host PAT. */
-static uint8_t pat_entry_tbl[PAT_TYPE_NUMS];
+static uint8_t __read_mostly pat_entry_tbl[PAT_TYPE_NUMS] =
+ { [0 ... PAT_TYPE_NUMS-1] = INVALID_MEM_TYPE };
static void get_mtrr_range(uint64_t base_msr, uint64_t mask_msr,
uint64_t *base, uint64_t *end)
@@ -78,7 +89,7 @@ static void get_mtrr_range(uint64_t base_msr, uint64_t mask_msr,
uint32_t base_hi = (uint32_t)(base_msr >> 32);
uint32_t size;
- if ( (mask_lo & 0x800) == 0 )
+ if ( !(mask_lo & MTRR_PHYSMASK_VALID) )
{
/* Invalid (i.e. free) range */
*base = 0;
@@ -133,33 +144,21 @@ bool_t is_var_mtrr_overlapped(struct mtrr_state *m)
return 0;
}
-#define MTRR_PHYSMASK_VALID_BIT 11
-#define MTRR_PHYSMASK_SHIFT 12
-
-#define MTRR_PHYSBASE_TYPE_MASK 0xff /* lowest 8 bits */
-#define MTRR_PHYSBASE_SHIFT 12
-#define MTRR_VCNT 8
-
-#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
-#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
-
-static int hvm_mtrr_pat_init(void)
+static int __init hvm_mtrr_pat_init(void)
{
unsigned int i, j;
- memset(&mtrr_epat_tbl, INVALID_MEM_TYPE, sizeof(mtrr_epat_tbl));
for ( i = 0; i < MTRR_NUM_TYPES; i++ )
{
for ( j = 0; j < PAT_TYPE_NUMS; j++ )
{
- int32_t tmp = mm_type_tbl[i][j];
- if ( (tmp >= 0) && (tmp < MEMORY_NUM_TYPES) )
+ unsigned int tmp = mm_type_tbl[i][j];
+
+ if ( tmp < MEMORY_NUM_TYPES )
mtrr_epat_tbl[i][tmp] = j;
}
}
- memset(&pat_entry_tbl, INVALID_MEM_TYPE,
- PAT_TYPE_NUMS * sizeof(pat_entry_tbl[0]));
for ( i = 0; i < PAT_TYPE_NUMS; i++ )
{
for ( j = 0; j < PAT_TYPE_NUMS; j++ )
@@ -180,16 +179,16 @@ __initcall(hvm_mtrr_pat_init);
uint8_t pat_type_2_pte_flags(uint8_t pat_type)
{
- int32_t pat_entry = pat_entry_tbl[pat_type];
+ unsigned int pat_entry = pat_entry_tbl[pat_type];
- /* INVALID_MEM_TYPE, means doesn't find the pat_entry in host pat for
- * a given pat_type. If host pat covers all the pat types,
- * it can't happen.
+ /*
+ * INVALID_MEM_TYPE, means doesn't find the pat_entry in host PAT for a
+ * given pat_type. If host PAT covers all the PAT types, it can't happen.
*/
- if ( likely(pat_entry != INVALID_MEM_TYPE) )
- return pat_entry_2_pte_flags[pat_entry];
+ if ( unlikely(pat_entry == INVALID_MEM_TYPE) )
+ pat_entry = pat_entry_tbl[PAT_TYPE_UNCACHABLE];
- return pat_entry_2_pte_flags[pat_entry_tbl[PAT_TYPE_UNCACHABLE]];
+ return pat_entry_2_pte_flags[pat_entry];
}
int hvm_vcpu_cacheattr_init(struct vcpu *v)
@@ -224,30 +223,40 @@ void hvm_vcpu_cacheattr_destroy(struct vcpu *v)
/*
* Get MTRR memory type for physical address pa.
+ *
+ * May return a negative value when order > 0, indicating to the caller
+ * that the respective mapping needs splitting.
*/
-static uint8_t get_mtrr_type(struct mtrr_state *m, paddr_t pa)
+static int get_mtrr_type(const struct mtrr_state *m,
+ paddr_t pa, unsigned int order)
{
- int32_t addr, seg, index;
uint8_t overlap_mtrr = 0;
uint8_t overlap_mtrr_pos = 0;
- uint64_t phys_base;
- uint64_t phys_mask;
- uint8_t num_var_ranges = m->mtrr_cap & 0xff;
+ uint64_t mask = -(uint64_t)PAGE_SIZE << order;
+ unsigned int seg, num_var_ranges = m->mtrr_cap & 0xff;
if ( unlikely(!(m->enabled & 0x2)) )
return MTRR_TYPE_UNCACHABLE;
+ pa &= mask;
if ( (pa < 0x100000) && (m->enabled & 1) )
{
- /* Fixed range MTRR takes effective */
- addr = (uint32_t) pa;
+ /* Fixed range MTRR takes effect. */
+ uint32_t addr = (uint32_t)pa, index;
+
if ( addr < 0x80000 )
{
+ /* 0x00000 ... 0x7FFFF in 64k steps */
+ if ( order > 4 )
+ return -1;
seg = (addr >> 16);
return m->fixed_ranges[seg];
}
else if ( addr < 0xc0000 )
{
+ /* 0x80000 ... 0xBFFFF in 16k steps */
+ if ( order > 2 )
+ return -1;
seg = (addr - 0x80000) >> 14;
index = (seg >> 3) + 1;
seg &= 7; /* select 0-7 segments */
@@ -255,7 +264,9 @@ static uint8_t get_mtrr_type(struct mtrr_state *m, paddr_t pa)
}
else
{
- /* 0xC0000 --- 0x100000 */
+ /* 0xC0000 ... 0xFFFFF in 4k steps */
+ if ( order )
+ return -1;
seg = (addr - 0xc0000) >> 12;
index = (seg >> 3) + 3;
seg &= 7; /* select 0-7 segments */
@@ -266,14 +277,15 @@ static uint8_t get_mtrr_type(struct mtrr_state *m, paddr_t pa)
/* Match with variable MTRRs. */
for ( seg = 0; seg < num_var_ranges; seg++ )
{
- phys_base = ((uint64_t*)m->var_ranges)[seg*2];
- phys_mask = ((uint64_t*)m->var_ranges)[seg*2 + 1];
- if ( phys_mask & (1 << MTRR_PHYSMASK_VALID_BIT) )
+ uint64_t phys_base = m->var_ranges[seg].base;
+ uint64_t phys_mask = m->var_ranges[seg].mask;
+
+ if ( phys_mask & MTRR_PHYSMASK_VALID )
{
- if ( ((uint64_t) pa & phys_mask) >> MTRR_PHYSMASK_SHIFT ==
- (phys_base & phys_mask) >> MTRR_PHYSMASK_SHIFT )
+ phys_mask &= mask;
+ if ( (pa & phys_mask) == (phys_base & phys_mask) )
{
- if ( unlikely(m->overlapped) )
+ if ( unlikely(m->overlapped) || order )
{
overlap_mtrr |= 1 << (phys_base & MTRR_PHYSBASE_TYPE_MASK);
overlap_mtrr_pos = phys_base & MTRR_PHYSBASE_TYPE_MASK;
@@ -287,22 +299,24 @@ static uint8_t get_mtrr_type(struct mtrr_state *m, paddr_t pa)
}
}
- /* Overlapped or not found. */
+ /* Not found? */
if ( unlikely(overlap_mtrr == 0) )
return m->def_type;
- if ( likely(!(overlap_mtrr & ~( ((uint8_t)1) << overlap_mtrr_pos ))) )
- /* Covers both one variable memory range matches and
- * two or more identical match.
- */
+ /* One match, or multiple identical ones? */
+ if ( likely(overlap_mtrr == (1 << overlap_mtrr_pos)) )
return overlap_mtrr_pos;
- if ( overlap_mtrr & 0x1 )
- /* Two or more match, one is UC. */
+ if ( order )
+ return -1;
+
+ /* Two or more matches, one being UC? */
+ if ( overlap_mtrr & (1 << MTRR_TYPE_UNCACHABLE) )
return MTRR_TYPE_UNCACHABLE;
- if ( !(overlap_mtrr & 0xaf) )
- /* Two or more match, WT and WB. */
+ /* Two or more matches, all of them WT and WB? */
+ if ( overlap_mtrr ==
+ ((1 << MTRR_TYPE_WRTHROUGH) | (1 << MTRR_TYPE_WRBACK)) )
return MTRR_TYPE_WRTHROUGH;
/* Behaviour is undefined, but return the last overlapped type. */
@@ -342,7 +356,7 @@ static uint8_t effective_mm_type(struct mtrr_state *m,
* just use it
*/
if ( gmtrr_mtype == NO_HARDCODE_MEM_TYPE )
- mtrr_mtype = get_mtrr_type(m, gpa);
+ mtrr_mtype = get_mtrr_type(m, gpa, 0);
else
mtrr_mtype = gmtrr_mtype;
@@ -371,7 +385,7 @@ uint32_t get_pat_flags(struct vcpu *v,
guest_eff_mm_type = effective_mm_type(g, pat, gpaddr,
gl1e_flags, gmtrr_mtype);
/* 2. Get the memory type of host physical address, with MTRR */
- shadow_mtrr_type = get_mtrr_type(&mtrr_state, spaddr);
+ shadow_mtrr_type = get_mtrr_type(&mtrr_state, spaddr, 0);
/* 3. Find the memory type in PAT, with host MTRR memory type
* and guest effective memory type.
@@ -399,13 +413,27 @@ uint32_t get_pat_flags(struct vcpu *v,
return pat_type_2_pte_flags(pat_entry_value);
}
-bool_t mtrr_def_type_msr_set(struct mtrr_state *m, uint64_t msr_content)
+static inline bool_t valid_mtrr_type(uint8_t type)
+{
+ switch ( type )
+ {
+ case MTRR_TYPE_UNCACHABLE:
+ case MTRR_TYPE_WRBACK:
+ case MTRR_TYPE_WRCOMB:
+ case MTRR_TYPE_WRPROT:
+ case MTRR_TYPE_WRTHROUGH:
+ return 1;
+ }
+ return 0;
+}
+
+bool_t mtrr_def_type_msr_set(struct domain *d, struct mtrr_state *m,
+ uint64_t msr_content)
{
uint8_t def_type = msr_content & 0xff;
uint8_t enabled = (msr_content >> 10) & 0x3;
- if ( unlikely(!(def_type == 0 || def_type == 1 || def_type == 4 ||
- def_type == 5 || def_type == 6)) )
+ if ( unlikely(!valid_mtrr_type(def_type)) )
{
HVM_DBG_LOG(DBG_LEVEL_MSR, "invalid MTRR def type:%x\n", def_type);
return 0;
@@ -418,31 +446,32 @@ bool_t mtrr_def_type_msr_set(struct mtrr_state *m, uint64_t msr_content)
return 0;
}
- m->enabled = enabled;
- m->def_type = def_type;
+ if ( m->enabled != enabled || m->def_type != def_type )
+ {
+ m->enabled = enabled;
+ m->def_type = def_type;
+ memory_type_changed(d);
+ }
return 1;
}
-bool_t mtrr_fix_range_msr_set(struct mtrr_state *m, uint32_t row,
- uint64_t msr_content)
+bool_t mtrr_fix_range_msr_set(struct domain *d, struct mtrr_state *m,
+ uint32_t row, uint64_t msr_content)
{
uint64_t *fixed_range_base = (uint64_t *)m->fixed_ranges;
if ( fixed_range_base[row] != msr_content )
{
uint8_t *range = (uint8_t*)&msr_content;
- int32_t i, type;
+ unsigned int i;
for ( i = 0; i < 8; i++ )
- {
- type = range[i];
- if ( unlikely(!(type == 0 || type == 1 ||
- type == 4 || type == 5 || type == 6)) )
+ if ( unlikely(!valid_mtrr_type(range[i])) )
return 0;
- }
fixed_range_base[row] = msr_content;
+ memory_type_changed(d);
}
return 1;
@@ -451,17 +480,15 @@ bool_t mtrr_fix_range_msr_set(struct mtrr_state *m, uint32_t row,
bool_t mtrr_var_range_msr_set(
struct domain *d, struct mtrr_state *m, uint32_t msr, uint64_t msr_content)
{
- uint32_t index, type, phys_addr, eax;
+ uint32_t index, phys_addr, eax;
uint64_t msr_mask;
uint64_t *var_range_base = (uint64_t*)m->var_ranges;
- index = msr - MSR_IA32_MTRR_PHYSBASE0;
+ index = msr - MSR_IA32_MTRR_PHYSBASE(0);
if ( var_range_base[index] == msr_content )
return 1;
- type = (uint8_t)msr_content;
- if ( unlikely(!(type == 0 || type == 1 ||
- type == 4 || type == 5 || type == 6)) )
+ if ( unlikely(!valid_mtrr_type((uint8_t)msr_content)) )
return 0;
if ( d == current->domain )
@@ -489,6 +516,8 @@ bool_t mtrr_var_range_msr_set(
m->overlapped = is_var_mtrr_overlapped(m);
+ memory_type_changed(d);
+
return 1;
}
@@ -523,6 +552,15 @@ bool_t mtrr_pat_not_equal(struct vcpu *vd, struct vcpu *vs)
return 0;
}
+struct hvm_mem_pinned_cacheattr_range {
+ struct list_head list;
+ uint64_t start, end;
+ uint32_t type;
+ struct rcu_head rcu;
+};
+
+static DEFINE_RCU_READ_LOCK(pinned_cacheattr_rcu_lock);
+
void hvm_init_cacheattr_region_list(
struct domain *d)
{
@@ -545,30 +583,48 @@ void hvm_destroy_cacheattr_region_list(
}
}
-int32_t hvm_get_mem_pinned_cacheattr(
+int hvm_get_mem_pinned_cacheattr(
struct domain *d,
uint64_t guest_fn,
+ unsigned int order,
uint32_t *type)
{
struct hvm_mem_pinned_cacheattr_range *range;
+ uint64_t mask = ~(uint64_t)0 << order;
+ int rc = 0;
- *type = 0;
+ *type = ~0;
if ( !is_hvm_domain(d) )
return 0;
+ rcu_read_lock(&pinned_cacheattr_rcu_lock);
list_for_each_entry_rcu ( range,
&d->arch.hvm_domain.pinned_cacheattr_ranges,
list )
{
- if ( (guest_fn >= range->start) && (guest_fn <= range->end) )
+ if ( ((guest_fn & mask) >= range->start) &&
+ ((guest_fn | ~mask) <= range->end) )
{
*type = range->type;
- return 1;
+ rc = 1;
+ break;
+ }
+ if ( ((guest_fn & mask) <= range->end) &&
+ (range->start <= (guest_fn | ~mask)) )
+ {
+ rc = -1;
+ break;
}
}
+ rcu_read_unlock(&pinned_cacheattr_rcu_lock);
- return 0;
+ return rc;
+}
+
+static void free_pinned_cacheattr_entry(struct rcu_head *rcu)
+{
+ xfree(container_of(rcu, struct hvm_mem_pinned_cacheattr_range, rcu));
}
int32_t hvm_set_mem_pinned_cacheattr(
@@ -578,6 +634,32 @@ int32_t hvm_set_mem_pinned_cacheattr(
uint32_t type)
{
struct hvm_mem_pinned_cacheattr_range *range;
+ int rc = 1;
+
+ if ( !is_hvm_domain(d) || gfn_end < gfn_start )
+ return 0;
+
+ if ( type == XEN_DOMCTL_DELETE_MEM_CACHEATTR )
+ {
+ /* Remove the requested range. */
+ rcu_read_lock(&pinned_cacheattr_rcu_lock);
+ list_for_each_entry_rcu ( range,
+ &d->arch.hvm_domain.pinned_cacheattr_ranges,
+ list )
+ if ( range->start == gfn_start && range->end == gfn_end )
+ {
+ rcu_read_unlock(&pinned_cacheattr_rcu_lock);
+ list_del_rcu(&range->list);
+ type = range->type;
+ call_rcu(&range->rcu, free_pinned_cacheattr_entry);
+ p2m_memory_type_changed(d);
+ if ( type != PAT_TYPE_UNCACHABLE )
+ flush_all(FLUSH_CACHE);
+ return 0;
+ }
+ rcu_read_unlock(&pinned_cacheattr_rcu_lock);
+ return -ENOENT;
+ }
if ( !((type == PAT_TYPE_UNCACHABLE) ||
(type == PAT_TYPE_WRCOMB) ||
@@ -588,6 +670,27 @@ int32_t hvm_set_mem_pinned_cacheattr(
!is_hvm_domain(d) )
return -EINVAL;
+ rcu_read_lock(&pinned_cacheattr_rcu_lock);
+ list_for_each_entry_rcu ( range,
+ &d->arch.hvm_domain.pinned_cacheattr_ranges,
+ list )
+ {
+ if ( range->start == gfn_start && range->end == gfn_end )
+ {
+ range->type = type;
+ rc = 0;
+ break;
+ }
+ if ( range->start <= gfn_end && gfn_start <= range->end )
+ {
+ rc = -EBUSY;
+ break;
+ }
+ }
+ rcu_read_unlock(&pinned_cacheattr_rcu_lock);
+ if ( rc <= 0 )
+ return rc;
+
range = xzalloc(struct hvm_mem_pinned_cacheattr_range);
if ( range == NULL )
return -ENOMEM;
@@ -597,6 +700,9 @@ int32_t hvm_set_mem_pinned_cacheattr(
range->type = type;
list_add_rcu(&range->list, &d->arch.hvm_domain.pinned_cacheattr_ranges);
+ p2m_memory_type_changed(d);
+ if ( type != PAT_TYPE_WRBACK )
+ flush_all(FLUSH_CACHE);
return 0;
}
@@ -663,17 +769,19 @@ static int hvm_load_mtrr_msr(struct domain *d, hvm_domain_context_t *h)
mtrr_state->mtrr_cap = hw_mtrr.msr_mtrr_cap;
for ( i = 0; i < NUM_FIXED_MSR; i++ )
- mtrr_fix_range_msr_set(mtrr_state, i, hw_mtrr.msr_mtrr_fixed[i]);
+ mtrr_fix_range_msr_set(d, mtrr_state, i, hw_mtrr.msr_mtrr_fixed[i]);
for ( i = 0; i < MTRR_VCNT; i++ )
{
mtrr_var_range_msr_set(d, mtrr_state,
- MTRRphysBase_MSR(i), hw_mtrr.msr_mtrr_var[i*2]);
+ MSR_IA32_MTRR_PHYSBASE(i),
+ hw_mtrr.msr_mtrr_var[i * 2]);
mtrr_var_range_msr_set(d, mtrr_state,
- MTRRphysMask_MSR(i), hw_mtrr.msr_mtrr_var[i*2+1]);
+ MSR_IA32_MTRR_PHYSMASK(i),
+ hw_mtrr.msr_mtrr_var[i * 2 + 1]);
}
- mtrr_def_type_msr_set(mtrr_state, hw_mtrr.msr_mtrr_def_type);
+ mtrr_def_type_msr_set(d, mtrr_state, hw_mtrr.msr_mtrr_def_type);
return 0;
}
@@ -681,10 +789,19 @@ static int hvm_load_mtrr_msr(struct domain *d, hvm_domain_context_t *h)
HVM_REGISTER_SAVE_RESTORE(MTRR, hvm_save_mtrr_msr, hvm_load_mtrr_msr,
1, HVMSR_PER_VCPU);
-uint8_t epte_get_entry_emt(struct domain *d, unsigned long gfn, mfn_t mfn,
- uint8_t *ipat, bool_t direct_mmio)
+void memory_type_changed(struct domain *d)
+{
+ if ( iommu_enabled && d->vcpu && d->vcpu[0] )
+ {
+ p2m_memory_type_changed(d);
+ flush_all(FLUSH_CACHE);
+ }
+}
+
+int epte_get_entry_emt(struct domain *d, unsigned long gfn, mfn_t mfn,
+ unsigned int order, uint8_t *ipat, bool_t direct_mmio)
{
- uint8_t gmtrr_mtype, hmtrr_mtype;
+ int gmtrr_mtype, hmtrr_mtype;
uint32_t type;
struct vcpu *v = current;
@@ -696,40 +813,41 @@ uint8_t epte_get_entry_emt(struct domain *d, unsigned long gfn, mfn_t mfn,
if ( !mfn_valid(mfn_x(mfn)) )
return MTRR_TYPE_UNCACHABLE;
- if ( hvm_get_mem_pinned_cacheattr(d, gfn, &type) )
- return type;
-
- if ( !iommu_enabled ||
- (rangeset_is_empty(d->iomem_caps) &&
- rangeset_is_empty(d->arch.ioport_caps) &&
- !has_arch_pdevs(d)) )
+ switch ( hvm_get_mem_pinned_cacheattr(d, gfn, order, &type) )
{
- ASSERT(!direct_mmio ||
- mfn_x(mfn) == d->arch.hvm_domain.vmx.apic_access_mfn);
+ case 1:
*ipat = 1;
- return MTRR_TYPE_WRBACK;
+ return type != PAT_TYPE_UC_MINUS ? type : PAT_TYPE_UNCACHABLE;
+ case -1:
+ return -1;
}
- if ( direct_mmio )
+ if ( !need_iommu(d) && !cache_flush_permitted(d) )
{
- if ( mfn_x(mfn) != d->arch.hvm_domain.vmx.apic_access_mfn )
- return MTRR_TYPE_UNCACHABLE;
+ ASSERT(!direct_mmio ||
+ !((mfn_x(mfn) ^ d->arch.hvm_domain.vmx.apic_access_mfn) >>
+ order));
*ipat = 1;
return MTRR_TYPE_WRBACK;
}
- if ( iommu_snoop )
+ if ( direct_mmio )
{
+ if ( (mfn_x(mfn) ^ d->arch.hvm_domain.vmx.apic_access_mfn) >> order )
+ return MTRR_TYPE_UNCACHABLE;
+ if ( order )
+ return -1;
*ipat = 1;
return MTRR_TYPE_WRBACK;
}
- gmtrr_mtype = is_hvm_domain(d) && v &&
- d->arch.hvm_domain.params[HVM_PARAM_IDENT_PT] ?
- get_mtrr_type(&v->arch.hvm_vcpu.mtrr, (gfn << PAGE_SHIFT)) :
+ gmtrr_mtype = is_hvm_domain(d) && v ?
+ get_mtrr_type(&v->arch.hvm_vcpu.mtrr,
+ gfn << PAGE_SHIFT, order) :
MTRR_TYPE_WRBACK;
-
- hmtrr_mtype = get_mtrr_type(&mtrr_state, (mfn_x(mfn) << PAGE_SHIFT));
+ hmtrr_mtype = get_mtrr_type(&mtrr_state, mfn_x(mfn) << PAGE_SHIFT, order);
+ if ( gmtrr_mtype < 0 || hmtrr_mtype < 0 )
+ return -1;
/* If both types match we're fine. */
if ( likely(gmtrr_mtype == hmtrr_mtype) )
diff --git a/xen/arch/x86/hvm/rtc.c b/xen/arch/x86/hvm/rtc.c
index 639b4c5..3fab660 100644
--- a/xen/arch/x86/hvm/rtc.c
+++ b/xen/arch/x86/hvm/rtc.c
@@ -27,6 +27,7 @@
#include <asm/hvm/io.h>
#include <asm/hvm/support.h>
#include <asm/current.h>
+#include <xen/trace.h>
#define USEC_PER_SEC 1000000UL
#define NS_PER_USEC 1000UL
@@ -91,6 +92,7 @@ static void rtc_pf_callback(struct vcpu *v, void *opaque)
&& ++(s->pt_dead_ticks) >= 10 )
{
/* VM is ignoring its RTC; no point in running the timer */
+ TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
destroy_periodic_time(&s->pt);
s->period = 0;
}
@@ -152,8 +154,11 @@ static void rtc_timer_update(RTCState *s)
else
delta = period - ((now - s->start_time) % period);
if ( s->hw.cmos_data[RTC_REG_B] & RTC_PIE )
+ {
+ TRACE_2D(TRC_HVM_EMUL_RTC_START_TIMER, delta, period);
create_periodic_time(v, &s->pt, delta, period,
RTC_IRQ, rtc_pf_callback, s);
+ }
else
s->check_ticks_since = now;
}
@@ -161,6 +166,7 @@ static void rtc_timer_update(RTCState *s)
}
/* fall through */
default:
+ TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
destroy_periodic_time(&s->pt);
s->period = 0;
break;
@@ -513,6 +519,7 @@ static int rtc_ioport_write(void *opaque, uint32_t addr, uint32_t data)
rtc_update_irq(s);
if ( (data ^ orig) & RTC_PIE )
{
+ TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
destroy_periodic_time(&s->pt);
s->period = 0;
rtc_timer_update(s);
@@ -772,6 +779,7 @@ void rtc_reset(struct domain *d)
{
RTCState *s = domain_vrtc(d);
+ TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
destroy_periodic_time(&s->pt);
s->period = 0;
s->pt.source = PTSRC_isa;
@@ -813,6 +821,7 @@ void rtc_deinit(struct domain *d)
spin_barrier(&s->lock);
+ TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
destroy_periodic_time(&s->pt);
kill_timer(&s->update_timer);
kill_timer(&s->update_timer2);
@@ -827,3 +836,12 @@ void rtc_update_clock(struct domain *d)
s->current_tm = gmtime(get_localtime(d));
spin_unlock(&s->lock);
}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/hvm/save.c b/xen/arch/x86/hvm/save.c
index 066fdb2..6af19be 100644
--- a/xen/arch/x86/hvm/save.c
+++ b/xen/arch/x86/hvm/save.c
@@ -34,6 +34,9 @@ void arch_hvm_save(struct domain *d, struct hvm_save_header *hdr)
/* Save guest's preferred TSC. */
hdr->gtsc_khz = d->arch.tsc_khz;
+
+ /* Time when saving started */
+ rdtscll(d->arch.hvm_domain.sync_tsc);
}
int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr)
@@ -67,6 +70,9 @@ int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr)
if ( d->arch.vtsc )
hvm_set_rdtsc_exiting(d, 1);
+ /* Time when restore started */
+ rdtscll(d->arch.hvm_domain.sync_tsc);
+
/* VGA state is not saved/restored, so we nobble the cache. */
d->arch.hvm_domain.stdvga.cache = 0;
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 3f274f0..9398690 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -90,6 +90,15 @@ static bool_t amd_erratum383_found __read_mostly;
static uint64_t osvw_length, osvw_status;
static DEFINE_SPINLOCK(osvw_lock);
+/* Only crash the guest if the problem originates in kernel mode. */
+static void svm_crash_or_fault(struct vcpu *v)
+{
+ if ( vmcb_get_cpl(v->arch.hvm_svm.vmcb) )
+ hvm_inject_hw_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE);
+ else
+ domain_crash(v->domain);
+}
+
void __update_guest_eip(struct cpu_user_regs *regs, unsigned int inst_len)
{
struct vcpu *curr = current;
@@ -100,7 +109,7 @@ void __update_guest_eip(struct cpu_user_regs *regs, unsigned int inst_len)
if ( unlikely(inst_len > 15) )
{
gdprintk(XENLOG_ERR, "Bad instruction length %u\n", inst_len);
- domain_crash(curr->domain);
+ svm_crash_or_fault(curr);
return;
}
@@ -160,14 +169,28 @@ void svm_intercept_msr(struct vcpu *v, uint32_t msr, int flags)
static void svm_save_dr(struct vcpu *v)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ unsigned int flag_dr_dirty = v->arch.hvm_vcpu.flag_dr_dirty;
- if ( !v->arch.hvm_vcpu.flag_dr_dirty )
+ if ( !flag_dr_dirty )
return;
/* Clear the DR dirty flag and re-enable intercepts for DR accesses. */
v->arch.hvm_vcpu.flag_dr_dirty = 0;
vmcb_set_dr_intercepts(vmcb, ~0u);
+ if ( flag_dr_dirty & 2 )
+ {
+ svm_intercept_msr(v, MSR_AMD64_DR0_ADDRESS_MASK, MSR_INTERCEPT_RW);
+ svm_intercept_msr(v, MSR_AMD64_DR1_ADDRESS_MASK, MSR_INTERCEPT_RW);
+ svm_intercept_msr(v, MSR_AMD64_DR2_ADDRESS_MASK, MSR_INTERCEPT_RW);
+ svm_intercept_msr(v, MSR_AMD64_DR3_ADDRESS_MASK, MSR_INTERCEPT_RW);
+
+ rdmsrl(MSR_AMD64_DR0_ADDRESS_MASK, v->arch.hvm_svm.dr_mask[0]);
+ rdmsrl(MSR_AMD64_DR1_ADDRESS_MASK, v->arch.hvm_svm.dr_mask[1]);
+ rdmsrl(MSR_AMD64_DR2_ADDRESS_MASK, v->arch.hvm_svm.dr_mask[2]);
+ rdmsrl(MSR_AMD64_DR3_ADDRESS_MASK, v->arch.hvm_svm.dr_mask[3]);
+ }
+
v->arch.debugreg[0] = read_debugreg(0);
v->arch.debugreg[1] = read_debugreg(1);
v->arch.debugreg[2] = read_debugreg(2);
@@ -178,12 +201,32 @@ static void svm_save_dr(struct vcpu *v)
static void __restore_debug_registers(struct vmcb_struct *vmcb, struct vcpu *v)
{
+ unsigned int ecx;
+
if ( v->arch.hvm_vcpu.flag_dr_dirty )
return;
v->arch.hvm_vcpu.flag_dr_dirty = 1;
vmcb_set_dr_intercepts(vmcb, 0);
+ ASSERT(v == current);
+ hvm_cpuid(0x80000001, NULL, NULL, &ecx, NULL);
+ if ( test_bit(X86_FEATURE_DBEXT & 31, &ecx) )
+ {
+ svm_intercept_msr(v, MSR_AMD64_DR0_ADDRESS_MASK, MSR_INTERCEPT_NONE);
+ svm_intercept_msr(v, MSR_AMD64_DR1_ADDRESS_MASK, MSR_INTERCEPT_NONE);
+ svm_intercept_msr(v, MSR_AMD64_DR2_ADDRESS_MASK, MSR_INTERCEPT_NONE);
+ svm_intercept_msr(v, MSR_AMD64_DR3_ADDRESS_MASK, MSR_INTERCEPT_NONE);
+
+ wrmsrl(MSR_AMD64_DR0_ADDRESS_MASK, v->arch.hvm_svm.dr_mask[0]);
+ wrmsrl(MSR_AMD64_DR1_ADDRESS_MASK, v->arch.hvm_svm.dr_mask[1]);
+ wrmsrl(MSR_AMD64_DR2_ADDRESS_MASK, v->arch.hvm_svm.dr_mask[2]);
+ wrmsrl(MSR_AMD64_DR3_ADDRESS_MASK, v->arch.hvm_svm.dr_mask[3]);
+
+ /* Can't use hvm_cpuid() in svm_save_dr(): v != current. */
+ v->arch.hvm_vcpu.flag_dr_dirty |= 2;
+ }
+
write_debugreg(0, v->arch.debugreg[0]);
write_debugreg(1, v->arch.debugreg[1]);
write_debugreg(2, v->arch.debugreg[2]);
@@ -287,17 +330,16 @@ static int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)
vmcb_set_h_cr3(vmcb, pagetable_get_paddr(p2m_get_pagetable(p2m)));
}
- if ( c->pending_valid )
+ if ( c->pending_valid &&
+ hvm_event_needs_reinjection(c->pending_type, c->pending_vector) )
{
gdprintk(XENLOG_INFO, "Re-injecting %#"PRIx32", %#"PRIx32"\n",
c->pending_event, c->error_code);
-
- if ( hvm_event_needs_reinjection(c->pending_type, c->pending_vector) )
- {
- vmcb->eventinj.bytes = c->pending_event;
- vmcb->eventinj.fields.errorcode = c->error_code;
- }
+ vmcb->eventinj.bytes = c->pending_event;
+ vmcb->eventinj.fields.errorcode = c->error_code;
}
+ else
+ vmcb->eventinj.bytes = 0;
vmcb->cleanbits.bytes = 0;
paging_update_paging_modes(v);
@@ -318,7 +360,8 @@ static void svm_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
data->msr_efer = v->arch.hvm_vcpu.guest_efer;
data->msr_flags = -1ULL;
- data->tsc = hvm_get_guest_tsc(v);
+ data->tsc = hvm_get_guest_tsc_fixed(v,
+ v->domain->arch.hvm_domain.sync_tsc);
}
@@ -334,7 +377,7 @@ static void svm_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
v->arch.hvm_vcpu.guest_efer = data->msr_efer;
svm_update_guest_efer(v);
- hvm_set_guest_tsc(v, data->tsc);
+ hvm_set_guest_tsc_fixed(v, data->tsc, v->domain->arch.hvm_domain.sync_tsc);
}
static void svm_save_vmcb_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt)
@@ -355,6 +398,72 @@ static int svm_load_vmcb_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt)
return 0;
}
+static unsigned int __init svm_init_msr(void)
+{
+ return boot_cpu_has(X86_FEATURE_DBEXT) ? 4 : 0;
+}
+
+static void svm_save_msr(struct vcpu *v, struct hvm_msr *ctxt)
+{
+ if ( boot_cpu_has(X86_FEATURE_DBEXT) )
+ {
+ ctxt->msr[ctxt->count].val = v->arch.hvm_svm.dr_mask[0];
+ if ( ctxt->msr[ctxt->count].val )
+ ctxt->msr[ctxt->count++].index = MSR_AMD64_DR0_ADDRESS_MASK;
+
+ ctxt->msr[ctxt->count].val = v->arch.hvm_svm.dr_mask[1];
+ if ( ctxt->msr[ctxt->count].val )
+ ctxt->msr[ctxt->count++].index = MSR_AMD64_DR1_ADDRESS_MASK;
+
+ ctxt->msr[ctxt->count].val = v->arch.hvm_svm.dr_mask[2];
+ if ( ctxt->msr[ctxt->count].val )
+ ctxt->msr[ctxt->count++].index = MSR_AMD64_DR2_ADDRESS_MASK;
+
+ ctxt->msr[ctxt->count].val = v->arch.hvm_svm.dr_mask[3];
+ if ( ctxt->msr[ctxt->count].val )
+ ctxt->msr[ctxt->count++].index = MSR_AMD64_DR3_ADDRESS_MASK;
+ }
+}
+
+static int svm_load_msr(struct vcpu *v, struct hvm_msr *ctxt)
+{
+ unsigned int i, idx;
+ int err = 0;
+
+ for ( i = 0; i < ctxt->count; ++i )
+ {
+ switch ( idx = ctxt->msr[i].index )
+ {
+ case MSR_AMD64_DR0_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) )
+ err = -ENXIO;
+ else if ( ctxt->msr[i].val >> 32 )
+ err = -EDOM;
+ else
+ v->arch.hvm_svm.dr_mask[0] = ctxt->msr[i].val;
+ break;
+
+ case MSR_AMD64_DR1_ADDRESS_MASK ... MSR_AMD64_DR3_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) )
+ err = -ENXIO;
+ else if ( ctxt->msr[i].val >> 32 )
+ err = -EDOM;
+ else
+ v->arch.hvm_svm.dr_mask[idx - MSR_AMD64_DR1_ADDRESS_MASK + 1] =
+ ctxt->msr[i].val;
+ break;
+
+ default:
+ continue;
+ }
+ if ( err )
+ break;
+ ctxt->msr[i]._rsvd = 1;
+ }
+
+ return err;
+}
+
static void svm_fpu_enter(struct vcpu *v)
{
struct vmcb_struct *n1vmcb = vcpu_nestedhvm(v).nv_n1vmcx;
@@ -680,7 +789,7 @@ static uint64_t svm_get_tsc_offset(uint64_t host_tsc, uint64_t guest_tsc,
return guest_tsc - offset;
}
-static void svm_set_tsc_offset(struct vcpu *v, u64 offset)
+static void svm_set_tsc_offset(struct vcpu *v, u64 offset, u64 at_tsc)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
struct vmcb_struct *n1vmcb, *n2vmcb;
@@ -688,11 +797,15 @@ static void svm_set_tsc_offset(struct vcpu *v, u64 offset)
struct domain *d = v->domain;
uint64_t host_tsc, guest_tsc;
- guest_tsc = hvm_get_guest_tsc(v);
+ guest_tsc = hvm_get_guest_tsc_fixed(v, at_tsc);
/* Re-adjust the offset value when TSC_RATIO is available */
- if ( cpu_has_tsc_ratio && d->arch.vtsc ) {
- rdtscll(host_tsc);
+ if ( cpu_has_tsc_ratio && !d->arch.vtsc )
+ {
+ if ( at_tsc )
+ host_tsc = at_tsc;
+ else
+ rdtscll(host_tsc);
offset = svm_get_tsc_offset(host_tsc, guest_tsc, vcpu_tsc_ratio(v));
}
@@ -847,13 +960,13 @@ static int svm_update_lwp_cfg(struct vcpu *v, uint64_t msr_content)
static inline void svm_tsc_ratio_save(struct vcpu *v)
{
/* Other vcpus might not have vtsc enabled. So disable TSC_RATIO here. */
- if ( cpu_has_tsc_ratio && v->domain->arch.vtsc )
+ if ( cpu_has_tsc_ratio && !v->domain->arch.vtsc )
wrmsrl(MSR_AMD64_TSC_RATIO, DEFAULT_TSC_RATIO);
}
static inline void svm_tsc_ratio_load(struct vcpu *v)
{
- if ( cpu_has_tsc_ratio && v->domain->arch.vtsc )
+ if ( cpu_has_tsc_ratio && !v->domain->arch.vtsc )
wrmsrl(MSR_AMD64_TSC_RATIO, vcpu_tsc_ratio(v));
}
@@ -919,7 +1032,7 @@ static void svm_ctxt_switch_to(struct vcpu *v)
wrmsrl(MSR_TSC_AUX, hvm_msr_tsc_aux(v));
}
-static void svm_do_resume(struct vcpu *v)
+static void noreturn svm_do_resume(struct vcpu *v)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
bool_t debug_state = v->domain->debugger_attached;
@@ -1073,17 +1186,16 @@ static void svm_inject_trap(struct hvm_trap *trap)
struct vmcb_struct *vmcb = curr->arch.hvm_svm.vmcb;
eventinj_t event = vmcb->eventinj;
struct hvm_trap _trap = *trap;
+ const struct cpu_user_regs *regs = guest_cpu_user_regs();
switch ( _trap.vector )
{
case TRAP_debug:
- if ( guest_cpu_user_regs()->eflags & X86_EFLAGS_TF )
+ if ( regs->eflags & X86_EFLAGS_TF )
{
__restore_debug_registers(vmcb, curr);
vmcb_set_dr6(vmcb, vmcb_get_dr6(vmcb) | 0x4000);
}
- if ( cpu_has_monitor_trap_flag )
- break;
/* fall through */
case TRAP_int3:
if ( curr->domain->debugger_attached )
@@ -1105,10 +1217,58 @@ static void svm_inject_trap(struct hvm_trap *trap)
event.bytes = 0;
event.fields.v = 1;
- event.fields.type = X86_EVENTTYPE_HW_EXCEPTION;
event.fields.vector = _trap.vector;
- event.fields.ev = (_trap.error_code != HVM_DELIVER_NO_ERROR_CODE);
- event.fields.errorcode = _trap.error_code;
+
+ /* Refer to AMD Vol 2: System Programming, 15.20 Event Injection. */
+ switch ( _trap.type )
+ {
+ case X86_EVENTTYPE_SW_INTERRUPT: /* int $n */
+ /*
+ * Injection type 4 (software interrupt) is only supported with
+ * NextRIP support. Without NextRIP, the emulator will have performed
+ * DPL and presence checks for us.
+ */
+ if ( cpu_has_svm_nrips )
+ {
+ vmcb->nextrip = regs->eip + _trap.insn_len;
+ event.fields.type = X86_EVENTTYPE_SW_INTERRUPT;
+ }
+ else
+ event.fields.type = X86_EVENTTYPE_HW_EXCEPTION;
+ break;
+
+ case X86_EVENTTYPE_PRI_SW_EXCEPTION: /* icebp */
+ /*
+ * icebp's injection must always be emulated. Software injection help
+ * in x86_emulate has moved eip forward, but NextRIP (if used) still
+ * needs setting or execution will resume from 0.
+ */
+ if ( cpu_has_svm_nrips )
+ vmcb->nextrip = regs->eip;
+ event.fields.type = X86_EVENTTYPE_HW_EXCEPTION;
+ break;
+
+ case X86_EVENTTYPE_SW_EXCEPTION: /* int3, into */
+ /*
+ * The AMD manual states that .type=3 (HW exception), .vector=3 or 4,
+ * will perform DPL checks. Experimentally, DPL and presence checks
+ * are indeed performed, even without NextRIP support.
+ *
+ * However without NextRIP support, the event injection still needs
+ * fully emulating to get the correct eip in the trap frame, yet get
+ * the correct faulting eip should a fault occur.
+ */
+ if ( cpu_has_svm_nrips )
+ vmcb->nextrip = regs->eip + _trap.insn_len;
+ event.fields.type = X86_EVENTTYPE_HW_EXCEPTION;
+ break;
+
+ default:
+ event.fields.type = X86_EVENTTYPE_HW_EXCEPTION;
+ event.fields.ev = (_trap.error_code != HVM_DELIVER_NO_ERROR_CODE);
+ event.fields.errorcode = _trap.error_code;
+ break;
+ }
vmcb->eventinj = event;
@@ -1259,7 +1419,7 @@ const struct hvm_function_table * __init start_svm(void)
setup_vmcb_dump();
- svm_feature_flags = ((cpuid_eax(0x80000000) >= 0x8000000A) ?
+ svm_feature_flags = (current_cpu_data.extended_cpuid_level >= 0x8000000A ?
cpuid_edx(0x8000000A) : 0);
printk("SVM: Supported advanced features:\n");
@@ -1289,7 +1449,7 @@ const struct hvm_function_table * __init start_svm(void)
}
static void svm_do_nested_pgfault(struct vcpu *v,
- struct cpu_user_regs *regs, uint32_t npfec, paddr_t gpa)
+ struct cpu_user_regs *regs, uint64_t pfec, paddr_t gpa)
{
int ret;
unsigned long gfn = gpa >> PAGE_SHIFT;
@@ -1298,10 +1458,24 @@ static void svm_do_nested_pgfault(struct vcpu *v,
p2m_access_t p2ma;
struct p2m_domain *p2m = NULL;
- ret = hvm_hap_nested_page_fault(gpa, 0, ~0ul,
- 1, /* All NPFs count as reads */
- npfec & PFEC_write_access,
- npfec & PFEC_insn_fetch);
+ /*
+ * Since HW doesn't explicitly provide a read access bit and we need to
+ * somehow describe read-modify-write instructions we will conservatively
+ * set read_access for all memory accesses that are not instruction fetches.
+ */
+ struct npfec npfec = {
+ .read_access = !(pfec & PFEC_insn_fetch),
+ .write_access = !!(pfec & PFEC_write_access),
+ .insn_fetch = !!(pfec & PFEC_insn_fetch)
+ };
+
+ /* These bits are mutually exclusive */
+ if ( pfec & NPT_PFEC_with_gla )
+ npfec.kind = npfec_kind_with_gla;
+ else if ( pfec & NPT_PFEC_in_gpt )
+ npfec.kind = npfec_kind_in_gpt;
+
+ ret = hvm_hap_nested_page_fault(gpa, ~0ul, npfec);
if ( tb_init_done )
{
@@ -1329,7 +1503,7 @@ static void svm_do_nested_pgfault(struct vcpu *v,
case -1:
ASSERT(nestedhvm_enabled(v->domain) && nestedhvm_vcpu_in_guestmode(v));
/* inject #VMEXIT(NPF) into guest. */
- nestedsvm_vmexit_defer(v, VMEXIT_NPF, npfec, gpa);
+ nestedsvm_vmexit_defer(v, VMEXIT_NPF, pfec, gpa);
return;
}
@@ -1459,6 +1633,8 @@ static int svm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
switch ( msr )
{
+ unsigned int ecx;
+
case MSR_IA32_SYSENTER_CS:
*msr_content = v->arch.hvm_svm.guest_sysenter_cs;
break;
@@ -1534,6 +1710,21 @@ static int svm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
vpmu_do_rdmsr(msr, msr_content);
break;
+ case MSR_AMD64_DR0_ADDRESS_MASK:
+ hvm_cpuid(0x80000001, NULL, NULL, &ecx, NULL);
+ if ( !test_bit(X86_FEATURE_DBEXT & 31, &ecx) )
+ goto gpf;
+ *msr_content = v->arch.hvm_svm.dr_mask[0];
+ break;
+
+ case MSR_AMD64_DR1_ADDRESS_MASK ... MSR_AMD64_DR3_ADDRESS_MASK:
+ hvm_cpuid(0x80000001, NULL, NULL, &ecx, NULL);
+ if ( !test_bit(X86_FEATURE_DBEXT & 31, &ecx) )
+ goto gpf;
+ *msr_content =
+ v->arch.hvm_svm.dr_mask[msr - MSR_AMD64_DR1_ADDRESS_MASK + 1];
+ break;
+
case MSR_AMD_OSVW_ID_LENGTH:
case MSR_AMD_OSVW_STATUS:
ret = svm_handle_osvw(v, msr, msr_content, 1);
@@ -1570,7 +1761,7 @@ static int svm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
goto gpf;
}
- HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, msr_value=%"PRIx64,
+ HVM_DBG_LOG(DBG_LEVEL_MSR, "returns: ecx=%x, msr_value=%"PRIx64,
msr, *msr_content);
return X86EMUL_OKAY;
@@ -1602,6 +1793,8 @@ static int svm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
switch ( msr )
{
+ unsigned int ecx;
+
case MSR_IA32_SYSENTER_CS:
vmcb->sysenter_cs = v->arch.hvm_svm.guest_sysenter_cs = msr_content;
break;
@@ -1665,7 +1858,7 @@ static int svm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
case MSR_AMD_FAM15H_EVNTSEL3:
case MSR_AMD_FAM15H_EVNTSEL4:
case MSR_AMD_FAM15H_EVNTSEL5:
- vpmu_do_wrmsr(msr, msr_content);
+ vpmu_do_wrmsr(msr, msr_content, 0);
break;
case MSR_IA32_MCx_MISC(4): /* Threshold register */
@@ -1677,6 +1870,21 @@ static int svm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
*/
break;
+ case MSR_AMD64_DR0_ADDRESS_MASK:
+ hvm_cpuid(0x80000001, NULL, NULL, &ecx, NULL);
+ if ( !test_bit(X86_FEATURE_DBEXT & 31, &ecx) || (msr_content >> 32) )
+ goto gpf;
+ v->arch.hvm_svm.dr_mask[0] = msr_content;
+ break;
+
+ case MSR_AMD64_DR1_ADDRESS_MASK ... MSR_AMD64_DR3_ADDRESS_MASK:
+ hvm_cpuid(0x80000001, NULL, NULL, &ecx, NULL);
+ if ( !test_bit(X86_FEATURE_DBEXT & 31, &ecx) || (msr_content >> 32) )
+ goto gpf;
+ v->arch.hvm_svm.dr_mask[msr - MSR_AMD64_DR1_ADDRESS_MASK + 1] =
+ msr_content;
+ break;
+
case MSR_AMD_OSVW_ID_LENGTH:
case MSR_AMD_OSVW_STATUS:
ret = svm_handle_osvw(v, msr, &msr_content, 0);
@@ -1696,7 +1904,7 @@ static int svm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
switch ( wrmsr_hypervisor_regs(msr, msr_content) )
{
- case -EAGAIN:
+ case -ERESTART:
result = X86EMUL_RETRY;
break;
case 0:
@@ -1917,6 +2125,19 @@ static void svm_vmexit_ud_intercept(struct cpu_user_regs *regs)
struct hvm_emulate_ctxt ctxt;
int rc;
+ if ( opt_hvm_fep )
+ {
+ char sig[5]; /* ud2; .ascii "xen" */
+
+ if ( (hvm_fetch_from_guest_virt_nofault(
+ sig, regs->eip, sizeof(sig), 0) == HVMCOPY_okay) &&
+ (memcmp(sig, "\xf\xbxen", sizeof(sig)) == 0) )
+ {
+ regs->eip += sizeof(sig);
+ regs->eflags &= ~X86_EFLAGS_RF;
+ }
+ }
+
hvm_emulate_prepare(&ctxt, regs);
rc = hvm_emulate_one(&ctxt);
@@ -1928,7 +2149,7 @@ static void svm_vmexit_ud_intercept(struct cpu_user_regs *regs)
break;
case X86EMUL_EXCEPTION:
if ( ctxt.exn_pending )
- hvm_inject_hw_exception(ctxt.exn_vector, ctxt.exn_error_code);
+ hvm_inject_trap(&ctxt.trap);
/* fall through */
default:
hvm_emulate_writeback(&ctxt);
@@ -1975,15 +2196,10 @@ static void svm_vmexit_mce_intercept(
}
}
-static void wbinvd_ipi(void *info)
-{
- wbinvd();
-}
-
static void svm_wbinvd_intercept(void)
{
if ( cache_flush_permitted(current->domain) )
- on_each_cpu(wbinvd_ipi, NULL, 1);
+ flush_all(FLUSH_CACHE);
}
static void svm_vmexit_do_invalidate_cache(struct cpu_user_regs *regs)
@@ -2030,6 +2246,9 @@ static struct hvm_function_table __initdata svm_function_table = {
.vcpu_destroy = svm_vcpu_destroy,
.save_cpu_ctxt = svm_save_vmcb_ctxt,
.load_cpu_ctxt = svm_load_vmcb_ctxt,
+ .init_msr = svm_init_msr,
+ .save_msr = svm_save_msr,
+ .load_msr = svm_load_msr,
.get_interrupt_shadow = svm_get_interrupt_shadow,
.set_interrupt_shadow = svm_set_interrupt_shadow,
.guest_x86_mode = svm_guest_x86_mode,
@@ -2428,7 +2647,17 @@ void svm_vmexit_handler(struct cpu_user_regs *regs)
perfc_incra(svmexits, VMEXIT_NPF_PERFC);
if ( cpu_has_svm_decode )
v->arch.hvm_svm.cached_insn_len = vmcb->guest_ins_len & 0xf;
- svm_do_nested_pgfault(v, regs, vmcb->exitinfo1, vmcb->exitinfo2);
+ rc = vmcb->exitinfo1 & PFEC_page_present
+ ? p2m_pt_handle_deferred_changes(vmcb->exitinfo2) : 0;
+ if ( rc >= 0 )
+ svm_do_nested_pgfault(v, regs, vmcb->exitinfo1, vmcb->exitinfo2);
+ else
+ {
+ printk(XENLOG_G_ERR
+ "%pv: Error %d handling NPF (gpa=%08lx ec=%04lx)\n",
+ v, rc, vmcb->exitinfo2, vmcb->exitinfo1);
+ domain_crash(v->domain);
+ }
v->arch.hvm_svm.cached_insn_len = 0;
break;
@@ -2460,7 +2689,7 @@ void svm_vmexit_handler(struct cpu_user_regs *regs)
"exitinfo1 = %#"PRIx64", exitinfo2 = %#"PRIx64"\n",
exit_reason,
(u64)vmcb->exitinfo1, (u64)vmcb->exitinfo2);
- domain_crash(v->domain);
+ svm_crash_or_fault(v);
break;
}
diff --git a/xen/arch/x86/hvm/svm/vpmu.c b/xen/arch/x86/hvm/svm/vpmu.c
index 66a3815..8e07a98 100644
--- a/xen/arch/x86/hvm/svm/vpmu.c
+++ b/xen/arch/x86/hvm/svm/vpmu.c
@@ -203,6 +203,8 @@ static void amd_vpmu_load(struct vcpu *v)
return;
}
+ vpmu_set(vpmu, VPMU_CONTEXT_LOADED);
+
context_load(v);
}
@@ -276,11 +278,14 @@ static void context_update(unsigned int msr, u64 msr_content)
}
}
-static int amd_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content)
+static int amd_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content,
+ uint64_t supported)
{
struct vcpu *v = current;
struct vpmu_struct *vpmu = vcpu_vpmu(v);
+ ASSERT(!supported);
+
/* For all counters, enable guest only mode for HVM guest */
if ( (get_pmu_reg_type(msr) == MSR_TYPE_CTRL) &&
!(is_guest_mode(msr_content)) )
diff --git a/xen/arch/x86/hvm/viridian.c b/xen/arch/x86/hvm/viridian.c
index 0fcbfd8..3197b6b 100644
--- a/xen/arch/x86/hvm/viridian.c
+++ b/xen/arch/x86/hvm/viridian.c
@@ -36,11 +36,11 @@
#define HvNotifyLongSpinWait 8
/* Viridian CPUID 4000003, Viridian MSR availability. */
-#define CPUID3A_MSR_REF_COUNT (1 << 1)
-#define CPUID3A_MSR_APIC_ACCESS (1 << 4)
-#define CPUID3A_MSR_HYPERCALL (1 << 5)
-#define CPUID3A_MSR_VP_INDEX (1 << 6)
-#define CPUID3A_MSR_FREQ (1 << 11)
+#define CPUID3A_MSR_TIME_REF_COUNT (1 << 1)
+#define CPUID3A_MSR_APIC_ACCESS (1 << 4)
+#define CPUID3A_MSR_HYPERCALL (1 << 5)
+#define CPUID3A_MSR_VP_INDEX (1 << 6)
+#define CPUID3A_MSR_FREQ (1 << 11)
/* Viridian CPUID 4000004, Implementation Recommendations. */
#define CPUID4A_MSR_BASED_APIC (1 << 3)
@@ -90,8 +90,11 @@ int cpuid_viridian_leaves(unsigned int leaf, unsigned int *eax,
/* Which hypervisor MSRs are available to the guest */
*eax = (CPUID3A_MSR_APIC_ACCESS |
CPUID3A_MSR_HYPERCALL |
- CPUID3A_MSR_VP_INDEX |
- CPUID3A_MSR_FREQ);
+ CPUID3A_MSR_VP_INDEX);
+ if ( !(viridian_feature_mask(d) & HVMPV_no_freq) )
+ *eax |= CPUID3A_MSR_FREQ;
+ if ( viridian_feature_mask(d) & HVMPV_time_ref_count )
+ *eax |= CPUID3A_MSR_TIME_REF_COUNT;
break;
case 4:
/* Recommended hypercall usage. */
@@ -119,37 +122,37 @@ int cpuid_viridian_leaves(unsigned int leaf, unsigned int *eax,
static void dump_guest_os_id(const struct domain *d)
{
- gdprintk(XENLOG_INFO, "GUEST_OS_ID:\n");
- gdprintk(XENLOG_INFO, "\tvendor: %x\n",
- d->arch.hvm_domain.viridian.guest_os_id.fields.vendor);
- gdprintk(XENLOG_INFO, "\tos: %x\n",
- d->arch.hvm_domain.viridian.guest_os_id.fields.os);
- gdprintk(XENLOG_INFO, "\tmajor: %x\n",
- d->arch.hvm_domain.viridian.guest_os_id.fields.major);
- gdprintk(XENLOG_INFO, "\tminor: %x\n",
- d->arch.hvm_domain.viridian.guest_os_id.fields.minor);
- gdprintk(XENLOG_INFO, "\tsp: %x\n",
- d->arch.hvm_domain.viridian.guest_os_id.fields.service_pack);
- gdprintk(XENLOG_INFO, "\tbuild: %x\n",
- d->arch.hvm_domain.viridian.guest_os_id.fields.build_number);
+ const union viridian_guest_os_id *goi;
+
+ goi = &d->arch.hvm_domain.viridian.guest_os_id;
+
+ printk(XENLOG_G_INFO
+ "d%d: VIRIDIAN GUEST_OS_ID: vendor: %x os: %x major: %x minor: %x sp: %x build: %x\n",
+ d->domain_id,
+ goi->fields.vendor, goi->fields.os,
+ goi->fields.major, goi->fields.minor,
+ goi->fields.service_pack, goi->fields.build_number);
}
static void dump_hypercall(const struct domain *d)
{
- gdprintk(XENLOG_INFO, "HYPERCALL:\n");
- gdprintk(XENLOG_INFO, "\tenabled: %x\n",
- d->arch.hvm_domain.viridian.hypercall_gpa.fields.enabled);
- gdprintk(XENLOG_INFO, "\tpfn: %lx\n",
- (unsigned long)d->arch.hvm_domain.viridian.hypercall_gpa.fields.pfn);
+ const union viridian_hypercall_gpa *hg;
+
+ hg = &d->arch.hvm_domain.viridian.hypercall_gpa;
+
+ printk(XENLOG_G_INFO "d%d: VIRIDIAN HYPERCALL: enabled: %x pfn: %lx\n",
+ d->domain_id,
+ hg->fields.enabled, (unsigned long)hg->fields.pfn);
}
static void dump_apic_assist(const struct vcpu *v)
{
- gdprintk(XENLOG_INFO, "APIC_ASSIST[%d]:\n", v->vcpu_id);
- gdprintk(XENLOG_INFO, "\tenabled: %x\n",
- v->arch.hvm_vcpu.viridian.apic_assist.fields.enabled);
- gdprintk(XENLOG_INFO, "\tpfn: %lx\n",
- (unsigned long)v->arch.hvm_vcpu.viridian.apic_assist.fields.pfn);
+ const union viridian_apic_assist *aa;
+
+ aa = &v->arch.hvm_vcpu.viridian.apic_assist;
+
+ printk(XENLOG_G_INFO "%pv: VIRIDIAN APIC_ASSIST: enabled: %x pfn: %lx\n",
+ v, aa->fields.enabled, (unsigned long)aa->fields.pfn);
}
static void enable_hypercall_page(struct domain *d)
@@ -286,6 +289,39 @@ int wrmsr_viridian_regs(uint32_t idx, uint64_t val)
return 1;
}
+static int64_t raw_trc_val(struct domain *d)
+{
+ uint64_t tsc;
+ struct time_scale tsc_to_ns;
+
+ tsc = hvm_get_guest_tsc(pt_global_vcpu_target(d));
+
+ /* convert tsc to count of 100ns periods */
+ set_time_scale(&tsc_to_ns, d->arch.tsc_khz * 1000ul);
+ return scale_delta(tsc, &tsc_to_ns) / 100ul;
+}
+
+void viridian_time_ref_count_freeze(struct domain *d)
+{
+ struct viridian_time_ref_count *trc;
+
+ trc = &d->arch.hvm_domain.viridian.time_ref_count;
+
+ if ( test_and_clear_bit(_TRC_running, &trc->flags) )
+ trc->val = raw_trc_val(d) + trc->off;
+}
+
+void viridian_time_ref_count_thaw(struct domain *d)
+{
+ struct viridian_time_ref_count *trc;
+
+ trc = &d->arch.hvm_domain.viridian.time_ref_count;
+
+ if ( !d->is_shutting_down &&
+ !test_and_set_bit(_TRC_running, &trc->flags) )
+ trc->off = (int64_t)trc->val - raw_trc_val(d);
+}
+
int rdmsr_viridian_regs(uint32_t idx, uint64_t *val)
{
struct vcpu *v = current;
@@ -312,11 +348,17 @@ int rdmsr_viridian_regs(uint32_t idx, uint64_t *val)
break;
case VIRIDIAN_MSR_TSC_FREQUENCY:
+ if ( viridian_feature_mask(d) & HVMPV_no_freq )
+ return 0;
+
perfc_incr(mshv_rdmsr_tsc_frequency);
*val = (uint64_t)d->arch.tsc_khz * 1000ull;
break;
case VIRIDIAN_MSR_APIC_FREQUENCY:
+ if ( viridian_feature_mask(d) & HVMPV_no_freq )
+ return 0;
+
perfc_incr(mshv_rdmsr_apic_frequency);
*val = 1000000000ull / APIC_BUS_CYCLE_NS;
break;
@@ -337,6 +379,24 @@ int rdmsr_viridian_regs(uint32_t idx, uint64_t *val)
*val = v->arch.hvm_vcpu.viridian.apic_assist.raw;
break;
+ case VIRIDIAN_MSR_TIME_REF_COUNT:
+ {
+ struct viridian_time_ref_count *trc;
+
+ trc = &d->arch.hvm_domain.viridian.time_ref_count;
+
+ if ( !(viridian_feature_mask(d) & HVMPV_time_ref_count) )
+ return 0;
+
+ if ( !test_and_set_bit(_TRC_accessed, &trc->flags) )
+ printk(XENLOG_G_INFO "d%d: VIRIDIAN MSR_TIME_REF_COUNT: accessed\n",
+ d->domain_id);
+
+ perfc_incr(mshv_rdmsr_time_ref_count);
+ *val = raw_trc_val(d) + trc->off;
+ break;
+ }
+
default:
return 0;
}
@@ -424,8 +484,9 @@ static int viridian_save_domain_ctxt(struct domain *d, hvm_domain_context_t *h)
if ( !is_viridian_domain(d) )
return 0;
- ctxt.hypercall_gpa = d->arch.hvm_domain.viridian.hypercall_gpa.raw;
- ctxt.guest_os_id = d->arch.hvm_domain.viridian.guest_os_id.raw;
+ ctxt.time_ref_count = d->arch.hvm_domain.viridian.time_ref_count.val;
+ ctxt.hypercall_gpa = d->arch.hvm_domain.viridian.hypercall_gpa.raw;
+ ctxt.guest_os_id = d->arch.hvm_domain.viridian.guest_os_id.raw;
return (hvm_save_entry(VIRIDIAN_DOMAIN, 0, h, &ctxt) != 0);
}
@@ -434,11 +495,12 @@ static int viridian_load_domain_ctxt(struct domain *d, hvm_domain_context_t *h)
{
struct hvm_viridian_domain_context ctxt;
- if ( hvm_load_entry(VIRIDIAN_DOMAIN, h, &ctxt) != 0 )
+ if ( hvm_load_entry_zeroextend(VIRIDIAN_DOMAIN, h, &ctxt) != 0 )
return -EINVAL;
- d->arch.hvm_domain.viridian.hypercall_gpa.raw = ctxt.hypercall_gpa;
- d->arch.hvm_domain.viridian.guest_os_id.raw = ctxt.guest_os_id;
+ d->arch.hvm_domain.viridian.time_ref_count.val = ctxt.time_ref_count;
+ d->arch.hvm_domain.viridian.hypercall_gpa.raw = ctxt.hypercall_gpa;
+ d->arch.hvm_domain.viridian.guest_os_id.raw = ctxt.guest_os_id;
return 0;
}
@@ -489,3 +551,13 @@ static int viridian_load_vcpu_ctxt(struct domain *d, hvm_domain_context_t *h)
HVM_REGISTER_SAVE_RESTORE(VIRIDIAN_VCPU, viridian_save_vcpu_ctxt,
viridian_load_vcpu_ctxt, 1, HVMSR_PER_VCPU);
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c
index bc06010..72b6509 100644
--- a/xen/arch/x86/hvm/vlapic.c
+++ b/xen/arch/x86/hvm/vlapic.c
@@ -45,11 +45,11 @@
#define VLAPIC_LVT_NUM 6
#define LVT_MASK \
- APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK
+ (APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK)
#define LINT_MASK \
- LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY |\
- APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER
+ (LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY |\
+ APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER)
static const unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] =
{
@@ -123,10 +123,34 @@ static int vlapic_find_highest_irr(struct vlapic *vlapic)
return vlapic_find_highest_vector(&vlapic->regs->data[APIC_IRR]);
}
+static void vlapic_error(struct vlapic *vlapic, unsigned int errmask)
+{
+ unsigned long flags;
+ uint32_t esr;
+
+ spin_lock_irqsave(&vlapic->esr_lock, flags);
+ esr = vlapic_get_reg(vlapic, APIC_ESR);
+ if ( (esr & errmask) != errmask )
+ {
+ uint32_t lvterr = vlapic_get_reg(vlapic, APIC_LVTERR);
+
+ vlapic_set_reg(vlapic, APIC_ESR, esr | errmask);
+ if ( !(lvterr & APIC_LVT_MASKED) )
+ vlapic_set_irq(vlapic, lvterr & APIC_VECTOR_MASK, 0);
+ }
+ spin_unlock_irqrestore(&vlapic->esr_lock, flags);
+}
+
void vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig)
{
struct vcpu *target = vlapic_vcpu(vlapic);
+ if ( unlikely(vec < 16) )
+ {
+ vlapic_error(vlapic, APIC_ESR_RECVILL);
+ return;
+ }
+
if ( trig )
vlapic_set_vector(vec, &vlapic->regs->data[APIC_TMR]);
@@ -173,18 +197,18 @@ uint32_t vlapic_set_ppr(struct vlapic *vlapic)
return ppr;
}
-static int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda)
+static bool_t vlapic_match_logical_addr(const struct vlapic *vlapic,
+ uint32_t mda)
{
- int result = 0;
- uint32_t logical_id;
+ bool_t result = 0;
+ uint32_t logical_id = vlapic_get_reg(vlapic, APIC_LDR);
if ( vlapic_x2apic_mode(vlapic) )
- {
- logical_id = vlapic_get_reg(vlapic, APIC_LDR);
- return !!(logical_id & mda);
- }
+ return ((logical_id >> 16) == (mda >> 16)) &&
+ (uint16_t)(logical_id & mda);
- logical_id = GET_xAPIC_LOGICAL_ID(vlapic_get_reg(vlapic, APIC_LDR));
+ logical_id = GET_xAPIC_LOGICAL_ID(logical_id);
+ mda = (uint8_t)mda;
switch ( vlapic_get_reg(vlapic, APIC_DFR) )
{
@@ -197,9 +221,9 @@ static int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda)
result = 1;
break;
default:
- gdprintk(XENLOG_WARNING, "Bad DFR value for lapic of vcpu %d: %08x\n",
- vlapic_vcpu(vlapic)->vcpu_id,
- vlapic_get_reg(vlapic, APIC_DFR));
+ printk(XENLOG_G_WARNING "%pv: bad LAPIC DFR value %08x\n",
+ const_vlapic_vcpu(vlapic),
+ vlapic_get_reg(vlapic, APIC_DFR));
break;
}
@@ -207,8 +231,8 @@ static int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda)
}
bool_t vlapic_match_dest(
- struct vlapic *target, struct vlapic *source,
- int short_hand, uint8_t dest, uint8_t dest_mode)
+ const struct vlapic *target, const struct vlapic *source,
+ int short_hand, uint32_t dest, bool_t dest_mode)
{
HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "target %p, source %p, dest %#x, "
"dest_mode %#x, short_hand %#x",
@@ -219,7 +243,8 @@ bool_t vlapic_match_dest(
case APIC_DEST_NOSHORT:
if ( dest_mode )
return vlapic_match_logical_addr(target, dest);
- return ((dest == 0xFF) || (dest == VLAPIC_ID(target)));
+ return (dest == _VLAPIC_ID(target, 0xffffffff)) ||
+ (dest == VLAPIC_ID(target));
case APIC_DEST_SELF:
return (target == source);
@@ -286,7 +311,7 @@ static void vlapic_init_sipi_action(unsigned long _vcpu)
uint32_t icr = vcpu_vlapic(origin)->init_sipi.icr;
uint32_t dest = vcpu_vlapic(origin)->init_sipi.dest;
uint32_t short_hand = icr & APIC_SHORT_MASK;
- uint32_t dest_mode = !!(icr & APIC_DEST_MASK);
+ bool_t dest_mode = !!(icr & APIC_DEST_MASK);
struct vcpu *v;
if ( icr == 0 )
@@ -352,8 +377,8 @@ static void vlapic_accept_irq(struct vcpu *v, uint32_t icr_low)
}
struct vlapic *vlapic_lowest_prio(
- struct domain *d, struct vlapic *source,
- int short_hand, uint8_t dest, uint8_t dest_mode)
+ struct domain *d, const struct vlapic *source,
+ int short_hand, uint32_t dest, bool_t dest_mode)
{
int old = d->arch.hvm_domain.irq.round_robin_prev_vcpu;
uint32_t ppr, target_ppr = UINT_MAX;
@@ -409,18 +434,36 @@ void vlapic_handle_EOI_induced_exit(struct vlapic *vlapic, int vector)
hvm_dpci_msi_eoi(current->domain, vector);
}
+static bool_t is_multicast_dest(struct vlapic *vlapic, unsigned int short_hand,
+ uint32_t dest, bool_t dest_mode)
+{
+ if ( vlapic_domain(vlapic)->max_vcpus <= 2 )
+ return 0;
+
+ if ( short_hand )
+ return short_hand != APIC_DEST_SELF;
+
+ if ( vlapic_x2apic_mode(vlapic) )
+ return dest_mode ? hweight16(dest) > 1 : dest == 0xffffffff;
+
+ if ( dest_mode )
+ return hweight8(dest &
+ GET_xAPIC_DEST_FIELD(vlapic_get_reg(vlapic,
+ APIC_DFR))) > 1;
+
+ return dest == 0xff;
+}
+
void vlapic_ipi(
struct vlapic *vlapic, uint32_t icr_low, uint32_t icr_high)
{
unsigned int dest;
unsigned int short_hand = icr_low & APIC_SHORT_MASK;
- unsigned int dest_mode = !!(icr_low & APIC_DEST_MASK);
+ bool_t dest_mode = !!(icr_low & APIC_DEST_MASK);
HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "icr = 0x%08x:%08x", icr_high, icr_low);
- dest = (vlapic_x2apic_mode(vlapic)
- ? icr_high
- : GET_xAPIC_DEST_FIELD(icr_high));
+ dest = _VLAPIC_ID(vlapic, icr_high);
switch ( icr_low & APIC_MODE_MASK )
{
@@ -440,19 +483,35 @@ void vlapic_ipi(
case APIC_DM_LOWEST: {
struct vlapic *target = vlapic_lowest_prio(
vlapic_domain(vlapic), vlapic, short_hand, dest, dest_mode);
- if ( target != NULL )
+
+ if ( unlikely((icr_low & APIC_VECTOR_MASK) < 16) )
+ vlapic_error(vlapic, APIC_ESR_SENDILL);
+ else if ( target )
vlapic_accept_irq(vlapic_vcpu(target), icr_low);
break;
}
+ case APIC_DM_FIXED:
+ if ( unlikely((icr_low & APIC_VECTOR_MASK) < 16) )
+ {
+ vlapic_error(vlapic, APIC_ESR_SENDILL);
+ break;
+ }
+ /* fall through */
default: {
struct vcpu *v;
+ bool_t batch = is_multicast_dest(vlapic, short_hand, dest, dest_mode);
+
+ if ( batch )
+ cpu_raise_softirq_batch_begin();
for_each_vcpu ( vlapic_domain(vlapic), v )
{
if ( vlapic_match_dest(vcpu_vlapic(v), vlapic,
short_hand, dest, dest_mode) )
vlapic_accept_irq(v, icr_low);
}
+ if ( batch )
+ cpu_raise_softirq_batch_finish();
break;
}
}
@@ -588,29 +647,48 @@ int hvm_x2apic_msr_read(struct vcpu *v, unsigned int msr, uint64_t *msr_content)
uint32_t low, high = 0, offset = (msr - MSR_IA32_APICBASE_MSR) << 4;
if ( !vlapic_x2apic_mode(vlapic) )
- return 1;
+ return X86EMUL_UNHANDLEABLE;
- vlapic_read_aligned(vlapic, offset, &low);
switch ( offset )
{
- case APIC_ID:
- low = GET_xAPIC_ID(low);
- break;
-
case APIC_ICR:
vlapic_read_aligned(vlapic, APIC_ICR2, &high);
+ /* Fallthrough. */
+ case APIC_ID:
+ case APIC_LVR:
+ case APIC_TASKPRI:
+ case APIC_PROCPRI:
+ case APIC_LDR:
+ case APIC_SPIV:
+ case APIC_ISR ... APIC_ISR + 0x70:
+ case APIC_TMR ... APIC_TMR + 0x70:
+ case APIC_IRR ... APIC_IRR + 0x70:
+ case APIC_ESR:
+ case APIC_CMCI:
+ case APIC_LVTT:
+ case APIC_LVTTHMR:
+ case APIC_LVTPC:
+ case APIC_LVT0:
+ case APIC_LVT1:
+ case APIC_LVTERR:
+ case APIC_TMICT:
+ case APIC_TMCCT:
+ case APIC_TDCR:
+ vlapic_read_aligned(vlapic, offset, &low);
break;
- case APIC_ICR2:
- return 1;
+ default:
+ return X86EMUL_UNHANDLEABLE;
}
*msr_content = (((uint64_t)high) << 32) | low;
- return 0;
+
+ return X86EMUL_OKAY;
}
static void vlapic_pt_cb(struct vcpu *v, void *data)
{
+ TRACE_0D(TRC_HVM_EMUL_LAPIC_TIMER_CB);
*(s_time_t *)data = hvm_get_guest_time(v);
}
@@ -626,13 +704,12 @@ static int vlapic_reg_write(struct vcpu *v,
struct vlapic *vlapic = vcpu_vlapic(v);
int rc = X86EMUL_OKAY;
+ memset(&vlapic->loaded, 0, sizeof(vlapic->loaded));
+
switch ( offset )
{
case APIC_ID:
- if ( !vlapic_x2apic_mode(vlapic) )
- vlapic_set_reg(vlapic, APIC_ID, val);
- else
- rc = X86EMUL_UNHANDLEABLE;
+ vlapic_set_reg(vlapic, APIC_ID, val);
break;
case APIC_TASKPRI:
@@ -644,17 +721,11 @@ static int vlapic_reg_write(struct vcpu *v,
break;
case APIC_LDR:
- if ( !vlapic_x2apic_mode(vlapic) )
- vlapic_set_reg(vlapic, APIC_LDR, val & APIC_LDR_MASK);
- else
- rc = X86EMUL_UNHANDLEABLE;
+ vlapic_set_reg(vlapic, APIC_LDR, val & APIC_LDR_MASK);
break;
case APIC_DFR:
- if ( !vlapic_x2apic_mode(vlapic) )
- vlapic_set_reg(vlapic, APIC_DFR, val | 0x0FFFFFFF);
- else
- rc = X86EMUL_UNHANDLEABLE;
+ vlapic_set_reg(vlapic, APIC_DFR, val | 0x0FFFFFFF);
break;
case APIC_SPIV:
@@ -681,21 +752,6 @@ static int vlapic_reg_write(struct vcpu *v,
}
break;
- case APIC_ESR:
- if ( vlapic_x2apic_mode(vlapic) && (val != 0) )
- {
- gdprintk(XENLOG_ERR, "Local APIC write ESR with non-zero %lx\n",
- val);
- rc = X86EMUL_UNHANDLEABLE;
- }
- break;
-
- case APIC_SELF_IPI:
- rc = vlapic_x2apic_mode(vlapic)
- ? vlapic_reg_write(v, APIC_ICR, 0x40000 | (val & 0xff))
- : X86EMUL_UNHANDLEABLE;
- break;
-
case APIC_ICR:
val &= ~(1 << 12); /* always clear the pending bit */
vlapic_ipi(vlapic, val, vlapic_get_reg(vlapic, APIC_ICR2));
@@ -703,15 +759,14 @@ static int vlapic_reg_write(struct vcpu *v,
break;
case APIC_ICR2:
- if ( !vlapic_x2apic_mode(vlapic) )
- val &= 0xff000000;
- vlapic_set_reg(vlapic, APIC_ICR2, val);
+ vlapic_set_reg(vlapic, APIC_ICR2, val & 0xff000000);
break;
case APIC_LVTT: /* LVT Timer Reg */
if ( (vlapic_get_reg(vlapic, offset) & APIC_TIMER_MODE_MASK) !=
(val & APIC_TIMER_MODE_MASK) )
{
+ TRACE_0D(TRC_HVM_EMUL_LAPIC_STOP_TIMER);
destroy_periodic_time(&vlapic->pt);
vlapic_set_reg(vlapic, APIC_TMICT, 0);
vlapic_set_reg(vlapic, APIC_TMCCT, 0);
@@ -746,12 +801,16 @@ static int vlapic_reg_write(struct vcpu *v,
vlapic_set_reg(vlapic, APIC_TMICT, val);
if ( val == 0 )
{
+ TRACE_0D(TRC_HVM_EMUL_LAPIC_STOP_TIMER);
destroy_periodic_time(&vlapic->pt);
break;
}
period = ((uint64_t)APIC_BUS_CYCLE_NS *
(uint32_t)val * vlapic->hw.timer_divisor);
+ TRACE_2_LONG_3D(TRC_HVM_EMUL_LAPIC_START_TIMER, TRC_PAR_LONG(period),
+ TRC_PAR_LONG(vlapic_lvtt_period(vlapic) ? period : 0LL),
+ vlapic->pt.irq);
create_periodic_time(current, &vlapic->pt, period,
vlapic_lvtt_period(vlapic) ? period : 0,
vlapic->pt.irq,
@@ -845,8 +904,17 @@ static int vlapic_write(struct vcpu *v, unsigned long address,
int vlapic_apicv_write(struct vcpu *v, unsigned int offset)
{
- uint32_t val = vlapic_get_reg(vcpu_vlapic(v), offset);
- return vlapic_reg_write(v, offset, val);
+ struct vlapic *vlapic = vcpu_vlapic(v);
+ uint32_t val = vlapic_get_reg(vlapic, offset);
+
+ if ( !vlapic_x2apic_mode(vlapic) )
+ return vlapic_reg_write(v, offset, val);
+
+ if ( offset != APIC_SELF_IPI )
+ return X86EMUL_UNHANDLEABLE;
+
+ return vlapic_reg_write(v, APIC_ICR,
+ APIC_DEST_SELF | (val & APIC_VECTOR_MASK));
}
int hvm_x2apic_msr_write(struct vcpu *v, unsigned int msr, uint64_t msr_content)
@@ -859,16 +927,69 @@ int hvm_x2apic_msr_write(struct vcpu *v, unsigned int msr, uint64_t msr_content)
switch ( offset )
{
- int rc;
+ case APIC_TASKPRI:
+ if ( msr_content & ~APIC_TPRI_MASK )
+ return X86EMUL_UNHANDLEABLE;
+ break;
+
+ case APIC_SPIV:
+ if ( msr_content & ~(APIC_VECTOR_MASK | APIC_SPIV_APIC_ENABLED |
+ (VLAPIC_VERSION & APIC_LVR_DIRECTED_EOI
+ ? APIC_SPIV_DIRECTED_EOI : 0)) )
+ return X86EMUL_UNHANDLEABLE;
+ break;
+
+ case APIC_LVTT:
+ if ( msr_content & ~(LVT_MASK | APIC_TIMER_MODE_MASK) )
+ return X86EMUL_UNHANDLEABLE;
+ break;
+
+ case APIC_LVTTHMR:
+ case APIC_LVTPC:
+ case APIC_CMCI:
+ if ( msr_content & ~(LVT_MASK | APIC_MODE_MASK) )
+ return X86EMUL_UNHANDLEABLE;
+ break;
+
+ case APIC_LVT0:
+ case APIC_LVT1:
+ if ( msr_content & ~LINT_MASK )
+ return X86EMUL_UNHANDLEABLE;
+ break;
+
+ case APIC_LVTERR:
+ if ( msr_content & ~LVT_MASK )
+ return X86EMUL_UNHANDLEABLE;
+ break;
+
+ case APIC_TMICT:
+ break;
+
+ case APIC_TDCR:
+ if ( msr_content & ~APIC_TDR_DIV_1 )
+ return X86EMUL_UNHANDLEABLE;
+ break;
case APIC_ICR:
- rc = vlapic_reg_write(v, APIC_ICR2, (uint32_t)(msr_content >> 32));
- if ( rc )
- return rc;
+ if ( (uint32_t)msr_content & ~(APIC_VECTOR_MASK | APIC_MODE_MASK |
+ APIC_DEST_MASK | APIC_INT_ASSERT |
+ APIC_INT_LEVELTRIG | APIC_SHORT_MASK) )
+ return X86EMUL_UNHANDLEABLE;
+ vlapic_set_reg(vlapic, APIC_ICR2, msr_content >> 32);
break;
- case APIC_ICR2:
- return X86EMUL_UNHANDLEABLE;
+ case APIC_SELF_IPI:
+ if ( msr_content & ~APIC_VECTOR_MASK )
+ return X86EMUL_UNHANDLEABLE;
+ offset = APIC_ICR;
+ msr_content = APIC_DEST_SELF | (msr_content & APIC_VECTOR_MASK);
+ break;
+
+ case APIC_EOI:
+ case APIC_ESR:
+ if ( msr_content )
+ default:
+ return X86EMUL_UNHANDLEABLE;
}
return vlapic_reg_write(v, offset, (uint32_t)msr_content);
@@ -878,7 +999,10 @@ static int vlapic_range(struct vcpu *v, unsigned long addr)
{
struct vlapic *vlapic = vcpu_vlapic(v);
unsigned long offset = addr - vlapic_base_address(vlapic);
- return (!vlapic_hw_disabled(vlapic) && (offset < PAGE_SIZE));
+
+ return !vlapic_hw_disabled(vlapic) &&
+ !vlapic_x2apic_mode(vlapic) &&
+ (offset < PAGE_SIZE);
}
const struct hvm_mmio_handler vlapic_mmio_handler = {
@@ -887,10 +1011,21 @@ const struct hvm_mmio_handler vlapic_mmio_handler = {
.write_handler = vlapic_write
};
-void vlapic_msr_set(struct vlapic *vlapic, uint64_t value)
+static void set_x2apic_id(struct vlapic *vlapic)
+{
+ u32 id = vlapic_vcpu(vlapic)->vcpu_id;
+ u32 ldr = ((id & ~0xf) << 12) | (1 << (id & 0xf));
+
+ vlapic_set_reg(vlapic, APIC_ID, id * 2);
+ vlapic_set_reg(vlapic, APIC_LDR, ldr);
+}
+
+bool_t vlapic_msr_set(struct vlapic *vlapic, uint64_t value)
{
if ( (vlapic->hw.apic_base_msr ^ value) & MSR_IA32_APICBASE_ENABLE )
{
+ if ( unlikely(value & MSR_IA32_APICBASE_EXTD) )
+ return 0;
if ( value & MSR_IA32_APICBASE_ENABLE )
{
vlapic_reset(vlapic);
@@ -899,24 +1034,28 @@ void vlapic_msr_set(struct vlapic *vlapic, uint64_t value)
}
else
{
+ if ( unlikely(vlapic_x2apic_mode(vlapic)) )
+ return 0;
vlapic->hw.disabled |= VLAPIC_HW_DISABLED;
pt_may_unmask_irq(vlapic_domain(vlapic), NULL);
}
}
+ else if ( !(value & MSR_IA32_APICBASE_ENABLE) &&
+ unlikely(value & MSR_IA32_APICBASE_EXTD) )
+ return 0;
vlapic->hw.apic_base_msr = value;
+ memset(&vlapic->loaded, 0, sizeof(vlapic->loaded));
if ( vlapic_x2apic_mode(vlapic) )
- {
- u32 id = vlapic_get_reg(vlapic, APIC_ID);
- u32 ldr = ((id & ~0xf) << 16) | (1 << (id & 0xf));
- vlapic_set_reg(vlapic, APIC_LDR, ldr);
- }
+ set_x2apic_id(vlapic);
vmx_vlapic_msr_changed(vlapic_vcpu(vlapic));
HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
"apic base msr is 0x%016"PRIx64, vlapic->hw.apic_base_msr);
+
+ return 1;
}
uint64_t vlapic_tdt_msr_get(struct vlapic *vlapic)
@@ -950,6 +1089,8 @@ void vlapic_tdt_msr_set(struct vlapic *vlapic, uint64_t value)
vlapic->hw.tdt_msr = value;
/* .... reprogram tdt timer */
+ TRACE_2_LONG_3D(TRC_HVM_EMUL_LAPIC_START_TIMER, TRC_PAR_LONG(delta),
+ TRC_PAR_LONG(0LL), vlapic->pt.irq);
create_periodic_time(v, &vlapic->pt, delta, 0,
vlapic->pt.irq, vlapic_tdt_pt_cb,
&vlapic->timer_last_update);
@@ -962,6 +1103,8 @@ void vlapic_tdt_msr_set(struct vlapic *vlapic, uint64_t value)
/* trigger a timer event if needed */
if ( value > 0 )
{
+ TRACE_2_LONG_3D(TRC_HVM_EMUL_LAPIC_START_TIMER, TRC_PAR_LONG(0LL),
+ TRC_PAR_LONG(0LL), vlapic->pt.irq);
create_periodic_time(v, &vlapic->pt, 0, 0,
vlapic->pt.irq, vlapic_tdt_pt_cb,
&vlapic->timer_last_update);
@@ -970,6 +1113,7 @@ void vlapic_tdt_msr_set(struct vlapic *vlapic, uint64_t value)
else
{
/* .... stop tdt timer */
+ TRACE_0D(TRC_HVM_EMUL_LAPIC_STOP_TIMER);
destroy_periodic_time(&vlapic->pt);
}
@@ -1003,6 +1147,10 @@ static int __vlapic_accept_pic_intr(struct vcpu *v)
int vlapic_accept_pic_intr(struct vcpu *v)
{
+ TRACE_2D(TRC_HVM_EMUL_LAPIC_PIC_INTR,
+ (v == v->domain->arch.hvm_domain.i8259_target),
+ v ? __vlapic_accept_pic_intr(v) : -1);
+
return ((v == v->domain->arch.hvm_domain.i8259_target) &&
__vlapic_accept_pic_intr(v));
}
@@ -1106,6 +1254,7 @@ void vlapic_reset(struct vlapic *vlapic)
vlapic_set_reg(vlapic, APIC_SPIV, 0xff);
vlapic->hw.disabled |= VLAPIC_SW_DISABLED;
+ TRACE_0D(TRC_HVM_EMUL_LAPIC_STOP_TIMER);
destroy_periodic_time(&vlapic->pt);
}
@@ -1129,6 +1278,8 @@ static void lapic_rearm(struct vlapic *s)
period = ((uint64_t)APIC_BUS_CYCLE_NS *
(uint32_t)tmict * s->hw.timer_divisor);
+ TRACE_2_LONG_3D(TRC_HVM_EMUL_LAPIC_START_TIMER, TRC_PAR_LONG(period),
+ TRC_PAR_LONG(vlapic_lvtt_period(s) ? period : 0LL), s->pt.irq);
create_periodic_time(vlapic_vcpu(s), &s->pt, period,
vlapic_lvtt_period(s) ? period : 0,
s->pt.irq,
@@ -1161,6 +1312,9 @@ static int lapic_save_regs(struct domain *d, hvm_domain_context_t *h)
for_each_vcpu ( d, v )
{
+ if ( hvm_funcs.sync_pir_to_irr )
+ hvm_funcs.sync_pir_to_irr(v);
+
s = vcpu_vlapic(v);
if ( (rc = hvm_save_entry(LAPIC_REGS, v->vcpu_id, h, s->regs)) != 0 )
break;
@@ -1169,6 +1323,35 @@ static int lapic_save_regs(struct domain *d, hvm_domain_context_t *h)
return rc;
}
+/*
+ * Following lapic_load_hidden()/lapic_load_regs() we may need to
+ * correct ID and LDR when they come from an old, broken hypervisor.
+ */
+static void lapic_load_fixup(struct vlapic *vlapic)
+{
+ uint32_t id = vlapic->loaded.id;
+
+ if ( vlapic_x2apic_mode(vlapic) && id && vlapic->loaded.ldr == 1 )
+ {
+ /*
+ * This is optional: ID != 0 contradicts LDR == 1. It's being added
+ * to aid in eventual debugging of issues arising from the fixup done
+ * here, but can be dropped as soon as it is found to conflict with
+ * other (future) changes.
+ */
+ if ( GET_xAPIC_ID(id) != vlapic_vcpu(vlapic)->vcpu_id * 2 ||
+ id != SET_xAPIC_ID(GET_xAPIC_ID(id)) )
+ printk(XENLOG_G_WARNING "%pv: bogus APIC ID %#x loaded\n",
+ vlapic_vcpu(vlapic), id);
+ set_x2apic_id(vlapic);
+ }
+ else /* Undo an eventual earlier fixup. */
+ {
+ vlapic_set_reg(vlapic, APIC_ID, id);
+ vlapic_set_reg(vlapic, APIC_LDR, vlapic->loaded.ldr);
+ }
+}
+
static int lapic_load_hidden(struct domain *d, hvm_domain_context_t *h)
{
uint16_t vcpuid;
@@ -1188,6 +1371,14 @@ static int lapic_load_hidden(struct domain *d, hvm_domain_context_t *h)
if ( hvm_load_entry_zeroextend(LAPIC, h, &s->hw) != 0 )
return -EINVAL;
+ s->loaded.hw = 1;
+ if ( s->loaded.regs )
+ lapic_load_fixup(s);
+
+ if ( !(s->hw.apic_base_msr & MSR_IA32_APICBASE_ENABLE) &&
+ unlikely(vlapic_x2apic_mode(s)) )
+ return -EINVAL;
+
vmx_vlapic_msr_changed(v);
return 0;
@@ -1212,6 +1403,12 @@ static int lapic_load_regs(struct domain *d, hvm_domain_context_t *h)
if ( hvm_load_entry(LAPIC_REGS, h, s->regs) != 0 )
return -EINVAL;
+ s->loaded.id = vlapic_get_reg(s, APIC_ID);
+ s->loaded.ldr = vlapic_get_reg(s, APIC_LDR);
+ s->loaded.regs = 1;
+ if ( s->loaded.hw )
+ lapic_load_fixup(s);
+
if ( hvm_funcs.process_isr )
hvm_funcs.process_isr(vlapic_find_highest_isr(s), v);
@@ -1232,6 +1429,12 @@ int vlapic_init(struct vcpu *v)
HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "%d", v->vcpu_id);
+ if ( is_pvh_vcpu(v) )
+ {
+ vlapic->hw.disabled = VLAPIC_HW_DISABLED;
+ return 0;
+ }
+
vlapic->pt.source = PTSRC_lapic;
if (vlapic->regs_page == NULL)
@@ -1263,6 +1466,8 @@ int vlapic_init(struct vcpu *v)
if ( v->vcpu_id == 0 )
vlapic->hw.apic_base_msr |= MSR_IA32_APICBASE_BSP;
+ spin_lock_init(&vlapic->esr_lock);
+
tasklet_init(&vlapic->init_sipi.tasklet,
vlapic_init_sipi_action,
(unsigned long)v);
@@ -1275,7 +1480,17 @@ void vlapic_destroy(struct vcpu *v)
struct vlapic *vlapic = vcpu_vlapic(v);
tasklet_kill(&vlapic->init_sipi.tasklet);
+ TRACE_0D(TRC_HVM_EMUL_LAPIC_STOP_TIMER);
destroy_periodic_time(&vlapic->pt);
unmap_domain_page_global(vlapic->regs);
free_domheap_page(vlapic->regs_page);
}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c
index 10e5f34..ab4ac50 100644
--- a/xen/arch/x86/hvm/vmsi.c
+++ b/xen/arch/x86/hvm/vmsi.c
@@ -43,14 +43,12 @@
#include <asm/io_apic.h>
static void vmsi_inj_irq(
- struct domain *d,
struct vlapic *target,
uint8_t vector,
uint8_t trig_mode,
uint8_t delivery_mode)
{
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vmsi_inj_irq "
- "irq %d trig %d delive mode %d\n",
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "vmsi_inj_irq: vec %02x trig %d dm %d\n",
vector, trig_mode, delivery_mode);
switch ( delivery_mode )
@@ -60,8 +58,7 @@ static void vmsi_inj_irq(
vlapic_set_irq(target, vector, trig_mode);
break;
default:
- gdprintk(XENLOG_WARNING, "error delivery mode %d\n", delivery_mode);
- break;
+ BUG();
}
}
@@ -76,38 +73,32 @@ int vmsi_deliver(
switch ( delivery_mode )
{
case dest_LowestPrio:
- {
target = vlapic_lowest_prio(d, NULL, 0, dest, dest_mode);
if ( target != NULL )
- vmsi_inj_irq(d, target, vector, trig_mode, delivery_mode);
- else
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "null round robin: "
- "vector=%x delivery_mode=%x\n",
- vector, dest_LowestPrio);
- break;
- }
+ {
+ vmsi_inj_irq(target, vector, trig_mode, delivery_mode);
+ break;
+ }
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "null MSI round robin: vector=%02x\n",
+ vector);
+ return -ESRCH;
case dest_Fixed:
- case dest_ExtINT:
- {
for_each_vcpu ( d, v )
if ( vlapic_match_dest(vcpu_vlapic(v), NULL,
0, dest, dest_mode) )
- vmsi_inj_irq(d, vcpu_vlapic(v),
- vector, trig_mode, delivery_mode);
+ vmsi_inj_irq(vcpu_vlapic(v), vector,
+ trig_mode, delivery_mode);
break;
- }
- case dest_SMI:
- case dest_NMI:
- case dest_INIT:
- case dest__reserved_2:
default:
- gdprintk(XENLOG_WARNING, "Unsupported delivery mode %d\n",
- delivery_mode);
- break;
+ printk(XENLOG_G_WARNING
+ "%pv: Unsupported MSI delivery mode %d for Dom%d\n",
+ current, delivery_mode, d->domain_id);
+ return -EINVAL;
}
- return 1;
+
+ return 0;
}
void vmsi_deliver_pirq(struct domain *d, const struct hvm_pirq_dpci *pirq_dpci)
@@ -235,6 +226,8 @@ static int msixtbl_read(
rcu_read_lock(&msixtbl_rcu_lock);
entry = msixtbl_find_entry(v, address);
+ if ( !entry )
+ goto out;
offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
if ( offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET )
@@ -277,6 +270,8 @@ static int msixtbl_write(struct vcpu *v, unsigned long address,
rcu_read_lock(&msixtbl_rcu_lock);
entry = msixtbl_find_entry(v, address);
+ if ( !entry )
+ goto out;
nr_entry = (address - entry->gtable) / PCI_MSIX_ENTRY_SIZE;
offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
diff --git a/xen/arch/x86/hvm/vmx/realmode.c b/xen/arch/x86/hvm/vmx/realmode.c
index 45066b2..fe8b4a0 100644
--- a/xen/arch/x86/hvm/vmx/realmode.c
+++ b/xen/arch/x86/hvm/vmx/realmode.c
@@ -129,27 +129,27 @@ static void realmode_emulate_one(struct hvm_emulate_ctxt *hvmemul_ctxt)
gdprintk(XENLOG_ERR, "Exception pending but no info.\n");
goto fail;
}
- hvmemul_ctxt->exn_vector = (uint8_t)intr_info;
- hvmemul_ctxt->exn_insn_len = 0;
+ hvmemul_ctxt->trap.vector = (uint8_t)intr_info;
+ hvmemul_ctxt->trap.insn_len = 0;
}
if ( unlikely(curr->domain->debugger_attached) &&
- ((hvmemul_ctxt->exn_vector == TRAP_debug) ||
- (hvmemul_ctxt->exn_vector == TRAP_int3)) )
+ ((hvmemul_ctxt->trap.vector == TRAP_debug) ||
+ (hvmemul_ctxt->trap.vector == TRAP_int3)) )
{
domain_pause_for_debugger();
}
else if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE )
{
gdprintk(XENLOG_ERR, "Exception %02x in protected mode.\n",
- hvmemul_ctxt->exn_vector);
+ hvmemul_ctxt->trap.vector);
goto fail;
}
else
{
realmode_deliver_exception(
- hvmemul_ctxt->exn_vector,
- hvmemul_ctxt->exn_insn_len,
+ hvmemul_ctxt->trap.vector,
+ hvmemul_ctxt->trap.insn_len,
hvmemul_ctxt);
}
}
@@ -157,14 +157,7 @@ static void realmode_emulate_one(struct hvm_emulate_ctxt *hvmemul_ctxt)
return;
fail:
- gdprintk(XENLOG_ERR,
- "Real-mode emulation failed @ %04x:%08lx: "
- "%02x %02x %02x %02x %02x %02x\n",
- hvmemul_get_seg_reg(x86_seg_cs, hvmemul_ctxt)->sel,
- hvmemul_ctxt->insn_buf_eip,
- hvmemul_ctxt->insn_buf[0], hvmemul_ctxt->insn_buf[1],
- hvmemul_ctxt->insn_buf[2], hvmemul_ctxt->insn_buf[3],
- hvmemul_ctxt->insn_buf[4], hvmemul_ctxt->insn_buf[5]);
+ hvm_dump_emulation_state(XENLOG_G_ERR "Real-mode", hvmemul_ctxt);
domain_crash(curr->domain);
}
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index ee1f4d5..9d8033e 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -22,6 +22,10 @@
#include <xen/lib.h>
#include <xen/errno.h>
#include <xen/domain_page.h>
+#include <xen/event.h>
+#include <xen/kernel.h>
+#include <xen/keyhandler.h>
+#include <xen/mem_event.h>
#include <asm/current.h>
#include <asm/cpufeature.h>
#include <asm/processor.h>
@@ -34,9 +38,6 @@
#include <asm/hvm/vmx/vvmx.h>
#include <asm/hvm/vmx/vmcs.h>
#include <asm/flushtlb.h>
-#include <xen/event.h>
-#include <xen/kernel.h>
-#include <xen/keyhandler.h>
#include <asm/shadow.h>
#include <asm/tboot.h>
@@ -71,6 +72,18 @@ u32 vmx_vmexit_control __read_mostly;
u32 vmx_vmentry_control __read_mostly;
u64 vmx_ept_vpid_cap __read_mostly;
+const u32 vmx_introspection_force_enabled_msrs[] = {
+ MSR_IA32_SYSENTER_EIP,
+ MSR_IA32_SYSENTER_ESP,
+ MSR_IA32_SYSENTER_CS,
+ MSR_IA32_MC0_CTL,
+ MSR_STAR,
+ MSR_LSTAR
+};
+
+const unsigned int vmx_introspection_force_enabled_msrs_size =
+ ARRAY_SIZE(vmx_introspection_force_enabled_msrs);
+
static DEFINE_PER_CPU_READ_MOSTLY(struct vmcs_struct *, vmxon_region);
static DEFINE_PER_CPU(struct vmcs_struct *, current_vmcs);
static DEFINE_PER_CPU(struct list_head, active_vmcs_list);
@@ -269,7 +282,8 @@ static int vmx_init_vmcs_config(void)
}
min = VM_EXIT_ACK_INTR_ON_EXIT;
- opt = VM_EXIT_SAVE_GUEST_PAT | VM_EXIT_LOAD_HOST_PAT;
+ opt = VM_EXIT_SAVE_GUEST_PAT | VM_EXIT_LOAD_HOST_PAT |
+ VM_EXIT_CLEAR_BNDCFGS;
min |= VM_EXIT_IA32E_MODE;
_vmx_vmexit_control = adjust_vmx_controls(
"VMExit Control", min, opt, MSR_IA32_VMX_EXIT_CTLS, &mismatch);
@@ -283,7 +297,7 @@ static int vmx_init_vmcs_config(void)
_vmx_pin_based_exec_control &= ~ PIN_BASED_POSTED_INTERRUPT;
min = 0;
- opt = VM_ENTRY_LOAD_GUEST_PAT;
+ opt = VM_ENTRY_LOAD_GUEST_PAT | VM_ENTRY_LOAD_BNDCFGS;
_vmx_vmentry_control = adjust_vmx_controls(
"VMEntry Control", min, opt, MSR_IA32_VMX_ENTRY_CTLS, &mismatch);
@@ -669,11 +683,6 @@ void vmx_vmcs_exit(struct vcpu *v)
}
}
-struct xgt_desc {
- unsigned short size;
- unsigned long address __attribute__((packed));
-};
-
static void vmx_set_host_env(struct vcpu *v)
{
unsigned int cpu = smp_processor_id();
@@ -699,11 +708,23 @@ static void vmx_set_host_env(struct vcpu *v)
void vmx_disable_intercept_for_msr(struct vcpu *v, u32 msr, int type)
{
unsigned long *msr_bitmap = v->arch.hvm_vmx.msr_bitmap;
+ struct domain *d = v->domain;
/* VMX MSR bitmap supported? */
if ( msr_bitmap == NULL )
return;
+ if ( unlikely(d->arch.hvm_domain.introspection_enabled) &&
+ mem_event_check_ring(&d->mem_event->access) )
+ {
+ unsigned int i;
+
+ /* Filter out MSR-s needed for memory introspection */
+ for ( i = 0; i < vmx_introspection_force_enabled_msrs_size; i++ )
+ if ( msr == vmx_introspection_force_enabled_msrs[i] )
+ return;
+ }
+
/*
* See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
* have the write-low and read-high bitmap offsets the wrong way round.
@@ -725,7 +746,7 @@ void vmx_disable_intercept_for_msr(struct vcpu *v, u32 msr, int type)
clear_bit(msr, msr_bitmap + 0xc00/BYTES_PER_LONG); /* write-high */
}
else
- HVM_DBG_LOG(DBG_LEVEL_0,
+ HVM_DBG_LOG(DBG_LEVEL_MSR,
"msr %x is out of the control range"
"0x00000000-0x00001fff and 0xc0000000-0xc0001fff"
"RDMSR or WRMSR will cause a VM exit", msr);
@@ -761,7 +782,7 @@ void vmx_enable_intercept_for_msr(struct vcpu *v, u32 msr, int type)
set_bit(msr, msr_bitmap + 0xc00/BYTES_PER_LONG); /* write-high */
}
else
- HVM_DBG_LOG(DBG_LEVEL_0,
+ HVM_DBG_LOG(DBG_LEVEL_MSR,
"msr %x is out of the control range"
"0x00000000-0x00001fff and 0xc0000000-0xc0001fff"
"RDMSR or WRMSR will cause a VM exit", msr);
@@ -959,6 +980,9 @@ static int construct_vmcs(struct vcpu *v)
vmx_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_EIP, MSR_TYPE_R | MSR_TYPE_W);
if ( paging_mode_hap(d) && (!iommu_enabled || iommu_snoop) )
vmx_disable_intercept_for_msr(v, MSR_IA32_CR_PAT, MSR_TYPE_R | MSR_TYPE_W);
+ if ( (vmexit_ctl & VM_EXIT_CLEAR_BNDCFGS) &&
+ (vmentry_ctl & VM_ENTRY_LOAD_BNDCFGS) )
+ vmx_disable_intercept_for_msr(v, MSR_IA32_BNDCFGS, MSR_TYPE_R | MSR_TYPE_W);
}
/* I/O access bitmap. */
@@ -1306,11 +1330,6 @@ void vm_resume_fail(void)
domain_crash_synchronous();
}
-static void wbinvd_ipi(void *info)
-{
- wbinvd();
-}
-
void vmx_do_resume(struct vcpu *v)
{
bool_t debug_state;
@@ -1337,7 +1356,7 @@ void vmx_do_resume(struct vcpu *v)
{
int cpu = v->arch.hvm_vmx.active_cpu;
if ( cpu != -1 )
- on_selected_cpus(cpumask_of(cpu), wbinvd_ipi, NULL, 1);
+ flush_mask(cpumask_of(cpu), FLUSH_CACHE);
}
vmx_clear_vmcs(v);
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 2cd4c59..2907afa 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -57,6 +57,10 @@
#include <asm/apic.h>
#include <asm/hvm/nestedhvm.h>
#include <asm/event.h>
+#include <public/arch-x86/cpuid.h>
+
+static bool_t __initdata opt_force_ept;
+boolean_param("force-ept", opt_force_ept);
enum handler_return { HNDL_done, HNDL_unhandled, HNDL_exception_raised };
@@ -130,6 +134,18 @@ static void vmx_vcpu_destroy(struct vcpu *v)
passive_domain_destroy(v);
}
+/* Only crash the guest if the problem originates in kernel mode. */
+static void vmx_crash_or_fault(struct vcpu *v)
+{
+ struct segment_register ss;
+
+ vmx_get_segment_register(v, x86_seg_ss, &ss);
+ if ( ss.attr.fields.dpl )
+ hvm_inject_hw_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE);
+ else
+ domain_crash(v->domain);
+}
+
static DEFINE_PER_CPU(struct vmx_msr_state, host_msr_state);
static const u32 msr_index[] =
@@ -195,7 +211,7 @@ long_mode_do_msr_read(unsigned int msr, uint64_t *msr_content)
return HNDL_unhandled;
}
- HVM_DBG_LOG(DBG_LEVEL_0, "msr %#x content %#"PRIx64, msr, *msr_content);
+ HVM_DBG_LOG(DBG_LEVEL_MSR, "msr %#x content %#"PRIx64, msr, *msr_content);
return HNDL_done;
}
@@ -207,7 +223,7 @@ long_mode_do_msr_write(unsigned int msr, uint64_t msr_content)
struct vmx_msr_state *guest_msr_state = &v->arch.hvm_vmx.msr_state;
struct vmx_msr_state *host_msr_state = &this_cpu(host_msr_state);
- HVM_DBG_LOG(DBG_LEVEL_0, "msr %#x content %#"PRIx64, msr, msr_content);
+ HVM_DBG_LOG(DBG_LEVEL_MSR, "msr %#x content %#"PRIx64, msr, msr_content);
switch ( msr )
{
@@ -250,7 +266,7 @@ long_mode_do_msr_write(unsigned int msr, uint64_t msr_content)
return HNDL_done;
uncanonical_address:
- HVM_DBG_LOG(DBG_LEVEL_0, "Not cano address of msr write %x", msr);
+ HVM_DBG_LOG(DBG_LEVEL_MSR, "Not cano address of msr write %x", msr);
hvm_inject_hw_exception(TRAP_gp_fault, 0);
return HNDL_exception_raised;
}
@@ -430,7 +446,8 @@ static void vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c)
c->error_code = 0;
__vmread(VM_ENTRY_INTR_INFO, &ev);
if ( (ev & INTR_INFO_VALID_MASK) &&
- hvm_event_needs_reinjection((ev >> 8) & 7, ev & 0xff) )
+ hvm_event_needs_reinjection(MASK_EXTR(ev, INTR_INFO_INTR_TYPE_MASK),
+ ev & INTR_INFO_VECTOR_MASK) )
{
c->pending_event = ev;
__vmread(VM_ENTRY_EXCEPTION_ERROR_CODE, &ev);
@@ -505,23 +522,22 @@ static int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c)
__vmwrite(GUEST_DR7, c->dr7);
- vmx_vmcs_exit(v);
-
- paging_update_paging_modes(v);
-
- if ( c->pending_valid )
+ if ( c->pending_valid &&
+ hvm_event_needs_reinjection(c->pending_type, c->pending_vector) )
{
gdprintk(XENLOG_INFO, "Re-injecting %#"PRIx32", %#"PRIx32"\n",
c->pending_event, c->error_code);
-
- if ( hvm_event_needs_reinjection(c->pending_type, c->pending_vector) )
- {
- vmx_vmcs_enter(v);
- __vmwrite(VM_ENTRY_INTR_INFO, c->pending_event);
- __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, c->error_code);
- vmx_vmcs_exit(v);
- }
+ __vmwrite(VM_ENTRY_INTR_INFO, c->pending_event);
+ __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, c->error_code);
}
+ else
+ {
+ __vmwrite(VM_ENTRY_INTR_INFO, 0);
+ __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, 0);
+ }
+ vmx_vmcs_exit(v);
+
+ paging_update_paging_modes(v);
return 0;
}
@@ -540,7 +556,8 @@ static void vmx_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
data->msr_star = guest_state->msrs[VMX_INDEX_MSR_STAR];
data->msr_syscall_mask = guest_state->msrs[VMX_INDEX_MSR_SYSCALL_MASK];
- data->tsc = hvm_get_guest_tsc(v);
+ data->tsc = hvm_get_guest_tsc_fixed(v,
+ v->domain->arch.hvm_domain.sync_tsc);
}
static void vmx_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
@@ -556,7 +573,7 @@ static void vmx_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
v->arch.hvm_vmx.cstar = data->msr_cstar;
v->arch.hvm_vmx.shadow_gs = data->shadow_gs;
- hvm_set_guest_tsc(v, data->tsc);
+ hvm_set_guest_tsc_fixed(v, data->tsc, v->domain->arch.hvm_domain.sync_tsc);
}
@@ -580,6 +597,55 @@ static int vmx_load_vmcs_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt)
return 0;
}
+static unsigned int __init vmx_init_msr(void)
+{
+ return !!cpu_has_mpx;
+}
+
+static void vmx_save_msr(struct vcpu *v, struct hvm_msr *ctxt)
+{
+ vmx_vmcs_enter(v);
+
+ if ( cpu_has_mpx )
+ {
+ __vmread(GUEST_BNDCFGS, &ctxt->msr[ctxt->count].val);
+ if ( ctxt->msr[ctxt->count].val )
+ ctxt->msr[ctxt->count++].index = MSR_IA32_BNDCFGS;
+ }
+
+ vmx_vmcs_exit(v);
+}
+
+static int vmx_load_msr(struct vcpu *v, struct hvm_msr *ctxt)
+{
+ unsigned int i;
+ int err = 0;
+
+ vmx_vmcs_enter(v);
+
+ for ( i = 0; i < ctxt->count; ++i )
+ {
+ switch ( ctxt->msr[i].index )
+ {
+ case MSR_IA32_BNDCFGS:
+ if ( cpu_has_mpx )
+ __vmwrite(GUEST_BNDCFGS, ctxt->msr[i].val);
+ else
+ err = -ENXIO;
+ break;
+ default:
+ continue;
+ }
+ if ( err )
+ break;
+ ctxt->msr[i]._rsvd = 1;
+ }
+
+ vmx_vmcs_exit(v);
+
+ return err;
+}
+
static void vmx_fpu_enter(struct vcpu *v)
{
vcpu_restore_fpu_lazy(v);
@@ -693,10 +759,10 @@ void vmx_get_segment_register(struct vcpu *v, enum x86_segment seg,
if ( !warned )
{
warned = 1;
- printk(XENLOG_WARNING "Segment register inaccessible for d%dv%d\n"
+ printk(XENLOG_WARNING "Segment register inaccessible for %pv\n"
"(If you see this outside of debugging activity,"
" please report to xen-devel at lists.xenproject.org)\n",
- v->domain->domain_id, v->vcpu_id);
+ v);
}
memset(reg, 0, sizeof(*reg));
return;
@@ -1011,7 +1077,7 @@ static void vmx_handle_cd(struct vcpu *v, unsigned long value)
}
}
-static void vmx_set_tsc_offset(struct vcpu *v, u64 offset)
+static void vmx_set_tsc_offset(struct vcpu *v, u64 offset, u64 at_tsc)
{
vmx_vmcs_enter(v);
@@ -1274,12 +1340,12 @@ static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr)
if ( !hvm_paging_enabled(v) )
{
/*
- * SMEP is disabled if CPU is in non-paging mode in hardware.
+ * SMEP/SMAP is disabled if CPU is in non-paging mode in hardware.
* However Xen always uses paging mode to emulate guest non-paging
- * mode. To emulate this behavior, SMEP needs to be manually
+ * mode. To emulate this behavior, SMEP/SMAP needs to be manually
* disabled when guest VCPU is in non-paging mode.
*/
- v->arch.hvm_vcpu.hw_cr[4] &= ~X86_CR4_SMEP;
+ v->arch.hvm_vcpu.hw_cr[4] &= ~(X86_CR4_SMEP | X86_CR4_SMAP);
}
__vmwrite(GUEST_CR4, v->arch.hvm_vcpu.hw_cr[4]);
break;
@@ -1530,6 +1596,8 @@ static void vmx_process_isr(int isr, struct vcpu *v)
{
unsigned long status;
u8 old;
+ unsigned int i;
+ const struct vlapic *vlapic = vcpu_vlapic(v);
if ( isr < 0 )
isr = 0;
@@ -1543,6 +1611,28 @@ static void vmx_process_isr(int isr, struct vcpu *v)
status |= isr << VMX_GUEST_INTR_STATUS_SVI_OFFSET;
__vmwrite(GUEST_INTR_STATUS, status);
}
+
+ /*
+ * Theoretically, only level triggered interrupts can have their
+ * corresponding bits set in the eoi exit bitmap. That is, the bits
+ * set in the eoi exit bitmap should also be set in TMR. But a periodic
+ * timer interrupt does not follow the rule: it is edge triggered, but
+ * requires its corresponding bit be set in the eoi exit bitmap. So we
+ * should not construct the eoi exit bitmap based on TMR.
+ * Here we will construct the eoi exit bitmap via (IRR | ISR). This
+ * means that EOIs to the interrupts that are set in the IRR or ISR will
+ * cause VM exits after restoring, regardless of the trigger modes. It
+ * is acceptable because the subsequent interrupts will set up the eoi
+ * bitmap correctly.
+ */
+ for ( i = 0x10; i < NR_VECTORS; ++i )
+ if ( vlapic_test_vector(i, &vlapic->regs->data[APIC_IRR]) ||
+ vlapic_test_vector(i, &vlapic->regs->data[APIC_ISR]) )
+ set_bit(i, v->arch.hvm_vmx.eoi_exit_bitmap);
+
+ for ( i = 0; i < ARRAY_SIZE(v->arch.hvm_vmx.eoi_exit_bitmap); ++i )
+ __vmwrite(EOI_EXIT_BITMAP(i), v->arch.hvm_vmx.eoi_exit_bitmap[i]);
+
vmx_vmcs_exit(v);
}
@@ -1610,6 +1700,36 @@ static void vmx_handle_eoi(u8 vector)
__vmwrite(GUEST_INTR_STATUS, status);
}
+void vmx_hypervisor_cpuid_leaf(uint32_t sub_idx,
+ uint32_t *eax, uint32_t *ebx,
+ uint32_t *ecx, uint32_t *edx)
+{
+ if ( sub_idx != 0 )
+ return;
+ if ( cpu_has_vmx_apic_reg_virt )
+ *eax |= XEN_HVM_CPUID_APIC_ACCESS_VIRT;
+ /*
+ * We want to claim that x2APIC is virtualized if APIC MSR accesses are
+ * not intercepted. When all three of these are true both rdmsr and wrmsr
+ * in the guest will run without VMEXITs (see vmx_vlapic_msr_changed()).
+ */
+ if ( cpu_has_vmx_virtualize_x2apic_mode && cpu_has_vmx_apic_reg_virt &&
+ cpu_has_vmx_virtual_intr_delivery )
+ *eax |= XEN_HVM_CPUID_X2APIC_VIRT;
+}
+
+static void vmx_enable_msr_exit_interception(struct domain *d)
+{
+ struct vcpu *v;
+ unsigned int i;
+
+ /* Enable interception for MSRs needed for memory introspection. */
+ for_each_vcpu ( d, v )
+ for ( i = 0; i < vmx_introspection_force_enabled_msrs_size; i++ )
+ vmx_enable_intercept_for_msr(v, vmx_introspection_force_enabled_msrs[i],
+ MSR_TYPE_W);
+}
+
static struct hvm_function_table __initdata vmx_function_table = {
.name = "VMX",
.cpu_up_prepare = vmx_cpu_up_prepare,
@@ -1620,6 +1740,9 @@ static struct hvm_function_table __initdata vmx_function_table = {
.vcpu_destroy = vmx_vcpu_destroy,
.save_cpu_ctxt = vmx_save_vmcs_ctxt,
.load_cpu_ctxt = vmx_load_vmcs_ctxt,
+ .init_msr = vmx_init_msr,
+ .save_msr = vmx_save_msr,
+ .load_msr = vmx_load_msr,
.get_interrupt_shadow = vmx_get_interrupt_shadow,
.set_interrupt_shadow = vmx_set_interrupt_shadow,
.guest_x86_mode = vmx_guest_x86_mode,
@@ -1664,6 +1787,8 @@ static struct hvm_function_table __initdata vmx_function_table = {
.sync_pir_to_irr = vmx_sync_pir_to_irr,
.handle_eoi = vmx_handle_eoi,
.nhvm_hap_walk_L1_p2m = nvmx_hap_walk_L1_p2m,
+ .hypervisor_cpuid_leaf = vmx_hypervisor_cpuid_leaf,
+ .enable_msr_exit_interception = vmx_enable_msr_exit_interception,
};
const struct hvm_function_table * __init start_vmx(void)
@@ -1680,7 +1805,7 @@ const struct hvm_function_table * __init start_vmx(void)
* Do not enable EPT when (!cpu_has_vmx_pat), to prevent security hole
* (refer to http://xenbits.xen.org/xsa/advisory-60.html).
*/
- if ( cpu_has_vmx_ept && cpu_has_vmx_pat )
+ if ( cpu_has_vmx_ept && (cpu_has_vmx_pat || opt_force_ept) )
{
vmx_function_table.hap_supported = 1;
@@ -1970,7 +2095,7 @@ static int is_last_branch_msr(u32 ecx)
static int vmx_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
{
- HVM_DBG_LOG(DBG_LEVEL_1, "ecx=%#x", msr);
+ HVM_DBG_LOG(DBG_LEVEL_MSR, "ecx=%#x", msr);
switch ( msr )
{
@@ -2035,7 +2160,7 @@ static int vmx_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
}
done:
- HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%#x, msr_value=%#"PRIx64,
+ HVM_DBG_LOG(DBG_LEVEL_MSR, "returns: ecx=%#x, msr_value=%#"PRIx64,
msr, *msr_content);
return X86EMUL_OKAY;
@@ -2090,6 +2215,7 @@ void vmx_vlapic_msr_changed(struct vcpu *v)
{
int virtualize_x2apic_mode;
struct vlapic *vlapic = vcpu_vlapic(v);
+ unsigned int msr;
virtualize_x2apic_mode = ( (cpu_has_vmx_apic_reg_virt ||
cpu_has_vmx_virtual_intr_delivery) &&
@@ -2106,8 +2232,6 @@ void vmx_vlapic_msr_changed(struct vcpu *v)
if ( !vlapic_hw_disabled(vlapic) &&
(vlapic_base_address(vlapic) == APIC_DEFAULT_PHYS_BASE) )
{
- unsigned int msr;
-
if ( virtualize_x2apic_mode && vlapic_x2apic_mode(vlapic) )
{
v->arch.hvm_vmx.secondary_exec_control |=
@@ -2136,15 +2260,15 @@ void vmx_vlapic_msr_changed(struct vcpu *v)
}
}
else
- {
v->arch.hvm_vmx.secondary_exec_control |=
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
- for ( msr = MSR_IA32_APICBASE_MSR;
- msr <= MSR_IA32_APICBASE_MSR + 0xff; msr++ )
- vmx_enable_intercept_for_msr(v, msr,
- MSR_TYPE_R | MSR_TYPE_W);
- }
}
+ if ( !(v->arch.hvm_vmx.secondary_exec_control &
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE) )
+ for ( msr = MSR_IA32_APICBASE_MSR;
+ msr <= MSR_IA32_APICBASE_MSR + 0xff; msr++ )
+ vmx_enable_intercept_for_msr(v, msr, MSR_TYPE_R | MSR_TYPE_W);
+
vmx_update_secondary_exec_control(v);
vmx_vmcs_exit(v);
}
@@ -2153,7 +2277,7 @@ static int vmx_msr_write_intercept(unsigned int msr, uint64_t msr_content)
{
struct vcpu *v = current;
- HVM_DBG_LOG(DBG_LEVEL_1, "ecx=%#x, msr_value=%#"PRIx64, msr, msr_content);
+ HVM_DBG_LOG(DBG_LEVEL_MSR, "ecx=%#x, msr_value=%#"PRIx64, msr, msr_content);
switch ( msr )
{
@@ -2161,21 +2285,25 @@ static int vmx_msr_write_intercept(unsigned int msr, uint64_t msr_content)
__vmwrite(GUEST_SYSENTER_CS, msr_content);
break;
case MSR_IA32_SYSENTER_ESP:
+ if ( !is_canonical_address(msr_content) )
+ goto gp_fault;
__vmwrite(GUEST_SYSENTER_ESP, msr_content);
break;
case MSR_IA32_SYSENTER_EIP:
+ if ( !is_canonical_address(msr_content) )
+ goto gp_fault;
__vmwrite(GUEST_SYSENTER_EIP, msr_content);
break;
case MSR_IA32_DEBUGCTLMSR: {
int i, rc = 0;
uint64_t supported = IA32_DEBUGCTLMSR_LBR | IA32_DEBUGCTLMSR_BTF;
- if ( !msr_content )
- break;
+ if ( boot_cpu_has(X86_FEATURE_RTM) )
+ supported |= IA32_DEBUGCTLMSR_RTM;
if ( msr_content & ~supported )
{
/* Perhaps some other bits are supported in vpmu. */
- if ( !vpmu_do_wrmsr(msr, msr_content) )
+ if ( !vpmu_do_wrmsr(msr, msr_content, supported) )
break;
}
if ( msr_content & IA32_DEBUGCTLMSR_LBR )
@@ -2191,12 +2319,10 @@ static int vmx_msr_write_intercept(unsigned int msr, uint64_t msr_content)
}
if ( (rc < 0) ||
- (vmx_add_host_load_msr(msr) < 0) )
+ (msr_content && (vmx_add_host_load_msr(msr) < 0)) )
hvm_inject_hw_exception(TRAP_machine_check, 0);
else
- {
__vmwrite(GUEST_IA32_DEBUGCTL, msr_content);
- }
break;
}
@@ -2206,7 +2332,7 @@ static int vmx_msr_write_intercept(unsigned int msr, uint64_t msr_content)
goto gp_fault;
break;
default:
- if ( vpmu_do_wrmsr(msr, msr_content) )
+ if ( vpmu_do_wrmsr(msr, msr_content, 0) )
return X86EMUL_OKAY;
if ( passive_domain_do_wrmsr(msr, msr_content) )
return X86EMUL_OKAY;
@@ -2221,7 +2347,7 @@ static int vmx_msr_write_intercept(unsigned int msr, uint64_t msr_content)
!is_last_branch_msr(msr) )
switch ( wrmsr_hypervisor_regs(msr, msr_content) )
{
- case -EAGAIN:
+ case -ERESTART:
return X86EMUL_RETRY;
case 0:
case 1:
@@ -2259,18 +2385,13 @@ static void vmx_do_extint(struct cpu_user_regs *regs)
do_IRQ(regs);
}
-static void wbinvd_ipi(void *info)
-{
- wbinvd();
-}
-
static void vmx_wbinvd_intercept(void)
{
if ( !cache_flush_permitted(current->domain) || iommu_snoop )
return;
if ( cpu_has_wbinvd_exiting )
- on_each_cpu(wbinvd_ipi, NULL, 1);
+ flush_all(FLUSH_CACHE);
else
wbinvd();
}
@@ -2283,6 +2404,24 @@ static void ept_handle_violation(unsigned long qualification, paddr_t gpa)
int ret;
struct domain *d = current->domain;
+ /*
+ * We treat all write violations also as read violations.
+ * The reason why this is required is the following warning:
+ * "An EPT violation that occurs during as a result of execution of a
+ * read-modify-write operation sets bit 1 (data write). Whether it also
+ * sets bit 0 (data read) is implementation-specific and, for a given
+ * implementation, may differ for different kinds of read-modify-write
+ * operations."
+ * - Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+ * Volume 3C: System Programming Guide, Part 3
+ */
+ struct npfec npfec = {
+ .read_access = !!(qualification & EPT_READ_VIOLATION) ||
+ !!(qualification & EPT_WRITE_VIOLATION),
+ .write_access = !!(qualification & EPT_WRITE_VIOLATION),
+ .insn_fetch = !!(qualification & EPT_EXEC_VIOLATION)
+ };
+
if ( tb_init_done )
{
struct {
@@ -2300,14 +2439,18 @@ static void ept_handle_violation(unsigned long qualification, paddr_t gpa)
}
if ( qualification & EPT_GLA_VALID )
+ {
__vmread(GUEST_LINEAR_ADDRESS, &gla);
+ npfec.gla_valid = 1;
+ if( qualification & EPT_GLA_FAULT )
+ npfec.kind = npfec_kind_with_gla;
+ else
+ npfec.kind = npfec_kind_in_gpt;
+ }
else
gla = ~0ull;
- ret = hvm_hap_nested_page_fault(gpa,
- !!(qualification & EPT_GLA_VALID), gla,
- !!(qualification & EPT_READ_VIOLATION),
- !!(qualification & EPT_WRITE_VIOLATION),
- !!(qualification & EPT_EXEC_VIOLATION));
+
+ ret = hvm_hap_nested_page_fault(gpa, gla, npfec);
switch ( ret )
{
case 0: // Unhandled L1 EPT violation
@@ -2377,7 +2520,7 @@ static void vmx_failed_vmentry(unsigned int exit_reason,
vmcs_dump_vcpu(curr);
printk("**************************************\n");
- domain_crash(curr->domain);
+ vmx_crash_or_fault(curr);
}
void vmx_enter_realmode(struct cpu_user_regs *regs)
@@ -2396,6 +2539,19 @@ static void vmx_vmexit_ud_intercept(struct cpu_user_regs *regs)
struct hvm_emulate_ctxt ctxt;
int rc;
+ if ( opt_hvm_fep )
+ {
+ char sig[5]; /* ud2; .ascii "xen" */
+
+ if ( (hvm_fetch_from_guest_virt_nofault(
+ sig, regs->eip, sizeof(sig), 0) == HVMCOPY_okay) &&
+ (memcmp(sig, "\xf\xbxen", sizeof(sig)) == 0) )
+ {
+ regs->eip += sizeof(sig);
+ regs->eflags &= ~X86_EFLAGS_RF;
+ }
+ }
+
hvm_emulate_prepare(&ctxt, regs);
rc = hvm_emulate_one(&ctxt);
@@ -2407,7 +2563,7 @@ static void vmx_vmexit_ud_intercept(struct cpu_user_regs *regs)
break;
case X86EMUL_EXCEPTION:
if ( ctxt.exn_pending )
- hvm_inject_hw_exception(ctxt.exn_vector, ctxt.exn_error_code);
+ hvm_inject_trap(&ctxt.trap);
/* fall through */
default:
hvm_emulate_writeback(&ctxt);
@@ -2442,7 +2598,9 @@ static void vmx_idtv_reinject(unsigned long idtv_info)
/* Event delivery caused this intercept? Queue for redelivery. */
if ( unlikely(idtv_info & INTR_INFO_VALID_MASK) )
{
- if ( hvm_event_needs_reinjection((idtv_info>>8)&7, idtv_info&0xff) )
+ if ( hvm_event_needs_reinjection(MASK_EXTR(idtv_info,
+ INTR_INFO_INTR_TYPE_MASK),
+ idtv_info & INTR_INFO_VECTOR_MASK) )
{
/* See SDM 3B 25.7.1.1 and .2 for info about masking resvd bits. */
__vmwrite(VM_ENTRY_INTR_INFO,
@@ -2972,6 +3130,16 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
break;
}
+ case EXIT_REASON_EPT_MISCONFIG:
+ {
+ paddr_t gpa;
+
+ __vmread(GUEST_PHYSICAL_ADDRESS, &gpa);
+ if ( !ept_handle_misconfig(gpa) )
+ goto exit_and_crash;
+ break;
+ }
+
case EXIT_REASON_MONITOR_TRAP_FLAG:
v->arch.hvm_vmx.exec_control &= ~CPU_BASED_MONITOR_TRAP_FLAG;
vmx_update_cpu_exec_control(v);
@@ -2995,8 +3163,7 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
break;
case EXIT_REASON_APIC_WRITE:
- if ( vmx_handle_apic_write() )
- hvm_inject_hw_exception(TRAP_gp_fault, 0);
+ vmx_handle_apic_write();
break;
case EXIT_REASON_ACCESS_GDTR_OR_IDTR:
@@ -3006,8 +3173,8 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
/* fall through */
default:
exit_and_crash:
- gdprintk(XENLOG_ERR, "Bad vmexit (reason %#lx)\n", exit_reason);
- domain_crash(v->domain);
+ gdprintk(XENLOG_WARNING, "Bad vmexit (reason %#lx)\n", exit_reason);
+ vmx_crash_or_fault(v);
break;
}
diff --git a/xen/arch/x86/hvm/vmx/vpmu_core2.c b/xen/arch/x86/hvm/vmx/vpmu_core2.c
index f6e8ec0..68b6272 100644
--- a/xen/arch/x86/hvm/vmx/vpmu_core2.c
+++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c
@@ -105,9 +105,9 @@ static void handle_pmc_quirk(u64 msr_content)
if ( val & 0x1 )
{
u64 cnt;
- rdmsrl(MSR_P6_PERFCTR0 + i, cnt);
+ rdmsrl(MSR_P6_PERFCTR(i), cnt);
if ( cnt == 0 )
- wrmsrl(MSR_P6_PERFCTR0 + i, 1);
+ wrmsrl(MSR_P6_PERFCTR(i), 1);
}
val >>= 1;
}
@@ -238,11 +238,11 @@ static int is_core2_vpmu_msr(u32 msr_index, int *type, int *index)
return 1;
}
- if ( (msr_index >= MSR_P6_EVNTSEL0) &&
- (msr_index < (MSR_P6_EVNTSEL0 + core2_get_pmc_count())) )
+ if ( (msr_index >= MSR_P6_EVNTSEL(0)) &&
+ (msr_index < (MSR_P6_EVNTSEL(core2_get_pmc_count()))) )
{
*type = MSR_TYPE_ARCH_CTRL;
- *index = msr_index - MSR_P6_EVNTSEL0;
+ *index = msr_index - MSR_P6_EVNTSEL(0);
return 1;
}
@@ -278,7 +278,7 @@ static void core2_vpmu_set_msr_bitmap(unsigned long *msr_bitmap)
for ( i = 0; i < core2_ctrls.num; i++ )
clear_bit(msraddr_to_bitpos(core2_ctrls.msr[i]), msr_bitmap);
for ( i = 0; i < core2_get_pmc_count(); i++ )
- clear_bit(msraddr_to_bitpos(MSR_P6_EVNTSEL0+i), msr_bitmap);
+ clear_bit(msraddr_to_bitpos(MSR_P6_EVNTSEL(i)), msr_bitmap);
}
static void core2_vpmu_unset_msr_bitmap(unsigned long *msr_bitmap)
@@ -308,7 +308,7 @@ static void core2_vpmu_unset_msr_bitmap(unsigned long *msr_bitmap)
for ( i = 0; i < core2_ctrls.num; i++ )
set_bit(msraddr_to_bitpos(core2_ctrls.msr[i]), msr_bitmap);
for ( i = 0; i < core2_get_pmc_count(); i++ )
- set_bit(msraddr_to_bitpos(MSR_P6_EVNTSEL0+i), msr_bitmap);
+ set_bit(msraddr_to_bitpos(MSR_P6_EVNTSEL(i)), msr_bitmap);
}
static inline void __core2_vpmu_save(struct vcpu *v)
@@ -359,7 +359,7 @@ static inline void __core2_vpmu_load(struct vcpu *v)
for ( i = 0; i < core2_ctrls.num; i++ )
wrmsrl(core2_ctrls.msr[i], core2_vpmu_cxt->ctrls[i]);
for ( i = 0; i < core2_get_pmc_count(); i++ )
- wrmsrl(MSR_P6_EVNTSEL0+i, core2_vpmu_cxt->arch_msr_pair[i].control);
+ wrmsrl(MSR_P6_EVNTSEL(i), core2_vpmu_cxt->arch_msr_pair[i].control);
}
static void core2_vpmu_load(struct vcpu *v)
@@ -369,6 +369,8 @@ static void core2_vpmu_load(struct vcpu *v)
if ( vpmu_is_set(vpmu, VPMU_CONTEXT_LOADED) )
return;
+ vpmu_set(vpmu, VPMU_CONTEXT_LOADED);
+
__core2_vpmu_load(v);
}
@@ -452,7 +454,8 @@ static int core2_vpmu_msr_common_check(u32 msr_index, int *type, int *index)
return 1;
}
-static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content)
+static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content,
+ uint64_t supported)
{
u64 global_ctrl, non_global_ctrl;
char pmu_enable = 0;
@@ -467,24 +470,26 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content)
/* Special handling for BTS */
if ( msr == MSR_IA32_DEBUGCTLMSR )
{
- uint64_t supported = IA32_DEBUGCTLMSR_TR | IA32_DEBUGCTLMSR_BTS |
- IA32_DEBUGCTLMSR_BTINT;
+ supported |= IA32_DEBUGCTLMSR_TR | IA32_DEBUGCTLMSR_BTS |
+ IA32_DEBUGCTLMSR_BTINT;
if ( cpu_has(¤t_cpu_data, X86_FEATURE_DSCPL) )
supported |= IA32_DEBUGCTLMSR_BTS_OFF_OS |
IA32_DEBUGCTLMSR_BTS_OFF_USR;
- if ( msr_content & supported )
- {
- if ( vpmu_is_set(vpmu, VPMU_CPU_HAS_BTS) )
- return 1;
- gdprintk(XENLOG_WARNING, "Debug Store is not supported on this cpu\n");
- hvm_inject_hw_exception(TRAP_gp_fault, 0);
- return 0;
- }
+ if ( !(msr_content & ~supported) &&
+ vpmu_is_set(vpmu, VPMU_CPU_HAS_BTS) )
+ return 1;
+ if ( (msr_content & supported) &&
+ !vpmu_is_set(vpmu, VPMU_CPU_HAS_BTS) )
+ printk(XENLOG_G_WARNING
+ "%pv: Debug Store unsupported on this CPU\n",
+ current);
}
return 0;
}
+ ASSERT(!supported);
+
core2_vpmu_cxt = vpmu->context;
switch ( msr )
{
@@ -521,7 +526,7 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content)
global_ctrl = msr_content;
for ( i = 0; i < core2_get_pmc_count(); i++ )
{
- rdmsrl(MSR_P6_EVNTSEL0+i, non_global_ctrl);
+ rdmsrl(MSR_P6_EVNTSEL(i), non_global_ctrl);
core2_vpmu_cxt->pmu_enable->arch_pmc_enable[i] =
global_ctrl & (non_global_ctrl >> 22) & 1;
global_ctrl >>= 1;
@@ -550,7 +555,7 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content)
}
break;
default:
- tmp = msr - MSR_P6_EVNTSEL0;
+ tmp = msr - MSR_P6_EVNTSEL(0);
vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, &global_ctrl);
if ( tmp >= 0 && tmp < core2_get_pmc_count() )
core2_vpmu_cxt->pmu_enable->arch_pmc_enable[tmp] =
@@ -759,19 +764,19 @@ static int core2_vpmu_initialise(struct vcpu *v, unsigned int vpmu_flags)
{
struct vpmu_struct *vpmu = vcpu_vpmu(v);
u64 msr_content;
- struct cpuinfo_x86 *c = ¤t_cpu_data;
+ static bool_t ds_warned;
if ( !(vpmu_flags & VPMU_BOOT_BTS) )
goto func_out;
/* Check the 'Debug Store' feature in the CPUID.EAX[1]:EDX[21] */
- if ( cpu_has(c, X86_FEATURE_DS) )
+ while ( boot_cpu_has(X86_FEATURE_DS) )
{
- if ( !cpu_has(c, X86_FEATURE_DTES64) )
+ if ( !boot_cpu_has(X86_FEATURE_DTES64) )
{
- printk(XENLOG_G_WARNING "CPU doesn't support 64-bit DS Area"
- " - Debug Store disabled for d%d:v%d\n",
- v->domain->domain_id, v->vcpu_id);
- goto func_out;
+ if ( !ds_warned )
+ printk(XENLOG_G_WARNING "CPU doesn't support 64-bit DS Area"
+ " - Debug Store disabled for guests\n");
+ break;
}
vpmu_set(vpmu, VPMU_CPU_HAS_DS);
rdmsrl(MSR_IA32_MISC_ENABLE, msr_content);
@@ -779,14 +784,16 @@ static int core2_vpmu_initialise(struct vcpu *v, unsigned int vpmu_flags)
{
/* If BTS_UNAVAIL is set reset the DS feature. */
vpmu_reset(vpmu, VPMU_CPU_HAS_DS);
- printk(XENLOG_G_WARNING "CPU has set BTS_UNAVAIL"
- " - Debug Store disabled for d%d:v%d\n",
- v->domain->domain_id, v->vcpu_id);
+ if ( !ds_warned )
+ printk(XENLOG_G_WARNING "CPU has set BTS_UNAVAIL"
+ " - Debug Store disabled for guests\n");
+ break;
}
- else
+
+ vpmu_set(vpmu, VPMU_CPU_HAS_BTS);
+ if ( !ds_warned )
{
- vpmu_set(vpmu, VPMU_CPU_HAS_BTS);
- if ( !cpu_has(c, X86_FEATURE_DSCPL) )
+ if ( !boot_cpu_has(X86_FEATURE_DSCPL) )
printk(XENLOG_G_INFO
"vpmu: CPU doesn't support CPL-Qualified BTS\n");
printk("******************************************************\n");
@@ -798,8 +805,10 @@ static int core2_vpmu_initialise(struct vcpu *v, unsigned int vpmu_flags)
printk("** It is NOT recommended for production use! **\n");
printk("******************************************************\n");
}
+ break;
}
-func_out:
+ ds_warned = 1;
+ func_out:
check_pmc_quirk();
return 0;
}
diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index 40167d6..9ccc03f 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1058,7 +1058,7 @@ static void load_shadow_guest_state(struct vcpu *v)
if ( control & VM_ENTRY_LOAD_PERF_GLOBAL_CTRL )
hvm_msr_write_intercept(MSR_CORE_PERF_GLOBAL_CTRL, __get_vvmcs(vvmcs, GUEST_PERF_GLOBAL_CTRL));
- hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset);
+ hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset, 0);
vvmcs_to_shadow_bulk(v, ARRAY_SIZE(vmentry_fields), vmentry_fields);
@@ -1259,7 +1259,7 @@ static void load_vvmcs_host_state(struct vcpu *v)
if ( control & VM_EXIT_LOAD_PERF_GLOBAL_CTRL )
hvm_msr_write_intercept(MSR_CORE_PERF_GLOBAL_CTRL, __get_vvmcs(vvmcs, HOST_PERF_GLOBAL_CTRL));
- hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset);
+ hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset, 0);
__set_vvmcs(vvmcs, VM_ENTRY_INTR_INFO, 0);
}
@@ -1394,7 +1394,6 @@ void nvmx_switch_guest(void)
struct vcpu *v = current;
struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v);
struct cpu_user_regs *regs = guest_cpu_user_regs();
- const ioreq_t *ioreq = get_ioreq(v);
/*
* A pending IO emulation may still be not finished. In this case, no
@@ -1404,7 +1403,7 @@ void nvmx_switch_guest(void)
* don't want to continue as this setup is not implemented nor supported
* as of right now.
*/
- if ( !ioreq || ioreq->state != STATE_IOREQ_NONE )
+ if ( hvm_io_pending(v) )
return;
/*
* a softirq may interrupt us between a virtual vmentry is
@@ -2522,3 +2521,13 @@ void nvmx_set_cr_read_shadow(struct vcpu *v, unsigned int cr)
/* nvcpu.guest_cr is what L2 write to cr actually. */
__vmwrite(read_shadow_field, v->arch.hvm_vcpu.nvcpu.guest_cr[cr]);
}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/hvm/vpic.c b/xen/arch/x86/hvm/vpic.c
index fea3f68..2c6e6e5 100644
--- a/xen/arch/x86/hvm/vpic.c
+++ b/xen/arch/x86/hvm/vpic.c
@@ -30,6 +30,7 @@
#include <xen/lib.h>
#include <xen/errno.h>
#include <xen/sched.h>
+#include <xen/trace.h>
#include <asm/hvm/hvm.h>
#include <asm/hvm/io.h>
#include <asm/hvm/support.h>
@@ -99,6 +100,8 @@ static void vpic_update_int_output(struct hvm_hw_vpic *vpic)
ASSERT(vpic_is_locked(vpic));
irq = vpic_get_highest_priority_irq(vpic);
+ TRACE_3D(TRC_HVM_EMUL_PIC_INT_OUTPUT, vpic->int_output, vpic->is_master,
+ irq);
if ( vpic->int_output == (irq >= 0) )
return;
@@ -112,7 +115,10 @@ static void vpic_update_int_output(struct hvm_hw_vpic *vpic)
/* Master INT line is connected in Virtual Wire Mode. */
struct vcpu *v = vpic_domain(vpic)->arch.hvm_domain.i8259_target;
if ( v != NULL )
+ {
+ TRACE_1D(TRC_HVM_EMUL_PIC_KICK, irq);
vcpu_kick(v);
+ }
}
else
{
@@ -135,6 +141,7 @@ static void __vpic_intack(struct hvm_hw_vpic *vpic, int irq)
ASSERT(vpic_is_locked(vpic));
+ TRACE_2D(TRC_HVM_EMUL_PIC_INTACK, vpic->is_master, irq);
/* Edge-triggered: clear the IRR (forget the edge). */
if ( !(vpic->elcr & mask) )
vpic->irr &= ~mask;
@@ -434,6 +441,7 @@ void vpic_irq_positive_edge(struct domain *d, int irq)
ASSERT(irq <= 15);
ASSERT(vpic_is_locked(vpic));
+ TRACE_1D(TRC_HVM_EMUL_PIC_POSEDGE, irq);
if ( irq == 2 )
return;
@@ -450,6 +458,7 @@ void vpic_irq_negative_edge(struct domain *d, int irq)
ASSERT(irq <= 15);
ASSERT(vpic_is_locked(vpic));
+ TRACE_1D(TRC_HVM_EMUL_PIC_NEGEDGE, irq);
if ( irq == 2 )
return;
@@ -463,6 +472,8 @@ int vpic_ack_pending_irq(struct vcpu *v)
int irq, vector;
struct hvm_hw_vpic *vpic = &v->domain->arch.hvm_domain.vpic[0];
+ TRACE_2D(TRC_HVM_EMUL_PIC_PEND_IRQ_CALL, vlapic_accept_pic_intr(v),
+ vpic->int_output);
if ( !vlapic_accept_pic_intr(v) || !vpic->int_output )
return -1;
@@ -473,3 +484,12 @@ int vpic_ack_pending_irq(struct vcpu *v)
vector = vpic[irq >> 3].irq_base + (irq & 7);
return vector;
}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/hvm/vpmu.c b/xen/arch/x86/hvm/vpmu.c
index 21fbaba..1df74c2 100644
--- a/xen/arch/x86/hvm/vpmu.c
+++ b/xen/arch/x86/hvm/vpmu.c
@@ -64,12 +64,12 @@ static void __init parse_vpmu_param(char *s)
}
}
-int vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content)
+int vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content, uint64_t supported)
{
struct vpmu_struct *vpmu = vcpu_vpmu(current);
if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->do_wrmsr )
- return vpmu->arch_vpmu_ops->do_wrmsr(msr, msr_content);
+ return vpmu->arch_vpmu_ops->do_wrmsr(msr, msr_content, supported);
return 0;
}
@@ -82,7 +82,7 @@ int vpmu_do_rdmsr(unsigned int msr, uint64_t *msr_content)
return 0;
}
-int vpmu_do_interrupt(struct cpu_user_regs *regs)
+void vpmu_do_interrupt(struct cpu_user_regs *regs)
{
struct vcpu *v = current;
struct vpmu_struct *vpmu = vcpu_vpmu(v);
@@ -91,25 +91,23 @@ int vpmu_do_interrupt(struct cpu_user_regs *regs)
{
struct vlapic *vlapic = vcpu_vlapic(v);
u32 vlapic_lvtpc;
- unsigned char int_vec;
- if ( !vpmu->arch_vpmu_ops->do_interrupt(regs) )
- return 0;
-
- if ( !is_vlapic_lvtpc_enabled(vlapic) )
- return 1;
+ if ( !vpmu->arch_vpmu_ops->do_interrupt(regs) ||
+ !is_vlapic_lvtpc_enabled(vlapic) )
+ return;
vlapic_lvtpc = vlapic_get_reg(vlapic, APIC_LVTPC);
- int_vec = vlapic_lvtpc & APIC_VECTOR_MASK;
- if ( GET_APIC_DELIVERY_MODE(vlapic_lvtpc) == APIC_MODE_FIXED )
- vlapic_set_irq(vcpu_vlapic(v), int_vec, 0);
- else
+ switch ( GET_APIC_DELIVERY_MODE(vlapic_lvtpc) )
+ {
+ case APIC_MODE_FIXED:
+ vlapic_set_irq(vlapic, vlapic_lvtpc & APIC_VECTOR_MASK, 0);
+ break;
+ case APIC_MODE_NMI:
v->nmi_pending = 1;
- return 1;
+ break;
+ }
}
-
- return 0;
}
void vpmu_do_cpuid(unsigned int input,
@@ -211,10 +209,9 @@ void vpmu_load(struct vcpu *v)
if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->arch_vpmu_load )
{
apic_write_around(APIC_LVTPC, vpmu->hw_lapic_lvtpc);
+ /* Arch code needs to set VPMU_CONTEXT_LOADED */
vpmu->arch_vpmu_ops->arch_vpmu_load(v);
}
-
- vpmu_set(vpmu, VPMU_CONTEXT_LOADED);
}
void vpmu_initialise(struct vcpu *v)
@@ -222,6 +219,9 @@ void vpmu_initialise(struct vcpu *v)
struct vpmu_struct *vpmu = vcpu_vpmu(v);
uint8_t vendor = current_cpu_data.x86_vendor;
+ if ( is_pvh_vcpu(v) )
+ return;
+
if ( vpmu_is_set(vpmu, VPMU_CONTEXT_ALLOCATED) )
vpmu_destroy(v);
vpmu_clear(vpmu);
diff --git a/xen/arch/x86/hvm/vpt.c b/xen/arch/x86/hvm/vpt.c
index f7af688..7c6549c 100644
--- a/xen/arch/x86/hvm/vpt.c
+++ b/xen/arch/x86/hvm/vpt.c
@@ -36,7 +36,7 @@ void hvm_init_guest_time(struct domain *d)
pl->last_guest_time = 0;
}
-u64 hvm_get_guest_time(struct vcpu *v)
+u64 hvm_get_guest_time_fixed(struct vcpu *v, u64 at_tsc)
{
struct pl_time *pl = &v->domain->arch.hvm_domain.pl_time;
u64 now;
@@ -45,11 +45,15 @@ u64 hvm_get_guest_time(struct vcpu *v)
ASSERT(is_hvm_vcpu(v));
spin_lock(&pl->pl_time_lock);
- now = get_s_time() + pl->stime_offset;
- if ( (int64_t)(now - pl->last_guest_time) > 0 )
- pl->last_guest_time = now;
- else
- now = ++pl->last_guest_time;
+ now = get_s_time_fixed(at_tsc) + pl->stime_offset;
+
+ if ( !at_tsc )
+ {
+ if ( (int64_t)(now - pl->last_guest_time) > 0 )
+ pl->last_guest_time = now;
+ else
+ now = ++pl->last_guest_time;
+ }
spin_unlock(&pl->pl_time_lock);
return now + v->arch.hvm_vcpu.stime_offset;
@@ -508,10 +512,10 @@ void pt_adjust_global_vcpu_target(struct vcpu *v)
pt_adjust_vcpu(&pl_time->vrtc.pt, v);
spin_unlock(&pl_time->vrtc.lock);
- spin_lock(&pl_time->vhpet.lock);
+ write_lock(&pl_time->vhpet.lock);
for ( i = 0; i < HPET_TIMER_NUM; i++ )
pt_adjust_vcpu(&pl_time->vhpet.pt[i], v);
- spin_unlock(&pl_time->vhpet.lock);
+ write_unlock(&pl_time->vhpet.lock);
}
diff --git a/xen/arch/x86/i8259.c b/xen/arch/x86/i8259.c
index 6fdcce8..c2c9005 100644
--- a/xen/arch/x86/i8259.c
+++ b/xen/arch/x86/i8259.c
@@ -23,67 +23,6 @@
#include <io_ports.h>
/*
- * Common place to define all x86 IRQ vectors
- *
- * This builds up the IRQ handler stubs using some ugly macros in irq.h
- *
- * These macros create the low-level assembly IRQ routines that save
- * register context and call do_IRQ(). do_IRQ() then does all the
- * operations that are needed to keep the AT (or SMP IOAPIC)
- * interrupt-controller happy.
- */
-
-__asm__(".section .text");
-
-BUILD_COMMON_IRQ()
-
-#define IRQ_NAME(nr) VEC##nr##_interrupt
-
-#define BI(nr) \
-void IRQ_NAME(nr)(void); \
-__asm__( \
-".if " STR(0x##nr) " >= " STR(FIRST_DYNAMIC_VECTOR) "\n" \
-__ALIGN_STR "\n" \
-STR(IRQ_NAME(nr)) ":\n\t" \
-BUILD_IRQ(0x##nr) "\n" \
-".else\n" \
-".equ " STR(IRQ_NAME(nr)) ", 0\n" \
-".endif\n")
-
-#define BUILD_16_IRQS(x) \
- BI(x##0); BI(x##1); BI(x##2); BI(x##3); \
- BI(x##4); BI(x##5); BI(x##6); BI(x##7); \
- BI(x##8); BI(x##9); BI(x##a); BI(x##b); \
- BI(x##c); BI(x##d); BI(x##e); BI(x##f)
-
-BUILD_16_IRQS(0); BUILD_16_IRQS(1); BUILD_16_IRQS(2); BUILD_16_IRQS(3);
-BUILD_16_IRQS(4); BUILD_16_IRQS(5); BUILD_16_IRQS(6); BUILD_16_IRQS(7);
-BUILD_16_IRQS(8); BUILD_16_IRQS(9); BUILD_16_IRQS(a); BUILD_16_IRQS(b);
-BUILD_16_IRQS(c); BUILD_16_IRQS(d); BUILD_16_IRQS(e); BUILD_16_IRQS(f);
-
-#undef BUILD_16_IRQS
-#undef BI
-
-
-#define IRQ(x,y) IRQ_NAME(x##y)
-
-#define IRQLIST_16(x) \
- IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \
- IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \
- IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
- IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
-
-static void (*__initdata interrupt[NR_VECTORS])(void) = {
- IRQLIST_16(0), IRQLIST_16(1), IRQLIST_16(2), IRQLIST_16(3),
- IRQLIST_16(4), IRQLIST_16(5), IRQLIST_16(6), IRQLIST_16(7),
- IRQLIST_16(8), IRQLIST_16(9), IRQLIST_16(a), IRQLIST_16(b),
- IRQLIST_16(c), IRQLIST_16(d), IRQLIST_16(e), IRQLIST_16(f)
-};
-
-#undef IRQ
-#undef IRQLIST_16
-
-/*
* This is the 'legacy' 8259A Programmable Interrupt Controller,
* present in the majority of PC/AT boxes.
* plus some generic x86 specific things if generic specifics makes
@@ -397,7 +336,7 @@ static struct irqaction __read_mostly cascade = { no_action, "cascade", NULL};
void __init init_IRQ(void)
{
- int vector, irq, cpu = smp_processor_id();
+ int irq, cpu = smp_processor_id();
init_bsp_APIC();
@@ -405,14 +344,6 @@ void __init init_IRQ(void)
BUG_ON(init_irq_data() < 0);
- for ( vector = FIRST_DYNAMIC_VECTOR; vector < NR_VECTORS; vector++ )
- {
- if (vector == HYPERCALL_VECTOR || vector == LEGACY_SYSCALL_VECTOR)
- continue;
- BUG_ON(!interrupt[vector]);
- set_intr_gate(vector, interrupt[vector]);
- }
-
for (irq = 0; platform_legacy_irq(irq); irq++) {
struct irq_desc *desc = irq_to_desc(irq);
@@ -435,6 +366,6 @@ void __init init_IRQ(void)
outb_p(LATCH & 0xff, PIT_CH0); /* LSB */
outb(LATCH >> 8, PIT_CH0); /* MSB */
- setup_irq(2, &cascade);
+ setup_irq(2, 0, &cascade);
}
diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c
index bddc588..6f8f62c 100644
--- a/xen/arch/x86/io_apic.c
+++ b/xen/arch/x86/io_apic.c
@@ -28,6 +28,7 @@
#include <xen/sched.h>
#include <xen/acpi.h>
#include <xen/keyhandler.h>
+#include <xen/softirq.h>
#include <asm/mc146818rtc.h>
#include <asm/smp.h>
#include <asm/desc.h>
@@ -1091,7 +1092,7 @@ static inline void UNEXPECTED_IO_APIC(void)
{
}
-static void /*__init*/ __print_IO_APIC(void)
+static void /*__init*/ __print_IO_APIC(bool_t boot)
{
int apic, i;
union IO_APIC_reg_00 reg_00;
@@ -1112,6 +1113,9 @@ static void /*__init*/ __print_IO_APIC(void)
printk(KERN_INFO "testing the IO APIC.......................\n");
for (apic = 0; apic < nr_ioapics; apic++) {
+ if ( !boot )
+ process_pending_softirqs();
+
if (!nr_ioapic_entries[apic])
continue;
@@ -1215,6 +1219,10 @@ static void /*__init*/ __print_IO_APIC(void)
printk(KERN_DEBUG "IRQ to pin mappings:\n");
for (i = 0; i < nr_irqs_gsi; i++) {
struct irq_pin_list *entry = irq_2_pin + i;
+
+ if ( !boot && !(i & 0x1f) )
+ process_pending_softirqs();
+
if (entry->pin < 0)
continue;
printk(KERN_DEBUG "IRQ%d ", irq_to_desc(i)->arch.vector);
@@ -1235,12 +1243,12 @@ static void /*__init*/ __print_IO_APIC(void)
static void __init print_IO_APIC(void)
{
if (apic_verbosity != APIC_QUIET)
- __print_IO_APIC();
+ __print_IO_APIC(1);
}
static void _print_IO_APIC_keyhandler(unsigned char key)
{
- __print_IO_APIC();
+ __print_IO_APIC(0);
}
static struct keyhandler print_IO_APIC_keyhandler = {
.diagnostic = 1,
@@ -2363,7 +2371,7 @@ int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
* that dom0 pirq == irq.
*/
pirq = (irq >= 256) ? irq : rte.vector;
- if ( (pirq < 0) || (pirq >= dom0->nr_pirqs) )
+ if ( (pirq < 0) || (pirq >= hardware_domain->nr_pirqs) )
return -EINVAL;
if ( desc->action )
@@ -2399,10 +2407,10 @@ int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
printk(XENLOG_INFO "allocated vector %02x for irq %d\n", ret, irq);
}
- spin_lock(&dom0->event_lock);
- ret = map_domain_pirq(dom0, pirq, irq,
+ spin_lock(&hardware_domain->event_lock);
+ ret = map_domain_pirq(hardware_domain, pirq, irq,
MAP_PIRQ_TYPE_GSI, NULL);
- spin_unlock(&dom0->event_lock);
+ spin_unlock(&hardware_domain->event_lock);
if ( ret < 0 )
return ret;
@@ -2454,6 +2462,9 @@ void dump_ioapic_irq_info(void)
for ( irq = 0; irq < nr_irqs_gsi; irq++ )
{
+ if ( !(irq & 0x1f) )
+ process_pending_softirqs();
+
entry = &irq_2_pin[irq];
if ( entry->pin == -1 )
continue;
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index 88444be..f214072 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -19,6 +19,7 @@
#include <xen/iommu.h>
#include <xen/symbols.h>
#include <xen/trace.h>
+#include <xen/softirq.h>
#include <xsm/xsm.h>
#include <asm/msi.h>
#include <asm/current.h>
@@ -185,9 +186,9 @@ int create_irq(int node)
desc->arch.used = IRQ_UNUSED;
irq = ret;
}
- else if ( dom0 )
+ else if ( hardware_domain )
{
- ret = irq_permit_access(dom0, irq);
+ ret = irq_permit_access(hardware_domain, irq);
if ( ret )
printk(XENLOG_G_ERR
"Could not grant Dom0 access to IRQ%d (error %d)\n",
@@ -205,9 +206,9 @@ void destroy_irq(unsigned int irq)
BUG_ON(!MSI_IRQ(irq));
- if ( dom0 )
+ if ( hardware_domain )
{
- int err = irq_deny_access(dom0, irq);
+ int err = irq_deny_access(hardware_domain, irq);
if ( err )
printk(XENLOG_G_ERR
@@ -949,7 +950,7 @@ static int __init irq_ratelimit_init(void)
}
__initcall(irq_ratelimit_init);
-int __init request_irq(unsigned int irq,
+int __init request_irq(unsigned int irq, unsigned int irqflags,
void (*handler)(int, void *, struct cpu_user_regs *),
const char * devname, void *dev_id)
{
@@ -976,14 +977,14 @@ int __init request_irq(unsigned int irq,
action->dev_id = dev_id;
action->free_on_release = 1;
- retval = setup_irq(irq, action);
+ retval = setup_irq(irq, irqflags, action);
if (retval)
xfree(action);
return retval;
}
-void __init release_irq(unsigned int irq)
+void __init release_irq(unsigned int irq, const void *dev_id)
{
struct irq_desc *desc;
unsigned long flags;
@@ -1005,11 +1006,14 @@ void __init release_irq(unsigned int irq)
xfree(action);
}
-int __init setup_irq(unsigned int irq, struct irqaction *new)
+int __init setup_irq(unsigned int irq, unsigned int irqflags,
+ struct irqaction *new)
{
struct irq_desc *desc;
unsigned long flags;
+ ASSERT(irqflags == 0);
+
desc = irq_to_desc(irq);
spin_lock_irqsave(&desc->lock,flags);
@@ -1068,14 +1072,14 @@ bool_t cpu_has_pending_apic_eoi(void)
static inline void set_pirq_eoi(struct domain *d, unsigned int irq)
{
- if ( is_pv_domain(d) && d->arch.pv_domain.pirq_eoi_map )
- set_bit(irq, d->arch.pv_domain.pirq_eoi_map);
+ if ( d->arch.pirq_eoi_map )
+ set_bit(irq, d->arch.pirq_eoi_map);
}
static inline void clear_pirq_eoi(struct domain *d, unsigned int irq)
{
- if ( is_pv_domain(d) && d->arch.pv_domain.pirq_eoi_map )
- clear_bit(irq, d->arch.pv_domain.pirq_eoi_map);
+ if ( d->arch.pirq_eoi_map )
+ clear_bit(irq, d->arch.pirq_eoi_map);
}
static void set_eoi_ready(void *data);
@@ -2231,6 +2235,8 @@ static void dump_irqs(unsigned char key)
for ( irq = 0; irq < nr_irqs; irq++ )
{
+ if ( !(irq & 0x1f) )
+ process_pending_softirqs();
desc = irq_to_desc(irq);
@@ -2284,6 +2290,7 @@ static void dump_irqs(unsigned char key)
xfree(ssid);
}
+ process_pending_softirqs();
printk("Direct vector information:\n");
for ( i = FIRST_DYNAMIC_VECTOR; i < NR_VECTORS; ++i )
if ( direct_apic_vector[i] )
diff --git a/xen/arch/x86/microcode_amd.c b/xen/arch/x86/microcode_amd.c
index 32d7fa1..b68cf93 100644
--- a/xen/arch/x86/microcode_amd.c
+++ b/xen/arch/x86/microcode_amd.c
@@ -8,7 +8,7 @@
* Tigran Aivazian <tigran at aivazian.fsnet.co.uk>
*
* This driver allows to upgrade microcode on AMD
- * family 0x10 and 0x11 processors.
+ * family 0x10 and later.
*
* Licensed unter the terms of the GNU General Public
* License version 2. See file COPYING for details.
@@ -27,15 +27,21 @@
#include <asm/microcode.h>
#include <asm/hvm/svm/svm.h>
-struct equiv_cpu_entry {
+#define pr_debug(x...) ((void)0)
+
+#define CONT_HDR_SIZE 12
+#define SECTION_HDR_SIZE 8
+#define PATCH_HDR_SIZE 32
+
+struct __packed equiv_cpu_entry {
uint32_t installed_cpu;
uint32_t fixed_errata_mask;
uint32_t fixed_errata_compare;
uint16_t equiv_cpu;
uint16_t reserved;
-} __attribute__((packed));
+};
-struct microcode_header_amd {
+struct __packed microcode_header_amd {
uint32_t data_code;
uint32_t patch_id;
uint8_t mc_patch_data_id[2];
@@ -50,7 +56,7 @@ struct microcode_header_amd {
uint8_t bios_api_rev;
uint8_t reserved1[3];
uint32_t match_reg[8];
-} __attribute__((packed));
+};
#define UCODE_MAGIC 0x00414d44
#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
@@ -88,8 +94,57 @@ static int collect_cpu_info(int cpu, struct cpu_signature *csig)
rdmsrl(MSR_AMD_PATCHLEVEL, csig->rev);
- printk(KERN_DEBUG "microcode: CPU%d collect_cpu_info: patch_id=%#x\n",
- cpu, csig->rev);
+ pr_debug("microcode: CPU%d collect_cpu_info: patch_id=%#x\n",
+ cpu, csig->rev);
+
+ return 0;
+}
+
+static bool_t verify_patch_size(uint32_t patch_size)
+{
+ uint32_t max_size;
+
+#define F1XH_MPB_MAX_SIZE 2048
+#define F14H_MPB_MAX_SIZE 1824
+#define F15H_MPB_MAX_SIZE 4096
+#define F16H_MPB_MAX_SIZE 3458
+
+ switch (boot_cpu_data.x86)
+ {
+ case 0x14:
+ max_size = F14H_MPB_MAX_SIZE;
+ break;
+ case 0x15:
+ max_size = F15H_MPB_MAX_SIZE;
+ break;
+ case 0x16:
+ max_size = F16H_MPB_MAX_SIZE;
+ break;
+ default:
+ max_size = F1XH_MPB_MAX_SIZE;
+ break;
+ }
+
+ return (patch_size <= max_size);
+}
+
+static bool_t find_equiv_cpu_id(const struct equiv_cpu_entry *equiv_cpu_table,
+ unsigned int current_cpu_id,
+ unsigned int *equiv_cpu_id)
+{
+ unsigned int i;
+
+ if ( !equiv_cpu_table )
+ return 0;
+
+ for ( i = 0; equiv_cpu_table[i].installed_cpu != 0; i++ )
+ {
+ if ( current_cpu_id == equiv_cpu_table[i].installed_cpu )
+ {
+ *equiv_cpu_id = equiv_cpu_table[i].equiv_cpu & 0xffff;
+ return 1;
+ }
+ }
return 0;
}
@@ -100,35 +155,33 @@ static bool_t microcode_fits(const struct microcode_amd *mc_amd, int cpu)
const struct microcode_header_amd *mc_header = mc_amd->mpb;
const struct equiv_cpu_entry *equiv_cpu_table = mc_amd->equiv_cpu_table;
unsigned int current_cpu_id;
- unsigned int equiv_cpu_id = 0x0;
- unsigned int i;
+ unsigned int equiv_cpu_id;
/* We should bind the task to the CPU */
BUG_ON(cpu != raw_smp_processor_id());
current_cpu_id = cpuid_eax(0x00000001);
- for ( i = 0; equiv_cpu_table[i].installed_cpu != 0; i++ )
- {
- if ( current_cpu_id == equiv_cpu_table[i].installed_cpu )
- {
- equiv_cpu_id = equiv_cpu_table[i].equiv_cpu & 0xffff;
- break;
- }
- }
-
- if ( !equiv_cpu_id )
+ if ( !find_equiv_cpu_id(equiv_cpu_table, current_cpu_id, &equiv_cpu_id) )
return 0;
if ( (mc_header->processor_rev_id) != equiv_cpu_id )
return 0;
+ if ( !verify_patch_size(mc_amd->mpb_size) )
+ {
+ pr_debug("microcode: patch size mismatch\n");
+ return 0;
+ }
+
if ( mc_header->patch_id <= uci->cpu_sig.rev )
+ {
+ pr_debug("microcode: patch is already at required level or greater.\n");
return 0;
+ }
- printk(KERN_DEBUG "microcode: CPU%d found a matching microcode "
- "update with version %#x (current=%#x)\n",
- cpu, mc_header->patch_id, uci->cpu_sig.rev);
+ pr_debug("microcode: CPU%d found a matching microcode update with version %#x (current=%#x)\n",
+ cpu, mc_header->patch_id, uci->cpu_sig.rev);
return 1;
}
@@ -140,6 +193,7 @@ static int apply_microcode(int cpu)
uint32_t rev;
struct microcode_amd *mc_amd = uci->mc.mc_amd;
struct microcode_header_amd *hdr;
+ int hw_err;
/* We should bind the task to the CPU */
BUG_ON(raw_smp_processor_id() != cpu);
@@ -153,7 +207,7 @@ static int apply_microcode(int cpu)
spin_lock_irqsave(µcode_update_lock, flags);
- wrmsrl(MSR_AMD_PATCHLOADER, (unsigned long)hdr);
+ hw_err = wrmsr_safe(MSR_AMD_PATCHLOADER, (unsigned long)hdr);
/* get patch id after patching */
rdmsrl(MSR_AMD_PATCHLEVEL, rev);
@@ -161,7 +215,7 @@ static int apply_microcode(int cpu)
spin_unlock_irqrestore(µcode_update_lock, flags);
/* check current patch id and patch's id for match */
- if ( rev != hdr->patch_id )
+ if ( hw_err || (rev != hdr->patch_id) )
{
printk(KERN_ERR "microcode: CPU%d update from revision "
"%#x to %#x failed\n", cpu, rev, hdr->patch_id);
@@ -182,27 +236,22 @@ static int get_ucode_from_buffer_amd(
size_t bufsize,
size_t *offset)
{
- const uint8_t *bufp = buf;
- size_t off;
- const struct mpbhdr *mpbuf;
-
- off = *offset;
+ const struct mpbhdr *mpbuf = buf + *offset;
/* No more data */
- if ( off >= bufsize )
+ if ( *offset >= bufsize )
{
printk(KERN_ERR "microcode: Microcode buffer overrun\n");
return -EINVAL;
}
- mpbuf = (const struct mpbhdr *)&bufp[off];
if ( mpbuf->type != UCODE_UCODE_TYPE )
{
printk(KERN_ERR "microcode: Wrong microcode payload type field\n");
return -EINVAL;
}
- if ( (off + mpbuf->len) > bufsize )
+ if ( (*offset + mpbuf->len) > bufsize )
{
printk(KERN_ERR "microcode: Bad data in microcode data file\n");
return -EINVAL;
@@ -222,26 +271,24 @@ static int get_ucode_from_buffer_amd(
}
memcpy(mc_amd->mpb, mpbuf->data, mpbuf->len);
- *offset = off + mpbuf->len + 8;
+ pr_debug("microcode: CPU%d size %zu, block size %u offset %zu equivID %#x rev %#x\n",
+ raw_smp_processor_id(), bufsize, mpbuf->len, *offset,
+ ((struct microcode_header_amd *)mc_amd->mpb)->processor_rev_id,
+ ((struct microcode_header_amd *)mc_amd->mpb)->patch_id);
- printk(KERN_DEBUG "microcode: CPU%d size %zu, block size %u offset %zu equivID %#x rev %#x\n",
- raw_smp_processor_id(), bufsize, mpbuf->len, off,
- ((struct microcode_header_amd *)mc_amd->mpb)->processor_rev_id,
- ((struct microcode_header_amd *)mc_amd->mpb)->patch_id);
+ *offset += mpbuf->len + SECTION_HDR_SIZE;
return 0;
}
static int install_equiv_cpu_table(
struct microcode_amd *mc_amd,
- const uint32_t *buf,
+ const void *data,
size_t *offset)
{
- const struct mpbhdr *mpbuf = (const struct mpbhdr *)&buf[1];
+ const struct mpbhdr *mpbuf = data + *offset + 4;
- /* No more data */
- if ( mpbuf->len + 12 >= *offset )
- return -EINVAL;
+ *offset += mpbuf->len + CONT_HDR_SIZE; /* add header length */
if ( mpbuf->type != UCODE_EQUIV_CPU_TABLE_TYPE )
{
@@ -265,7 +312,32 @@ static int install_equiv_cpu_table(
memcpy(mc_amd->equiv_cpu_table, mpbuf->data, mpbuf->len);
mc_amd->equiv_cpu_table_size = mpbuf->len;
- *offset = mpbuf->len + 12; /* add header length */
+ return 0;
+}
+
+static int container_fast_forward(const void *data, size_t size_left, size_t *offset)
+{
+ for ( ; ; )
+ {
+ size_t size;
+ const uint32_t *header;
+
+ if ( size_left < SECTION_HDR_SIZE )
+ return -EINVAL;
+
+ header = data + *offset;
+
+ if ( header[0] == UCODE_MAGIC &&
+ header[1] == UCODE_EQUIV_CPU_TABLE_TYPE )
+ break;
+
+ size = header[1] + SECTION_HDR_SIZE;
+ if ( size < PATCH_HDR_SIZE || size_left < size )
+ return -EINVAL;
+
+ size_left -= size;
+ *offset += size;
+ }
return 0;
}
@@ -273,14 +345,18 @@ static int install_equiv_cpu_table(
static int cpu_request_microcode(int cpu, const void *buf, size_t bufsize)
{
struct microcode_amd *mc_amd, *mc_old;
- size_t offset = bufsize;
+ size_t offset = 0;
size_t last_offset, applied_offset = 0;
int error = 0, save_error = 1;
struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu);
+ unsigned int current_cpu_id;
+ unsigned int equiv_cpu_id;
/* We should bind the task to the CPU */
BUG_ON(cpu != raw_smp_processor_id());
+ current_cpu_id = cpuid_eax(0x00000001);
+
if ( *(const uint32_t *)buf != UCODE_MAGIC )
{
printk(KERN_ERR "microcode: Wrong microcode patch file magic\n");
@@ -296,12 +372,48 @@ static int cpu_request_microcode(int cpu, const void *buf, size_t bufsize)
goto out;
}
- error = install_equiv_cpu_table(mc_amd, buf, &offset);
+ /*
+ * Multiple container file support:
+ * 1. check if this container file has equiv_cpu_id match
+ * 2. If not, fast-fwd to next container file
+ */
+ while ( offset < bufsize )
+ {
+ error = install_equiv_cpu_table(mc_amd, buf, &offset);
+ if ( error )
+ {
+ printk(KERN_ERR "microcode: installing equivalent cpu table failed\n");
+ break;
+ }
+
+ if ( find_equiv_cpu_id(mc_amd->equiv_cpu_table, current_cpu_id,
+ &equiv_cpu_id) )
+ break;
+
+ /*
+ * Could happen as we advance 'offset' early
+ * in install_equiv_cpu_table
+ */
+ if ( offset > bufsize )
+ {
+ printk(KERN_ERR "microcode: Microcode buffer overrun\n");
+ error = -EINVAL;
+ break;
+ }
+
+ error = container_fast_forward(buf, bufsize - offset, &offset);
+ if ( error )
+ {
+ printk(KERN_ERR "microcode: CPU%d incorrect or corrupt container file\n"
+ "microcode: Failed to update patch level. "
+ "Current lvl:%#x\n", cpu, uci->cpu_sig.rev);
+ break;
+ }
+ }
+
if ( error )
{
xfree(mc_amd);
- printk(KERN_ERR "microcode: installing equivalent cpu table failed\n");
- error = -EINVAL;
goto out;
}
@@ -331,6 +443,30 @@ static int cpu_request_microcode(int cpu, const void *buf, size_t bufsize)
if ( offset >= bufsize )
break;
+
+ /*
+ * 1. Given a situation where multiple containers exist and correct
+ * patch lives on a container that is not the last container.
+ * 2. We match equivalent ids using find_equiv_cpu_id() from the
+ * earlier while() (On this case, matches on earlier container
+ * file and we break)
+ * 3. Proceed to while ( (error = get_ucode_from_buffer_amd(mc_amd,
+ * buf, bufsize,&offset)) == 0 )
+ * 4. Find correct patch using microcode_fits() and apply the patch
+ * (Assume: apply_microcode() is successful)
+ * 5. The while() loop from (3) continues to parse the binary as
+ * there is a subsequent container file, but...
+ * 6. ...a correct patch can only be on one container and not on any
+ * subsequent ones. (Refer docs for more info) Therefore, we
+ * don't have to parse a subsequent container. So, we can abort
+ * the process here.
+ * 7. This ensures that we retain a success value (= 0) to 'error'
+ * before if ( mpbuf->type != UCODE_UCODE_TYPE ) evaluates to
+ * false and returns -EINVAL.
+ */
+ if ( offset + SECTION_HDR_SIZE <= bufsize &&
+ *(const uint32_t *)(buf + offset) == UCODE_MAGIC )
+ break;
}
/* On success keep the microcode patch for
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index fdc5ed3..522c43d 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -104,6 +104,7 @@
#include <xen/xmalloc.h>
#include <xen/efi.h>
#include <xen/grant_table.h>
+#include <xen/hypercall.h>
#include <asm/paging.h>
#include <asm/shadow.h>
#include <asm/page.h>
@@ -121,6 +122,7 @@
#include <xen/trace.h>
#include <asm/setup.h>
#include <asm/fixmap.h>
+#include <asm/io_apic.h>
#include <asm/pci.h>
/* Mapping of the fixmap space needed early. */
@@ -146,9 +148,6 @@ struct domain *dom_xen, *dom_io, *dom_cow;
unsigned long max_page;
unsigned long total_pages;
-unsigned long __read_mostly pdx_group_valid[BITS_TO_LONGS(
- (FRAMETABLE_NR + PDX_GROUP_COUNT - 1) / PDX_GROUP_COUNT)] = { [0] = 1 };
-
bool_t __read_mostly machine_to_phys_mapping_valid = 0;
struct rangeset *__read_mostly mmio_ro_ranges;
@@ -161,7 +160,8 @@ boolean_param("allowsuperpage", opt_allow_superpage);
static void put_superpage(unsigned long mfn);
static uint32_t base_disallow_mask;
-#define L1_DISALLOW_MASK (base_disallow_mask | _PAGE_GNTTAB)
+/* Global bit is allowed to be set on L1 PTEs. Intended for user mappings. */
+#define L1_DISALLOW_MASK ((base_disallow_mask | _PAGE_GNTTAB) & ~_PAGE_GLOBAL)
#define L2_DISALLOW_MASK (base_disallow_mask & ~_PAGE_PSE)
#define l3_disallow_mask(d) (!is_pv_32on64_domain(d) ? \
@@ -170,12 +170,6 @@ static uint32_t base_disallow_mask;
#define L4_DISALLOW_MASK (base_disallow_mask)
-#ifdef USER_MAPPINGS_ARE_GLOBAL
-/* Global bit is allowed to be set on L1 PTEs. Intended for user mappings. */
-#undef L1_DISALLOW_MASK
-#define L1_DISALLOW_MASK ((base_disallow_mask | _PAGE_GNTTAB) & ~_PAGE_GLOBAL)
-#endif
-
#define l1_disallow_mask(d) \
((d != dom_io) && \
(rangeset_is_empty((d)->iomem_caps) && \
@@ -993,7 +987,6 @@ get_page_from_l4e(
return rc;
}
-#ifdef USER_MAPPINGS_ARE_GLOBAL
#define adjust_guest_l1e(pl1e, d) \
do { \
if ( likely(l1e_get_flags((pl1e)) & _PAGE_PRESENT) && \
@@ -1010,14 +1003,6 @@ get_page_from_l4e(
l1e_add_flags((pl1e), (_PAGE_GLOBAL|_PAGE_USER)); \
} \
} while ( 0 )
-#else
-#define adjust_guest_l1e(pl1e, d) \
- do { \
- if ( likely(l1e_get_flags((pl1e)) & _PAGE_PRESENT) && \
- likely(!is_pv_32on64_domain(d)) ) \
- l1e_add_flags((pl1e), _PAGE_USER); \
- } while ( 0 )
-#endif
#define adjust_guest_l2e(pl2e, d) \
do { \
@@ -1284,7 +1269,7 @@ static int alloc_l2_table(struct page_info *page, unsigned long type,
&& hypercall_preempt_check() )
{
page->nr_validated_ptes = i;
- rc = -EAGAIN;
+ rc = -ERESTART;
break;
}
@@ -1355,7 +1340,7 @@ static int alloc_l3_table(struct page_info *page)
(rc = get_page_from_l3e(pl3e[i], pfn, d, partial)) > 0 )
continue;
- if ( rc == -EAGAIN )
+ if ( rc == -ERESTART )
{
page->nr_validated_ptes = i;
page->partial_pte = partial ?: 1;
@@ -1364,7 +1349,7 @@ static int alloc_l3_table(struct page_info *page)
{
page->nr_validated_ptes = i;
page->partial_pte = 0;
- rc = -EAGAIN;
+ rc = -ERESTART;
}
if ( rc < 0 )
break;
@@ -1374,7 +1359,7 @@ static int alloc_l3_table(struct page_info *page)
if ( rc >= 0 && !create_pae_xen_mappings(d, pl3e) )
rc = -EINVAL;
- if ( rc < 0 && rc != -EAGAIN && rc != -EINTR )
+ if ( rc < 0 && rc != -ERESTART && rc != -EINTR )
{
MEM_LOG("Failure in alloc_l3_table: entry %d", i);
if ( i )
@@ -1427,7 +1412,7 @@ static int alloc_l4_table(struct page_info *page)
(rc = get_page_from_l4e(pl4e[i], pfn, d, partial)) > 0 )
continue;
- if ( rc == -EAGAIN )
+ if ( rc == -ERESTART )
{
page->nr_validated_ptes = i;
page->partial_pte = partial ?: 1;
@@ -1441,7 +1426,7 @@ static int alloc_l4_table(struct page_info *page)
page->nr_validated_ptes = i;
page->partial_pte = 0;
if ( rc == -EINTR )
- rc = -EAGAIN;
+ rc = -ERESTART;
else
{
if ( current->arch.old_guest_table )
@@ -1499,7 +1484,7 @@ static int free_l2_table(struct page_info *page, int preemptible)
preemptible && i && hypercall_preempt_check() )
{
page->nr_validated_ptes = i;
- err = -EAGAIN;
+ err = -ERESTART;
}
} while ( !err && i-- );
@@ -1536,7 +1521,7 @@ static int free_l3_table(struct page_info *page)
unmap_domain_page(pl3e);
- if ( rc == -EAGAIN )
+ if ( rc == -ERESTART )
{
page->nr_validated_ptes = i;
page->partial_pte = partial ?: -1;
@@ -1545,7 +1530,7 @@ static int free_l3_table(struct page_info *page)
{
page->nr_validated_ptes = i + 1;
page->partial_pte = 0;
- rc = -EAGAIN;
+ rc = -ERESTART;
}
return rc > 0 ? 0 : rc;
}
@@ -1566,7 +1551,7 @@ static int free_l4_table(struct page_info *page)
partial = 0;
} while ( i-- );
- if ( rc == -EAGAIN )
+ if ( rc == -ERESTART )
{
page->nr_validated_ptes = i;
page->partial_pte = partial ?: -1;
@@ -1575,7 +1560,7 @@ static int free_l4_table(struct page_info *page)
{
page->nr_validated_ptes = i + 1;
page->partial_pte = 0;
- rc = -EAGAIN;
+ rc = -ERESTART;
}
unmap_domain_page(pl4e);
@@ -2103,7 +2088,7 @@ static int alloc_page_type(struct page_info *page, unsigned long type,
{
ASSERT((page->u.inuse.type_info &
(PGT_count_mask | PGT_validated)) == 1);
- case -EAGAIN:
+ case -ERESTART:
get_page_light(page);
page->u.inuse.type_info |= PGT_partial;
}
@@ -2202,7 +2187,7 @@ static int __put_final_page_type(
}
else
{
- BUG_ON(rc != -EAGAIN);
+ BUG_ON(rc != -ERESTART);
wmb();
get_page_light(page);
page->u.inuse.type_info |= PGT_partial;
@@ -2420,7 +2405,7 @@ int get_page_type(struct page_info *page, unsigned long type)
int rc = __get_page_type(page, type, 0);
if ( likely(rc == 0) )
return 1;
- ASSERT(rc != -EINTR && rc != -EAGAIN);
+ ASSERT(rc != -EINTR && rc != -ERESTART);
return 0;
}
@@ -2632,8 +2617,8 @@ int put_old_guest_table(struct vcpu *v)
switch ( rc = put_page_and_type_preemptible(v->arch.old_guest_table) )
{
case -EINTR:
- case -EAGAIN:
- return -EAGAIN;
+ case -ERESTART:
+ return -ERESTART;
}
v->arch.old_guest_table = NULL;
@@ -2721,8 +2706,8 @@ int new_guest_cr3(unsigned long mfn)
case 0:
break;
case -EINTR:
- case -EAGAIN:
- return -EAGAIN;
+ case -ERESTART:
+ return -ERESTART;
default:
MEM_LOG("Error while installing new compat baseptr %lx", mfn);
return rc;
@@ -2757,8 +2742,8 @@ int new_guest_cr3(unsigned long mfn)
case 0:
break;
case -EINTR:
- case -EAGAIN:
- return -EAGAIN;
+ case -ERESTART:
+ return -ERESTART;
default:
MEM_LOG("Error while installing new baseptr %lx", mfn);
return rc;
@@ -2781,8 +2766,8 @@ int new_guest_cr3(unsigned long mfn)
switch ( rc = put_page_and_type_preemptible(page) )
{
case -EINTR:
- rc = -EAGAIN;
- case -EAGAIN:
+ rc = -ERESTART;
+ case -ERESTART:
curr->arch.old_guest_table = page;
break;
default:
@@ -2810,7 +2795,7 @@ static struct domain *get_pg_owner(domid_t domid)
goto out;
}
- if ( unlikely(paging_mode_translate(curr)) )
+ if ( !is_pvh_domain(curr) && unlikely(paging_mode_translate(curr)) )
{
MEM_LOG("Cannot mix foreign mappings with translated domains");
goto out;
@@ -2895,7 +2880,7 @@ long do_mmuext_op(
if ( unlikely(rc) )
{
- if ( likely(rc == -EAGAIN) )
+ if ( likely(rc == -ERESTART) )
rc = hypercall_create_continuation(
__HYPERVISOR_mmuext_op, "hihi", uops, count, pdone,
foreigndom);
@@ -2936,7 +2921,7 @@ long do_mmuext_op(
{
if ( curr->arch.old_guest_table || (i && hypercall_preempt_check()) )
{
- rc = -EAGAIN;
+ rc = -ERESTART;
break;
}
@@ -2990,8 +2975,8 @@ long do_mmuext_op(
if ( unlikely(!okay) )
{
if ( rc == -EINTR )
- rc = -EAGAIN;
- else if ( rc != -EAGAIN )
+ rc = -ERESTART;
+ else if ( rc != -ERESTART )
MEM_LOG("Error while pinning mfn %lx", page_to_mfn(page));
if ( page != curr->arch.old_guest_table )
put_page(page);
@@ -3060,7 +3045,7 @@ long do_mmuext_op(
switch ( rc = put_page_and_type_preemptible(page) )
{
case -EINTR:
- case -EAGAIN:
+ case -ERESTART:
curr->arch.old_guest_table = page;
rc = 0;
break;
@@ -3077,23 +3062,23 @@ long do_mmuext_op(
}
case MMUEXT_NEW_BASEPTR:
- if ( paging_mode_translate(d) )
- okay = 0;
+ if ( unlikely(d != pg_owner) )
+ rc = -EPERM;
+ else if ( unlikely(paging_mode_translate(d)) )
+ rc = -EINVAL;
else
- {
rc = new_guest_cr3(op.arg1.mfn);
- okay = !rc;
- }
break;
case MMUEXT_NEW_USER_BASEPTR: {
unsigned long old_mfn;
- if ( paging_mode_translate(current->domain) )
- {
- okay = 0;
+ if ( unlikely(d != pg_owner) )
+ rc = -EPERM;
+ else if ( unlikely(paging_mode_translate(d)) )
+ rc = -EINVAL;
+ if ( unlikely(rc) )
break;
- }
old_mfn = pagetable_get_pfn(curr->arch.guest_table_user);
/*
@@ -3116,8 +3101,8 @@ long do_mmuext_op(
if ( unlikely(!okay) )
{
if ( rc == -EINTR )
- rc = -EAGAIN;
- else if ( rc != -EAGAIN )
+ rc = -ERESTART;
+ else if ( rc != -ERESTART )
MEM_LOG("Error while installing new mfn %lx",
op.arg1.mfn);
break;
@@ -3136,8 +3121,8 @@ long do_mmuext_op(
switch ( rc = put_page_and_type_preemptible(page) )
{
case -EINTR:
- rc = -EAGAIN;
- case -EAGAIN:
+ rc = -ERESTART;
+ case -ERESTART:
curr->arch.old_guest_table = page;
okay = 0;
break;
@@ -3151,12 +3136,17 @@ long do_mmuext_op(
}
case MMUEXT_TLB_FLUSH_LOCAL:
- flush_tlb_local();
+ if ( likely(d == pg_owner) )
+ flush_tlb_local();
+ else
+ rc = -EPERM;
break;
case MMUEXT_INVLPG_LOCAL:
- if ( !paging_mode_enabled(d)
- || paging_invlpg(curr, op.arg1.linear_addr) != 0 )
+ if ( unlikely(d != pg_owner) )
+ rc = -EPERM;
+ else if ( !paging_mode_enabled(d) ||
+ paging_invlpg(curr, op.arg1.linear_addr) != 0 )
flush_tlb_one_local(op.arg1.linear_addr);
break;
@@ -3165,13 +3155,16 @@ long do_mmuext_op(
{
cpumask_t pmask;
- if ( unlikely(vcpumask_to_pcpumask(d,
- guest_handle_to_param(op.arg2.vcpumask, const_void),
- &pmask)) )
- {
- okay = 0;
+ if ( unlikely(d != pg_owner) )
+ rc = -EPERM;
+ else if ( unlikely(vcpumask_to_pcpumask(d,
+ guest_handle_to_param(op.arg2.vcpumask,
+ const_void),
+ &pmask)) )
+ rc = -EINVAL;
+ if ( unlikely(rc) )
break;
- }
+
if ( op.cmd == MMUEXT_TLB_FLUSH_MULTI )
flush_tlb_mask(&pmask);
else
@@ -3180,18 +3173,26 @@ long do_mmuext_op(
}
case MMUEXT_TLB_FLUSH_ALL:
- flush_tlb_mask(d->domain_dirty_cpumask);
+ if ( likely(d == pg_owner) )
+ flush_tlb_mask(d->domain_dirty_cpumask);
+ else
+ rc = -EPERM;
break;
case MMUEXT_INVLPG_ALL:
- flush_tlb_one_mask(d->domain_dirty_cpumask, op.arg1.linear_addr);
+ if ( likely(d == pg_owner) )
+ flush_tlb_one_mask(d->domain_dirty_cpumask, op.arg1.linear_addr);
+ else
+ rc = -EPERM;
break;
case MMUEXT_FLUSH_CACHE:
- if ( unlikely(!cache_flush_permitted(d)) )
+ if ( unlikely(d != pg_owner) )
+ rc = -EPERM;
+ else if ( unlikely(!cache_flush_permitted(d)) )
{
MEM_LOG("Non-physdev domain tried to FLUSH_CACHE.");
- okay = 0;
+ rc = -EACCES;
}
else
{
@@ -3200,8 +3201,8 @@ long do_mmuext_op(
break;
case MMUEXT_FLUSH_CACHE_GLOBAL:
- if ( unlikely(foreigndom != DOMID_SELF) )
- okay = 0;
+ if ( unlikely(d != pg_owner) )
+ rc = -EPERM;
else if ( likely(cache_flush_permitted(d)) )
{
unsigned int cpu;
@@ -3226,7 +3227,9 @@ long do_mmuext_op(
unsigned long ptr = op.arg1.linear_addr;
unsigned long ents = op.arg2.nr_ents;
- if ( paging_mode_external(d) )
+ if ( unlikely(d != pg_owner) )
+ rc = -EPERM;
+ else if ( paging_mode_external(d) )
{
MEM_LOG("ignoring SET_LDT hypercall from external domain");
okay = 0;
@@ -3252,7 +3255,7 @@ long do_mmuext_op(
case MMUEXT_CLEAR_PAGE: {
struct page_info *page;
- page = get_page_from_gfn(d, op.arg1.mfn, NULL, P2M_ALLOC);
+ page = get_page_from_gfn(pg_owner, op.arg1.mfn, NULL, P2M_ALLOC);
if ( !page || !get_page_type(page, PGT_writable_page) )
{
if ( page )
@@ -3263,7 +3266,7 @@ long do_mmuext_op(
}
/* A page is dirtied when it's being cleared. */
- paging_mark_dirty(d, page_to_mfn(page));
+ paging_mark_dirty(pg_owner, page_to_mfn(page));
clear_domain_page(page_to_mfn(page));
@@ -3275,7 +3278,8 @@ long do_mmuext_op(
{
struct page_info *src_page, *dst_page;
- src_page = get_page_from_gfn(d, op.arg2.src_mfn, NULL, P2M_ALLOC);
+ src_page = get_page_from_gfn(pg_owner, op.arg2.src_mfn, NULL,
+ P2M_ALLOC);
if ( unlikely(!src_page) )
{
okay = 0;
@@ -3283,7 +3287,8 @@ long do_mmuext_op(
break;
}
- dst_page = get_page_from_gfn(d, op.arg1.mfn, NULL, P2M_ALLOC);
+ dst_page = get_page_from_gfn(pg_owner, op.arg1.mfn, NULL,
+ P2M_ALLOC);
okay = (dst_page && get_page_type(dst_page, PGT_writable_page));
if ( unlikely(!okay) )
{
@@ -3295,7 +3300,7 @@ long do_mmuext_op(
}
/* A page is dirtied when it's being copied to. */
- paging_mark_dirty(d, page_to_mfn(dst_page));
+ paging_mark_dirty(pg_owner, page_to_mfn(dst_page));
copy_domain_page(page_to_mfn(dst_page), page_to_mfn(src_page));
@@ -3306,73 +3311,61 @@ long do_mmuext_op(
case MMUEXT_MARK_SUPER:
{
- unsigned long mfn;
- struct spage_info *spage;
+ unsigned long mfn = op.arg1.mfn;
- mfn = op.arg1.mfn;
- if ( mfn & (L1_PAGETABLE_ENTRIES-1) )
+ if ( unlikely(d != pg_owner) )
+ rc = -EPERM;
+ else if ( mfn & (L1_PAGETABLE_ENTRIES-1) )
{
MEM_LOG("Unaligned superpage reference mfn %lx", mfn);
okay = 0;
- break;
}
-
- if ( !opt_allow_superpage )
+ else if ( !opt_allow_superpage )
{
MEM_LOG("Superpages disallowed");
- okay = 0;
rc = -ENOSYS;
- break;
}
-
- spage = mfn_to_spage(mfn);
- okay = (mark_superpage(spage, d) >= 0);
+ else
+ rc = mark_superpage(mfn_to_spage(mfn), d);
break;
}
case MMUEXT_UNMARK_SUPER:
{
- unsigned long mfn;
- struct spage_info *spage;
+ unsigned long mfn = op.arg1.mfn;
- mfn = op.arg1.mfn;
- if ( mfn & (L1_PAGETABLE_ENTRIES-1) )
+ if ( unlikely(d != pg_owner) )
+ rc = -EPERM;
+ else if ( mfn & (L1_PAGETABLE_ENTRIES-1) )
{
MEM_LOG("Unaligned superpage reference mfn %lx", mfn);
okay = 0;
- break;
}
-
- if ( !opt_allow_superpage )
+ else if ( !opt_allow_superpage )
{
MEM_LOG("Superpages disallowed");
- okay = 0;
rc = -ENOSYS;
- break;
}
-
- spage = mfn_to_spage(mfn);
- okay = (unmark_superpage(spage) >= 0);
+ else
+ rc = unmark_superpage(mfn_to_spage(mfn));
break;
}
default:
MEM_LOG("Invalid extended pt command %#x", op.cmd);
rc = -ENOSYS;
- okay = 0;
break;
}
- if ( unlikely(!okay) )
- {
- rc = rc ? rc : -EINVAL;
+ if ( unlikely(!okay) && !rc )
+ rc = -EINVAL;
+ if ( unlikely(rc) )
break;
- }
guest_handle_add_offset(uops, 1);
}
- if ( rc == -EAGAIN )
+ if ( rc == -ERESTART )
{
ASSERT(i < count);
rc = hypercall_create_continuation(
@@ -3429,7 +3422,7 @@ long do_mmu_update(
if ( unlikely(rc) )
{
- if ( likely(rc == -EAGAIN) )
+ if ( likely(rc == -ERESTART) )
rc = hypercall_create_continuation(
__HYPERVISOR_mmu_update, "hihi", ureqs, count, pdone,
foreigndom);
@@ -3483,7 +3476,7 @@ long do_mmu_update(
{
if ( curr->arch.old_guest_table || (i && hypercall_preempt_check()) )
{
- rc = -EAGAIN;
+ rc = -ERESTART;
break;
}
@@ -3508,6 +3501,10 @@ long do_mmu_update(
{
p2m_type_t p2mt;
+ rc = -EOPNOTSUPP;
+ if ( unlikely(paging_mode_refcounts(pt_owner)) )
+ break;
+
xsm_needed |= XSM_MMU_NORMAL_UPDATE;
if ( get_pte_flags(req.val) & _PAGE_PRESENT )
{
@@ -3613,7 +3610,7 @@ long do_mmu_update(
}
page_unlock(page);
if ( rc == -EINTR )
- rc = -EAGAIN;
+ rc = -ERESTART;
}
else if ( get_page_type(page, PGT_writable_page) )
{
@@ -3629,6 +3626,17 @@ long do_mmu_update(
break;
case MMU_MACHPHYS_UPDATE:
+ if ( unlikely(d != pt_owner) )
+ {
+ rc = -EPERM;
+ break;
+ }
+
+ if ( unlikely(paging_mode_translate(pg_owner)) )
+ {
+ rc = -EINVAL;
+ break;
+ }
mfn = req.ptr >> PAGE_SHIFT;
gpfn = req.val;
@@ -3649,13 +3657,6 @@ long do_mmu_update(
break;
}
- if ( unlikely(paging_mode_translate(pg_owner)) )
- {
- MEM_LOG("Mach-phys update on auto-translate guest");
- rc = -EINVAL;
- break;
- }
-
set_gpfn_from_mfn(mfn, gpfn);
paging_mark_dirty(pg_owner, mfn);
@@ -3675,7 +3676,7 @@ long do_mmu_update(
guest_handle_add_offset(ureqs, 1);
}
- if ( rc == -EAGAIN )
+ if ( rc == -ERESTART )
{
ASSERT(i < count);
rc = hypercall_create_continuation(
@@ -3705,7 +3706,7 @@ long do_mmu_update(
perfc_add(num_page_updates, i);
out:
- if ( pt_owner && (pt_owner != d) )
+ if ( pt_owner != d )
rcu_unlock_domain(pt_owner);
/* Add incremental work we have done to the @done output parameter. */
@@ -4494,10 +4495,9 @@ struct memory_map_context
struct xen_memory_map map;
};
-static int handle_iomem_range(unsigned long s, unsigned long e, void *p)
+static int _handle_iomem_range(unsigned long s, unsigned long e,
+ struct memory_map_context *ctxt)
{
- struct memory_map_context *ctxt = p;
-
if ( s > ctxt->s )
{
e820entry_t ent;
@@ -4520,6 +4520,31 @@ static int handle_iomem_range(unsigned long s, unsigned long e, void *p)
return 0;
}
+static int handle_iomem_range(unsigned long s, unsigned long e, void *p)
+{
+ int err = 0;
+
+ do {
+ unsigned long low = -1UL;
+ unsigned int i;
+
+ for ( i = 0; i < nr_ioapics; ++i )
+ {
+ unsigned long mfn = paddr_to_pfn(mp_ioapics[i].mpc_apicaddr);
+
+ if ( mfn >= s && mfn <= e && mfn < low )
+ low = mfn;
+ }
+ if ( !(low + 1) )
+ break;
+ if ( s < low )
+ err = _handle_iomem_range(s, low - 1, p);
+ s = low + 1;
+ } while ( !err );
+
+ return err || s > e ? err : _handle_iomem_range(s, e, p);
+}
+
int xenmem_add_to_physmap_one(
struct domain *d,
unsigned int space,
@@ -4555,7 +4580,7 @@ int xenmem_add_to_physmap_one(
else
{
if ( (idx >= nr_grant_frames(d->grant_table)) &&
- (idx < max_nr_grant_frames) )
+ (idx < max_grant_frames) )
gnttab_grow_table(d, idx + 1);
if ( idx < nr_grant_frames(d->grant_table) )
@@ -4583,6 +4608,8 @@ int xenmem_add_to_physmap_one(
page = mfn_to_page(mfn);
break;
}
+ case XENMAPSPACE_gmfn_foreign:
+ return p2m_add_foreign(d, idx, gpfn, foreign_domid);
default:
break;
}
@@ -4631,9 +4658,10 @@ int xenmem_add_to_physmap_one(
return rc;
}
-long arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
+long arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
{
int rc;
+ int op = cmd & MEMOP_CMD_MASK;
switch ( op )
{
@@ -4744,7 +4772,7 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
{
unsigned long s = PFN_DOWN(e820.map[i].addr);
- if ( s )
+ if ( s > ctxt.s )
{
rc = rangeset_report_ranges(current->domain->iomem_caps,
ctxt.s, s - 1,
@@ -4787,7 +4815,7 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
.max_mfn = MACH2PHYS_NR_ENTRIES - 1
};
- if ( !mem_hotplug && current->domain == dom0 )
+ if ( !mem_hotplug && is_hardware_domain(current->domain) )
mapping.max_mfn = max_page - 1;
if ( copy_to_guest(arg, &mapping, 1) )
return -EFAULT;
@@ -4828,7 +4856,7 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
rc = p2m_pod_set_mem_target(d, target.target_pages);
}
- if ( rc == -EAGAIN )
+ if ( rc == -ERESTART )
{
rc = hypercall_create_continuation(
__HYPERVISOR_memory_op, "lh", op, arg);
@@ -4853,7 +4881,7 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
}
default:
- return subarch_memory_op(op, arg);
+ return subarch_memory_op(cmd, arg);
}
return 0;
@@ -5109,6 +5137,7 @@ int ptwr_do_page_fault(struct vcpu *v, unsigned long addr,
ptwr_ctxt.ctxt.force_writeback = 0;
ptwr_ctxt.ctxt.addr_size = ptwr_ctxt.ctxt.sp_size =
is_pv_32on64_domain(d) ? 32 : BITS_PER_LONG;
+ ptwr_ctxt.ctxt.swint_emulate = x86_swint_emulate_none;
ptwr_ctxt.cr2 = addr;
ptwr_ctxt.pte = pte;
@@ -5185,6 +5214,7 @@ int mmio_ro_do_page_fault(struct vcpu *v, unsigned long addr,
.ctxt.regs = regs,
.ctxt.addr_size = addr_size,
.ctxt.sp_size = addr_size,
+ .ctxt.swint_emulate = x86_swint_emulate_none,
.cr2 = addr
};
int rc;
@@ -5222,7 +5252,7 @@ void *alloc_xen_pagetable(void)
{
void *ptr = alloc_xenheap_page();
- BUG_ON(!dom0 && !ptr);
+ BUG_ON(!hardware_domain && !ptr);
return ptr;
}
diff --git a/xen/arch/x86/mm/Makefile b/xen/arch/x86/mm/Makefile
index 73dcdf4..ed4b1f8 100644
--- a/xen/arch/x86/mm/Makefile
+++ b/xen/arch/x86/mm/Makefile
@@ -6,10 +6,8 @@ obj-y += p2m.o p2m-pt.o p2m-ept.o p2m-pod.o
obj-y += guest_walk_2.o
obj-y += guest_walk_3.o
obj-$(x86_64) += guest_walk_4.o
-obj-$(x86_64) += mem_event.o
obj-$(x86_64) += mem_paging.o
obj-$(x86_64) += mem_sharing.o
-obj-$(x86_64) += mem_access.o
guest_walk_%.o: guest_walk.c Makefile
$(CC) $(CFLAGS) -DGUEST_PAGING_LEVELS=$* -c $< -o $@
diff --git a/xen/arch/x86/mm/guest_walk.c b/xen/arch/x86/mm/guest_walk.c
index 70460b6..1b26175 100644
--- a/xen/arch/x86/mm/guest_walk.c
+++ b/xen/arch/x86/mm/guest_walk.c
@@ -144,7 +144,7 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
guest_l4e_t *l4p;
#endif
uint32_t gflags, mflags, iflags, rc = 0;
- int smep;
+ bool_t smep = 0, smap = 0;
bool_t pse1G = 0, pse2M = 0;
p2m_query_t qt = P2M_ALLOC | P2M_UNSHARE;
@@ -159,13 +159,46 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
mflags = mandatory_flags(v, pfec);
iflags = (_PAGE_NX_BIT | _PAGE_INVALID_BITS);
- /* SMEP: kernel-mode instruction fetches from user-mode mappings
- * should fault. Unlike NX or invalid bits, we're looking for _all_
- * entries in the walk to have _PAGE_USER set, so we need to do the
- * whole walk as if it were a user-mode one and then invert the answer. */
- smep = (is_hvm_vcpu(v) && hvm_smep_enabled(v)
- && (pfec & PFEC_insn_fetch) && !(pfec & PFEC_user_mode) );
- if ( smep )
+ if ( is_hvm_vcpu(v) && !(pfec & PFEC_user_mode) )
+ {
+ struct segment_register seg;
+ const struct cpu_user_regs *regs = guest_cpu_user_regs();
+
+ /* SMEP: kernel-mode instruction fetches from user-mode mappings
+ * should fault. Unlike NX or invalid bits, we're looking for _all_
+ * entries in the walk to have _PAGE_USER set, so we need to do the
+ * whole walk as if it were a user-mode one and then invert the answer. */
+ smep = hvm_smep_enabled(v) && (pfec & PFEC_insn_fetch);
+
+ switch ( v->arch.smap_check_policy )
+ {
+ case SMAP_CHECK_HONOR_CPL_AC:
+ hvm_get_segment_register(v, x86_seg_ss, &seg);
+
+ /*
+ * SMAP: kernel-mode data accesses from user-mode mappings
+ * should fault.
+ * A fault is considered as a SMAP violation if the following
+ * conditions come true:
+ * - X86_CR4_SMAP is set in CR4
+ * - A user page is accessed
+ * - CPL = 3 or X86_EFLAGS_AC is clear
+ * - Page fault in kernel mode
+ */
+ smap = hvm_smap_enabled(v) &&
+ ((seg.attr.fields.dpl == 3) ||
+ !(regs->eflags & X86_EFLAGS_AC));
+ break;
+ case SMAP_CHECK_ENABLED:
+ smap = hvm_smap_enabled(v);
+ break;
+ default:
+ ASSERT(v->arch.smap_check_policy == SMAP_CHECK_DISABLED);
+ break;
+ }
+ }
+
+ if ( smep || smap )
mflags |= _PAGE_USER;
#if GUEST_PAGING_LEVELS >= 3 /* PAE or 64... */
@@ -338,8 +371,8 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
#if GUEST_PAGING_LEVELS >= 4 /* 64-bit only... */
set_ad:
#endif
- /* Now re-invert the user-mode requirement for SMEP. */
- if ( smep )
+ /* Now re-invert the user-mode requirement for SMEP and SMAP */
+ if ( smep || smap )
rc ^= _PAGE_USER;
/* Go back and set accessed and dirty bits only if the walk was a
diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c
index 71227ef..abf3d7a 100644
--- a/xen/arch/x86/mm/hap/hap.c
+++ b/xen/arch/x86/mm/hap/hap.c
@@ -81,7 +81,6 @@ int hap_track_dirty_vram(struct domain *d,
if ( !paging_mode_log_dirty(d) )
{
- hap_logdirty_init(d);
rc = paging_log_dirty_enable(d, 0);
if ( rc )
goto out;
@@ -110,11 +109,18 @@ int hap_track_dirty_vram(struct domain *d,
if ( begin_pfn != dirty_vram->begin_pfn ||
begin_pfn + nr != dirty_vram->end_pfn )
{
+ unsigned long ostart = dirty_vram->begin_pfn;
+ unsigned long oend = dirty_vram->end_pfn;
+
dirty_vram->begin_pfn = begin_pfn;
dirty_vram->end_pfn = begin_pfn + nr;
paging_unlock(d);
+ if ( oend > ostart )
+ p2m_change_type_range(d, ostart, oend,
+ p2m_ram_logdirty, p2m_ram_rw);
+
/* set l1e entries of range within P2M table to be read-only. */
p2m_change_type_range(d, begin_pfn, begin_pfn + nr,
p2m_ram_rw, p2m_ram_logdirty);
@@ -150,11 +156,16 @@ int hap_track_dirty_vram(struct domain *d,
* If zero pages specified while tracking dirty vram
* then stop tracking
*/
+ begin_pfn = dirty_vram->begin_pfn;
+ nr = dirty_vram->end_pfn - dirty_vram->begin_pfn;
xfree(dirty_vram);
d->arch.hvm_domain.dirty_vram = NULL;
}
paging_unlock(d);
+ if ( nr )
+ p2m_change_type_range(d, begin_pfn, begin_pfn + nr,
+ p2m_ram_logdirty, p2m_ram_rw);
}
out:
if ( dirty_bitmap )
@@ -207,15 +218,6 @@ static void hap_clean_dirty_bitmap(struct domain *d)
flush_tlb_mask(d->domain_dirty_cpumask);
}
-void hap_logdirty_init(struct domain *d)
-{
-
- /* Reinitialize logdirty mechanism */
- paging_log_dirty_init(d, hap_enable_log_dirty,
- hap_disable_log_dirty,
- hap_clean_dirty_bitmap);
-}
-
/************************************************/
/* HAP SUPPORT FUNCTIONS */
/************************************************/
@@ -233,9 +235,8 @@ static struct page_info *hap_alloc(struct domain *d)
d->arch.paging.hap.free_pages--;
p = __map_domain_page(pg);
- ASSERT(p != NULL);
clear_page(p);
- hap_unmap_domain_page(p);
+ unmap_domain_page(p);
return pg;
}
@@ -269,7 +270,7 @@ static struct page_info *hap_alloc_p2m_page(struct domain *d)
else if ( !d->arch.paging.p2m_alloc_failed )
{
d->arch.paging.p2m_alloc_failed = 1;
- dprintk(XENLOG_ERR, "d%i failed to allocate from HAP pool",
+ dprintk(XENLOG_ERR, "d%i failed to allocate from HAP pool\n",
d->domain_id);
}
@@ -375,7 +376,6 @@ static void hap_install_xen_entries_in_l4(struct vcpu *v, mfn_t l4mfn)
l4_pgentry_t *l4e;
l4e = hap_map_domain_page(l4mfn);
- ASSERT(l4e != NULL);
/* Copy the common Xen mappings from the idle domain */
memcpy(&l4e[ROOT_PAGETABLE_FIRST_XEN_SLOT],
@@ -428,6 +428,11 @@ static void hap_destroy_monitor_table(struct vcpu* v, mfn_t mmfn)
void hap_domain_init(struct domain *d)
{
INIT_PAGE_LIST_HEAD(&d->arch.paging.hap.freelist);
+
+ /* Use HAP logdirty mechanism. */
+ paging_log_dirty_init(d, hap_enable_log_dirty,
+ hap_disable_log_dirty,
+ hap_clean_dirty_bitmap);
}
/* return 0 for success, -errno for failure */
@@ -589,6 +594,18 @@ int hap_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
}
}
+void __init hap_set_alloc_for_pvh_dom0(struct domain *d,
+ unsigned long hap_pages)
+{
+ int rc;
+
+ paging_lock(d);
+ rc = hap_set_allocation(d, hap_pages, NULL);
+ paging_unlock(d);
+
+ BUG_ON(rc);
+}
+
static const struct paging_mode hap_paging_real_mode;
static const struct paging_mode hap_paging_protected_mode;
static const struct paging_mode hap_paging_pae_mode;
@@ -685,10 +702,9 @@ static void hap_update_paging_modes(struct vcpu *v)
}
static void
-hap_write_p2m_entry(struct vcpu *v, unsigned long gfn, l1_pgentry_t *p,
- mfn_t table_mfn, l1_pgentry_t new, unsigned int level)
+hap_write_p2m_entry(struct domain *d, unsigned long gfn, l1_pgentry_t *p,
+ l1_pgentry_t new, unsigned int level)
{
- struct domain *d = v->domain;
uint32_t old_flags;
bool_t flush_nestedp2m = 0;
diff --git a/xen/arch/x86/mm/hap/nested_ept.c b/xen/arch/x86/mm/hap/nested_ept.c
index 0d044bc..cbbc4e9 100644
--- a/xen/arch/x86/mm/hap/nested_ept.c
+++ b/xen/arch/x86/mm/hap/nested_ept.c
@@ -17,14 +17,14 @@
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
+#include <xen/mem_event.h>
+#include <xen/event.h>
+#include <public/mem_event.h>
#include <asm/domain.h>
#include <asm/page.h>
#include <asm/paging.h>
#include <asm/p2m.h>
-#include <asm/mem_event.h>
-#include <public/mem_event.h>
#include <asm/mem_sharing.h>
-#include <xen/event.h>
#include <asm/hap.h>
#include <asm/hvm/support.h>
diff --git a/xen/arch/x86/mm/hap/nested_hap.c b/xen/arch/x86/mm/hap/nested_hap.c
index f4c3f34..9c1ec11 100644
--- a/xen/arch/x86/mm/hap/nested_hap.c
+++ b/xen/arch/x86/mm/hap/nested_hap.c
@@ -19,14 +19,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <xen/mem_event.h>
+#include <xen/event.h>
+#include <public/mem_event.h>
#include <asm/domain.h>
#include <asm/page.h>
#include <asm/paging.h>
#include <asm/p2m.h>
-#include <asm/mem_event.h>
-#include <public/mem_event.h>
#include <asm/mem_sharing.h>
-#include <xen/event.h>
#include <asm/hap.h>
#include <asm/hvm/support.h>
@@ -79,7 +79,7 @@
void
nestedp2m_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
- l1_pgentry_t *p, mfn_t table_mfn, l1_pgentry_t new, unsigned int level)
+ l1_pgentry_t *p, l1_pgentry_t new, unsigned int level)
{
struct domain *d = p2m->domain;
uint32_t old_flags;
@@ -103,7 +103,7 @@ nestedhap_fix_p2m(struct vcpu *v, struct p2m_domain *p2m,
paddr_t L2_gpa, paddr_t L0_gpa,
unsigned int page_order, p2m_type_t p2mt, p2m_access_t p2ma)
{
- int rv = 1;
+ int rc = 0;
ASSERT(p2m);
ASSERT(p2m->set_entry);
@@ -124,15 +124,16 @@ nestedhap_fix_p2m(struct vcpu *v, struct p2m_domain *p2m,
gfn = (L2_gpa >> PAGE_SHIFT) & mask;
mfn = _mfn((L0_gpa >> PAGE_SHIFT) & mask);
- rv = set_p2m_entry(p2m, gfn, mfn, page_order, p2mt, p2ma);
+ rc = p2m_set_entry(p2m, gfn, mfn, page_order, p2mt, p2ma);
}
p2m_unlock(p2m);
- if (rv == 0) {
+ if ( rc )
+ {
gdprintk(XENLOG_ERR,
- "failed to set entry for %#"PRIx64" -> %#"PRIx64"\n",
- L2_gpa, L0_gpa);
+ "failed to set entry for %#"PRIx64" -> %#"PRIx64" rc:%d\n",
+ L2_gpa, L0_gpa, rc);
domain_crash(p2m->domain);
}
}
@@ -263,7 +264,7 @@ nestedhvm_hap_nested_page_fault(struct vcpu *v, paddr_t *L2_gpa,
switch ( p2ma_10 )
{
- case p2m_access_n ... p2m_access_rwx:
+ case p2m_access_rwx ... p2m_access_n:
break;
case p2m_access_rx2rw:
p2ma_10 = p2m_access_rx;
diff --git a/xen/arch/x86/mm/mem_access.c b/xen/arch/x86/mm/mem_access.c
deleted file mode 100644
index 50aaf27..0000000
--- a/xen/arch/x86/mm/mem_access.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/******************************************************************************
- * arch/x86/mm/mem_access.c
- *
- * Memory access support.
- *
- * Copyright (c) 2011 Virtuata, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <asm/p2m.h>
-#include <asm/mem_event.h>
-
-
-int mem_access_memop(struct domain *d, xen_mem_event_op_t *meo)
-{
- int rc;
-
- if ( unlikely(!d->mem_event->access.ring_page) )
- return -ENODEV;
-
- switch( meo->op )
- {
- case XENMEM_access_op_resume:
- {
- p2m_mem_access_resume(d);
- rc = 0;
- }
- break;
-
- default:
- rc = -ENOSYS;
- break;
- }
-
- return rc;
-}
-
-int mem_access_send_req(struct domain *d, mem_event_request_t *req)
-{
- int rc = mem_event_claim_slot(d, &d->mem_event->access);
- if ( rc < 0 )
- return rc;
-
- mem_event_put_request(d, &d->mem_event->access, req);
-
- return 0;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/arch/x86/mm/mem_event.c b/xen/arch/x86/mm/mem_event.c
deleted file mode 100644
index 909d7a4..0000000
--- a/xen/arch/x86/mm/mem_event.c
+++ /dev/null
@@ -1,698 +0,0 @@
-/******************************************************************************
- * arch/x86/mm/mem_event.c
- *
- * Memory event support.
- *
- * Copyright (c) 2009 Citrix Systems, Inc. (Patrick Colp)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <asm/domain.h>
-#include <xen/event.h>
-#include <xen/wait.h>
-#include <asm/p2m.h>
-#include <asm/mem_event.h>
-#include <asm/mem_paging.h>
-#include <asm/mem_access.h>
-#include <asm/mem_sharing.h>
-#include <xsm/xsm.h>
-
-/* for public/io/ring.h macros */
-#define xen_mb() mb()
-#define xen_rmb() rmb()
-#define xen_wmb() wmb()
-
-#define mem_event_ring_lock_init(_med) spin_lock_init(&(_med)->ring_lock)
-#define mem_event_ring_lock(_med) spin_lock(&(_med)->ring_lock)
-#define mem_event_ring_unlock(_med) spin_unlock(&(_med)->ring_lock)
-
-static int mem_event_enable(
- struct domain *d,
- xen_domctl_mem_event_op_t *mec,
- struct mem_event_domain *med,
- int pause_flag,
- int param,
- xen_event_channel_notification_t notification_fn)
-{
- int rc;
- unsigned long ring_gfn = d->arch.hvm_domain.params[param];
-
- /* Only one helper at a time. If the helper crashed,
- * the ring is in an undefined state and so is the guest.
- */
- if ( med->ring_page )
- return -EBUSY;
-
- /* The parameter defaults to zero, and it should be
- * set to something */
- if ( ring_gfn == 0 )
- return -ENOSYS;
-
- mem_event_ring_lock_init(med);
- mem_event_ring_lock(med);
-
- rc = prepare_ring_for_helper(d, ring_gfn, &med->ring_pg_struct,
- &med->ring_page);
- if ( rc < 0 )
- goto err;
-
- /* Set the number of currently blocked vCPUs to 0. */
- med->blocked = 0;
-
- /* Allocate event channel */
- rc = alloc_unbound_xen_event_channel(d->vcpu[0],
- current->domain->domain_id,
- notification_fn);
- if ( rc < 0 )
- goto err;
-
- med->xen_port = mec->port = rc;
-
- /* Prepare ring buffer */
- FRONT_RING_INIT(&med->front_ring,
- (mem_event_sring_t *)med->ring_page,
- PAGE_SIZE);
-
- /* Save the pause flag for this particular ring. */
- med->pause_flag = pause_flag;
-
- /* Initialize the last-chance wait queue. */
- init_waitqueue_head(&med->wq);
-
- mem_event_ring_unlock(med);
- return 0;
-
- err:
- destroy_ring_for_helper(&med->ring_page,
- med->ring_pg_struct);
- mem_event_ring_unlock(med);
-
- return rc;
-}
-
-static unsigned int mem_event_ring_available(struct mem_event_domain *med)
-{
- int avail_req = RING_FREE_REQUESTS(&med->front_ring);
- avail_req -= med->target_producers;
- avail_req -= med->foreign_producers;
-
- BUG_ON(avail_req < 0);
-
- return avail_req;
-}
-
-/*
- * mem_event_wake_blocked() will wakeup vcpus waiting for room in the
- * ring. These vCPUs were paused on their way out after placing an event,
- * but need to be resumed where the ring is capable of processing at least
- * one event from them.
- */
-static void mem_event_wake_blocked(struct domain *d, struct mem_event_domain *med)
-{
- struct vcpu *v;
- int online = d->max_vcpus;
- unsigned int avail_req = mem_event_ring_available(med);
-
- if ( avail_req == 0 || med->blocked == 0 )
- return;
-
- /*
- * We ensure that we only have vCPUs online if there are enough free slots
- * for their memory events to be processed. This will ensure that no
- * memory events are lost (due to the fact that certain types of events
- * cannot be replayed, we need to ensure that there is space in the ring
- * for when they are hit).
- * See comment below in mem_event_put_request().
- */
- for_each_vcpu ( d, v )
- if ( test_bit(med->pause_flag, &v->pause_flags) )
- online--;
-
- ASSERT(online == (d->max_vcpus - med->blocked));
-
- /* We remember which vcpu last woke up to avoid scanning always linearly
- * from zero and starving higher-numbered vcpus under high load */
- if ( d->vcpu )
- {
- int i, j, k;
-
- for (i = med->last_vcpu_wake_up + 1, j = 0; j < d->max_vcpus; i++, j++)
- {
- k = i % d->max_vcpus;
- v = d->vcpu[k];
- if ( !v )
- continue;
-
- if ( !(med->blocked) || online >= avail_req )
- break;
-
- if ( test_and_clear_bit(med->pause_flag, &v->pause_flags) )
- {
- vcpu_unpause(v);
- online++;
- med->blocked--;
- med->last_vcpu_wake_up = k;
- }
- }
- }
-}
-
-/*
- * In the event that a vCPU attempted to place an event in the ring and
- * was unable to do so, it is queued on a wait queue. These are woken as
- * needed, and take precedence over the blocked vCPUs.
- */
-static void mem_event_wake_queued(struct domain *d, struct mem_event_domain *med)
-{
- unsigned int avail_req = mem_event_ring_available(med);
-
- if ( avail_req > 0 )
- wake_up_nr(&med->wq, avail_req);
-}
-
-/*
- * mem_event_wake() will wakeup all vcpus waiting for the ring to
- * become available. If we have queued vCPUs, they get top priority. We
- * are guaranteed that they will go through code paths that will eventually
- * call mem_event_wake() again, ensuring that any blocked vCPUs will get
- * unpaused once all the queued vCPUs have made it through.
- */
-void mem_event_wake(struct domain *d, struct mem_event_domain *med)
-{
- if (!list_empty(&med->wq.list))
- mem_event_wake_queued(d, med);
- else
- mem_event_wake_blocked(d, med);
-}
-
-static int mem_event_disable(struct domain *d, struct mem_event_domain *med)
-{
- if ( med->ring_page )
- {
- struct vcpu *v;
-
- mem_event_ring_lock(med);
-
- if ( !list_empty(&med->wq.list) )
- {
- mem_event_ring_unlock(med);
- return -EBUSY;
- }
-
- /* Free domU's event channel and leave the other one unbound */
- free_xen_event_channel(d->vcpu[0], med->xen_port);
-
- /* Unblock all vCPUs */
- for_each_vcpu ( d, v )
- {
- if ( test_and_clear_bit(med->pause_flag, &v->pause_flags) )
- {
- vcpu_unpause(v);
- med->blocked--;
- }
- }
-
- destroy_ring_for_helper(&med->ring_page,
- med->ring_pg_struct);
- mem_event_ring_unlock(med);
- }
-
- return 0;
-}
-
-static inline void mem_event_release_slot(struct domain *d,
- struct mem_event_domain *med)
-{
- /* Update the accounting */
- if ( current->domain == d )
- med->target_producers--;
- else
- med->foreign_producers--;
-
- /* Kick any waiters */
- mem_event_wake(d, med);
-}
-
-/*
- * mem_event_mark_and_pause() tags vcpu and put it to sleep.
- * The vcpu will resume execution in mem_event_wake_waiters().
- */
-void mem_event_mark_and_pause(struct vcpu *v, struct mem_event_domain *med)
-{
- if ( !test_and_set_bit(med->pause_flag, &v->pause_flags) )
- {
- vcpu_pause_nosync(v);
- med->blocked++;
- }
-}
-
-/*
- * This must be preceded by a call to claim_slot(), and is guaranteed to
- * succeed. As a side-effect however, the vCPU may be paused if the ring is
- * overly full and its continued execution would cause stalling and excessive
- * waiting. The vCPU will be automatically unpaused when the ring clears.
- */
-void mem_event_put_request(struct domain *d,
- struct mem_event_domain *med,
- mem_event_request_t *req)
-{
- mem_event_front_ring_t *front_ring;
- int free_req;
- unsigned int avail_req;
- RING_IDX req_prod;
-
- if ( current->domain != d )
- {
- req->flags |= MEM_EVENT_FLAG_FOREIGN;
- ASSERT( !(req->flags & MEM_EVENT_FLAG_VCPU_PAUSED) );
- }
-
- mem_event_ring_lock(med);
-
- /* Due to the reservations, this step must succeed. */
- front_ring = &med->front_ring;
- free_req = RING_FREE_REQUESTS(front_ring);
- ASSERT(free_req > 0);
-
- /* Copy request */
- req_prod = front_ring->req_prod_pvt;
- memcpy(RING_GET_REQUEST(front_ring, req_prod), req, sizeof(*req));
- req_prod++;
-
- /* Update ring */
- front_ring->req_prod_pvt = req_prod;
- RING_PUSH_REQUESTS(front_ring);
-
- /* We've actually *used* our reservation, so release the slot. */
- mem_event_release_slot(d, med);
-
- /* Give this vCPU a black eye if necessary, on the way out.
- * See the comments above wake_blocked() for more information
- * on how this mechanism works to avoid waiting. */
- avail_req = mem_event_ring_available(med);
- if( current->domain == d && avail_req < d->max_vcpus )
- mem_event_mark_and_pause(current, med);
-
- mem_event_ring_unlock(med);
-
- notify_via_xen_event_channel(d, med->xen_port);
-}
-
-int mem_event_get_response(struct domain *d, struct mem_event_domain *med, mem_event_response_t *rsp)
-{
- mem_event_front_ring_t *front_ring;
- RING_IDX rsp_cons;
-
- mem_event_ring_lock(med);
-
- front_ring = &med->front_ring;
- rsp_cons = front_ring->rsp_cons;
-
- if ( !RING_HAS_UNCONSUMED_RESPONSES(front_ring) )
- {
- mem_event_ring_unlock(med);
- return 0;
- }
-
- /* Copy response */
- memcpy(rsp, RING_GET_RESPONSE(front_ring, rsp_cons), sizeof(*rsp));
- rsp_cons++;
-
- /* Update ring */
- front_ring->rsp_cons = rsp_cons;
- front_ring->sring->rsp_event = rsp_cons + 1;
-
- /* Kick any waiters -- since we've just consumed an event,
- * there may be additional space available in the ring. */
- mem_event_wake(d, med);
-
- mem_event_ring_unlock(med);
-
- return 1;
-}
-
-void mem_event_cancel_slot(struct domain *d, struct mem_event_domain *med)
-{
- mem_event_ring_lock(med);
- mem_event_release_slot(d, med);
- mem_event_ring_unlock(med);
-}
-
-static int mem_event_grab_slot(struct mem_event_domain *med, int foreign)
-{
- unsigned int avail_req;
-
- if ( !med->ring_page )
- return -ENOSYS;
-
- mem_event_ring_lock(med);
-
- avail_req = mem_event_ring_available(med);
- if ( avail_req == 0 )
- {
- mem_event_ring_unlock(med);
- return -EBUSY;
- }
-
- if ( !foreign )
- med->target_producers++;
- else
- med->foreign_producers++;
-
- mem_event_ring_unlock(med);
-
- return 0;
-}
-
-/* Simple try_grab wrapper for use in the wait_event() macro. */
-static int mem_event_wait_try_grab(struct mem_event_domain *med, int *rc)
-{
- *rc = mem_event_grab_slot(med, 0);
- return *rc;
-}
-
-/* Call mem_event_grab_slot() until the ring doesn't exist, or is available. */
-static int mem_event_wait_slot(struct mem_event_domain *med)
-{
- int rc = -EBUSY;
- wait_event(med->wq, mem_event_wait_try_grab(med, &rc) != -EBUSY);
- return rc;
-}
-
-bool_t mem_event_check_ring(struct mem_event_domain *med)
-{
- return (med->ring_page != NULL);
-}
-
-/*
- * Determines whether or not the current vCPU belongs to the target domain,
- * and calls the appropriate wait function. If it is a guest vCPU, then we
- * use mem_event_wait_slot() to reserve a slot. As long as there is a ring,
- * this function will always return 0 for a guest. For a non-guest, we check
- * for space and return -EBUSY if the ring is not available.
- *
- * Return codes: -ENOSYS: the ring is not yet configured
- * -EBUSY: the ring is busy
- * 0: a spot has been reserved
- *
- */
-int __mem_event_claim_slot(struct domain *d, struct mem_event_domain *med,
- bool_t allow_sleep)
-{
- if ( (current->domain == d) && allow_sleep )
- return mem_event_wait_slot(med);
- else
- return mem_event_grab_slot(med, (current->domain != d));
-}
-
-/* Registered with Xen-bound event channel for incoming notifications. */
-static void mem_paging_notification(struct vcpu *v, unsigned int port)
-{
- if ( likely(v->domain->mem_event->paging.ring_page != NULL) )
- p2m_mem_paging_resume(v->domain);
-}
-
-/* Registered with Xen-bound event channel for incoming notifications. */
-static void mem_access_notification(struct vcpu *v, unsigned int port)
-{
- if ( likely(v->domain->mem_event->access.ring_page != NULL) )
- p2m_mem_access_resume(v->domain);
-}
-
-/* Registered with Xen-bound event channel for incoming notifications. */
-static void mem_sharing_notification(struct vcpu *v, unsigned int port)
-{
- if ( likely(v->domain->mem_event->share.ring_page != NULL) )
- mem_sharing_sharing_resume(v->domain);
-}
-
-int do_mem_event_op(int op, uint32_t domain, void *arg)
-{
- int ret;
- struct domain *d;
-
- ret = rcu_lock_live_remote_domain_by_id(domain, &d);
- if ( ret )
- return ret;
-
- ret = xsm_mem_event_op(XSM_TARGET, d, op);
- if ( ret )
- goto out;
-
- switch (op)
- {
- case XENMEM_paging_op:
- ret = mem_paging_memop(d, (xen_mem_event_op_t *) arg);
- break;
- case XENMEM_access_op:
- ret = mem_access_memop(d, (xen_mem_event_op_t *) arg);
- break;
- case XENMEM_sharing_op:
- ret = mem_sharing_memop(d, (xen_mem_sharing_op_t *) arg);
- break;
- default:
- ret = -ENOSYS;
- }
-
- out:
- rcu_unlock_domain(d);
- return ret;
-}
-
-/* Clean up on domain destruction */
-void mem_event_cleanup(struct domain *d)
-{
- if ( d->mem_event->paging.ring_page ) {
- /* Destroying the wait queue head means waking up all
- * queued vcpus. This will drain the list, allowing
- * the disable routine to complete. It will also drop
- * all domain refs the wait-queued vcpus are holding.
- * Finally, because this code path involves previously
- * pausing the domain (domain_kill), unpausing the
- * vcpus causes no harm. */
- destroy_waitqueue_head(&d->mem_event->paging.wq);
- (void)mem_event_disable(d, &d->mem_event->paging);
- }
- if ( d->mem_event->access.ring_page ) {
- destroy_waitqueue_head(&d->mem_event->access.wq);
- (void)mem_event_disable(d, &d->mem_event->access);
- }
- if ( d->mem_event->share.ring_page ) {
- destroy_waitqueue_head(&d->mem_event->share.wq);
- (void)mem_event_disable(d, &d->mem_event->share);
- }
-}
-
-int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
- XEN_GUEST_HANDLE_PARAM(void) u_domctl)
-{
- int rc;
-
- rc = xsm_mem_event_control(XSM_PRIV, d, mec->mode, mec->op);
- if ( rc )
- return rc;
-
- if ( unlikely(d == current->domain) )
- {
- gdprintk(XENLOG_INFO, "Tried to do a memory event op on itself.\n");
- return -EINVAL;
- }
-
- if ( unlikely(d->is_dying) )
- {
- gdprintk(XENLOG_INFO, "Ignoring memory event op on dying domain %u\n",
- d->domain_id);
- return 0;
- }
-
- if ( unlikely(d->vcpu == NULL) || unlikely(d->vcpu[0] == NULL) )
- {
- gdprintk(XENLOG_INFO,
- "Memory event op on a domain (%u) with no vcpus\n",
- d->domain_id);
- return -EINVAL;
- }
-
- rc = -ENOSYS;
-
- switch ( mec->mode )
- {
- case XEN_DOMCTL_MEM_EVENT_OP_PAGING:
- {
- struct mem_event_domain *med = &d->mem_event->paging;
- rc = -EINVAL;
-
- switch( mec->op )
- {
- case XEN_DOMCTL_MEM_EVENT_OP_PAGING_ENABLE:
- {
- struct p2m_domain *p2m = p2m_get_hostp2m(d);
- rc = -ENODEV;
- /* Only HAP is supported */
- if ( !hap_enabled(d) )
- break;
-
- /* No paging if iommu is used */
- rc = -EMLINK;
- if ( unlikely(need_iommu(d)) )
- break;
-
- rc = -EXDEV;
- /* Disallow paging in a PoD guest */
- if ( p2m->pod.entry_count )
- break;
-
- rc = mem_event_enable(d, mec, med, _VPF_mem_paging,
- HVM_PARAM_PAGING_RING_PFN,
- mem_paging_notification);
- }
- break;
-
- case XEN_DOMCTL_MEM_EVENT_OP_PAGING_DISABLE:
- {
- if ( med->ring_page )
- rc = mem_event_disable(d, med);
- }
- break;
-
- default:
- rc = -ENOSYS;
- break;
- }
- }
- break;
-
- case XEN_DOMCTL_MEM_EVENT_OP_ACCESS:
- {
- struct mem_event_domain *med = &d->mem_event->access;
- rc = -EINVAL;
-
- switch( mec->op )
- {
- case XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE:
- {
- rc = -ENODEV;
- /* Only HAP is supported */
- if ( !hap_enabled(d) )
- break;
-
- /* Currently only EPT is supported */
- if ( !cpu_has_vmx )
- break;
-
- rc = mem_event_enable(d, mec, med, _VPF_mem_access,
- HVM_PARAM_ACCESS_RING_PFN,
- mem_access_notification);
- }
- break;
-
- case XEN_DOMCTL_MEM_EVENT_OP_ACCESS_DISABLE:
- {
- if ( med->ring_page )
- rc = mem_event_disable(d, med);
- }
- break;
-
- default:
- rc = -ENOSYS;
- break;
- }
- }
- break;
-
- case XEN_DOMCTL_MEM_EVENT_OP_SHARING:
- {
- struct mem_event_domain *med = &d->mem_event->share;
- rc = -EINVAL;
-
- switch( mec->op )
- {
- case XEN_DOMCTL_MEM_EVENT_OP_SHARING_ENABLE:
- {
- rc = -ENODEV;
- /* Only HAP is supported */
- if ( !hap_enabled(d) )
- break;
-
- rc = mem_event_enable(d, mec, med, _VPF_mem_sharing,
- HVM_PARAM_SHARING_RING_PFN,
- mem_sharing_notification);
- }
- break;
-
- case XEN_DOMCTL_MEM_EVENT_OP_SHARING_DISABLE:
- {
- if ( med->ring_page )
- rc = mem_event_disable(d, med);
- }
- break;
-
- default:
- rc = -ENOSYS;
- break;
- }
- }
- break;
-
- default:
- rc = -ENOSYS;
- }
-
- return rc;
-}
-
-void mem_event_vcpu_pause(struct vcpu *v)
-{
- ASSERT(v == current);
-
- atomic_inc(&v->mem_event_pause_count);
- vcpu_pause_nosync(v);
-}
-
-void mem_event_vcpu_unpause(struct vcpu *v)
-{
- int old, new, prev = v->mem_event_pause_count.counter;
-
- /* All unpause requests as a result of toolstack responses. Prevent
- * underflow of the vcpu pause count. */
- do
- {
- old = prev;
- new = old - 1;
-
- if ( new < 0 )
- {
- printk(XENLOG_G_WARNING
- "d%d:v%d mem_event: Too many unpause attempts\n",
- v->domain->domain_id, v->vcpu_id);
- return;
- }
-
- prev = cmpxchg(&v->mem_event_pause_count.counter, old, new);
- } while ( prev != old );
-
- vcpu_unpause(v);
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/arch/x86/mm/mem_paging.c b/xen/arch/x86/mm/mem_paging.c
index 235776d..65f6a3d 100644
--- a/xen/arch/x86/mm/mem_paging.c
+++ b/xen/arch/x86/mm/mem_paging.c
@@ -22,7 +22,7 @@
#include <asm/p2m.h>
-#include <asm/mem_event.h>
+#include <xen/mem_event.h>
int mem_paging_memop(struct domain *d, xen_mem_event_op_t *mec)
diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c
index 11df871..7c0fc7d 100644
--- a/xen/arch/x86/mm/mem_sharing.c
+++ b/xen/arch/x86/mm/mem_sharing.c
@@ -27,12 +27,12 @@
#include <xen/mm.h>
#include <xen/grant_table.h>
#include <xen/sched.h>
+#include <xen/rcupdate.h>
+#include <xen/mem_event.h>
#include <asm/page.h>
#include <asm/string.h>
#include <asm/p2m.h>
-#include <asm/mem_event.h>
#include <asm/atomic.h>
-#include <xen/rcupdate.h>
#include <asm/event.h>
#include <xsm/xsm.h>
@@ -855,7 +855,6 @@ int mem_sharing_nominate_page(struct domain *d,
mfn_t mfn;
struct page_info *page = NULL; /* gcc... */
int ret;
- struct gfn_info *gfn_info;
*phandle = 0UL;
@@ -914,7 +913,7 @@ int mem_sharing_nominate_page(struct domain *d,
page->sharing->handle = get_next_handle();
/* Create the local gfn info */
- if ( (gfn_info = mem_sharing_gfn_alloc(page, d, gfn)) == NULL )
+ if ( mem_sharing_gfn_alloc(page, d, gfn) == NULL )
{
xfree(page->sharing);
page->sharing = NULL;
@@ -923,7 +922,7 @@ int mem_sharing_nominate_page(struct domain *d,
}
/* Change the p2m type, should never fail with p2m locked. */
- BUG_ON(p2m_change_type(d, gfn, p2mt, p2m_ram_shared) != p2mt);
+ BUG_ON(p2m_change_type_one(d, gfn, p2mt, p2m_ram_shared));
/* Account for this page. */
atomic_inc(&nr_shared_mfns);
@@ -1031,7 +1030,7 @@ int mem_sharing_share_pages(struct domain *sd, unsigned long sgfn, shr_handle_t
put_page_and_type(cpage);
d = get_domain_by_id(gfn->domain);
BUG_ON(!d);
- BUG_ON(set_shared_p2m_entry(d, gfn->gfn, smfn) == 0);
+ BUG_ON(set_shared_p2m_entry(d, gfn->gfn, smfn));
put_domain(d);
}
ASSERT(list_empty(&cpage->sharing->gfns));
@@ -1102,16 +1101,14 @@ int mem_sharing_add_to_physmap(struct domain *sd, unsigned long sgfn, shr_handle
goto err_unlock;
}
- ret = set_p2m_entry(p2m, cgfn, smfn, PAGE_ORDER_4K, p2m_ram_shared, a);
+ ret = p2m_set_entry(p2m, cgfn, smfn, PAGE_ORDER_4K, p2m_ram_shared, a);
/* Tempted to turn this into an assert */
- if ( !ret )
+ if ( ret )
{
- ret = -ENOENT;
mem_sharing_gfn_destroy(spage, cd, gfn_info);
put_page_and_type(spage);
} else {
- ret = 0;
/* There is a chance we're plugging a hole where a paged out page was */
if ( p2m_is_paging(cmfn_type) && (cmfn_type != p2m_ram_paging_out) )
{
@@ -1242,14 +1239,13 @@ int __mem_sharing_unshare_page(struct domain *d,
unmap_domain_page(s);
unmap_domain_page(t);
- BUG_ON(set_shared_p2m_entry(d, gfn, page_to_mfn(page)) == 0);
+ BUG_ON(set_shared_p2m_entry(d, gfn, page_to_mfn(page)));
mem_sharing_gfn_destroy(old_page, d, gfn_info);
mem_sharing_page_unlock(old_page);
put_page_and_type(old_page);
private_page_found:
- if ( p2m_change_type(d, gfn, p2m_ram_shared, p2m_ram_rw) !=
- p2m_ram_shared )
+ if ( p2m_change_type_one(d, gfn, p2m_ram_shared, p2m_ram_rw) )
{
gdprintk(XENLOG_ERR, "Could not change p2m type d %hu gfn %lx.\n",
d->domain_id, gfn);
@@ -1298,7 +1294,7 @@ int relinquish_shared_pages(struct domain *d)
* we hold the p2m lock. */
set_rc = p2m->set_entry(p2m, gfn, _mfn(0), PAGE_ORDER_4K,
p2m_invalid, p2m_access_rwx);
- ASSERT(set_rc != 0);
+ ASSERT(set_rc == 0);
count += 0x10;
}
else
@@ -1310,7 +1306,7 @@ int relinquish_shared_pages(struct domain *d)
if ( hypercall_preempt_check() )
{
p2m->next_shared_gfn_to_relinquish = gfn + 1;
- rc = -EAGAIN;
+ rc = -ERESTART;
break;
}
count = 0;
@@ -1371,7 +1367,7 @@ int mem_sharing_memop(struct domain *d, xen_mem_sharing_op_t *mec)
if ( rc )
return rc;
- rc = xsm_mem_sharing_op(XSM_TARGET, d, cd, mec->op);
+ rc = xsm_mem_sharing_op(XSM_DM_PRIV, d, cd, mec->op);
if ( rc )
{
rcu_unlock_domain(cd);
@@ -1435,7 +1431,7 @@ int mem_sharing_memop(struct domain *d, xen_mem_sharing_op_t *mec)
if ( rc )
return rc;
- rc = xsm_mem_sharing_op(XSM_TARGET, d, cd, mec->op);
+ rc = xsm_mem_sharing_op(XSM_DM_PRIV, d, cd, mec->op);
if ( rc )
{
rcu_unlock_domain(cd);
diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
index 92d9e2d..15c6e83 100644
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -36,8 +36,6 @@
#define atomic_read_ept_entry(__pepte) \
( (ept_entry_t) { .epte = read_atomic(&(__pepte)->epte) } )
-#define atomic_write_ept_entry(__pepte, __epte) \
- write_atomic(&(__pepte)->epte, (__epte).epte)
#define is_epte_present(ept_entry) ((ept_entry)->epte & 0x7)
#define is_epte_superpage(ept_entry) ((ept_entry)->sp)
@@ -46,6 +44,64 @@ static inline bool_t is_epte_valid(ept_entry_t *e)
return (e->epte != 0 && e->sa_p2mt != p2m_invalid);
}
+/* returns : 0 for success, -errno otherwise */
+static int atomic_write_ept_entry(ept_entry_t *entryptr, ept_entry_t new,
+ int level)
+{
+ int rc;
+ unsigned long oldmfn = INVALID_MFN;
+ bool_t check_foreign = (new.mfn != entryptr->mfn ||
+ new.sa_p2mt != entryptr->sa_p2mt);
+
+ if ( level )
+ {
+ ASSERT(!is_epte_superpage(&new) || !p2m_is_foreign(new.sa_p2mt));
+ write_atomic(&entryptr->epte, new.epte);
+ return 0;
+ }
+
+ if ( unlikely(p2m_is_foreign(new.sa_p2mt)) )
+ {
+ rc = -EINVAL;
+ if ( !is_epte_present(&new) )
+ goto out;
+
+ if ( check_foreign )
+ {
+ struct domain *fdom;
+
+ if ( !mfn_valid(new.mfn) )
+ goto out;
+
+ rc = -ESRCH;
+ fdom = page_get_owner(mfn_to_page(new.mfn));
+ if ( fdom == NULL )
+ goto out;
+
+ /* get refcount on the page */
+ rc = -EBUSY;
+ if ( !get_page(mfn_to_page(new.mfn), fdom) )
+ goto out;
+ }
+ }
+
+ if ( unlikely(p2m_is_foreign(entryptr->sa_p2mt)) && check_foreign )
+ oldmfn = entryptr->mfn;
+
+ write_atomic(&entryptr->epte, new.epte);
+
+ if ( unlikely(oldmfn != INVALID_MFN) )
+ put_page(mfn_to_page(oldmfn));
+
+ rc = 0;
+
+ out:
+ if ( rc )
+ gdprintk(XENLOG_ERR, "epte o:%"PRIx64" n:%"PRIx64" rc:%d\n",
+ entryptr->epte, new.epte, rc);
+ return rc;
+}
+
static void ept_p2m_type_to_flags(ept_entry_t *entry, p2m_type_t type, p2m_access_t access)
{
/* First apply type permissions */
@@ -75,6 +131,7 @@ static void ept_p2m_type_to_flags(ept_entry_t *entry, p2m_type_t type, p2m_acces
entry->w = 0;
break;
case p2m_grant_map_rw:
+ case p2m_map_foreign:
entry->r = entry->w = 1;
entry->x = 0;
break;
@@ -182,14 +239,12 @@ static int ept_split_super_page(struct p2m_domain *p2m, ept_entry_t *ept_entry,
{
ept_entry_t *epte = table + i;
- epte->epte = 0;
- epte->emt = ept_entry->emt;
- epte->ipat = ept_entry->ipat;
- epte->sp = (level > 1) ? 1 : 0;
- epte->access = ept_entry->access;
- epte->sa_p2mt = ept_entry->sa_p2mt;
- epte->mfn = ept_entry->mfn + i * trunk;
- epte->rsvd2_snp = ( iommu_enabled && iommu_snoop ) ? 1 : 0;
+ *epte = *ept_entry;
+ epte->sp = (level > 1);
+ epte->mfn += i * trunk;
+ epte->snp = (iommu_enabled && iommu_snoop);
+ ASSERT(!epte->rsvd1);
+ ASSERT(!epte->avail3);
ept_p2m_type_to_flags(epte, epte->sa_p2mt, epte->access);
@@ -272,8 +327,284 @@ static int ept_next_level(struct p2m_domain *p2m, bool_t read_only,
}
/*
+ * Invalidate (via setting the EMT field to an invalid value) all valid
+ * present entries in the given page table, optionally marking the entries
+ * also for their subtrees needing P2M type re-calculation.
+ */
+static bool_t ept_invalidate_emt(mfn_t mfn, bool_t recalc, int level)
+{
+ int rc;
+ ept_entry_t *epte = map_domain_page(mfn_x(mfn));
+ unsigned int i;
+ bool_t changed = 0;
+
+ for ( i = 0; i < EPT_PAGETABLE_ENTRIES; i++ )
+ {
+ ept_entry_t e = atomic_read_ept_entry(&epte[i]);
+
+ if ( !is_epte_valid(&e) || !is_epte_present(&e) ||
+ (e.emt == MTRR_NUM_TYPES && (e.recalc || !recalc)) )
+ continue;
+
+ e.emt = MTRR_NUM_TYPES;
+ if ( recalc )
+ e.recalc = 1;
+ rc = atomic_write_ept_entry(&epte[i], e, level);
+ ASSERT(rc == 0);
+ changed = 1;
+ }
+
+ unmap_domain_page(epte);
+
+ return changed;
+}
+
+/*
+ * Just like ept_invalidate_emt() except that
+ * - not all entries at the targeted level may need processing,
+ * - the re-calculation flag gets always set.
+ * The passed in range is guaranteed to not cross a page (table)
+ * boundary at the targeted level.
+ */
+static int ept_invalidate_emt_range(struct p2m_domain *p2m,
+ unsigned int target,
+ unsigned long first_gfn,
+ unsigned long last_gfn)
+{
+ ept_entry_t *table;
+ unsigned long gfn_remainder = first_gfn;
+ unsigned int i, index;
+ int wrc, rc = 0, ret = GUEST_TABLE_MAP_FAILED;
+
+ table = map_domain_page(pagetable_get_pfn(p2m_get_pagetable(p2m)));
+ for ( i = ept_get_wl(&p2m->ept); i > target; --i )
+ {
+ ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
+ if ( ret == GUEST_TABLE_MAP_FAILED )
+ goto out;
+ if ( ret != GUEST_TABLE_NORMAL_PAGE )
+ break;
+ }
+
+ if ( i > target )
+ {
+ /* We need to split the original page. */
+ ept_entry_t split_ept_entry;
+
+ index = gfn_remainder >> (i * EPT_TABLE_ORDER);
+ split_ept_entry = atomic_read_ept_entry(&table[index]);
+ ASSERT(is_epte_superpage(&split_ept_entry));
+ if ( !ept_split_super_page(p2m, &split_ept_entry, i, target) )
+ {
+ ept_free_entry(p2m, &split_ept_entry, i);
+ rc = -ENOMEM;
+ goto out;
+ }
+ wrc = atomic_write_ept_entry(&table[index], split_ept_entry, i);
+ ASSERT(wrc == 0);
+
+ for ( ; i > target; --i )
+ if ( !ept_next_level(p2m, 1, &table, &gfn_remainder, i) )
+ break;
+ ASSERT(i == target);
+ }
+
+ index = gfn_remainder >> (i * EPT_TABLE_ORDER);
+ i = (last_gfn >> (i * EPT_TABLE_ORDER)) & (EPT_PAGETABLE_ENTRIES - 1);
+ for ( ; index <= i; ++index )
+ {
+ ept_entry_t e = atomic_read_ept_entry(&table[index]);
+
+ if ( is_epte_valid(&e) && is_epte_present(&e) &&
+ (e.emt != MTRR_NUM_TYPES || !e.recalc) )
+ {
+ e.emt = MTRR_NUM_TYPES;
+ e.recalc = 1;
+ wrc = atomic_write_ept_entry(&table[index], e, target);
+ ASSERT(wrc == 0);
+ rc = 1;
+ }
+ }
+
+ out:
+ unmap_domain_page(table);
+
+ return rc;
+}
+
+/*
+ * Resolve deliberately mis-configured (EMT field set to an invalid value)
+ * entries in the page table hierarchy for the given GFN:
+ * - calculate the correct value for the EMT field,
+ * - if marked so, re-calculate the P2M type,
+ * - propagate EMT and re-calculation flag down to the next page table level
+ * for entries not involved in the translation of the given GFN.
+ * Returns:
+ * - negative errno values in error,
+ * - zero if no adjustment was done,
+ * - a positive value if at least one adjustment was done.
+ */
+static int resolve_misconfig(struct p2m_domain *p2m, unsigned long gfn)
+{
+ struct ept_data *ept = &p2m->ept;
+ unsigned int level = ept_get_wl(ept);
+ unsigned long mfn = ept_get_asr(ept);
+ ept_entry_t *epte;
+ int wrc, rc = 0;
+
+ if ( !mfn )
+ return 0;
+
+ for ( ; ; --level )
+ {
+ ept_entry_t e;
+ unsigned int i;
+
+ epte = map_domain_page(mfn);
+ i = (gfn >> (level * EPT_TABLE_ORDER)) & (EPT_PAGETABLE_ENTRIES - 1);
+ e = atomic_read_ept_entry(&epte[i]);
+
+ if ( level == 0 || is_epte_superpage(&e) )
+ {
+ uint8_t ipat = 0;
+
+ if ( e.emt != MTRR_NUM_TYPES )
+ break;
+
+ if ( level == 0 )
+ {
+ for ( gfn -= i, i = 0; i < EPT_PAGETABLE_ENTRIES; ++i )
+ {
+ e = atomic_read_ept_entry(&epte[i]);
+ if ( e.emt == MTRR_NUM_TYPES )
+ e.emt = 0;
+ if ( !is_epte_valid(&e) || !is_epte_present(&e) )
+ continue;
+ e.emt = epte_get_entry_emt(p2m->domain, gfn + i,
+ _mfn(e.mfn), 0, &ipat,
+ e.sa_p2mt == p2m_mmio_direct);
+ e.ipat = ipat;
+ if ( e.recalc && p2m_is_changeable(e.sa_p2mt) )
+ {
+ e.sa_p2mt = p2m_is_logdirty_range(p2m, gfn + i, gfn + i)
+ ? p2m_ram_logdirty : p2m_ram_rw;
+ ept_p2m_type_to_flags(&e, e.sa_p2mt, e.access);
+ }
+ e.recalc = 0;
+ wrc = atomic_write_ept_entry(&epte[i], e, level);
+ ASSERT(wrc == 0);
+ }
+ }
+ else
+ {
+ int emt = epte_get_entry_emt(p2m->domain, gfn, _mfn(e.mfn),
+ level * EPT_TABLE_ORDER, &ipat,
+ e.sa_p2mt == p2m_mmio_direct);
+ bool_t recalc = e.recalc;
+
+ if ( recalc && p2m_is_changeable(e.sa_p2mt) )
+ {
+ unsigned long mask = ~0UL << (level * EPT_TABLE_ORDER);
+
+ switch ( p2m_is_logdirty_range(p2m, gfn & mask,
+ gfn | ~mask) )
+ {
+ case 0:
+ e.sa_p2mt = p2m_ram_rw;
+ e.recalc = 0;
+ break;
+ case 1:
+ e.sa_p2mt = p2m_ram_logdirty;
+ e.recalc = 0;
+ break;
+ default: /* Force split. */
+ emt = -1;
+ break;
+ }
+ }
+ if ( unlikely(emt < 0) )
+ {
+ if ( ept_split_super_page(p2m, &e, level, level - 1) )
+ {
+ wrc = atomic_write_ept_entry(&epte[i], e, level);
+ ASSERT(wrc == 0);
+ unmap_domain_page(epte);
+ mfn = e.mfn;
+ continue;
+ }
+ ept_free_entry(p2m, &e, level);
+ rc = -ENOMEM;
+ break;
+ }
+ e.emt = emt;
+ e.ipat = ipat;
+ e.recalc = 0;
+ if ( recalc && p2m_is_changeable(e.sa_p2mt) )
+ ept_p2m_type_to_flags(&e, e.sa_p2mt, e.access);
+ wrc = atomic_write_ept_entry(&epte[i], e, level);
+ ASSERT(wrc == 0);
+ }
+
+ rc = 1;
+ break;
+ }
+
+ if ( e.emt == MTRR_NUM_TYPES )
+ {
+ ASSERT(is_epte_present(&e));
+ ept_invalidate_emt(_mfn(e.mfn), e.recalc, level);
+ smp_wmb();
+ e.emt = 0;
+ e.recalc = 0;
+ wrc = atomic_write_ept_entry(&epte[i], e, level);
+ ASSERT(wrc == 0);
+ unmap_domain_page(epte);
+ rc = 1;
+ }
+ else if ( is_epte_present(&e) && !e.emt )
+ unmap_domain_page(epte);
+ else
+ break;
+
+ mfn = e.mfn;
+ }
+
+ unmap_domain_page(epte);
+ if ( rc )
+ {
+ struct vcpu *v;
+
+ for_each_vcpu ( p2m->domain, v )
+ v->arch.hvm_vmx.ept_spurious_misconfig = 1;
+ }
+
+ return rc;
+}
+
+bool_t ept_handle_misconfig(uint64_t gpa)
+{
+ struct vcpu *curr = current;
+ struct p2m_domain *p2m = p2m_get_hostp2m(curr->domain);
+ bool_t spurious;
+ int rc;
+
+ p2m_lock(p2m);
+
+ spurious = curr->arch.hvm_vmx.ept_spurious_misconfig;
+ rc = resolve_misconfig(p2m, PFN_DOWN(gpa));
+ curr->arch.hvm_vmx.ept_spurious_misconfig = 0;
+ ept_sync_domain(p2m);
+
+ p2m_unlock(p2m);
+
+ return spurious ? (rc >= 0) : (rc > 0);
+}
+
+/*
* ept_set_entry() computes 'need_modify_vtd_table' for itself,
* by observing whether any gfn->mfn translations are modified.
+ *
+ * Returns: 0 for success, -errno for failure
*/
static int
ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
@@ -281,17 +612,15 @@ ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
{
ept_entry_t *table, *ept_entry = NULL;
unsigned long gfn_remainder = gfn;
- unsigned long offset = 0;
- u32 index;
int i, target = order / EPT_TABLE_ORDER;
- int rv = 0;
- int ret = 0;
+ int ret, rc = 0;
bool_t direct_mmio = (p2mt == p2m_mmio_direct);
uint8_t ipat = 0;
int need_modify_vtd_table = 1;
int vtd_pte_present = 0;
- int needs_sync = 1;
+ enum { sync_off, sync_on, sync_check } needs_sync = sync_check;
ept_entry_t old_entry = { .epte = 0 };
+ ept_entry_t new_entry = { .epte = 0 };
struct ept_data *ept = &p2m->ept;
struct domain *d = p2m->domain;
@@ -305,32 +634,44 @@ ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
if ( ((gfn | mfn_x(mfn)) & ((1UL << order) - 1)) ||
((u64)gfn >> ((ept_get_wl(ept) + 1) * EPT_TABLE_ORDER)) ||
(order % EPT_TABLE_ORDER) )
- return 0;
+ return -EINVAL;
+
+ /* Carry out any eventually pending earlier changes first. */
+ ret = resolve_misconfig(p2m, gfn);
+ if ( ret < 0 )
+ {
+ ept_sync_domain(p2m);
+ return ret;
+ }
+ if ( ret > 0 )
+ needs_sync = sync_on;
ASSERT((target == 2 && hvm_hap_has_1gb()) ||
(target == 1 && hvm_hap_has_2mb()) ||
(target == 0));
+ ASSERT(!p2m_is_foreign(p2mt) || target == 0);
table = map_domain_page(pagetable_get_pfn(p2m_get_pagetable(p2m)));
+ ret = GUEST_TABLE_MAP_FAILED;
for ( i = ept_get_wl(ept); i > target; i-- )
{
ret = ept_next_level(p2m, 0, &table, &gfn_remainder, i);
if ( !ret )
+ {
+ rc = -ENOENT;
goto out;
+ }
else if ( ret != GUEST_TABLE_NORMAL_PAGE )
break;
}
ASSERT(ret != GUEST_TABLE_POD_PAGE || i != target);
- index = gfn_remainder >> (i * EPT_TABLE_ORDER);
- offset = gfn_remainder & ((1UL << (i * EPT_TABLE_ORDER)) - 1);
-
- ept_entry = table + index;
+ ept_entry = table + (gfn_remainder >> (i * EPT_TABLE_ORDER));
/* In case VT-d uses same page table, this flag is needed by VT-d */
- vtd_pte_present = is_epte_present(ept_entry) ? 1 : 0;
+ vtd_pte_present = is_epte_present(ept_entry);
/*
* If we're here with i > target, we must be at a leaf node, and
@@ -344,46 +685,21 @@ ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
if ( i == target )
{
/* We reached the target level. */
- ept_entry_t new_entry = { .epte = 0 };
/* No need to flush if the old entry wasn't valid */
- if ( !is_epte_present(ept_entry) )
- needs_sync = 0;
+ if ( needs_sync == sync_check && !is_epte_present(ept_entry) )
+ needs_sync = sync_off;
/* If we're replacing a non-leaf entry with a leaf entry (1GiB or 2MiB),
* the intermediate tables will be freed below after the ept flush
*
* Read-then-write is OK because we hold the p2m lock. */
old_entry = *ept_entry;
-
- if ( mfn_valid(mfn_x(mfn)) || direct_mmio || p2m_is_paged(p2mt) ||
- (p2mt == p2m_ram_paging_in) )
- {
- /* Construct the new entry, and then write it once */
- new_entry.emt = epte_get_entry_emt(p2m->domain, gfn, mfn, &ipat,
- direct_mmio);
-
- new_entry.ipat = ipat;
- new_entry.sp = order ? 1 : 0;
- new_entry.sa_p2mt = p2mt;
- new_entry.access = p2ma;
- new_entry.rsvd2_snp = (iommu_enabled && iommu_snoop);
-
- new_entry.mfn = mfn_x(mfn);
-
- if ( old_entry.mfn == new_entry.mfn )
- need_modify_vtd_table = 0;
-
- ept_p2m_type_to_flags(&new_entry, p2mt, p2ma);
- }
-
- atomic_write_ept_entry(ept_entry, new_entry);
}
else
{
/* We need to split the original page. */
ept_entry_t split_ept_entry;
- ept_entry_t new_entry = { .epte = 0 };
ASSERT(is_epte_superpage(ept_entry));
@@ -392,12 +708,14 @@ ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
if ( !ept_split_super_page(p2m, &split_ept_entry, i, target) )
{
ept_free_entry(p2m, &split_ept_entry, i);
+ rc = -ENOMEM;
goto out;
}
/* now install the newly split ept sub-tree */
/* NB: please make sure domian is paused and no in-fly VT-d DMA. */
- atomic_write_ept_entry(ept_entry, split_ept_entry);
+ rc = atomic_write_ept_entry(ept_entry, split_ept_entry, i);
+ ASSERT(rc == 0);
/* then move to the level we want to make real changes */
for ( ; i > target; i-- )
@@ -406,17 +724,25 @@ ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
/* We just installed the pages we need. */
ASSERT(i == target);
- index = gfn_remainder >> (i * EPT_TABLE_ORDER);
- offset = gfn_remainder & ((1UL << (i * EPT_TABLE_ORDER)) - 1);
+ ept_entry = table + (gfn_remainder >> (i * EPT_TABLE_ORDER));
+ }
- ept_entry = table + index;
+ if ( mfn_valid(mfn_x(mfn)) || direct_mmio || p2m_is_paged(p2mt) ||
+ (p2mt == p2m_ram_paging_in) )
+ {
+ int emt = epte_get_entry_emt(p2m->domain, gfn, mfn,
+ i * EPT_TABLE_ORDER, &ipat, direct_mmio);
+
+ if ( emt >= 0 )
+ new_entry.emt = emt;
+ else /* ept_handle_misconfig() will need to take care of this. */
+ new_entry.emt = MTRR_NUM_TYPES;
- new_entry.emt = epte_get_entry_emt(d, gfn, mfn, &ipat, direct_mmio);
new_entry.ipat = ipat;
- new_entry.sp = i ? 1 : 0;
+ new_entry.sp = !!i;
new_entry.sa_p2mt = p2mt;
new_entry.access = p2ma;
- new_entry.rsvd2_snp = (iommu_enabled && iommu_snoop);
+ new_entry.snp = (iommu_enabled && iommu_snoop);
/* the caller should take care of the previous page */
new_entry.mfn = mfn_x(mfn);
@@ -426,55 +752,38 @@ ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
need_modify_vtd_table = 0;
ept_p2m_type_to_flags(&new_entry, p2mt, p2ma);
-
- atomic_write_ept_entry(ept_entry, new_entry);
}
- /* Track the highest gfn for which we have ever had a valid mapping */
- if ( p2mt != p2m_invalid &&
- (gfn + (1UL << order) - 1 > p2m->max_mapped_pfn) )
+ rc = atomic_write_ept_entry(ept_entry, new_entry, target);
+ if ( unlikely(rc) )
+ old_entry.epte = 0;
+ else if ( p2mt != p2m_invalid &&
+ (gfn + (1UL << order) - 1 > p2m->max_mapped_pfn) )
+ /* Track the highest gfn for which we have ever had a valid mapping */
p2m->max_mapped_pfn = gfn + (1UL << order) - 1;
- /* Success */
- rv = 1;
-
out:
unmap_domain_page(table);
- if ( needs_sync )
+ if ( needs_sync != sync_off )
ept_sync_domain(p2m);
/* For non-nested p2m, may need to change VT-d page table.*/
- if ( rv && !p2m_is_nestedp2m(p2m) && iommu_enabled &&
- need_iommu(p2m->domain) && need_modify_vtd_table )
+ if ( rc == 0 && !p2m_is_nestedp2m(p2m) && need_iommu(d) &&
+ need_modify_vtd_table )
{
if ( iommu_hap_pt_share )
- iommu_pte_flush(d, gfn, (u64*)ept_entry, order, vtd_pte_present);
+ iommu_pte_flush(d, gfn, &ept_entry->epte, order, vtd_pte_present);
else
{
- if ( p2mt == p2m_ram_rw )
- {
- if ( order > 0 )
- {
- for ( i = 0; i < (1 << order); i++ )
- iommu_map_page(
- p2m->domain, gfn - offset + i, mfn_x(mfn) - offset + i,
- IOMMUF_readable | IOMMUF_writable);
- }
- else if ( !order )
- iommu_map_page(
- p2m->domain, gfn, mfn_x(mfn), IOMMUF_readable | IOMMUF_writable);
- }
+ unsigned int flags = p2m_get_iommu_flags(p2mt);
+
+ if ( flags != 0 )
+ for ( i = 0; i < (1 << order); i++ )
+ iommu_map_page(d, gfn + i, mfn_x(mfn) + i, flags);
else
- {
- if ( order > 0 )
- {
- for ( i = 0; i < (1 << order); i++ )
- iommu_unmap_page(p2m->domain, gfn - offset + i);
- }
- else if ( !order )
- iommu_unmap_page(p2m->domain, gfn);
- }
+ for ( i = 0; i < (1 << order); i++ )
+ iommu_unmap_page(d, gfn + i);
}
}
@@ -485,7 +794,7 @@ out:
if ( is_epte_present(&old_entry) )
ept_free_entry(p2m, &old_entry, target);
- return rv;
+ return rc;
}
/* Read ept p2m entries */
@@ -499,6 +808,7 @@ static mfn_t ept_get_entry(struct p2m_domain *p2m,
u32 index;
int i;
int ret = 0;
+ bool_t recalc = 0;
mfn_t mfn = _mfn(INVALID_MFN);
struct ept_data *ept = &p2m->ept;
@@ -514,6 +824,8 @@ static mfn_t ept_get_entry(struct p2m_domain *p2m,
for ( i = ept_get_wl(ept); i > 0; i-- )
{
retry:
+ if ( table[gfn_remainder >> (i * EPT_TABLE_ORDER)].recalc )
+ recalc = 1;
ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
if ( !ret )
goto out;
@@ -558,11 +870,14 @@ static mfn_t ept_get_entry(struct p2m_domain *p2m,
goto out;
}
- /* Need to check for all-zeroes because typecode 0 is p2m_ram and an
- * entirely empty entry shouldn't have RAM type. */
- if ( ept_entry->epte != 0 && ept_entry->sa_p2mt != p2m_invalid )
+ if ( is_epte_valid(ept_entry) )
{
- *t = ept_entry->sa_p2mt;
+ if ( (recalc || ept_entry->recalc) &&
+ p2m_is_changeable(ept_entry->sa_p2mt) )
+ *t = p2m_is_logdirty_range(p2m, gfn, gfn) ? p2m_ram_logdirty
+ : p2m_ram_rw;
+ else
+ *t = ept_entry->sa_p2mt;
*a = ept_entry->access;
mfn = _mfn(ept_entry->mfn);
@@ -638,53 +953,74 @@ out:
return;
}
-/*
- * Walk the whole p2m table, changing any entries of the old type
- * to the new type. This is used in hardware-assisted paging to
- * quickly enable or diable log-dirty tracking
- */
-static void ept_change_entry_type_page(mfn_t ept_page_mfn, int ept_page_level,
- p2m_type_t ot, p2m_type_t nt)
+static void ept_change_entry_type_global(struct p2m_domain *p2m,
+ p2m_type_t ot, p2m_type_t nt)
{
- ept_entry_t e, *epte = map_domain_page(mfn_x(ept_page_mfn));
+ unsigned long mfn = ept_get_asr(&p2m->ept);
- for ( int i = 0; i < EPT_PAGETABLE_ENTRIES; i++ )
+ if ( !mfn )
+ return;
+
+ if ( ept_invalidate_emt(_mfn(mfn), 1, ept_get_wl(&p2m->ept)) )
+ ept_sync_domain(p2m);
+}
+
+static int ept_change_entry_type_range(struct p2m_domain *p2m,
+ p2m_type_t ot, p2m_type_t nt,
+ unsigned long first_gfn,
+ unsigned long last_gfn)
+{
+ unsigned int i, wl = ept_get_wl(&p2m->ept);
+ unsigned long mask = (1 << EPT_TABLE_ORDER) - 1;
+ int rc = 0, sync = 0;
+
+ if ( !ept_get_asr(&p2m->ept) )
+ return -EINVAL;
+
+ for ( i = 0; i <= wl; )
{
- if ( !is_epte_valid(epte + i) )
- continue;
+ if ( first_gfn & mask )
+ {
+ unsigned long end_gfn = min(first_gfn | mask, last_gfn);
- if ( (ept_page_level > 0) && !is_epte_superpage(epte + i) )
- ept_change_entry_type_page(_mfn(epte[i].mfn),
- ept_page_level - 1, ot, nt);
- else
+ rc = ept_invalidate_emt_range(p2m, i, first_gfn, end_gfn);
+ sync |= rc;
+ if ( rc < 0 || end_gfn >= last_gfn )
+ break;
+ first_gfn = end_gfn + 1;
+ }
+ else if ( (last_gfn & mask) != mask )
{
- e = atomic_read_ept_entry(&epte[i]);
- if ( e.sa_p2mt != ot )
- continue;
+ unsigned long start_gfn = max(first_gfn, last_gfn & ~mask);
- e.sa_p2mt = nt;
- ept_p2m_type_to_flags(&e, nt, e.access);
- atomic_write_ept_entry(&epte[i], e);
+ rc = ept_invalidate_emt_range(p2m, i, start_gfn, last_gfn);
+ sync |= rc;
+ if ( rc < 0 || start_gfn <= first_gfn )
+ break;
+ last_gfn = start_gfn - 1;
+ }
+ else
+ {
+ ++i;
+ mask |= mask << EPT_TABLE_ORDER;
}
}
- unmap_domain_page(epte);
+ if ( sync )
+ ept_sync_domain(p2m);
+
+ return rc < 0 ? rc : 0;
}
-static void ept_change_entry_type_global(struct p2m_domain *p2m,
- p2m_type_t ot, p2m_type_t nt)
+static void ept_memory_type_changed(struct p2m_domain *p2m)
{
- struct ept_data *ept = &p2m->ept;
- if ( ept_get_asr(ept) == 0 )
- return;
+ unsigned long mfn = ept_get_asr(&p2m->ept);
- BUG_ON(p2m_is_grant(ot) || p2m_is_grant(nt));
- BUG_ON(ot != nt && (ot == p2m_mmio_direct || nt == p2m_mmio_direct));
-
- ept_change_entry_type_page(_mfn(ept_get_asr(ept)),
- ept_get_wl(ept), ot, nt);
+ if ( !mfn )
+ return;
- ept_sync_domain(p2m);
+ if ( ept_invalidate_emt(_mfn(mfn), 0, ept_get_wl(&p2m->ept)) )
+ ept_sync_domain(p2m);
}
static void __ept_sync_domain(void *info)
@@ -724,6 +1060,8 @@ int ept_p2m_init(struct p2m_domain *p2m)
p2m->set_entry = ept_set_entry;
p2m->get_entry = ept_get_entry;
p2m->change_entry_type_global = ept_change_entry_type_global;
+ p2m->change_entry_type_range = ept_change_entry_type_range;
+ p2m->memory_type_changed = ept_memory_type_changed;
p2m->audit_p2m = NULL;
/* Set the memory type used when accessing EPT paging structures. */
@@ -750,16 +1088,22 @@ static void ept_dump_p2m_table(unsigned char key)
{
struct domain *d;
ept_entry_t *table, *ept_entry;
- mfn_t mfn;
int order;
int i;
- int is_pod;
int ret = 0;
- unsigned long index;
unsigned long gfn, gfn_remainder;
unsigned long record_counter = 0;
struct p2m_domain *p2m;
struct ept_data *ept;
+ static const char memory_types[8][2] = {
+ [0 ... 7] = "?",
+ [MTRR_TYPE_UNCACHABLE] = "UC",
+ [MTRR_TYPE_WRCOMB] = "WC",
+ [MTRR_TYPE_WRTHROUGH] = "WT",
+ [MTRR_TYPE_WRPROT] = "WP",
+ [MTRR_TYPE_WRBACK] = "WB",
+ [MTRR_NUM_TYPES] = "??"
+ };
for_each_domain(d)
{
@@ -768,41 +1112,45 @@ static void ept_dump_p2m_table(unsigned char key)
p2m = p2m_get_hostp2m(d);
ept = &p2m->ept;
- printk("\ndomain%d EPT p2m table: \n", d->domain_id);
+ printk("\ndomain%d EPT p2m table:\n", d->domain_id);
- for ( gfn = 0; gfn <= p2m->max_mapped_pfn; gfn += (1 << order) )
+ for ( gfn = 0; gfn <= p2m->max_mapped_pfn; gfn += 1UL << order )
{
+ char c = 0;
+
gfn_remainder = gfn;
- mfn = _mfn(INVALID_MFN);
table = map_domain_page(pagetable_get_pfn(p2m_get_pagetable(p2m)));
for ( i = ept_get_wl(ept); i > 0; i-- )
{
+ ept_entry = table + (gfn_remainder >> (i * EPT_TABLE_ORDER));
+ if ( ept_entry->emt == MTRR_NUM_TYPES )
+ c = '?';
ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
if ( ret != GUEST_TABLE_NORMAL_PAGE )
break;
}
order = i * EPT_TABLE_ORDER;
-
- if ( ret == GUEST_TABLE_MAP_FAILED )
- goto out;
-
- index = gfn_remainder >> order;
- ept_entry = table + index;
- if ( ept_entry->sa_p2mt != p2m_invalid )
+ ept_entry = table + (gfn_remainder >> order);
+ if ( ret != GUEST_TABLE_MAP_FAILED && is_epte_valid(ept_entry) )
{
- ( ept_entry->sa_p2mt == p2m_populate_on_demand ) ?
- ( mfn = _mfn(INVALID_MFN), is_pod = 1 ) :
- ( mfn = _mfn(ept_entry->mfn), is_pod = 0 );
-
- printk("gfn: %-16lx mfn: %-16lx order: %2d is_pod: %d\n",
- gfn, mfn_x(mfn), order, is_pod);
+ if ( ept_entry->sa_p2mt == p2m_populate_on_demand )
+ printk("gfn: %13lx order: %2d PoD\n", gfn, order);
+ else
+ printk("gfn: %13lx order: %2d mfn: %13lx %c%c%c %c%c%c\n",
+ gfn, order, ept_entry->mfn + 0UL,
+ ept_entry->r ? 'r' : ' ',
+ ept_entry->w ? 'w' : ' ',
+ ept_entry->x ? 'x' : ' ',
+ memory_types[ept_entry->emt][0],
+ memory_types[ept_entry->emt][1]
+ ?: ept_entry->emt + '0',
+ c ?: ept_entry->ipat ? '!' : ' ');
if ( !(record_counter++ % 100) )
process_pending_softirqs();
}
-out:
unmap_domain_page(table);
}
}
diff --git a/xen/arch/x86/mm/p2m-pod.c b/xen/arch/x86/mm/p2m-pod.c
index d14565d..43f507c 100644
--- a/xen/arch/x86/mm/p2m-pod.c
+++ b/xen/arch/x86/mm/p2m-pod.c
@@ -20,16 +20,16 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <xen/iommu.h>
+#include <xen/mem_event.h>
+#include <xen/event.h>
+#include <public/mem_event.h>
#include <asm/domain.h>
#include <asm/page.h>
#include <asm/paging.h>
#include <asm/p2m.h>
#include <asm/hvm/vmx/vmx.h> /* ept_p2m_init() */
-#include <xen/iommu.h>
-#include <asm/mem_event.h>
-#include <public/mem_event.h>
#include <asm/mem_sharing.h>
-#include <xen/event.h>
#include <asm/hvm/nestedhvm.h>
#include <asm/hvm/svm/amd-iommu-proto.h>
@@ -245,7 +245,7 @@ p2m_pod_set_cache_target(struct p2m_domain *p2m, unsigned long pod_target, int p
if ( preemptible && pod_target != p2m->pod.count &&
hypercall_preempt_check() )
{
- ret = -EAGAIN;
+ ret = -ERESTART;
goto out;
}
}
@@ -290,7 +290,7 @@ p2m_pod_set_cache_target(struct p2m_domain *p2m, unsigned long pod_target, int p
if ( preemptible && pod_target != p2m->pod.count &&
hypercall_preempt_check() )
{
- ret = -EAGAIN;
+ ret = -ERESTART;
goto out;
}
}
@@ -556,7 +556,8 @@ recount:
{
/* All PoD: Mark the whole region invalid and tell caller
* we're done. */
- set_p2m_entry(p2m, gpfn, _mfn(INVALID_MFN), order, p2m_invalid, p2m->default_access);
+ p2m_set_entry(p2m, gpfn, _mfn(INVALID_MFN), order, p2m_invalid,
+ p2m->default_access);
p2m->pod.entry_count-=(1<<order);
BUG_ON(p2m->pod.entry_count < 0);
ret = 1;
@@ -589,7 +590,8 @@ recount:
mfn = p2m->get_entry(p2m, gpfn + i, &t, &a, 0, NULL);
if ( t == p2m_populate_on_demand )
{
- set_p2m_entry(p2m, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid, p2m->default_access);
+ p2m_set_entry(p2m, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid,
+ p2m->default_access);
p2m->pod.entry_count--;
BUG_ON(p2m->pod.entry_count < 0);
pod--;
@@ -602,7 +604,8 @@ recount:
page = mfn_to_page(mfn);
- set_p2m_entry(p2m, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid, p2m->default_access);
+ p2m_set_entry(p2m, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid,
+ p2m->default_access);
set_gpfn_from_mfn(mfn_x(mfn), INVALID_M2P_ENTRY);
p2m_pod_cache_add(p2m, page, 0);
@@ -721,7 +724,7 @@ p2m_pod_zero_check_superpage(struct p2m_domain *p2m, unsigned long gfn)
}
/* Try to remove the page, restoring old mapping if it fails. */
- set_p2m_entry(p2m, gfn, _mfn(0), PAGE_ORDER_2M,
+ p2m_set_entry(p2m, gfn, _mfn(0), PAGE_ORDER_2M,
p2m_populate_on_demand, p2m->default_access);
/* Make none of the MFNs are used elsewhere... for example, mapped
@@ -779,7 +782,7 @@ p2m_pod_zero_check_superpage(struct p2m_domain *p2m, unsigned long gfn)
out_reset:
if ( reset )
- set_p2m_entry(p2m, gfn, mfn0, 9, type0, p2m->default_access);
+ p2m_set_entry(p2m, gfn, mfn0, 9, type0, p2m->default_access);
out:
gfn_unlock(p2m, gfn, SUPERPAGE_ORDER);
@@ -837,7 +840,7 @@ p2m_pod_zero_check(struct p2m_domain *p2m, unsigned long *gfns, int count)
}
/* Try to remove the page, restoring old mapping if it fails. */
- set_p2m_entry(p2m, gfns[i], _mfn(0), PAGE_ORDER_4K,
+ p2m_set_entry(p2m, gfns[i], _mfn(0), PAGE_ORDER_4K,
p2m_populate_on_demand, p2m->default_access);
/* See if the page was successfully unmapped. (Allow one refcount
@@ -847,7 +850,7 @@ p2m_pod_zero_check(struct p2m_domain *p2m, unsigned long *gfns, int count)
unmap_domain_page(map[i]);
map[i] = NULL;
- set_p2m_entry(p2m, gfns[i], mfns[i], PAGE_ORDER_4K,
+ p2m_set_entry(p2m, gfns[i], mfns[i], PAGE_ORDER_4K,
types[i], p2m->default_access);
continue;
@@ -870,7 +873,7 @@ p2m_pod_zero_check(struct p2m_domain *p2m, unsigned long *gfns, int count)
* check timing. */
if ( j < PAGE_SIZE/sizeof(*map[i]) )
{
- set_p2m_entry(p2m, gfns[i], mfns[i], PAGE_ORDER_4K,
+ p2m_set_entry(p2m, gfns[i], mfns[i], PAGE_ORDER_4K,
types[i], p2m->default_access);
}
else
@@ -1000,15 +1003,15 @@ p2m_pod_demand_populate(struct p2m_domain *p2m, unsigned long gfn,
{
pod_unlock(p2m);
gfn_aligned = (gfn >> order) << order;
- /* Note that we are supposed to call set_p2m_entry() 512 times to
+ /* Note that we are supposed to call p2m_set_entry() 512 times to
* split 1GB into 512 2MB pages here. But We only do once here because
- * set_p2m_entry() should automatically shatter the 1GB page into
+ * p2m_set_entry() should automatically shatter the 1GB page into
* 512 2MB pages. The rest of 511 calls are unnecessary.
*
* NOTE: In a fine-grained p2m locking scenario this operation
* may need to promote its locking from gfn->1g superpage
*/
- set_p2m_entry(p2m, gfn_aligned, _mfn(0), PAGE_ORDER_2M,
+ p2m_set_entry(p2m, gfn_aligned, _mfn(0), PAGE_ORDER_2M,
p2m_populate_on_demand, p2m->default_access);
return 0;
}
@@ -1037,7 +1040,8 @@ p2m_pod_demand_populate(struct p2m_domain *p2m, unsigned long gfn,
gfn_aligned = (gfn >> order) << order;
- set_p2m_entry(p2m, gfn_aligned, mfn, order, p2m_ram_rw, p2m->default_access);
+ p2m_set_entry(p2m, gfn_aligned, mfn, order, p2m_ram_rw,
+ p2m->default_access);
for( i = 0; i < (1UL << order); i++ )
{
@@ -1091,7 +1095,7 @@ remap_and_retry:
* need promoting the gfn lock from gfn->2M superpage */
gfn_aligned = (gfn>>order)<<order;
for(i=0; i<(1<<order); i++)
- set_p2m_entry(p2m, gfn_aligned+i, _mfn(0), PAGE_ORDER_4K,
+ p2m_set_entry(p2m, gfn_aligned+i, _mfn(0), PAGE_ORDER_4K,
p2m_populate_on_demand, p2m->default_access);
if ( tb_init_done )
{
@@ -1146,10 +1150,9 @@ guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
}
/* Now, actually do the two-way mapping */
- if ( !set_p2m_entry(p2m, gfn, _mfn(0), order,
- p2m_populate_on_demand, p2m->default_access) )
- rc = -EINVAL;
- else
+ rc = p2m_set_entry(p2m, gfn, _mfn(0), order, p2m_populate_on_demand,
+ p2m->default_access);
+ if ( rc == 0 )
{
pod_lock(p2m);
p2m->pod.entry_count += 1 << order;
diff --git a/xen/arch/x86/mm/p2m-pt.c b/xen/arch/x86/mm/p2m-pt.c
index a1d5650..e48b63a 100644
--- a/xen/arch/x86/mm/p2m-pt.c
+++ b/xen/arch/x86/mm/p2m-pt.c
@@ -25,16 +25,16 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <xen/iommu.h>
+#include <xen/mem_event.h>
+#include <xen/event.h>
+#include <xen/trace.h>
+#include <public/mem_event.h>
#include <asm/domain.h>
#include <asm/page.h>
#include <asm/paging.h>
#include <asm/p2m.h>
-#include <xen/iommu.h>
-#include <asm/mem_event.h>
-#include <public/mem_event.h>
#include <asm/mem_sharing.h>
-#include <xen/event.h>
-#include <xen/trace.h>
#include <asm/hvm/nestedhvm.h>
#include <asm/hvm/svm/amd-iommu-proto.h>
@@ -60,6 +60,19 @@
#define P2M_BASE_FLAGS \
(_PAGE_PRESENT | _PAGE_USER | _PAGE_DIRTY | _PAGE_ACCESSED)
+#define RECALC_FLAGS (_PAGE_USER|_PAGE_ACCESSED)
+#define set_recalc(level, ent) level##e_remove_flags(ent, RECALC_FLAGS)
+#define clear_recalc(level, ent) level##e_add_flags(ent, RECALC_FLAGS)
+#define _needs_recalc(flags) (!((flags) & _PAGE_USER))
+#define needs_recalc(level, ent) _needs_recalc(level##e_get_flags(ent))
+#define valid_recalc(level, ent) (!(level##e_get_flags(ent) & _PAGE_ACCESSED))
+
+static const unsigned long pgt[] = {
+ PGT_l1_page_table,
+ PGT_l2_page_table,
+ PGT_l3_page_table
+};
+
static unsigned long p2m_type_to_flags(p2m_type_t t, mfn_t mfn)
{
unsigned long flags;
@@ -89,6 +102,7 @@ static unsigned long p2m_type_to_flags(p2m_type_t t, mfn_t mfn)
case p2m_ram_rw:
return flags | P2M_BASE_FLAGS | _PAGE_RW;
case p2m_grant_map_rw:
+ case p2m_map_foreign:
return flags | P2M_BASE_FLAGS | _PAGE_RW | _PAGE_NX_BIT;
case p2m_mmio_direct:
if ( !rangeset_contains_singleton(mmio_ro_ranges, mfn_x(mfn)) )
@@ -154,10 +168,11 @@ static void p2m_add_iommu_flags(l1_pgentry_t *p2m_entry,
l1e_add_flags(*p2m_entry, iommu_nlevel_to_flags(nlevel, flags));
}
+/* Returns: 0 for success, -errno for failure */
static int
-p2m_next_level(struct p2m_domain *p2m, mfn_t *table_mfn, void **table,
+p2m_next_level(struct p2m_domain *p2m, void **table,
unsigned long *gfn_remainder, unsigned long gfn, u32 shift,
- u32 max, unsigned long type)
+ u32 max, unsigned long type, bool_t unmap)
{
l1_pgentry_t *l1_entry;
l1_pgentry_t *p2m_entry;
@@ -167,7 +182,7 @@ p2m_next_level(struct p2m_domain *p2m, mfn_t *table_mfn, void **table,
if ( !(p2m_entry = p2m_find_entry(*table, gfn_remainder, gfn,
shift, max)) )
- return 0;
+ return -ENOENT;
/* PoD/paging: Not present doesn't imply empty. */
if ( !l1e_get_flags(*p2m_entry) )
@@ -176,23 +191,23 @@ p2m_next_level(struct p2m_domain *p2m, mfn_t *table_mfn, void **table,
pg = p2m_alloc_ptp(p2m, type);
if ( pg == NULL )
- return 0;
+ return -ENOMEM;
new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
- __PAGE_HYPERVISOR | _PAGE_USER);
+ P2M_BASE_FLAGS | _PAGE_RW);
switch ( type ) {
case PGT_l3_page_table:
p2m_add_iommu_flags(&new_entry, 3, IOMMUF_readable|IOMMUF_writable);
- p2m->write_p2m_entry(p2m, gfn, p2m_entry, *table_mfn, new_entry, 4);
+ p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, 4);
break;
case PGT_l2_page_table:
p2m_add_iommu_flags(&new_entry, 2, IOMMUF_readable|IOMMUF_writable);
- p2m->write_p2m_entry(p2m, gfn, p2m_entry, *table_mfn, new_entry, 3);
+ p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, 3);
break;
case PGT_l1_page_table:
p2m_add_iommu_flags(&new_entry, 1, IOMMUF_readable|IOMMUF_writable);
- p2m->write_p2m_entry(p2m, gfn, p2m_entry, *table_mfn, new_entry, 2);
+ p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, 2);
break;
default:
BUG();
@@ -210,24 +225,23 @@ p2m_next_level(struct p2m_domain *p2m, mfn_t *table_mfn, void **table,
pg = p2m_alloc_ptp(p2m, PGT_l2_page_table);
if ( pg == NULL )
- return 0;
+ return -ENOMEM;
flags = l1e_get_flags(*p2m_entry);
pfn = l1e_get_pfn(*p2m_entry);
- l1_entry = map_domain_page(mfn_x(page_to_mfn(pg)));
+ l1_entry = __map_domain_page(pg);
for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
{
new_entry = l1e_from_pfn(pfn + (i * L1_PAGETABLE_ENTRIES), flags);
p2m_add_iommu_flags(&new_entry, 1, IOMMUF_readable|IOMMUF_writable);
- p2m->write_p2m_entry(p2m, gfn,
- l1_entry+i, *table_mfn, new_entry, 2);
+ p2m->write_p2m_entry(p2m, gfn, l1_entry + i, new_entry, 2);
}
unmap_domain_page(l1_entry);
new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
- __PAGE_HYPERVISOR|_PAGE_USER); //disable PSE
+ P2M_BASE_FLAGS | _PAGE_RW); /* disable PSE */
p2m_add_iommu_flags(&new_entry, 2, IOMMUF_readable|IOMMUF_writable);
- p2m->write_p2m_entry(p2m, gfn, p2m_entry, *table_mfn, new_entry, 3);
+ p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, 3);
}
@@ -239,7 +253,7 @@ p2m_next_level(struct p2m_domain *p2m, mfn_t *table_mfn, void **table,
pg = p2m_alloc_ptp(p2m, PGT_l1_page_table);
if ( pg == NULL )
- return 0;
+ return -ENOMEM;
/* New splintered mappings inherit the flags of the old superpage,
* with a little reorganisation for the _PAGE_PSE_PAT bit. */
@@ -255,43 +269,229 @@ p2m_next_level(struct p2m_domain *p2m, mfn_t *table_mfn, void **table,
{
new_entry = l1e_from_pfn(pfn + i, flags);
p2m_add_iommu_flags(&new_entry, 0, 0);
- p2m->write_p2m_entry(p2m, gfn,
- l1_entry+i, *table_mfn, new_entry, 1);
+ p2m->write_p2m_entry(p2m, gfn, l1_entry + i, new_entry, 1);
}
unmap_domain_page(l1_entry);
new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
- __PAGE_HYPERVISOR|_PAGE_USER);
+ P2M_BASE_FLAGS | _PAGE_RW);
p2m_add_iommu_flags(&new_entry, 1, IOMMUF_readable|IOMMUF_writable);
- p2m->write_p2m_entry(p2m, gfn,
- p2m_entry, *table_mfn, new_entry, 2);
+ p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, 2);
}
- *table_mfn = _mfn(l1e_get_pfn(*p2m_entry));
- next = map_domain_page(mfn_x(*table_mfn));
- unmap_domain_page(*table);
+ next = map_domain_page(l1e_get_pfn(*p2m_entry));
+ if ( unmap )
+ unmap_domain_page(*table);
*table = next;
- return 1;
+ return 0;
+}
+
+/*
+ * Mark (via clearing the U flag) as needing P2M type re-calculation all valid
+ * present entries at the targeted level for the passed in GFN range, which is
+ * guaranteed to not cross a page (table) boundary at that level.
+ */
+static int p2m_pt_set_recalc_range(struct p2m_domain *p2m,
+ unsigned int level,
+ unsigned long first_gfn,
+ unsigned long last_gfn)
+{
+ void *table;
+ unsigned long gfn_remainder = first_gfn, remainder;
+ unsigned int i;
+ l1_pgentry_t *pent, *plast;
+ int err = 0;
+
+ table = map_domain_page(mfn_x(pagetable_get_mfn(p2m_get_pagetable(p2m))));
+ for ( i = 4; i-- > level; )
+ {
+ remainder = gfn_remainder;
+ pent = p2m_find_entry(table, &remainder, first_gfn,
+ i * PAGETABLE_ORDER, 1 << PAGETABLE_ORDER);
+ if ( !pent )
+ {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if ( !(l1e_get_flags(*pent) & _PAGE_PRESENT) )
+ goto out;
+
+ err = p2m_next_level(p2m, &table, &gfn_remainder, first_gfn,
+ i * PAGETABLE_ORDER, 1 << PAGETABLE_ORDER,
+ pgt[i - 1], 1);
+ if ( err )
+ goto out;
+ }
+
+ remainder = gfn_remainder + (last_gfn - first_gfn);
+ pent = p2m_find_entry(table, &gfn_remainder, first_gfn,
+ i * PAGETABLE_ORDER, 1 << PAGETABLE_ORDER);
+ plast = p2m_find_entry(table, &remainder, last_gfn,
+ i * PAGETABLE_ORDER, 1 << PAGETABLE_ORDER);
+ if ( pent && plast )
+ for ( ; pent <= plast; ++pent )
+ {
+ l1_pgentry_t e = *pent;
+
+ if ( (l1e_get_flags(e) & _PAGE_PRESENT) && !needs_recalc(l1, e) )
+ {
+ set_recalc(l1, e);
+ p2m->write_p2m_entry(p2m, first_gfn, pent, e, level);
+ }
+ first_gfn += 1UL << (i * PAGETABLE_ORDER);
+ }
+ else
+ err = -EIO;
+
+ out:
+ unmap_domain_page(table);
+
+ return err;
+}
+
+/*
+ * Handle possibly necessary P2M type re-calculation (U flag clear for a
+ * present entry) for the entries in the page table hierarchy for the given
+ * GFN. Propagate the re-calculation flag down to the next page table level
+ * for entries not involved in the translation of the given GFN.
+ */
+static int do_recalc(struct p2m_domain *p2m, unsigned long gfn)
+{
+ void *table;
+ unsigned long gfn_remainder = gfn;
+ unsigned int level = 4;
+ l1_pgentry_t *pent;
+ int err = 0;
+
+ table = map_domain_page(mfn_x(pagetable_get_mfn(p2m_get_pagetable(p2m))));
+ while ( --level )
+ {
+ unsigned long remainder = gfn_remainder;
+
+ pent = p2m_find_entry(table, &remainder, gfn,
+ level * PAGETABLE_ORDER, 1 << PAGETABLE_ORDER);
+ if ( !pent || !(l1e_get_flags(*pent) & _PAGE_PRESENT) )
+ goto out;
+
+ if ( l1e_get_flags(*pent) & _PAGE_PSE )
+ {
+ unsigned long mask = ~0UL << (level * PAGETABLE_ORDER);
+
+ if ( !needs_recalc(l1, *pent) ||
+ !p2m_is_changeable(p2m_flags_to_type(l1e_get_flags(*pent))) ||
+ p2m_is_logdirty_range(p2m, gfn & mask, gfn | ~mask) >= 0 )
+ break;
+ }
+
+ err = p2m_next_level(p2m, &table, &gfn_remainder, gfn,
+ level * PAGETABLE_ORDER, 1 << PAGETABLE_ORDER,
+ pgt[level - 1], 0);
+ if ( err )
+ goto out;
+
+ if ( needs_recalc(l1, *pent) )
+ {
+ l1_pgentry_t e = *pent, *ptab = table;
+ unsigned int i;
+
+ if ( !valid_recalc(l1, e) )
+ P2M_DEBUG("bogus recalc state at d%d:%lx:%u\n",
+ p2m->domain->domain_id, gfn, level);
+ remainder = gfn_remainder;
+ for ( i = 0; i < (1 << PAGETABLE_ORDER); ++i )
+ {
+ l1_pgentry_t ent = ptab[i];
+
+ if ( (l1e_get_flags(ent) & _PAGE_PRESENT) &&
+ !needs_recalc(l1, ent) )
+ {
+ set_recalc(l1, ent);
+ p2m->write_p2m_entry(p2m, gfn - remainder, &ptab[i],
+ ent, level);
+ }
+ remainder -= 1UL << ((level - 1) * PAGETABLE_ORDER);
+ }
+ smp_wmb();
+ clear_recalc(l1, e);
+ p2m->write_p2m_entry(p2m, gfn, pent, e, level + 1);
+ }
+ unmap_domain_page((void *)((unsigned long)pent & PAGE_MASK));
+ }
+
+ pent = p2m_find_entry(table, &gfn_remainder, gfn,
+ level * PAGETABLE_ORDER, 1 << PAGETABLE_ORDER);
+ if ( pent && (l1e_get_flags(*pent) & _PAGE_PRESENT) &&
+ needs_recalc(l1, *pent) )
+ {
+ l1_pgentry_t e = *pent;
+
+ if ( !valid_recalc(l1, e) )
+ P2M_DEBUG("bogus recalc leaf at d%d:%lx:%u\n",
+ p2m->domain->domain_id, gfn, level);
+ if ( p2m_is_changeable(p2m_flags_to_type(l1e_get_flags(e))) )
+ {
+ unsigned long mask = ~0UL << (level * PAGETABLE_ORDER);
+ p2m_type_t p2mt = p2m_is_logdirty_range(p2m, gfn & mask, gfn | ~mask)
+ ? p2m_ram_logdirty : p2m_ram_rw;
+ unsigned long mfn = l1e_get_pfn(e);
+ unsigned long flags = p2m_type_to_flags(p2mt, _mfn(mfn));
+
+ if ( level )
+ {
+ if ( flags & _PAGE_PAT )
+ {
+ BUILD_BUG_ON(_PAGE_PAT != _PAGE_PSE);
+ mfn |= _PAGE_PSE_PAT >> PAGE_SHIFT;
+ }
+ else
+ mfn &= ~(_PAGE_PSE_PAT >> PAGE_SHIFT);
+ flags |= _PAGE_PSE;
+ }
+ e = l1e_from_pfn(mfn, flags);
+ p2m_add_iommu_flags(&e, level,
+ (p2mt == p2m_ram_rw)
+ ? IOMMUF_readable|IOMMUF_writable : 0);
+ ASSERT(!needs_recalc(l1, e));
+ }
+ else
+ clear_recalc(l1, e);
+ p2m->write_p2m_entry(p2m, gfn, pent, e, level + 1);
+ }
+
+ out:
+ unmap_domain_page(table);
+
+ return err;
}
-// Returns 0 on error (out of memory)
+int p2m_pt_handle_deferred_changes(uint64_t gpa)
+{
+ struct p2m_domain *p2m = p2m_get_hostp2m(current->domain);
+ int rc;
+
+ p2m_lock(p2m);
+ rc = do_recalc(p2m, PFN_DOWN(gpa));
+ p2m_unlock(p2m);
+
+ return rc;
+}
+
+/* Returns: 0 for success, -errno for failure */
static int
-p2m_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
- unsigned int page_order, p2m_type_t p2mt, p2m_access_t p2ma)
+p2m_pt_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
+ unsigned int page_order, p2m_type_t p2mt, p2m_access_t p2ma)
{
- // XXX -- this might be able to be faster iff current->domain == d
- mfn_t table_mfn = pagetable_get_mfn(p2m_get_pagetable(p2m));
- void *table =map_domain_page(mfn_x(table_mfn));
+ /* XXX -- this might be able to be faster iff current->domain == d */
+ void *table;
unsigned long i, gfn_remainder = gfn;
l1_pgentry_t *p2m_entry;
l1_pgentry_t entry_content;
l2_pgentry_t l2e_content;
l3_pgentry_t l3e_content;
- int rv=0;
- unsigned int iommu_pte_flags = (p2mt == p2m_ram_rw) ?
- IOMMUF_readable|IOMMUF_writable:
- 0;
+ int rc;
+ unsigned int iommu_pte_flags = p2m_get_iommu_flags(p2mt);
unsigned long old_mfn = 0;
if ( tb_init_done )
@@ -311,9 +511,23 @@ p2m_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
__trace_var(TRC_MEM_SET_P2M_ENTRY, 0, sizeof(t), &t);
}
- if ( !p2m_next_level(p2m, &table_mfn, &table, &gfn_remainder, gfn,
- L4_PAGETABLE_SHIFT - PAGE_SHIFT,
- L4_PAGETABLE_ENTRIES, PGT_l3_page_table) )
+ if ( unlikely(p2m_is_foreign(p2mt)) )
+ {
+ /* pvh fixme: foreign types are only supported on ept at present */
+ gdprintk(XENLOG_WARNING, "Unimplemented foreign p2m type.\n");
+ return -EINVAL;
+ }
+
+ /* Carry out any eventually pending earlier changes first. */
+ rc = do_recalc(p2m, gfn);
+ if ( rc < 0 )
+ return rc;
+
+ table = map_domain_page(mfn_x(pagetable_get_mfn(p2m_get_pagetable(p2m))));
+ rc = p2m_next_level(p2m, &table, &gfn_remainder, gfn,
+ L4_PAGETABLE_SHIFT - PAGE_SHIFT,
+ L4_PAGETABLE_ENTRIES, PGT_l3_page_table, 1);
+ if ( rc )
goto out;
/*
@@ -347,24 +561,28 @@ p2m_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
old_mfn = l1e_get_pfn(*p2m_entry);
}
- p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 3);
+ p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 3);
/* NB: paging_write_p2m_entry() handles tlb flushes properly */
/* Free old intermediate tables if necessary */
if ( l1e_get_flags(old_entry) & _PAGE_PRESENT )
p2m_free_entry(p2m, &old_entry, page_order);
}
- else if ( !p2m_next_level(p2m, &table_mfn, &table, &gfn_remainder, gfn,
- L3_PAGETABLE_SHIFT - PAGE_SHIFT,
- L3_PAGETABLE_ENTRIES,
- PGT_l2_page_table) )
- goto out;
+ else
+ {
+ rc = p2m_next_level(p2m, &table, &gfn_remainder, gfn,
+ L3_PAGETABLE_SHIFT - PAGE_SHIFT,
+ L3_PAGETABLE_ENTRIES, PGT_l2_page_table, 1);
+ if ( rc )
+ goto out;
+ }
if ( page_order == PAGE_ORDER_4K )
{
- if ( !p2m_next_level(p2m, &table_mfn, &table, &gfn_remainder, gfn,
- L2_PAGETABLE_SHIFT - PAGE_SHIFT,
- L2_PAGETABLE_ENTRIES, PGT_l1_page_table) )
+ rc = p2m_next_level(p2m, &table, &gfn_remainder, gfn,
+ L2_PAGETABLE_SHIFT - PAGE_SHIFT,
+ L2_PAGETABLE_ENTRIES, PGT_l1_page_table, 1);
+ if ( rc )
goto out;
p2m_entry = p2m_find_entry(table, &gfn_remainder, gfn,
@@ -384,7 +602,7 @@ p2m_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
old_mfn = l1e_get_pfn(*p2m_entry);
}
/* level 1 entry */
- p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 1);
+ p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 1);
/* NB: paging_write_p2m_entry() handles tlb flushes properly */
}
else if ( page_order == PAGE_ORDER_2M )
@@ -420,7 +638,7 @@ p2m_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
old_mfn = l1e_get_pfn(*p2m_entry);
}
- p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 2);
+ p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 2);
/* NB: paging_write_p2m_entry() handles tlb flushes properly */
/* Free old intermediate tables if necessary */
@@ -442,35 +660,43 @@ p2m_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
}
else
{
- if ( p2mt == p2m_ram_rw )
+ unsigned int flags = p2m_get_iommu_flags(p2mt);
+
+ if ( flags != 0 )
for ( i = 0; i < (1UL << page_order); i++ )
- iommu_map_page(p2m->domain, gfn+i, mfn_x(mfn)+i,
- IOMMUF_readable|IOMMUF_writable);
+ iommu_map_page(p2m->domain, gfn+i, mfn_x(mfn)+i, flags);
else
for ( int i = 0; i < (1UL << page_order); i++ )
iommu_unmap_page(p2m->domain, gfn+i);
}
}
- /* Success */
- rv = 1;
-
-out:
+ out:
unmap_domain_page(table);
- return rv;
+ return rc;
+}
+
+static inline p2m_type_t recalc_type(bool_t recalc, p2m_type_t t,
+ struct p2m_domain *p2m, unsigned long gfn)
+{
+ if ( !recalc || !p2m_is_changeable(t) )
+ return t;
+ return p2m_is_logdirty_range(p2m, gfn, gfn) ? p2m_ram_logdirty
+ : p2m_ram_rw;
}
static mfn_t
-p2m_gfn_to_mfn(struct p2m_domain *p2m, unsigned long gfn,
- p2m_type_t *t, p2m_access_t *a, p2m_query_t q,
- unsigned int *page_order)
+p2m_pt_get_entry(struct p2m_domain *p2m, unsigned long gfn,
+ p2m_type_t *t, p2m_access_t *a, p2m_query_t q,
+ unsigned int *page_order)
{
mfn_t mfn;
paddr_t addr = ((paddr_t)gfn) << PAGE_SHIFT;
l2_pgentry_t *l2e;
l1_pgentry_t *l1e;
- unsigned long l1e_flags;
+ unsigned int flags;
p2m_type_t l1t;
+ bool_t recalc;
ASSERT(paging_mode_translate(p2m->domain));
@@ -497,15 +723,17 @@ p2m_gfn_to_mfn(struct p2m_domain *p2m, unsigned long gfn,
return _mfn(INVALID_MFN);
}
mfn = _mfn(l4e_get_pfn(*l4e));
+ recalc = needs_recalc(l4, *l4e);
unmap_domain_page(l4e);
}
{
l3_pgentry_t *l3e = map_domain_page(mfn_x(mfn));
l3e += l3_table_offset(addr);
pod_retry_l3:
- if ( (l3e_get_flags(*l3e) & _PAGE_PRESENT) == 0 )
+ flags = l3e_get_flags(*l3e);
+ if ( !(flags & _PAGE_PRESENT) )
{
- if ( p2m_flags_to_type(l3e_get_flags(*l3e)) == p2m_populate_on_demand )
+ if ( p2m_flags_to_type(flags) == p2m_populate_on_demand )
{
if ( q & P2M_ALLOC )
{
@@ -519,12 +747,13 @@ pod_retry_l3:
unmap_domain_page(l3e);
return _mfn(INVALID_MFN);
}
- else if ( (l3e_get_flags(*l3e) & _PAGE_PSE) )
+ if ( flags & _PAGE_PSE )
{
mfn = _mfn(l3e_get_pfn(*l3e) +
l2_table_offset(addr) * L1_PAGETABLE_ENTRIES +
l1_table_offset(addr));
- *t = p2m_flags_to_type(l3e_get_flags(*l3e));
+ *t = recalc_type(recalc || _needs_recalc(flags),
+ p2m_flags_to_type(flags), p2m, gfn);
unmap_domain_page(l3e);
ASSERT(mfn_valid(mfn) || !p2m_is_ram(*t));
@@ -534,6 +763,8 @@ pod_retry_l3:
}
mfn = _mfn(l3e_get_pfn(*l3e));
+ if ( _needs_recalc(flags) )
+ recalc = 1;
unmap_domain_page(l3e);
}
@@ -541,10 +772,11 @@ pod_retry_l3:
l2e += l2_table_offset(addr);
pod_retry_l2:
- if ( (l2e_get_flags(*l2e) & _PAGE_PRESENT) == 0 )
+ flags = l2e_get_flags(*l2e);
+ if ( !(flags & _PAGE_PRESENT) )
{
/* PoD: Try to populate a 2-meg chunk */
- if ( p2m_flags_to_type(l2e_get_flags(*l2e)) == p2m_populate_on_demand )
+ if ( p2m_flags_to_type(flags) == p2m_populate_on_demand )
{
if ( q & P2M_ALLOC ) {
if ( !p2m_pod_demand_populate(p2m, gfn, PAGE_ORDER_2M, q) )
@@ -556,10 +788,11 @@ pod_retry_l2:
unmap_domain_page(l2e);
return _mfn(INVALID_MFN);
}
- else if ( (l2e_get_flags(*l2e) & _PAGE_PSE) )
+ if ( flags & _PAGE_PSE )
{
mfn = _mfn(l2e_get_pfn(*l2e) + l1_table_offset(addr));
- *t = p2m_flags_to_type(l2e_get_flags(*l2e));
+ *t = recalc_type(recalc || _needs_recalc(flags),
+ p2m_flags_to_type(flags), p2m, gfn);
unmap_domain_page(l2e);
ASSERT(mfn_valid(mfn) || !p2m_is_ram(*t));
@@ -569,14 +802,16 @@ pod_retry_l2:
}
mfn = _mfn(l2e_get_pfn(*l2e));
+ if ( needs_recalc(l2, *l2e) )
+ recalc = 1;
unmap_domain_page(l2e);
l1e = map_domain_page(mfn_x(mfn));
l1e += l1_table_offset(addr);
pod_retry_l1:
- l1e_flags = l1e_get_flags(*l1e);
- l1t = p2m_flags_to_type(l1e_flags);
- if ( ((l1e_flags & _PAGE_PRESENT) == 0) && (!p2m_is_paging(l1t)) )
+ flags = l1e_get_flags(*l1e);
+ l1t = p2m_flags_to_type(flags);
+ if ( !(flags & _PAGE_PRESENT) && !p2m_is_paging(l1t) )
{
/* PoD: Try to populate */
if ( l1t == p2m_populate_on_demand )
@@ -592,7 +827,7 @@ pod_retry_l1:
return _mfn(INVALID_MFN);
}
mfn = _mfn(l1e_get_pfn(*l1e));
- *t = l1t;
+ *t = recalc_type(recalc || _needs_recalc(flags), l1t, p2m, gfn);
unmap_domain_page(l1e);
ASSERT(mfn_valid(mfn) || !p2m_is_ram(*t) || p2m_is_paging(*t));
@@ -601,118 +836,77 @@ pod_retry_l1:
return (p2m_is_valid(*t) || p2m_is_grant(*t)) ? mfn : _mfn(INVALID_MFN);
}
-/* Walk the whole p2m table, changing any entries of the old type
- * to the new type. This is used in hardware-assisted paging to
- * quickly enable or diable log-dirty tracking */
-static void p2m_change_type_global(struct p2m_domain *p2m,
- p2m_type_t ot, p2m_type_t nt)
+static void p2m_pt_change_entry_type_global(struct p2m_domain *p2m,
+ p2m_type_t ot, p2m_type_t nt)
{
- unsigned long mfn, gfn, flags;
- l1_pgentry_t l1e_content;
- l1_pgentry_t *l1e;
- l2_pgentry_t *l2e;
- mfn_t l1mfn, l2mfn, l3mfn;
- unsigned long i1, i2, i3;
- l3_pgentry_t *l3e;
- l4_pgentry_t *l4e;
- unsigned long i4;
-
- BUG_ON(p2m_is_grant(ot) || p2m_is_grant(nt));
- BUG_ON(ot != nt && (ot == p2m_mmio_direct || nt == p2m_mmio_direct));
-
- if ( !paging_mode_translate(p2m->domain) )
- return;
+ l1_pgentry_t *tab;
+ unsigned long gfn = 0;
+ unsigned int i, changed;
if ( pagetable_get_pfn(p2m_get_pagetable(p2m)) == 0 )
return;
- ASSERT(p2m_locked_by_me(p2m));
-
- l4e = map_domain_page(mfn_x(pagetable_get_mfn(p2m_get_pagetable(p2m))));
+ ASSERT(hap_enabled(p2m->domain));
- for ( i4 = 0; i4 < L4_PAGETABLE_ENTRIES; i4++ )
+ tab = map_domain_page(mfn_x(pagetable_get_mfn(p2m_get_pagetable(p2m))));
+ for ( changed = i = 0; i < (1 << PAGETABLE_ORDER); ++i )
{
- if ( !(l4e_get_flags(l4e[i4]) & _PAGE_PRESENT) )
+ l1_pgentry_t e = tab[i];
+
+ if ( (l1e_get_flags(e) & _PAGE_PRESENT) &&
+ !needs_recalc(l1, e) )
{
- continue;
+ set_recalc(l1, e);
+ p2m->write_p2m_entry(p2m, gfn, &tab[i], e, 4);
+ ++changed;
}
- l3mfn = _mfn(l4e_get_pfn(l4e[i4]));
- l3e = map_domain_page(l4e_get_pfn(l4e[i4]));
- for ( i3 = 0;
- i3 < L3_PAGETABLE_ENTRIES;
- i3++ )
- {
- if ( !(l3e_get_flags(l3e[i3]) & _PAGE_PRESENT) )
- {
- continue;
- }
- if ( (l3e_get_flags(l3e[i3]) & _PAGE_PSE) )
- {
- flags = l3e_get_flags(l3e[i3]);
- if ( p2m_flags_to_type(flags) != ot )
- continue;
- mfn = l3e_get_pfn(l3e[i3]);
- gfn = get_gpfn_from_mfn(mfn);
- flags = p2m_type_to_flags(nt, _mfn(mfn));
- l1e_content = l1e_from_pfn(mfn, flags | _PAGE_PSE);
- p2m->write_p2m_entry(p2m, gfn,
- (l1_pgentry_t *)&l3e[i3],
- l3mfn, l1e_content, 3);
- continue;
- }
+ gfn += 1UL << (L4_PAGETABLE_SHIFT - PAGE_SHIFT);
+ }
+ unmap_domain_page(tab);
- l2mfn = _mfn(l3e_get_pfn(l3e[i3]));
- l2e = map_domain_page(l3e_get_pfn(l3e[i3]));
- for ( i2 = 0; i2 < L2_PAGETABLE_ENTRIES; i2++ )
- {
- if ( !(l2e_get_flags(l2e[i2]) & _PAGE_PRESENT) )
- {
- continue;
- }
+ if ( changed )
+ flush_tlb_mask(p2m->domain->domain_dirty_cpumask);
+}
- if ( (l2e_get_flags(l2e[i2]) & _PAGE_PSE) )
- {
- flags = l2e_get_flags(l2e[i2]);
- if ( p2m_flags_to_type(flags) != ot )
- continue;
- mfn = l2e_get_pfn(l2e[i2]);
- /* Do not use get_gpfn_from_mfn because it may return
- SHARED_M2P_ENTRY */
- gfn = (i2 + (i3 + (i4 * L3_PAGETABLE_ENTRIES))
- * L2_PAGETABLE_ENTRIES) * L1_PAGETABLE_ENTRIES;
- flags = p2m_type_to_flags(nt, _mfn(mfn));
- l1e_content = l1e_from_pfn(mfn, flags | _PAGE_PSE);
- p2m->write_p2m_entry(p2m, gfn,
- (l1_pgentry_t *)&l2e[i2],
- l2mfn, l1e_content, 2);
- continue;
- }
+static int p2m_pt_change_entry_type_range(struct p2m_domain *p2m,
+ p2m_type_t ot, p2m_type_t nt,
+ unsigned long first_gfn,
+ unsigned long last_gfn)
+{
+ unsigned long mask = (1 << PAGETABLE_ORDER) - 1;
+ unsigned int i;
+ int err = 0;
- l1mfn = _mfn(l2e_get_pfn(l2e[i2]));
- l1e = map_domain_page(mfn_x(l1mfn));
+ ASSERT(hap_enabled(p2m->domain));
- for ( i1 = 0; i1 < L1_PAGETABLE_ENTRIES; i1++ )
- {
- flags = l1e_get_flags(l1e[i1]);
- if ( p2m_flags_to_type(flags) != ot )
- continue;
- mfn = l1e_get_pfn(l1e[i1]);
- gfn = i1 + (i2 + (i3 + (i4 * L3_PAGETABLE_ENTRIES))
- * L2_PAGETABLE_ENTRIES) * L1_PAGETABLE_ENTRIES;
- /* create a new 1le entry with the new type */
- flags = p2m_type_to_flags(nt, _mfn(mfn));
- l1e_content = p2m_l1e_from_pfn(mfn, flags);
- p2m->write_p2m_entry(p2m, gfn, &l1e[i1],
- l1mfn, l1e_content, 1);
- }
- unmap_domain_page(l1e);
- }
- unmap_domain_page(l2e);
+ for ( i = 1; i <= 4; )
+ {
+ if ( first_gfn & mask )
+ {
+ unsigned long end_gfn = min(first_gfn | mask, last_gfn);
+
+ err = p2m_pt_set_recalc_range(p2m, i, first_gfn, end_gfn);
+ if ( err || end_gfn >= last_gfn )
+ break;
+ first_gfn = end_gfn + 1;
+ }
+ else if ( (last_gfn & mask) != mask )
+ {
+ unsigned long start_gfn = max(first_gfn, last_gfn & ~mask);
+
+ err = p2m_pt_set_recalc_range(p2m, i, start_gfn, last_gfn);
+ if ( err || start_gfn <= first_gfn )
+ break;
+ last_gfn = start_gfn - 1;
+ }
+ else
+ {
+ ++i;
+ mask |= mask << PAGETABLE_ORDER;
}
- unmap_domain_page(l3e);
}
- unmap_domain_page(l4e);
+ return err;
}
#if P2M_AUDIT
@@ -744,7 +938,7 @@ long p2m_pt_audit_p2m(struct p2m_domain *p2m)
gfn += 1 << (L4_PAGETABLE_SHIFT - PAGE_SHIFT);
continue;
}
- l3e = map_domain_page(mfn_x(_mfn(l4e_get_pfn(l4e[i4]))));
+ l3e = map_domain_page(l4e_get_pfn(l4e[i4]));
for ( i3 = 0;
i3 < L3_PAGETABLE_ENTRIES;
i3++ )
@@ -779,7 +973,7 @@ long p2m_pt_audit_p2m(struct p2m_domain *p2m)
}
}
- l2e = map_domain_page(mfn_x(_mfn(l3e_get_pfn(l3e[i3]))));
+ l2e = map_domain_page(l3e_get_pfn(l3e[i3]));
for ( i2 = 0; i2 < L2_PAGETABLE_ENTRIES; i2++ )
{
if ( !(l2e_get_flags(l2e[i2]) & _PAGE_PRESENT) )
@@ -815,7 +1009,7 @@ long p2m_pt_audit_p2m(struct p2m_domain *p2m)
continue;
}
- l1e = map_domain_page(mfn_x(_mfn(l2e_get_pfn(l2e[i2]))));
+ l1e = map_domain_page(l2e_get_pfn(l2e[i2]));
for ( i1 = 0; i1 < L1_PAGETABLE_ENTRIES; i1++, gfn++ )
{
@@ -870,9 +1064,10 @@ long p2m_pt_audit_p2m(struct p2m_domain *p2m)
/* Set up the p2m function pointers for pagetable format */
void p2m_pt_init(struct p2m_domain *p2m)
{
- p2m->set_entry = p2m_set_entry;
- p2m->get_entry = p2m_gfn_to_mfn;
- p2m->change_entry_type_global = p2m_change_type_global;
+ p2m->set_entry = p2m_pt_set_entry;
+ p2m->get_entry = p2m_pt_get_entry;
+ p2m->change_entry_type_global = p2m_pt_change_entry_type_global;
+ p2m->change_entry_type_range = p2m_pt_change_entry_type_range;
p2m->write_p2m_entry = paging_write_p2m_entry;
#if P2M_AUDIT
p2m->audit_p2m = p2m_pt_audit_p2m;
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index 246ddd7..efa49dd 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -24,18 +24,19 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <xen/iommu.h>
+#include <xen/mem_event.h>
+#include <xen/event.h>
+#include <public/mem_event.h>
#include <asm/domain.h>
#include <asm/page.h>
#include <asm/paging.h>
#include <asm/p2m.h>
#include <asm/hvm/vmx/vmx.h> /* ept_p2m_init() */
-#include <xen/iommu.h>
-#include <asm/mem_event.h>
-#include <public/mem_event.h>
#include <asm/mem_sharing.h>
-#include <xen/event.h>
#include <asm/hvm/nestedhvm.h>
#include <asm/hvm/svm/amd-iommu-proto.h>
+#include <xsm/xsm.h>
#include "mm-locks.h"
@@ -116,8 +117,14 @@ static int p2m_init_hostp2m(struct domain *d)
if ( p2m )
{
- d->arch.p2m = p2m;
- return 0;
+ p2m->logdirty_ranges = rangeset_new(d, "log-dirty",
+ RANGESETF_prettyprint_hex);
+ if ( p2m->logdirty_ranges )
+ {
+ d->arch.p2m = p2m;
+ return 0;
+ }
+ p2m_free_one(p2m);
}
return -ENOMEM;
}
@@ -129,6 +136,7 @@ static void p2m_teardown_hostp2m(struct domain *d)
if ( p2m )
{
+ rangeset_destroy(p2m->logdirty_ranges);
p2m_free_one(p2m);
d->arch.p2m = NULL;
}
@@ -191,15 +199,44 @@ int p2m_init(struct domain *d)
return rc;
}
+int p2m_is_logdirty_range(struct p2m_domain *p2m, unsigned long start,
+ unsigned long end)
+{
+ ASSERT(!p2m_is_nestedp2m(p2m));
+ if ( p2m->global_logdirty ||
+ rangeset_contains_range(p2m->logdirty_ranges, start, end) )
+ return 1;
+ if ( rangeset_overlaps_range(p2m->logdirty_ranges, start, end) )
+ return -1;
+ return 0;
+}
+
void p2m_change_entry_type_global(struct domain *d,
p2m_type_t ot, p2m_type_t nt)
{
struct p2m_domain *p2m = p2m_get_hostp2m(d);
+
+ ASSERT(ot != nt);
+ ASSERT(p2m_is_changeable(ot) && p2m_is_changeable(nt));
+
p2m_lock(p2m);
p2m->change_entry_type_global(p2m, ot, nt);
+ p2m->global_logdirty = (nt == p2m_ram_logdirty);
p2m_unlock(p2m);
}
+void p2m_memory_type_changed(struct domain *d)
+{
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
+
+ if ( p2m->memory_type_changed )
+ {
+ p2m_lock(p2m);
+ p2m->memory_type_changed(p2m);
+ p2m_unlock(p2m);
+ }
+}
+
mfn_t __get_gfn_type_access(struct p2m_domain *p2m, unsigned long gfn,
p2m_type_t *t, p2m_access_t *a, p2m_query_t q,
unsigned int *page_order, bool_t locked)
@@ -275,14 +312,20 @@ struct page_info *get_page_from_gfn_p2m(
/* Fast path: look up and get out */
p2m_read_lock(p2m);
mfn = __get_gfn_type_access(p2m, gfn, t, a, 0, NULL, 0);
- if ( (p2m_is_ram(*t) || p2m_is_grant(*t))
- && mfn_valid(mfn)
+ if ( p2m_is_any_ram(*t) && mfn_valid(mfn)
&& !((q & P2M_UNSHARE) && p2m_is_shared(*t)) )
{
page = mfn_to_page(mfn);
- if ( !get_page(page, d)
- /* Page could be shared */
- && !get_page(page, dom_cow) )
+ if ( unlikely(p2m_is_foreign(*t)) )
+ {
+ struct domain *fdom = page_get_owner_and_reference(page);
+ ASSERT(fdom != d);
+ if ( fdom == NULL )
+ page = NULL;
+ }
+ else if ( !get_page(page, d)
+ /* Page could be shared */
+ && !get_page(page, dom_cow) )
page = NULL;
}
p2m_read_unlock(p2m);
@@ -308,14 +351,14 @@ struct page_info *get_page_from_gfn_p2m(
return page;
}
-
-int set_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
+/* Returns: 0 for success, -errno for failure */
+int p2m_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
unsigned int page_order, p2m_type_t p2mt, p2m_access_t p2ma)
{
struct domain *d = p2m->domain;
unsigned long todo = 1ul << page_order;
unsigned int order;
- int rc = 1;
+ int set_rc, rc = 0;
ASSERT(gfn_locked_by_me(p2m, gfn));
@@ -329,8 +372,10 @@ int set_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
else
order = 0;
- if ( !p2m->set_entry(p2m, gfn, mfn, order, p2mt, p2ma) )
- rc = 0;
+ set_rc = p2m->set_entry(p2m, gfn, mfn, order, p2mt, p2ma);
+ if ( set_rc )
+ rc = set_rc;
+
gfn += 1ul << order;
if ( mfn_x(mfn) != INVALID_MFN )
mfn = _mfn(mfn_x(mfn) + (1ul << order));
@@ -370,23 +415,30 @@ void p2m_free_ptp(struct p2m_domain *p2m, struct page_info *pg)
return;
}
-// Allocate a new p2m table for a domain.
-//
-// The structure of the p2m table is that of a pagetable for xen (i.e. it is
-// controlled by CONFIG_PAGING_LEVELS).
-//
-// Returns 0 for success or -errno.
-//
+/*
+ * Allocate a new p2m table for a domain.
+ *
+ * The structure of the p2m table is that of a pagetable for xen (i.e. it is
+ * controlled by CONFIG_PAGING_LEVELS).
+ *
+ * Returns 0 for success, -errno for failure.
+ */
int p2m_alloc_table(struct p2m_domain *p2m)
{
- mfn_t mfn = _mfn(INVALID_MFN);
- struct page_info *page, *p2m_top;
- unsigned int page_count = 0;
- unsigned long gfn = -1UL;
+ struct page_info *p2m_top;
struct domain *d = p2m->domain;
+ int rc = 0;
p2m_lock(p2m);
+ if ( !p2m_is_nestedp2m(p2m)
+ && !page_list_empty(&d->page_list) )
+ {
+ P2M_ERROR("dom %d already has memory allocated\n", d->domain_id);
+ p2m_unlock(p2m);
+ return -EINVAL;
+ }
+
if ( pagetable_get_pfn(p2m_get_pagetable(p2m)) != 0 )
{
P2M_ERROR("p2m already allocated for this domain\n");
@@ -412,51 +464,27 @@ int p2m_alloc_table(struct p2m_domain *p2m)
/* Initialise physmap tables for slot zero. Other code assumes this. */
p2m->defer_nested_flush = 1;
- if ( !set_p2m_entry(p2m, 0, _mfn(INVALID_MFN), PAGE_ORDER_4K,
- p2m_invalid, p2m->default_access) )
- goto error;
-
- if ( !p2m_is_nestedp2m(p2m) )
- {
- /* Copy all existing mappings from the page list and m2p */
- spin_lock(&p2m->domain->page_alloc_lock);
- page_list_for_each(page, &p2m->domain->page_list)
- {
- mfn = page_to_mfn(page);
- gfn = get_gpfn_from_mfn(mfn_x(mfn));
- /* Pages should not be shared that early */
- ASSERT(gfn != SHARED_M2P_ENTRY);
- page_count++;
- if ( gfn != INVALID_M2P_ENTRY
- && !set_p2m_entry(p2m, gfn, mfn, PAGE_ORDER_4K, p2m_ram_rw, p2m->default_access) )
- goto error_unlock;
- }
- spin_unlock(&p2m->domain->page_alloc_lock);
- }
+ rc = p2m_set_entry(p2m, 0, _mfn(INVALID_MFN), PAGE_ORDER_4K,
+ p2m_invalid, p2m->default_access);
p2m->defer_nested_flush = 0;
-
- P2M_PRINTK("p2m table initialised (%u pages)\n", page_count);
p2m_unlock(p2m);
- return 0;
-
-error_unlock:
- spin_unlock(&p2m->domain->page_alloc_lock);
- error:
- P2M_PRINTK("failed to initialize p2m table, gfn=%05lx, mfn=%"
- PRI_mfn "\n", gfn, mfn_x(mfn));
- p2m_unlock(p2m);
- return -ENOMEM;
+ if ( !rc )
+ P2M_PRINTK("p2m table initialised for slot zero\n");
+ else
+ P2M_PRINTK("failed to initialise p2m table for slot zero (%d)\n", rc);
+ return rc;
}
+/*
+ * pvh fixme: when adding support for pvh non-hardware domains, this path must
+ * cleanup any foreign p2m types (release refcnts on them).
+ */
void p2m_teardown(struct p2m_domain *p2m)
/* Return all the p2m pages to Xen.
* We know we don't have any extra mappings to these pages */
{
struct page_info *pg;
struct domain *d;
- unsigned long gfn;
- p2m_type_t t;
- mfn_t mfn;
if (p2m == NULL)
return;
@@ -464,23 +492,7 @@ void p2m_teardown(struct p2m_domain *p2m)
d = p2m->domain;
p2m_lock(p2m);
-
- /* Try to unshare any remaining shared p2m entries. Safeguard
- * Since relinquish_shared_pages should have done the work. */
- for ( gfn=0; gfn < p2m->max_mapped_pfn; gfn++ )
- {
- p2m_access_t a;
- if ( atomic_read(&d->shr_pages) == 0 )
- break;
- mfn = p2m->get_entry(p2m, gfn, &t, &a, 0, NULL);
- if ( mfn_valid(mfn) && (t == p2m_ram_shared) )
- {
- ASSERT(!p2m_is_nestedp2m(p2m));
- /* Does not fail with ENOMEM given the DESTROY flag */
- BUG_ON(mem_sharing_unshare_page(d, gfn, MEM_SHARING_DESTROY_GFN));
- }
- }
-
+ ASSERT(atomic_read(&d->shr_pages) == 0);
p2m->phys_table = pagetable_null();
while ( (pg = page_list_remove_head(&p2m->pages)) )
@@ -500,7 +512,7 @@ void p2m_final_teardown(struct domain *d)
}
-static void
+static int
p2m_remove_page(struct p2m_domain *p2m, unsigned long gfn, unsigned long mfn,
unsigned int page_order)
{
@@ -514,7 +526,7 @@ p2m_remove_page(struct p2m_domain *p2m, unsigned long gfn, unsigned long mfn,
if ( need_iommu(p2m->domain) )
for ( i = 0; i < (1 << page_order); i++ )
iommu_unmap_page(p2m->domain, mfn + i);
- return;
+ return 0;
}
ASSERT(gfn_locked_by_me(p2m, gfn));
@@ -525,12 +537,13 @@ p2m_remove_page(struct p2m_domain *p2m, unsigned long gfn, unsigned long mfn,
for ( i = 0; i < (1UL << page_order); i++ )
{
mfn_return = p2m->get_entry(p2m, gfn + i, &t, &a, 0, NULL);
- if ( !p2m_is_grant(t) && !p2m_is_shared(t) )
+ if ( !p2m_is_grant(t) && !p2m_is_shared(t) && !p2m_is_foreign(t) )
set_gpfn_from_mfn(mfn+i, INVALID_M2P_ENTRY);
ASSERT( !p2m_is_valid(t) || mfn + i == mfn_x(mfn_return) );
}
}
- set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), page_order, p2m_invalid, p2m->default_access);
+ return p2m_set_entry(p2m, gfn, _mfn(INVALID_MFN), page_order, p2m_invalid,
+ p2m->default_access);
}
void
@@ -575,6 +588,10 @@ guest_physmap_add_entry(struct domain *d, unsigned long gfn,
return 0;
}
+ /* foreign pages are added thru p2m_add_foreign */
+ if ( p2m_is_foreign(t) )
+ return -EINVAL;
+
p2m_lock(p2m);
P2M_DEBUG("adding gfn=%#lx mfn=%#lx\n", gfn, mfn);
@@ -609,9 +626,9 @@ guest_physmap_add_entry(struct domain *d, unsigned long gfn,
omfn = p2m->get_entry(p2m, gfn + i, &ot, &a, 0, NULL);
ASSERT(!p2m_is_shared(ot));
}
- if ( p2m_is_grant(ot) )
+ if ( p2m_is_grant(ot) || p2m_is_foreign(ot) )
{
- /* Really shouldn't be unmapping grant maps this way */
+ /* Really shouldn't be unmapping grant/foreign maps this way */
domain_crash(d);
p2m_unlock(p2m);
@@ -669,11 +686,11 @@ guest_physmap_add_entry(struct domain *d, unsigned long gfn,
/* Now, actually do the two-way mapping */
if ( mfn_valid(_mfn(mfn)) )
{
- if ( !set_p2m_entry(p2m, gfn, _mfn(mfn), page_order, t, p2m->default_access) )
- {
- rc = -EINVAL;
+ rc = p2m_set_entry(p2m, gfn, _mfn(mfn), page_order, t,
+ p2m->default_access);
+ if ( rc )
goto out; /* Failed to update p2m, bail without updating m2p. */
- }
+
if ( !p2m_is_grant(t) )
{
for ( i = 0; i < (1UL << page_order); i++ )
@@ -684,10 +701,9 @@ guest_physmap_add_entry(struct domain *d, unsigned long gfn,
{
gdprintk(XENLOG_WARNING, "Adding bad mfn to p2m map (%#lx -> %#lx)\n",
gfn, mfn);
- if ( !set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), page_order,
- p2m_invalid, p2m->default_access) )
- rc = -EINVAL;
- else
+ rc = p2m_set_entry(p2m, gfn, _mfn(INVALID_MFN), page_order,
+ p2m_invalid, p2m->default_access);
+ if ( rc == 0 )
{
pod_lock(p2m);
p2m->pod.entry_count -= pod_count;
@@ -703,51 +719,87 @@ out:
}
-/* Modify the p2m type of a single gfn from ot to nt, returning the
- * entry's previous type. Resets the access permissions. */
-p2m_type_t p2m_change_type(struct domain *d, unsigned long gfn,
- p2m_type_t ot, p2m_type_t nt)
+/*
+ * Modify the p2m type of a single gfn from ot to nt.
+ * Returns: 0 for success, -errno for failure.
+ * Resets the access permissions.
+ */
+int p2m_change_type_one(struct domain *d, unsigned long gfn,
+ p2m_type_t ot, p2m_type_t nt)
{
p2m_access_t a;
p2m_type_t pt;
mfn_t mfn;
struct p2m_domain *p2m = p2m_get_hostp2m(d);
+ int rc;
BUG_ON(p2m_is_grant(ot) || p2m_is_grant(nt));
+ BUG_ON(p2m_is_foreign(ot) || p2m_is_foreign(nt));
gfn_lock(p2m, gfn, 0);
mfn = p2m->get_entry(p2m, gfn, &pt, &a, 0, NULL);
- if ( pt == ot )
- set_p2m_entry(p2m, gfn, mfn, PAGE_ORDER_4K, nt, p2m->default_access);
+ rc = likely(pt == ot)
+ ? p2m_set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, nt,
+ p2m->default_access)
+ : -EBUSY;
gfn_unlock(p2m, gfn, 0);
- return pt;
+ return rc;
}
-/* Modify the p2m type of a range of gfns from ot to nt.
- * Resets the access permissions. */
+/* Modify the p2m type of a range of gfns from ot to nt. */
void p2m_change_type_range(struct domain *d,
unsigned long start, unsigned long end,
p2m_type_t ot, p2m_type_t nt)
{
- p2m_access_t a;
- p2m_type_t pt;
- unsigned long gfn;
- mfn_t mfn;
+ unsigned long gfn = start;
struct p2m_domain *p2m = p2m_get_hostp2m(d);
+ int rc = 0;
- BUG_ON(p2m_is_grant(ot) || p2m_is_grant(nt));
+ ASSERT(ot != nt);
+ ASSERT(p2m_is_changeable(ot) && p2m_is_changeable(nt));
p2m_lock(p2m);
p2m->defer_nested_flush = 1;
- for ( gfn = start; gfn < end; gfn++ )
+ if ( unlikely(end > p2m->max_mapped_pfn) )
{
- mfn = p2m->get_entry(p2m, gfn, &pt, &a, 0, NULL);
- if ( pt == ot )
- set_p2m_entry(p2m, gfn, mfn, PAGE_ORDER_4K, nt, p2m->default_access);
+ if ( !gfn )
+ {
+ p2m->change_entry_type_global(p2m, ot, nt);
+ gfn = end;
+ }
+ end = p2m->max_mapped_pfn + 1;
+ }
+ if ( gfn < end )
+ rc = p2m->change_entry_type_range(p2m, ot, nt, gfn, end - 1);
+ if ( rc )
+ {
+ printk(XENLOG_G_ERR "Error %d changing Dom%d GFNs [%lx,%lx] from %d to %d\n",
+ rc, d->domain_id, start, end - 1, ot, nt);
+ domain_crash(d);
+ }
+
+ switch ( nt )
+ {
+ case p2m_ram_rw:
+ if ( ot == p2m_ram_logdirty )
+ rc = rangeset_remove_range(p2m->logdirty_ranges, start, end - 1);
+ break;
+ case p2m_ram_logdirty:
+ if ( ot == p2m_ram_rw )
+ rc = rangeset_add_range(p2m->logdirty_ranges, start, end - 1);
+ break;
+ default:
+ break;
+ }
+ if ( rc )
+ {
+ printk(XENLOG_G_ERR "Error %d manipulating Dom%d's log-dirty ranges\n",
+ rc, d->domain_id);
+ domain_crash(d);
}
p2m->defer_nested_flush = 0;
@@ -756,10 +808,9 @@ void p2m_change_type_range(struct domain *d,
p2m_unlock(p2m);
}
-
-
-int
-set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
+/* Returns: 0 for success, -errno for failure */
+static int set_typed_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
+ p2m_type_t gfn_p2mt)
{
int rc = 0;
p2m_access_t a;
@@ -768,15 +819,15 @@ set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
struct p2m_domain *p2m = p2m_get_hostp2m(d);
if ( !paging_mode_translate(d) )
- return 0;
+ return -EIO;
gfn_lock(p2m, gfn, 0);
omfn = p2m->get_entry(p2m, gfn, &ot, &a, 0, NULL);
- if ( p2m_is_grant(ot) )
+ if ( p2m_is_grant(ot) || p2m_is_foreign(ot) )
{
p2m_unlock(p2m);
domain_crash(d);
- return 0;
+ return -ENOENT;
}
else if ( p2m_is_ram(ot) )
{
@@ -784,48 +835,66 @@ set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY);
}
- P2M_DEBUG("set mmio %lx %lx\n", gfn, mfn_x(mfn));
- rc = set_p2m_entry(p2m, gfn, mfn, PAGE_ORDER_4K, p2m_mmio_direct, p2m->default_access);
+ P2M_DEBUG("set %d %lx %lx\n", gfn_p2mt, gfn, mfn_x(mfn));
+ rc = p2m_set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, gfn_p2mt,
+ p2m->default_access);
gfn_unlock(p2m, gfn, 0);
- if ( 0 == rc )
+ if ( rc )
gdprintk(XENLOG_ERR,
- "set_mmio_p2m_entry: set_p2m_entry failed! mfn=%08lx\n",
- mfn_x(get_gfn_query_unlocked(p2m->domain, gfn, &ot)));
+ "p2m_set_entry failed! mfn=%08lx rc:%d\n",
+ mfn_x(get_gfn_query_unlocked(p2m->domain, gfn, &ot)), rc);
return rc;
}
-int
-clear_mmio_p2m_entry(struct domain *d, unsigned long gfn)
+/* Set foreign mfn in the given guest's p2m table. */
+static int set_foreign_p2m_entry(struct domain *d, unsigned long gfn,
+ mfn_t mfn)
{
- int rc = 0;
- mfn_t mfn;
+ return set_typed_p2m_entry(d, gfn, mfn, p2m_map_foreign);
+}
+
+int set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
+{
+ return set_typed_p2m_entry(d, gfn, mfn, p2m_mmio_direct);
+}
+
+/* Returns: 0 for success, -errno for failure */
+int clear_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
+{
+ int rc = -EINVAL;
+ mfn_t actual_mfn;
p2m_access_t a;
p2m_type_t t;
struct p2m_domain *p2m = p2m_get_hostp2m(d);
if ( !paging_mode_translate(d) )
- return 0;
+ return -EIO;
gfn_lock(p2m, gfn, 0);
- mfn = p2m->get_entry(p2m, gfn, &t, &a, 0, NULL);
+ actual_mfn = p2m->get_entry(p2m, gfn, &t, &a, 0, NULL);
/* Do not use mfn_valid() here as it will usually fail for MMIO pages. */
- if ( (INVALID_MFN == mfn_x(mfn)) || (t != p2m_mmio_direct) )
+ if ( (INVALID_MFN == mfn_x(actual_mfn)) || (t != p2m_mmio_direct) )
{
gdprintk(XENLOG_ERR,
- "clear_mmio_p2m_entry: gfn_to_mfn failed! gfn=%08lx\n", gfn);
+ "gfn_to_mfn failed! gfn=%08lx type:%d\n", gfn, t);
goto out;
}
- rc = set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), PAGE_ORDER_4K, p2m_invalid, p2m->default_access);
+ if ( mfn_x(mfn) != mfn_x(actual_mfn) )
+ gdprintk(XENLOG_WARNING,
+ "no mapping between mfn %08lx and gfn %08lx\n",
+ mfn_x(mfn), gfn);
+ rc = p2m_set_entry(p2m, gfn, _mfn(INVALID_MFN), PAGE_ORDER_4K, p2m_invalid,
+ p2m->default_access);
-out:
+ out:
gfn_unlock(p2m, gfn, 0);
return rc;
}
-int
-set_shared_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
+/* Returns: 0 for success, -errno for failure */
+int set_shared_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
{
struct p2m_domain *p2m = p2m_get_hostp2m(d);
int rc = 0;
@@ -835,7 +904,7 @@ set_shared_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
unsigned long pg_type;
if ( !paging_mode_translate(p2m->domain) )
- return 0;
+ return -EIO;
gfn_lock(p2m, gfn, 0);
omfn = p2m->get_entry(p2m, gfn, &ot, &a, 0, NULL);
@@ -851,12 +920,13 @@ set_shared_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY);
P2M_DEBUG("set shared %lx %lx\n", gfn, mfn_x(mfn));
- rc = set_p2m_entry(p2m, gfn, mfn, PAGE_ORDER_4K, p2m_ram_shared, p2m->default_access);
+ rc = p2m_set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, p2m_ram_shared,
+ p2m->default_access);
gfn_unlock(p2m, gfn, 0);
- if ( 0 == rc )
+ if ( rc )
gdprintk(XENLOG_ERR,
- "set_shared_p2m_entry: set_p2m_entry failed! mfn=%08lx\n",
- mfn_x(get_gfn_query_unlocked(p2m->domain, gfn, &ot)));
+ "p2m_set_entry failed! mfn=%08lx rc:%d\n",
+ mfn_x(get_gfn_query_unlocked(p2m->domain, gfn, &ot)), rc);
return rc;
}
@@ -913,8 +983,7 @@ int p2m_mem_paging_nominate(struct domain *d, unsigned long gfn)
goto out;
/* Fix p2m entry */
- set_p2m_entry(p2m, gfn, mfn, PAGE_ORDER_4K, p2m_ram_paging_out, a);
- ret = 0;
+ ret = p2m_set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, p2m_ram_paging_out, a);
out:
gfn_unlock(p2m, gfn, 0);
@@ -978,7 +1047,8 @@ int p2m_mem_paging_evict(struct domain *d, unsigned long gfn)
put_page(page);
/* Remove mapping from p2m table */
- set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), PAGE_ORDER_4K, p2m_ram_paged, a);
+ ret = p2m_set_entry(p2m, gfn, _mfn(INVALID_MFN), PAGE_ORDER_4K,
+ p2m_ram_paged, a);
/* Clear content before returning the page to Xen */
scrub_one_page(page);
@@ -986,8 +1056,6 @@ int p2m_mem_paging_evict(struct domain *d, unsigned long gfn)
/* Track number of paged gfns */
atomic_inc(&d->paged_pages);
- ret = 0;
-
out_put:
/* Put the page back so it gets freed */
put_page(page);
@@ -1087,7 +1155,7 @@ void p2m_mem_paging_populate(struct domain *d, unsigned long gfn)
if ( p2mt == p2m_ram_paging_out )
req.flags |= MEM_EVENT_FLAG_EVICT_FAIL;
- set_p2m_entry(p2m, gfn, mfn, PAGE_ORDER_4K, p2m_ram_paging_in, a);
+ p2m_set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, p2m_ram_paging_in, a);
}
gfn_unlock(p2m, gfn, 0);
@@ -1187,16 +1255,14 @@ int p2m_mem_paging_prep(struct domain *d, unsigned long gfn, uint64_t buffer)
/* Make the page already guest-accessible. If the pager still has a
* pending resume operation, it will be idempotent p2m entry-wise,
* but will unpause the vcpu */
- set_p2m_entry(p2m, gfn, mfn, PAGE_ORDER_4K,
- paging_mode_log_dirty(d) ? p2m_ram_logdirty :
- p2m_ram_rw, a);
+ ret = p2m_set_entry(p2m, gfn, mfn, PAGE_ORDER_4K,
+ paging_mode_log_dirty(d) ? p2m_ram_logdirty
+ : p2m_ram_rw, a);
set_gpfn_from_mfn(mfn_x(mfn), gfn);
if ( !page_extant )
atomic_dec(&d->paged_pages);
- ret = 0;
-
out:
gfn_unlock(p2m, gfn, 0);
return ret;
@@ -1248,9 +1314,9 @@ void p2m_mem_paging_resume(struct domain *d)
* were nominated but not evicted */
if ( mfn_valid(mfn) && (p2mt == p2m_ram_paging_in) )
{
- set_p2m_entry(p2m, rsp.gfn, mfn, PAGE_ORDER_4K,
- paging_mode_log_dirty(d) ? p2m_ram_logdirty :
- p2m_ram_rw, a);
+ p2m_set_entry(p2m, rsp.gfn, mfn, PAGE_ORDER_4K,
+ paging_mode_log_dirty(d) ? p2m_ram_logdirty :
+ p2m_ram_rw, a);
set_gpfn_from_mfn(mfn_x(mfn), rsp.gfn);
}
gfn_unlock(p2m, rsp.gfn, 0);
@@ -1261,9 +1327,126 @@ void p2m_mem_paging_resume(struct domain *d)
}
}
-bool_t p2m_mem_access_check(paddr_t gpa, bool_t gla_valid, unsigned long gla,
- bool_t access_r, bool_t access_w, bool_t access_x,
- mem_event_request_t **req_ptr)
+static void p2m_mem_event_fill_regs(mem_event_request_t *req)
+{
+ const struct cpu_user_regs *regs = guest_cpu_user_regs();
+ struct segment_register seg;
+ struct hvm_hw_cpu ctxt;
+ struct vcpu *curr = current;
+
+ /* Architecture-specific vmcs/vmcb bits */
+ hvm_funcs.save_cpu_ctxt(curr, &ctxt);
+
+ req->x86_regs.rax = regs->eax;
+ req->x86_regs.rcx = regs->ecx;
+ req->x86_regs.rdx = regs->edx;
+ req->x86_regs.rbx = regs->ebx;
+ req->x86_regs.rsp = regs->esp;
+ req->x86_regs.rbp = regs->ebp;
+ req->x86_regs.rsi = regs->esi;
+ req->x86_regs.rdi = regs->edi;
+
+ req->x86_regs.r8 = regs->r8;
+ req->x86_regs.r9 = regs->r9;
+ req->x86_regs.r10 = regs->r10;
+ req->x86_regs.r11 = regs->r11;
+ req->x86_regs.r12 = regs->r12;
+ req->x86_regs.r13 = regs->r13;
+ req->x86_regs.r14 = regs->r14;
+ req->x86_regs.r15 = regs->r15;
+
+ req->x86_regs.rflags = regs->eflags;
+ req->x86_regs.rip = regs->eip;
+
+ req->x86_regs.dr7 = curr->arch.debugreg[7];
+ req->x86_regs.cr0 = ctxt.cr0;
+ req->x86_regs.cr2 = ctxt.cr2;
+ req->x86_regs.cr3 = ctxt.cr3;
+ req->x86_regs.cr4 = ctxt.cr4;
+
+ req->x86_regs.sysenter_cs = ctxt.sysenter_cs;
+ req->x86_regs.sysenter_esp = ctxt.sysenter_esp;
+ req->x86_regs.sysenter_eip = ctxt.sysenter_eip;
+
+ req->x86_regs.msr_efer = ctxt.msr_efer;
+ req->x86_regs.msr_star = ctxt.msr_star;
+ req->x86_regs.msr_lstar = ctxt.msr_lstar;
+
+ hvm_get_segment_register(curr, x86_seg_fs, &seg);
+ req->x86_regs.fs_base = seg.base;
+
+ hvm_get_segment_register(curr, x86_seg_gs, &seg);
+ req->x86_regs.gs_base = seg.base;
+
+ hvm_get_segment_register(curr, x86_seg_cs, &seg);
+ req->x86_regs.cs_arbytes = seg.attr.bytes;
+}
+
+void p2m_mem_event_emulate_check(struct vcpu *v, const mem_event_response_t *rsp)
+{
+ /* Mark vcpu for skipping one instruction upon rescheduling. */
+ if ( rsp->flags & MEM_EVENT_FLAG_EMULATE )
+ {
+ xenmem_access_t access;
+ bool_t violation = 1;
+
+ if ( p2m_get_mem_access(v->domain, rsp->gfn, &access) == 0 )
+ {
+ switch ( access )
+ {
+ case XENMEM_access_n:
+ case XENMEM_access_n2rwx:
+ default:
+ violation = rsp->access_r || rsp->access_w || rsp->access_x;
+ break;
+
+ case XENMEM_access_r:
+ violation = rsp->access_w || rsp->access_x;
+ break;
+
+ case XENMEM_access_w:
+ violation = rsp->access_r || rsp->access_x;
+ break;
+
+ case XENMEM_access_x:
+ violation = rsp->access_r || rsp->access_w;
+ break;
+
+ case XENMEM_access_rx:
+ case XENMEM_access_rx2rw:
+ violation = rsp->access_w;
+ break;
+
+ case XENMEM_access_wx:
+ violation = rsp->access_r;
+ break;
+
+ case XENMEM_access_rw:
+ violation = rsp->access_x;
+ break;
+
+ case XENMEM_access_rwx:
+ violation = 0;
+ break;
+ }
+ }
+
+ v->arch.mem_event.emulate_flags = violation ? rsp->flags : 0;
+ }
+}
+
+void p2m_setup_introspection(struct domain *d)
+{
+ if ( hvm_funcs.enable_msr_exit_interception )
+ {
+ d->arch.hvm_domain.introspection_enabled = 1;
+ hvm_funcs.enable_msr_exit_interception(d);
+ }
+}
+
+bool_t p2m_mem_access_check(paddr_t gpa, unsigned long gla,
+ struct npfec npfec,
+ mem_event_request_t **req_ptr)
{
struct vcpu *v = current;
unsigned long gfn = gpa >> PAGE_SHIFT;
@@ -1274,6 +1457,7 @@ bool_t p2m_mem_access_check(paddr_t gpa, bool_t gla_valid, unsigned long gla,
p2m_access_t p2ma;
mem_event_request_t *req;
int rc;
+ unsigned long eip = guest_cpu_user_regs()->eip;
/* First, handle rx2rw conversion automatically.
* These calls to p2m->set_entry() must succeed: we have the gfn
@@ -1281,19 +1465,19 @@ bool_t p2m_mem_access_check(paddr_t gpa, bool_t gla_valid, unsigned long gla,
gfn_lock(p2m, gfn, 0);
mfn = p2m->get_entry(p2m, gfn, &p2mt, &p2ma, 0, NULL);
- if ( access_w && p2ma == p2m_access_rx2rw )
+ if ( npfec.write_access && p2ma == p2m_access_rx2rw )
{
rc = p2m->set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, p2mt, p2m_access_rw);
- ASSERT(rc);
+ ASSERT(rc == 0);
gfn_unlock(p2m, gfn, 0);
return 1;
}
else if ( p2ma == p2m_access_n2rwx )
{
- ASSERT(access_w || access_r || access_x);
+ ASSERT(npfec.write_access || npfec.read_access || npfec.insn_fetch);
rc = p2m->set_entry(p2m, gfn, mfn, PAGE_ORDER_4K,
p2mt, p2m_access_rwx);
- ASSERT(rc);
+ ASSERT(rc == 0);
}
gfn_unlock(p2m, gfn, 0);
@@ -1320,13 +1504,37 @@ bool_t p2m_mem_access_check(paddr_t gpa, bool_t gla_valid, unsigned long gla,
* gfn locked and just did a successful get_entry(). */
rc = p2m->set_entry(p2m, gfn, mfn, PAGE_ORDER_4K,
p2mt, p2m_access_rwx);
- ASSERT(rc);
+ ASSERT(rc == 0);
}
gfn_unlock(p2m, gfn, 0);
return 1;
}
}
+ /* The previous mem_event reply does not match the current state. */
+ if ( v->arch.mem_event.gpa != gpa || v->arch.mem_event.eip != eip )
+ {
+ /* Don't emulate the current instruction, send a new mem_event. */
+ v->arch.mem_event.emulate_flags = 0;
+
+ /*
+ * Make sure to mark the current state to match it again against
+ * the new mem_event about to be sent.
+ */
+ v->arch.mem_event.gpa = gpa;
+ v->arch.mem_event.eip = eip;
+ }
+
+ if ( v->arch.mem_event.emulate_flags )
+ {
+ hvm_mem_event_emulate_one((v->arch.mem_event.emulate_flags &
+ MEM_EVENT_FLAG_EMULATE_NOWRITE) != 0,
+ TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE);
+
+ v->arch.mem_event.emulate_flags = 0;
+ return 1;
+ }
+
*req_ptr = NULL;
req = xzalloc(mem_event_request_t);
if ( req )
@@ -1341,13 +1549,18 @@ bool_t p2m_mem_access_check(paddr_t gpa, bool_t gla_valid, unsigned long gla,
/* Send request to mem event */
req->gfn = gfn;
req->offset = gpa & ((1 << PAGE_SHIFT) - 1);
- req->gla_valid = gla_valid;
+ req->gla_valid = npfec.gla_valid;
req->gla = gla;
- req->access_r = access_r;
- req->access_w = access_w;
- req->access_x = access_x;
-
+ if ( npfec.kind == npfec_kind_with_gla )
+ req->fault_with_gla = 1;
+ else if ( npfec.kind == npfec_kind_in_gpt )
+ req->fault_in_gpt = 1;
+ req->access_r = npfec.read_access;
+ req->access_w = npfec.write_access;
+ req->access_x = npfec.insn_fetch;
req->vcpu_id = v->vcpu_id;
+
+ p2m_mem_event_fill_regs(req);
}
/* Pause the current VCPU */
@@ -1358,60 +1571,43 @@ bool_t p2m_mem_access_check(paddr_t gpa, bool_t gla_valid, unsigned long gla,
return (p2ma == p2m_access_n2rwx);
}
-void p2m_mem_access_resume(struct domain *d)
-{
- mem_event_response_t rsp;
-
- /* Pull all responses off the ring */
- while( mem_event_get_response(d, &d->mem_event->access, &rsp) )
- {
- struct vcpu *v;
-
- if ( rsp.flags & MEM_EVENT_FLAG_DUMMY )
- continue;
-
- /* Validate the vcpu_id in the response. */
- if ( (rsp.vcpu_id >= d->max_vcpus) || !d->vcpu[rsp.vcpu_id] )
- continue;
-
- v = d->vcpu[rsp.vcpu_id];
-
- /* Unpause domain */
- if ( rsp.flags & MEM_EVENT_FLAG_VCPU_PAUSED )
- mem_event_vcpu_unpause(v);
- }
-}
-
/* Set access type for a region of pfns.
* If start_pfn == -1ul, sets the default access type */
long p2m_set_mem_access(struct domain *d, unsigned long pfn, uint32_t nr,
- hvmmem_access_t access)
+ uint32_t start, uint32_t mask, xenmem_access_t access)
{
struct p2m_domain *p2m = p2m_get_hostp2m(d);
p2m_access_t a, _a;
p2m_type_t t;
mfn_t mfn;
- long rc;
-
- /* N.B. _not_ static: initializer depends on p2m->default_access */
- p2m_access_t memaccess[] = {
- p2m_access_n,
- p2m_access_r,
- p2m_access_w,
- p2m_access_rw,
- p2m_access_x,
- p2m_access_rx,
- p2m_access_wx,
- p2m_access_rwx,
- p2m_access_rx2rw,
- p2m_access_n2rwx,
- p2m->default_access,
+ long rc = 0;
+
+ static const p2m_access_t memaccess[] = {
+#define ACCESS(ac) [XENMEM_access_##ac] = p2m_access_##ac
+ ACCESS(n),
+ ACCESS(r),
+ ACCESS(w),
+ ACCESS(rw),
+ ACCESS(x),
+ ACCESS(rx),
+ ACCESS(wx),
+ ACCESS(rwx),
+ ACCESS(rx2rw),
+ ACCESS(n2rwx),
+#undef ACCESS
};
- if ( (unsigned) access >= HVMMEM_access_default )
+ switch ( access )
+ {
+ case 0 ... ARRAY_SIZE(memaccess) - 1:
+ a = memaccess[access];
+ break;
+ case XENMEM_access_default:
+ a = p2m->default_access;
+ break;
+ default:
return -EINVAL;
-
- a = memaccess[access];
+ }
/* If request to set default access */
if ( pfn == ~0ul )
@@ -1420,23 +1616,18 @@ long p2m_set_mem_access(struct domain *d, unsigned long pfn, uint32_t nr,
return 0;
}
- if ( !nr )
- return 0;
-
p2m_lock(p2m);
- for ( ; ; ++pfn )
+ for ( pfn += start; nr > start; ++pfn )
{
mfn = p2m->get_entry(p2m, pfn, &t, &_a, 0, NULL);
- if ( p2m->set_entry(p2m, pfn, mfn, PAGE_ORDER_4K, t, a) == 0 )
- {
- rc = -ENOMEM;
+ rc = p2m->set_entry(p2m, pfn, mfn, PAGE_ORDER_4K, t, a);
+ if ( rc )
break;
- }
- /* Check for continuation if it's not the last interation. */
- if ( !--nr || hypercall_preempt_check() )
+ /* Check for continuation if it's not the last iteration. */
+ if ( nr > ++start && !(start & mask) && hypercall_preempt_check() )
{
- rc = nr;
+ rc = start;
break;
}
}
@@ -1447,23 +1638,26 @@ long p2m_set_mem_access(struct domain *d, unsigned long pfn, uint32_t nr,
/* Get access type for a pfn
* If pfn == -1ul, gets the default access type */
int p2m_get_mem_access(struct domain *d, unsigned long pfn,
- hvmmem_access_t *access)
+ xenmem_access_t *access)
{
struct p2m_domain *p2m = p2m_get_hostp2m(d);
p2m_type_t t;
p2m_access_t a;
mfn_t mfn;
- static const hvmmem_access_t memaccess[] = {
- HVMMEM_access_n,
- HVMMEM_access_r,
- HVMMEM_access_w,
- HVMMEM_access_rw,
- HVMMEM_access_x,
- HVMMEM_access_rx,
- HVMMEM_access_wx,
- HVMMEM_access_rwx,
- HVMMEM_access_rx2rw
+ static const xenmem_access_t memaccess[] = {
+#define ACCESS(ac) [p2m_access_##ac] = XENMEM_access_##ac
+ ACCESS(n),
+ ACCESS(r),
+ ACCESS(w),
+ ACCESS(rw),
+ ACCESS(x),
+ ACCESS(rx),
+ ACCESS(wx),
+ ACCESS(rwx),
+ ACCESS(rx2rw),
+ ACCESS(n2rwx),
+#undef ACCESS
};
/* If request to get default access */
@@ -1651,6 +1845,51 @@ unsigned long paging_gva_to_gfn(struct vcpu *v,
return hostmode->gva_to_gfn(v, hostp2m, va, pfec);
}
+int map_mmio_regions(struct domain *d,
+ unsigned long start_gfn,
+ unsigned long nr,
+ unsigned long mfn)
+{
+ int ret = 0;
+ unsigned long i;
+
+ if ( !paging_mode_translate(d) )
+ return 0;
+
+ for ( i = 0; !ret && i < nr; i++ )
+ {
+ ret = set_mmio_p2m_entry(d, start_gfn + i, _mfn(mfn + i));
+ if ( ret )
+ {
+ unmap_mmio_regions(d, start_gfn, i, mfn);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int unmap_mmio_regions(struct domain *d,
+ unsigned long start_gfn,
+ unsigned long nr,
+ unsigned long mfn)
+{
+ int err = 0;
+ unsigned long i;
+
+ if ( !paging_mode_translate(d) )
+ return 0;
+
+ for ( i = 0; i < nr; i++ )
+ {
+ int ret = clear_mmio_p2m_entry(d, start_gfn + i, _mfn(mfn + i));
+ if ( ret )
+ err = ret;
+ }
+
+ return err;
+}
+
/*** Audit ***/
#if P2M_AUDIT
@@ -1740,7 +1979,7 @@ void audit_p2m(struct domain *d,
P2M_PRINTK("p2m audit complete\n");
if ( orphans_count | mpbad | pmbad )
- P2M_PRINTK("p2m audit found %lu orphans\n", orphans);
+ P2M_PRINTK("p2m audit found %lu orphans\n", orphans_count);
if ( mpbad | pmbad )
{
P2M_PRINTK("p2m audit found %lu odd p2m, %lu bad m2p entries\n",
@@ -1756,6 +1995,107 @@ out_p2m_audit:
#endif /* P2M_AUDIT */
/*
+ * Add frame from foreign domain to target domain's physmap. Similar to
+ * XENMAPSPACE_gmfn but the frame is foreign being mapped into current,
+ * and is not removed from foreign domain.
+ *
+ * Usage: - libxl on pvh dom0 creating a guest and doing privcmd_ioctl_mmap.
+ * - xentrace running on dom0 mapping xenheap pages. foreigndom would
+ * be DOMID_XEN in such a case.
+ * etc..
+ *
+ * Side Effect: the mfn for fgfn will be refcounted in lower level routines
+ * so it is not lost while mapped here. The refcnt is released
+ * via the XENMEM_remove_from_physmap path.
+ *
+ * Returns: 0 ==> success
+ */
+int p2m_add_foreign(struct domain *tdom, unsigned long fgfn,
+ unsigned long gpfn, domid_t foreigndom)
+{
+ p2m_type_t p2mt, p2mt_prev;
+ unsigned long prev_mfn, mfn;
+ struct page_info *page;
+ int rc;
+ struct domain *fdom;
+
+ ASSERT(tdom);
+ if ( foreigndom == DOMID_SELF || !is_pvh_domain(tdom) )
+ return -EINVAL;
+ /*
+ * pvh fixme: until support is added to p2m teardown code to cleanup any
+ * foreign entries, limit this to hardware domain only.
+ */
+ if ( !is_hardware_domain(tdom) )
+ return -EPERM;
+
+ if ( foreigndom == DOMID_XEN )
+ fdom = rcu_lock_domain(dom_xen);
+ else
+ fdom = rcu_lock_domain_by_id(foreigndom);
+ if ( fdom == NULL )
+ return -ESRCH;
+
+ rc = -EINVAL;
+ if ( tdom == fdom )
+ goto out;
+
+ rc = xsm_map_gmfn_foreign(XSM_TARGET, tdom, fdom);
+ if ( rc )
+ goto out;
+
+ /*
+ * Take a refcnt on the mfn. NB: following supported for foreign mapping:
+ * ram_rw | ram_logdirty | ram_ro | paging_out.
+ */
+ page = get_page_from_gfn(fdom, fgfn, &p2mt, P2M_ALLOC);
+ if ( !page ||
+ !p2m_is_ram(p2mt) || p2m_is_shared(p2mt) || p2m_is_hole(p2mt) )
+ {
+ if ( page )
+ put_page(page);
+ rc = -EINVAL;
+ goto out;
+ }
+ mfn = mfn_x(page_to_mfn(page));
+
+ /* Remove previously mapped page if it is present. */
+ prev_mfn = mfn_x(get_gfn(tdom, gpfn, &p2mt_prev));
+ if ( mfn_valid(_mfn(prev_mfn)) )
+ {
+ if ( is_xen_heap_mfn(prev_mfn) )
+ /* Xen heap frames are simply unhooked from this phys slot */
+ guest_physmap_remove_page(tdom, gpfn, prev_mfn, 0);
+ else
+ /* Normal domain memory is freed, to avoid leaking memory. */
+ guest_remove_page(tdom, gpfn);
+ }
+ /*
+ * Create the new mapping. Can't use guest_physmap_add_page() because it
+ * will update the m2p table which will result in mfn -> gpfn of dom0
+ * and not fgfn of domU.
+ */
+ rc = set_foreign_p2m_entry(tdom, gpfn, _mfn(mfn));
+ if ( rc )
+ gdprintk(XENLOG_WARNING, "set_foreign_p2m_entry failed. "
+ "gpfn:%lx mfn:%lx fgfn:%lx td:%d fd:%d\n",
+ gpfn, mfn, fgfn, tdom->domain_id, fdom->domain_id);
+
+ put_page(page);
+
+ /*
+ * This put_gfn for the above get_gfn for prev_mfn. We must do this
+ * after set_foreign_p2m_entry so another cpu doesn't populate the gpfn
+ * before us.
+ */
+ put_gfn(tdom, gpfn);
+
+out:
+ if ( fdom )
+ rcu_unlock_domain(fdom);
+ return rc;
+}
+/*
* Local variables:
* mode: C
* c-file-style: "BSD"
diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c
index ab5eacb..6b788f7 100644
--- a/xen/arch/x86/mm/paging.c
+++ b/xen/arch/x86/mm/paging.c
@@ -26,6 +26,7 @@
#include <asm/shadow.h>
#include <asm/p2m.h>
#include <asm/hap.h>
+#include <asm/event.h>
#include <asm/hvm/nestedhvm.h>
#include <xen/numa.h>
#include <xsm/xsm.h>
@@ -116,26 +117,46 @@ static void paging_free_log_dirty_page(struct domain *d, mfn_t mfn)
d->arch.paging.free_page(d, mfn_to_page(mfn));
}
-void paging_free_log_dirty_bitmap(struct domain *d)
+static int paging_free_log_dirty_bitmap(struct domain *d, int rc)
{
mfn_t *l4, *l3, *l2;
int i4, i3, i2;
+ paging_lock(d);
+
if ( !mfn_valid(d->arch.paging.log_dirty.top) )
- return;
+ {
+ paging_unlock(d);
+ return 0;
+ }
- paging_lock(d);
+ if ( !d->arch.paging.preempt.dom )
+ {
+ memset(&d->arch.paging.preempt.log_dirty, 0,
+ sizeof(d->arch.paging.preempt.log_dirty));
+ ASSERT(rc <= 0);
+ d->arch.paging.preempt.log_dirty.done = -rc;
+ }
+ else if ( d->arch.paging.preempt.dom != current->domain ||
+ d->arch.paging.preempt.op != XEN_DOMCTL_SHADOW_OP_OFF )
+ {
+ paging_unlock(d);
+ return -EBUSY;
+ }
l4 = map_domain_page(mfn_x(d->arch.paging.log_dirty.top));
+ i4 = d->arch.paging.preempt.log_dirty.i4;
+ i3 = d->arch.paging.preempt.log_dirty.i3;
+ rc = 0;
- for ( i4 = 0; i4 < LOGDIRTY_NODE_ENTRIES; i4++ )
+ for ( ; i4 < LOGDIRTY_NODE_ENTRIES; i4++, i3 = 0 )
{
if ( !mfn_valid(l4[i4]) )
continue;
l3 = map_domain_page(mfn_x(l4[i4]));
- for ( i3 = 0; i3 < LOGDIRTY_NODE_ENTRIES; i3++ )
+ for ( ; i3 < LOGDIRTY_NODE_ENTRIES; i3++ )
{
if ( !mfn_valid(l3[i3]) )
continue;
@@ -148,26 +169,69 @@ void paging_free_log_dirty_bitmap(struct domain *d)
unmap_domain_page(l2);
paging_free_log_dirty_page(d, l3[i3]);
+ l3[i3] = _mfn(INVALID_MFN);
+
+ if ( i3 < LOGDIRTY_NODE_ENTRIES - 1 && hypercall_preempt_check() )
+ {
+ d->arch.paging.preempt.log_dirty.i3 = i3 + 1;
+ d->arch.paging.preempt.log_dirty.i4 = i4;
+ rc = -ERESTART;
+ break;
+ }
}
unmap_domain_page(l3);
+ if ( rc )
+ break;
paging_free_log_dirty_page(d, l4[i4]);
+ l4[i4] = _mfn(INVALID_MFN);
+
+ if ( i4 < LOGDIRTY_NODE_ENTRIES - 1 && hypercall_preempt_check() )
+ {
+ d->arch.paging.preempt.log_dirty.i3 = 0;
+ d->arch.paging.preempt.log_dirty.i4 = i4 + 1;
+ rc = -ERESTART;
+ break;
+ }
}
unmap_domain_page(l4);
- paging_free_log_dirty_page(d, d->arch.paging.log_dirty.top);
- d->arch.paging.log_dirty.top = _mfn(INVALID_MFN);
- ASSERT(d->arch.paging.log_dirty.allocs == 0);
- d->arch.paging.log_dirty.failed_allocs = 0;
+ if ( !rc )
+ {
+ paging_free_log_dirty_page(d, d->arch.paging.log_dirty.top);
+ d->arch.paging.log_dirty.top = _mfn(INVALID_MFN);
+
+ ASSERT(d->arch.paging.log_dirty.allocs == 0);
+ d->arch.paging.log_dirty.failed_allocs = 0;
+
+ rc = -d->arch.paging.preempt.log_dirty.done;
+ d->arch.paging.preempt.dom = NULL;
+ }
+ else
+ {
+ d->arch.paging.preempt.dom = current->domain;
+ d->arch.paging.preempt.op = XEN_DOMCTL_SHADOW_OP_OFF;
+ }
paging_unlock(d);
+
+ return rc;
}
int paging_log_dirty_enable(struct domain *d, bool_t log_global)
{
int ret;
+ if ( need_iommu(d) && log_global )
+ {
+ /*
+ * Refuse to turn on global log-dirty mode
+ * if the domain is using the IOMMU.
+ */
+ return -EINVAL;
+ }
+
if ( paging_mode_log_dirty(d) )
return -EINVAL;
@@ -178,15 +242,25 @@ int paging_log_dirty_enable(struct domain *d, bool_t log_global)
return ret;
}
-int paging_log_dirty_disable(struct domain *d)
+static int paging_log_dirty_disable(struct domain *d, bool_t resuming)
{
- int ret;
+ int ret = 1;
+
+ if ( !resuming )
+ {
+ domain_pause(d);
+ /* Safe because the domain is paused. */
+ if ( paging_mode_log_dirty(d) )
+ {
+ ret = d->arch.paging.log_dirty.disable_log_dirty(d);
+ ASSERT(ret <= 0);
+ }
+ }
+
+ ret = paging_free_log_dirty_bitmap(d, ret);
+ if ( ret == -ERESTART )
+ return ret;
- domain_pause(d);
- /* Safe because the domain is paused. */
- ret = d->arch.paging.log_dirty.disable_log_dirty(d);
- if ( !paging_mode_log_dirty(d) )
- paging_free_log_dirty_bitmap(d);
domain_unpause(d);
return ret;
@@ -326,7 +400,9 @@ int paging_mfn_is_dirty(struct domain *d, mfn_t gmfn)
/* Read a domain's log-dirty bitmap and stats. If the operation is a CLEAN,
* clear the bitmap and stats as well. */
-int paging_log_dirty_op(struct domain *d, struct xen_domctl_shadow_op *sc)
+static int paging_log_dirty_op(struct domain *d,
+ struct xen_domctl_shadow_op *sc,
+ bool_t resuming)
{
int rv = 0, clean = 0, peek = 1;
unsigned long pages = 0;
@@ -334,9 +410,22 @@ int paging_log_dirty_op(struct domain *d, struct xen_domctl_shadow_op *sc)
unsigned long *l1 = NULL;
int i4, i3, i2;
- domain_pause(d);
+ if ( !resuming )
+ domain_pause(d);
paging_lock(d);
+ if ( !d->arch.paging.preempt.dom )
+ memset(&d->arch.paging.preempt.log_dirty, 0,
+ sizeof(d->arch.paging.preempt.log_dirty));
+ else if ( d->arch.paging.preempt.dom != current->domain ||
+ d->arch.paging.preempt.op != sc->op )
+ {
+ paging_unlock(d);
+ ASSERT(!resuming);
+ domain_unpause(d);
+ return -EBUSY;
+ }
+
clean = (sc->op == XEN_DOMCTL_SHADOW_OP_CLEAN);
PAGING_DEBUG(LOGDIRTY, "log-dirty %s: dom %u faults=%u dirty=%u\n",
@@ -348,12 +437,6 @@ int paging_log_dirty_op(struct domain *d, struct xen_domctl_shadow_op *sc)
sc->stats.fault_count = d->arch.paging.log_dirty.fault_count;
sc->stats.dirty_count = d->arch.paging.log_dirty.dirty_count;
- if ( clean )
- {
- d->arch.paging.log_dirty.fault_count = 0;
- d->arch.paging.log_dirty.dirty_count = 0;
- }
-
if ( guest_handle_is_null(sc->dirty_bitmap) )
/* caller may have wanted just to clean the state or access stats. */
peek = 0;
@@ -365,17 +448,15 @@ int paging_log_dirty_op(struct domain *d, struct xen_domctl_shadow_op *sc)
goto out;
}
- pages = 0;
l4 = paging_map_log_dirty_bitmap(d);
+ i4 = d->arch.paging.preempt.log_dirty.i4;
+ i3 = d->arch.paging.preempt.log_dirty.i3;
+ pages = d->arch.paging.preempt.log_dirty.done;
- for ( i4 = 0;
- (pages < sc->pages) && (i4 < LOGDIRTY_NODE_ENTRIES);
- i4++ )
+ for ( ; (pages < sc->pages) && (i4 < LOGDIRTY_NODE_ENTRIES); i4++, i3 = 0 )
{
l3 = (l4 && mfn_valid(l4[i4])) ? map_domain_page(mfn_x(l4[i4])) : NULL;
- for ( i3 = 0;
- (pages < sc->pages) && (i3 < LOGDIRTY_NODE_ENTRIES);
- i3++ )
+ for ( ; (pages < sc->pages) && (i3 < LOGDIRTY_NODE_ENTRIES); i3++ )
{
l2 = ((l3 && mfn_valid(l3[i3])) ?
map_domain_page(mfn_x(l3[i3])) : NULL);
@@ -410,18 +491,58 @@ int paging_log_dirty_op(struct domain *d, struct xen_domctl_shadow_op *sc)
}
if ( l2 )
unmap_domain_page(l2);
+
+ if ( i3 < LOGDIRTY_NODE_ENTRIES - 1 && hypercall_preempt_check() )
+ {
+ d->arch.paging.preempt.log_dirty.i4 = i4;
+ d->arch.paging.preempt.log_dirty.i3 = i3 + 1;
+ rv = -ERESTART;
+ break;
+ }
}
if ( l3 )
unmap_domain_page(l3);
+
+ if ( !rv && i4 < LOGDIRTY_NODE_ENTRIES - 1 &&
+ hypercall_preempt_check() )
+ {
+ d->arch.paging.preempt.log_dirty.i4 = i4 + 1;
+ d->arch.paging.preempt.log_dirty.i3 = 0;
+ rv = -ERESTART;
+ }
+ if ( rv )
+ break;
}
if ( l4 )
unmap_domain_page(l4);
- if ( pages < sc->pages )
- sc->pages = pages;
+ if ( !rv )
+ {
+ d->arch.paging.preempt.dom = NULL;
+ if ( clean )
+ {
+ d->arch.paging.log_dirty.fault_count = 0;
+ d->arch.paging.log_dirty.dirty_count = 0;
+ }
+ }
+ else
+ {
+ d->arch.paging.preempt.dom = current->domain;
+ d->arch.paging.preempt.op = sc->op;
+ d->arch.paging.preempt.log_dirty.done = pages;
+ }
paging_unlock(d);
+ if ( rv )
+ {
+ /* Never leave the domain paused on real errors. */
+ ASSERT(rv == -ERESTART);
+ return rv;
+ }
+
+ if ( pages < sc->pages )
+ sc->pages = pages;
if ( clean )
{
/* We need to further call clean_dirty_bitmap() functions of specific
@@ -432,6 +553,7 @@ int paging_log_dirty_op(struct domain *d, struct xen_domctl_shadow_op *sc)
return rv;
out:
+ d->arch.paging.preempt.dom = NULL;
paging_unlock(d);
domain_unpause(d);
@@ -469,12 +591,8 @@ void paging_log_dirty_range(struct domain *d,
p2m_lock(p2m);
for ( i = 0, pfn = begin_pfn; pfn < begin_pfn + nr; i++, pfn++ )
- {
- p2m_type_t pt;
- pt = p2m_change_type(d, pfn, p2m_ram_rw, p2m_ram_logdirty);
- if ( pt == p2m_ram_rw )
+ if ( !p2m_change_type_one(d, pfn, p2m_ram_rw, p2m_ram_logdirty) )
dirty_bitmap[i >> 3] |= (1 << (i & 7));
- }
p2m_unlock(p2m);
@@ -499,12 +617,6 @@ void paging_log_dirty_init(struct domain *d,
d->arch.paging.log_dirty.clean_dirty_bitmap = clean_dirty_bitmap;
}
-/* This function fress log dirty bitmap resources. */
-static void paging_log_dirty_teardown(struct domain*d)
-{
- paging_free_log_dirty_bitmap(d);
-}
-
/************************************************/
/* CODE FOR PAGING SUPPORT */
/************************************************/
@@ -546,7 +658,7 @@ void paging_vcpu_init(struct vcpu *v)
int paging_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
- XEN_GUEST_HANDLE_PARAM(void) u_domctl)
+ XEN_GUEST_HANDLE_PARAM(void) u_domctl, bool_t resuming)
{
int rc;
@@ -570,6 +682,20 @@ int paging_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
return -EINVAL;
}
+ if ( resuming
+ ? (d->arch.paging.preempt.dom != current->domain ||
+ d->arch.paging.preempt.op != sc->op)
+ : (d->arch.paging.preempt.dom &&
+ sc->op != XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION) )
+ {
+ printk(XENLOG_G_DEBUG
+ "%pv: Paging op %#x on Dom%u with unfinished prior op %#x by Dom%u\n",
+ current, sc->op, d->domain_id, d->arch.paging.preempt.op,
+ d->arch.paging.preempt.dom
+ ? d->arch.paging.preempt.dom->domain_id : DOMID_INVALID);
+ return -EBUSY;
+ }
+
rc = xsm_shadow_control(XSM_HOOK, d, sc->op);
if ( rc )
return rc;
@@ -589,19 +715,16 @@ int paging_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
break;
/* Else fall through... */
case XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY:
- if ( hap_enabled(d) )
- hap_logdirty_init(d);
return paging_log_dirty_enable(d, 1);
case XEN_DOMCTL_SHADOW_OP_OFF:
- if ( paging_mode_log_dirty(d) )
- if ( (rc = paging_log_dirty_disable(d)) != 0 )
- return rc;
+ if ( (rc = paging_log_dirty_disable(d, resuming)) != 0 )
+ return rc;
break;
case XEN_DOMCTL_SHADOW_OP_CLEAN:
case XEN_DOMCTL_SHADOW_OP_PEEK:
- return paging_log_dirty_op(d, sc);
+ return paging_log_dirty_op(d, sc, resuming);
}
/* Here, dispatch domctl to the appropriate paging code */
@@ -611,19 +734,67 @@ int paging_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
return shadow_domctl(d, sc, u_domctl);
}
+long paging_domctl_continuation(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
+{
+ struct xen_domctl op;
+ struct domain *d;
+ int ret;
+
+ if ( copy_from_guest(&op, u_domctl, 1) )
+ return -EFAULT;
+
+ if ( op.interface_version != XEN_DOMCTL_INTERFACE_VERSION ||
+ op.cmd != XEN_DOMCTL_shadow_op )
+ return -EBADRQC;
+
+ d = rcu_lock_domain_by_id(op.domain);
+ if ( d == NULL )
+ return -ESRCH;
+
+ ret = xsm_domctl(XSM_OTHER, d, op.cmd);
+ if ( !ret )
+ {
+ if ( domctl_lock_acquire() )
+ {
+ ret = paging_domctl(d, &op.u.shadow_op,
+ guest_handle_cast(u_domctl, void), 1);
+
+ domctl_lock_release();
+ }
+ else
+ ret = -ERESTART;
+ }
+
+ rcu_unlock_domain(d);
+
+ if ( ret == -ERESTART )
+ ret = hypercall_create_continuation(__HYPERVISOR_arch_1,
+ "h", u_domctl);
+ else if ( __copy_field_to_guest(u_domctl, &op, u.shadow_op) )
+ ret = -EFAULT;
+
+ return ret;
+}
+
/* Call when destroying a domain */
-void paging_teardown(struct domain *d)
+int paging_teardown(struct domain *d)
{
+ int rc;
+
if ( hap_enabled(d) )
hap_teardown(d);
else
shadow_teardown(d);
/* clean up log dirty resources. */
- paging_log_dirty_teardown(d);
+ rc = paging_free_log_dirty_bitmap(d, 0);
+ if ( rc == -ERESTART )
+ return rc;
/* Move populate-on-demand cache back to domain_list for destruction */
p2m_pod_empty_cache(d);
+
+ return rc;
}
/* Call once all of the references to the domain have gone away */
@@ -724,18 +895,15 @@ void paging_update_nestedmode(struct vcpu *v)
}
void paging_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
- l1_pgentry_t *p, mfn_t table_mfn,
- l1_pgentry_t new, unsigned int level)
+ l1_pgentry_t *p, l1_pgentry_t new,
+ unsigned int level)
{
struct domain *d = p2m->domain;
struct vcpu *v = current;
if ( v->domain != d )
v = d->vcpu ? d->vcpu[0] : NULL;
if ( likely(v && paging_mode_enabled(d) && paging_get_hostmode(v) != NULL) )
- {
- return paging_get_hostmode(v)->write_p2m_entry(v, gfn, p, table_mfn,
- new, level);
- }
+ paging_get_hostmode(v)->write_p2m_entry(d, gfn, p, new, level);
else
safe_write_pte(p, new);
}
diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
index be095f6..a5eed28 100644
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -366,6 +366,7 @@ const struct x86_emulate_ops *shadow_init_emulation(
sh_ctxt->ctxt.regs = regs;
sh_ctxt->ctxt.force_writeback = 0;
+ sh_ctxt->ctxt.swint_emulate = x86_swint_emulate_none;
if ( is_pv_vcpu(v) )
{
@@ -786,8 +787,7 @@ static void oos_hash_remove(struct vcpu *v, mfn_t gmfn)
mfn_t *oos;
struct domain *d = v->domain;
- SHADOW_PRINTK("D%dV%d gmfn %lx\n",
- v->domain->domain_id, v->vcpu_id, mfn_x(gmfn));
+ SHADOW_PRINTK("%pv gmfn %lx\n", v, mfn_x(gmfn));
for_each_vcpu(d, v)
{
@@ -875,7 +875,6 @@ static int sh_skip_sync(struct vcpu *v, mfn_t gl1mfn)
SHADOW_ERROR("gmfn %#lx was OOS but not shadowed as an l1.\n",
mfn_x(gl1mfn));
BUG();
- return 0; /* BUG() is no longer __attribute__((noreturn)). */
}
@@ -3312,11 +3311,14 @@ static int shadow_test_disable(struct domain *d)
* shadow processing jobs.
*/
-static void sh_unshadow_for_p2m_change(struct vcpu *v, unsigned long gfn,
- l1_pgentry_t *p, mfn_t table_mfn,
- l1_pgentry_t new, unsigned int level)
+static void sh_unshadow_for_p2m_change(struct domain *d, unsigned long gfn,
+ l1_pgentry_t *p, l1_pgentry_t new,
+ unsigned int level)
{
- struct domain *d = v->domain;
+ struct vcpu *v = current;
+
+ if ( v->domain != d )
+ v = d->vcpu ? d->vcpu[0] : NULL;
/* The following assertion is to make sure we don't step on 1GB host
* page support of HVM guest. */
@@ -3381,18 +3383,16 @@ static void sh_unshadow_for_p2m_change(struct vcpu *v, unsigned long gfn,
}
void
-shadow_write_p2m_entry(struct vcpu *v, unsigned long gfn,
- l1_pgentry_t *p, mfn_t table_mfn,
- l1_pgentry_t new, unsigned int level)
+shadow_write_p2m_entry(struct domain *d, unsigned long gfn,
+ l1_pgentry_t *p, l1_pgentry_t new,
+ unsigned int level)
{
- struct domain *d = v->domain;
-
paging_lock(d);
/* If there are any shadows, update them. But if shadow_teardown()
* has already been called then it's not safe to try. */
if ( likely(d->arch.paging.shadow.total_pages != 0) )
- sh_unshadow_for_p2m_change(v, gfn, p, table_mfn, new, level);
+ sh_unshadow_for_p2m_change(d, gfn, p, new, level);
/* Update the entry with new content */
safe_write_pte(p, new);
@@ -3486,7 +3486,7 @@ int shadow_track_dirty_vram(struct domain *d,
int flush_tlb = 0;
unsigned long i;
p2m_type_t t;
- struct sh_dirty_vram *dirty_vram = d->arch.hvm_domain.dirty_vram;
+ struct sh_dirty_vram *dirty_vram;
struct p2m_domain *p2m = p2m_get_hostp2m(d);
if ( end_pfn < begin_pfn || end_pfn > p2m->max_mapped_pfn + 1 )
@@ -3496,6 +3496,8 @@ int shadow_track_dirty_vram(struct domain *d,
p2m_lock(p2m_get_hostp2m(d));
paging_lock(d);
+ dirty_vram = d->arch.hvm_domain.dirty_vram;
+
if ( dirty_vram && (!nr ||
( begin_pfn != dirty_vram->begin_pfn
|| end_pfn != dirty_vram->end_pfn )) )
diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
index 3d35537..225290e 100644
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -592,6 +592,8 @@ _sh_propagate(struct vcpu *v,
{
unsigned int type;
+ ASSERT(!(sflags & (_PAGE_PAT | _PAGE_PCD | _PAGE_PWT)));
+
/* compute the PAT index for shadow page entry when VT-d is enabled
* and device assigned.
* 1) direct MMIO: compute the PAT index with gMTRR=UC and gPAT.
@@ -599,7 +601,7 @@ _sh_propagate(struct vcpu *v,
* 3) if disables snoop control, compute the PAT index with
* gMTRR and gPAT.
*/
- if ( hvm_get_mem_pinned_cacheattr(d, gfn_x(target_gfn), &type) )
+ if ( hvm_get_mem_pinned_cacheattr(d, gfn_x(target_gfn), 0, &type) )
sflags |= pat_type_2_pte_flags(type);
else if ( d->arch.hvm_domain.is_in_uc_mode )
sflags |= pat_type_2_pte_flags(PAT_TYPE_UNCACHABLE);
@@ -692,21 +694,7 @@ _sh_propagate(struct vcpu *v,
&& (ft == ft_demand_write))
#endif /* OOS */
) )
- {
- if ( shadow_mode_trap_reads(d) )
- {
- // if we are trapping both reads & writes, then mark this page
- // as not present...
- //
- sflags &= ~_PAGE_PRESENT;
- }
- else
- {
- // otherwise, just prevent any writes...
- //
- sflags &= ~_PAGE_RW;
- }
- }
+ sflags &= ~_PAGE_RW;
// PV guests in 64-bit mode use two different page tables for user vs
// supervisor permissions, making the guest's _PAGE_USER bit irrelevant.
@@ -816,7 +804,6 @@ shadow_write_entries(void *d, void *s, int entries, mfn_t mfn)
{
perfc_incr(shadow_linear_map_failed);
map = sh_map_domain_page(mfn);
- ASSERT(map != NULL);
dst = map + ((unsigned long)dst & (PAGE_SIZE - 1));
}
@@ -1436,8 +1423,7 @@ void sh_install_xen_entries_in_l4(struct vcpu *v, mfn_t gl4mfn, mfn_t sl4mfn)
unsigned int slots;
sl4e = sh_map_domain_page(sl4mfn);
- ASSERT(sl4e != NULL);
- ASSERT(sizeof (l4_pgentry_t) == sizeof (shadow_l4e_t));
+ BUILD_BUG_ON(sizeof (l4_pgentry_t) != sizeof (shadow_l4e_t));
/* Copy the common Xen mappings from the idle domain */
slots = (shadow_mode_external(d)
@@ -1490,8 +1476,7 @@ static void sh_install_xen_entries_in_l2h(struct vcpu *v, mfn_t sl2hmfn)
return;
sl2e = sh_map_domain_page(sl2hmfn);
- ASSERT(sl2e != NULL);
- ASSERT(sizeof (l2_pgentry_t) == sizeof (shadow_l2e_t));
+ BUILD_BUG_ON(sizeof (l2_pgentry_t) != sizeof (shadow_l2e_t));
/* Copy the common Xen mappings from the idle domain */
memcpy(
@@ -2712,13 +2697,13 @@ static inline void trace_shadow_fixup(guest_l1e_t gl1e,
{
if ( tb_init_done )
{
- struct {
+ struct __packed {
/* for PAE, guest_l1e may be 64 while guest_va may be 32;
so put it first for alignment sake. */
guest_l1e_t gl1e;
guest_va_t va;
u32 flags;
- } __attribute__((packed)) d;
+ } d;
u32 event;
event = TRC_SHADOW_FIXUP | ((GUEST_PAGING_LEVELS-2)<<8);
@@ -2736,13 +2721,13 @@ static inline void trace_not_shadow_fault(guest_l1e_t gl1e,
{
if ( tb_init_done )
{
- struct {
+ struct __packed {
/* for PAE, guest_l1e may be 64 while guest_va may be 32;
so put it first for alignment sake. */
guest_l1e_t gl1e;
guest_va_t va;
u32 flags;
- } __attribute__((packed)) d;
+ } d;
u32 event;
event = TRC_SHADOW_NOT_SHADOW | ((GUEST_PAGING_LEVELS-2)<<8);
@@ -2761,7 +2746,7 @@ static inline void trace_shadow_emulate_other(u32 event,
{
if ( tb_init_done )
{
- struct {
+ struct __packed {
/* for PAE, guest_l1e may be 64 while guest_va may be 32;
so put it first for alignment sake. */
#if GUEST_PAGING_LEVELS == 2
@@ -2770,7 +2755,7 @@ static inline void trace_shadow_emulate_other(u32 event,
u64 gfn;
#endif
guest_va_t va;
- } __attribute__((packed)) d;
+ } d;
event |= ((GUEST_PAGING_LEVELS-2)<<8);
@@ -2791,13 +2776,13 @@ static inline void trace_shadow_emulate(guest_l1e_t gl1e, unsigned long va)
{
if ( tb_init_done )
{
- struct {
+ struct __packed {
/* for PAE, guest_l1e may be 64 while guest_va may be 32;
so put it first for alignment sake. */
guest_l1e_t gl1e, write_val;
guest_va_t va;
unsigned flags:29, emulation_count:3;
- } __attribute__((packed)) d;
+ } d;
u32 event;
event = TRC_SHADOW_EMULATE | ((GUEST_PAGING_LEVELS-2)<<8);
@@ -2839,6 +2824,11 @@ static int sh_page_fault(struct vcpu *v,
p2m_type_t p2mt;
uint32_t rc;
int version;
+ struct npfec access = {
+ .read_access = 1,
+ .gla_valid = 1,
+ .kind = npfec_kind_with_gla
+ };
#if SHADOW_OPTIMIZATIONS & SHOPT_FAST_EMULATION
int fast_emul = 0;
#endif
@@ -2849,6 +2839,9 @@ static int sh_page_fault(struct vcpu *v,
perfc_incr(shadow_fault);
+ if ( regs->error_code & PFEC_write_access )
+ access.write_access = 1;
+
#if SHADOW_OPTIMIZATIONS & SHOPT_FAST_EMULATION
/* If faulting frame is successfully emulated in last shadow fault
* it's highly likely to reach same emulation action for this frame.
@@ -2950,7 +2943,7 @@ static int sh_page_fault(struct vcpu *v,
SHADOW_PRINTK("fast path mmio %#"PRIpaddr"\n", gpa);
reset_early_unshadow(v);
trace_shadow_gen(TRC_SHADOW_FAST_MMIO, va);
- return (handle_mmio_with_translation(va, gpa >> PAGE_SHIFT)
+ return (handle_mmio_with_translation(va, gpa >> PAGE_SHIFT, access)
? EXCRET_fault_fixed : 0);
}
else
@@ -3181,18 +3174,10 @@ static int sh_page_fault(struct vcpu *v,
&& !(mfn_is_out_of_sync(gmfn)
&& !(regs->error_code & PFEC_user_mode))
#endif
- )
+ && (ft == ft_demand_write) )
{
- if ( ft == ft_demand_write )
- {
- perfc_incr(shadow_fault_emulate_write);
- goto emulate;
- }
- else if ( shadow_mode_trap_reads(d) && ft == ft_demand_read )
- {
- perfc_incr(shadow_fault_emulate_read);
- goto emulate;
- }
+ perfc_incr(shadow_fault_emulate_write);
+ goto emulate;
}
/* Need to hand off device-model MMIO to the device model */
@@ -3447,7 +3432,7 @@ static int sh_page_fault(struct vcpu *v,
paging_unlock(d);
put_gfn(d, gfn_x(gfn));
trace_shadow_gen(TRC_SHADOW_MMIO, va);
- return (handle_mmio_with_translation(va, gpa >> PAGE_SHIFT)
+ return (handle_mmio_with_translation(va, gpa >> PAGE_SHIFT, access)
? EXCRET_fault_fixed : 0);
not_a_shadow_fault:
diff --git a/xen/arch/x86/mm/shadow/private.h b/xen/arch/x86/mm/shadow/private.h
index 58844f1..b778fcf 100644
--- a/xen/arch/x86/mm/shadow/private.h
+++ b/xen/arch/x86/mm/shadow/private.h
@@ -359,9 +359,9 @@ extern int sh_remove_write_access(struct vcpu *v, mfn_t readonly_mfn,
unsigned long fault_addr);
/* Functions that atomically write PT/P2M entries and update state */
-void shadow_write_p2m_entry(struct vcpu *v, unsigned long gfn,
- l1_pgentry_t *p, mfn_t table_mfn,
- l1_pgentry_t new, unsigned int level);
+void shadow_write_p2m_entry(struct domain *d, unsigned long gfn,
+ l1_pgentry_t *p, l1_pgentry_t new,
+ unsigned int level);
int shadow_write_guest_entry(struct vcpu *v, intpte_t *p,
intpte_t new, mfn_t gmfn);
int shadow_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p,
diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c
index 61d6dd0..14d37ec 100644
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -496,15 +496,8 @@ int __setup_msi_irq(struct irq_desc *desc, struct msi_desc *msidesc,
int msi_free_irq(struct msi_desc *entry)
{
- unsigned int nr = entry->msi.nvec;
-
- if ( entry->msi_attrib.type == PCI_CAP_ID_MSIX )
- {
- unsigned long start;
- start = (unsigned long)entry->mask_base & ~(PAGE_SIZE - 1);
- msix_put_fixmap(entry->dev->msix, virt_to_fix(start));
- nr = 1;
- }
+ unsigned int nr = entry->msi_attrib.type != PCI_CAP_ID_MSIX
+ ? entry->msi.nvec : 1;
while ( nr-- )
{
@@ -515,6 +508,10 @@ int msi_free_irq(struct msi_desc *entry)
iommu_update_ire_from_msi(entry + nr, NULL);
}
+ if ( entry->msi_attrib.type == PCI_CAP_ID_MSIX )
+ msix_put_fixmap(entry->dev->msix,
+ virt_to_fix((unsigned long)entry->mask_base));
+
list_del(&entry->list);
xfree(entry);
return 0;
@@ -825,32 +822,22 @@ static int msix_capability_init(struct pci_dev *dev,
msix->pba.last) )
WARN();
- if ( dev->domain )
- p2m_change_entry_type_global(dev->domain,
- p2m_mmio_direct, p2m_mmio_direct);
- if ( desc && (!dev->domain || !paging_mode_translate(dev->domain)) )
+ if ( desc )
{
- struct domain *d = dev->domain;
-
- if ( !d )
- for_each_domain(d)
- if ( !paging_mode_translate(d) &&
- (iomem_access_permitted(d, msix->table.first,
- msix->table.last) ||
- iomem_access_permitted(d, msix->pba.first,
- msix->pba.last)) )
- break;
- if ( d )
- {
- if ( !is_hardware_domain(d) && msix->warned != d->domain_id )
- {
- msix->warned = d->domain_id;
- printk(XENLOG_ERR
- "Potentially insecure use of MSI-X on %04x:%02x:%02x.%u by Dom%d\n",
- seg, bus, slot, func, d->domain_id);
- }
- /* XXX How to deal with existing mappings? */
- }
+ struct domain *currd = current->domain;
+ struct domain *d = dev->domain ?: currd;
+
+ if ( !is_hardware_domain(currd) || d != currd )
+ printk("%s use of MSI-X on %04x:%02x:%02x.%u by Dom%d\n",
+ is_hardware_domain(currd)
+ ? XENLOG_WARNING "Potentially insecure"
+ : XENLOG_ERR "Insecure",
+ seg, bus, slot, func, d->domain_id);
+ if ( !is_hardware_domain(d) &&
+ /* Assume a domain without memory has no mappings yet. */
+ (!is_hardware_domain(currd) || d->tot_pages) )
+ domain_crash(d);
+ /* XXX How to deal with existing mappings? */
}
}
WARN_ON(msix->nr_entries != nr_entries);
diff --git a/xen/arch/x86/nmi.c b/xen/arch/x86/nmi.c
index 7aaab8a..98c1e15 100644
--- a/xen/arch/x86/nmi.c
+++ b/xen/arch/x86/nmi.c
@@ -43,7 +43,32 @@ static DEFINE_PER_CPU(unsigned int, nmi_timer_ticks);
/* opt_watchdog: If true, run a watchdog NMI on each processor. */
bool_t __initdata opt_watchdog = 0;
-boolean_param("watchdog", opt_watchdog);
+
+/* watchdog_force: If true, process unknown NMIs when running the watchdog. */
+bool_t watchdog_force = 0;
+
+static void __init parse_watchdog(char *s)
+{
+ if ( !*s )
+ {
+ opt_watchdog = 1;
+ return;
+ }
+
+ switch ( parse_bool(s) )
+ {
+ case 0:
+ opt_watchdog = 0;
+ return;
+ case 1:
+ opt_watchdog = 1;
+ return;
+ }
+
+ if ( !strcmp(s, "force") )
+ watchdog_force = opt_watchdog = 1;
+}
+custom_param("watchdog", parse_watchdog);
/* opt_watchdog_timeout: Number of seconds to wait before panic. */
static unsigned int opt_watchdog_timeout = 5;
@@ -82,6 +107,7 @@ int nmi_active;
#define K7_EVNTSEL_USR (1 << 16)
#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76
#define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
+#define K7_EVENT_WIDTH 32
#define P6_EVNTSEL0_ENABLE (1 << 22)
#define P6_EVNTSEL_INT (1 << 20)
@@ -89,10 +115,12 @@ int nmi_active;
#define P6_EVNTSEL_USR (1 << 16)
#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79
#define CORE_EVENT_CPU_CLOCKS_NOT_HALTED 0x3c
+#define P6_EVENT_WIDTH 32
#define P4_ESCR_EVENT_SELECT(N) ((N)<<25)
#define P4_CCCR_OVF_PMI0 (1<<26)
#define P4_CCCR_OVF_PMI1 (1<<27)
+#define P4_CCCR_OVF (1<<31)
#define P4_CCCR_THRESHOLD(N) ((N)<<20)
#define P4_CCCR_COMPLEMENT (1<<19)
#define P4_CCCR_COMPARE (1<<18)
@@ -127,7 +155,6 @@ int __init check_nmi_watchdog (void)
for_each_online_cpu ( cpu )
prev_nmi_count[cpu] = nmi_count(cpu);
- local_irq_enable();
/* Wait for 10 ticks. Busy-wait on all CPUs: the LAPIC counter that
* the NMI watchdog uses only runs while the core's not halted */
@@ -178,7 +205,7 @@ void disable_lapic_nmi_watchdog(void)
case X86_VENDOR_INTEL:
switch (boot_cpu_data.x86) {
case 6:
- wrmsr(MSR_P6_EVNTSEL0, 0, 0);
+ wrmsr(MSR_P6_EVNTSEL(0), 0, 0);
break;
case 15:
wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
@@ -277,21 +304,21 @@ static void __pminit setup_p6_watchdog(unsigned counter)
{
unsigned int evntsel;
- nmi_perfctr_msr = MSR_P6_PERFCTR0;
+ nmi_perfctr_msr = MSR_P6_PERFCTR(0);
- clear_msr_range(MSR_P6_EVNTSEL0, 2);
- clear_msr_range(MSR_P6_PERFCTR0, 2);
+ clear_msr_range(MSR_P6_EVNTSEL(0), 2);
+ clear_msr_range(MSR_P6_PERFCTR(0), 2);
evntsel = P6_EVNTSEL_INT
| P6_EVNTSEL_OS
| P6_EVNTSEL_USR
| counter;
- wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
+ wrmsr(MSR_P6_EVNTSEL(0), evntsel, 0);
write_watchdog_counter("P6_PERFCTR0");
apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= P6_EVNTSEL0_ENABLE;
- wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
+ wrmsr(MSR_P6_EVNTSEL(0), evntsel, 0);
}
static int __pminit setup_p4_watchdog(void)
@@ -433,8 +460,10 @@ int __init watchdog_setup(void)
return 0;
}
-void nmi_watchdog_tick(struct cpu_user_regs * regs)
+/* Returns false if this was not a watchdog NMI, true otherwise */
+bool_t nmi_watchdog_tick(const struct cpu_user_regs *regs)
{
+ bool_t watchdog_tick = 1;
unsigned int sum = this_cpu(nmi_timer_ticks);
if ( (this_cpu(last_irq_sums) == sum) && watchdog_enabled() )
@@ -449,7 +478,7 @@ void nmi_watchdog_tick(struct cpu_user_regs * regs)
console_force_unlock();
printk("Watchdog timer detects that CPU%d is stuck!\n",
smp_processor_id());
- fatal_trap(TRAP_nmi, regs);
+ fatal_trap(regs);
}
}
else
@@ -460,8 +489,15 @@ void nmi_watchdog_tick(struct cpu_user_regs * regs)
if ( nmi_perfctr_msr )
{
+ uint64_t msr_content;
+
+ /* Work out if this is a watchdog tick by checking for overflow. */
if ( nmi_perfctr_msr == MSR_P4_IQ_PERFCTR0 )
{
+ rdmsrl(MSR_P4_IQ_CCCR0, msr_content);
+ if ( !(msr_content & P4_CCCR_OVF) )
+ watchdog_tick = 0;
+
/*
* P4 quirks:
* - An overflown perfctr will assert its interrupt
@@ -472,16 +508,28 @@ void nmi_watchdog_tick(struct cpu_user_regs * regs)
wrmsrl(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val);
apic_write(APIC_LVTPC, APIC_DM_NMI);
}
- else if ( nmi_perfctr_msr == MSR_P6_PERFCTR0 )
+ else if ( nmi_perfctr_msr == MSR_P6_PERFCTR(0) )
{
+ rdmsrl(MSR_P6_PERFCTR(0), msr_content);
+ if ( msr_content & (1ULL << P6_EVENT_WIDTH) )
+ watchdog_tick = 0;
+
/*
* Only P6 based Pentium M need to re-unmask the apic vector but
* it doesn't hurt other P6 variants.
*/
apic_write(APIC_LVTPC, APIC_DM_NMI);
}
+ else if ( nmi_perfctr_msr == MSR_K7_PERFCTR0 )
+ {
+ rdmsrl(MSR_K7_PERFCTR0, msr_content);
+ if ( msr_content & (1ULL << K7_EVENT_WIDTH) )
+ watchdog_tick = 0;
+ }
write_watchdog_counter(NULL);
}
+
+ return watchdog_tick;
}
/*
@@ -521,7 +569,7 @@ static void do_nmi_stats(unsigned char key)
for_each_online_cpu ( i )
printk("%3d\t%3d\n", i, nmi_count(i));
- if ( ((d = dom0) == NULL) || (d->vcpu == NULL) ||
+ if ( ((d = hardware_domain) == NULL) || (d->vcpu == NULL) ||
((v = d->vcpu[0]) == NULL) )
return;
diff --git a/xen/arch/x86/numa.c b/xen/arch/x86/numa.c
index b141877..628a40a 100644
--- a/xen/arch/x86/numa.c
+++ b/xen/arch/x86/numa.c
@@ -36,13 +36,13 @@ unsigned long memnodemapsize;
u8 *memnodemap;
unsigned char cpu_to_node[NR_CPUS] __read_mostly = {
- [0 ... NR_CPUS-1] = NUMA_NO_NODE
+ [0 ... NR_CPUS-1] = NUMA_NO_NODE
};
/*
* Keep BIOS's CPU2node information, should not be used for memory allocaion
*/
unsigned char apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
- [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
+ [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
};
cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly;
@@ -54,7 +54,7 @@ int acpi_numa __devinitdata;
int srat_disabled(void)
{
- return numa_off || acpi_numa < 0;
+ return numa_off || acpi_numa < 0;
}
/*
@@ -67,53 +67,56 @@ int srat_disabled(void)
static int __init populate_memnodemap(const struct node *nodes,
int numnodes, int shift, int *nodeids)
{
- unsigned long spdx, epdx;
- int i, res = -1;
-
- memset(memnodemap, NUMA_NO_NODE, memnodemapsize * sizeof(*memnodemap));
- for (i = 0; i < numnodes; i++) {
- spdx = paddr_to_pdx(nodes[i].start);
- epdx = paddr_to_pdx(nodes[i].end - 1) + 1;
- if (spdx >= epdx)
- continue;
- if ((epdx >> shift) >= memnodemapsize)
- return 0;
- do {
- if (memnodemap[spdx >> shift] != NUMA_NO_NODE)
- return -1;
-
- if (!nodeids)
- memnodemap[spdx >> shift] = i;
- else
- memnodemap[spdx >> shift] = nodeids[i];
-
- spdx += (1UL << shift);
- } while (spdx < epdx);
- res = 1;
- }
- return res;
+ unsigned long spdx, epdx;
+ int i, res = -1;
+
+ memset(memnodemap, NUMA_NO_NODE, memnodemapsize * sizeof(*memnodemap));
+ for ( i = 0; i < numnodes; i++ )
+ {
+ spdx = paddr_to_pdx(nodes[i].start);
+ epdx = paddr_to_pdx(nodes[i].end - 1) + 1;
+ if ( spdx >= epdx )
+ continue;
+ if ( (epdx >> shift) >= memnodemapsize )
+ return 0;
+ do {
+ if ( memnodemap[spdx >> shift] != NUMA_NO_NODE )
+ return -1;
+
+ if ( !nodeids )
+ memnodemap[spdx >> shift] = i;
+ else
+ memnodemap[spdx >> shift] = nodeids[i];
+
+ spdx += (1UL << shift);
+ } while ( spdx < epdx );
+ res = 1;
+ }
+
+ return res;
}
static int __init allocate_cachealigned_memnodemap(void)
{
- unsigned long size = PFN_UP(memnodemapsize * sizeof(*memnodemap));
- unsigned long mfn = alloc_boot_pages(size, 1);
-
- if (!mfn) {
- printk(KERN_ERR
- "NUMA: Unable to allocate Memory to Node hash map\n");
- memnodemapsize = 0;
- return -1;
- }
-
- memnodemap = mfn_to_virt(mfn);
- mfn <<= PAGE_SHIFT;
- size <<= PAGE_SHIFT;
- printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
- mfn, mfn + size);
- memnodemapsize = size / sizeof(*memnodemap);
-
- return 0;
+ unsigned long size = PFN_UP(memnodemapsize * sizeof(*memnodemap));
+ unsigned long mfn = alloc_boot_pages(size, 1);
+
+ if ( !mfn )
+ {
+ printk(KERN_ERR
+ "NUMA: Unable to allocate Memory to Node hash map\n");
+ memnodemapsize = 0;
+ return -1;
+ }
+
+ memnodemap = mfn_to_virt(mfn);
+ mfn <<= PAGE_SHIFT;
+ size <<= PAGE_SHIFT;
+ printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
+ mfn, mfn + size);
+ memnodemapsize = size / sizeof(*memnodemap);
+
+ return 0;
}
/*
@@ -121,84 +124,87 @@ static int __init allocate_cachealigned_memnodemap(void)
* maximum possible shift.
*/
static int __init extract_lsb_from_nodes(const struct node *nodes,
- int numnodes)
+ int numnodes)
{
- int i, nodes_used = 0;
- unsigned long spdx, epdx;
- unsigned long bitfield = 0, memtop = 0;
-
- for (i = 0; i < numnodes; i++) {
- spdx = paddr_to_pdx(nodes[i].start);
- epdx = paddr_to_pdx(nodes[i].end - 1) + 1;
- if (spdx >= epdx)
- continue;
- bitfield |= spdx;
- nodes_used++;
- if (epdx > memtop)
- memtop = epdx;
- }
- if (nodes_used <= 1)
- i = BITS_PER_LONG - 1;
- else
- i = find_first_bit(&bitfield, sizeof(unsigned long)*8);
- memnodemapsize = (memtop >> i) + 1;
- return i;
+ int i, nodes_used = 0;
+ unsigned long spdx, epdx;
+ unsigned long bitfield = 0, memtop = 0;
+
+ for ( i = 0; i < numnodes; i++ )
+ {
+ spdx = paddr_to_pdx(nodes[i].start);
+ epdx = paddr_to_pdx(nodes[i].end - 1) + 1;
+ if ( spdx >= epdx )
+ continue;
+ bitfield |= spdx;
+ nodes_used++;
+ if ( epdx > memtop )
+ memtop = epdx;
+ }
+ if ( nodes_used <= 1 )
+ i = BITS_PER_LONG - 1;
+ else
+ i = find_first_bit(&bitfield, sizeof(unsigned long)*8);
+ memnodemapsize = (memtop >> i) + 1;
+ return i;
}
int __init compute_hash_shift(struct node *nodes, int numnodes,
- int *nodeids)
+ int *nodeids)
{
- int shift;
-
- shift = extract_lsb_from_nodes(nodes, numnodes);
- if (memnodemapsize <= ARRAY_SIZE(_memnodemap))
- memnodemap = _memnodemap;
- else if (allocate_cachealigned_memnodemap())
- return -1;
- printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n",
- shift);
-
- if (populate_memnodemap(nodes, numnodes, shift, nodeids) != 1) {
- printk(KERN_INFO "Your memory is not aligned you need to "
- "rebuild your kernel with a bigger NODEMAPSIZE "
- "shift=%d\n", shift);
- return -1;
- }
- return shift;
+ int shift;
+
+ shift = extract_lsb_from_nodes(nodes, numnodes);
+ if ( memnodemapsize <= ARRAY_SIZE(_memnodemap) )
+ memnodemap = _memnodemap;
+ else if ( allocate_cachealigned_memnodemap() )
+ return -1;
+ printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n", shift);
+
+ if ( populate_memnodemap(nodes, numnodes, shift, nodeids) != 1 )
+ {
+ printk(KERN_INFO "Your memory is not aligned you need to "
+ "rebuild your hypervisor with a bigger NODEMAPSIZE "
+ "shift=%d\n", shift);
+ return -1;
+ }
+
+ return shift;
}
/* initialize NODE_DATA given nodeid and start/end */
void __init setup_node_bootmem(int nodeid, u64 start, u64 end)
{
- unsigned long start_pfn, end_pfn;
+ unsigned long start_pfn, end_pfn;
- start_pfn = start >> PAGE_SHIFT;
- end_pfn = end >> PAGE_SHIFT;
+ start_pfn = start >> PAGE_SHIFT;
+ end_pfn = end >> PAGE_SHIFT;
- NODE_DATA(nodeid)->node_id = nodeid;
- NODE_DATA(nodeid)->node_start_pfn = start_pfn;
- NODE_DATA(nodeid)->node_spanned_pages = end_pfn - start_pfn;
+ NODE_DATA(nodeid)->node_id = nodeid;
+ NODE_DATA(nodeid)->node_start_pfn = start_pfn;
+ NODE_DATA(nodeid)->node_spanned_pages = end_pfn - start_pfn;
- node_set_online(nodeid);
+ node_set_online(nodeid);
}
void __init numa_init_array(void)
{
- int rr, i;
- /* There are unfortunately some poorly designed mainboards around
- that only connect memory to a single CPU. This breaks the 1:1 cpu->node
- mapping. To avoid this fill in the mapping for all possible
- CPUs, as the number of CPUs is not known yet.
- We round robin the existing nodes. */
- rr = first_node(node_online_map);
- for (i = 0; i < nr_cpu_ids; i++) {
- if (cpu_to_node[i] != NUMA_NO_NODE)
- continue;
- numa_set_node(i, rr);
- rr = next_node(rr, node_online_map);
- if (rr == MAX_NUMNODES)
- rr = first_node(node_online_map);
- }
-
+ int rr, i;
+
+ /* There are unfortunately some poorly designed mainboards around
+ that only connect memory to a single CPU. This breaks the 1:1 cpu->node
+ mapping. To avoid this fill in the mapping for all possible
+ CPUs, as the number of CPUs is not known yet.
+ We round robin the existing nodes. */
+ rr = first_node(node_online_map);
+ for ( i = 0; i < nr_cpu_ids; i++ )
+ {
+ if ( cpu_to_node[i] != NUMA_NO_NODE )
+ continue;
+ numa_set_node(i, rr);
+ rr = next_node(rr, node_online_map);
+ if ( rr == MAX_NUMNODES )
+ rr = first_node(node_online_map);
+ }
}
#ifdef CONFIG_NUMA_EMU
@@ -207,109 +213,117 @@ static int numa_fake __initdata = 0;
/* Numa emulation */
static int __init numa_emulation(u64 start_pfn, u64 end_pfn)
{
- int i;
- struct node nodes[MAX_NUMNODES];
- u64 sz = ((end_pfn - start_pfn)<<PAGE_SHIFT) / numa_fake;
-
- /* Kludge needed for the hash function */
- if (hweight64(sz) > 1) {
- u64 x = 1;
- while ((x << 1) < sz)
- x <<= 1;
- if (x < sz/2)
- printk(KERN_ERR "Numa emulation unbalanced. Complain to maintainer\n");
- sz = x;
- }
-
- memset(&nodes,0,sizeof(nodes));
- for (i = 0; i < numa_fake; i++) {
- nodes[i].start = (start_pfn<<PAGE_SHIFT) + i*sz;
- if (i == numa_fake-1)
- sz = (end_pfn<<PAGE_SHIFT) - nodes[i].start;
- nodes[i].end = nodes[i].start + sz;
- printk(KERN_INFO "Faking node %d at %"PRIx64"-%"PRIx64" (%"PRIu64"MB)\n",
- i,
- nodes[i].start, nodes[i].end,
- (nodes[i].end - nodes[i].start) >> 20);
- node_set_online(i);
- }
- memnode_shift = compute_hash_shift(nodes, numa_fake, NULL);
- if (memnode_shift < 0) {
- memnode_shift = 0;
- printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n");
- return -1;
- }
- for_each_online_node(i)
- setup_node_bootmem(i, nodes[i].start, nodes[i].end);
- numa_init_array();
- return 0;
+ int i;
+ struct node nodes[MAX_NUMNODES];
+ u64 sz = ((end_pfn - start_pfn)<<PAGE_SHIFT) / numa_fake;
+
+ /* Kludge needed for the hash function */
+ if ( hweight64(sz) > 1 )
+ {
+ u64 x = 1;
+ while ( (x << 1) < sz )
+ x <<= 1;
+ if ( x < sz/2 )
+ printk(KERN_ERR "Numa emulation unbalanced. Complain to maintainer\n");
+ sz = x;
+ }
+
+ memset(&nodes,0,sizeof(nodes));
+ for ( i = 0; i < numa_fake; i++ )
+ {
+ nodes[i].start = (start_pfn<<PAGE_SHIFT) + i*sz;
+ if ( i == numa_fake - 1 )
+ sz = (end_pfn<<PAGE_SHIFT) - nodes[i].start;
+ nodes[i].end = nodes[i].start + sz;
+ printk(KERN_INFO "Faking node %d at %"PRIx64"-%"PRIx64" (%"PRIu64"MB)\n",
+ i,
+ nodes[i].start, nodes[i].end,
+ (nodes[i].end - nodes[i].start) >> 20);
+ node_set_online(i);
+ }
+ memnode_shift = compute_hash_shift(nodes, numa_fake, NULL);
+ if ( memnode_shift < 0 )
+ {
+ memnode_shift = 0;
+ printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n");
+ return -1;
+ }
+ for_each_online_node ( i )
+ setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+ numa_init_array();
+
+ return 0;
}
#endif
void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
{
- int i;
+ int i;
#ifdef CONFIG_NUMA_EMU
- if (numa_fake && !numa_emulation(start_pfn, end_pfn))
- return;
+ if ( numa_fake && !numa_emulation(start_pfn, end_pfn) )
+ return;
#endif
#ifdef CONFIG_ACPI_NUMA
- if (!numa_off && !acpi_scan_nodes((u64)start_pfn << PAGE_SHIFT,
- (u64)end_pfn << PAGE_SHIFT))
- return;
+ if ( !numa_off && !acpi_scan_nodes((u64)start_pfn << PAGE_SHIFT,
+ (u64)end_pfn << PAGE_SHIFT) )
+ return;
#endif
- printk(KERN_INFO "%s\n",
- numa_off ? "NUMA turned off" : "No NUMA configuration found");
-
- printk(KERN_INFO "Faking a node at %016"PRIx64"-%016"PRIx64"\n",
- (u64)start_pfn << PAGE_SHIFT,
- (u64)end_pfn << PAGE_SHIFT);
- /* setup dummy node covering all memory */
- memnode_shift = BITS_PER_LONG - 1;
- memnodemap = _memnodemap;
- nodes_clear(node_online_map);
- node_set_online(0);
- for (i = 0; i < nr_cpu_ids; i++)
- numa_set_node(i, 0);
- cpumask_copy(&node_to_cpumask[0], cpumask_of(0));
- setup_node_bootmem(0, (u64)start_pfn << PAGE_SHIFT, (u64)end_pfn << PAGE_SHIFT);
+ printk(KERN_INFO "%s\n",
+ numa_off ? "NUMA turned off" : "No NUMA configuration found");
+
+ printk(KERN_INFO "Faking a node at %016"PRIx64"-%016"PRIx64"\n",
+ (u64)start_pfn << PAGE_SHIFT,
+ (u64)end_pfn << PAGE_SHIFT);
+ /* setup dummy node covering all memory */
+ memnode_shift = BITS_PER_LONG - 1;
+ memnodemap = _memnodemap;
+ nodes_clear(node_online_map);
+ node_set_online(0);
+ for ( i = 0; i < nr_cpu_ids; i++ )
+ numa_set_node(i, 0);
+ cpumask_copy(&node_to_cpumask[0], cpumask_of(0));
+ setup_node_bootmem(0, (u64)start_pfn << PAGE_SHIFT,
+ (u64)end_pfn << PAGE_SHIFT);
}
__cpuinit void numa_add_cpu(int cpu)
{
- cpumask_set_cpu(cpu, &node_to_cpumask[cpu_to_node(cpu)]);
+ cpumask_set_cpu(cpu, &node_to_cpumask[cpu_to_node(cpu)]);
}
void __cpuinit numa_set_node(int cpu, int node)
{
- cpu_to_node[cpu] = node;
+ cpu_to_node[cpu] = node;
}
/* [numa=off] */
static __init int numa_setup(char *opt)
{
- if (!strncmp(opt,"off",3))
- numa_off = 1;
- if (!strncmp(opt,"on",2))
- numa_off = 0;
+ if ( !strncmp(opt,"off",3) )
+ numa_off = 1;
+ if ( !strncmp(opt,"on",2) )
+ numa_off = 0;
#ifdef CONFIG_NUMA_EMU
- if(!strncmp(opt, "fake=", 5)) {
- numa_off = 0;
- numa_fake = simple_strtoul(opt+5,NULL,0); ;
- if (numa_fake >= MAX_NUMNODES)
- numa_fake = MAX_NUMNODES;
- }
+ if ( !strncmp(opt, "fake=", 5) )
+ {
+ numa_off = 0;
+ numa_fake = simple_strtoul(opt+5,NULL,0);
+ if ( numa_fake >= MAX_NUMNODES )
+ numa_fake = MAX_NUMNODES;
+ }
#endif
#ifdef CONFIG_ACPI_NUMA
- if (!strncmp(opt,"noacpi",6)) {
- numa_off = 0;
- acpi_numa = -1;
- }
+ if ( !strncmp(opt,"noacpi",6) )
+ {
+ numa_off = 0;
+ acpi_numa = -1;
+ }
#endif
- return 1;
+
+ return 1;
}
/*
@@ -326,16 +340,18 @@ static __init int numa_setup(char *opt)
*/
void __init init_cpu_to_node(void)
{
- int i, node;
- for (i = 0; i < nr_cpu_ids; i++) {
- u32 apicid = x86_cpu_to_apicid[i];
- if (apicid == BAD_APICID)
- continue;
- node = apicid_to_node[apicid];
- if ( node == NUMA_NO_NODE || !node_online(node) )
- node = 0;
- numa_set_node(i, node);
- }
+ int i, node;
+
+ for ( i = 0; i < nr_cpu_ids; i++ )
+ {
+ u32 apicid = x86_cpu_to_apicid[i];
+ if ( apicid == BAD_APICID )
+ continue;
+ node = apicid_to_node[apicid];
+ if ( node == NUMA_NO_NODE || !node_online(node) )
+ node = 0;
+ numa_set_node(i, node);
+ }
}
EXPORT_SYMBOL(cpu_to_node);
@@ -346,64 +362,67 @@ EXPORT_SYMBOL(node_data);
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);
-
- for_each_online_node(i) {
- paddr_t pa = (paddr_t)(NODE_DATA(i)->node_start_pfn + 1)<< PAGE_SHIFT;
- printk("idx%d -> NODE%d start->%lu size->%lu free->%lu\n",
- i, NODE_DATA(i)->node_id,
- NODE_DATA(i)->node_start_pfn,
- NODE_DATA(i)->node_spanned_pages,
- avail_node_heap_pages(i));
- /* sanity check phys_to_nid() */
- printk("phys_to_nid(%"PRIpaddr") -> %d should be %d\n", pa, phys_to_nid(pa),
- NODE_DATA(i)->node_id);
- }
- 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;
-
- spin_lock(&d->page_alloc_lock);
- page_list_for_each(page, &d->page_list)
- {
- i = phys_to_nid((paddr_t)page_to_mfn(page) << PAGE_SHIFT);
- page_num_node[i]++;
- }
- spin_unlock(&d->page_alloc_lock);
-
- for_each_online_node(i)
- printk(" Node %u: %u\n", i, page_num_node[i]);
- }
-
- rcu_read_unlock(&domlist_read_lock);
+ 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);
+
+ for_each_online_node ( i )
+ {
+ paddr_t pa = (paddr_t)(NODE_DATA(i)->node_start_pfn + 1)<< PAGE_SHIFT;
+ printk("idx%d -> NODE%d start->%lu size->%lu free->%lu\n",
+ i, NODE_DATA(i)->node_id,
+ NODE_DATA(i)->node_start_pfn,
+ NODE_DATA(i)->node_spanned_pages,
+ avail_node_heap_pages(i));
+ /* sanity check phys_to_nid() */
+ printk("phys_to_nid(%"PRIpaddr") -> %d should be %d\n", pa,
+ phys_to_nid(pa),
+ NODE_DATA(i)->node_id);
+ }
+
+ 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;
+
+ spin_lock(&d->page_alloc_lock);
+ page_list_for_each(page, &d->page_list)
+ {
+ i = phys_to_nid((paddr_t)page_to_mfn(page) << PAGE_SHIFT);
+ page_num_node[i]++;
+ }
+ spin_unlock(&d->page_alloc_lock);
+
+ for_each_online_node ( i )
+ printk(" Node %u: %u\n", i, page_num_node[i]);
+ }
+
+ rcu_read_unlock(&domlist_read_lock);
}
static struct keyhandler dump_numa_keyhandler = {
- .diagnostic = 1,
- .u.fn = dump_numa,
- .desc = "dump numa info"
+ .diagnostic = 1,
+ .u.fn = dump_numa,
+ .desc = "dump numa info"
};
static __init int register_numa_trigger(void)
{
- register_keyhandler('u', &dump_numa_keyhandler);
- return 0;
+ register_keyhandler('u', &dump_numa_keyhandler);
+ return 0;
}
__initcall(register_numa_trigger);
diff --git a/xen/arch/x86/oprofile/backtrace.c b/xen/arch/x86/oprofile/backtrace.c
index b3ea7f3..94bd24c 100644
--- a/xen/arch/x86/oprofile/backtrace.c
+++ b/xen/arch/x86/oprofile/backtrace.c
@@ -15,17 +15,17 @@
#include <xen/xenoprof.h>
#include <xen/guest_access.h>
-struct frame_head {
+struct __packed frame_head {
struct frame_head * ebp;
unsigned long ret;
-} __attribute__((packed));
+};
typedef struct frame_head frame_head_t;
DEFINE_XEN_GUEST_HANDLE(frame_head_t);
-struct frame_head_32bit {
+struct __packed frame_head_32bit {
uint32_t ebp;
uint32_t ret;
-} __attribute__((packed));
+};
typedef struct frame_head_32bit frame_head32_t;
DEFINE_COMPAT_HANDLE(frame_head32_t);
diff --git a/xen/arch/x86/oprofile/nmi_int.c b/xen/arch/x86/oprofile/nmi_int.c
index c824b84..13534d4 100644
--- a/xen/arch/x86/oprofile/nmi_int.c
+++ b/xen/arch/x86/oprofile/nmi_int.c
@@ -82,7 +82,7 @@ void passive_domain_destroy(struct vcpu *v)
model->free_msr(v);
}
-static int nmi_callback(struct cpu_user_regs *regs, int cpu)
+static int nmi_callback(const struct cpu_user_regs *regs, int cpu)
{
int xen_mode, ovf;
@@ -274,7 +274,7 @@ static void nmi_cpu_stop(void * dummy)
* power on apic lvt contain a zero vector nr which are legal only for
* NMI delivery mode. So inhibit apic err before restoring lvtpc
*/
- if ( !(apic_read(APIC_LVTPC) & APIC_DM_NMI)
+ if ( (apic_read(APIC_LVTPC) & APIC_MODE_MASK) != APIC_DM_NMI
|| (apic_read(APIC_LVTPC) & APIC_LVT_MASKED) )
{
printk("nmi_stop: APIC not good %ul\n", apic_read(APIC_LVTPC));
diff --git a/xen/arch/x86/oprofile/op_model_athlon.c b/xen/arch/x86/oprofile/op_model_athlon.c
index e784018..c0a81ed 100644
--- a/xen/arch/x86/oprofile/op_model_athlon.c
+++ b/xen/arch/x86/oprofile/op_model_athlon.c
@@ -20,7 +20,8 @@
#include <asm/current.h>
#include <asm/hvm/support.h>
#include <xen/pci_regs.h>
-
+#include <xen/pci_ids.h>
+
#include "op_x86_model.h"
#include "op_counter.h"
@@ -236,7 +237,7 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
}
static inline void
-ibs_log_event(u64 data, struct cpu_user_regs * const regs, int mode)
+ibs_log_event(u64 data, struct cpu_user_regs const * const regs, int mode)
{
struct vcpu *v = current;
u32 temp = 0;
@@ -249,7 +250,7 @@ ibs_log_event(u64 data, struct cpu_user_regs * const regs, int mode)
}
-static inline int handle_ibs(int mode, struct cpu_user_regs * const regs)
+static inline int handle_ibs(int mode, struct cpu_user_regs const * const regs)
{
u64 val, ctl;
struct vcpu *v = current;
@@ -309,7 +310,7 @@ static inline int handle_ibs(int mode, struct cpu_user_regs * const regs)
static int athlon_check_ctrs(unsigned int const cpu,
struct op_msrs const * const msrs,
- struct cpu_user_regs * const regs)
+ struct cpu_user_regs const * const regs)
{
uint64_t msr_content;
@@ -445,7 +446,6 @@ static inline void __init init_ibs_nmi_per_cpu(void *arg)
apic_write(reg, APIC_EILVT_MSG_NMI << 8);
}
-#define PCI_VENDOR_ID_AMD 0x1022
#define PCI_DEVICE_ID_AMD_10H_NB_MISC 0x1203
#define IBSCTL 0x1cc
static int __init init_ibs_nmi(void)
@@ -497,14 +497,11 @@ static int __init init_ibs_nmi(void)
static void __init get_ibs_caps(void)
{
- unsigned int max_level;
-
if (!boot_cpu_has(X86_FEATURE_IBS))
return;
/* check IBS cpuid feature flags */
- max_level = cpuid_eax(0x80000000);
- if (max_level >= IBS_CPUID_FEATURES)
+ if (current_cpu_data.extended_cpuid_level >= IBS_CPUID_FEATURES)
ibs_caps = cpuid_eax(IBS_CPUID_FEATURES);
if (!(ibs_caps & IBS_CAPS_AVAIL))
/* cpuid flags not valid */
diff --git a/xen/arch/x86/oprofile/op_model_p4.c b/xen/arch/x86/oprofile/op_model_p4.c
index 34f5fdb..29fe3bc 100644
--- a/xen/arch/x86/oprofile/op_model_p4.c
+++ b/xen/arch/x86/oprofile/op_model_p4.c
@@ -611,7 +611,7 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs)
static int p4_check_ctrs(unsigned int const cpu,
struct op_msrs const * const msrs,
- struct cpu_user_regs * const regs)
+ struct cpu_user_regs const * const regs)
{
unsigned long ctr, stag, real;
uint64_t msr_content;
diff --git a/xen/arch/x86/oprofile/op_model_ppro.c b/xen/arch/x86/oprofile/op_model_ppro.c
index 3225937..aa99e4d 100644
--- a/xen/arch/x86/oprofile/op_model_ppro.c
+++ b/xen/arch/x86/oprofile/op_model_ppro.c
@@ -64,9 +64,9 @@ static void ppro_fill_in_addresses(struct op_msrs * const msrs)
int i;
for (i = 0; i < num_counters; i++)
- msrs->counters[i].addr = MSR_P6_PERFCTR0 + i;
+ msrs->counters[i].addr = MSR_P6_PERFCTR(i);
for (i = 0; i < num_counters; i++)
- msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i;
+ msrs->controls[i].addr = MSR_P6_EVNTSEL(i);
}
@@ -126,7 +126,7 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
static int ppro_check_ctrs(unsigned int const cpu,
struct op_msrs const * const msrs,
- struct cpu_user_regs * const regs)
+ struct cpu_user_regs const * const regs)
{
u64 val;
int i;
@@ -211,11 +211,11 @@ static int ppro_is_arch_pmu_msr(u64 msr_index, int *type, int *index)
*index = msr_index - MSR_IA32_PERFCTR0;
return 1;
}
- if ( (msr_index >= MSR_P6_EVNTSEL0) &&
- (msr_index < (MSR_P6_EVNTSEL0 + num_counters)) )
+ if ( (msr_index >= MSR_P6_EVNTSEL(0)) &&
+ (msr_index < (MSR_P6_EVNTSEL(num_counters))) )
{
*type = MSR_TYPE_ARCH_CTRL;
- *index = msr_index - MSR_P6_EVNTSEL0;
+ *index = msr_index - MSR_P6_EVNTSEL(0);
return 1;
}
diff --git a/xen/arch/x86/oprofile/op_x86_model.h b/xen/arch/x86/oprofile/op_x86_model.h
index 31d473b..35bc3c1 100644
--- a/xen/arch/x86/oprofile/op_x86_model.h
+++ b/xen/arch/x86/oprofile/op_x86_model.h
@@ -33,7 +33,7 @@ struct op_x86_model_spec {
void (*setup_ctrs)(struct op_msrs const * const msrs);
int (*check_ctrs)(unsigned int const cpu,
struct op_msrs const * const msrs,
- struct cpu_user_regs * const regs);
+ struct cpu_user_regs const * const regs);
void (*start)(struct op_msrs const * const msrs);
void (*stop)(struct op_msrs const * const msrs);
int (*is_arch_pmu_msr)(u64 msr_index, int *type, int *index);
diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c
index bc0634c..6b3201b 100644
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -37,9 +37,8 @@ static int physdev_hvm_map_pirq(
switch ( type )
{
case MAP_PIRQ_TYPE_GSI: {
- struct hvm_irq_dpci *hvm_irq_dpci;
- struct hvm_girq_dpci_mapping *girq;
- uint32_t machine_gsi = 0;
+ const struct hvm_irq_dpci *hvm_irq_dpci;
+ unsigned int machine_gsi = 0;
if ( *index < 0 || *index >= NR_HVM_IRQS )
{
@@ -52,6 +51,8 @@ static int physdev_hvm_map_pirq(
hvm_irq_dpci = domain_get_irq_dpci(d);
if ( hvm_irq_dpci )
{
+ const struct hvm_girq_dpci_mapping *girq;
+
BUILD_BUG_ON(ARRAY_SIZE(hvm_irq_dpci->girq) < NR_HVM_IRQS);
list_for_each_entry ( girq,
&hvm_irq_dpci->girq[*index],
@@ -310,8 +311,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
spin_unlock(&v->domain->event_lock);
break;
}
- if ( is_pv_domain(v->domain) &&
- v->domain->arch.pv_domain.auto_unmask )
+ if ( v->domain->arch.auto_unmask )
evtchn_unmask(pirq->evtchn);
if ( is_pv_domain(v->domain) ||
domain_pirq_to_irq(v->domain, eoi.irq) > 0 )
@@ -354,7 +354,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
}
mfn = page_to_mfn(page);
- if ( cmpxchg(&v->domain->arch.pv_domain.pirq_eoi_map_mfn,
+ if ( cmpxchg(&v->domain->arch.pirq_eoi_map_mfn,
0, mfn) != 0 )
{
put_page_and_type(mfn_to_page(mfn));
@@ -362,16 +362,16 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
break;
}
- v->domain->arch.pv_domain.pirq_eoi_map = map_domain_page_global(mfn);
- if ( v->domain->arch.pv_domain.pirq_eoi_map == NULL )
+ v->domain->arch.pirq_eoi_map = map_domain_page_global(mfn);
+ if ( v->domain->arch.pirq_eoi_map == NULL )
{
- v->domain->arch.pv_domain.pirq_eoi_map_mfn = 0;
+ v->domain->arch.pirq_eoi_map_mfn = 0;
put_page_and_type(mfn_to_page(mfn));
ret = -ENOSPC;
break;
}
if ( cmd == PHYSDEVOP_pirq_eoi_gmfn_v1 )
- v->domain->arch.pv_domain.auto_unmask = 1;
+ v->domain->arch.auto_unmask = 1;
ret = 0;
break;
diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c
index 2162811..32f39b2 100644
--- a/xen/arch/x86/platform_hypercall.c
+++ b/xen/arch/x86/platform_hypercall.c
@@ -61,6 +61,98 @@ long cpu_down_helper(void *data);
long core_parking_helper(void *data);
uint32_t get_cur_idle_nums(void);
+#define RESOURCE_ACCESS_MAX_ENTRIES 2
+struct xen_resource_access {
+ unsigned int nr_done;
+ unsigned int nr_entries;
+ xenpf_resource_entry_t *entries;
+};
+
+static bool_t allow_access_msr(unsigned int msr)
+{
+ switch ( msr )
+ {
+ /* MSR for CMT, refer to chapter 17.14 of Intel SDM. */
+ case MSR_IA32_CMT_EVTSEL:
+ case MSR_IA32_CMT_CTR:
+ return 1;
+ }
+
+ return 0;
+}
+
+static void check_resource_access(struct xen_resource_access *ra)
+{
+ unsigned int i;
+
+ for ( i = 0; i < ra->nr_entries; i++ )
+ {
+ int ret = 0;
+ xenpf_resource_entry_t *entry = ra->entries + i;
+
+ if ( entry->rsvd )
+ {
+ entry->u.ret = -EINVAL;
+ break;
+ }
+
+ switch ( entry->u.cmd )
+ {
+ case XEN_RESOURCE_OP_MSR_READ:
+ case XEN_RESOURCE_OP_MSR_WRITE:
+ if ( entry->idx >> 32 )
+ ret = -EINVAL;
+ else if ( !allow_access_msr(entry->idx) )
+ ret = -EACCES;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ if ( ret )
+ {
+ entry->u.ret = ret;
+ break;
+ }
+ }
+
+ ra->nr_done = i;
+}
+
+static void resource_access(void *info)
+{
+ struct xen_resource_access *ra = info;
+ unsigned int i;
+
+ for ( i = 0; i < ra->nr_done; i++ )
+ {
+ int ret;
+ xenpf_resource_entry_t *entry = ra->entries + i;
+
+ switch ( entry->u.cmd )
+ {
+ case XEN_RESOURCE_OP_MSR_READ:
+ ret = rdmsr_safe(entry->idx, entry->val);
+ break;
+ case XEN_RESOURCE_OP_MSR_WRITE:
+ ret = wrmsr_safe(entry->idx, entry->val);
+ break;
+ default:
+ BUG();
+ break;
+ }
+
+ if ( ret )
+ {
+ entry->u.ret = ret;
+ break;
+ }
+ }
+
+ ra->nr_done = i;
+}
+
ret_t do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
{
ret_t ret = 0;
@@ -601,6 +693,73 @@ ret_t do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
}
break;
+ case XENPF_resource_op:
+ {
+ struct xen_resource_access ra;
+ unsigned int cpu;
+ XEN_GUEST_HANDLE(xenpf_resource_entry_t) guest_entries;
+
+ ra.nr_entries = op->u.resource_op.nr_entries;
+ if ( ra.nr_entries == 0 )
+ break;
+ if ( ra.nr_entries > RESOURCE_ACCESS_MAX_ENTRIES )
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ ra.entries = xmalloc_array(xenpf_resource_entry_t, ra.nr_entries);
+ if ( !ra.entries )
+ {
+ ret = -ENOMEM;
+ break;
+ }
+
+ guest_from_compat_handle(guest_entries, op->u.resource_op.entries);
+
+ if ( copy_from_guest(ra.entries, guest_entries, ra.nr_entries) )
+ {
+ xfree(ra.entries);
+ ret = -EFAULT;
+ break;
+ }
+
+ /* Do sanity check earlier to omit the potential IPI overhead. */
+ check_resource_access(&ra);
+ if ( ra.nr_done == 0 )
+ {
+ /* Copy the return value for entry 0 if it failed. */
+ if ( __copy_to_guest(guest_entries, ra.entries, 1) )
+ ret = -EFAULT;
+
+ xfree(ra.entries);
+ break;
+ }
+
+ cpu = op->u.resource_op.cpu;
+ if ( (cpu >= nr_cpu_ids) || !cpu_online(cpu) )
+ {
+ xfree(ra.entries);
+ ret = -ENODEV;
+ break;
+ }
+ if ( cpu == smp_processor_id() )
+ resource_access(&ra);
+ else
+ on_selected_cpus(cpumask_of(cpu), resource_access, &ra, 1);
+
+ /* Copy all if succeeded or up to the failed entry. */
+ if ( __copy_to_guest(guest_entries, ra.entries,
+ ra.nr_done < ra.nr_entries ? ra.nr_done + 1
+ : ra.nr_entries) )
+ ret = -EFAULT;
+ else
+ ret = ra.nr_done;
+
+ xfree(ra.entries);
+ }
+ break;
+
default:
ret = -ENOSYS;
break;
diff --git a/xen/arch/x86/psr.c b/xen/arch/x86/psr.c
new file mode 100644
index 0000000..2ef83df
--- /dev/null
+++ b/xen/arch/x86/psr.c
@@ -0,0 +1,200 @@
+/*
+ * psr.c: Platform Shared Resource related service for guest.
+ *
+ * Copyright (c) 2014, Intel Corporation
+ * Author: Dongxiao Xu <dongxiao.xu at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+#include <xen/init.h>
+#include <xen/cpu.h>
+#include <xen/sched.h>
+#include <asm/psr.h>
+
+#define PSR_CMT (1<<0)
+
+struct psr_assoc {
+ uint64_t val;
+ bool_t initialized;
+};
+
+struct psr_cmt *__read_mostly psr_cmt;
+static bool_t __initdata opt_psr;
+static unsigned int __initdata opt_rmid_max = 255;
+static uint64_t rmid_mask;
+static DEFINE_PER_CPU(struct psr_assoc, psr_assoc);
+
+static void __init parse_psr_param(char *s)
+{
+ char *ss, *val_str;
+
+ do {
+ ss = strchr(s, ',');
+ if ( ss )
+ *ss = '\0';
+
+ val_str = strchr(s, ':');
+ if ( val_str )
+ *val_str++ = '\0';
+
+ if ( !strcmp(s, "cmt") )
+ {
+ if ( !val_str )
+ opt_psr |= PSR_CMT;
+ else
+ {
+ int val_int = parse_bool(val_str);
+ if ( val_int == 1 )
+ opt_psr |= PSR_CMT;
+ else if ( val_int != 0 )
+ printk("PSR: unknown cmt value: %s - CMT disabled!\n",
+ val_str);
+ }
+ }
+ else if ( val_str && !strcmp(s, "rmid_max") )
+ opt_rmid_max = simple_strtoul(val_str, NULL, 0);
+
+ s = ss + 1;
+ } while ( ss );
+}
+custom_param("psr", parse_psr_param);
+
+static void __init init_psr_cmt(unsigned int rmid_max)
+{
+ unsigned int eax, ebx, ecx, edx;
+ unsigned int rmid;
+
+ if ( !boot_cpu_has(X86_FEATURE_CMT) )
+ return;
+
+ cpuid_count(0xf, 0, &eax, &ebx, &ecx, &edx);
+ if ( !edx )
+ return;
+
+ psr_cmt = xzalloc(struct psr_cmt);
+ if ( !psr_cmt )
+ return;
+
+ psr_cmt->features = edx;
+ psr_cmt->rmid_max = min(rmid_max, ebx);
+ rmid_mask = ~(~0ull << get_count_order(ebx));
+
+ if ( psr_cmt->features & PSR_RESOURCE_TYPE_L3 )
+ {
+ cpuid_count(0xf, 1, &eax, &ebx, &ecx, &edx);
+ psr_cmt->l3.upscaling_factor = ebx;
+ psr_cmt->l3.rmid_max = ecx;
+ psr_cmt->l3.features = edx;
+ }
+
+ psr_cmt->rmid_max = min(psr_cmt->rmid_max, psr_cmt->l3.rmid_max);
+ psr_cmt->rmid_to_dom = xmalloc_array(domid_t, psr_cmt->rmid_max + 1UL);
+ if ( !psr_cmt->rmid_to_dom )
+ {
+ xfree(psr_cmt);
+ psr_cmt = NULL;
+ return;
+ }
+
+ /*
+ * Once CMT is enabled each CPU will always require a RMID to associate
+ * with it. To reduce the waste of RMID, reserve RMID 0 for all CPUs that
+ * have no domain being monitored.
+ */
+ psr_cmt->rmid_to_dom[0] = DOMID_XEN;
+ for ( rmid = 1; rmid <= psr_cmt->rmid_max; rmid++ )
+ psr_cmt->rmid_to_dom[rmid] = DOMID_INVALID;
+
+ printk(XENLOG_INFO "Cache Monitoring Technology enabled\n");
+}
+
+static int __init init_psr(void)
+{
+ if ( (opt_psr & PSR_CMT) && opt_rmid_max )
+ init_psr_cmt(opt_rmid_max);
+ return 0;
+}
+__initcall(init_psr);
+
+/* Called with domain lock held, no psr specific lock needed */
+int psr_alloc_rmid(struct domain *d)
+{
+ unsigned int rmid;
+
+ ASSERT(psr_cmt_enabled());
+
+ if ( d->arch.psr_rmid > 0 )
+ return -EEXIST;
+
+ for ( rmid = 1; rmid <= psr_cmt->rmid_max; rmid++ )
+ {
+ if ( psr_cmt->rmid_to_dom[rmid] != DOMID_INVALID )
+ continue;
+
+ psr_cmt->rmid_to_dom[rmid] = d->domain_id;
+ break;
+ }
+
+ /* No RMID available, assign RMID=0 by default. */
+ if ( rmid > psr_cmt->rmid_max )
+ {
+ d->arch.psr_rmid = 0;
+ return -EUSERS;
+ }
+
+ d->arch.psr_rmid = rmid;
+
+ return 0;
+}
+
+/* Called with domain lock held, no psr specific lock needed */
+void psr_free_rmid(struct domain *d)
+{
+ unsigned int rmid;
+
+ rmid = d->arch.psr_rmid;
+ /* We do not free system reserved "RMID=0". */
+ if ( rmid == 0 )
+ return;
+
+ psr_cmt->rmid_to_dom[rmid] = DOMID_INVALID;
+ d->arch.psr_rmid = 0;
+}
+
+void psr_assoc_rmid(unsigned int rmid)
+{
+ uint64_t val;
+ uint64_t new_val;
+ struct psr_assoc *psra = &this_cpu(psr_assoc);
+
+ if ( !psra->initialized )
+ {
+ rdmsrl(MSR_IA32_PSR_ASSOC, psra->val);
+ psra->initialized = 1;
+ }
+ val = psra->val;
+
+ new_val = (val & ~rmid_mask) | (rmid & rmid_mask);
+ if ( val != new_val )
+ {
+ wrmsrl(MSR_IA32_PSR_ASSOC, new_val);
+ psra->val = new_val;
+ }
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index b49256d..73e95c6 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -48,6 +48,7 @@
#include <asm/setup.h>
#include <xen/cpu.h>
#include <asm/nmi.h>
+#include <asm/alternative.h>
/* opt_nosmp: If true, secondary processors are ignored. */
static bool_t __initdata opt_nosmp;
@@ -61,20 +62,23 @@ integer_param("maxcpus", max_cpus);
static bool_t __initdata disable_smep;
invbool_param("smep", disable_smep);
+/* smap: Enable/disable Supervisor Mode Access Prevention (default on). */
+static bool_t __initdata disable_smap;
+invbool_param("smap", disable_smap);
+
+/* Boot dom0 in pvh mode */
+static bool_t __initdata opt_dom0pvh;
+boolean_param("dom0pvh", opt_dom0pvh);
+
/* **** Linux config option: propagated to domain0. */
/* "acpi=off": Sisables both ACPI table parsing and interpreter. */
/* "acpi=force": Override the disable blacklist. */
-/* "acpi=strict": Disables out-of-spec workarounds. */
/* "acpi=ht": Limit ACPI just to boot-time to enable HT. */
/* "acpi=noirq": Disables ACPI interrupt routing. */
static void parse_acpi_param(char *s);
custom_param("acpi", parse_acpi_param);
/* **** Linux config option: propagated to domain0. */
-/* acpi_skip_timer_override: Skip IRQ0 overrides. */
-boolean_param("acpi_skip_timer_override", acpi_skip_timer_override);
-
-/* **** Linux config option: propagated to domain0. */
/* noapic: Disable IOAPIC setup. */
boolean_param("noapic", skip_ioapic_setup);
@@ -100,8 +104,7 @@ char __attribute__ ((__section__(".bss.stack_aligned"))) cpu0_stack[STACK_SIZE];
struct cpuinfo_x86 __read_mostly boot_cpu_data = { 0, 0, 0, 0, -1 };
-unsigned long __read_mostly mmu_cr4_features =
- X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE;
+unsigned long __read_mostly mmu_cr4_features = XEN_MINIMAL_CR4;
bool_t __initdata acpi_disabled;
bool_t __initdata acpi_force;
@@ -134,11 +137,6 @@ static void __init parse_acpi_param(char *s)
}
}
-#define EARLY_FAIL(f, a...) do { \
- printk( f , ## a ); \
- for ( ; ; ) halt(); \
-} while (0)
-
static const module_t *__initdata initial_images;
static unsigned int __initdata nr_initial_images;
@@ -394,16 +392,6 @@ static void __init setup_max_pdx(unsigned long top_page)
max_page = pdx_to_pfn(max_pdx - 1) + 1;
}
-void set_pdx_range(unsigned long smfn, unsigned long emfn)
-{
- unsigned long idx, eidx;
-
- idx = pfn_to_pdx(smfn) / PDX_GROUP_COUNT;
- eidx = (pfn_to_pdx(emfn - 1) + PDX_GROUP_COUNT) / PDX_GROUP_COUNT;
- for ( ; idx < eidx; ++idx )
- __set_bit(idx, pdx_group_valid);
-}
-
/* A temporary copy of the e820 map that we can mess with during bootstrap. */
static struct e820map __initdata boot_e820;
@@ -520,7 +508,7 @@ static bool_t __init loader_is_grub2(const char *loader_name)
return (p != NULL) && (p[5] != '0');
}
-static char * __init cmdline_cook(char *p, char *loader_name)
+static char * __init cmdline_cook(char *p, const char *loader_name)
{
p = p ? : "";
@@ -541,25 +529,38 @@ static char * __init cmdline_cook(char *p, char *loader_name)
return p;
}
-void __init __start_xen(unsigned long mbi_p)
+void __init noreturn __start_xen(unsigned long mbi_p)
{
char *memmap_type = NULL;
char *cmdline, *kextra, *loader;
- unsigned int initrdidx;
+ unsigned int initrdidx, domcr_flags = DOMCRF_s3_integrity;
multiboot_info_t *mbi = __va(mbi_p);
module_t *mod = (module_t *)__va(mbi->mods_addr);
unsigned long nr_pages, raw_max_page, modules_headroom, *module_map;
int i, j, e820_warn = 0, bytes = 0;
bool_t acpi_boot_table_init_done = 0;
+ struct domain *dom0;
struct ns16550_defaults ns16550 = {
.data_bits = 8,
.parity = 'n',
.stop_bits = 1
};
+ /* Critical region without IDT or TSS. Any fault is deadly! */
+
+ set_processor_id(0);
+ set_current((struct vcpu *)0xfffff000); /* debug sanity. */
+ idle_vcpu[0] = current;
+
percpu_init_areas();
- set_intr_gate(TRAP_page_fault, &early_page_fault);
+ init_idt_traps();
+ load_system_tables();
+
+ smp_prepare_boot_cpu();
+ sort_exception_tables();
+
+ /* Full exception support from here on in. */
loader = (mbi->flags & MBI_LOADERNAME)
? (char *)__va(mbi->boot_loader_name) : "unknown";
@@ -587,15 +588,10 @@ void __init __start_xen(unsigned long mbi_p)
parse_video_info();
- set_current((struct vcpu *)0xfffff000); /* debug sanity */
- idle_vcpu[0] = current;
- set_processor_id(0); /* needed early, for smp_processor_id() */
if ( cpu_has_efer )
rdmsrl(MSR_EFER, this_cpu(efer));
asm volatile ( "mov %%cr4,%0" : "=r" (this_cpu(cr4)) );
- smp_prepare_boot_cpu();
-
/* We initialise the serial devices very early so we can get debugging. */
ns16550.io_base = 0x3f8;
ns16550.irq = 4;
@@ -662,11 +658,10 @@ void __init __start_xen(unsigned long mbi_p)
/* Check that we have at least one Multiboot module. */
if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) )
- EARLY_FAIL("dom0 kernel not specified. "
- "Check bootloader configuration.\n");
+ panic("dom0 kernel not specified. Check bootloader configuration.");
if ( ((unsigned long)cpu0_stack & (STACK_SIZE-1)) != 0 )
- EARLY_FAIL("Misaligned CPU0 stack.\n");
+ panic("Misaligned CPU0 stack.");
if ( efi_enabled )
{
@@ -747,9 +742,7 @@ void __init __start_xen(unsigned long mbi_p)
e820_raw_nr = 2;
}
else
- {
- EARLY_FAIL("Bootloader provided no memory information.\n");
- }
+ panic("Bootloader provided no memory information.");
/* Sanitise the raw E820 map to produce a final clean version. */
max_page = raw_max_page = init_e820(memmap_type, e820_raw, &e820_raw_nr);
@@ -784,7 +777,7 @@ void __init __start_xen(unsigned long mbi_p)
for ( i = 0; !efi_enabled && i < mbi->mods_count; i++ )
{
if ( mod[i].mod_start & (PAGE_SIZE - 1) )
- EARLY_FAIL("Bootloader didn't honor module alignment request.\n");
+ panic("Bootloader didn't honor module alignment request.");
mod[i].mod_end -= mod[i].mod_start;
mod[i].mod_start >>= PAGE_SHIFT;
mod[i].reserved = 0;
@@ -905,15 +898,17 @@ void __init __start_xen(unsigned long mbi_p)
/* Re-sync the stack and then switch to relocated pagetables. */
asm volatile (
- "rep movsb ; " /* re-sync the stack */
+ "rep movsq ; " /* re-sync the stack */
"movq %%cr4,%%rsi ; "
"andb $0x7f,%%sil ; "
"movq %%rsi,%%cr4 ; " /* CR4.PGE == 0 */
- "movq %0,%%cr3 ; " /* CR3 == new pagetables */
+ "movq %[pg],%%cr3 ; " /* CR3 == new pagetables */
"orb $0x80,%%sil ; "
"movq %%rsi,%%cr4 " /* CR4.PGE == 1 */
- : : "r" (__pa(idle_pg_table)), "S" (cpu0_stack),
- "D" (__va(__pa(cpu0_stack))), "c" (STACK_SIZE) : "memory" );
+ : "=&S" (i), "=&D" (i), "=&c" (i) /* All outputs discarded. */
+ : [pg] "r" (__pa(idle_pg_table)), "0" (cpu0_stack),
+ "1" (__va(__pa(cpu0_stack))), "2" (STACK_SIZE / 8)
+ : "memory" );
bootstrap_map(NULL);
}
@@ -957,7 +952,7 @@ void __init __start_xen(unsigned long mbi_p)
}
if ( modules_headroom && !mod->reserved )
- EARLY_FAIL("Not enough memory to relocate the dom0 kernel image.\n");
+ panic("Not enough memory to relocate the dom0 kernel image.");
for ( i = 0; i < mbi->mods_count; ++i )
{
uint64_t s = (uint64_t)mod[i].mod_start << PAGE_SHIFT;
@@ -966,7 +961,7 @@ void __init __start_xen(unsigned long mbi_p)
}
if ( !xen_phys_start )
- EARLY_FAIL("Not enough memory to relocate Xen.\n");
+ panic("Not enough memory to relocate Xen.");
reserve_e820_ram(&boot_e820, efi_enabled ? mbi->mem_upper : __pa(&_start),
__pa(&_end));
@@ -1211,8 +1206,6 @@ void __init __start_xen(unsigned long mbi_p)
if ( opt_watchdog )
nmi_watchdog = NMI_LOCAL_APIC;
- sort_exception_tables();
-
find_smp_config();
dmi_scan_machine();
@@ -1255,7 +1248,7 @@ void __init __start_xen(unsigned long mbi_p)
bitmap_fill(module_map, mbi->mods_count);
__clear_bit(0, module_map); /* Dom0 kernel is always first */
- xsm_init(module_map, mbi, bootstrap_map);
+ xsm_multiboot_init(module_map, mbi, bootstrap_map);
microcode_grab_module(module_map, mbi, bootstrap_map);
@@ -1283,9 +1276,16 @@ void __init __start_xen(unsigned long mbi_p)
if ( cpu_has_smep )
set_in_cr4(X86_CR4_SMEP);
+ if ( disable_smap )
+ setup_clear_cpu_cap(X86_FEATURE_SMAP);
+ if ( cpu_has_smap )
+ set_in_cr4(X86_CR4_SMAP);
+
if ( cpu_has_fsgsbase )
set_in_cr4(X86_CR4_FSGSBASE);
+ alternative_instructions();
+
local_irq_enable();
pt_pci_init();
@@ -1313,6 +1313,8 @@ void __init __start_xen(unsigned long mbi_p)
console_init_postirq();
+ system_state = SYS_STATE_smp_boot;
+
do_presmp_initcalls();
for_each_present_cpu ( i )
@@ -1341,9 +1343,12 @@ void __init __start_xen(unsigned long mbi_p)
if ( !tboot_protect_mem_regions() )
panic("Could not protect TXT memory regions");
+ if ( opt_dom0pvh )
+ domcr_flags |= DOMCRF_pvh | DOMCRF_hap;
+
/* Create initial domain 0. */
- dom0 = domain_create(0, DOMCRF_s3_integrity, 0);
- if ( IS_ERR(dom0) || (alloc_dom0_vcpu0() == NULL) )
+ dom0 = domain_create(0, domcr_flags, 0);
+ if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
panic("Error creating domain 0");
dom0->is_privileged = 1;
@@ -1365,9 +1370,6 @@ void __init __start_xen(unsigned long mbi_p)
/* Append any extra parameters. */
if ( skip_ioapic_setup && !strstr(dom0_cmdline, "noapic") )
safe_strcat(dom0_cmdline, " noapic");
- if ( acpi_skip_timer_override &&
- !strstr(dom0_cmdline, "acpi_skip_timer_override") )
- safe_strcat(dom0_cmdline, " acpi_skip_timer_override");
if ( (strlen(acpi_param) == 0) && acpi_disabled )
{
printk("ACPI is disabled, notifying Domain 0 (acpi=off)\n");
@@ -1392,6 +1394,14 @@ void __init __start_xen(unsigned long mbi_p)
initrdidx);
/*
+ * Temporarily clear SMAP in CR4 to allow user-accesses in construct_dom0().
+ * This saves a large number of corner cases interactions with
+ * copy_from_user().
+ */
+ if ( cpu_has_smap )
+ write_cr4(read_cr4() & ~X86_CR4_SMAP);
+
+ /*
* We're going to setup domain0 using the module(s) that we stashed safely
* above our heap. The second module, if present, is an initrd ramdisk.
*/
@@ -1401,6 +1411,9 @@ void __init __start_xen(unsigned long mbi_p)
bootstrap_map, cmdline) != 0)
panic("Could not set up DOM0 guest OS");
+ if ( cpu_has_smap )
+ write_cr4(read_cr4() | X86_CR4_SMAP);
+
/* Scrub RAM that is still free and so may go to an unprivileged domain. */
scrub_heap_pages();
@@ -1445,7 +1458,7 @@ void arch_get_xen_caps(xen_capabilities_info_t *info)
}
}
-int __init xen_in_range(unsigned long mfn)
+int __hwdom_init xen_in_range(unsigned long mfn)
{
paddr_t start, end;
int i;
@@ -1453,7 +1466,7 @@ int __init xen_in_range(unsigned long mfn)
enum { region_s3, region_text, region_bss, nr_regions };
static struct {
paddr_t s, e;
- } xen_regions[nr_regions] __initdata;
+ } xen_regions[nr_regions] __hwdom_initdata;
/* initialize first time */
if ( !xen_regions[0].s )
diff --git a/xen/arch/x86/shutdown.c b/xen/arch/x86/shutdown.c
index 6eba271..21f6cf5 100644
--- a/xen/arch/x86/shutdown.c
+++ b/xen/arch/x86/shutdown.c
@@ -34,13 +34,13 @@ enum reboot_type {
BOOT_CF9 = 'p',
};
-static long no_idt[2];
static int reboot_mode;
/*
- * reboot=b[ios] | t[riple] | k[bd] | n[o] [, [w]arm | [c]old]
+ * reboot=t[riple] | k[bd] | a[cpi] | p[ci] | n[o] [, [w]arm | [c]old]
* warm Don't set the cold reboot flag
* cold Set the cold reboot flag
+ * no Suppress automatic reboot after panics or crashes
* triple Force a triple fault (init)
* kbd Use the keyboard controller. cold reset (default)
* acpi Use the RESET_REG in the FADT
@@ -85,7 +85,7 @@ static inline void kb_wait(void)
break;
}
-static void __attribute__((noreturn)) __machine_halt(void *unused)
+static void noreturn __machine_halt(void *unused)
{
local_irq_disable();
for ( ; ; )
@@ -96,8 +96,13 @@ void machine_halt(void)
{
watchdog_disable();
console_start_sync();
- local_irq_enable();
- smp_call_function(__machine_halt, NULL, 0);
+
+ if ( system_state >= SYS_STATE_smp_boot )
+ {
+ local_irq_enable();
+ smp_call_function(__machine_halt, NULL, 0);
+ }
+
__machine_halt(NULL);
}
@@ -452,7 +457,7 @@ static int __init reboot_init(void)
}
__initcall(reboot_init);
-static void __machine_restart(void *pdelay)
+static void noreturn __machine_restart(void *pdelay)
{
machine_restart(*(unsigned int *)pdelay);
}
@@ -461,23 +466,12 @@ void machine_restart(unsigned int delay_millisecs)
{
unsigned int i, attempt;
enum reboot_type orig_reboot_type = reboot_type;
+ const struct desc_ptr no_idt = { 0 };
watchdog_disable();
console_start_sync();
spin_debug_disable();
- local_irq_enable();
-
- /* Ensure we are the boot CPU. */
- if ( get_apic_id() != boot_cpu_physical_apicid )
- {
- /* Send IPI to the boot CPU (logical cpu 0). */
- on_selected_cpus(cpumask_of(0), __machine_restart,
- &delay_millisecs, 0);
- for ( ; ; )
- halt();
- }
-
/*
* We may be called from an interrupt context, and various functions we
* may need to call (alloc_domheap_pages, map_domain_page, ...) assert that
@@ -485,7 +479,22 @@ void machine_restart(unsigned int delay_millisecs)
*/
local_irq_count(0) = 0;
- smp_send_stop();
+ if ( system_state >= SYS_STATE_smp_boot )
+ {
+ local_irq_enable();
+
+ /* Ensure we are the boot CPU. */
+ if ( get_apic_id() != boot_cpu_physical_apicid )
+ {
+ /* Send IPI to the boot CPU (logical cpu 0). */
+ on_selected_cpus(cpumask_of(0), __machine_restart,
+ &delay_millisecs, 0);
+ for ( ; ; )
+ halt();
+ }
+
+ smp_send_stop();
+ }
mdelay(delay_millisecs);
@@ -524,7 +533,7 @@ void machine_restart(unsigned int delay_millisecs)
? BOOT_ACPI : BOOT_TRIPLE);
break;
case BOOT_TRIPLE:
- asm volatile ( "lidt %0 ; int3" : "=m" (no_idt) );
+ asm volatile ("lidt %0; int3" : : "m" (no_idt));
reboot_type = BOOT_KBD;
break;
case BOOT_ACPI:
diff --git a/xen/arch/x86/smp.c b/xen/arch/x86/smp.c
index 0433f30..06a833e 100644
--- a/xen/arch/x86/smp.c
+++ b/xen/arch/x86/smp.c
@@ -124,21 +124,11 @@ static void __default_send_IPI_shortcut(unsigned int shortcut, int vector,
apic_write_around(APIC_ICR, cfg);
}
-void send_IPI_self_flat(int vector)
+void send_IPI_self_legacy(uint8_t vector)
{
__default_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
}
-void send_IPI_self_phys(int vector)
-{
- __default_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
-}
-
-void send_IPI_self_x2apic(int vector)
-{
- apic_write(APIC_SELF_IPI, vector);
-}
-
void send_IPI_mask_flat(const cpumask_t *cpumask, int vector)
{
unsigned long mask = cpumask_bits(cpumask)[0];
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
index 42b8a59..c54be7e 100644
--- a/xen/arch/x86/smpboot.c
+++ b/xen/arch/x86/smpboot.c
@@ -303,15 +303,6 @@ static void set_cpu_sibling_map(int cpu)
}
}
-static void construct_percpu_idt(unsigned int cpu)
-{
- unsigned char idt_load[10];
-
- *(unsigned short *)(&idt_load[0]) = (IDT_ENTRIES*sizeof(idt_entry_t))-1;
- *(unsigned long *)(&idt_load[2]) = (unsigned long)idt_tables[cpu];
- __asm__ __volatile__ ( "lidt %0" : "=m" (idt_load) );
-}
-
void start_secondary(void *unused)
{
/*
@@ -320,12 +311,13 @@ void start_secondary(void *unused)
*/
unsigned int cpu = booting_cpu;
+ /* Critical region without IDT or TSS. Any fault is deadly! */
+
set_processor_id(cpu);
set_current(idle_vcpu[cpu]);
this_cpu(curr_vcpu) = idle_vcpu[cpu];
if ( cpu_has_efer )
rdmsrl(MSR_EFER, this_cpu(efer));
- asm volatile ( "mov %%cr4,%0" : "=r" (this_cpu(cr4)) );
/*
* Just as during early bootstrap, it is convenient here to disable
@@ -345,18 +337,21 @@ void start_secondary(void *unused)
*/
spin_debug_disable();
+ load_system_tables();
+
+ /* Full exception support from here on in. */
+
+ /* Safe to enable feature such as CR4.MCE with the IDT set up now. */
+ write_cr4(mmu_cr4_features);
+
percpu_traps_init();
+ init_percpu_time();
+
cpu_init();
smp_callin();
- /*
- * At this point, boot CPU has fully initialised the IDT. It is
- * now safe to make ourselves a private copy.
- */
- construct_percpu_idt(cpu);
-
setup_secondary_APIC_clock();
/*
@@ -381,8 +376,6 @@ void start_secondary(void *unused)
cpumask_set_cpu(cpu, &cpu_online_map);
unlock_vector_lock();
- init_percpu_time();
-
/* We can take interrupts now: we're officially "up". */
local_irq_enable();
mtrr_ap_init();
@@ -398,17 +391,17 @@ extern void *stack_start;
static int wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
{
unsigned long send_status = 0, accept_status = 0;
- int maxlvt, timeout, num_starts, i;
+ int maxlvt, timeout, i;
/*
* Be paranoid about clearing APIC errors.
*/
- if ( APIC_INTEGRATED(apic_version[phys_apicid]) )
- {
- apic_read_around(APIC_SPIV);
- apic_write(APIC_ESR, 0);
- apic_read(APIC_ESR);
- }
+ if ( !APIC_INTEGRATED(apic_version[phys_apicid]) )
+ return -ENODEV;
+
+ apic_read_around(APIC_SPIV);
+ apic_write(APIC_ESR, 0);
+ apic_read(APIC_ESR);
Dprintk("Asserting INIT.\n");
@@ -455,20 +448,9 @@ static int wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
udelay(10);
}
- /*
- * Should we send STARTUP IPIs ?
- *
- * Determine this based on the APIC version.
- * If we don't have an integrated APIC, don't send the STARTUP IPIs.
- */
- num_starts = APIC_INTEGRATED(apic_version[phys_apicid]) ? 2 : 0;
-
- /* Run STARTUP IPI loop. */
- Dprintk("#startup loops: %d.\n", num_starts);
-
maxlvt = get_maxlvt();
- for ( i = 0; i < num_starts; i++ )
+ for ( i = 0; i < 2; i++ )
{
Dprintk("Sending STARTUP #%d.\n", i+1);
apic_read_around(APIC_SPIV);
@@ -768,8 +750,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
/* If we couldn't find a local APIC, then get out of here now! */
- if ( APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])
- && !cpu_has_apic )
+ if ( !APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])
+ || !cpu_has_apic )
{
printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
boot_cpu_physical_apicid);
diff --git a/xen/arch/x86/srat.c b/xen/arch/x86/srat.c
index 2b05272..29fc724 100644
--- a/xen/arch/x86/srat.c
+++ b/xen/arch/x86/srat.c
@@ -339,13 +339,6 @@ void __init acpi_numa_arch_fixup(void) {}
static u64 __initdata srat_region_mask;
-static u64 __init fill_mask(u64 mask)
-{
- while (mask & (mask + 1))
- mask |= mask + 1;
- return mask;
-}
-
static int __init srat_parse_region(struct acpi_subtable_header *header,
const unsigned long end)
{
@@ -366,8 +359,7 @@ static int __init srat_parse_region(struct acpi_subtable_header *header,
ma->base_address, ma->base_address + ma->length - 1);
srat_region_mask |= ma->base_address |
- fill_mask(ma->base_address ^
- (ma->base_address + ma->length - 1));
+ pdx_region_mask(ma->base_address, ma->length);
return 0;
}
@@ -381,7 +373,7 @@ void __init srat_parse_regions(u64 addr)
acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat))
return;
- srat_region_mask = fill_mask(addr - 1);
+ srat_region_mask = pdx_init_mask(addr);
acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
srat_parse_region, 0);
@@ -389,9 +381,7 @@ void __init srat_parse_regions(u64 addr)
if (e820.map[i].type != E820_RAM)
continue;
- if (~mask &
- fill_mask(e820.map[i].addr ^
- (e820.map[i].addr + e820.map[i].size - 1)))
+ if (~mask & pdx_region_mask(e820.map[i].addr, e820.map[i].size))
mask = 0;
}
diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c
index 15d4b91..57ad992 100644
--- a/xen/arch/x86/sysctl.c
+++ b/xen/arch/x86/sysctl.c
@@ -28,9 +28,25 @@
#include <xen/nodemask.h>
#include <xen/cpu.h>
#include <xsm/xsm.h>
+#include <asm/psr.h>
#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0)
+struct l3_cache_info {
+ int ret;
+ unsigned long size;
+};
+
+static void l3_cache_get(void *arg)
+{
+ struct cpuid4_info info;
+ struct l3_cache_info *l3_info = arg;
+
+ l3_info->ret = cpuid4_cache_lookup(3, &info);
+ if ( !l3_info->ret )
+ l3_info->size = info.size / 1024; /* in KB unit */
+}
+
long cpu_up_helper(void *data)
{
int cpu = (unsigned long)data;
@@ -101,6 +117,57 @@ long arch_do_sysctl(
}
break;
+ case XEN_SYSCTL_psr_cmt_op:
+ if ( !psr_cmt_enabled() )
+ return -ENODEV;
+
+ if ( sysctl->u.psr_cmt_op.flags != 0 )
+ return -EINVAL;
+
+ switch ( sysctl->u.psr_cmt_op.cmd )
+ {
+ case XEN_SYSCTL_PSR_CMT_enabled:
+ sysctl->u.psr_cmt_op.u.data =
+ (psr_cmt->features & PSR_RESOURCE_TYPE_L3) &&
+ (psr_cmt->l3.features & PSR_CMT_L3_OCCUPANCY);
+ break;
+ case XEN_SYSCTL_PSR_CMT_get_total_rmid:
+ sysctl->u.psr_cmt_op.u.data = psr_cmt->rmid_max;
+ break;
+ case XEN_SYSCTL_PSR_CMT_get_l3_upscaling_factor:
+ sysctl->u.psr_cmt_op.u.data = psr_cmt->l3.upscaling_factor;
+ break;
+ case XEN_SYSCTL_PSR_CMT_get_l3_cache_size:
+ {
+ struct l3_cache_info info;
+ unsigned int cpu = sysctl->u.psr_cmt_op.u.l3_cache.cpu;
+
+ if ( (cpu >= nr_cpu_ids) || !cpu_online(cpu) )
+ {
+ ret = -ENODEV;
+ sysctl->u.psr_cmt_op.u.data = 0;
+ break;
+ }
+ if ( cpu == smp_processor_id() )
+ l3_cache_get(&info);
+ else
+ on_selected_cpus(cpumask_of(cpu), l3_cache_get, &info, 1);
+
+ ret = info.ret;
+ sysctl->u.psr_cmt_op.u.data = (ret ? 0 : info.size);
+ break;
+ }
+ default:
+ sysctl->u.psr_cmt_op.u.data = 0;
+ ret = -ENOSYS;
+ break;
+ }
+
+ if ( __copy_to_guest(u_sysctl, sysctl, 1) )
+ ret = -EFAULT;
+
+ break;
+
default:
ret = -ENOSYS;
break;
diff --git a/xen/arch/x86/tboot.c b/xen/arch/x86/tboot.c
index ccde4a0..a8fb3a0 100644
--- a/xen/arch/x86/tboot.c
+++ b/xen/arch/x86/tboot.c
@@ -15,8 +15,8 @@
#include <crypto/vmac.h>
/* tboot=<physical address of shared page> */
-static char __initdata opt_tboot[20] = "";
-string_param("tboot", opt_tboot);
+static unsigned long __initdata opt_tboot_pa;
+integer_param("tboot", opt_tboot_pa);
/* Global pointer to shared data; NULL means no measured launch. */
tboot_shared_t *g_tboot_shared;
@@ -93,15 +93,13 @@ static void __init tboot_copy_memory(unsigned char *va, uint32_t size,
void __init tboot_probe(void)
{
tboot_shared_t *tboot_shared;
- unsigned long p_tboot_shared;
/* Look for valid page-aligned address for shared page. */
- p_tboot_shared = simple_strtoul(opt_tboot, NULL, 0);
- if ( (p_tboot_shared == 0) || ((p_tboot_shared & ~PAGE_MASK) != 0) )
+ if ( !opt_tboot_pa || (opt_tboot_pa & ~PAGE_MASK) )
return;
/* Map and check for tboot UUID. */
- set_fixmap(FIX_TBOOT_SHARED_BASE, p_tboot_shared);
+ set_fixmap(FIX_TBOOT_SHARED_BASE, opt_tboot_pa);
tboot_shared = (tboot_shared_t *)fix_to_virt(FIX_TBOOT_SHARED_BASE);
if ( tboot_shared == NULL )
return;
@@ -117,7 +115,7 @@ void __init tboot_probe(void)
}
g_tboot_shared = tboot_shared;
- printk("TBOOT: found shared page at phys addr %lx:\n", p_tboot_shared);
+ printk("TBOOT: found shared page at phys addr %#lx:\n", opt_tboot_pa);
printk(" version: %d\n", tboot_shared->version);
printk(" log_addr: %#x\n", tboot_shared->log_addr);
printk(" shutdown_entry: %#x\n", tboot_shared->shutdown_entry);
@@ -230,7 +228,8 @@ static void tboot_gen_domain_integrity(const uint8_t key[TB_KEY_SIZE],
if ( !is_idle_domain(d) )
{
struct hvm_iommu *hd = domain_hvm_iommu(d);
- update_iommu_mac(&ctx, hd->pgd_maddr, agaw_to_level(hd->agaw));
+ update_iommu_mac(&ctx, hd->arch.pgd_maddr,
+ agaw_to_level(hd->arch.agaw));
}
}
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index f80d661..74c01e3 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -85,6 +85,9 @@ static u16 pit_stamp16;
static u32 pit_stamp32;
static bool_t __read_mostly using_pit;
+/* Boot timestamp, filled in head.S */
+u64 __initdata boot_tsc_stamp;
+
/*
* 32-bit division of integer dividend and integer divisor yielding
* 32-bit fractional quotient.
@@ -118,7 +121,7 @@ static inline u32 mul_frac(u32 multiplicand, u32 multiplier)
* Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
* yielding a 64-bit result.
*/
-static inline u64 scale_delta(u64 delta, struct time_scale *scale)
+u64 scale_delta(u64 delta, struct time_scale *scale)
{
u64 product;
@@ -269,7 +272,7 @@ static u64 init_pit_and_calibrate_tsc(void)
return ((end - start) * (u64)CALIBRATE_FRAC);
}
-static void set_time_scale(struct time_scale *ts, u64 ticks_per_sec)
+void set_time_scale(struct time_scale *ts, u64 ticks_per_sec)
{
u64 tps64 = ticks_per_sec;
u32 tps32;
@@ -651,37 +654,40 @@ mktime (unsigned int year, unsigned int mon,
)*60 + sec; /* finally seconds */
}
-static unsigned long __get_cmos_time(void)
-{
+struct rtc_time {
unsigned int year, mon, day, hour, min, sec;
+};
- sec = CMOS_READ(RTC_SECONDS);
- min = CMOS_READ(RTC_MINUTES);
- hour = CMOS_READ(RTC_HOURS);
- day = CMOS_READ(RTC_DAY_OF_MONTH);
- mon = CMOS_READ(RTC_MONTH);
- year = CMOS_READ(RTC_YEAR);
+static void __get_cmos_time(struct rtc_time *rtc)
+{
+ rtc->sec = CMOS_READ(RTC_SECONDS);
+ rtc->min = CMOS_READ(RTC_MINUTES);
+ rtc->hour = CMOS_READ(RTC_HOURS);
+ rtc->day = CMOS_READ(RTC_DAY_OF_MONTH);
+ rtc->mon = CMOS_READ(RTC_MONTH);
+ rtc->year = CMOS_READ(RTC_YEAR);
- if ( !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD )
+ if ( RTC_ALWAYS_BCD || !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) )
{
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
+ BCD_TO_BIN(rtc->sec);
+ BCD_TO_BIN(rtc->min);
+ BCD_TO_BIN(rtc->hour);
+ BCD_TO_BIN(rtc->day);
+ BCD_TO_BIN(rtc->mon);
+ BCD_TO_BIN(rtc->year);
}
- if ( (year += 1900) < 1970 )
- year += 100;
-
- return mktime(year, mon, day, hour, min, sec);
+ if ( (rtc->year += 1900) < 1970 )
+ rtc->year += 100;
}
static unsigned long get_cmos_time(void)
{
unsigned long res, flags;
- int i;
+ struct rtc_time rtc;
+ unsigned int seconds = 60;
+ static bool_t __read_mostly cmos_rtc_probe;
+ boolean_param("cmos-rtc-probe", cmos_rtc_probe);
if ( efi_enabled )
{
@@ -690,42 +696,85 @@ static unsigned long get_cmos_time(void)
return res;
}
- if ( unlikely(acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) )
- panic("System without CMOS RTC must be booted from EFI");
+ if ( likely(!(acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC)) )
+ cmos_rtc_probe = 0;
+ else if ( system_state < SYS_STATE_smp_boot && !cmos_rtc_probe )
+ panic("System with no CMOS RTC advertised must be booted from EFI"
+ " (or with command line option \"cmos-rtc-probe\")");
+
+ for ( ; ; )
+ {
+ s_time_t start, t1, t2;
+
+ spin_lock_irqsave(&rtc_lock, flags);
+
+ /* read RTC exactly on falling edge of update flag */
+ start = NOW();
+ do { /* may take up to 1 second... */
+ t1 = NOW() - start;
+ } while ( !(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) &&
+ t1 <= SECONDS(1) );
+
+ start = NOW();
+ do { /* must try at least 2.228 ms */
+ t2 = NOW() - start;
+ } while ( (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) &&
+ t2 < MILLISECS(3) );
+
+ __get_cmos_time(&rtc);
- spin_lock_irqsave(&rtc_lock, flags);
+ spin_unlock_irqrestore(&rtc_lock, flags);
- /* read RTC exactly on falling edge of update flag */
- for ( i = 0 ; i < 1000000 ; i++ ) /* may take up to 1 second... */
- if ( (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) )
+ if ( likely(!cmos_rtc_probe) ||
+ t1 > SECONDS(1) || t2 >= MILLISECS(3) ||
+ rtc.sec >= 60 || rtc.min >= 60 || rtc.hour >= 24 ||
+ !rtc.day || rtc.day > 31 ||
+ !rtc.mon || rtc.mon > 12 )
break;
- for ( i = 0 ; i < 1000000 ; i++ ) /* must try at least 2.228 ms */
- if ( !(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) )
+
+ if ( seconds < 60 )
+ {
+ if ( rtc.sec != seconds )
+ cmos_rtc_probe = 0;
break;
+ }
+
+ process_pending_softirqs();
- res = __get_cmos_time();
+ seconds = rtc.sec;
+ }
+
+ if ( unlikely(cmos_rtc_probe) )
+ panic("No CMOS RTC found - system must be booted from EFI");
- spin_unlock_irqrestore(&rtc_lock, flags);
- return res;
+ return mktime(rtc.year, rtc.mon, rtc.day, rtc.hour, rtc.min, rtc.sec);
}
/***************************************************************************
* System Time
***************************************************************************/
-s_time_t get_s_time(void)
+s_time_t get_s_time_fixed(u64 at_tsc)
{
struct cpu_time *t = &this_cpu(cpu_time);
u64 tsc, delta;
s_time_t now;
- rdtscll(tsc);
+ if ( at_tsc )
+ tsc = at_tsc;
+ else
+ rdtscll(tsc);
delta = tsc - t->local_tsc_stamp;
now = t->stime_local_stamp + scale_delta(delta, &t->tsc_scale);
return now;
}
+s_time_t get_s_time()
+{
+ return get_s_time_fixed(0);
+}
+
uint64_t tsc_ticks2ns(uint64_t ticks)
{
struct cpu_time *t = &this_cpu(cpu_time);
@@ -810,17 +859,23 @@ static void __update_vcpu_system_time(struct vcpu *v, int force)
v->arch.pv_vcpu.pending_system_time = _u;
}
-bool_t update_secondary_system_time(const struct vcpu *v,
+bool_t update_secondary_system_time(struct vcpu *v,
struct vcpu_time_info *u)
{
XEN_GUEST_HANDLE(vcpu_time_info_t) user_u = v->arch.time_info_guest;
+ smap_check_policy_t saved_policy;
if ( guest_handle_is_null(user_u) )
return 1;
+ saved_policy = smap_policy_change(v, SMAP_CHECK_ENABLED);
+
/* 1. Update userspace version. */
if ( __copy_field_to_guest(user_u, u, version) == sizeof(u->version) )
+ {
+ smap_policy_change(v, saved_policy);
return 0;
+ }
wmb();
/* 2. Update all other userspace fields. */
__copy_to_guest(user_u, u, 1);
@@ -829,6 +884,8 @@ bool_t update_secondary_system_time(const struct vcpu *v,
u->version = version_update_end(u->version);
__copy_field_to_guest(user_u, u, version);
+ smap_policy_change(v, saved_policy);
+
return 1;
}
@@ -922,15 +979,15 @@ int cpu_frequency_change(u64 freq)
void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
{
u64 x;
- u32 y, _wc_sec, _wc_nsec;
+ u32 y;
struct domain *d;
- x = (secs * 1000000000ULL) + (u64)nsecs - system_time_base;
+ x = SECONDS(secs) + (u64)nsecs - system_time_base;
y = do_div(x, 1000000000);
spin_lock(&wc_lock);
- wc_sec = _wc_sec = (u32)x;
- wc_nsec = _wc_nsec = (u32)y;
+ wc_sec = x;
+ wc_nsec = y;
spin_unlock(&wc_lock);
rcu_read_lock(&domlist_read_lock);
@@ -1324,7 +1381,7 @@ void init_percpu_time(void)
s_time_t now;
/* Initial estimate for TSC rate. */
- this_cpu(cpu_time).tsc_scale = per_cpu(cpu_time, 0).tsc_scale;
+ t->tsc_scale = per_cpu(cpu_time, 0).tsc_scale;
local_irq_save(flags);
rdtscll(t->local_tsc_stamp);
@@ -1434,9 +1491,6 @@ int __init init_xen_time(void)
open_softirq(TIME_CALIBRATE_SOFTIRQ, local_time_calibration);
- /* System time (get_s_time()) starts ticking from now. */
- rdtscll(this_cpu(cpu_time).local_tsc_stamp);
-
/* NB. get_cmos_time() can take over one second to execute. */
do_settime(get_cmos_time(), 0, NOW());
@@ -1454,16 +1508,18 @@ int __init init_xen_time(void)
/* Early init function. */
void __init early_time_init(void)
{
+ struct cpu_time *t = &this_cpu(cpu_time);
u64 tmp = init_pit_and_calibrate_tsc();
- set_time_scale(&this_cpu(cpu_time).tsc_scale, tmp);
+ set_time_scale(&t->tsc_scale, tmp);
+ t->local_tsc_stamp = boot_tsc_stamp;
do_div(tmp, 1000);
cpu_khz = (unsigned long)tmp;
printk("Detected %lu.%03lu MHz processor.\n",
cpu_khz / 1000, cpu_khz % 1000);
- setup_irq(0, &irq0);
+ setup_irq(0, 0, &irq0);
}
/* keep pit enabled for pit_broadcast working while cpuidle enabled */
@@ -1549,8 +1605,8 @@ unsigned long get_localtime(struct domain *d)
/* Return microsecs after 00:00:00 localtime, 1 January, 1970. */
uint64_t get_localtime_us(struct domain *d)
{
- return ((wc_sec + d->time_offset_seconds) * 1000000000ULL
- + wc_nsec + NOW()) / 1000UL;
+ return (SECONDS(wc_sec + d->time_offset_seconds) + wc_nsec + NOW())
+ / 1000UL;
}
unsigned long get_sec(void)
@@ -1601,7 +1657,7 @@ int time_resume(void)
return 0;
}
-int dom0_pit_access(struct ioreq *ioreq)
+int hwdom_pit_access(struct ioreq *ioreq)
{
/* Is Xen using Channel 2? Then disallow direct dom0 access. */
if ( using_pit )
@@ -1646,15 +1702,19 @@ int dom0_pit_access(struct ioreq *ioreq)
return 0;
}
-struct tm wallclock_time(void)
+struct tm wallclock_time(uint64_t *ns)
{
- uint64_t seconds;
+ uint64_t seconds, nsec;
if ( !wc_sec )
return (struct tm) { 0 };
- seconds = NOW() + (wc_sec * 1000000000ull) + wc_nsec;
- do_div(seconds, 1000000000);
+ seconds = NOW() + SECONDS(wc_sec) + wc_nsec;
+ nsec = do_div(seconds, 1000000000);
+
+ if ( ns )
+ *ns = nsec;
+
return gmtime(seconds);
}
@@ -1740,10 +1800,9 @@ void cpuid_time_leaf(uint32_t sub_idx, uint32_t *eax, uint32_t *ebx,
switch ( sub_idx )
{
case 0: /* features */
- *eax = ( ( (!!d->arch.vtsc) << 0 ) |
- ( (!!host_tsc_is_safe()) << 1 ) |
- ( (!!boot_cpu_has(X86_FEATURE_RDTSCP)) << 2 ) |
- 0 );
+ *eax = (!!d->arch.vtsc << 0) |
+ (!!host_tsc_is_safe() << 1) |
+ (!!boot_cpu_has(X86_FEATURE_RDTSCP) << 2);
*ebx = d->arch.tsc_mode;
*ecx = d->arch.tsc_khz;
*edx = d->arch.incarnation;
@@ -1781,39 +1840,34 @@ void tsc_get_info(struct domain *d, uint32_t *tsc_mode,
switch ( *tsc_mode )
{
+ uint64_t tsc;
+
case TSC_MODE_NEVER_EMULATE:
- *elapsed_nsec = *gtsc_khz = 0;
+ *elapsed_nsec = *gtsc_khz = 0;
break;
- case TSC_MODE_ALWAYS_EMULATE:
- *elapsed_nsec = get_s_time() - d->arch.vtsc_offset;
- *gtsc_khz = d->arch.tsc_khz;
- break;
case TSC_MODE_DEFAULT:
if ( d->arch.vtsc )
{
+ case TSC_MODE_ALWAYS_EMULATE:
*elapsed_nsec = get_s_time() - d->arch.vtsc_offset;
- *gtsc_khz = d->arch.tsc_khz;
- }
- else
- {
- uint64_t tsc = 0;
- rdtscll(tsc);
- *elapsed_nsec = scale_delta(tsc,&d->arch.vtsc_to_ns);
- *gtsc_khz = cpu_khz;
+ *gtsc_khz = d->arch.tsc_khz;
+ break;
}
+ rdtscll(tsc);
+ *elapsed_nsec = scale_delta(tsc, &d->arch.vtsc_to_ns);
+ *gtsc_khz = cpu_khz;
break;
case TSC_MODE_PVRDTSCP:
if ( d->arch.vtsc )
{
*elapsed_nsec = get_s_time() - d->arch.vtsc_offset;
- *gtsc_khz = cpu_khz;
+ *gtsc_khz = cpu_khz;
}
else
{
- uint64_t tsc = 0;
rdtscll(tsc);
- *elapsed_nsec = (scale_delta(tsc,&d->arch.vtsc_to_ns) -
- d->arch.vtsc_offset);
+ *elapsed_nsec = scale_delta(tsc, &d->arch.vtsc_to_ns) -
+ d->arch.vtsc_offset;
*gtsc_khz = 0; /* ignored by tsc_set_info */
}
break;
@@ -1835,7 +1889,7 @@ void tsc_set_info(struct domain *d,
uint32_t tsc_mode, uint64_t elapsed_nsec,
uint32_t gtsc_khz, uint32_t incarnation)
{
- if ( is_idle_domain(d) || (d->domain_id == 0) )
+ if ( is_idle_domain(d) || is_hardware_domain(d) )
{
d->arch.vtsc = 0;
return;
@@ -1870,38 +1924,32 @@ void tsc_set_info(struct domain *d,
switch ( d->arch.tsc_mode = tsc_mode )
{
- case TSC_MODE_NEVER_EMULATE:
- d->arch.vtsc = 0;
- break;
- case TSC_MODE_ALWAYS_EMULATE:
- d->arch.vtsc = 1;
- d->arch.vtsc_offset = get_s_time() - elapsed_nsec;
- d->arch.tsc_khz = gtsc_khz ? gtsc_khz : cpu_khz;
- set_time_scale(&d->arch.vtsc_to_ns, d->arch.tsc_khz * 1000 );
- d->arch.ns_to_vtsc = scale_reciprocal(d->arch.vtsc_to_ns);
- break;
case TSC_MODE_DEFAULT:
- d->arch.vtsc = 1;
+ case TSC_MODE_ALWAYS_EMULATE:
d->arch.vtsc_offset = get_s_time() - elapsed_nsec;
- d->arch.tsc_khz = gtsc_khz ? gtsc_khz : cpu_khz;
- set_time_scale(&d->arch.vtsc_to_ns, d->arch.tsc_khz * 1000 );
+ d->arch.tsc_khz = gtsc_khz ?: cpu_khz;
+ set_time_scale(&d->arch.vtsc_to_ns, d->arch.tsc_khz * 1000);
/*
- * Use native TSC if the host has safe TSC and:
+ * In default mode use native TSC if the host has safe TSC and:
* HVM/PVH: host and guest frequencies are the same (either
* "naturally" or via TSC scaling)
* PV: guest has not migrated yet (and thus arch.tsc_khz == cpu_khz)
*/
- if ( host_tsc_is_safe() &&
- ((has_hvm_container_domain(d) &&
- (d->arch.tsc_khz == cpu_khz || cpu_has_tsc_ratio)) ||
+ if ( tsc_mode == TSC_MODE_DEFAULT && host_tsc_is_safe() &&
+ (has_hvm_container_domain(d) ?
+ d->arch.tsc_khz == cpu_khz || cpu_has_tsc_ratio :
incarnation == 0) )
+ {
+ case TSC_MODE_NEVER_EMULATE:
d->arch.vtsc = 0;
- else
- d->arch.ns_to_vtsc = scale_reciprocal(d->arch.vtsc_to_ns);
+ break;
+ }
+ d->arch.vtsc = 1;
+ d->arch.ns_to_vtsc = scale_reciprocal(d->arch.vtsc_to_ns);
break;
case TSC_MODE_PVRDTSCP:
- d->arch.vtsc = boot_cpu_has(X86_FEATURE_RDTSCP) &&
- host_tsc_is_safe() ? 0 : 1;
+ d->arch.vtsc = !boot_cpu_has(X86_FEATURE_RDTSCP) ||
+ !host_tsc_is_safe();
d->arch.tsc_khz = cpu_khz;
set_time_scale(&d->arch.vtsc_to_ns, d->arch.tsc_khz * 1000 );
d->arch.ns_to_vtsc = scale_reciprocal(d->arch.vtsc_to_ns);
@@ -1919,7 +1967,24 @@ void tsc_set_info(struct domain *d,
}
d->arch.incarnation = incarnation + 1;
if ( is_hvm_domain(d) )
+ {
hvm_set_rdtsc_exiting(d, d->arch.vtsc);
+ if ( d->vcpu && d->vcpu[0] && incarnation == 0 )
+ {
+ /*
+ * set_tsc_offset() is called from hvm_vcpu_initialise() before
+ * tsc_set_info(). New vtsc mode may require recomputing TSC
+ * offset.
+ * We only need to do this for BSP during initial boot. APs will
+ * call set_tsc_offset() later from hvm_vcpu_reset_state() and they
+ * will sync their TSC to BSP's sync_tsc.
+ */
+ rdtscll(d->arch.hvm_domain.sync_tsc);
+ hvm_funcs.set_tsc_offset(d->vcpu[0],
+ d->vcpu[0]->arch.hvm_vcpu.cache_tsc_offset,
+ d->arch.hvm_domain.sync_tsc);
+ }
+ }
}
/* vtsc may incur measurable performance degradation, diagnose with this */
@@ -1945,7 +2010,7 @@ static void dump_softtsc(unsigned char key)
"warp=%lu (count=%lu)\n", tsc_max_warp, tsc_check_count);
for_each_domain ( d )
{
- if ( d->domain_id == 0 && d->arch.tsc_mode == TSC_MODE_DEFAULT )
+ if ( is_hardware_domain(d) && d->arch.tsc_mode == TSC_MODE_DEFAULT )
continue;
printk("dom%u%s: mode=%d",d->domain_id,
is_hvm_domain(d) ? "(hvm)" : "", d->arch.tsc_mode);
diff --git a/xen/arch/x86/trace.c b/xen/arch/x86/trace.c
index b1804a4..64e9ad0 100644
--- a/xen/arch/x86/trace.c
+++ b/xen/arch/x86/trace.c
@@ -38,12 +38,12 @@ void __trace_pv_trap(int trapnr, unsigned long eip,
{
if ( is_pv_32on64_vcpu(current) )
{
- struct {
+ struct __packed {
unsigned eip:32,
trapnr:15,
use_error_code:1,
error_code:16;
- } __attribute__((packed)) d;
+ } d;
d.eip = eip;
d.trapnr = trapnr;
@@ -54,12 +54,12 @@ void __trace_pv_trap(int trapnr, unsigned long eip,
}
else
{
- struct {
+ struct __packed {
unsigned long eip;
unsigned trapnr:15,
use_error_code:1,
error_code:16;
- } __attribute__((packed)) d;
+ } d;
unsigned event;
d.eip = eip;
@@ -79,9 +79,9 @@ void __trace_pv_page_fault(unsigned long addr, unsigned error_code)
if ( is_pv_32on64_vcpu(current) )
{
- struct {
+ struct __packed {
u32 eip, addr, error_code;
- } __attribute__((packed)) d;
+ } d;
d.eip = eip;
d.addr = addr;
@@ -91,10 +91,10 @@ void __trace_pv_page_fault(unsigned long addr, unsigned error_code)
}
else
{
- struct {
+ struct __packed {
unsigned long eip, addr;
u32 error_code;
- } __attribute__((packed)) d;
+ } d;
unsigned event;
d.eip = eip;
@@ -125,18 +125,18 @@ void __trace_trap_two_addr(unsigned event, unsigned long va1,
{
if ( is_pv_32on64_vcpu(current) )
{
- struct {
+ struct __packed {
u32 va1, va2;
- } __attribute__((packed)) d;
+ } d;
d.va1=va1;
d.va2=va2;
__trace_var(event, 1, sizeof(d), &d);
}
else
{
- struct {
+ struct __packed {
unsigned long va1, va2;
- } __attribute__((packed)) d;
+ } d;
d.va1=va1;
d.va2=va2;
event |= TRC_64_FLAG;
@@ -158,10 +158,10 @@ void __trace_ptwr_emulation(unsigned long addr, l1_pgentry_t npte)
if ( is_pv_32on64_vcpu(current) )
{
- struct {
+ struct __packed {
l1_pgentry_t pte;
u32 addr, eip;
- } __attribute__((packed)) d;
+ } d;
d.addr = addr;
d.eip = eip;
d.pte = npte;
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 4d27e12..10fc2ca 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -114,7 +114,7 @@ boolean_param("ler", opt_ler);
#define stack_words_per_line 4
#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)regs->rsp)
-static void show_guest_stack(struct vcpu *v, struct cpu_user_regs *regs)
+static void show_guest_stack(struct vcpu *v, const struct cpu_user_regs *regs)
{
int i;
unsigned long *stack, addr;
@@ -290,7 +290,7 @@ static void show_trace(const struct cpu_user_regs *regs)
printk("\n");
}
-void show_stack(struct cpu_user_regs *regs)
+void show_stack(const struct cpu_user_regs *regs)
{
unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;
int i;
@@ -349,7 +349,7 @@ void show_stack_overflow(unsigned int cpu, const struct cpu_user_regs *regs)
#endif
}
-void show_execution_state(struct cpu_user_regs *regs)
+void show_execution_state(const struct cpu_user_regs *regs)
{
show_registers(regs);
show_stack(regs);
@@ -375,21 +375,18 @@ void vcpu_show_execution_state(struct vcpu *v)
vcpu_unpause(v);
}
-static char *trapstr(int trapnr)
+static const char *trapstr(unsigned int trapnr)
{
- static char *strings[] = {
- "divide error", "debug", "nmi", "bkpt", "overflow", "bounds",
- "invalid opcode", "device not available", "double fault",
- "coprocessor segment", "invalid tss", "segment not found",
- "stack error", "general protection fault", "page fault",
- "spurious interrupt", "coprocessor error", "alignment check",
- "machine check", "simd error"
+ static const char * const strings[] = {
+ "divide error", "debug", "nmi", "bkpt", "overflow", "bounds",
+ "invalid opcode", "device not available", "double fault",
+ "coprocessor segment", "invalid tss", "segment not found",
+ "stack error", "general protection fault", "page fault",
+ "spurious interrupt", "coprocessor error", "alignment check",
+ "machine check", "simd error", "virtualisation exception"
};
- if ( (trapnr < 0) || (trapnr >= ARRAY_SIZE(strings)) )
- return "???";
-
- return strings[trapnr];
+ return trapnr < ARRAY_SIZE(strings) ? strings[trapnr] : "???";
}
/*
@@ -397,9 +394,13 @@ static char *trapstr(int trapnr)
* are disabled). In such situations we can't do much that is safe. We try to
* print out some tracing and then we just spin.
*/
-void fatal_trap(int trapnr, struct cpu_user_regs *regs)
+void fatal_trap(const struct cpu_user_regs *regs)
{
static DEFINE_PER_CPU(char, depth);
+ unsigned int trapnr = regs->entry_vector;
+
+ /* Set AC to reduce chance of further SMAP faults */
+ stac();
/*
* In some cases, we can end up in a vicious cycle of fatal_trap()s
@@ -534,10 +535,19 @@ int set_guest_nmi_trapbounce(void)
return !null_trap_bounce(v, tb);
}
-static inline void do_trap(
- int trapnr, struct cpu_user_regs *regs, int use_error_code)
+void do_reserved_trap(struct cpu_user_regs *regs)
+{
+ unsigned int trapnr = regs->entry_vector;
+
+ DEBUGGER_trap_fatal(trapnr, regs);
+ show_execution_state(regs);
+ panic("FATAL RESERVED TRAP %#x: %s", trapnr, trapstr(trapnr));
+}
+
+static void do_trap(struct cpu_user_regs *regs, int use_error_code)
{
struct vcpu *curr = current;
+ unsigned int trapnr = regs->entry_vector;
unsigned long fixup;
DEBUGGER_trap_entry(trapnr, regs);
@@ -558,7 +568,8 @@ static inline void do_trap(
}
if ( ((trapnr == TRAP_copro_error) || (trapnr == TRAP_simd_error)) &&
- has_hvm_container_vcpu(curr) && curr->arch.hvm_vcpu.fpu_exception_callback )
+ system_state >= SYS_STATE_active && has_hvm_container_vcpu(curr) &&
+ curr->arch.hvm_vcpu.fpu_exception_callback )
{
curr->arch.hvm_vcpu.fpu_exception_callback(
curr->arch.hvm_vcpu.fpu_exception_callback_arg, regs);
@@ -573,28 +584,27 @@ static inline void do_trap(
trapnr, trapstr(trapnr), regs->error_code);
}
-#define DO_ERROR_NOCODE(trapnr, name) \
-void do_##name(struct cpu_user_regs *regs) \
+#define DO_ERROR_NOCODE(name) \
+void do_##name(struct cpu_user_regs *regs) \
{ \
- do_trap(trapnr, regs, 0); \
+ do_trap(regs, 0); \
}
-#define DO_ERROR(trapnr, name) \
-void do_##name(struct cpu_user_regs *regs) \
+#define DO_ERROR(name) \
+void do_##name(struct cpu_user_regs *regs) \
{ \
- do_trap(trapnr, regs, 1); \
+ do_trap(regs, 1); \
}
-DO_ERROR_NOCODE(TRAP_divide_error, divide_error)
-DO_ERROR_NOCODE(TRAP_overflow, overflow)
-DO_ERROR_NOCODE(TRAP_bounds, bounds)
-DO_ERROR_NOCODE(TRAP_copro_seg, coprocessor_segment_overrun)
-DO_ERROR( TRAP_invalid_tss, invalid_TSS)
-DO_ERROR( TRAP_no_segment, segment_not_present)
-DO_ERROR( TRAP_stack_error, stack_segment)
-DO_ERROR_NOCODE(TRAP_copro_error, coprocessor_error)
-DO_ERROR( TRAP_alignment_check, alignment_check)
-DO_ERROR_NOCODE(TRAP_simd_error, simd_coprocessor_error)
+DO_ERROR_NOCODE(divide_error)
+DO_ERROR_NOCODE(overflow)
+DO_ERROR_NOCODE(bounds)
+DO_ERROR( invalid_TSS)
+DO_ERROR( segment_not_present)
+DO_ERROR( stack_segment)
+DO_ERROR_NOCODE(coprocessor_error)
+DO_ERROR( alignment_check)
+DO_ERROR_NOCODE(simd_coprocessor_error)
/* Returns 0 if not handled, and non-0 for success. */
int rdmsr_hypervisor_regs(uint32_t idx, uint64_t *val)
@@ -650,7 +660,7 @@ int wrmsr_hypervisor_regs(uint32_t idx, uint64_t val)
if ( p2m_is_paging(t) )
{
p2m_mem_paging_populate(d, gmfn);
- return -EAGAIN;
+ return -ERESTART;
}
gdprintk(XENLOG_WARNING,
@@ -677,15 +687,25 @@ int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
struct domain *d = current->domain;
/* Optionally shift out of the way of Viridian architectural leaves. */
uint32_t base = is_viridian_domain(d) ? 0x40000100 : 0x40000000;
- uint32_t limit;
+ uint32_t limit, dummy;
idx -= base;
+ if ( idx > XEN_CPUID_MAX_NUM_LEAVES )
+ return 0; /* Avoid unnecessary pass through domain_cpuid() */
- /*
- * Some Solaris PV drivers fail if max > base + 2. Help them out by
- * hiding the PVRDTSCP leaf if PVRDTSCP is disabled.
- */
- limit = (d->arch.tsc_mode < TSC_MODE_PVRDTSCP) ? 2 : 3;
+ domain_cpuid(d, base, 0, &limit, &dummy, &dummy, &dummy);
+ if ( limit == 0 )
+ /* Default number of leaves */
+ limit = XEN_CPUID_MAX_NUM_LEAVES;
+ else
+ {
+ /* User-specified number of leaves */
+ limit &= 0xff;
+ if ( limit < 2 )
+ limit = 2;
+ else if ( limit > XEN_CPUID_MAX_NUM_LEAVES )
+ limit = XEN_CPUID_MAX_NUM_LEAVES;
+ }
if ( idx > limit )
return 0;
@@ -722,6 +742,10 @@ int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
cpuid_time_leaf( sub_idx, eax, ebx, ecx, edx );
break;
+ case 4:
+ hvm_hypervisor_cpuid_leaf(sub_idx, eax, ebx, ecx, edx);
+ break;
+
default:
BUG();
}
@@ -732,18 +756,19 @@ int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
void pv_cpuid(struct cpu_user_regs *regs)
{
uint32_t a, b, c, d;
+ struct vcpu *curr = current;
a = regs->eax;
b = regs->ebx;
c = regs->ecx;
d = regs->edx;
- if ( current->domain->domain_id != 0 )
+ if ( !is_control_domain(curr->domain) && !is_hardware_domain(curr->domain) )
{
unsigned int cpuid_leaf = a, sub_leaf = c;
if ( !cpuid_hypervisor_leaves(a, c, &a, &b, &c, &d) )
- domain_cpuid(current->domain, a, c, &a, &b, &c, &d);
+ domain_cpuid(curr->domain, a, c, &a, &b, &c, &d);
switch ( cpuid_leaf )
{
@@ -751,15 +776,15 @@ void pv_cpuid(struct cpu_user_regs *regs)
{
unsigned int _eax, _ebx, _ecx, _edx;
/* EBX value of main leaf 0 depends on enabled xsave features */
- if ( sub_leaf == 0 && current->arch.xcr0 )
+ if ( sub_leaf == 0 && curr->arch.xcr0 )
{
/* reset EBX to default value first */
b = XSTATE_AREA_MIN_SIZE;
for ( sub_leaf = 2; sub_leaf < 63; sub_leaf++ )
{
- if ( !(current->arch.xcr0 & (1ULL << sub_leaf)) )
+ if ( !(curr->arch.xcr0 & (1ULL << sub_leaf)) )
continue;
- domain_cpuid(current->domain, cpuid_leaf, sub_leaf,
+ domain_cpuid(curr->domain, cpuid_leaf, sub_leaf,
&_eax, &_ebx, &_ecx, &_edx);
if ( (_eax + _ebx) > b )
b = _eax + _ebx;
@@ -779,12 +804,16 @@ void pv_cpuid(struct cpu_user_regs *regs)
if ( (regs->eax & 0x7fffffff) == 0x00000001 )
{
/* Modify Feature Information. */
- __clear_bit(X86_FEATURE_VME, &d);
if ( !cpu_has_apic )
__clear_bit(X86_FEATURE_APIC, &d);
- __clear_bit(X86_FEATURE_PSE, &d);
- __clear_bit(X86_FEATURE_PGE, &d);
- __clear_bit(X86_FEATURE_PSE36, &d);
+
+ if ( !is_pvh_vcpu(curr) )
+ {
+ __clear_bit(X86_FEATURE_PSE, &d);
+ __clear_bit(X86_FEATURE_PGE, &d);
+ __clear_bit(X86_FEATURE_PSE36, &d);
+ __clear_bit(X86_FEATURE_VME, &d);
+ }
}
switch ( (uint32_t)regs->eax )
@@ -796,7 +825,7 @@ void pv_cpuid(struct cpu_user_regs *regs)
__clear_bit(X86_FEATURE_DS, &d);
__clear_bit(X86_FEATURE_ACC, &d);
__clear_bit(X86_FEATURE_PBE, &d);
- if ( is_pvh_vcpu(current) )
+ if ( is_pvh_vcpu(curr) )
__clear_bit(X86_FEATURE_MTRR, &d);
__clear_bit(X86_FEATURE_DTES64 % 32, &c);
@@ -805,7 +834,7 @@ void pv_cpuid(struct cpu_user_regs *regs)
__clear_bit(X86_FEATURE_VMXE % 32, &c);
__clear_bit(X86_FEATURE_SMXE % 32, &c);
__clear_bit(X86_FEATURE_TM2 % 32, &c);
- if ( is_pv_32bit_vcpu(current) )
+ if ( is_pv_32bit_vcpu(curr) )
__clear_bit(X86_FEATURE_CX16 % 32, &c);
__clear_bit(X86_FEATURE_XTPR % 32, &c);
__clear_bit(X86_FEATURE_PDCM % 32, &c);
@@ -829,6 +858,8 @@ void pv_cpuid(struct cpu_user_regs *regs)
cpufeat_mask(X86_FEATURE_BMI2) |
cpufeat_mask(X86_FEATURE_ERMS) |
cpufeat_mask(X86_FEATURE_RTM) |
+ cpufeat_mask(X86_FEATURE_RDSEED) |
+ cpufeat_mask(X86_FEATURE_ADX) |
cpufeat_mask(X86_FEATURE_FSGSBASE));
else
b = 0;
@@ -842,12 +873,12 @@ void pv_cpuid(struct cpu_user_regs *regs)
case 0x80000001:
/* Modify Feature Information. */
- if ( is_pv_32bit_vcpu(current) )
+ if ( is_pv_32bit_vcpu(curr) )
{
__clear_bit(X86_FEATURE_LM % 32, &d);
__clear_bit(X86_FEATURE_LAHF_LM % 32, &c);
}
- if ( is_pv_32on64_vcpu(current) &&
+ if ( is_pv_32on64_vcpu(curr) &&
boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
__clear_bit(X86_FEATURE_SYSCALL % 32, &d);
__clear_bit(X86_FEATURE_PAGE1GB % 32, &d);
@@ -1060,16 +1091,11 @@ void do_int3(struct cpu_user_regs *regs)
do_guest_trap(TRAP_int3, regs, 0);
}
-void do_machine_check(struct cpu_user_regs *regs)
-{
- machine_check_vector(regs, regs->error_code);
-}
-
static void reserved_bit_page_fault(
unsigned long addr, struct cpu_user_regs *regs)
{
- printk("d%d:v%d: reserved bit in page table (ec=%04X)\n",
- current->domain->domain_id, current->vcpu_id, regs->error_code);
+ printk("%pv: reserved bit in page table (ec=%04X)\n",
+ current, regs->error_code);
show_page_walk(addr);
show_execution_state(regs);
}
@@ -1111,8 +1137,7 @@ struct trap_bounce *propagate_page_fault(unsigned long addr, u16 error_code)
tb->flags |= TBF_INTERRUPT;
if ( unlikely(null_trap_bounce(v, tb)) )
{
- printk("d%d:v%d: unhandled page fault (ec=%04X)\n",
- v->domain->domain_id, v->vcpu_id, error_code);
+ printk("%pv: unhandled page fault (ec=%04X)\n", v, error_code);
show_page_walk(addr);
}
@@ -1181,11 +1206,12 @@ static int handle_gdt_ldt_mapping_fault(
enum pf_type {
real_fault,
smep_fault,
+ smap_fault,
spurious_fault
};
static enum pf_type __page_fault_type(
- unsigned long addr, unsigned int error_code)
+ unsigned long addr, const struct cpu_user_regs *regs)
{
unsigned long mfn, cr3 = read_cr3();
l4_pgentry_t l4e, *l4t;
@@ -1193,6 +1219,7 @@ static enum pf_type __page_fault_type(
l2_pgentry_t l2e, *l2t;
l1_pgentry_t l1e, *l1t;
unsigned int required_flags, disallowed_flags, page_user;
+ unsigned int error_code = regs->error_code;
/*
* We do not take spurious page faults in IRQ handlers as we do not
@@ -1261,19 +1288,37 @@ static enum pf_type __page_fault_type(
page_user &= l1e_get_flags(l1e);
leaf:
- /*
- * Supervisor Mode Execution Protection (SMEP):
- * Disallow supervisor execution from user-accessible mappings
- */
- if ( (read_cr4() & X86_CR4_SMEP) && page_user &&
- ((error_code & (PFEC_insn_fetch|PFEC_user_mode)) == PFEC_insn_fetch) )
- return smep_fault;
+ if ( page_user )
+ {
+ unsigned long cr4 = read_cr4();
+ /*
+ * Supervisor Mode Execution Prevention (SMEP):
+ * Disallow supervisor execution from user-accessible mappings
+ */
+ if ( (cr4 & X86_CR4_SMEP) &&
+ ((error_code & (PFEC_insn_fetch|PFEC_user_mode)) == PFEC_insn_fetch) )
+ return smep_fault;
+
+ /*
+ * Supervisor Mode Access Prevention (SMAP):
+ * Disallow supervisor access user-accessible mappings
+ * A fault is considered as an SMAP violation if the following
+ * conditions are true:
+ * - X86_CR4_SMAP is set in CR4
+ * - A user page is being accessed
+ * - CPL=3 or X86_EFLAGS_AC is clear
+ * - Page fault in kernel mode
+ */
+ if ( (cr4 & X86_CR4_SMAP) && !(error_code & PFEC_user_mode) &&
+ (((regs->cs & 3) == 3) || !(regs->eflags & X86_EFLAGS_AC)) )
+ return smap_fault;
+ }
return spurious_fault;
}
static enum pf_type spurious_page_fault(
- unsigned long addr, unsigned int error_code)
+ unsigned long addr, const struct cpu_user_regs *regs)
{
unsigned long flags;
enum pf_type pf_type;
@@ -1283,7 +1328,7 @@ static enum pf_type spurious_page_fault(
* page tables from becoming invalid under our feet during the walk.
*/
local_irq_save(flags);
- pf_type = __page_fault_type(addr, error_code);
+ pf_type = __page_fault_type(addr, regs);
local_irq_restore(flags);
return pf_type;
@@ -1378,8 +1423,14 @@ void do_page_fault(struct cpu_user_regs *regs)
if ( unlikely(!guest_mode(regs)) )
{
- pf_type = spurious_page_fault(addr, error_code);
- BUG_ON(pf_type == smep_fault);
+ pf_type = spurious_page_fault(addr, regs);
+ if ( (pf_type == smep_fault) || (pf_type == smap_fault) )
+ {
+ console_start_sync();
+ printk("Xen SM%cP violation\n", (pf_type == smep_fault) ? 'E' : 'A');
+ fatal_trap(regs);
+ }
+
if ( pf_type != real_fault )
return;
@@ -1405,10 +1456,12 @@ void do_page_fault(struct cpu_user_regs *regs)
if ( unlikely(current->domain->arch.suppress_spurious_page_faults) )
{
- pf_type = spurious_page_fault(addr, error_code);
- if ( pf_type == smep_fault )
+ pf_type = spurious_page_fault(addr, regs);
+ if ( (pf_type == smep_fault) || (pf_type == smap_fault))
{
- gdprintk(XENLOG_ERR, "Fatal SMEP fault\n");
+ printk(XENLOG_G_ERR "%pv fatal SM%cP violation\n",
+ current, (pf_type == smep_fault) ? 'E' : 'A');
+
domain_crash(current->domain);
}
if ( pf_type != real_fault )
@@ -1443,15 +1496,10 @@ void __init do_early_page_fault(struct cpu_user_regs *regs)
if ( stuck++ == 1000 )
{
- unsigned long *stk = (unsigned long *)regs;
- printk("Early fatal page fault at %04x:%p (cr2=%p, ec=%04x)\n",
+ console_start_sync();
+ printk("Early fatal page fault at %04x:%p (cr2=%p, ec=%04x)\n",
regs->cs, _p(regs->eip), _p(cr2), regs->error_code);
- show_page_walk(cr2);
- printk("Stack dump: ");
- while ( ((long)stk & ((PAGE_SIZE - 1) & ~(BYTES_PER_LONG - 1))) != 0 )
- printk("%p ", _p(*stk++));
- for ( ; ; )
- halt();
+ fatal_trap(regs);
}
}
@@ -1859,7 +1907,7 @@ static inline uint64_t guest_misc_enable(uint64_t val)
static int is_cpufreq_controller(struct domain *d)
{
return ((cpufreq_controller == FREQCTL_dom0_kernel) &&
- (d->domain_id == 0));
+ is_hardware_domain(d));
}
#include "x86_64/mmconfig.h"
@@ -2344,7 +2392,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
{
case 0:
break;
- case -EAGAIN: /* retry after preemption */
+ case -ERESTART: /* retry after preemption */
goto skip;
default: /* not okay */
goto fail;
@@ -2497,6 +2545,23 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
if ( wrmsr_safe(regs->ecx, msr_content) != 0 )
goto fail;
break;
+
+ case MSR_AMD64_DR0_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) || (msr_content >> 32) )
+ goto fail;
+ v->arch.pv_vcpu.dr_mask[0] = msr_content;
+ if ( v->arch.debugreg[7] & DR7_ACTIVE_MASK )
+ wrmsrl(MSR_AMD64_DR0_ADDRESS_MASK, msr_content);
+ break;
+ case MSR_AMD64_DR1_ADDRESS_MASK ... MSR_AMD64_DR3_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) || (msr_content >> 32) )
+ goto fail;
+ v->arch.pv_vcpu.dr_mask
+ [regs->_ecx - MSR_AMD64_DR1_ADDRESS_MASK + 1] = msr_content;
+ if ( v->arch.debugreg[7] & DR7_ACTIVE_MASK )
+ wrmsrl(regs->_ecx, msr_content);
+ break;
+
default:
if ( wrmsr_hypervisor_regs(regs->ecx, msr_content) == 1 )
break;
@@ -2584,6 +2649,21 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
regs->eax = (uint32_t)msr_content;
regs->edx = (uint32_t)(msr_content >> 32);
break;
+
+ case MSR_AMD64_DR0_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) )
+ goto fail;
+ regs->eax = v->arch.pv_vcpu.dr_mask[0];
+ regs->edx = 0;
+ break;
+ case MSR_AMD64_DR1_ADDRESS_MASK ... MSR_AMD64_DR3_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) )
+ goto fail;
+ regs->eax = v->arch.pv_vcpu.dr_mask
+ [regs->_ecx - MSR_AMD64_DR1_ADDRESS_MASK + 1];
+ regs->edx = 0;
+ break;
+
default:
if ( rdmsr_hypervisor_regs(regs->ecx, &val) )
{
@@ -3093,7 +3173,8 @@ static void nmi_mce_softirq(void)
/* Set the tmp value unconditionally, so that
* the check in the iret hypercall works. */
- cpumask_copy(st->vcpu->cpu_affinity_tmp, st->vcpu->cpu_affinity);
+ cpumask_copy(st->vcpu->cpu_hard_affinity_tmp,
+ st->vcpu->cpu_hard_affinity);
if ((cpu != st->processor)
|| (st->processor != st->vcpu->processor))
@@ -3102,7 +3183,7 @@ static void nmi_mce_softirq(void)
* Make sure to wakeup the vcpu on the
* specified processor.
*/
- vcpu_set_affinity(st->vcpu, cpumask_of(st->processor));
+ vcpu_set_hard_affinity(st->vcpu, cpumask_of(st->processor));
/* Affinity is restored in the iret hypercall. */
}
@@ -3128,11 +3209,11 @@ void async_exception_cleanup(struct vcpu *curr)
return;
/* Restore affinity. */
- if ( !cpumask_empty(curr->cpu_affinity_tmp) &&
- !cpumask_equal(curr->cpu_affinity_tmp, curr->cpu_affinity) )
+ if ( !cpumask_empty(curr->cpu_hard_affinity_tmp) &&
+ !cpumask_equal(curr->cpu_hard_affinity_tmp, curr->cpu_hard_affinity) )
{
- vcpu_set_affinity(curr, curr->cpu_affinity_tmp);
- cpumask_clear(curr->cpu_affinity_tmp);
+ vcpu_set_hard_affinity(curr, curr->cpu_hard_affinity_tmp);
+ cpumask_clear(curr->cpu_hard_affinity_tmp);
}
if ( !(curr->async_exception_mask & (curr->async_exception_mask - 1)) )
@@ -3148,9 +3229,9 @@ void async_exception_cleanup(struct vcpu *curr)
curr->async_exception_mask = curr->async_exception_state(trap).old_mask;
}
-static void nmi_dom0_report(unsigned int reason_idx)
+static void nmi_hwdom_report(unsigned int reason_idx)
{
- struct domain *d = dom0;
+ struct domain *d = hardware_domain;
if ( (d == NULL) || (d->vcpu == NULL) || (d->vcpu[0] == NULL) )
return;
@@ -3160,14 +3241,14 @@ static void nmi_dom0_report(unsigned int reason_idx)
send_guest_trap(d, 0, TRAP_nmi);
}
-static void pci_serr_error(struct cpu_user_regs *regs)
+static void pci_serr_error(const struct cpu_user_regs *regs)
{
outb((inb(0x61) & 0x0f) | 0x04, 0x61); /* clear-and-disable the PCI SERR error line. */
switch ( opt_nmi[0] )
{
case 'd': /* 'dom0' */
- nmi_dom0_report(_XEN_NMIREASON_pci_serr);
+ nmi_hwdom_report(_XEN_NMIREASON_pci_serr);
case 'i': /* 'ignore' */
/* Would like to print a diagnostic here but can't call printk()
from NMI context -- raise a softirq instead. */
@@ -3176,22 +3257,22 @@ static void pci_serr_error(struct cpu_user_regs *regs)
default: /* 'fatal' */
console_force_unlock();
printk("\n\nNMI - PCI system error (SERR)\n");
- fatal_trap(TRAP_nmi, regs);
+ fatal_trap(regs);
}
}
-static void io_check_error(struct cpu_user_regs *regs)
+static void io_check_error(const struct cpu_user_regs *regs)
{
switch ( opt_nmi[0] )
{
case 'd': /* 'dom0' */
- nmi_dom0_report(_XEN_NMIREASON_io_error);
+ nmi_hwdom_report(_XEN_NMIREASON_io_error);
case 'i': /* 'ignore' */
break;
default: /* 'fatal' */
console_force_unlock();
printk("\n\nNMI - I/O ERROR\n");
- fatal_trap(TRAP_nmi, regs);
+ fatal_trap(regs);
}
outb((inb(0x61) & 0x0f) | 0x08, 0x61); /* clear-and-disable IOCK */
@@ -3199,41 +3280,42 @@ static void io_check_error(struct cpu_user_regs *regs)
outb((inb(0x61) & 0x07) | 0x00, 0x61); /* enable IOCK */
}
-static void unknown_nmi_error(struct cpu_user_regs *regs, unsigned char reason)
+static void unknown_nmi_error(const struct cpu_user_regs *regs, unsigned char reason)
{
switch ( opt_nmi[0] )
{
case 'd': /* 'dom0' */
- nmi_dom0_report(_XEN_NMIREASON_unknown);
+ nmi_hwdom_report(_XEN_NMIREASON_unknown);
case 'i': /* 'ignore' */
break;
default: /* 'fatal' */
console_force_unlock();
printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
printk("Do you have a strange power saving mode enabled?\n");
- fatal_trap(TRAP_nmi, regs);
+ fatal_trap(regs);
}
}
-static int dummy_nmi_callback(struct cpu_user_regs *regs, int cpu)
+static int dummy_nmi_callback(const struct cpu_user_regs *regs, int cpu)
{
return 0;
}
static nmi_callback_t nmi_callback = dummy_nmi_callback;
-void do_nmi(struct cpu_user_regs *regs)
+void do_nmi(const struct cpu_user_regs *regs)
{
unsigned int cpu = smp_processor_id();
unsigned char reason;
+ bool_t handle_unknown = 0;
++nmi_count(cpu);
if ( nmi_callback(regs, cpu) )
return;
- if ( nmi_watchdog )
- nmi_watchdog_tick(regs);
+ if ( !nmi_watchdog || (!nmi_watchdog_tick(regs) && watchdog_force) )
+ handle_unknown = 1;
/* Only the BSP gets external NMIs from the system. */
if ( cpu == 0 )
@@ -3243,14 +3325,18 @@ void do_nmi(struct cpu_user_regs *regs)
pci_serr_error(regs);
if ( reason & 0x40 )
io_check_error(regs);
- if ( !(reason & 0xc0) && !nmi_watchdog )
+ if ( !(reason & 0xc0) && handle_unknown )
unknown_nmi_error(regs, reason);
}
}
-void set_nmi_callback(nmi_callback_t callback)
+nmi_callback_t set_nmi_callback(nmi_callback_t callback)
{
+ nmi_callback_t old_nmi_callback = nmi_callback;
+
nmi_callback = callback;
+
+ return old_nmi_callback;
}
void unset_nmi_callback(void)
@@ -3319,7 +3405,7 @@ void do_debug(struct cpu_user_regs *regs)
}
if ( !debugger_trap_fatal(TRAP_debug, regs) )
{
- WARN_ON(1);
+ WARN();
regs->eflags &= ~X86_EFLAGS_TF;
}
}
@@ -3348,26 +3434,17 @@ void do_debug(struct cpu_user_regs *regs)
return;
}
-void do_spurious_interrupt_bug(struct cpu_user_regs *regs)
+static void __init noinline __set_intr_gate(unsigned int n, uint32_t dpl, void *addr)
{
+ _set_gate(&idt_table[n], SYS_DESC_irq_gate, dpl, addr);
}
-static void __set_intr_gate(unsigned int n, uint32_t dpl, void *addr)
-{
- int i;
- /* Keep secondary tables in sync with IRQ updates. */
- for ( i = 1; i < nr_cpu_ids; i++ )
- if ( idt_tables[i] != NULL )
- _set_gate(&idt_tables[i][n], 14, dpl, addr);
- _set_gate(&idt_table[n], 14, dpl, addr);
-}
-
-static void set_swint_gate(unsigned int n, void *addr)
+static void __init set_swint_gate(unsigned int n, void *addr)
{
__set_intr_gate(n, 3, addr);
}
-void set_intr_gate(unsigned int n, void *addr)
+static void __init set_intr_gate(unsigned int n, void *addr)
{
__set_intr_gate(n, 0, addr);
}
@@ -3384,12 +3461,12 @@ void load_TR(void)
this_cpu(gdt_table) + TSS_ENTRY - FIRST_RESERVED_GDT_ENTRY,
(unsigned long)tss,
offsetof(struct tss_struct, __cacheline_filler) - 1,
- 9);
+ SYS_DESC_tss_avail);
_set_tssldt_desc(
this_cpu(compat_gdt_table) + TSS_ENTRY - FIRST_RESERVED_GDT_ENTRY,
(unsigned long)tss,
offsetof(struct tss_struct, __cacheline_filler) - 1,
- 11);
+ SYS_DESC_tss_busy);
/* Switch to non-compat GDT (which has B bit clear) to execute LTR. */
asm volatile (
@@ -3431,14 +3508,14 @@ void __devinit percpu_traps_init(void)
ler_enable();
}
-void __init trap_init(void)
+void __init init_idt_traps(void)
{
/*
- * Note that interrupt gates are always used, rather than trap gates. We
- * must have interrupts disabled until DS/ES/FS/GS are saved because the
- * first activation must have the "bad" value(s) for these registers and
- * we may lose them if another activation is installed before they are
- * saved. The page-fault handler also needs interrupts disabled until %cr2
+ * Note that interrupt gates are always used, rather than trap gates. We
+ * must have interrupts disabled until DS/ES/FS/GS are saved because the
+ * first activation must have the "bad" value(s) for these registers and
+ * we may lose them if another activation is installed before they are
+ * saved. The page-fault handler also needs interrupts disabled until %cr2
* has been read and saved on the stack.
*/
set_intr_gate(TRAP_divide_error,÷_error);
@@ -3449,23 +3526,58 @@ void __init trap_init(void)
set_intr_gate(TRAP_bounds,&bounds);
set_intr_gate(TRAP_invalid_op,&invalid_op);
set_intr_gate(TRAP_no_device,&device_not_available);
- set_intr_gate(TRAP_copro_seg,&coprocessor_segment_overrun);
+ set_intr_gate(TRAP_double_fault,&double_fault);
set_intr_gate(TRAP_invalid_tss,&invalid_TSS);
set_intr_gate(TRAP_no_segment,&segment_not_present);
set_intr_gate(TRAP_stack_error,&stack_segment);
set_intr_gate(TRAP_gp_fault,&general_protection);
- set_intr_gate(TRAP_page_fault,&page_fault);
- set_intr_gate(TRAP_spurious_int,&spurious_interrupt_bug);
+ set_intr_gate(TRAP_page_fault,&early_page_fault);
set_intr_gate(TRAP_copro_error,&coprocessor_error);
set_intr_gate(TRAP_alignment_check,&alignment_check);
set_intr_gate(TRAP_machine_check,&machine_check);
set_intr_gate(TRAP_simd_error,&simd_coprocessor_error);
+ /* Specify dedicated interrupt stacks for NMI, #DF, and #MC. */
+ set_ist(&idt_table[TRAP_double_fault], IST_DF);
+ set_ist(&idt_table[TRAP_nmi], IST_NMI);
+ set_ist(&idt_table[TRAP_machine_check], IST_MCE);
+
/* CPU0 uses the master IDT. */
idt_tables[0] = idt_table;
this_cpu(gdt_table) = boot_cpu_gdt_table;
this_cpu(compat_gdt_table) = boot_cpu_compat_gdt_table;
+}
+
+extern void (*__initconst autogen_entrypoints[NR_VECTORS])(void);
+void __init trap_init(void)
+{
+ unsigned int vector;
+
+ /* Replace early pagefault with real pagefault handler. */
+ set_intr_gate(TRAP_page_fault, &page_fault);
+
+ /* The 32-on-64 hypercall vector is only accessible from ring 1. */
+ _set_gate(idt_table + HYPERCALL_VECTOR,
+ SYS_DESC_trap_gate, 1, &compat_hypercall);
+
+ /* Fast trap for int80 (faster than taking the #GP-fixup path). */
+ _set_gate(idt_table + 0x80, SYS_DESC_trap_gate, 3, &int80_direct_trap);
+
+ for ( vector = 0; vector < NR_VECTORS; ++vector )
+ {
+ if ( autogen_entrypoints[vector] )
+ {
+ /* Found autogen entry: check we won't clobber an existing trap. */
+ ASSERT(idt_table[vector].b == 0);
+ set_intr_gate(vector, autogen_entrypoints[vector]);
+ }
+ else
+ {
+ /* No entry point: confirm we have an existing trap in place. */
+ ASSERT(idt_table[vector].b != 0);
+ }
+ }
percpu_traps_init();
@@ -3627,7 +3739,34 @@ long do_set_trap_table(XEN_GUEST_HANDLE_PARAM(const_trap_info_t) traps)
return rc;
}
-long set_debugreg(struct vcpu *v, int reg, unsigned long value)
+void activate_debugregs(const struct vcpu *curr)
+{
+ ASSERT(curr == current);
+
+ write_debugreg(0, curr->arch.debugreg[0]);
+ write_debugreg(1, curr->arch.debugreg[1]);
+ write_debugreg(2, curr->arch.debugreg[2]);
+ write_debugreg(3, curr->arch.debugreg[3]);
+ write_debugreg(6, curr->arch.debugreg[6]);
+
+ /*
+ * Avoid writing the subsequently getting replaced value when getting
+ * called from set_debugreg() below. Eventual future callers will need
+ * to take this into account.
+ */
+ if ( curr->arch.debugreg[7] & DR7_ACTIVE_MASK )
+ write_debugreg(7, curr->arch.debugreg[7]);
+
+ if ( boot_cpu_has(X86_FEATURE_DBEXT) )
+ {
+ wrmsrl(MSR_AMD64_DR0_ADDRESS_MASK, curr->arch.pv_vcpu.dr_mask[0]);
+ wrmsrl(MSR_AMD64_DR1_ADDRESS_MASK, curr->arch.pv_vcpu.dr_mask[1]);
+ wrmsrl(MSR_AMD64_DR2_ADDRESS_MASK, curr->arch.pv_vcpu.dr_mask[2]);
+ wrmsrl(MSR_AMD64_DR3_ADDRESS_MASK, curr->arch.pv_vcpu.dr_mask[3]);
+ }
+}
+
+long set_debugreg(struct vcpu *v, unsigned int reg, unsigned long value)
{
int i;
struct vcpu *curr = current;
@@ -3708,11 +3847,8 @@ long set_debugreg(struct vcpu *v, int reg, unsigned long value)
if ( (v == curr) &&
!(v->arch.debugreg[7] & DR7_ACTIVE_MASK) )
{
- write_debugreg(0, v->arch.debugreg[0]);
- write_debugreg(1, v->arch.debugreg[1]);
- write_debugreg(2, v->arch.debugreg[2]);
- write_debugreg(3, v->arch.debugreg[3]);
- write_debugreg(6, v->arch.debugreg[6]);
+ activate_debugregs(v);
+ break;
}
}
if ( v == curr )
@@ -3753,6 +3889,18 @@ unsigned long do_get_debugreg(int reg)
void asm_domain_crash_synchronous(unsigned long addr)
{
+ /*
+ * We need clear AC bit here because in entry.S AC is set
+ * by ASM_STAC to temporarily allow accesses to user pages
+ * which is prevented by SMAP by default.
+ *
+ * For some code paths, where this function is called, clac()
+ * is not needed, but adding clac() here instead of each place
+ * asm_domain_crash_synchronous() is called can reduce the code
+ * redundancy, and it is harmless as well.
+ */
+ clac();
+
if ( addr == 0 )
addr = this_cpu(last_extable_addr);
diff --git a/xen/arch/x86/usercopy.c b/xen/arch/x86/usercopy.c
index b79202b..4cc78f5 100644
--- a/xen/arch/x86/usercopy.c
+++ b/xen/arch/x86/usercopy.c
@@ -14,6 +14,7 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned n)
{
unsigned long __d0, __d1, __d2, __n = n;
+ stac();
asm volatile (
" cmp $"STR(2*BYTES_PER_LONG-1)",%0\n"
" jbe 1f\n"
@@ -42,6 +43,7 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned n)
: "=&c" (__n), "=&D" (__d0), "=&S" (__d1), "=&r" (__d2)
: "0" (__n), "1" (to), "2" (from), "3" (__n)
: "memory" );
+ clac();
return __n;
}
@@ -51,6 +53,7 @@ __copy_from_user_ll(void *to, const void __user *from, unsigned n)
{
unsigned long __d0, __d1, __d2, __n = n;
+ stac();
asm volatile (
" cmp $"STR(2*BYTES_PER_LONG-1)",%0\n"
" jbe 1f\n"
@@ -85,6 +88,7 @@ __copy_from_user_ll(void *to, const void __user *from, unsigned n)
: "=&c" (__n), "=&D" (__d0), "=&S" (__d1), "=&r" (__d2)
: "0" (__n), "1" (to), "2" (from), "3" (__n)
: "memory" );
+ clac();
return __n;
}
@@ -113,6 +117,7 @@ copy_to_user(void __user *to, const void *from, unsigned n)
#define __do_clear_user(addr,size) \
do { \
long __d0; \
+ stac(); \
__asm__ __volatile__( \
"0: rep; stosl\n" \
" movl %2,%0\n" \
@@ -126,6 +131,7 @@ do { \
_ASM_EXTABLE(1b,2b) \
: "=&c"(size), "=&D" (__d0) \
: "r"(size & 3), "0"(size / 4), "1"((long)addr), "a"(0)); \
+ clac(); \
} while (0)
/**
diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c
index b0098b3..447c650 100644
--- a/xen/arch/x86/x86_64/asm-offsets.c
+++ b/xen/arch/x86/x86_64/asm-offsets.c
@@ -14,11 +14,12 @@
#include <asm/hardirq.h>
#include <xen/multiboot.h>
-#define DEFINE(_sym, _val) \
- __asm__ __volatile__ ( "\n->" #_sym " %0 " #_val : : "i" (_val) )
-#define BLANK() \
- __asm__ __volatile__ ( "\n->" : : )
-#define OFFSET(_sym, _str, _mem) \
+#define DEFINE(_sym, _val) \
+ asm volatile ("\n.ascii\"==>#define " #_sym " %0 /* " #_val " */<==\"" \
+ : : "i" (_val) )
+#define BLANK() \
+ asm volatile ( "\n.ascii\"==><==\"" : : )
+#define OFFSET(_sym, _str, _mem) \
DEFINE(_sym, offsetof(_str, _mem));
void __dummy__(void)
@@ -159,9 +160,10 @@ void __dummy__(void)
OFFSET(IRQSTAT_softirq_pending, irq_cpustat_t, __softirq_pending);
BLANK();
- OFFSET(CPUINFO86_ext_features, struct cpuinfo_x86, x86_capability[1]);
+ OFFSET(CPUINFO_features, struct cpuinfo_x86, x86_capability);
BLANK();
OFFSET(MB_flags, multiboot_info_t, flags);
OFFSET(MB_cmdline, multiboot_info_t, cmdline);
+ OFFSET(MB_mem_lower, multiboot_info_t, mem_lower);
}
diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S
index 594b0b9..5b0af61 100644
--- a/xen/arch/x86/x86_64/compat/entry.S
+++ b/xen/arch/x86/x86_64/compat/entry.S
@@ -13,6 +13,7 @@
#include <irq_vectors.h>
ENTRY(compat_hypercall)
+ ASM_CLAC
pushq $0
SAVE_VOLATILE type=TRAP_syscall compat=1
@@ -404,7 +405,7 @@ ENTRY(compat_hypercall_table)
.quad compat_vcpu_op
.quad compat_ni_hypercall /* 25 */
.quad compat_mmuext_op
- .quad do_xsm_op
+ .quad compat_xsm_op
.quad compat_nmi_op
.quad compat_sched_op
.quad compat_callback_op /* 30 */
@@ -420,6 +421,7 @@ ENTRY(compat_hypercall_table)
.quad compat_ni_hypercall
.endr
.quad do_mca /* 48 */
+ .quad paging_domctl_continuation
.rept NR_hypercalls-((.-compat_hypercall_table)/8)
.quad compat_ni_hypercall
.endr
@@ -468,6 +470,7 @@ ENTRY(compat_hypercall_args_table)
.byte 0 /* compat_ni_hypercall */
.endr
.byte 1 /* do_mca */
+ .byte 1 /* paging_domctl_continuation */
.rept NR_hypercalls-(.-compat_hypercall_args_table)
.byte 0 /* compat_ni_hypercall */
.endr
diff --git a/xen/arch/x86/x86_64/compat/mm.c b/xen/arch/x86/x86_64/compat/mm.c
index 0a8408b..dce3f1f 100644
--- a/xen/arch/x86/x86_64/compat/mm.c
+++ b/xen/arch/x86/x86_64/compat/mm.c
@@ -1,8 +1,9 @@
#include <xen/event.h>
+#include <xen/mem_event.h>
+#include <xen/mem_access.h>
#include <xen/multicall.h>
#include <compat/memory.h>
#include <compat/xen.h>
-#include <asm/mem_event.h>
#include <asm/mem_sharing.h>
int compat_set_gdt(XEN_GUEST_HANDLE_PARAM(uint) frame_list, unsigned int entries)
@@ -44,7 +45,7 @@ int compat_update_descriptor(u32 pa_lo, u32 pa_hi, u32 desc_lo, u32 desc_hi)
desc_lo | ((u64)desc_hi << 32));
}
-int compat_arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
+int compat_arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
{
struct compat_machphys_mfn_list xmml;
l2_pgentry_t l2e;
@@ -52,6 +53,7 @@ int compat_arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
compat_pfn_t mfn;
unsigned int i;
int rc = 0;
+ int op = cmd & MEMOP_CMD_MASK;
switch ( op )
{
@@ -68,7 +70,7 @@ int compat_arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
XLAT_foreign_memory_map(nat, &cmp);
#undef XLAT_memory_map_HNDL_buffer
- rc = arch_memory_op(op, guest_handle_from_ptr(nat, void));
+ rc = arch_memory_op(cmd, guest_handle_from_ptr(nat, void));
break;
}
@@ -87,7 +89,7 @@ int compat_arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
XLAT_memory_map(nat, &cmp);
#undef XLAT_memory_map_HNDL_buffer
- rc = arch_memory_op(op, guest_handle_from_ptr(nat, void));
+ rc = arch_memory_op(cmd, guest_handle_from_ptr(nat, void));
if ( rc < 0 )
break;
@@ -111,12 +113,12 @@ int compat_arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
XLAT_pod_target(nat, &cmp);
- rc = arch_memory_op(op, guest_handle_from_ptr(nat, void));
+ rc = arch_memory_op(cmd, guest_handle_from_ptr(nat, void));
if ( rc < 0 )
break;
if ( rc == __HYPERVISOR_memory_op )
- hypercall_xlat_continuation(NULL, 0x2, nat, arg);
+ hypercall_xlat_continuation(NULL, 2, 0x2, nat, arg);
XLAT_pod_target(&cmp, nat);
@@ -146,6 +148,7 @@ int compat_arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
}
case XENMEM_machphys_mfn_list:
+ case XENMEM_machphys_compat_mfn_list:
{
unsigned long limit;
compat_pfn_t last_mfn;
@@ -185,7 +188,6 @@ int compat_arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
return mem_sharing_get_nr_shared_mfns();
case XENMEM_paging_op:
- case XENMEM_access_op:
{
xen_mem_event_op_t meo;
if ( copy_from_guest(&meo, arg, 1) )
@@ -195,6 +197,7 @@ int compat_arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
return -EFAULT;
break;
}
+
case XENMEM_sharing_op:
{
xen_mem_sharing_op_t mso;
@@ -351,7 +354,7 @@ int compat_mmuext_op(XEN_GUEST_HANDLE_PARAM(mmuext_op_compat_t) cmp_uops,
left = 1;
if ( arg1 != MMU_UPDATE_PREEMPTED )
{
- BUG_ON(!hypercall_xlat_continuation(&left, 0x01, nat_ops,
+ BUG_ON(!hypercall_xlat_continuation(&left, 4, 0x01, nat_ops,
cmp_uops));
if ( !test_bit(_MCSF_in_multicall, &mcs->flags) )
regs->_ecx += count - i;
@@ -359,7 +362,7 @@ int compat_mmuext_op(XEN_GUEST_HANDLE_PARAM(mmuext_op_compat_t) cmp_uops,
mcs->compat_call.args[1] += count - i;
}
else
- BUG_ON(hypercall_xlat_continuation(&left, 0));
+ BUG_ON(hypercall_xlat_continuation(&left, 4, 0));
BUG_ON(left != arg1);
}
else
diff --git a/xen/arch/x86/x86_64/compat/traps.c b/xen/arch/x86/x86_64/compat/traps.c
index 5f0ea0a..b6c2563 100644
--- a/xen/arch/x86/x86_64/compat/traps.c
+++ b/xen/arch/x86/x86_64/compat/traps.c
@@ -3,7 +3,7 @@
#include <compat/callback.h>
#include <compat/arch-x86_32.h>
-void compat_show_guest_stack(struct vcpu *v, struct cpu_user_regs *regs,
+void compat_show_guest_stack(struct vcpu *v, const struct cpu_user_regs *regs,
int debug_stack_lines)
{
unsigned int i, *stack, addr, mask = STACK_SIZE;
diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
index 3ea4683..b3d6e32 100644
--- a/xen/arch/x86/x86_64/entry.S
+++ b/xen/arch/x86/x86_64/entry.S
@@ -273,6 +273,7 @@ ENTRY(sysenter_entry)
pushq $0
pushfq
GLOBAL(sysenter_eflags_saved)
+ ASM_CLAC
pushq $3 /* ring 3 null cs */
pushq $0 /* null rip */
pushq $0
@@ -309,6 +310,7 @@ UNLIKELY_END(sysenter_gpf)
jmp .Lbounce_exception
ENTRY(int80_direct_trap)
+ ASM_CLAC
pushq $0
SAVE_VOLATILE 0x80
@@ -377,6 +379,7 @@ __UNLIKELY_END(create_bounce_frame_bad_sp)
movb TRAPBOUNCE_flags(%rdx),%cl
subq $40,%rsi
movq UREGS_ss+8(%rsp),%rax
+ ASM_STAC
.Lft2: movq %rax,32(%rsi) # SS
movq UREGS_rsp+8(%rsp),%rax
.Lft3: movq %rax,24(%rsi) # RSP
@@ -421,6 +424,7 @@ UNLIKELY_END(bounce_failsafe)
.Lft12: movq %rax,8(%rsi) # R11
movq UREGS_rcx+8(%rsp),%rax
.Lft13: movq %rax,(%rsi) # RCX
+ ASM_CLAC
/* Rewrite our stack frame and return to guest-OS mode. */
/* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */
/* Also clear AC: alignment checks shouldn't trigger in kernel mode. */
@@ -438,19 +442,30 @@ UNLIKELY_START(z, create_bounce_frame_bad_bounce_ip)
__UNLIKELY_END(create_bounce_frame_bad_bounce_ip)
movq %rax,UREGS_rip+8(%rsp)
ret
- _ASM_EXTABLE(.Lft2, dom_crash_sync_extable)
- _ASM_EXTABLE(.Lft3, dom_crash_sync_extable)
- _ASM_EXTABLE(.Lft4, dom_crash_sync_extable)
- _ASM_EXTABLE(.Lft5, dom_crash_sync_extable)
- _ASM_EXTABLE(.Lft6, dom_crash_sync_extable)
- _ASM_EXTABLE(.Lft7, dom_crash_sync_extable)
- _ASM_EXTABLE(.Lft8, dom_crash_sync_extable)
- _ASM_EXTABLE(.Lft9, dom_crash_sync_extable)
- _ASM_EXTABLE(.Lft10, dom_crash_sync_extable)
- _ASM_EXTABLE(.Lft11, dom_crash_sync_extable)
- _ASM_EXTABLE(.Lft12, dom_crash_sync_extable)
- _ASM_EXTABLE(.Lft13, dom_crash_sync_extable)
-
+ _ASM_EXTABLE(.Lft2, domain_crash_page_fault_32)
+ _ASM_EXTABLE(.Lft3, domain_crash_page_fault_24)
+ _ASM_EXTABLE(.Lft4, domain_crash_page_fault_8)
+ _ASM_EXTABLE(.Lft5, domain_crash_page_fault_16)
+ _ASM_EXTABLE(.Lft6, domain_crash_page_fault)
+ _ASM_EXTABLE(.Lft7, domain_crash_page_fault)
+ _ASM_EXTABLE(.Lft8, domain_crash_page_fault_24)
+ _ASM_EXTABLE(.Lft9, domain_crash_page_fault_16)
+ _ASM_EXTABLE(.Lft10, domain_crash_page_fault_8)
+ _ASM_EXTABLE(.Lft11, domain_crash_page_fault)
+ _ASM_EXTABLE(.Lft12, domain_crash_page_fault_8)
+ _ASM_EXTABLE(.Lft13, domain_crash_page_fault)
+
+domain_crash_page_fault_32:
+ addq $8,%rsi
+domain_crash_page_fault_24:
+ addq $8,%rsi
+domain_crash_page_fault_16:
+ addq $8,%rsi
+domain_crash_page_fault_8:
+ addq $8,%rsi
+domain_crash_page_fault:
+ movq %rsi,%rdi
+ call show_page_walk
ENTRY(dom_crash_sync_extable)
# Get out of the guest-save area of the stack.
GET_STACK_BASE(%rax)
@@ -465,6 +480,12 @@ ENTRY(dom_crash_sync_extable)
xorl %edi,%edi
jmp asm_domain_crash_synchronous /* Does not return */
+ENTRY(common_interrupt)
+ SAVE_ALL CLAC
+ movq %rsp,%rdi
+ callq do_IRQ
+ jmp ret_from_intr
+
/* No special register assumptions. */
ENTRY(ret_from_intr)
GET_CURRENT(%rbx)
@@ -479,7 +500,7 @@ ENTRY(page_fault)
movl $TRAP_page_fault,4(%rsp)
/* No special register assumptions. */
GLOBAL(handle_exception)
- SAVE_ALL
+ SAVE_ALL CLAC
handle_exception_saved:
testb $X86_EFLAGS_IF>>8,UREGS_eflags+1(%rsp)
jz exception_with_ints_disabled
@@ -526,8 +547,7 @@ exception_with_ints_disabled:
/* No special register assumptions. */
FATAL_exception_with_ints_disabled:
- movzbl UREGS_entry_vector(%rsp),%edi
- movq %rsp,%rsi
+ movq %rsp,%rdi
call fatal_trap
ud2
@@ -576,11 +596,6 @@ ENTRY(invalid_op)
movl $TRAP_invalid_op,4(%rsp)
jmp handle_exception
-ENTRY(coprocessor_segment_overrun)
- pushq $0
- movl $TRAP_copro_seg,4(%rsp)
- jmp handle_exception
-
ENTRY(invalid_TSS)
movl $TRAP_invalid_tss,4(%rsp)
jmp handle_exception
@@ -601,14 +616,10 @@ ENTRY(alignment_check)
movl $TRAP_alignment_check,4(%rsp)
jmp handle_exception
-ENTRY(spurious_interrupt_bug)
- pushq $0
- movl $TRAP_spurious_int,4(%rsp)
- jmp handle_exception
-
ENTRY(double_fault)
movl $TRAP_double_fault,4(%rsp)
- SAVE_ALL
+ /* Set AC to reduce chance of further SMAP faults */
+ SAVE_ALL STAC
movq %rsp,%rdi
call do_double_fault
ud2
@@ -625,7 +636,7 @@ ENTRY(nmi)
pushq $0
movl $TRAP_nmi,4(%rsp)
handle_ist_exception:
- SAVE_ALL
+ SAVE_ALL CLAC
testb $3,UREGS_cs(%rsp)
jz 1f
/* Interrupted guest context. Copy the context to stack bottom. */
@@ -661,7 +672,8 @@ handle_ist_exception:
ENTRY(nmi_crash)
pushq $0
movl $TRAP_nmi,4(%rsp)
- SAVE_ALL
+ /* Set AC to reduce chance of further SMAP faults */
+ SAVE_ALL STAC
movq %rsp,%rdi
callq do_nmi_crash /* Does not return */
ud2
@@ -704,18 +716,21 @@ ENTRY(exception_table)
.quad do_bounds
.quad do_invalid_op
.quad do_device_not_available
- .quad 0 # double_fault
- .quad do_coprocessor_segment_overrun
+ .quad do_reserved_trap /* double_fault - has its own entry. */
+ .quad do_reserved_trap /* coproc_seg_overrun - Intel 387 only. */
.quad do_invalid_TSS
.quad do_segment_not_present
.quad do_stack_segment
.quad do_general_protection
.quad do_page_fault
- .quad do_spurious_interrupt_bug
+ .quad do_reserved_trap /* Default PIC spurious irq - architecturally reserved. */
.quad do_coprocessor_error
.quad do_alignment_check
.quad do_machine_check
.quad do_simd_coprocessor_error
+ .rept TRAP_last_reserved + 1 - ((. - exception_table) / 8)
+ .quad do_reserved_trap /* Architecturally reserved exceptions. */
+ .endr
ENTRY(hypercall_table)
.quad do_set_trap_table /* 0 */
@@ -761,6 +776,7 @@ ENTRY(hypercall_table)
.quad do_ni_hypercall
.endr
.quad do_mca /* 48 */
+ .quad paging_domctl_continuation
.rept NR_hypercalls-((.-hypercall_table)/8)
.quad do_ni_hypercall
.endr
@@ -809,6 +825,55 @@ ENTRY(hypercall_args_table)
.byte 0 /* do_ni_hypercall */
.endr
.byte 1 /* do_mca */ /* 48 */
+ .byte 1 /* paging_domctl_continuation */
.rept NR_hypercalls-(.-hypercall_args_table)
.byte 0 /* do_ni_hypercall */
.endr
+
+/* Table of automatically generated entry points. One per vector. */
+ .section .init.rodata, "a", @progbits
+GLOBAL(autogen_entrypoints)
+ /* pop into the .init.rodata section and record an entry point. */
+ .macro entrypoint ent
+ .pushsection .init.rodata
+ .quad \ent
+ .popsection
+ .endm
+
+ .text
+autogen_stubs: /* Automatically generated stubs. */
+
+ vec = 0
+ .rept NR_VECTORS
+ ALIGN
+
+ /* Common interrupts, heading towards do_IRQ(). */
+ .if vec >= FIRST_DYNAMIC_VECTOR && vec != HYPERCALL_VECTOR && vec != LEGACY_SYSCALL_VECTOR
+
+1: pushq $0
+ movb $vec,4(%rsp)
+ jmp common_interrupt
+
+ entrypoint 1b
+
+ /* Reserved exceptions, heading towards do_reserved_trap(). */
+ .elseif vec == TRAP_copro_seg || vec == TRAP_spurious_int || (vec > TRAP_simd_error && vec <= TRAP_last_reserved)
+
+1: test $8,%spl /* 64bit exception frames are 16 byte aligned, but the word */
+ jz 2f /* size is 8 bytes. Check whether the processor gave us an */
+ pushq $0 /* error code, and insert an empty one if not. */
+2: movb $vec,4(%rsp)
+ jmp handle_exception
+
+ entrypoint 1b
+
+ /* Hand crafted entry points above. */
+ .else
+ entrypoint 0
+ .endif
+
+ vec = vec + 1
+ .endr
+
+ .section .init.rodata
+ .size autogen_entrypoints, . - autogen_entrypoints
diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c
index f6ea012..8e5a1a1 100644
--- a/xen/arch/x86/x86_64/mm.c
+++ b/xen/arch/x86/x86_64/mm.c
@@ -25,6 +25,9 @@
#include <xen/numa.h>
#include <xen/nodemask.h>
#include <xen/guest_access.h>
+#include <xen/hypercall.h>
+#include <xen/mem_event.h>
+#include <xen/mem_access.h>
#include <asm/current.h>
#include <asm/asm_defns.h>
#include <asm/page.h>
@@ -34,19 +37,9 @@
#include <asm/msr.h>
#include <asm/setup.h>
#include <asm/numa.h>
-#include <asm/mem_event.h>
#include <asm/mem_sharing.h>
#include <public/memory.h>
-/* Parameters for PFN/MADDR compression. */
-unsigned long __read_mostly max_pdx;
-unsigned long __read_mostly pfn_pdx_bottom_mask = ~0UL;
-unsigned long __read_mostly ma_va_bottom_mask = ~0UL;
-unsigned long __read_mostly pfn_top_mask = 0;
-unsigned long __read_mostly ma_top_mask = 0;
-unsigned long __read_mostly pfn_hole_mask = 0;
-unsigned int __read_mostly pfn_pdx_hole_shift = 0;
-
unsigned int __read_mostly m2p_compat_vstart = __HYPERVISOR_COMPAT_VIRT_START;
/* Enough page directories to map into the bottom 1GB. */
@@ -57,14 +50,6 @@ l2_pgentry_t __attribute__ ((__section__ (".bss.page_aligned")))
l2_pgentry_t *compat_idle_pg_table_l2;
-int __mfn_valid(unsigned long mfn)
-{
- return likely(mfn < max_page) &&
- likely(!(mfn & pfn_hole_mask)) &&
- likely(test_bit(pfn_to_pdx(mfn) / PDX_GROUP_COUNT,
- pdx_group_valid));
-}
-
void *do_page_walk(struct vcpu *v, unsigned long addr)
{
unsigned long mfn = pagetable_get_pfn(v->arch.guest_table);
@@ -117,42 +102,6 @@ void *do_page_walk(struct vcpu *v, unsigned long addr)
return map_domain_page(mfn) + (addr & ~PAGE_MASK);
}
-void __init pfn_pdx_hole_setup(unsigned long mask)
-{
- unsigned int i, j, bottom_shift = 0, hole_shift = 0;
-
- /*
- * We skip the first MAX_ORDER bits, as we never want to compress them.
- * This guarantees that page-pointer arithmetic remains valid within
- * contiguous aligned ranges of 2^MAX_ORDER pages. Among others, our
- * buddy allocator relies on this assumption.
- */
- for ( j = MAX_ORDER-1; ; )
- {
- i = find_next_zero_bit(&mask, BITS_PER_LONG, j);
- j = find_next_bit(&mask, BITS_PER_LONG, i);
- if ( j >= BITS_PER_LONG )
- break;
- if ( j - i > hole_shift )
- {
- hole_shift = j - i;
- bottom_shift = i;
- }
- }
- if ( !hole_shift )
- return;
-
- printk(KERN_INFO "PFN compression on bits %u...%u\n",
- bottom_shift, bottom_shift + hole_shift - 1);
-
- pfn_pdx_hole_shift = hole_shift;
- pfn_pdx_bottom_mask = (1UL << bottom_shift) - 1;
- ma_va_bottom_mask = (PAGE_SIZE << bottom_shift) - 1;
- pfn_hole_mask = ((1UL << hole_shift) - 1) << bottom_shift;
- pfn_top_mask = ~(pfn_pdx_bottom_mask | pfn_hole_mask);
- ma_top_mask = pfn_top_mask << PAGE_SHIFT;
-}
-
/*
* Allocate page table pages for m2p table
*/
@@ -948,15 +897,16 @@ void __init subarch_init_memory(void)
}
}
-long subarch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
+long subarch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
{
struct xen_machphys_mfn_list xmml;
l3_pgentry_t l3e;
l2_pgentry_t l2e;
- unsigned long v;
+ unsigned long v, limit;
xen_pfn_t mfn, last_mfn;
unsigned int i;
long rc = 0;
+ int op = cmd & MEMOP_CMD_MASK;
switch ( op )
{
@@ -1000,6 +950,34 @@ long subarch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
break;
+ case XENMEM_machphys_compat_mfn_list:
+ if ( copy_from_guest(&xmml, arg, 1) )
+ return -EFAULT;
+
+ limit = (unsigned long)(compat_machine_to_phys_mapping + max_page);
+ if ( limit > RDWR_COMPAT_MPT_VIRT_END )
+ limit = RDWR_COMPAT_MPT_VIRT_END;
+ for ( i = 0, v = RDWR_COMPAT_MPT_VIRT_START, last_mfn = 0;
+ (i != xmml.max_extents) && (v < limit);
+ i++, v += 1 << L2_PAGETABLE_SHIFT )
+ {
+ l2e = compat_idle_pg_table_l2[l2_table_offset(v)];
+ if ( l2e_get_flags(l2e) & _PAGE_PRESENT )
+ mfn = l2e_get_pfn(l2e);
+ else
+ mfn = last_mfn;
+ ASSERT(mfn);
+ if ( copy_to_guest_offset(xmml.extent_start, i, &mfn, 1) )
+ return -EFAULT;
+ last_mfn = mfn;
+ }
+
+ xmml.nr_extents = i;
+ if ( __copy_to_guest(arg, &xmml, 1) )
+ rc = -EFAULT;
+
+ break;
+
case XENMEM_get_sharing_freed_pages:
return mem_sharing_get_nr_saved_mfns();
@@ -1007,7 +985,6 @@ long subarch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
return mem_sharing_get_nr_shared_mfns();
case XENMEM_paging_op:
- case XENMEM_access_op:
{
xen_mem_event_op_t meo;
if ( copy_from_guest(&meo, arg, 1) )
@@ -1017,6 +994,7 @@ long subarch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
return -EFAULT;
break;
}
+
case XENMEM_sharing_op:
{
xen_mem_sharing_op_t mso;
@@ -1447,15 +1425,15 @@ int memory_add(unsigned long spfn, unsigned long epfn, unsigned int pxm)
if ( ret )
goto destroy_m2p;
- if ( !need_iommu(dom0) )
+ if ( !need_iommu(hardware_domain) )
{
for ( i = spfn; i < epfn; i++ )
- if ( iommu_map_page(dom0, i, i, IOMMUF_readable|IOMMUF_writable) )
+ if ( iommu_map_page(hardware_domain, i, i, IOMMUF_readable|IOMMUF_writable) )
break;
if ( i != epfn )
{
while (i-- > old_max)
- iommu_unmap_page(dom0, i);
+ iommu_unmap_page(hardware_domain, i);
goto destroy_m2p;
}
}
diff --git a/xen/arch/x86/x86_64/mmconf-fam10h.c b/xen/arch/x86/x86_64/mmconf-fam10h.c
index 1373acb..65260f6 100644
--- a/xen/arch/x86/x86_64/mmconf-fam10h.c
+++ b/xen/arch/x86/x86_64/mmconf-fam10h.c
@@ -6,6 +6,7 @@
#include <xen/acpi.h>
#include <xen/pci.h>
#include <xen/pci_regs.h>
+#include <xen/pci_ids.h>
#include <xen/init.h>
#include <xen/dmi.h>
#include <asm/amd.h>
diff --git a/xen/arch/x86/x86_64/mmconfig-shared.c b/xen/arch/x86/x86_64/mmconfig-shared.c
index 7589b64..742bc18 100644
--- a/xen/arch/x86/x86_64/mmconfig-shared.c
+++ b/xen/arch/x86/x86_64/mmconfig-shared.c
@@ -19,6 +19,7 @@
#include <xen/xmalloc.h>
#include <xen/pci.h>
#include <xen/pci_regs.h>
+#include <xen/pci_ids.h>
#include <asm/e820.h>
#include <asm/msr.h>
#include <asm/msr-index.h>
diff --git a/xen/arch/x86/x86_64/mmconfig.h b/xen/arch/x86/x86_64/mmconfig.h
index 36e0448..c447e5a 100644
--- a/xen/arch/x86/x86_64/mmconfig.h
+++ b/xen/arch/x86/x86_64/mmconfig.h
@@ -17,7 +17,6 @@
* Author: Allen Kay <allen.m.kay at intel.com> - adapted from linux
*/
-#define PCI_VENDOR_ID_INTEL 0x8086
#define PCI_DEVICE_ID_INTEL_E7520_MCH 0x3590
#define PCI_DEVICE_ID_INTEL_82945G_HB 0x2770
@@ -29,11 +28,8 @@
#define PCI_PROBE_MASK 0x000f
#define PCI_PROBE_NOEARLY 0x0010
-#define PCI_VENDOR_ID_AMD 0x1022
#define PCI_CHECK_ENABLE_AMD_MMCONF 0x20000
-#define PCI_VENDOR_ID_NVIDIA 0x10de
-
extern unsigned int pci_probe;
/*
diff --git a/xen/arch/x86/x86_64/platform_hypercall.c b/xen/arch/x86/x86_64/platform_hypercall.c
index b6f380e..ccfd30d 100644
--- a/xen/arch/x86/x86_64/platform_hypercall.c
+++ b/xen/arch/x86/x86_64/platform_hypercall.c
@@ -32,6 +32,10 @@ CHECK_pf_pcpu_version;
CHECK_pf_enter_acpi_sleep;
#undef xen_pf_enter_acpi_sleep
+#define xen_pf_resource_entry xenpf_resource_entry
+CHECK_pf_resource_entry;
+#undef xen_pf_resource_entry
+
#define COMPAT
#define _XEN_GUEST_HANDLE(t) XEN_GUEST_HANDLE(t)
#define _XEN_GUEST_HANDLE_PARAM(t) XEN_GUEST_HANDLE_PARAM(t)
diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c
index 90072c1..0040bef 100644
--- a/xen/arch/x86/x86_64/traps.c
+++ b/xen/arch/x86/x86_64/traps.c
@@ -79,14 +79,14 @@ static void _show_registers(
regs->gs, regs->ss, regs->cs);
}
-void show_registers(struct cpu_user_regs *regs)
+void show_registers(const struct cpu_user_regs *regs)
{
struct cpu_user_regs fault_regs = *regs;
unsigned long fault_crs[8];
enum context context;
struct vcpu *v = current;
- if ( has_hvm_container_vcpu(v) && guest_mode(regs) )
+ if ( guest_mode(regs) && has_hvm_container_vcpu(v) )
{
struct segment_register sreg;
context = CTXT_hvm_guest;
@@ -223,7 +223,6 @@ void show_page_walk(unsigned long addr)
l1_table_offset(addr), l1e_get_intpte(l1e), pfn);
}
-void double_fault(void);
void do_double_fault(struct cpu_user_regs *regs)
{
unsigned int cpu;
@@ -267,12 +266,8 @@ void toggle_guest_mode(struct vcpu *v)
v->arch.flags ^= TF_kernel_mode;
asm volatile ( "swapgs" );
update_cr3(v);
-#ifdef USER_MAPPINGS_ARE_GLOBAL
/* Don't flush user global mappings from the TLB. Don't tick TLB clock. */
asm volatile ( "mov %0, %%cr3" : : "r" (v->arch.cr3) : "memory" );
-#else
- write_ptbase(v);
-#endif
if ( !(v->arch.flags & TF_kernel_mode) )
return;
@@ -380,25 +375,6 @@ static int write_stack_trampoline(
void __devinit subarch_percpu_traps_init(void)
{
char *stack_bottom, *stack;
- int cpu = smp_processor_id();
-
- if ( cpu == 0 )
- {
- /* Specify dedicated interrupt stacks for NMI, #DF, and #MC. */
- set_intr_gate(TRAP_double_fault, &double_fault);
- set_ist(&idt_table[TRAP_double_fault], IST_DF);
- set_ist(&idt_table[TRAP_nmi], IST_NMI);
- set_ist(&idt_table[TRAP_machine_check], IST_MCE);
-
- /*
- * The 32-on-64 hypercall entry vector is only accessible from ring 1.
- * Also note that this is a trap gate, not an interrupt gate.
- */
- _set_gate(idt_table+HYPERCALL_VECTOR, 15, 1, &compat_hypercall);
-
- /* Fast trap for int80 (faster than taking the #GP-fixup path). */
- _set_gate(idt_table+0x80, 15, 3, &int80_direct_trap);
- }
stack_bottom = (char *)get_stack_bottom();
stack = (char *)((unsigned long)stack_bottom & ~(STACK_SIZE - 1));
@@ -406,15 +382,6 @@ void __devinit subarch_percpu_traps_init(void)
/* IST_MAX IST pages + 1 syscall page + 1 guard page + primary stack. */
BUILD_BUG_ON((IST_MAX + 2) * PAGE_SIZE + PRIMARY_STACK_SIZE > STACK_SIZE);
- /* Machine Check handler has its own per-CPU 4kB stack. */
- this_cpu(init_tss).ist[IST_MCE-1] = (unsigned long)&stack[IST_MCE * PAGE_SIZE];
-
- /* Double-fault handler has its own per-CPU 4kB stack. */
- this_cpu(init_tss).ist[IST_DF-1] = (unsigned long)&stack[IST_DF * PAGE_SIZE];
-
- /* NMI handler has its own per-CPU 4kB stack. */
- this_cpu(init_tss).ist[IST_NMI-1] = (unsigned long)&stack[IST_NMI * PAGE_SIZE];
-
/* Trampoline for SYSCALL entry from long mode. */
stack = &stack[IST_MAX * PAGE_SIZE]; /* Skip the IST stacks. */
wrmsrl(MSR_LSTAR, (unsigned long)stack);
@@ -436,10 +403,7 @@ void __devinit subarch_percpu_traps_init(void)
/* Common SYSCALL parameters. */
wrmsr(MSR_STAR, 0, (FLAT_RING3_CS32<<16) | __HYPERVISOR_CS);
- wrmsr(MSR_SYSCALL_MASK,
- X86_EFLAGS_VM|X86_EFLAGS_RF|X86_EFLAGS_NT|
- X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_TF,
- 0U);
+ wrmsr(MSR_SYSCALL_MASK, XEN_SYSCALL_MASK, 0U);
}
void init_int80_direct_trap(struct vcpu *v)
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c
index 50d8965..fef97ea 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -403,6 +403,11 @@ typedef union {
#define EXC_PF 14
#define EXC_MF 16
+/* Segment selector error code bits. */
+#define ECODE_EXT (1 << 0)
+#define ECODE_IDT (1 << 1)
+#define ECODE_TI (1 << 2)
+
/*
* Instruction emulation:
* Most instructions are emulated directly via a fragment of inline assembly
@@ -1114,7 +1119,7 @@ realmode_load_seg(
static int
protmode_load_seg(
enum x86_segment seg,
- uint16_t sel,
+ uint16_t sel, bool_t is_ret,
struct x86_emulate_ctxt *ctxt,
const struct x86_emulate_ops *ops)
{
@@ -1180,9 +1185,23 @@ protmode_load_seg(
/* Code segment? */
if ( !(desc.b & (1u<<11)) )
goto raise_exn;
- /* Non-conforming segment: check DPL against RPL. */
- if ( ((desc.b & (6u<<9)) != (6u<<9)) && (dpl != rpl) )
+ if ( is_ret
+ ? /*
+ * Really rpl < cpl, but our sole caller doesn't handle
+ * privilege level changes.
+ */
+ rpl != cpl || (desc.b & (1 << 10) ? dpl > rpl : dpl != rpl)
+ : desc.b & (1 << 10)
+ /* Conforming segment: check DPL against CPL. */
+ ? dpl > cpl
+ /* Non-conforming segment: check RPL and DPL against CPL. */
+ : rpl > cpl || dpl != cpl )
+ goto raise_exn;
+ /* 64-bit code segments (L bit set) must have D bit clear. */
+ if ( in_longmode(ctxt, ops) &&
+ (desc.b & (1 << 21)) && (desc.b & (1 << 22)) )
goto raise_exn;
+ sel = (sel ^ rpl) | cpl;
break;
case x86_seg_ss:
/* Writable data segment? */
@@ -1247,7 +1266,7 @@ protmode_load_seg(
static int
load_seg(
enum x86_segment seg,
- uint16_t sel,
+ uint16_t sel, bool_t is_ret,
struct x86_emulate_ctxt *ctxt,
const struct x86_emulate_ops *ops)
{
@@ -1256,7 +1275,7 @@ load_seg(
return X86EMUL_UNHANDLEABLE;
if ( in_protmode(ctxt, ops) )
- return protmode_load_seg(seg, sel, ctxt, ops);
+ return protmode_load_seg(seg, sel, is_ret, ctxt, ops);
return realmode_load_seg(seg, sel, ctxt, ops);
}
@@ -1318,6 +1337,115 @@ decode_segment(uint8_t modrm_reg)
return decode_segment_failed;
}
+/* Inject a software interrupt/exception, emulating if needed. */
+static int inject_swint(enum x86_swint_type type,
+ uint8_t vector, uint8_t insn_len,
+ struct x86_emulate_ctxt *ctxt,
+ const struct x86_emulate_ops *ops)
+{
+ int rc, error_code, fault_type = EXC_GP;
+
+ fail_if(ops->inject_sw_interrupt == NULL);
+ fail_if(ops->inject_hw_exception == NULL);
+
+ /*
+ * Without hardware support, injecting software interrupts/exceptions is
+ * problematic.
+ *
+ * All software methods of generating exceptions (other than BOUND) yield
+ * traps, so eip in the exception frame needs to point after the
+ * instruction, not at it.
+ *
+ * However, if injecting it as a hardware exception causes a fault during
+ * delivery, our adjustment of eip will cause the fault to be reported
+ * after the faulting instruction, not pointing to it.
+ *
+ * Therefore, eip can only safely be wound forwards if we are certain that
+ * injecting an equivalent hardware exception won't fault, which means
+ * emulating everything the processor would do on a control transfer.
+ *
+ * However, emulation of complete control transfers is very complicated.
+ * All we care about is that guest userspace cannot avoid the descriptor
+ * DPL check by using the Xen emulator, and successfully invoke DPL=0
+ * descriptors.
+ *
+ * Any OS which would further fault during injection is going to receive a
+ * double fault anyway, and won't be in a position to care that the
+ * faulting eip is incorrect.
+ */
+
+ if ( (ctxt->swint_emulate == x86_swint_emulate_all) ||
+ ((ctxt->swint_emulate == x86_swint_emulate_icebp) &&
+ (type == x86_swint_icebp)) )
+ {
+ if ( !in_realmode(ctxt, ops) )
+ {
+ unsigned int idte_size = (ctxt->addr_size == 64) ? 16 : 8;
+ unsigned int idte_offset = vector * idte_size;
+ struct segment_register idtr;
+ uint32_t idte_ctl;
+
+ /* icebp sets the External Event bit despite being an instruction. */
+ error_code = (vector << 3) | ECODE_IDT |
+ (type == x86_swint_icebp ? ECODE_EXT : 0);
+
+ /*
+ * TODO - this does not cover the v8086 mode with CR4.VME case
+ * correctly, but falls on the safe side from the point of view of
+ * a 32bit OS. Someone with many TUITs can see about reading the
+ * TSS Software Interrupt Redirection bitmap.
+ */
+ if ( (ctxt->regs->eflags & EFLG_VM) &&
+ ((ctxt->regs->eflags & EFLG_IOPL) != EFLG_IOPL) )
+ goto raise_exn;
+
+ fail_if(ops->read_segment == NULL);
+ fail_if(ops->read == NULL);
+ if ( (rc = ops->read_segment(x86_seg_idtr, &idtr, ctxt)) )
+ goto done;
+
+ if ( (idte_offset + idte_size - 1) > idtr.limit )
+ goto raise_exn;
+
+ /*
+ * Should strictly speaking read all 8/16 bytes of an entry,
+ * but we currently only care about the dpl and present bits.
+ */
+ ops->read(x86_seg_none, idtr.base + idte_offset + 4,
+ &idte_ctl, sizeof(idte_ctl), ctxt);
+
+ /* Is this entry present? */
+ if ( !(idte_ctl & (1u << 15)) )
+ {
+ fault_type = EXC_NP;
+ goto raise_exn;
+ }
+
+ /* icebp counts as a hardware event, and bypasses the dpl check. */
+ if ( type != x86_swint_icebp )
+ {
+ struct segment_register ss;
+
+ if ( (rc = ops->read_segment(x86_seg_ss, &ss, ctxt)) )
+ goto done;
+
+ if ( ss.attr.fields.dpl > ((idte_ctl >> 13) & 3) )
+ goto raise_exn;
+ }
+ }
+
+ ctxt->regs->eip += insn_len;
+ }
+
+ rc = ops->inject_sw_interrupt(type, vector, insn_len, ctxt);
+
+ done:
+ return rc;
+
+ raise_exn:
+ return ops->inject_hw_exception(fault_type, error_code, ctxt);
+}
+
int
x86_emulate(
struct x86_emulate_ctxt *ctxt,
@@ -1333,6 +1461,7 @@ x86_emulate(
bool_t lock_prefix = 0;
int override_seg = -1, rc = X86EMUL_OKAY;
struct operand src, dst;
+ enum x86_swint_type swint_type;
DECLARE_ALIGNED(mmval_t, mmval);
/*
* Data operand effective address (usually computed from ModRM).
@@ -1888,7 +2017,7 @@ x86_emulate(
if ( (rc = read_ulong(x86_seg_ss, sp_post_inc(op_bytes),
&dst.val, op_bytes, ctxt, ops)) != 0 )
goto done;
- if ( (rc = load_seg(src.val, (uint16_t)dst.val, ctxt, ops)) != 0 )
+ if ( (rc = load_seg(src.val, dst.val, 0, ctxt, ops)) != 0 )
return rc;
break;
@@ -2242,7 +2371,7 @@ x86_emulate(
enum x86_segment seg = decode_segment(modrm_reg);
generate_exception_if(seg == decode_segment_failed, EXC_UD, -1);
generate_exception_if(seg == x86_seg_cs, EXC_UD, -1);
- if ( (rc = load_seg(seg, (uint16_t)src.val, ctxt, ops)) != 0 )
+ if ( (rc = load_seg(seg, src.val, 0, ctxt, ops)) != 0 )
goto done;
if ( seg == x86_seg_ss )
ctxt->retire.flags.mov_ss = 1;
@@ -2323,7 +2452,7 @@ x86_emulate(
&_regs.eip, op_bytes, ctxt)) )
goto done;
- if ( (rc = load_seg(x86_seg_cs, sel, ctxt, ops)) != 0 )
+ if ( (rc = load_seg(x86_seg_cs, sel, 0, ctxt, ops)) != 0 )
goto done;
_regs.eip = eip;
break;
@@ -2547,7 +2676,7 @@ x86_emulate(
if ( (rc = read_ulong(src.mem.seg, src.mem.off + src.bytes,
&sel, 2, ctxt, ops)) != 0 )
goto done;
- if ( (rc = load_seg(dst.val, (uint16_t)sel, ctxt, ops)) != 0 )
+ if ( (rc = load_seg(dst.val, sel, 0, ctxt, ops)) != 0 )
goto done;
dst.val = src.val;
break;
@@ -2621,7 +2750,7 @@ x86_emulate(
&dst.val, op_bytes, ctxt, ops)) ||
(rc = read_ulong(x86_seg_ss, sp_post_inc(op_bytes + offset),
&src.val, op_bytes, ctxt, ops)) ||
- (rc = load_seg(x86_seg_cs, (uint16_t)src.val, ctxt, ops)) )
+ (rc = load_seg(x86_seg_cs, src.val, 1, ctxt, ops)) )
goto done;
_regs.eip = dst.val;
break;
@@ -2629,14 +2758,16 @@ x86_emulate(
case 0xcc: /* int3 */
src.val = EXC_BP;
+ swint_type = x86_swint_int3;
goto swint;
case 0xcd: /* int imm8 */
src.val = insn_fetch_type(uint8_t);
+ swint_type = x86_swint_int;
swint:
- fail_if(ops->inject_sw_interrupt == NULL);
- rc = ops->inject_sw_interrupt(src.val, _regs.eip - ctxt->regs->eip,
- ctxt) ? : X86EMUL_EXCEPTION;
+ rc = inject_swint(swint_type, src.val,
+ _regs.eip - ctxt->regs->eip,
+ ctxt, ops) ? : X86EMUL_EXCEPTION;
goto done;
case 0xce: /* into */
@@ -2644,6 +2775,7 @@ x86_emulate(
if ( !(_regs.eflags & EFLG_OF) )
break;
src.val = EXC_OF;
+ swint_type = x86_swint_into;
goto swint;
case 0xcf: /* iret */ {
@@ -2667,7 +2799,7 @@ x86_emulate(
_regs.eflags &= mask;
_regs.eflags |= (uint32_t)(eflags & ~mask) | 0x02;
_regs.eip = eip;
- if ( (rc = load_seg(x86_seg_cs, (uint16_t)cs, ctxt, ops)) != 0 )
+ if ( (rc = load_seg(x86_seg_cs, cs, 1, ctxt, ops)) != 0 )
goto done;
break;
}
@@ -3297,7 +3429,7 @@ x86_emulate(
generate_exception_if(mode_64bit(), EXC_UD, -1);
eip = insn_fetch_bytes(op_bytes);
sel = insn_fetch_type(uint16_t);
- if ( (rc = load_seg(x86_seg_cs, sel, ctxt, ops)) != 0 )
+ if ( (rc = load_seg(x86_seg_cs, sel, 0, ctxt, ops)) != 0 )
goto done;
_regs.eip = eip;
break;
@@ -3311,9 +3443,11 @@ x86_emulate(
case 0xf1: /* int1 (icebp) */
src.val = EXC_DB;
+ swint_type = x86_swint_icebp;
goto swint;
case 0xf4: /* hlt */
+ generate_exception_if(!mode_ring0(), EXC_GP, 0);
ctxt->retire.flags.hlt = 1;
break;
@@ -3594,7 +3728,7 @@ x86_emulate(
goto done;
}
- if ( (rc = load_seg(x86_seg_cs, sel, ctxt, ops)) != 0 )
+ if ( (rc = load_seg(x86_seg_cs, sel, 0, ctxt, ops)) != 0 )
goto done;
_regs.eip = src.val;
@@ -3661,7 +3795,7 @@ x86_emulate(
generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1);
generate_exception_if(!mode_ring0(), EXC_GP, 0);
if ( (rc = load_seg((modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr,
- src.val, ctxt, ops)) != 0 )
+ src.val, 0, ctxt, ops)) != 0 )
goto done;
break;
@@ -3710,6 +3844,7 @@ x86_emulate(
break;
case 2: /* lgdt */
case 3: /* lidt */
+ generate_exception_if(!mode_ring0(), EXC_GP, 0);
generate_exception_if(ea.type != OP_MEM, EXC_UD, -1);
fail_if(ops->write_segment == NULL);
memset(®, 0, sizeof(reg));
@@ -3738,6 +3873,7 @@ x86_emulate(
case 6: /* lmsw */
fail_if(ops->read_cr == NULL);
fail_if(ops->write_cr == NULL);
+ generate_exception_if(!mode_ring0(), EXC_GP, 0);
if ( (rc = ops->read_cr(0, &cr0, ctxt)) )
goto done;
if ( ea.type == OP_REG )
@@ -3765,8 +3901,7 @@ x86_emulate(
case 0x05: /* syscall */ {
uint64_t msr_content;
- struct segment_register cs = { 0 }, ss = { 0 };
- int rc;
+ struct segment_register cs, ss;
generate_exception_if(in_realmode(ctxt, ops), EXC_UD, -1);
generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1);
@@ -3780,13 +3915,11 @@ x86_emulate(
if ( (rc = ops->read_msr(MSR_STAR, &msr_content, ctxt)) != 0 )
goto done;
- msr_content >>= 32;
- cs.sel = (uint16_t)(msr_content & 0xfffc);
- ss.sel = (uint16_t)(msr_content + 8);
+ cs.sel = (msr_content >> 32) & ~3; /* SELECTOR_RPL_MASK */
+ ss.sel = cs.sel + 8;
cs.base = ss.base = 0; /* flat segment */
cs.limit = ss.limit = ~0u; /* 4GB limit */
- cs.attr.bytes = 0xc9b; /* G+DB+P+S+Code */
ss.attr.bytes = 0xc93; /* G+DB+P+S+Data */
#ifdef __x86_64__
@@ -3795,8 +3928,7 @@ x86_emulate(
goto cannot_emulate;
if ( rc )
{
- cs.attr.fields.db = 0;
- cs.attr.fields.l = 1;
+ cs.attr.bytes = 0xa9b; /* L+DB+P+S+Code */
_regs.rcx = _regs.rip;
_regs.r11 = _regs.eflags & ~EFLG_RF;
@@ -3813,10 +3945,9 @@ x86_emulate(
else
#endif
{
- if ( (rc = ops->read_msr(MSR_STAR, &msr_content, ctxt)) != 0 )
- goto done;
+ cs.attr.bytes = 0xc9b; /* G+DB+P+S+Code */
- _regs.ecx = _regs.eip;
+ _regs.ecx = (uint32_t)_regs.eip;
_regs.eip = (uint32_t)msr_content;
_regs.eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
}
@@ -4008,7 +4139,7 @@ x86_emulate(
case 0x34: /* sysenter */ {
uint64_t msr_content;
struct segment_register cs, ss;
- int rc;
+ int lm;
generate_exception_if(mode_ring0(), EXC_GP, 0);
generate_exception_if(in_realmode(ctxt, ops), EXC_GP, 0);
@@ -4018,34 +4149,26 @@ x86_emulate(
if ( (rc = ops->read_msr(MSR_SYSENTER_CS, &msr_content, ctxt)) != 0 )
goto done;
- if ( mode_64bit() )
- generate_exception_if(msr_content == 0, EXC_GP, 0);
- else
- generate_exception_if((msr_content & 0xfffc) == 0, EXC_GP, 0);
+ generate_exception_if(!(msr_content & 0xfffc), EXC_GP, 0);
+ lm = in_longmode(ctxt, ops);
+ if ( lm < 0 )
+ goto cannot_emulate;
_regs.eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
fail_if(ops->read_segment == NULL);
ops->read_segment(x86_seg_cs, &cs, ctxt);
- cs.sel = (uint16_t)msr_content & ~3; /* SELECTOR_RPL_MASK */
+ cs.sel = msr_content & ~3; /* SELECTOR_RPL_MASK */
cs.base = 0; /* flat segment */
cs.limit = ~0u; /* 4GB limit */
- cs.attr.bytes = 0xc9b; /* G+DB+P+S+Code */
+ cs.attr.bytes = lm ? 0xa9b /* L+DB+P+S+Code */
+ : 0xc9b; /* G+DB+P+S+Code */
ss.sel = cs.sel + 8;
ss.base = 0; /* flat segment */
ss.limit = ~0u; /* 4GB limit */
ss.attr.bytes = 0xc93; /* G+DB+P+S+Data */
- rc = in_longmode(ctxt, ops);
- if ( rc < 0 )
- goto cannot_emulate;
- if ( rc )
- {
- cs.attr.fields.db = 0;
- cs.attr.fields.l = 1;
- }
-
fail_if(ops->write_segment == NULL);
if ( (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) != 0 ||
(rc = ops->write_segment(x86_seg_ss, &ss, ctxt)) != 0 )
@@ -4053,11 +4176,11 @@ x86_emulate(
if ( (rc = ops->read_msr(MSR_SYSENTER_EIP, &msr_content, ctxt)) != 0 )
goto done;
- _regs.eip = msr_content;
+ _regs.eip = lm ? msr_content : (uint32_t)msr_content;
if ( (rc = ops->read_msr(MSR_SYSENTER_ESP, &msr_content, ctxt)) != 0 )
goto done;
- _regs.esp = msr_content;
+ _regs.esp = lm ? msr_content : (uint32_t)msr_content;
break;
}
@@ -4066,7 +4189,6 @@ x86_emulate(
uint64_t msr_content;
struct segment_register cs, ss;
bool_t user64 = !!(rex_prefix & REX_W);
- int rc;
generate_exception_if(!mode_ring0(), EXC_GP, 0);
generate_exception_if(in_realmode(ctxt, ops), EXC_GP, 0);
@@ -4076,42 +4198,27 @@ x86_emulate(
if ( (rc = ops->read_msr(MSR_SYSENTER_CS, &msr_content, ctxt)) != 0 )
goto done;
- if ( user64 )
- {
- cs.sel = (uint16_t)(msr_content + 32);
- ss.sel = (cs.sel + 8);
- generate_exception_if(msr_content == 0, EXC_GP, 0);
- }
- else
- {
- cs.sel = (uint16_t)(msr_content + 16);
- ss.sel = (uint16_t)(msr_content + 24);
- generate_exception_if((msr_content & 0xfffc) == 0, EXC_GP, 0);
- }
+ generate_exception_if(!(msr_content & 0xfffc), EXC_GP, 0);
- cs.sel |= 0x3; /* SELECTOR_RPL_MASK */
+ cs.sel = (msr_content | 3) + /* SELECTOR_RPL_MASK */
+ (user64 ? 32 : 16);
cs.base = 0; /* flat segment */
cs.limit = ~0u; /* 4GB limit */
- cs.attr.bytes = 0xcfb; /* G+DB+P+DPL3+S+Code */
+ cs.attr.bytes = user64 ? 0xafb /* L+DB+P+DPL3+S+Code */
+ : 0xcfb; /* G+DB+P+DPL3+S+Code */
- ss.sel |= 0x3; /* SELECTOR_RPL_MASK */
+ ss.sel = cs.sel + 8;
ss.base = 0; /* flat segment */
ss.limit = ~0u; /* 4GB limit */
ss.attr.bytes = 0xcf3; /* G+DB+P+DPL3+S+Data */
- if ( user64 )
- {
- cs.attr.fields.db = 0;
- cs.attr.fields.l = 1;
- }
-
fail_if(ops->write_segment == NULL);
if ( (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) != 0 ||
(rc = ops->write_segment(x86_seg_ss, &ss, ctxt)) != 0 )
goto done;
- _regs.eip = _regs.edx;
- _regs.esp = _regs.ecx;
+ _regs.eip = user64 ? _regs.edx : (uint32_t)_regs.edx;
+ _regs.esp = user64 ? _regs.ecx : (uint32_t)_regs.ecx;
break;
}
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.h b/xen/arch/x86/x86_emulate/x86_emulate.h
index 85bc4bc..b059341 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.h
+++ b/xen/arch/x86/x86_emulate/x86_emulate.h
@@ -51,11 +51,26 @@ enum x86_segment {
#define is_x86_user_segment(seg) ((unsigned)(seg) <= x86_seg_gs)
+/* Classification of the types of software generated interrupts/exceptions. */
+enum x86_swint_type {
+ x86_swint_icebp, /* 0xf1 */
+ x86_swint_int3, /* 0xcc */
+ x86_swint_into, /* 0xce */
+ x86_swint_int, /* 0xcd $n */
+};
+
+/* How much help is required with software event injection? */
+enum x86_swint_emulation {
+ x86_swint_emulate_none, /* Hardware supports all software injection properly */
+ x86_swint_emulate_icebp,/* Help needed with `icebp` (0xf1) */
+ x86_swint_emulate_all, /* Help needed with all software events */
+};
+
/*
* Attribute for segment selector. This is a copy of bit 40:47 & 52:55 of the
* segment descriptor. It happens to match the format of an AMD SVM VMCB.
*/
-typedef union segment_attributes {
+typedef union __packed segment_attributes {
uint16_t bytes;
struct
{
@@ -69,18 +84,18 @@ typedef union segment_attributes {
uint16_t g: 1; /* 11; Bit 55 */
uint16_t pad: 4;
} fields;
-} __attribute__ ((packed)) segment_attributes_t;
+} segment_attributes_t;
/*
* Full state of a segment register (visible and hidden portions).
* Again, this happens to match the format of an AMD SVM VMCB.
*/
-struct segment_register {
+struct __packed segment_register {
uint16_t sel;
segment_attributes_t attr;
uint32_t limit;
uint64_t base;
-} __attribute__ ((packed));
+};
/*
* Return codes from state-accessor functions and from x86_emulate().
@@ -337,6 +352,7 @@ struct x86_emulate_ops
/* inject_sw_interrupt */
int (*inject_sw_interrupt)(
+ enum x86_swint_type type,
uint8_t vector,
uint8_t insn_len,
struct x86_emulate_ctxt *ctxt);
@@ -379,6 +395,9 @@ struct x86_emulate_ctxt
/* Set this if writes may have side effects. */
uint8_t force_writeback;
+ /* Software event injection support. */
+ enum x86_swint_emulation swint_emulate;
+
/* Retirement state, set by the emulator (valid only on X86EMUL_OKAY). */
union {
struct {
diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S
index 17db361..d4b1f1a 100644
--- a/xen/arch/x86/xen.lds.S
+++ b/xen/arch/x86/xen.lds.S
@@ -105,6 +105,12 @@ SECTIONS
.init.text : {
_sinittext = .;
*(.init.text)
+ /*
+ * Here are the replacement instructions. The linker sticks them
+ * as binary blobs. The .altinstructions has enough data to get
+ * the address and the length of them to patch the kernel safely.
+ */
+ *(.altinstr_replacement)
_einittext = .;
} :text
.init.data : {
@@ -120,6 +126,15 @@ SECTIONS
__trampoline_seg_start = .;
*(.trampoline_seg)
__trampoline_seg_stop = .;
+ /*
+ * struct alt_inst entries. From the header (alternative.h):
+ * "Alternative instructions for different CPU types or capabilities"
+ * Think locking instructions on spinlocks.
+ */
+ . = ALIGN(8);
+ __alt_instructions = .;
+ *(.altinstructions)
+ __alt_instructions_end = .;
. = ALIGN(8);
__ctors_start = .;
diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c
index 9e74929..5f3b161 100644
--- a/xen/arch/x86/xstate.c
+++ b/xen/arch/x86/xstate.c
@@ -24,7 +24,7 @@ bool_t __read_mostly cpu_has_xsaveopt;
static u32 __read_mostly xsave_cntxt_size;
/* A 64-bit bitmask of the XSAVE/XRSTOR features supported by processor. */
-u64 xfeature_mask;
+u64 __read_mostly xfeature_mask;
/* Cached xcr0 for fast read */
static DEFINE_PER_CPU(uint64_t, xcr0);
@@ -250,10 +250,37 @@ void xstate_free_save_area(struct vcpu *v)
v->arch.xsave_area = NULL;
}
+static unsigned int _xstate_ctxt_size(u64 xcr0)
+{
+ u64 act_xcr0 = get_xcr0();
+ u32 eax, ebx = 0, ecx, edx;
+ bool_t ok = set_xcr0(xcr0);
+
+ ASSERT(ok);
+ cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
+ ASSERT(ebx <= ecx);
+ ok = set_xcr0(act_xcr0);
+ ASSERT(ok);
+
+ return ebx;
+}
+
+/* Fastpath for common xstate size requests, avoiding reloads of xcr0. */
+unsigned int xstate_ctxt_size(u64 xcr0)
+{
+ if ( xcr0 == xfeature_mask )
+ return xsave_cntxt_size;
+
+ if ( xcr0 == 0 )
+ return 0;
+
+ return _xstate_ctxt_size(xcr0);
+}
+
/* Collect the information of processor's extended state */
void xstate_init(bool_t bsp)
{
- u32 eax, ebx, ecx, edx, min_size;
+ u32 eax, ebx, ecx, edx;
u64 feature_mask;
if ( boot_cpu_data.cpuid_level < XSTATE_CPUID )
@@ -269,12 +296,6 @@ void xstate_init(bool_t bsp)
BUG_ON((eax & XSTATE_YMM) && !(eax & XSTATE_SSE));
feature_mask = (((u64)edx << 32) | eax) & XCNTXT_MASK;
- /* FP/SSE, XSAVE.HEADER, YMM */
- min_size = XSTATE_AREA_MIN_SIZE;
- if ( eax & XSTATE_YMM )
- min_size += XSTATE_YMM_SIZE;
- BUG_ON(ecx < min_size);
-
/*
* Set CR4_OSXSAVE and run "cpuid" to get xsave_cntxt_size.
*/
@@ -289,14 +310,14 @@ void xstate_init(bool_t bsp)
* xsave_cntxt_size is the max size required by enabled features.
* We know FP/SSE and YMM about eax, and nothing about edx at present.
*/
- xsave_cntxt_size = xstate_ctxt_size(feature_mask);
+ xsave_cntxt_size = _xstate_ctxt_size(feature_mask);
printk("%s: using cntxt_size: %#x and states: %#"PRIx64"\n",
__func__, xsave_cntxt_size, xfeature_mask);
}
else
{
BUG_ON(xfeature_mask != feature_mask);
- BUG_ON(xsave_cntxt_size != xstate_ctxt_size(feature_mask));
+ BUG_ON(xsave_cntxt_size != _xstate_ctxt_size(feature_mask));
}
/* Check XSAVEOPT feature. */
@@ -307,34 +328,37 @@ void xstate_init(bool_t bsp)
BUG_ON(!cpu_has_xsaveopt != !(eax & XSTATE_FEATURE_XSAVEOPT));
}
-unsigned int xstate_ctxt_size(u64 xcr0)
+static bool_t valid_xcr0(u64 xcr0)
{
- u32 ebx = 0;
+ /* FP must be unconditionally set. */
+ if ( !(xcr0 & XSTATE_FP) )
+ return 0;
+
+ /* YMM depends on SSE. */
+ if ( (xcr0 & XSTATE_YMM) && !(xcr0 & XSTATE_SSE) )
+ return 0;
- if ( xcr0 )
+ if ( xcr0 & (XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM) )
{
- u64 act_xcr0 = get_xcr0();
- u32 eax, ecx, edx;
- bool_t ok = set_xcr0(xcr0);
-
- ASSERT(ok);
- cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
- ASSERT(ebx <= ecx);
- ok = set_xcr0(act_xcr0);
- ASSERT(ok);
+ /* OPMASK, ZMM, and HI_ZMM require YMM. */
+ if ( !(xcr0 & XSTATE_YMM) )
+ return 0;
+
+ /* OPMASK, ZMM, and HI_ZMM must be the same. */
+ if ( ~xcr0 & (XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM) )
+ return 0;
}
- return ebx;
+ /* BNDREGS and BNDCSR must be the same. */
+ return !(xcr0 & XSTATE_BNDREGS) == !(xcr0 & XSTATE_BNDCSR);
}
-int validate_xstate(u64 xcr0, u64 xcr0_accum, u64 xstate_bv, u64 xfeat_mask)
+int validate_xstate(u64 xcr0, u64 xcr0_accum, u64 xstate_bv)
{
- if ( (xcr0_accum & ~xfeat_mask) ||
- (xstate_bv & ~xcr0_accum) ||
+ if ( (xstate_bv & ~xcr0_accum) ||
(xcr0 & ~xcr0_accum) ||
- !(xcr0 & XSTATE_FP) ||
- ((xcr0 & XSTATE_YMM) && !(xcr0 & XSTATE_SSE)) ||
- ((xcr0_accum & XSTATE_YMM) && !(xcr0_accum & XSTATE_SSE)) )
+ !valid_xcr0(xcr0) ||
+ !valid_xcr0(xcr0_accum) )
return -EINVAL;
if ( xcr0_accum & ~xfeature_mask )
@@ -351,10 +375,7 @@ int handle_xsetbv(u32 index, u64 new_bv)
if ( index != XCR_XFEATURE_ENABLED_MASK )
return -EOPNOTSUPP;
- if ( (new_bv & ~xfeature_mask) || !(new_bv & XSTATE_FP) )
- return -EINVAL;
-
- if ( (new_bv & XSTATE_YMM) && !(new_bv & XSTATE_SSE) )
+ if ( (new_bv & ~xfeature_mask) || !valid_xcr0(new_bv) )
return -EINVAL;
if ( !set_xcr0(new_bv) )
@@ -364,6 +385,10 @@ int handle_xsetbv(u32 index, u64 new_bv)
curr->arch.xcr0 = new_bv;
curr->arch.xcr0_accum |= new_bv;
+ /* LWP sets nonlazy_xstate_used independently. */
+ if ( new_bv & (XSTATE_NONLAZY & ~XSTATE_LWP) )
+ curr->arch.nonlazy_xstate_used = 1;
+
mask &= curr->fpu_dirtied ? ~XSTATE_FP_SSE : XSTATE_NONLAZY;
if ( mask )
{
diff --git a/xen/common/Makefile b/xen/common/Makefile
index 3683ae3..8391246 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -26,6 +26,7 @@ obj-y += sched_credit.o
obj-y += sched_credit2.o
obj-y += sched_sedf.o
obj-y += sched_arinc653.o
+obj-y += sched_rt.o
obj-y += schedule.o
obj-y += shutdown.o
obj-y += softirq.o
@@ -51,6 +52,9 @@ obj-y += tmem_xen.o
obj-y += radix-tree.o
obj-y += rbtree.o
obj-y += lzo.o
+obj-$(HAS_PDX) += pdx.o
+obj-$(HAS_MEM_ACCESS) += mem_access.o
+obj-$(HAS_MEM_ACCESS) += mem_event.o
obj-bin-$(CONFIG_X86) += $(foreach n,decompress bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o)
diff --git a/xen/common/bitmap.c b/xen/common/bitmap.c
index 67dfd00..61d1ea4 100644
--- a/xen/common/bitmap.c
+++ b/xen/common/bitmap.c
@@ -144,7 +144,9 @@ void __bitmap_shift_right(unsigned long *dst,
lower = src[off + k];
if (left && off + k == lim - 1)
lower &= mask;
- dst[k] = upper << (BITS_PER_LONG - rem) | lower >> rem;
+ dst[k] = rem
+ ? (upper << (BITS_PER_LONG - rem)) | (lower >> rem)
+ : lower;
if (left && k == lim - 1)
dst[k] &= mask;
}
@@ -185,7 +187,9 @@ void __bitmap_shift_left(unsigned long *dst,
upper = src[k];
if (left && k == lim - 1)
upper &= (1UL << left) - 1;
- dst[k + off] = lower >> (BITS_PER_LONG - rem) | upper << rem;
+ dst[k + off] = rem ? (lower >> (BITS_PER_LONG - rem))
+ | (upper << rem)
+ : upper;
if (left && k + off == lim - 1)
dst[k + off] &= (1UL << left) - 1;
}
diff --git a/xen/common/compat/domain.c b/xen/common/compat/domain.c
index e756f54..b4be3b3 100644
--- a/xen/common/compat/domain.c
+++ b/xen/common/compat/domain.c
@@ -58,7 +58,7 @@ int compat_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE_PARAM(void) arg)
rc = v->is_initialised ? -EEXIST : arch_set_info_guest(v, cmp_ctxt);
domain_unlock(d);
- if ( rc == -EAGAIN )
+ if ( rc == -ERESTART )
rc = hypercall_create_continuation(__HYPERVISOR_vcpu_op, "iih",
cmd, vcpuid, arg);
diff --git a/xen/common/compat/grant_table.c b/xen/common/compat/grant_table.c
index 7ebbbc1..0368289 100644
--- a/xen/common/compat/grant_table.c
+++ b/xen/common/compat/grant_table.c
@@ -51,16 +51,21 @@ CHECK_gnttab_get_version;
CHECK_gnttab_swap_grant_ref;
#undef xen_gnttab_swap_grant_ref
+#define xen_gnttab_cache_flush gnttab_cache_flush
+CHECK_gnttab_cache_flush;
+#undef xen_gnttab_cache_flush
+
int compat_grant_table_op(unsigned int cmd,
XEN_GUEST_HANDLE_PARAM(void) cmp_uop,
unsigned int count)
{
int rc = 0;
- unsigned int i;
+ unsigned int i, cmd_op;
XEN_GUEST_HANDLE_PARAM(void) cnt_uop;
set_xen_guest_handle(cnt_uop, NULL);
- switch ( cmd )
+ cmd_op = cmd & GNTTABOP_CMD_MASK;
+ switch ( cmd_op )
{
#define CASE(name) \
case GNTTABOP_##name: \
@@ -106,6 +111,10 @@ int compat_grant_table_op(unsigned int cmd,
CASE(swap_grant_ref);
#endif
+#ifndef CHECK_gnttab_cache_flush
+ CASE(cache_flush);
+#endif
+
#undef CASE
default:
return do_grant_table_op(cmd, cmp_uop, count);
@@ -132,7 +141,7 @@ int compat_grant_table_op(unsigned int cmd,
} cmp;
set_xen_guest_handle(nat.uop, COMPAT_ARG_XLAT_VIRT_BASE);
- switch ( cmd )
+ switch ( cmd_op )
{
case GNTTABOP_setup_table:
if ( unlikely(count > 1) )
@@ -146,11 +155,11 @@ int compat_grant_table_op(unsigned int cmd,
unsigned int max_frame_list_size_in_page =
(COMPAT_ARG_XLAT_SIZE - sizeof(*nat.setup)) /
sizeof(*nat.setup->frame_list.p);
- if ( max_frame_list_size_in_page < max_nr_grant_frames )
+ if ( max_frame_list_size_in_page < max_grant_frames )
{
gdprintk(XENLOG_WARNING,
- "max_nr_grant_frames is too large (%u,%u)\n",
- max_nr_grant_frames, max_frame_list_size_in_page);
+ "max_grant_frames is too large (%u,%u)\n",
+ max_grant_frames, max_frame_list_size_in_page);
rc = -EINVAL;
}
else
@@ -284,11 +293,11 @@ int compat_grant_table_op(unsigned int cmd,
break;
}
if ( max_frame_list_size_in_pages <
- grant_to_status_frames(max_nr_grant_frames) )
+ grant_to_status_frames(max_grant_frames) )
{
gdprintk(XENLOG_WARNING,
- "grant_to_status_frames(max_nr_grant_frames) is too large (%u,%u)\n",
- grant_to_status_frames(max_nr_grant_frames),
+ "grant_to_status_frames(max_grant_frames) is too large (%u,%u)\n",
+ grant_to_status_frames(max_grant_frames),
max_frame_list_size_in_pages);
rc = -EINVAL;
break;
diff --git a/xen/common/compat/memory.c b/xen/common/compat/memory.c
index daa2e04..06c90be 100644
--- a/xen/common/compat/memory.c
+++ b/xen/common/compat/memory.c
@@ -4,6 +4,7 @@
#include <xen/guest_access.h>
#include <xen/sched.h>
#include <xen/event.h>
+#include <xen/mem_access.h>
#include <asm/current.h>
#include <compat/memory.h>
@@ -13,6 +14,8 @@ CHECK_TYPE(domid);
#undef compat_domid_t
#undef xen_domid_t
+CHECK_mem_access_op;
+
int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) compat)
{
int split, op = cmd & MEMOP_CMD_MASK;
@@ -279,7 +282,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) compat)
break;
cmd = 0;
- if ( hypercall_xlat_continuation(&cmd, 0x02, nat.hnd, compat) )
+ if ( hypercall_xlat_continuation(&cmd, 2, 0x02, nat.hnd, compat) )
{
BUG_ON(rc != __HYPERVISOR_memory_op);
BUG_ON((cmd & MEMOP_CMD_MASK) != op);
@@ -379,6 +382,10 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) compat)
break;
}
+ case XENMEM_access_op:
+ rc = mem_access_memop(cmd, guest_handle_cast(compat, xen_mem_access_op_t));
+ break;
+
case XENMEM_add_to_physmap_batch:
start_extent = end_extent;
break;
diff --git a/xen/common/cpupool.c b/xen/common/cpupool.c
index e46e930..a758a8b 100644
--- a/xen/common/cpupool.c
+++ b/xen/common/cpupool.c
@@ -225,6 +225,35 @@ static int cpupool_destroy(struct cpupool *c)
}
/*
+ * Move domain to another cpupool
+ */
+static int cpupool_move_domain_locked(struct domain *d, struct cpupool *c)
+{
+ int ret;
+
+ d->cpupool->n_dom--;
+ ret = sched_move_domain(d, c);
+ if ( ret )
+ d->cpupool->n_dom++;
+ else
+ c->n_dom++;
+
+ return ret;
+}
+int cpupool_move_domain(struct domain *d, struct cpupool *c)
+{
+ int ret;
+
+ spin_lock(&cpupool_lock);
+
+ ret = cpupool_move_domain_locked(d, c);
+
+ spin_unlock(&cpupool_lock);
+
+ return ret;
+}
+
+/*
* assign a specific cpu to a cpupool
* cpupool_lock must be held
*/
@@ -307,7 +336,7 @@ out:
* - last cpu and still active domains in cpupool
* - cpu just being unplugged
*/
-int cpupool_unassign_cpu(struct cpupool *c, unsigned int cpu)
+static int cpupool_unassign_cpu(struct cpupool *c, unsigned int cpu)
{
int work_cpu;
int ret;
@@ -338,14 +367,9 @@ int cpupool_unassign_cpu(struct cpupool *c, unsigned int cpu)
ret = -EBUSY;
break;
}
- c->n_dom--;
- ret = sched_move_domain(d, cpupool0);
+ ret = cpupool_move_domain_locked(d, cpupool0);
if ( ret )
- {
- c->n_dom++;
break;
- }
- cpupool0->n_dom++;
}
rcu_read_unlock(&domlist_read_lock);
if ( ret )
@@ -613,16 +637,11 @@ int cpupool_do_sysctl(struct xen_sysctl_cpupool_op *op)
d->domain_id, op->cpupool_id);
ret = -ENOENT;
spin_lock(&cpupool_lock);
+
c = cpupool_find_by_id(op->cpupool_id);
if ( (c != NULL) && cpumask_weight(c->cpu_valid) )
- {
- d->cpupool->n_dom--;
- ret = sched_move_domain(d, c);
- if ( ret )
- d->cpupool->n_dom++;
- else
- c->n_dom++;
- }
+ ret = cpupool_move_domain_locked(d, c);
+
spin_unlock(&cpupool_lock);
cpupool_dprintk("cpupool move_domain(dom=%d)->pool=%d ret %d\n",
d->domain_id, op->cpupool_id, ret);
diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 2ebacb2..f72b2e9 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -22,10 +22,8 @@
#include <xen/string.h>
#include <xen/cpumask.h>
#include <xen/ctype.h>
-#include <xen/lib.h>
-#include <asm/early_printk.h>
+#include <asm/setup.h>
-struct dt_early_info __initdata early_info;
const void *device_tree_flattened;
dt_irq_xlate_func dt_irq_xlate;
/* Host device tree */
@@ -54,21 +52,10 @@ struct dt_alias_prop {
static LIST_HEAD(aliases_lookup);
-/* Some device tree functions may be called both before and after the
- console is initialized. */
-#define dt_printk(fmt, ...) \
- do \
- { \
- if ( system_state == SYS_STATE_early_boot ) \
- early_printk(fmt, ## __VA_ARGS__); \
- else \
- printk(fmt, ## __VA_ARGS__); \
- } while (0)
-
// #define DEBUG_DT
#ifdef DEBUG_DT
-# define dt_dprintk(fmt, args...) dt_printk(XENLOG_DEBUG fmt, ##args)
+# define dt_dprintk(fmt, args...) printk(XENLOG_DEBUG fmt, ##args)
static void dt_dump_addr(const char *s, const __be32 *addr, int na)
{
dt_dprintk("%s", s);
@@ -101,52 +88,6 @@ struct dt_bus
unsigned int (*get_flags)(const __be32 *addr);
};
-static bool_t __init device_tree_node_matches(const void *fdt, int node,
- const char *match)
-{
- const char *name;
- size_t match_len;
-
- name = fdt_get_name(fdt, node, NULL);
- match_len = strlen(match);
-
- /* Match both "match" and "match at ..." patterns but not
- "match-foo". */
- return strncmp(name, match, match_len) == 0
- && (name[match_len] == '@' || name[match_len] == '\0');
-}
-
-static bool_t __init device_tree_node_compatible(const void *fdt, int node,
- const char *match)
-{
- int len, l;
- int mlen;
- const void *prop;
-
- mlen = strlen(match);
-
- prop = fdt_getprop(fdt, node, "compatible", &len);
- if ( prop == NULL )
- return 0;
-
- while ( len > 0 ) {
- if ( !dt_compat_cmp(prop, match) )
- return 1;
- l = strlen(prop) + 1;
- prop += l;
- len -= l;
- }
-
- return 0;
-}
-
-static void __init device_tree_get_reg(const __be32 **cell, u32 address_cells,
- u32 size_cells, u64 *start, u64 *size)
-{
- *start = dt_next_cell(address_cells, cell);
- *size = dt_next_cell(size_cells, cell);
-}
-
void dt_get_range(const __be32 **cell, const struct dt_device_node *np,
u64 *address, u64 *size)
{
@@ -174,344 +115,6 @@ void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
dt_set_cell(cellp, dt_n_size_cells(np), size);
}
-static u32 __init device_tree_get_u32(const void *fdt, int node,
- const char *prop_name, u32 dflt)
-{
- const struct fdt_property *prop;
-
- prop = fdt_get_property(fdt, node, prop_name, NULL);
- if ( !prop || prop->len < sizeof(u32) )
- return dflt;
-
- return fdt32_to_cpu(*(uint32_t*)prop->data);
-}
-
-/**
- * device_tree_for_each_node - iterate over all device tree nodes
- * @fdt: flat device tree.
- * @func: function to call for each node.
- * @data: data to pass to @func.
- *
- * Any nodes nested at DEVICE_TREE_MAX_DEPTH or deeper are ignored.
- *
- * Returns 0 if all nodes were iterated over successfully. If @func
- * returns a value different from 0, that value is returned immediately.
- */
-static int __init device_tree_for_each_node(const void *fdt,
- device_tree_node_func func,
- void *data)
-{
- int node;
- int depth;
- u32 address_cells[DEVICE_TREE_MAX_DEPTH];
- u32 size_cells[DEVICE_TREE_MAX_DEPTH];
- int ret;
-
- for ( node = 0, depth = 0;
- node >=0 && depth >= 0;
- node = fdt_next_node(fdt, node, &depth) )
- {
- const char *name = fdt_get_name(fdt, node, NULL);
-
- if ( depth >= DEVICE_TREE_MAX_DEPTH )
- {
- dt_printk("Warning: device tree node `%s' is nested too deep\n",
- name);
- continue;
- }
-
- address_cells[depth] = device_tree_get_u32(fdt, node, "#address-cells",
- depth > 0 ? address_cells[depth-1] : 0);
- size_cells[depth] = device_tree_get_u32(fdt, node, "#size-cells",
- depth > 0 ? size_cells[depth-1] : 0);
-
-
- ret = func(fdt, node, name, depth,
- address_cells[depth-1], size_cells[depth-1], data);
- if ( ret != 0 )
- return ret;
- }
- return 0;
-}
-
-/**
- * device_tree_bootargs - return the bootargs (the Xen command line)
- * @fdt flat device tree.
- */
-const char *device_tree_bootargs(const void *fdt)
-{
- int node;
- const struct fdt_property *prop;
-
- node = fdt_path_offset(fdt, "/chosen");
- if ( node < 0 )
- return NULL;
-
- prop = fdt_get_property(fdt, node, "xen,xen-bootargs", NULL);
- if ( prop == NULL )
- {
- struct dt_mb_module *dom0_mod = NULL;
-
- if ( early_info.modules.nr_mods >= MOD_KERNEL )
- dom0_mod = &early_info.modules.module[MOD_KERNEL];
-
- if (fdt_get_property(fdt, node, "xen,dom0-bootargs", NULL) ||
- ( dom0_mod && dom0_mod->cmdline[0] ) )
- prop = fdt_get_property(fdt, node, "bootargs", NULL);
- }
- if ( prop == NULL )
- return NULL;
-
- return prop->data;
-}
-
-static int dump_node(const void *fdt, int node, const char *name, int depth,
- u32 address_cells, u32 size_cells, void *data)
-{
- char prefix[2*DEVICE_TREE_MAX_DEPTH + 1] = "";
- int i;
- int prop;
-
- for ( i = 0; i < depth; i++ )
- safe_strcat(prefix, " ");
-
- if ( name[0] == '\0' )
- name = "/";
- dt_printk("%s%s:\n", prefix, name);
-
- for ( prop = fdt_first_property_offset(fdt, node);
- prop >= 0;
- prop = fdt_next_property_offset(fdt, prop) )
- {
- const struct fdt_property *p;
-
- p = fdt_get_property_by_offset(fdt, prop, NULL);
-
- dt_printk("%s %s\n", prefix, fdt_string(fdt, fdt32_to_cpu(p->nameoff)));
- }
-
- return 0;
-}
-
-/**
- * device_tree_dump - print a text representation of a device tree
- * @fdt: flat device tree to print
- */
-void __init device_tree_dump(const void *fdt)
-{
- device_tree_for_each_node(fdt, dump_node, NULL);
-}
-
-
-static void __init process_memory_node(const void *fdt, int node,
- const char *name,
- u32 address_cells, u32 size_cells)
-{
- const struct fdt_property *prop;
- int i;
- int banks;
- const __be32 *cell;
- paddr_t start, size;
- u32 reg_cells = address_cells + size_cells;
-
- if ( address_cells < 1 || size_cells < 1 )
- {
- early_printk("fdt: node `%s': invalid #address-cells or #size-cells",
- name);
- return;
- }
-
- prop = fdt_get_property(fdt, node, "reg", NULL);
- if ( !prop )
- {
- early_printk("fdt: node `%s': missing `reg' property\n", name);
- return;
- }
-
- cell = (const __be32 *)prop->data;
- banks = fdt32_to_cpu(prop->len) / (reg_cells * sizeof (u32));
-
- for ( i = 0; i < banks && early_info.mem.nr_banks < NR_MEM_BANKS; i++ )
- {
- device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
- early_info.mem.bank[early_info.mem.nr_banks].start = start;
- early_info.mem.bank[early_info.mem.nr_banks].size = size;
- early_info.mem.nr_banks++;
- }
-}
-
-static void __init process_multiboot_node(const void *fdt, int node,
- const char *name,
- u32 address_cells, u32 size_cells)
-{
- const struct fdt_property *prop;
- const __be32 *cell;
- int nr;
- struct dt_mb_module *mod;
- int len;
-
- if ( fdt_node_check_compatible(fdt, node, "xen,linux-zimage") == 0 ||
- fdt_node_check_compatible(fdt, node, "multiboot,kernel") == 0 )
- nr = MOD_KERNEL;
- else if ( fdt_node_check_compatible(fdt, node, "xen,linux-initrd") == 0 ||
- fdt_node_check_compatible(fdt, node, "multiboot,ramdisk") == 0 )
- nr = MOD_INITRD;
- else
- early_panic("%s not a known xen multiboot type\n", name);
-
- mod = &early_info.modules.module[nr];
-
- prop = fdt_get_property(fdt, node, "reg", &len);
- if ( !prop )
- early_panic("node %s missing `reg' property\n", name);
-
- if ( len < dt_cells_to_size(address_cells + size_cells) )
- early_panic("fdt: node `%s': `reg` property length is too short\n",
- name);
-
- cell = (const __be32 *)prop->data;
- device_tree_get_reg(&cell, address_cells, size_cells,
- &mod->start, &mod->size);
-
- prop = fdt_get_property(fdt, node, "bootargs", &len);
- if ( prop )
- {
- if ( len > sizeof(mod->cmdline) )
- early_panic("module %d command line too long\n", nr);
-
- safe_strcpy(mod->cmdline, prop->data);
- }
- else
- mod->cmdline[0] = 0;
-
- if ( nr > early_info.modules.nr_mods )
- early_info.modules.nr_mods = nr;
-}
-
-static void __init process_chosen_node(const void *fdt, int node,
- const char *name,
- u32 address_cells, u32 size_cells)
-{
- const struct fdt_property *prop;
- struct dt_mb_module *mod = &early_info.modules.module[MOD_INITRD];
- paddr_t start, end;
- int len;
-
- dt_printk("Checking for initrd in /chosen\n");
-
- prop = fdt_get_property(fdt, node, "linux,initrd-start", &len);
- if ( !prop )
- /* No initrd present. */
- return;
- if ( len != sizeof(u32) && len != sizeof(u64) )
- {
- dt_printk("linux,initrd-start property has invalid length %d\n", len);
- return;
- }
- start = dt_read_number((void *)&prop->data, dt_size_to_cells(len));
-
- prop = fdt_get_property(fdt, node, "linux,initrd-end", &len);
- if ( !prop )
- {
- dt_printk("linux,initrd-end not present but -start was\n");
- return;
- }
- if ( len != sizeof(u32) && len != sizeof(u64) )
- {
- dt_printk("linux,initrd-end property has invalid length %d\n", len);
- return;
- }
- end = dt_read_number((void *)&prop->data, dt_size_to_cells(len));
-
- if ( start >= end )
- {
- dt_printk("linux,initrd limits invalid: %"PRIpaddr" >= %"PRIpaddr"\n",
- start, end);
- return;
- }
-
- dt_printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end);
-
- mod->start = start;
- mod->size = end - start;
-
- early_info.modules.nr_mods = MAX(MOD_INITRD, early_info.modules.nr_mods);
-}
-
-static int __init early_scan_node(const void *fdt,
- int node, const char *name, int depth,
- u32 address_cells, u32 size_cells,
- void *data)
-{
- if ( device_tree_node_matches(fdt, node, "memory") )
- process_memory_node(fdt, node, name, address_cells, size_cells);
- else if ( device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) ||
- device_tree_node_compatible(fdt, node, "multiboot,module" ))
- process_multiboot_node(fdt, node, name, address_cells, size_cells);
- else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") )
- process_chosen_node(fdt, node, name, address_cells, size_cells);
-
- return 0;
-}
-
-static void __init early_print_info(void)
-{
- struct dt_mem_info *mi = &early_info.mem;
- struct dt_module_info *mods = &early_info.modules;
- int i, nr_rsvd;
-
- for ( i = 0; i < mi->nr_banks; i++ )
- early_printk("RAM: %"PRIpaddr" - %"PRIpaddr"\n",
- mi->bank[i].start,
- mi->bank[i].start + mi->bank[i].size - 1);
- early_printk("\n");
- for ( i = 1 ; i < mods->nr_mods + 1; i++ )
- early_printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %s\n",
- i,
- mods->module[i].start,
- mods->module[i].start + mods->module[i].size,
- mods->module[i].cmdline);
- nr_rsvd = fdt_num_mem_rsv(device_tree_flattened);
- for ( i = 0; i < nr_rsvd; i++ )
- {
- paddr_t s, e;
- if ( fdt_get_mem_rsv(device_tree_flattened, i, &s, &e) < 0 )
- continue;
- /* fdt_get_mem_rsv returns length */
- e += s;
- early_printk(" RESVD[%d]: %"PRIpaddr" - %"PRIpaddr"\n",
- i, s, e);
- }
- early_printk("\n");
-}
-
-/**
- * device_tree_early_init - initialize early info from a DTB
- * @fdt: flattened device tree binary
- *
- * Returns the size of the DTB.
- */
-size_t __init device_tree_early_init(const void *fdt, paddr_t paddr)
-{
- struct dt_mb_module *mod;
- int ret;
-
- ret = fdt_check_header(fdt);
- if ( ret < 0 )
- early_panic("No valid device tree\n");
-
- mod = &early_info.modules.module[MOD_FDT];
- mod->start = paddr;
- mod->size = fdt_totalsize(fdt);
-
- early_info.modules.nr_mods = max(MOD_FDT, early_info.modules.nr_mods);
-
- device_tree_for_each_node((void *)fdt, early_scan_node, NULL);
- early_print_info();
-
- return fdt_totalsize(fdt);
-}
-
static void __init *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
unsigned long align)
{
@@ -525,10 +128,8 @@ static void __init *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
}
/* Find a property with a given name for a given node and return it. */
-static const struct dt_property *
-dt_find_property(const struct dt_device_node *np,
- const char *name,
- u32 *lenp)
+const struct dt_property *dt_find_property(const struct dt_device_node *np,
+ const char *name, u32 *lenp)
{
const struct dt_property *pp;
@@ -695,7 +296,8 @@ bool_t dt_match_node(const struct dt_device_match *matches,
if ( !matches )
return 0;
- while ( matches->path || matches->type || matches->compatible )
+ while ( matches->path || matches->type ||
+ matches->compatible || matches->not_available )
{
bool_t match = 1;
@@ -708,6 +310,9 @@ bool_t dt_match_node(const struct dt_device_match *matches,
if ( matches->compatible )
match &= dt_device_is_compatible(node, matches->compatible);
+ if ( matches->not_available )
+ match &= !dt_device_is_available(node);
+
if ( match )
return match;
@@ -948,7 +553,7 @@ static int dt_translate_one(const struct dt_device_node *parent,
ranges = dt_get_property(parent, rprop, &rlen);
if ( ranges == NULL )
{
- dt_printk(XENLOG_ERR "DT: no ranges; cannot translate\n");
+ printk(XENLOG_ERR "DT: no ranges; cannot translate\n");
return 1;
}
if ( rlen == 0 )
@@ -1018,7 +623,7 @@ static u64 __dt_translate_address(const struct dt_device_node *dev,
bus->count_cells(dev, &na, &ns);
if ( !DT_CHECK_COUNTS(na, ns) )
{
- dt_printk(XENLOG_ERR "dt_parse: Bad cell count for device %s\n",
+ printk(XENLOG_ERR "dt_parse: Bad cell count for device %s\n",
dev->full_name);
goto bail;
}
@@ -1047,7 +652,7 @@ static u64 __dt_translate_address(const struct dt_device_node *dev,
pbus = dt_match_bus(parent);
if ( pbus == NULL )
{
- dt_printk("DT: %s is not a valid bus\n", parent->full_name);
+ printk("DT: %s is not a valid bus\n", parent->full_name);
break;
}
pbus->count_cells(dev, &pna, &pns);
@@ -1105,9 +710,9 @@ int dt_device_get_address(const struct dt_device_node *dev, int index,
*
* Returns a node pointer.
*/
-static const struct dt_device_node *dt_find_node_by_phandle(dt_phandle handle)
+static struct dt_device_node *dt_find_node_by_phandle(dt_phandle handle)
{
- const struct dt_device_node *np;
+ struct dt_device_node *np;
dt_for_each_device_node(dt_host, np)
if ( np->phandle == handle )
@@ -1492,6 +1097,153 @@ bool_t dt_device_is_available(const struct dt_device_node *device)
return 0;
}
+static int __dt_parse_phandle_with_args(const struct dt_device_node *np,
+ const char *list_name,
+ const char *cells_name,
+ int cell_count, int index,
+ struct dt_phandle_args *out_args)
+{
+ const __be32 *list, *list_end;
+ int rc = 0, cur_index = 0;
+ u32 size, count = 0;
+ struct dt_device_node *node = NULL;
+ dt_phandle phandle;
+
+ /* Retrieve the phandle list property */
+ list = dt_get_property(np, list_name, &size);
+ if ( !list )
+ return -ENOENT;
+ list_end = list + size / sizeof(*list);
+
+ /* Loop over the phandles until all the requested entry is found */
+ while ( list < list_end )
+ {
+ rc = -EINVAL;
+ count = 0;
+
+ /*
+ * If phandle is 0, then it is an empty entry with no
+ * arguments. Skip forward to the next entry.
+ * */
+ phandle = be32_to_cpup(list++);
+ if ( phandle )
+ {
+ /*
+ * Find the provider node and parse the #*-cells
+ * property to determine the argument length.
+ *
+ * This is not needed if the cell count is hard-coded
+ * (i.e. cells_name not set, but cell_count is set),
+ * except when we're going to return the found node
+ * below.
+ */
+ if ( cells_name || cur_index == index )
+ {
+ node = dt_find_node_by_phandle(phandle);
+ if ( !node )
+ {
+ printk(XENLOG_ERR "%s: could not find phandle\n",
+ np->full_name);
+ goto err;
+ }
+ }
+
+ if ( cells_name )
+ {
+ if ( !dt_property_read_u32(node, cells_name, &count) )
+ {
+ printk("%s: could not get %s for %s\n",
+ np->full_name, cells_name, node->full_name);
+ goto err;
+ }
+ }
+ else
+ count = cell_count;
+
+ /*
+ * Make sure that the arguments actually fit in the
+ * remaining property data length
+ */
+ if ( list + count > list_end )
+ {
+ printk(XENLOG_ERR "%s: arguments longer than property\n",
+ np->full_name);
+ goto err;
+ }
+ }
+
+ /*
+ * All of the error cases above bail out of the loop, so at
+ * this point, the parsing is successful. If the requested
+ * index matches, then fill the out_args structure and return,
+ * or return -ENOENT for an empty entry.
+ */
+ rc = -ENOENT;
+ if ( cur_index == index )
+ {
+ if (!phandle)
+ goto err;
+
+ if ( out_args )
+ {
+ int i;
+
+ WARN_ON(count > MAX_PHANDLE_ARGS);
+ if (count > MAX_PHANDLE_ARGS)
+ count = MAX_PHANDLE_ARGS;
+ out_args->np = node;
+ out_args->args_count = count;
+ for ( i = 0; i < count; i++ )
+ out_args->args[i] = be32_to_cpup(list++);
+ }
+
+ /* Found it! return success */
+ return 0;
+ }
+
+ node = NULL;
+ list += count;
+ cur_index++;
+ }
+
+ /*
+ * Returning result will be one of:
+ * -ENOENT : index is for empty phandle
+ * -EINVAL : parsing error on data
+ * [1..n] : Number of phandle (count mode; when index = -1)
+ */
+ rc = index < 0 ? cur_index : -ENOENT;
+err:
+ return rc;
+}
+
+struct dt_device_node *dt_parse_phandle(const struct dt_device_node *np,
+ const char *phandle_name, int index)
+{
+ struct dt_phandle_args args;
+
+ if (index < 0)
+ return NULL;
+
+ if (__dt_parse_phandle_with_args(np, phandle_name, NULL, 0,
+ index, &args))
+ return NULL;
+
+ return args.np;
+}
+
+
+int dt_parse_phandle_with_args(const struct dt_device_node *np,
+ const char *list_name,
+ const char *cells_name, int index,
+ struct dt_phandle_args *out_args)
+{
+ if ( index < 0 )
+ return -EINVAL;
+ return __dt_parse_phandle_with_args(np, list_name, cells_name, 0,
+ index, out_args);
+}
+
/**
* unflatten_dt_node - Alloc and populate a device_node from the flat tree
* @fdt: The parent device tree blob
@@ -1519,7 +1271,7 @@ static unsigned long __init unflatten_dt_node(const void *fdt,
tag = be32_to_cpup((__be32 *)(*p));
if ( tag != FDT_BEGIN_NODE )
{
- dt_printk(XENLOG_WARNING "Weird tag at start of node: %x\n", tag);
+ printk(XENLOG_WARNING "Weird tag at start of node: %x\n", tag);
return mem;
}
*p += 4;
@@ -1563,6 +1315,10 @@ static unsigned long __init unflatten_dt_node(const void *fdt,
np->full_name = ((char *)np) + sizeof(struct dt_device_node);
/* By default dom0 owns the device */
np->used_by = 0;
+ /* By default the device is not protected */
+ np->is_protected = false;
+ INIT_LIST_HEAD(&np->domain_list);
+
if ( new_format )
{
char *fn = np->full_name;
@@ -1721,7 +1477,7 @@ static unsigned long __init unflatten_dt_node(const void *fdt,
}
if ( tag != FDT_END_NODE )
{
- dt_printk(XENLOG_WARNING "Weird tag at end of node: %x\n", tag);
+ printk(XENLOG_WARNING "Weird tag at end of node: %x\n", tag);
return mem;
}
@@ -1770,10 +1526,10 @@ static void __init __unflatten_device_tree(const void *fdt,
start = ((unsigned long)fdt) + fdt_off_dt_struct(fdt);
unflatten_dt_node(fdt, mem, &start, NULL, &allnextp, 0);
if ( be32_to_cpup((__be32 *)start) != FDT_END )
- dt_printk(XENLOG_WARNING "Weird tag at end of tree: %08x\n",
+ printk(XENLOG_WARNING "Weird tag at end of tree: %08x\n",
*((u32 *)start));
if ( be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef )
- dt_printk(XENLOG_WARNING "End of tree marker overwritten: %08x\n",
+ printk(XENLOG_WARNING "End of tree marker overwritten: %08x\n",
be32_to_cpu(((__be32 *)mem)[size / 4]));
*allnextp = NULL;
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 1308193..4a62c1d 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -15,6 +15,7 @@
#include <xen/domain.h>
#include <xen/mm.h>
#include <xen/event.h>
+#include <xen/mem_event.h>
#include <xen/time.h>
#include <xen/console.h>
#include <xen/softirq.h>
@@ -59,17 +60,17 @@ DEFINE_RCU_READ_LOCK(domlist_read_lock);
static struct domain *domain_hash[DOMAIN_HASH_SIZE];
struct domain *domain_list;
-struct domain *dom0;
+struct domain *hardware_domain __read_mostly;
+
+#ifdef CONFIG_LATE_HWDOM
+domid_t hardware_domid __read_mostly;
+integer_param("hardware_dom", hardware_domid);
+#endif
struct vcpu *idle_vcpu[NR_CPUS] __read_mostly;
vcpu_info_t dummy_vcpu_info;
-int current_domain_id(void)
-{
- return current->domain->domain_id;
-}
-
static void __domain_finalise_shutdown(struct domain *d)
{
struct vcpu *v;
@@ -125,9 +126,10 @@ struct vcpu *alloc_vcpu(
tasklet_init(&v->continue_hypercall_tasklet, NULL, 0);
- if ( !zalloc_cpumask_var(&v->cpu_affinity) ||
- !zalloc_cpumask_var(&v->cpu_affinity_tmp) ||
- !zalloc_cpumask_var(&v->cpu_affinity_saved) ||
+ if ( !zalloc_cpumask_var(&v->cpu_hard_affinity) ||
+ !zalloc_cpumask_var(&v->cpu_hard_affinity_tmp) ||
+ !zalloc_cpumask_var(&v->cpu_hard_affinity_saved) ||
+ !zalloc_cpumask_var(&v->cpu_soft_affinity) ||
!zalloc_cpumask_var(&v->vcpu_dirty_cpumask) )
goto fail_free;
@@ -156,9 +158,10 @@ struct vcpu *alloc_vcpu(
fail_wq:
destroy_waitqueue_vcpu(v);
fail_free:
- free_cpumask_var(v->cpu_affinity);
- free_cpumask_var(v->cpu_affinity_tmp);
- free_cpumask_var(v->cpu_affinity_saved);
+ free_cpumask_var(v->cpu_hard_affinity);
+ free_cpumask_var(v->cpu_hard_affinity_tmp);
+ free_cpumask_var(v->cpu_hard_affinity_saved);
+ free_cpumask_var(v->cpu_soft_affinity);
free_cpumask_var(v->vcpu_dirty_cpumask);
free_vcpu_struct(v);
return NULL;
@@ -183,6 +186,51 @@ struct vcpu *alloc_vcpu(
return v;
}
+static int late_hwdom_init(struct domain *d)
+{
+#ifdef CONFIG_LATE_HWDOM
+ struct domain *dom0;
+ int rv;
+
+ if ( d != hardware_domain || d->domain_id == 0 )
+ return 0;
+
+ rv = xsm_init_hardware_domain(XSM_HOOK, d);
+ if ( rv )
+ return rv;
+
+ printk("Initialising hardware domain %d\n", hardware_domid);
+
+ dom0 = rcu_lock_domain_by_id(0);
+ ASSERT(dom0 != NULL);
+ /*
+ * Hardware resource ranges for domain 0 have been set up from
+ * various sources intended to restrict the hardware domain's
+ * access. Apply these ranges to the actual hardware domain.
+ *
+ * Because the lists are being swapped, a side effect of this
+ * operation is that Domain 0's rangesets are cleared. Since
+ * domain 0 should not be accessing the hardware when it constructs
+ * a hardware domain, this should not be a problem. Both lists
+ * may be modified after this hypercall returns if a more complex
+ * device model is desired.
+ */
+ rangeset_swap(d->irq_caps, dom0->irq_caps);
+ rangeset_swap(d->iomem_caps, dom0->iomem_caps);
+#ifdef CONFIG_X86
+ rangeset_swap(d->arch.ioport_caps, dom0->arch.ioport_caps);
+#endif
+
+ rcu_unlock_domain(dom0);
+
+ iommu_hwdom_init(d);
+
+ return rv;
+#else
+ return 0;
+#endif
+}
+
static unsigned int __read_mostly extra_dom0_irqs = 256;
static unsigned int __read_mostly extra_domU_irqs = 32;
static void __init parse_extra_guest_irqs(const char *s)
@@ -197,7 +245,7 @@ custom_param("extra_guest_irqs", parse_extra_guest_irqs);
struct domain *domain_create(
domid_t domid, unsigned int domcr_flags, uint32_t ssidref)
{
- struct domain *d, **pd;
+ struct domain *d, **pd, *old_hwdom = NULL;
enum { INIT_xsm = 1u<<0, INIT_watchdog = 1u<<1, INIT_rangeset = 1u<<2,
INIT_evtchn = 1u<<3, INIT_gnttab = 1u<<4, INIT_arch = 1u<<5 };
int err, init_status = 0;
@@ -233,6 +281,8 @@ struct domain *domain_create(
spin_lock_init(&d->pbuf_lock);
+ rwlock_init(&d->vnuma_rwlock);
+
err = -ENOMEM;
if ( !zalloc_cpumask_var(&d->domain_dirty_cpumask) )
goto fail;
@@ -241,11 +291,17 @@ struct domain *domain_create(
d->guest_type = guest_type_hvm;
else if ( domcr_flags & DOMCRF_pvh )
d->guest_type = guest_type_pvh;
+ else
+ d->guest_type = guest_type_pv;
- if ( domid == 0 )
+ if ( domid == 0 || domid == hardware_domid )
{
+ if ( hardware_domid < 0 || hardware_domid >= DOMID_FIRST_RESERVED )
+ panic("The value of hardware_dom must be a valid domain ID");
d->is_pinned = opt_dom0_vcpus_pin;
d->disable_migrate = 1;
+ old_hwdom = hardware_domain;
+ hardware_domain = d;
}
rangeset_domain_initialise(d);
@@ -267,7 +323,7 @@ struct domain *domain_create(
d->controller_pause_count = 1;
atomic_inc(&d->pause_count);
- if ( domid )
+ if ( !is_hardware_domain(d) )
d->nr_pirqs = nr_static_irqs + extra_domU_irqs;
else
d->nr_pirqs = nr_static_irqs + extra_dom0_irqs;
@@ -306,6 +362,9 @@ struct domain *domain_create(
if ( (err = sched_init_domain(d)) != 0 )
goto fail;
+ if ( (err = late_hwdom_init(d)) != 0 )
+ goto fail;
+
if ( !is_idle_domain(d) )
{
spin_lock(&domlist_update_lock);
@@ -324,6 +383,8 @@ struct domain *domain_create(
fail:
d->is_dying = DOMDYING_dead;
+ if ( hardware_domain == d )
+ hardware_domain = old_hwdom;
atomic_set(&d->refcnt, DOMAIN_DESTROYED);
xfree(d->mem_event);
xfree(d->pbuf);
@@ -351,17 +412,21 @@ struct domain *domain_create(
void domain_update_node_affinity(struct domain *d)
{
- cpumask_var_t cpumask;
- cpumask_var_t online_affinity;
+ cpumask_var_t dom_cpumask, dom_cpumask_soft;
+ cpumask_t *dom_affinity;
const cpumask_t *online;
struct vcpu *v;
- unsigned int node;
+ unsigned int cpu;
- if ( !zalloc_cpumask_var(&cpumask) )
+ /* Do we have vcpus already? If not, no need to update node-affinity. */
+ if ( !d->vcpu || !d->vcpu[0] )
return;
- if ( !alloc_cpumask_var(&online_affinity) )
+
+ if ( !zalloc_cpumask_var(&dom_cpumask) )
+ return;
+ if ( !zalloc_cpumask_var(&dom_cpumask_soft) )
{
- free_cpumask_var(cpumask);
+ free_cpumask_var(dom_cpumask);
return;
}
@@ -369,33 +434,48 @@ void domain_update_node_affinity(struct domain *d)
spin_lock(&d->node_affinity_lock);
- for_each_vcpu ( d, v )
- {
- cpumask_and(online_affinity, v->cpu_affinity, online);
- cpumask_or(cpumask, cpumask, online_affinity);
- }
-
/*
- * If d->auto_node_affinity is true, the domain's node-affinity mask
- * (d->node_affinity) is automaically computed from all the domain's
- * vcpus' vcpu-affinity masks (the union of which we have just built
- * above in cpumask). OTOH, if d->auto_node_affinity is false, we
- * must leave the node-affinity of the domain alone.
+ * If d->auto_node_affinity is true, let's compute the domain's
+ * node-affinity and update d->node_affinity accordingly. if false,
+ * just leave d->auto_node_affinity alone.
*/
if ( d->auto_node_affinity )
{
+ /*
+ * We want the narrowest possible set of pcpus (to get the narowest
+ * possible set of nodes). What we need is the cpumask of where the
+ * domain can run (the union of the hard affinity of all its vcpus),
+ * and the full mask of where it would prefer to run (the union of
+ * the soft affinity of all its various vcpus). Let's build them.
+ */
+ for_each_vcpu ( d, v )
+ {
+ cpumask_or(dom_cpumask, dom_cpumask, v->cpu_hard_affinity);
+ cpumask_or(dom_cpumask_soft, dom_cpumask_soft,
+ v->cpu_soft_affinity);
+ }
+ /* Filter out non-online cpus */
+ cpumask_and(dom_cpumask, dom_cpumask, online);
+ ASSERT(!cpumask_empty(dom_cpumask));
+ /* And compute the intersection between hard, online and soft */
+ cpumask_and(dom_cpumask_soft, dom_cpumask_soft, dom_cpumask);
+
+ /*
+ * If not empty, the intersection of hard, soft and online is the
+ * narrowest set we want. If empty, we fall back to hard&online.
+ */
+ dom_affinity = cpumask_empty(dom_cpumask_soft) ?
+ dom_cpumask : dom_cpumask_soft;
+
nodes_clear(d->node_affinity);
- for_each_online_node ( node )
- if ( cpumask_intersects(&node_to_cpumask(node), cpumask) )
- node_set(node, d->node_affinity);
+ for_each_cpu ( cpu, dom_affinity )
+ node_set(cpu_to_node(cpu), d->node_affinity);
}
- sched_set_node_affinity(d, &d->node_affinity);
-
spin_unlock(&d->node_affinity_lock);
- free_cpumask_var(online_affinity);
- free_cpumask_var(cpumask);
+ free_cpumask_var(dom_cpumask_soft);
+ free_cpumask_var(dom_cpumask);
}
@@ -529,6 +609,7 @@ int domain_kill(struct domain *d)
evtchn_destroy(d);
gnttab_release_mappings(d);
tmem_destroy(d->tmem_client);
+ vnuma_destroy(d->vnuma);
domain_set_outstanding_pages(d, 0);
d->tmem_client = NULL;
/* fallthrough */
@@ -536,10 +617,11 @@ int domain_kill(struct domain *d)
rc = domain_relinquish_resources(d);
if ( rc != 0 )
{
- BUG_ON(rc != -EAGAIN);
+ if ( rc == -ERESTART )
+ rc = -EAGAIN;
break;
}
- if ( sched_move_domain(d, cpupool0) )
+ if ( cpupool_move_domain(d, cpupool0) )
return -EAGAIN;
for_each_vcpu ( d, v )
unmap_vcpu_info(v);
@@ -601,8 +683,8 @@ void domain_shutdown(struct domain *d, u8 reason)
d->shutdown_code = reason;
reason = d->shutdown_code;
- if ( d->domain_id == 0 )
- dom0_shutdown(reason);
+ if ( is_hardware_domain(d) )
+ hwdom_shutdown(reason);
if ( d->is_shutting_down )
{
@@ -624,6 +706,8 @@ void domain_shutdown(struct domain *d, u8 reason)
v->paused_for_shutdown = 1;
}
+ arch_domain_shutdown(d);
+
__domain_finalise_shutdown(d);
spin_unlock(&d->shutdown_lock);
@@ -729,9 +813,10 @@ static void complete_domain_destroy(struct rcu_head *head)
for ( i = d->max_vcpus - 1; i >= 0; i-- )
if ( (v = d->vcpu[i]) != NULL )
{
- free_cpumask_var(v->cpu_affinity);
- free_cpumask_var(v->cpu_affinity_tmp);
- free_cpumask_var(v->cpu_affinity_saved);
+ free_cpumask_var(v->cpu_hard_affinity);
+ free_cpumask_var(v->cpu_hard_affinity_tmp);
+ free_cpumask_var(v->cpu_hard_affinity_saved);
+ free_cpumask_var(v->cpu_soft_affinity);
free_cpumask_var(v->vcpu_dirty_cpumask);
free_vcpu_struct(v);
}
@@ -754,13 +839,12 @@ static void complete_domain_destroy(struct rcu_head *head)
void domain_destroy(struct domain *d)
{
struct domain **pd;
- atomic_t old, new;
+ atomic_t old = ATOMIC_INIT(0);
+ atomic_t new = ATOMIC_INIT(DOMAIN_DESTROYED);
BUG_ON(!d->is_dying);
/* May be already destroyed, or get_domain() can race us. */
- _atomic_set(old, 0);
- _atomic_set(new, DOMAIN_DESTROYED);
old = atomic_compareandswap(old, new, &d->refcnt);
if ( _atomic_read(old) != 0 )
return;
@@ -803,32 +887,76 @@ void vcpu_unpause(struct vcpu *v)
vcpu_wake(v);
}
-void domain_pause(struct domain *d)
+int vcpu_pause_by_systemcontroller(struct vcpu *v)
{
- struct vcpu *v;
+ int old, new, prev = v->controller_pause_count;
- ASSERT(d != current->domain);
+ do
+ {
+ old = prev;
+ new = old + 1;
- atomic_inc(&d->pause_count);
+ if ( new > 255 )
+ return -EUSERS;
- for_each_vcpu( d, v )
- vcpu_sleep_sync(v);
+ prev = cmpxchg(&v->controller_pause_count, old, new);
+ } while ( prev != old );
+
+ vcpu_pause(v);
+
+ return 0;
}
-void domain_pause_nosync(struct domain *d)
+int vcpu_unpause_by_systemcontroller(struct vcpu *v)
+{
+ int old, new, prev = v->controller_pause_count;
+
+ do
+ {
+ old = prev;
+ new = old - 1;
+
+ if ( new < 0 )
+ return -EINVAL;
+
+ prev = cmpxchg(&v->controller_pause_count, old, new);
+ } while ( prev != old );
+
+ vcpu_unpause(v);
+
+ return 0;
+}
+
+static void do_domain_pause(struct domain *d,
+ void (*sleep_fn)(struct vcpu *v))
{
struct vcpu *v;
atomic_inc(&d->pause_count);
for_each_vcpu( d, v )
- vcpu_sleep_nosync(v);
+ sleep_fn(v);
+
+ arch_domain_pause(d);
+}
+
+void domain_pause(struct domain *d)
+{
+ ASSERT(d != current->domain);
+ do_domain_pause(d, vcpu_sleep_sync);
+}
+
+void domain_pause_nosync(struct domain *d)
+{
+ do_domain_pause(d, vcpu_sleep_nosync);
}
void domain_unpause(struct domain *d)
{
struct vcpu *v;
+ arch_domain_unpause(d);
+
if ( atomic_dec_and_test(&d->pause_count) )
for_each_vcpu( d, v )
vcpu_wake(v);
@@ -904,7 +1032,7 @@ int vcpu_reset(struct vcpu *v)
v->async_exception_mask = 0;
memset(v->async_exception_state, 0, sizeof(v->async_exception_state));
#endif
- cpumask_clear(v->cpu_affinity_tmp);
+ cpumask_clear(v->cpu_hard_affinity_tmp);
clear_bit(_VPF_blocked, &v->pause_flags);
clear_bit(_VPF_in_reset, &v->pause_flags);
@@ -983,6 +1111,7 @@ int map_vcpu_info(struct vcpu *v, unsigned long gfn, unsigned offset)
vcpu_info(v, evtchn_upcall_pending) = 1;
for ( i = 0; i < BITS_PER_EVTCHN_WORD(d); i++ )
set_bit(i, &vcpu_info(v, evtchn_pending_sel));
+ arch_evtchn_inject(v);
return 0;
}
@@ -1043,7 +1172,7 @@ long do_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE_PARAM(void) arg)
free_vcpu_guest_context(ctxt);
- if ( rc == -EAGAIN )
+ if ( rc == -ERESTART )
rc = hypercall_create_continuation(__HYPERVISOR_vcpu_op, "iih",
cmd, vcpuid, arg);
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 060af1b..f15dcfe 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -24,18 +24,20 @@
#include <xen/bitmap.h>
#include <xen/paging.h>
#include <xen/hypercall.h>
+#include <xen/mem_event.h>
#include <asm/current.h>
#include <asm/irq.h>
#include <asm/page.h>
+#include <asm/p2m.h>
#include <public/domctl.h>
#include <xsm/xsm.h>
static DEFINE_SPINLOCK(domctl_lock);
DEFINE_SPINLOCK(vcpu_alloc_lock);
-int bitmap_to_xenctl_bitmap(struct xenctl_bitmap *xenctl_bitmap,
- const unsigned long *bitmap,
- unsigned int nbits)
+static int bitmap_to_xenctl_bitmap(struct xenctl_bitmap *xenctl_bitmap,
+ const unsigned long *bitmap,
+ unsigned int nbits)
{
unsigned int guest_bytes, copy_bytes, i;
uint8_t zero = 0;
@@ -63,9 +65,9 @@ int bitmap_to_xenctl_bitmap(struct xenctl_bitmap *xenctl_bitmap,
return err;
}
-int xenctl_bitmap_to_bitmap(unsigned long *bitmap,
- const struct xenctl_bitmap *xenctl_bitmap,
- unsigned int nbits)
+static int xenctl_bitmap_to_bitmap(unsigned long *bitmap,
+ const struct xenctl_bitmap *xenctl_bitmap,
+ unsigned int nbits)
{
unsigned int guest_bytes, copy_bytes;
int err = 0;
@@ -118,15 +120,15 @@ int xenctl_bitmap_to_cpumask(cpumask_var_t *cpumask,
return err;
}
-int nodemask_to_xenctl_bitmap(struct xenctl_bitmap *xenctl_nodemap,
- const nodemask_t *nodemask)
+static int nodemask_to_xenctl_bitmap(struct xenctl_bitmap *xenctl_nodemap,
+ const nodemask_t *nodemask)
{
return bitmap_to_xenctl_bitmap(xenctl_nodemap, nodes_addr(*nodemask),
MAX_NUMNODES);
}
-int xenctl_bitmap_to_nodemask(nodemask_t *nodemask,
- const struct xenctl_bitmap *xenctl_nodemap)
+static int xenctl_bitmap_to_nodemask(nodemask_t *nodemask,
+ const struct xenctl_bitmap *xenctl_nodemap)
{
return xenctl_bitmap_to_bitmap(nodes_addr(*nodemask), xenctl_nodemap,
MAX_NUMNODES);
@@ -154,6 +156,7 @@ void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info)
struct vcpu_runstate_info runstate;
info->domain = d->domain_id;
+ info->max_vcpu_id = XEN_INVALID_MAX_VCPU_ID;
info->nr_online_vcpus = 0;
info->ssidref = 0;
@@ -287,6 +290,130 @@ void domctl_lock_release(void)
spin_unlock(¤t->domain->hypercall_deadlock_mutex);
}
+static inline
+int vcpuaffinity_params_invalid(const xen_domctl_vcpuaffinity_t *vcpuaff)
+{
+ return vcpuaff->flags == 0 ||
+ ((vcpuaff->flags & XEN_VCPUAFFINITY_HARD) &&
+ guest_handle_is_null(vcpuaff->cpumap_hard.bitmap)) ||
+ ((vcpuaff->flags & XEN_VCPUAFFINITY_SOFT) &&
+ guest_handle_is_null(vcpuaff->cpumap_soft.bitmap));
+}
+
+void vnuma_destroy(struct vnuma_info *vnuma)
+{
+ if ( vnuma )
+ {
+ xfree(vnuma->vmemrange);
+ xfree(vnuma->vcpu_to_vnode);
+ xfree(vnuma->vdistance);
+ xfree(vnuma->vnode_to_pnode);
+ xfree(vnuma);
+ }
+}
+
+/*
+ * Allocates memory for vNUMA, **vnuma should be NULL.
+ * Caller has to make sure that domain has max_pages
+ * and number of vcpus set for domain.
+ * Verifies that single allocation does not exceed
+ * PAGE_SIZE.
+ */
+static struct vnuma_info *vnuma_alloc(unsigned int nr_vnodes,
+ unsigned int nr_ranges,
+ unsigned int nr_vcpus)
+{
+
+ struct vnuma_info *vnuma;
+
+ /*
+ * Check if any of the allocations are bigger than PAGE_SIZE.
+ * See XSA-77.
+ */
+ if ( nr_vnodes * nr_vnodes > (PAGE_SIZE / sizeof(*vnuma->vdistance)) ||
+ nr_ranges > (PAGE_SIZE / sizeof(*vnuma->vmemrange)) )
+ return ERR_PTR(-EINVAL);
+
+ /*
+ * If allocations become larger then PAGE_SIZE, these allocations
+ * should be split into PAGE_SIZE allocations due to XSA-77.
+ */
+ vnuma = xmalloc(struct vnuma_info);
+ if ( !vnuma )
+ return ERR_PTR(-ENOMEM);
+
+ vnuma->vdistance = xmalloc_array(unsigned int, nr_vnodes * nr_vnodes);
+ vnuma->vcpu_to_vnode = xmalloc_array(unsigned int, nr_vcpus);
+ vnuma->vnode_to_pnode = xmalloc_array(unsigned int, nr_vnodes);
+ vnuma->vmemrange = xmalloc_array(xen_vmemrange_t, nr_ranges);
+
+ if ( vnuma->vdistance == NULL || vnuma->vmemrange == NULL ||
+ vnuma->vcpu_to_vnode == NULL || vnuma->vnode_to_pnode == NULL )
+ {
+ vnuma_destroy(vnuma);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ return vnuma;
+}
+
+/*
+ * Construct vNUMA topology form uinfo.
+ */
+static struct vnuma_info *vnuma_init(const struct xen_domctl_vnuma *uinfo,
+ const struct domain *d)
+{
+ unsigned int i, nr_vnodes;
+ int ret = -EINVAL;
+ struct vnuma_info *info;
+
+ nr_vnodes = uinfo->nr_vnodes;
+
+ if ( nr_vnodes == 0 || uinfo->nr_vcpus != d->max_vcpus || uinfo->pad != 0 )
+ return ERR_PTR(ret);
+
+ info = vnuma_alloc(nr_vnodes, uinfo->nr_vmemranges, d->max_vcpus);
+ if ( IS_ERR(info) )
+ return info;
+
+ ret = -EFAULT;
+
+ if ( copy_from_guest(info->vdistance, uinfo->vdistance,
+ nr_vnodes * nr_vnodes) )
+ goto vnuma_fail;
+
+ if ( copy_from_guest(info->vcpu_to_vnode, uinfo->vcpu_to_vnode,
+ d->max_vcpus) )
+ goto vnuma_fail;
+
+ if ( copy_from_guest(info->vnode_to_pnode, uinfo->vnode_to_pnode,
+ nr_vnodes) )
+ goto vnuma_fail;
+
+ if (copy_from_guest(info->vmemrange, uinfo->vmemrange,
+ uinfo->nr_vmemranges))
+ goto vnuma_fail;
+
+ info->nr_vnodes = nr_vnodes;
+ info->nr_vmemranges = uinfo->nr_vmemranges;
+
+ /* Check that vmemranges flags are zero. */
+ for ( i = 0; i < info->nr_vmemranges; i++ )
+ {
+ if ( info->vmemrange[i].flags != 0 )
+ {
+ ret = -EINVAL;
+ goto vnuma_fail;
+ }
+ }
+
+ return info;
+
+ vnuma_fail:
+ vnuma_destroy(info);
+ return ERR_PTR(ret);
+}
+
long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
{
long ret = 0;
@@ -342,7 +469,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
if ( guest_handle_is_null(op->u.vcpucontext.ctxt) )
{
ret = vcpu_reset(v);
- if ( ret == -EAGAIN )
+ if ( ret == -ERESTART )
ret = hypercall_create_continuation(
__HYPERVISOR_domctl, "h", u_domctl);
break;
@@ -374,7 +501,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
ret = arch_set_info_guest(v, c);
domain_unpause(d);
- if ( ret == -EAGAIN )
+ if ( ret == -ERESTART )
ret = hypercall_create_continuation(
__HYPERVISOR_domctl, "h", u_domctl);
}
@@ -428,7 +555,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
for ( dom = rover + 1; dom != rover; dom++ )
{
if ( dom == DOMID_FIRST_RESERVED )
- dom = 0;
+ dom = 1;
if ( is_free_domid(dom) )
break;
}
@@ -593,31 +720,108 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
case XEN_DOMCTL_getvcpuaffinity:
{
struct vcpu *v;
+ xen_domctl_vcpuaffinity_t *vcpuaff = &op->u.vcpuaffinity;
ret = -EINVAL;
- if ( op->u.vcpuaffinity.vcpu >= d->max_vcpus )
+ if ( vcpuaff->vcpu >= d->max_vcpus )
break;
ret = -ESRCH;
- if ( (v = d->vcpu[op->u.vcpuaffinity.vcpu]) == NULL )
+ if ( (v = d->vcpu[vcpuaff->vcpu]) == NULL )
+ break;
+
+ ret = -EINVAL;
+ if ( vcpuaffinity_params_invalid(vcpuaff) )
break;
if ( op->cmd == XEN_DOMCTL_setvcpuaffinity )
{
- cpumask_var_t new_affinity;
+ cpumask_var_t new_affinity, old_affinity;
+ cpumask_t *online = cpupool_online_cpumask(v->domain->cpupool);;
+
+ /*
+ * We want to be able to restore hard affinity if we are trying
+ * setting both and changing soft affinity (which happens later,
+ * when hard affinity has been succesfully chaged already) fails.
+ */
+ if ( !alloc_cpumask_var(&old_affinity) )
+ {
+ ret = -ENOMEM;
+ break;
+ }
+ cpumask_copy(old_affinity, v->cpu_hard_affinity);
- ret = xenctl_bitmap_to_cpumask(
- &new_affinity, &op->u.vcpuaffinity.cpumap);
- if ( !ret )
+ if ( !alloc_cpumask_var(&new_affinity) )
{
- ret = vcpu_set_affinity(v, new_affinity);
- free_cpumask_var(new_affinity);
+ free_cpumask_var(old_affinity);
+ ret = -ENOMEM;
+ break;
}
+
+ /*
+ * We both set a new affinity and report back to the caller what
+ * the scheduler will be effectively using.
+ */
+ if ( vcpuaff->flags & XEN_VCPUAFFINITY_HARD )
+ {
+ ret = xenctl_bitmap_to_bitmap(cpumask_bits(new_affinity),
+ &vcpuaff->cpumap_hard,
+ nr_cpu_ids);
+ if ( !ret )
+ ret = vcpu_set_hard_affinity(v, new_affinity);
+ if ( ret )
+ goto setvcpuaffinity_out;
+
+ /*
+ * For hard affinity, what we return is the intersection of
+ * cpupool's online mask and the new hard affinity.
+ */
+ cpumask_and(new_affinity, online, v->cpu_hard_affinity);
+ ret = cpumask_to_xenctl_bitmap(&vcpuaff->cpumap_hard,
+ new_affinity);
+ }
+ if ( vcpuaff->flags & XEN_VCPUAFFINITY_SOFT )
+ {
+ ret = xenctl_bitmap_to_bitmap(cpumask_bits(new_affinity),
+ &vcpuaff->cpumap_soft,
+ nr_cpu_ids);
+ if ( !ret)
+ ret = vcpu_set_soft_affinity(v, new_affinity);
+ if ( ret )
+ {
+ /*
+ * Since we're returning error, the caller expects nothing
+ * happened, so we rollback the changes to hard affinity
+ * (if any).
+ */
+ if ( vcpuaff->flags & XEN_VCPUAFFINITY_HARD )
+ vcpu_set_hard_affinity(v, old_affinity);
+ goto setvcpuaffinity_out;
+ }
+
+ /*
+ * For soft affinity, we return the intersection between the
+ * new soft affinity, the cpupool's online map and the (new)
+ * hard affinity.
+ */
+ cpumask_and(new_affinity, new_affinity, online);
+ cpumask_and(new_affinity, new_affinity, v->cpu_hard_affinity);
+ ret = cpumask_to_xenctl_bitmap(&vcpuaff->cpumap_soft,
+ new_affinity);
+ }
+
+ setvcpuaffinity_out:
+ free_cpumask_var(new_affinity);
+ free_cpumask_var(old_affinity);
}
else
{
- ret = cpumask_to_xenctl_bitmap(
- &op->u.vcpuaffinity.cpumap, v->cpu_affinity);
+ if ( vcpuaff->flags & XEN_VCPUAFFINITY_HARD )
+ ret = cpumask_to_xenctl_bitmap(&vcpuaff->cpumap_hard,
+ v->cpu_hard_affinity);
+ if ( vcpuaff->flags & XEN_VCPUAFFINITY_SOFT )
+ ret = cpumask_to_xenctl_bitmap(&vcpuaff->cpumap_soft,
+ v->cpu_soft_affinity);
}
}
break;
@@ -782,7 +986,8 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
if ( pirq >= d->nr_pirqs )
ret = -EINVAL;
- else if ( xsm_irq_permission(XSM_HOOK, d, pirq, allow) )
+ else if ( !pirq_access_permitted(current->domain, pirq) ||
+ xsm_irq_permission(XSM_HOOK, d, pirq, allow) )
ret = -EPERM;
else if ( allow )
ret = pirq_permit_access(d, pirq);
@@ -801,12 +1006,68 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
if ( (mfn + nr_mfns - 1) < mfn ) /* wrap? */
break;
- if ( xsm_iomem_permission(XSM_HOOK, d, mfn, mfn + nr_mfns - 1, allow) )
+ if ( !iomem_access_permitted(current->domain,
+ mfn, mfn + nr_mfns - 1) ||
+ xsm_iomem_permission(XSM_HOOK, d, mfn, mfn + nr_mfns - 1, allow) )
ret = -EPERM;
else if ( allow )
ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
else
ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
+ if ( !ret )
+ memory_type_changed(d);
+ }
+ break;
+
+ case XEN_DOMCTL_memory_mapping:
+ {
+ unsigned long gfn = op->u.memory_mapping.first_gfn;
+ unsigned long mfn = op->u.memory_mapping.first_mfn;
+ unsigned long nr_mfns = op->u.memory_mapping.nr_mfns;
+ unsigned long mfn_end = mfn + nr_mfns - 1;
+ int add = op->u.memory_mapping.add_mapping;
+
+ ret = -EINVAL;
+ if ( mfn_end < mfn || /* wrap? */
+ ((mfn | mfn_end) >> (paddr_bits - PAGE_SHIFT)) ||
+ (gfn + nr_mfns - 1) < gfn ) /* wrap? */
+ break;
+
+ ret = -EPERM;
+ if ( !iomem_access_permitted(current->domain, mfn, mfn_end) ||
+ !iomem_access_permitted(d, mfn, mfn_end) )
+ break;
+
+ ret = xsm_iomem_mapping(XSM_HOOK, d, mfn, mfn_end, add);
+ if ( ret )
+ break;
+
+ if ( add )
+ {
+ printk(XENLOG_G_INFO
+ "memory_map:add: dom%d gfn=%lx mfn=%lx nr=%lx\n",
+ d->domain_id, gfn, mfn, nr_mfns);
+
+ ret = map_mmio_regions(d, gfn, nr_mfns, mfn);
+ if ( ret )
+ printk(XENLOG_G_WARNING
+ "memory_map:fail: dom%d gfn=%lx mfn=%lx nr=%lx ret:%ld\n",
+ d->domain_id, gfn, mfn, nr_mfns, ret);
+ }
+ else
+ {
+ printk(XENLOG_G_INFO
+ "memory_map:remove: dom%d gfn=%lx mfn=%lx nr=%lx\n",
+ d->domain_id, gfn, mfn, nr_mfns);
+
+ ret = unmap_mmio_regions(d, gfn, nr_mfns, mfn);
+ if ( ret && is_hardware_domain(current->domain) )
+ printk(XENLOG_ERR
+ "memory_map: error %ld removing dom%d access to [%lx,%lx]\n",
+ ret, d->domain_id, mfn, mfn_end);
+ }
+ /* Do this unconditionally to cover errors on above failure paths. */
+ memory_type_changed(d);
}
break;
@@ -852,12 +1113,34 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
}
break;
+ case XEN_DOMCTL_mem_event_op:
+ ret = mem_event_domctl(d, &op->u.mem_event_op,
+ guest_handle_cast(u_domctl, void));
+ copyback = 1;
+ break;
+
case XEN_DOMCTL_disable_migrate:
{
d->disable_migrate = op->u.disable_migrate.disable;
}
break;
+#ifdef HAS_MEM_ACCESS
+ case XEN_DOMCTL_set_access_required:
+ {
+ struct p2m_domain* p2m;
+
+ ret = -EPERM;
+ if ( current->domain == d )
+ break;
+
+ ret = 0;
+ p2m = p2m_get_hostp2m(d);
+ p2m->access_required = op->u.access_required.access_required;
+ }
+ break;
+#endif
+
case XEN_DOMCTL_set_virq_handler:
{
uint32_t virq = op->u.set_virq_handler.virq;
@@ -873,6 +1156,27 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
}
break;
+ case XEN_DOMCTL_setvnumainfo:
+ {
+ struct vnuma_info *vnuma;
+
+ vnuma = vnuma_init(&op->u.vnuma, d);
+ if ( IS_ERR(vnuma) )
+ {
+ ret = PTR_ERR(vnuma);
+ break;
+ }
+
+ /* overwrite vnuma topology for domain. */
+ write_lock(&d->vnuma_rwlock);
+ vnuma_destroy(d->vnuma);
+ d->vnuma = vnuma;
+ write_unlock(&d->vnuma_rwlock);
+
+ ret = 0;
+ }
+ break;
+
default:
ret = arch_do_domctl(op, d, u_domctl);
break;
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
new file mode 100644
index 0000000..c68efdb
--- /dev/null
+++ b/xen/common/efi/boot.c
@@ -0,0 +1,1322 @@
+#include "efi.h"
+#include <efi/efiprot.h>
+#include <efi/efipciio.h>
+#include <public/xen.h>
+#include <xen/bitops.h>
+#include <xen/compile.h>
+#include <xen/ctype.h>
+#include <xen/dmi.h>
+#include <xen/init.h>
+#include <xen/keyhandler.h>
+#include <xen/lib.h>
+#include <xen/mm.h>
+#include <xen/multiboot.h>
+#include <xen/pci_regs.h>
+#include <xen/pfn.h>
+#if EFI_PAGE_SIZE != PAGE_SIZE
+# error Cannot use xen/pfn.h here!
+#endif
+#include <xen/string.h>
+#include <xen/stringify.h>
+#ifdef CONFIG_X86
+/*
+ * Keep this arch-specific modified include in the common file, as moving
+ * it to the arch specific include file would obscure that special care is
+ * taken to include it with __ASSEMBLY__ defined.
+ */
+#define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */
+#include <asm/fixmap.h>
+#undef __ASSEMBLY__
+#endif
+
+/* Using SetVirtualAddressMap() is incompatible with kexec: */
+#undef USE_SET_VIRTUAL_ADDRESS_MAP
+
+#define SHIM_LOCK_PROTOCOL_GUID \
+ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
+
+typedef EFI_STATUS
+(/* _not_ EFIAPI */ *EFI_SHIM_LOCK_VERIFY) (
+ IN VOID *Buffer,
+ IN UINT32 Size);
+
+typedef struct {
+ EFI_SHIM_LOCK_VERIFY Verify;
+} EFI_SHIM_LOCK_PROTOCOL;
+
+union string {
+ CHAR16 *w;
+ char *s;
+ const char *cs;
+};
+
+struct file {
+ UINTN size;
+ union {
+ EFI_PHYSICAL_ADDRESS addr;
+ void *ptr;
+ };
+};
+
+static CHAR16 *FormatDec(UINT64 Val, CHAR16 *Buffer);
+static CHAR16 *FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer);
+static void DisplayUint(UINT64 Val, INTN Width);
+static CHAR16 *wstrcpy(CHAR16 *d, const CHAR16 *s);
+static void noreturn blexit(const CHAR16 *str);
+static void PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode);
+static char *get_value(const struct file *cfg, const char *section,
+ const char *item);
+static char *split_string(char *s);
+static CHAR16 *s2w(union string *str);
+static char *w2s(const union string *str);
+static bool_t read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
+ struct file *file, char *options);
+static size_t wstrlen(const CHAR16 * s);
+static int set_color(u32 mask, int bpp, u8 *pos, u8 *sz);
+static bool_t match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2);
+
+static const EFI_BOOT_SERVICES *__initdata efi_bs;
+static EFI_HANDLE __initdata efi_ih;
+
+static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdOut;
+static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdErr;
+
+static UINT32 __initdata mdesc_ver;
+
+static struct file __initdata cfg;
+static struct file __initdata kernel;
+static struct file __initdata ramdisk;
+static struct file __initdata xsm;
+static CHAR16 __initdata newline[] = L"\r\n";
+
+#define PrintStr(s) StdOut->OutputString(StdOut, s)
+#define PrintErr(s) StdErr->OutputString(StdErr, s)
+
+/*
+ * Include architecture specific implementation here, which references the
+ * static globals defined above.
+ */
+#include "efi-boot.h"
+
+static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer)
+{
+ if ( Val >= 10 )
+ Buffer = FormatDec(Val / 10, Buffer);
+ *Buffer = (CHAR16)(L'0' + Val % 10);
+ return Buffer + 1;
+}
+
+static CHAR16 *__init FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer)
+{
+ if ( Width > 1 || Val >= 0x10 )
+ Buffer = FormatHex(Val >> 4, Width ? Width - 1 : 0, Buffer);
+ *Buffer = (CHAR16)((Val &= 0xf) < 10 ? L'0' + Val : L'a' + Val - 10);
+ return Buffer + 1;
+}
+
+static void __init DisplayUint(UINT64 Val, INTN Width)
+{
+ CHAR16 PrintString[32], *end;
+
+ if (Width < 0)
+ end = FormatDec(Val, PrintString);
+ else
+ {
+ PrintStr(L"0x");
+ end = FormatHex(Val, Width, PrintString);
+ }
+ *end = 0;
+ PrintStr(PrintString);
+}
+
+static size_t __init __maybe_unused wstrlen(const CHAR16 *s)
+{
+ const CHAR16 *sc;
+
+ for ( sc = s; *sc != L'\0'; ++sc )
+ /* nothing */;
+ return sc - s;
+}
+
+static CHAR16 *__init wstrcpy(CHAR16 *d, const CHAR16 *s)
+{
+ CHAR16 *r = d;
+
+ while ( (*d++ = *s++) != 0 )
+ ;
+ return r;
+}
+
+static int __init wstrcmp(const CHAR16 *s1, const CHAR16 *s2)
+{
+ while ( *s1 && *s1 == *s2 )
+ {
+ ++s1;
+ ++s2;
+ }
+ return *s1 - *s2;
+}
+
+static int __init wstrncmp(const CHAR16 *s1, const CHAR16 *s2, UINTN n)
+{
+ while ( n && *s1 && *s1 == *s2 )
+ {
+ --n;
+ ++s1;
+ ++s2;
+ }
+ return n ? *s1 - *s2 : 0;
+}
+
+static CHAR16 *__init s2w(union string *str)
+{
+ const char *s = str->s;
+ CHAR16 *w;
+ void *ptr;
+
+ if ( efi_bs->AllocatePool(EfiLoaderData, (strlen(s) + 1) * sizeof(*w),
+ &ptr) != EFI_SUCCESS )
+ return NULL;
+
+ w = str->w = ptr;
+ do {
+ *w = *s++;
+ } while ( *w++ );
+
+ return str->w;
+}
+
+static char *__init w2s(const union string *str)
+{
+ const CHAR16 *w = str->w;
+ char *s = str->s;
+
+ do {
+ if ( *w > 0x007f )
+ return NULL;
+ *s = *w++;
+ } while ( *s++ );
+
+ return str->s;
+}
+
+static bool_t __init match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2)
+{
+ return guid1->Data1 == guid2->Data1 &&
+ guid1->Data2 == guid2->Data2 &&
+ guid1->Data3 == guid2->Data3 &&
+ !memcmp(guid1->Data4, guid2->Data4, sizeof(guid1->Data4));
+}
+
+static void __init noreturn blexit(const CHAR16 *str)
+{
+ if ( str )
+ PrintStr((CHAR16 *)str);
+ PrintStr(newline);
+
+ if ( cfg.addr )
+ efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
+ if ( kernel.addr )
+ efi_bs->FreePages(kernel.addr, PFN_UP(kernel.size));
+ if ( ramdisk.addr )
+ efi_bs->FreePages(ramdisk.addr, PFN_UP(ramdisk.size));
+ if ( xsm.addr )
+ efi_bs->FreePages(xsm.addr, PFN_UP(xsm.size));
+
+ efi_arch_blexit();
+
+ efi_bs->Exit(efi_ih, EFI_SUCCESS, 0, NULL);
+ unreachable(); /* not reached */
+}
+
+/* generic routine for printing error messages */
+static void __init PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode)
+{
+ StdOut = StdErr;
+ PrintErr((CHAR16 *)mesg);
+ PrintErr(L": ");
+
+ switch (ErrCode)
+ {
+ case EFI_NOT_FOUND:
+ mesg = L"Not found";
+ break;
+ case EFI_NO_MEDIA:
+ mesg = L"The device has no media";
+ break;
+ case EFI_MEDIA_CHANGED:
+ mesg = L"Media changed";
+ break;
+ case EFI_DEVICE_ERROR:
+ mesg = L"Device error";
+ break;
+ case EFI_VOLUME_CORRUPTED:
+ mesg = L"Volume corrupted";
+ break;
+ case EFI_ACCESS_DENIED:
+ mesg = L"Access denied";
+ break;
+ case EFI_OUT_OF_RESOURCES:
+ mesg = L"Out of resources";
+ break;
+ case EFI_VOLUME_FULL:
+ mesg = L"Volume is full";
+ break;
+ case EFI_SECURITY_VIOLATION:
+ mesg = L"Security violation";
+ break;
+ case EFI_CRC_ERROR:
+ mesg = L"CRC error";
+ break;
+ case EFI_COMPROMISED_DATA:
+ mesg = L"Compromised data";
+ break;
+ case EFI_BUFFER_TOO_SMALL:
+ mesg = L"Buffer too small";
+ break;
+ default:
+ PrintErr(L"ErrCode: ");
+ DisplayUint(ErrCode, 0);
+ mesg = NULL;
+ break;
+ }
+ blexit(mesg);
+}
+
+static unsigned int __init get_argv(unsigned int argc, CHAR16 **argv,
+ CHAR16 *cmdline, UINTN cmdsize,
+ CHAR16 **options)
+{
+ CHAR16 *ptr = (CHAR16 *)(argv + argc + 1), *prev = NULL;
+ bool_t prev_sep = TRUE;
+
+ for ( ; cmdsize > sizeof(*cmdline) && *cmdline;
+ cmdsize -= sizeof(*cmdline), ++cmdline )
+ {
+ bool_t cur_sep = *cmdline == L' ' || *cmdline == L'\t';
+
+ if ( !prev_sep )
+ {
+ if ( cur_sep )
+ ++ptr;
+ else if ( argv )
+ {
+ *ptr = *cmdline;
+ *++ptr = 0;
+ }
+ }
+ else if ( !cur_sep )
+ {
+ if ( !argv )
+ ++argc;
+ else if ( prev && wstrcmp(prev, L"--") == 0 )
+ {
+ if ( options )
+ *options = cmdline;
+ break;
+ }
+ else
+ {
+ *argv++ = prev = ptr;
+ *ptr = *cmdline;
+ *++ptr = 0;
+ }
+ }
+ prev_sep = cur_sep;
+ }
+ if ( argv )
+ *argv = NULL;
+ return argc;
+}
+
+static EFI_FILE_HANDLE __init get_parent_handle(EFI_LOADED_IMAGE *loaded_image,
+ CHAR16 **leaf)
+{
+ static EFI_GUID __initdata fs_protocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
+ EFI_FILE_HANDLE dir_handle;
+ EFI_DEVICE_PATH *dp;
+ CHAR16 *pathend, *ptr;
+ EFI_STATUS ret;
+
+ do {
+ EFI_FILE_IO_INTERFACE *fio;
+
+ /* Get the file system interface. */
+ ret = efi_bs->HandleProtocol(loaded_image->DeviceHandle,
+ &fs_protocol, (void **)&fio);
+ if ( EFI_ERROR(ret) )
+ PrintErrMesg(L"Couldn't obtain the File System Protocol Interface",
+ ret);
+ ret = fio->OpenVolume(fio, &dir_handle);
+ } while ( ret == EFI_MEDIA_CHANGED );
+ if ( ret != EFI_SUCCESS )
+ PrintErrMesg(L"OpenVolume failure", ret);
+
+#define buffer ((CHAR16 *)keyhandler_scratch)
+#define BUFFERSIZE sizeof(keyhandler_scratch)
+ for ( dp = loaded_image->FilePath, *buffer = 0;
+ DevicePathType(dp) != END_DEVICE_PATH_TYPE;
+ dp = (void *)dp + DevicePathNodeLength(dp) )
+ {
+ FILEPATH_DEVICE_PATH *fp;
+
+ if ( DevicePathType(dp) != MEDIA_DEVICE_PATH ||
+ DevicePathSubType(dp) != MEDIA_FILEPATH_DP )
+ blexit(L"Unsupported device path component");
+
+ if ( *buffer )
+ {
+ EFI_FILE_HANDLE new_handle;
+
+ ret = dir_handle->Open(dir_handle, &new_handle, buffer,
+ EFI_FILE_MODE_READ, 0);
+ if ( ret != EFI_SUCCESS )
+ {
+ PrintErr(L"Open failed for ");
+ PrintErrMesg(buffer, ret);
+ }
+ dir_handle->Close(dir_handle);
+ dir_handle = new_handle;
+ }
+ fp = (void *)dp;
+ if ( BUFFERSIZE < DevicePathNodeLength(dp) -
+ sizeof(*dp) + sizeof(*buffer) )
+ blexit(L"Increase BUFFERSIZE");
+ memcpy(buffer, fp->PathName, DevicePathNodeLength(dp) - sizeof(*dp));
+ buffer[(DevicePathNodeLength(dp) - sizeof(*dp)) / sizeof(*buffer)] = 0;
+ }
+ for ( ptr = buffer, pathend = NULL; *ptr; ++ptr )
+ if ( *ptr == L'\\' )
+ pathend = ptr;
+ if ( pathend )
+ {
+ *pathend = 0;
+ *leaf = pathend + 1;
+ if ( *buffer )
+ {
+ EFI_FILE_HANDLE new_handle;
+
+ ret = dir_handle->Open(dir_handle, &new_handle, buffer,
+ EFI_FILE_MODE_READ, 0);
+ if ( ret != EFI_SUCCESS ) {
+ PrintErr(L"Open failed for ");
+ PrintErrMesg(buffer, ret);
+ }
+ dir_handle->Close(dir_handle);
+ dir_handle = new_handle;
+ }
+ }
+ else
+ *leaf = buffer;
+#undef BUFFERSIZE
+#undef buffer
+
+ return dir_handle;
+}
+
+static CHAR16 *__init point_tail(CHAR16 *fn)
+{
+ CHAR16 *tail = NULL;
+
+ for ( ; ; ++fn )
+ switch ( *fn )
+ {
+ case 0:
+ return tail;
+ case L'.':
+ case L'-':
+ case L'_':
+ tail = fn;
+ break;
+ }
+}
+/*
+ * Truncate string at first space, and return pointer
+ * to remainder of string, if any/ NULL returned if
+ * no remainder after space.
+ */
+static char * __init split_string(char *s)
+{
+ while ( *s && !isspace(*s) )
+ ++s;
+ if ( *s )
+ {
+ *s = 0;
+ return s + 1;
+ }
+ return NULL;
+}
+
+static bool_t __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
+ struct file *file, char *options)
+{
+ EFI_FILE_HANDLE FileHandle = NULL;
+ UINT64 size;
+ EFI_STATUS ret;
+ CHAR16 *what = NULL;
+
+ if ( !name )
+ PrintErrMesg(L"No filename", EFI_OUT_OF_RESOURCES);
+ ret = dir_handle->Open(dir_handle, &FileHandle, name,
+ EFI_FILE_MODE_READ, 0);
+ if ( file == &cfg && ret == EFI_NOT_FOUND )
+ return 0;
+ if ( EFI_ERROR(ret) )
+ what = L"Open";
+ else
+ ret = FileHandle->SetPosition(FileHandle, -1);
+ if ( EFI_ERROR(ret) )
+ what = what ?: L"Seek";
+ else
+ ret = FileHandle->GetPosition(FileHandle, &size);
+ if ( EFI_ERROR(ret) )
+ what = what ?: L"Get size";
+ else
+ ret = FileHandle->SetPosition(FileHandle, 0);
+ if ( EFI_ERROR(ret) )
+ what = what ?: L"Seek";
+ else
+ {
+ file->addr = min(1UL << (32 + PAGE_SHIFT),
+ HYPERVISOR_VIRT_END - DIRECTMAP_VIRT_START);
+ ret = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
+ PFN_UP(size), &file->addr);
+ }
+ if ( EFI_ERROR(ret) )
+ {
+ file->addr = 0;
+ what = what ?: L"Allocation";
+ }
+ else
+ {
+ file->size = size;
+ if ( file != &cfg )
+ {
+ PrintStr(name);
+ PrintStr(L": ");
+ DisplayUint(file->addr, 2 * sizeof(file->addr));
+ PrintStr(L"-");
+ DisplayUint(file->addr + size, 2 * sizeof(file->addr));
+ PrintStr(newline);
+ efi_arch_handle_module(file, name, options);
+ }
+
+ ret = FileHandle->Read(FileHandle, &file->size, file->ptr);
+ if ( !EFI_ERROR(ret) && file->size != size )
+ ret = EFI_ABORTED;
+ if ( EFI_ERROR(ret) )
+ what = L"Read";
+ }
+
+ if ( FileHandle )
+ FileHandle->Close(FileHandle);
+
+ if ( what )
+ {
+ PrintErr(what);
+ PrintErr(L" failed for ");
+ PrintErrMesg(name, ret);
+ }
+
+ return 1;
+}
+
+static void __init pre_parse(const struct file *cfg)
+{
+ char *ptr = cfg->ptr, *end = ptr + cfg->size;
+ bool_t start = 1, comment = 0;
+
+ for ( ; ptr < end; ++ptr )
+ {
+ if ( iscntrl(*ptr) )
+ {
+ comment = 0;
+ start = 1;
+ *ptr = 0;
+ }
+ else if ( comment || (start && isspace(*ptr)) )
+ *ptr = 0;
+ else if ( *ptr == '#' || (start && *ptr == ';') )
+ {
+ comment = 1;
+ *ptr = 0;
+ }
+ else
+ start = 0;
+ }
+ if ( cfg->size && end[-1] )
+ PrintStr(L"No newline at end of config file,"
+ " last line will be ignored.\r\n");
+}
+
+static char *__init get_value(const struct file *cfg, const char *section,
+ const char *item)
+{
+ char *ptr = cfg->ptr, *end = ptr + cfg->size;
+ size_t slen = section ? strlen(section) : 0, ilen = strlen(item);
+ bool_t match = !slen;
+
+ for ( ; ptr < end; ++ptr )
+ {
+ switch ( *ptr )
+ {
+ case 0:
+ continue;
+ case '[':
+ if ( !slen )
+ break;
+ if ( match )
+ return NULL;
+ match = strncmp(++ptr, section, slen) == 0 && ptr[slen] == ']';
+ break;
+ default:
+ if ( match && strncmp(ptr, item, ilen) == 0 && ptr[ilen] == '=' )
+ {
+ ptr += ilen + 1;
+ /* strip off any leading spaces */
+ while ( *ptr && isspace(*ptr) )
+ ptr++;
+ return ptr;
+ }
+ break;
+ }
+ ptr += strlen(ptr);
+ }
+ return NULL;
+}
+
+static void __init setup_efi_pci(void)
+{
+ EFI_STATUS status;
+ EFI_HANDLE *handles;
+ static EFI_GUID __initdata pci_guid = EFI_PCI_IO_PROTOCOL;
+ UINTN i, nr_pci, size = 0;
+ struct efi_pci_rom *last = NULL;
+
+ status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size, NULL);
+ if ( status != EFI_BUFFER_TOO_SMALL )
+ return;
+ status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
+ if ( EFI_ERROR(status) )
+ return;
+ status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size, handles);
+ if ( EFI_ERROR(status) )
+ size = 0;
+
+ nr_pci = size / sizeof(*handles);
+ for ( i = 0; i < nr_pci; ++i )
+ {
+ EFI_PCI_IO *pci = NULL;
+ u64 attributes;
+ struct efi_pci_rom *rom, *va;
+ UINTN segment, bus, device, function;
+
+ status = efi_bs->HandleProtocol(handles[i], &pci_guid, (void **)&pci);
+ if ( EFI_ERROR(status) || !pci || !pci->RomImage || !pci->RomSize )
+ continue;
+
+ status = pci->Attributes(pci, EfiPciIoAttributeOperationGet, 0,
+ &attributes);
+ if ( EFI_ERROR(status) ||
+ !(attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) ||
+ EFI_ERROR(pci->GetLocation(pci, &segment, &bus, &device,
+ &function)) )
+ continue;
+
+ DisplayUint(segment, 4);
+ PrintStr(L":");
+ DisplayUint(bus, 2);
+ PrintStr(L":");
+ DisplayUint(device, 2);
+ PrintStr(L".");
+ DisplayUint(function, 1);
+ PrintStr(L": ROM: ");
+ DisplayUint(pci->RomSize, 0);
+ PrintStr(L" bytes at ");
+ DisplayUint((UINTN)pci->RomImage, 0);
+ PrintStr(newline);
+
+ size = pci->RomSize + sizeof(*rom);
+ status = efi_bs->AllocatePool(EfiRuntimeServicesData, size,
+ (void **)&rom);
+ if ( EFI_ERROR(status) )
+ continue;
+
+ rom->next = NULL;
+ rom->size = pci->RomSize;
+
+ status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_VENDOR_ID, 1,
+ &rom->vendor);
+ if ( !EFI_ERROR(status) )
+ status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_DEVICE_ID, 1,
+ &rom->devid);
+ if ( EFI_ERROR(status) )
+ {
+ efi_bs->FreePool(rom);
+ continue;
+ }
+
+ rom->segment = segment;
+ rom->bus = bus;
+ rom->devfn = (device << 3) | function;
+ memcpy(rom->data, pci->RomImage, pci->RomSize);
+
+ va = (void *)rom + DIRECTMAP_VIRT_START;
+ if ( last )
+ last->next = va;
+ else
+ efi_pci_roms = va;
+ last = rom;
+ }
+
+ efi_bs->FreePool(handles);
+}
+
+static int __init __maybe_unused set_color(u32 mask, int bpp, u8 *pos, u8 *sz)
+{
+ if ( bpp < 0 )
+ return bpp;
+ if ( !mask )
+ return -EINVAL;
+ for ( *pos = 0; !(mask & 1); ++*pos )
+ mask >>= 1;
+ for ( *sz = 0; mask & 1; ++sz)
+ mask >>= 1;
+ if ( mask )
+ return -EINVAL;
+ return max(*pos + *sz, bpp);
+}
+
+void EFIAPI __init noreturn
+efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
+{
+ static EFI_GUID __initdata loaded_image_guid = LOADED_IMAGE_PROTOCOL;
+ static EFI_GUID __initdata gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+ static EFI_GUID __initdata shim_lock_guid = SHIM_LOCK_PROTOCOL_GUID;
+ EFI_LOADED_IMAGE *loaded_image;
+ EFI_STATUS status;
+ unsigned int i, argc;
+ CHAR16 **argv, *file_name, *cfg_file_name = NULL, *options = NULL;
+ UINTN map_key, info_size, gop_mode = ~0;
+ EFI_HANDLE *handles = NULL;
+ EFI_SHIM_LOCK_PROTOCOL *shim_lock;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
+ union string section = { NULL }, name;
+ bool_t base_video = 0, retry;
+ char *option_str;
+ bool_t use_cfg_file;
+
+ efi_ih = ImageHandle;
+ efi_bs = SystemTable->BootServices;
+ efi_rs = SystemTable->RuntimeServices;
+ efi_ct = SystemTable->ConfigurationTable;
+ efi_num_ct = SystemTable->NumberOfTableEntries;
+ efi_version = SystemTable->Hdr.Revision;
+ efi_fw_vendor = SystemTable->FirmwareVendor;
+ efi_fw_revision = SystemTable->FirmwareRevision;
+
+ StdOut = SystemTable->ConOut;
+ StdErr = SystemTable->StdErr ?: StdOut;
+ use_cfg_file = efi_arch_use_config_file(SystemTable);
+
+ status = efi_bs->HandleProtocol(ImageHandle, &loaded_image_guid,
+ (void **)&loaded_image);
+ if ( status != EFI_SUCCESS )
+ PrintErrMesg(L"No Loaded Image Protocol", status);
+
+ efi_arch_load_addr_check(loaded_image);
+
+ if ( use_cfg_file )
+ {
+ argc = get_argv(0, NULL, loaded_image->LoadOptions,
+ loaded_image->LoadOptionsSize, NULL);
+ if ( argc > 0 &&
+ efi_bs->AllocatePool(EfiLoaderData,
+ (argc + 1) * sizeof(*argv) +
+ loaded_image->LoadOptionsSize,
+ (void **)&argv) == EFI_SUCCESS )
+ get_argv(argc, argv, loaded_image->LoadOptions,
+ loaded_image->LoadOptionsSize, &options);
+ else
+ argc = 0;
+ for ( i = 1; i < argc; ++i )
+ {
+ CHAR16 *ptr = argv[i];
+
+ if ( !ptr )
+ break;
+ if ( *ptr == L'/' || *ptr == L'-' )
+ {
+ if ( wstrcmp(ptr + 1, L"basevideo") == 0 )
+ base_video = 1;
+ else if ( wstrncmp(ptr + 1, L"cfg=", 4) == 0 )
+ cfg_file_name = ptr + 5;
+ else if ( i + 1 < argc && wstrcmp(ptr + 1, L"cfg") == 0 )
+ cfg_file_name = argv[++i];
+ else if ( wstrcmp(ptr + 1, L"help") == 0 ||
+ (ptr[1] == L'?' && !ptr[2]) )
+ {
+ PrintStr(L"Xen EFI Loader options:\r\n");
+ PrintStr(L"-basevideo retain current video mode\r\n");
+ PrintStr(L"-cfg=<file> specify configuration file\r\n");
+ PrintStr(L"-help, -? display this help\r\n");
+ blexit(NULL);
+ }
+ else
+ {
+ PrintStr(L"WARNING: Unknown command line option '");
+ PrintStr(ptr);
+ PrintStr(L"' ignored\r\n");
+ }
+ }
+ else
+ section.w = ptr;
+ }
+
+ if ( !base_video )
+ {
+ unsigned int best;
+ UINTN cols, rows, size;
+
+ for ( i = 0, size = 0, best = StdOut->Mode->Mode;
+ i < StdOut->Mode->MaxMode; ++i )
+ {
+ if ( StdOut->QueryMode(StdOut, i, &cols, &rows) == EFI_SUCCESS &&
+ cols * rows > size )
+ {
+ size = cols * rows;
+ best = i;
+ }
+ }
+ if ( best != StdOut->Mode->Mode )
+ StdOut->SetMode(StdOut, best);
+ }
+ }
+
+ PrintStr(L"Xen " __stringify(XEN_VERSION) "." __stringify(XEN_SUBVERSION)
+ XEN_EXTRAVERSION " (c/s " XEN_CHANGESET ") EFI loader\r\n");
+
+ efi_arch_relocate_image(0);
+
+ if ( use_cfg_file )
+ {
+ EFI_FILE_HANDLE dir_handle;
+ UINTN depth, cols, rows, size;
+
+ size = cols = rows = depth = 0;
+
+ if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
+ &cols, &rows) == EFI_SUCCESS )
+ efi_arch_console_init(cols, rows);
+
+ status = efi_bs->LocateHandle(ByProtocol, &gop_guid, NULL, &size, NULL);
+ if ( status == EFI_BUFFER_TOO_SMALL )
+ status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
+ if ( !EFI_ERROR(status) )
+ status = efi_bs->LocateHandle(ByProtocol, &gop_guid, NULL, &size,
+ handles);
+ if ( EFI_ERROR(status) )
+ size = 0;
+ for ( i = 0; i < size / sizeof(*handles); ++i )
+ {
+ status = efi_bs->HandleProtocol(handles[i], &gop_guid, (void **)&gop);
+ if ( EFI_ERROR(status) )
+ continue;
+ status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info);
+ if ( !EFI_ERROR(status) )
+ break;
+ }
+ if ( handles )
+ efi_bs->FreePool(handles);
+ if ( EFI_ERROR(status) )
+ gop = NULL;
+
+ /* Get the file system interface. */
+ dir_handle = get_parent_handle(loaded_image, &file_name);
+
+ /* Read and parse the config file. */
+ if ( !cfg_file_name )
+ {
+ CHAR16 *tail;
+
+ while ( (tail = point_tail(file_name)) != NULL )
+ {
+ wstrcpy(tail, L".cfg");
+ if ( read_file(dir_handle, file_name, &cfg, NULL) )
+ break;
+ *tail = 0;
+ }
+ if ( !tail )
+ blexit(L"No configuration file found.");
+ PrintStr(L"Using configuration file '");
+ PrintStr(file_name);
+ PrintStr(L"'\r\n");
+ }
+ else if ( !read_file(dir_handle, cfg_file_name, &cfg, NULL) )
+ blexit(L"Configuration file not found.");
+ pre_parse(&cfg);
+
+ if ( section.w )
+ w2s(§ion);
+ else
+ section.s = get_value(&cfg, "global", "default");
+
+ for ( ; ; )
+ {
+ name.s = get_value(&cfg, section.s, "kernel");
+ if ( name.s )
+ break;
+ name.s = get_value(&cfg, "global", "chain");
+ if ( !name.s )
+ break;
+ efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
+ cfg.addr = 0;
+ if ( !read_file(dir_handle, s2w(&name), &cfg, NULL) )
+ {
+ PrintStr(L"Chained configuration file '");
+ PrintStr(name.w);
+ efi_bs->FreePool(name.w);
+ blexit(L"'not found.");
+ }
+ pre_parse(&cfg);
+ efi_bs->FreePool(name.w);
+ }
+
+ if ( !name.s )
+ blexit(L"No Dom0 kernel image specified.");
+
+ efi_arch_cfg_file_early(dir_handle, section.s);
+
+ option_str = split_string(name.s);
+ read_file(dir_handle, s2w(&name), &kernel, option_str);
+ efi_bs->FreePool(name.w);
+
+ if ( !EFI_ERROR(efi_bs->LocateProtocol(&shim_lock_guid, NULL,
+ (void **)&shim_lock)) &&
+ (status = shim_lock->Verify(kernel.ptr, kernel.size)) != EFI_SUCCESS )
+ PrintErrMesg(L"Dom0 kernel image could not be verified", status);
+
+ name.s = get_value(&cfg, section.s, "ramdisk");
+ if ( name.s )
+ {
+ read_file(dir_handle, s2w(&name), &ramdisk, NULL);
+ efi_bs->FreePool(name.w);
+ }
+
+ name.s = get_value(&cfg, section.s, "xsm");
+ if ( name.s )
+ {
+ read_file(dir_handle, s2w(&name), &xsm, NULL);
+ efi_bs->FreePool(name.w);
+ }
+
+ name.s = get_value(&cfg, section.s, "options");
+ efi_arch_handle_cmdline(argc ? *argv : NULL, options, name.s);
+
+ if ( !base_video )
+ {
+ name.cs = get_value(&cfg, section.s, "video");
+ if ( !name.cs )
+ name.cs = get_value(&cfg, "global", "video");
+ if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
+ {
+ cols = simple_strtoul(name.cs + 4, &name.cs, 10);
+ if ( *name.cs == 'x' )
+ rows = simple_strtoul(name.cs + 1, &name.cs, 10);
+ if ( *name.cs == 'x' )
+ depth = simple_strtoul(name.cs + 1, &name.cs, 10);
+ if ( *name.cs )
+ cols = rows = depth = 0;
+ }
+ }
+
+ efi_arch_cfg_file_late(dir_handle, section.s);
+
+ efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
+ cfg.addr = 0;
+
+ dir_handle->Close(dir_handle);
+
+ if ( gop && !base_video )
+ {
+ for ( i = size = 0; i < gop->Mode->MaxMode; ++i )
+ {
+ unsigned int bpp = 0;
+
+ status = gop->QueryMode(gop, i, &info_size, &mode_info);
+ if ( EFI_ERROR(status) )
+ continue;
+ switch ( mode_info->PixelFormat )
+ {
+ case PixelBitMask:
+ bpp = hweight32(mode_info->PixelInformation.RedMask |
+ mode_info->PixelInformation.GreenMask |
+ mode_info->PixelInformation.BlueMask);
+ break;
+ case PixelRedGreenBlueReserved8BitPerColor:
+ case PixelBlueGreenRedReserved8BitPerColor:
+ bpp = 24;
+ break;
+ default:
+ continue;
+ }
+ if ( cols == mode_info->HorizontalResolution &&
+ rows == mode_info->VerticalResolution &&
+ (!depth || bpp == depth) )
+ {
+ gop_mode = i;
+ break;
+ }
+ if ( !cols && !rows &&
+ mode_info->HorizontalResolution *
+ mode_info->VerticalResolution > size )
+ {
+ size = mode_info->HorizontalResolution *
+ mode_info->VerticalResolution;
+ gop_mode = i;
+ }
+ }
+ }
+ }
+
+ efi_arch_edd();
+
+ /* XXX Collect EDID info. */
+ efi_arch_cpu();
+
+ /* Obtain basic table pointers. */
+ for ( i = 0; i < efi_num_ct; ++i )
+ {
+ static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID;
+ static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID;
+ static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID;
+ static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID;
+
+ if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) )
+ efi.acpi20 = (long)efi_ct[i].VendorTable;
+ if ( match_guid(&acpi_guid, &efi_ct[i].VendorGuid) )
+ efi.acpi = (long)efi_ct[i].VendorTable;
+ if ( match_guid(&mps_guid, &efi_ct[i].VendorGuid) )
+ efi.mps = (long)efi_ct[i].VendorTable;
+ if ( match_guid(&smbios_guid, &efi_ct[i].VendorGuid) )
+ efi.smbios = (long)efi_ct[i].VendorTable;
+ }
+
+#ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
+ if (efi.smbios != EFI_INVALID_TABLE_ADDR)
+ dmi_efi_get_table((void *)(long)efi.smbios);
+#endif
+
+ /* Collect PCI ROM contents. */
+ setup_efi_pci();
+
+ /* Get snapshot of variable store parameters. */
+ status = (efi_rs->Hdr.Revision >> 16) >= 2 ?
+ efi_rs->QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ &efi_boot_max_var_store_size,
+ &efi_boot_remain_var_store_size,
+ &efi_boot_max_var_size) :
+ EFI_INCOMPATIBLE_VERSION;
+ if ( EFI_ERROR(status) )
+ {
+ efi_boot_max_var_store_size = 0;
+ efi_boot_remain_var_store_size = 0;
+ efi_boot_max_var_size = status;
+ PrintStr(L"Warning: Could not query variable store: ");
+ DisplayUint(status, 0);
+ PrintStr(newline);
+ }
+
+ efi_arch_memory_setup();
+
+ if ( gop )
+ {
+
+ /* Set graphics mode. */
+ if ( gop_mode < gop->Mode->MaxMode && gop_mode != gop->Mode->Mode )
+ gop->SetMode(gop, gop_mode);
+
+ /* Get graphics and frame buffer info. */
+ status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info);
+ if ( !EFI_ERROR(status) )
+ efi_arch_video_init(gop, info_size, mode_info);
+ }
+
+ efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key,
+ &efi_mdesc_size, &mdesc_ver);
+ efi_memmap = efi_arch_allocate_mmap_buffer(&efi_memmap_size);
+ if ( !efi_memmap )
+ blexit(L"Unable to allocate memory for EFI memory map");
+
+ for ( retry = 0; ; retry = 1 )
+ {
+ status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key,
+ &efi_mdesc_size, &mdesc_ver);
+ if ( EFI_ERROR(status) )
+ PrintErrMesg(L"Cannot obtain memory map", status);
+
+ efi_arch_process_memory_map(SystemTable, efi_memmap, efi_memmap_size,
+ efi_mdesc_size, mdesc_ver);
+
+ efi_arch_pre_exit_boot();
+
+ status = efi_bs->ExitBootServices(ImageHandle, map_key);
+ if ( status != EFI_INVALID_PARAMETER || retry )
+ break;
+ }
+
+ if ( EFI_ERROR(status) )
+ PrintErrMesg(L"Cannot exit boot services", status);
+
+ /* Adjust pointers into EFI. */
+ efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
+#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
+ efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START;
+#endif
+ efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
+ efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
+
+ efi_arch_post_exit_boot();
+ for( ; ; ); /* not reached */
+}
+
+#ifndef CONFIG_ARM /* TODO - runtime service support */
+
+static bool_t __initdata efi_rs_enable = 1;
+boolean_param("efi-rs", efi_rs_enable);
+
+#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
+static __init void copy_mapping(unsigned long mfn, unsigned long end,
+ bool_t (*is_valid)(unsigned long smfn,
+ unsigned long emfn))
+{
+ unsigned long next;
+
+ for ( ; mfn < end; mfn = next )
+ {
+ l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)];
+ l3_pgentry_t *l3src, *l3dst;
+ unsigned long va = (unsigned long)mfn_to_virt(mfn);
+
+ next = mfn + (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT));
+ if ( !is_valid(mfn, min(next, end)) )
+ continue;
+ if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
+ {
+ l3dst = alloc_xen_pagetable();
+ BUG_ON(!l3dst);
+ clear_page(l3dst);
+ efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)] =
+ l4e_from_paddr(virt_to_maddr(l3dst), __PAGE_HYPERVISOR);
+ }
+ else
+ l3dst = l4e_to_l3e(l4e);
+ l3src = l4e_to_l3e(idle_pg_table[l4_table_offset(va)]);
+ l3dst[l3_table_offset(mfn << PAGE_SHIFT)] = l3src[l3_table_offset(va)];
+ }
+}
+
+static bool_t __init ram_range_valid(unsigned long smfn, unsigned long emfn)
+{
+ unsigned long sz = pfn_to_pdx(emfn - 1) / PDX_GROUP_COUNT + 1;
+
+ return !(smfn & pfn_hole_mask) &&
+ find_next_bit(pdx_group_valid, sz,
+ pfn_to_pdx(smfn) / PDX_GROUP_COUNT) < sz;
+}
+
+static bool_t __init rt_range_valid(unsigned long smfn, unsigned long emfn)
+{
+ return 1;
+}
+#endif
+
+#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \
+ (EFI_PAGE_SHIFT + BITS_PER_LONG - 32))
+
+void __init efi_init_memory(void)
+{
+ unsigned int i;
+#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
+ struct rt_extra {
+ struct rt_extra *next;
+ unsigned long smfn, emfn;
+ unsigned int prot;
+ } *extra, *extra_head = NULL;
+#endif
+
+ printk(XENLOG_INFO "EFI memory map:\n");
+ for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
+ {
+ EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
+ u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
+ unsigned long smfn, emfn;
+ unsigned int prot = PAGE_HYPERVISOR;
+
+ printk(XENLOG_INFO " %013" PRIx64 "-%013" PRIx64
+ " type=%u attr=%016" PRIx64 "\n",
+ desc->PhysicalStart, desc->PhysicalStart + len - 1,
+ desc->Type, desc->Attribute);
+
+ if ( !efi_rs_enable || !(desc->Attribute & EFI_MEMORY_RUNTIME) )
+ continue;
+
+ desc->VirtualStart = INVALID_VIRTUAL_ADDRESS;
+
+ smfn = PFN_DOWN(desc->PhysicalStart);
+ emfn = PFN_UP(desc->PhysicalStart + len);
+
+ if ( desc->Attribute & EFI_MEMORY_WB )
+ /* nothing */;
+ else if ( desc->Attribute & EFI_MEMORY_WT )
+ prot |= _PAGE_PWT | MAP_SMALL_PAGES;
+ else if ( desc->Attribute & EFI_MEMORY_WC )
+ prot |= _PAGE_PAT | MAP_SMALL_PAGES;
+ else if ( desc->Attribute & (EFI_MEMORY_UC | EFI_MEMORY_UCE) )
+ prot |= _PAGE_PWT | _PAGE_PCD | MAP_SMALL_PAGES;
+ else
+ {
+ printk(XENLOG_ERR "Unknown cachability for MFNs %#lx-%#lx\n",
+ smfn, emfn - 1);
+ continue;
+ }
+
+ if ( desc->Attribute & EFI_MEMORY_WP )
+ prot &= _PAGE_RW;
+ if ( desc->Attribute & EFI_MEMORY_XP )
+ prot |= _PAGE_NX_BIT;
+
+ if ( pfn_to_pdx(emfn - 1) < (DIRECTMAP_SIZE >> PAGE_SHIFT) &&
+ !(smfn & pfn_hole_mask) &&
+ !((smfn ^ (emfn - 1)) & ~pfn_pdx_bottom_mask) )
+ {
+ if ( (unsigned long)mfn_to_virt(emfn - 1) >= HYPERVISOR_VIRT_END )
+ prot &= ~_PAGE_GLOBAL;
+ if ( map_pages_to_xen((unsigned long)mfn_to_virt(smfn),
+ smfn, emfn - smfn, prot) == 0 )
+ desc->VirtualStart =
+ (unsigned long)maddr_to_virt(desc->PhysicalStart);
+ else
+ printk(XENLOG_ERR "Could not map MFNs %#lx-%#lx\n",
+ smfn, emfn - 1);
+ }
+#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
+ else if ( !((desc->PhysicalStart + len - 1) >> (VADDR_BITS - 1)) &&
+ (extra = xmalloc(struct rt_extra)) != NULL )
+ {
+ extra->smfn = smfn;
+ extra->emfn = emfn;
+ extra->prot = prot & ~_PAGE_GLOBAL;
+ extra->next = extra_head;
+ extra_head = extra;
+ desc->VirtualStart = desc->PhysicalStart;
+ }
+#endif
+ else
+ {
+#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
+ /* XXX allocate e.g. down from FIXADDR_START */
+#endif
+ printk(XENLOG_ERR "No mapping for MFNs %#lx-%#lx\n",
+ smfn, emfn - 1);
+ }
+ }
+
+ if ( !efi_rs_enable )
+ {
+ efi_fw_vendor = NULL;
+ return;
+ }
+
+#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
+ efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size,
+ mdesc_ver, efi_memmap);
+#else
+ /* Set up 1:1 page tables to do runtime calls in "physical" mode. */
+ efi_l4_pgtable = alloc_xen_pagetable();
+ BUG_ON(!efi_l4_pgtable);
+ clear_page(efi_l4_pgtable);
+
+ copy_mapping(0, max_page, ram_range_valid);
+
+ /* Insert non-RAM runtime mappings inside the direct map. */
+ for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
+ {
+ const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
+
+ if ( (desc->Attribute & EFI_MEMORY_RUNTIME) &&
+ desc->VirtualStart != INVALID_VIRTUAL_ADDRESS &&
+ desc->VirtualStart != desc->PhysicalStart )
+ copy_mapping(PFN_DOWN(desc->PhysicalStart),
+ PFN_UP(desc->PhysicalStart +
+ (desc->NumberOfPages << EFI_PAGE_SHIFT)),
+ rt_range_valid);
+ }
+
+ /* Insert non-RAM runtime mappings outside of the direct map. */
+ while ( (extra = extra_head) != NULL )
+ {
+ unsigned long addr = extra->smfn << PAGE_SHIFT;
+ l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(addr)];
+ l3_pgentry_t *pl3e;
+ l2_pgentry_t *pl2e;
+ l1_pgentry_t *l1t;
+
+ if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
+ {
+ pl3e = alloc_xen_pagetable();
+ BUG_ON(!pl3e);
+ clear_page(pl3e);
+ efi_l4_pgtable[l4_table_offset(addr)] =
+ l4e_from_paddr(virt_to_maddr(pl3e), __PAGE_HYPERVISOR);
+ }
+ else
+ pl3e = l4e_to_l3e(l4e);
+ pl3e += l3_table_offset(addr);
+ if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
+ {
+ pl2e = alloc_xen_pagetable();
+ BUG_ON(!pl2e);
+ clear_page(pl2e);
+ *pl3e = l3e_from_paddr(virt_to_maddr(pl2e), __PAGE_HYPERVISOR);
+ }
+ else
+ {
+ BUG_ON(l3e_get_flags(*pl3e) & _PAGE_PSE);
+ pl2e = l3e_to_l2e(*pl3e);
+ }
+ pl2e += l2_table_offset(addr);
+ if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
+ {
+ l1t = alloc_xen_pagetable();
+ BUG_ON(!l1t);
+ clear_page(l1t);
+ *pl2e = l2e_from_paddr(virt_to_maddr(l1t), __PAGE_HYPERVISOR);
+ }
+ else
+ {
+ BUG_ON(l2e_get_flags(*pl2e) & _PAGE_PSE);
+ l1t = l2e_to_l1e(*pl2e);
+ }
+ for ( i = l1_table_offset(addr);
+ i < L1_PAGETABLE_ENTRIES && extra->smfn < extra->emfn;
+ ++i, ++extra->smfn )
+ l1t[i] = l1e_from_pfn(extra->smfn, extra->prot);
+
+ if ( extra->smfn == extra->emfn )
+ {
+ extra_head = extra->next;
+ xfree(extra);
+ }
+ }
+
+ /* Insert Xen mappings. */
+ for ( i = l4_table_offset(HYPERVISOR_VIRT_START);
+ i < l4_table_offset(DIRECTMAP_VIRT_END); ++i )
+ efi_l4_pgtable[i] = idle_pg_table[i];
+#endif
+}
+#endif
diff --git a/xen/arch/x86/efi/compat.c b/xen/common/efi/compat.c
similarity index 100%
rename from xen/arch/x86/efi/compat.c
rename to xen/common/efi/compat.c
diff --git a/xen/common/efi/efi.h b/xen/common/efi/efi.h
new file mode 100644
index 0000000..c557104
--- /dev/null
+++ b/xen/common/efi/efi.h
@@ -0,0 +1,41 @@
+#include <asm/efibind.h>
+#include <efi/efidef.h>
+#include <efi/efierr.h>
+#include <efi/eficon.h>
+#include <efi/efidevp.h>
+#include <efi/eficapsule.h>
+#include <efi/efiapi.h>
+#include <xen/efi.h>
+#include <xen/spinlock.h>
+#include <asm/page.h>
+
+struct efi_pci_rom {
+ const struct efi_pci_rom *next;
+ u16 vendor, devid, segment;
+ u8 bus, devfn;
+ unsigned long size;
+ unsigned char data[];
+};
+
+extern unsigned int efi_num_ct;
+extern const EFI_CONFIGURATION_TABLE *efi_ct;
+
+extern unsigned int efi_version, efi_fw_revision;
+extern const CHAR16 *efi_fw_vendor;
+
+extern const EFI_RUNTIME_SERVICES *efi_rs;
+
+extern UINTN efi_memmap_size, efi_mdesc_size;
+extern void *efi_memmap;
+
+#ifdef CONFIG_X86
+extern l4_pgentry_t *efi_l4_pgtable;
+#endif
+
+extern const struct efi_pci_rom *efi_pci_roms;
+
+extern UINT64 efi_boot_max_var_store_size, efi_boot_remain_var_store_size,
+ efi_boot_max_var_size;
+
+unsigned long efi_rs_enter(void);
+void efi_rs_leave(unsigned long);
diff --git a/xen/common/efi/runtime.c b/xen/common/efi/runtime.c
new file mode 100644
index 0000000..c840e08
--- /dev/null
+++ b/xen/common/efi/runtime.c
@@ -0,0 +1,600 @@
+#include "efi.h"
+#include "runtime.h"
+#include <xen/cache.h>
+#include <xen/errno.h>
+#include <xen/guest_access.h>
+#include <xen/irq.h>
+#include <xen/time.h>
+
+DEFINE_XEN_GUEST_HANDLE(CHAR16);
+
+#ifndef COMPAT
+
+#ifdef CONFIG_ARM /* Disabled until runtime services implemented */
+const bool_t efi_enabled = 0;
+#else
+# include <asm/i387.h>
+# include <asm/xstate.h>
+# include <public/platform.h>
+
+const bool_t efi_enabled = 1;
+#endif
+
+unsigned int __read_mostly efi_num_ct;
+const EFI_CONFIGURATION_TABLE *__read_mostly efi_ct;
+
+unsigned int __read_mostly efi_version;
+unsigned int __read_mostly efi_fw_revision;
+const CHAR16 *__read_mostly efi_fw_vendor;
+
+const EFI_RUNTIME_SERVICES *__read_mostly efi_rs;
+#ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
+static DEFINE_SPINLOCK(efi_rs_lock);
+#endif
+
+UINTN __read_mostly efi_memmap_size;
+UINTN __read_mostly efi_mdesc_size;
+void *__read_mostly efi_memmap;
+
+UINT64 __read_mostly efi_boot_max_var_store_size;
+UINT64 __read_mostly efi_boot_remain_var_store_size;
+UINT64 __read_mostly efi_boot_max_var_size;
+
+struct efi __read_mostly efi = {
+ .acpi = EFI_INVALID_TABLE_ADDR,
+ .acpi20 = EFI_INVALID_TABLE_ADDR,
+ .mps = EFI_INVALID_TABLE_ADDR,
+ .smbios = EFI_INVALID_TABLE_ADDR,
+};
+
+const struct efi_pci_rom *__read_mostly efi_pci_roms;
+
+#ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
+unsigned long efi_rs_enter(void)
+{
+ static const u16 fcw = FCW_DEFAULT;
+ static const u32 mxcsr = MXCSR_DEFAULT;
+ unsigned long cr3 = read_cr3();
+
+ if ( !efi_l4_pgtable )
+ return 0;
+
+ save_fpu_enable();
+ asm volatile ( "fldcw %0" :: "m" (fcw) );
+ asm volatile ( "ldmxcsr %0" :: "m" (mxcsr) );
+
+ spin_lock(&efi_rs_lock);
+
+ /* prevent fixup_page_fault() from doing anything */
+ irq_enter();
+
+ if ( is_pv_vcpu(current) && !is_idle_vcpu(current) )
+ {
+ struct desc_ptr gdt_desc = {
+ .limit = LAST_RESERVED_GDT_BYTE,
+ .base = (unsigned long)(per_cpu(gdt_table, smp_processor_id()) -
+ FIRST_RESERVED_GDT_ENTRY)
+ };
+
+ asm volatile ( "lgdt %0" : : "m" (gdt_desc) );
+ }
+
+ write_cr3(virt_to_maddr(efi_l4_pgtable));
+
+ return cr3;
+}
+
+void efi_rs_leave(unsigned long cr3)
+{
+ if ( !cr3 )
+ return;
+ write_cr3(cr3);
+ if ( is_pv_vcpu(current) && !is_idle_vcpu(current) )
+ {
+ struct desc_ptr gdt_desc = {
+ .limit = LAST_RESERVED_GDT_BYTE,
+ .base = GDT_VIRT_START(current)
+ };
+
+ asm volatile ( "lgdt %0" : : "m" (gdt_desc) );
+ }
+ irq_exit();
+ spin_unlock(&efi_rs_lock);
+ stts();
+}
+
+paddr_t efi_rs_page_table(void)
+{
+ return efi_l4_pgtable ? virt_to_maddr(efi_l4_pgtable) : 0;
+}
+
+unsigned long efi_get_time(void)
+{
+ EFI_TIME time;
+ EFI_STATUS status;
+ unsigned long cr3 = efi_rs_enter(), flags;
+
+ if ( !cr3 )
+ return 0;
+ spin_lock_irqsave(&rtc_lock, flags);
+ status = efi_rs->GetTime(&time, NULL);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ efi_rs_leave(cr3);
+
+ if ( EFI_ERROR(status) )
+ return 0;
+
+ return mktime(time.Year, time.Month, time.Day,
+ time.Hour, time.Minute, time.Second);
+}
+
+void efi_halt_system(void)
+{
+ EFI_STATUS status;
+ unsigned long cr3 = efi_rs_enter();
+
+ if ( !cr3 )
+ return;
+ status = efi_rs->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
+ efi_rs_leave(cr3);
+
+ printk(XENLOG_WARNING "EFI: could not halt system (%#lx)\n", status);
+}
+
+void efi_reset_system(bool_t warm)
+{
+ EFI_STATUS status;
+ unsigned long cr3 = efi_rs_enter();
+
+ if ( !cr3 )
+ return;
+ status = efi_rs->ResetSystem(warm ? EfiResetWarm : EfiResetCold,
+ EFI_SUCCESS, 0, NULL);
+ efi_rs_leave(cr3);
+
+ printk(XENLOG_WARNING "EFI: could not reset system (%#lx)\n", status);
+}
+
+#endif /* CONFIG_ARM */
+#endif
+
+#ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
+int efi_get_info(uint32_t idx, union xenpf_efi_info *info)
+{
+ unsigned int i, n;
+
+ switch ( idx )
+ {
+ case XEN_FW_EFI_VERSION:
+ info->version = efi_version;
+ break;
+ case XEN_FW_EFI_RT_VERSION:
+ {
+ unsigned long cr3 = efi_rs_enter();
+
+ if ( !cr3 )
+ return -EOPNOTSUPP;
+ info->version = efi_rs->Hdr.Revision;
+ efi_rs_leave(cr3);
+ break;
+ }
+ case XEN_FW_EFI_CONFIG_TABLE:
+ info->cfg.addr = __pa(efi_ct);
+ info->cfg.nent = efi_num_ct;
+ break;
+ case XEN_FW_EFI_VENDOR:
+ if ( !efi_fw_vendor )
+ return -EOPNOTSUPP;
+ info->vendor.revision = efi_fw_revision;
+ n = info->vendor.bufsz / sizeof(*efi_fw_vendor);
+ if ( !guest_handle_okay(guest_handle_cast(info->vendor.name,
+ CHAR16), n) )
+ return -EFAULT;
+ for ( i = 0; i < n; ++i )
+ {
+ if ( __copy_to_guest_offset(info->vendor.name, i,
+ efi_fw_vendor + i, 1) )
+ return -EFAULT;
+ if ( !efi_fw_vendor[i] )
+ break;
+ }
+ break;
+ case XEN_FW_EFI_MEM_INFO:
+ for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
+ {
+ EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
+ u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
+
+ if ( info->mem.addr >= desc->PhysicalStart &&
+ info->mem.addr < desc->PhysicalStart + len )
+ {
+ info->mem.type = desc->Type;
+ info->mem.attr = desc->Attribute;
+ if ( info->mem.addr + info->mem.size < info->mem.addr ||
+ info->mem.addr + info->mem.size >
+ desc->PhysicalStart + len )
+ info->mem.size = desc->PhysicalStart + len -
+ info->mem.addr;
+ return 0;
+ }
+ }
+ return -ESRCH;
+ case XEN_FW_EFI_PCI_ROM: {
+ const struct efi_pci_rom *ent;
+
+ for ( ent = efi_pci_roms; ent; ent = ent->next )
+ if ( info->pci_rom.segment == ent->segment &&
+ info->pci_rom.bus == ent->bus &&
+ info->pci_rom.devfn == ent->devfn &&
+ info->pci_rom.vendor == ent->vendor &&
+ info->pci_rom.devid == ent->devid )
+ {
+ info->pci_rom.address = __pa(ent->data);
+ info->pci_rom.size = ent->size;
+ return 0;
+ }
+ return -ESRCH;
+ }
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static long gwstrlen(XEN_GUEST_HANDLE_PARAM(CHAR16) str)
+{
+ unsigned long len;
+
+ for ( len = 0; ; ++len )
+ {
+ CHAR16 c;
+
+ if ( copy_from_guest_offset(&c, str, len, 1) )
+ return -EFAULT;
+ if ( !c )
+ break;
+ }
+
+ return len;
+}
+
+static inline EFI_TIME *cast_time(struct xenpf_efi_time *time)
+{
+#define chk_fld(F, f) \
+ BUILD_BUG_ON(sizeof(cast_time(NULL)->F) != sizeof(time->f) || \
+ offsetof(EFI_TIME, F) != offsetof(struct xenpf_efi_time, f))
+ chk_fld(Year, year);
+ chk_fld(Month, month);
+ chk_fld(Day, day);
+ chk_fld(Hour, hour);
+ chk_fld(Minute, min);
+ chk_fld(Second, sec);
+ chk_fld(Nanosecond, ns);
+ chk_fld(TimeZone, tz);
+ chk_fld(Daylight, daylight);
+#undef chk_fld
+ return (void *)time;
+}
+
+static inline EFI_GUID *cast_guid(struct xenpf_efi_guid *guid)
+{
+#define chk_fld(n) \
+ BUILD_BUG_ON(sizeof(cast_guid(NULL)->Data##n) != sizeof(guid->data##n) || \
+ offsetof(EFI_GUID, Data##n) != \
+ offsetof(struct xenpf_efi_guid, data##n))
+ chk_fld(1);
+ chk_fld(2);
+ chk_fld(3);
+ chk_fld(4);
+#undef chk_fld
+ return (void *)guid;
+}
+
+int efi_runtime_call(struct xenpf_efi_runtime_call *op)
+{
+ unsigned long cr3, flags;
+ EFI_STATUS status = EFI_NOT_STARTED;
+ int rc = 0;
+
+ switch ( op->function )
+ {
+ case XEN_EFI_get_time:
+ {
+ EFI_TIME_CAPABILITIES caps;
+
+ if ( op->misc )
+ return -EINVAL;
+
+ cr3 = efi_rs_enter();
+ if ( !cr3 )
+ return -EOPNOTSUPP;
+ spin_lock_irqsave(&rtc_lock, flags);
+ status = efi_rs->GetTime(cast_time(&op->u.get_time.time), &caps);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ efi_rs_leave(cr3);
+
+ if ( !EFI_ERROR(status) )
+ {
+ op->u.get_time.resolution = caps.Resolution;
+ op->u.get_time.accuracy = caps.Accuracy;
+ if ( caps.SetsToZero )
+ op->misc = XEN_EFI_GET_TIME_SET_CLEARS_NS;
+ }
+ }
+ break;
+
+ case XEN_EFI_set_time:
+ if ( op->misc )
+ return -EINVAL;
+
+ cr3 = efi_rs_enter();
+ if ( !cr3 )
+ return -EOPNOTSUPP;
+ spin_lock_irqsave(&rtc_lock, flags);
+ status = efi_rs->SetTime(cast_time(&op->u.set_time));
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ efi_rs_leave(cr3);
+ break;
+
+ case XEN_EFI_get_wakeup_time:
+ {
+ BOOLEAN enabled, pending;
+
+ if ( op->misc )
+ return -EINVAL;
+
+ cr3 = efi_rs_enter();
+ if ( !cr3 )
+ return -EOPNOTSUPP;
+ spin_lock_irqsave(&rtc_lock, flags);
+ status = efi_rs->GetWakeupTime(&enabled, &pending,
+ cast_time(&op->u.get_wakeup_time));
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ efi_rs_leave(cr3);
+
+ if ( !EFI_ERROR(status) )
+ {
+ if ( enabled )
+ op->misc |= XEN_EFI_GET_WAKEUP_TIME_ENABLED;
+ if ( pending )
+ op->misc |= XEN_EFI_GET_WAKEUP_TIME_PENDING;
+ }
+ }
+ break;
+
+ case XEN_EFI_set_wakeup_time:
+ if ( op->misc & ~(XEN_EFI_SET_WAKEUP_TIME_ENABLE |
+ XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY) )
+ return -EINVAL;
+
+ cr3 = efi_rs_enter();
+ if ( !cr3 )
+ return -EOPNOTSUPP;
+ spin_lock_irqsave(&rtc_lock, flags);
+ status = efi_rs->SetWakeupTime(!!(op->misc &
+ XEN_EFI_SET_WAKEUP_TIME_ENABLE),
+ (op->misc &
+ XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY) ?
+ NULL :
+ cast_time(&op->u.set_wakeup_time));
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ efi_rs_leave(cr3);
+
+ op->misc = 0;
+ break;
+
+ case XEN_EFI_get_next_high_monotonic_count:
+ if ( op->misc )
+ return -EINVAL;
+
+ cr3 = efi_rs_enter();
+ if ( cr3 )
+ status = efi_rs->GetNextHighMonotonicCount(&op->misc);
+ else
+ rc = -EOPNOTSUPP;
+ efi_rs_leave(cr3);
+ break;
+
+ case XEN_EFI_get_variable:
+ {
+ CHAR16 *name;
+ long len;
+ unsigned char *data;
+ UINTN size;
+
+ if ( op->misc )
+ return -EINVAL;
+
+ len = gwstrlen(guest_handle_cast(op->u.get_variable.name, CHAR16));
+ if ( len < 0 )
+ return len;
+ name = xmalloc_array(CHAR16, ++len);
+ if ( !name )
+ return -ENOMEM;
+ __copy_from_guest(name, op->u.get_variable.name, len);
+
+ size = op->u.get_variable.size;
+ if ( size )
+ {
+ data = xmalloc_bytes(size);
+ if ( !data )
+ {
+ xfree(name);
+ return -ENOMEM;
+ }
+ }
+ else
+ data = NULL;
+
+ cr3 = efi_rs_enter();
+ if ( cr3 )
+ {
+ status = efi_rs->GetVariable(
+ name, cast_guid(&op->u.get_variable.vendor_guid),
+ &op->misc, &size, data);
+ efi_rs_leave(cr3);
+
+ if ( !EFI_ERROR(status) &&
+ copy_to_guest(op->u.get_variable.data, data, size) )
+ rc = -EFAULT;
+ op->u.get_variable.size = size;
+ }
+ else
+ rc = -EOPNOTSUPP;
+
+ xfree(data);
+ xfree(name);
+ }
+ break;
+
+ case XEN_EFI_set_variable:
+ {
+ CHAR16 *name;
+ long len;
+ unsigned char *data;
+
+ len = gwstrlen(guest_handle_cast(op->u.set_variable.name, CHAR16));
+ if ( len < 0 )
+ return len;
+ name = xmalloc_array(CHAR16, ++len);
+ if ( !name )
+ return -ENOMEM;
+ __copy_from_guest(name, op->u.set_variable.name, len);
+
+ data = xmalloc_bytes(op->u.set_variable.size);
+ if ( !data )
+ rc = -ENOMEM;
+ else if ( copy_from_guest(data, op->u.set_variable.data,
+ op->u.set_variable.size) )
+ rc = -EFAULT;
+ else
+ {
+ cr3 = efi_rs_enter();
+ if ( cr3 )
+ status = efi_rs->SetVariable(
+ name, cast_guid(&op->u.set_variable.vendor_guid),
+ op->misc, op->u.set_variable.size, data);
+ else
+ rc = -EOPNOTSUPP;
+ efi_rs_leave(cr3);
+ }
+
+ xfree(data);
+ xfree(name);
+ }
+ break;
+
+ case XEN_EFI_get_next_variable_name:
+ {
+ union {
+ CHAR16 *str;
+ unsigned char *raw;
+ } name;
+ UINTN size;
+
+ if ( op->misc )
+ return -EINVAL;
+
+ size = op->u.get_next_variable_name.size;
+ name.raw = xmalloc_bytes(size);
+ if ( !name.raw )
+ return -ENOMEM;
+ if ( copy_from_guest(name.raw, op->u.get_next_variable_name.name,
+ size) )
+ {
+ xfree(name.raw);
+ return -EFAULT;
+ }
+
+ cr3 = efi_rs_enter();
+ if ( cr3 )
+ {
+ status = efi_rs->GetNextVariableName(
+ &size, name.str,
+ cast_guid(&op->u.get_next_variable_name.vendor_guid));
+ efi_rs_leave(cr3);
+
+ if ( !EFI_ERROR(status) &&
+ copy_to_guest(op->u.get_next_variable_name.name,
+ name.raw, size) )
+ rc = -EFAULT;
+ op->u.get_next_variable_name.size = size;
+ }
+ else
+ rc = -EOPNOTSUPP;
+
+ xfree(name.raw);
+ }
+ break;
+
+ case XEN_EFI_query_variable_info:
+ if ( op->misc & ~XEN_EFI_VARINFO_BOOT_SNAPSHOT )
+ return -EINVAL;
+
+ if ( op->misc & XEN_EFI_VARINFO_BOOT_SNAPSHOT )
+ {
+ if ( (op->u.query_variable_info.attr
+ & ~EFI_VARIABLE_APPEND_WRITE) !=
+ (EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS) )
+ return -EINVAL;
+
+ op->u.query_variable_info.max_store_size =
+ efi_boot_max_var_store_size;
+ op->u.query_variable_info.remain_store_size =
+ efi_boot_remain_var_store_size;
+ if ( efi_boot_max_var_store_size )
+ {
+ op->u.query_variable_info.max_size = efi_boot_max_var_size;
+ status = EFI_SUCCESS;
+ }
+ else
+ {
+ op->u.query_variable_info.max_size = 0;
+ status = efi_boot_max_var_size;
+ }
+ break;
+ }
+
+ cr3 = efi_rs_enter();
+ if ( !cr3 || (efi_rs->Hdr.Revision >> 16) < 2 )
+ {
+ efi_rs_leave(cr3);
+ return -EOPNOTSUPP;
+ }
+ status = efi_rs->QueryVariableInfo(
+ op->u.query_variable_info.attr,
+ &op->u.query_variable_info.max_store_size,
+ &op->u.query_variable_info.remain_store_size,
+ &op->u.query_variable_info.max_size);
+ efi_rs_leave(cr3);
+ break;
+
+ case XEN_EFI_query_capsule_capabilities:
+ case XEN_EFI_update_capsule:
+ if ( op->misc )
+ return -EINVAL;
+
+ cr3 = efi_rs_enter();
+ if ( !cr3 || (efi_rs->Hdr.Revision >> 16) < 2 )
+ {
+ efi_rs_leave(cr3);
+ return -EOPNOTSUPP;
+ }
+ efi_rs_leave(cr3);
+ /* XXX fall through for now */
+ default:
+ return -ENOSYS;
+ }
+
+#ifndef COMPAT
+ op->status = status;
+#else
+ op->status = (status & 0x3fffffff) | ((status >> 32) & 0xc0000000);
+#endif
+
+ return rc;
+}
+#endif
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index 6fd4a2c..7d6de54 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -59,7 +59,7 @@
* with a pointer, we stash them dynamically in a small lookup array which
* can be indexed by a small integer.
*/
-static xen_event_channel_notification_t xen_consumers[8];
+static xen_event_channel_notification_t xen_consumers[NR_XEN_CONSUMERS];
/* Default notification action: wake up from wait_on_xen_event_channel(). */
static void default_xen_notification_fn(struct vcpu *v, unsigned int port)
@@ -743,7 +743,7 @@ void send_global_virq(uint32_t virq)
ASSERT(virq < NR_VIRQS);
ASSERT(virq_is_global(virq));
- send_guest_global_virq(global_virq_handlers[virq] ?: dom0, virq);
+ send_guest_global_virq(global_virq_handlers[virq] ?: hardware_domain, virq);
}
int set_global_virq_handler(struct domain *d, uint32_t virq)
@@ -957,6 +957,21 @@ static long evtchn_reset(evtchn_reset_t *r)
for ( i = 0; port_is_valid(d, i); i++ )
(void)__evtchn_close(d, i);
+ spin_lock(&d->event_lock);
+
+ if ( (dom == DOMID_SELF) && d->evtchn_fifo )
+ {
+ /*
+ * Guest domain called EVTCHNOP_reset with DOMID_SELF, destroying
+ * FIFO event array and control blocks, resetting evtchn_port_ops to
+ * evtchn_port_ops_2l.
+ */
+ evtchn_fifo_destroy(d);
+ evtchn_2l_init(d);
+ }
+
+ spin_unlock(&d->event_lock);
+
rc = 0;
out:
diff --git a/xen/common/event_fifo.c b/xen/common/event_fifo.c
index 1fce3f1..b81fae4 100644
--- a/xen/common/event_fifo.c
+++ b/xen/common/event_fifo.c
@@ -178,6 +178,18 @@ static void evtchn_fifo_set_pending(struct vcpu *v, struct evtchn *evtchn)
bool_t linked = 0;
/*
+ * Control block not mapped. The guest must not unmask an
+ * event until the control block is initialized, so we can
+ * just drop the event.
+ */
+ if ( unlikely(!v->evtchn_fifo->control_block) )
+ {
+ printk(XENLOG_G_WARNING
+ "%pv has no FIFO event channel control block\n", v);
+ goto done;
+ }
+
+ /*
* No locking around getting the queue. This may race with
* changing the priority but we are allowed to signal the
* event once on the old priority.
@@ -385,36 +397,42 @@ static void init_queue(struct vcpu *v, struct evtchn_fifo_queue *q,
{
spin_lock_init(&q->lock);
q->priority = i;
- q->head = &v->evtchn_fifo->control_block->head[i];
}
-static int setup_control_block(struct vcpu *v, uint64_t gfn, uint32_t offset)
+static int setup_control_block(struct vcpu *v)
{
- struct domain *d = v->domain;
struct evtchn_fifo_vcpu *efv;
- void *virt;
unsigned int i;
- int rc;
-
- if ( v->evtchn_fifo )
- return -EINVAL;
efv = xzalloc(struct evtchn_fifo_vcpu);
if ( !efv )
return -ENOMEM;
- rc = map_guest_page(d, gfn, &virt);
+ for ( i = 0; i <= EVTCHN_FIFO_PRIORITY_MIN; i++ )
+ init_queue(v, &efv->queue[i], i);
+
+ v->evtchn_fifo = efv;
+
+ return 0;
+}
+
+static int map_control_block(struct vcpu *v, uint64_t gfn, uint32_t offset)
+{
+ void *virt;
+ unsigned int i;
+ int rc;
+
+ if ( v->evtchn_fifo->control_block )
+ return -EINVAL;
+
+ rc = map_guest_page(v->domain, gfn, &virt);
if ( rc < 0 )
- {
- xfree(efv);
return rc;
- }
- v->evtchn_fifo = efv;
v->evtchn_fifo->control_block = virt + offset;
for ( i = 0; i <= EVTCHN_FIFO_PRIORITY_MIN; i++ )
- init_queue(v, &v->evtchn_fifo->queue[i], i);
+ v->evtchn_fifo->queue[i].head = &v->evtchn_fifo->control_block->head[i];
return 0;
}
@@ -451,6 +469,7 @@ static void cleanup_event_array(struct domain *d)
for ( i = 0; i < EVTCHN_FIFO_MAX_EVENT_ARRAY_PAGES; i++ )
unmap_guest_page(d->evtchn_fifo->event_array[i]);
xfree(d->evtchn_fifo);
+ d->evtchn_fifo = NULL;
}
static void setup_ports(struct domain *d)
@@ -508,28 +527,43 @@ int evtchn_fifo_init_control(struct evtchn_init_control *init_control)
spin_lock(&d->event_lock);
- rc = setup_control_block(v, gfn, offset);
-
/*
* If this is the first control block, setup an empty event array
* and switch to the fifo port ops.
*/
- if ( rc == 0 && !d->evtchn_fifo )
+ if ( !d->evtchn_fifo )
{
+ struct vcpu *vcb;
+
+ for_each_vcpu ( d, vcb ) {
+ rc = setup_control_block(vcb);
+ if ( rc < 0 )
+ goto error;
+ }
+
rc = setup_event_array(d);
if ( rc < 0 )
- cleanup_control_block(v);
- else
- {
- d->evtchn_port_ops = &evtchn_port_ops_fifo;
- d->max_evtchns = EVTCHN_FIFO_NR_CHANNELS;
- setup_ports(d);
- }
+ goto error;
+
+ rc = map_control_block(v, gfn, offset);
+ if ( rc < 0 )
+ goto error;
+
+ d->evtchn_port_ops = &evtchn_port_ops_fifo;
+ d->max_evtchns = EVTCHN_FIFO_NR_CHANNELS;
+ setup_ports(d);
}
+ else
+ rc = map_control_block(v, gfn, offset);
spin_unlock(&d->event_lock);
return rc;
+
+ error:
+ evtchn_fifo_destroy(d);
+ spin_unlock(&d->event_lock);
+ return rc;
}
static int add_page_to_event_array(struct domain *d, unsigned long gfn)
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 107b000..8fba923 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -40,16 +40,31 @@
#include <xsm/xsm.h>
#include <asm/flushtlb.h>
-#ifndef max_nr_grant_frames
-unsigned int max_nr_grant_frames = DEFAULT_MAX_NR_GRANT_FRAMES;
+/*
+ * This option is deprecated, use gnttab_max_frames and
+ * gnttab_max_maptrack_frames instead.
+ */
+static unsigned int __initdata max_nr_grant_frames;
integer_param("gnttab_max_nr_frames", max_nr_grant_frames);
-#endif
+
+unsigned int __read_mostly max_grant_frames;
+integer_param("gnttab_max_frames", max_grant_frames);
/* The maximum number of grant mappings is defined as a multiplier of the
* maximum number of grant table entries. This defines the multiplier used.
* Pretty arbitrary. [POLICY]
+ * As gnttab_max_nr_frames has been deprecated, this multiplier is deprecated too.
+ * New options allow to set max_maptrack_frames and
+ * map_grant_table_frames independently.
*/
-#define MAX_MAPTRACK_TO_GRANTS_RATIO 8
+#define DEFAULT_MAX_MAPTRACK_FRAMES 256
+
+static unsigned int __read_mostly max_maptrack_frames;
+integer_param("gnttab_max_maptrack_frames", max_maptrack_frames);
+
+#define GNTTABOP_CONTINUATION_ARG_SHIFT 12
+#define GNTTABOP_CMD_MASK ((1<<GNTTABOP_CONTINUATION_ARG_SHIFT)-1)
+#define GNTTABOP_ARG_MASK (~GNTTABOP_CMD_MASK)
/*
* The first two members of a grant entry are updated as a combined pair.
@@ -102,11 +117,6 @@ nr_maptrack_frames(struct grant_table *t)
return t->maptrack_limit / MAPTRACK_PER_PAGE;
}
-static unsigned inline int max_nr_maptrack_frames(void)
-{
- return (max_nr_grant_frames * MAX_MAPTRACK_TO_GRANTS_RATIO);
-}
-
#define MAPTRACK_TAIL (~0u)
#define SHGNT_PER_PAGE_V1 (PAGE_SIZE / sizeof(grant_entry_v1_t))
@@ -147,6 +157,12 @@ struct active_grant_entry {
#define active_entry(t, e) \
((t)->active[(e)/ACGNT_PER_PAGE][(e)%ACGNT_PER_PAGE])
+static inline void gnttab_flush_tlb(const struct domain *d)
+{
+ if ( !paging_mode_external(d) )
+ flush_tlb_mask(d->domain_dirty_cpumask);
+}
+
static inline unsigned int
num_act_frames_from_sha_frames(const unsigned int num)
{
@@ -158,7 +174,7 @@ num_act_frames_from_sha_frames(const unsigned int num)
}
#define max_nr_active_grant_frames \
- num_act_frames_from_sha_frames(max_nr_grant_frames)
+ num_act_frames_from_sha_frames(max_grant_frames)
static inline unsigned int
nr_active_grant_frames(struct grant_table *gt)
@@ -265,7 +281,7 @@ get_maptrack_handle(
while ( unlikely((handle = __get_maptrack_handle(lgt)) == -1) )
{
nr_frames = nr_maptrack_frames(lgt);
- if ( nr_frames >= max_nr_maptrack_frames() )
+ if ( nr_frames >= max_maptrack_frames )
break;
new_mt = alloc_xenheap_page();
@@ -478,6 +494,43 @@ static int _set_status(unsigned gt_version,
return _set_status_v2(domid, readonly, mapflag, shah, act, status);
}
+static int grant_map_exists(const struct domain *ld,
+ struct grant_table *rgt,
+ unsigned long mfn,
+ unsigned int *ref_count)
+{
+ const struct active_grant_entry *act;
+ unsigned int ref, max_iter;
+
+ ASSERT(spin_is_locked(&rgt->lock));
+
+ max_iter = min(*ref_count + (1 << GNTTABOP_CONTINUATION_ARG_SHIFT),
+ nr_grant_entries(rgt));
+ for ( ref = *ref_count; ref < max_iter; ref++ )
+ {
+ act = &active_entry(rgt, ref);
+
+ if ( !act->pin )
+ continue;
+
+ if ( act->domid != ld->domain_id )
+ continue;
+
+ if ( act->frame != mfn )
+ continue;
+
+ return 0;
+ }
+
+ if ( ref < nr_grant_entries(rgt) )
+ {
+ *ref_count = ref;
+ return 1;
+ }
+
+ return -EINVAL;
+}
+
static void mapcount(
struct grant_table *lgt, struct domain *rd, unsigned long mfn,
unsigned int *wrc, unsigned int *rdc)
@@ -574,7 +627,7 @@ __gnttab_map_grant_ref(
if ( rgt->gt_version == 0 )
PIN_FAIL(unlock_out, GNTST_general_error,
- "remote grant table not yet set up");
+ "remote grant table not yet set up\n");
/* Bounds check on the grant ref */
if ( unlikely(op->ref >= nr_grant_entries(rgt)))
@@ -721,12 +774,10 @@ __gnttab_map_grant_ref(
double_gt_lock(lgt, rgt);
- if ( is_pv_domain(ld) && need_iommu(ld) )
+ if ( gnttab_need_iommu_mapping(ld) )
{
unsigned int wrc, rdc;
int err = 0;
- /* Shouldn't happen, because you can't use iommu in a HVM domain. */
- BUG_ON(paging_mode_translate(ld));
/* We're not translated, so we know that gmfns and mfns are
the same things, so the IOMMU entry is always 1-to-1. */
mapcount(lgt, rd, frame, &wrc, &rdc);
@@ -931,11 +982,10 @@ __gnttab_unmap_common(
act->pin -= GNTPIN_hstw_inc;
}
- if ( is_pv_domain(ld) && need_iommu(ld) )
+ if ( gnttab_need_iommu_mapping(ld) )
{
unsigned int wrc, rdc;
int err = 0;
- BUG_ON(paging_mode_translate(ld));
mapcount(lgt, rd, op->frame, &wrc, &rdc);
if ( (wrc + rdc) == 0 )
err = iommu_unmap_page(ld, op->frame);
@@ -1099,7 +1149,7 @@ gnttab_unmap_grant_ref(
guest_handle_add_offset(uop, 1);
}
- flush_tlb_mask(current->domain->domain_dirty_cpumask);
+ gnttab_flush_tlb(current->domain);
for ( i = 0; i < partial_done; i++ )
__gnttab_unmap_common_complete(&(common[i]));
@@ -1114,7 +1164,7 @@ gnttab_unmap_grant_ref(
return 0;
fault:
- flush_tlb_mask(current->domain->domain_dirty_cpumask);
+ gnttab_flush_tlb(current->domain);
for ( i = 0; i < partial_done; i++ )
__gnttab_unmap_common_complete(&(common[i]));
@@ -1162,7 +1212,7 @@ gnttab_unmap_and_replace(
guest_handle_add_offset(uop, 1);
}
- flush_tlb_mask(current->domain->domain_dirty_cpumask);
+ gnttab_flush_tlb(current->domain);
for ( i = 0; i < partial_done; i++ )
__gnttab_unmap_common_complete(&(common[i]));
@@ -1177,7 +1227,7 @@ gnttab_unmap_and_replace(
return 0;
fault:
- flush_tlb_mask(current->domain->domain_dirty_cpumask);
+ gnttab_flush_tlb(current->domain);
for ( i = 0; i < partial_done; i++ )
__gnttab_unmap_common_complete(&(common[i]));
@@ -1242,7 +1292,7 @@ gnttab_grow_table(struct domain *d, unsigned int req_nr_frames)
struct grant_table *gt = d->grant_table;
unsigned int i;
- ASSERT(req_nr_frames <= max_nr_grant_frames);
+ ASSERT(req_nr_frames <= max_grant_frames);
gdprintk(XENLOG_INFO,
"Expanding dom (%d) grant table from (%d) to (%d) frames.\n",
@@ -1315,11 +1365,11 @@ gnttab_setup_table(
return -EFAULT;
}
- if ( unlikely(op.nr_frames > max_nr_grant_frames) )
+ if ( unlikely(op.nr_frames > max_grant_frames) )
{
gdprintk(XENLOG_INFO, "Xen only supports up to %d grant-table frames"
" per domain.\n",
- max_nr_grant_frames);
+ max_grant_frames);
op.status = GNTST_general_error;
goto out1;
}
@@ -1354,7 +1404,7 @@ gnttab_setup_table(
{
gdprintk(XENLOG_INFO,
"Expand grant table to %u failed. Current: %u Max: %u\n",
- op.nr_frames, nr_grant_frames(gt), max_nr_grant_frames);
+ op.nr_frames, nr_grant_frames(gt), max_grant_frames);
op.status = GNTST_general_error;
goto out3;
}
@@ -1415,7 +1465,7 @@ gnttab_query_size(
spin_lock(&d->grant_table->lock);
op.nr_frames = nr_grant_frames(d->grant_table);
- op.max_nr_frames = max_nr_grant_frames;
+ op.max_nr_frames = max_grant_frames;
op.status = GNTST_okay;
spin_unlock(&d->grant_table->lock);
@@ -1569,7 +1619,7 @@ gnttab_transfer(
}
guest_physmap_remove_page(d, gop.mfn, mfn, 0);
- flush_tlb_mask(d->domain_dirty_cpumask);
+ gnttab_flush_tlb(d);
/* Find the target domain. */
if ( unlikely((e = rcu_lock_domain_by_id(gop.domid)) == NULL) )
@@ -2459,17 +2509,124 @@ gnttab_swap_grant_ref(XEN_GUEST_HANDLE_PARAM(gnttab_swap_grant_ref_t) uop,
return 0;
}
+static int __gnttab_cache_flush(gnttab_cache_flush_t *cflush,
+ unsigned int *ref_count)
+{
+ struct domain *d, *owner;
+ struct page_info *page;
+ unsigned long mfn;
+ void *v;
+ int ret;
+
+ if ( (cflush->offset >= PAGE_SIZE) ||
+ (cflush->length > PAGE_SIZE) ||
+ (cflush->offset + cflush->length > PAGE_SIZE) )
+ return -EINVAL;
+
+ if ( cflush->length == 0 || cflush->op == 0 )
+ return 0;
+
+ /* currently unimplemented */
+ if ( cflush->op & GNTTAB_CACHE_SOURCE_GREF )
+ return -EOPNOTSUPP;
+
+ if ( cflush->op & ~(GNTTAB_CACHE_INVAL|GNTTAB_CACHE_CLEAN) )
+ return -EINVAL;
+
+ d = rcu_lock_current_domain();
+ mfn = cflush->a.dev_bus_addr >> PAGE_SHIFT;
+
+ if ( !mfn_valid(mfn) )
+ {
+ rcu_unlock_domain(d);
+ return -EINVAL;
+ }
+
+ page = mfn_to_page(mfn);
+ owner = page_get_owner_and_reference(page);
+ if ( !owner )
+ {
+ rcu_unlock_domain(d);
+ return -EPERM;
+ }
+
+ if ( d != owner )
+ {
+ spin_lock(&owner->grant_table->lock);
+
+ ret = grant_map_exists(d, owner->grant_table, mfn, ref_count);
+ if ( ret != 0 )
+ {
+ spin_unlock(&owner->grant_table->lock);
+ rcu_unlock_domain(d);
+ put_page(page);
+ return ret;
+ }
+ }
+
+ v = map_domain_page(mfn);
+ v += cflush->offset;
+
+ if ( (cflush->op & GNTTAB_CACHE_INVAL) && (cflush->op & GNTTAB_CACHE_CLEAN) )
+ ret = clean_and_invalidate_dcache_va_range(v, cflush->length);
+ else if ( cflush->op & GNTTAB_CACHE_INVAL )
+ ret = invalidate_dcache_va_range(v, cflush->length);
+ else if ( cflush->op & GNTTAB_CACHE_CLEAN )
+ ret = clean_dcache_va_range(v, cflush->length);
+ else
+ ret = 0;
+
+ if ( d != owner )
+ spin_unlock(&owner->grant_table->lock);
+ unmap_domain_page(v);
+ put_page(page);
+
+ return ret;
+}
+
+static long
+gnttab_cache_flush(XEN_GUEST_HANDLE_PARAM(gnttab_cache_flush_t) uop,
+ unsigned int *ref_count,
+ unsigned int count)
+{
+ unsigned int i;
+ gnttab_cache_flush_t op;
+
+ for ( i = 0; i < count; i++ )
+ {
+ if ( i && hypercall_preempt_check() )
+ return i;
+ if ( unlikely(__copy_from_guest(&op, uop, 1)) )
+ return -EFAULT;
+ for ( ; ; )
+ {
+ int ret = __gnttab_cache_flush(&op, ref_count);
+
+ if ( ret < 0 )
+ return ret;
+ if ( ret == 0 )
+ break;
+ if ( hypercall_preempt_check() )
+ return i;
+ }
+ *ref_count = 0;
+ guest_handle_add_offset(uop, 1);
+ }
+ return 0;
+}
+
long
do_grant_table_op(
unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) uop, unsigned int count)
{
long rc;
+ unsigned int opaque_in = cmd & GNTTABOP_ARG_MASK, opaque_out = 0;
if ( (int)count < 0 )
return -EINVAL;
rc = -EFAULT;
- switch ( cmd )
+ switch ( cmd &= GNTTABOP_CMD_MASK )
{
case GNTTABOP_map_grant_ref:
{
@@ -2588,17 +2745,34 @@ do_grant_table_op(
}
break;
}
+ case GNTTABOP_cache_flush:
+ {
+ XEN_GUEST_HANDLE_PARAM(gnttab_cache_flush_t) cflush =
+ guest_handle_cast(uop, gnttab_cache_flush_t);
+
+ if ( unlikely(!guest_handle_okay(cflush, count)) )
+ goto out;
+ rc = gnttab_cache_flush(cflush, &opaque_in, count);
+ if ( rc > 0 )
+ {
+ guest_handle_add_offset(cflush, rc);
+ uop = guest_handle_cast(cflush, void);
+ }
+ opaque_out = opaque_in;
+ break;
+ }
default:
rc = -ENOSYS;
break;
}
out:
- if ( rc > 0 )
+ if ( rc > 0 || opaque_out != 0 )
{
ASSERT(rc < count);
- rc = hypercall_create_continuation(__HYPERVISOR_grant_table_op,
- "ihi", cmd, uop, count - rc);
+ ASSERT((opaque_out & GNTTABOP_CMD_MASK) == 0);
+ rc = hypercall_create_continuation(__HYPERVISOR_grant_table_op, "ihi",
+ opaque_out | cmd, uop, count - rc);
}
return rc;
@@ -2636,7 +2810,7 @@ grant_table_create(
/* Tracking of mapped foreign frames table */
if ( (t->maptrack = xzalloc_array(struct grant_mapping *,
- max_nr_maptrack_frames())) == NULL )
+ max_maptrack_frames)) == NULL )
goto no_mem_2;
if ( (t->maptrack[0] = alloc_xenheap_page()) == NULL )
goto no_mem_3;
@@ -2647,7 +2821,7 @@ grant_table_create(
t->maptrack[0][i - 1].ref = MAPTRACK_TAIL;
/* Shared grant table. */
- if ( (t->shared_raw = xzalloc_array(void *, max_nr_grant_frames)) == NULL )
+ if ( (t->shared_raw = xzalloc_array(void *, max_grant_frames)) == NULL )
goto no_mem_3;
for ( i = 0; i < INITIAL_NR_GRANT_FRAMES; i++ )
{
@@ -2658,7 +2832,7 @@ grant_table_create(
/* Status pages for grant table - for version 2 */
t->status = xzalloc_array(grant_status_t *,
- grant_to_status_frames(max_nr_grant_frames));
+ grant_to_status_frames(max_grant_frames));
if ( t->status == NULL )
goto no_mem_4;
@@ -2907,6 +3081,24 @@ static struct keyhandler gnttab_usage_print_all_keyhandler = {
static int __init gnttab_usage_init(void)
{
+ if ( max_nr_grant_frames )
+ {
+ printk(XENLOG_WARNING
+ "gnttab_max_nr_frames is deprecated, use gnttab_max_frames instead\n");
+ if ( !max_grant_frames )
+ max_grant_frames = max_nr_grant_frames;
+ BUILD_BUG_ON(DEFAULT_MAX_MAPTRACK_FRAMES < DEFAULT_MAX_NR_GRANT_FRAMES);
+ if ( !max_maptrack_frames )
+ max_maptrack_frames = max_nr_grant_frames *
+ (DEFAULT_MAX_MAPTRACK_FRAMES / DEFAULT_MAX_NR_GRANT_FRAMES);
+ }
+
+ if ( !max_grant_frames )
+ max_grant_frames = DEFAULT_MAX_NR_GRANT_FRAMES;
+
+ if ( !max_maptrack_frames )
+ max_maptrack_frames = DEFAULT_MAX_MAPTRACK_FRAMES;
+
register_keyhandler('g', &gnttab_usage_print_all_keyhandler);
return 0;
}
diff --git a/xen/common/hvm/save.c b/xen/common/hvm/save.c
index 6c16399..da6e668 100644
--- a/xen/common/hvm/save.c
+++ b/xen/common/hvm/save.c
@@ -292,19 +292,22 @@ int _hvm_check_entry(struct hvm_domain_context *h,
{
struct hvm_save_descriptor *d
= (struct hvm_save_descriptor *)&h->data[h->cur];
- if ( len + sizeof (*d) > h->size - h->cur)
+ if ( sizeof(*d) > h->size - h->cur)
{
printk(XENLOG_G_WARNING
- "HVM restore: not enough data left to read %u bytes "
- "for type %u\n", len, type);
+ "HVM restore: not enough data left to read %zu bytes "
+ "for type %u header\n", sizeof(*d), type);
return -1;
- }
- if ( (type != d->typecode) || (len < d->length) ||
- (strict_length && (len != d->length)) )
+ }
+ if ( (type != d->typecode) ||
+ (strict_length ? (len != d->length) : (len < d->length)) ||
+ (d->length > (h->size - h->cur - sizeof(*d))) )
{
printk(XENLOG_G_WARNING
- "HVM restore mismatch: expected type %u length %u, "
- "saw type %u length %u\n", type, len, d->typecode, d->length);
+ "HVM restore mismatch: expected %s type %u length %u, "
+ "saw type %u length %u. %zu bytes remaining\n",
+ strict_length ? "strict" : "zeroextended", type, len,
+ d->typecode, d->length, h->size - h->cur - sizeof(*d));
return -1;
}
h->cur += sizeof(*d);
diff --git a/xen/common/kernel.c b/xen/common/kernel.c
index b371f8f..d23c422 100644
--- a/xen/common/kernel.c
+++ b/xen/common/kernel.c
@@ -135,6 +135,13 @@ void __init cmdline_parse(const char *cmdline)
parse_size_and_unit(optval, NULL));
break;
case OPT_CUSTOM:
+ if ( !bool_assert )
+ {
+ if ( *optval )
+ break;
+ safe_strcpy(opt, "no");
+ optval = opt;
+ }
((void (*)(const char *))param->var)(optval);
break;
default:
@@ -303,7 +310,7 @@ DO(xen_version)(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
(1U << XENFEAT_auto_translated_physmap);
if ( supervisor_mode_kernel )
fi.submap |= 1U << XENFEAT_supervisor_mode_kernel;
- if ( current->domain == dom0 )
+ if ( is_hardware_domain(current->domain) )
fi.submap |= 1U << XENFEAT_dom0;
#ifdef CONFIG_X86
switch ( d->guest_type )
diff --git a/xen/common/kexec.c b/xen/common/kexec.c
index 23d964e..2239ee8 100644
--- a/xen/common/kexec.c
+++ b/xen/common/kexec.c
@@ -872,7 +872,7 @@ static int kexec_load_slot(struct kexec_image *kimage)
static uint16_t kexec_load_v1_arch(void)
{
#ifdef CONFIG_X86
- return is_pv_32on64_domain(dom0) ? EM_386 : EM_X86_64;
+ return is_pv_32on64_domain(hardware_domain) ? EM_386 : EM_X86_64;
#else
return EM_NONE;
#endif
diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c
index 8e4b3f8..a917726 100644
--- a/xen/common/keyhandler.c
+++ b/xen/common/keyhandler.c
@@ -89,9 +89,8 @@ void dump_execstate(struct cpu_user_regs *regs)
if ( !is_idle_vcpu(current) )
{
- printk("*** Dumping CPU%u guest state (d%d:v%d): ***\n",
- smp_processor_id(), current->domain->domain_id,
- current->vcpu_id);
+ printk("*** Dumping CPU%u guest state (%pv): ***\n",
+ smp_processor_id(), current);
show_execution_state(guest_cpu_user_regs());
printk("\n");
}
@@ -149,9 +148,9 @@ static struct keyhandler dump_registers_keyhandler = {
.desc = "dump registers"
};
-static DECLARE_TASKLET(dump_dom0_tasklet, NULL, 0);
+static DECLARE_TASKLET(dump_hwdom_tasklet, NULL, 0);
-static void dump_dom0_action(unsigned long arg)
+static void dump_hwdom_action(unsigned long arg)
{
struct vcpu *v = (void *)arg;
@@ -162,39 +161,39 @@ static void dump_dom0_action(unsigned long arg)
break;
if ( softirq_pending(smp_processor_id()) )
{
- dump_dom0_tasklet.data = (unsigned long)v;
- tasklet_schedule_on_cpu(&dump_dom0_tasklet, v->processor);
+ dump_hwdom_tasklet.data = (unsigned long)v;
+ tasklet_schedule_on_cpu(&dump_hwdom_tasklet, v->processor);
break;
}
}
}
-static void dump_dom0_registers(unsigned char key)
+static void dump_hwdom_registers(unsigned char key)
{
struct vcpu *v;
- if ( dom0 == NULL )
+ if ( hardware_domain == NULL )
return;
printk("'%c' pressed -> dumping Dom0's registers\n", key);
- for_each_vcpu ( dom0, v )
+ for_each_vcpu ( hardware_domain, v )
{
if ( alt_key_handling && softirq_pending(smp_processor_id()) )
{
- tasklet_kill(&dump_dom0_tasklet);
- tasklet_init(&dump_dom0_tasklet, dump_dom0_action,
+ tasklet_kill(&dump_hwdom_tasklet);
+ tasklet_init(&dump_hwdom_tasklet, dump_hwdom_action,
(unsigned long)v);
- tasklet_schedule_on_cpu(&dump_dom0_tasklet, v->processor);
+ tasklet_schedule_on_cpu(&dump_hwdom_tasklet, v->processor);
return;
}
vcpu_show_execution_state(v);
}
}
-static struct keyhandler dump_dom0_registers_keyhandler = {
+static struct keyhandler dump_hwdom_registers_keyhandler = {
.diagnostic = 1,
- .u.fn = dump_dom0_registers,
+ .u.fn = dump_hwdom_registers,
.desc = "dump Dom0 registers"
};
@@ -254,6 +253,9 @@ static void dump_domains(unsigned char key)
for_each_domain ( d )
{
unsigned int i;
+
+ process_pending_softirqs();
+
printk("General information for domain %u:\n", d->domain_id);
cpuset_print(tmpstr, sizeof(tmpstr), d->domain_dirty_cpumask);
printk(" refcnt=%d dying=%d pause_count=%d\n",
@@ -288,6 +290,9 @@ static void dump_domains(unsigned char key)
d->domain_id);
for_each_vcpu ( d, v )
{
+ if ( !(v->vcpu_id & 0x3f) )
+ process_pending_softirqs();
+
printk(" VCPU%d: CPU%d [has=%c] poll=%d "
"upcall_pend = %02x, upcall_mask = %02x ",
v->vcpu_id, v->processor,
@@ -296,8 +301,10 @@ static void dump_domains(unsigned char key)
!vcpu_event_delivery_is_enabled(v));
cpuset_print(tmpstr, sizeof(tmpstr), v->vcpu_dirty_cpumask);
printk("dirty_cpus=%s ", tmpstr);
- cpuset_print(tmpstr, sizeof(tmpstr), v->cpu_affinity);
+ cpuset_print(tmpstr, sizeof(tmpstr), v->cpu_hard_affinity);
printk("cpu_affinity=%s\n", tmpstr);
+ cpuset_print(tmpstr, sizeof(tmpstr), v->cpu_soft_affinity);
+ printk("cpu_soft_affinity=%s\n", tmpstr);
printk(" pause_count=%d pause_flags=%lx\n",
atomic_read(&v->pause_count), v->pause_flags);
arch_dump_vcpu_info(v);
@@ -310,6 +317,9 @@ static void dump_domains(unsigned char key)
{
for_each_vcpu ( d, v )
{
+ if ( !(v->vcpu_id & 0x3f) )
+ process_pending_softirqs();
+
printk("Notifying guest %d:%d (virq %d, port %d)\n",
d->domain_id, v->vcpu_id,
VIRQ_DEBUG, v->virq_to_evtchn[VIRQ_DEBUG]);
@@ -544,7 +554,7 @@ void __init initialize_keytable(void)
register_keyhandler('r', &dump_runq_keyhandler);
register_keyhandler('R', &reboot_machine_keyhandler);
register_keyhandler('t', &read_clocks_keyhandler);
- register_keyhandler('0', &dump_dom0_registers_keyhandler);
+ register_keyhandler('0', &dump_hwdom_registers_keyhandler);
register_keyhandler('%', &do_debug_key_keyhandler);
register_keyhandler('*', &run_all_keyhandlers_keyhandler);
diff --git a/xen/common/lib.c b/xen/common/lib.c
index e3cb3f4..89c74ad 100644
--- a/xen/common/lib.c
+++ b/xen/common/lib.c
@@ -459,6 +459,8 @@ unsigned long long parse_size_and_unit(const char *s, const char **ps)
switch ( *s1 )
{
+ case 'T': case 't':
+ ret <<= 10;
case 'G': case 'g':
ret <<= 10;
case 'M': case 'm':
@@ -487,6 +489,9 @@ void __init init_constructors(void)
const ctor_func_t *f;
for ( f = __ctors_start; f < __ctors_end; ++f )
(*f)();
+
+ /* Putting this here seems as good (or bad) as any other place. */
+ BUILD_BUG_ON(sizeof(size_t) != sizeof(ssize_t));
}
/*
diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h
index f4b79c7..854a0d7 100644
--- a/xen/common/libelf/libelf-private.h
+++ b/xen/common/libelf/libelf-private.h
@@ -61,6 +61,11 @@
#define bswap_16(x) swap16(x)
#define bswap_32(x) swap32(x)
#define bswap_64(x) swap64(x)
+#elif defined(__FreeBSD__)
+#include <sys/endian.h>
+#define bswap_16(x) bswap16(x)
+#define bswap_32(x) bswap32(x)
+#define bswap_64(x) bswap64(x)
#elif defined(__linux__) || defined(__Linux__) || defined(__MINIOS__)
#include <byteswap.h>
#else
diff --git a/xen/common/libfdt/Makefile.libfdt b/xen/common/libfdt/Makefile.libfdt
index d55a6f8..91126c0 100644
--- a/xen/common/libfdt/Makefile.libfdt
+++ b/xen/common/libfdt/Makefile.libfdt
@@ -4,7 +4,7 @@
# be easily embeddable into other systems of Makefiles.
#
LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
-LIBFDT_INCLUDES = fdt.h libfdt.h
+LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
LIBFDT_VERSION = version.lds
-LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
diff --git a/xen/common/libfdt/fdt.c b/xen/common/libfdt/fdt.c
index e56833a..2ce6a44 100644
--- a/xen/common/libfdt/fdt.c
+++ b/xen/common/libfdt/fdt.c
@@ -92,7 +92,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
- const uint32_t *tagp, *lenp;
+ const fdt32_t *tagp, *lenp;
uint32_t tag;
int offset = startoffset;
const char *p;
@@ -198,6 +198,34 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
return offset;
}
+int fdt_first_subnode(const void *fdt, int offset)
+{
+ int depth = 0;
+
+ offset = fdt_next_node(fdt, offset, &depth);
+ if (offset < 0 || depth != 1)
+ return -FDT_ERR_NOTFOUND;
+
+ return offset;
+}
+
+int fdt_next_subnode(const void *fdt, int offset)
+{
+ int depth = 1;
+
+ /*
+ * With respect to the parent, the depth of the next subnode will be
+ * the same as the last.
+ */
+ do {
+ offset = fdt_next_node(fdt, offset, &depth);
+ if (offset < 0 || depth < 1)
+ return -FDT_ERR_NOTFOUND;
+ } while (depth > 1);
+
+ return offset;
+}
+
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
{
int len = strlen(s) + 1;
diff --git a/xen/common/libfdt/fdt_empty_tree.c b/xen/common/libfdt/fdt_empty_tree.c
new file mode 100644
index 0000000..f72d13b
--- /dev/null
+++ b/xen/common/libfdt/fdt_empty_tree.c
@@ -0,0 +1,84 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2012 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_create_empty_tree(void *buf, int bufsize)
+{
+ int err;
+
+ err = fdt_create(buf, bufsize);
+ if (err)
+ return err;
+
+ err = fdt_finish_reservemap(buf);
+ if (err)
+ return err;
+
+ err = fdt_begin_node(buf, "");
+ if (err)
+ return err;
+
+ err = fdt_end_node(buf);
+ if (err)
+ return err;
+
+ err = fdt_finish(buf);
+ if (err)
+ return err;
+
+ return fdt_open_into(buf, buf, bufsize);
+}
+
diff --git a/xen/common/libfdt/fdt_ro.c b/xen/common/libfdt/fdt_ro.c
index 02b6d68..50007f6 100644
--- a/xen/common/libfdt/fdt_ro.c
+++ b/xen/common/libfdt/fdt_ro.c
@@ -322,7 +322,7 @@ const void *fdt_getprop(const void *fdt, int nodeoffset,
uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
{
- const uint32_t *php;
+ const fdt32_t *php;
int len;
/* FIXME: This is a bit sub-optimal, since we potentially scan
@@ -515,8 +515,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
return offset; /* error from fdt_next_node() */
}
-static int _fdt_stringlist_contains(const char *strlist, int listlen,
- const char *str)
+int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
{
int len = strlen(str);
const char *p;
@@ -542,7 +541,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
if (!prop)
return len;
- if (_fdt_stringlist_contains(prop, len, compatible))
+ if (fdt_stringlist_contains(prop, len, compatible))
return 0;
else
return 1;
diff --git a/xen/common/libfdt/fdt_rw.c b/xen/common/libfdt/fdt_rw.c
index 994037b..fdba618 100644
--- a/xen/common/libfdt/fdt_rw.c
+++ b/xen/common/libfdt/fdt_rw.c
@@ -289,6 +289,33 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
return 0;
}
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len)
+{
+ struct fdt_property *prop;
+ int err, oldlen, newlen;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+ if (prop) {
+ newlen = len + oldlen;
+ err = _fdt_splice_struct(fdt, prop->data,
+ FDT_TAGALIGN(oldlen),
+ FDT_TAGALIGN(newlen));
+ if (err)
+ return err;
+ prop->len = cpu_to_fdt32(newlen);
+ memcpy(prop->data + oldlen, val, len);
+ } else {
+ err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+ if (err)
+ return err;
+ memcpy(prop->data, val, len);
+ }
+ return 0;
+}
+
int fdt_delprop(void *fdt, int nodeoffset, const char *name)
{
struct fdt_property *prop;
@@ -312,7 +339,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
int nodelen;
int err;
uint32_t tag;
- uint32_t *endtag;
+ fdt32_t *endtag;
FDT_RW_CHECK_HEADER(fdt);
@@ -339,7 +366,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
memcpy(nh->name, name, namelen);
- endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
+ endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
*endtag = cpu_to_fdt32(FDT_END_NODE);
return offset;
diff --git a/xen/common/libfdt/fdt_sw.c b/xen/common/libfdt/fdt_sw.c
index 55ebebf..f422754 100644
--- a/xen/common/libfdt/fdt_sw.c
+++ b/xen/common/libfdt/fdt_sw.c
@@ -153,7 +153,7 @@ int fdt_begin_node(void *fdt, const char *name)
int fdt_end_node(void *fdt)
{
- uint32_t *en;
+ fdt32_t *en;
FDT_SW_CHECK_HEADER(fdt);
@@ -213,7 +213,7 @@ int fdt_property(void *fdt, const char *name, const void *val, int len)
int fdt_finish(void *fdt)
{
char *p = (char *)fdt;
- uint32_t *end;
+ fdt32_t *end;
int oldstroffset, newstroffset;
uint32_t tag;
int offset, nextoffset;
diff --git a/xen/common/libfdt/fdt_wip.c b/xen/common/libfdt/fdt_wip.c
index 6025fa1..c5bbb68 100644
--- a/xen/common/libfdt/fdt_wip.c
+++ b/xen/common/libfdt/fdt_wip.c
@@ -74,7 +74,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
static void _fdt_nop_region(void *start, int len)
{
- uint32_t *p;
+ fdt32_t *p;
for (p = start; (char *)p < ((char *)start + len); p++)
*p = cpu_to_fdt32(FDT_NOP);
diff --git a/xen/common/libfdt/version.lds b/xen/common/libfdt/version.lds
index 3c3994e..80b322b 100644
--- a/xen/common/libfdt/version.lds
+++ b/xen/common/libfdt/version.lds
@@ -48,6 +48,12 @@ LIBFDT_1.2 {
fdt_strerror;
fdt_offset_ptr;
fdt_next_tag;
+ fdt_appendprop;
+ fdt_create_empty_tree;
+ fdt_first_property_offset;
+ fdt_get_property_by_offset;
+ fdt_getprop_by_offset;
+ fdt_next_property_offset;
local:
*;
diff --git a/xen/common/lz4/defs.h b/xen/common/lz4/defs.h
index f46df08..d886a4e 100644
--- a/xen/common/lz4/defs.h
+++ b/xen/common/lz4/defs.h
@@ -12,7 +12,6 @@
#include <asm/byteorder.h>
#endif
-#ifdef __LITTLE_ENDIAN
static inline u16 INIT get_unaligned_le16(const void *p)
{
return le16_to_cpup(p);
@@ -22,19 +21,6 @@ static inline u32 INIT get_unaligned_le32(const void *p)
{
return le32_to_cpup(p);
}
-#else
-#include <asm/unaligned.h>
-
-static inline u16 INIT get_unaligned_le16(const void *p)
-{
- return le16_to_cpu(__get_unaligned(p, 2));
-}
-
-static inline u32 INIT get_unaligned_le32(void *p)
-{
- return le32_to_cpu(__get_unaligned(p, 4));
-}
-#endif
/*
* Detects 64 bits mode
diff --git a/xen/common/lzo.c b/xen/common/lzo.c
index f1213d2..74831cb 100644
--- a/xen/common/lzo.c
+++ b/xen/common/lzo.c
@@ -1,7 +1,7 @@
/*
- * lzo.c -- LZO1X Compressor from MiniLZO
+ * lzo.c -- LZO1X Compressor from LZO
*
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus at oberhumer.com>
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus at oberhumer.com>
*
* The full LZO package can be found at:
* http://www.oberhumer.com/opensource/lzo/
@@ -14,19 +14,47 @@
/*
* lzodefs.h -- architecture, OS and compiler specific defines
*
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus at oberhumer.com>
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus at oberhumer.com>
*
* The full LZO package can be found at:
* http://www.oberhumer.com/opensource/lzo/
*
- * Changed for kernel use by:
+ * Changed for Linux kernel use by:
* Nitin Gupta <nitingupta910 at gmail.com>
* Richard Purdie <rpurdie at openedhand.com>
*/
-#define LZO_VERSION 0x2020
-#define LZO_VERSION_STRING "2.02"
-#define LZO_VERSION_DATE "Oct 17 2005"
+
+#define COPY4(dst, src) \
+ put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
+#if defined(__x86_64__)
+#define COPY8(dst, src) \
+ put_unaligned(get_unaligned((const u64 *)(src)), (u64 *)(dst))
+#else
+#define COPY8(dst, src) \
+ COPY4(dst, src); COPY4((dst) + 4, (src) + 4)
+#endif
+
+#ifdef __MINIOS__
+# include <lib.h>
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+# undef __BIG_ENDIAN
+# endif
+# if __BYTE_ORDER == __BIG_ENDIAN
+# undef __LITTLE_ENDIAN
+# endif
+#endif
+
+#if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN)
+#error "conflicting endian definitions"
+#elif defined(__x86_64__)
+#define LZO_USE_CTZ64 1
+#define LZO_USE_CTZ32 1
+#elif defined(__i386__) || defined(__powerpc__)
+#define LZO_USE_CTZ32 1
+#elif defined(__arm__) && (__LINUX_ARM_ARCH__ >= 5)
+#define LZO_USE_CTZ32 1
+#endif
#define M1_MAX_OFFSET 0x0400
#define M2_MAX_OFFSET 0x0800
@@ -47,208 +75,257 @@
#define M3_MARKER 32
#define M4_MARKER 16
-#define D_BITS 14
-#define D_MASK ((1u << D_BITS) - 1)
+#define lzo_dict_t unsigned short
+#define D_BITS 13
+#define D_SIZE (1u << D_BITS)
+#define D_MASK (D_SIZE - 1)
#define D_HIGH ((D_MASK >> 1) + 1)
-#define DX2(p, s1, s2) (((((size_t)((p)[2]) << (s2)) ^ (p)[1]) \
- << (s1)) ^ (p)[0])
-#define DX3(p, s1, s2, s3) ((DX2((p)+1, s2, s3) << (s1)) ^ (p)[0])
-
/*
- * LZO1X Compressor from MiniLZO
+ * LZO1X Compressor from LZO
*
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus at oberhumer.com>
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus at oberhumer.com>
*
* The full LZO package can be found at:
* http://www.oberhumer.com/opensource/lzo/
*
- * Changed for kernel use by:
+ * Changed for Linux kernel use by:
* Nitin Gupta <nitingupta910 at gmail.com>
* Richard Purdie <rpurdie at openedhand.com>
*/
#ifdef __XEN__
-#include <xen/types.h>
+#include <xen/lib.h>
+#include <asm/byteorder.h>
#endif
#include <xen/lzo.h>
#define get_unaligned(_p) (*(_p))
#define put_unaligned(_val,_p) (*(_p)=_val)
#define get_unaligned_le16(_p) (*(u16 *)(_p))
+#define get_unaligned_le32(_p) (*(u32 *)(_p))
static noinline size_t
-_lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
- unsigned char *out, size_t *out_len, void *wrkmem)
+lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len,
+ size_t ti, void *wrkmem)
{
+ const unsigned char *ip;
+ unsigned char *op;
const unsigned char * const in_end = in + in_len;
- const unsigned char * const ip_end = in + in_len - M2_MAX_LEN - 5;
- const unsigned char ** const dict = wrkmem;
- const unsigned char *ip = in, *ii = ip;
- const unsigned char *end, *m, *m_pos;
- size_t m_off, m_len, dindex;
- unsigned char *op = out;
+ const unsigned char * const ip_end = in + in_len - 20;
+ const unsigned char *ii;
+ lzo_dict_t * const dict = (lzo_dict_t *) wrkmem;
- ip += 4;
+ op = out;
+ ip = in;
+ ii = ip;
+ ip += ti < 4 ? 4 - ti : 0;
for (;;) {
- dindex = ((size_t)(0x21 * DX3(ip, 5, 5, 6)) >> 5) & D_MASK;
- m_pos = dict[dindex];
-
- if (m_pos < in)
- goto literal;
-
- if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
- goto literal;
-
- m_off = ip - m_pos;
- if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
- goto try_match;
-
- dindex = (dindex & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f);
- m_pos = dict[dindex];
-
- if (m_pos < in)
- goto literal;
-
- if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
- goto literal;
-
- m_off = ip - m_pos;
- if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
- goto try_match;
-
- goto literal;
-
- try_match:
- if (get_unaligned((const unsigned short *)m_pos)
- == get_unaligned((const unsigned short *)ip)) {
- if (likely(m_pos[2] == ip[2]))
- goto match;
- }
-
+ const unsigned char *m_pos;
+ size_t t, m_len, m_off;
+ u32 dv;
literal:
- dict[dindex] = ip;
- ++ip;
+ ip += 1 + ((ip - ii) >> 5);
+ next:
if (unlikely(ip >= ip_end))
break;
- continue;
-
- match:
- dict[dindex] = ip;
- if (ip != ii) {
- size_t t = ip - ii;
+ dv = get_unaligned_le32(ip);
+ t = ((dv * 0x1824429d) >> (32 - D_BITS)) & D_MASK;
+ m_pos = in + dict[t];
+ dict[t] = (lzo_dict_t) (ip - in);
+ if (unlikely(dv != get_unaligned_le32(m_pos)))
+ goto literal;
+ ii -= ti;
+ ti = 0;
+ t = ip - ii;
+ if (t != 0) {
if (t <= 3) {
op[-2] |= t;
- } else if (t <= 18) {
+ COPY4(op, ii);
+ op += t;
+ } else if (t <= 16) {
*op++ = (t - 3);
+ COPY8(op, ii);
+ COPY8(op + 8, ii + 8);
+ op += t;
} else {
- size_t tt = t - 18;
-
- *op++ = 0;
- while (tt > 255) {
- tt -= 255;
+ if (t <= 18) {
+ *op++ = (t - 3);
+ } else {
+ size_t tt = t - 18;
*op++ = 0;
+ while (unlikely(tt > 255)) {
+ tt -= 255;
+ *op++ = 0;
+ }
+ *op++ = tt;
}
- *op++ = tt;
+ do {
+ COPY8(op, ii);
+ COPY8(op + 8, ii + 8);
+ op += 16;
+ ii += 16;
+ t -= 16;
+ } while (t >= 16);
+ if (t > 0) do {
+ *op++ = *ii++;
+ } while (--t > 0);
}
+ }
+
+ m_len = 4;
+ {
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ64)
+ u64 v;
+ v = get_unaligned((const u64 *) (ip + m_len)) ^
+ get_unaligned((const u64 *) (m_pos + m_len));
+ if (unlikely(v == 0)) {
do {
- *op++ = *ii++;
- } while (--t > 0);
+ m_len += 8;
+ v = get_unaligned((const u64 *) (ip + m_len)) ^
+ get_unaligned((const u64 *) (m_pos + m_len));
+ if (unlikely(ip + m_len >= ip_end))
+ goto m_len_done;
+ } while (v == 0);
}
+# if defined(__LITTLE_ENDIAN)
+ m_len += (unsigned) __builtin_ctzll(v) / 8;
+# elif defined(__BIG_ENDIAN)
+ m_len += (unsigned) __builtin_clzll(v) / 8;
+# else
+# error "missing endian definition"
+# endif
+#elif defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ32)
+ u32 v;
+ v = get_unaligned((const u32 *) (ip + m_len)) ^
+ get_unaligned((const u32 *) (m_pos + m_len));
+ if (unlikely(v == 0)) {
+ do {
+ m_len += 4;
+ v = get_unaligned((const u32 *) (ip + m_len)) ^
+ get_unaligned((const u32 *) (m_pos + m_len));
+ if (v != 0)
+ break;
+ m_len += 4;
+ v = get_unaligned((const u32 *) (ip + m_len)) ^
+ get_unaligned((const u32 *) (m_pos + m_len));
+ if (unlikely(ip + m_len >= ip_end))
+ goto m_len_done;
+ } while (v == 0);
+ }
+# if defined(__LITTLE_ENDIAN)
+ m_len += (unsigned) __builtin_ctz(v) / 8;
+# elif defined(__BIG_ENDIAN)
+ m_len += (unsigned) __builtin_clz(v) / 8;
+# else
+# error "missing endian definition"
+# endif
+#else
+ if (unlikely(ip[m_len] == m_pos[m_len])) {
+ do {
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (unlikely(ip + m_len >= ip_end))
+ goto m_len_done;
+ } while (ip[m_len] == m_pos[m_len]);
+ }
+#endif
+ }
+ m_len_done:
- ip += 3;
- if (m_pos[3] != *ip++ || m_pos[4] != *ip++
- || m_pos[5] != *ip++ || m_pos[6] != *ip++
- || m_pos[7] != *ip++ || m_pos[8] != *ip++) {
- --ip;
- m_len = ip - ii;
-
- if (m_off <= M2_MAX_OFFSET) {
- m_off -= 1;
- *op++ = (((m_len - 1) << 5)
- | ((m_off & 7) << 2));
- *op++ = (m_off >> 3);
- } else if (m_off <= M3_MAX_OFFSET) {
- m_off -= 1;
+ m_off = ip - m_pos;
+ ip += m_len;
+ ii = ip;
+ if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) {
+ m_off -= 1;
+ *op++ = (((m_len - 1) << 5) | ((m_off & 7) << 2));
+ *op++ = (m_off >> 3);
+ } else if (m_off <= M3_MAX_OFFSET) {
+ m_off -= 1;
+ if (m_len <= M3_MAX_LEN)
*op++ = (M3_MARKER | (m_len - 2));
- goto m3_m4_offset;
- } else {
- m_off -= 0x4000;
-
- *op++ = (M4_MARKER | ((m_off & 0x4000) >> 11)
- | (m_len - 2));
- goto m3_m4_offset;
+ else {
+ m_len -= M3_MAX_LEN;
+ *op++ = M3_MARKER | 0;
+ while (unlikely(m_len > 255)) {
+ m_len -= 255;
+ *op++ = 0;
+ }
+ *op++ = (m_len);
}
+ *op++ = (m_off << 2);
+ *op++ = (m_off >> 6);
} else {
- end = in_end;
- m = m_pos + M2_MAX_LEN + 1;
-
- while (ip < end && *m == *ip) {
- m++;
- ip++;
- }
- m_len = ip - ii;
-
- if (m_off <= M3_MAX_OFFSET) {
- m_off -= 1;
- if (m_len <= 33) {
- *op++ = (M3_MARKER | (m_len - 2));
- } else {
- m_len -= 33;
- *op++ = M3_MARKER | 0;
- goto m3_m4_len;
- }
- } else {
- m_off -= 0x4000;
- if (m_len <= M4_MAX_LEN) {
- *op++ = (M4_MARKER
- | ((m_off & 0x4000) >> 11)
+ m_off -= 0x4000;
+ if (m_len <= M4_MAX_LEN)
+ *op++ = (M4_MARKER | ((m_off >> 11) & 8)
| (m_len - 2));
- } else {
- m_len -= M4_MAX_LEN;
- *op++ = (M4_MARKER
- | ((m_off & 0x4000) >> 11));
- m3_m4_len:
- while (m_len > 255) {
- m_len -= 255;
- *op++ = 0;
- }
-
- *op++ = (m_len);
+ else {
+ m_len -= M4_MAX_LEN;
+ *op++ = (M4_MARKER | ((m_off >> 11) & 8));
+ while (unlikely(m_len > 255)) {
+ m_len -= 255;
+ *op++ = 0;
}
+ *op++ = (m_len);
}
- m3_m4_offset:
- *op++ = ((m_off & 63) << 2);
+ *op++ = (m_off << 2);
*op++ = (m_off >> 6);
}
-
- ii = ip;
- if (unlikely(ip >= ip_end))
- break;
+ goto next;
}
-
*out_len = op - out;
- return in_end - ii;
+ return in_end - (ii - ti);
}
-int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
- size_t *out_len, void *wrkmem)
+int lzo1x_1_compress(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len,
+ void *wrkmem)
{
- const unsigned char *ii;
+ const unsigned char *ip = in;
unsigned char *op = out;
- size_t t;
+ size_t l = in_len;
+ size_t t = 0;
- if (unlikely(in_len <= M2_MAX_LEN + 5)) {
- t = in_len;
- } else {
- t = _lzo1x_1_do_compress(in, in_len, op, out_len, wrkmem);
+ while (l > 20) {
+ size_t ll = l <= (M4_MAX_OFFSET + 1) ? l : (M4_MAX_OFFSET + 1);
+ uintptr_t ll_end = (uintptr_t) ip + ll;
+ if ((ll_end + ((t + ll) >> 5)) <= ll_end)
+ break;
+ BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS);
+ memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t));
+ t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem);
+ ip += ll;
op += *out_len;
+ l -= ll;
}
+ t += l;
if (t > 0) {
- ii = in + in_len - t;
+ const unsigned char *ii = in + in_len - t;
if (op == out && t <= 238) {
*op++ = (17 + t);
@@ -258,16 +335,21 @@ int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
*op++ = (t - 3);
} else {
size_t tt = t - 18;
-
*op++ = 0;
while (tt > 255) {
tt -= 255;
*op++ = 0;
}
-
*op++ = tt;
}
- do {
+ if (t >= 16) do {
+ COPY8(op, ii);
+ COPY8(op + 8, ii + 8);
+ op += 16;
+ ii += 16;
+ t -= 16;
+ } while (t >= 16);
+ if (t > 0) do {
*op++ = *ii++;
} while (--t > 0);
}
@@ -281,232 +363,246 @@ int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
}
/*
- * LZO1X Decompressor from MiniLZO
+ * LZO1X Decompressor from LZO
*
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus at oberhumer.com>
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus at oberhumer.com>
*
* The full LZO package can be found at:
* http://www.oberhumer.com/opensource/lzo/
*
- * Changed for kernel use by:
+ * Changed for Linux kernel use by:
* Nitin Gupta <nitingupta910 at gmail.com>
* Richard Purdie <rpurdie at openedhand.com>
*/
-#define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x))
-#define HAVE_OP(x, op_end, op) ((size_t)(op_end - op) < (x))
-#define HAVE_LB(m_pos, out, op) (m_pos < out || m_pos >= op)
-
-#define COPY4(dst, src) \
- put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
+#define HAVE_IP(x) ((size_t)(ip_end - ip) >= (size_t)(x))
+#define HAVE_OP(x) ((size_t)(op_end - op) >= (size_t)(x))
+#define NEED_IP(x) if (!HAVE_IP(x)) goto input_overrun
+#define NEED_OP(x) if (!HAVE_OP(x)) goto output_overrun
+#define TEST_LB(m_pos) if ((m_pos) < out) goto lookbehind_overrun
+
+/* This MAX_255_COUNT is the maximum number of times we can add 255 to a base
+ * count without overflowing an integer. The multiply will overflow when
+ * multiplying 255 by more than MAXINT/255. The sum will overflow earlier
+ * depending on the base count. Since the base count is taken from a u8
+ * and a few bits, it is safe to assume that it will always be lower than
+ * or equal to 2*255, thus we can always prevent any overflow by accepting
+ * two less 255 steps. See Documentation/lzo.txt for more information.
+ */
+#define MAX_255_COUNT ((((size_t)~0) / 255) - 2)
int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
unsigned char *out, size_t *out_len)
{
+ unsigned char *op;
+ const unsigned char *ip;
+ size_t t, next;
+ size_t state = 0;
+ const unsigned char *m_pos;
const unsigned char * const ip_end = in + in_len;
unsigned char * const op_end = out + *out_len;
- const unsigned char *ip = in, *m_pos;
- unsigned char *op = out;
- size_t t;
- *out_len = 0;
+ op = out;
+ ip = in;
+ if (unlikely(in_len < 3))
+ goto input_overrun;
if (*ip > 17) {
t = *ip++ - 17;
- if (t < 4)
+ if (t < 4) {
+ next = t;
goto match_next;
- if (HAVE_OP(t, op_end, op))
- goto output_overrun;
- if (HAVE_IP(t + 1, ip_end, ip))
- goto input_overrun;
- do {
- *op++ = *ip++;
- } while (--t > 0);
- goto first_literal_run;
+ }
+ goto copy_literal_run;
}
- while ((ip < ip_end)) {
+ for (;;) {
t = *ip++;
- if (t >= 16)
- goto match;
- if (t == 0) {
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- while (*ip == 0) {
- t += 255;
- ip++;
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- }
- t += 15 + *ip++;
- }
- if (HAVE_OP(t + 3, op_end, op))
- goto output_overrun;
- if (HAVE_IP(t + 4, ip_end, ip))
- goto input_overrun;
-
- COPY4(op, ip);
- op += 4;
- ip += 4;
- if (--t > 0) {
- if (t >= 4) {
- do {
- COPY4(op, ip);
- op += 4;
- ip += 4;
- t -= 4;
- } while (t >= 4);
- if (t > 0) {
- do {
- *op++ = *ip++;
- } while (--t > 0);
- }
- } else {
- do {
- *op++ = *ip++;
- } while (--t > 0);
- }
- }
+ if (t < 16) {
+ if (likely(state == 0)) {
+ if (unlikely(t == 0)) {
+ size_t offset;
+ const unsigned char *ip_last = ip;
- first_literal_run:
- t = *ip++;
- if (t >= 16)
- goto match;
- m_pos = op - (1 + M2_MAX_OFFSET);
- m_pos -= t >> 2;
- m_pos -= *ip++ << 2;
-
- if (HAVE_LB(m_pos, out, op))
- goto lookbehind_overrun;
-
- if (HAVE_OP(3, op_end, op))
- goto output_overrun;
- *op++ = *m_pos++;
- *op++ = *m_pos++;
- *op++ = *m_pos;
-
- goto match_done;
-
- do {
- match:
- if (t >= 64) {
- m_pos = op - 1;
- m_pos -= (t >> 2) & 7;
- m_pos -= *ip++ << 3;
- t = (t >> 5) - 1;
- if (HAVE_LB(m_pos, out, op))
- goto lookbehind_overrun;
- if (HAVE_OP(t + 3 - 1, op_end, op))
- goto output_overrun;
- goto copy_match;
- } else if (t >= 32) {
- t &= 31;
- if (t == 0) {
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- while (*ip == 0) {
- t += 255;
+ while (unlikely(*ip == 0)) {
ip++;
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
+ NEED_IP(1);
}
- t += 31 + *ip++;
+ offset = ip - ip_last;
+ if (unlikely(offset > MAX_255_COUNT))
+ return LZO_E_ERROR;
+
+ offset = (offset << 8) - offset;
+ t += offset + 15 + *ip++;
}
- m_pos = op - 1;
- m_pos -= get_unaligned_le16(ip) >> 2;
- ip += 2;
- } else if (t >= 16) {
- m_pos = op;
- m_pos -= (t & 8) << 11;
-
- t &= 7;
- if (t == 0) {
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- while (*ip == 0) {
- t += 255;
- ip++;
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- }
- t += 7 + *ip++;
+ t += 3;
+ copy_literal_run:
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ if (likely(HAVE_IP(t + 15) && HAVE_OP(t + 15))) {
+ const unsigned char *ie = ip + t;
+ unsigned char *oe = op + t;
+ do {
+ COPY8(op, ip);
+ op += 8;
+ ip += 8;
+ COPY8(op, ip);
+ op += 8;
+ ip += 8;
+ } while (ip < ie);
+ ip = ie;
+ op = oe;
+ } else
+#endif
+ {
+ NEED_OP(t);
+ NEED_IP(t + 3);
+ do {
+ *op++ = *ip++;
+ } while (--t > 0);
}
- m_pos -= get_unaligned_le16(ip) >> 2;
- ip += 2;
- if (m_pos == op)
- goto eof_found;
- m_pos -= 0x4000;
- } else {
+ state = 4;
+ continue;
+ } else if (state != 4) {
+ next = t & 3;
m_pos = op - 1;
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
-
- if (HAVE_LB(m_pos, out, op))
- goto lookbehind_overrun;
- if (HAVE_OP(2, op_end, op))
- goto output_overrun;
-
- *op++ = *m_pos++;
- *op++ = *m_pos;
- goto match_done;
+ TEST_LB(m_pos);
+ NEED_OP(2);
+ op[0] = m_pos[0];
+ op[1] = m_pos[1];
+ op += 2;
+ goto match_next;
+ } else {
+ next = t & 3;
+ m_pos = op - (1 + M2_MAX_OFFSET);
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+ t = 3;
}
+ } else if (t >= 64) {
+ next = t & 3;
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 7;
+ m_pos -= *ip++ << 3;
+ t = (t >> 5) - 1 + (3 - 1);
+ } else if (t >= 32) {
+ t = (t & 31) + (3 - 1);
+ if (unlikely(t == 2)) {
+ size_t offset;
+ const unsigned char *ip_last = ip;
+
+ while (unlikely(*ip == 0)) {
+ ip++;
+ NEED_IP(1);
+ }
+ offset = ip - ip_last;
+ if (unlikely(offset > MAX_255_COUNT))
+ return LZO_E_ERROR;
- if (HAVE_LB(m_pos, out, op))
- goto lookbehind_overrun;
- if (HAVE_OP(t + 3 - 1, op_end, op))
- goto output_overrun;
+ offset = (offset << 8) - offset;
+ t += offset + 31 + *ip++;
+ NEED_IP(2);
+ }
+ m_pos = op - 1;
+ next = get_unaligned_le16(ip);
+ ip += 2;
+ m_pos -= next >> 2;
+ next &= 3;
+ } else {
+ m_pos = op;
+ m_pos -= (t & 8) << 11;
+ t = (t & 7) + (3 - 1);
+ if (unlikely(t == 2)) {
+ size_t offset;
+ const unsigned char *ip_last = ip;
+
+ while (unlikely(*ip == 0)) {
+ ip++;
+ NEED_IP(1);
+ }
+ offset = ip - ip_last;
+ if (unlikely(offset > MAX_255_COUNT))
+ return LZO_E_ERROR;
- if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
- COPY4(op, m_pos);
- op += 4;
- m_pos += 4;
- t -= 4 - (3 - 1);
+ offset = (offset << 8) - offset;
+ t += offset + 7 + *ip++;
+ NEED_IP(2);
+ }
+ next = get_unaligned_le16(ip);
+ ip += 2;
+ m_pos -= next >> 2;
+ next &= 3;
+ if (m_pos == op)
+ goto eof_found;
+ m_pos -= 0x4000;
+ }
+ TEST_LB(m_pos);
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ if (op - m_pos >= 8) {
+ unsigned char *oe = op + t;
+ if (likely(HAVE_OP(t + 15))) {
do {
- COPY4(op, m_pos);
- op += 4;
- m_pos += 4;
- t -= 4;
- } while (t >= 4);
- if (t > 0)
- do {
- *op++ = *m_pos++;
- } while (--t > 0);
+ COPY8(op, m_pos);
+ op += 8;
+ m_pos += 8;
+ COPY8(op, m_pos);
+ op += 8;
+ m_pos += 8;
+ } while (op < oe);
+ op = oe;
+ if (HAVE_IP(6)) {
+ state = next;
+ COPY4(op, ip);
+ op += next;
+ ip += next;
+ continue;
+ }
} else {
- copy_match:
- *op++ = *m_pos++;
- *op++ = *m_pos++;
+ NEED_OP(t);
do {
*op++ = *m_pos++;
- } while (--t > 0);
+ } while (op < oe);
}
- match_done:
- t = ip[-2] & 3;
- if (t == 0)
- break;
+ } else
+#endif
+ {
+ unsigned char *oe = op + t;
+ NEED_OP(t);
+ op[0] = m_pos[0];
+ op[1] = m_pos[1];
+ op += 2;
+ m_pos += 2;
+ do {
+ *op++ = *m_pos++;
+ } while (op < oe);
+ }
match_next:
- if (HAVE_OP(t, op_end, op))
- goto output_overrun;
- if (HAVE_IP(t + 1, ip_end, ip))
- goto input_overrun;
-
- *op++ = *ip++;
- if (t > 1) {
+ state = next;
+ t = next;
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ if (likely(HAVE_IP(6) && HAVE_OP(4))) {
+ COPY4(op, ip);
+ op += t;
+ ip += t;
+ } else
+#endif
+ {
+ NEED_IP(t + 3);
+ NEED_OP(t);
+ while (t > 0) {
*op++ = *ip++;
- if (t > 2)
- *op++ = *ip++;
+ t--;
}
-
- t = *ip++;
- } while (ip < ip_end);
+ }
}
- *out_len = op - out;
- return LZO_E_EOF_NOT_FOUND;
-
eof_found:
*out_len = op - out;
- return (ip == ip_end ? LZO_E_OK :
- (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
+ return (t != 3 ? LZO_E_ERROR :
+ ip == ip_end ? LZO_E_OK :
+ ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN);
+
input_overrun:
*out_len = op - out;
return LZO_E_INPUT_OVERRUN;
diff --git a/xen/common/mem_access.c b/xen/common/mem_access.c
new file mode 100644
index 0000000..6c2724b
--- /dev/null
+++ b/xen/common/mem_access.c
@@ -0,0 +1,159 @@
+/******************************************************************************
+ * mem_access.c
+ *
+ * Memory access support.
+ *
+ * Copyright (c) 2011 Virtuata, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <xen/sched.h>
+#include <xen/guest_access.h>
+#include <xen/hypercall.h>
+#include <xen/mem_event.h>
+#include <public/memory.h>
+#include <asm/p2m.h>
+#include <xsm/xsm.h>
+
+void mem_access_resume(struct domain *d)
+{
+ mem_event_response_t rsp;
+
+ /* Pull all responses off the ring. */
+ while ( mem_event_get_response(d, &d->mem_event->access, &rsp) )
+ {
+ struct vcpu *v;
+
+ if ( rsp.flags & MEM_EVENT_FLAG_DUMMY )
+ continue;
+
+ /* Validate the vcpu_id in the response. */
+ if ( (rsp.vcpu_id >= d->max_vcpus) || !d->vcpu[rsp.vcpu_id] )
+ continue;
+
+ v = d->vcpu[rsp.vcpu_id];
+
+ p2m_mem_event_emulate_check(v, &rsp);
+
+ /* Unpause domain. */
+ if ( rsp.flags & MEM_EVENT_FLAG_VCPU_PAUSED )
+ mem_event_vcpu_unpause(v);
+ }
+}
+
+int mem_access_memop(unsigned long cmd,
+ XEN_GUEST_HANDLE_PARAM(xen_mem_access_op_t) arg)
+{
+ long rc;
+ xen_mem_access_op_t mao;
+ struct domain *d;
+
+ if ( copy_from_guest(&mao, arg, 1) )
+ return -EFAULT;
+
+ rc = rcu_lock_live_remote_domain_by_id(mao.domid, &d);
+ if ( rc )
+ return rc;
+
+ rc = -EINVAL;
+ if ( !p2m_mem_access_sanity_check(d) )
+ goto out;
+
+ rc = xsm_mem_event_op(XSM_DM_PRIV, d, XENMEM_access_op);
+ if ( rc )
+ goto out;
+
+ rc = -ENODEV;
+ if ( unlikely(!d->mem_event->access.ring_page) )
+ goto out;
+
+ switch ( mao.op )
+ {
+ case XENMEM_access_op_resume:
+ mem_access_resume(d);
+ rc = 0;
+ break;
+
+ case XENMEM_access_op_set_access:
+ {
+ unsigned long start_iter = cmd & ~MEMOP_CMD_MASK;
+
+ rc = -EINVAL;
+ if ( (mao.pfn != ~0ull) &&
+ (mao.nr < start_iter ||
+ ((mao.pfn + mao.nr - 1) < mao.pfn) ||
+ ((mao.pfn + mao.nr - 1) > domain_get_maximum_gpfn(d))) )
+ break;
+
+ rc = p2m_set_mem_access(d, mao.pfn, mao.nr, start_iter,
+ MEMOP_CMD_MASK, mao.access);
+ if ( rc > 0 )
+ {
+ ASSERT(!(rc & MEMOP_CMD_MASK));
+ rc = hypercall_create_continuation(__HYPERVISOR_memory_op, "lh",
+ XENMEM_access_op | rc, arg);
+ }
+ break;
+ }
+
+ case XENMEM_access_op_get_access:
+ {
+ xenmem_access_t access;
+
+ rc = -EINVAL;
+ if ( (mao.pfn > domain_get_maximum_gpfn(d)) && mao.pfn != ~0ull )
+ break;
+
+ rc = p2m_get_mem_access(d, mao.pfn, &access);
+ if ( rc != 0 )
+ break;
+
+ mao.access = access;
+ rc = __copy_field_to_guest(arg, &mao, access) ? -EFAULT : 0;
+
+ break;
+ }
+
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+
+ out:
+ rcu_unlock_domain(d);
+ return rc;
+}
+
+int mem_access_send_req(struct domain *d, mem_event_request_t *req)
+{
+ int rc = mem_event_claim_slot(d, &d->mem_event->access);
+ if ( rc < 0 )
+ return rc;
+
+ mem_event_put_request(d, &d->mem_event->access, req);
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/mem_event.c b/xen/common/mem_event.c
new file mode 100644
index 0000000..16ebdb5
--- /dev/null
+++ b/xen/common/mem_event.c
@@ -0,0 +1,742 @@
+/******************************************************************************
+ * mem_event.c
+ *
+ * Memory event support.
+ *
+ * Copyright (c) 2009 Citrix Systems, Inc. (Patrick Colp)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <xen/sched.h>
+#include <xen/event.h>
+#include <xen/wait.h>
+#include <xen/mem_event.h>
+#include <xen/mem_access.h>
+#include <asm/p2m.h>
+
+#ifdef HAS_MEM_PAGING
+#include <asm/mem_paging.h>
+#endif
+
+#ifdef HAS_MEM_SHARING
+#include <asm/mem_sharing.h>
+#endif
+
+#include <xsm/xsm.h>
+
+/* for public/io/ring.h macros */
+#define xen_mb() mb()
+#define xen_rmb() rmb()
+#define xen_wmb() wmb()
+
+#define mem_event_ring_lock_init(_med) spin_lock_init(&(_med)->ring_lock)
+#define mem_event_ring_lock(_med) spin_lock(&(_med)->ring_lock)
+#define mem_event_ring_unlock(_med) spin_unlock(&(_med)->ring_lock)
+
+static int mem_event_enable(
+ struct domain *d,
+ xen_domctl_mem_event_op_t *mec,
+ struct mem_event_domain *med,
+ int pause_flag,
+ int param,
+ xen_event_channel_notification_t notification_fn)
+{
+ int rc;
+ unsigned long ring_gfn = d->arch.hvm_domain.params[param];
+
+ /* Only one helper at a time. If the helper crashed,
+ * the ring is in an undefined state and so is the guest.
+ */
+ if ( med->ring_page )
+ return -EBUSY;
+
+ /* The parameter defaults to zero, and it should be
+ * set to something */
+ if ( ring_gfn == 0 )
+ return -ENOSYS;
+
+ mem_event_ring_lock_init(med);
+ mem_event_ring_lock(med);
+
+ rc = prepare_ring_for_helper(d, ring_gfn, &med->ring_pg_struct,
+ &med->ring_page);
+ if ( rc < 0 )
+ goto err;
+
+ /* Set the number of currently blocked vCPUs to 0. */
+ med->blocked = 0;
+
+ /* Allocate event channel */
+ rc = alloc_unbound_xen_event_channel(d->vcpu[0],
+ current->domain->domain_id,
+ notification_fn);
+ if ( rc < 0 )
+ goto err;
+
+ med->xen_port = mec->port = rc;
+
+ /* Prepare ring buffer */
+ FRONT_RING_INIT(&med->front_ring,
+ (mem_event_sring_t *)med->ring_page,
+ PAGE_SIZE);
+
+ /* Save the pause flag for this particular ring. */
+ med->pause_flag = pause_flag;
+
+ /* Initialize the last-chance wait queue. */
+ init_waitqueue_head(&med->wq);
+
+ mem_event_ring_unlock(med);
+ return 0;
+
+ err:
+ destroy_ring_for_helper(&med->ring_page,
+ med->ring_pg_struct);
+ mem_event_ring_unlock(med);
+
+ return rc;
+}
+
+static unsigned int mem_event_ring_available(struct mem_event_domain *med)
+{
+ int avail_req = RING_FREE_REQUESTS(&med->front_ring);
+ avail_req -= med->target_producers;
+ avail_req -= med->foreign_producers;
+
+ BUG_ON(avail_req < 0);
+
+ return avail_req;
+}
+
+/*
+ * mem_event_wake_blocked() will wakeup vcpus waiting for room in the
+ * ring. These vCPUs were paused on their way out after placing an event,
+ * but need to be resumed where the ring is capable of processing at least
+ * one event from them.
+ */
+static void mem_event_wake_blocked(struct domain *d, struct mem_event_domain *med)
+{
+ struct vcpu *v;
+ int online = d->max_vcpus;
+ unsigned int avail_req = mem_event_ring_available(med);
+
+ if ( avail_req == 0 || med->blocked == 0 )
+ return;
+
+ /*
+ * We ensure that we only have vCPUs online if there are enough free slots
+ * for their memory events to be processed. This will ensure that no
+ * memory events are lost (due to the fact that certain types of events
+ * cannot be replayed, we need to ensure that there is space in the ring
+ * for when they are hit).
+ * See comment below in mem_event_put_request().
+ */
+ for_each_vcpu ( d, v )
+ if ( test_bit(med->pause_flag, &v->pause_flags) )
+ online--;
+
+ ASSERT(online == (d->max_vcpus - med->blocked));
+
+ /* We remember which vcpu last woke up to avoid scanning always linearly
+ * from zero and starving higher-numbered vcpus under high load */
+ if ( d->vcpu )
+ {
+ int i, j, k;
+
+ for (i = med->last_vcpu_wake_up + 1, j = 0; j < d->max_vcpus; i++, j++)
+ {
+ k = i % d->max_vcpus;
+ v = d->vcpu[k];
+ if ( !v )
+ continue;
+
+ if ( !(med->blocked) || online >= avail_req )
+ break;
+
+ if ( test_and_clear_bit(med->pause_flag, &v->pause_flags) )
+ {
+ vcpu_unpause(v);
+ online++;
+ med->blocked--;
+ med->last_vcpu_wake_up = k;
+ }
+ }
+ }
+}
+
+/*
+ * In the event that a vCPU attempted to place an event in the ring and
+ * was unable to do so, it is queued on a wait queue. These are woken as
+ * needed, and take precedence over the blocked vCPUs.
+ */
+static void mem_event_wake_queued(struct domain *d, struct mem_event_domain *med)
+{
+ unsigned int avail_req = mem_event_ring_available(med);
+
+ if ( avail_req > 0 )
+ wake_up_nr(&med->wq, avail_req);
+}
+
+/*
+ * mem_event_wake() will wakeup all vcpus waiting for the ring to
+ * become available. If we have queued vCPUs, they get top priority. We
+ * are guaranteed that they will go through code paths that will eventually
+ * call mem_event_wake() again, ensuring that any blocked vCPUs will get
+ * unpaused once all the queued vCPUs have made it through.
+ */
+void mem_event_wake(struct domain *d, struct mem_event_domain *med)
+{
+ if (!list_empty(&med->wq.list))
+ mem_event_wake_queued(d, med);
+ else
+ mem_event_wake_blocked(d, med);
+}
+
+static int mem_event_disable(struct domain *d, struct mem_event_domain *med)
+{
+ if ( med->ring_page )
+ {
+ struct vcpu *v;
+
+ mem_event_ring_lock(med);
+
+ if ( !list_empty(&med->wq.list) )
+ {
+ mem_event_ring_unlock(med);
+ return -EBUSY;
+ }
+
+ /* Free domU's event channel and leave the other one unbound */
+ free_xen_event_channel(d->vcpu[0], med->xen_port);
+
+ /* Unblock all vCPUs */
+ for_each_vcpu ( d, v )
+ {
+ if ( test_and_clear_bit(med->pause_flag, &v->pause_flags) )
+ {
+ vcpu_unpause(v);
+ med->blocked--;
+ }
+ }
+
+ destroy_ring_for_helper(&med->ring_page,
+ med->ring_pg_struct);
+ mem_event_ring_unlock(med);
+ }
+
+ return 0;
+}
+
+static inline void mem_event_release_slot(struct domain *d,
+ struct mem_event_domain *med)
+{
+ /* Update the accounting */
+ if ( current->domain == d )
+ med->target_producers--;
+ else
+ med->foreign_producers--;
+
+ /* Kick any waiters */
+ mem_event_wake(d, med);
+}
+
+/*
+ * mem_event_mark_and_pause() tags vcpu and put it to sleep.
+ * The vcpu will resume execution in mem_event_wake_waiters().
+ */
+void mem_event_mark_and_pause(struct vcpu *v, struct mem_event_domain *med)
+{
+ if ( !test_and_set_bit(med->pause_flag, &v->pause_flags) )
+ {
+ vcpu_pause_nosync(v);
+ med->blocked++;
+ }
+}
+
+/*
+ * This must be preceded by a call to claim_slot(), and is guaranteed to
+ * succeed. As a side-effect however, the vCPU may be paused if the ring is
+ * overly full and its continued execution would cause stalling and excessive
+ * waiting. The vCPU will be automatically unpaused when the ring clears.
+ */
+void mem_event_put_request(struct domain *d,
+ struct mem_event_domain *med,
+ mem_event_request_t *req)
+{
+ mem_event_front_ring_t *front_ring;
+ int free_req;
+ unsigned int avail_req;
+ RING_IDX req_prod;
+
+ if ( current->domain != d )
+ {
+ req->flags |= MEM_EVENT_FLAG_FOREIGN;
+#ifndef NDEBUG
+ if ( !(req->flags & MEM_EVENT_FLAG_VCPU_PAUSED) )
+ gdprintk(XENLOG_G_WARNING, "d%dv%d was not paused.\n",
+ d->domain_id, req->vcpu_id);
+#endif
+ }
+
+ mem_event_ring_lock(med);
+
+ /* Due to the reservations, this step must succeed. */
+ front_ring = &med->front_ring;
+ free_req = RING_FREE_REQUESTS(front_ring);
+ ASSERT(free_req > 0);
+
+ /* Copy request */
+ req_prod = front_ring->req_prod_pvt;
+ memcpy(RING_GET_REQUEST(front_ring, req_prod), req, sizeof(*req));
+ req_prod++;
+
+ /* Update ring */
+ front_ring->req_prod_pvt = req_prod;
+ RING_PUSH_REQUESTS(front_ring);
+
+ /* We've actually *used* our reservation, so release the slot. */
+ mem_event_release_slot(d, med);
+
+ /* Give this vCPU a black eye if necessary, on the way out.
+ * See the comments above wake_blocked() for more information
+ * on how this mechanism works to avoid waiting. */
+ avail_req = mem_event_ring_available(med);
+ if( current->domain == d && avail_req < d->max_vcpus )
+ mem_event_mark_and_pause(current, med);
+
+ mem_event_ring_unlock(med);
+
+ notify_via_xen_event_channel(d, med->xen_port);
+}
+
+int mem_event_get_response(struct domain *d, struct mem_event_domain *med, mem_event_response_t *rsp)
+{
+ mem_event_front_ring_t *front_ring;
+ RING_IDX rsp_cons;
+
+ mem_event_ring_lock(med);
+
+ front_ring = &med->front_ring;
+ rsp_cons = front_ring->rsp_cons;
+
+ if ( !RING_HAS_UNCONSUMED_RESPONSES(front_ring) )
+ {
+ mem_event_ring_unlock(med);
+ return 0;
+ }
+
+ /* Copy response */
+ memcpy(rsp, RING_GET_RESPONSE(front_ring, rsp_cons), sizeof(*rsp));
+ rsp_cons++;
+
+ /* Update ring */
+ front_ring->rsp_cons = rsp_cons;
+ front_ring->sring->rsp_event = rsp_cons + 1;
+
+ /* Kick any waiters -- since we've just consumed an event,
+ * there may be additional space available in the ring. */
+ mem_event_wake(d, med);
+
+ mem_event_ring_unlock(med);
+
+ return 1;
+}
+
+void mem_event_cancel_slot(struct domain *d, struct mem_event_domain *med)
+{
+ mem_event_ring_lock(med);
+ mem_event_release_slot(d, med);
+ mem_event_ring_unlock(med);
+}
+
+static int mem_event_grab_slot(struct mem_event_domain *med, int foreign)
+{
+ unsigned int avail_req;
+
+ if ( !med->ring_page )
+ return -ENOSYS;
+
+ mem_event_ring_lock(med);
+
+ avail_req = mem_event_ring_available(med);
+ if ( avail_req == 0 )
+ {
+ mem_event_ring_unlock(med);
+ return -EBUSY;
+ }
+
+ if ( !foreign )
+ med->target_producers++;
+ else
+ med->foreign_producers++;
+
+ mem_event_ring_unlock(med);
+
+ return 0;
+}
+
+/* Simple try_grab wrapper for use in the wait_event() macro. */
+static int mem_event_wait_try_grab(struct mem_event_domain *med, int *rc)
+{
+ *rc = mem_event_grab_slot(med, 0);
+ return *rc;
+}
+
+/* Call mem_event_grab_slot() until the ring doesn't exist, or is available. */
+static int mem_event_wait_slot(struct mem_event_domain *med)
+{
+ int rc = -EBUSY;
+ wait_event(med->wq, mem_event_wait_try_grab(med, &rc) != -EBUSY);
+ return rc;
+}
+
+bool_t mem_event_check_ring(struct mem_event_domain *med)
+{
+ return (med->ring_page != NULL);
+}
+
+/*
+ * Determines whether or not the current vCPU belongs to the target domain,
+ * and calls the appropriate wait function. If it is a guest vCPU, then we
+ * use mem_event_wait_slot() to reserve a slot. As long as there is a ring,
+ * this function will always return 0 for a guest. For a non-guest, we check
+ * for space and return -EBUSY if the ring is not available.
+ *
+ * Return codes: -ENOSYS: the ring is not yet configured
+ * -EBUSY: the ring is busy
+ * 0: a spot has been reserved
+ *
+ */
+int __mem_event_claim_slot(struct domain *d, struct mem_event_domain *med,
+ bool_t allow_sleep)
+{
+ if ( (current->domain == d) && allow_sleep )
+ return mem_event_wait_slot(med);
+ else
+ return mem_event_grab_slot(med, (current->domain != d));
+}
+
+#ifdef HAS_MEM_PAGING
+/* Registered with Xen-bound event channel for incoming notifications. */
+static void mem_paging_notification(struct vcpu *v, unsigned int port)
+{
+ if ( likely(v->domain->mem_event->paging.ring_page != NULL) )
+ p2m_mem_paging_resume(v->domain);
+}
+#endif
+
+#ifdef HAS_MEM_ACCESS
+/* Registered with Xen-bound event channel for incoming notifications. */
+static void mem_access_notification(struct vcpu *v, unsigned int port)
+{
+ if ( likely(v->domain->mem_event->access.ring_page != NULL) )
+ mem_access_resume(v->domain);
+}
+#endif
+
+#ifdef HAS_MEM_SHARING
+/* Registered with Xen-bound event channel for incoming notifications. */
+static void mem_sharing_notification(struct vcpu *v, unsigned int port)
+{
+ if ( likely(v->domain->mem_event->share.ring_page != NULL) )
+ mem_sharing_sharing_resume(v->domain);
+}
+#endif
+
+int do_mem_event_op(int op, uint32_t domain, void *arg)
+{
+ int ret;
+ struct domain *d;
+
+ ret = rcu_lock_live_remote_domain_by_id(domain, &d);
+ if ( ret )
+ return ret;
+
+ ret = xsm_mem_event_op(XSM_DM_PRIV, d, op);
+ if ( ret )
+ goto out;
+
+ switch (op)
+ {
+#ifdef HAS_MEM_PAGING
+ case XENMEM_paging_op:
+ ret = mem_paging_memop(d, (xen_mem_event_op_t *) arg);
+ break;
+#endif
+#ifdef HAS_MEM_SHARING
+ case XENMEM_sharing_op:
+ ret = mem_sharing_memop(d, (xen_mem_sharing_op_t *) arg);
+ break;
+#endif
+ default:
+ ret = -ENOSYS;
+ }
+
+ out:
+ rcu_unlock_domain(d);
+ return ret;
+}
+
+/* Clean up on domain destruction */
+void mem_event_cleanup(struct domain *d)
+{
+#ifdef HAS_MEM_PAGING
+ if ( d->mem_event->paging.ring_page ) {
+ /* Destroying the wait queue head means waking up all
+ * queued vcpus. This will drain the list, allowing
+ * the disable routine to complete. It will also drop
+ * all domain refs the wait-queued vcpus are holding.
+ * Finally, because this code path involves previously
+ * pausing the domain (domain_kill), unpausing the
+ * vcpus causes no harm. */
+ destroy_waitqueue_head(&d->mem_event->paging.wq);
+ (void)mem_event_disable(d, &d->mem_event->paging);
+ }
+#endif
+#ifdef HAS_MEM_ACCESS
+ if ( d->mem_event->access.ring_page ) {
+ destroy_waitqueue_head(&d->mem_event->access.wq);
+ (void)mem_event_disable(d, &d->mem_event->access);
+ }
+#endif
+#ifdef HAS_MEM_SHARING
+ if ( d->mem_event->share.ring_page ) {
+ destroy_waitqueue_head(&d->mem_event->share.wq);
+ (void)mem_event_disable(d, &d->mem_event->share);
+ }
+#endif
+}
+
+int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
+ XEN_GUEST_HANDLE_PARAM(void) u_domctl)
+{
+ int rc;
+
+ rc = xsm_mem_event_control(XSM_PRIV, d, mec->mode, mec->op);
+ if ( rc )
+ return rc;
+
+ if ( unlikely(d == current->domain) )
+ {
+ gdprintk(XENLOG_INFO, "Tried to do a memory event op on itself.\n");
+ return -EINVAL;
+ }
+
+ if ( unlikely(d->is_dying) )
+ {
+ gdprintk(XENLOG_INFO, "Ignoring memory event op on dying domain %u\n",
+ d->domain_id);
+ return 0;
+ }
+
+ if ( unlikely(d->vcpu == NULL) || unlikely(d->vcpu[0] == NULL) )
+ {
+ gdprintk(XENLOG_INFO,
+ "Memory event op on a domain (%u) with no vcpus\n",
+ d->domain_id);
+ return -EINVAL;
+ }
+
+ rc = -ENOSYS;
+
+ switch ( mec->mode )
+ {
+#ifdef HAS_MEM_PAGING
+ case XEN_DOMCTL_MEM_EVENT_OP_PAGING:
+ {
+ struct mem_event_domain *med = &d->mem_event->paging;
+ rc = -EINVAL;
+
+ switch( mec->op )
+ {
+ case XEN_DOMCTL_MEM_EVENT_OP_PAGING_ENABLE:
+ {
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
+
+ rc = -EOPNOTSUPP;
+ /* pvh fixme: p2m_is_foreign types need addressing */
+ if ( is_pvh_vcpu(current) || is_pvh_domain(hardware_domain) )
+ break;
+
+ rc = -ENODEV;
+ /* Only HAP is supported */
+ if ( !hap_enabled(d) )
+ break;
+
+ /* No paging if iommu is used */
+ rc = -EMLINK;
+ if ( unlikely(need_iommu(d)) )
+ break;
+
+ rc = -EXDEV;
+ /* Disallow paging in a PoD guest */
+ if ( p2m->pod.entry_count )
+ break;
+
+ rc = mem_event_enable(d, mec, med, _VPF_mem_paging,
+ HVM_PARAM_PAGING_RING_PFN,
+ mem_paging_notification);
+ }
+ break;
+
+ case XEN_DOMCTL_MEM_EVENT_OP_PAGING_DISABLE:
+ {
+ if ( med->ring_page )
+ rc = mem_event_disable(d, med);
+ }
+ break;
+
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+ }
+ break;
+#endif
+
+#ifdef HAS_MEM_ACCESS
+ case XEN_DOMCTL_MEM_EVENT_OP_ACCESS:
+ {
+ struct mem_event_domain *med = &d->mem_event->access;
+ rc = -EINVAL;
+
+ switch( mec->op )
+ {
+ case XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE:
+ case XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE_INTROSPECTION:
+ {
+ rc = -ENODEV;
+ if ( !p2m_mem_event_sanity_check(d) )
+ break;
+
+ rc = mem_event_enable(d, mec, med, _VPF_mem_access,
+ HVM_PARAM_ACCESS_RING_PFN,
+ mem_access_notification);
+
+ if ( mec->op == XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE_INTROSPECTION
+ && !rc )
+ p2m_setup_introspection(d);
+
+ }
+ break;
+
+ case XEN_DOMCTL_MEM_EVENT_OP_ACCESS_DISABLE:
+ {
+ if ( med->ring_page )
+ {
+ rc = mem_event_disable(d, med);
+ d->arch.hvm_domain.introspection_enabled = 0;
+ }
+ }
+ break;
+
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+ }
+ break;
+#endif
+
+#ifdef HAS_MEM_SHARING
+ case XEN_DOMCTL_MEM_EVENT_OP_SHARING:
+ {
+ struct mem_event_domain *med = &d->mem_event->share;
+ rc = -EINVAL;
+
+ switch( mec->op )
+ {
+ case XEN_DOMCTL_MEM_EVENT_OP_SHARING_ENABLE:
+ {
+ rc = -EOPNOTSUPP;
+ /* pvh fixme: p2m_is_foreign types need addressing */
+ if ( is_pvh_vcpu(current) || is_pvh_domain(hardware_domain) )
+ break;
+
+ rc = -ENODEV;
+ /* Only HAP is supported */
+ if ( !hap_enabled(d) )
+ break;
+
+ rc = mem_event_enable(d, mec, med, _VPF_mem_sharing,
+ HVM_PARAM_SHARING_RING_PFN,
+ mem_sharing_notification);
+ }
+ break;
+
+ case XEN_DOMCTL_MEM_EVENT_OP_SHARING_DISABLE:
+ {
+ if ( med->ring_page )
+ rc = mem_event_disable(d, med);
+ }
+ break;
+
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+ }
+ break;
+#endif
+
+ default:
+ rc = -ENOSYS;
+ }
+
+ return rc;
+}
+
+void mem_event_vcpu_pause(struct vcpu *v)
+{
+ ASSERT(v == current);
+
+ atomic_inc(&v->mem_event_pause_count);
+ vcpu_pause_nosync(v);
+}
+
+void mem_event_vcpu_unpause(struct vcpu *v)
+{
+ int old, new, prev = v->mem_event_pause_count.counter;
+
+ /* All unpause requests as a result of toolstack responses. Prevent
+ * underflow of the vcpu pause count. */
+ do
+ {
+ old = prev;
+ new = old - 1;
+
+ if ( new < 0 )
+ {
+ printk(XENLOG_G_WARNING
+ "%pv mem_event: Too many unpause attempts\n", v);
+ return;
+ }
+
+ prev = cmpxchg(&v->mem_event_pause_count.counter, old, new);
+ } while ( prev != old );
+
+ vcpu_unpause(v);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/memory.c b/xen/common/memory.c
index 4d6ffee..9f21bd3 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -21,17 +21,14 @@
#include <xen/errno.h>
#include <xen/tmem.h>
#include <xen/tmem_xen.h>
+#include <xen/numa.h>
+#include <xen/mem_access.h>
+#include <xen/trace.h>
#include <asm/current.h>
#include <asm/hardirq.h>
#include <asm/p2m.h>
-#include <xen/numa.h>
#include <public/memory.h>
#include <xsm/xsm.h>
-#include <xen/trace.h>
-
-#ifndef is_domain_direct_mapped
-# define is_domain_direct_mapped(d) ((void)(d), 0)
-#endif
struct memop_args {
/* INPUT */
@@ -204,6 +201,12 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
p2m_mem_paging_drop_page(d, gmfn, p2mt);
return 1;
}
+ if ( p2mt == p2m_mmio_direct )
+ {
+ clear_mmio_p2m_entry(d, gmfn, _mfn(mfn));
+ put_gfn(d, gmfn);
+ return 1;
+ }
#else
mfn = gmfn_to_mfn(d, gmfn);
#endif
@@ -937,6 +940,10 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
break;
}
+ case XENMEM_access_op:
+ rc = mem_access_memop(cmd, guest_handle_cast(arg, xen_mem_access_op_t));
+ break;
+
case XENMEM_claim_pages:
if ( copy_from_guest(&reservation, arg, 1) )
return -EFAULT;
@@ -963,14 +970,208 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
break;
+ case XENMEM_get_vnumainfo:
+ {
+ struct xen_vnuma_topology_info topology;
+ struct domain *d;
+ unsigned int dom_vnodes, dom_vranges, dom_vcpus;
+ struct vnuma_info tmp;
+
+ /*
+ * Guest passes nr_vnodes, number of regions and nr_vcpus thus
+ * we know how much memory guest has allocated.
+ */
+ if ( copy_from_guest(&topology, arg, 1 ))
+ return -EFAULT;
+
+ if ( topology.pad != 0 )
+ return -EINVAL;
+
+ if ( (d = rcu_lock_domain_by_any_id(topology.domid)) == NULL )
+ return -ESRCH;
+
+ rc = xsm_get_vnumainfo(XSM_TARGET, d);
+ if ( rc )
+ {
+ rcu_unlock_domain(d);
+ return rc;
+ }
+
+ read_lock(&d->vnuma_rwlock);
+
+ if ( d->vnuma == NULL )
+ {
+ read_unlock(&d->vnuma_rwlock);
+ rcu_unlock_domain(d);
+ return -EOPNOTSUPP;
+ }
+
+ dom_vnodes = d->vnuma->nr_vnodes;
+ dom_vranges = d->vnuma->nr_vmemranges;
+ dom_vcpus = d->max_vcpus;
+
+ /*
+ * Copied from guest values may differ from domain vnuma config.
+ * Check here guest parameters make sure we dont overflow.
+ * Additionaly check padding.
+ */
+ if ( topology.nr_vnodes < dom_vnodes ||
+ topology.nr_vcpus < dom_vcpus ||
+ topology.nr_vmemranges < dom_vranges )
+ {
+ read_unlock(&d->vnuma_rwlock);
+ rcu_unlock_domain(d);
+
+ topology.nr_vnodes = dom_vnodes;
+ topology.nr_vcpus = dom_vcpus;
+ topology.nr_vmemranges = dom_vranges;
+
+ /* Copy back needed values. */
+ return __copy_to_guest(arg, &topology, 1) ? -EFAULT : -ENOBUFS;
+ }
+
+ read_unlock(&d->vnuma_rwlock);
+
+ tmp.vdistance = xmalloc_array(unsigned int, dom_vnodes * dom_vnodes);
+ tmp.vmemrange = xmalloc_array(xen_vmemrange_t, dom_vranges);
+ tmp.vcpu_to_vnode = xmalloc_array(unsigned int, dom_vcpus);
+
+ if ( tmp.vdistance == NULL ||
+ tmp.vmemrange == NULL ||
+ tmp.vcpu_to_vnode == NULL )
+ {
+ rc = -ENOMEM;
+ goto vnumainfo_out;
+ }
+
+ /*
+ * Check if vnuma info has changed and if the allocated arrays
+ * are not big enough.
+ */
+ read_lock(&d->vnuma_rwlock);
+
+ if ( dom_vnodes < d->vnuma->nr_vnodes ||
+ dom_vranges < d->vnuma->nr_vmemranges ||
+ dom_vcpus < d->max_vcpus )
+ {
+ read_unlock(&d->vnuma_rwlock);
+ rc = -EAGAIN;
+ goto vnumainfo_out;
+ }
+
+ dom_vnodes = d->vnuma->nr_vnodes;
+ dom_vranges = d->vnuma->nr_vmemranges;
+ dom_vcpus = d->max_vcpus;
+
+ memcpy(tmp.vmemrange, d->vnuma->vmemrange,
+ sizeof(*d->vnuma->vmemrange) * dom_vranges);
+ memcpy(tmp.vdistance, d->vnuma->vdistance,
+ sizeof(*d->vnuma->vdistance) * dom_vnodes * dom_vnodes);
+ memcpy(tmp.vcpu_to_vnode, d->vnuma->vcpu_to_vnode,
+ sizeof(*d->vnuma->vcpu_to_vnode) * dom_vcpus);
+
+ read_unlock(&d->vnuma_rwlock);
+
+ rc = -EFAULT;
+
+ if ( copy_to_guest(topology.vmemrange.h, tmp.vmemrange,
+ dom_vranges) != 0 )
+ goto vnumainfo_out;
+
+ if ( copy_to_guest(topology.vdistance.h, tmp.vdistance,
+ dom_vnodes * dom_vnodes) != 0 )
+ goto vnumainfo_out;
+
+ if ( copy_to_guest(topology.vcpu_to_vnode.h, tmp.vcpu_to_vnode,
+ dom_vcpus) != 0 )
+ goto vnumainfo_out;
+
+ topology.nr_vnodes = dom_vnodes;
+ topology.nr_vcpus = dom_vcpus;
+ topology.nr_vmemranges = dom_vranges;
+
+ rc = __copy_to_guest(arg, &topology, 1) ? -EFAULT : 0;
+
+ vnumainfo_out:
+ rcu_unlock_domain(d);
+
+ xfree(tmp.vdistance);
+ xfree(tmp.vmemrange);
+ xfree(tmp.vcpu_to_vnode);
+ break;
+ }
+
default:
- rc = arch_memory_op(op, arg);
+ rc = arch_memory_op(cmd, arg);
break;
}
return rc;
}
+void destroy_ring_for_helper(
+ void **_va, struct page_info *page)
+{
+ void *va = *_va;
+
+ if ( va != NULL )
+ {
+ unmap_domain_page_global(va);
+ put_page_and_type(page);
+ *_va = NULL;
+ }
+}
+
+int prepare_ring_for_helper(
+ struct domain *d, unsigned long gmfn, struct page_info **_page,
+ void **_va)
+{
+ struct page_info *page;
+ p2m_type_t p2mt;
+ void *va;
+
+ page = get_page_from_gfn(d, gmfn, &p2mt, P2M_UNSHARE);
+
+#ifdef HAS_MEM_PAGING
+ if ( p2m_is_paging(p2mt) )
+ {
+ if ( page )
+ put_page(page);
+ p2m_mem_paging_populate(d, gmfn);
+ return -ENOENT;
+ }
+#endif
+#ifdef HAS_MEM_SHARING
+ if ( p2m_is_shared(p2mt) )
+ {
+ if ( page )
+ put_page(page);
+ return -ENOENT;
+ }
+#endif
+
+ if ( !page )
+ return -EINVAL;
+
+ if ( !get_page_type(page, PGT_writable_page) )
+ {
+ put_page(page);
+ return -EINVAL;
+ }
+
+ va = __map_domain_page_global(page);
+ if ( va == NULL )
+ {
+ put_page_and_type(page);
+ return -ENOMEM;
+ }
+
+ *_va = va;
+ *_page = page;
+
+ return 0;
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 5cbdeb7..7b4092d 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -65,6 +65,13 @@ static bool_t opt_bootscrub __initdata = 1;
boolean_param("bootscrub", opt_bootscrub);
/*
+ * bootscrub_chunk -> Amount of bytes to scrub lockstep on non-SMT CPUs
+ * on all NUMA nodes.
+ */
+static unsigned long __initdata opt_bootscrub_chunk = MB(128);
+size_param("bootscrub_chunk", opt_bootscrub_chunk);
+
+/*
* Bit width of the DMA heap -- used to override NUMA-node-first.
* allocation strategy, which can otherwise exhaust low memory.
*/
@@ -90,6 +97,16 @@ static struct bootmem_region {
} *__initdata bootmem_region_list;
static unsigned int __initdata nr_bootmem_regions;
+struct scrub_region {
+ unsigned long offset;
+ unsigned long start;
+ unsigned long per_cpu_sz;
+ unsigned long rem;
+ cpumask_t cpus;
+};
+static struct scrub_region __initdata region[MAX_NUMNODES];
+static unsigned long __initdata chunk_size;
+
static void __init boot_bug(int line)
{
panic("Boot BUG at %s:%d", __FILE__, line);
@@ -1256,42 +1273,203 @@ void __init end_boot_allocator(void)
printk("\n");
}
+static void __init smp_scrub_heap_pages(void *data)
+{
+ unsigned long mfn, start, end;
+ struct page_info *pg;
+ struct scrub_region *r;
+ unsigned int temp_cpu, node, cpu_idx = 0;
+ unsigned int cpu = smp_processor_id();
+
+ if ( data )
+ r = data;
+ else
+ {
+ node = cpu_to_node(cpu);
+ if ( node == NUMA_NO_NODE )
+ return;
+ r = ®ion[node];
+ }
+
+ /* Determine the current CPU's index into CPU's linked to this node. */
+ for_each_cpu ( temp_cpu, &r->cpus )
+ {
+ if ( cpu == temp_cpu )
+ break;
+ cpu_idx++;
+ }
+
+ /* Calculate the starting mfn for this CPU's memory block. */
+ start = r->start + (r->per_cpu_sz * cpu_idx) + r->offset;
+
+ /* Calculate the end mfn into this CPU's memory block for this iteration. */
+ if ( r->offset + chunk_size >= r->per_cpu_sz )
+ {
+ end = r->start + (r->per_cpu_sz * cpu_idx) + r->per_cpu_sz;
+
+ if ( r->rem && (cpumask_weight(&r->cpus) - 1 == cpu_idx) )
+ end += r->rem;
+ }
+ else
+ end = start + chunk_size;
+
+ for ( mfn = start; mfn < end; mfn++ )
+ {
+ pg = mfn_to_page(mfn);
+
+ /* Check the mfn is valid and page is free. */
+ if ( !mfn_valid(mfn) || !page_state_is(pg, free) )
+ continue;
+
+ scrub_one_page(pg);
+ }
+}
+
+static int __init find_non_smt(unsigned int node, cpumask_t *dest)
+{
+ cpumask_t node_cpus;
+ unsigned int i, cpu;
+
+ cpumask_and(&node_cpus, &node_to_cpumask(node), &cpu_online_map);
+ cpumask_clear(dest);
+ for_each_cpu ( i, &node_cpus )
+ {
+ if ( cpumask_intersects(dest, per_cpu(cpu_sibling_mask, i)) )
+ continue;
+ cpu = cpumask_first(per_cpu(cpu_sibling_mask, i));
+ cpumask_set_cpu(cpu, dest);
+ }
+ return cpumask_weight(dest);
+}
+
/*
- * Scrub all unallocated pages in all heap zones. This function is more
- * convoluted than appears necessary because we do not want to continuously
- * hold the lock while scrubbing very large memory areas.
+ * Scrub all unallocated pages in all heap zones. This function uses all
+ * online cpu's to scrub the memory in parallel.
*/
void __init scrub_heap_pages(void)
{
- unsigned long mfn;
- struct page_info *pg;
+ cpumask_t node_cpus, all_worker_cpus;
+ unsigned int i, j;
+ unsigned long offset, max_per_cpu_sz = 0;
+ unsigned long start, end;
+ unsigned long rem = 0;
+ int last_distance, best_node;
+ int cpus;
if ( !opt_bootscrub )
return;
- printk("Scrubbing Free RAM: ");
+ cpumask_clear(&all_worker_cpus);
+ /* Scrub block size. */
+ chunk_size = opt_bootscrub_chunk >> PAGE_SHIFT;
+ if ( chunk_size == 0 )
+ chunk_size = MB(128) >> PAGE_SHIFT;
- for ( mfn = first_valid_mfn; mfn < max_page; mfn++ )
+ /* Round #0 - figure out amounts and which CPUs to use. */
+ for_each_online_node ( i )
{
+ if ( !node_spanned_pages(i) )
+ continue;
+ /* Calculate Node memory start and end address. */
+ start = max(node_start_pfn(i), first_valid_mfn);
+ end = min(node_start_pfn(i) + node_spanned_pages(i), max_page);
+ /* Just in case NODE has 1 page and starts below first_valid_mfn. */
+ end = max(end, start);
+ /* CPUs that are online and on this node (if none, that it is OK). */
+ cpus = find_non_smt(i, &node_cpus);
+ cpumask_or(&all_worker_cpus, &all_worker_cpus, &node_cpus);
+ if ( cpus <= 0 )
+ {
+ /* No CPUs on this node. Round #2 will take of it. */
+ rem = 0;
+ region[i].per_cpu_sz = (end - start);
+ }
+ else
+ {
+ rem = (end - start) % cpus;
+ region[i].per_cpu_sz = (end - start) / cpus;
+ if ( region[i].per_cpu_sz > max_per_cpu_sz )
+ max_per_cpu_sz = region[i].per_cpu_sz;
+ }
+ region[i].start = start;
+ region[i].rem = rem;
+ cpumask_copy(®ion[i].cpus, &node_cpus);
+ }
+
+ printk("Scrubbing Free RAM on %d nodes using %d CPUs\n", num_online_nodes(),
+ cpumask_weight(&all_worker_cpus));
+
+ /* Round: #1 - do NUMA nodes with CPUs. */
+ for ( offset = 0; offset < max_per_cpu_sz; offset += chunk_size )
+ {
+ for_each_online_node ( i )
+ region[i].offset = offset;
+
process_pending_softirqs();
- pg = mfn_to_page(mfn);
+ spin_lock(&heap_lock);
+ on_selected_cpus(&all_worker_cpus, smp_scrub_heap_pages, NULL, 1);
+ spin_unlock(&heap_lock);
- /* Quick lock-free check. */
- if ( !mfn_valid(mfn) || !page_state_is(pg, free) )
+ printk(".");
+ }
+
+ /*
+ * Round #2: NUMA nodes with no CPUs get scrubbed with CPUs on the node
+ * closest to us and with CPUs.
+ */
+ for_each_online_node ( i )
+ {
+ node_cpus = node_to_cpumask(i);
+
+ if ( !cpumask_empty(&node_cpus) )
continue;
- /* Every 100MB, print a progress dot. */
- if ( (mfn % ((100*1024*1024)/PAGE_SIZE)) == 0 )
- printk(".");
+ last_distance = INT_MAX;
+ best_node = first_node(node_online_map);
+ /* Figure out which NODE CPUs are close. */
+ for_each_online_node ( j )
+ {
+ int distance;
- spin_lock(&heap_lock);
+ if ( cpumask_empty(&node_to_cpumask(j)) )
+ continue;
+
+ distance = __node_distance(i, j);
+ if ( distance < last_distance )
+ {
+ last_distance = distance;
+ best_node = j;
+ }
+ }
+ /*
+ * Use CPUs from best node, and if there are no CPUs on the
+ * first node (the default) use the BSP.
+ */
+ cpus = find_non_smt(best_node, &node_cpus);
+ if ( cpus == 0 )
+ {
+ cpumask_set_cpu(smp_processor_id(), &node_cpus);
+ cpus = 1;
+ }
+ /* We already have the node information from round #0. */
+ region[i].rem = region[i].per_cpu_sz % cpus;
+ region[i].per_cpu_sz /= cpus;
+ max_per_cpu_sz = region[i].per_cpu_sz;
+ cpumask_copy(®ion[i].cpus, &node_cpus);
- /* Re-check page status with lock held. */
- if ( page_state_is(pg, free) )
- scrub_one_page(pg);
+ for ( offset = 0; offset < max_per_cpu_sz; offset += chunk_size )
+ {
+ region[i].offset = offset;
- spin_unlock(&heap_lock);
+ process_pending_softirqs();
+
+ spin_lock(&heap_lock);
+ on_selected_cpus(&node_cpus, smp_scrub_heap_pages, ®ion[i], 1);
+ spin_unlock(&heap_lock);
+
+ printk(".");
+ }
}
printk("done.\n");
@@ -1546,47 +1724,52 @@ void free_domheap_pages(struct page_info *pg, unsigned int order)
spin_unlock_recursive(&d->page_alloc_lock);
}
- else if ( likely(d != NULL) && likely(d != dom_cow) )
+ else
{
- /* NB. May recursively lock from relinquish_memory(). */
- spin_lock_recursive(&d->page_alloc_lock);
+ bool_t scrub;
- for ( i = 0; i < (1 << order); i++ )
+ if ( likely(d) && likely(d != dom_cow) )
{
- BUG_ON((pg[i].u.inuse.type_info & PGT_count_mask) != 0);
- page_list_del2(&pg[i], &d->page_list, &d->arch.relmem_list);
- }
+ /* NB. May recursively lock from relinquish_memory(). */
+ spin_lock_recursive(&d->page_alloc_lock);
- drop_dom_ref = !domain_adjust_tot_pages(d, -(1 << order));
+ for ( i = 0; i < (1 << order); i++ )
+ {
+ BUG_ON((pg[i].u.inuse.type_info & PGT_count_mask) != 0);
+ page_list_del2(&pg[i], &d->page_list, &d->arch.relmem_list);
+ }
- spin_unlock_recursive(&d->page_alloc_lock);
+ drop_dom_ref = !domain_adjust_tot_pages(d, -(1 << order));
- /*
- * Normally we expect a domain to clear pages before freeing them, if
- * it cares about the secrecy of their contents. However, after a
- * domain has died we assume responsibility for erasure.
- */
- if ( unlikely(d->is_dying) )
+ spin_unlock_recursive(&d->page_alloc_lock);
+
+ /*
+ * Normally we expect a domain to clear pages before freeing them,
+ * if it cares about the secrecy of their contents. However, after
+ * a domain has died we assume responsibility for erasure.
+ */
+ scrub = !!d->is_dying;
+ }
+ else
+ {
+ /*
+ * All we need to check is that on dom_cow only order-0 chunks
+ * make it here. Due to the if() above, the only two possible
+ * cases right now are d == NULL and d == dom_cow. To protect
+ * against relaxation of that if() condition without updating the
+ * check here, don't check d != dom_cow for now.
+ */
+ ASSERT(!d || !order);
+ drop_dom_ref = 0;
+ scrub = 1;
+ }
+
+ if ( unlikely(scrub) )
for ( i = 0; i < (1 << order); i++ )
scrub_one_page(&pg[i]);
free_heap_pages(pg, order);
}
- else if ( unlikely(d == dom_cow) )
- {
- ASSERT(order == 0);
- scrub_one_page(pg);
- free_heap_pages(pg, 0);
- drop_dom_ref = 0;
- }
- else
- {
- /* Freeing anonymous domain-heap pages. */
- for ( i = 0; i < (1 << order); i++ )
- scrub_one_page(&pg[i]);
- free_heap_pages(pg, order);
- drop_dom_ref = 0;
- }
if ( drop_dom_ref )
put_domain(d);
diff --git a/xen/common/pdx.c b/xen/common/pdx.c
new file mode 100644
index 0000000..cf8b9b5
--- /dev/null
+++ b/xen/common/pdx.c
@@ -0,0 +1,117 @@
+/******************************************************************************
+ * Original code extracted from arch/x86/x86_64/mm.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/bitops.h>
+
+/* Parameters for PFN/MADDR compression. */
+unsigned long __read_mostly max_pdx;
+unsigned long __read_mostly pfn_pdx_bottom_mask = ~0UL;
+unsigned long __read_mostly ma_va_bottom_mask = ~0UL;
+unsigned long __read_mostly pfn_top_mask = 0;
+unsigned long __read_mostly ma_top_mask = 0;
+unsigned long __read_mostly pfn_hole_mask = 0;
+unsigned int __read_mostly pfn_pdx_hole_shift = 0;
+
+unsigned long __read_mostly pdx_group_valid[BITS_TO_LONGS(
+ (FRAMETABLE_NR + PDX_GROUP_COUNT - 1) / PDX_GROUP_COUNT)] = { [0] = 1 };
+
+int __mfn_valid(unsigned long mfn)
+{
+ return likely(mfn < max_page) &&
+ likely(!(mfn & pfn_hole_mask)) &&
+ likely(test_bit(pfn_to_pdx(mfn) / PDX_GROUP_COUNT,
+ pdx_group_valid));
+}
+
+/* Sets all bits from the most-significant 1-bit down to the LSB */
+static u64 __init fill_mask(u64 mask)
+{
+ while (mask & (mask + 1))
+ mask |= mask + 1;
+ return mask;
+}
+
+u64 __init pdx_init_mask(u64 base_addr)
+{
+ return fill_mask(base_addr - 1);
+}
+
+u64 __init pdx_region_mask(u64 base, u64 len)
+{
+ return fill_mask(base ^ (base + len - 1));
+}
+
+void set_pdx_range(unsigned long smfn, unsigned long emfn)
+{
+ unsigned long idx, eidx;
+
+ idx = pfn_to_pdx(smfn) / PDX_GROUP_COUNT;
+ eidx = (pfn_to_pdx(emfn - 1) + PDX_GROUP_COUNT) / PDX_GROUP_COUNT;
+
+ for ( ; idx < eidx; ++idx )
+ __set_bit(idx, pdx_group_valid);
+}
+
+void __init pfn_pdx_hole_setup(unsigned long mask)
+{
+ unsigned int i, j, bottom_shift = 0, hole_shift = 0;
+
+ /*
+ * We skip the first MAX_ORDER bits, as we never want to compress them.
+ * This guarantees that page-pointer arithmetic remains valid within
+ * contiguous aligned ranges of 2^MAX_ORDER pages. Among others, our
+ * buddy allocator relies on this assumption.
+ */
+ for ( j = MAX_ORDER-1; ; )
+ {
+ i = find_next_zero_bit(&mask, BITS_PER_LONG, j);
+ j = find_next_bit(&mask, BITS_PER_LONG, i);
+ if ( j >= BITS_PER_LONG )
+ break;
+ if ( j - i > hole_shift )
+ {
+ hole_shift = j - i;
+ bottom_shift = i;
+ }
+ }
+ if ( !hole_shift )
+ return;
+
+ printk(KERN_INFO "PFN compression on bits %u...%u\n",
+ bottom_shift, bottom_shift + hole_shift - 1);
+
+ pfn_pdx_hole_shift = hole_shift;
+ pfn_pdx_bottom_mask = (1UL << bottom_shift) - 1;
+ ma_va_bottom_mask = (PAGE_SIZE << bottom_shift) - 1;
+ pfn_hole_mask = ((1UL << hole_shift) - 1) << bottom_shift;
+ pfn_top_mask = ~(pfn_pdx_bottom_mask | pfn_hole_mask);
+ ma_top_mask = pfn_top_mask << PAGE_SHIFT;
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/rangeset.c b/xen/common/rangeset.c
index f09c0c4..116d5dc 100644
--- a/xen/common/rangeset.c
+++ b/xen/common/rangeset.c
@@ -25,7 +25,10 @@ struct rangeset {
/* Ordered list of ranges contained in this set, and protecting lock. */
struct list_head range_list;
- spinlock_t lock;
+
+ /* Number of ranges that can be allocated */
+ long nr_ranges;
+ rwlock_t lock;
/* Pretty-printing name. */
char name[32];
@@ -81,12 +84,30 @@ static void insert_range(
/* Remove a range from its list and free it. */
static void destroy_range(
- struct range *x)
+ struct rangeset *r, struct range *x)
{
+ r->nr_ranges++;
+
list_del(&x->list);
xfree(x);
}
+/* Allocate a new range */
+static struct range *alloc_range(
+ struct rangeset *r)
+{
+ struct range *x;
+
+ if ( r->nr_ranges == 0 )
+ return NULL;
+
+ x = xmalloc(struct range);
+ if ( x )
+ --r->nr_ranges;
+
+ return x;
+}
+
/*****************************
* Core public functions
*/
@@ -99,7 +120,7 @@ int rangeset_add_range(
ASSERT(s <= e);
- spin_lock(&r->lock);
+ write_lock(&r->lock);
x = find_range(r, s);
y = find_range(r, e);
@@ -108,7 +129,7 @@ int rangeset_add_range(
{
if ( (x == NULL) || ((x->e < s) && ((x->e + 1) != s)) )
{
- x = xmalloc(struct range);
+ x = alloc_range(r);
if ( x == NULL )
{
rc = -ENOMEM;
@@ -143,7 +164,7 @@ int rangeset_add_range(
y = next_range(r, x);
if ( (y == NULL) || (y->e > x->e) )
break;
- destroy_range(y);
+ destroy_range(r, y);
}
}
@@ -151,11 +172,11 @@ int rangeset_add_range(
if ( (y != NULL) && ((x->e + 1) == y->s) )
{
x->e = y->e;
- destroy_range(y);
+ destroy_range(r, y);
}
out:
- spin_unlock(&r->lock);
+ write_unlock(&r->lock);
return rc;
}
@@ -167,7 +188,7 @@ int rangeset_remove_range(
ASSERT(s <= e);
- spin_lock(&r->lock);
+ write_lock(&r->lock);
x = find_range(r, s);
y = find_range(r, e);
@@ -179,7 +200,7 @@ int rangeset_remove_range(
if ( (x->s < s) && (x->e > e) )
{
- y = xmalloc(struct range);
+ y = alloc_range(r);
if ( y == NULL )
{
rc = -ENOMEM;
@@ -193,7 +214,7 @@ int rangeset_remove_range(
insert_range(r, x, y);
}
else if ( (x->s == s) && (x->e <= e) )
- destroy_range(x);
+ destroy_range(r, x);
else if ( x->s == s )
x->s = e + 1;
else if ( x->e <= e )
@@ -214,16 +235,16 @@ int rangeset_remove_range(
{
t = x;
x = next_range(r, x);
- destroy_range(t);
+ destroy_range(r, t);
}
x->s = e + 1;
if ( x->s > x->e )
- destroy_range(x);
+ destroy_range(r, x);
}
out:
- spin_unlock(&r->lock);
+ write_unlock(&r->lock);
return rc;
}
@@ -235,10 +256,10 @@ int rangeset_contains_range(
ASSERT(s <= e);
- spin_lock(&r->lock);
+ read_lock(&r->lock);
x = find_range(r, s);
contains = (x && (x->e >= e));
- spin_unlock(&r->lock);
+ read_unlock(&r->lock);
return contains;
}
@@ -251,10 +272,10 @@ int rangeset_overlaps_range(
ASSERT(s <= e);
- spin_lock(&r->lock);
+ read_lock(&r->lock);
x = find_range(r, e);
overlaps = (x && (s <= x->e));
- spin_unlock(&r->lock);
+ read_unlock(&r->lock);
return overlaps;
}
@@ -266,13 +287,13 @@ int rangeset_report_ranges(
struct range *x;
int rc = 0;
- spin_lock(&r->lock);
+ read_lock(&r->lock);
for ( x = find_range(r, s); x && (x->s <= e) && !rc; x = next_range(r, x) )
if ( x->e >= s )
rc = cb(max(x->s, s), min(x->e, e), ctxt);
- spin_unlock(&r->lock);
+ read_unlock(&r->lock);
return rc;
}
@@ -310,8 +331,9 @@ struct rangeset *rangeset_new(
if ( r == NULL )
return NULL;
- spin_lock_init(&r->lock);
+ rwlock_init(&r->lock);
INIT_LIST_HEAD(&r->range_list);
+ r->nr_ranges = -1;
BUG_ON(flags & ~RANGESETF_prettyprint_hex);
r->flags = flags;
@@ -351,11 +373,17 @@ void rangeset_destroy(
}
while ( (x = first_range(r)) != NULL )
- destroy_range(x);
+ destroy_range(r, x);
xfree(r);
}
+void rangeset_limit(
+ struct rangeset *r, unsigned int limit)
+{
+ r->nr_ranges = limit;
+}
+
void rangeset_domain_initialise(
struct domain *d)
{
@@ -380,6 +408,29 @@ void rangeset_domain_destroy(
}
}
+void rangeset_swap(struct rangeset *a, struct rangeset *b)
+{
+ LIST_HEAD(tmp);
+
+ if ( a < b )
+ {
+ write_lock(&a->lock);
+ write_lock(&b->lock);
+ }
+ else
+ {
+ write_lock(&b->lock);
+ write_lock(&a->lock);
+ }
+
+ list_splice_init(&a->range_list, &tmp);
+ list_splice_init(&b->range_list, &a->range_list);
+ list_splice(&tmp, &b->range_list);
+
+ write_unlock(&a->lock);
+ write_unlock(&b->lock);
+}
+
/*****************************
* Pretty-printing functions
*/
@@ -395,7 +446,7 @@ void rangeset_printk(
int nr_printed = 0;
struct range *x;
- spin_lock(&r->lock);
+ read_lock(&r->lock);
printk("%-10s {", r->name);
@@ -414,7 +465,7 @@ void rangeset_printk(
printk(" }");
- spin_unlock(&r->lock);
+ read_unlock(&r->lock);
}
void rangeset_domain_printk(
@@ -438,3 +489,13 @@ void rangeset_domain_printk(
spin_unlock(&d->rangesets_lock);
}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/sched_credit.c b/xen/common/sched_credit.c
index db5512e..8b02b7b 100644
--- a/xen/common/sched_credit.c
+++ b/xen/common/sched_credit.c
@@ -112,10 +112,24 @@
/*
- * Node Balancing
+ * Hard and soft affinity load balancing.
+ *
+ * Idea is each vcpu has some pcpus that it prefers, some that it does not
+ * prefer but is OK with, and some that it cannot run on at all. The first
+ * set of pcpus are the ones that are both in the soft affinity *and* in the
+ * hard affinity; the second set of pcpus are the ones that are in the hard
+ * affinity but *not* in the soft affinity; the third set of pcpus are the
+ * ones that are not in the hard affinity.
+ *
+ * We implement a two step balancing logic. Basically, every time there is
+ * the need to decide where to run a vcpu, we first check the soft affinity
+ * (well, actually, the && between soft and hard affinity), to see if we can
+ * send it where it prefers to (and can) run on. However, if the first step
+ * does not find any suitable and free pcpu, we fall back checking the hard
+ * affinity.
*/
-#define CSCHED_BALANCE_NODE_AFFINITY 0
-#define CSCHED_BALANCE_CPU_AFFINITY 1
+#define CSCHED_BALANCE_SOFT_AFFINITY 0
+#define CSCHED_BALANCE_HARD_AFFINITY 1
/*
* Boot parameters
@@ -138,7 +152,7 @@ struct csched_pcpu {
/*
* Convenience macro for accessing the per-PCPU cpumask we need for
- * implementing the two steps (vcpu and node affinity) balancing logic.
+ * implementing the two steps (soft and hard affinity) balancing logic.
* It is stored in csched_pcpu so that serialization is not an issue,
* as there is a csched_pcpu for each PCPU and we always hold the
* runqueue spin-lock when using this.
@@ -178,9 +192,6 @@ struct csched_dom {
struct list_head active_vcpu;
struct list_head active_sdom_elem;
struct domain *dom;
- /* cpumask translated from the domain's node-affinity.
- * Basically, the CPUs we prefer to be scheduled on. */
- cpumask_var_t node_affinity_cpumask;
uint16_t active_vcpu_count;
uint16_t weight;
uint16_t cap;
@@ -261,59 +272,28 @@ __runq_remove(struct csched_vcpu *svc)
list_del_init(&svc->runq_elem);
}
-/*
- * Translates node-affinity mask into a cpumask, so that we can use it during
- * actual scheduling. That of course will contain all the cpus from all the
- * set nodes in the original node-affinity mask.
- *
- * Note that any serialization needed to access mask safely is complete
- * responsibility of the caller of this function/hook.
- */
-static void csched_set_node_affinity(
- const struct scheduler *ops,
- struct domain *d,
- nodemask_t *mask)
-{
- struct csched_dom *sdom;
- int node;
-
- /* Skip idle domain since it doesn't even have a node_affinity_cpumask */
- if ( unlikely(is_idle_domain(d)) )
- return;
-
- sdom = CSCHED_DOM(d);
- cpumask_clear(sdom->node_affinity_cpumask);
- for_each_node_mask( node, *mask )
- cpumask_or(sdom->node_affinity_cpumask, sdom->node_affinity_cpumask,
- &node_to_cpumask(node));
-}
#define for_each_csched_balance_step(step) \
- for ( (step) = 0; (step) <= CSCHED_BALANCE_CPU_AFFINITY; (step)++ )
+ for ( (step) = 0; (step) <= CSCHED_BALANCE_HARD_AFFINITY; (step)++ )
/*
- * vcpu-affinity balancing is always necessary and must never be skipped.
- * OTOH, if a domain's node-affinity is said to be automatically computed
- * (or if it just spans all the nodes), we can safely avoid dealing with
- * node-affinity entirely.
+ * Hard affinity balancing is always necessary and must never be skipped.
+ * OTOH, if the vcpu's soft affinity is full (it spans all the possible
+ * pcpus) we can safely avoid dealing with it entirely.
*
- * Node-affinity is also deemed meaningless in case it has empty
- * intersection with mask, to cover the cases where using the node-affinity
+ * A vcpu's soft affinity is also deemed meaningless in case it has empty
+ * intersection with mask, to cover the cases where using the soft affinity
* mask seems legit, but would instead led to trying to schedule the vcpu
* on _no_ pcpu! Typical use cases are for mask to be equal to the vcpu's
- * vcpu-affinity, or to the && of vcpu-affinity and the set of online cpus
+ * hard affinity, or to the && of hard affinity and the set of online cpus
* in the domain's cpupool.
*/
-static inline int __vcpu_has_node_affinity(const struct vcpu *vc,
+static inline int __vcpu_has_soft_affinity(const struct vcpu *vc,
const cpumask_t *mask)
{
- const struct domain *d = vc->domain;
- const struct csched_dom *sdom = CSCHED_DOM(d);
-
- if ( d->auto_node_affinity
- || cpumask_full(sdom->node_affinity_cpumask)
- || !cpumask_intersects(sdom->node_affinity_cpumask, mask) )
+ if ( cpumask_full(vc->cpu_soft_affinity)
+ || !cpumask_intersects(vc->cpu_soft_affinity, mask) )
return 0;
return 1;
@@ -321,24 +301,23 @@ static inline int __vcpu_has_node_affinity(const struct vcpu *vc,
/*
* Each csched-balance step uses its own cpumask. This function determines
- * which one (given the step) and copies it in mask. For the node-affinity
- * balancing step, the pcpus that are not part of vc's vcpu-affinity are
+ * which one (given the step) and copies it in mask. For the soft affinity
+ * balancing step, the pcpus that are not part of vc's hard affinity are
* filtered out from the result, to avoid running a vcpu where it would
* like, but is not allowed to!
*/
static void
csched_balance_cpumask(const struct vcpu *vc, int step, cpumask_t *mask)
{
- if ( step == CSCHED_BALANCE_NODE_AFFINITY )
+ if ( step == CSCHED_BALANCE_SOFT_AFFINITY )
{
- cpumask_and(mask, CSCHED_DOM(vc->domain)->node_affinity_cpumask,
- vc->cpu_affinity);
+ cpumask_and(mask, vc->cpu_soft_affinity, vc->cpu_hard_affinity);
if ( unlikely(cpumask_empty(mask)) )
- cpumask_copy(mask, vc->cpu_affinity);
+ cpumask_copy(mask, vc->cpu_hard_affinity);
}
- else /* step == CSCHED_BALANCE_CPU_AFFINITY */
- cpumask_copy(mask, vc->cpu_affinity);
+ else /* step == CSCHED_BALANCE_HARD_AFFINITY */
+ cpumask_copy(mask, vc->cpu_hard_affinity);
}
static void burn_credits(struct csched_vcpu *svc, s_time_t now)
@@ -398,16 +377,16 @@ __runq_tickle(unsigned int cpu, struct csched_vcpu *new)
else if ( !idlers_empty )
{
/*
- * Node and vcpu-affinity balancing loop. For vcpus without
- * a useful node-affinity, consider vcpu-affinity only.
+ * Soft and hard affinity balancing loop. For vcpus without
+ * a useful soft affinity, consider hard affinity only.
*/
for_each_csched_balance_step( balance_step )
{
int new_idlers_empty;
- if ( balance_step == CSCHED_BALANCE_NODE_AFFINITY
- && !__vcpu_has_node_affinity(new->vcpu,
- new->vcpu->cpu_affinity) )
+ if ( balance_step == CSCHED_BALANCE_SOFT_AFFINITY
+ && !__vcpu_has_soft_affinity(new->vcpu,
+ new->vcpu->cpu_hard_affinity) )
continue;
/* Are there idlers suitable for new (for this balance step)? */
@@ -418,11 +397,11 @@ __runq_tickle(unsigned int cpu, struct csched_vcpu *new)
/*
* Let's not be too harsh! If there aren't idlers suitable
- * for new in its node-affinity mask, make sure we check its
- * vcpu-affinity as well, before taking final decisions.
+ * for new in its soft affinity mask, make sure we check its
+ * hard affinity as well, before taking final decisions.
*/
if ( new_idlers_empty
- && balance_step == CSCHED_BALANCE_NODE_AFFINITY )
+ && balance_step == CSCHED_BALANCE_SOFT_AFFINITY )
continue;
/*
@@ -642,30 +621,30 @@ _csched_cpu_pick(const struct scheduler *ops, struct vcpu *vc, bool_t commit)
/* Store in cpus the mask of online cpus on which the domain can run */
online = cpupool_scheduler_cpumask(vc->domain->cpupool);
- cpumask_and(&cpus, vc->cpu_affinity, online);
+ cpumask_and(&cpus, vc->cpu_hard_affinity, online);
for_each_csched_balance_step( balance_step )
{
/*
* We want to pick up a pcpu among the ones that are online and
* can accommodate vc, which is basically what we computed above
- * and stored in cpus. As far as vcpu-affinity is concerned,
+ * and stored in cpus. As far as hard affinity is concerned,
* there always will be at least one of these pcpus, hence cpus
* is never empty and the calls to cpumask_cycle() and
* cpumask_test_cpu() below are ok.
*
- * On the other hand, when considering node-affinity too, it
+ * On the other hand, when considering soft affinity too, it
* is possible for the mask to become empty (for instance, if the
* domain has been put in a cpupool that does not contain any of the
- * nodes in its node-affinity), which would result in the ASSERT()-s
+ * pcpus in its soft affinity), which would result in the ASSERT()-s
* inside cpumask_*() operations triggering (in debug builds).
*
- * Therefore, in this case, we filter the node-affinity mask against
- * cpus and, if the result is empty, we just skip the node-affinity
+ * Therefore, in this case, we filter the soft affinity mask against
+ * cpus and, if the result is empty, we just skip the soft affinity
* balancing step all together.
*/
- if ( balance_step == CSCHED_BALANCE_NODE_AFFINITY
- && !__vcpu_has_node_affinity(vc, &cpus) )
+ if ( balance_step == CSCHED_BALANCE_SOFT_AFFINITY
+ && !__vcpu_has_soft_affinity(vc, &cpus) )
continue;
/* Pick an online CPU from the proper affinity mask */
@@ -1122,13 +1101,6 @@ csched_alloc_domdata(const struct scheduler *ops, struct domain *dom)
if ( sdom == NULL )
return NULL;
- if ( !alloc_cpumask_var(&sdom->node_affinity_cpumask) )
- {
- xfree(sdom);
- return NULL;
- }
- cpumask_setall(sdom->node_affinity_cpumask);
-
/* Initialize credit and weight */
INIT_LIST_HEAD(&sdom->active_vcpu);
INIT_LIST_HEAD(&sdom->active_sdom_elem);
@@ -1158,9 +1130,6 @@ csched_dom_init(const struct scheduler *ops, struct domain *dom)
static void
csched_free_domdata(const struct scheduler *ops, void *data)
{
- struct csched_dom *sdom = data;
-
- free_cpumask_var(sdom->node_affinity_cpumask);
xfree(data);
}
@@ -1486,19 +1455,19 @@ csched_runq_steal(int peer_cpu, int cpu, int pri, int balance_step)
BUG_ON( is_idle_vcpu(vc) );
/*
- * If the vcpu has no useful node-affinity, skip this vcpu.
- * In fact, what we want is to check if we have any node-affine
- * work to steal, before starting to look at vcpu-affine work.
+ * If the vcpu has no useful soft affinity, skip this vcpu.
+ * In fact, what we want is to check if we have any "soft-affine
+ * work" to steal, before starting to look at "hard-affine work".
*
* Notice that, if not even one vCPU on this runq has a useful
- * node-affinity, we could have avoid considering this runq for
- * a node balancing step in the first place. This, for instance,
+ * soft affinity, we could have avoid considering this runq for
+ * a soft balancing step in the first place. This, for instance,
* can be implemented by taking note of on what runq there are
- * vCPUs with useful node-affinities in some sort of bitmap
+ * vCPUs with useful soft affinities in some sort of bitmap
* or counter.
*/
- if ( balance_step == CSCHED_BALANCE_NODE_AFFINITY
- && !__vcpu_has_node_affinity(vc, vc->cpu_affinity) )
+ if ( balance_step == CSCHED_BALANCE_SOFT_AFFINITY
+ && !__vcpu_has_soft_affinity(vc, vc->cpu_hard_affinity) )
continue;
csched_balance_cpumask(vc, balance_step, csched_balance_mask);
@@ -1546,17 +1515,17 @@ csched_load_balance(struct csched_private *prv, int cpu,
SCHED_STAT_CRANK(load_balance_other);
/*
- * Let's look around for work to steal, taking both vcpu-affinity
- * and node-affinity into account. More specifically, we check all
+ * Let's look around for work to steal, taking both hard affinity
+ * and soft affinity into account. More specifically, we check all
* the non-idle CPUs' runq, looking for:
- * 1. any node-affine work to steal first,
- * 2. if not finding anything, any vcpu-affine work to steal.
+ * 1. any "soft-affine work" to steal first,
+ * 2. if not finding anything, any "hard-affine work" to steal.
*/
for_each_csched_balance_step( bstep )
{
/*
* We peek at the non-idling CPUs in a node-wise fashion. In fact,
- * it is more likely that we find some node-affine work on our same
+ * it is more likely that we find some affine work on our same
* node, not to mention that migrating vcpus within the same node
* could well expected to be cheaper than across-nodes (memory
* stays local, there might be some node-wide cache[s], etc.).
@@ -1982,8 +1951,6 @@ const struct scheduler sched_credit_def = {
.adjust = csched_dom_cntl,
.adjust_global = csched_sys_cntl,
- .set_node_affinity = csched_set_node_affinity,
-
.pick_cpu = csched_cpu_pick,
.do_schedule = csched_schedule,
diff --git a/xen/common/sched_credit2.c b/xen/common/sched_credit2.c
index 4e68375..1ca521b 100644
--- a/xen/common/sched_credit2.c
+++ b/xen/common/sched_credit2.c
@@ -3,7 +3,7 @@
* (C) 2009 - George Dunlap - Citrix Systems R&D UK, Ltd
****************************************************************************
*
- * File: common/csched_credit2.c
+ * File: common/sched_credit2.c
* Author: George Dunlap
*
* Description: Credit-based SMP CPU scheduler
@@ -108,29 +108,29 @@
* Basic constants
*/
/* Default weight: How much a new domain starts with */
-#define CSCHED_DEFAULT_WEIGHT 256
+#define CSCHED2_DEFAULT_WEIGHT 256
/* Min timer: Minimum length a timer will be set, to
* achieve efficiency */
-#define CSCHED_MIN_TIMER MICROSECS(500)
+#define CSCHED2_MIN_TIMER MICROSECS(500)
/* Amount of credit VMs begin with, and are reset to.
* ATM, set so that highest-weight VMs can only run for 10ms
* before a reset event. */
-#define CSCHED_CREDIT_INIT MILLISECS(10)
+#define CSCHED2_CREDIT_INIT MILLISECS(10)
/* Carryover: How much "extra" credit may be carried over after
* a reset. */
-#define CSCHED_CARRYOVER_MAX CSCHED_MIN_TIMER
+#define CSCHED2_CARRYOVER_MAX CSCHED2_MIN_TIMER
/* Stickiness: Cross-L2 migration resistance. Should be less than
* MIN_TIMER. */
-#define CSCHED_MIGRATE_RESIST ((opt_migrate_resist)*MICROSECS(1))
+#define CSCHED2_MIGRATE_RESIST ((opt_migrate_resist)*MICROSECS(1))
/* How much to "compensate" a vcpu for L2 migration */
-#define CSCHED_MIGRATE_COMPENSATION MICROSECS(50)
+#define CSCHED2_MIGRATE_COMPENSATION MICROSECS(50)
/* Reset: Value below which credit will be reset. */
-#define CSCHED_CREDIT_RESET 0
+#define CSCHED2_CREDIT_RESET 0
/* Max timer: Maximum time a guest can be run for. */
-#define CSCHED_MAX_TIMER MILLISECS(2)
+#define CSCHED2_MAX_TIMER MILLISECS(2)
-#define CSCHED_IDLE_CREDIT (-(1<<30))
+#define CSCHED2_IDLE_CREDIT (-(1<<30))
/*
* Flags
@@ -138,8 +138,8 @@
/* CSFLAG_scheduled: Is this vcpu either running on, or context-switching off,
* a physical cpu?
* + Accessed only with runqueue lock held
- * + Set when chosen as next in csched_schedule().
- * + Cleared after context switch has been saved in csched_context_saved()
+ * + Set when chosen as next in csched2_schedule().
+ * + Cleared after context switch has been saved in csched2_context_saved()
* + Checked in vcpu_wake to see if we can add to the runqueue, or if we should
* set CSFLAG_delayed_runq_add
* + Checked to be false in runq_insert.
@@ -148,9 +148,9 @@
#define CSFLAG_scheduled (1<<__CSFLAG_scheduled)
/* CSFLAG_delayed_runq_add: Do we need to add this to the runqueue once it'd done
* being context switched out?
- * + Set when scheduling out in csched_schedule() if prev is runnable
- * + Set in csched_vcpu_wake if it finds CSFLAG_scheduled set
- * + Read in csched_context_saved(). If set, it adds prev to the runqueue and
+ * + Set when scheduling out in csched2_schedule() if prev is runnable
+ * + Set in csched2_vcpu_wake if it finds CSFLAG_scheduled set
+ * + Read in csched2_context_saved(). If set, it adds prev to the runqueue and
* clears the bit.
*/
#define __CSFLAG_delayed_runq_add 2
@@ -169,14 +169,14 @@ integer_param("sched_credit2_migrate_resist", opt_migrate_resist);
/*
* Useful macros
*/
-#define CSCHED_PRIV(_ops) \
- ((struct csched_private *)((_ops)->sched_data))
-#define CSCHED_VCPU(_vcpu) ((struct csched_vcpu *) (_vcpu)->sched_priv)
-#define CSCHED_DOM(_dom) ((struct csched_dom *) (_dom)->sched_priv)
+#define CSCHED2_PRIV(_ops) \
+ ((struct csched2_private *)((_ops)->sched_data))
+#define CSCHED2_VCPU(_vcpu) ((struct csched2_vcpu *) (_vcpu)->sched_priv)
+#define CSCHED2_DOM(_dom) ((struct csched2_dom *) (_dom)->sched_priv)
/* CPU to runq_id macro */
-#define c2r(_ops, _cpu) (CSCHED_PRIV(_ops)->runq_map[(_cpu)])
+#define c2r(_ops, _cpu) (CSCHED2_PRIV(_ops)->runq_map[(_cpu)])
/* CPU to runqueue struct macro */
-#define RQD(_ops, _cpu) (&CSCHED_PRIV(_ops)->rqd[c2r(_ops, _cpu)])
+#define RQD(_ops, _cpu) (&CSCHED2_PRIV(_ops)->rqd[c2r(_ops, _cpu)])
/*
* Shifts for load average.
@@ -197,7 +197,7 @@ integer_param("credit2_balance_over", opt_overload_balance_tolerance);
/*
* Per-runqueue data
*/
-struct csched_runqueue_data {
+struct csched2_runqueue_data {
int id;
spinlock_t lock; /* Lock for this runqueue. */
@@ -218,7 +218,7 @@ struct csched_runqueue_data {
/*
* System-wide private data
*/
-struct csched_private {
+struct csched2_private {
spinlock_t lock;
cpumask_t initialized; /* CPU is initialized for this pool */
@@ -226,7 +226,7 @@ struct csched_private {
int runq_map[NR_CPUS];
cpumask_t active_queues; /* Queues which may have active cpus */
- struct csched_runqueue_data rqd[NR_CPUS];
+ struct csched2_runqueue_data rqd[NR_CPUS];
int load_window_shift;
};
@@ -234,14 +234,14 @@ struct csched_private {
/*
* Virtual CPU
*/
-struct csched_vcpu {
+struct csched2_vcpu {
struct list_head rqd_elem; /* On the runqueue data list */
struct list_head sdom_elem; /* On the domain vcpu list */
struct list_head runq_elem; /* On the runqueue */
- struct csched_runqueue_data *rqd; /* Up-pointer to the runqueue */
+ struct csched2_runqueue_data *rqd; /* Up-pointer to the runqueue */
/* Up-pointers */
- struct csched_dom *sdom;
+ struct csched2_dom *sdom;
struct vcpu *vcpu;
unsigned int weight;
@@ -255,13 +255,13 @@ struct csched_vcpu {
s_time_t load_last_update; /* Last time average was updated */
s_time_t avgload; /* Decaying queue load */
- struct csched_runqueue_data *migrate_rqd; /* Pre-determined rqd to which to migrate */
+ struct csched2_runqueue_data *migrate_rqd; /* Pre-determined rqd to which to migrate */
};
/*
* Domain
*/
-struct csched_dom {
+struct csched2_dom {
struct list_head vcpu;
struct list_head sdom_elem;
struct domain *dom;
@@ -278,8 +278,8 @@ struct csched_dom {
*
* FIXME: Do pre-calculated division?
*/
-static void t2c_update(struct csched_runqueue_data *rqd, s_time_t time,
- struct csched_vcpu *svc)
+static void t2c_update(struct csched2_runqueue_data *rqd, s_time_t time,
+ struct csched2_vcpu *svc)
{
uint64_t val = time * rqd->max_weight + svc->residual;
@@ -287,7 +287,7 @@ static void t2c_update(struct csched_runqueue_data *rqd, s_time_t time,
svc->credit -= val;
}
-static s_time_t c2t(struct csched_runqueue_data *rqd, s_time_t credit, struct csched_vcpu *svc)
+static s_time_t c2t(struct csched2_runqueue_data *rqd, s_time_t credit, struct csched2_vcpu *svc)
{
return credit * svc->weight / rqd->max_weight;
}
@@ -297,22 +297,22 @@ static s_time_t c2t(struct csched_runqueue_data *rqd, s_time_t credit, struct cs
*/
static /*inline*/ int
-__vcpu_on_runq(struct csched_vcpu *svc)
+__vcpu_on_runq(struct csched2_vcpu *svc)
{
return !list_empty(&svc->runq_elem);
}
-static /*inline*/ struct csched_vcpu *
+static /*inline*/ struct csched2_vcpu *
__runq_elem(struct list_head *elem)
{
- return list_entry(elem, struct csched_vcpu, runq_elem);
+ return list_entry(elem, struct csched2_vcpu, runq_elem);
}
static void
__update_runq_load(const struct scheduler *ops,
- struct csched_runqueue_data *rqd, int change, s_time_t now)
+ struct csched2_runqueue_data *rqd, int change, s_time_t now)
{
- struct csched_private *prv = CSCHED_PRIV(ops);
+ struct csched2_private *prv = CSCHED2_PRIV(ops);
s_time_t delta=-1;
now >>= LOADAVG_GRANULARITY_SHIFT;
@@ -354,9 +354,9 @@ __update_runq_load(const struct scheduler *ops,
static void
__update_svc_load(const struct scheduler *ops,
- struct csched_vcpu *svc, int change, s_time_t now)
+ struct csched2_vcpu *svc, int change, s_time_t now)
{
- struct csched_private *prv = CSCHED_PRIV(ops);
+ struct csched2_private *prv = CSCHED2_PRIV(ops);
s_time_t delta=-1;
int vcpu_load;
@@ -399,8 +399,8 @@ __update_svc_load(const struct scheduler *ops,
static void
update_load(const struct scheduler *ops,
- struct csched_runqueue_data *rqd,
- struct csched_vcpu *svc, int change, s_time_t now)
+ struct csched2_runqueue_data *rqd,
+ struct csched2_vcpu *svc, int change, s_time_t now)
{
__update_runq_load(ops, rqd, change, now);
if ( svc )
@@ -408,14 +408,12 @@ update_load(const struct scheduler *ops,
}
static int
-__runq_insert(struct list_head *runq, struct csched_vcpu *svc)
+__runq_insert(struct list_head *runq, struct csched2_vcpu *svc)
{
struct list_head *iter;
int pos = 0;
- d2printk("rqi d%dv%d\n",
- svc->vcpu->domain->domain_id,
- svc->vcpu->vcpu_id);
+ d2printk("rqi %pv\n", svc->vcpu);
BUG_ON(&svc->rqd->runq != runq);
/* Idle vcpus not allowed on the runqueue anymore */
@@ -425,14 +423,11 @@ __runq_insert(struct list_head *runq, struct csched_vcpu *svc)
list_for_each( iter, runq )
{
- struct csched_vcpu * iter_svc = __runq_elem(iter);
+ struct csched2_vcpu * iter_svc = __runq_elem(iter);
if ( svc->credit > iter_svc->credit )
{
- d2printk(" p%d d%dv%d\n",
- pos,
- iter_svc->vcpu->domain->domain_id,
- iter_svc->vcpu->vcpu_id);
+ d2printk(" p%d %pv\n", pos, iter_svc->vcpu);
break;
}
pos++;
@@ -444,7 +439,7 @@ __runq_insert(struct list_head *runq, struct csched_vcpu *svc)
}
static void
-runq_insert(const struct scheduler *ops, unsigned int cpu, struct csched_vcpu *svc)
+runq_insert(const struct scheduler *ops, unsigned int cpu, struct csched2_vcpu *svc)
{
struct list_head * runq = &RQD(ops, cpu)->runq;
int pos = 0;
@@ -473,36 +468,32 @@ runq_insert(const struct scheduler *ops, unsigned int cpu, struct csched_vcpu *s
}
static inline void
-__runq_remove(struct csched_vcpu *svc)
+__runq_remove(struct csched2_vcpu *svc)
{
BUG_ON( !__vcpu_on_runq(svc) );
list_del_init(&svc->runq_elem);
}
-void burn_credits(struct csched_runqueue_data *rqd, struct csched_vcpu *, s_time_t);
+void burn_credits(struct csched2_runqueue_data *rqd, struct csched2_vcpu *, s_time_t);
/* Check to see if the item on the runqueue is higher priority than what's
* currently running; if so, wake up the processor */
static /*inline*/ void
-runq_tickle(const struct scheduler *ops, unsigned int cpu, struct csched_vcpu *new, s_time_t now)
+runq_tickle(const struct scheduler *ops, unsigned int cpu, struct csched2_vcpu *new, s_time_t now)
{
int i, ipid=-1;
s_time_t lowest=(1<<30);
- struct csched_runqueue_data *rqd = RQD(ops, cpu);
+ struct csched2_runqueue_data *rqd = RQD(ops, cpu);
cpumask_t mask;
- struct csched_vcpu * cur;
+ struct csched2_vcpu * cur;
- d2printk("rqt d%dv%d cd%dv%d\n",
- new->vcpu->domain->domain_id,
- new->vcpu->vcpu_id,
- current->domain->domain_id,
- current->vcpu_id);
+ d2printk("rqt %pv curr %pv\n", new->vcpu, current);
BUG_ON(new->vcpu->processor != cpu);
BUG_ON(new->rqd != rqd);
/* Look at the cpu it's running on first */
- cur = CSCHED_VCPU(per_cpu(schedule_data, cpu).curr);
+ cur = CSCHED2_VCPU(per_cpu(schedule_data, cpu).curr);
burn_credits(rqd, cur, now);
if ( cur->credit < new->credit )
@@ -529,13 +520,13 @@ runq_tickle(const struct scheduler *ops, unsigned int cpu, struct csched_vcpu *n
for_each_cpu(i, &mask)
{
- struct csched_vcpu * cur;
+ struct csched2_vcpu * cur;
/* Already looked at this one above */
if ( i == cpu )
continue;
- cur = CSCHED_VCPU(per_cpu(schedule_data, i).curr);
+ cur = CSCHED2_VCPU(per_cpu(schedule_data, i).curr);
BUG_ON(is_idle_vcpu(cur->vcpu));
@@ -564,7 +555,7 @@ runq_tickle(const struct scheduler *ops, unsigned int cpu, struct csched_vcpu *n
/* Only switch to another processor if the credit difference is greater
* than the migrate resistance */
- if ( ipid == -1 || lowest + CSCHED_MIGRATE_RESIST > new->credit )
+ if ( ipid == -1 || lowest + CSCHED2_MIGRATE_RESIST > new->credit )
goto no_tickle;
tickle:
@@ -590,17 +581,17 @@ no_tickle:
* Credit-related code
*/
static void reset_credit(const struct scheduler *ops, int cpu, s_time_t now,
- struct csched_vcpu *snext)
+ struct csched2_vcpu *snext)
{
- struct csched_runqueue_data *rqd = RQD(ops, cpu);
+ struct csched2_runqueue_data *rqd = RQD(ops, cpu);
struct list_head *iter;
int m;
/*
* Under normal circumstances, snext->credit should never be less
- * than -CSCHED_MIN_TIMER. However, under some circumstances, a
+ * than -CSCHED2_MIN_TIMER. However, under some circumstances, a
* vcpu with low credits may be allowed to run long enough that
- * its credits are actually less than -CSCHED_CREDIT_INIT.
+ * its credits are actually less than -CSCHED2_CREDIT_INIT.
* (Instances have been observed, for example, where a vcpu with
* 200us of credit was allowed to run for 11ms, giving it -10.8ms
* of credit. Thus it was still negative even after the reset.)
@@ -614,15 +605,15 @@ static void reset_credit(const struct scheduler *ops, int cpu, s_time_t now,
* case.
*/
m = 1;
- if ( snext->credit < -CSCHED_CREDIT_INIT )
- m += (-snext->credit) / CSCHED_CREDIT_INIT;
+ if ( snext->credit < -CSCHED2_CREDIT_INIT )
+ m += (-snext->credit) / CSCHED2_CREDIT_INIT;
list_for_each( iter, &rqd->svc )
{
- struct csched_vcpu * svc;
+ struct csched2_vcpu * svc;
int start_credit;
- svc = list_entry(iter, struct csched_vcpu, rqd_elem);
+ svc = list_entry(iter, struct csched2_vcpu, rqd_elem);
BUG_ON( is_idle_vcpu(svc->vcpu) );
BUG_ON( svc->rqd != rqd );
@@ -632,13 +623,13 @@ static void reset_credit(const struct scheduler *ops, int cpu, s_time_t now,
/* And add INIT * m, avoiding integer multiplication in the
* common case. */
if ( likely(m==1) )
- svc->credit += CSCHED_CREDIT_INIT;
+ svc->credit += CSCHED2_CREDIT_INIT;
else
- svc->credit += m * CSCHED_CREDIT_INIT;
+ svc->credit += m * CSCHED2_CREDIT_INIT;
/* "Clip" credits to max carryover */
- if ( svc->credit > CSCHED_CREDIT_INIT + CSCHED_CARRYOVER_MAX )
- svc->credit = CSCHED_CREDIT_INIT + CSCHED_CARRYOVER_MAX;
+ if ( svc->credit > CSCHED2_CREDIT_INIT + CSCHED2_CARRYOVER_MAX )
+ svc->credit = CSCHED2_CREDIT_INIT + CSCHED2_CARRYOVER_MAX;
svc->start_time = now;
@@ -662,16 +653,16 @@ static void reset_credit(const struct scheduler *ops, int cpu, s_time_t now,
/* No need to resort runqueue, as everyone's order should be the same. */
}
-void burn_credits(struct csched_runqueue_data *rqd, struct csched_vcpu *svc, s_time_t now)
+void burn_credits(struct csched2_runqueue_data *rqd, struct csched2_vcpu *svc, s_time_t now)
{
s_time_t delta;
/* Assert svc is current */
- ASSERT(svc==CSCHED_VCPU(per_cpu(schedule_data, svc->vcpu->processor).curr));
+ ASSERT(svc==CSCHED2_VCPU(per_cpu(schedule_data, svc->vcpu->processor).curr));
if ( is_idle_vcpu(svc->vcpu) )
{
- BUG_ON(svc->credit != CSCHED_IDLE_CREDIT);
+ BUG_ON(svc->credit != CSCHED2_IDLE_CREDIT);
return;
}
@@ -681,10 +672,7 @@ void burn_credits(struct csched_runqueue_data *rqd, struct csched_vcpu *svc, s_t
t2c_update(rqd, delta, svc);
svc->start_time = now;
- d2printk("b d%dv%d c%d\n",
- svc->vcpu->domain->domain_id,
- svc->vcpu->vcpu_id,
- svc->credit);
+ d2printk("b %pv c%d\n", svc->vcpu, svc->credit);
} else {
d2printk("%s: Time went backwards? now %"PRI_stime" start %"PRI_stime"\n",
__func__, now, svc->start_time);
@@ -708,7 +696,8 @@ void burn_credits(struct csched_runqueue_data *rqd, struct csched_vcpu *svc, s_t
}
/* Find the domain with the highest weight. */
-void update_max_weight(struct csched_runqueue_data *rqd, int new_weight, int old_weight)
+static void update_max_weight(struct csched2_runqueue_data *rqd, int new_weight,
+ int old_weight)
{
/* Try to avoid brute-force search:
* - If new_weight is larger, max_weigth <- new_weight
@@ -728,7 +717,7 @@ void update_max_weight(struct csched_runqueue_data *rqd, int new_weight, int old
list_for_each( iter, &rqd->svc )
{
- struct csched_vcpu * svc = list_entry(iter, struct csched_vcpu, rqd_elem);
+ struct csched2_vcpu * svc = list_entry(iter, struct csched2_vcpu, rqd_elem);
if ( svc->weight > max_weight )
max_weight = svc->weight;
@@ -741,13 +730,13 @@ void update_max_weight(struct csched_runqueue_data *rqd, int new_weight, int old
#ifndef NDEBUG
static /*inline*/ void
-__csched_vcpu_check(struct vcpu *vc)
+__csched2_vcpu_check(struct vcpu *vc)
{
- struct csched_vcpu * const svc = CSCHED_VCPU(vc);
- struct csched_dom * const sdom = svc->sdom;
+ struct csched2_vcpu * const svc = CSCHED2_VCPU(vc);
+ struct csched2_dom * const sdom = svc->sdom;
BUG_ON( svc->vcpu != vc );
- BUG_ON( sdom != CSCHED_DOM(vc->domain) );
+ BUG_ON( sdom != CSCHED2_DOM(vc->domain) );
if ( sdom )
{
BUG_ON( is_idle_vcpu(vc) );
@@ -758,18 +747,18 @@ __csched_vcpu_check(struct vcpu *vc)
BUG_ON( !is_idle_vcpu(vc) );
}
}
-#define CSCHED_VCPU_CHECK(_vc) (__csched_vcpu_check(_vc))
+#define CSCHED2_VCPU_CHECK(_vc) (__csched2_vcpu_check(_vc))
#else
-#define CSCHED_VCPU_CHECK(_vc)
+#define CSCHED2_VCPU_CHECK(_vc)
#endif
static void *
-csched_alloc_vdata(const struct scheduler *ops, struct vcpu *vc, void *dd)
+csched2_alloc_vdata(const struct scheduler *ops, struct vcpu *vc, void *dd)
{
- struct csched_vcpu *svc;
+ struct csched2_vcpu *svc;
/* Allocate per-VCPU info */
- svc = xzalloc(struct csched_vcpu);
+ svc = xzalloc(struct csched2_vcpu);
if ( svc == NULL )
return NULL;
@@ -785,16 +774,16 @@ csched_alloc_vdata(const struct scheduler *ops, struct vcpu *vc, void *dd)
{
BUG_ON( svc->sdom == NULL );
- svc->credit = CSCHED_CREDIT_INIT;
+ svc->credit = CSCHED2_CREDIT_INIT;
svc->weight = svc->sdom->weight;
/* Starting load of 50% */
- svc->avgload = 1ULL << (CSCHED_PRIV(ops)->load_window_shift - 1);
+ svc->avgload = 1ULL << (CSCHED2_PRIV(ops)->load_window_shift - 1);
svc->load_last_update = NOW();
}
else
{
BUG_ON( svc->sdom != NULL );
- svc->credit = CSCHED_IDLE_CREDIT;
+ svc->credit = CSCHED2_IDLE_CREDIT;
svc->weight = 0;
}
@@ -805,7 +794,7 @@ csched_alloc_vdata(const struct scheduler *ops, struct vcpu *vc, void *dd)
/* Add and remove from runqueue assignment (not active run queue) */
static void
-__runq_assign(struct csched_vcpu *svc, struct csched_runqueue_data *rqd)
+__runq_assign(struct csched2_vcpu *svc, struct csched2_runqueue_data *rqd)
{
svc->rqd = rqd;
@@ -835,7 +824,7 @@ __runq_assign(struct csched_vcpu *svc, struct csched_runqueue_data *rqd)
static void
runq_assign(const struct scheduler *ops, struct vcpu *vc)
{
- struct csched_vcpu *svc = vc->sched_priv;
+ struct csched2_vcpu *svc = vc->sched_priv;
BUG_ON(svc->rqd != NULL);
@@ -843,7 +832,7 @@ runq_assign(const struct scheduler *ops, struct vcpu *vc)
}
static void
-__runq_deassign(struct csched_vcpu *svc)
+__runq_deassign(struct csched2_vcpu *svc)
{
BUG_ON(__vcpu_on_runq(svc));
BUG_ON(test_bit(__CSFLAG_scheduled, &svc->flags));
@@ -860,7 +849,7 @@ __runq_deassign(struct csched_vcpu *svc)
static void
runq_deassign(const struct scheduler *ops, struct vcpu *vc)
{
- struct csched_vcpu *svc = vc->sched_priv;
+ struct csched2_vcpu *svc = vc->sched_priv;
BUG_ON(svc->rqd != RQD(ops, vc->processor));
@@ -868,14 +857,12 @@ runq_deassign(const struct scheduler *ops, struct vcpu *vc)
}
static void
-csched_vcpu_insert(const struct scheduler *ops, struct vcpu *vc)
+csched2_vcpu_insert(const struct scheduler *ops, struct vcpu *vc)
{
- struct csched_vcpu *svc = vc->sched_priv;
- struct domain * const dom = vc->domain;
- struct csched_dom * const sdom = svc->sdom;
+ struct csched2_vcpu *svc = vc->sched_priv;
+ struct csched2_dom * const sdom = svc->sdom;
- printk("%s: Inserting d%dv%d\n",
- __func__, dom->domain_id, vc->vcpu_id);
+ printk("%s: Inserting %pv\n", __func__, vc);
/* NB: On boot, idle vcpus are inserted before alloc_pdata() has
* been called for that cpu.
@@ -897,22 +884,22 @@ csched_vcpu_insert(const struct scheduler *ops, struct vcpu *vc)
sdom->nr_vcpus++;
}
- CSCHED_VCPU_CHECK(vc);
+ CSCHED2_VCPU_CHECK(vc);
}
static void
-csched_free_vdata(const struct scheduler *ops, void *priv)
+csched2_free_vdata(const struct scheduler *ops, void *priv)
{
- struct csched_vcpu *svc = priv;
+ struct csched2_vcpu *svc = priv;
xfree(svc);
}
static void
-csched_vcpu_remove(const struct scheduler *ops, struct vcpu *vc)
+csched2_vcpu_remove(const struct scheduler *ops, struct vcpu *vc)
{
- struct csched_vcpu * const svc = CSCHED_VCPU(vc);
- struct csched_dom * const sdom = svc->sdom;
+ struct csched2_vcpu * const svc = CSCHED2_VCPU(vc);
+ struct csched2_dom * const sdom = svc->sdom;
BUG_ON( sdom == NULL );
BUG_ON( !list_empty(&svc->runq_elem) );
@@ -939,9 +926,9 @@ csched_vcpu_remove(const struct scheduler *ops, struct vcpu *vc)
}
static void
-csched_vcpu_sleep(const struct scheduler *ops, struct vcpu *vc)
+csched2_vcpu_sleep(const struct scheduler *ops, struct vcpu *vc)
{
- struct csched_vcpu * const svc = CSCHED_VCPU(vc);
+ struct csched2_vcpu * const svc = CSCHED2_VCPU(vc);
BUG_ON( is_idle_vcpu(vc) );
@@ -958,14 +945,14 @@ csched_vcpu_sleep(const struct scheduler *ops, struct vcpu *vc)
}
static void
-csched_vcpu_wake(const struct scheduler *ops, struct vcpu *vc)
+csched2_vcpu_wake(const struct scheduler *ops, struct vcpu *vc)
{
- struct csched_vcpu * const svc = CSCHED_VCPU(vc);
+ struct csched2_vcpu * const svc = CSCHED2_VCPU(vc);
s_time_t now = 0;
/* Schedule lock should be held at this point. */
- d2printk("w d%dv%d\n", vc->domain->domain_id, vc->vcpu_id);
+ d2printk("w %pv\n", vc);
BUG_ON( is_idle_vcpu(vc) );
@@ -1011,9 +998,9 @@ out:
}
static void
-csched_context_saved(const struct scheduler *ops, struct vcpu *vc)
+csched2_context_saved(const struct scheduler *ops, struct vcpu *vc)
{
- struct csched_vcpu * const svc = CSCHED_VCPU(vc);
+ struct csched2_vcpu * const svc = CSCHED2_VCPU(vc);
s_time_t now = NOW();
spinlock_t *lock = vcpu_schedule_lock_irq(vc);
@@ -1048,9 +1035,9 @@ csched_context_saved(const struct scheduler *ops, struct vcpu *vc)
static int
choose_cpu(const struct scheduler *ops, struct vcpu *vc)
{
- struct csched_private *prv = CSCHED_PRIV(ops);
+ struct csched2_private *prv = CSCHED2_PRIV(ops);
int i, min_rqi = -1, new_cpu;
- struct csched_vcpu *svc = CSCHED_VCPU(vc);
+ struct csched2_vcpu *svc = CSCHED2_VCPU(vc);
s_time_t min_avgload;
BUG_ON(cpumask_empty(&prv->active_queues));
@@ -1074,7 +1061,7 @@ choose_cpu(const struct scheduler *ops, struct vcpu *vc)
{
if ( test_and_clear_bit(__CSFLAG_runq_migrate_request, &svc->flags) )
{
- d2printk("d%dv%d -\n", svc->vcpu->domain->domain_id, svc->vcpu->vcpu_id);
+ d2printk("%pv -\n", svc->vcpu);
clear_bit(__CSFLAG_runq_migrate_request, &svc->flags);
}
/* Leave it where it is for now. When we actually pay attention
@@ -1094,7 +1081,7 @@ choose_cpu(const struct scheduler *ops, struct vcpu *vc)
}
else
{
- d2printk("d%dv%d +\n", svc->vcpu->domain->domain_id, svc->vcpu->vcpu_id);
+ d2printk("%pv +\n", svc->vcpu);
new_cpu = cpumask_cycle(vc->processor, &svc->migrate_rqd->active);
goto out_up;
}
@@ -1107,7 +1094,7 @@ choose_cpu(const struct scheduler *ops, struct vcpu *vc)
/* Find the runqueue with the lowest instantaneous load */
for_each_cpu(i, &prv->active_queues)
{
- struct csched_runqueue_data *rqd;
+ struct csched2_runqueue_data *rqd;
s_time_t rqd_avgload;
rqd = prv->rqd + i;
@@ -1156,15 +1143,15 @@ out_up:
typedef struct {
/* NB: Modified by consider() */
s_time_t load_delta;
- struct csched_vcpu * best_push_svc, *best_pull_svc;
+ struct csched2_vcpu * best_push_svc, *best_pull_svc;
/* NB: Read by consider() */
- struct csched_runqueue_data *lrqd;
- struct csched_runqueue_data *orqd;
+ struct csched2_runqueue_data *lrqd;
+ struct csched2_runqueue_data *orqd;
} balance_state_t;
static void consider(balance_state_t *st,
- struct csched_vcpu *push_svc,
- struct csched_vcpu *pull_svc)
+ struct csched2_vcpu *push_svc,
+ struct csched2_vcpu *pull_svc)
{
s_time_t l_load, o_load, delta;
@@ -1196,15 +1183,14 @@ static void consider(balance_state_t *st,
}
-void migrate(const struct scheduler *ops,
- struct csched_vcpu *svc,
- struct csched_runqueue_data *trqd,
- s_time_t now)
+static void migrate(const struct scheduler *ops,
+ struct csched2_vcpu *svc,
+ struct csched2_runqueue_data *trqd,
+ s_time_t now)
{
if ( test_bit(__CSFLAG_scheduled, &svc->flags) )
{
- d2printk("d%dv%d %d-%d a\n", svc->vcpu->domain->domain_id, svc->vcpu->vcpu_id,
- svc->rqd->id, trqd->id);
+ d2printk("%pv %d-%d a\n", svc->vcpu, svc->rqd->id, trqd->id);
/* It's running; mark it to migrate. */
svc->migrate_rqd = trqd;
set_bit(_VPF_migrating, &svc->vcpu->pause_flags);
@@ -1214,8 +1200,7 @@ void migrate(const struct scheduler *ops,
{
int on_runq=0;
/* It's not running; just move it */
- d2printk("d%dv%d %d-%d i\n", svc->vcpu->domain->domain_id, svc->vcpu->vcpu_id,
- svc->rqd->id, trqd->id);
+ d2printk("%pv %d-%d i\n", svc->vcpu, svc->rqd->id, trqd->id);
if ( __vcpu_on_runq(svc) )
{
__runq_remove(svc);
@@ -1237,7 +1222,7 @@ void migrate(const struct scheduler *ops,
static void balance_load(const struct scheduler *ops, int cpu, s_time_t now)
{
- struct csched_private *prv = CSCHED_PRIV(ops);
+ struct csched2_private *prv = CSCHED2_PRIV(ops);
int i, max_delta_rqi = -1;
struct list_head *push_iter, *pull_iter;
@@ -1338,7 +1323,7 @@ retry:
list_for_each( push_iter, &st.lrqd->svc )
{
int inner_load_updated = 0;
- struct csched_vcpu * push_svc = list_entry(push_iter, struct csched_vcpu, rqd_elem);
+ struct csched2_vcpu * push_svc = list_entry(push_iter, struct csched2_vcpu, rqd_elem);
__update_svc_load(ops, push_svc, 0, now);
@@ -1348,7 +1333,7 @@ retry:
list_for_each( pull_iter, &st.orqd->svc )
{
- struct csched_vcpu * pull_svc = list_entry(pull_iter, struct csched_vcpu, rqd_elem);
+ struct csched2_vcpu * pull_svc = list_entry(pull_iter, struct csched2_vcpu, rqd_elem);
if ( ! inner_load_updated )
{
@@ -1370,7 +1355,7 @@ retry:
list_for_each( pull_iter, &st.orqd->svc )
{
- struct csched_vcpu * pull_svc = list_entry(pull_iter, struct csched_vcpu, rqd_elem);
+ struct csched2_vcpu * pull_svc = list_entry(pull_iter, struct csched2_vcpu, rqd_elem);
/* Skip this one if it's already been flagged to migrate */
if ( test_bit(__CSFLAG_runq_migrate_request, &pull_svc->flags) )
@@ -1394,7 +1379,7 @@ out:
}
static int
-csched_cpu_pick(const struct scheduler *ops, struct vcpu *vc)
+csched2_cpu_pick(const struct scheduler *ops, struct vcpu *vc)
{
int new_cpu;
@@ -1404,14 +1389,14 @@ csched_cpu_pick(const struct scheduler *ops, struct vcpu *vc)
}
static void
-csched_vcpu_migrate(
+csched2_vcpu_migrate(
const struct scheduler *ops, struct vcpu *vc, unsigned int new_cpu)
{
- struct csched_vcpu * const svc = CSCHED_VCPU(vc);
- struct csched_runqueue_data *trqd;
+ struct csched2_vcpu * const svc = CSCHED2_VCPU(vc);
+ struct csched2_runqueue_data *trqd;
/* Check if new_cpu is valid */
- BUG_ON(!cpumask_test_cpu(new_cpu, &CSCHED_PRIV(ops)->initialized));
+ BUG_ON(!cpumask_test_cpu(new_cpu, &CSCHED2_PRIV(ops)->initialized));
trqd = RQD(ops, new_cpu);
@@ -1420,16 +1405,16 @@ csched_vcpu_migrate(
}
static int
-csched_dom_cntl(
+csched2_dom_cntl(
const struct scheduler *ops,
struct domain *d,
struct xen_domctl_scheduler_op *op)
{
- struct csched_dom * const sdom = CSCHED_DOM(d);
- struct csched_private *prv = CSCHED_PRIV(ops);
+ struct csched2_dom * const sdom = CSCHED2_DOM(d);
+ struct csched2_private *prv = CSCHED2_PRIV(ops);
unsigned long flags;
- /* Must hold csched_priv lock to read and update sdom,
+ /* Must hold csched2_priv lock to read and update sdom,
* runq lock to update csvcs. */
spin_lock_irqsave(&prv->lock, flags);
@@ -1453,10 +1438,10 @@ csched_dom_cntl(
/* Update weights for vcpus, and max_weight for runqueues on which they reside */
list_for_each ( iter, &sdom->vcpu )
{
- struct csched_vcpu *svc = list_entry(iter, struct csched_vcpu, sdom_elem);
+ struct csched2_vcpu *svc = list_entry(iter, struct csched2_vcpu, sdom_elem);
/* NB: Locking order is important here. Because we grab this lock here, we
- * must never lock csched_priv.lock if we're holding a runqueue lock.
+ * must never lock csched2_priv.lock if we're holding a runqueue lock.
* Also, calling vcpu_schedule_lock() is enough, since IRQs have already
* been disabled. */
spinlock_t *lock = vcpu_schedule_lock(svc->vcpu);
@@ -1477,12 +1462,12 @@ csched_dom_cntl(
}
static void *
-csched_alloc_domdata(const struct scheduler *ops, struct domain *dom)
+csched2_alloc_domdata(const struct scheduler *ops, struct domain *dom)
{
- struct csched_dom *sdom;
+ struct csched2_dom *sdom;
unsigned long flags;
- sdom = xzalloc(struct csched_dom);
+ sdom = xzalloc(struct csched2_dom);
if ( sdom == NULL )
return NULL;
@@ -1490,29 +1475,29 @@ csched_alloc_domdata(const struct scheduler *ops, struct domain *dom)
INIT_LIST_HEAD(&sdom->vcpu);
INIT_LIST_HEAD(&sdom->sdom_elem);
sdom->dom = dom;
- sdom->weight = CSCHED_DEFAULT_WEIGHT;
+ sdom->weight = CSCHED2_DEFAULT_WEIGHT;
sdom->nr_vcpus = 0;
- spin_lock_irqsave(&CSCHED_PRIV(ops)->lock, flags);
+ spin_lock_irqsave(&CSCHED2_PRIV(ops)->lock, flags);
- list_add_tail(&sdom->sdom_elem, &CSCHED_PRIV(ops)->sdom);
+ list_add_tail(&sdom->sdom_elem, &CSCHED2_PRIV(ops)->sdom);
- spin_unlock_irqrestore(&CSCHED_PRIV(ops)->lock, flags);
+ spin_unlock_irqrestore(&CSCHED2_PRIV(ops)->lock, flags);
return (void *)sdom;
}
static int
-csched_dom_init(const struct scheduler *ops, struct domain *dom)
+csched2_dom_init(const struct scheduler *ops, struct domain *dom)
{
- struct csched_dom *sdom;
+ struct csched2_dom *sdom;
printk("%s: Initializing domain %d\n", __func__, dom->domain_id);
if ( is_idle_domain(dom) )
return 0;
- sdom = csched_alloc_domdata(ops, dom);
+ sdom = csched2_alloc_domdata(ops, dom);
if ( sdom == NULL )
return -ENOMEM;
@@ -1522,41 +1507,41 @@ csched_dom_init(const struct scheduler *ops, struct domain *dom)
}
static void
-csched_free_domdata(const struct scheduler *ops, void *data)
+csched2_free_domdata(const struct scheduler *ops, void *data)
{
unsigned long flags;
- struct csched_dom *sdom = data;
+ struct csched2_dom *sdom = data;
- spin_lock_irqsave(&CSCHED_PRIV(ops)->lock, flags);
+ spin_lock_irqsave(&CSCHED2_PRIV(ops)->lock, flags);
list_del_init(&sdom->sdom_elem);
- spin_unlock_irqrestore(&CSCHED_PRIV(ops)->lock, flags);
+ spin_unlock_irqrestore(&CSCHED2_PRIV(ops)->lock, flags);
xfree(data);
}
static void
-csched_dom_destroy(const struct scheduler *ops, struct domain *dom)
+csched2_dom_destroy(const struct scheduler *ops, struct domain *dom)
{
- struct csched_dom *sdom = CSCHED_DOM(dom);
+ struct csched2_dom *sdom = CSCHED2_DOM(dom);
BUG_ON(!list_empty(&sdom->vcpu));
- csched_free_domdata(ops, CSCHED_DOM(dom));
+ csched2_free_domdata(ops, CSCHED2_DOM(dom));
}
/* How long should we let this vcpu run for? */
static s_time_t
-csched_runtime(const struct scheduler *ops, int cpu, struct csched_vcpu *snext)
+csched2_runtime(const struct scheduler *ops, int cpu, struct csched2_vcpu *snext)
{
s_time_t time;
int rt_credit; /* Proposed runtime measured in credits */
- struct csched_runqueue_data *rqd = RQD(ops, cpu);
+ struct csched2_runqueue_data *rqd = RQD(ops, cpu);
struct list_head *runq = &rqd->runq;
if ( is_idle_vcpu(snext->vcpu) )
- return CSCHED_MAX_TIMER;
+ return CSCHED2_MAX_TIMER;
/* General algorithm:
* 1) Run until snext's credit will be 0
@@ -1572,7 +1557,7 @@ csched_runtime(const struct scheduler *ops, int cpu, struct csched_vcpu *snext)
* run until your credit ~= his */
if ( ! list_empty(runq) )
{
- struct csched_vcpu *swait = __runq_elem(runq->next);
+ struct csched2_vcpu *swait = __runq_elem(runq->next);
if ( ! is_idle_vcpu(swait->vcpu)
&& swait->credit > 0 )
@@ -1584,7 +1569,7 @@ csched_runtime(const struct scheduler *ops, int cpu, struct csched_vcpu *snext)
/* The next guy may actually have a higher credit, if we've tried to
* avoid migrating him from a different cpu. DTRT. */
if ( rt_credit <= 0 )
- time = CSCHED_MIN_TIMER;
+ time = CSCHED2_MIN_TIMER;
else
{
/* FIXME: See if we can eliminate this conversion if we know time
@@ -1594,10 +1579,10 @@ csched_runtime(const struct scheduler *ops, int cpu, struct csched_vcpu *snext)
time = c2t(rqd, rt_credit, snext);
/* Check limits */
- if ( time < CSCHED_MIN_TIMER )
- time = CSCHED_MIN_TIMER;
- else if ( time > CSCHED_MAX_TIMER )
- time = CSCHED_MAX_TIMER;
+ if ( time < CSCHED2_MIN_TIMER )
+ time = CSCHED2_MIN_TIMER;
+ else if ( time > CSCHED2_MAX_TIMER )
+ time = CSCHED2_MAX_TIMER;
}
return time;
@@ -1608,28 +1593,28 @@ void __dump_execstate(void *unused);
/*
* Find a candidate.
*/
-static struct csched_vcpu *
-runq_candidate(struct csched_runqueue_data *rqd,
- struct csched_vcpu *scurr,
+static struct csched2_vcpu *
+runq_candidate(struct csched2_runqueue_data *rqd,
+ struct csched2_vcpu *scurr,
int cpu, s_time_t now)
{
struct list_head *iter;
- struct csched_vcpu *snext = NULL;
+ struct csched2_vcpu *snext = NULL;
/* Default to current if runnable, idle otherwise */
if ( vcpu_runnable(scurr->vcpu) )
snext = scurr;
else
- snext = CSCHED_VCPU(idle_vcpu[cpu]);
+ snext = CSCHED2_VCPU(idle_vcpu[cpu]);
list_for_each( iter, &rqd->runq )
{
- struct csched_vcpu * svc = list_entry(iter, struct csched_vcpu, runq_elem);
+ struct csched2_vcpu * svc = list_entry(iter, struct csched2_vcpu, runq_elem);
/* If this is on a different processor, don't pull it unless
- * its credit is at least CSCHED_MIGRATE_RESIST higher. */
+ * its credit is at least CSCHED2_MIGRATE_RESIST higher. */
if ( svc->vcpu->processor != cpu
- && snext->credit + CSCHED_MIGRATE_RESIST > svc->credit )
+ && snext->credit + CSCHED2_MIGRATE_RESIST > svc->credit )
continue;
/* If the next one on the list has more credit than current
@@ -1650,25 +1635,21 @@ runq_candidate(struct csched_runqueue_data *rqd,
* fast for the common case.
*/
static struct task_slice
-csched_schedule(
+csched2_schedule(
const struct scheduler *ops, s_time_t now, bool_t tasklet_work_scheduled)
{
const int cpu = smp_processor_id();
- struct csched_runqueue_data *rqd;
- struct csched_vcpu * const scurr = CSCHED_VCPU(current);
- struct csched_vcpu *snext = NULL;
+ struct csched2_runqueue_data *rqd;
+ struct csched2_vcpu * const scurr = CSCHED2_VCPU(current);
+ struct csched2_vcpu *snext = NULL;
struct task_slice ret;
SCHED_STAT_CRANK(schedule);
- CSCHED_VCPU_CHECK(current);
+ CSCHED2_VCPU_CHECK(current);
- d2printk("sc p%d c d%dv%d now %"PRI_stime"\n",
- cpu,
- scurr->vcpu->domain->domain_id,
- scurr->vcpu->vcpu_id,
- now);
+ d2printk("sc p%d c %pv now %"PRI_stime"\n", cpu, scurr->vcpu, now);
- BUG_ON(!cpumask_test_cpu(cpu, &CSCHED_PRIV(ops)->initialized));
+ BUG_ON(!cpumask_test_cpu(cpu, &CSCHED2_PRIV(ops)->initialized));
rqd = RQD(ops, cpu);
BUG_ON(!cpumask_test_cpu(cpu, &rqd->active));
@@ -1684,21 +1665,20 @@ csched_schedule(
{
int rq;
other_rqi = -2;
- for_each_cpu ( rq, &CSCHED_PRIV(ops)->active_queues )
+ for_each_cpu ( rq, &CSCHED2_PRIV(ops)->active_queues )
{
- if ( scurr->rqd == &CSCHED_PRIV(ops)->rqd[rq] )
+ if ( scurr->rqd == &CSCHED2_PRIV(ops)->rqd[rq] )
{
other_rqi = rq;
break;
}
}
}
- printk("%s: pcpu %d rq %d, but scurr d%dv%d assigned to "
+ printk("%s: pcpu %d rq %d, but scurr %pv assigned to "
"pcpu %d rq %d!\n",
__func__,
cpu, this_rqi,
- scurr->vcpu->domain->domain_id, scurr->vcpu->vcpu_id,
- scurr->vcpu->processor, other_rqi);
+ scurr->vcpu, scurr->vcpu->processor, other_rqi);
}
BUG_ON(!is_idle_vcpu(scurr->vcpu) && scurr->rqd != rqd);
@@ -1730,7 +1710,7 @@ csched_schedule(
if ( tasklet_work_scheduled )
{
trace_var(TRC_CSCHED2_SCHED_TASKLET, 0, 0, NULL);
- snext = CSCHED_VCPU(idle_vcpu[cpu]);
+ snext = CSCHED2_VCPU(idle_vcpu[cpu]);
}
else
snext=runq_candidate(rqd, scurr, cpu, now);
@@ -1755,19 +1735,15 @@ csched_schedule(
__runq_remove(snext);
if ( snext->vcpu->is_running )
{
- printk("p%d: snext d%dv%d running on p%d! scurr d%dv%d\n",
- cpu,
- snext->vcpu->domain->domain_id, snext->vcpu->vcpu_id,
- snext->vcpu->processor,
- scurr->vcpu->domain->domain_id,
- scurr->vcpu->vcpu_id);
+ printk("p%d: snext %pv running on p%d! scurr %pv\n",
+ cpu, snext->vcpu, snext->vcpu->processor, scurr->vcpu);
BUG();
}
set_bit(__CSFLAG_scheduled, &snext->flags);
}
/* Check for the reset condition */
- if ( snext->credit <= CSCHED_CREDIT_RESET )
+ if ( snext->credit <= CSCHED2_CREDIT_RESET )
{
reset_credit(ops, cpu, now, snext);
balance_load(ops, cpu, now);
@@ -1782,7 +1758,7 @@ csched_schedule(
/* Safe because lock for old processor is held */
if ( snext->vcpu->processor != cpu )
{
- snext->credit += CSCHED_MIGRATE_COMPENSATION;
+ snext->credit += CSCHED2_MIGRATE_COMPENSATION;
snext->vcpu->processor = cpu;
ret.migrated = 1;
}
@@ -1800,15 +1776,15 @@ csched_schedule(
/*
* Return task to run next...
*/
- ret.time = csched_runtime(ops, cpu, snext);
+ ret.time = csched2_runtime(ops, cpu, snext);
ret.task = snext->vcpu;
- CSCHED_VCPU_CHECK(ret.task);
+ CSCHED2_VCPU_CHECK(ret.task);
return ret;
}
static void
-csched_dump_vcpu(struct csched_vcpu *svc)
+csched2_dump_vcpu(struct csched2_vcpu *svc)
{
printk("[%i.%i] flags=%x cpu=%i",
svc->vcpu->domain->domain_id,
@@ -1822,10 +1798,10 @@ csched_dump_vcpu(struct csched_vcpu *svc)
}
static void
-csched_dump_pcpu(const struct scheduler *ops, int cpu)
+csched2_dump_pcpu(const struct scheduler *ops, int cpu)
{
struct list_head *runq, *iter;
- struct csched_vcpu *svc;
+ struct csched2_vcpu *svc;
int loop;
char cpustr[100];
@@ -1839,11 +1815,11 @@ csched_dump_pcpu(const struct scheduler *ops, int cpu)
printk("core=%s\n", cpustr);
/* current VCPU */
- svc = CSCHED_VCPU(per_cpu(schedule_data, cpu).curr);
+ svc = CSCHED2_VCPU(per_cpu(schedule_data, cpu).curr);
if ( svc )
{
printk("\trun: ");
- csched_dump_vcpu(svc);
+ csched2_dump_vcpu(svc);
}
loop = 0;
@@ -1853,22 +1829,22 @@ csched_dump_pcpu(const struct scheduler *ops, int cpu)
if ( svc )
{
printk("\t%3d: ", ++loop);
- csched_dump_vcpu(svc);
+ csched2_dump_vcpu(svc);
}
}
}
static void
-csched_dump(const struct scheduler *ops)
+csched2_dump(const struct scheduler *ops)
{
struct list_head *iter_sdom, *iter_svc;
- struct csched_private *prv = CSCHED_PRIV(ops);
+ struct csched2_private *prv = CSCHED2_PRIV(ops);
int i, loop;
printk("Active queues: %d\n"
"\tdefault-weight = %d\n",
cpumask_weight(&prv->active_queues),
- CSCHED_DEFAULT_WEIGHT);
+ CSCHED2_DEFAULT_WEIGHT);
for_each_cpu(i, &prv->active_queues)
{
s_time_t fraction;
@@ -1893,8 +1869,8 @@ csched_dump(const struct scheduler *ops)
loop = 0;
list_for_each( iter_sdom, &prv->sdom )
{
- struct csched_dom *sdom;
- sdom = list_entry(iter_sdom, struct csched_dom, sdom_elem);
+ struct csched2_dom *sdom;
+ sdom = list_entry(iter_sdom, struct csched2_dom, sdom_elem);
printk("\tDomain: %d w %d v %d\n\t",
sdom->dom->domain_id,
@@ -1903,18 +1879,18 @@ csched_dump(const struct scheduler *ops)
list_for_each( iter_svc, &sdom->vcpu )
{
- struct csched_vcpu *svc;
- svc = list_entry(iter_svc, struct csched_vcpu, sdom_elem);
+ struct csched2_vcpu *svc;
+ svc = list_entry(iter_svc, struct csched2_vcpu, sdom_elem);
printk("\t%3d: ", ++loop);
- csched_dump_vcpu(svc);
+ csched2_dump_vcpu(svc);
}
}
}
-static void activate_runqueue(struct csched_private *prv, int rqi)
+static void activate_runqueue(struct csched2_private *prv, int rqi)
{
- struct csched_runqueue_data *rqd;
+ struct csched2_runqueue_data *rqd;
rqd = prv->rqd + rqi;
@@ -1929,9 +1905,9 @@ static void activate_runqueue(struct csched_private *prv, int rqi)
cpumask_set_cpu(rqi, &prv->active_queues);
}
-static void deactivate_runqueue(struct csched_private *prv, int rqi)
+static void deactivate_runqueue(struct csched2_private *prv, int rqi)
{
- struct csched_runqueue_data *rqd;
+ struct csched2_runqueue_data *rqd;
rqd = prv->rqd + rqi;
@@ -1946,8 +1922,8 @@ static void init_pcpu(const struct scheduler *ops, int cpu)
{
int rqi;
unsigned long flags;
- struct csched_private *prv = CSCHED_PRIV(ops);
- struct csched_runqueue_data *rqd;
+ struct csched2_private *prv = CSCHED2_PRIV(ops);
+ struct csched2_runqueue_data *rqd;
spinlock_t *old_lock;
spin_lock_irqsave(&prv->lock, flags);
@@ -2008,7 +1984,7 @@ static void init_pcpu(const struct scheduler *ops, int cpu)
}
static void *
-csched_alloc_pdata(const struct scheduler *ops, int cpu)
+csched2_alloc_pdata(const struct scheduler *ops, int cpu)
{
/* Check to see if the cpu is online yet */
/* Note: cpu 0 doesn't get a STARTING callback */
@@ -2022,11 +1998,11 @@ csched_alloc_pdata(const struct scheduler *ops, int cpu)
}
static void
-csched_free_pdata(const struct scheduler *ops, void *pcpu, int cpu)
+csched2_free_pdata(const struct scheduler *ops, void *pcpu, int cpu)
{
unsigned long flags;
- struct csched_private *prv = CSCHED_PRIV(ops);
- struct csched_runqueue_data *rqd;
+ struct csched2_private *prv = CSCHED2_PRIV(ops);
+ struct csched2_runqueue_data *rqd;
struct schedule_data *sd = &per_cpu(schedule_data, cpu);
int rqi;
@@ -2070,14 +2046,14 @@ csched_free_pdata(const struct scheduler *ops, void *pcpu, int cpu)
}
static int
-csched_cpu_starting(int cpu)
+csched2_cpu_starting(int cpu)
{
struct scheduler *ops;
/* Hope this is safe from cpupools switching things around. :-) */
ops = per_cpu(scheduler, cpu);
- if ( ops->alloc_pdata == csched_alloc_pdata )
+ if ( ops->alloc_pdata == csched2_alloc_pdata )
init_pcpu(ops, cpu);
return NOTIFY_DONE;
@@ -2092,7 +2068,7 @@ static int cpu_credit2_callback(
switch ( action )
{
case CPU_STARTING:
- csched_cpu_starting(cpu);
+ csched2_cpu_starting(cpu);
break;
default:
break;
@@ -2106,17 +2082,17 @@ static struct notifier_block cpu_credit2_nfb = {
};
static int
-csched_global_init(void)
+csched2_global_init(void)
{
register_cpu_notifier(&cpu_credit2_nfb);
return 0;
}
static int
-csched_init(struct scheduler *ops)
+csched2_init(struct scheduler *ops)
{
int i;
- struct csched_private *prv;
+ struct csched2_private *prv;
printk("Initializing Credit2 scheduler\n" \
" WARNING: This is experimental software in development.\n" \
@@ -2137,7 +2113,7 @@ csched_init(struct scheduler *ops)
* set up basic structures, and a callback when the CPU info is
* available. */
- prv = xzalloc(struct csched_private);
+ prv = xzalloc(struct csched2_private);
if ( prv == NULL )
return -ENOMEM;
ops->sched_data = prv;
@@ -2157,49 +2133,49 @@ csched_init(struct scheduler *ops)
}
static void
-csched_deinit(const struct scheduler *ops)
+csched2_deinit(const struct scheduler *ops)
{
- struct csched_private *prv;
+ struct csched2_private *prv;
- prv = CSCHED_PRIV(ops);
+ prv = CSCHED2_PRIV(ops);
if ( prv != NULL )
xfree(prv);
}
-static struct csched_private _csched_priv;
+static struct csched2_private _csched2_priv;
const struct scheduler sched_credit2_def = {
.name = "SMP Credit Scheduler rev2",
.opt_name = "credit2",
.sched_id = XEN_SCHEDULER_CREDIT2,
- .sched_data = &_csched_priv,
-
- .init_domain = csched_dom_init,
- .destroy_domain = csched_dom_destroy,
-
- .insert_vcpu = csched_vcpu_insert,
- .remove_vcpu = csched_vcpu_remove,
-
- .sleep = csched_vcpu_sleep,
- .wake = csched_vcpu_wake,
-
- .adjust = csched_dom_cntl,
-
- .pick_cpu = csched_cpu_pick,
- .migrate = csched_vcpu_migrate,
- .do_schedule = csched_schedule,
- .context_saved = csched_context_saved,
-
- .dump_cpu_state = csched_dump_pcpu,
- .dump_settings = csched_dump,
- .global_init = csched_global_init,
- .init = csched_init,
- .deinit = csched_deinit,
- .alloc_vdata = csched_alloc_vdata,
- .free_vdata = csched_free_vdata,
- .alloc_pdata = csched_alloc_pdata,
- .free_pdata = csched_free_pdata,
- .alloc_domdata = csched_alloc_domdata,
- .free_domdata = csched_free_domdata,
+ .sched_data = &_csched2_priv,
+
+ .init_domain = csched2_dom_init,
+ .destroy_domain = csched2_dom_destroy,
+
+ .insert_vcpu = csched2_vcpu_insert,
+ .remove_vcpu = csched2_vcpu_remove,
+
+ .sleep = csched2_vcpu_sleep,
+ .wake = csched2_vcpu_wake,
+
+ .adjust = csched2_dom_cntl,
+
+ .pick_cpu = csched2_cpu_pick,
+ .migrate = csched2_vcpu_migrate,
+ .do_schedule = csched2_schedule,
+ .context_saved = csched2_context_saved,
+
+ .dump_cpu_state = csched2_dump_pcpu,
+ .dump_settings = csched2_dump,
+ .global_init = csched2_global_init,
+ .init = csched2_init,
+ .deinit = csched2_deinit,
+ .alloc_vdata = csched2_alloc_vdata,
+ .free_vdata = csched2_free_vdata,
+ .alloc_pdata = csched2_alloc_pdata,
+ .free_pdata = csched2_free_pdata,
+ .alloc_domdata = csched2_alloc_domdata,
+ .free_domdata = csched2_free_domdata,
};
diff --git a/xen/common/sched_rt.c b/xen/common/sched_rt.c
new file mode 100644
index 0000000..e70d6c7
--- /dev/null
+++ b/xen/common/sched_rt.c
@@ -0,0 +1,1112 @@
+/*****************************************************************************
+ * Preemptive Global Earliest Deadline First (EDF) scheduler for Xen
+ * EDF scheduling is a real-time scheduling algorithm used in embedded field.
+ *
+ * by Sisu Xi, 2013, Washington University in Saint Louis
+ * and Meng Xu, 2014, University of Pennsylvania
+ *
+ * based on the code of credit Scheduler
+ */
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/sched.h>
+#include <xen/domain.h>
+#include <xen/delay.h>
+#include <xen/event.h>
+#include <xen/time.h>
+#include <xen/perfc.h>
+#include <xen/sched-if.h>
+#include <xen/softirq.h>
+#include <asm/atomic.h>
+#include <xen/errno.h>
+#include <xen/trace.h>
+#include <xen/cpu.h>
+#include <xen/keyhandler.h>
+#include <xen/trace.h>
+#include <xen/guest_access.h>
+
+/*
+ * TODO:
+ *
+ * Migration compensation and resist like credit2 to better use cache;
+ * Lock Holder Problem, using yield?
+ * Self switch problem: VCPUs of the same domain may preempt each other;
+ */
+
+/*
+ * Design:
+ *
+ * This scheduler follows the Preemptive Global Earliest Deadline First (EDF)
+ * theory in real-time field.
+ * At any scheduling point, the VCPU with earlier deadline has higher priority.
+ * The scheduler always picks highest priority VCPU to run on a feasible PCPU.
+ * A PCPU is feasible if the VCPU can run on this PCPU and (the PCPU is idle or
+ * has a lower-priority VCPU running on it.)
+ *
+ * Each VCPU has a dedicated period and budget.
+ * The deadline of a VCPU is at the end of each period;
+ * A VCPU has its budget replenished at the beginning of each period;
+ * While scheduled, a VCPU burns its budget.
+ * The VCPU needs to finish its budget before its deadline in each period;
+ * The VCPU discards its unused budget at the end of each period.
+ * If a VCPU runs out of budget in a period, it has to wait until next period.
+ *
+ * Each VCPU is implemented as a deferable server.
+ * When a VCPU has a task running on it, its budget is continuously burned;
+ * When a VCPU has no task but with budget left, its budget is preserved.
+ *
+ * Queue scheme:
+ * A global runqueue and a global depletedqueue for each CPU pool.
+ * The runqueue holds all runnable VCPUs with budget, sorted by deadline;
+ * The depletedqueue holds all VCPUs without budget, unsorted;
+ *
+ * Note: cpumask and cpupool is supported.
+ */
+
+/*
+ * Locking:
+ * A global system lock is used to protect the RunQ and DepletedQ.
+ * The global lock is referenced by schedule_data.schedule_lock
+ * from all physical cpus.
+ *
+ * The lock is already grabbed when calling wake/sleep/schedule/ functions
+ * in schedule.c
+ *
+ * The functions involes RunQ and needs to grab locks are:
+ * vcpu_insert, vcpu_remove, context_saved, __runq_insert
+ */
+
+
+/*
+ * Default parameters:
+ * Period and budget in default is 10 and 4 ms, respectively
+ */
+#define RTDS_DEFAULT_PERIOD (MICROSECS(10000))
+#define RTDS_DEFAULT_BUDGET (MICROSECS(4000))
+
+#define UPDATE_LIMIT_SHIFT 10
+#define MAX_SCHEDULE (MILLISECS(1))
+/*
+ * Flags
+ */
+/*
+ * RTDS_scheduled: Is this vcpu either running on, or context-switching off,
+ * a phyiscal cpu?
+ * + Accessed only with global lock held.
+ * + Set when chosen as next in rt_schedule().
+ * + Cleared after context switch has been saved in rt_context_saved()
+ * + Checked in vcpu_wake to see if we can add to the Runqueue, or if we should
+ * set RTDS_delayed_runq_add
+ * + Checked to be false in runq_insert.
+ */
+#define __RTDS_scheduled 1
+#define RTDS_scheduled (1<<__RTDS_scheduled)
+/*
+ * RTDS_delayed_runq_add: Do we need to add this to the RunQ/DepletedQ
+ * once it's done being context switching out?
+ * + Set when scheduling out in rt_schedule() if prev is runable
+ * + Set in rt_vcpu_wake if it finds RTDS_scheduled set
+ * + Read in rt_context_saved(). If set, it adds prev to the Runqueue/DepletedQ
+ * and clears the bit.
+ */
+#define __RTDS_delayed_runq_add 2
+#define RTDS_delayed_runq_add (1<<__RTDS_delayed_runq_add)
+
+/*
+ * rt tracing events ("only" 512 available!). Check
+ * include/public/trace.h for more details.
+ */
+#define TRC_RTDS_TICKLE TRC_SCHED_CLASS_EVT(RTDS, 1)
+#define TRC_RTDS_RUNQ_PICK TRC_SCHED_CLASS_EVT(RTDS, 2)
+#define TRC_RTDS_BUDGET_BURN TRC_SCHED_CLASS_EVT(RTDS, 3)
+#define TRC_RTDS_BUDGET_REPLENISH TRC_SCHED_CLASS_EVT(RTDS, 4)
+#define TRC_RTDS_SCHED_TASKLET TRC_SCHED_CLASS_EVT(RTDS, 5)
+
+/*
+ * Systme-wide private data, include global RunQueue/DepletedQ
+ * Global lock is referenced by schedule_data.schedule_lock from all
+ * physical cpus. It can be grabbed via vcpu_schedule_lock_irq()
+ */
+struct rt_private {
+ spinlock_t lock; /* the global coarse grand lock */
+ struct list_head sdom; /* list of availalbe domains, used for dump */
+ struct list_head runq; /* ordered list of runnable vcpus */
+ struct list_head depletedq; /* unordered list of depleted vcpus */
+ cpumask_t tickled; /* cpus been tickled */
+};
+
+/*
+ * Virtual CPU
+ */
+struct rt_vcpu {
+ struct list_head q_elem; /* on the runq/depletedq list */
+ struct list_head sdom_elem; /* on the domain VCPU list */
+
+ /* Up-pointers */
+ struct rt_dom *sdom;
+ struct vcpu *vcpu;
+
+ /* VCPU parameters, in nanoseconds */
+ s_time_t period;
+ s_time_t budget;
+
+ /* VCPU current infomation in nanosecond */
+ s_time_t cur_budget; /* current budget */
+ s_time_t last_start; /* last start time */
+ s_time_t cur_deadline; /* current deadline for EDF */
+
+ unsigned flags; /* mark __RTDS_scheduled, etc.. */
+};
+
+/*
+ * Domain
+ */
+struct rt_dom {
+ struct list_head vcpu; /* link its VCPUs */
+ struct list_head sdom_elem; /* link list on rt_priv */
+ struct domain *dom; /* pointer to upper domain */
+};
+
+/*
+ * Useful inline functions
+ */
+static inline struct rt_private *rt_priv(const struct scheduler *ops)
+{
+ return ops->sched_data;
+}
+
+static inline struct rt_vcpu *rt_vcpu(const struct vcpu *vcpu)
+{
+ return vcpu->sched_priv;
+}
+
+static inline struct rt_dom *rt_dom(const struct domain *dom)
+{
+ return dom->sched_priv;
+}
+
+static inline struct list_head *rt_runq(const struct scheduler *ops)
+{
+ return &rt_priv(ops)->runq;
+}
+
+static inline struct list_head *rt_depletedq(const struct scheduler *ops)
+{
+ return &rt_priv(ops)->depletedq;
+}
+
+/*
+ * Queue helper functions for runq and depletedq
+ */
+static int
+__vcpu_on_q(const struct rt_vcpu *svc)
+{
+ return !list_empty(&svc->q_elem);
+}
+
+static struct rt_vcpu *
+__q_elem(struct list_head *elem)
+{
+ return list_entry(elem, struct rt_vcpu, q_elem);
+}
+
+/*
+ * Debug related code, dump vcpu/cpu information
+ */
+static void
+rt_dump_vcpu(const struct scheduler *ops, const struct rt_vcpu *svc)
+{
+ char cpustr[1024];
+ cpumask_t *cpupool_mask;
+
+ ASSERT(svc != NULL);
+ /* idle vcpu */
+ if( svc->sdom == NULL )
+ {
+ printk("\n");
+ return;
+ }
+
+ cpumask_scnprintf(cpustr, sizeof(cpustr), svc->vcpu->cpu_hard_affinity);
+ printk("[%5d.%-2u] cpu %u, (%"PRI_stime", %"PRI_stime"),"
+ " cur_b=%"PRI_stime" cur_d=%"PRI_stime" last_start=%"PRI_stime"\n"
+ " \t\t onQ=%d runnable=%d cpu_hard_affinity=%s ",
+ svc->vcpu->domain->domain_id,
+ svc->vcpu->vcpu_id,
+ svc->vcpu->processor,
+ svc->period,
+ svc->budget,
+ svc->cur_budget,
+ svc->cur_deadline,
+ svc->last_start,
+ __vcpu_on_q(svc),
+ vcpu_runnable(svc->vcpu),
+ cpustr);
+ memset(cpustr, 0, sizeof(cpustr));
+ cpupool_mask = cpupool_scheduler_cpumask(svc->vcpu->domain->cpupool);
+ cpumask_scnprintf(cpustr, sizeof(cpustr), cpupool_mask);
+ printk("cpupool=%s\n", cpustr);
+}
+
+static void
+rt_dump_pcpu(const struct scheduler *ops, int cpu)
+{
+ struct rt_vcpu *svc = rt_vcpu(curr_on_cpu(cpu));
+
+ rt_dump_vcpu(ops, svc);
+}
+
+static void
+rt_dump(const struct scheduler *ops)
+{
+ struct list_head *iter_sdom, *iter_svc, *runq, *depletedq, *iter;
+ struct rt_private *prv = rt_priv(ops);
+ struct rt_vcpu *svc;
+ cpumask_t *online;
+ struct rt_dom *sdom;
+ unsigned long flags;
+
+ ASSERT(!list_empty(&prv->sdom));
+
+ sdom = list_entry(prv->sdom.next, struct rt_dom, sdom_elem);
+ online = cpupool_scheduler_cpumask(sdom->dom->cpupool);
+ runq = rt_runq(ops);
+ depletedq = rt_depletedq(ops);
+
+ spin_lock_irqsave(&prv->lock, flags);
+ printk("Global RunQueue info:\n");
+ list_for_each( iter, runq )
+ {
+ svc = __q_elem(iter);
+ rt_dump_vcpu(ops, svc);
+ }
+
+ printk("Global DepletedQueue info:\n");
+ list_for_each( iter, depletedq )
+ {
+ svc = __q_elem(iter);
+ rt_dump_vcpu(ops, svc);
+ }
+
+ printk("Domain info:\n");
+ list_for_each( iter_sdom, &prv->sdom )
+ {
+ sdom = list_entry(iter_sdom, struct rt_dom, sdom_elem);
+ printk("\tdomain: %d\n", sdom->dom->domain_id);
+
+ list_for_each( iter_svc, &sdom->vcpu )
+ {
+ svc = list_entry(iter_svc, struct rt_vcpu, sdom_elem);
+ rt_dump_vcpu(ops, svc);
+ }
+ }
+
+ spin_unlock_irqrestore(&prv->lock, flags);
+}
+
+/*
+ * update deadline and budget when now >= cur_deadline
+ * it need to be updated to the deadline of the current period
+ */
+static void
+rt_update_deadline(s_time_t now, struct rt_vcpu *svc)
+{
+ ASSERT(now >= svc->cur_deadline);
+ ASSERT(svc->period != 0);
+
+ if ( svc->cur_deadline + (svc->period << UPDATE_LIMIT_SHIFT) > now )
+ {
+ do
+ svc->cur_deadline += svc->period;
+ while ( svc->cur_deadline <= now );
+ }
+ else
+ {
+ long count = ((now - svc->cur_deadline) / svc->period) + 1;
+ svc->cur_deadline += count * svc->period;
+ }
+
+ svc->cur_budget = svc->budget;
+
+ /* TRACE */
+ {
+ struct {
+ unsigned dom:16,vcpu:16;
+ unsigned cur_deadline_lo, cur_deadline_hi;
+ unsigned cur_budget_lo, cur_budget_hi;
+ } d;
+ d.dom = svc->vcpu->domain->domain_id;
+ d.vcpu = svc->vcpu->vcpu_id;
+ d.cur_deadline_lo = (unsigned) svc->cur_deadline;
+ d.cur_deadline_hi = (unsigned) (svc->cur_deadline >> 32);
+ d.cur_budget_lo = (unsigned) svc->cur_budget;
+ d.cur_budget_hi = (unsigned) (svc->cur_budget >> 32);
+ trace_var(TRC_RTDS_BUDGET_REPLENISH, 1,
+ sizeof(d),
+ (unsigned char *) &d);
+ }
+
+ return;
+}
+
+static inline void
+__q_remove(struct rt_vcpu *svc)
+{
+ if ( __vcpu_on_q(svc) )
+ list_del_init(&svc->q_elem);
+}
+
+/*
+ * Insert svc with budget in RunQ according to EDF:
+ * vcpus with smaller deadlines go first.
+ * Insert svc without budget in DepletedQ unsorted;
+ */
+static void
+__runq_insert(const struct scheduler *ops, struct rt_vcpu *svc)
+{
+ struct rt_private *prv = rt_priv(ops);
+ struct list_head *runq = rt_runq(ops);
+ struct list_head *iter;
+
+ ASSERT( spin_is_locked(&prv->lock) );
+
+ ASSERT( !__vcpu_on_q(svc) );
+
+ /* add svc to runq if svc still has budget */
+ if ( svc->cur_budget > 0 )
+ {
+ list_for_each(iter, runq)
+ {
+ struct rt_vcpu * iter_svc = __q_elem(iter);
+ if ( svc->cur_deadline <= iter_svc->cur_deadline )
+ break;
+ }
+ list_add_tail(&svc->q_elem, iter);
+ }
+ else
+ {
+ list_add(&svc->q_elem, &prv->depletedq);
+ }
+}
+
+/*
+ * Init/Free related code
+ */
+static int
+rt_init(struct scheduler *ops)
+{
+ struct rt_private *prv = xzalloc(struct rt_private);
+
+ printk("Initializing RTDS scheduler\n"
+ "WARNING: This is experimental software in development.\n"
+ "Use at your own risk.\n");
+
+ if ( prv == NULL )
+ return -ENOMEM;
+
+ spin_lock_init(&prv->lock);
+ INIT_LIST_HEAD(&prv->sdom);
+ INIT_LIST_HEAD(&prv->runq);
+ INIT_LIST_HEAD(&prv->depletedq);
+
+ cpumask_clear(&prv->tickled);
+
+ ops->sched_data = prv;
+
+ return 0;
+}
+
+static void
+rt_deinit(const struct scheduler *ops)
+{
+ struct rt_private *prv = rt_priv(ops);
+
+ xfree(prv);
+}
+
+/*
+ * Point per_cpu spinlock to the global system lock;
+ * All cpu have same global system lock
+ */
+static void *
+rt_alloc_pdata(const struct scheduler *ops, int cpu)
+{
+ struct rt_private *prv = rt_priv(ops);
+ unsigned long flags;
+
+ spin_lock_irqsave(&prv->lock, flags);
+ per_cpu(schedule_data, cpu).schedule_lock = &prv->lock;
+ spin_unlock_irqrestore(&prv->lock, flags);
+
+ /* 1 indicates alloc. succeed in schedule.c */
+ return (void *)1;
+}
+
+static void *
+rt_alloc_domdata(const struct scheduler *ops, struct domain *dom)
+{
+ unsigned long flags;
+ struct rt_dom *sdom;
+ struct rt_private * prv = rt_priv(ops);
+
+ sdom = xzalloc(struct rt_dom);
+ if ( sdom == NULL )
+ return NULL;
+
+ INIT_LIST_HEAD(&sdom->vcpu);
+ INIT_LIST_HEAD(&sdom->sdom_elem);
+ sdom->dom = dom;
+
+ /* spinlock here to insert the dom */
+ spin_lock_irqsave(&prv->lock, flags);
+ list_add_tail(&sdom->sdom_elem, &(prv->sdom));
+ spin_unlock_irqrestore(&prv->lock, flags);
+
+ return sdom;
+}
+
+static void
+rt_free_domdata(const struct scheduler *ops, void *data)
+{
+ unsigned long flags;
+ struct rt_dom *sdom = data;
+ struct rt_private *prv = rt_priv(ops);
+
+ spin_lock_irqsave(&prv->lock, flags);
+ list_del_init(&sdom->sdom_elem);
+ spin_unlock_irqrestore(&prv->lock, flags);
+ xfree(data);
+}
+
+static int
+rt_dom_init(const struct scheduler *ops, struct domain *dom)
+{
+ struct rt_dom *sdom;
+
+ /* IDLE Domain does not link on rt_private */
+ if ( is_idle_domain(dom) )
+ return 0;
+
+ sdom = rt_alloc_domdata(ops, dom);
+ if ( sdom == NULL )
+ return -ENOMEM;
+
+ dom->sched_priv = sdom;
+
+ return 0;
+}
+
+static void
+rt_dom_destroy(const struct scheduler *ops, struct domain *dom)
+{
+ rt_free_domdata(ops, rt_dom(dom));
+}
+
+static void *
+rt_alloc_vdata(const struct scheduler *ops, struct vcpu *vc, void *dd)
+{
+ struct rt_vcpu *svc;
+
+ /* Allocate per-VCPU info */
+ svc = xzalloc(struct rt_vcpu);
+ if ( svc == NULL )
+ return NULL;
+
+ INIT_LIST_HEAD(&svc->q_elem);
+ INIT_LIST_HEAD(&svc->sdom_elem);
+ svc->flags = 0U;
+ svc->sdom = dd;
+ svc->vcpu = vc;
+ svc->last_start = 0;
+
+ svc->period = RTDS_DEFAULT_PERIOD;
+ if ( !is_idle_vcpu(vc) )
+ svc->budget = RTDS_DEFAULT_BUDGET;
+
+ return svc;
+}
+
+static void
+rt_free_vdata(const struct scheduler *ops, void *priv)
+{
+ struct rt_vcpu *svc = priv;
+
+ xfree(svc);
+}
+
+/*
+ * This function is called in sched_move_domain() in schedule.c
+ * When move a domain to a new cpupool.
+ * It inserts vcpus of moving domain to the scheduler's RunQ in
+ * dest. cpupool; and insert rt_vcpu svc to scheduler-specific
+ * vcpu list of the dom
+ */
+static void
+rt_vcpu_insert(const struct scheduler *ops, struct vcpu *vc)
+{
+ struct rt_vcpu *svc = rt_vcpu(vc);
+ s_time_t now = NOW();
+
+ /* not addlocate idle vcpu to dom vcpu list */
+ if ( is_idle_vcpu(vc) )
+ return;
+
+ if ( now >= svc->cur_deadline )
+ rt_update_deadline(now, svc);
+
+ if ( !__vcpu_on_q(svc) && vcpu_runnable(vc) && !vc->is_running )
+ __runq_insert(ops, svc);
+
+ /* add rt_vcpu svc to scheduler-specific vcpu list of the dom */
+ list_add_tail(&svc->sdom_elem, &svc->sdom->vcpu);
+}
+
+/*
+ * Remove rt_vcpu svc from the old scheduler in source cpupool; and
+ * Remove rt_vcpu svc from scheduler-specific vcpu list of the dom
+ */
+static void
+rt_vcpu_remove(const struct scheduler *ops, struct vcpu *vc)
+{
+ struct rt_vcpu * const svc = rt_vcpu(vc);
+ struct rt_dom * const sdom = svc->sdom;
+ spinlock_t *lock;
+
+ BUG_ON( sdom == NULL );
+
+ lock = vcpu_schedule_lock_irq(vc);
+ if ( __vcpu_on_q(svc) )
+ __q_remove(svc);
+ vcpu_schedule_unlock_irq(lock, vc);
+
+ if ( !is_idle_vcpu(vc) )
+ list_del_init(&svc->sdom_elem);
+}
+
+/*
+ * Pick a valid CPU for the vcpu vc
+ * Valid CPU of a vcpu is intesection of vcpu's affinity
+ * and available cpus
+ */
+static int
+rt_cpu_pick(const struct scheduler *ops, struct vcpu *vc)
+{
+ cpumask_t cpus;
+ cpumask_t *online;
+ int cpu;
+
+ online = cpupool_scheduler_cpumask(vc->domain->cpupool);
+ cpumask_and(&cpus, online, vc->cpu_hard_affinity);
+
+ cpu = cpumask_test_cpu(vc->processor, &cpus)
+ ? vc->processor
+ : cpumask_cycle(vc->processor, &cpus);
+ ASSERT( !cpumask_empty(&cpus) && cpumask_test_cpu(cpu, &cpus) );
+
+ return cpu;
+}
+
+/*
+ * Burn budget in nanosecond granularity
+ */
+static void
+burn_budget(const struct scheduler *ops, struct rt_vcpu *svc, s_time_t now)
+{
+ s_time_t delta;
+
+ /* don't burn budget for idle VCPU */
+ if ( is_idle_vcpu(svc->vcpu) )
+ return;
+
+ /* burn at nanoseconds level */
+ delta = now - svc->last_start;
+ /*
+ * delta < 0 only happens in nested virtualization;
+ * TODO: how should we handle delta < 0 in a better way?
+ */
+ if ( delta < 0 )
+ {
+ printk("%s, ATTENTION: now is behind last_start! delta=%"PRI_stime"\n",
+ __func__, delta);
+ svc->last_start = now;
+ return;
+ }
+
+ svc->cur_budget -= delta;
+
+ if ( svc->cur_budget < 0 )
+ svc->cur_budget = 0;
+
+ /* TRACE */
+ {
+ struct {
+ unsigned dom:16, vcpu:16;
+ unsigned cur_budget_lo;
+ unsigned cur_budget_hi;
+ int delta;
+ } d;
+ d.dom = svc->vcpu->domain->domain_id;
+ d.vcpu = svc->vcpu->vcpu_id;
+ d.cur_budget_lo = (unsigned) svc->cur_budget;
+ d.cur_budget_hi = (unsigned) (svc->cur_budget >> 32);
+ d.delta = delta;
+ trace_var(TRC_RTDS_BUDGET_BURN, 1,
+ sizeof(d),
+ (unsigned char *) &d);
+ }
+}
+
+/*
+ * RunQ is sorted. Pick first one within cpumask. If no one, return NULL
+ * lock is grabbed before calling this function
+ */
+static struct rt_vcpu *
+__runq_pick(const struct scheduler *ops, cpumask_t *mask)
+{
+ struct list_head *runq = rt_runq(ops);
+ struct list_head *iter;
+ struct rt_vcpu *svc = NULL;
+ struct rt_vcpu *iter_svc = NULL;
+ cpumask_t cpu_common;
+ cpumask_t *online;
+
+ list_for_each(iter, runq)
+ {
+ iter_svc = __q_elem(iter);
+
+ /* mask cpu_hard_affinity & cpupool & mask */
+ online = cpupool_scheduler_cpumask(iter_svc->vcpu->domain->cpupool);
+ cpumask_and(&cpu_common, online, iter_svc->vcpu->cpu_hard_affinity);
+ cpumask_and(&cpu_common, mask, &cpu_common);
+ if ( cpumask_empty(&cpu_common) )
+ continue;
+
+ ASSERT( iter_svc->cur_budget > 0 );
+
+ svc = iter_svc;
+ break;
+ }
+
+ /* TRACE */
+ {
+ if( svc != NULL )
+ {
+ struct {
+ unsigned dom:16, vcpu:16;
+ unsigned cur_deadline_lo, cur_deadline_hi;
+ unsigned cur_budget_lo, cur_budget_hi;
+ } d;
+ d.dom = svc->vcpu->domain->domain_id;
+ d.vcpu = svc->vcpu->vcpu_id;
+ d.cur_deadline_lo = (unsigned) svc->cur_deadline;
+ d.cur_deadline_hi = (unsigned) (svc->cur_deadline >> 32);
+ d.cur_budget_lo = (unsigned) svc->cur_budget;
+ d.cur_budget_hi = (unsigned) (svc->cur_budget >> 32);
+ trace_var(TRC_RTDS_RUNQ_PICK, 1,
+ sizeof(d),
+ (unsigned char *) &d);
+ }
+ else
+ trace_var(TRC_RTDS_RUNQ_PICK, 1, 0, NULL);
+ }
+
+ return svc;
+}
+
+/*
+ * Update vcpu's budget and
+ * sort runq by insert the modifed vcpu back to runq
+ * lock is grabbed before calling this function
+ */
+static void
+__repl_update(const struct scheduler *ops, s_time_t now)
+{
+ struct list_head *runq = rt_runq(ops);
+ struct list_head *depletedq = rt_depletedq(ops);
+ struct list_head *iter;
+ struct list_head *tmp;
+ struct rt_vcpu *svc = NULL;
+
+ list_for_each_safe(iter, tmp, runq)
+ {
+ svc = __q_elem(iter);
+ if ( now < svc->cur_deadline )
+ break;
+
+ rt_update_deadline(now, svc);
+ /* reinsert the vcpu if its deadline is updated */
+ __q_remove(svc);
+ __runq_insert(ops, svc);
+ }
+
+ list_for_each_safe(iter, tmp, depletedq)
+ {
+ svc = __q_elem(iter);
+ if ( now >= svc->cur_deadline )
+ {
+ rt_update_deadline(now, svc);
+ __q_remove(svc); /* remove from depleted queue */
+ __runq_insert(ops, svc); /* add to runq */
+ }
+ }
+}
+
+/*
+ * schedule function for rt scheduler.
+ * The lock is already grabbed in schedule.c, no need to lock here
+ */
+static struct task_slice
+rt_schedule(const struct scheduler *ops, s_time_t now, bool_t tasklet_work_scheduled)
+{
+ const int cpu = smp_processor_id();
+ struct rt_private *prv = rt_priv(ops);
+ struct rt_vcpu *const scurr = rt_vcpu(current);
+ struct rt_vcpu *snext = NULL;
+ struct task_slice ret = { .migrated = 0 };
+
+ /* clear ticked bit now that we've been scheduled */
+ cpumask_clear_cpu(cpu, &prv->tickled);
+
+ /* burn_budget would return for IDLE VCPU */
+ burn_budget(ops, scurr, now);
+
+ __repl_update(ops, now);
+
+ if ( tasklet_work_scheduled )
+ {
+ snext = rt_vcpu(idle_vcpu[cpu]);
+ }
+ else
+ {
+ cpumask_t cur_cpu;
+ cpumask_clear(&cur_cpu);
+ cpumask_set_cpu(cpu, &cur_cpu);
+ snext = __runq_pick(ops, &cur_cpu);
+ if ( snext == NULL )
+ snext = rt_vcpu(idle_vcpu[cpu]);
+
+ /* if scurr has higher priority and budget, still pick scurr */
+ if ( !is_idle_vcpu(current) &&
+ vcpu_runnable(current) &&
+ scurr->cur_budget > 0 &&
+ ( is_idle_vcpu(snext->vcpu) ||
+ scurr->cur_deadline <= snext->cur_deadline ) )
+ snext = scurr;
+ }
+
+ if ( snext != scurr &&
+ !is_idle_vcpu(current) &&
+ vcpu_runnable(current) )
+ set_bit(__RTDS_delayed_runq_add, &scurr->flags);
+
+ snext->last_start = now;
+ if ( !is_idle_vcpu(snext->vcpu) )
+ {
+ if ( snext != scurr )
+ {
+ __q_remove(snext);
+ set_bit(__RTDS_scheduled, &snext->flags);
+ }
+ if ( snext->vcpu->processor != cpu )
+ {
+ snext->vcpu->processor = cpu;
+ ret.migrated = 1;
+ }
+ }
+
+ ret.time = MIN(snext->budget, MAX_SCHEDULE); /* sched quantum */
+ ret.task = snext->vcpu;
+
+ /* TRACE */
+ {
+ struct {
+ unsigned dom:16,vcpu:16;
+ unsigned cur_deadline_lo, cur_deadline_hi;
+ unsigned cur_budget_lo, cur_budget_hi;
+ } d;
+ d.dom = snext->vcpu->domain->domain_id;
+ d.vcpu = snext->vcpu->vcpu_id;
+ d.cur_deadline_lo = (unsigned) snext->cur_deadline;
+ d.cur_deadline_hi = (unsigned) (snext->cur_deadline >> 32);
+ d.cur_budget_lo = (unsigned) snext->cur_budget;
+ d.cur_budget_hi = (unsigned) (snext->cur_budget >> 32);
+ trace_var(TRC_RTDS_SCHED_TASKLET, 1,
+ sizeof(d),
+ (unsigned char *)&d);
+ }
+
+ return ret;
+}
+
+/*
+ * Remove VCPU from RunQ
+ * The lock is already grabbed in schedule.c, no need to lock here
+ */
+static void
+rt_vcpu_sleep(const struct scheduler *ops, struct vcpu *vc)
+{
+ struct rt_vcpu * const svc = rt_vcpu(vc);
+
+ BUG_ON( is_idle_vcpu(vc) );
+
+ if ( curr_on_cpu(vc->processor) == vc )
+ cpu_raise_softirq(vc->processor, SCHEDULE_SOFTIRQ);
+ else if ( __vcpu_on_q(svc) )
+ __q_remove(svc);
+ else if ( test_bit(__RTDS_delayed_runq_add, &svc->flags) )
+ clear_bit(__RTDS_delayed_runq_add, &svc->flags);
+}
+
+/*
+ * Pick a cpu where to run a vcpu,
+ * possibly kicking out the vcpu running there
+ * Called by wake() and context_saved()
+ * We have a running candidate here, the kick logic is:
+ * Among all the cpus that are within the cpu affinity
+ * 1) if the new->cpu is idle, kick it. This could benefit cache hit
+ * 2) if there are any idle vcpu, kick it.
+ * 3) now all pcpus are busy;
+ * among all the running vcpus, pick lowest priority one
+ * if snext has higher priority, kick it.
+ *
+ * TODO:
+ * 1) what if these two vcpus belongs to the same domain?
+ * replace a vcpu belonging to the same domain introduces more overhead
+ *
+ * lock is grabbed before calling this function
+ */
+static void
+runq_tickle(const struct scheduler *ops, struct rt_vcpu *new)
+{
+ struct rt_private *prv = rt_priv(ops);
+ struct rt_vcpu *latest_deadline_vcpu = NULL; /* lowest priority */
+ struct rt_vcpu *iter_svc;
+ struct vcpu *iter_vc;
+ int cpu = 0, cpu_to_tickle = 0;
+ cpumask_t not_tickled;
+ cpumask_t *online;
+
+ if ( new == NULL || is_idle_vcpu(new->vcpu) )
+ return;
+
+ online = cpupool_scheduler_cpumask(new->vcpu->domain->cpupool);
+ cpumask_and(¬_tickled, online, new->vcpu->cpu_hard_affinity);
+ cpumask_andnot(¬_tickled, ¬_tickled, &prv->tickled);
+
+ /* 1) if new's previous cpu is idle, kick it for cache benefit */
+ if ( is_idle_vcpu(curr_on_cpu(new->vcpu->processor)) )
+ {
+ cpu_to_tickle = new->vcpu->processor;
+ goto out;
+ }
+
+ /* 2) if there are any idle pcpu, kick it */
+ /* The same loop also find the one with lowest priority */
+ for_each_cpu(cpu, ¬_tickled)
+ {
+ iter_vc = curr_on_cpu(cpu);
+ if ( is_idle_vcpu(iter_vc) )
+ {
+ cpu_to_tickle = cpu;
+ goto out;
+ }
+ iter_svc = rt_vcpu(iter_vc);
+ if ( latest_deadline_vcpu == NULL ||
+ iter_svc->cur_deadline > latest_deadline_vcpu->cur_deadline )
+ latest_deadline_vcpu = iter_svc;
+ }
+
+ /* 3) candicate has higher priority, kick out lowest priority vcpu */
+ if ( latest_deadline_vcpu != NULL &&
+ new->cur_deadline < latest_deadline_vcpu->cur_deadline )
+ {
+ cpu_to_tickle = latest_deadline_vcpu->vcpu->processor;
+ goto out;
+ }
+
+ /* didn't tickle any cpu */
+ return;
+out:
+ /* TRACE */
+ {
+ struct {
+ unsigned cpu:16, pad:16;
+ } d;
+ d.cpu = cpu_to_tickle;
+ d.pad = 0;
+ trace_var(TRC_RTDS_TICKLE, 0,
+ sizeof(d),
+ (unsigned char *)&d);
+ }
+
+ cpumask_set_cpu(cpu_to_tickle, &prv->tickled);
+ cpu_raise_softirq(cpu_to_tickle, SCHEDULE_SOFTIRQ);
+ return;
+}
+
+/*
+ * Should always wake up runnable vcpu, put it back to RunQ.
+ * Check priority to raise interrupt
+ * The lock is already grabbed in schedule.c, no need to lock here
+ * TODO: what if these two vcpus belongs to the same domain?
+ */
+static void
+rt_vcpu_wake(const struct scheduler *ops, struct vcpu *vc)
+{
+ struct rt_vcpu * const svc = rt_vcpu(vc);
+ s_time_t now = NOW();
+ struct rt_private *prv = rt_priv(ops);
+ struct rt_vcpu *snext = NULL; /* highest priority on RunQ */
+ struct rt_dom *sdom = NULL;
+ cpumask_t *online;
+
+ BUG_ON( is_idle_vcpu(vc) );
+
+ if ( unlikely(curr_on_cpu(vc->processor) == vc) )
+ return;
+
+ /* on RunQ/DepletedQ, just update info is ok */
+ if ( unlikely(__vcpu_on_q(svc)) )
+ return;
+
+ /* If context hasn't been saved for this vcpu yet, we can't put it on
+ * the Runqueue/DepletedQ. Instead, we set a flag so that it will be
+ * put on the Runqueue/DepletedQ after the context has been saved.
+ */
+ if ( unlikely(test_bit(__RTDS_scheduled, &svc->flags)) )
+ {
+ set_bit(__RTDS_delayed_runq_add, &svc->flags);
+ return;
+ }
+
+ if ( now >= svc->cur_deadline)
+ rt_update_deadline(now, svc);
+
+ /* insert svc to runq/depletedq because svc is not in queue now */
+ __runq_insert(ops, svc);
+
+ __repl_update(ops, now);
+
+ ASSERT(!list_empty(&prv->sdom));
+ sdom = list_entry(prv->sdom.next, struct rt_dom, sdom_elem);
+ online = cpupool_scheduler_cpumask(sdom->dom->cpupool);
+ snext = __runq_pick(ops, online); /* pick snext from ALL valid cpus */
+
+ runq_tickle(ops, snext);
+
+ return;
+}
+
+/*
+ * scurr has finished context switch, insert it back to the RunQ,
+ * and then pick the highest priority vcpu from runq to run
+ */
+static void
+rt_context_saved(const struct scheduler *ops, struct vcpu *vc)
+{
+ struct rt_vcpu *svc = rt_vcpu(vc);
+ struct rt_vcpu *snext = NULL;
+ struct rt_dom *sdom = NULL;
+ struct rt_private *prv = rt_priv(ops);
+ cpumask_t *online;
+ spinlock_t *lock = vcpu_schedule_lock_irq(vc);
+
+ clear_bit(__RTDS_scheduled, &svc->flags);
+ /* not insert idle vcpu to runq */
+ if ( is_idle_vcpu(vc) )
+ goto out;
+
+ if ( test_and_clear_bit(__RTDS_delayed_runq_add, &svc->flags) &&
+ likely(vcpu_runnable(vc)) )
+ {
+ __runq_insert(ops, svc);
+ __repl_update(ops, NOW());
+
+ ASSERT(!list_empty(&prv->sdom));
+ sdom = list_entry(prv->sdom.next, struct rt_dom, sdom_elem);
+ online = cpupool_scheduler_cpumask(sdom->dom->cpupool);
+ snext = __runq_pick(ops, online); /* pick snext from ALL cpus */
+
+ runq_tickle(ops, snext);
+ }
+out:
+ vcpu_schedule_unlock_irq(lock, vc);
+}
+
+/*
+ * set/get each vcpu info of each domain
+ */
+static int
+rt_dom_cntl(
+ const struct scheduler *ops,
+ struct domain *d,
+ struct xen_domctl_scheduler_op *op)
+{
+ struct rt_private *prv = rt_priv(ops);
+ struct rt_dom * const sdom = rt_dom(d);
+ struct rt_vcpu *svc;
+ struct list_head *iter;
+ unsigned long flags;
+ int rc = 0;
+
+ switch ( op->cmd )
+ {
+ case XEN_DOMCTL_SCHEDOP_getinfo:
+ spin_lock_irqsave(&prv->lock, flags);
+ svc = list_entry(sdom->vcpu.next, struct rt_vcpu, sdom_elem);
+ op->u.rtds.period = svc->period / MICROSECS(1); /* transfer to us */
+ op->u.rtds.budget = svc->budget / MICROSECS(1);
+ spin_unlock_irqrestore(&prv->lock, flags);
+ break;
+ case XEN_DOMCTL_SCHEDOP_putinfo:
+ if ( op->u.rtds.period == 0 || op->u.rtds.budget == 0 )
+ {
+ rc = -EINVAL;
+ break;
+ }
+ spin_lock_irqsave(&prv->lock, flags);
+ list_for_each( iter, &sdom->vcpu )
+ {
+ struct rt_vcpu * svc = list_entry(iter, struct rt_vcpu, sdom_elem);
+ svc->period = MICROSECS(op->u.rtds.period); /* transfer to nanosec */
+ svc->budget = MICROSECS(op->u.rtds.budget);
+ }
+ spin_unlock_irqrestore(&prv->lock, flags);
+ break;
+ }
+
+ return rc;
+}
+
+static struct rt_private _rt_priv;
+
+const struct scheduler sched_rtds_def = {
+ .name = "SMP RTDS Scheduler",
+ .opt_name = "rtds",
+ .sched_id = XEN_SCHEDULER_RTDS,
+ .sched_data = &_rt_priv,
+
+ .dump_cpu_state = rt_dump_pcpu,
+ .dump_settings = rt_dump,
+ .init = rt_init,
+ .deinit = rt_deinit,
+ .alloc_pdata = rt_alloc_pdata,
+ .alloc_domdata = rt_alloc_domdata,
+ .free_domdata = rt_free_domdata,
+ .init_domain = rt_dom_init,
+ .destroy_domain = rt_dom_destroy,
+ .alloc_vdata = rt_alloc_vdata,
+ .free_vdata = rt_free_vdata,
+ .insert_vcpu = rt_vcpu_insert,
+ .remove_vcpu = rt_vcpu_remove,
+
+ .adjust = rt_dom_cntl,
+
+ .pick_cpu = rt_cpu_pick,
+ .do_schedule = rt_schedule,
+ .sleep = rt_vcpu_sleep,
+ .wake = rt_vcpu_wake,
+ .context_saved = rt_context_saved,
+};
diff --git a/xen/common/sched_sedf.c b/xen/common/sched_sedf.c
index 7c24171..7c80bad 100644
--- a/xen/common/sched_sedf.c
+++ b/xen/common/sched_sedf.c
@@ -138,18 +138,6 @@ static inline int extraq_on(struct vcpu *d, int i)
(EXTRALIST(d,i)->next != EXTRALIST(d,i)));
}
-static inline void extraq_add_head(struct vcpu *d, int i)
-{
- list_add(EXTRALIST(d,i), EXTRAQ(d->processor,i));
- ASSERT(extraq_on(d, i));
-}
-
-static inline void extraq_add_tail(struct vcpu *d, int i)
-{
- list_add_tail(EXTRALIST(d,i), EXTRAQ(d->processor,i));
- ASSERT(extraq_on(d, i));
-}
-
static inline void extraq_del(struct vcpu *d, int i)
{
struct list_head *list = EXTRALIST(d,i);
@@ -396,7 +384,7 @@ static int sedf_pick_cpu(const struct scheduler *ops, struct vcpu *v)
cpumask_t *online;
online = cpupool_scheduler_cpumask(v->domain->cpupool);
- cpumask_and(&online_affinity, v->cpu_affinity, online);
+ cpumask_and(&online_affinity, v->cpu_hard_affinity, online);
return cpumask_cycle(v->vcpu_id % cpumask_weight(&online_affinity) - 1,
&online_affinity);
}
diff --git a/xen/common/schedule.c b/xen/common/schedule.c
index 2f28487..6285a6e 100644
--- a/xen/common/schedule.c
+++ b/xen/common/schedule.c
@@ -69,6 +69,7 @@ static const struct scheduler *schedulers[] = {
&sched_credit_def,
&sched_credit2_def,
&sched_arinc653_def,
+ &sched_rtds_def,
};
static struct scheduler __read_mostly ops;
@@ -194,9 +195,11 @@ int sched_init_vcpu(struct vcpu *v, unsigned int processor)
*/
v->processor = processor;
if ( is_idle_domain(d) || d->is_pinned )
- cpumask_copy(v->cpu_affinity, cpumask_of(processor));
+ cpumask_copy(v->cpu_hard_affinity, cpumask_of(processor));
else
- cpumask_setall(v->cpu_affinity);
+ cpumask_setall(v->cpu_hard_affinity);
+
+ cpumask_setall(v->cpu_soft_affinity);
/* Initialise the per-vcpu timers. */
init_timer(&v->periodic_timer, vcpu_periodic_timer_fn,
@@ -224,6 +227,12 @@ int sched_init_vcpu(struct vcpu *v, unsigned int processor)
return 0;
}
+static void sched_move_irqs(struct vcpu *v)
+{
+ arch_move_irqs(v);
+ evtchn_move_pirqs(v);
+}
+
int sched_move_domain(struct domain *d, struct cpupool *c)
{
struct vcpu *v;
@@ -285,7 +294,8 @@ int sched_move_domain(struct domain *d, struct cpupool *c)
migrate_timer(&v->singleshot_timer, new_p);
migrate_timer(&v->poll_timer, new_p);
- cpumask_setall(v->cpu_affinity);
+ cpumask_setall(v->cpu_hard_affinity);
+ cpumask_setall(v->cpu_soft_affinity);
lock = vcpu_schedule_lock_irq(v);
v->processor = new_p;
@@ -298,7 +308,7 @@ int sched_move_domain(struct domain *d, struct cpupool *c)
v->sched_priv = vcpu_priv[v->vcpu_id];
if ( !d->is_dying )
- evtchn_move_pirqs(v);
+ sched_move_irqs(v);
new_p = cpumask_cycle(new_p, c->cpu_valid);
@@ -458,7 +468,7 @@ static void vcpu_migrate(struct vcpu *v)
*/
if ( pick_called &&
(new_lock == per_cpu(schedule_data, new_cpu).schedule_lock) &&
- cpumask_test_cpu(new_cpu, v->cpu_affinity) &&
+ cpumask_test_cpu(new_cpu, v->cpu_hard_affinity) &&
cpumask_test_cpu(new_cpu, v->domain->cpupool->cpu_valid) )
break;
@@ -523,7 +533,7 @@ static void vcpu_migrate(struct vcpu *v)
spin_unlock_irqrestore(old_lock, flags);
if ( old_cpu != new_cpu )
- evtchn_move_pirqs(v);
+ sched_move_irqs(v);
/* Wake on new CPU. */
vcpu_wake(v);
@@ -560,9 +570,8 @@ void restore_vcpu_affinity(struct domain *d)
if ( v->affinity_broken )
{
- printk(XENLOG_DEBUG "Restoring affinity for d%dv%d\n",
- d->domain_id, v->vcpu_id);
- cpumask_copy(v->cpu_affinity, v->cpu_affinity_saved);
+ printk(XENLOG_DEBUG "Restoring affinity for %pv\n", v);
+ cpumask_copy(v->cpu_hard_affinity, v->cpu_hard_affinity_saved);
v->affinity_broken = 0;
}
@@ -605,20 +614,20 @@ int cpu_disable_scheduler(unsigned int cpu)
unsigned long flags;
spinlock_t *lock = vcpu_schedule_lock_irqsave(v, &flags);
- cpumask_and(&online_affinity, v->cpu_affinity, c->cpu_valid);
+ cpumask_and(&online_affinity, v->cpu_hard_affinity, c->cpu_valid);
if ( cpumask_empty(&online_affinity) &&
- cpumask_test_cpu(cpu, v->cpu_affinity) )
+ cpumask_test_cpu(cpu, v->cpu_hard_affinity) )
{
- printk(XENLOG_DEBUG "Breaking affinity for d%dv%d\n",
- d->domain_id, v->vcpu_id);
+ printk(XENLOG_DEBUG "Breaking affinity for %pv\n", v);
if (system_state == SYS_STATE_suspend)
{
- cpumask_copy(v->cpu_affinity_saved, v->cpu_affinity);
+ cpumask_copy(v->cpu_hard_affinity_saved,
+ v->cpu_hard_affinity);
v->affinity_broken = 1;
}
- cpumask_setall(v->cpu_affinity);
+ cpumask_setall(v->cpu_hard_affinity);
}
if ( v->processor == cpu )
@@ -646,27 +655,14 @@ int cpu_disable_scheduler(unsigned int cpu)
return ret;
}
-void sched_set_node_affinity(struct domain *d, nodemask_t *mask)
+static int vcpu_set_affinity(
+ struct vcpu *v, const cpumask_t *affinity, cpumask_t *which)
{
- SCHED_OP(DOM2OP(d), set_node_affinity, d, mask);
-}
-
-int vcpu_set_affinity(struct vcpu *v, const cpumask_t *affinity)
-{
- cpumask_t online_affinity;
- cpumask_t *online;
spinlock_t *lock;
- if ( v->domain->is_pinned )
- return -EINVAL;
- online = VCPU2ONLINE(v);
- cpumask_and(&online_affinity, affinity, online);
- if ( cpumask_empty(&online_affinity) )
- return -EINVAL;
-
lock = vcpu_schedule_lock_irq(v);
- cpumask_copy(v->cpu_affinity, affinity);
+ cpumask_copy(which, affinity);
/* Always ask the scheduler to re-evaluate placement
* when changing the affinity */
@@ -685,6 +681,27 @@ int vcpu_set_affinity(struct vcpu *v, const cpumask_t *affinity)
return 0;
}
+int vcpu_set_hard_affinity(struct vcpu *v, const cpumask_t *affinity)
+{
+ cpumask_t online_affinity;
+ cpumask_t *online;
+
+ if ( v->domain->is_pinned )
+ return -EINVAL;
+
+ online = VCPU2ONLINE(v);
+ cpumask_and(&online_affinity, affinity, online);
+ if ( cpumask_empty(&online_affinity) )
+ return -EINVAL;
+
+ return vcpu_set_affinity(v, affinity, v->cpu_hard_affinity);
+}
+
+int vcpu_set_soft_affinity(struct vcpu *v, const cpumask_t *affinity)
+{
+ return vcpu_set_affinity(v, affinity, v->cpu_soft_affinity);
+}
+
/* Block the currently-executing domain until a pertinent event occurs. */
void vcpu_block(void)
{
@@ -783,7 +800,7 @@ static long do_poll(struct sched_poll *sched_poll)
}
/* Voluntarily yield the processor for this allocation. */
-static long do_yield(void)
+long vcpu_yield(void)
{
struct vcpu * v=current;
spinlock_t *lock = vcpu_schedule_lock_irq(v);
@@ -876,7 +893,7 @@ long do_sched_op_compat(int cmd, unsigned long arg)
{
case SCHEDOP_yield:
{
- ret = do_yield();
+ ret = vcpu_yield();
break;
}
@@ -913,7 +930,7 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
{
case SCHEDOP_yield:
{
- ret = do_yield();
+ ret = vcpu_yield();
break;
}
@@ -1239,7 +1256,7 @@ static void schedule(void)
stop_timer(&prev->periodic_timer);
if ( next_slice.migrated )
- evtchn_move_pirqs(next);
+ sched_move_irqs(next);
vcpu_periodic_timer_work(next);
diff --git a/xen/common/shutdown.c b/xen/common/shutdown.c
index 9bccd34..94d4c53 100644
--- a/xen/common/shutdown.c
+++ b/xen/common/shutdown.c
@@ -17,7 +17,7 @@
bool_t __read_mostly opt_noreboot;
boolean_param("noreboot", opt_noreboot);
-static void maybe_reboot(void)
+static void noreturn maybe_reboot(void)
{
if ( opt_noreboot )
{
@@ -32,7 +32,7 @@ static void maybe_reboot(void)
}
}
-void dom0_shutdown(u8 reason)
+void hwdom_shutdown(u8 reason)
{
switch ( reason )
{
diff --git a/xen/common/softirq.c b/xen/common/softirq.c
index 195f8ff..22e417a 100644
--- a/xen/common/softirq.c
+++ b/xen/common/softirq.c
@@ -23,6 +23,9 @@ irq_cpustat_t irq_stat[NR_CPUS];
static softirq_handler softirq_handlers[NR_SOFTIRQS];
+static DEFINE_PER_CPU(cpumask_t, batch_mask);
+static DEFINE_PER_CPU(unsigned int, batching);
+
static void __do_softirq(unsigned long ignore_mask)
{
unsigned int i, cpu;
@@ -70,22 +73,59 @@ void open_softirq(int nr, softirq_handler handler)
void cpumask_raise_softirq(const cpumask_t *mask, unsigned int nr)
{
- int cpu;
- cpumask_t send_mask;
+ unsigned int cpu, this_cpu = smp_processor_id();
+ cpumask_t send_mask, *raise_mask;
+
+ if ( !per_cpu(batching, this_cpu) || in_irq() )
+ {
+ cpumask_clear(&send_mask);
+ raise_mask = &send_mask;
+ }
+ else
+ raise_mask = &per_cpu(batch_mask, this_cpu);
- cpumask_clear(&send_mask);
for_each_cpu(cpu, mask)
- if ( !test_and_set_bit(nr, &softirq_pending(cpu)) )
- cpumask_set_cpu(cpu, &send_mask);
+ if ( !test_and_set_bit(nr, &softirq_pending(cpu)) &&
+ cpu != this_cpu &&
+ !arch_skip_send_event_check(cpu) )
+ cpumask_set_cpu(cpu, raise_mask);
- smp_send_event_check_mask(&send_mask);
+ if ( raise_mask == &send_mask )
+ smp_send_event_check_mask(raise_mask);
}
void cpu_raise_softirq(unsigned int cpu, unsigned int nr)
{
- if ( !test_and_set_bit(nr, &softirq_pending(cpu))
- && (cpu != smp_processor_id()) )
+ unsigned int this_cpu = smp_processor_id();
+
+ if ( test_and_set_bit(nr, &softirq_pending(cpu))
+ || (cpu == this_cpu)
+ || arch_skip_send_event_check(cpu) )
+ return;
+
+ if ( !per_cpu(batching, this_cpu) || in_irq() )
smp_send_event_check_cpu(cpu);
+ else
+ set_bit(nr, &per_cpu(batch_mask, this_cpu));
+}
+
+void cpu_raise_softirq_batch_begin(void)
+{
+ ++this_cpu(batching);
+}
+
+void cpu_raise_softirq_batch_finish(void)
+{
+ unsigned int cpu, this_cpu = smp_processor_id();
+ cpumask_t *mask = &per_cpu(batch_mask, this_cpu);
+
+ ASSERT(per_cpu(batching, this_cpu));
+ for_each_cpu ( cpu, mask )
+ if ( !softirq_pending(cpu) )
+ cpumask_clear_cpu(cpu, mask);
+ smp_send_event_check_mask(mask);
+ cpumask_clear(mask);
+ --per_cpu(batching, this_cpu);
}
void raise_softirq(unsigned int nr)
diff --git a/xen/common/symbols.c b/xen/common/symbols.c
index 45941e1..bc2fde6 100644
--- a/xen/common/symbols.c
+++ b/xen/common/symbols.c
@@ -96,7 +96,7 @@ static unsigned int get_symbol_offset(unsigned long pos)
bool_t is_active_kernel_text(unsigned long addr)
{
return (is_kernel_text(addr) ||
- (system_state == SYS_STATE_boot && is_kernel_inittext(addr)));
+ (system_state < SYS_STATE_active && is_kernel_inittext(addr)));
}
const char *symbols_lookup(unsigned long addr,
diff --git a/xen/common/tmem.c b/xen/common/tmem.c
index ea4d9cc..f2dc26e 100644
--- a/xen/common/tmem.c
+++ b/xen/common/tmem.c
@@ -88,6 +88,7 @@ struct share_list {
struct client *client;
};
+#define POOL_PAGESHIFT (PAGE_SHIFT - 12)
#define OBJ_HASH_BUCKETS 256 /* must be power of two */
#define OBJ_HASH_BUCKETS_MASK (OBJ_HASH_BUCKETS-1)
@@ -95,8 +96,6 @@ struct tmem_pool {
bool_t shared;
bool_t persistent;
bool_t is_dying;
- int pageshift; /* 0 == 2**12 */
- struct list_head pool_list;
struct client *client;
uint64_t uuid[2]; /* 0 for private, non-zero for shared */
uint32_t pool_id;
@@ -199,7 +198,6 @@ rwlock_t pcd_tree_rwlocks[256]; /* poor man's concurrency for now */
static LIST_HEAD(global_ephemeral_page_list); /* all pages in ephemeral pools */
static LIST_HEAD(global_client_list);
-static LIST_HEAD(global_pool_list);
static struct tmem_pool *global_shared_pools[MAX_GLOBAL_SHARED_POOLS] = { 0 };
static bool_t global_shared_auth = 0;
@@ -654,15 +652,21 @@ static void pgp_free_data(struct tmem_page_descriptor *pgp, struct tmem_pool *po
pgp->size = -1;
}
-static void pgp_free(struct tmem_page_descriptor *pgp, int from_delete)
+static void __pgp_free(struct tmem_page_descriptor *pgp, struct tmem_pool *pool)
+{
+ pgp->us.obj = NULL;
+ pgp->index = -1;
+ tmem_free(pgp, pool);
+}
+
+static void pgp_free(struct tmem_page_descriptor *pgp)
{
struct tmem_pool *pool = NULL;
ASSERT(pgp->us.obj != NULL);
- ASSERT(pgp->us.obj->pool->client != NULL);
- if ( from_delete )
- ASSERT(pgp_lookup_in_obj(pgp->us.obj,pgp->index) == NULL);
ASSERT(pgp->us.obj->pool != NULL);
+ ASSERT(pgp->us.obj->pool->client != NULL);
+
pool = pgp->us.obj->pool;
if ( !is_persistent(pool) )
{
@@ -679,34 +683,25 @@ static void pgp_free(struct tmem_page_descriptor *pgp, int from_delete)
pgp->pool_id = pool->pool_id;
return;
}
- pgp->us.obj = NULL;
- pgp->index = -1;
- tmem_free(pgp, pool);
-}
-
-static void pgp_free_from_inv_list(struct client *client, struct tmem_page_descriptor *pgp)
-{
- struct tmem_pool *pool = client->pools[pgp->pool_id];
-
- pgp->us.obj = NULL;
- pgp->index = -1;
- tmem_free(pgp, pool);
+ __pgp_free(pgp, pool);
}
-/* remove the page from appropriate lists but not from parent object */
-static void pgp_delist(struct tmem_page_descriptor *pgp, bool_t no_eph_lock)
+/* remove pgp from global/pool/client lists and free it */
+static void pgp_delist_free(struct tmem_page_descriptor *pgp)
{
struct client *client;
+ uint64_t life;
ASSERT(pgp != NULL);
ASSERT(pgp->us.obj != NULL);
ASSERT(pgp->us.obj->pool != NULL);
client = pgp->us.obj->pool->client;
ASSERT(client != NULL);
+
+ /* Delist pgp */
if ( !is_persistent(pgp->us.obj->pool) )
{
- if ( !no_eph_lock )
- spin_lock(&eph_lists_spinlock);
+ spin_lock(&eph_lists_spinlock);
if ( !list_empty(&pgp->us.client_eph_pages) )
client->eph_count--;
ASSERT(client->eph_count >= 0);
@@ -715,9 +710,10 @@ static void pgp_delist(struct tmem_page_descriptor *pgp, bool_t no_eph_lock)
global_eph_count--;
ASSERT(global_eph_count >= 0);
list_del_init(&pgp->global_eph_pages);
- if ( !no_eph_lock )
- spin_unlock(&eph_lists_spinlock);
- } else {
+ spin_unlock(&eph_lists_spinlock);
+ }
+ else
+ {
if ( client->live_migrating )
{
spin_lock(&pers_lists_spinlock);
@@ -726,26 +722,19 @@ static void pgp_delist(struct tmem_page_descriptor *pgp, bool_t no_eph_lock)
if ( pgp != pgp->us.obj->pool->cur_pgp )
list_del_init(&pgp->us.pool_pers_pages);
spin_unlock(&pers_lists_spinlock);
- } else {
+ }
+ else
+ {
spin_lock(&pers_lists_spinlock);
list_del_init(&pgp->us.pool_pers_pages);
spin_unlock(&pers_lists_spinlock);
}
}
-}
-
-/* remove page from lists (but not from parent object) and free it */
-static void pgp_delete(struct tmem_page_descriptor *pgp, bool_t no_eph_lock)
-{
- uint64_t life;
-
- ASSERT(pgp != NULL);
- ASSERT(pgp->us.obj != NULL);
- ASSERT(pgp->us.obj->pool != NULL);
life = get_cycles() - pgp->timestamp;
pgp->us.obj->pool->sum_life_cycles += life;
- pgp_delist(pgp, no_eph_lock);
- pgp_free(pgp,1);
+
+ /* free pgp */
+ pgp_free(pgp);
}
/* called only indirectly by radix_tree_destroy */
@@ -753,12 +742,8 @@ static void pgp_destroy(void *v)
{
struct tmem_page_descriptor *pgp = (struct tmem_page_descriptor *)v;
- ASSERT_SPINLOCK(&pgp->us.obj->obj_spinlock);
- pgp_delist(pgp,0);
- ASSERT(pgp->us.obj != NULL);
pgp->us.obj->pgp_count--;
- ASSERT(pgp->us.obj->pgp_count >= 0);
- pgp_free(pgp,0);
+ pgp_delist_free(pgp);
}
static int pgp_add_to_obj(struct tmem_object_root *obj, uint32_t index, struct tmem_page_descriptor *pgp)
@@ -829,7 +814,7 @@ static void rtn_free(struct radix_tree_node *rtn, void *arg)
/************ POOL OBJECT COLLECTION MANIPULATION ROUTINES *******************/
-int oid_compare(struct oid *left, struct oid *right)
+static int oid_compare(struct oid *left, struct oid *right)
{
if ( left->oid[2] == right->oid[2] )
{
@@ -853,12 +838,12 @@ int oid_compare(struct oid *left, struct oid *right)
return 1;
}
-void oid_set_invalid(struct oid *oidp)
+static void oid_set_invalid(struct oid *oidp)
{
oidp->oid[0] = oidp->oid[1] = oidp->oid[2] = -1UL;
}
-unsigned oid_hash(struct oid *oidp)
+static unsigned oid_hash(struct oid *oidp)
{
return (tmem_hash(oidp->oid[0] ^ oidp->oid[1] ^ oidp->oid[2],
BITS_PER_LONG) & OBJ_HASH_BUCKETS_MASK);
@@ -898,7 +883,7 @@ restart_find:
}
/* free an object that has no more pgps in it */
-static void obj_free(struct tmem_object_root *obj, int no_rebalance)
+static void obj_free(struct tmem_object_root *obj)
{
struct tmem_pool *pool;
struct oid old_oid;
@@ -921,9 +906,7 @@ static void obj_free(struct tmem_object_root *obj, int no_rebalance)
oid_set_invalid(&obj->oid);
obj->last_client = TMEM_CLI_ID_NULL;
atomic_dec_and_assert(global_obj_count);
- /* use no_rebalance only if all objects are being destroyed anyway */
- if ( !no_rebalance )
- rb_erase(&obj->rb_tree_node,&pool->obj_rb_root[oid_hash(&old_oid)]);
+ rb_erase(&obj->rb_tree_node, &pool->obj_rb_root[oid_hash(&old_oid)]);
spin_unlock(&obj->obj_spinlock);
tmem_free(obj, pool);
}
@@ -959,12 +942,11 @@ static int obj_rb_insert(struct rb_root *root, struct tmem_object_root *obj)
* allocate, initialize, and insert an tmem_object_root
* (should be called only if find failed)
*/
-static struct tmem_object_root * obj_new(struct tmem_pool *pool, struct oid *oidp)
+static struct tmem_object_root * obj_alloc(struct tmem_pool *pool, struct oid *oidp)
{
struct tmem_object_root *obj;
ASSERT(pool != NULL);
- ASSERT_WRITELOCK(&pool->pool_rwlock);
if ( (obj = tmem_malloc(sizeof(struct tmem_object_root), pool)) == NULL )
return NULL;
pool->obj_count++;
@@ -979,22 +961,19 @@ static struct tmem_object_root * obj_new(struct tmem_pool *pool, struct oid *oid
obj->objnode_count = 0;
obj->pgp_count = 0;
obj->last_client = TMEM_CLI_ID_NULL;
- spin_lock(&obj->obj_spinlock);
- obj_rb_insert(&pool->obj_rb_root[oid_hash(oidp)], obj);
- ASSERT_SPINLOCK(&obj->obj_spinlock);
return obj;
}
/* free an object after destroying any pgps in it */
-static void obj_destroy(struct tmem_object_root *obj, int no_rebalance)
+static void obj_destroy(struct tmem_object_root *obj)
{
ASSERT_WRITELOCK(&obj->pool->pool_rwlock);
radix_tree_destroy(&obj->tree_root, pgp_destroy);
- obj_free(obj,no_rebalance);
+ obj_free(obj);
}
/* destroys all objs in a pool, or only if obj->last_client matches cli_id */
-static void pool_destroy_objs(struct tmem_pool *pool, bool_t selective, domid_t cli_id)
+static void pool_destroy_objs(struct tmem_pool *pool, domid_t cli_id)
{
struct rb_node *node;
struct tmem_object_root *obj;
@@ -1010,11 +989,8 @@ static void pool_destroy_objs(struct tmem_pool *pool, bool_t selective, domid_t
obj = container_of(node, struct tmem_object_root, rb_tree_node);
spin_lock(&obj->obj_spinlock);
node = rb_next(node);
- if ( !selective )
- /* FIXME: should be obj,1 but walking/erasing rbtree is racy */
- obj_destroy(obj,0);
- else if ( obj->last_client == cli_id )
- obj_destroy(obj,0);
+ if ( obj->last_client == cli_id )
+ obj_destroy(obj);
else
spin_unlock(&obj->obj_spinlock);
}
@@ -1030,50 +1006,39 @@ static struct tmem_pool * pool_alloc(void)
struct tmem_pool *pool;
int i;
- if ( (pool = xmalloc(struct tmem_pool)) == NULL )
+ if ( (pool = xzalloc(struct tmem_pool)) == NULL )
return NULL;
for (i = 0; i < OBJ_HASH_BUCKETS; i++)
pool->obj_rb_root[i] = RB_ROOT;
- INIT_LIST_HEAD(&pool->pool_list);
INIT_LIST_HEAD(&pool->persistent_page_list);
- pool->cur_pgp = NULL;
rwlock_init(&pool->pool_rwlock);
- pool->pgp_count_max = pool->obj_count_max = 0;
- pool->objnode_count = pool->objnode_count_max = 0;
- atomic_set(&pool->pgp_count,0);
- pool->obj_count = 0; pool->shared_count = 0;
- pool->pageshift = PAGE_SHIFT - 12;
- pool->good_puts = pool->puts = pool->dup_puts_flushed = 0;
- pool->dup_puts_replaced = pool->no_mem_puts = 0;
- pool->found_gets = pool->gets = 0;
- pool->flushs_found = pool->flushs = 0;
- pool->flush_objs_found = pool->flush_objs = 0;
- pool->is_dying = 0;
return pool;
}
static void pool_free(struct tmem_pool *pool)
{
pool->client = NULL;
- list_del(&pool->pool_list);
xfree(pool);
}
-/* register new_client as a user of this shared pool and return new
- total number of registered users */
+/*
+ * Register new_client as a user of this shared pool and return 0 on succ.
+ */
static int shared_pool_join(struct tmem_pool *pool, struct client *new_client)
{
struct share_list *sl;
-
ASSERT(is_shared(pool));
+
if ( (sl = tmem_malloc(sizeof(struct share_list), NULL)) == NULL )
return -1;
sl->client = new_client;
list_add_tail(&sl->share_list, &pool->share_list);
if ( new_client->cli_id != pool->client->cli_id )
tmem_client_info("adding new %s %d to shared pool owned by %s %d\n",
- tmem_client_str, new_client->cli_id, tmem_client_str, pool->client->cli_id);
- return ++pool->shared_count;
+ tmem_client_str, new_client->cli_id, tmem_client_str,
+ pool->client->cli_id);
+ ++pool->shared_count;
+ return 0;
}
/* reassign "ownership" of the pool to another client that shares this pool */
@@ -1117,7 +1082,7 @@ static int shared_pool_quit(struct tmem_pool *pool, domid_t cli_id)
ASSERT(pool->client != NULL);
ASSERT_WRITELOCK(&tmem_rwlock);
- pool_destroy_objs(pool,1,cli_id);
+ pool_destroy_objs(pool, cli_id);
list_for_each_entry(sl,&pool->share_list, share_list)
{
if (sl->client->cli_id != cli_id)
@@ -1143,7 +1108,7 @@ static int shared_pool_quit(struct tmem_pool *pool, domid_t cli_id)
}
/* flush all data (owned by cli_id) from a pool and, optionally, free it */
-static void pool_flush(struct tmem_pool *pool, domid_t cli_id, bool_t destroy)
+static void pool_flush(struct tmem_pool *pool, domid_t cli_id)
{
ASSERT(pool != NULL);
if ( (is_shared(pool)) && (shared_pool_quit(pool,cli_id) > 0) )
@@ -1152,23 +1117,19 @@ static void pool_flush(struct tmem_pool *pool, domid_t cli_id, bool_t destroy)
tmem_cli_id_str, cli_id, pool->pool_id, tmem_cli_id_str,pool->client->cli_id);
return;
}
- tmem_client_info("%s %s-%s tmem pool %s=%d pool_id=%d\n",
- destroy ? "destroying" : "flushing",
+ tmem_client_info("Destroying %s-%s tmem pool %s=%d pool_id=%d\n",
is_persistent(pool) ? "persistent" : "ephemeral" ,
is_shared(pool) ? "shared" : "private",
tmem_cli_id_str, pool->client->cli_id, pool->pool_id);
if ( pool->client->live_migrating )
{
- tmem_client_warn("can't %s pool while %s is live-migrating\n",
- destroy?"destroy":"flush", tmem_client_str);
+ tmem_client_warn("can't destroy pool while %s is live-migrating\n",
+ tmem_client_str);
return;
}
- pool_destroy_objs(pool,0,TMEM_CLI_ID_NULL);
- if ( destroy )
- {
- pool->client->pools[pool->pool_id] = NULL;
- pool_free(pool);
- }
+ pool_destroy_objs(pool, TMEM_CLI_ID_NULL);
+ pool->client->pools[pool->pool_id] = NULL;
+ pool_free(pool);
}
/************ CLIENT MANIPULATION OPERATIONS **************************/
@@ -1217,15 +1178,9 @@ static struct client *client_create(domid_t cli_id)
for ( i = 0; i < MAX_GLOBAL_SHARED_POOLS; i++)
client->shared_auth_uuid[i][0] =
client->shared_auth_uuid[i][1] = -1L;
- client->frozen = 0; client->live_migrating = 0;
- client->weight = 0; client->cap = 0;
list_add_tail(&client->client_list, &global_client_list);
INIT_LIST_HEAD(&client->ephemeral_page_list);
INIT_LIST_HEAD(&client->persistent_invalidated_list);
- client->cur_pgp = NULL;
- client->eph_count = client->eph_count_max = 0;
- client->total_cycles = 0; client->succ_pers_puts = 0;
- client->succ_eph_gets = 0; client->succ_pers_gets = 0;
tmem_client_info("ok\n");
return client;
@@ -1242,7 +1197,7 @@ static void client_free(struct client *client)
}
/* flush all data from a client and, optionally, free it */
-static void client_flush(struct client *client, bool_t destroy)
+static void client_flush(struct client *client)
{
int i;
struct tmem_pool *pool;
@@ -1251,12 +1206,10 @@ static void client_flush(struct client *client, bool_t destroy)
{
if ( (pool = client->pools[i]) == NULL )
continue;
- pool_flush(pool,client->cli_id,destroy);
- if ( destroy )
- client->pools[i] = NULL;
+ pool_flush(pool, client->cli_id);
+ client->pools[i] = NULL;
}
- if ( destroy )
- client_free(client);
+ client_free(client);
}
static bool_t client_over_quota(struct client *client)
@@ -1271,11 +1224,6 @@ static bool_t client_over_quota(struct client *client)
((total*100L) / client->weight) );
}
-static void client_freeze(struct client *client, int freeze)
-{
- client->frozen = freeze;
-}
-
/************ MEMORY REVOCATION ROUTINES *******************************/
static bool_t tmem_try_to_evict_pgp(struct tmem_page_descriptor *pgp, bool_t *hold_pool_rwlock)
@@ -1315,7 +1263,8 @@ static bool_t tmem_try_to_evict_pgp(struct tmem_page_descriptor *pgp, bool_t *ho
return 1;
}
pcd_unlock:
- write_unlock(&pcd_tree_rwlocks[firstbyte]);
+ if ( tmem_dedup_enabled() )
+ write_unlock(&pcd_tree_rwlocks[firstbyte]);
obj_unlock:
spin_unlock(&obj->obj_spinlock);
}
@@ -1325,7 +1274,7 @@ obj_unlock:
static int tmem_evict(void)
{
struct client *client = current->domain->tmem_client;
- struct tmem_page_descriptor *pgp = NULL, *pgp2, *pgp_del;
+ struct tmem_page_descriptor *pgp = NULL, *pgp_del;
struct tmem_object_root *obj;
struct tmem_pool *pool;
int ret = 0;
@@ -1336,21 +1285,33 @@ static int tmem_evict(void)
if ( (client != NULL) && client_over_quota(client) &&
!list_empty(&client->ephemeral_page_list) )
{
- list_for_each_entry_safe(pgp,pgp2,&client->ephemeral_page_list,us.client_eph_pages)
- if ( tmem_try_to_evict_pgp(pgp,&hold_pool_rwlock) )
+ list_for_each_entry(pgp, &client->ephemeral_page_list, us.client_eph_pages)
+ if ( tmem_try_to_evict_pgp(pgp, &hold_pool_rwlock) )
goto found;
- } else if ( list_empty(&global_ephemeral_page_list) ) {
- goto out;
- } else {
- list_for_each_entry_safe(pgp,pgp2,&global_ephemeral_page_list,global_eph_pages)
- if ( tmem_try_to_evict_pgp(pgp,&hold_pool_rwlock) )
+ }
+ else if ( !list_empty(&global_ephemeral_page_list) )
+ {
+ list_for_each_entry(pgp, &global_ephemeral_page_list, global_eph_pages)
+ if ( tmem_try_to_evict_pgp(pgp, &hold_pool_rwlock) )
+ {
+ client = pgp->us.obj->pool->client;
goto found;
+ }
}
-
- ret = 0;
+ /* global_ephemeral_page_list is empty, so we bail out. */
+ spin_unlock(&eph_lists_spinlock);
goto out;
found:
+ /* Delist */
+ list_del_init(&pgp->us.client_eph_pages);
+ client->eph_count--;
+ list_del_init(&pgp->global_eph_pages);
+ global_eph_count--;
+ ASSERT(global_eph_count >= 0);
+ ASSERT(client->eph_count >= 0);
+ spin_unlock(&eph_lists_spinlock);
+
ASSERT(pgp != NULL);
obj = pgp->us.obj;
ASSERT(obj != NULL);
@@ -1365,11 +1326,13 @@ found:
ASSERT(pgp->pcd->pgp_ref_count == 1 || pgp->eviction_attempted);
pcd_disassociate(pgp,pool,1);
}
- pgp_delete(pgp,1);
+
+ /* pgp already delist, so call pgp_free directly */
+ pgp_free(pgp);
if ( obj->pgp_count == 0 )
{
ASSERT_WRITELOCK(&pool->pool_rwlock);
- obj_free(obj,0);
+ obj_free(obj);
}
else
spin_unlock(&obj->obj_spinlock);
@@ -1377,9 +1340,7 @@ found:
write_unlock(&pool->pool_rwlock);
evicted_pgs++;
ret = 1;
-
out:
- spin_unlock(&eph_lists_spinlock);
return ret;
}
@@ -1546,11 +1507,11 @@ failed_dup:
cleanup:
pgpfound = pgp_delete_from_obj(obj, pgp->index);
ASSERT(pgpfound == pgp);
- pgp_delete(pgpfound,0);
+ pgp_delist_free(pgpfound);
if ( obj->pgp_count == 0 )
{
write_lock(&pool->pool_rwlock);
- obj_free(obj,0);
+ obj_free(obj);
write_unlock(&pool->pool_rwlock);
} else {
spin_unlock(&obj->obj_spinlock);
@@ -1570,10 +1531,13 @@ static int do_tmem_put(struct tmem_pool *pool,
ASSERT(pool != NULL);
client = pool->client;
+ ASSERT(client != NULL);
ret = client->frozen ? -EFROZEN : -ENOMEM;
pool->puts++;
+
+refind:
/* does page already exist (dup)? if so, handle specially */
- if ( (obj = obj_find(pool,oidp)) != NULL )
+ if ( (obj = obj_find(pool, oidp)) != NULL )
{
if ((pgp = pgp_lookup_in_obj(obj, index)) != NULL)
{
@@ -1591,12 +1555,22 @@ static int do_tmem_put(struct tmem_pool *pool,
/* no puts allowed into a frozen pool (except dup puts) */
if ( client->frozen )
return ret;
+ if ( (obj = obj_alloc(pool, oidp)) == NULL )
+ return -ENOMEM;
+
write_lock(&pool->pool_rwlock);
- if ( (obj = obj_new(pool,oidp)) == NULL )
+ /*
+ * Parallel callers may already allocated obj and inserted to obj_rb_root
+ * before us.
+ */
+ if (!obj_rb_insert(&pool->obj_rb_root[oid_hash(oidp)], obj))
{
+ tmem_free(obj, pool);
write_unlock(&pool->pool_rwlock);
- return -ENOMEM;
+ goto refind;
}
+
+ spin_lock(&obj->obj_spinlock);
newobj = 1;
write_unlock(&pool->pool_rwlock);
}
@@ -1646,8 +1620,11 @@ copy_uncompressed:
if ( tmem_dedup_enabled() && !is_persistent(pool) )
{
- if ( pcd_associate(pgp,NULL,0) == -ENOMEM )
+ if ( pcd_associate(pgp, NULL, 0) == -ENOMEM )
+ {
+ ret = -ENOMEM;
goto del_pgp_from_obj;
+ }
}
insert_page:
@@ -1693,12 +1670,12 @@ del_pgp_from_obj:
pgp_delete_from_obj(obj, pgp->index);
free_pgp:
- pgp_delete(pgp, 0);
+ pgp_free(pgp);
unlock_obj:
if ( newobj )
{
write_lock(&pool->pool_rwlock);
- obj_free(obj, 0);
+ obj_free(obj);
write_unlock(&pool->pool_rwlock);
}
else
@@ -1752,11 +1729,11 @@ static int do_tmem_get(struct tmem_pool *pool, struct oid *oidp, uint32_t index,
{
if ( !is_shared(pool) )
{
- pgp_delete(pgp,0);
+ pgp_delist_free(pgp);
if ( obj->pgp_count == 0 )
{
write_lock(&pool->pool_rwlock);
- obj_free(obj,0);
+ obj_free(obj);
obj = NULL;
write_unlock(&pool->pool_rwlock);
}
@@ -1802,11 +1779,11 @@ static int do_tmem_flush_page(struct tmem_pool *pool, struct oid *oidp, uint32_t
spin_unlock(&obj->obj_spinlock);
goto out;
}
- pgp_delete(pgp,0);
+ pgp_delist_free(pgp);
if ( obj->pgp_count == 0 )
{
write_lock(&pool->pool_rwlock);
- obj_free(obj,0);
+ obj_free(obj);
write_unlock(&pool->pool_rwlock);
} else {
spin_unlock(&obj->obj_spinlock);
@@ -1829,7 +1806,7 @@ static int do_tmem_flush_object(struct tmem_pool *pool, struct oid *oidp)
if ( obj == NULL )
goto out;
write_lock(&pool->pool_rwlock);
- obj_destroy(obj,0);
+ obj_destroy(obj);
pool->flush_objs_found++;
write_unlock(&pool->pool_rwlock);
@@ -1850,7 +1827,7 @@ static int do_tmem_destroy_pool(uint32_t pool_id)
if ( (pool = client->pools[pool_id]) == NULL )
return 0;
client->pools[pool_id] = NULL;
- pool_flush(pool,client->cli_id,1);
+ pool_flush(pool, client->cli_id);
return 1;
}
@@ -1867,8 +1844,7 @@ static int do_tmem_new_pool(domid_t this_cli_id,
int specversion = (flags >> TMEM_POOL_VERSION_SHIFT)
& TMEM_POOL_VERSION_MASK;
struct tmem_pool *pool, *shpool;
- int s_poolid, first_unused_s_poolid;
- int i;
+ int i, first_unused_s_poolid;
if ( this_cli_id == TMEM_CLI_ID_NULL )
cli_id = current->domain->domain_id;
@@ -1882,6 +1858,11 @@ static int do_tmem_new_pool(domid_t this_cli_id,
tmem_client_err("failed... unsupported spec version\n");
return -EPERM;
}
+ if ( shared && persistent )
+ {
+ tmem_client_err("failed... unable to create a shared-persistant pool\n");
+ return -EPERM;
+ }
if ( pagebits != (PAGE_SHIFT - 12) )
{
tmem_client_err("failed... unsupported pagesize %d\n",
@@ -1898,17 +1879,12 @@ static int do_tmem_new_pool(domid_t this_cli_id,
tmem_client_err("failed... reserved bits must be zero\n");
return -EPERM;
}
- if ( (pool = pool_alloc()) == NULL )
- {
- tmem_client_err("failed... out of memory\n");
- return -ENOMEM;
- }
if ( this_cli_id != TMEM_CLI_ID_NULL )
{
if ( (client = tmem_client_from_cli_id(this_cli_id)) == NULL
|| d_poolid >= MAX_POOLS_PER_DOMAIN
|| client->pools[d_poolid] != NULL )
- goto fail;
+ return -EPERM;
}
else
{
@@ -1921,13 +1897,35 @@ static int do_tmem_new_pool(domid_t this_cli_id,
{
tmem_client_err("failed... no more pool slots available for this %s\n",
tmem_client_str);
- goto fail;
+ return -EPERM;
}
}
+
+ if ( (pool = pool_alloc()) == NULL )
+ {
+ tmem_client_err("failed... out of memory\n");
+ return -ENOMEM;
+ }
+ client->pools[d_poolid] = pool;
+ pool->client = client;
+ pool->pool_id = d_poolid;
+ pool->shared = shared;
+ pool->persistent = persistent;
+ pool->uuid[0] = uuid_lo;
+ pool->uuid[1] = uuid_hi;
+
+ /*
+ * Already created a pool when arrived here, but need some special process
+ * for shared pool.
+ */
if ( shared )
{
if ( uuid_lo == -1L && uuid_hi == -1L )
- shared = 0;
+ {
+ tmem_client_info("Invalid uuid, create non shared pool instead!\n");
+ pool->shared = 0;
+ goto out;
+ }
if ( client->shared_auth_required && !global_shared_auth )
{
for ( i = 0; i < MAX_GLOBAL_SHARED_POOLS; i++)
@@ -1935,49 +1933,60 @@ static int do_tmem_new_pool(domid_t this_cli_id,
(client->shared_auth_uuid[i][1] == uuid_hi) )
break;
if ( i == MAX_GLOBAL_SHARED_POOLS )
- shared = 0;
+ {
+ tmem_client_info("Shared auth failed, create non shared pool instead!\n");
+ pool->shared = 0;
+ goto out;
+ }
}
- }
- pool->shared = shared;
- pool->client = client;
- if ( shared )
- {
+
+ /*
+ * Authorize okay, match a global shared pool or use the newly allocated
+ * one
+ */
first_unused_s_poolid = MAX_GLOBAL_SHARED_POOLS;
- for ( s_poolid = 0; s_poolid < MAX_GLOBAL_SHARED_POOLS; s_poolid++ )
+ for ( i = 0; i < MAX_GLOBAL_SHARED_POOLS; i++ )
{
- if ( (shpool = global_shared_pools[s_poolid]) != NULL )
+ if ( (shpool = global_shared_pools[i]) != NULL )
{
if ( shpool->uuid[0] == uuid_lo && shpool->uuid[1] == uuid_hi )
{
+ /* Succ to match a global shared pool */
tmem_client_info("(matches shared pool uuid=%"PRIx64".%"PRIx64") pool_id=%d\n",
uuid_hi, uuid_lo, d_poolid);
- client->pools[d_poolid] = global_shared_pools[s_poolid];
- shared_pool_join(global_shared_pools[s_poolid], client);
- pool_free(pool);
- return d_poolid;
+ client->pools[d_poolid] = shpool;
+ if ( !shared_pool_join(shpool, client) )
+ {
+ pool_free(pool);
+ goto out;
+ }
+ else
+ goto fail;
}
}
- else if ( first_unused_s_poolid == MAX_GLOBAL_SHARED_POOLS )
- first_unused_s_poolid = s_poolid;
+ else
+ {
+ if ( first_unused_s_poolid == MAX_GLOBAL_SHARED_POOLS )
+ first_unused_s_poolid = i;
+ }
}
+
+ /* Failed to find a global shard pool slot */
if ( first_unused_s_poolid == MAX_GLOBAL_SHARED_POOLS )
{
tmem_client_warn("tmem: failed... no global shared pool slots available\n");
goto fail;
}
+ /* Add pool to global shard pool */
else
{
INIT_LIST_HEAD(&pool->share_list);
pool->shared_count = 0;
global_shared_pools[first_unused_s_poolid] = pool;
- (void)shared_pool_join(pool,client);
}
}
- client->pools[d_poolid] = pool;
- list_add_tail(&pool->pool_list, &global_pool_list);
- pool->pool_id = d_poolid;
- pool->persistent = persistent;
- pool->uuid[0] = uuid_lo; pool->uuid[1] = uuid_hi;
+
+out:
tmem_client_info("pool_id=%d\n", d_poolid);
return d_poolid;
@@ -2000,14 +2009,14 @@ static int tmemc_freeze_pools(domid_t cli_id, int arg)
if ( cli_id == TMEM_CLI_ID_NULL )
{
list_for_each_entry(client,&global_client_list,client_list)
- client_freeze(client,freeze);
+ client->frozen = freeze;
tmem_client_info("tmem: all pools %s for all %ss\n", s, tmem_client_str);
}
else
{
if ( (client = tmem_client_from_cli_id(cli_id)) == NULL)
return -1;
- client_freeze(client,freeze);
+ client->frozen = freeze;
tmem_client_info("tmem: all pools %s for %s=%d\n",
s, tmem_cli_id_str, cli_id);
}
@@ -2203,7 +2212,7 @@ static int tmemc_list(domid_t cli_id, tmem_cli_va_param_t buf, uint32_t len,
return 0;
}
-static int tmemc_set_var_one(struct client *client, uint32_t subop, uint32_t arg1)
+static int __tmemc_set_var(struct client *client, uint32_t subop, uint32_t arg1)
{
domid_t cli_id = client->cli_id;
uint32_t old_weight;
@@ -2245,15 +2254,24 @@ static int tmemc_set_var_one(struct client *client, uint32_t subop, uint32_t arg
static int tmemc_set_var(domid_t cli_id, uint32_t subop, uint32_t arg1)
{
struct client *client;
+ int ret = -1;
if ( cli_id == TMEM_CLI_ID_NULL )
+ {
list_for_each_entry(client,&global_client_list,client_list)
- tmemc_set_var_one(client, subop, arg1);
- else if ( (client = tmem_client_from_cli_id(cli_id)) == NULL)
- return -1;
+ {
+ ret = __tmemc_set_var(client, subop, arg1);
+ if (ret)
+ break;
+ }
+ }
else
- tmemc_set_var_one(client, subop, arg1);
- return 0;
+ {
+ client = tmem_client_from_cli_id(cli_id);
+ if ( client )
+ ret = __tmemc_set_var(client, subop, arg1);
+ }
+ return ret;
}
static int tmemc_shared_pool_auth(domid_t cli_id, uint64_t uuid_lo,
@@ -2270,27 +2288,39 @@ static int tmemc_shared_pool_auth(domid_t cli_id, uint64_t uuid_lo,
client = tmem_client_from_cli_id(cli_id);
if ( client == NULL )
return -EINVAL;
+
for ( i = 0; i < MAX_GLOBAL_SHARED_POOLS; i++)
{
- if ( (client->shared_auth_uuid[i][0] == uuid_lo) &&
- (client->shared_auth_uuid[i][1] == uuid_hi) )
+ if ( auth == 0 )
{
- if ( auth == 0 )
- client->shared_auth_uuid[i][0] =
- client->shared_auth_uuid[i][1] = -1L;
- return 1;
+ if ( (client->shared_auth_uuid[i][0] == uuid_lo) &&
+ (client->shared_auth_uuid[i][1] == uuid_hi) )
+ {
+ client->shared_auth_uuid[i][0] = -1L;
+ client->shared_auth_uuid[i][1] = -1L;
+ return 1;
+ }
}
- if ( (auth == 1) && (client->shared_auth_uuid[i][0] == -1L) &&
- (client->shared_auth_uuid[i][1] == -1L) && (free == -1) )
- free = i;
+ else
+ {
+ if ( (client->shared_auth_uuid[i][0] == -1L) &&
+ (client->shared_auth_uuid[i][1] == -1L) )
+ {
+ free = i;
+ break;
+ }
+ }
}
if ( auth == 0 )
return 0;
- if ( auth == 1 && free == -1 )
+ else if ( free == -1)
return -ENOMEM;
- client->shared_auth_uuid[free][0] = uuid_lo;
- client->shared_auth_uuid[free][1] = uuid_hi;
- return 1;
+ else
+ {
+ client->shared_auth_uuid[free][0] = uuid_lo;
+ client->shared_auth_uuid[free][1] = uuid_hi;
+ return 1;
+ }
}
static int tmemc_save_subop(int cli_id, uint32_t pool_id,
@@ -2353,7 +2383,7 @@ static int tmemc_save_subop(int cli_id, uint32_t pool_id,
break;
rc = (pool->persistent ? TMEM_POOL_PERSIST : 0) |
(pool->shared ? TMEM_POOL_SHARED : 0) |
- (pool->pageshift << TMEM_POOL_PAGESIZE_SHIFT) |
+ (POOL_PAGESHIFT << TMEM_POOL_PAGESIZE_SHIFT) |
(TMEM_SPEC_VERSION << TMEM_POOL_VERSION_SHIFT);
break;
case TMEMC_SAVE_GET_POOL_NPAGES:
@@ -2375,7 +2405,7 @@ static int tmemc_save_subop(int cli_id, uint32_t pool_id,
if ( !list_empty(&client->persistent_invalidated_list) )
list_for_each_entry_safe(pgp,pgp2,
&client->persistent_invalidated_list, client_inv_pages)
- pgp_free_from_inv_list(client,pgp);
+ __pgp_free(pgp, client->pools[pgp->pool_id]);
client->frozen = client->was_frozen;
rc = 0;
break;
@@ -2393,13 +2423,11 @@ static int tmemc_save_get_next_page(int cli_id, uint32_t pool_id,
struct oid oid;
int ret = 0;
struct tmem_handle h;
- unsigned int pagesize;
if ( pool == NULL || !is_persistent(pool) )
return -1;
- pagesize = 1 << (pool->pageshift + 12);
- if ( bufsize < pagesize + sizeof(struct tmem_handle) )
+ if ( bufsize < PAGE_SIZE + sizeof(struct tmem_handle) )
return -ENOMEM;
spin_lock(&pers_lists_spinlock);
@@ -2600,7 +2628,6 @@ long do_tmem_op(tmem_cli_op_t uops)
bool_t succ_get = 0, succ_put = 0;
bool_t non_succ_get = 0, non_succ_put = 0;
bool_t flush = 0, flush_obj = 0;
- bool_t write_lock_set = 0, read_lock_set = 0;
if ( !tmem_initialized )
return -ENODEV;
@@ -2612,127 +2639,116 @@ long do_tmem_op(tmem_cli_op_t uops)
if ( client != NULL && client->domain->is_dying )
{
- rc = -ENODEV;
- simple_error:
errored_tmem_ops++;
- return rc;
+ return -ENODEV;
}
if ( unlikely(tmem_get_tmemop_from_client(&op, uops) != 0) )
{
tmem_client_err("tmem: can't get tmem struct from %s\n", tmem_client_str);
- rc = -EFAULT;
- goto simple_error;
+ errored_tmem_ops++;
+ return -EFAULT;
}
+ /* Acquire wirte lock for all command at first */
+ write_lock(&tmem_rwlock);
+
if ( op.cmd == TMEM_CONTROL )
{
- write_lock(&tmem_rwlock);
- write_lock_set = 1;
rc = do_tmem_control(&op);
- goto out;
- } else if ( op.cmd == TMEM_AUTH ) {
- write_lock(&tmem_rwlock);
- write_lock_set = 1;
+ }
+ else if ( op.cmd == TMEM_AUTH )
+ {
rc = tmemc_shared_pool_auth(op.u.creat.arg1,op.u.creat.uuid[0],
op.u.creat.uuid[1],op.u.creat.flags);
- goto out;
- } else if ( op.cmd == TMEM_RESTORE_NEW ) {
- write_lock(&tmem_rwlock);
- write_lock_set = 1;
+ }
+ else if ( op.cmd == TMEM_RESTORE_NEW )
+ {
rc = do_tmem_new_pool(op.u.creat.arg1, op.pool_id, op.u.creat.flags,
op.u.creat.uuid[0], op.u.creat.uuid[1]);
- goto out;
}
-
- /* create per-client tmem structure dynamically on first use by client */
- if ( client == NULL )
- {
- write_lock(&tmem_rwlock);
- write_lock_set = 1;
- if ( (client = client_create(current->domain->domain_id)) == NULL )
+ else {
+ /*
+ * For other commands, create per-client tmem structure dynamically on
+ * first use by client.
+ */
+ if ( client == NULL )
{
- tmem_client_err("tmem: can't create tmem structure for %s\n",
- tmem_client_str);
- rc = -ENOMEM;
- goto out;
+ if ( (client = client_create(current->domain->domain_id)) == NULL )
+ {
+ tmem_client_err("tmem: can't create tmem structure for %s\n",
+ tmem_client_str);
+ rc = -ENOMEM;
+ goto out;
+ }
}
- }
- if ( op.cmd == TMEM_NEW_POOL || op.cmd == TMEM_DESTROY_POOL )
- {
- if ( !write_lock_set )
+ if ( op.cmd == TMEM_NEW_POOL || op.cmd == TMEM_DESTROY_POOL )
{
- write_lock(&tmem_rwlock);
- write_lock_set = 1;
+ if ( op.cmd == TMEM_NEW_POOL )
+ rc = do_tmem_new_pool(TMEM_CLI_ID_NULL, 0, op.u.creat.flags,
+ op.u.creat.uuid[0], op.u.creat.uuid[1]);
+ else
+ rc = do_tmem_destroy_pool(op.pool_id);
}
- }
- else
- {
- if ( !write_lock_set )
+ else
{
+ if ( ((uint32_t)op.pool_id >= MAX_POOLS_PER_DOMAIN) ||
+ ((pool = client->pools[op.pool_id]) == NULL) )
+ {
+ tmem_client_err("tmem: operation requested on uncreated pool\n");
+ rc = -ENODEV;
+ goto out;
+ }
+ /* Commands only need read lock */
+ write_unlock(&tmem_rwlock);
read_lock(&tmem_rwlock);
- read_lock_set = 1;
- }
- if ( ((uint32_t)op.pool_id >= MAX_POOLS_PER_DOMAIN) ||
- ((pool = client->pools[op.pool_id]) == NULL) )
- {
- tmem_client_err("tmem: operation requested on uncreated pool\n");
- rc = -ENODEV;
- goto out;
- }
- }
- oidp = (struct oid *)&op.u.gen.oid[0];
- switch ( op.cmd )
- {
- case TMEM_NEW_POOL:
- rc = do_tmem_new_pool(TMEM_CLI_ID_NULL, 0, op.u.creat.flags,
- op.u.creat.uuid[0], op.u.creat.uuid[1]);
- break;
- case TMEM_PUT_PAGE:
- if (tmem_ensure_avail_pages())
- rc = do_tmem_put(pool, oidp, op.u.gen.index, op.u.gen.cmfn,
- tmem_cli_buf_null);
- else
- rc = -ENOMEM;
- if (rc == 1) succ_put = 1;
- else non_succ_put = 1;
- break;
- case TMEM_GET_PAGE:
- rc = do_tmem_get(pool, oidp, op.u.gen.index, op.u.gen.cmfn,
- tmem_cli_buf_null);
- if (rc == 1) succ_get = 1;
- else non_succ_get = 1;
- break;
- case TMEM_FLUSH_PAGE:
- flush = 1;
- rc = do_tmem_flush_page(pool, oidp, op.u.gen.index);
- break;
- case TMEM_FLUSH_OBJECT:
- rc = do_tmem_flush_object(pool, oidp);
- flush_obj = 1;
- break;
- case TMEM_DESTROY_POOL:
- flush = 1;
- rc = do_tmem_destroy_pool(op.pool_id);
- break;
- default:
- tmem_client_warn("tmem: op %d not implemented\n", op.cmd);
- rc = -ENOSYS;
- break;
+ oidp = (struct oid *)&op.u.gen.oid[0];
+ switch ( op.cmd )
+ {
+ case TMEM_NEW_POOL:
+ case TMEM_DESTROY_POOL:
+ BUG(); /* Done earlier. */
+ break;
+ case TMEM_PUT_PAGE:
+ if (tmem_ensure_avail_pages())
+ rc = do_tmem_put(pool, oidp, op.u.gen.index, op.u.gen.cmfn,
+ tmem_cli_buf_null);
+ else
+ rc = -ENOMEM;
+ if (rc == 1) succ_put = 1;
+ else non_succ_put = 1;
+ break;
+ case TMEM_GET_PAGE:
+ rc = do_tmem_get(pool, oidp, op.u.gen.index, op.u.gen.cmfn,
+ tmem_cli_buf_null);
+ if (rc == 1) succ_get = 1;
+ else non_succ_get = 1;
+ break;
+ case TMEM_FLUSH_PAGE:
+ flush = 1;
+ rc = do_tmem_flush_page(pool, oidp, op.u.gen.index);
+ break;
+ case TMEM_FLUSH_OBJECT:
+ rc = do_tmem_flush_object(pool, oidp);
+ flush_obj = 1;
+ break;
+ default:
+ tmem_client_warn("tmem: op %d not implemented\n", op.cmd);
+ rc = -ENOSYS;
+ break;
+ }
+ read_unlock(&tmem_rwlock);
+ if ( rc < 0 )
+ errored_tmem_ops++;
+ return rc;
+ }
}
-
out:
+ write_unlock(&tmem_rwlock);
if ( rc < 0 )
errored_tmem_ops++;
- if ( write_lock_set )
- write_unlock(&tmem_rwlock);
- else if ( read_lock_set )
- read_unlock(&tmem_rwlock);
- else
- ASSERT(0);
-
return rc;
}
@@ -2754,7 +2770,7 @@ void tmem_destroy(void *v)
printk("tmem: flushing tmem pools for %s=%d\n",
tmem_cli_id_str, client->cli_id);
- client_flush(client, 1);
+ client_flush(client);
write_unlock(&tmem_rwlock);
}
@@ -2778,9 +2794,6 @@ void *tmem_relinquish_pages(unsigned int order, unsigned int memflags)
return NULL;
}
- if ( memflags & MEMF_tmem )
- read_lock(&tmem_rwlock);
-
while ( (pfp = tmem_page_list_get()) == NULL )
{
if ( (max_evictions-- <= 0) || !tmem_evict())
@@ -2796,9 +2809,6 @@ void *tmem_relinquish_pages(unsigned int order, unsigned int memflags)
relinq_pgs++;
}
- if ( memflags & MEMF_tmem )
- read_unlock(&tmem_rwlock);
-
return pfp;
}
diff --git a/xen/common/trace.c b/xen/common/trace.c
index 0bc8ca2..f651cf3 100644
--- a/xen/common/trace.c
+++ b/xen/common/trace.c
@@ -641,11 +641,11 @@ static inline void insert_wrap_record(struct t_buf *buf,
static inline void insert_lost_records(struct t_buf *buf)
{
- struct {
+ struct __packed {
u32 lost_records;
- u32 did:16, vid:16;
+ u16 did, vid;
u64 first_tsc;
- } __attribute__((packed)) ed;
+ } ed;
ed.vid = current->vcpu_id;
ed.did = current->domain->domain_id;
@@ -819,10 +819,10 @@ unlock:
void __trace_hypercall(uint32_t event, unsigned long op,
const xen_ulong_t *args)
{
- struct {
+ struct __packed {
uint32_t op;
uint32_t args[6];
- } __attribute__((packed)) d;
+ } d;
uint32_t *a = d.args;
#define APPEND_ARG32(i) \
diff --git a/xen/common/unlzma.c b/xen/common/unlzma.c
index 4d04330..a7da55b 100644
--- a/xen/common/unlzma.c
+++ b/xen/common/unlzma.c
@@ -218,7 +218,7 @@ struct lzma_header {
uint8_t pos;
uint32_t dict_size;
uint64_t dst_size;
-} __attribute__ ((packed)) ;
+} __attribute__((packed)) ;
#define LZMA_BASE_SIZE 1846
diff --git a/xen/common/vsprintf.c b/xen/common/vsprintf.c
index 1a6198e..065cc42 100644
--- a/xen/common/vsprintf.c
+++ b/xen/common/vsprintf.c
@@ -19,6 +19,7 @@
#include <xen/ctype.h>
#include <xen/symbols.h>
#include <xen/lib.h>
+#include <xen/sched.h>
#include <asm/div64.h>
#include <asm/page.h>
@@ -191,45 +192,45 @@ static char *number(
size -= precision;
if (!(type&(ZEROPAD+LEFT))) {
while(size-->0) {
- if (buf <= end)
+ if (buf < end)
*buf = ' ';
++buf;
}
}
if (sign) {
- if (buf <= end)
+ if (buf < end)
*buf = sign;
++buf;
}
if (type & SPECIAL) {
- if (buf <= end)
+ if (buf < end)
*buf = '0';
++buf;
if (base == 16) {
- if (buf <= end)
+ if (buf < end)
*buf = digits[33];
++buf;
}
}
if (!(type & LEFT)) {
while (size-- > 0) {
- if (buf <= end)
+ if (buf < end)
*buf = c;
++buf;
}
}
while (i < precision--) {
- if (buf <= end)
+ if (buf < end)
*buf = '0';
++buf;
}
while (i-- > 0) {
- if (buf <= end)
+ if (buf < end)
*buf = tmp[i];
++buf;
}
while (size-- > 0) {
- if (buf <= end)
+ if (buf < end)
*buf = ' ';
++buf;
}
@@ -239,22 +240,22 @@ static char *number(
static char *string(char *str, char *end, const char *s,
int field_width, int precision, int flags)
{
- int i, len = strnlen(s, precision);
+ int i, len = (precision < 0) ? strlen(s) : strnlen(s, precision);
if (!(flags & LEFT)) {
while (len < field_width--) {
- if (str <= end)
+ if (str < end)
*str = ' ';
++str;
}
}
for (i = 0; i < len; ++i) {
- if (str <= end)
+ if (str < end)
*str = *s;
++str; ++s;
}
while (len < field_width--) {
- if (str <= end)
+ if (str < end)
*str = ' ';
++str;
}
@@ -271,6 +272,34 @@ static char *pointer(char *str, char *end, const char **fmt_ptr,
/* Custom %p suffixes. See XEN_ROOT/docs/misc/printk-formats.txt */
switch ( fmt[1] )
{
+ case 'h': /* Raw buffer as hex string. */
+ {
+ const uint8_t *hex_buffer = arg;
+ unsigned int i;
+
+ /* Consumed 'h' from the format string. */
+ ++*fmt_ptr;
+
+ /* Bound user count from %* to between 0 and 64 bytes. */
+ if ( field_width <= 0 )
+ return str;
+ if ( field_width > 64 )
+ field_width = 64;
+
+ for ( i = 0; ; )
+ {
+ /* Each byte: 2 chars, 0-padded, base 16, no hex prefix. */
+ str = number(str, end, hex_buffer[i], 16, 2, -1, ZEROPAD);
+
+ if ( ++i == field_width )
+ return str;
+
+ if ( str < end )
+ *str = ' ';
+ ++str;
+ }
+ }
+
case 's': /* Symbol name with offset and size (iff offset != 0) */
case 'S': /* Symbol name unconditionally with offset and size */
{
@@ -293,7 +322,7 @@ static char *pointer(char *str, char *end, const char **fmt_ptr,
{
/* Print '+<offset>/<len>' */
str = number(str, end, sym_offset, 16, -1, -1, SPECIAL|SIGN|PLUS);
- if ( str <= end )
+ if ( str < end )
*str = '/';
++str;
str = number(str, end, sym_size, 16, -1, -1, SPECIAL);
@@ -301,6 +330,19 @@ static char *pointer(char *str, char *end, const char **fmt_ptr,
return str;
}
+
+ case 'v': /* d<domain-id>v<vcpu-id> from a struct vcpu */
+ {
+ const struct vcpu *v = arg;
+
+ ++*fmt_ptr;
+ if ( str < end )
+ *str = 'd';
+ str = number(str + 1, end, v->domain->domain_id, 10, -1, -1, 0);
+ if ( str < end )
+ *str = 'v';
+ return number(str + 1, end, v->vcpu_id, 10, -1, -1, 0);
+ }
}
if ( field_width == -1 )
@@ -351,16 +393,16 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
BUG_ON(((int)size < 0) || ((unsigned int)size != size));
str = buf;
- end = buf + size - 1;
+ end = buf + size;
- if (end < buf - 1) {
+ if (end < buf) {
end = ((void *) -1);
- size = end - buf + 1;
+ size = end - buf;
}
for (; *fmt ; ++fmt) {
if (*fmt != '%') {
- if (str <= end)
+ if (str < end)
*str = *fmt;
++str;
continue;
@@ -426,17 +468,17 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
case 'c':
if (!(flags & LEFT)) {
while (--field_width > 0) {
- if (str <= end)
+ if (str < end)
*str = ' ';
++str;
}
}
c = (unsigned char) va_arg(args, int);
- if (str <= end)
+ if (str < end)
*str = c;
++str;
while (--field_width > 0) {
- if (str <= end)
+ if (str < end)
*str = ' ';
++str;
}
@@ -471,7 +513,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
continue;
case '%':
- if (str <= end)
+ if (str < end)
*str = '%';
++str;
continue;
@@ -494,11 +536,11 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
break;
default:
- if (str <= end)
+ if (str < end)
*str = '%';
++str;
if (*fmt) {
- if (str <= end)
+ if (str < end)
*str = *fmt;
++str;
} else {
@@ -527,11 +569,14 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
str = number(str, end, num, base,
field_width, precision, flags);
}
- if (str <= end)
- *str = '\0';
- else if (size > 0)
- /* don't write out a null byte if the buf size is zero */
- *end = '\0';
+
+ /* don't write out a null byte if the buf size is zero */
+ if (size > 0) {
+ if (str < end)
+ *str = '\0';
+ else
+ end[-1] = '\0';
+ }
/* the trailing null byte doesn't count towards the total
* ++str;
*/
@@ -617,6 +662,60 @@ int scnprintf(char * buf, size_t size, const char *fmt, ...)
}
EXPORT_SYMBOL(scnprintf);
+/**
+ * vasprintf - Format a string and allocate a buffer to place it in
+ *
+ * @bufp: Pointer to a pointer to receive the allocated buffer
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * -ENOMEM is returned on failure and @bufp is not touched.
+ * On success, 0 is returned. The buffer passed back is
+ * guaranteed to be null terminated. The memory is allocated
+ * from xenheap, so the buffer should be freed with xfree().
+ */
+int vasprintf(char **bufp, const char *fmt, va_list args)
+{
+ va_list args_copy;
+ size_t size;
+ char *buf;
+
+ va_copy(args_copy, args);
+ size = vsnprintf(NULL, 0, fmt, args_copy);
+ va_end(args_copy);
+
+ buf = xmalloc_array(char, ++size);
+ if ( !buf )
+ return -ENOMEM;
+
+ (void) vsnprintf(buf, size, fmt, args);
+
+ *bufp = buf;
+ return 0;
+}
+
+/**
+ * asprintf - Format a string and place it in a buffer
+ * @bufp: Pointer to a pointer to receive the allocated buffer
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ *
+ * -ENOMEM is returned on failure and @bufp is not touched.
+ * On success, 0 is returned. The buffer passed back is
+ * guaranteed to be null terminated. The memory is allocated
+ * from xenheap, so the buffer should be freed with xfree().
+ */
+int asprintf(char **bufp, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vasprintf(bufp,fmt,args);
+ va_end(args);
+ return i;
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/common/wait.c b/xen/common/wait.c
index 3c9366c..1f6b597 100644
--- a/xen/common/wait.c
+++ b/xen/common/wait.c
@@ -134,8 +134,8 @@ static void __prepare_to_wait(struct waitqueue_vcpu *wqv)
/* Save current VCPU affinity; force wakeup on *this* CPU only. */
wqv->wakeup_cpu = smp_processor_id();
- cpumask_copy(&wqv->saved_affinity, curr->cpu_affinity);
- if ( vcpu_set_affinity(curr, cpumask_of(wqv->wakeup_cpu)) )
+ cpumask_copy(&wqv->saved_affinity, curr->cpu_hard_affinity);
+ if ( vcpu_set_hard_affinity(curr, cpumask_of(wqv->wakeup_cpu)) )
{
gdprintk(XENLOG_ERR, "Unable to set vcpu affinity\n");
domain_crash_synchronous();
@@ -166,7 +166,7 @@ static void __prepare_to_wait(struct waitqueue_vcpu *wqv)
static void __finish_wait(struct waitqueue_vcpu *wqv)
{
wqv->esp = NULL;
- (void)vcpu_set_affinity(current, &wqv->saved_affinity);
+ (void)vcpu_set_hard_affinity(current, &wqv->saved_affinity);
}
void check_wakeup_from_wait(void)
@@ -183,8 +183,8 @@ void check_wakeup_from_wait(void)
{
/* Re-set VCPU affinity and re-enter the scheduler. */
struct vcpu *curr = current;
- cpumask_copy(&wqv->saved_affinity, curr->cpu_affinity);
- if ( vcpu_set_affinity(curr, cpumask_of(wqv->wakeup_cpu)) )
+ cpumask_copy(&wqv->saved_affinity, curr->cpu_hard_affinity);
+ if ( vcpu_set_hard_affinity(curr, cpumask_of(wqv->wakeup_cpu)) )
{
gdprintk(XENLOG_ERR, "Unable to set vcpu affinity\n");
domain_crash_synchronous();
diff --git a/xen/common/xenoprof.c b/xen/common/xenoprof.c
index 52ab00d..3de20b8 100644
--- a/xen/common/xenoprof.c
+++ b/xen/common/xenoprof.c
@@ -219,7 +219,7 @@ static int alloc_xenoprof_struct(
bufsize = sizeof(struct xenoprof_buf);
i = sizeof(struct event_log);
#ifdef CONFIG_COMPAT
- d->xenoprof->is_compat = is_pv_32on64_domain(is_passive ? dom0 : d);
+ d->xenoprof->is_compat = is_pv_32on64_domain(is_passive ? hardware_domain : d);
if ( XENOPROF_COMPAT(d->xenoprof) )
{
bufsize = sizeof(struct compat_oprof_buf);
@@ -601,9 +601,15 @@ static int xenoprof_op_init(XEN_GUEST_HANDLE_PARAM(void) arg)
xenoprof_init.cpu_type)) )
return ret;
+ /* Only the hardware domain may become the primary profiler here because
+ * there is currently no cleanup of xenoprof_primary_profiler or associated
+ * profiling state when the primary profiling domain is shut down or
+ * crashes. Once a better cleanup method is present, it will be possible to
+ * allow another domain to be the primary profiler.
+ */
xenoprof_init.is_primary =
((xenoprof_primary_profiler == d) ||
- ((xenoprof_primary_profiler == NULL) && (d->domain_id == 0)));
+ ((xenoprof_primary_profiler == NULL) && is_hardware_domain(d)));
if ( xenoprof_init.is_primary )
xenoprof_primary_profiler = current->domain;
diff --git a/xen/crypto/rijndael.c b/xen/crypto/rijndael.c
index b7cd0d1..9de0992 100644
--- a/xen/crypto/rijndael.c
+++ b/xen/crypto/rijndael.c
@@ -380,6 +380,8 @@ static const u32 Te4[256] = {
0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
};
+
+#ifdef NEED_RIJNDAEL_DECRYPT
static const u32 Td0[256] = {
0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
@@ -710,6 +712,7 @@ static const u32 Td4[256] = {
0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
};
+#endif
static const u32 rcon[] = {
0x01000000, 0x02000000, 0x04000000, 0x08000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000,
diff --git a/xen/drivers/acpi/apei/erst.c b/xen/drivers/acpi/apei/erst.c
index 2583afa..21593cf 100644
--- a/xen/drivers/acpi/apei/erst.c
+++ b/xen/drivers/acpi/apei/erst.c
@@ -383,21 +383,26 @@ static int erst_get_erange(struct erst_erange *range)
return 0;
}
-static size_t __erst_get_record_count(void)
+#ifndef NDEBUG /* currently dead code */
+
+static ssize_t __erst_get_record_count(void)
{
struct apei_exec_context ctx;
int rc;
+ u64 output;
+ ssize_t count;
erst_exec_ctx_init(&ctx);
rc = apei_exec_run(&ctx, ACPI_ERST_GET_RECORD_COUNT);
if (rc)
return rc;
- return apei_exec_ctx_get_output(&ctx);
+ count = output = apei_exec_ctx_get_output(&ctx);
+ return count >= 0 && count == output ? count : -ERANGE;
}
-size_t erst_get_record_count(void)
+ssize_t erst_get_record_count(void)
{
- size_t count;
+ ssize_t count;
unsigned long flags;
if (!erst_enabled)
@@ -444,6 +449,8 @@ int erst_get_next_record_id(u64 *record_id)
return rc;
}
+#endif /* currently dead code */
+
static int __erst_write_to_storage(u64 offset)
{
struct apei_exec_context ctx;
@@ -483,6 +490,8 @@ static int __erst_write_to_storage(u64 offset)
return erst_errno(val);
}
+#ifndef NDEBUG /* currently dead code */
+
static int __erst_read_from_storage(u64 record_id, u64 offset)
{
struct apei_exec_context ctx;
@@ -565,6 +574,8 @@ static int __erst_clear_from_storage(u64 record_id)
return erst_errno(val);
}
+#endif /* currently dead code */
+
/* NVRAM ERST Error Log Address Range is not supported yet */
static int __erst_write_to_nvram(const struct cper_record_header *record)
{
@@ -572,6 +583,8 @@ static int __erst_write_to_nvram(const struct cper_record_header *record)
return -ENOSYS;
}
+#ifndef NDEBUG /* currently dead code */
+
static int __erst_read_to_erange_from_nvram(u64 record_id, u64 *offset)
{
printk(KERN_WARNING
@@ -586,6 +599,8 @@ static int __erst_clear_from_nvram(u64 record_id)
return -ENOSYS;
}
+#endif /* currently dead code */
+
int erst_write(const struct cper_record_header *record)
{
int rc;
@@ -625,6 +640,8 @@ int erst_write(const struct cper_record_header *record)
return rc;
}
+#ifndef NDEBUG /* currently dead code */
+
static int __erst_read_to_erange(u64 record_id, u64 *offset)
{
int rc;
@@ -641,22 +658,24 @@ static int __erst_read_to_erange(u64 record_id, u64 *offset)
return 0;
}
-static size_t __erst_read(u64 record_id, struct cper_record_header *record,
+static ssize_t __erst_read(u64 record_id, struct cper_record_header *record,
size_t buflen)
{
int rc;
- u64 offset, len = 0;
+ u64 offset;
+ ssize_t len;
struct cper_record_header *rcd_tmp;
rc = __erst_read_to_erange(record_id, &offset);
if (rc)
return rc;
rcd_tmp = erst_erange.vaddr + offset;
+ if (rcd_tmp->record_length > buflen)
+ return -ENOBUFS;
len = rcd_tmp->record_length;
- if (len <= buflen)
- memcpy(record, rcd_tmp, len);
+ memcpy(record, rcd_tmp, len);
- return len;
+ return len >= 0 ? len : -ERANGE;
}
/*
@@ -664,10 +683,10 @@ static size_t __erst_read(u64 record_id, struct cper_record_header *record,
* else if return value < 0, something goes wrong,
* else everything is OK, and return value is record length
*/
-size_t erst_read(u64 record_id, struct cper_record_header *record,
+ssize_t erst_read(u64 record_id, struct cper_record_header *record,
size_t buflen)
{
- size_t len;
+ ssize_t len;
unsigned long flags;
if (!erst_enabled)
@@ -685,10 +704,10 @@ size_t erst_read(u64 record_id, struct cper_record_header *record,
* else if return value < 0, something goes wrong,
* else everything is OK, and return value is record length
*/
-size_t erst_read_next(struct cper_record_header *record, size_t buflen)
+ssize_t erst_read_next(struct cper_record_header *record, size_t buflen)
{
int rc;
- size_t len;
+ ssize_t len;
unsigned long flags;
u64 record_id;
@@ -731,6 +750,8 @@ int erst_clear(u64 record_id)
return rc;
}
+#endif /* currently dead code */
+
static int __init erst_check_table(struct acpi_table_erst *erst_tab)
{
if (erst_tab->header.length < sizeof(*erst_tab))
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 89ffe64..2f03259 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -28,6 +28,7 @@
#include <asm/debugger.h>
#include <asm/div64.h>
#include <xen/hypercall.h> /* for do_console_io */
+#include <xen/early_printk.h>
/* console: comma-separated list of console outputs. */
static char __initdata opt_console[30] = OPT_CONSOLE_STR;
@@ -49,8 +50,18 @@ static bool_t __read_mostly opt_console_to_ring;
boolean_param("console_to_ring", opt_console_to_ring);
/* console_timestamps: include a timestamp prefix on every Xen console line. */
-static bool_t __read_mostly opt_console_timestamps;
-boolean_param("console_timestamps", opt_console_timestamps);
+enum con_timestamp_mode
+{
+ TSM_NONE, /* No timestamps */
+ TSM_DATE, /* [YYYY-MM-DD HH:MM:SS] */
+ TSM_DATE_MS, /* [YYYY-MM-DD HH:MM:SS.mmm] */
+ TSM_BOOT /* [SSSSSS.uuuuuu] */
+};
+
+static enum con_timestamp_mode __read_mostly opt_con_timestamp_mode = TSM_NONE;
+
+static void parse_console_timestamps(char *s);
+custom_param("console_timestamps", parse_console_timestamps);
/* conring_size: allows a large console ring than default (16kB). */
static uint32_t __initdata opt_conring_size;
@@ -245,7 +256,7 @@ long read_console_ring(struct xen_sysctl_readconsole *op)
static char serial_rx_ring[SERIAL_RX_SIZE];
static unsigned int serial_rx_cons, serial_rx_prod;
-static void (*serial_steal_fn)(const char *);
+static void (*serial_steal_fn)(const char *) = early_puts;
int console_steal(int handle, void (*fn)(const char *))
{
@@ -546,23 +557,69 @@ static int printk_prefix_check(char *p, char **pp)
((loglvl < upper_thresh) && printk_ratelimit()));
}
+static void __init parse_console_timestamps(char *s)
+{
+ switch ( parse_bool(s) )
+ {
+ case 0:
+ opt_con_timestamp_mode = TSM_NONE;
+ return;
+ case 1:
+ opt_con_timestamp_mode = TSM_DATE;
+ return;
+ }
+ if ( *s == '\0' || /* Compat for old booleanparam() */
+ !strcmp(s, "date") )
+ opt_con_timestamp_mode = TSM_DATE;
+ else if ( !strcmp(s, "datems") )
+ opt_con_timestamp_mode = TSM_DATE_MS;
+ else if ( !strcmp(s, "boot") )
+ opt_con_timestamp_mode = TSM_BOOT;
+ else if ( !strcmp(s, "none") )
+ opt_con_timestamp_mode = TSM_NONE;
+}
+
static void printk_start_of_line(const char *prefix)
{
struct tm tm;
char tstr[32];
+ uint64_t sec, nsec;
__putstr(prefix);
- if ( !opt_console_timestamps )
- return;
+ switch ( opt_con_timestamp_mode )
+ {
+ case TSM_DATE:
+ case TSM_DATE_MS:
+ tm = wallclock_time(&nsec);
+
+ if ( tm.tm_mday == 0 )
+ return;
- tm = wallclock_time();
- if ( tm.tm_mday == 0 )
+ if ( opt_con_timestamp_mode == TSM_DATE )
+ snprintf(tstr, sizeof(tstr), "[%04u-%02u-%02u %02u:%02u:%02u] ",
+ 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+ else
+ snprintf(tstr, sizeof(tstr),
+ "[%04u-%02u-%02u %02u:%02u:%02u.%03"PRIu64"] ",
+ 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec, nsec / 1000000);
+ break;
+
+ case TSM_BOOT:
+ sec = NOW();
+ nsec = do_div(sec, 1000000000);
+
+ snprintf(tstr, sizeof(tstr), "[%5"PRIu64".%06"PRIu64"] ",
+ sec, nsec / 1000);
+ break;
+
+ case TSM_NONE:
+ default:
return;
+ }
- snprintf(tstr, sizeof(tstr), "[%04u-%02u-%02u %02u:%02u:%02u] ",
- 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec);
__putstr(tstr);
}
@@ -652,7 +709,10 @@ void __init console_init_preirq(void)
else if ( !strncmp(p, "none", 4) )
continue;
else if ( (sh = serial_parse_handle(p)) >= 0 )
+ {
sercon_handle = sh;
+ serial_steal_fn = NULL;
+ }
else
{
char *q = strchr(p, ',');
@@ -1073,14 +1133,9 @@ void panic(const char *fmt, ...)
#endif
if ( opt_noreboot )
- {
machine_halt();
- }
else
- {
- watchdog_disable();
machine_restart(5000);
- }
}
void __bug(char *file, int line)
@@ -1089,7 +1144,6 @@ void __bug(char *file, int line)
printk("Xen BUG at %s:%d\n", file, line);
dump_execution_state();
panic("Xen BUG at %s:%d", file, line);
- for ( ; ; ) ;
}
void __warn(char *file, int line)
diff --git a/xen/drivers/char/dt-uart.c b/xen/drivers/char/dt-uart.c
index d7204fb..fa92b5c 100644
--- a/xen/drivers/char/dt-uart.c
+++ b/xen/drivers/char/dt-uart.c
@@ -18,7 +18,6 @@
*/
#include <asm/device.h>
-#include <asm/early_printk.h>
#include <asm/types.h>
#include <xen/console.h>
#include <xen/device_tree.h>
@@ -44,7 +43,7 @@ void __init dt_uart_init(void)
if ( !console_has("dtuart") || !strcmp(opt_dtuart, "") )
{
- early_printk("No console\n");
+ printk("No console\n");
return;
}
@@ -54,7 +53,7 @@ void __init dt_uart_init(void)
else
options = "";
- early_printk("Looking for UART console %s\n", devpath);
+ printk("Looking for UART console %s\n", devpath);
if ( *devpath == '/' )
dev = dt_find_node_by_path(devpath);
else
@@ -62,12 +61,12 @@ void __init dt_uart_init(void)
if ( !dev )
{
- early_printk("Unable to find device \"%s\"\n", devpath);
+ printk("Unable to find device \"%s\"\n", devpath);
return;
}
ret = device_init(dev, DEVICE_SERIAL, options);
if ( ret )
- early_printk("Unable to initialize serial: %d\n", ret);
+ printk("Unable to initialize serial: %d\n", ret);
}
diff --git a/xen/drivers/char/ehci-dbgp.c b/xen/drivers/char/ehci-dbgp.c
index b900d60..3feeafe 100644
--- a/xen/drivers/char/ehci-dbgp.c
+++ b/xen/drivers/char/ehci-dbgp.c
@@ -251,25 +251,25 @@ struct ehci_dbg_port {
* For most devices, interfaces don't coordinate with each other, so
* such requests may be made at any time.
*/
-struct usb_ctrlrequest {
+struct __packed usb_ctrlrequest {
u8 bRequestType;
u8 bRequest;
__le16 wValue;
__le16 wIndex;
__le16 wLength;
-} __attribute__ ((packed));
+};
/* USB_DT_DEBUG: for special highspeed devices, replacing serial console */
#define USB_DT_DEBUG 0x0a
-struct usb_debug_descriptor {
+struct __packed usb_debug_descriptor {
u8 bLength;
u8 bDescriptorType;
/* bulk endpoints with 8 byte maxpacket */
u8 bDebugInEndpoint;
u8 bDebugOutEndpoint;
-} __attribute__((packed));
+};
#define USB_DEBUG_DEVNUM 127
diff --git a/xen/drivers/char/exynos4210-uart.c b/xen/drivers/char/exynos4210-uart.c
index 0619575..cba8729 100644
--- a/xen/drivers/char/exynos4210-uart.c
+++ b/xen/drivers/char/exynos4210-uart.c
@@ -24,14 +24,13 @@
#include <xen/init.h>
#include <xen/irq.h>
#include <xen/mm.h>
-#include <asm/early_printk.h>
#include <asm/device.h>
#include <asm/exynos4210-uart.h>
#include <asm/io.h>
static struct exynos4210_uart {
unsigned int baud, clock_hz, data_bits, parity, stop_bits;
- struct dt_irq irq;
+ unsigned int irq;
void *regs;
struct irqaction irqaction;
struct vuart_info vuart;
@@ -198,9 +197,9 @@ static void __init exynos4210_uart_init_postirq(struct serial_port *port)
uart->irqaction.name = "exynos4210_uart";
uart->irqaction.dev_id = port;
- if ( (rc = setup_dt_irq(&uart->irq, &uart->irqaction)) != 0 )
+ if ( (rc = setup_irq(uart->irq, 0, &uart->irqaction)) != 0 )
dprintk(XENLOG_ERR, "Failed to allocated exynos4210_uart IRQ %d\n",
- uart->irq.irq);
+ uart->irq);
/* Unmask interrupts */
exynos4210_write(uart, UINTM, ~UINTM_ALLI);
@@ -273,14 +272,7 @@ static int __init exynos4210_uart_irq(struct serial_port *port)
{
struct exynos4210_uart *uart = port->uart;
- return uart->irq.irq;
-}
-
-static const struct dt_irq __init *exynos4210_uart_dt_irq(struct serial_port *port)
-{
- struct exynos4210_uart *uart = port->uart;
-
- return &uart->irq;
+ return uart->irq;
}
static const struct vuart_info *exynos4210_vuart_info(struct serial_port *port)
@@ -300,7 +292,6 @@ static struct uart_driver __read_mostly exynos4210_uart_driver = {
.putc = exynos4210_uart_putc,
.getc = exynos4210_uart_getc,
.irq = exynos4210_uart_irq,
- .dt_irq_get = exynos4210_uart_dt_irq,
.vuart_info = exynos4210_vuart_info,
};
@@ -314,9 +305,7 @@ static int __init exynos4210_uart_init(struct dt_device_node *dev,
u64 addr, size;
if ( strcmp(config, "") )
- {
- early_printk("WARNING: UART configuration is not supported\n");
- }
+ printk("WARNING: UART configuration is not supported\n");
uart = &exynos4210_com;
@@ -329,23 +318,25 @@ static int __init exynos4210_uart_init(struct dt_device_node *dev,
res = dt_device_get_address(dev, 0, &addr, &size);
if ( res )
{
- early_printk("exynos4210: Unable to retrieve the base"
- " address of the UART\n");
+ printk("exynos4210: Unable to retrieve the base"
+ " address of the UART\n");
return res;
}
+ res = platform_get_irq(dev, 0);
+ if ( res < 0 )
+ {
+ printk("exynos4210: Unable to retrieve the IRQ\n");
+ return -EINVAL;
+ }
+ uart->irq = res;
+
uart->regs = ioremap_nocache(addr, size);
if ( !uart->regs )
{
- early_printk("exynos4210: Unable to map the UART memory\n");
+ printk("exynos4210: Unable to map the UART memory\n");
return -ENOMEM;
}
- res = dt_device_get_irq(dev, 0, &uart->irq);
- if ( res )
- {
- early_printk("exynos4210: Unable to retrieve the IRQ\n");
- return res;
- }
uart->vuart.base_addr = addr;
uart->vuart.size = size;
diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c
index e7cb0ba..161b251 100644
--- a/xen/drivers/char/ns16550.c
+++ b/xen/drivers/char/ns16550.c
@@ -19,6 +19,7 @@
#ifdef HAS_PCI
#include <xen/pci.h>
#include <xen/pci_regs.h>
+#include <xen/pci_ids.h>
#endif
#include <xen/8250-uart.h>
#include <xen/vmap.h>
@@ -46,13 +47,14 @@ string_param("com2", opt_com2);
static struct ns16550 {
int baud, clock_hz, data_bits, parity, stop_bits, fifo_size, irq;
u64 io_base; /* I/O port or memory-mapped I/O address. */
- u32 io_size;
+ u64 io_size;
int reg_shift; /* Bits to shift register offset by */
int reg_width; /* Size of access to use, the registers
* themselves are still bytes */
char __iomem *remapped_io_base; /* Remapped virtual address of MMIO. */
/* UART with IRQ line: interrupt-driven I/O. */
struct irqaction irqaction;
+ u8 lsr_mask;
#ifdef CONFIG_ARM
struct vuart_info vuart;
#endif
@@ -69,14 +71,278 @@ static struct ns16550 {
bool_t pb_bdf_enable; /* if =1, pb-bdf effective, port behind bridge */
bool_t ps_bdf_enable; /* if =1, ps_bdf effective, port on pci card */
u32 bar;
+ u32 bar64;
u16 cr;
u8 bar_idx;
-#endif
-#ifdef HAS_DEVICE_TREE
- struct dt_irq dt_irq;
+ bool_t enable_ro; /* Make MMIO devices read only to Dom0 */
#endif
} ns16550_com[2] = { { 0 } };
+struct ns16550_config_mmio {
+ u16 vendor_id;
+ u16 dev_id;
+ unsigned int param;
+};
+
+/* Defining uart config options for MMIO devices */
+struct ns16550_config_param {
+ unsigned int reg_shift;
+ unsigned int reg_width;
+ unsigned int fifo_size;
+ u8 lsr_mask;
+ unsigned int max_bars;
+ unsigned int base_baud;
+ unsigned int uart_offset;
+ unsigned int first_offset;
+};
+
+
+#ifdef HAS_PCI
+enum {
+ param_default = 0,
+ param_trumanage,
+ param_oxford,
+ param_oxford_2port,
+};
+/*
+ * Create lookup tables for specific MMIO devices..
+ * It is assumed that if the device found is MMIO,
+ * then you have indexed it here. Else, the driver
+ * does nothing.
+ */
+static const struct ns16550_config_param __initconst uart_param[] = {
+ [param_default] = { }, /* Ignored. */
+ [param_trumanage] = {
+ .reg_shift = 2,
+ .reg_width = 1,
+ .fifo_size = 16,
+ .lsr_mask = (UART_LSR_THRE | UART_LSR_TEMT),
+ .max_bars = 1,
+ },
+ [param_oxford] = {
+ .base_baud = 4000000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ .reg_width = 1,
+ .reg_shift = 0,
+ .fifo_size = 16,
+ .lsr_mask = UART_LSR_THRE,
+ .max_bars = 1, /* It can do more, but we would need more custom code.*/
+ },
+ [param_oxford_2port] = {
+ .base_baud = 4000000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ .reg_width = 1,
+ .reg_shift = 0,
+ .fifo_size = 16,
+ .lsr_mask = UART_LSR_THRE,
+ .max_bars = 2,
+ }
+};
+static const struct ns16550_config_mmio __initconst uart_config[] =
+{
+ /* Broadcom TruManage device */
+ {
+ .vendor_id = PCI_VENDOR_ID_BROADCOM,
+ .dev_id = 0x160a,
+ .param = param_trumanage,
+ },
+ /* OXPCIe952 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc11b,
+ .param = param_oxford,
+ },
+ /* OXPCIe952 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc11f,
+ .param = param_oxford,
+ },
+ /* OXPCIe952 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc138,
+ .param = param_oxford,
+ },
+ /* OXPCIe952 2 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc158,
+ .param = param_oxford_2port,
+ },
+ /* OXPCIe952 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc13d,
+ .param = param_oxford,
+ },
+ /* OXPCIe952 2 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc15d,
+ .param = param_oxford_2port,
+ },
+ /* OXPCIe952 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc40b,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc40f,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc41b,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc41f,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc42b,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc42f,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc43b,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc43f,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc44b,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc44f,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc45b,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc45f,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc46b,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc46f,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc47b,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc47f,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc48b,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc48f,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc49b,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc49f,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc4ab,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc4af,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc4bb,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc4bf,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc4cb,
+ .param = param_oxford,
+ },
+ /* OXPCIe200 1 Native UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_OXSEMI,
+ .dev_id = 0xc4cf,
+ .param = param_oxford,
+ }
+};
+#endif
+
static void ns16550_delayed_resume(void *data);
static char ns_read_reg(struct ns16550 *uart, int reg)
@@ -134,7 +400,7 @@ static void ns16550_interrupt(
while ( !(ns_read_reg(uart, UART_IIR) & UART_IIR_NOINT) )
{
char lsr = ns_read_reg(uart, UART_LSR);
- if ( lsr & UART_LSR_THRE )
+ if ( (lsr & uart->lsr_mask) == uart->lsr_mask )
serial_tx_interrupt(port, regs);
if ( lsr & UART_LSR_DR )
serial_rx_interrupt(port, regs);
@@ -160,7 +426,7 @@ static void __ns16550_poll(struct cpu_user_regs *regs)
serial_rx_interrupt(port, regs);
}
- if ( ns_read_reg(uart, UART_LSR) & UART_LSR_THRE )
+ if ( ( ns_read_reg(uart, UART_LSR) & uart->lsr_mask ) == uart->lsr_mask )
serial_tx_interrupt(port, regs);
out:
@@ -183,7 +449,9 @@ static int ns16550_tx_ready(struct serial_port *port)
if ( ns16550_ioport_invalid(uart) )
return -EIO;
- return ns_read_reg(uart, UART_LSR) & UART_LSR_THRE ? uart->fifo_size : 0;
+
+ return ( (ns_read_reg(uart, UART_LSR) &
+ uart->lsr_mask ) == uart->lsr_mask ) ? uart->fifo_size : 0;
}
static void ns16550_putc(struct serial_port *port, char c)
@@ -341,21 +609,32 @@ static void __init ns16550_init_postirq(struct serial_port *port)
uart->irqaction.handler = ns16550_interrupt;
uart->irqaction.name = "ns16550";
uart->irqaction.dev_id = port;
-#ifdef HAS_DEVICE_TREE
- if ( (rc = setup_dt_irq(&uart->dt_irq, &uart->irqaction)) != 0 )
- printk("ERROR: Failed to allocate ns16550 DT IRQ.\n");
-#else
- if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
+ if ( (rc = setup_irq(uart->irq, 0, &uart->irqaction)) != 0 )
printk("ERROR: Failed to allocate ns16550 IRQ %d\n", uart->irq);
-#endif
}
ns16550_setup_postirq(uart);
#ifdef HAS_PCI
if ( uart->bar || uart->ps_bdf_enable )
- pci_hide_device(uart->ps_bdf[0], PCI_DEVFN(uart->ps_bdf[1],
- uart->ps_bdf[2]));
+ {
+ if ( !uart->enable_ro )
+ pci_hide_device(uart->ps_bdf[0], PCI_DEVFN(uart->ps_bdf[1],
+ uart->ps_bdf[2]));
+ else
+ {
+ if ( rangeset_add_range(mmio_ro_ranges,
+ uart->io_base,
+ uart->io_base + uart->io_size - 1) )
+ printk(XENLOG_INFO "Error while adding MMIO range of device to mmio_ro_ranges\n");
+
+ if ( pci_ro_device(0, uart->ps_bdf[0],
+ PCI_DEVFN(uart->ps_bdf[1], uart->ps_bdf[2])) )
+ printk(XENLOG_INFO "Could not mark config space of %02x:%02x.%u read-only.\n",
+ uart->ps_bdf[0], uart->ps_bdf[1],
+ uart->ps_bdf[2]);
+ }
+ }
#endif
}
@@ -381,6 +660,13 @@ static void _ns16550_resume(struct serial_port *port)
{
pci_conf_write32(0, uart->ps_bdf[0], uart->ps_bdf[1], uart->ps_bdf[2],
PCI_BASE_ADDRESS_0 + uart->bar_idx*4, uart->bar);
+
+ /* If 64 bit BAR, write higher 32 bits to BAR+4 */
+ if ( uart->bar & PCI_BASE_ADDRESS_MEM_TYPE_64 )
+ pci_conf_write32(0, uart->ps_bdf[0],
+ uart->ps_bdf[1], uart->ps_bdf[2],
+ PCI_BASE_ADDRESS_0 + (uart->bar_idx+1)*4, uart->bar64);
+
pci_conf_write16(0, uart->ps_bdf[0], uart->ps_bdf[1], uart->ps_bdf[2],
PCI_COMMAND, uart->cr);
}
@@ -432,10 +718,12 @@ static void __init ns16550_endboot(struct serial_port *port)
{
#ifdef HAS_IOPORTS
struct ns16550 *uart = port->uart;
+ int rv;
if ( uart->remapped_io_base )
return;
- if ( ioports_deny_access(dom0, uart->io_base, uart->io_base + 7) != 0 )
+ rv = ioports_deny_access(hardware_domain, uart->io_base, uart->io_base + 7);
+ if ( rv != 0 )
BUG();
#endif
}
@@ -446,14 +734,6 @@ static int __init ns16550_irq(struct serial_port *port)
return ((uart->irq > 0) ? uart->irq : -1);
}
-#ifdef HAS_DEVICE_TREE
-static const struct dt_irq __init *ns16550_dt_irq(struct serial_port *port)
-{
- struct ns16550 *uart = port->uart;
- return &uart->dt_irq;
-}
-#endif
-
#ifdef CONFIG_ARM
static const struct vuart_info *ns16550_vuart_info(struct serial_port *port)
{
@@ -473,9 +753,6 @@ static struct uart_driver __read_mostly ns16550_driver = {
.putc = ns16550_putc,
.getc = ns16550_getc,
.irq = ns16550_irq,
-#ifdef HAS_DEVICE_TREE
- .dt_irq_get = ns16550_dt_irq,
-#endif
#ifdef CONFIG_ARM
.vuart_info = ns16550_vuart_info,
#endif
@@ -546,12 +823,16 @@ static int __init check_existence(struct ns16550 *uart)
}
#ifdef HAS_PCI
-static int
+static int __init
pci_uart_config (struct ns16550 *uart, int skip_amt, int bar_idx)
{
- uint32_t bar, len;
- int b, d, f, nextf;
+ uint32_t bar, bar_64 = 0, len, len_64;
+ u64 size, mask, orig_base;
+ unsigned int b, d, f, nextf, i;
+ u16 vendor, device;
+ orig_base = uart->io_base;
+ uart->io_base = 0;
/* NB. Start at bus 1 to avoid AMT: a plug-in card cannot be on bus 0. */
for ( b = skip_amt ? 1 : 0; b < 0x100; b++ )
{
@@ -579,24 +860,105 @@ pci_uart_config (struct ns16550 *uart, int skip_amt, int bar_idx)
bar = pci_conf_read32(0, b, d, f,
PCI_BASE_ADDRESS_0 + bar_idx*4);
- /* Not IO */
+ /* MMIO based */
if ( !(bar & PCI_BASE_ADDRESS_SPACE_IO) )
- continue;
-
- pci_conf_write32(0, b, d, f, PCI_BASE_ADDRESS_0, ~0u);
- len = pci_conf_read32(0, b, d, f, PCI_BASE_ADDRESS_0);
- pci_conf_write32(0, b, d, f, PCI_BASE_ADDRESS_0 + bar_idx*4, bar);
-
- /* Not 8 bytes */
- if ( (len & 0xffff) != 0xfff9 )
- continue;
+ {
+ vendor = pci_conf_read16(0, b, d, f, PCI_VENDOR_ID);
+ device = pci_conf_read16(0, b, d, f, PCI_DEVICE_ID);
+
+ pci_conf_write32(0, b, d, f,
+ PCI_BASE_ADDRESS_0 + bar_idx*4, ~0u);
+ len = pci_conf_read32(0, b, d, f, PCI_BASE_ADDRESS_0 + bar_idx*4);
+ pci_conf_write32(0, b, d, f,
+ PCI_BASE_ADDRESS_0 + bar_idx*4, bar);
+
+ /* Handle 64 bit BAR if found */
+ if ( bar & PCI_BASE_ADDRESS_MEM_TYPE_64 )
+ {
+ bar_64 = pci_conf_read32(0, b, d, f,
+ PCI_BASE_ADDRESS_0 + (bar_idx+1)*4);
+ pci_conf_write32(0, b, d, f,
+ PCI_BASE_ADDRESS_0 + (bar_idx+1)*4, ~0u);
+ len_64 = pci_conf_read32(0, b, d, f,
+ PCI_BASE_ADDRESS_0 + (bar_idx+1)*4);
+ pci_conf_write32(0, b, d, f,
+ PCI_BASE_ADDRESS_0 + (bar_idx+1)*4, bar_64);
+ mask = ((u64)~0 << 32) | PCI_BASE_ADDRESS_MEM_MASK;
+ size = (((u64)len_64 << 32) | len) & mask;
+ }
+ else
+ size = len & PCI_BASE_ADDRESS_MEM_MASK;
+
+ size &= -size;
+
+ /* Check for params in uart_config lookup table */
+ for ( i = 0; i < ARRAY_SIZE(uart_config); i++)
+ {
+ unsigned int p;
+
+ if ( uart_config[i].vendor_id != vendor )
+ continue;
+
+ if ( uart_config[i].dev_id != device )
+ continue;
+
+ p = uart_config[i].param;
+ /*
+ * Force length of mmio region to be at least
+ * 8 bytes times (1 << reg_shift)
+ */
+ if ( size < (0x8 * (1 << uart_param[p].reg_shift)) )
+ continue;
+
+ if ( bar_idx >= uart_param[p].max_bars )
+ continue;
+
+ if ( uart_param[p].fifo_size )
+ uart->fifo_size = uart_param[p].fifo_size;
+
+ uart->reg_shift = uart_param[p].reg_shift;
+ uart->reg_width = uart_param[p].reg_width;
+ uart->lsr_mask = uart_param[p].lsr_mask;
+ uart->io_base = ((u64)bar_64 << 32) |
+ (bar & PCI_BASE_ADDRESS_MEM_MASK);
+ uart->io_base += uart_param[p].first_offset;
+ uart->io_base += bar_idx * uart_param[p].uart_offset;
+ if ( uart_param[p].base_baud )
+ uart->clock_hz = uart_param[p].base_baud * 16;
+ /* Set device and MMIO region read only to Dom0 */
+ uart->enable_ro = 1;
+ break;
+ }
+
+ /* If we have an io_base, then we succeeded in the lookup */
+ if ( !uart->io_base )
+ continue;
+ }
+ /* IO based */
+ else
+ {
+ pci_conf_write32(0, b, d, f,
+ PCI_BASE_ADDRESS_0 + bar_idx*4, ~0u);
+ len = pci_conf_read32(0, b, d, f, PCI_BASE_ADDRESS_0);
+ pci_conf_write32(0, b, d, f,
+ PCI_BASE_ADDRESS_0 + bar_idx*4, bar);
+ size = len & PCI_BASE_ADDRESS_IO_MASK;
+ size &= -size;
+
+ /* Not 8 bytes */
+ if ( size != 0x8 )
+ continue;
+
+ uart->io_base = bar & ~PCI_BASE_ADDRESS_SPACE_IO;
+ }
uart->ps_bdf[0] = b;
uart->ps_bdf[1] = d;
uart->ps_bdf[2] = f;
- uart->bar = bar;
uart->bar_idx = bar_idx;
- uart->io_base = bar & ~PCI_BASE_ADDRESS_SPACE_IO;
+ uart->bar = bar;
+ uart->bar64 = bar_64;
+ uart->io_size = size;
uart->irq = pci_conf_read8(0, b, d, f, PCI_INTERRUPT_PIN) ?
pci_conf_read8(0, b, d, f, PCI_INTERRUPT_LINE) : 0;
@@ -608,9 +970,8 @@ pci_uart_config (struct ns16550 *uart, int skip_amt, int bar_idx)
if ( !skip_amt )
return -1;
- uart->io_base = 0x3f8;
- uart->irq = 0;
- uart->clock_hz = UART_CLOCK_HZ;
+ /* No AMT found, fallback to the defaults. */
+ uart->io_base = orig_base;
return 0;
}
@@ -721,6 +1082,21 @@ static void __init ns16550_parse_port_config(
serial_register_uart(uart - ns16550_com, &ns16550_driver, uart);
}
+static void ns16550_init_common(struct ns16550 *uart)
+{
+ uart->clock_hz = UART_CLOCK_HZ;
+
+#ifdef HAS_PCI
+ uart->enable_ro = 0;
+#endif
+
+ /* Default is no transmit FIFO. */
+ uart->fifo_size = 1;
+
+ /* Default lsr_mask = UART_LSR_THRE */
+ uart->lsr_mask = UART_LSR_THRE;
+}
+
void __init ns16550_init(int index, struct ns16550_defaults *defaults)
{
struct ns16550 *uart;
@@ -730,10 +1106,11 @@ void __init ns16550_init(int index, struct ns16550_defaults *defaults)
uart = &ns16550_com[index];
+ ns16550_init_common(uart);
+
uart->baud = (defaults->baud ? :
console_has((index == 0) ? "com1" : "com2")
? BAUD_AUTO : 0);
- uart->clock_hz = UART_CLOCK_HZ;
uart->data_bits = defaults->data_bits;
uart->parity = parse_parity_char(defaults->parity);
uart->stop_bits = defaults->stop_bits;
@@ -743,9 +1120,6 @@ void __init ns16550_init(int index, struct ns16550_defaults *defaults)
uart->reg_width = 1;
uart->reg_shift = 0;
- /* Default is no transmit FIFO. */
- uart->fifo_size = 1;
-
ns16550_parse_port_config(uart, (index == 0) ? opt_com1 : opt_com2);
}
@@ -760,13 +1134,12 @@ static int __init ns16550_uart_dt_init(struct dt_device_node *dev,
uart = &ns16550_com[0];
+ ns16550_init_common(uart);
+
uart->baud = BAUD_AUTO;
- uart->clock_hz = UART_CLOCK_HZ;
uart->data_bits = 8;
uart->parity = UART_PARITY_NONE;
uart->stop_bits = 1;
- /* Default is no transmit FIFO. */
- uart->fifo_size = 1;
res = dt_device_get_address(dev, 0, &uart->io_base, &io_size);
if ( res )
@@ -791,12 +1164,10 @@ static int __init ns16550_uart_dt_init(struct dt_device_node *dev,
if ( uart->reg_width != 1 && uart->reg_width != 4 )
return -EINVAL;
- res = dt_device_get_irq(dev, 0, &uart->dt_irq);
- if ( res )
- return res;
-
- /* The common bit of the driver mostly deals with irq not dt_irq. */
- uart->irq = uart->dt_irq.irq;
+ res = platform_get_irq(dev, 0);
+ if ( ! res )
+ return -EINVAL;
+ uart->irq = res;
uart->dw_usr_bsy = dt_device_is_compatible(dev, "snps,dw-apb-uart");
diff --git a/xen/drivers/char/omap-uart.c b/xen/drivers/char/omap-uart.c
index c1580ef..a798b8d 100644
--- a/xen/drivers/char/omap-uart.c
+++ b/xen/drivers/char/omap-uart.c
@@ -15,7 +15,6 @@
#include <xen/serial.h>
#include <xen/init.h>
#include <xen/irq.h>
-#include <asm/early_printk.h>
#include <xen/device_tree.h>
#include <asm/device.h>
#include <xen/errno.h>
@@ -31,7 +30,7 @@
static struct omap_uart {
u32 baud, clock_hz, data_bits, parity, stop_bits, fifo_size;
- struct dt_irq irq;
+ unsigned int irq;
char __iomem *regs;
struct irqaction irqaction;
struct vuart_info vuart;
@@ -206,10 +205,10 @@ static void __init omap_uart_init_postirq(struct serial_port *port)
uart->irqaction.name = "omap_uart";
uart->irqaction.dev_id = port;
- if ( setup_dt_irq(&uart->irq, &uart->irqaction) != 0 )
+ if ( setup_irq(uart->irq, 0, &uart->irqaction) != 0 )
{
dprintk(XENLOG_ERR, "Failed to allocated omap_uart IRQ %d\n",
- uart->irq.irq);
+ uart->irq);
return;
}
@@ -260,14 +259,7 @@ static int __init omap_uart_irq(struct serial_port *port)
{
struct omap_uart *uart = port->uart;
- return ((uart->irq.irq > 0) ? uart->irq.irq : -1);
-}
-
-static const struct dt_irq __init *omap_uart_dt_irq(struct serial_port *port)
-{
- struct omap_uart *uart = port->uart;
-
- return &uart->irq;
+ return ((uart->irq > 0) ? uart->irq : -1);
}
static const struct vuart_info *omap_vuart_info(struct serial_port *port)
@@ -287,7 +279,6 @@ static struct uart_driver __read_mostly omap_uart_driver = {
.putc = omap_uart_putc,
.getc = omap_uart_getc,
.irq = omap_uart_irq,
- .dt_irq_get = omap_uart_dt_irq,
.vuart_info = omap_vuart_info,
};
@@ -301,14 +292,14 @@ static int __init omap_uart_init(struct dt_device_node *dev,
u64 addr, size;
if ( strcmp(config, "") )
- early_printk("WARNING: UART configuration is not supported\n");
+ printk("WARNING: UART configuration is not supported\n");
uart = &omap_com;
res = dt_property_read_u32(dev, "clock-frequency", &clkspec);
if ( !res )
{
- early_printk("omap-uart: Unable to retrieve the clock frequency\n");
+ printk("omap-uart: Unable to retrieve the clock frequency\n");
return -EINVAL;
}
@@ -321,25 +312,27 @@ static int __init omap_uart_init(struct dt_device_node *dev,
res = dt_device_get_address(dev, 0, &addr, &size);
if ( res )
{
- early_printk("omap-uart: Unable to retrieve the base"
- " address of the UART\n");
+ printk("omap-uart: Unable to retrieve the base"
+ " address of the UART\n");
return res;
}
- uart->regs = ioremap_attr(addr, size, PAGE_HYPERVISOR_NOCACHE);
- if ( !uart->regs )
+ res = platform_get_irq(dev, 0);
+ if ( res < 0 )
{
- early_printk("omap-uart: Unable to map the UART memory\n");
- return -ENOMEM;
+ printk("omap-uart: Unable to retrieve the IRQ\n");
+ return -EINVAL;
}
+ uart->irq = res;
- res = dt_device_get_irq(dev, 0, &uart->irq);
- if ( res )
+ uart->regs = ioremap_nocache(addr, size);
+ if ( !uart->regs )
{
- early_printk("omap-uart: Unable to retrieve the IRQ\n");
- return res;
+ printk("omap-uart: Unable to map the UART memory\n");
+ return -ENOMEM;
}
+
uart->vuart.base_addr = addr;
uart->vuart.size = size;
uart->vuart.data_off = UART_THR;
diff --git a/xen/drivers/char/pl011.c b/xen/drivers/char/pl011.c
index fd82511..dd19ce8 100644
--- a/xen/drivers/char/pl011.c
+++ b/xen/drivers/char/pl011.c
@@ -22,7 +22,6 @@
#include <xen/serial.h>
#include <xen/init.h>
#include <xen/irq.h>
-#include <asm/early_printk.h>
#include <xen/device_tree.h>
#include <xen/errno.h>
#include <asm/device.h>
@@ -33,7 +32,7 @@
static struct pl011 {
unsigned int baud, clock_hz, data_bits, parity, stop_bits;
- struct dt_irq irq;
+ unsigned int irq;
void __iomem *regs;
/* UART with IRQ line: interrupt-driven I/O. */
struct irqaction irqaction;
@@ -107,7 +106,7 @@ static void __init pl011_init_preirq(struct serial_port *port)
/* Baud rate already set: read it out from the divisor latch. */
divisor = (pl011_read(uart, IBRD) << 6) | (pl011_read(uart, FBRD));
if (!divisor)
- early_panic("pl011: No Baud rate configured\n");
+ panic("pl011: No Baud rate configured\n");
uart->baud = (uart->clock_hz << 2) / divisor;
}
/* This write must follow FBRD and IBRD writes. */
@@ -133,13 +132,13 @@ static void __init pl011_init_postirq(struct serial_port *port)
struct pl011 *uart = port->uart;
int rc;
- if ( uart->irq.irq > 0 )
+ if ( uart->irq > 0 )
{
uart->irqaction.handler = pl011_interrupt;
uart->irqaction.name = "pl011";
uart->irqaction.dev_id = port;
- if ( (rc = setup_dt_irq(&uart->irq, &uart->irqaction)) != 0 )
- printk("ERROR: Failed to allocate pl011 IRQ %d\n", uart->irq.irq);
+ if ( (rc = setup_irq(uart->irq, 0, &uart->irqaction)) != 0 )
+ printk("ERROR: Failed to allocate pl011 IRQ %d\n", uart->irq);
}
/* Clear pending error interrupts */
@@ -187,14 +186,8 @@ static int pl011_getc(struct serial_port *port, char *pc)
static int __init pl011_irq(struct serial_port *port)
{
struct pl011 *uart = port->uart;
- return ((uart->irq.irq > 0) ? uart->irq.irq : -1);
-}
-
-static const struct dt_irq __init *pl011_dt_irq(struct serial_port *port)
-{
- struct pl011 *uart = port->uart;
- return &uart->irq;
+ return ((uart->irq > 0) ? uart->irq : -1);
}
static const struct vuart_info *pl011_vuart(struct serial_port *port)
@@ -214,7 +207,6 @@ static struct uart_driver __read_mostly pl011_driver = {
.putc = pl011_putc,
.getc = pl011_getc,
.irq = pl011_irq,
- .dt_irq_get = pl011_dt_irq,
.vuart_info = pl011_vuart,
};
@@ -229,7 +221,7 @@ static int __init pl011_uart_init(struct dt_device_node *dev,
if ( strcmp(config, "") )
{
- early_printk("WARNING: UART configuration is not supported\n");
+ printk("WARNING: UART configuration is not supported\n");
}
uart = &pl011_com;
@@ -243,24 +235,24 @@ static int __init pl011_uart_init(struct dt_device_node *dev,
res = dt_device_get_address(dev, 0, &addr, &size);
if ( res )
{
- early_printk("pl011: Unable to retrieve the base"
- " address of the UART\n");
+ printk("pl011: Unable to retrieve the base"
+ " address of the UART\n");
return res;
}
- uart->regs = ioremap_attr(addr, size, PAGE_HYPERVISOR_NOCACHE);
- if ( !uart->regs )
+ res = platform_get_irq(dev, 0);
+ if ( res < 0 )
{
- early_printk("pl011: Unable to map the UART memory\n");
-
- return -ENOMEM;
+ printk("pl011: Unable to retrieve the IRQ\n");
+ return -EINVAL;
}
+ uart->irq = res;
- res = dt_device_get_irq(dev, 0, &uart->irq);
- if ( res )
+ uart->regs = ioremap_nocache(addr, size);
+ if ( !uart->regs )
{
- early_printk("pl011: Unable to retrieve the IRQ\n");
- return res;
+ printk("pl011: Unable to map the UART memory\n");
+ return -ENOMEM;
}
uart->vuart.base_addr = addr;
diff --git a/xen/drivers/char/serial.c b/xen/drivers/char/serial.c
index 9b006f2..44026b1 100644
--- a/xen/drivers/char/serial.c
+++ b/xen/drivers/char/serial.c
@@ -500,15 +500,6 @@ int __init serial_irq(int idx)
return -1;
}
-const struct dt_irq __init *serial_dt_irq(int idx)
-{
- if ( (idx >= 0) && (idx < ARRAY_SIZE(com)) &&
- com[idx].driver && com[idx].driver->dt_irq_get )
- return com[idx].driver->dt_irq_get(&com[idx]);
-
- return NULL;
-}
-
const struct vuart_info *serial_vuart_info(int idx)
{
if ( (idx >= 0) && (idx < ARRAY_SIZE(com)) &&
diff --git a/xen/drivers/passthrough/Makefile b/xen/drivers/passthrough/Makefile
index 7c40fa5..16e9027 100644
--- a/xen/drivers/passthrough/Makefile
+++ b/xen/drivers/passthrough/Makefile
@@ -1,7 +1,9 @@
subdir-$(x86) += vtd
subdir-$(x86) += amd
subdir-$(x86_64) += x86
+subdir-$(arm) += arm
obj-y += iommu.o
-obj-y += io.o
-obj-y += pci.o
+obj-$(x86) += io.o
+obj-$(HAS_PCI) += pci.o
+obj-$(HAS_DEVICE_TREE) += device_tree.o
diff --git a/xen/drivers/passthrough/amd/iommu_cmd.c b/xen/drivers/passthrough/amd/iommu_cmd.c
index d27bd3c..4faa01b 100644
--- a/xen/drivers/passthrough/amd/iommu_cmd.c
+++ b/xen/drivers/passthrough/amd/iommu_cmd.c
@@ -354,8 +354,7 @@ static void _amd_iommu_flush_pages(struct domain *d,
{
unsigned long flags;
struct amd_iommu *iommu;
- struct hvm_iommu *hd = domain_hvm_iommu(d);
- unsigned int dom_id = hd->domain_id;
+ unsigned int dom_id = d->domain_id;
/* send INVALIDATE_IOMMU_PAGES command */
for_each_amd_iommu ( iommu )
diff --git a/xen/drivers/passthrough/amd/iommu_detect.c b/xen/drivers/passthrough/amd/iommu_detect.c
index be1b761..98e5cc2 100644
--- a/xen/drivers/passthrough/amd/iommu_detect.c
+++ b/xen/drivers/passthrough/amd/iommu_detect.c
@@ -95,7 +95,7 @@ void __init get_iommu_features(struct amd_iommu *iommu)
while ( feature_str[i] )
{
- if ( iommu_has_feature(iommu, i) )
+ if ( amd_iommu_has_feature(iommu, i) )
printk( " %s\n", feature_str[i]);
i++;
}
diff --git a/xen/drivers/passthrough/amd/iommu_guest.c b/xen/drivers/passthrough/amd/iommu_guest.c
index 477de20..98e7b38 100644
--- a/xen/drivers/passthrough/amd/iommu_guest.c
+++ b/xen/drivers/passthrough/amd/iommu_guest.c
@@ -60,12 +60,12 @@ static uint16_t guest_bdf(struct domain *d, uint16_t machine_bdf)
static inline struct guest_iommu *domain_iommu(struct domain *d)
{
- return domain_hvm_iommu(d)->g_iommu;
+ return domain_hvm_iommu(d)->arch.g_iommu;
}
static inline struct guest_iommu *vcpu_iommu(struct vcpu *v)
{
- return domain_hvm_iommu(v->domain)->g_iommu;
+ return domain_hvm_iommu(v->domain)->arch.g_iommu;
}
static void guest_iommu_enable(struct guest_iommu *iommu)
@@ -823,7 +823,7 @@ int guest_iommu_set_base(struct domain *d, uint64_t base)
unsigned long gfn = base + i;
get_gfn_query(d, gfn, &t);
- p2m_change_type(d, gfn, t, p2m_mmio_dm);
+ p2m_change_type_one(d, gfn, t, p2m_mmio_dm);
put_gfn(d, gfn);
}
@@ -885,8 +885,9 @@ int guest_iommu_init(struct domain* d)
}
guest_iommu_reg_init(iommu);
+ iommu->mmio_base = ~0ULL;
iommu->domain = d;
- hd->g_iommu = iommu;
+ hd->arch.g_iommu = iommu;
tasklet_init(&iommu->cmd_buffer_tasklet,
guest_iommu_process_command, (unsigned long)d);
@@ -907,7 +908,7 @@ void guest_iommu_destroy(struct domain *d)
tasklet_kill(&iommu->cmd_buffer_tasklet);
xfree(iommu);
- domain_hvm_iommu(d)->g_iommu = NULL;
+ domain_hvm_iommu(d)->arch.g_iommu = NULL;
}
static int guest_iommu_mmio_range(struct vcpu *v, unsigned long addr)
diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c
index 4686813..56bda00 100644
--- a/xen/drivers/passthrough/amd/iommu_init.c
+++ b/xen/drivers/passthrough/amd/iommu_init.c
@@ -815,7 +815,7 @@ static bool_t __init set_iommu_interrupt_handler(struct amd_iommu *iommu)
handler = &iommu_msi_type;
ret = __setup_msi_irq(irq_to_desc(irq), &iommu->msi, handler);
if ( !ret )
- ret = request_irq(irq, iommu_interrupt_handler, "amd_iommu", iommu);
+ ret = request_irq(irq, 0, iommu_interrupt_handler, "amd_iommu", iommu);
if ( ret )
{
destroy_irq(irq);
@@ -884,7 +884,7 @@ static void enable_iommu(struct amd_iommu *iommu)
register_iommu_event_log_in_mmio_space(iommu);
register_iommu_exclusion_range(iommu);
- if ( iommu_has_feature(iommu, IOMMU_EXT_FEATURE_PPRSUP_SHIFT) )
+ if ( amd_iommu_has_feature(iommu, IOMMU_EXT_FEATURE_PPRSUP_SHIFT) )
register_iommu_ppr_log_in_mmio_space(iommu);
desc = irq_to_desc(iommu->msi.irq);
@@ -898,15 +898,15 @@ static void enable_iommu(struct amd_iommu *iommu)
set_iommu_command_buffer_control(iommu, IOMMU_CONTROL_ENABLED);
set_iommu_event_log_control(iommu, IOMMU_CONTROL_ENABLED);
- if ( iommu_has_feature(iommu, IOMMU_EXT_FEATURE_PPRSUP_SHIFT) )
+ if ( amd_iommu_has_feature(iommu, IOMMU_EXT_FEATURE_PPRSUP_SHIFT) )
set_iommu_ppr_log_control(iommu, IOMMU_CONTROL_ENABLED);
- if ( iommu_has_feature(iommu, IOMMU_EXT_FEATURE_GTSUP_SHIFT) )
+ if ( amd_iommu_has_feature(iommu, IOMMU_EXT_FEATURE_GTSUP_SHIFT) )
set_iommu_guest_translation_control(iommu, IOMMU_CONTROL_ENABLED);
set_iommu_translation_control(iommu, IOMMU_CONTROL_ENABLED);
- if ( iommu_has_feature(iommu, IOMMU_EXT_FEATURE_IASUP_SHIFT) )
+ if ( amd_iommu_has_feature(iommu, IOMMU_EXT_FEATURE_IASUP_SHIFT) )
amd_iommu_flush_all_caches(iommu);
iommu->enabled = 1;
@@ -1009,7 +1009,7 @@ static int __init amd_iommu_init_one(struct amd_iommu *iommu)
if ( allocate_event_log(iommu) == NULL )
goto error_out;
- if ( iommu_has_feature(iommu, IOMMU_EXT_FEATURE_PPRSUP_SHIFT) )
+ if ( amd_iommu_has_feature(iommu, IOMMU_EXT_FEATURE_PPRSUP_SHIFT) )
if ( allocate_ppr_log(iommu) == NULL )
goto error_out;
@@ -1255,6 +1255,14 @@ int __init amd_iommu_init(void)
if ( iterate_ivrs_mappings(amd_iommu_setup_device_table) != 0 )
goto error_out;
+ /*
+ * Disable sharing HAP page tables with AMD IOMMU,
+ * since it only supports p2m_ram_rw, and this would
+ * prevent doing IO to/from mapped grant frames.
+ */
+ iommu_hap_pt_share = 0;
+ printk(XENLOG_DEBUG "AMD-Vi: Disabled HAP memory map sharing with IOMMU\n");
+
/* per iommu initialization */
for_each_amd_iommu ( iommu )
if ( amd_iommu_init_one(iommu) != 0 )
@@ -1283,10 +1291,10 @@ static void disable_iommu(struct amd_iommu *iommu)
set_iommu_command_buffer_control(iommu, IOMMU_CONTROL_DISABLED);
set_iommu_event_log_control(iommu, IOMMU_CONTROL_DISABLED);
- if ( iommu_has_feature(iommu, IOMMU_EXT_FEATURE_PPRSUP_SHIFT) )
+ if ( amd_iommu_has_feature(iommu, IOMMU_EXT_FEATURE_PPRSUP_SHIFT) )
set_iommu_ppr_log_control(iommu, IOMMU_CONTROL_DISABLED);
- if ( iommu_has_feature(iommu, IOMMU_EXT_FEATURE_GTSUP_SHIFT) )
+ if ( amd_iommu_has_feature(iommu, IOMMU_EXT_FEATURE_GTSUP_SHIFT) )
set_iommu_guest_translation_control(iommu, IOMMU_CONTROL_DISABLED);
set_iommu_translation_control(iommu, IOMMU_CONTROL_DISABLED);
@@ -1356,7 +1364,7 @@ void amd_iommu_resume(void)
}
/* flush all cache entries after iommu re-enabled */
- if ( !iommu_has_feature(iommu, IOMMU_EXT_FEATURE_IASUP_SHIFT) )
+ if ( !amd_iommu_has_feature(iommu, IOMMU_EXT_FEATURE_IASUP_SHIFT) )
{
invalidate_all_devices();
invalidate_all_domain_pages();
diff --git a/xen/drivers/passthrough/amd/iommu_map.c b/xen/drivers/passthrough/amd/iommu_map.c
index 5e02ac8..a8c60ec 100644
--- a/xen/drivers/passthrough/amd/iommu_map.c
+++ b/xen/drivers/passthrough/amd/iommu_map.c
@@ -344,7 +344,7 @@ static int iommu_update_pde_count(struct domain *d, unsigned long pt_mfn,
struct hvm_iommu *hd = domain_hvm_iommu(d);
bool_t ok = 0;
- ASSERT( spin_is_locked(&hd->mapping_lock) && pt_mfn );
+ ASSERT( spin_is_locked(&hd->arch.mapping_lock) && pt_mfn );
next_level = merge_level - 1;
@@ -398,7 +398,7 @@ static int iommu_merge_pages(struct domain *d, unsigned long pt_mfn,
unsigned long first_mfn;
struct hvm_iommu *hd = domain_hvm_iommu(d);
- ASSERT( spin_is_locked(&hd->mapping_lock) && pt_mfn );
+ ASSERT( spin_is_locked(&hd->arch.mapping_lock) && pt_mfn );
table = map_domain_page(pt_mfn);
pde = table + pfn_to_pde_idx(gfn, merge_level);
@@ -448,8 +448,8 @@ static int iommu_pde_from_gfn(struct domain *d, unsigned long pfn,
struct page_info *table;
struct hvm_iommu *hd = domain_hvm_iommu(d);
- table = hd->root_table;
- level = hd->paging_mode;
+ table = hd->arch.root_table;
+ level = hd->arch.paging_mode;
BUG_ON( table == NULL || level < IOMMU_PAGING_MODE_LEVEL_1 ||
level > IOMMU_PAGING_MODE_LEVEL_6 );
@@ -557,11 +557,11 @@ static int update_paging_mode(struct domain *d, unsigned long gfn)
unsigned long old_root_mfn;
struct hvm_iommu *hd = domain_hvm_iommu(d);
- level = hd->paging_mode;
- old_root = hd->root_table;
+ level = hd->arch.paging_mode;
+ old_root = hd->arch.root_table;
offset = gfn >> (PTE_PER_TABLE_SHIFT * (level - 1));
- ASSERT(spin_is_locked(&hd->mapping_lock) && is_hvm_domain(d));
+ ASSERT(spin_is_locked(&hd->arch.mapping_lock) && is_hvm_domain(d));
while ( offset >= PTE_PER_TABLE_SIZE )
{
@@ -587,8 +587,8 @@ static int update_paging_mode(struct domain *d, unsigned long gfn)
if ( new_root != NULL )
{
- hd->paging_mode = level;
- hd->root_table = new_root;
+ hd->arch.paging_mode = level;
+ hd->arch.root_table = new_root;
if ( !spin_is_locked(&pcidevs_lock) )
AMD_IOMMU_DEBUG("%s Try to access pdev_list "
@@ -613,9 +613,9 @@ static int update_paging_mode(struct domain *d, unsigned long gfn)
/* valid = 0 only works for dom0 passthrough mode */
amd_iommu_set_root_page_table((u32 *)device_entry,
- page_to_maddr(hd->root_table),
- hd->domain_id,
- hd->paging_mode, 1);
+ page_to_maddr(hd->arch.root_table),
+ d->domain_id,
+ hd->arch.paging_mode, 1);
amd_iommu_flush_device(iommu, req_id);
bdf += pdev->phantom_stride;
@@ -638,14 +638,14 @@ int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn,
unsigned long pt_mfn[7];
unsigned int merge_level;
- BUG_ON( !hd->root_table );
+ BUG_ON( !hd->arch.root_table );
if ( iommu_use_hap_pt(d) )
return 0;
memset(pt_mfn, 0, sizeof(pt_mfn));
- spin_lock(&hd->mapping_lock);
+ spin_lock(&hd->arch.mapping_lock);
/* Since HVM domain is initialized with 2 level IO page table,
* we might need a deeper page table for lager gfn now */
@@ -653,7 +653,7 @@ int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn,
{
if ( update_paging_mode(d, gfn) )
{
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
AMD_IOMMU_DEBUG("Update page mode failed gfn = %lx\n", gfn);
domain_crash(d);
return -EFAULT;
@@ -662,7 +662,7 @@ int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn,
if ( iommu_pde_from_gfn(d, gfn, pt_mfn) || (pt_mfn[1] == 0) )
{
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
AMD_IOMMU_DEBUG("Invalid IO pagetable entry gfn = %lx\n", gfn);
domain_crash(d);
return -EFAULT;
@@ -684,7 +684,7 @@ int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn,
amd_iommu_flush_pages(d, gfn, 0);
for ( merge_level = IOMMU_PAGING_MODE_LEVEL_2;
- merge_level <= hd->paging_mode; merge_level++ )
+ merge_level <= hd->arch.paging_mode; merge_level++ )
{
if ( pt_mfn[merge_level] == 0 )
break;
@@ -695,7 +695,7 @@ int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn,
if ( iommu_merge_pages(d, pt_mfn[merge_level], gfn,
flags, merge_level) )
{
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
AMD_IOMMU_DEBUG("Merge iommu page failed at level %d, "
"gfn = %lx mfn = %lx\n", merge_level, gfn, mfn);
domain_crash(d);
@@ -707,7 +707,7 @@ int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn,
}
out:
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
return 0;
}
@@ -716,14 +716,14 @@ int amd_iommu_unmap_page(struct domain *d, unsigned long gfn)
unsigned long pt_mfn[7];
struct hvm_iommu *hd = domain_hvm_iommu(d);
- BUG_ON( !hd->root_table );
+ BUG_ON( !hd->arch.root_table );
if ( iommu_use_hap_pt(d) )
return 0;
memset(pt_mfn, 0, sizeof(pt_mfn));
- spin_lock(&hd->mapping_lock);
+ spin_lock(&hd->arch.mapping_lock);
/* Since HVM domain is initialized with 2 level IO page table,
* we might need a deeper page table for lager gfn now */
@@ -731,7 +731,7 @@ int amd_iommu_unmap_page(struct domain *d, unsigned long gfn)
{
if ( update_paging_mode(d, gfn) )
{
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
AMD_IOMMU_DEBUG("Update page mode failed gfn = %lx\n", gfn);
domain_crash(d);
return -EFAULT;
@@ -740,7 +740,7 @@ int amd_iommu_unmap_page(struct domain *d, unsigned long gfn)
if ( iommu_pde_from_gfn(d, gfn, pt_mfn) || (pt_mfn[1] == 0) )
{
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
AMD_IOMMU_DEBUG("Invalid IO pagetable entry gfn = %lx\n", gfn);
domain_crash(d);
return -EFAULT;
@@ -748,7 +748,7 @@ int amd_iommu_unmap_page(struct domain *d, unsigned long gfn)
/* mark PTE as 'page not present' */
clear_iommu_pte_present(pt_mfn[1], gfn);
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
amd_iommu_flush_pages(d, gfn, 0);
@@ -793,13 +793,13 @@ void amd_iommu_share_p2m(struct domain *d)
pgd_mfn = pagetable_get_mfn(p2m_get_pagetable(p2m_get_hostp2m(d)));
p2m_table = mfn_to_page(mfn_x(pgd_mfn));
- if ( hd->root_table != p2m_table )
+ if ( hd->arch.root_table != p2m_table )
{
- free_amd_iommu_pgtable(hd->root_table);
- hd->root_table = p2m_table;
+ free_amd_iommu_pgtable(hd->arch.root_table);
+ hd->arch.root_table = p2m_table;
/* When sharing p2m with iommu, paging mode = 4 */
- hd->paging_mode = IOMMU_PAGING_MODE_LEVEL_4;
+ hd->arch.paging_mode = IOMMU_PAGING_MODE_LEVEL_4;
AMD_IOMMU_DEBUG("Share p2m table with iommu: p2m table = %#lx\n",
mfn_x(pgd_mfn));
}
diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c
index f97fcf2..e83bb35 100644
--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c
+++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c
@@ -19,6 +19,7 @@
*/
#include <xen/sched.h>
+#include <xen/iocap.h>
#include <xen/pci.h>
#include <xen/pci_regs.h>
#include <xen/paging.h>
@@ -120,9 +121,10 @@ static void amd_iommu_setup_domain_device(
struct hvm_iommu *hd = domain_hvm_iommu(domain);
- BUG_ON( !hd->root_table || !hd->paging_mode || !iommu->dev_table.buffer );
+ BUG_ON( !hd->arch.root_table || !hd->arch.paging_mode ||
+ !iommu->dev_table.buffer );
- if ( iommu_passthrough && (domain->domain_id == 0) )
+ if ( iommu_passthrough && is_hardware_domain(domain) )
valid = 0;
if ( ats_enabled )
@@ -138,8 +140,8 @@ static void amd_iommu_setup_domain_device(
{
/* bind DTE to domain page-tables */
amd_iommu_set_root_page_table(
- (u32 *)dte, page_to_maddr(hd->root_table), hd->domain_id,
- hd->paging_mode, valid);
+ (u32 *)dte, page_to_maddr(hd->arch.root_table), domain->domain_id,
+ hd->arch.paging_mode, valid);
if ( pci_ats_device(iommu->seg, bus, pdev->devfn) &&
iommu_has_cap(iommu, PCI_CAP_IOTLB_SHIFT) )
@@ -151,8 +153,8 @@ static void amd_iommu_setup_domain_device(
"root table = %#"PRIx64", "
"domain = %d, paging mode = %d\n",
req_id, pdev->type,
- page_to_maddr(hd->root_table),
- hd->domain_id, hd->paging_mode);
+ page_to_maddr(hd->arch.root_table),
+ domain->domain_id, hd->arch.paging_mode);
}
spin_unlock_irqrestore(&iommu->lock, flags);
@@ -169,7 +171,8 @@ static void amd_iommu_setup_domain_device(
}
}
-static int __init amd_iommu_setup_dom0_device(u8 devfn, struct pci_dev *pdev)
+static int __hwdom_init amd_iommu_setup_hwdom_device(
+ u8 devfn, struct pci_dev *pdev)
{
int bdf = PCI_BDF2(pdev->bus, pdev->devfn);
struct amd_iommu *iommu = find_iommu_for_device(pdev->seg, bdf);
@@ -225,17 +228,17 @@ int __init amd_iov_detect(void)
static int allocate_domain_resources(struct hvm_iommu *hd)
{
/* allocate root table */
- spin_lock(&hd->mapping_lock);
- if ( !hd->root_table )
+ spin_lock(&hd->arch.mapping_lock);
+ if ( !hd->arch.root_table )
{
- hd->root_table = alloc_amd_iommu_pgtable();
- if ( !hd->root_table )
+ hd->arch.root_table = alloc_amd_iommu_pgtable();
+ if ( !hd->arch.root_table )
{
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
return -ENOMEM;
}
}
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
return 0;
}
@@ -262,27 +265,26 @@ static int amd_iommu_domain_init(struct domain *d)
/* allocate page directroy */
if ( allocate_domain_resources(hd) != 0 )
{
- if ( hd->root_table )
- free_domheap_page(hd->root_table);
+ if ( hd->arch.root_table )
+ free_domheap_page(hd->arch.root_table);
return -ENOMEM;
}
/* For pv and dom0, stick with get_paging_mode(max_page)
* For HVM dom0, use 2 level page table at first */
- hd->paging_mode = is_hvm_domain(d) ?
+ hd->arch.paging_mode = is_hvm_domain(d) ?
IOMMU_PAGING_MODE_LEVEL_2 :
get_paging_mode(max_page);
- hd->domain_id = d->domain_id;
-
guest_iommu_init(d);
return 0;
}
-static void __init amd_iommu_dom0_init(struct domain *d)
+static void __hwdom_init amd_iommu_hwdom_init(struct domain *d)
{
unsigned long i;
+ const struct amd_iommu *iommu;
if ( !iommu_passthrough && !need_iommu(d) )
{
@@ -304,7 +306,13 @@ static void __init amd_iommu_dom0_init(struct domain *d)
}
}
- setup_dom0_pci_devices(d, amd_iommu_setup_dom0_device);
+ for_each_amd_iommu ( iommu )
+ if ( iomem_deny_access(d, PFN_DOWN(iommu->mmio_base_phys),
+ PFN_DOWN(iommu->mmio_base_phys +
+ IOMMU_MMIO_REGION_LENGTH - 1)) )
+ BUG();
+
+ setup_hwdom_pci_devices(d, amd_iommu_setup_hwdom_device);
}
void amd_iommu_disable_domain_device(struct domain *domain,
@@ -333,8 +341,8 @@ void amd_iommu_disable_domain_device(struct domain *domain,
AMD_IOMMU_DEBUG("Disable: device id = %#x, "
"domain = %d, paging mode = %d\n",
- req_id, domain_hvm_iommu(domain)->domain_id,
- domain_hvm_iommu(domain)->paging_mode);
+ req_id, domain->domain_id,
+ domain_hvm_iommu(domain)->arch.paging_mode);
}
spin_unlock_irqrestore(&iommu->lock, flags);
@@ -374,7 +382,7 @@ static int reassign_device(struct domain *source, struct domain *target,
/* IO page tables might be destroyed after pci-detach the last device
* In this case, we have to re-allocate root table for next pci-attach.*/
- if ( t->root_table == NULL )
+ if ( t->arch.root_table == NULL )
allocate_domain_resources(t);
amd_iommu_setup_domain_device(target, iommu, devfn, pdev);
@@ -402,7 +410,7 @@ static int amd_iommu_assign_device(struct domain *d, u8 devfn,
ivrs_mappings[req_id].read_permission);
}
- return reassign_device(dom0, d, devfn, pdev);
+ return reassign_device(hardware_domain, d, devfn, pdev);
}
static void deallocate_next_page_table(struct page_info *pg, int level)
@@ -456,13 +464,13 @@ static void deallocate_iommu_page_tables(struct domain *d)
if ( iommu_use_hap_pt(d) )
return;
- spin_lock(&hd->mapping_lock);
- if ( hd->root_table )
+ spin_lock(&hd->arch.mapping_lock);
+ if ( hd->arch.root_table )
{
- deallocate_next_page_table(hd->root_table, hd->paging_mode);
- hd->root_table = NULL;
+ deallocate_next_page_table(hd->arch.root_table, hd->arch.paging_mode);
+ hd->arch.root_table = NULL;
}
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
}
@@ -593,16 +601,16 @@ static void amd_dump_p2m_table(struct domain *d)
{
struct hvm_iommu *hd = domain_hvm_iommu(d);
- if ( !hd->root_table )
+ if ( !hd->arch.root_table )
return;
- printk("p2m table has %d levels\n", hd->paging_mode);
- amd_dump_p2m_table_level(hd->root_table, hd->paging_mode, 0, 0);
+ printk("p2m table has %d levels\n", hd->arch.paging_mode);
+ amd_dump_p2m_table_level(hd->arch.root_table, hd->arch.paging_mode, 0, 0);
}
const struct iommu_ops amd_iommu_ops = {
.init = amd_iommu_domain_init,
- .dom0_init = amd_iommu_dom0_init,
+ .hwdom_init = amd_iommu_hwdom_init,
.add_device = amd_iommu_add_device,
.remove_device = amd_iommu_remove_device,
.assign_device = amd_iommu_assign_device,
diff --git a/xen/drivers/passthrough/arm/Makefile b/xen/drivers/passthrough/arm/Makefile
new file mode 100644
index 0000000..f4cd26e
--- /dev/null
+++ b/xen/drivers/passthrough/arm/Makefile
@@ -0,0 +1,2 @@
+obj-y += iommu.o
+obj-y += smmu.o
diff --git a/xen/drivers/passthrough/arm/iommu.c b/xen/drivers/passthrough/arm/iommu.c
new file mode 100644
index 0000000..3007b99
--- /dev/null
+++ b/xen/drivers/passthrough/arm/iommu.c
@@ -0,0 +1,70 @@
+/*
+ * Generic IOMMU framework via the device tree
+ *
+ * Julien Grall <julien.grall at linaro.org>
+ * Copyright (c) 2014 Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <xen/lib.h>
+#include <xen/iommu.h>
+#include <xen/device_tree.h>
+#include <asm/device.h>
+
+static const struct iommu_ops *iommu_ops;
+
+const struct iommu_ops *iommu_get_ops(void)
+{
+ return iommu_ops;
+}
+
+void __init iommu_set_ops(const struct iommu_ops *ops)
+{
+ BUG_ON(ops == NULL);
+
+ if ( iommu_ops && iommu_ops != ops )
+ printk("WARNING: Cannot set IOMMU ops, already set to a different value\n");
+
+ iommu_ops = ops;
+}
+
+int __init iommu_hardware_setup(void)
+{
+ struct dt_device_node *np;
+ int rc;
+ unsigned int num_iommus = 0;
+
+ dt_for_each_device_node(dt_host, np)
+ {
+ rc = device_init(np, DEVICE_IOMMU, NULL);
+ if ( !rc )
+ num_iommus++;
+ }
+
+ return ( num_iommus > 0 ) ? 0 : -ENODEV;
+}
+
+void __hwdom_init arch_iommu_check_autotranslated_hwdom(struct domain *d)
+{
+ /* ARM doesn't require specific check for hwdom */
+ return;
+}
+
+int arch_iommu_domain_init(struct domain *d)
+{
+ return iommu_dt_domain_init(d);
+}
+
+void arch_iommu_domain_destroy(struct domain *d)
+{
+ iommu_dt_domain_destroy(d);
+}
diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c
new file mode 100644
index 0000000..42bde75
--- /dev/null
+++ b/xen/drivers/passthrough/arm/smmu.c
@@ -0,0 +1,1784 @@
+/*
+ * IOMMU API for ARM architected SMMU implementations.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Based on Linux drivers/iommu/arm-smmu.c (commit 89a23cd)
+ * Copyright (C) 2013 ARM Limited
+ *
+ * Author: Will Deacon <will.deacon at arm.com>
+ *
+ * Xen modification:
+ * Julien Grall <julien.grall at linaro.org>
+ * Copyright (C) 2014 Linaro Limited.
+ *
+ * This driver currently supports:
+ * - SMMUv1 and v2 implementations (didn't try v2 SMMU)
+ * - Stream-matching and stream-indexing
+ * - v7/v8 long-descriptor format
+ * - Non-secure access to the SMMU
+ * - 4k pages, p2m shared with the processor
+ * - Up to 40-bit addressing
+ * - Context fault reporting
+ */
+
+#include <xen/config.h>
+#include <xen/delay.h>
+#include <xen/errno.h>
+#include <xen/irq.h>
+#include <xen/lib.h>
+#include <xen/list.h>
+#include <xen/mm.h>
+#include <xen/vmap.h>
+#include <xen/rbtree.h>
+#include <xen/sched.h>
+#include <asm/atomic.h>
+#include <asm/device.h>
+#include <asm/io.h>
+#include <asm/platform.h>
+
+/* Driver options */
+#define SMMU_OPT_SECURE_CONFIG_ACCESS (1 << 0)
+
+/* Maximum number of stream IDs assigned to a single device */
+#define MAX_MASTER_STREAMIDS MAX_PHANDLE_ARGS
+
+/* Maximum stream ID */
+#define SMMU_MAX_STREAMIDS (PAGE_SIZE_64K - 1)
+
+/* Maximum number of context banks per SMMU */
+#define SMMU_MAX_CBS 128
+
+/* Maximum number of mapping groups per SMMU */
+#define SMMU_MAX_SMRS 128
+
+/* SMMU global address space */
+#define SMMU_GR0(smmu) ((smmu)->base)
+#define SMMU_GR1(smmu) ((smmu)->base + (smmu)->pagesize)
+
+/*
+ * SMMU global address space with conditional offset to access secure aliases of
+ * non-secure registers (e.g. nsCR0: 0x400, nsGFSR: 0x448, nsGFSYNR0: 0x450)
+ */
+#define SMMU_GR0_NS(smmu) \
+ ((smmu)->base + \
+ ((smmu->options & SMMU_OPT_SECURE_CONFIG_ACCESS) \
+ ? 0x400 : 0))
+
+/* Page table bits */
+#define SMMU_PTE_PAGE (((pteval_t)3) << 0)
+#define SMMU_PTE_CONT (((pteval_t)1) << 52)
+#define SMMU_PTE_AF (((pteval_t)1) << 10)
+#define SMMU_PTE_SH_NS (((pteval_t)0) << 8)
+#define SMMU_PTE_SH_OS (((pteval_t)2) << 8)
+#define SMMU_PTE_SH_IS (((pteval_t)3) << 8)
+
+#if PAGE_SIZE == PAGE_SIZE_4K
+#define SMMU_PTE_CONT_ENTRIES 16
+#elif PAGE_SIZE == PAGE_SIZE_64K
+#define SMMU_PTE_CONT_ENTRIES 32
+#else
+#define SMMU_PTE_CONT_ENTRIES 1
+#endif
+
+#define SMMU_PTE_CONT_SIZE (PAGE_SIZE * SMMU_PTE_CONT_ENTRIES)
+#define SMMU_PTE_CONT_MASK (~(SMMU_PTE_CONT_SIZE - 1))
+#define SMMU_PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(pte_t))
+
+/* Stage-1 PTE */
+#define SMMU_PTE_AP_UNPRIV (((pteval_t)1) << 6)
+#define SMMU_PTE_AP_RDONLY (((pteval_t)2) << 6)
+#define SMMU_PTE_ATTRINDX_SHIFT 2
+#define SMMU_PTE_nG (((pteval_t)1) << 11)
+
+/* Stage-2 PTE */
+#define SMMU_PTE_HAP_FAULT (((pteval_t)0) << 6)
+#define SMMU_PTE_HAP_READ (((pteval_t)1) << 6)
+#define SMMU_PTE_HAP_WRITE (((pteval_t)2) << 6)
+#define SMMU_PTE_MEMATTR_OIWB (((pteval_t)0xf) << 2)
+#define SMMU_PTE_MEMATTR_NC (((pteval_t)0x5) << 2)
+#define SMMU_PTE_MEMATTR_DEV (((pteval_t)0x1) << 2)
+
+/* Configuration registers */
+#define SMMU_GR0_sCR0 0x0
+#define SMMU_sCR0_CLIENTPD (1 << 0)
+#define SMMU_sCR0_GFRE (1 << 1)
+#define SMMU_sCR0_GFIE (1 << 2)
+#define SMMU_sCR0_GCFGFRE (1 << 4)
+#define SMMU_sCR0_GCFGFIE (1 << 5)
+#define SMMU_sCR0_USFCFG (1 << 10)
+#define SMMU_sCR0_VMIDPNE (1 << 11)
+#define SMMU_sCR0_PTM (1 << 12)
+#define SMMU_sCR0_FB (1 << 13)
+#define SMMU_sCR0_BSU_SHIFT 14
+#define SMMU_sCR0_BSU_MASK 0x3
+
+/* Identification registers */
+#define SMMU_GR0_ID0 0x20
+#define SMMU_GR0_ID1 0x24
+#define SMMU_GR0_ID2 0x28
+#define SMMU_GR0_ID3 0x2c
+#define SMMU_GR0_ID4 0x30
+#define SMMU_GR0_ID5 0x34
+#define SMMU_GR0_ID6 0x38
+#define SMMU_GR0_ID7 0x3c
+#define SMMU_GR0_sGFSR 0x48
+#define SMMU_GR0_sGFSYNR0 0x50
+#define SMMU_GR0_sGFSYNR1 0x54
+#define SMMU_GR0_sGFSYNR2 0x58
+#define SMMU_GR0_PIDR0 0xfe0
+#define SMMU_GR0_PIDR1 0xfe4
+#define SMMU_GR0_PIDR2 0xfe8
+
+#define SMMU_ID0_S1TS (1 << 30)
+#define SMMU_ID0_S2TS (1 << 29)
+#define SMMU_ID0_NTS (1 << 28)
+#define SMMU_ID0_SMS (1 << 27)
+#define SMMU_ID0_PTFS_SHIFT 24
+#define SMMU_ID0_PTFS_MASK 0x2
+#define SMMU_ID0_PTFS_V8_ONLY 0x2
+#define SMMU_ID0_CTTW (1 << 14)
+#define SMMU_ID0_NUMIRPT_SHIFT 16
+#define SMMU_ID0_NUMIRPT_MASK 0xff
+#define SMMU_ID0_NUMSMRG_SHIFT 0
+#define SMMU_ID0_NUMSMRG_MASK 0xff
+
+#define SMMU_ID1_PAGESIZE (1 << 31)
+#define SMMU_ID1_NUMPAGENDXB_SHIFT 28
+#define SMMU_ID1_NUMPAGENDXB_MASK 7
+#define SMMU_ID1_NUMS2CB_SHIFT 16
+#define SMMU_ID1_NUMS2CB_MASK 0xff
+#define SMMU_ID1_NUMCB_SHIFT 0
+#define SMMU_ID1_NUMCB_MASK 0xff
+
+#define SMMU_ID2_OAS_SHIFT 4
+#define SMMU_ID2_OAS_MASK 0xf
+#define SMMU_ID2_IAS_SHIFT 0
+#define SMMU_ID2_IAS_MASK 0xf
+#define SMMU_ID2_UBS_SHIFT 8
+#define SMMU_ID2_UBS_MASK 0xf
+#define SMMU_ID2_PTFS_4K (1 << 12)
+#define SMMU_ID2_PTFS_16K (1 << 13)
+#define SMMU_ID2_PTFS_64K (1 << 14)
+
+#define SMMU_PIDR2_ARCH_SHIFT 4
+#define SMMU_PIDR2_ARCH_MASK 0xf
+
+/* Global TLB invalidation */
+#define SMMU_GR0_STLBIALL 0x60
+#define SMMU_GR0_TLBIVMID 0x64
+#define SMMU_GR0_TLBIALLNSNH 0x68
+#define SMMU_GR0_TLBIALLH 0x6c
+#define SMMU_GR0_sTLBGSYNC 0x70
+#define SMMU_GR0_sTLBGSTATUS 0x74
+#define SMMU_sTLBGSTATUS_GSACTIVE (1 << 0)
+#define SMMU_TLB_LOOP_TIMEOUT 1000000 /* 1s! */
+
+/* Stream mapping registers */
+#define SMMU_GR0_SMR(n) (0x800 + ((n) << 2))
+#define SMMU_SMR_VALID (1 << 31)
+#define SMMU_SMR_MASK_SHIFT 16
+#define SMMU_SMR_MASK_MASK 0x7fff
+#define SMMU_SMR_ID_SHIFT 0
+#define SMMU_SMR_ID_MASK 0x7fff
+
+#define SMMU_GR0_S2CR(n) (0xc00 + ((n) << 2))
+#define SMMU_S2CR_CBNDX_SHIFT 0
+#define SMMU_S2CR_CBNDX_MASK 0xff
+#define SMMU_S2CR_TYPE_SHIFT 16
+#define SMMU_S2CR_TYPE_MASK 0x3
+#define SMMU_S2CR_TYPE_TRANS (0 << SMMU_S2CR_TYPE_SHIFT)
+#define SMMU_S2CR_TYPE_BYPASS (1 << SMMU_S2CR_TYPE_SHIFT)
+#define SMMU_S2CR_TYPE_FAULT (2 << SMMU_S2CR_TYPE_SHIFT)
+
+/* Context bank attribute registers */
+#define SMMU_GR1_CBAR(n) (0x0 + ((n) << 2))
+#define SMMU_CBAR_VMID_SHIFT 0
+#define SMMU_CBAR_VMID_MASK 0xff
+#define SMMU_CBAR_S1_MEMATTR_SHIFT 12
+#define SMMU_CBAR_S1_MEMATTR_MASK 0xf
+#define SMMU_CBAR_S1_MEMATTR_WB 0xf
+#define SMMU_CBAR_TYPE_SHIFT 16
+#define SMMU_CBAR_TYPE_MASK 0x3
+#define SMMU_CBAR_TYPE_S2_TRANS (0 << SMMU_CBAR_TYPE_SHIFT)
+#define SMMU_CBAR_TYPE_S1_TRANS_S2_BYPASS (1 << SMMU_CBAR_TYPE_SHIFT)
+#define SMMU_CBAR_TYPE_S1_TRANS_S2_FAULT (2 << SMMU_CBAR_TYPE_SHIFT)
+#define SMMU_CBAR_TYPE_S1_TRANS_S2_TRANS (3 << SMMU_CBAR_TYPE_SHIFT)
+#define SMMU_CBAR_IRPTNDX_SHIFT 24
+#define SMMU_CBAR_IRPTNDX_MASK 0xff
+
+#define SMMU_GR1_CBA2R(n) (0x800 + ((n) << 2))
+#define SMMU_CBA2R_RW64_32BIT (0 << 0)
+#define SMMU_CBA2R_RW64_64BIT (1 << 0)
+
+/* Translation context bank */
+#define SMMU_CB_BASE(smmu) ((smmu)->base + ((smmu)->size >> 1))
+#define SMMU_CB(smmu, n) ((n) * (smmu)->pagesize)
+
+#define SMMU_CB_SCTLR 0x0
+#define SMMU_CB_RESUME 0x8
+#define SMMU_CB_TCR2 0x10
+#define SMMU_CB_TTBR0_LO 0x20
+#define SMMU_CB_TTBR0_HI 0x24
+#define SMMU_CB_TCR 0x30
+#define SMMU_CB_S1_MAIR0 0x38
+#define SMMU_CB_FSR 0x58
+#define SMMU_CB_FAR_LO 0x60
+#define SMMU_CB_FAR_HI 0x64
+#define SMMU_CB_FSYNR0 0x68
+#define SMMU_CB_S1_TLBIASID 0x610
+
+#define SMMU_SCTLR_S1_ASIDPNE (1 << 12)
+#define SMMU_SCTLR_CFCFG (1 << 7)
+#define SMMU_SCTLR_CFIE (1 << 6)
+#define SMMU_SCTLR_CFRE (1 << 5)
+#define SMMU_SCTLR_E (1 << 4)
+#define SMMU_SCTLR_AFE (1 << 2)
+#define SMMU_SCTLR_TRE (1 << 1)
+#define SMMU_SCTLR_M (1 << 0)
+#define SMMU_SCTLR_EAE_SBOP (SMMU_SCTLR_AFE | SMMU_SCTLR_TRE)
+
+#define SMMU_RESUME_RETRY (0 << 0)
+#define SMMU_RESUME_TERMINATE (1 << 0)
+
+#define SMMU_TCR_EAE (1 << 31)
+
+#define SMMU_TCR_PASIZE_SHIFT 16
+#define SMMU_TCR_PASIZE_MASK 0x7
+
+#define SMMU_TCR_TG0_4K (0 << 14)
+#define SMMU_TCR_TG0_64K (1 << 14)
+
+#define SMMU_TCR_SH0_SHIFT 12
+#define SMMU_TCR_SH0_MASK 0x3
+#define SMMU_TCR_SH_NS 0
+#define SMMU_TCR_SH_OS 2
+#define SMMU_TCR_SH_IS 3
+
+#define SMMU_TCR_ORGN0_SHIFT 10
+#define SMMU_TCR_IRGN0_SHIFT 8
+#define SMMU_TCR_RGN_MASK 0x3
+#define SMMU_TCR_RGN_NC 0
+#define SMMU_TCR_RGN_WBWA 1
+#define SMMU_TCR_RGN_WT 2
+#define SMMU_TCR_RGN_WB 3
+
+#define SMMU_TCR_SL0_SHIFT 6
+#define SMMU_TCR_SL0_MASK 0x3
+#define SMMU_TCR_SL0_LVL_2 0
+#define SMMU_TCR_SL0_LVL_1 1
+
+#define SMMU_TCR_T1SZ_SHIFT 16
+#define SMMU_TCR_T0SZ_SHIFT 0
+#define SMMU_TCR_SZ_MASK 0xf
+
+#define SMMU_TCR2_SEP_SHIFT 15
+#define SMMU_TCR2_SEP_MASK 0x7
+
+#define SMMU_TCR2_PASIZE_SHIFT 0
+#define SMMU_TCR2_PASIZE_MASK 0x7
+
+/* Common definitions for PASize and SEP fields */
+#define SMMU_TCR2_ADDR_32 0
+#define SMMU_TCR2_ADDR_36 1
+#define SMMU_TCR2_ADDR_40 2
+#define SMMU_TCR2_ADDR_42 3
+#define SMMU_TCR2_ADDR_44 4
+#define SMMU_TCR2_ADDR_48 5
+
+#define SMMU_TTBRn_HI_ASID_SHIFT 16
+
+#define SMMU_MAIR_ATTR_SHIFT(n) ((n) << 3)
+#define SMMU_MAIR_ATTR_MASK 0xff
+#define SMMU_MAIR_ATTR_DEVICE 0x04
+#define SMMU_MAIR_ATTR_NC 0x44
+#define SMMU_MAIR_ATTR_WBRWA 0xff
+#define SMMU_MAIR_ATTR_IDX_NC 0
+#define SMMU_MAIR_ATTR_IDX_CACHE 1
+#define SMMU_MAIR_ATTR_IDX_DEV 2
+
+#define SMMU_FSR_MULTI (1 << 31)
+#define SMMU_FSR_SS (1 << 30)
+#define SMMU_FSR_UUT (1 << 8)
+#define SMMU_FSR_ASF (1 << 7)
+#define SMMU_FSR_TLBLKF (1 << 6)
+#define SMMU_FSR_TLBMCF (1 << 5)
+#define SMMU_FSR_EF (1 << 4)
+#define SMMU_FSR_PF (1 << 3)
+#define SMMU_FSR_AFF (1 << 2)
+#define SMMU_FSR_TF (1 << 1)
+
+#define SMMU_FSR_IGN (SMMU_FSR_AFF | SMMU_FSR_ASF | \
+ SMMU_FSR_TLBMCF | SMMU_FSR_TLBLKF)
+#define SMMU_FSR_FAULT (SMMU_FSR_MULTI | SMMU_FSR_SS | \
+ SMMU_FSR_UUT | SMMU_FSR_EF | \
+ SMMU_FSR_PF | SMMU_FSR_TF | \
+ SMMU_FSR_IGN)
+
+#define SMMU_FSYNR0_WNR (1 << 4)
+
+#define smmu_print(dev, lvl, fmt, ...) \
+ printk(lvl "smmu: %s: " fmt, dt_node_full_name(dev->node), ## __VA_ARGS__)
+
+#define smmu_err(dev, fmt, ...) smmu_print(dev, XENLOG_ERR, fmt, ## __VA_ARGS__)
+
+#define smmu_dbg(dev, fmt, ...) \
+ smmu_print(dev, XENLOG_DEBUG, fmt, ## __VA_ARGS__)
+
+#define smmu_info(dev, fmt, ...) \
+ smmu_print(dev, XENLOG_INFO, fmt, ## __VA_ARGS__)
+
+#define smmu_warn(dev, fmt, ...) \
+ smmu_print(dev, XENLOG_WARNING, fmt, ## __VA_ARGS__)
+
+struct arm_smmu_device {
+ const struct dt_device_node *node;
+
+ void __iomem *base;
+ unsigned long size;
+ unsigned long pagesize;
+
+#define SMMU_FEAT_COHERENT_WALK (1 << 0)
+#define SMMU_FEAT_STREAM_MATCH (1 << 1)
+#define SMMU_FEAT_TRANS_S1 (1 << 2)
+#define SMMU_FEAT_TRANS_S2 (1 << 3)
+#define SMMU_FEAT_TRANS_NESTED (1 << 4)
+ u32 features;
+ u32 options;
+ int version;
+
+ u32 num_context_banks;
+ u32 num_s2_context_banks;
+ DECLARE_BITMAP(context_map, SMMU_MAX_CBS);
+ atomic_t irptndx;
+
+ u32 num_mapping_groups;
+ DECLARE_BITMAP(smr_map, SMMU_MAX_SMRS);
+
+ unsigned long input_size;
+ unsigned long s1_output_size;
+ unsigned long s2_output_size;
+
+ u32 num_global_irqs;
+ u32 num_context_irqs;
+ unsigned int *irqs;
+
+ u32 smr_mask_mask;
+ u32 smr_id_mask;
+
+ unsigned long *sids;
+
+ struct list_head list;
+ struct rb_root masters;
+};
+
+struct arm_smmu_smr {
+ u8 idx;
+ u16 mask;
+ u16 id;
+};
+
+#define INVALID_IRPTNDX 0xff
+
+#define SMMU_CB_ASID(cfg) ((cfg)->cbndx)
+#define SMMU_CB_VMID(cfg) ((cfg)->cbndx + 1)
+
+struct arm_smmu_domain_cfg {
+ struct arm_smmu_device *smmu;
+ u8 cbndx;
+ u8 irptndx;
+ u32 cbar;
+ /* Domain associated to this device */
+ struct domain *domain;
+ /* List of master which use this structure */
+ struct list_head masters;
+
+ /* Used to link domain context for a same domain */
+ struct list_head list;
+};
+
+struct arm_smmu_master {
+ const struct dt_device_node *dt_node;
+
+ /*
+ * The following is specific to the master's position in the
+ * SMMU chain.
+ */
+ struct rb_node node;
+ u32 num_streamids;
+ u16 streamids[MAX_MASTER_STREAMIDS];
+ int num_s2crs;
+
+ struct arm_smmu_smr *smrs;
+ struct arm_smmu_domain_cfg *cfg;
+
+ /* Used to link masters in a same domain context */
+ struct list_head list;
+};
+
+static LIST_HEAD(arm_smmu_devices);
+
+struct arm_smmu_domain {
+ spinlock_t lock;
+ struct list_head contexts;
+};
+
+struct arm_smmu_option_prop {
+ u32 opt;
+ const char *prop;
+};
+
+static const struct arm_smmu_option_prop arm_smmu_options [] __initconst =
+{
+ { SMMU_OPT_SECURE_CONFIG_ACCESS, "calxeda,smmu-secure-config-access" },
+ { 0, NULL},
+};
+
+static void __init check_driver_options(struct arm_smmu_device *smmu)
+{
+ int i = 0;
+
+ do {
+ if ( dt_property_read_bool(smmu->node, arm_smmu_options[i].prop) )
+ {
+ smmu->options |= arm_smmu_options[i].opt;
+ smmu_dbg(smmu, "option %s\n", arm_smmu_options[i].prop);
+ }
+ } while ( arm_smmu_options[++i].opt );
+}
+
+static void arm_smmu_context_fault(int irq, void *data,
+ struct cpu_user_regs *regs)
+{
+ u32 fsr, far, fsynr;
+ uint64_t iova;
+ struct arm_smmu_domain_cfg *cfg = data;
+ struct arm_smmu_device *smmu = cfg->smmu;
+ void __iomem *cb_base;
+
+ cb_base = SMMU_CB_BASE(smmu) + SMMU_CB(smmu, cfg->cbndx);
+ fsr = readl_relaxed(cb_base + SMMU_CB_FSR);
+
+ if ( !(fsr & SMMU_FSR_FAULT) )
+ return;
+
+ if ( fsr & SMMU_FSR_IGN )
+ smmu_err(smmu, "Unexpected context fault (fsr 0x%u)\n", fsr);
+
+ fsynr = readl_relaxed(cb_base + SMMU_CB_FSYNR0);
+ far = readl_relaxed(cb_base + SMMU_CB_FAR_LO);
+ iova = far;
+ far = readl_relaxed(cb_base + SMMU_CB_FAR_HI);
+ iova |= ((uint64_t)far << 32);
+
+ smmu_err(smmu, "Unhandled context fault for domain %u\n",
+ cfg->domain->domain_id);
+ smmu_err(smmu, "\tFSR 0x%x, IOVA 0x%"PRIx64", FSYNR 0x%x, CB %d\n",
+ fsr, iova, fsynr, cfg->cbndx);
+
+ /* Clear the faulting FSR */
+ writel(fsr, cb_base + SMMU_CB_FSR);
+
+ /* Terminate any stalled transactions */
+ if ( fsr & SMMU_FSR_SS )
+ writel_relaxed(SMMU_RESUME_TERMINATE, cb_base + SMMU_CB_RESUME);
+}
+
+static void arm_smmu_global_fault(int irq, void *data,
+ struct cpu_user_regs *regs)
+{
+ u32 gfsr, gfsynr0, gfsynr1, gfsynr2;
+ struct arm_smmu_device *smmu = data;
+ void __iomem *gr0_base = SMMU_GR0_NS(smmu);
+
+ gfsr = readl_relaxed(gr0_base + SMMU_GR0_sGFSR);
+ gfsynr0 = readl_relaxed(gr0_base + SMMU_GR0_sGFSYNR0);
+ gfsynr1 = readl_relaxed(gr0_base + SMMU_GR0_sGFSYNR1);
+ gfsynr2 = readl_relaxed(gr0_base + SMMU_GR0_sGFSYNR2);
+
+ if ( !gfsr )
+ return;
+
+ smmu_err(smmu, "Unexpected global fault, this could be serious\n");
+ smmu_err(smmu,
+ "\tGFSR 0x%08x, GFSYNR0 0x%08x, GFSYNR1 0x%08x, GFSYNR2 0x%08x\n",
+ gfsr, gfsynr0, gfsynr1, gfsynr2);
+ writel(gfsr, gr0_base + SMMU_GR0_sGFSR);
+}
+
+static struct arm_smmu_master *
+find_smmu_master(struct arm_smmu_device *smmu,
+ const struct dt_device_node *dev_node)
+{
+ struct rb_node *node = smmu->masters.rb_node;
+
+ while ( node )
+ {
+ struct arm_smmu_master *master;
+
+ master = container_of(node, struct arm_smmu_master, node);
+
+ if ( dev_node < master->dt_node )
+ node = node->rb_left;
+ else if ( dev_node > master->dt_node )
+ node = node->rb_right;
+ else
+ return master;
+ }
+
+ return NULL;
+}
+
+static __init int insert_smmu_master(struct arm_smmu_device *smmu,
+ struct arm_smmu_master *master)
+{
+ struct rb_node **new, *parent;
+
+ new = &smmu->masters.rb_node;
+ parent = NULL;
+ while ( *new )
+ {
+ struct arm_smmu_master *this;
+
+ this = container_of(*new, struct arm_smmu_master, node);
+
+ parent = *new;
+ if ( master->dt_node < this->dt_node )
+ new = &((*new)->rb_left);
+ else if (master->dt_node > this->dt_node)
+ new = &((*new)->rb_right);
+ else
+ return -EEXIST;
+ }
+
+ rb_link_node(&master->node, parent, new);
+ rb_insert_color(&master->node, &smmu->masters);
+ return 0;
+}
+
+static __init int register_smmu_master(struct arm_smmu_device *smmu,
+ struct dt_phandle_args *masterspec)
+{
+ int i, sid;
+ struct arm_smmu_master *master;
+ int rc = 0;
+
+ smmu_dbg(smmu, "Try to add master %s\n", masterspec->np->name);
+
+ master = find_smmu_master(smmu, masterspec->np);
+ if ( master )
+ {
+ smmu_err(smmu,
+ "rejecting multiple registrations for master device %s\n",
+ masterspec->np->name);
+ return -EBUSY;
+ }
+
+ if ( masterspec->args_count > MAX_MASTER_STREAMIDS )
+ {
+ smmu_err(smmu,
+ "reached maximum number (%d) of stream IDs for master device %s\n",
+ MAX_MASTER_STREAMIDS, masterspec->np->name);
+ return -ENOSPC;
+ }
+
+ master = xzalloc(struct arm_smmu_master);
+ if ( !master )
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&master->list);
+ master->dt_node = masterspec->np;
+ master->num_streamids = masterspec->args_count;
+
+ dt_device_set_protected(masterspec->np);
+
+ for ( i = 0; i < master->num_streamids; ++i )
+ {
+ sid = masterspec->args[i];
+ if ( test_and_set_bit(sid, smmu->sids) )
+ {
+ smmu_err(smmu, "duplicate stream ID (%d)\n", sid);
+ xfree(master);
+ return -EEXIST;
+ }
+ master->streamids[i] = masterspec->args[i];
+ }
+
+ rc = insert_smmu_master(smmu, master);
+ /* Insertion should never fail */
+ ASSERT(rc == 0);
+
+ return 0;
+}
+
+static int __arm_smmu_alloc_bitmap(unsigned long *map, int start, int end)
+{
+ int idx;
+
+ do
+ {
+ idx = find_next_zero_bit(map, end, start);
+ if ( idx == end )
+ return -ENOSPC;
+ } while ( test_and_set_bit(idx, map) );
+
+ return idx;
+}
+
+static void __arm_smmu_free_bitmap(unsigned long *map, int idx)
+{
+ clear_bit(idx, map);
+}
+
+static void arm_smmu_tlb_sync(struct arm_smmu_device *smmu)
+{
+ int count = 0;
+ void __iomem *gr0_base = SMMU_GR0(smmu);
+
+ writel_relaxed(0, gr0_base + SMMU_GR0_sTLBGSYNC);
+ while ( readl_relaxed(gr0_base + SMMU_GR0_sTLBGSTATUS) &
+ SMMU_sTLBGSTATUS_GSACTIVE )
+ {
+ cpu_relax();
+ if ( ++count == SMMU_TLB_LOOP_TIMEOUT )
+ {
+ smmu_err(smmu, "TLB sync timed out -- SMMU may be deadlocked\n");
+ return;
+ }
+ udelay(1);
+ }
+}
+
+static void arm_smmu_tlb_inv_context(struct arm_smmu_domain_cfg *cfg)
+{
+ struct arm_smmu_device *smmu = cfg->smmu;
+ void __iomem *base = SMMU_GR0(smmu);
+
+ writel_relaxed(SMMU_CB_VMID(cfg),
+ base + SMMU_GR0_TLBIVMID);
+
+ arm_smmu_tlb_sync(smmu);
+}
+
+static void arm_smmu_iotlb_flush_all(struct domain *d)
+{
+ struct arm_smmu_domain *smmu_domain = domain_hvm_iommu(d)->arch.priv;
+ struct arm_smmu_domain_cfg *cfg;
+
+ spin_lock(&smmu_domain->lock);
+ list_for_each_entry(cfg, &smmu_domain->contexts, list)
+ arm_smmu_tlb_inv_context(cfg);
+ spin_unlock(&smmu_domain->lock);
+}
+
+static void arm_smmu_iotlb_flush(struct domain *d, unsigned long gfn,
+ unsigned int page_count)
+{
+ /* ARM SMMU v1 doesn't have flush by VMA and VMID */
+ arm_smmu_iotlb_flush_all(d);
+}
+
+static int determine_smr_mask(struct arm_smmu_device *smmu,
+ struct arm_smmu_master *master,
+ struct arm_smmu_smr *smr, int start, int order)
+{
+ u16 i, zero_bits_mask, one_bits_mask, const_mask;
+ int nr;
+
+ nr = 1 << order;
+
+ if ( nr == 1 )
+ {
+ /* no mask, use streamid to match and be done with it */
+ smr->mask = 0;
+ smr->id = master->streamids[start];
+ return 0;
+ }
+
+ zero_bits_mask = 0;
+ one_bits_mask = 0xffff;
+ for ( i = start; i < start + nr; i++)
+ {
+ zero_bits_mask |= master->streamids[i]; /* const 0 bits */
+ one_bits_mask &= master->streamids[i]; /* const 1 bits */
+ }
+ zero_bits_mask = ~zero_bits_mask;
+
+ /* bits having constant values (either 0 or 1) */
+ const_mask = zero_bits_mask | one_bits_mask;
+
+ i = hweight16(~const_mask);
+ if ( (1 << i) == nr )
+ {
+ smr->mask = ~const_mask;
+ smr->id = one_bits_mask;
+ }
+ else
+ /* no usable mask for this set of streamids */
+ return 1;
+
+ if ( ((smr->mask & smmu->smr_mask_mask) != smr->mask) ||
+ ((smr->id & smmu->smr_id_mask) != smr->id) )
+ /* insufficient number of mask/id bits */
+ return 1;
+
+ return 0;
+}
+
+static int determine_smr_mapping(struct arm_smmu_device *smmu,
+ struct arm_smmu_master *master,
+ struct arm_smmu_smr *smrs, int max_smrs)
+{
+ int nr_sid, nr, i, bit, start;
+
+ /*
+ * This function is called only once -- when a master is added
+ * to a domain. If master->num_s2crs != 0 then this master
+ * was already added to a domain.
+ */
+ BUG_ON(master->num_s2crs);
+
+ start = nr = 0;
+ nr_sid = master->num_streamids;
+ do
+ {
+ /*
+ * largest power-of-2 number of streamids for which to
+ * determine a usable mask/id pair for stream matching
+ */
+ bit = fls(nr_sid);
+ if (!bit)
+ return 0;
+
+ /*
+ * iterate over power-of-2 numbers to determine
+ * largest possible mask/id pair for stream matching
+ * of next 2**i streamids
+ */
+ for ( i = bit - 1; i >= 0; i-- )
+ {
+ if( !determine_smr_mask(smmu, master,
+ &smrs[master->num_s2crs],
+ start, i))
+ break;
+ }
+
+ if ( i < 0 )
+ goto out;
+
+ nr = 1 << i;
+ nr_sid -= nr;
+ start += nr;
+ master->num_s2crs++;
+ } while ( master->num_s2crs <= max_smrs );
+
+out:
+ if ( nr_sid )
+ {
+ /* not enough mapping groups available */
+ master->num_s2crs = 0;
+ return -ENOSPC;
+ }
+
+ return 0;
+}
+
+static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu,
+ struct arm_smmu_master *master)
+{
+ int i, max_smrs, ret;
+ struct arm_smmu_smr *smrs;
+ void __iomem *gr0_base = SMMU_GR0(smmu);
+
+ if ( !(smmu->features & SMMU_FEAT_STREAM_MATCH) )
+ return 0;
+
+ if ( master->smrs )
+ return -EEXIST;
+
+ max_smrs = min(smmu->num_mapping_groups, master->num_streamids);
+ smrs = xmalloc_array(struct arm_smmu_smr, max_smrs);
+ if ( !smrs )
+ {
+ smmu_err(smmu, "failed to allocated %d SMRs for master %s\n",
+ max_smrs, dt_node_name(master->dt_node));
+ return -ENOMEM;
+ }
+
+ ret = determine_smr_mapping(smmu, master, smrs, max_smrs);
+ if ( ret )
+ goto err_free_smrs;
+
+ /* Allocate the SMRs on the root SMMU */
+ for ( i = 0; i < master->num_s2crs; ++i )
+ {
+ int idx = __arm_smmu_alloc_bitmap(smmu->smr_map, 0,
+ smmu->num_mapping_groups);
+ if ( idx < 0 )
+ {
+ smmu_err(smmu, "failed to allocate free SMR\n");
+ goto err_free_bitmap;
+ }
+ smrs[i].idx = idx;
+ }
+
+ /* It worked! Now, poke the actual hardware */
+ for ( i = 0; i < master->num_s2crs; ++i )
+ {
+ u32 reg = SMMU_SMR_VALID | smrs[i].id << SMMU_SMR_ID_SHIFT |
+ smrs[i].mask << SMMU_SMR_MASK_SHIFT;
+ smmu_dbg(smmu, "SMR%d: 0x%x\n", smrs[i].idx, reg);
+ writel_relaxed(reg, gr0_base + SMMU_GR0_SMR(smrs[i].idx));
+ }
+
+ master->smrs = smrs;
+ return 0;
+
+err_free_bitmap:
+ while (--i >= 0)
+ __arm_smmu_free_bitmap(smmu->smr_map, smrs[i].idx);
+ master->num_s2crs = 0;
+err_free_smrs:
+ xfree(smrs);
+ return -ENOSPC;
+}
+
+/* Forward declaration */
+static void arm_smmu_destroy_domain_context(struct arm_smmu_domain_cfg *cfg);
+
+static int arm_smmu_domain_add_master(struct domain *d,
+ struct arm_smmu_domain_cfg *cfg,
+ struct arm_smmu_master *master)
+{
+ int i, ret;
+ struct arm_smmu_device *smmu = cfg->smmu;
+ void __iomem *gr0_base = SMMU_GR0(smmu);
+ struct arm_smmu_smr *smrs = master->smrs;
+
+ if ( master->cfg )
+ return -EBUSY;
+
+ ret = arm_smmu_master_configure_smrs(smmu, master);
+ if ( ret )
+ return ret;
+
+ /* Now we're at the root, time to point at our context bank */
+ if ( !master->num_s2crs )
+ master->num_s2crs = master->num_streamids;
+
+ for ( i = 0; i < master->num_s2crs; ++i )
+ {
+ u32 idx, s2cr;
+
+ idx = smrs ? smrs[i].idx : master->streamids[i];
+ s2cr = (SMMU_S2CR_TYPE_TRANS << SMMU_S2CR_TYPE_SHIFT) |
+ (cfg->cbndx << SMMU_S2CR_CBNDX_SHIFT);
+ smmu_dbg(smmu, "S2CR%d: 0x%x\n", idx, s2cr);
+ writel_relaxed(s2cr, gr0_base + SMMU_GR0_S2CR(idx));
+ }
+
+ master->cfg = cfg;
+ list_add(&master->list, &cfg->masters);
+
+ return 0;
+}
+
+static void arm_smmu_domain_remove_master(struct arm_smmu_master *master)
+{
+ int i;
+ struct arm_smmu_domain_cfg *cfg = master->cfg;
+ struct arm_smmu_device *smmu = cfg->smmu;
+ void __iomem *gr0_base = SMMU_GR0(smmu);
+ struct arm_smmu_smr *smrs = master->smrs;
+
+ /*
+ * We *must* clear the S2CR first, because freeing the SMR means
+ * that it can be reallocated immediately
+ */
+ for ( i = 0; i < master->num_streamids; ++i )
+ {
+ u16 sid = master->streamids[i];
+ writel_relaxed(SMMU_S2CR_TYPE_FAULT,
+ gr0_base + SMMU_GR0_S2CR(sid));
+ }
+
+ /* Invalidate the SMRs before freeing back to the allocator */
+ for (i = 0; i < master->num_s2crs; ++i) {
+ u8 idx = smrs[i].idx;
+ writel_relaxed(~SMMU_SMR_VALID, gr0_base + SMMU_GR0_SMR(idx));
+ __arm_smmu_free_bitmap(smmu->smr_map, idx);
+ }
+
+ master->smrs = NULL;
+ master->num_s2crs = 0;
+ xfree(smrs);
+
+ master->cfg = NULL;
+ list_del(&master->list);
+ INIT_LIST_HEAD(&master->list);
+}
+
+static void arm_smmu_init_context_bank(struct arm_smmu_domain_cfg *cfg)
+{
+ u32 reg;
+ struct arm_smmu_device *smmu = cfg->smmu;
+ void __iomem *cb_base, *gr1_base;
+ paddr_t p2maddr;
+
+ ASSERT(cfg->domain != NULL);
+ p2maddr = page_to_maddr(cfg->domain->arch.p2m.root);
+
+ gr1_base = SMMU_GR1(smmu);
+ cb_base = SMMU_CB_BASE(smmu) + SMMU_CB(smmu, cfg->cbndx);
+
+ /* CBAR */
+ reg = cfg->cbar;
+ if ( smmu->version == 1 )
+ reg |= cfg->irptndx << SMMU_CBAR_IRPTNDX_SHIFT;
+
+ reg |= SMMU_CB_VMID(cfg) << SMMU_CBAR_VMID_SHIFT;
+ writel_relaxed(reg, gr1_base + SMMU_GR1_CBAR(cfg->cbndx));
+
+ if ( smmu->version > 1 )
+ {
+ /* CBA2R */
+#ifdef CONFIG_ARM_64
+ reg = SMMU_CBA2R_RW64_64BIT;
+#else
+ reg = SMMU_CBA2R_RW64_32BIT;
+#endif
+ writel_relaxed(reg, gr1_base + SMMU_GR1_CBA2R(cfg->cbndx));
+ }
+
+ /* TTBR0 */
+ reg = (p2maddr & ((1ULL << 32) - 1));
+ writel_relaxed(reg, cb_base + SMMU_CB_TTBR0_LO);
+ reg = (p2maddr >> 32);
+ writel_relaxed(reg, cb_base + SMMU_CB_TTBR0_HI);
+
+ /*
+ * TCR
+ * We use long descriptor, with inner-shareable WBWA tables in TTBR0.
+ */
+ if ( smmu->version > 1 )
+ {
+ /* 4K Page Table */
+ if ( PAGE_SIZE == PAGE_SIZE_4K )
+ reg = SMMU_TCR_TG0_4K;
+ else
+ reg = SMMU_TCR_TG0_64K;
+
+ switch ( smmu->s2_output_size ) {
+ case 32:
+ reg |= (SMMU_TCR2_ADDR_32 << SMMU_TCR_PASIZE_SHIFT);
+ break;
+ case 36:
+ reg |= (SMMU_TCR2_ADDR_36 << SMMU_TCR_PASIZE_SHIFT);
+ break;
+ case 40:
+ reg |= (SMMU_TCR2_ADDR_40 << SMMU_TCR_PASIZE_SHIFT);
+ break;
+ case 42:
+ reg |= (SMMU_TCR2_ADDR_42 << SMMU_TCR_PASIZE_SHIFT);
+ break;
+ case 44:
+ reg |= (SMMU_TCR2_ADDR_44 << SMMU_TCR_PASIZE_SHIFT);
+ break;
+ case 48:
+ reg |= (SMMU_TCR2_ADDR_48 << SMMU_TCR_PASIZE_SHIFT);
+ break;
+ }
+ }
+ else
+ reg = 0;
+
+ /* The attribute to walk the page table should be the same as VTCR_EL2 */
+ reg |= SMMU_TCR_EAE |
+ (SMMU_TCR_SH_IS << SMMU_TCR_SH0_SHIFT) |
+ (SMMU_TCR_RGN_WBWA << SMMU_TCR_ORGN0_SHIFT) |
+ (SMMU_TCR_RGN_WBWA << SMMU_TCR_IRGN0_SHIFT) |
+ (SMMU_TCR_SL0_LVL_1 << SMMU_TCR_SL0_SHIFT) |
+ /* T0SZ=(1)100 = -8 ( 32 -(-8) = 40 bit physical addresses ) */
+ (0x18 << SMMU_TCR_T0SZ_SHIFT);
+ writel_relaxed(reg, cb_base + SMMU_CB_TCR);
+
+ /* SCTLR */
+ reg = SMMU_SCTLR_CFCFG |
+ SMMU_SCTLR_CFIE |
+ SMMU_SCTLR_CFRE |
+ SMMU_SCTLR_M |
+ SMMU_SCTLR_EAE_SBOP;
+
+ writel_relaxed(reg, cb_base + SMMU_CB_SCTLR);
+}
+
+static struct arm_smmu_domain_cfg *
+arm_smmu_alloc_domain_context(struct domain *d,
+ struct arm_smmu_device *smmu)
+{
+ unsigned int irq;
+ int ret, start;
+ struct arm_smmu_domain_cfg *cfg;
+ struct arm_smmu_domain *smmu_domain = domain_hvm_iommu(d)->arch.priv;
+
+ ASSERT(spin_is_locked(&smmu_domain->lock));
+
+ cfg = xzalloc(struct arm_smmu_domain_cfg);
+ if ( !cfg )
+ return NULL;
+
+ /* Master already initialized to another domain ... */
+ if ( cfg->domain != NULL )
+ goto out_free_mem;
+
+ cfg->cbar = SMMU_CBAR_TYPE_S2_TRANS;
+ start = 0;
+
+ ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
+ smmu->num_context_banks);
+ if ( ret < 0 )
+ goto out_free_mem;
+
+ cfg->cbndx = ret;
+ if ( smmu->version == 1 )
+ {
+ cfg->irptndx = atomic_inc_return(&smmu->irptndx);
+ cfg->irptndx %= smmu->num_context_irqs;
+ }
+ else
+ cfg->irptndx = cfg->cbndx;
+
+ irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
+ ret = request_irq(irq, IRQF_SHARED, arm_smmu_context_fault,
+ "arm-smmu-context-fault", cfg);
+ if ( ret )
+ {
+ smmu_err(smmu, "failed to request context IRQ %d (%u)\n",
+ cfg->irptndx, irq);
+ cfg->irptndx = INVALID_IRPTNDX;
+ goto out_free_context;
+ }
+
+ cfg->domain = d;
+ cfg->smmu = smmu;
+ if ( smmu->features & SMMU_FEAT_COHERENT_WALK )
+ iommu_set_feature(d, IOMMU_FEAT_COHERENT_WALK);
+
+ arm_smmu_init_context_bank(cfg);
+ list_add(&cfg->list, &smmu_domain->contexts);
+ INIT_LIST_HEAD(&cfg->masters);
+
+ return cfg;
+
+out_free_context:
+ __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
+out_free_mem:
+ xfree(cfg);
+
+ return NULL;
+}
+
+static void arm_smmu_destroy_domain_context(struct arm_smmu_domain_cfg *cfg)
+{
+ struct domain *d = cfg->domain;
+ struct arm_smmu_domain *smmu_domain = domain_hvm_iommu(d)->arch.priv;
+ struct arm_smmu_device *smmu = cfg->smmu;
+ void __iomem *cb_base;
+ unsigned int irq;
+
+ ASSERT(spin_is_locked(&smmu_domain->lock));
+ BUG_ON(!list_empty(&cfg->masters));
+
+ /* Disable the context bank and nuke the TLB before freeing it */
+ cb_base = SMMU_CB_BASE(smmu) + SMMU_CB(smmu, cfg->cbndx);
+ writel_relaxed(0, cb_base + SMMU_CB_SCTLR);
+ arm_smmu_tlb_inv_context(cfg);
+
+ if ( cfg->irptndx != INVALID_IRPTNDX )
+ {
+ irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
+ release_irq(irq, cfg);
+ }
+
+ __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
+ list_del(&cfg->list);
+ xfree(cfg);
+}
+
+static struct arm_smmu_device *
+arm_smmu_find_smmu_by_dev(const struct dt_device_node *dev)
+{
+ struct arm_smmu_device *smmu;
+ struct arm_smmu_master *master = NULL;
+
+ list_for_each_entry( smmu, &arm_smmu_devices, list )
+ {
+ master = find_smmu_master(smmu, dev);
+ if ( master )
+ break;
+ }
+
+ if ( !master )
+ return NULL;
+
+ return smmu;
+}
+
+static int arm_smmu_attach_dev(struct domain *d,
+ const struct dt_device_node *dev)
+{
+ struct arm_smmu_device *smmu = arm_smmu_find_smmu_by_dev(dev);
+ struct arm_smmu_master *master;
+ struct arm_smmu_domain *smmu_domain = domain_hvm_iommu(d)->arch.priv;
+ struct arm_smmu_domain_cfg *cfg = NULL;
+ struct arm_smmu_domain_cfg *curr;
+ int ret;
+
+ printk(XENLOG_DEBUG "arm-smmu: attach %s to domain %d\n",
+ dt_node_full_name(dev), d->domain_id);
+
+ if ( !smmu )
+ {
+ printk(XENLOG_ERR "%s: cannot attach to SMMU, is it on the same bus?\n",
+ dt_node_full_name(dev));
+ return -ENODEV;
+ }
+
+ master = find_smmu_master(smmu, dev);
+ BUG_ON(master == NULL);
+
+ /* Check if the device is already assigned to someone */
+ if ( master->cfg )
+ return -EBUSY;
+
+ spin_lock(&smmu_domain->lock);
+ list_for_each_entry( curr, &smmu_domain->contexts, list )
+ {
+ if ( curr->smmu == smmu )
+ {
+ cfg = curr;
+ break;
+ }
+ }
+
+ if ( !cfg )
+ {
+ cfg = arm_smmu_alloc_domain_context(d, smmu);
+ if ( !cfg )
+ {
+ smmu_err(smmu, "unable to allocate context for domain %u\n",
+ d->domain_id);
+ spin_unlock(&smmu_domain->lock);
+ return -ENOMEM;
+ }
+ }
+ spin_unlock(&smmu_domain->lock);
+
+ ret = arm_smmu_domain_add_master(d, cfg, master);
+ if ( ret )
+ {
+ spin_lock(&smmu_domain->lock);
+ if ( list_empty(&cfg->masters) )
+ arm_smmu_destroy_domain_context(cfg);
+ spin_unlock(&smmu_domain->lock);
+ }
+
+ return ret;
+}
+
+static int arm_smmu_detach_dev(struct domain *d,
+ const struct dt_device_node *dev)
+{
+ struct arm_smmu_domain *smmu_domain = domain_hvm_iommu(d)->arch.priv;
+ struct arm_smmu_master *master;
+ struct arm_smmu_device *smmu = arm_smmu_find_smmu_by_dev(dev);
+ struct arm_smmu_domain_cfg *cfg;
+
+ printk(XENLOG_DEBUG "arm-smmu: detach %s to domain %d\n",
+ dt_node_full_name(dev), d->domain_id);
+
+ if ( !smmu )
+ {
+ printk(XENLOG_ERR "%s: cannot find the SMMU, is it on the same bus?\n",
+ dt_node_full_name(dev));
+ return -ENODEV;
+ }
+
+ master = find_smmu_master(smmu, dev);
+ BUG_ON(master == NULL);
+
+ cfg = master->cfg;
+
+ /* Sanity check to avoid removing a device that doesn't belong to
+ * the domain
+ */
+ if ( !cfg || cfg->domain != d )
+ {
+ printk(XENLOG_ERR "%s: was not attach to domain %d\n",
+ dt_node_full_name(dev), d->domain_id);
+ return -ESRCH;
+ }
+
+ arm_smmu_domain_remove_master(master);
+
+ spin_lock(&smmu_domain->lock);
+ if ( list_empty(&cfg->masters) )
+ arm_smmu_destroy_domain_context(cfg);
+ spin_unlock(&smmu_domain->lock);
+
+ return 0;
+}
+
+static int arm_smmu_reassign_dt_dev(struct domain *s, struct domain *t,
+ const struct dt_device_node *dev)
+{
+ int ret = 0;
+
+ /* Don't allow remapping on other domain than hwdom */
+ if ( t != hardware_domain )
+ return -EPERM;
+
+ if ( t == s )
+ return 0;
+
+ ret = arm_smmu_detach_dev(s, dev);
+ if ( ret )
+ return ret;
+
+ ret = arm_smmu_attach_dev(t, dev);
+
+ return ret;
+}
+
+static __init int arm_smmu_id_size_to_bits(int size)
+{
+ switch ( size )
+ {
+ case 0:
+ return 32;
+ case 1:
+ return 36;
+ case 2:
+ return 40;
+ case 3:
+ return 42;
+ case 4:
+ return 44;
+ case 5:
+ default:
+ return 48;
+ }
+}
+
+static __init int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
+{
+ unsigned long size;
+ void __iomem *gr0_base = SMMU_GR0(smmu);
+ u32 id;
+
+ smmu_info(smmu, "probing hardware configuration...\n");
+
+ /*
+ * Primecell ID
+ */
+ id = readl_relaxed(gr0_base + SMMU_GR0_PIDR2);
+ smmu->version = ((id >> SMMU_PIDR2_ARCH_SHIFT) & SMMU_PIDR2_ARCH_MASK) + 1;
+ smmu_info(smmu, "SMMUv%d with:\n", smmu->version);
+
+ /* ID0 */
+ id = readl_relaxed(gr0_base + SMMU_GR0_ID0);
+#ifndef CONFIG_ARM_64
+ if ( ((id >> SMMU_ID0_PTFS_SHIFT) & SMMU_ID0_PTFS_MASK) ==
+ SMMU_ID0_PTFS_V8_ONLY )
+ {
+ smmu_err(smmu, "\tno v7 descriptor support!\n");
+ return -ENODEV;
+ }
+#endif
+ if ( id & SMMU_ID0_S1TS )
+ {
+ smmu->features |= SMMU_FEAT_TRANS_S1;
+ smmu_info(smmu, "\tstage 1 translation\n");
+ }
+
+ if ( id & SMMU_ID0_S2TS )
+ {
+ smmu->features |= SMMU_FEAT_TRANS_S2;
+ smmu_info(smmu, "\tstage 2 translation\n");
+ }
+
+ if ( id & SMMU_ID0_NTS )
+ {
+ smmu->features |= SMMU_FEAT_TRANS_NESTED;
+ smmu_info(smmu, "\tnested translation\n");
+ }
+
+ if ( !(smmu->features &
+ (SMMU_FEAT_TRANS_S1 | SMMU_FEAT_TRANS_S2 |
+ SMMU_FEAT_TRANS_NESTED)) )
+ {
+ smmu_err(smmu, "\tno translation support!\n");
+ return -ENODEV;
+ }
+
+ /* We need at least support for Stage 2 */
+ if ( !(smmu->features & SMMU_FEAT_TRANS_S2) )
+ {
+ smmu_err(smmu, "\tno stage 2 translation!\n");
+ return -ENODEV;
+ }
+
+ if ( id & SMMU_ID0_CTTW )
+ {
+ smmu->features |= SMMU_FEAT_COHERENT_WALK;
+ smmu_info(smmu, "\tcoherent table walk\n");
+ }
+
+ if ( id & SMMU_ID0_SMS )
+ {
+ u32 smr, sid, mask;
+
+ smmu->features |= SMMU_FEAT_STREAM_MATCH;
+ smmu->num_mapping_groups = (id >> SMMU_ID0_NUMSMRG_SHIFT) &
+ SMMU_ID0_NUMSMRG_MASK;
+ if ( smmu->num_mapping_groups == 0 )
+ {
+ smmu_err(smmu,
+ "stream-matching supported, but no SMRs present!\n");
+ return -ENODEV;
+ }
+
+ smr = SMMU_SMR_MASK_MASK << SMMU_SMR_MASK_SHIFT;
+ smr |= (SMMU_SMR_ID_MASK << SMMU_SMR_ID_SHIFT);
+ writel_relaxed(smr, gr0_base + SMMU_GR0_SMR(0));
+ smr = readl_relaxed(gr0_base + SMMU_GR0_SMR(0));
+
+ mask = (smr >> SMMU_SMR_MASK_SHIFT) & SMMU_SMR_MASK_MASK;
+ sid = (smr >> SMMU_SMR_ID_SHIFT) & SMMU_SMR_ID_MASK;
+ if ( (mask & sid) != sid )
+ {
+ smmu_err(smmu,
+ "SMR mask bits (0x%x) insufficient for ID field (0x%x)\n",
+ mask, sid);
+ return -ENODEV;
+ }
+ smmu->smr_mask_mask = mask;
+ smmu->smr_id_mask = sid;
+
+ smmu_info(smmu,
+ "\tstream matching with %u register groups, mask 0x%x\n",
+ smmu->num_mapping_groups, mask);
+ }
+
+ /* ID1 */
+ id = readl_relaxed(gr0_base + SMMU_GR0_ID1);
+ smmu->pagesize = (id & SMMU_ID1_PAGESIZE) ? PAGE_SIZE_64K : PAGE_SIZE_4K;
+
+ /* Check for size mismatch of SMMU address space from mapped region */
+ size = 1 << (((id >> SMMU_ID1_NUMPAGENDXB_SHIFT) &
+ SMMU_ID1_NUMPAGENDXB_MASK) + 1);
+ size *= (smmu->pagesize << 1);
+ if ( smmu->size != size )
+ smmu_warn(smmu, "SMMU address space size (0x%lx) differs "
+ "from mapped region size (0x%lx)!\n", size, smmu->size);
+
+ smmu->num_s2_context_banks = (id >> SMMU_ID1_NUMS2CB_SHIFT) &
+ SMMU_ID1_NUMS2CB_MASK;
+ smmu->num_context_banks = (id >> SMMU_ID1_NUMCB_SHIFT) &
+ SMMU_ID1_NUMCB_MASK;
+ if ( smmu->num_s2_context_banks > smmu->num_context_banks )
+ {
+ smmu_err(smmu, "impossible number of S2 context banks!\n");
+ return -ENODEV;
+ }
+ smmu_info(smmu, "\t%u context banks (%u stage-2 only)\n",
+ smmu->num_context_banks, smmu->num_s2_context_banks);
+
+ /* ID2 */
+ id = readl_relaxed(gr0_base + SMMU_GR0_ID2);
+ size = arm_smmu_id_size_to_bits((id >> SMMU_ID2_IAS_SHIFT) &
+ SMMU_ID2_IAS_MASK);
+
+ /*
+ * Stage-1 output limited by stage-2 input size due to VTCR_EL2
+ * setup (see setup_virt_paging)
+ */
+ /* Current maximum output size of 40 bits */
+ smmu->s1_output_size = min(40UL, size);
+
+ /* The stage-2 output mask is also applied for bypass */
+ size = arm_smmu_id_size_to_bits((id >> SMMU_ID2_OAS_SHIFT) &
+ SMMU_ID2_OAS_MASK);
+ smmu->s2_output_size = min((unsigned long)PADDR_BITS, size);
+
+ if ( smmu->version == 1 )
+ smmu->input_size = 32;
+ else
+ {
+#ifdef CONFIG_ARM_64
+ size = (id >> SMMU_ID2_UBS_SHIFT) & SMMU_ID2_UBS_MASK;
+ size = min(39, arm_smmu_id_size_to_bits(size));
+#else
+ size = 32;
+#endif
+ smmu->input_size = size;
+
+ if ( (PAGE_SIZE == PAGE_SIZE_4K && !(id & SMMU_ID2_PTFS_4K) ) ||
+ (PAGE_SIZE == PAGE_SIZE_64K && !(id & SMMU_ID2_PTFS_64K)) ||
+ (PAGE_SIZE != PAGE_SIZE_4K && PAGE_SIZE != PAGE_SIZE_64K) )
+ {
+ smmu_err(smmu, "CPU page size 0x%lx unsupported\n",
+ PAGE_SIZE);
+ return -ENODEV;
+ }
+ }
+
+ smmu_info(smmu, "\t%lu-bit VA, %lu-bit IPA, %lu-bit PA\n",
+ smmu->input_size, smmu->s1_output_size, smmu->s2_output_size);
+ return 0;
+}
+
+static __init void arm_smmu_device_reset(struct arm_smmu_device *smmu)
+{
+ void __iomem *gr0_base = SMMU_GR0(smmu);
+ void __iomem *cb_base;
+ int i = 0;
+ u32 reg;
+
+ smmu_dbg(smmu, "device reset\n");
+
+ /* Clear Global FSR */
+ reg = readl_relaxed(SMMU_GR0_NS(smmu) + SMMU_GR0_sGFSR);
+ writel(reg, SMMU_GR0_NS(smmu) + SMMU_GR0_sGFSR);
+
+ /* Mark all SMRn as invalid and all S2CRn as fault */
+ for ( i = 0; i < smmu->num_mapping_groups; ++i )
+ {
+ writel_relaxed(~SMMU_SMR_VALID, gr0_base + SMMU_GR0_SMR(i));
+ writel_relaxed(SMMU_S2CR_TYPE_FAULT, gr0_base + SMMU_GR0_S2CR(i));
+ }
+
+ /* Make sure all context banks are disabled and clear CB_FSR */
+ for ( i = 0; i < smmu->num_context_banks; ++i )
+ {
+ cb_base = SMMU_CB_BASE(smmu) + SMMU_CB(smmu, i);
+ writel_relaxed(0, cb_base + SMMU_CB_SCTLR);
+ writel_relaxed(SMMU_FSR_FAULT, cb_base + SMMU_CB_FSR);
+ }
+
+ /* Invalidate the TLB, just in case */
+ writel_relaxed(0, gr0_base + SMMU_GR0_STLBIALL);
+ writel_relaxed(0, gr0_base + SMMU_GR0_TLBIALLH);
+ writel_relaxed(0, gr0_base + SMMU_GR0_TLBIALLNSNH);
+
+ reg = readl_relaxed(SMMU_GR0_NS(smmu) + SMMU_GR0_sCR0);
+
+ /* Enable fault reporting */
+ reg |= (SMMU_sCR0_GFRE | SMMU_sCR0_GFIE |
+ SMMU_sCR0_GCFGFRE | SMMU_sCR0_GCFGFIE);
+
+ /* Disable TLB broadcasting. */
+ reg |= (SMMU_sCR0_VMIDPNE | SMMU_sCR0_PTM);
+
+ /* Enable client access, generate a fault if no mapping is found */
+ reg &= ~(SMMU_sCR0_CLIENTPD);
+ reg |= SMMU_sCR0_USFCFG;
+
+ /* Disable forced broadcasting */
+ reg &= ~SMMU_sCR0_FB;
+
+ /* Don't upgrade barriers when client devices are not mapped to
+ * a translation context banks (just here for clarity as Xen policy
+ * is to deny invalid transaction). */
+ reg &= ~(SMMU_sCR0_BSU_MASK << SMMU_sCR0_BSU_SHIFT);
+
+ /* Push the button */
+ arm_smmu_tlb_sync(smmu);
+ writel_relaxed(reg, SMMU_GR0_NS(smmu) + SMMU_GR0_sCR0);
+}
+
+static int arm_smmu_iommu_domain_init(struct domain *d)
+{
+ struct arm_smmu_domain *smmu_domain;
+
+ smmu_domain = xzalloc(struct arm_smmu_domain);
+ if ( !smmu_domain )
+ return -ENOMEM;
+
+ spin_lock_init(&smmu_domain->lock);
+ INIT_LIST_HEAD(&smmu_domain->contexts);
+
+ domain_hvm_iommu(d)->arch.priv = smmu_domain;
+
+ return 0;
+}
+
+static void __hwdom_init arm_smmu_iommu_hwdom_init(struct domain *d)
+{
+}
+
+static void arm_smmu_iommu_domain_teardown(struct domain *d)
+{
+ struct arm_smmu_domain *smmu_domain = domain_hvm_iommu(d)->arch.priv;
+
+ ASSERT(list_empty(&smmu_domain->contexts));
+ xfree(smmu_domain);
+}
+
+static int arm_smmu_map_page(struct domain *d, unsigned long gfn,
+ unsigned long mfn, unsigned int flags)
+{
+ p2m_type_t t;
+
+ /* Grant mappings can be used for DMA requests. The dev_bus_addr returned by
+ * the hypercall is the MFN (not the IPA). For device protected by
+ * an IOMMU, Xen needs to add a 1:1 mapping in the domain p2m to
+ * allow DMA request to work.
+ * This is only valid when the domain is directed mapped. Hence this
+ * function should only be used by gnttab code with gfn == mfn.
+ */
+ BUG_ON(!is_domain_direct_mapped(d));
+ BUG_ON(mfn != gfn);
+
+ /* We only support readable and writable flags */
+ if ( !(flags & (IOMMUF_readable | IOMMUF_writable)) )
+ return -EINVAL;
+
+ t = (flags & IOMMUF_writable) ? p2m_iommu_map_rw : p2m_iommu_map_ro;
+
+ /* The function guest_physmap_add_entry replaces the current mapping
+ * if there is already one...
+ */
+ return guest_physmap_add_entry(d, gfn, mfn, 0, t);
+}
+
+static int arm_smmu_unmap_page(struct domain *d, unsigned long gfn)
+{
+ /* This function should only be used by gnttab code when the domain
+ * is direct mapped
+ */
+ if ( !is_domain_direct_mapped(d) )
+ return -EINVAL;
+
+ guest_physmap_remove_page(d, gfn, gfn, 0);
+
+ return 0;
+}
+
+static const struct iommu_ops arm_smmu_iommu_ops = {
+ .init = arm_smmu_iommu_domain_init,
+ .hwdom_init = arm_smmu_iommu_hwdom_init,
+ .teardown = arm_smmu_iommu_domain_teardown,
+ .iotlb_flush = arm_smmu_iotlb_flush,
+ .iotlb_flush_all = arm_smmu_iotlb_flush_all,
+ .assign_dt_device = arm_smmu_attach_dev,
+ .reassign_dt_device = arm_smmu_reassign_dt_dev,
+ .map_page = arm_smmu_map_page,
+ .unmap_page = arm_smmu_unmap_page,
+};
+
+static int __init smmu_init(struct dt_device_node *dev,
+ const void *data)
+{
+ struct arm_smmu_device *smmu;
+ int res;
+ u64 addr, size;
+ unsigned int num_irqs, i;
+ struct dt_phandle_args masterspec;
+ struct rb_node *node;
+
+ /* Even if the device can't be initialized, we don't want to give
+ * the smmu device to dom0.
+ */
+ dt_device_set_used_by(dev, DOMID_XEN);
+
+ smmu = xzalloc(struct arm_smmu_device);
+ if ( !smmu )
+ {
+ printk(XENLOG_ERR "%s: failed to allocate arm_smmu_device\n",
+ dt_node_full_name(dev));
+ return -ENOMEM;
+ }
+
+ smmu->node = dev;
+ check_driver_options(smmu);
+
+ res = dt_device_get_address(smmu->node, 0, &addr, &size);
+ if ( res )
+ {
+ smmu_err(smmu, "unable to retrieve the base address of the SMMU\n");
+ goto out_err;
+ }
+
+ smmu->base = ioremap_nocache(addr, size);
+ if ( !smmu->base )
+ {
+ smmu_err(smmu, "unable to map the SMMU memory\n");
+ goto out_err;
+ }
+
+ smmu->size = size;
+
+ if ( !dt_property_read_u32(smmu->node, "#global-interrupts",
+ &smmu->num_global_irqs) )
+ {
+ smmu_err(smmu, "missing #global-interrupts\n");
+ goto out_unmap;
+ }
+
+ num_irqs = dt_number_of_irq(smmu->node);
+ if ( num_irqs > smmu->num_global_irqs )
+ smmu->num_context_irqs = num_irqs - smmu->num_global_irqs;
+
+ if ( !smmu->num_context_irqs )
+ {
+ smmu_err(smmu, "found %d interrupts but expected at least %d\n",
+ num_irqs, smmu->num_global_irqs + 1);
+ goto out_unmap;
+ }
+
+ smmu->irqs = xzalloc_array(unsigned int, num_irqs);
+ if ( !smmu->irqs )
+ {
+ smmu_err(smmu, "failed to allocated %d irqs\n", num_irqs);
+ goto out_unmap;
+ }
+
+ for ( i = 0; i < num_irqs; i++ )
+ {
+ res = platform_get_irq(smmu->node, i);
+ if ( res < 0 )
+ {
+ smmu_err(smmu, "failed to get irq index %d\n", i);
+ goto out_free_irqs;
+ }
+ smmu->irqs[i] = res;
+ }
+
+ smmu->sids = xzalloc_array(unsigned long,
+ BITS_TO_LONGS(SMMU_MAX_STREAMIDS));
+ if ( !smmu->sids )
+ {
+ smmu_err(smmu, "failed to allocated bitmap for stream ID tracking\n");
+ goto out_free_masters;
+ }
+
+
+ i = 0;
+ smmu->masters = RB_ROOT;
+ while ( !dt_parse_phandle_with_args(smmu->node, "mmu-masters",
+ "#stream-id-cells", i, &masterspec) )
+ {
+ res = register_smmu_master(smmu, &masterspec);
+ if ( res )
+ {
+ smmu_err(smmu, "failed to add master %s\n",
+ masterspec.np->name);
+ goto out_free_masters;
+ }
+ i++;
+ }
+
+ smmu_info(smmu, "registered %d master devices\n", i);
+
+ res = arm_smmu_device_cfg_probe(smmu);
+ if ( res )
+ {
+ smmu_err(smmu, "failed to probe the SMMU\n");
+ goto out_free_masters;
+ }
+
+ if ( smmu->version > 1 &&
+ smmu->num_context_banks != smmu->num_context_irqs )
+ {
+ smmu_err(smmu,
+ "found only %d context interrupt(s) but %d required\n",
+ smmu->num_context_irqs, smmu->num_context_banks);
+ goto out_free_masters;
+ }
+
+ smmu_dbg(smmu, "register global IRQs handler\n");
+
+ for ( i = 0; i < smmu->num_global_irqs; ++i )
+ {
+ smmu_dbg(smmu, "\t- global IRQ %u\n", smmu->irqs[i]);
+ res = request_irq(smmu->irqs[i], IRQF_SHARED, arm_smmu_global_fault,
+ "arm-smmu global fault", smmu);
+ if ( res )
+ {
+ smmu_err(smmu, "failed to request global IRQ %d (%u)\n",
+ i, smmu->irqs[i]);
+ goto out_release_irqs;
+ }
+ }
+
+ INIT_LIST_HEAD(&smmu->list);
+ list_add(&smmu->list, &arm_smmu_devices);
+
+ arm_smmu_device_reset(smmu);
+
+ iommu_set_ops(&arm_smmu_iommu_ops);
+
+ /* sids field can be freed... */
+ xfree(smmu->sids);
+ smmu->sids = NULL;
+
+ return 0;
+
+out_release_irqs:
+ while (i--)
+ release_irq(smmu->irqs[i], smmu);
+
+out_free_masters:
+ for ( node = rb_first(&smmu->masters); node; node = rb_next(node) )
+ {
+ struct arm_smmu_master *master;
+
+ master = container_of(node, struct arm_smmu_master, node);
+ xfree(master);
+ }
+
+ xfree(smmu->sids);
+
+out_free_irqs:
+ xfree(smmu->irqs);
+
+out_unmap:
+ iounmap(smmu->base);
+
+out_err:
+ xfree(smmu);
+
+ return -ENODEV;
+}
+
+static const char * const smmu_dt_compat[] __initconst =
+{
+ "arm,mmu-400",
+ NULL
+};
+
+DT_DEVICE_START(smmu, "ARM SMMU", DEVICE_IOMMU)
+ .compatible = smmu_dt_compat,
+ .init = smmu_init,
+DT_DEVICE_END
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/drivers/passthrough/device_tree.c b/xen/drivers/passthrough/device_tree.c
new file mode 100644
index 0000000..3e47df5
--- /dev/null
+++ b/xen/drivers/passthrough/device_tree.c
@@ -0,0 +1,108 @@
+/*
+ * Code to passthrough a device tree node to a guest
+ *
+ * TODO: This contains only the necessary code to protected device passed to
+ * dom0. It will need some updates when device passthrough will is added.
+ *
+ * Julien Grall <julien.grall at linaro.org>
+ * Copyright (c) 2014 Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <xen/lib.h>
+#include <xen/sched.h>
+#include <xen/iommu.h>
+#include <xen/device_tree.h>
+
+static spinlock_t dtdevs_lock = SPIN_LOCK_UNLOCKED;
+
+int iommu_assign_dt_device(struct domain *d, struct dt_device_node *dev)
+{
+ int rc = -EBUSY;
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+
+ if ( !iommu_enabled || !hd->platform_ops )
+ return -EINVAL;
+
+ if ( !dt_device_is_protected(dev) )
+ return -EINVAL;
+
+ spin_lock(&dtdevs_lock);
+
+ if ( !list_empty(&dev->domain_list) )
+ goto fail;
+
+ rc = hd->platform_ops->assign_dt_device(d, dev);
+
+ if ( rc )
+ goto fail;
+
+ list_add(&dev->domain_list, &hd->dt_devices);
+ dt_device_set_used_by(dev, d->domain_id);
+
+fail:
+ spin_unlock(&dtdevs_lock);
+
+ return rc;
+}
+
+int iommu_deassign_dt_device(struct domain *d, struct dt_device_node *dev)
+{
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+ int rc;
+
+ if ( !iommu_enabled || !hd->platform_ops )
+ return -EINVAL;
+
+ if ( !dt_device_is_protected(dev) )
+ return -EINVAL;
+
+ spin_lock(&dtdevs_lock);
+
+ rc = hd->platform_ops->reassign_dt_device(d, hardware_domain, dev);
+ if ( rc )
+ goto fail;
+
+ list_del(&dev->domain_list);
+
+ dt_device_set_used_by(dev, hardware_domain->domain_id);
+ list_add(&dev->domain_list, &domain_hvm_iommu(hardware_domain)->dt_devices);
+
+fail:
+ spin_unlock(&dtdevs_lock);
+
+ return rc;
+}
+
+int iommu_dt_domain_init(struct domain *d)
+{
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+
+ INIT_LIST_HEAD(&hd->dt_devices);
+
+ return 0;
+}
+
+void iommu_dt_domain_destroy(struct domain *d)
+{
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+ struct dt_device_node *dev, *_dev;
+ int rc;
+
+ list_for_each_entry_safe(dev, _dev, &hd->dt_devices, domain_list)
+ {
+ rc = iommu_deassign_dt_device(d, dev);
+ if ( rc )
+ dprintk(XENLOG_ERR, "Failed to deassign %s in domain %u\n",
+ dt_node_full_name(dev), d->domain_id);
+ }
+}
diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c
index f64e4ac..ae050df 100644
--- a/xen/drivers/passthrough/io.c
+++ b/xen/drivers/passthrough/io.c
@@ -20,14 +20,123 @@
#include <xen/event.h>
#include <xen/iommu.h>
+#include <xen/cpu.h>
#include <xen/irq.h>
#include <asm/hvm/irq.h>
#include <asm/hvm/iommu.h>
#include <asm/hvm/support.h>
#include <xen/hvm/irq.h>
-#include <xen/tasklet.h>
-static void hvm_dirq_assist(unsigned long _d);
+static DEFINE_PER_CPU(struct list_head, dpci_list);
+
+/*
+ * These two bit states help to safely schedule, deschedule, and wait until
+ * the softirq has finished.
+ *
+ * The semantics behind these two bits is as follow:
+ * - STATE_SCHED - whoever modifies it has to ref-count the domain (->dom).
+ * - STATE_RUN - only softirq is allowed to set and clear it. If it has
+ * been set hvm_dirq_assist will RUN with a saved value of the
+ * 'struct domain' copied from 'pirq_dpci->dom' before STATE_RUN was set.
+ *
+ * The usual states are: STATE_SCHED(set) -> STATE_RUN(set) ->
+ * STATE_SCHED(unset) -> STATE_RUN(unset).
+ *
+ * However the states can also diverge such as: STATE_SCHED(set) ->
+ * STATE_SCHED(unset) -> STATE_RUN(set) -> STATE_RUN(unset). That means
+ * the 'hvm_dirq_assist' never run and that the softirq did not do any
+ * ref-counting.
+ */
+
+enum {
+ STATE_SCHED,
+ STATE_RUN
+};
+
+/*
+ * This can be called multiple times, but the softirq is only raised once.
+ * That is until the STATE_SCHED state has been cleared. The state can be
+ * cleared by: the 'dpci_softirq' (when it has executed 'hvm_dirq_assist'),
+ * or by 'pt_pirq_softirq_reset' (which will try to clear the state before
+ * the softirq had a chance to run).
+ */
+static void raise_softirq_for(struct hvm_pirq_dpci *pirq_dpci)
+{
+ unsigned long flags;
+
+ if ( test_and_set_bit(STATE_SCHED, &pirq_dpci->state) )
+ return;
+
+ get_knownalive_domain(pirq_dpci->dom);
+
+ local_irq_save(flags);
+ list_add_tail(&pirq_dpci->softirq_list, &this_cpu(dpci_list));
+ local_irq_restore(flags);
+
+ raise_softirq(HVM_DPCI_SOFTIRQ);
+}
+
+/*
+ * If we are racing with softirq_dpci (STATE_SCHED) we return
+ * true. Otherwise we return false.
+ *
+ * If it is false, it is the callers responsibility to make sure
+ * that the softirq (with the event_lock dropped) has ran.
+ */
+bool_t pt_pirq_softirq_active(struct hvm_pirq_dpci *pirq_dpci)
+{
+ if ( pirq_dpci->state & ((1 << STATE_RUN) | (1 << STATE_SCHED)) )
+ return 1;
+
+ /*
+ * If in the future we would call 'raise_softirq_for' right away
+ * after 'pt_pirq_softirq_active' we MUST reset the list (otherwise it
+ * might have stale data).
+ */
+ return 0;
+}
+
+/*
+ * Reset the pirq_dpci->dom parameter to NULL.
+ *
+ * This function checks the different states to make sure it can do it
+ * at the right time. If it unschedules the 'hvm_dirq_assist' from running
+ * it also refcounts (which is what the softirq would have done) properly.
+ */
+static void pt_pirq_softirq_reset(struct hvm_pirq_dpci *pirq_dpci)
+{
+ struct domain *d = pirq_dpci->dom;
+
+ ASSERT(spin_is_locked(&d->event_lock));
+
+ switch ( cmpxchg(&pirq_dpci->state, 1 << STATE_SCHED, 0) )
+ {
+ case (1 << STATE_SCHED):
+ /*
+ * We are going to try to de-schedule the softirq before it goes in
+ * STATE_RUN. Whoever clears STATE_SCHED MUST refcount the 'dom'.
+ */
+ put_domain(d);
+ /* fallthrough. */
+ case (1 << STATE_RUN):
+ case (1 << STATE_RUN) | (1 << STATE_SCHED):
+ /*
+ * The reason it is OK to reset 'dom' when STATE_RUN bit is set is due
+ * to a shortcut the 'dpci_softirq' implements. It stashes the 'dom'
+ * in local variable before it sets STATE_RUN - and therefore will not
+ * dereference '->dom' which would crash.
+ */
+ pirq_dpci->dom = NULL;
+ break;
+ }
+ /*
+ * Inhibit 'hvm_dirq_assist' from doing anything useful and at worst
+ * calling 'set_timer' which will blow up (as we have called kill_timer
+ * or never initialized it). Note that we hold the lock that
+ * 'hvm_dirq_assist' could be spinning on.
+ */
+ pirq_dpci->masked = 0;
+}
bool_t pt_irq_need_timer(uint32_t flags)
{
@@ -51,11 +160,8 @@ static int pt_irq_guest_eoi(struct domain *d, struct hvm_pirq_dpci *pirq_dpci,
static void pt_irq_time_out(void *data)
{
struct hvm_pirq_dpci *irq_map = data;
- unsigned int guest_gsi;
- struct hvm_irq_dpci *dpci = NULL;
- struct dev_intx_gsi_link *digl;
- struct hvm_girq_dpci_mapping *girq;
- uint32_t device, intx;
+ const struct hvm_irq_dpci *dpci;
+ const struct dev_intx_gsi_link *digl;
spin_lock(&irq_map->dom->event_lock);
@@ -63,16 +169,16 @@ static void pt_irq_time_out(void *data)
ASSERT(dpci);
list_for_each_entry ( digl, &irq_map->digl_list, list )
{
- guest_gsi = digl->gsi;
+ unsigned int guest_gsi = hvm_pci_intx_gsi(digl->device, digl->intx);
+ const struct hvm_girq_dpci_mapping *girq;
+
list_for_each_entry ( girq, &dpci->girq[guest_gsi], list )
{
struct pirq *pirq = pirq_info(irq_map->dom, girq->machine_gsi);
pirq_dpci(pirq)->flags |= HVM_IRQ_DPCI_EOI_LATCH;
}
- device = digl->device;
- intx = digl->intx;
- hvm_pci_intx_deassert(irq_map->dom, device, intx);
+ hvm_pci_intx_deassert(irq_map->dom, digl->device, digl->intx);
}
pt_pirq_iterate(irq_map->dom, pt_irq_guest_eoi, NULL);
@@ -96,33 +202,29 @@ void free_hvm_irq_dpci(struct hvm_irq_dpci *dpci)
int pt_irq_create_bind(
struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
{
- struct hvm_irq_dpci *hvm_irq_dpci = NULL;
+ struct hvm_irq_dpci *hvm_irq_dpci;
struct hvm_pirq_dpci *pirq_dpci;
struct pirq *info;
- uint32_t guest_gsi;
- uint32_t device, intx, link;
- struct dev_intx_gsi_link *digl;
- struct hvm_girq_dpci_mapping *girq;
int rc, pirq = pt_irq_bind->machine_irq;
if ( pirq < 0 || pirq >= d->nr_pirqs )
return -EINVAL;
+ restart:
spin_lock(&d->event_lock);
hvm_irq_dpci = domain_get_irq_dpci(d);
if ( hvm_irq_dpci == NULL )
{
+ unsigned int i;
+
hvm_irq_dpci = xzalloc(struct hvm_irq_dpci);
if ( hvm_irq_dpci == NULL )
{
spin_unlock(&d->event_lock);
return -ENOMEM;
}
- softirq_tasklet_init(
- &hvm_irq_dpci->dirq_tasklet,
- hvm_dirq_assist, (unsigned long)d);
- for ( int i = 0; i < NR_HVM_IRQS; i++ )
+ for ( i = 0; i < NR_HVM_IRQS; i++ )
INIT_LIST_HEAD(&hvm_irq_dpci->girq[i]);
d->arch.hvm_domain.irq.dpci = hvm_irq_dpci;
@@ -136,7 +238,24 @@ int pt_irq_create_bind(
}
pirq_dpci = pirq_dpci(info);
- if ( pt_irq_bind->irq_type == PT_IRQ_TYPE_MSI )
+ /*
+ * A crude 'while' loop with us dropping the spinlock and giving
+ * the softirq_dpci a chance to run.
+ * We MUST check for this condition as the softirq could be scheduled
+ * and hasn't run yet. Note that this code replaced tasklet_kill which
+ * would have spun forever and would do the same thing (wait to flush out
+ * outstanding hvm_dirq_assist calls.
+ */
+ if ( pt_pirq_softirq_active(pirq_dpci) )
+ {
+ spin_unlock(&d->event_lock);
+ cpu_relax();
+ goto restart;
+ }
+
+ switch ( pt_irq_bind->irq_type )
+ {
+ case PT_IRQ_TYPE_MSI:
{
uint8_t dest, dest_mode;
int dest_vcpu_id;
@@ -147,18 +266,40 @@ int pt_irq_create_bind(
HVM_IRQ_DPCI_GUEST_MSI;
pirq_dpci->gmsi.gvec = pt_irq_bind->u.msi.gvec;
pirq_dpci->gmsi.gflags = pt_irq_bind->u.msi.gflags;
+ /*
+ * 'pt_irq_create_bind' can be called after 'pt_irq_destroy_bind'.
+ * The 'pirq_cleanup_check' which would free the structure is only
+ * called if the event channel for the PIRQ is active. However
+ * OS-es that use event channels usually bind PIRQs to eventds
+ * and unbind them before calling 'pt_irq_destroy_bind' - with the
+ * result that we re-use the 'dpci' structure. This can be
+ * reproduced with unloading and loading the driver for a device.
+ *
+ * As such on every 'pt_irq_create_bind' call we MUST set it.
+ */
+ pirq_dpci->dom = d;
/* bind after hvm_irq_dpci is setup to avoid race with irq handler*/
rc = pirq_guest_bind(d->vcpu[0], info, 0);
if ( rc == 0 && pt_irq_bind->u.msi.gtable )
{
rc = msixtbl_pt_register(d, info, pt_irq_bind->u.msi.gtable);
if ( unlikely(rc) )
+ {
pirq_guest_unbind(d, info);
+ /*
+ * Between 'pirq_guest_bind' and before 'pirq_guest_unbind'
+ * an interrupt can be scheduled. No more of them are going
+ * to be scheduled but we must deal with the one that may be
+ * in the queue.
+ */
+ pt_pirq_softirq_reset(pirq_dpci);
+ }
}
if ( unlikely(rc) )
{
pirq_dpci->gmsi.gflags = 0;
pirq_dpci->gmsi.gvec = 0;
+ pirq_dpci->dom = NULL;
pirq_dpci->flags = 0;
pirq_cleanup_check(info, d);
spin_unlock(&d->event_lock);
@@ -169,15 +310,16 @@ int pt_irq_create_bind(
{
uint32_t mask = HVM_IRQ_DPCI_MACH_MSI | HVM_IRQ_DPCI_GUEST_MSI;
- if ( (pirq_dpci->flags & mask) != mask)
+ if ( (pirq_dpci->flags & mask) != mask )
{
- spin_unlock(&d->event_lock);
- return -EBUSY;
+ spin_unlock(&d->event_lock);
+ return -EBUSY;
}
- /* if pirq is already mapped as vmsi, update the guest data/addr */
+ /* If pirq is already mapped as vmsi, update guest data/addr. */
if ( pirq_dpci->gmsi.gvec != pt_irq_bind->u.msi.gvec ||
- pirq_dpci->gmsi.gflags != pt_irq_bind->u.msi.gflags) {
+ pirq_dpci->gmsi.gflags != pt_irq_bind->u.msi.gflags )
+ {
/* Directly clear pending EOIs before enabling new MSI info. */
pirq_guest_eoi(info);
@@ -185,7 +327,7 @@ int pt_irq_create_bind(
pirq_dpci->gmsi.gflags = pt_irq_bind->u.msi.gflags;
}
}
- /* Caculate dest_vcpu_id for MSI-type pirq migration */
+ /* Calculate dest_vcpu_id for MSI-type pirq migration. */
dest = pirq_dpci->gmsi.gflags & VMSI_DEST_ID_MASK;
dest_mode = !!(pirq_dpci->gmsi.gflags & VMSI_DM_MASK);
dest_vcpu_id = hvm_girq_dest_2_vcpu_id(d, dest, dest_mode);
@@ -193,36 +335,37 @@ int pt_irq_create_bind(
spin_unlock(&d->event_lock);
if ( dest_vcpu_id >= 0 )
hvm_migrate_pirqs(d->vcpu[dest_vcpu_id]);
+ break;
}
- else
- {
- device = pt_irq_bind->u.pci.device;
- intx = pt_irq_bind->u.pci.intx;
- guest_gsi = hvm_pci_intx_gsi(device, intx);
- link = hvm_pci_intx_link(device, intx);
- hvm_irq_dpci->link_cnt[link]++;
- digl = xmalloc(struct dev_intx_gsi_link);
- if ( !digl )
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
+ {
+ unsigned int bus = pt_irq_bind->u.pci.bus;
+ unsigned int device = pt_irq_bind->u.pci.device;
+ unsigned int intx = pt_irq_bind->u.pci.intx;
+ unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx);
+ unsigned int link = hvm_pci_intx_link(device, intx);
+ struct dev_intx_gsi_link *digl = xmalloc(struct dev_intx_gsi_link);
+ struct hvm_girq_dpci_mapping *girq =
+ xmalloc(struct hvm_girq_dpci_mapping);
+
+ if ( !digl || !girq )
{
spin_unlock(&d->event_lock);
- return -ENOMEM;
- }
-
- girq = xmalloc(struct hvm_girq_dpci_mapping);
- if ( !girq )
- {
+ xfree(girq);
xfree(digl);
- spin_unlock(&d->event_lock);
return -ENOMEM;
}
+ hvm_irq_dpci->link_cnt[link]++;
+
+ digl->bus = bus;
digl->device = device;
digl->intx = intx;
- digl->gsi = guest_gsi;
- digl->link = link;
list_add_tail(&digl->list, &pirq_dpci->digl_list);
+ girq->bus = bus;
girq->device = device;
girq->intx = intx;
girq->machine_gsi = pirq;
@@ -233,6 +376,7 @@ int pt_irq_create_bind(
{
unsigned int share;
+ /* MUST be set, as the pirq_dpci can be re-used. */
pirq_dpci->dom = d;
if ( pt_irq_bind->irq_type == PT_IRQ_TYPE_MSI_TRANSLATE )
{
@@ -259,14 +403,18 @@ int pt_irq_create_bind(
{
if ( pt_irq_need_timer(pirq_dpci->flags) )
kill_timer(&pirq_dpci->timer);
+ /*
+ * There is no path for __do_IRQ to schedule softirq as
+ * IRQ_GUEST is not set. As such we can reset 'dom' directly.
+ */
pirq_dpci->dom = NULL;
list_del(&girq->list);
- xfree(girq);
list_del(&digl->list);
hvm_irq_dpci->link_cnt[link]--;
pirq_dpci->flags = 0;
pirq_cleanup_check(info, d);
spin_unlock(&d->event_lock);
+ xfree(girq);
xfree(digl);
return rc;
}
@@ -276,33 +424,50 @@ int pt_irq_create_bind(
if ( iommu_verbose )
dprintk(XENLOG_G_INFO,
- "d%d: bind: m_gsi=%u g_gsi=%u device=%u intx=%u\n",
- d->domain_id, pirq, guest_gsi, device, intx);
+ "d%d: bind: m_gsi=%u g_gsi=%u dev=%02x.%02x.%u intx=%u\n",
+ d->domain_id, pirq, guest_gsi, bus,
+ PCI_SLOT(device), PCI_FUNC(device), intx);
+ break;
+ }
+
+ default:
+ spin_unlock(&d->event_lock);
+ return -EOPNOTSUPP;
}
+
return 0;
}
int pt_irq_destroy_bind(
struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
{
- struct hvm_irq_dpci *hvm_irq_dpci = NULL;
+ struct hvm_irq_dpci *hvm_irq_dpci;
struct hvm_pirq_dpci *pirq_dpci;
- uint32_t machine_gsi, guest_gsi;
- uint32_t device, intx, link;
- struct dev_intx_gsi_link *digl, *tmp;
- struct hvm_girq_dpci_mapping *girq;
+ unsigned int machine_gsi = pt_irq_bind->machine_irq;
struct pirq *pirq;
+ const char *what = NULL;
- machine_gsi = pt_irq_bind->machine_irq;
- device = pt_irq_bind->u.pci.device;
- intx = pt_irq_bind->u.pci.intx;
- guest_gsi = hvm_pci_intx_gsi(device, intx);
- link = hvm_pci_intx_link(device, intx);
+ switch ( pt_irq_bind->irq_type )
+ {
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
+ if ( iommu_verbose )
+ {
+ unsigned int device = pt_irq_bind->u.pci.device;
+ unsigned int intx = pt_irq_bind->u.pci.intx;
- if ( iommu_verbose )
- dprintk(XENLOG_G_INFO,
- "d%d: unbind: m_gsi=%u g_gsi=%u device=%u intx=%u\n",
- d->domain_id, machine_gsi, guest_gsi, device, intx);
+ dprintk(XENLOG_G_INFO,
+ "d%d: unbind: m_gsi=%u g_gsi=%u dev=%02x:%02x.%u intx=%u\n",
+ d->domain_id, machine_gsi, hvm_pci_intx_gsi(device, intx),
+ pt_irq_bind->u.pci.bus,
+ PCI_SLOT(device), PCI_FUNC(device), intx);
+ }
+ break;
+ case PT_IRQ_TYPE_MSI:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
spin_lock(&d->event_lock);
@@ -314,53 +479,88 @@ int pt_irq_destroy_bind(
return -EINVAL;
}
- hvm_irq_dpci->link_cnt[link]--;
+ pirq = pirq_info(d, machine_gsi);
+ pirq_dpci = pirq_dpci(pirq);
- list_for_each_entry ( girq, &hvm_irq_dpci->girq[guest_gsi], list )
+ if ( pt_irq_bind->irq_type != PT_IRQ_TYPE_MSI )
{
- if ( girq->machine_gsi == machine_gsi )
+ unsigned int bus = pt_irq_bind->u.pci.bus;
+ unsigned int device = pt_irq_bind->u.pci.device;
+ unsigned int intx = pt_irq_bind->u.pci.intx;
+ unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx);
+ unsigned int link = hvm_pci_intx_link(device, intx);
+ struct hvm_girq_dpci_mapping *girq;
+ struct dev_intx_gsi_link *digl, *tmp;
+
+ list_for_each_entry ( girq, &hvm_irq_dpci->girq[guest_gsi], list )
{
+ if ( girq->bus == bus &&
+ girq->device == device &&
+ girq->intx == intx &&
+ girq->machine_gsi == machine_gsi )
+ {
list_del(&girq->list);
xfree(girq);
+ girq = NULL;
break;
+ }
}
- }
- pirq = pirq_info(d, machine_gsi);
- pirq_dpci = pirq_dpci(pirq);
+ if ( girq )
+ {
+ spin_unlock(&d->event_lock);
+ return -EINVAL;
+ }
- /* clear the mirq info */
- if ( pirq_dpci && (pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) )
- {
- list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
+ hvm_irq_dpci->link_cnt[link]--;
+
+ /* clear the mirq info */
+ if ( pirq_dpci && (pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) )
{
- if ( digl->device == device &&
- digl->intx == intx &&
- digl->link == link &&
- digl->gsi == guest_gsi )
+ list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
{
- list_del(&digl->list);
- xfree(digl);
+ if ( digl->bus == bus &&
+ digl->device == device &&
+ digl->intx == intx )
+ {
+ list_del(&digl->list);
+ xfree(digl);
+ }
}
+ what = list_empty(&pirq_dpci->digl_list) ? "final" : "partial";
}
+ else
+ what = "bogus";
+ }
- if ( list_empty(&pirq_dpci->digl_list) )
- {
- pirq_guest_unbind(d, pirq);
- msixtbl_pt_unregister(d, pirq);
- if ( pt_irq_need_timer(pirq_dpci->flags) )
- kill_timer(&pirq_dpci->timer);
- pirq_dpci->dom = NULL;
- pirq_dpci->flags = 0;
- pirq_cleanup_check(pirq, d);
- }
+ if ( pirq_dpci && (pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) &&
+ list_empty(&pirq_dpci->digl_list) )
+ {
+ pirq_guest_unbind(d, pirq);
+ msixtbl_pt_unregister(d, pirq);
+ if ( pt_irq_need_timer(pirq_dpci->flags) )
+ kill_timer(&pirq_dpci->timer);
+ pirq_dpci->flags = 0;
+ /*
+ * See comment in pt_irq_create_bind's PT_IRQ_TYPE_MSI before the
+ * call to pt_pirq_softirq_reset.
+ */
+ pt_pirq_softirq_reset(pirq_dpci);
+
+ pirq_cleanup_check(pirq, d);
}
+
spin_unlock(&d->event_lock);
- if ( iommu_verbose )
+ if ( what && iommu_verbose )
+ {
+ unsigned int device = pt_irq_bind->u.pci.device;
+
dprintk(XENLOG_G_INFO,
- "d%d unmap: m_irq=%u device=%u intx=%u\n",
- d->domain_id, machine_gsi, device, intx);
+ "d%d %s unmap: m_irq=%u dev=%02x:%02x.%u intx=%u\n",
+ d->domain_id, what, machine_gsi, pt_irq_bind->u.pci.bus,
+ PCI_SLOT(device), PCI_FUNC(device), pt_irq_bind->u.pci.intx);
+ }
return 0;
}
@@ -373,7 +573,12 @@ void pt_pirq_init(struct domain *d, struct hvm_pirq_dpci *dpci)
bool_t pt_pirq_cleanup_check(struct hvm_pirq_dpci *dpci)
{
- return !dpci->flags;
+ if ( !dpci->flags && !pt_pirq_softirq_active(dpci) )
+ {
+ dpci->dom = NULL;
+ return 1;
+ }
+ return 0;
}
int pt_pirq_iterate(struct domain *d,
@@ -413,7 +618,7 @@ int hvm_do_IRQ_dpci(struct domain *d, struct pirq *pirq)
return 0;
pirq_dpci->masked = 1;
- tasklet_schedule(&dpci->dirq_tasklet);
+ raise_softirq_for(pirq_dpci);
return 1;
}
@@ -467,48 +672,46 @@ void hvm_dpci_msi_eoi(struct domain *d, int vector)
spin_unlock(&d->event_lock);
}
-static void hvm_pci_msi_assert(
- struct domain *d, struct hvm_pirq_dpci *pirq_dpci)
+static void hvm_dirq_assist(struct domain *d, struct hvm_pirq_dpci *pirq_dpci)
{
- struct pirq *pirq = dpci_pirq(pirq_dpci);
-
- if ( hvm_domain_use_pirq(d, pirq) )
- send_guest_pirq(d, pirq);
- else
- vmsi_deliver_pirq(d, pirq_dpci);
-}
-
-static int _hvm_dirq_assist(struct domain *d, struct hvm_pirq_dpci *pirq_dpci,
- void *arg)
-{
- uint32_t device, intx;
- struct dev_intx_gsi_link *digl;
+ ASSERT(d->arch.hvm_domain.irq.dpci);
+ spin_lock(&d->event_lock);
if ( test_and_clear_bool(pirq_dpci->masked) )
{
+ struct pirq *pirq = dpci_pirq(pirq_dpci);
+ const struct dev_intx_gsi_link *digl;
+
+ if ( hvm_domain_use_pirq(d, pirq) )
+ {
+ send_guest_pirq(d, pirq);
+
+ if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI )
+ {
+ spin_unlock(&d->event_lock);
+ return;
+ }
+ }
+
if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI )
{
- hvm_pci_msi_assert(d, pirq_dpci);
- return 0;
+ vmsi_deliver_pirq(d, pirq_dpci);
+ spin_unlock(&d->event_lock);
+ return;
}
list_for_each_entry ( digl, &pirq_dpci->digl_list, list )
{
- struct pirq *info = dpci_pirq(pirq_dpci);
-
- device = digl->device;
- intx = digl->intx;
- if ( hvm_domain_use_pirq(d, info) )
- send_guest_pirq(d, info);
- else
- hvm_pci_intx_assert(d, device, intx);
+ hvm_pci_intx_assert(d, digl->device, digl->intx);
pirq_dpci->pending++;
+ }
- if ( pirq_dpci->flags & HVM_IRQ_DPCI_TRANSLATE )
- {
- /* for translated MSI to INTx interrupt, eoi as early as possible */
- __msi_pirq_eoi(pirq_dpci);
- }
+ if ( pirq_dpci->flags & HVM_IRQ_DPCI_TRANSLATE )
+ {
+ /* for translated MSI to INTx interrupt, eoi as early as possible */
+ __msi_pirq_eoi(pirq_dpci);
+ spin_unlock(&d->event_lock);
+ return;
}
/*
@@ -518,37 +721,22 @@ static int _hvm_dirq_assist(struct domain *d, struct hvm_pirq_dpci *pirq_dpci,
* guest will never deal with the irq, then the physical interrupt line
* will never be deasserted.
*/
- if ( pt_irq_need_timer(pirq_dpci->flags) )
- set_timer(&pirq_dpci->timer, NOW() + PT_IRQ_TIME_OUT);
+ ASSERT(pt_irq_need_timer(pirq_dpci->flags));
+ set_timer(&pirq_dpci->timer, NOW() + PT_IRQ_TIME_OUT);
}
-
- return 0;
-}
-
-static void hvm_dirq_assist(unsigned long _d)
-{
- struct domain *d = (struct domain *)_d;
-
- ASSERT(d->arch.hvm_domain.irq.dpci);
-
- spin_lock(&d->event_lock);
- pt_pirq_iterate(d, _hvm_dirq_assist, NULL);
spin_unlock(&d->event_lock);
}
static void __hvm_dpci_eoi(struct domain *d,
- struct hvm_girq_dpci_mapping *girq,
- union vioapic_redir_entry *ent)
+ const struct hvm_girq_dpci_mapping *girq,
+ const union vioapic_redir_entry *ent)
{
- uint32_t device, intx;
- struct pirq *pirq;
+ struct pirq *pirq = pirq_info(d, girq->machine_gsi);
struct hvm_pirq_dpci *pirq_dpci;
- device = girq->device;
- intx = girq->intx;
- hvm_pci_intx_deassert(d, device, intx);
+ if ( !hvm_domain_use_pirq(d, pirq) )
+ hvm_pci_intx_deassert(d, girq->device, girq->intx);
- pirq = pirq_info(d, girq->machine_gsi);
pirq_dpci = pirq_dpci(pirq);
/*
@@ -556,8 +744,8 @@ static void __hvm_dpci_eoi(struct domain *d,
* since interrupt is still not EOIed
*/
if ( --pirq_dpci->pending ||
- ( ent && ent->fields.mask ) ||
- ! pt_irq_need_timer(pirq_dpci->flags) )
+ (ent && ent->fields.mask) ||
+ !pt_irq_need_timer(pirq_dpci->flags) )
return;
stop_timer(&pirq_dpci->timer);
@@ -565,10 +753,10 @@ static void __hvm_dpci_eoi(struct domain *d,
}
void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
- union vioapic_redir_entry *ent)
+ const union vioapic_redir_entry *ent)
{
- struct hvm_irq_dpci *hvm_irq_dpci;
- struct hvm_girq_dpci_mapping *girq;
+ const struct hvm_irq_dpci *hvm_irq_dpci;
+ const struct hvm_girq_dpci_mapping *girq;
if ( !iommu_enabled )
return;
@@ -591,3 +779,83 @@ void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
unlock:
spin_unlock(&d->event_lock);
}
+
+/*
+ * Note: 'pt_pirq_softirq_reset' can clear the STATE_SCHED before we get to
+ * doing it. If that is the case we let 'pt_pirq_softirq_reset' do ref-counting.
+ */
+static void dpci_softirq(void)
+{
+ unsigned int cpu = smp_processor_id();
+ LIST_HEAD(our_list);
+
+ local_irq_disable();
+ list_splice_init(&per_cpu(dpci_list, cpu), &our_list);
+ local_irq_enable();
+
+ while ( !list_empty(&our_list) )
+ {
+ struct hvm_pirq_dpci *pirq_dpci;
+ struct domain *d;
+
+ pirq_dpci = list_entry(our_list.next, struct hvm_pirq_dpci, softirq_list);
+ list_del(&pirq_dpci->softirq_list);
+
+ d = pirq_dpci->dom;
+ smp_mb(); /* 'd' MUST be saved before we set/clear the bits. */
+ if ( test_and_set_bit(STATE_RUN, &pirq_dpci->state) )
+ BUG();
+ /*
+ * The one who clears STATE_SCHED MUST refcount the domain.
+ */
+ if ( test_and_clear_bit(STATE_SCHED, &pirq_dpci->state) )
+ {
+ hvm_dirq_assist(d, pirq_dpci);
+ put_domain(d);
+ }
+ clear_bit(STATE_RUN, &pirq_dpci->state);
+ }
+}
+
+static int cpu_callback(
+ struct notifier_block *nfb, unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+
+ switch ( action )
+ {
+ case CPU_UP_PREPARE:
+ INIT_LIST_HEAD(&per_cpu(dpci_list, cpu));
+ break;
+ case CPU_UP_CANCELED:
+ case CPU_DEAD:
+ /*
+ * On CPU_DYING this callback is called (on the CPU that is dying)
+ * with an possible HVM_DPIC_SOFTIRQ pending - at which point we can
+ * clear out any outstanding domains (by the virtue of the idle loop
+ * calling the softirq later). In CPU_DEAD case the CPU is deaf and
+ * there are no pending softirqs for us to handle so we can chill.
+ */
+ ASSERT(list_empty(&per_cpu(dpci_list, cpu)));
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block cpu_nfb = {
+ .notifier_call = cpu_callback,
+};
+
+static int __init setup_dpci_softirq(void)
+{
+ unsigned int cpu;
+
+ for_each_online_cpu(cpu)
+ INIT_LIST_HEAD(&per_cpu(dpci_list, cpu));
+
+ open_softirq(HVM_DPCI_SOFTIRQ, dpci_softirq);
+ register_cpu_notifier(&cpu_nfb);
+ return 0;
+}
+__initcall(setup_dpci_softirq);
diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c
index c687c53..cc12735 100644
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -24,7 +24,6 @@
#include <xsm/xsm.h>
static void parse_iommu_param(char *s);
-static int iommu_populate_page_table(struct domain *d);
static void iommu_dump_p2m_table(unsigned char key);
/*
@@ -45,7 +44,7 @@ custom_param("iommu", parse_iommu_param);
bool_t __initdata iommu_enable = 1;
bool_t __read_mostly iommu_enabled;
bool_t __read_mostly force_iommu;
-bool_t __initdata iommu_dom0_strict;
+bool_t __hwdom_initdata iommu_dom0_strict;
bool_t __read_mostly iommu_verbose;
bool_t __read_mostly iommu_workaround_bios_bug;
bool_t __read_mostly iommu_passthrough;
@@ -118,10 +117,11 @@ static void __init parse_iommu_param(char *s)
int iommu_domain_init(struct domain *d)
{
struct hvm_iommu *hd = domain_hvm_iommu(d);
+ int ret = 0;
- spin_lock_init(&hd->mapping_lock);
- INIT_LIST_HEAD(&hd->g2m_ioport_list);
- INIT_LIST_HEAD(&hd->mapped_rmrrs);
+ ret = arch_iommu_domain_init(d);
+ if ( ret )
+ return ret;
if ( !iommu_enabled )
return 0;
@@ -130,30 +130,32 @@ int iommu_domain_init(struct domain *d)
return hd->platform_ops->init(d);
}
-static __init void check_dom0_pvh_reqs(struct domain *d)
+static void __hwdom_init check_hwdom_reqs(struct domain *d)
{
- if ( !iommu_enabled )
- panic("Presently, iommu must be enabled for pvh dom0\n");
+ if ( !paging_mode_translate(d) )
+ return;
+
+ arch_iommu_check_autotranslated_hwdom(d);
if ( iommu_passthrough )
- panic("For pvh dom0, dom0-passthrough must not be enabled\n");
+ panic("Dom0 uses paging translated mode, dom0-passthrough must not be "
+ "enabled\n");
iommu_dom0_strict = 1;
}
-void __init iommu_dom0_init(struct domain *d)
+void __hwdom_init iommu_hwdom_init(struct domain *d)
{
struct hvm_iommu *hd = domain_hvm_iommu(d);
- if ( is_pvh_domain(d) )
- check_dom0_pvh_reqs(d);
+ check_hwdom_reqs(d);
if ( !iommu_enabled )
return;
register_keyhandler('o', &iommu_p2m_table);
d->need_iommu = !!iommu_dom0_strict;
- if ( need_iommu(d) )
+ if ( need_iommu(d) && !iommu_use_hap_pt(d) )
{
struct page_info *page;
unsigned int i = 0;
@@ -173,89 +175,10 @@ void __init iommu_dom0_init(struct domain *d)
}
}
- return hd->platform_ops->dom0_init(d);
+ return hd->platform_ops->hwdom_init(d);
}
-int iommu_add_device(struct pci_dev *pdev)
-{
- struct hvm_iommu *hd;
- int rc;
- u8 devfn;
-
- if ( !pdev->domain )
- return -EINVAL;
-
- ASSERT(spin_is_locked(&pcidevs_lock));
-
- hd = domain_hvm_iommu(pdev->domain);
- if ( !iommu_enabled || !hd->platform_ops )
- return 0;
-
- rc = hd->platform_ops->add_device(pdev->devfn, pdev);
- if ( rc || !pdev->phantom_stride )
- return rc;
-
- for ( devfn = pdev->devfn ; ; )
- {
- devfn += pdev->phantom_stride;
- if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) )
- return 0;
- rc = hd->platform_ops->add_device(devfn, pdev);
- if ( rc )
- printk(XENLOG_WARNING "IOMMU: add %04x:%02x:%02x.%u failed (%d)\n",
- pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn), rc);
- }
-}
-
-int iommu_enable_device(struct pci_dev *pdev)
-{
- struct hvm_iommu *hd;
-
- if ( !pdev->domain )
- return -EINVAL;
-
- ASSERT(spin_is_locked(&pcidevs_lock));
-
- hd = domain_hvm_iommu(pdev->domain);
- if ( !iommu_enabled || !hd->platform_ops ||
- !hd->platform_ops->enable_device )
- return 0;
-
- return hd->platform_ops->enable_device(pdev);
-}
-
-int iommu_remove_device(struct pci_dev *pdev)
-{
- struct hvm_iommu *hd;
- u8 devfn;
-
- if ( !pdev->domain )
- return -EINVAL;
-
- hd = domain_hvm_iommu(pdev->domain);
- if ( !iommu_enabled || !hd->platform_ops )
- return 0;
-
- for ( devfn = pdev->devfn ; pdev->phantom_stride; )
- {
- int rc;
-
- devfn += pdev->phantom_stride;
- if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) )
- break;
- rc = hd->platform_ops->remove_device(devfn, pdev);
- if ( !rc )
- continue;
-
- printk(XENLOG_ERR "IOMMU: remove %04x:%02x:%02x.%u failed (%d)\n",
- pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn), rc);
- return rc;
- }
-
- return hd->platform_ops->remove_device(pdev->devfn, pdev);
-}
-
-static void iommu_teardown(struct domain *d)
+void iommu_teardown(struct domain *d)
{
const struct hvm_iommu *hd = domain_hvm_iommu(d);
@@ -264,156 +187,9 @@ static void iommu_teardown(struct domain *d)
tasklet_schedule(&iommu_pt_cleanup_tasklet);
}
-/*
- * If the device isn't owned by dom0, it means it already
- * has been assigned to other domain, or it doesn't exist.
- */
-static int device_assigned(u16 seg, u8 bus, u8 devfn)
-{
- struct pci_dev *pdev;
-
- spin_lock(&pcidevs_lock);
- pdev = pci_get_pdev_by_domain(dom0, seg, bus, devfn);
- spin_unlock(&pcidevs_lock);
-
- return pdev ? 0 : -EBUSY;
-}
-
-static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn)
-{
- struct hvm_iommu *hd = domain_hvm_iommu(d);
- struct pci_dev *pdev;
- int rc = 0;
-
- if ( !iommu_enabled || !hd->platform_ops )
- return 0;
-
- /* Prevent device assign if mem paging or mem sharing have been
- * enabled for this domain */
- if ( unlikely(!need_iommu(d) &&
- (d->arch.hvm_domain.mem_sharing_enabled ||
- d->mem_event->paging.ring_page)) )
- return -EXDEV;
-
- if ( !spin_trylock(&pcidevs_lock) )
- return -ERESTART;
-
- if ( need_iommu(d) <= 0 )
- {
- if ( !iommu_use_hap_pt(d) )
- {
- rc = iommu_populate_page_table(d);
- if ( rc )
- {
- spin_unlock(&pcidevs_lock);
- return rc;
- }
- }
- d->need_iommu = 1;
- }
-
- pdev = pci_get_pdev_by_domain(dom0, seg, bus, devfn);
- if ( !pdev )
- {
- rc = pci_get_pdev(seg, bus, devfn) ? -EBUSY : -ENODEV;
- goto done;
- }
-
- pdev->fault.count = 0;
-
- if ( (rc = hd->platform_ops->assign_device(d, devfn, pdev)) )
- goto done;
-
- for ( ; pdev->phantom_stride; rc = 0 )
- {
- devfn += pdev->phantom_stride;
- if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) )
- break;
- rc = hd->platform_ops->assign_device(d, devfn, pdev);
- if ( rc )
- printk(XENLOG_G_WARNING "d%d: assign %04x:%02x:%02x.%u failed (%d)\n",
- d->domain_id, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
- rc);
- }
-
- done:
- if ( !has_arch_pdevs(d) && need_iommu(d) )
- iommu_teardown(d);
- spin_unlock(&pcidevs_lock);
-
- return rc;
-}
-
-static int iommu_populate_page_table(struct domain *d)
-{
- struct hvm_iommu *hd = domain_hvm_iommu(d);
- struct page_info *page;
- int rc = 0, n = 0;
-
- d->need_iommu = -1;
-
- this_cpu(iommu_dont_flush_iotlb) = 1;
- spin_lock(&d->page_alloc_lock);
-
- if ( unlikely(d->is_dying) )
- rc = -ESRCH;
-
- while ( !rc && (page = page_list_remove_head(&d->page_list)) )
- {
- if ( is_hvm_domain(d) ||
- (page->u.inuse.type_info & PGT_type_mask) == PGT_writable_page )
- {
- BUG_ON(SHARED_M2P(mfn_to_gmfn(d, page_to_mfn(page))));
- rc = hd->platform_ops->map_page(
- d, mfn_to_gmfn(d, page_to_mfn(page)), page_to_mfn(page),
- IOMMUF_readable|IOMMUF_writable);
- if ( rc )
- {
- page_list_add(page, &d->page_list);
- break;
- }
- }
- page_list_add_tail(page, &d->arch.relmem_list);
- if ( !(++n & 0xff) && !page_list_empty(&d->page_list) &&
- hypercall_preempt_check() )
- rc = -ERESTART;
- }
-
- if ( !rc )
- {
- /*
- * The expectation here is that generally there are many normal pages
- * on relmem_list (the ones we put there) and only few being in an
- * offline/broken state. The latter ones are always at the head of the
- * list. Hence we first move the whole list, and then move back the
- * first few entries.
- */
- page_list_move(&d->page_list, &d->arch.relmem_list);
- while ( (page = page_list_first(&d->page_list)) != NULL &&
- (page->count_info & (PGC_state|PGC_broken)) )
- {
- page_list_del(page, &d->page_list);
- page_list_add_tail(page, &d->arch.relmem_list);
- }
- }
-
- spin_unlock(&d->page_alloc_lock);
- this_cpu(iommu_dont_flush_iotlb) = 0;
-
- if ( !rc )
- iommu_iotlb_flush_all(d);
- else if ( rc != -ERESTART )
- iommu_teardown(d);
-
- return rc;
-}
-
-
void iommu_domain_destroy(struct domain *d)
{
- struct hvm_iommu *hd = domain_hvm_iommu(d);
- struct list_head *ioport_list, *tmp;
- struct g2m_ioport *ioport;
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
if ( !iommu_enabled || !hd->platform_ops )
return;
@@ -421,12 +197,7 @@ void iommu_domain_destroy(struct domain *d)
if ( need_iommu(d) )
iommu_teardown(d);
- list_for_each_safe ( ioport_list, tmp, &hd->g2m_ioport_list )
- {
- ioport = list_entry(ioport_list, struct g2m_ioport, list);
- list_del(&ioport->list);
- xfree(ioport);
- }
+ arch_iommu_domain_destroy(d);
}
int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn,
@@ -487,53 +258,6 @@ void iommu_iotlb_flush_all(struct domain *d)
hd->platform_ops->iotlb_flush_all(d);
}
-/* caller should hold the pcidevs_lock */
-int deassign_device(struct domain *d, u16 seg, u8 bus, u8 devfn)
-{
- struct hvm_iommu *hd = domain_hvm_iommu(d);
- struct pci_dev *pdev = NULL;
- int ret = 0;
-
- if ( !iommu_enabled || !hd->platform_ops )
- return -EINVAL;
-
- ASSERT(spin_is_locked(&pcidevs_lock));
- pdev = pci_get_pdev_by_domain(d, seg, bus, devfn);
- if ( !pdev )
- return -ENODEV;
-
- while ( pdev->phantom_stride )
- {
- devfn += pdev->phantom_stride;
- if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) )
- break;
- ret = hd->platform_ops->reassign_device(d, dom0, devfn, pdev);
- if ( !ret )
- continue;
-
- printk(XENLOG_G_ERR "d%d: deassign %04x:%02x:%02x.%u failed (%d)\n",
- d->domain_id, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), ret);
- return ret;
- }
-
- devfn = pdev->devfn;
- ret = hd->platform_ops->reassign_device(d, dom0, devfn, pdev);
- if ( ret )
- {
- dprintk(XENLOG_G_ERR,
- "d%d: deassign device (%04x:%02x:%02x.%u) failed\n",
- d->domain_id, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
- return ret;
- }
-
- pdev->fault.count = 0;
-
- if ( !has_arch_pdevs(d) && need_iommu(d) )
- iommu_teardown(d);
-
- return ret;
-}
-
int __init iommu_setup(void)
{
int rc = -ENODEV;
@@ -574,91 +298,27 @@ int __init iommu_setup(void)
return rc;
}
-static int iommu_get_device_group(
- struct domain *d, u16 seg, u8 bus, u8 devfn,
- XEN_GUEST_HANDLE_64(uint32) buf, int max_sdevs)
-{
- struct hvm_iommu *hd = domain_hvm_iommu(d);
- struct pci_dev *pdev;
- int group_id, sdev_id;
- u32 bdf;
- int i = 0;
- const struct iommu_ops *ops = hd->platform_ops;
-
- if ( !iommu_enabled || !ops || !ops->get_device_group_id )
- return 0;
-
- group_id = ops->get_device_group_id(seg, bus, devfn);
-
- spin_lock(&pcidevs_lock);
- for_each_pdev( d, pdev )
- {
- if ( (pdev->seg != seg) ||
- ((pdev->bus == bus) && (pdev->devfn == devfn)) )
- continue;
-
- if ( xsm_get_device_group(XSM_HOOK, (seg << 16) | (pdev->bus << 8) | pdev->devfn) )
- continue;
-
- sdev_id = ops->get_device_group_id(seg, pdev->bus, pdev->devfn);
- if ( (sdev_id == group_id) && (i < max_sdevs) )
- {
- bdf = 0;
- bdf |= (pdev->bus & 0xff) << 16;
- bdf |= (pdev->devfn & 0xff) << 8;
-
- if ( unlikely(copy_to_guest_offset(buf, i, &bdf, 1)) )
- {
- spin_unlock(&pcidevs_lock);
- return -1;
- }
- i++;
- }
- }
- spin_unlock(&pcidevs_lock);
-
- return i;
-}
-
-void iommu_update_ire_from_apic(
- unsigned int apic, unsigned int reg, unsigned int value)
-{
- const struct iommu_ops *ops = iommu_get_ops();
- ops->update_ire_from_apic(apic, reg, value);
-}
-
-int iommu_update_ire_from_msi(
- struct msi_desc *msi_desc, struct msi_msg *msg)
+void iommu_resume()
{
const struct iommu_ops *ops = iommu_get_ops();
- return iommu_intremap ? ops->update_ire_from_msi(msi_desc, msg) : 0;
+ if ( iommu_enabled )
+ ops->resume();
}
-void iommu_read_msi_from_ire(
- struct msi_desc *msi_desc, struct msi_msg *msg)
+int iommu_do_domctl(
+ struct xen_domctl *domctl, struct domain *d,
+ XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
{
- const struct iommu_ops *ops = iommu_get_ops();
- if ( iommu_intremap )
- ops->read_msi_from_ire(msi_desc, msg);
-}
+ int ret = -ENOSYS;
-unsigned int iommu_read_apic_from_ire(unsigned int apic, unsigned int reg)
-{
- const struct iommu_ops *ops = iommu_get_ops();
- return ops->read_apic_from_ire(apic, reg);
-}
+ if ( !iommu_enabled )
+ return -ENOSYS;
-int __init iommu_setup_hpet_msi(struct msi_desc *msi)
-{
- const struct iommu_ops *ops = iommu_get_ops();
- return ops->setup_hpet_msi ? ops->setup_hpet_msi(msi) : -ENODEV;
-}
+#ifdef HAS_PCI
+ ret = iommu_do_pci_domctl(domctl, d, u_domctl);
+#endif
-void iommu_resume()
-{
- const struct iommu_ops *ops = iommu_get_ops();
- if ( iommu_enabled )
- ops->resume();
+ return ret;
}
void iommu_suspend()
@@ -684,123 +344,14 @@ void iommu_crash_shutdown(void)
iommu_enabled = iommu_intremap = 0;
}
-int iommu_do_domctl(
- struct xen_domctl *domctl, struct domain *d,
- XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
+bool_t iommu_has_feature(struct domain *d, enum iommu_feature feature)
{
- u16 seg;
- u8 bus, devfn;
- int ret = 0;
+ const struct hvm_iommu *hd = domain_hvm_iommu(d);
if ( !iommu_enabled )
- return -ENOSYS;
-
- switch ( domctl->cmd )
- {
- case XEN_DOMCTL_get_device_group:
- {
- u32 max_sdevs;
- XEN_GUEST_HANDLE_64(uint32) sdevs;
-
- ret = xsm_get_device_group(XSM_HOOK, domctl->u.get_device_group.machine_sbdf);
- if ( ret )
- break;
-
- seg = domctl->u.get_device_group.machine_sbdf >> 16;
- bus = (domctl->u.get_device_group.machine_sbdf >> 8) & 0xff;
- devfn = domctl->u.get_device_group.machine_sbdf & 0xff;
- max_sdevs = domctl->u.get_device_group.max_sdevs;
- sdevs = domctl->u.get_device_group.sdev_array;
-
- ret = iommu_get_device_group(d, seg, bus, devfn, sdevs, max_sdevs);
- if ( ret < 0 )
- {
- dprintk(XENLOG_ERR, "iommu_get_device_group() failed!\n");
- ret = -EFAULT;
- domctl->u.get_device_group.num_sdevs = 0;
- }
- else
- {
- domctl->u.get_device_group.num_sdevs = ret;
- ret = 0;
- }
- if ( __copy_field_to_guest(u_domctl, domctl, u.get_device_group) )
- ret = -EFAULT;
- }
- break;
-
- case XEN_DOMCTL_test_assign_device:
- ret = xsm_test_assign_device(XSM_HOOK, domctl->u.assign_device.machine_sbdf);
- if ( ret )
- break;
-
- seg = domctl->u.assign_device.machine_sbdf >> 16;
- bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff;
- devfn = domctl->u.assign_device.machine_sbdf & 0xff;
-
- if ( device_assigned(seg, bus, devfn) )
- {
- printk(XENLOG_G_INFO
- "%04x:%02x:%02x.%u already assigned, or non-existent\n",
- seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
- ret = -EINVAL;
- }
- break;
-
- case XEN_DOMCTL_assign_device:
- if ( unlikely(d->is_dying) )
- {
- ret = -EINVAL;
- break;
- }
-
- ret = xsm_assign_device(XSM_HOOK, d, domctl->u.assign_device.machine_sbdf);
- if ( ret )
- break;
-
- seg = domctl->u.assign_device.machine_sbdf >> 16;
- bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff;
- devfn = domctl->u.assign_device.machine_sbdf & 0xff;
-
- ret = device_assigned(seg, bus, devfn) ?:
- assign_device(d, seg, bus, devfn);
- if ( ret == -ERESTART )
- ret = hypercall_create_continuation(__HYPERVISOR_domctl,
- "h", u_domctl);
- else if ( ret )
- printk(XENLOG_G_ERR "XEN_DOMCTL_assign_device: "
- "assign %04x:%02x:%02x.%u to dom%d failed (%d)\n",
- seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
- d->domain_id, ret);
-
- break;
-
- case XEN_DOMCTL_deassign_device:
- ret = xsm_deassign_device(XSM_HOOK, d, domctl->u.assign_device.machine_sbdf);
- if ( ret )
- break;
-
- seg = domctl->u.assign_device.machine_sbdf >> 16;
- bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff;
- devfn = domctl->u.assign_device.machine_sbdf & 0xff;
-
- spin_lock(&pcidevs_lock);
- ret = deassign_device(d, seg, bus, devfn);
- spin_unlock(&pcidevs_lock);
- if ( ret )
- printk(XENLOG_G_ERR
- "deassign %04x:%02x:%02x.%u from dom%d failed (%d)\n",
- seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
- d->domain_id, ret);
-
- break;
-
- default:
- ret = -ENOSYS;
- break;
- }
+ return 0;
- return ret;
+ return test_bit(feature, hd->features);
}
static void iommu_dump_p2m_table(unsigned char key)
@@ -817,7 +368,7 @@ static void iommu_dump_p2m_table(unsigned char key)
ops = iommu_get_ops();
for_each_domain(d)
{
- if ( !d->domain_id )
+ if ( is_hardware_domain(d) )
continue;
if ( iommu_use_hap_pt(d) )
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index e5d332d..78c6977 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -26,6 +26,9 @@
#include <asm/hvm/irq.h>
#include <xen/delay.h>
#include <xen/keyhandler.h>
+#include <xen/event.h>
+#include <xen/guest_access.h>
+#include <xen/paging.h>
#include <xen/radix-tree.h>
#include <xen/softirq.h>
#include <xen/tasklet.h>
@@ -682,7 +685,7 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn, const struct pci_dev_info *info)
ret = 0;
if ( !pdev->domain )
{
- pdev->domain = dom0;
+ pdev->domain = hardware_domain;
ret = iommu_add_device(pdev);
if ( ret )
{
@@ -690,7 +693,7 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn, const struct pci_dev_info *info)
goto out;
}
- list_add(&pdev->domain_list, &dom0->arch.pdev_list);
+ list_add(&pdev->domain_list, &hardware_domain->arch.pdev_list);
}
else
iommu_enable_device(pdev);
@@ -764,40 +767,51 @@ static int pci_clean_dpci_irq(struct domain *d,
xfree(digl);
}
- return 0;
+ return pt_pirq_softirq_active(pirq_dpci) ? -ERESTART : 0;
}
-static void pci_clean_dpci_irqs(struct domain *d)
+static int pci_clean_dpci_irqs(struct domain *d)
{
struct hvm_irq_dpci *hvm_irq_dpci = NULL;
if ( !iommu_enabled )
- return;
+ return 0;
if ( !is_hvm_domain(d) )
- return;
+ return 0;
spin_lock(&d->event_lock);
hvm_irq_dpci = domain_get_irq_dpci(d);
if ( hvm_irq_dpci != NULL )
{
- tasklet_kill(&hvm_irq_dpci->dirq_tasklet);
+ int ret = pt_pirq_iterate(d, pci_clean_dpci_irq, NULL);
- pt_pirq_iterate(d, pci_clean_dpci_irq, NULL);
+ if ( ret )
+ {
+ spin_unlock(&d->event_lock);
+ return ret;
+ }
d->arch.hvm_domain.irq.dpci = NULL;
free_hvm_irq_dpci(hvm_irq_dpci);
}
spin_unlock(&d->event_lock);
+ return 0;
}
-void pci_release_devices(struct domain *d)
+int pci_release_devices(struct domain *d)
{
struct pci_dev *pdev;
u8 bus, devfn;
+ int ret;
spin_lock(&pcidevs_lock);
- pci_clean_dpci_irqs(d);
+ ret = pci_clean_dpci_irqs(d);
+ if ( ret )
+ {
+ spin_unlock(&pcidevs_lock);
+ return ret;
+ }
while ( (pdev = pci_get_pdev_by_domain(d, -1, -1, -1)) )
{
bus = pdev->bus;
@@ -808,6 +822,8 @@ void pci_release_devices(struct domain *d)
PCI_SLOT(devfn), PCI_FUNC(devfn));
}
spin_unlock(&pcidevs_lock);
+
+ return 0;
}
#define PCI_CLASS_BRIDGE_HOST 0x0600
@@ -980,12 +996,12 @@ int __init scan_pci_devices(void)
return ret;
}
-struct setup_dom0 {
+struct setup_hwdom {
struct domain *d;
int (*handler)(u8 devfn, struct pci_dev *);
};
-static void setup_one_dom0_device(const struct setup_dom0 *ctxt,
+static void setup_one_hwdom_device(const struct setup_hwdom *ctxt,
struct pci_dev *pdev)
{
u8 devfn = pdev->devfn;
@@ -1006,9 +1022,9 @@ static void setup_one_dom0_device(const struct setup_dom0 *ctxt,
PCI_SLOT(devfn) == PCI_SLOT(pdev->devfn) );
}
-static int __init _setup_dom0_pci_devices(struct pci_seg *pseg, void *arg)
+static int __hwdom_init _setup_hwdom_pci_devices(struct pci_seg *pseg, void *arg)
{
- struct setup_dom0 *ctxt = arg;
+ struct setup_hwdom *ctxt = arg;
int bus, devfn;
for ( bus = 0; bus < 256; bus++ )
@@ -1024,12 +1040,12 @@ static int __init _setup_dom0_pci_devices(struct pci_seg *pseg, void *arg)
{
pdev->domain = ctxt->d;
list_add(&pdev->domain_list, &ctxt->d->arch.pdev_list);
- setup_one_dom0_device(ctxt, pdev);
+ setup_one_hwdom_device(ctxt, pdev);
}
else if ( pdev->domain == dom_xen )
{
pdev->domain = ctxt->d;
- setup_one_dom0_device(ctxt, pdev);
+ setup_one_hwdom_device(ctxt, pdev);
pdev->domain = dom_xen;
}
else if ( pdev->domain != ctxt->d )
@@ -1056,13 +1072,13 @@ static int __init _setup_dom0_pci_devices(struct pci_seg *pseg, void *arg)
return 0;
}
-void __init setup_dom0_pci_devices(
+void __hwdom_init setup_hwdom_pci_devices(
struct domain *d, int (*handler)(u8 devfn, struct pci_dev *))
{
- struct setup_dom0 ctxt = { .d = d, .handler = handler };
+ struct setup_hwdom ctxt = { .d = d, .handler = handler };
spin_lock(&pcidevs_lock);
- pci_segments_iterate(_setup_dom0_pci_devices, &ctxt);
+ pci_segments_iterate(_setup_hwdom_pci_devices, &ctxt);
spin_unlock(&pcidevs_lock);
}
@@ -1208,6 +1224,391 @@ static int __init setup_dump_pcidevs(void)
}
__initcall(setup_dump_pcidevs);
+int iommu_update_ire_from_msi(
+ struct msi_desc *msi_desc, struct msi_msg *msg)
+{
+ const struct iommu_ops *ops = iommu_get_ops();
+ return iommu_intremap ? ops->update_ire_from_msi(msi_desc, msg) : 0;
+}
+
+void iommu_read_msi_from_ire(
+ struct msi_desc *msi_desc, struct msi_msg *msg)
+{
+ const struct iommu_ops *ops = iommu_get_ops();
+ if ( iommu_intremap )
+ ops->read_msi_from_ire(msi_desc, msg);
+}
+
+int iommu_add_device(struct pci_dev *pdev)
+{
+ struct hvm_iommu *hd;
+ int rc;
+ u8 devfn;
+
+ if ( !pdev->domain )
+ return -EINVAL;
+
+ ASSERT(spin_is_locked(&pcidevs_lock));
+
+ hd = domain_hvm_iommu(pdev->domain);
+ if ( !iommu_enabled || !hd->platform_ops )
+ return 0;
+
+ rc = hd->platform_ops->add_device(pdev->devfn, pdev);
+ if ( rc || !pdev->phantom_stride )
+ return rc;
+
+ for ( devfn = pdev->devfn ; ; )
+ {
+ devfn += pdev->phantom_stride;
+ if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) )
+ return 0;
+ rc = hd->platform_ops->add_device(devfn, pdev);
+ if ( rc )
+ printk(XENLOG_WARNING "IOMMU: add %04x:%02x:%02x.%u failed (%d)\n",
+ pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn), rc);
+ }
+}
+
+int iommu_enable_device(struct pci_dev *pdev)
+{
+ struct hvm_iommu *hd;
+
+ if ( !pdev->domain )
+ return -EINVAL;
+
+ ASSERT(spin_is_locked(&pcidevs_lock));
+
+ hd = domain_hvm_iommu(pdev->domain);
+ if ( !iommu_enabled || !hd->platform_ops ||
+ !hd->platform_ops->enable_device )
+ return 0;
+
+ return hd->platform_ops->enable_device(pdev);
+}
+
+int iommu_remove_device(struct pci_dev *pdev)
+{
+ struct hvm_iommu *hd;
+ u8 devfn;
+
+ if ( !pdev->domain )
+ return -EINVAL;
+
+ hd = domain_hvm_iommu(pdev->domain);
+ if ( !iommu_enabled || !hd->platform_ops )
+ return 0;
+
+ for ( devfn = pdev->devfn ; pdev->phantom_stride; )
+ {
+ int rc;
+
+ devfn += pdev->phantom_stride;
+ if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) )
+ break;
+ rc = hd->platform_ops->remove_device(devfn, pdev);
+ if ( !rc )
+ continue;
+
+ printk(XENLOG_ERR "IOMMU: remove %04x:%02x:%02x.%u failed (%d)\n",
+ pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn), rc);
+ return rc;
+ }
+
+ return hd->platform_ops->remove_device(pdev->devfn, pdev);
+}
+
+/*
+ * If the device isn't owned by the hardware domain, it means it already
+ * has been assigned to other domain, or it doesn't exist.
+ */
+static int device_assigned(u16 seg, u8 bus, u8 devfn)
+{
+ struct pci_dev *pdev;
+
+ spin_lock(&pcidevs_lock);
+ pdev = pci_get_pdev_by_domain(hardware_domain, seg, bus, devfn);
+ spin_unlock(&pcidevs_lock);
+
+ return pdev ? 0 : -EBUSY;
+}
+
+static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn)
+{
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+ struct pci_dev *pdev;
+ int rc = 0;
+
+ if ( !iommu_enabled || !hd->platform_ops )
+ return 0;
+
+ /* Prevent device assign if mem paging or mem sharing have been
+ * enabled for this domain */
+ if ( unlikely(!need_iommu(d) &&
+ (d->arch.hvm_domain.mem_sharing_enabled ||
+ d->mem_event->paging.ring_page ||
+ p2m_get_hostp2m(d)->global_logdirty)) )
+ return -EXDEV;
+
+ if ( !spin_trylock(&pcidevs_lock) )
+ return -ERESTART;
+
+ if ( need_iommu(d) <= 0 )
+ {
+ if ( !iommu_use_hap_pt(d) )
+ {
+ rc = arch_iommu_populate_page_table(d);
+ if ( rc )
+ {
+ spin_unlock(&pcidevs_lock);
+ return rc;
+ }
+ }
+ d->need_iommu = 1;
+ }
+
+ pdev = pci_get_pdev_by_domain(hardware_domain, seg, bus, devfn);
+ if ( !pdev )
+ {
+ rc = pci_get_pdev(seg, bus, devfn) ? -EBUSY : -ENODEV;
+ goto done;
+ }
+
+ pdev->fault.count = 0;
+
+ if ( (rc = hd->platform_ops->assign_device(d, devfn, pdev)) )
+ goto done;
+
+ for ( ; pdev->phantom_stride; rc = 0 )
+ {
+ devfn += pdev->phantom_stride;
+ if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) )
+ break;
+ rc = hd->platform_ops->assign_device(d, devfn, pdev);
+ if ( rc )
+ printk(XENLOG_G_WARNING "d%d: assign %04x:%02x:%02x.%u failed (%d)\n",
+ d->domain_id, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
+ rc);
+ }
+
+ done:
+ if ( !has_arch_pdevs(d) && need_iommu(d) )
+ iommu_teardown(d);
+ spin_unlock(&pcidevs_lock);
+
+ return rc;
+}
+
+/* caller should hold the pcidevs_lock */
+int deassign_device(struct domain *d, u16 seg, u8 bus, u8 devfn)
+{
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+ struct pci_dev *pdev = NULL;
+ int ret = 0;
+
+ if ( !iommu_enabled || !hd->platform_ops )
+ return -EINVAL;
+
+ ASSERT(spin_is_locked(&pcidevs_lock));
+ pdev = pci_get_pdev_by_domain(d, seg, bus, devfn);
+ if ( !pdev )
+ return -ENODEV;
+
+ while ( pdev->phantom_stride )
+ {
+ devfn += pdev->phantom_stride;
+ if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) )
+ break;
+ ret = hd->platform_ops->reassign_device(d, hardware_domain, devfn, pdev);
+ if ( !ret )
+ continue;
+
+ printk(XENLOG_G_ERR "d%d: deassign %04x:%02x:%02x.%u failed (%d)\n",
+ d->domain_id, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), ret);
+ return ret;
+ }
+
+ devfn = pdev->devfn;
+ ret = hd->platform_ops->reassign_device(d, hardware_domain, devfn, pdev);
+ if ( ret )
+ {
+ dprintk(XENLOG_G_ERR,
+ "d%d: deassign device (%04x:%02x:%02x.%u) failed\n",
+ d->domain_id, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ return ret;
+ }
+
+ pdev->fault.count = 0;
+
+ if ( !has_arch_pdevs(d) && need_iommu(d) )
+ iommu_teardown(d);
+
+ return ret;
+}
+
+static int iommu_get_device_group(
+ struct domain *d, u16 seg, u8 bus, u8 devfn,
+ XEN_GUEST_HANDLE_64(uint32) buf, int max_sdevs)
+{
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+ struct pci_dev *pdev;
+ int group_id, sdev_id;
+ u32 bdf;
+ int i = 0;
+ const struct iommu_ops *ops = hd->platform_ops;
+
+ if ( !iommu_enabled || !ops || !ops->get_device_group_id )
+ return 0;
+
+ group_id = ops->get_device_group_id(seg, bus, devfn);
+
+ spin_lock(&pcidevs_lock);
+ for_each_pdev( d, pdev )
+ {
+ if ( (pdev->seg != seg) ||
+ ((pdev->bus == bus) && (pdev->devfn == devfn)) )
+ continue;
+
+ if ( xsm_get_device_group(XSM_HOOK, (seg << 16) | (pdev->bus << 8) | pdev->devfn) )
+ continue;
+
+ sdev_id = ops->get_device_group_id(seg, pdev->bus, pdev->devfn);
+ if ( (sdev_id == group_id) && (i < max_sdevs) )
+ {
+ bdf = 0;
+ bdf |= (pdev->bus & 0xff) << 16;
+ bdf |= (pdev->devfn & 0xff) << 8;
+
+ if ( unlikely(copy_to_guest_offset(buf, i, &bdf, 1)) )
+ {
+ spin_unlock(&pcidevs_lock);
+ return -1;
+ }
+ i++;
+ }
+ }
+
+ spin_unlock(&pcidevs_lock);
+
+ return i;
+}
+
+int iommu_do_pci_domctl(
+ struct xen_domctl *domctl, struct domain *d,
+ XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
+{
+ u16 seg;
+ u8 bus, devfn;
+ int ret = 0;
+
+ switch ( domctl->cmd )
+ {
+ case XEN_DOMCTL_get_device_group:
+ {
+ u32 max_sdevs;
+ XEN_GUEST_HANDLE_64(uint32) sdevs;
+
+ ret = xsm_get_device_group(XSM_HOOK, domctl->u.get_device_group.machine_sbdf);
+ if ( ret )
+ break;
+
+ seg = domctl->u.get_device_group.machine_sbdf >> 16;
+ bus = (domctl->u.get_device_group.machine_sbdf >> 8) & 0xff;
+ devfn = domctl->u.get_device_group.machine_sbdf & 0xff;
+ max_sdevs = domctl->u.get_device_group.max_sdevs;
+ sdevs = domctl->u.get_device_group.sdev_array;
+
+ ret = iommu_get_device_group(d, seg, bus, devfn, sdevs, max_sdevs);
+ if ( ret < 0 )
+ {
+ dprintk(XENLOG_ERR, "iommu_get_device_group() failed!\n");
+ ret = -EFAULT;
+ domctl->u.get_device_group.num_sdevs = 0;
+ }
+ else
+ {
+ domctl->u.get_device_group.num_sdevs = ret;
+ ret = 0;
+ }
+ if ( __copy_field_to_guest(u_domctl, domctl, u.get_device_group) )
+ ret = -EFAULT;
+ }
+ break;
+
+ case XEN_DOMCTL_test_assign_device:
+ ret = xsm_test_assign_device(XSM_HOOK, domctl->u.assign_device.machine_sbdf);
+ if ( ret )
+ break;
+
+ seg = domctl->u.assign_device.machine_sbdf >> 16;
+ bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff;
+ devfn = domctl->u.assign_device.machine_sbdf & 0xff;
+
+ if ( device_assigned(seg, bus, devfn) )
+ {
+ printk(XENLOG_G_INFO
+ "%04x:%02x:%02x.%u already assigned, or non-existent\n",
+ seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ ret = -EINVAL;
+ }
+ break;
+
+ case XEN_DOMCTL_assign_device:
+ if ( unlikely(d->is_dying) )
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ ret = xsm_assign_device(XSM_HOOK, d, domctl->u.assign_device.machine_sbdf);
+ if ( ret )
+ break;
+
+ seg = domctl->u.assign_device.machine_sbdf >> 16;
+ bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff;
+ devfn = domctl->u.assign_device.machine_sbdf & 0xff;
+
+ ret = device_assigned(seg, bus, devfn) ?:
+ assign_device(d, seg, bus, devfn);
+ if ( ret == -ERESTART )
+ ret = hypercall_create_continuation(__HYPERVISOR_domctl,
+ "h", u_domctl);
+ else if ( ret )
+ printk(XENLOG_G_ERR "XEN_DOMCTL_assign_device: "
+ "assign %04x:%02x:%02x.%u to dom%d failed (%d)\n",
+ seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
+ d->domain_id, ret);
+
+ break;
+
+ case XEN_DOMCTL_deassign_device:
+ ret = xsm_deassign_device(XSM_HOOK, d, domctl->u.assign_device.machine_sbdf);
+ if ( ret )
+ break;
+
+ seg = domctl->u.assign_device.machine_sbdf >> 16;
+ bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff;
+ devfn = domctl->u.assign_device.machine_sbdf & 0xff;
+
+ spin_lock(&pcidevs_lock);
+ ret = deassign_device(d, seg, bus, devfn);
+ spin_unlock(&pcidevs_lock);
+ if ( ret )
+ printk(XENLOG_G_ERR
+ "deassign %04x:%02x:%02x.%u from dom%d failed (%d)\n",
+ seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
+ d->domain_id, ret);
+
+ break;
+
+ default:
+ ret = -ENOSYS;
+ break;
+ }
+
+ return ret;
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/drivers/passthrough/vtd/extern.h b/xen/drivers/passthrough/vtd/extern.h
index afe7faf..5524dba 100644
--- a/xen/drivers/passthrough/vtd/extern.h
+++ b/xen/drivers/passthrough/vtd/extern.h
@@ -42,13 +42,6 @@ void iommu_flush_cache_page(void *addr, unsigned long npages);
int iommu_alloc(struct acpi_drhd_unit *drhd);
void iommu_free(struct acpi_drhd_unit *drhd);
-int queue_invalidate_context(struct iommu *iommu,
- u16 did, u16 source_id, u8 function_mask, u8 granu);
-int queue_invalidate_iotlb(struct iommu *iommu,
- u8 granu, u8 dr, u8 dw, u16 did, u8 am, u8 ih, u64 addr);
-int queue_invalidate_iec(struct iommu *iommu,
- u8 granu, u8 im, u16 iidx);
-int invalidate_sync(struct iommu *iommu);
int iommu_flush_iec_global(struct iommu *iommu);
int iommu_flush_iec_index(struct iommu *iommu, u8 im, u16 iidx);
void clear_fault_bits(struct iommu *iommu);
@@ -103,4 +96,6 @@ void pci_vtd_quirk(const struct pci_dev *);
int platform_supports_intremap(void);
int platform_supports_x2apic(void);
+void vtd_set_hwdom_mapping(struct domain *d);
+
#endif // _VTD_EXTERN_H_
diff --git a/xen/drivers/passthrough/vtd/intremap.c b/xen/drivers/passthrough/vtd/intremap.c
index 2f8b9eb..0333686 100644
--- a/xen/drivers/passthrough/vtd/intremap.c
+++ b/xen/drivers/passthrough/vtd/intremap.c
@@ -358,7 +358,6 @@ static int ioapic_rte_to_remap_entry(struct iommu *iommu,
memcpy(iremap_entry, &new_ire, sizeof(struct iremap_entry));
iommu_flush_cache_entry(iremap_entry, sizeof(struct iremap_entry));
iommu_flush_iec_index(iommu, 0, index);
- invalidate_sync(iommu);
unmap_vtd_domain_page(iremap_entries);
spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);
@@ -535,7 +534,7 @@ static int remap_entry_to_msi_msg(
msg->dest32 = iremap_entry->lo.dst;
else
msg->dest32 = (iremap_entry->lo.dst >> 8) & 0xff;
- msg->address_lo |= (msg->dest32 & 0xff) << MSI_ADDR_DEST_ID_SHIFT;
+ msg->address_lo |= MSI_ADDR_DEST_ID(msg->dest32);
msg->data =
MSI_DATA_TRIGGER_EDGE |
@@ -643,7 +642,6 @@ static int msi_msg_to_remap_entry(
memcpy(iremap_entry, &new_ire, sizeof(struct iremap_entry));
iommu_flush_cache_entry(iremap_entry, sizeof(struct iremap_entry));
iommu_flush_iec_index(iommu, 0, index);
- invalidate_sync(iommu);
unmap_vtd_domain_page(iremap_entries);
spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);
diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c
index e543c08..19d8165 100644
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -23,6 +23,7 @@
#include <xen/sched.h>
#include <xen/xmalloc.h>
#include <xen/domain_page.h>
+#include <xen/iocap.h>
#include <xen/iommu.h>
#include <asm/hvm/iommu.h>
#include <xen/numa.h>
@@ -55,8 +56,8 @@ int nr_iommus;
static struct tasklet vtd_fault_tasklet;
-static int setup_dom0_device(u8 devfn, struct pci_dev *);
-static void setup_dom0_rmrr(struct domain *d);
+static int setup_hwdom_device(u8 devfn, struct pci_dev *);
+static void setup_hwdom_rmrr(struct domain *d);
static int domain_iommu_domid(struct domain *d,
struct iommu *iommu)
@@ -147,7 +148,6 @@ static struct intel_iommu *__init alloc_intel_iommu(void)
if ( intel == NULL )
return NULL;
- spin_lock_init(&intel->qi_ctrl.qinval_lock);
spin_lock_init(&intel->ir_ctrl.iremap_lock);
return intel;
@@ -254,16 +254,16 @@ static u64 addr_to_dma_page_maddr(struct domain *domain, u64 addr, int alloc)
struct acpi_drhd_unit *drhd;
struct pci_dev *pdev;
struct hvm_iommu *hd = domain_hvm_iommu(domain);
- int addr_width = agaw_to_width(hd->agaw);
+ int addr_width = agaw_to_width(hd->arch.agaw);
struct dma_pte *parent, *pte = NULL;
- int level = agaw_to_level(hd->agaw);
+ int level = agaw_to_level(hd->arch.agaw);
int offset;
u64 pte_maddr = 0, maddr;
u64 *vaddr = NULL;
addr &= (((u64)1) << addr_width) - 1;
- ASSERT(spin_is_locked(&hd->mapping_lock));
- if ( hd->pgd_maddr == 0 )
+ ASSERT(spin_is_locked(&hd->arch.mapping_lock));
+ if ( hd->arch.pgd_maddr == 0 )
{
/*
* just get any passthrough device in the domainr - assume user
@@ -271,11 +271,11 @@ static u64 addr_to_dma_page_maddr(struct domain *domain, u64 addr, int alloc)
*/
pdev = pci_get_pdev_by_domain(domain, -1, -1, -1);
drhd = acpi_find_matched_drhd_unit(pdev);
- if ( !alloc || ((hd->pgd_maddr = alloc_pgtable_maddr(drhd, 1)) == 0) )
+ if ( !alloc || ((hd->arch.pgd_maddr = alloc_pgtable_maddr(drhd, 1)) == 0) )
goto out;
}
- parent = (struct dma_pte *)map_vtd_domain_page(hd->pgd_maddr);
+ parent = (struct dma_pte *)map_vtd_domain_page(hd->arch.pgd_maddr);
while ( level > 1 )
{
offset = address_level_offset(addr, level);
@@ -585,7 +585,7 @@ static void __intel_iommu_iotlb_flush(struct domain *d, unsigned long gfn,
{
iommu = drhd->iommu;
- if ( !test_bit(iommu->index, &hd->iommu_bitmap) )
+ if ( !test_bit(iommu->index, &hd->arch.iommu_bitmap) )
continue;
flush_dev_iotlb = find_ats_dev_drhd(iommu) ? 1 : 0;
@@ -626,12 +626,12 @@ static void dma_pte_clear_one(struct domain *domain, u64 addr)
struct dma_pte *page = NULL, *pte = NULL;
u64 pg_maddr;
- spin_lock(&hd->mapping_lock);
+ spin_lock(&hd->arch.mapping_lock);
/* get last level pte */
pg_maddr = addr_to_dma_page_maddr(domain, addr, 0);
if ( pg_maddr == 0 )
{
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
return;
}
@@ -640,13 +640,13 @@ static void dma_pte_clear_one(struct domain *domain, u64 addr)
if ( !dma_pte_present(*pte) )
{
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
unmap_vtd_domain_page(page);
return;
}
dma_clear_pte(*pte);
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
iommu_flush_cache_entry(pte, sizeof(struct dma_pte));
if ( !this_cpu(iommu_dont_flush_iotlb) )
@@ -1044,7 +1044,7 @@ static void dma_msi_set_affinity(struct irq_desc *desc, const cpumask_t *mask)
if (x2apic_enabled)
msg.address_hi = dest & 0xFFFFFF00;
msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
- msg.address_lo |= MSI_ADDR_DEST_ID(dest & 0xff);
+ msg.address_lo |= MSI_ADDR_DEST_ID(dest);
iommu->msi.msg = msg;
spin_lock_irqsave(&iommu->register_lock, flags);
@@ -1082,7 +1082,7 @@ static int __init iommu_set_interrupt(struct acpi_drhd_unit *drhd)
desc = irq_to_desc(irq);
desc->handler = &dma_msi_type;
- ret = request_irq(irq, iommu_page_fault, "dmar", iommu);
+ ret = request_irq(irq, 0, iommu_page_fault, "dmar", iommu);
if ( ret )
{
desc->handler = &no_irq_type;
@@ -1237,28 +1237,31 @@ static int intel_iommu_domain_init(struct domain *d)
{
struct hvm_iommu *hd = domain_hvm_iommu(d);
- hd->agaw = width_to_agaw(DEFAULT_DOMAIN_ADDRESS_WIDTH);
+ hd->arch.agaw = width_to_agaw(DEFAULT_DOMAIN_ADDRESS_WIDTH);
return 0;
}
-static void __init intel_iommu_dom0_init(struct domain *d)
+static void __hwdom_init intel_iommu_hwdom_init(struct domain *d)
{
struct acpi_drhd_unit *drhd;
if ( !iommu_passthrough && !need_iommu(d) )
{
- /* Set up 1:1 page table for dom0 */
- iommu_set_dom0_mapping(d);
+ /* Set up 1:1 page table for hardware domain. */
+ vtd_set_hwdom_mapping(d);
}
- setup_dom0_pci_devices(d, setup_dom0_device);
- setup_dom0_rmrr(d);
+ setup_hwdom_pci_devices(d, setup_hwdom_device);
+ setup_hwdom_rmrr(d);
iommu_flush_all();
for_each_drhd_unit ( drhd )
{
+ if ( iomem_deny_access(d, PFN_DOWN(drhd->address),
+ PFN_DOWN(drhd->address)) )
+ BUG();
iommu_enable_translation(drhd);
}
}
@@ -1327,23 +1330,23 @@ int domain_context_mapping_one(
return res;
}
- if ( iommu_passthrough && (domain->domain_id == 0) )
+ if ( iommu_passthrough && is_hardware_domain(domain) )
{
context_set_translation_type(*context, CONTEXT_TT_PASS_THRU);
agaw = level_to_agaw(iommu->nr_pt_levels);
}
else
{
- spin_lock(&hd->mapping_lock);
+ spin_lock(&hd->arch.mapping_lock);
/* Ensure we have pagetables allocated down to leaf PTE. */
- if ( hd->pgd_maddr == 0 )
+ if ( hd->arch.pgd_maddr == 0 )
{
addr_to_dma_page_maddr(domain, 0, 1);
- if ( hd->pgd_maddr == 0 )
+ if ( hd->arch.pgd_maddr == 0 )
{
nomem:
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
spin_unlock(&iommu->lock);
unmap_vtd_domain_page(context_entries);
return -ENOMEM;
@@ -1351,7 +1354,7 @@ int domain_context_mapping_one(
}
/* Skip top levels of page tables for 2- and 3-level DRHDs. */
- pgd_maddr = hd->pgd_maddr;
+ pgd_maddr = hd->arch.pgd_maddr;
for ( agaw = level_to_agaw(4);
agaw != level_to_agaw(iommu->nr_pt_levels);
agaw-- )
@@ -1369,7 +1372,7 @@ int domain_context_mapping_one(
else
context_set_translation_type(*context, CONTEXT_TT_MULTI_LEVEL);
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
}
if ( context_set_domain_id(context, domain, iommu) )
@@ -1395,7 +1398,7 @@ int domain_context_mapping_one(
iommu_flush_iotlb_dsi(iommu, 0, 1, flush_dev_iotlb);
}
- set_bit(iommu->index, &hd->iommu_bitmap);
+ set_bit(iommu->index, &hd->arch.iommu_bitmap);
unmap_vtd_domain_page(context_entries);
@@ -1641,7 +1644,7 @@ static int domain_context_unmap(
struct hvm_iommu *hd = domain_hvm_iommu(domain);
int iommu_domid;
- clear_bit(iommu->index, &hd->iommu_bitmap);
+ clear_bit(iommu->index, &hd->arch.iommu_bitmap);
iommu_domid = domain_iommu_domid(domain, iommu);
if ( iommu_domid == -1 )
@@ -1658,39 +1661,7 @@ out:
return ret;
}
-static int reassign_device_ownership(
- struct domain *source,
- struct domain *target,
- u8 devfn, struct pci_dev *pdev)
-{
- int ret;
-
- /*
- * Devices assigned to untrusted domains (here assumed to be any domU)
- * can attempt to send arbitrary LAPIC/MSI messages. We are unprotected
- * by the root complex unless interrupt remapping is enabled.
- */
- if ( (target != dom0) && !iommu_intremap )
- untrusted_msi = 1;
-
- ret = domain_context_unmap(source, devfn, pdev);
- if ( ret )
- return ret;
-
- ret = domain_context_mapping(target, devfn, pdev);
- if ( ret )
- return ret;
-
- if ( devfn == pdev->devfn )
- {
- list_move(&pdev->domain_list, &target->arch.pdev_list);
- pdev->domain = target;
- }
-
- return ret;
-}
-
-void iommu_domain_teardown(struct domain *d)
+static void iommu_domain_teardown(struct domain *d)
{
struct hvm_iommu *hd = domain_hvm_iommu(d);
struct mapped_rmrr *mrmrr, *tmp;
@@ -1698,7 +1669,7 @@ void iommu_domain_teardown(struct domain *d)
if ( list_empty(&acpi_drhd_units) )
return;
- list_for_each_entry_safe ( mrmrr, tmp, &hd->mapped_rmrrs, list )
+ list_for_each_entry_safe ( mrmrr, tmp, &hd->arch.mapped_rmrrs, list )
{
list_del(&mrmrr->list);
xfree(mrmrr);
@@ -1707,10 +1678,10 @@ void iommu_domain_teardown(struct domain *d)
if ( iommu_use_hap_pt(d) )
return;
- spin_lock(&hd->mapping_lock);
- iommu_free_pagetable(hd->pgd_maddr, agaw_to_level(hd->agaw));
- hd->pgd_maddr = 0;
- spin_unlock(&hd->mapping_lock);
+ spin_lock(&hd->arch.mapping_lock);
+ iommu_free_pagetable(hd->arch.pgd_maddr, agaw_to_level(hd->arch.agaw));
+ hd->arch.pgd_maddr = 0;
+ spin_unlock(&hd->arch.mapping_lock);
}
static int intel_iommu_map_page(
@@ -1725,16 +1696,16 @@ static int intel_iommu_map_page(
if ( iommu_use_hap_pt(d) )
return 0;
- /* do nothing if dom0 and iommu supports pass thru */
- if ( iommu_passthrough && (d->domain_id == 0) )
+ /* Do nothing if hardware domain and iommu supports pass thru. */
+ if ( iommu_passthrough && is_hardware_domain(d) )
return 0;
- spin_lock(&hd->mapping_lock);
+ spin_lock(&hd->arch.mapping_lock);
pg_maddr = addr_to_dma_page_maddr(d, (paddr_t)gfn << PAGE_SHIFT_4K, 1);
if ( pg_maddr == 0 )
{
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
return -ENOMEM;
}
page = (struct dma_pte *)map_vtd_domain_page(pg_maddr);
@@ -1751,14 +1722,14 @@ static int intel_iommu_map_page(
if ( old.val == new.val )
{
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
unmap_vtd_domain_page(page);
return 0;
}
*pte = new;
iommu_flush_cache_entry(pte, sizeof(struct dma_pte));
- spin_unlock(&hd->mapping_lock);
+ spin_unlock(&hd->arch.mapping_lock);
unmap_vtd_domain_page(page);
if ( !this_cpu(iommu_dont_flush_iotlb) )
@@ -1769,8 +1740,8 @@ static int intel_iommu_map_page(
static int intel_iommu_unmap_page(struct domain *d, unsigned long gfn)
{
- /* Do nothing if dom0 and iommu supports pass thru. */
- if ( iommu_passthrough && (d->domain_id == 0) )
+ /* Do nothing if hardware domain and iommu supports pass thru. */
+ if ( iommu_passthrough && is_hardware_domain(d) )
return 0;
dma_pte_clear_one(d, (paddr_t)gfn << PAGE_SHIFT_4K);
@@ -1792,7 +1763,7 @@ void iommu_pte_flush(struct domain *d, u64 gfn, u64 *pte,
for_each_drhd_unit ( drhd )
{
iommu = drhd->iommu;
- if ( !test_bit(iommu->index, &hd->iommu_bitmap) )
+ if ( !test_bit(iommu->index, &hd->arch.iommu_bitmap) )
continue;
flush_dev_iotlb = find_ats_dev_drhd(iommu) ? 1 : 0;
@@ -1806,7 +1777,7 @@ void iommu_pte_flush(struct domain *d, u64 gfn, u64 *pte,
}
}
-static int vtd_ept_page_compatible(struct iommu *iommu)
+static int __init vtd_ept_page_compatible(struct iommu *iommu)
{
u64 ept_cap, vtd_cap = iommu->cap;
@@ -1815,14 +1786,14 @@ static int vtd_ept_page_compatible(struct iommu *iommu)
if ( rdmsr_safe(MSR_IA32_VMX_EPT_VPID_CAP, ept_cap) != 0 )
return 0;
- return ( ept_has_2mb(ept_cap) == cap_sps_2mb(vtd_cap)
- && ept_has_1gb(ept_cap) == cap_sps_1gb(vtd_cap) );
+ return (ept_has_2mb(ept_cap) && opt_hap_2mb) == cap_sps_2mb(vtd_cap) &&
+ (ept_has_1gb(ept_cap) && opt_hap_1gb) == cap_sps_1gb(vtd_cap);
}
/*
* set VT-d page table directory to EPT table if allowed
*/
-void iommu_set_pgd(struct domain *d)
+static void iommu_set_pgd(struct domain *d)
{
struct hvm_iommu *hd = domain_hvm_iommu(d);
mfn_t pgd_mfn;
@@ -1833,14 +1804,14 @@ void iommu_set_pgd(struct domain *d)
return;
pgd_mfn = pagetable_get_mfn(p2m_get_pagetable(p2m_get_hostp2m(d)));
- hd->pgd_maddr = pagetable_get_paddr(pagetable_from_mfn(pgd_mfn));
+ hd->arch.pgd_maddr = pagetable_get_paddr(pagetable_from_mfn(pgd_mfn));
}
-static int rmrr_identity_mapping(struct domain *d,
- struct acpi_rmrr_unit *rmrr)
+static int rmrr_identity_mapping(struct domain *d, bool_t map,
+ const struct acpi_rmrr_unit *rmrr)
{
- u64 base, end;
- unsigned long base_pfn, end_pfn;
+ unsigned long base_pfn = rmrr->base_address >> PAGE_SHIFT_4K;
+ unsigned long end_pfn = PAGE_ALIGN_4K(rmrr->end_address) >> PAGE_SHIFT_4K;
struct mapped_rmrr *mrmrr;
struct hvm_iommu *hd = domain_hvm_iommu(d);
@@ -1848,29 +1819,48 @@ static int rmrr_identity_mapping(struct domain *d,
ASSERT(rmrr->base_address < rmrr->end_address);
/*
- * No need to acquire hd->mapping_lock: Both insertion and removal
+ * No need to acquire hd->arch.mapping_lock: Both insertion and removal
* get done while holding pcidevs_lock.
*/
- list_for_each_entry( mrmrr, &hd->mapped_rmrrs, list )
+ list_for_each_entry( mrmrr, &hd->arch.mapped_rmrrs, list )
{
if ( mrmrr->base == rmrr->base_address &&
mrmrr->end == rmrr->end_address )
{
- ++mrmrr->count;
- return 0;
+ int ret = 0;
+
+ if ( map )
+ {
+ ++mrmrr->count;
+ return 0;
+ }
+
+ if ( --mrmrr->count )
+ return 0;
+
+ while ( base_pfn < end_pfn )
+ {
+ if ( intel_iommu_unmap_page(d, base_pfn) )
+ ret = -ENXIO;
+ base_pfn++;
+ }
+
+ list_del(&mrmrr->list);
+ xfree(mrmrr);
+ return ret;
}
}
- base = rmrr->base_address & PAGE_MASK_4K;
- base_pfn = base >> PAGE_SHIFT_4K;
- end = PAGE_ALIGN_4K(rmrr->end_address);
- end_pfn = end >> PAGE_SHIFT_4K;
+ if ( !map )
+ return -ENOENT;
while ( base_pfn < end_pfn )
{
- if ( intel_iommu_map_page(d, base_pfn, base_pfn,
- IOMMUF_readable|IOMMUF_writable) )
- return -1;
+ int err = intel_iommu_map_page(d, base_pfn, base_pfn,
+ IOMMUF_readable|IOMMUF_writable);
+
+ if ( err )
+ return err;
base_pfn++;
}
@@ -1880,7 +1870,7 @@ static int rmrr_identity_mapping(struct domain *d,
mrmrr->base = rmrr->base_address;
mrmrr->end = rmrr->end_address;
mrmrr->count = 1;
- list_add_tail(&mrmrr->list, &hd->mapped_rmrrs);
+ list_add_tail(&mrmrr->list, &hd->arch.mapped_rmrrs);
return 0;
}
@@ -1910,14 +1900,14 @@ static int intel_iommu_add_device(u8 devfn, struct pci_dev *pdev)
PCI_BUS(bdf) == pdev->bus &&
PCI_DEVFN2(bdf) == devfn )
{
- ret = rmrr_identity_mapping(pdev->domain, rmrr);
+ ret = rmrr_identity_mapping(pdev->domain, 1, rmrr);
if ( ret )
dprintk(XENLOG_ERR VTDPREFIX, "d%d: RMRR mapping failed\n",
pdev->domain->domain_id);
}
}
- return ret;
+ return 0;
}
static int intel_iommu_enable_device(struct pci_dev *pdev)
@@ -1946,57 +1936,18 @@ static int intel_iommu_remove_device(u8 devfn, struct pci_dev *pdev)
for_each_rmrr_device ( rmrr, bdf, i )
{
- struct hvm_iommu *hd;
- struct mapped_rmrr *mrmrr, *tmp;
-
if ( rmrr->segment != pdev->seg ||
PCI_BUS(bdf) != pdev->bus ||
PCI_DEVFN2(bdf) != devfn )
continue;
- /*
- * If the device belongs to dom0, and it has RMRR, don't remove
- * it from dom0, because BIOS may use RMRR at booting time.
- */
- if ( is_hardware_domain(pdev->domain) )
- return 0;
-
- hd = domain_hvm_iommu(pdev->domain);
-
- /*
- * No need to acquire hd->mapping_lock: Both insertion and removal
- * get done while holding pcidevs_lock.
- */
- ASSERT(spin_is_locked(&pcidevs_lock));
- list_for_each_entry_safe ( mrmrr, tmp, &hd->mapped_rmrrs, list )
- {
- unsigned long base_pfn, end_pfn;
-
- if ( rmrr->base_address != mrmrr->base ||
- rmrr->end_address != mrmrr->end )
- continue;
-
- if ( --mrmrr->count )
- break;
-
- base_pfn = (mrmrr->base & PAGE_MASK_4K) >> PAGE_SHIFT_4K;
- end_pfn = PAGE_ALIGN_4K(mrmrr->end) >> PAGE_SHIFT_4K;
- while ( base_pfn < end_pfn )
- {
- if ( intel_iommu_unmap_page(pdev->domain, base_pfn) )
- return -ENXIO;
- base_pfn++;
- }
-
- list_del(&mrmrr->list);
- xfree(mrmrr);
- }
+ rmrr_identity_mapping(pdev->domain, 0, rmrr);
}
return domain_context_unmap(pdev->domain, devfn, pdev);
}
-static int __init setup_dom0_device(u8 devfn, struct pci_dev *pdev)
+static int __hwdom_init setup_hwdom_device(u8 devfn, struct pci_dev *pdev)
{
return domain_context_mapping(pdev->domain, devfn, pdev);
}
@@ -2139,7 +2090,7 @@ static int init_vtd_hw(void)
return 0;
}
-static void __init setup_dom0_rmrr(struct domain *d)
+static void __hwdom_init setup_hwdom_rmrr(struct domain *d)
{
struct acpi_rmrr_unit *rmrr;
u16 bdf;
@@ -2148,7 +2099,7 @@ static void __init setup_dom0_rmrr(struct domain *d)
spin_lock(&pcidevs_lock);
for_each_rmrr_device ( rmrr, bdf, i )
{
- ret = rmrr_identity_mapping(d, rmrr);
+ ret = rmrr_identity_mapping(d, 1, rmrr);
if ( ret )
dprintk(XENLOG_ERR VTDPREFIX,
"IOMMU: mapping reserved region failed\n");
@@ -2258,6 +2209,62 @@ int __init intel_vtd_setup(void)
return ret;
}
+static int reassign_device_ownership(
+ struct domain *source,
+ struct domain *target,
+ u8 devfn, struct pci_dev *pdev)
+{
+ int ret;
+
+ /*
+ * Devices assigned to untrusted domains (here assumed to be any domU)
+ * can attempt to send arbitrary LAPIC/MSI messages. We are unprotected
+ * by the root complex unless interrupt remapping is enabled.
+ */
+ if ( (target != hardware_domain) && !iommu_intremap )
+ untrusted_msi = 1;
+
+ /*
+ * If the device belongs to the hardware domain, and it has RMRR, don't
+ * remove it from the hardware domain, because BIOS may use RMRR at
+ * booting time. Also account for the special casing of USB below (in
+ * intel_iommu_assign_device()).
+ */
+ if ( !is_hardware_domain(source) &&
+ !is_usb_device(pdev->seg, pdev->bus, pdev->devfn) )
+ {
+ const struct acpi_rmrr_unit *rmrr;
+ u16 bdf;
+ unsigned int i;
+
+ for_each_rmrr_device( rmrr, bdf, i )
+ if ( rmrr->segment == pdev->seg &&
+ PCI_BUS(bdf) == pdev->bus &&
+ PCI_DEVFN2(bdf) == devfn )
+ {
+ ret = rmrr_identity_mapping(source, 0, rmrr);
+ if ( ret != -ENOENT )
+ return ret;
+ }
+ }
+
+ ret = domain_context_unmap(source, devfn, pdev);
+ if ( ret )
+ return ret;
+
+ ret = domain_context_mapping(target, devfn, pdev);
+ if ( ret )
+ return ret;
+
+ if ( devfn == pdev->devfn )
+ {
+ list_move(&pdev->domain_list, &target->arch.pdev_list);
+ pdev->domain = target;
+ }
+
+ return ret;
+}
+
static int intel_iommu_assign_device(
struct domain *d, u8 devfn, struct pci_dev *pdev)
{
@@ -2269,9 +2276,9 @@ static int intel_iommu_assign_device(
if ( list_empty(&acpi_drhd_units) )
return -ENODEV;
- ret = reassign_device_ownership(dom0, d, devfn, pdev);
+ ret = reassign_device_ownership(hardware_domain, d, devfn, pdev);
if ( ret )
- goto done;
+ return ret;
/* FIXME: Because USB RMRR conflicts with guest bios region,
* ignore USB RMRR temporarily.
@@ -2279,10 +2286,7 @@ static int intel_iommu_assign_device(
seg = pdev->seg;
bus = pdev->bus;
if ( is_usb_device(seg, bus, pdev->devfn) )
- {
- ret = 0;
- goto done;
- }
+ return 0;
/* Setup rmrr identity mapping */
for_each_rmrr_device( rmrr, bdf, i )
@@ -2291,17 +2295,19 @@ static int intel_iommu_assign_device(
PCI_BUS(bdf) == bus &&
PCI_DEVFN2(bdf) == devfn )
{
- ret = rmrr_identity_mapping(d, rmrr);
+ ret = rmrr_identity_mapping(d, 1, rmrr);
if ( ret )
{
- dprintk(XENLOG_ERR VTDPREFIX,
- "IOMMU: mapping reserved region failed\n");
- goto done;
+ reassign_device_ownership(d, hardware_domain, devfn, pdev);
+ printk(XENLOG_G_ERR VTDPREFIX
+ " cannot map reserved region (%"PRIx64",%"PRIx64"] for Dom%d (%d)\n",
+ rmrr->base_address, rmrr->end_address,
+ d->domain_id, ret);
+ break;
}
}
}
-done:
return ret;
}
@@ -2457,13 +2463,13 @@ static void vtd_dump_p2m_table(struct domain *d)
return;
hd = domain_hvm_iommu(d);
- printk("p2m table has %d levels\n", agaw_to_level(hd->agaw));
- vtd_dump_p2m_table_level(hd->pgd_maddr, agaw_to_level(hd->agaw), 0, 0);
+ printk("p2m table has %d levels\n", agaw_to_level(hd->arch.agaw));
+ vtd_dump_p2m_table_level(hd->arch.pgd_maddr, agaw_to_level(hd->arch.agaw), 0, 0);
}
const struct iommu_ops intel_iommu_ops = {
.init = intel_iommu_domain_init,
- .dom0_init = intel_iommu_dom0_init,
+ .hwdom_init = intel_iommu_hwdom_init,
.add_device = intel_iommu_add_device,
.enable_device = intel_iommu_enable_device,
.remove_device = intel_iommu_remove_device,
diff --git a/xen/drivers/passthrough/vtd/iommu.h b/xen/drivers/passthrough/vtd/iommu.h
index 1a1f20a..6b2cf1a 100644
--- a/xen/drivers/passthrough/vtd/iommu.h
+++ b/xen/drivers/passthrough/vtd/iommu.h
@@ -487,8 +487,6 @@ extern struct list_head acpi_ioapic_units;
struct qi_ctrl {
u64 qinval_maddr; /* queue invalidation page machine address */
- int qinval_index; /* queue invalidation index */
- spinlock_t qinval_lock; /* lock for queue invalidation page */
};
struct ir_ctrl {
diff --git a/xen/drivers/passthrough/vtd/qinval.c b/xen/drivers/passthrough/vtd/qinval.c
index fe29e82..4603020 100644
--- a/xen/drivers/passthrough/vtd/qinval.c
+++ b/xen/drivers/passthrough/vtd/qinval.c
@@ -43,7 +43,7 @@ static void print_qi_regs(struct iommu *iommu)
printk("DMAR_IQT_REG = %"PRIx64"\n", val);
}
-static int qinval_next_index(struct iommu *iommu)
+static unsigned int qinval_next_index(struct iommu *iommu)
{
u64 tail;
@@ -58,7 +58,7 @@ static int qinval_next_index(struct iommu *iommu)
return tail;
}
-static int qinval_update_qtail(struct iommu *iommu, int index)
+static void qinval_update_qtail(struct iommu *iommu, unsigned int index)
{
u64 val;
@@ -66,22 +66,23 @@ static int qinval_update_qtail(struct iommu *iommu, int index)
ASSERT( spin_is_locked(&iommu->register_lock) );
val = (index + 1) % QINVAL_ENTRY_NR;
dmar_writeq(iommu->reg, DMAR_IQT_REG, (val << QINVAL_INDEX_SHIFT));
- return 0;
}
-static int gen_cc_inv_dsc(struct iommu *iommu, int index,
+static void queue_invalidate_context(struct iommu *iommu,
u16 did, u16 source_id, u8 function_mask, u8 granu)
{
unsigned long flags;
- struct qinval_entry *qinval_entry = NULL, *qinval_entries;
- struct qi_ctrl *qi_ctrl = iommu_qi_ctrl(iommu);
- u64 entry_base = qi_ctrl->qinval_maddr +
- (( index >> QINVAL_ENTRY_ORDER ) << PAGE_SHIFT );
+ unsigned int index;
+ u64 entry_base;
+ struct qinval_entry *qinval_entry, *qinval_entries;
- spin_lock_irqsave(&qi_ctrl->qinval_lock, flags);
- qinval_entries =
- (struct qinval_entry *)map_vtd_domain_page(entry_base);
+ spin_lock_irqsave(&iommu->register_lock, flags);
+ index = qinval_next_index(iommu);
+ entry_base = iommu_qi_ctrl(iommu)->qinval_maddr +
+ ((index >> QINVAL_ENTRY_ORDER) << PAGE_SHIFT);
+ qinval_entries = map_vtd_domain_page(entry_base);
qinval_entry = &qinval_entries[index % (1 << QINVAL_ENTRY_ORDER)];
+
qinval_entry->q.cc_inv_dsc.lo.type = TYPE_INVAL_CONTEXT;
qinval_entry->q.cc_inv_dsc.lo.granu = granu;
qinval_entry->q.cc_inv_dsc.lo.res_1 = 0;
@@ -91,44 +92,27 @@ static int gen_cc_inv_dsc(struct iommu *iommu, int index,
qinval_entry->q.cc_inv_dsc.lo.res_2 = 0;
qinval_entry->q.cc_inv_dsc.hi.res = 0;
- unmap_vtd_domain_page(qinval_entries);
- spin_unlock_irqrestore(&qi_ctrl->qinval_lock, flags);
+ qinval_update_qtail(iommu, index);
+ spin_unlock_irqrestore(&iommu->register_lock, flags);
- return 0;
+ unmap_vtd_domain_page(qinval_entries);
}
-int queue_invalidate_context(struct iommu *iommu,
- u16 did, u16 source_id, u8 function_mask, u8 granu)
+static void queue_invalidate_iotlb(struct iommu *iommu,
+ u8 granu, u8 dr, u8 dw, u16 did, u8 am, u8 ih, u64 addr)
{
- int ret = -1;
unsigned long flags;
- int index = -1;
+ unsigned int index;
+ u64 entry_base;
+ struct qinval_entry *qinval_entry, *qinval_entries;
spin_lock_irqsave(&iommu->register_lock, flags);
index = qinval_next_index(iommu);
- if ( index == -1 )
- return -EBUSY;
- ret = gen_cc_inv_dsc(iommu, index, did, source_id,
- function_mask, granu);
- ret |= qinval_update_qtail(iommu, index);
- spin_unlock_irqrestore(&iommu->register_lock, flags);
- return ret;
-}
-
-static int gen_iotlb_inv_dsc(struct iommu *iommu, int index,
- u8 granu, u8 dr, u8 dw, u16 did, u8 am, u8 ih, u64 addr)
-{
- unsigned long flags;
- struct qinval_entry *qinval_entry = NULL, *qinval_entries;
- struct qi_ctrl *qi_ctrl = iommu_qi_ctrl(iommu);
- u64 entry_base = qi_ctrl->qinval_maddr +
- (( index >> QINVAL_ENTRY_ORDER ) << PAGE_SHIFT );
-
- spin_lock_irqsave(&qi_ctrl->qinval_lock, flags);
-
- qinval_entries =
- (struct qinval_entry *)map_vtd_domain_page(entry_base);
+ entry_base = iommu_qi_ctrl(iommu)->qinval_maddr +
+ ((index >> QINVAL_ENTRY_ORDER) << PAGE_SHIFT);
+ qinval_entries = map_vtd_domain_page(entry_base);
qinval_entry = &qinval_entries[index % (1 << QINVAL_ENTRY_ORDER)];
+
qinval_entry->q.iotlb_inv_dsc.lo.type = TYPE_INVAL_IOTLB;
qinval_entry->q.iotlb_inv_dsc.lo.granu = granu;
qinval_entry->q.iotlb_inv_dsc.lo.dr = dr;
@@ -143,71 +127,38 @@ static int gen_iotlb_inv_dsc(struct iommu *iommu, int index,
qinval_entry->q.iotlb_inv_dsc.hi.addr = addr >> PAGE_SHIFT_4K;
unmap_vtd_domain_page(qinval_entries);
- spin_unlock_irqrestore(&qi_ctrl->qinval_lock, flags);
- return 0;
+ qinval_update_qtail(iommu, index);
+ spin_unlock_irqrestore(&iommu->register_lock, flags);
}
-int queue_invalidate_iotlb(struct iommu *iommu,
- u8 granu, u8 dr, u8 dw, u16 did, u8 am, u8 ih, u64 addr)
+static int queue_invalidate_wait(struct iommu *iommu,
+ u8 iflag, u8 sw, u8 fn)
{
- int ret = -1;
+ s_time_t start_time;
+ volatile u32 poll_slot = QINVAL_STAT_INIT;
+ unsigned int index;
unsigned long flags;
- int index = -1;
+ u64 entry_base;
+ struct qinval_entry *qinval_entry, *qinval_entries;
spin_lock_irqsave(&iommu->register_lock, flags);
-
index = qinval_next_index(iommu);
- if ( index == -1 )
- return -EBUSY;
- ret = gen_iotlb_inv_dsc(iommu, index, granu, dr, dw, did,
- am, ih, addr);
- ret |= qinval_update_qtail(iommu, index);
- spin_unlock_irqrestore(&iommu->register_lock, flags);
- return ret;
-}
-
-static int gen_wait_dsc(struct iommu *iommu, int index,
- u8 iflag, u8 sw, u8 fn, u32 sdata, volatile u32 *saddr)
-{
- unsigned long flags;
- struct qinval_entry *qinval_entry = NULL, *qinval_entries;
- struct qi_ctrl *qi_ctrl = iommu_qi_ctrl(iommu);
- u64 entry_base = qi_ctrl->qinval_maddr +
- (( index >> QINVAL_ENTRY_ORDER ) << PAGE_SHIFT );
-
- spin_lock_irqsave(&qi_ctrl->qinval_lock, flags);
- qinval_entries =
- (struct qinval_entry *)map_vtd_domain_page(entry_base);
+ entry_base = iommu_qi_ctrl(iommu)->qinval_maddr +
+ ((index >> QINVAL_ENTRY_ORDER) << PAGE_SHIFT);
+ qinval_entries = map_vtd_domain_page(entry_base);
qinval_entry = &qinval_entries[index % (1 << QINVAL_ENTRY_ORDER)];
+
qinval_entry->q.inv_wait_dsc.lo.type = TYPE_INVAL_WAIT;
qinval_entry->q.inv_wait_dsc.lo.iflag = iflag;
qinval_entry->q.inv_wait_dsc.lo.sw = sw;
qinval_entry->q.inv_wait_dsc.lo.fn = fn;
qinval_entry->q.inv_wait_dsc.lo.res_1 = 0;
- qinval_entry->q.inv_wait_dsc.lo.sdata = sdata;
+ qinval_entry->q.inv_wait_dsc.lo.sdata = QINVAL_STAT_DONE;
qinval_entry->q.inv_wait_dsc.hi.res_1 = 0;
- qinval_entry->q.inv_wait_dsc.hi.saddr = virt_to_maddr(saddr) >> 2;
- unmap_vtd_domain_page(qinval_entries);
- spin_unlock_irqrestore(&qi_ctrl->qinval_lock, flags);
- return 0;
-}
+ qinval_entry->q.inv_wait_dsc.hi.saddr = virt_to_maddr(&poll_slot) >> 2;
-static int queue_invalidate_wait(struct iommu *iommu,
- u8 iflag, u8 sw, u8 fn)
-{
- s_time_t start_time;
- volatile u32 poll_slot = QINVAL_STAT_INIT;
- int index = -1;
- int ret = -1;
- unsigned long flags;
-
- spin_lock_irqsave(&iommu->register_lock, flags);
- index = qinval_next_index(iommu);
- if ( index == -1 )
- return -EBUSY;
-
- ret = gen_wait_dsc(iommu, index, iflag, sw, fn, QINVAL_STAT_DONE, &poll_slot);
- ret |= qinval_update_qtail(iommu, index);
+ unmap_vtd_domain_page(qinval_entries);
+ qinval_update_qtail(iommu, index);
spin_unlock_irqrestore(&iommu->register_lock, flags);
/* Now we don't support interrupt method */
@@ -224,37 +175,36 @@ static int queue_invalidate_wait(struct iommu *iommu,
}
cpu_relax();
}
+ return 0;
}
- return ret;
+
+ return -EOPNOTSUPP;
}
-int invalidate_sync(struct iommu *iommu)
+static int invalidate_sync(struct iommu *iommu)
{
- int ret = -1;
struct qi_ctrl *qi_ctrl = iommu_qi_ctrl(iommu);
- if ( qi_ctrl->qinval_maddr != 0 )
- {
- ret = queue_invalidate_wait(iommu, 0, 1, 1);
- return ret;
- }
+ if ( qi_ctrl->qinval_maddr )
+ return queue_invalidate_wait(iommu, 0, 1, 1);
return 0;
}
-static int gen_dev_iotlb_inv_dsc(struct iommu *iommu, int index,
+int qinval_device_iotlb(struct iommu *iommu,
u32 max_invs_pend, u16 sid, u16 size, u64 addr)
{
unsigned long flags;
- struct qinval_entry *qinval_entry = NULL, *qinval_entries;
- struct qi_ctrl *qi_ctrl = iommu_qi_ctrl(iommu);
- u64 entry_base = qi_ctrl->qinval_maddr +
- (( index >> QINVAL_ENTRY_ORDER ) << PAGE_SHIFT );
+ unsigned int index;
+ u64 entry_base;
+ struct qinval_entry *qinval_entry, *qinval_entries;
- spin_lock_irqsave(&qi_ctrl->qinval_lock, flags);
-
- qinval_entries =
- (struct qinval_entry *)map_vtd_domain_page(entry_base);
+ spin_lock_irqsave(&iommu->register_lock, flags);
+ index = qinval_next_index(iommu);
+ entry_base = iommu_qi_ctrl(iommu)->qinval_maddr +
+ ((index >> QINVAL_ENTRY_ORDER) << PAGE_SHIFT);
+ qinval_entries = map_vtd_domain_page(entry_base);
qinval_entry = &qinval_entries[index % (1 << QINVAL_ENTRY_ORDER)];
+
qinval_entry->q.dev_iotlb_inv_dsc.lo.type = TYPE_INVAL_DEVICE_IOTLB;
qinval_entry->q.dev_iotlb_inv_dsc.lo.res_1 = 0;
qinval_entry->q.dev_iotlb_inv_dsc.lo.max_invs_pend = max_invs_pend;
@@ -267,42 +217,26 @@ static int gen_dev_iotlb_inv_dsc(struct iommu *iommu, int index,
qinval_entry->q.dev_iotlb_inv_dsc.hi.addr = addr >> PAGE_SHIFT_4K;
unmap_vtd_domain_page(qinval_entries);
- spin_unlock_irqrestore(&qi_ctrl->qinval_lock, flags);
+ qinval_update_qtail(iommu, index);
+ spin_unlock_irqrestore(&iommu->register_lock, flags);
+
return 0;
}
-int qinval_device_iotlb(struct iommu *iommu,
- u32 max_invs_pend, u16 sid, u16 size, u64 addr)
+static void queue_invalidate_iec(struct iommu *iommu, u8 granu, u8 im, u16 iidx)
{
- int ret = -1;
unsigned long flags;
- int index = -1;
+ unsigned int index;
+ u64 entry_base;
+ struct qinval_entry *qinval_entry, *qinval_entries;
spin_lock_irqsave(&iommu->register_lock, flags);
index = qinval_next_index(iommu);
- if ( index == -1 )
- return -EBUSY;
- ret = gen_dev_iotlb_inv_dsc(iommu, index, max_invs_pend,
- sid, size, addr);
- ret |= qinval_update_qtail(iommu, index);
- spin_unlock_irqrestore(&iommu->register_lock, flags);
- return ret;
-}
-
-static int gen_iec_inv_dsc(struct iommu *iommu, int index,
- u8 granu, u8 im, u16 iidx)
-{
- unsigned long flags;
- struct qinval_entry *qinval_entry = NULL, *qinval_entries;
- struct qi_ctrl *qi_ctrl = iommu_qi_ctrl(iommu);
- u64 entry_base = qi_ctrl->qinval_maddr +
- (( index >> QINVAL_ENTRY_ORDER ) << PAGE_SHIFT );
-
- spin_lock_irqsave(&qi_ctrl->qinval_lock, flags);
-
- qinval_entries =
- (struct qinval_entry *)map_vtd_domain_page(entry_base);
+ entry_base = iommu_qi_ctrl(iommu)->qinval_maddr +
+ ((index >> QINVAL_ENTRY_ORDER) << PAGE_SHIFT);
+ qinval_entries = map_vtd_domain_page(entry_base);
qinval_entry = &qinval_entries[index % (1 << QINVAL_ENTRY_ORDER)];
+
qinval_entry->q.iec_inv_dsc.lo.type = TYPE_INVAL_IEC;
qinval_entry->q.iec_inv_dsc.lo.granu = granu;
qinval_entry->q.iec_inv_dsc.lo.res_1 = 0;
@@ -312,37 +246,22 @@ static int gen_iec_inv_dsc(struct iommu *iommu, int index,
qinval_entry->q.iec_inv_dsc.hi.res = 0;
unmap_vtd_domain_page(qinval_entries);
- spin_unlock_irqrestore(&qi_ctrl->qinval_lock, flags);
- return 0;
-}
-
-int queue_invalidate_iec(struct iommu *iommu, u8 granu, u8 im, u16 iidx)
-{
- int ret;
- unsigned long flags;
- int index = -1;
-
- spin_lock_irqsave(&iommu->register_lock, flags);
- index = qinval_next_index(iommu);
- if ( index == -1 )
- return -EBUSY;
- ret = gen_iec_inv_dsc(iommu, index, granu, im, iidx);
- ret |= qinval_update_qtail(iommu, index);
+ qinval_update_qtail(iommu, index);
spin_unlock_irqrestore(&iommu->register_lock, flags);
- return ret;
}
static int __iommu_flush_iec(struct iommu *iommu, u8 granu, u8 im, u16 iidx)
{
int ret;
- ret = queue_invalidate_iec(iommu, granu, im, iidx);
- ret |= invalidate_sync(iommu);
+ queue_invalidate_iec(iommu, granu, im, iidx);
+ ret = invalidate_sync(iommu);
/*
* reading vt-d architecture register will ensure
* draining happens in implementation independent way.
*/
(void)dmar_readq(iommu->reg, DMAR_CAP_REG);
+
return ret;
}
@@ -380,9 +299,9 @@ static int flush_context_qi(
if ( qi_ctrl->qinval_maddr != 0 )
{
- ret = queue_invalidate_context(iommu, did, sid, fm,
- type >> DMA_CCMD_INVL_GRANU_OFFSET);
- ret |= invalidate_sync(iommu);
+ queue_invalidate_context(iommu, did, sid, fm,
+ type >> DMA_CCMD_INVL_GRANU_OFFSET);
+ ret = invalidate_sync(iommu);
}
return ret;
}
@@ -413,18 +332,22 @@ static int flush_iotlb_qi(
if ( qi_ctrl->qinval_maddr != 0 )
{
+ int rc;
+
/* use queued invalidation */
if (cap_write_drain(iommu->cap))
dw = 1;
if (cap_read_drain(iommu->cap))
dr = 1;
/* Need to conside the ih bit later */
- ret = queue_invalidate_iotlb(iommu,
- (type >> DMA_TLB_FLUSH_GRANU_OFFSET), dr,
- dw, did, (u8)size_order, 0, addr);
+ queue_invalidate_iotlb(iommu,
+ type >> DMA_TLB_FLUSH_GRANU_OFFSET, dr,
+ dw, did, size_order, 0, addr);
if ( flush_dev_iotlb )
- ret |= dev_invalidate_iotlb(iommu, did, addr, size_order, type);
- ret |= invalidate_sync(iommu);
+ ret = dev_invalidate_iotlb(iommu, did, addr, size_order, type);
+ rc = invalidate_sync(iommu);
+ if ( !ret )
+ ret = rc;
}
return ret;
}
diff --git a/xen/drivers/passthrough/vtd/quirks.c b/xen/drivers/passthrough/vtd/quirks.c
index 647723d..839dc45 100644
--- a/xen/drivers/passthrough/vtd/quirks.c
+++ b/xen/drivers/passthrough/vtd/quirks.c
@@ -117,7 +117,7 @@ static void __init snb_errata_init(void)
*/
static void __init map_igd_reg(void)
{
- u64 igd_mmio, igd_reg;
+ u64 igd_mmio;
if ( !is_cantiga_b3 && !is_snb_gfx )
return;
@@ -125,16 +125,10 @@ static void __init map_igd_reg(void)
if ( igd_reg_va )
return;
- /* get IGD mmio address in PCI BAR */
- igd_mmio = ((u64)pci_conf_read32(0, 0, IGD_DEV, 0, 0x14) << 32) +
- pci_conf_read32(0, 0, IGD_DEV, 0, 0x10);
-
- /* offset of IGD regster we want to access is in 0x2000 range */
- igd_reg = (igd_mmio & IGD_BAR_MASK) + 0x2000;
-
- /* ioremap this physical page */
- set_fixmap_nocache(FIX_IGD_MMIO, igd_reg);
- igd_reg_va = (u8 *)fix_to_virt(FIX_IGD_MMIO);
+ igd_mmio = pci_conf_read32(0, 0, IGD_DEV, 0, PCI_BASE_ADDRESS_1);
+ igd_mmio <<= 32;
+ igd_mmio += pci_conf_read32(0, 0, IGD_DEV, 0, PCI_BASE_ADDRESS_0);
+ igd_reg_va = ioremap(igd_mmio & IGD_BAR_MASK, 0x3000);
}
/*
@@ -152,12 +146,10 @@ static int cantiga_vtd_ops_preamble(struct iommu* iommu)
return 0;
/*
- * read IGD register at IGD MMIO + 0x20A4 to force IGD
- * to exit low power state. Since map_igd_reg()
- * already mapped page starting 0x2000, we just need to
- * add page offset 0x0A4 to virtual address base.
+ * Read IGD register at IGD MMIO + 0x20A4 to force IGD
+ * to exit low power state.
*/
- return ( *((volatile int *)(igd_reg_va + 0x0A4)) );
+ return *(volatile int *)(igd_reg_va + 0x20A4);
}
/*
@@ -179,11 +171,11 @@ static void snb_vtd_ops_preamble(struct iommu* iommu)
if ( !igd_reg_va )
return;
- *((volatile u32 *)(igd_reg_va + 0x54)) = 0x000FFFFF;
- *((volatile u32 *)(igd_reg_va + 0x700)) = 0;
+ *(volatile u32 *)(igd_reg_va + 0x2054) = 0x000FFFFF;
+ *(volatile u32 *)(igd_reg_va + 0x2700) = 0;
start_time = NOW();
- while ( (*((volatile u32 *)(igd_reg_va + 0x2AC)) & 0xF) != 0 )
+ while ( (*(volatile u32 *)(igd_reg_va + 0x22AC) & 0xF) != 0 )
{
if ( NOW() > start_time + DMAR_OPERATION_TIMEOUT )
{
@@ -194,7 +186,7 @@ static void snb_vtd_ops_preamble(struct iommu* iommu)
cpu_relax();
}
- *((volatile u32*)(igd_reg_va + 0x50)) = 0x10001;
+ *(volatile u32 *)(igd_reg_va + 0x2050) = 0x10001;
}
static void snb_vtd_ops_postamble(struct iommu* iommu)
@@ -208,8 +200,8 @@ static void snb_vtd_ops_postamble(struct iommu* iommu)
if ( !igd_reg_va )
return;
- *((volatile u32 *)(igd_reg_va + 0x54)) = 0xA;
- *((volatile u32 *)(igd_reg_va + 0x50)) = 0x10000;
+ *(volatile u32 *)(igd_reg_va + 0x2054) = 0xA;
+ *(volatile u32 *)(igd_reg_va + 0x2050) = 0x10000;
}
/*
@@ -474,10 +466,12 @@ void pci_vtd_quirk(const struct pci_dev *pdev)
action, seg, bus, dev, func);
break;
- case 0x100: case 0x104: case 0x108: /* Sandybridge */
- case 0x150: case 0x154: case 0x158: /* Ivybridge */
- case 0xa04: /* Haswell ULT */
- case 0xc00: case 0xc04: case 0xc08: /* Haswell */
+ case 0x0040: case 0x0044: case 0x0048: /* Nehalem/Westmere */
+ case 0x0100: case 0x0104: case 0x0108: /* Sandybridge */
+ case 0x0150: case 0x0154: case 0x0158: /* Ivybridge */
+ case 0x0a04: /* Haswell ULT */
+ case 0x0c00: case 0x0c04: case 0x0c08: /* Haswell */
+ case 0x1600: case 0x1604: case 0x1608: /* Broadwell */
bar = pci_conf_read32(seg, bus, dev, func, 0x6c);
bar = (bar << 32) | pci_conf_read32(seg, bus, dev, func, 0x68);
pa = bar & 0x7ffffff000UL; /* bits 12...38 */
diff --git a/xen/drivers/passthrough/vtd/x86/vtd.c b/xen/drivers/passthrough/vtd/x86/vtd.c
index ca17cb1..109234e 100644
--- a/xen/drivers/passthrough/vtd/x86/vtd.c
+++ b/xen/drivers/passthrough/vtd/x86/vtd.c
@@ -36,7 +36,7 @@
* iommu_inclusive_mapping: when set, all memory below 4GB is included in dom0
* 1:1 iommu mappings except xen and unusable regions.
*/
-static bool_t __initdata iommu_inclusive_mapping = 1;
+static bool_t __hwdom_initdata iommu_inclusive_mapping = 1;
boolean_param("iommu_inclusive_mapping", iommu_inclusive_mapping);
void *map_vtd_domain_page(u64 maddr)
@@ -69,11 +69,13 @@ static int _hvm_dpci_isairq_eoi(struct domain *d,
{
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
unsigned int isairq = (long)arg;
- struct dev_intx_gsi_link *digl, *tmp;
+ const struct dev_intx_gsi_link *digl;
- list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
+ list_for_each_entry ( digl, &pirq_dpci->digl_list, list )
{
- if ( hvm_irq->pci_link.route[digl->link] == isairq )
+ unsigned int link = hvm_pci_intx_link(digl->device, digl->intx);
+
+ if ( hvm_irq->pci_link.route[link] == isairq )
{
hvm_pci_intx_deassert(d, digl->device, digl->intx);
if ( --pirq_dpci->pending == 0 )
@@ -107,11 +109,11 @@ void hvm_dpci_isairq_eoi(struct domain *d, unsigned int isairq)
spin_unlock(&d->event_lock);
}
-void __init iommu_set_dom0_mapping(struct domain *d)
+void __hwdom_init vtd_set_hwdom_mapping(struct domain *d)
{
unsigned long i, j, tmp, top;
- BUG_ON(d->domain_id != 0);
+ BUG_ON(!is_hardware_domain(d));
top = max(max_pdx, pfn_to_pdx(0xffffffffUL >> PAGE_SHIFT) + 1);
diff --git a/xen/drivers/passthrough/x86/Makefile b/xen/drivers/passthrough/x86/Makefile
index c124a51..a70cf94 100644
--- a/xen/drivers/passthrough/x86/Makefile
+++ b/xen/drivers/passthrough/x86/Makefile
@@ -1 +1,2 @@
obj-y += ats.o
+obj-y += iommu.o
diff --git a/xen/drivers/passthrough/x86/ats.c b/xen/drivers/passthrough/x86/ats.c
index 1e3e03a..436eada 100644
--- a/xen/drivers/passthrough/x86/ats.c
+++ b/xen/drivers/passthrough/x86/ats.c
@@ -20,7 +20,7 @@
LIST_HEAD(ats_devices);
-bool_t __read_mostly ats_enabled = 1;
+bool_t __read_mostly ats_enabled = 0;
boolean_param("ats", ats_enabled);
int enable_ats_device(int seg, int bus, int devfn, const void *iommu)
diff --git a/xen/drivers/passthrough/x86/iommu.c b/xen/drivers/passthrough/x86/iommu.c
new file mode 100644
index 0000000..ce0ca5a
--- /dev/null
+++ b/xen/drivers/passthrough/x86/iommu.c
@@ -0,0 +1,145 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <xen/sched.h>
+#include <xen/iommu.h>
+#include <xen/paging.h>
+#include <xen/guest_access.h>
+#include <xen/event.h>
+#include <xen/softirq.h>
+#include <xsm/xsm.h>
+
+void iommu_update_ire_from_apic(
+ unsigned int apic, unsigned int reg, unsigned int value)
+{
+ const struct iommu_ops *ops = iommu_get_ops();
+ ops->update_ire_from_apic(apic, reg, value);
+}
+
+unsigned int iommu_read_apic_from_ire(unsigned int apic, unsigned int reg)
+{
+ const struct iommu_ops *ops = iommu_get_ops();
+ return ops->read_apic_from_ire(apic, reg);
+}
+
+int __init iommu_setup_hpet_msi(struct msi_desc *msi)
+{
+ const struct iommu_ops *ops = iommu_get_ops();
+ return ops->setup_hpet_msi ? ops->setup_hpet_msi(msi) : -ENODEV;
+}
+
+int arch_iommu_populate_page_table(struct domain *d)
+{
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+ struct page_info *page;
+ int rc = 0, n = 0;
+
+ d->need_iommu = -1;
+
+ this_cpu(iommu_dont_flush_iotlb) = 1;
+ spin_lock(&d->page_alloc_lock);
+
+ if ( unlikely(d->is_dying) )
+ rc = -ESRCH;
+
+ while ( !rc && (page = page_list_remove_head(&d->page_list)) )
+ {
+ if ( is_hvm_domain(d) ||
+ (page->u.inuse.type_info & PGT_type_mask) == PGT_writable_page )
+ {
+ BUG_ON(SHARED_M2P(mfn_to_gmfn(d, page_to_mfn(page))));
+ rc = hd->platform_ops->map_page(
+ d, mfn_to_gmfn(d, page_to_mfn(page)), page_to_mfn(page),
+ IOMMUF_readable|IOMMUF_writable);
+ if ( rc )
+ {
+ page_list_add(page, &d->page_list);
+ break;
+ }
+ }
+ page_list_add_tail(page, &d->arch.relmem_list);
+ if ( !(++n & 0xff) && !page_list_empty(&d->page_list) &&
+ hypercall_preempt_check() )
+ rc = -ERESTART;
+ }
+
+ if ( !rc )
+ {
+ /*
+ * The expectation here is that generally there are many normal pages
+ * on relmem_list (the ones we put there) and only few being in an
+ * offline/broken state. The latter ones are always at the head of the
+ * list. Hence we first move the whole list, and then move back the
+ * first few entries.
+ */
+ page_list_move(&d->page_list, &d->arch.relmem_list);
+ while ( (page = page_list_first(&d->page_list)) != NULL &&
+ (page->count_info & (PGC_state|PGC_broken)) )
+ {
+ page_list_del(page, &d->page_list);
+ page_list_add_tail(page, &d->arch.relmem_list);
+ }
+ }
+
+ spin_unlock(&d->page_alloc_lock);
+ this_cpu(iommu_dont_flush_iotlb) = 0;
+
+ if ( !rc )
+ iommu_iotlb_flush_all(d);
+ else if ( rc != -ERESTART )
+ iommu_teardown(d);
+
+ return rc;
+}
+
+void __hwdom_init arch_iommu_check_autotranslated_hwdom(struct domain *d)
+{
+ if ( !iommu_enabled )
+ panic("Presently, iommu must be enabled for PVH hardware domain\n");
+}
+
+int arch_iommu_domain_init(struct domain *d)
+{
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+
+ spin_lock_init(&hd->arch.mapping_lock);
+ INIT_LIST_HEAD(&hd->arch.g2m_ioport_list);
+ INIT_LIST_HEAD(&hd->arch.mapped_rmrrs);
+
+ return 0;
+}
+
+void arch_iommu_domain_destroy(struct domain *d)
+{
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+ struct list_head *ioport_list, *tmp;
+ struct g2m_ioport *ioport;
+
+ list_for_each_safe ( ioport_list, tmp, &hd->arch.g2m_ioport_list )
+ {
+ ioport = list_entry(ioport_list, struct g2m_ioport, list);
+ list_del(&ioport->list);
+ xfree(ioport);
+ }
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/drivers/video/arm_hdlcd.c b/xen/drivers/video/arm_hdlcd.c
index 647f22c..841d0d0 100644
--- a/xen/drivers/video/arm_hdlcd.c
+++ b/xen/drivers/video/arm_hdlcd.c
@@ -25,7 +25,6 @@
#include <xen/libfdt/libfdt.h>
#include <xen/init.h>
#include <xen/mm.h>
-#include <asm/early_printk.h>
#include "font.h"
#include "lfb.h"
#include "modelines.h"
@@ -78,7 +77,7 @@ void (*video_puts)(const char *) = vga_noop_puts;
static void hdlcd_flush(void)
{
- dsb();
+ dsb(sy);
}
static int __init get_color_masks(const char* bpp, struct color_masks **masks)
@@ -123,21 +122,21 @@ void __init video_init(void)
if ( !dev )
{
- early_printk("HDLCD: Cannot find node compatible with \"arm,hdcld\"\n");
+ printk("HDLCD: Cannot find node compatible with \"arm,hdcld\"\n");
return;
}
res = dt_device_get_address(dev, 0, &hdlcd_start, &hdlcd_size);
if ( !res )
{
- early_printk("HDLCD: Unable to retrieve MMIO base address\n");
+ printk("HDLCD: Unable to retrieve MMIO base address\n");
return;
}
cells = dt_get_property(dev, "framebuffer", &lenp);
if ( !cells )
{
- early_printk("HDLCD: Unable to retrieve framebuffer property\n");
+ printk("HDLCD: Unable to retrieve framebuffer property\n");
return;
}
@@ -146,13 +145,13 @@ void __init video_init(void)
if ( !hdlcd_start )
{
- early_printk(KERN_ERR "HDLCD: address missing from device tree, disabling driver\n");
+ printk(KERN_ERR "HDLCD: address missing from device tree, disabling driver\n");
return;
}
if ( !framebuffer_start )
{
- early_printk(KERN_ERR "HDLCD: framebuffer address missing from device tree, disabling driver\n");
+ printk(KERN_ERR "HDLCD: framebuffer address missing from device tree, disabling driver\n");
return;
}
@@ -166,13 +165,13 @@ void __init video_init(void)
else if ( strlen(mode_string) < strlen("800x600 at 60") ||
strlen(mode_string) > sizeof(_mode_string) - 1 )
{
- early_printk(KERN_ERR "HDLCD: invalid modeline=%s\n", mode_string);
+ printk(KERN_ERR "HDLCD: invalid modeline=%s\n", mode_string);
return;
} else {
char *s = strchr(mode_string, '-');
if ( !s )
{
- early_printk(KERN_INFO "HDLCD: bpp not found in modeline %s, assume 32 bpp\n",
+ printk(KERN_INFO "HDLCD: bpp not found in modeline %s, assume 32 bpp\n",
mode_string);
get_color_masks("32", &c);
memcpy(_mode_string, mode_string, strlen(mode_string) + 1);
@@ -180,13 +179,13 @@ void __init video_init(void)
} else {
if ( strlen(s) < 6 )
{
- early_printk(KERN_ERR "HDLCD: invalid mode %s\n", mode_string);
+ printk(KERN_ERR "HDLCD: invalid mode %s\n", mode_string);
return;
}
s++;
if ( get_color_masks(s, &c) < 0 )
{
- early_printk(KERN_WARNING "HDLCD: unsupported bpp %s\n", s);
+ printk(KERN_WARNING "HDLCD: unsupported bpp %s\n", s);
return;
}
bytes_per_pixel = simple_strtoll(s, NULL, 10) / 8;
@@ -205,23 +204,23 @@ void __init video_init(void)
}
if ( !videomode )
{
- early_printk(KERN_WARNING "HDLCD: unsupported videomode %s\n",
- _mode_string);
+ printk(KERN_WARNING "HDLCD: unsupported videomode %s\n",
+ _mode_string);
return;
}
if ( framebuffer_size < bytes_per_pixel * videomode->xres * videomode->yres )
{
- early_printk(KERN_ERR "HDLCD: the framebuffer is too small, disabling the HDLCD driver\n");
+ printk(KERN_ERR "HDLCD: the framebuffer is too small, disabling the HDLCD driver\n");
return;
}
- early_printk(KERN_INFO "Initializing HDLCD driver\n");
+ printk(KERN_INFO "Initializing HDLCD driver\n");
lfb = ioremap_wc(framebuffer_start, framebuffer_size);
if ( !lfb )
{
- early_printk(KERN_ERR "Couldn't map the framebuffer\n");
+ printk(KERN_ERR "Couldn't map the framebuffer\n");
return;
}
memset(lfb, 0x00, bytes_per_pixel * videomode->xres * videomode->yres);
diff --git a/xen/include/Makefile b/xen/include/Makefile
index 62846a1..f7ccbc9 100644
--- a/xen/include/Makefile
+++ b/xen/include/Makefile
@@ -27,6 +27,7 @@ headers-$(CONFIG_X86) += compat/arch-x86/xen-mca.h
headers-$(CONFIG_X86) += compat/arch-x86/xen.h
headers-$(CONFIG_X86) += compat/arch-x86/xen-$(compat-arch-y).h
headers-y += compat/arch-$(compat-arch-y).h compat/xlat.h
+headers-$(FLASK_ENABLE) += compat/xsm/flask_op.h
cppflags-y := -include public/xen-compat.h
cppflags-$(CONFIG_X86) += -m32
@@ -65,12 +66,24 @@ compat/%.c: public/%.h xlat.lst Makefile $(BASEDIR)/tools/compat-build-source.py
$(PYTHON) $(BASEDIR)/tools/compat-build-source.py >$@.new
mv -f $@.new $@
-compat/xlat.h: xlat.lst $(filter-out compat/xlat.h,$(headers-y)) $(BASEDIR)/tools/get-fields.sh Makefile
+compat/.xlat/%.h: compat/%.h compat/.xlat/%.lst $(BASEDIR)/tools/get-fields.sh Makefile
export PYTHON=$(PYTHON); \
- grep -v '^[ ]*#' xlat.lst | \
- while read what name hdr; do \
- $(SHELL) $(BASEDIR)/tools/get-fields.sh "$$what" compat_$$name $$(echo compat/$$hdr | sed 's, at arch@,$(compat-arch-y),g') || exit $$?; \
- done >$@.new
+ while read what name; do \
+ $(SHELL) $(BASEDIR)/tools/get-fields.sh "$$what" compat_$$name $< || exit $$?; \
+ done <$(patsubst compat/%,compat/.xlat/%,$(basename $<)).lst >$@.new
+ mv -f $@.new $@
+
+.PRECIOUS: compat/.xlat/%.lst
+compat/.xlat/%.lst: xlat.lst Makefile
+ mkdir -p $(@D)
+ grep -v '^[[:blank:]]*#' $< | sed -ne 's, at arch@,$(compat-arch-y),g' -re 's,[[:blank:]]+$*\.h[[:blank:]]*$$,,p' >$@.new
+ $(call move-if-changed,$@.new,$@)
+
+xlat-y := $(shell sed -ne 's, at arch@,$(compat-arch-y),g' -re 's,^[?!][[:blank:]]+[^[:blank:]]+[[:blank:]]+,,p' xlat.lst | uniq)
+xlat-y := $(filter $(patsubst compat/%,%,$(headers-y)),$(xlat-y))
+
+compat/xlat.h: $(addprefix compat/.xlat/,$(xlat-y)) Makefile
+ cat $(filter %.h,$^) >$@.new
mv -f $@.new $@
ifeq ($(XEN_TARGET_ARCH),$(XEN_COMPILE_ARCH))
@@ -78,7 +91,7 @@ ifeq ($(XEN_TARGET_ARCH),$(XEN_COMPILE_ARCH))
all: headers.chk
headers.chk: $(filter-out public/arch-% public/%ctl.h public/xsm/% public/%hvm/save.h, $(wildcard public/*.h public/*/*.h) $(public-y)) Makefile
- for i in $(filter %.h,$^); do $(CC) -ansi -include stdint.h -Wall -W -Werror -S -o /dev/null -xc $$i || exit 1; echo $$i; done >$@.new
+ for i in $(filter %.h,$^); do $(CC) -ansi -include stdint.h -Wall -W -Werror -S -o /dev/null -x c $$i || exit 1; echo $$i; done >$@.new
mv $@.new $@
endif
diff --git a/xen/include/acpi/apei.h b/xen/include/acpi/apei.h
index 087bbef..eab16e2 100644
--- a/xen/include/acpi/apei.h
+++ b/xen/include/acpi/apei.h
@@ -16,11 +16,11 @@ typedef int (*apei_hest_func_t)(const struct acpi_hest_header *, void *);
int apei_hest_parse(apei_hest_func_t, void *);
int erst_write(const struct cper_record_header *record);
-size_t erst_get_record_count(void);
+ssize_t erst_get_record_count(void);
int erst_get_next_record_id(u64 *record_id);
-size_t erst_read(u64 record_id, struct cper_record_header *record,
+ssize_t erst_read(u64 record_id, struct cper_record_header *record,
size_t buflen);
-size_t erst_read_next(struct cper_record_header *record, size_t buflen);
+ssize_t erst_read_next(struct cper_record_header *record, size_t buflen);
int erst_clear(u64 record_id);
void __iomem *apei_pre_map(paddr_t paddr, unsigned long size);
diff --git a/xen/include/asm-arm/arm32/atomic.h b/xen/include/asm-arm/arm32/atomic.h
index 523c745..7ec712f 100644
--- a/xen/include/asm-arm/arm32/atomic.h
+++ b/xen/include/asm-arm/arm32/atomic.h
@@ -18,122 +18,142 @@
*/
static inline void atomic_add(int i, atomic_t *v)
{
- unsigned long tmp;
- int result;
-
- __asm__ __volatile__("@ atomic_add\n"
-"1: ldrex %0, [%3]\n"
-" add %0, %0, %4\n"
-" strex %1, %0, [%3]\n"
-" teq %1, #0\n"
-" bne 1b"
- : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
- : "r" (&v->counter), "Ir" (i)
- : "cc");
+ unsigned long tmp;
+ int result;
+
+ prefetchw(&v->counter);
+ __asm__ __volatile__("@ atomic_add\n"
+"1: ldrex %0, [%3]\n"
+" add %0, %0, %4\n"
+" strex %1, %0, [%3]\n"
+" teq %1, #0\n"
+" bne 1b"
+ : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
+ : "r" (&v->counter), "Ir" (i)
+ : "cc");
}
static inline int atomic_add_return(int i, atomic_t *v)
{
- unsigned long tmp;
- int result;
+ unsigned long tmp;
+ int result;
- smp_mb();
+ smp_mb();
+ prefetchw(&v->counter);
- __asm__ __volatile__("@ atomic_add_return\n"
-"1: ldrex %0, [%3]\n"
-" add %0, %0, %4\n"
-" strex %1, %0, [%3]\n"
-" teq %1, #0\n"
-" bne 1b"
- : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
- : "r" (&v->counter), "Ir" (i)
- : "cc");
+ __asm__ __volatile__("@ atomic_add_return\n"
+"1: ldrex %0, [%3]\n"
+" add %0, %0, %4\n"
+" strex %1, %0, [%3]\n"
+" teq %1, #0\n"
+" bne 1b"
+ : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
+ : "r" (&v->counter), "Ir" (i)
+ : "cc");
- smp_mb();
+ smp_mb();
- return result;
+ return result;
}
static inline void atomic_sub(int i, atomic_t *v)
{
- unsigned long tmp;
- int result;
-
- __asm__ __volatile__("@ atomic_sub\n"
-"1: ldrex %0, [%3]\n"
-" sub %0, %0, %4\n"
-" strex %1, %0, [%3]\n"
-" teq %1, #0\n"
-" bne 1b"
- : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
- : "r" (&v->counter), "Ir" (i)
- : "cc");
+ unsigned long tmp;
+ int result;
+
+ prefetchw(&v->counter);
+ __asm__ __volatile__("@ atomic_sub\n"
+"1: ldrex %0, [%3]\n"
+" sub %0, %0, %4\n"
+" strex %1, %0, [%3]\n"
+" teq %1, #0\n"
+" bne 1b"
+ : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
+ : "r" (&v->counter), "Ir" (i)
+ : "cc");
}
static inline int atomic_sub_return(int i, atomic_t *v)
{
- unsigned long tmp;
- int result;
+ unsigned long tmp;
+ int result;
- smp_mb();
+ smp_mb();
+ prefetchw(&v->counter);
- __asm__ __volatile__("@ atomic_sub_return\n"
-"1: ldrex %0, [%3]\n"
-" sub %0, %0, %4\n"
-" strex %1, %0, [%3]\n"
-" teq %1, #0\n"
-" bne 1b"
- : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
- : "r" (&v->counter), "Ir" (i)
- : "cc");
+ __asm__ __volatile__("@ atomic_sub_return\n"
+"1: ldrex %0, [%3]\n"
+" sub %0, %0, %4\n"
+" strex %1, %0, [%3]\n"
+" teq %1, #0\n"
+" bne 1b"
+ : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
+ : "r" (&v->counter), "Ir" (i)
+ : "cc");
- smp_mb();
+ smp_mb();
- return result;
+ return result;
}
static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new)
{
- unsigned long oldval, res;
-
- smp_mb();
-
- do {
- __asm__ __volatile__("@ atomic_cmpxchg\n"
- "ldrex %1, [%3]\n"
- "mov %0, #0\n"
- "teq %1, %4\n"
- "strexeq %0, %5, [%3]\n"
- : "=&r" (res), "=&r" (oldval), "+Qo" (ptr->counter)
- : "r" (&ptr->counter), "Ir" (old), "r" (new)
- : "cc");
- } while (res);
-
- smp_mb();
-
- return oldval;
+ int oldval;
+ unsigned long res;
+
+ smp_mb();
+ prefetchw(&ptr->counter);
+
+ do {
+ __asm__ __volatile__("@ atomic_cmpxchg\n"
+ "ldrex %1, [%3]\n"
+ "mov %0, #0\n"
+ "teq %1, %4\n"
+ "strexeq %0, %5, [%3]\n"
+ : "=&r" (res), "=&r" (oldval), "+Qo" (ptr->counter)
+ : "r" (&ptr->counter), "Ir" (old), "r" (new)
+ : "cc");
+ } while (res);
+
+ smp_mb();
+
+ return oldval;
}
-static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
{
- unsigned long tmp, tmp2;
-
- __asm__ __volatile__("@ atomic_clear_mask\n"
-"1: ldrex %0, [%3]\n"
-" bic %0, %0, %4\n"
-" strex %1, %0, [%3]\n"
-" teq %1, #0\n"
-" bne 1b"
- : "=&r" (tmp), "=&r" (tmp2), "+Qo" (*addr)
- : "r" (addr), "Ir" (mask)
- : "cc");
+ int oldval, newval;
+ unsigned long tmp;
+
+ smp_mb();
+ prefetchw(&v->counter);
+
+ __asm__ __volatile__ ("@ atomic_add_unless\n"
+"1: ldrex %0, [%4]\n"
+" teq %0, %5\n"
+" beq 2f\n"
+" add %1, %0, %6\n"
+" strex %2, %1, [%4]\n"
+" teq %2, #0\n"
+" bne 1b\n"
+"2:"
+ : "=&r" (oldval), "=&r" (newval), "=&r" (tmp), "+Qo" (v->counter)
+ : "r" (&v->counter), "r" (u), "r" (a)
+ : "cc");
+
+ if (oldval != u)
+ smp_mb();
+
+ return oldval;
}
-#define atomic_inc(v) atomic_add(1, v)
-#define atomic_dec(v) atomic_sub(1, v)
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+#define atomic_inc(v) atomic_add(1, v)
+#define atomic_dec(v) atomic_sub(1, v)
-#define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0)
-#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
+#define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0)
+#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
#define atomic_inc_return(v) (atomic_add_return(1, v))
#define atomic_dec_return(v) (atomic_sub_return(1, v))
#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
@@ -145,7 +165,7 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
* Local variables:
* mode: C
* c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
+ * c-basic-offset: 8
+ * indent-tabs-mode: t
* End:
*/
diff --git a/xen/include/asm-arm/arm32/bug.h b/xen/include/asm-arm/arm32/bug.h
new file mode 100644
index 0000000..155b420
--- /dev/null
+++ b/xen/include/asm-arm/arm32/bug.h
@@ -0,0 +1,13 @@
+#ifndef __ARM_ARM32_BUG_H__
+#define __ARM_ARM32_BUG_H__
+
+#include <xen/stringify.h>
+
+/* ARMv7 provides a list of undefined opcode (see A8.8.247 DDI 0406C.b)
+ * Use one them encoding A1 to go in exception mode
+ */
+#define BUG_OPCODE 0xe7f00f0
+
+#define BUG_INSTR ".word " __stringify(BUG_OPCODE)
+
+#endif /* __ARM_ARM32_BUG_H__ */
diff --git a/xen/include/asm-arm/arm32/cmpxchg.h b/xen/include/asm-arm/arm32/cmpxchg.h
new file mode 100644
index 0000000..03e0bed
--- /dev/null
+++ b/xen/include/asm-arm/arm32/cmpxchg.h
@@ -0,0 +1,155 @@
+#ifndef __ASM_ARM32_CMPXCHG_H
+#define __ASM_ARM32_CMPXCHG_H
+
+#include <xen/prefetch.h>
+
+extern void __bad_xchg(volatile void *, int);
+
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
+{
+ unsigned long ret;
+ unsigned int tmp;
+
+ smp_mb();
+ prefetchw((const void *)ptr);
+
+ switch (size) {
+ case 1:
+ asm volatile("@ __xchg1\n"
+ "1: ldrexb %0, [%3]\n"
+ " strexb %1, %2, [%3]\n"
+ " teq %1, #0\n"
+ " bne 1b"
+ : "=&r" (ret), "=&r" (tmp)
+ : "r" (x), "r" (ptr)
+ : "memory", "cc");
+ break;
+ case 4:
+ asm volatile("@ __xchg4\n"
+ "1: ldrex %0, [%3]\n"
+ " strex %1, %2, [%3]\n"
+ " teq %1, #0\n"
+ " bne 1b"
+ : "=&r" (ret), "=&r" (tmp)
+ : "r" (x), "r" (ptr)
+ : "memory", "cc");
+ break;
+ default:
+ __bad_xchg(ptr, size), ret = 0;
+ break;
+ }
+ smp_mb();
+
+ return ret;
+}
+
+#define xchg(ptr,x) \
+ ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+/*
+ * Atomic compare and exchange. Compare OLD with MEM, if identical,
+ * store NEW in MEM. Return the initial value in MEM. Success is
+ * indicated by comparing RETURN with OLD.
+ */
+
+extern void __bad_cmpxchg(volatile void *ptr, int size);
+
+static always_inline unsigned long __cmpxchg(
+ volatile void *ptr, unsigned long old, unsigned long new, int size)
+{
+ unsigned long oldval, res;
+
+ prefetchw((const void *)ptr);
+
+ switch (size) {
+ case 1:
+ do {
+ asm volatile("@ __cmpxchg1\n"
+ " ldrexb %1, [%2]\n"
+ " mov %0, #0\n"
+ " teq %1, %3\n"
+ " strexbeq %0, %4, [%2]\n"
+ : "=&r" (res), "=&r" (oldval)
+ : "r" (ptr), "Ir" (old), "r" (new)
+ : "memory", "cc");
+ } while (res);
+ break;
+ case 2:
+ do {
+ asm volatile("@ __cmpxchg2\n"
+ " ldrexh %1, [%2]\n"
+ " mov %0, #0\n"
+ " teq %1, %3\n"
+ " strexheq %0, %4, [%2]\n"
+ : "=&r" (res), "=&r" (oldval)
+ : "r" (ptr), "Ir" (old), "r" (new)
+ : "memory", "cc");
+ } while (res);
+ break;
+ case 4:
+ do {
+ asm volatile("@ __cmpxchg4\n"
+ " ldrex %1, [%2]\n"
+ " mov %0, #0\n"
+ " teq %1, %3\n"
+ " strexeq %0, %4, [%2]\n"
+ : "=&r" (res), "=&r" (oldval)
+ : "r" (ptr), "Ir" (old), "r" (new)
+ : "memory", "cc");
+ } while (res);
+ break;
+#if 0
+ case 8:
+ do {
+ asm volatile("@ __cmpxchg8\n"
+ " ldrexd %1, [%2]\n"
+ " mov %0, #0\n"
+ " teq %1, %3\n"
+ " strexdeq %0, %4, [%2]\n"
+ : "=&r" (res), "=&r" (oldval)
+ : "r" (ptr), "Ir" (old), "r" (new)
+ : "memory", "cc");
+ } while (res);
+ break;
+#endif
+ default:
+ __bad_cmpxchg(ptr, size);
+ oldval = 0;
+ }
+
+ return oldval;
+}
+
+static always_inline unsigned long __cmpxchg_mb(volatile void *ptr,
+ unsigned long old,
+ unsigned long new, int size)
+{
+ unsigned long ret;
+
+ smp_mb();
+ ret = __cmpxchg(ptr, old, new, size);
+ smp_mb();
+
+ return ret;
+}
+
+#define cmpxchg(ptr,o,n) \
+ ((__typeof__(*(ptr)))__cmpxchg_mb((ptr), \
+ (unsigned long)(o), \
+ (unsigned long)(n), \
+ sizeof(*(ptr))))
+
+#define cmpxchg_local(ptr,o,n) \
+ ((__typeof__(*(ptr)))__cmpxchg((ptr), \
+ (unsigned long)(o), \
+ (unsigned long)(n), \
+ sizeof(*(ptr))))
+#endif
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 8
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/xen/include/asm-arm/arm32/flushtlb.h b/xen/include/asm-arm/arm32/flushtlb.h
index 7183a07..bbcc82f 100644
--- a/xen/include/asm-arm/arm32/flushtlb.h
+++ b/xen/include/asm-arm/arm32/flushtlb.h
@@ -4,44 +4,44 @@
/* Flush local TLBs, current VMID only */
static inline void flush_tlb_local(void)
{
- dsb();
+ dsb(sy);
WRITE_CP32((uint32_t) 0, TLBIALL);
- dsb();
+ dsb(sy);
isb();
}
/* Flush inner shareable TLBs, current VMID only */
static inline void flush_tlb(void)
{
- dsb();
+ dsb(sy);
WRITE_CP32((uint32_t) 0, TLBIALLIS);
- dsb();
+ dsb(sy);
isb();
}
/* Flush local TLBs, all VMIDs, non-hypervisor mode */
static inline void flush_tlb_all_local(void)
{
- dsb();
+ dsb(sy);
WRITE_CP32((uint32_t) 0, TLBIALLNSNH);
- dsb();
+ dsb(sy);
isb();
}
/* Flush innershareable TLBs, all VMIDs, non-hypervisor mode */
static inline void flush_tlb_all(void)
{
- dsb();
+ dsb(sy);
WRITE_CP32((uint32_t) 0, TLBIALLNSNHIS);
- dsb();
+ dsb(sy);
isb();
}
diff --git a/xen/include/asm-arm/arm32/macros.h b/xen/include/asm-arm/arm32/macros.h
new file mode 100644
index 0000000..a4e20aa
--- /dev/null
+++ b/xen/include/asm-arm/arm32/macros.h
@@ -0,0 +1,8 @@
+#ifndef __ASM_ARM_ARM32_MACROS_H
+#define __ASM_ARM_ARM32_MACROS_H
+
+ .macro ret
+ mov pc, lr
+ .endm
+
+#endif /* __ASM_ARM_ARM32_MACROS_H */
diff --git a/xen/include/asm-arm/arm32/page.h b/xen/include/asm-arm/arm32/page.h
index 80d5c36..a07e217 100644
--- a/xen/include/asm-arm/arm32/page.h
+++ b/xen/include/asm-arm/arm32/page.h
@@ -19,62 +19,62 @@ static inline void write_pte(lpae_t *p, lpae_t pte)
: : "r" (pte.bits), "r" (p) : "memory");
}
+/* Inline ASM to invalidate dcache on register R (may be an inline asm operand) */
+#define __invalidate_dcache_one(R) STORE_CP32(R, DCIMVAC)
+
/* Inline ASM to flush dcache on register R (may be an inline asm operand) */
-#define __clean_xen_dcache_one(R) STORE_CP32(R, DCCMVAC)
+#define __clean_dcache_one(R) STORE_CP32(R, DCCMVAC)
/* Inline ASM to clean and invalidate dcache on register R (may be an
* inline asm operand) */
-#define __clean_and_invalidate_xen_dcache_one(R) STORE_CP32(R, DCCIMVAC)
+#define __clean_and_invalidate_dcache_one(R) STORE_CP32(R, DCCIMVAC)
/*
- * Flush all hypervisor mappings from the TLB and branch predictor.
+ * Flush all hypervisor mappings from the TLB and branch predictor of
+ * the local processor.
+ *
* This is needed after changing Xen code mappings.
*
* The caller needs to issue the necessary DSB and D-cache flushes
* before calling flush_xen_text_tlb.
*/
-static inline void flush_xen_text_tlb(void)
+static inline void flush_xen_text_tlb_local(void)
{
- register unsigned long r0 asm ("r0");
asm volatile (
"isb;" /* Ensure synchronization with previous changes to text */
- STORE_CP32(0, TLBIALLH) /* Flush hypervisor TLB */
- STORE_CP32(0, ICIALLU) /* Flush I-cache */
- STORE_CP32(0, BPIALL) /* Flush branch predictor */
+ CMD_CP32(TLBIALLH) /* Flush hypervisor TLB */
+ CMD_CP32(ICIALLU) /* Flush I-cache */
+ CMD_CP32(BPIALL) /* Flush branch predictor */
"dsb;" /* Ensure completion of TLB+BP flush */
"isb;"
- : : "r" (r0) /*dummy*/ : "memory");
+ : : : "memory");
}
/*
- * Flush all hypervisor mappings from the data TLB. This is not
- * sufficient when changing code mappings or for self modifying code.
+ * Flush all hypervisor mappings from the data TLB of the local
+ * processor. This is not sufficient when changing code mappings or
+ * for self modifying code.
*/
-static inline void flush_xen_data_tlb(void)
+static inline void flush_xen_data_tlb_local(void)
{
- register unsigned long r0 asm ("r0");
asm volatile("dsb;" /* Ensure preceding are visible */
- STORE_CP32(0, TLBIALLH)
+ CMD_CP32(TLBIALLH)
"dsb;" /* Ensure completion of the TLB flush */
"isb;"
- : : "r" (r0) /* dummy */: "memory");
+ : : : "memory");
}
-/*
- * Flush a range of VA's hypervisor mappings from the data TLB. This is not
- * sufficient when changing code mappings or for self modifying code.
- */
-static inline void flush_xen_data_tlb_range_va(unsigned long va, unsigned long size)
+/* Flush TLB of local processor for address va. */
+static inline void __flush_xen_data_tlb_one_local(vaddr_t va)
{
- unsigned long end = va + size;
- dsb(); /* Ensure preceding are visible */
- while ( va < end ) {
- asm volatile(STORE_CP32(0, TLBIMVAH)
- : : "r" (va) : "memory");
- va += PAGE_SIZE;
- }
- dsb(); /* Ensure completion of the TLB flush */
- isb();
+ asm volatile(STORE_CP32(0, TLBIMVAH) : : "r" (va) : "memory");
+}
+
+/* Flush TLB of all processors in the inner-shareable domain for
+ * address va. */
+static inline void __flush_xen_data_tlb_one(vaddr_t va)
+{
+ asm volatile(STORE_CP32(0, TLBIMVAHIS) : : "r" (va) : "memory");
}
/* Ask the MMU to translate a VA for us */
@@ -114,6 +114,8 @@ static inline uint64_t gva_to_ipa_par(vaddr_t va)
return par;
}
+#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
+
#endif /* __ASSEMBLY__ */
#endif /* __ARM_ARM32_PAGE_H__ */
diff --git a/xen/include/asm-arm/arm32/processor.h b/xen/include/asm-arm/arm32/processor.h
index d1b89d0..f41644d 100644
--- a/xen/include/asm-arm/arm32/processor.h
+++ b/xen/include/asm-arm/arm32/processor.h
@@ -1,7 +1,7 @@
#ifndef __ASM_ARM_ARM32_PROCESSOR_H
#define __ASM_ARM_ARM32_PROCESSOR_H
-#define ACTLR_V7_SMP (1<<6)
+#define ACTLR_CAXX_SMP (1<<6)
#ifndef __ASSEMBLY__
/* On stack VCPU state */
@@ -69,6 +69,10 @@ struct cpu_user_regs
#define LOAD_CP64(r, name...) "mrrc " __stringify(CP64(%r, %H##r, name)) ";"
#define STORE_CP64(r, name...) "mcrr " __stringify(CP64(%r, %H##r, name)) ";"
+/* Issue a CP operation which takes no argument,
+ * uses r0 as a placeholder register. */
+#define CMD_CP32(name...) "mcr " __stringify(CP32(r0, name)) ";"
+
#ifndef __ASSEMBLY__
/* C wrappers */
diff --git a/xen/include/asm-arm/arm32/system.h b/xen/include/asm-arm/arm32/system.h
index 60148cb..b47b942 100644
--- a/xen/include/asm-arm/arm32/system.h
+++ b/xen/include/asm-arm/arm32/system.h
@@ -2,136 +2,7 @@
#ifndef __ASM_ARM32_SYSTEM_H
#define __ASM_ARM32_SYSTEM_H
-#define sev() __asm__ __volatile__ ("sev" : : : "memory")
-#define wfe() __asm__ __volatile__ ("wfe" : : : "memory")
-#define wfi() __asm__ __volatile__ ("wfi" : : : "memory")
-
-#define isb() __asm__ __volatile__ ("isb" : : : "memory")
-#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
-#define dmb() __asm__ __volatile__ ("dmb" : : : "memory")
-
-#define mb() dsb()
-#define rmb() dsb()
-#define wmb() mb()
-
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-
-extern void __bad_xchg(volatile void *, int);
-
-static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
-{
- unsigned long ret;
- unsigned int tmp;
-
- smp_mb();
-
- switch (size) {
- case 1:
- asm volatile("@ __xchg1\n"
- "1: ldrexb %0, [%3]\n"
- " strexb %1, %2, [%3]\n"
- " teq %1, #0\n"
- " bne 1b"
- : "=&r" (ret), "=&r" (tmp)
- : "r" (x), "r" (ptr)
- : "memory", "cc");
- break;
- case 4:
- asm volatile("@ __xchg4\n"
- "1: ldrex %0, [%3]\n"
- " strex %1, %2, [%3]\n"
- " teq %1, #0\n"
- " bne 1b"
- : "=&r" (ret), "=&r" (tmp)
- : "r" (x), "r" (ptr)
- : "memory", "cc");
- break;
- default:
- __bad_xchg(ptr, size), ret = 0;
- break;
- }
- smp_mb();
-
- return ret;
-}
-
-/*
- * Atomic compare and exchange. Compare OLD with MEM, if identical,
- * store NEW in MEM. Return the initial value in MEM. Success is
- * indicated by comparing RETURN with OLD.
- */
-
-extern void __bad_cmpxchg(volatile void *ptr, int size);
-
-static always_inline unsigned long __cmpxchg(
- volatile void *ptr, unsigned long old, unsigned long new, int size)
-{
- unsigned long /*long*/ oldval, res;
-
- switch (size) {
- case 1:
- do {
- asm volatile("@ __cmpxchg1\n"
- " ldrexb %1, [%2]\n"
- " mov %0, #0\n"
- " teq %1, %3\n"
- " strexbeq %0, %4, [%2]\n"
- : "=&r" (res), "=&r" (oldval)
- : "r" (ptr), "Ir" (old), "r" (new)
- : "memory", "cc");
- } while (res);
- break;
- case 2:
- do {
- asm volatile("@ __cmpxchg2\n"
- " ldrexh %1, [%2]\n"
- " mov %0, #0\n"
- " teq %1, %3\n"
- " strexheq %0, %4, [%2]\n"
- : "=&r" (res), "=&r" (oldval)
- : "r" (ptr), "Ir" (old), "r" (new)
- : "memory", "cc");
- } while (res);
- break;
- case 4:
- do {
- asm volatile("@ __cmpxchg4\n"
- " ldrex %1, [%2]\n"
- " mov %0, #0\n"
- " teq %1, %3\n"
- " strexeq %0, %4, [%2]\n"
- : "=&r" (res), "=&r" (oldval)
- : "r" (ptr), "Ir" (old), "r" (new)
- : "memory", "cc");
- } while (res);
- break;
-#if 0
- case 8:
- do {
- asm volatile("@ __cmpxchg8\n"
- " ldrexd %1, [%2]\n"
- " mov %0, #0\n"
- " teq %1, %3\n"
- " strexdeq %0, %4, [%2]\n"
- : "=&r" (res), "=&r" (oldval)
- : "r" (ptr), "Ir" (old), "r" (new)
- : "memory", "cc");
- } while (res);
- break;
-#endif
- default:
- __bad_cmpxchg(ptr, size);
- oldval = 0;
- }
-
- return oldval;
-}
-
-#define cmpxchg(ptr,o,n) \
- ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o), \
- (unsigned long)(n),sizeof(*(ptr))))
+#include <asm/arm32/cmpxchg.h>
#define local_irq_disable() asm volatile ( "cpsid i @ local_irq_disable\n" : : : "cc" )
#define local_irq_enable() asm volatile ( "cpsie i @ local_irq_enable\n" : : : "cc" )
diff --git a/xen/include/asm-arm/arm64/atomic.h b/xen/include/asm-arm/arm64/atomic.h
index a279755..b49219e 100644
--- a/xen/include/asm-arm/arm64/atomic.h
+++ b/xen/include/asm-arm/arm64/atomic.h
@@ -38,8 +38,7 @@ static inline void atomic_add(int i, atomic_t *v)
" stxr %w1, %w0, %2\n"
" cbnz %w1, 1b"
: "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
- : "Ir" (i)
- : "cc");
+ : "Ir" (i));
}
static inline int atomic_add_return(int i, atomic_t *v)
@@ -48,14 +47,15 @@ static inline int atomic_add_return(int i, atomic_t *v)
int result;
asm volatile("// atomic_add_return\n"
-"1: ldaxr %w0, %2\n"
+"1: ldxr %w0, %2\n"
" add %w0, %w0, %w3\n"
" stlxr %w1, %w0, %2\n"
" cbnz %w1, 1b"
: "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
: "Ir" (i)
- : "cc", "memory");
+ : "memory");
+ smp_mb();
return result;
}
@@ -70,8 +70,7 @@ static inline void atomic_sub(int i, atomic_t *v)
" stxr %w1, %w0, %2\n"
" cbnz %w1, 1b"
: "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
- : "Ir" (i)
- : "cc");
+ : "Ir" (i));
}
static inline int atomic_sub_return(int i, atomic_t *v)
@@ -80,14 +79,15 @@ static inline int atomic_sub_return(int i, atomic_t *v)
int result;
asm volatile("// atomic_sub_return\n"
-"1: ldaxr %w0, %2\n"
+"1: ldxr %w0, %2\n"
" sub %w0, %w0, %w3\n"
" stlxr %w1, %w0, %2\n"
" cbnz %w1, 1b"
: "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
: "Ir" (i)
- : "cc", "memory");
+ : "memory");
+ smp_mb();
return result;
}
@@ -96,34 +96,23 @@ static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new)
unsigned long tmp;
int oldval;
+ smp_mb();
+
asm volatile("// atomic_cmpxchg\n"
-"1: ldaxr %w1, %2\n"
+"1: ldxr %w1, %2\n"
" cmp %w1, %w3\n"
" b.ne 2f\n"
-" stlxr %w0, %w4, %2\n"
+" stxr %w0, %w4, %2\n"
" cbnz %w0, 1b\n"
"2:"
: "=&r" (tmp), "=&r" (oldval), "+Q" (ptr->counter)
: "Ir" (old), "r" (new)
- : "cc", "memory");
+ : "cc");
+ smp_mb();
return oldval;
}
-static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
-{
- unsigned long tmp, tmp2;
-
- asm volatile("// atomic_clear_mask\n"
-"1: ldxr %0, %2\n"
-" bic %0, %0, %3\n"
-" stxr %w1, %0, %2\n"
-" cbnz %w1, 1b"
- : "=&r" (tmp), "=&r" (tmp2), "+Q" (*addr)
- : "Ir" (mask)
- : "cc");
-}
-
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
static inline int __atomic_add_unless(atomic_t *v, int a, int u)
@@ -147,17 +136,12 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u)
#define atomic_add_negative(i,v) (atomic_add_return(i, v) < 0)
-#define smp_mb__before_atomic_dec() smp_mb()
-#define smp_mb__after_atomic_dec() smp_mb()
-#define smp_mb__before_atomic_inc() smp_mb()
-#define smp_mb__after_atomic_inc() smp_mb()
-
#endif
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
+ * c-basic-offset: 8
+ * indent-tabs-mode: t
* End:
*/
diff --git a/xen/include/asm-arm/arm64/bug.h b/xen/include/asm-arm/arm64/bug.h
new file mode 100644
index 0000000..42b0e4f
--- /dev/null
+++ b/xen/include/asm-arm/arm64/bug.h
@@ -0,0 +1,10 @@
+#ifndef __ARM_ARM64_BUG_H__
+#define __ARM_ARM64_BUG_H__
+
+#include <xen/stringify.h>
+
+#define BRK_BUG_FRAME 1
+
+#define BUG_INSTR "brk " __stringify(BRK_BUG_FRAME)
+
+#endif /* __ARM_ARM64_BUG_H__ */
diff --git a/xen/include/asm-arm/arm64/cmpxchg.h b/xen/include/asm-arm/arm64/cmpxchg.h
new file mode 100644
index 0000000..ae42b2f
--- /dev/null
+++ b/xen/include/asm-arm/arm64/cmpxchg.h
@@ -0,0 +1,178 @@
+#ifndef __ASM_ARM64_CMPXCHG_H
+#define __ASM_ARM64_CMPXCHG_H
+
+extern void __bad_xchg(volatile void *, int);
+
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
+{
+ unsigned long ret, tmp;
+
+ switch (size) {
+ case 1:
+ asm volatile("// __xchg1\n"
+ "1: ldxrb %w0, %2\n"
+ " stlxrb %w1, %w3, %2\n"
+ " cbnz %w1, 1b\n"
+ : "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr)
+ : "r" (x)
+ : "memory");
+ break;
+ case 2:
+ asm volatile("// __xchg2\n"
+ "1: ldxrh %w0, %2\n"
+ " stlxrh %w1, %w3, %2\n"
+ " cbnz %w1, 1b\n"
+ : "=&r" (ret), "=&r" (tmp), "+Q" (*(u16 *)ptr)
+ : "r" (x)
+ : "memory");
+ break;
+ case 4:
+ asm volatile("// __xchg4\n"
+ "1: ldxr %w0, %2\n"
+ " stlxr %w1, %w3, %2\n"
+ " cbnz %w1, 1b\n"
+ : "=&r" (ret), "=&r" (tmp), "+Q" (*(u32 *)ptr)
+ : "r" (x)
+ : "memory");
+ break;
+ case 8:
+ asm volatile("// __xchg8\n"
+ "1: ldxr %0, %2\n"
+ " stlxr %w1, %3, %2\n"
+ " cbnz %w1, 1b\n"
+ : "=&r" (ret), "=&r" (tmp), "+Q" (*(u64 *)ptr)
+ : "r" (x)
+ : "memory");
+ break;
+ default:
+ __bad_xchg(ptr, size), ret = 0;
+ break;
+ }
+
+ smp_mb();
+ return ret;
+}
+
+#define xchg(ptr,x) \
+({ \
+ __typeof__(*(ptr)) __ret; \
+ __ret = (__typeof__(*(ptr))) \
+ __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))); \
+ __ret; \
+})
+
+extern void __bad_cmpxchg(volatile void *ptr, int size);
+
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+ unsigned long new, int size)
+{
+ unsigned long oldval = 0, res;
+
+ switch (size) {
+ case 1:
+ do {
+ asm volatile("// __cmpxchg1\n"
+ " ldxrb %w1, %2\n"
+ " mov %w0, #0\n"
+ " cmp %w1, %w3\n"
+ " b.ne 1f\n"
+ " stxrb %w0, %w4, %2\n"
+ "1:\n"
+ : "=&r" (res), "=&r" (oldval), "+Q" (*(u8 *)ptr)
+ : "Ir" (old), "r" (new)
+ : "cc");
+ } while (res);
+ break;
+
+ case 2:
+ do {
+ asm volatile("// __cmpxchg2\n"
+ " ldxrh %w1, %2\n"
+ " mov %w0, #0\n"
+ " cmp %w1, %w3\n"
+ " b.ne 1f\n"
+ " stxrh %w0, %w4, %2\n"
+ "1:\n"
+ : "=&r" (res), "=&r" (oldval), "+Q" (*(u16 *)ptr)
+ : "Ir" (old), "r" (new)
+ : "cc");
+ } while (res);
+ break;
+
+ case 4:
+ do {
+ asm volatile("// __cmpxchg4\n"
+ " ldxr %w1, %2\n"
+ " mov %w0, #0\n"
+ " cmp %w1, %w3\n"
+ " b.ne 1f\n"
+ " stxr %w0, %w4, %2\n"
+ "1:\n"
+ : "=&r" (res), "=&r" (oldval), "+Q" (*(u32 *)ptr)
+ : "Ir" (old), "r" (new)
+ : "cc");
+ } while (res);
+ break;
+
+ case 8:
+ do {
+ asm volatile("// __cmpxchg8\n"
+ " ldxr %1, %2\n"
+ " mov %w0, #0\n"
+ " cmp %1, %3\n"
+ " b.ne 1f\n"
+ " stxr %w0, %4, %2\n"
+ "1:\n"
+ : "=&r" (res), "=&r" (oldval), "+Q" (*(u64 *)ptr)
+ : "Ir" (old), "r" (new)
+ : "cc");
+ } while (res);
+ break;
+
+ default:
+ __bad_cmpxchg(ptr, size);
+ oldval = 0;
+ }
+
+ return oldval;
+}
+
+static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
+ unsigned long new, int size)
+{
+ unsigned long ret;
+
+ smp_mb();
+ ret = __cmpxchg(ptr, old, new, size);
+ smp_mb();
+
+ return ret;
+}
+
+#define cmpxchg(ptr, o, n) \
+({ \
+ __typeof__(*(ptr)) __ret; \
+ __ret = (__typeof__(*(ptr))) \
+ __cmpxchg_mb((ptr), (unsigned long)(o), (unsigned long)(n), \
+ sizeof(*(ptr))); \
+ __ret; \
+})
+
+#define cmpxchg_local(ptr, o, n) \
+({ \
+ __typeof__(*(ptr)) __ret; \
+ __ret = (__typeof__(*(ptr))) \
+ __cmpxchg((ptr), (unsigned long)(o), \
+ (unsigned long)(n), sizeof(*(ptr))); \
+ __ret; \
+})
+
+#endif
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 8
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/xen/include/asm-arm/arm64/efibind.h b/xen/include/asm-arm/arm64/efibind.h
new file mode 100644
index 0000000..2b0bf40
--- /dev/null
+++ b/xen/include/asm-arm/arm64/efibind.h
@@ -0,0 +1,216 @@
+/*++
+
+Copyright (c) 1998 Intel Corporation
+
+Module Name:
+
+ efefind.h
+
+Abstract:
+
+ EFI to compile bindings
+
+
+
+
+Revision History
+
+--*/
+
+#ifndef __GNUC__
+#pragma pack()
+#endif
+
+#define EFIERR(a) (0x8000000000000000 | a)
+#define EFI_ERROR_MASK 0x8000000000000000
+#define EFIERR_OEM(a) (0xc000000000000000 | a)
+
+#define BAD_POINTER 0xFBFBFBFBFBFBFBFB
+#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF
+
+#define EFI_STUB_ERROR MAX_ADDRESS
+
+#ifndef __ASSEMBLY__
+//
+// Basic int types of various widths
+//
+
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L )
+
+ // No ANSI C 1999/2000 stdint.h integer width declarations
+
+ #if defined(__GNUC__)
+ typedef unsigned long long uint64_t __attribute__((aligned (8)));
+ typedef long long int64_t __attribute__((aligned (8)));
+ typedef unsigned int uint32_t;
+ typedef int int32_t;
+ typedef unsigned short uint16_t;
+ typedef short int16_t;
+ typedef unsigned char uint8_t;
+ typedef char int8_t;
+ #elif defined(UNIX_LP64)
+
+ /* Use LP64 programming model from C_FLAGS for integer width declarations */
+
+ typedef unsigned long uint64_t;
+ typedef long int64_t;
+ typedef unsigned int uint32_t;
+ typedef int int32_t;
+ typedef unsigned short uint16_t;
+ typedef short int16_t;
+ typedef unsigned char uint8_t;
+ typedef char int8_t;
+ #else
+
+ /* Assume P64 programming model from C_FLAGS for integer width declarations */
+
+ typedef unsigned long long uint64_t __attribute__((aligned (8)));
+ typedef long long int64_t __attribute__((aligned (8)));
+ typedef unsigned int uint32_t;
+ typedef int int32_t;
+ typedef unsigned short uint16_t;
+ typedef short int16_t;
+ typedef unsigned char uint8_t;
+ typedef char int8_t;
+ #endif
+#endif
+
+//
+// Basic EFI types of various widths
+//
+
+#ifndef __WCHAR_TYPE__
+# define __WCHAR_TYPE__ short
+#endif
+
+typedef uint64_t UINT64;
+typedef int64_t INT64;
+
+#ifndef _BASETSD_H_
+ typedef uint32_t UINT32;
+ typedef int32_t INT32;
+#endif
+
+typedef uint16_t UINT16;
+typedef int16_t INT16;
+typedef uint8_t UINT8;
+typedef int8_t INT8;
+typedef __WCHAR_TYPE__ WCHAR;
+
+#undef VOID
+#define VOID void
+
+
+typedef int64_t INTN;
+typedef uint64_t UINTN;
+
+#define POST_CODE(_Data)
+
+
+#define BREAKPOINT() while (TRUE); // Make it hang on Bios[Dbg]32
+
+//
+// Pointers must be aligned to these address to function
+//
+
+#define MIN_ALIGNMENT_SIZE 4
+
+#define ALIGN_VARIABLE(Value ,Adjustment) \
+ (UINTN)Adjustment = 0; \
+ if((UINTN)Value % MIN_ALIGNMENT_SIZE) \
+ (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \
+ Value = (UINTN)Value + (UINTN)Adjustment
+
+
+//
+// Define macros to build data structure signatures from characters.
+//
+
+#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8))
+#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16))
+#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32))
+
+#define EXPORTAPI
+
+
+//
+// EFIAPI - prototype calling convention for EFI function pointers
+// BOOTSERVICE - prototype for implementation of a boot service interface
+// RUNTIMESERVICE - prototype for implementation of a runtime service interface
+// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service
+// RUNTIME_CODE - pragma macro for declaring runtime code
+//
+
+#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options
+ #define EFIAPI // Substitute expresion to force C calling convention
+#endif
+
+#define BOOTSERVICE
+//#define RUNTIMESERVICE(proto,a) alloc_text("rtcode",a); proto a
+//#define RUNTIMEFUNCTION(proto,a) alloc_text("rtcode",a); proto a
+#define RUNTIMESERVICE
+#define RUNTIMEFUNCTION
+
+
+#define RUNTIME_CODE(a) alloc_text("rtcode", a)
+#define BEGIN_RUNTIME_DATA() data_seg("rtdata")
+#define END_RUNTIME_DATA() data_seg("")
+
+#define VOLATILE volatile
+
+#define MEMORY_FENCE()
+
+
+//
+// When build similiar to FW, then link everything together as
+// one big module.
+//
+
+#define EFI_DRIVER_ENTRY_POINT(InitFunction) \
+ UINTN \
+ InitializeDriver ( \
+ VOID *ImageHandle, \
+ VOID *SystemTable \
+ ) \
+ { \
+ return InitFunction(ImageHandle, \
+ SystemTable); \
+ } \
+ \
+ EFI_STATUS efi_main( \
+ EFI_HANDLE image, \
+ EFI_SYSTEM_TABLE *systab \
+ ) __attribute__((weak, \
+ alias ("InitializeDriver")));
+
+#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \
+ (_if)->LoadInternal(type, name, entry)
+
+
+//
+// Some compilers don't support the forward reference construct:
+// typedef struct XXXXX
+//
+// The following macro provide a workaround for such cases.
+//
+#ifdef NO_INTERFACE_DECL
+#define INTERFACE_DECL(x)
+#else
+#ifdef __GNUC__
+#define INTERFACE_DECL(x) struct x
+#else
+#define INTERFACE_DECL(x) typedef struct x
+#endif
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/arm64/page.h b/xen/include/asm-arm/arm64/page.h
index 3922d87..1fd416d 100644
--- a/xen/include/asm-arm/arm64/page.h
+++ b/xen/include/asm-arm/arm64/page.h
@@ -14,21 +14,25 @@ static inline void write_pte(lpae_t *p, lpae_t pte)
: : "r" (pte.bits), "r" (p) : "memory");
}
+/* Inline ASM to invalidate dcache on register R (may be an inline asm operand) */
+#define __invalidate_dcache_one(R) "dc ivac, %" #R ";"
+
/* Inline ASM to flush dcache on register R (may be an inline asm operand) */
-#define __clean_xen_dcache_one(R) "dc cvac, %" #R ";"
+#define __clean_dcache_one(R) "dc cvac, %" #R ";"
/* Inline ASM to clean and invalidate dcache on register R (may be an
* inline asm operand) */
-#define __clean_and_invalidate_xen_dcache_one(R) "dc civac, %" #R ";"
+#define __clean_and_invalidate_dcache_one(R) "dc civac, %" #R ";"
/*
- * Flush all hypervisor mappings from the TLB
+ * Flush all hypervisor mappings from the TLB of the local processor.
+ *
* This is needed after changing Xen code mappings.
*
* The caller needs to issue the necessary DSB and D-cache flushes
* before calling flush_xen_text_tlb.
*/
-static inline void flush_xen_text_tlb(void)
+static inline void flush_xen_text_tlb_local(void)
{
asm volatile (
"isb;" /* Ensure synchronization with previous changes to text */
@@ -40,10 +44,11 @@ static inline void flush_xen_text_tlb(void)
}
/*
- * Flush all hypervisor mappings from the data TLB. This is not
- * sufficient when changing code mappings or for self modifying code.
+ * Flush all hypervisor mappings from the data TLB of the local
+ * processor. This is not sufficient when changing code mappings or
+ * for self modifying code.
*/
-static inline void flush_xen_data_tlb(void)
+static inline void flush_xen_data_tlb_local(void)
{
asm volatile (
"dsb sy;" /* Ensure visibility of PTE writes */
@@ -53,21 +58,17 @@ static inline void flush_xen_data_tlb(void)
: : : "memory");
}
-/*
- * Flush a range of VA's hypervisor mappings from the data TLB. This is not
- * sufficient when changing code mappings or for self modifying code.
- */
-static inline void flush_xen_data_tlb_range_va(unsigned long va, unsigned long size)
+/* Flush TLB of local processor for address va. */
+static inline void __flush_xen_data_tlb_one_local(vaddr_t va)
{
- unsigned long end = va + size;
- dsb(); /* Ensure preceding are visible */
- while ( va < end ) {
- asm volatile("tlbi vae2, %0;"
- : : "r" (va>>PAGE_SHIFT) : "memory");
- va += PAGE_SIZE;
- }
- dsb(); /* Ensure completion of the TLB flush */
- isb();
+ asm volatile("tlbi vae2, %0;" : : "r" (va>>PAGE_SHIFT) : "memory");
+}
+
+/* Flush TLB of all processors in the inner-shareable domain for
+ * address va. */
+static inline void __flush_xen_data_tlb_one(vaddr_t va)
+{
+ asm volatile("tlbi vae2is, %0;" : : "r" (va>>PAGE_SHIFT) : "memory");
}
/* Ask the MMU to translate a VA for us */
@@ -108,6 +109,8 @@ static inline uint64_t gva_to_ipa_par(vaddr_t va)
return par;
}
+extern void clear_page(void *to);
+
#endif /* __ASSEMBLY__ */
#endif /* __ARM_ARM64_PAGE_H__ */
diff --git a/xen/include/asm-arm/arm64/processor.h b/xen/include/asm-arm/arm64/processor.h
index 5bf0867..3a9c0cd 100644
--- a/xen/include/asm-arm/arm64/processor.h
+++ b/xen/include/asm-arm/arm64/processor.h
@@ -1,6 +1,8 @@
#ifndef __ASM_ARM_ARM64_PROCESSOR_H
#define __ASM_ARM_ARM64_PROCESSOR_H
+#include <xen/stringify.h>
+
#ifndef __ASSEMBLY__
/* Anonymous union includes both 32- and 64-bit names (e.g., r0/x0). */
@@ -85,20 +87,20 @@ struct cpu_user_regs
#define READ_SYSREG32(name) ({ \
uint32_t _r; \
- asm volatile("mrs %0, "#name : "=r" (_r)); \
+ asm volatile("mrs %0, "__stringify(name) : "=r" (_r)); \
_r; })
#define WRITE_SYSREG32(v, name) do { \
uint32_t _r = v; \
- asm volatile("msr "#name", %0" : : "r" (_r)); \
+ asm volatile("msr "__stringify(name)", %0" : : "r" (_r)); \
} while (0)
#define WRITE_SYSREG64(v, name) do { \
uint64_t _r = v; \
- asm volatile("msr "#name", %0" : : "r" (_r)); \
+ asm volatile("msr "__stringify(name)", %0" : : "r" (_r)); \
} while (0)
#define READ_SYSREG64(name) ({ \
uint64_t _r; \
- asm volatile("mrs %0, "#name : "=r" (_r)); \
+ asm volatile("mrs %0, "__stringify(name) : "=r" (_r)); \
_r; })
#define READ_SYSREG(name) READ_SYSREG64(name)
diff --git a/xen/include/asm-arm/arm64/spinlock.h b/xen/include/asm-arm/arm64/spinlock.h
index 3a36cfd..04300bc 100644
--- a/xen/include/asm-arm/arm64/spinlock.h
+++ b/xen/include/asm-arm/arm64/spinlock.h
@@ -70,7 +70,7 @@ static always_inline int _raw_read_trylock(raw_rwlock_t *rw)
"1:\n"
: "=&r" (tmp), "+r" (tmp2), "+Q" (rw->lock)
:
- : "cc", "memory");
+ : "memory");
return !tmp2;
}
@@ -86,7 +86,7 @@ static always_inline int _raw_write_trylock(raw_rwlock_t *rw)
"1:\n"
: "=&r" (tmp), "+Q" (rw->lock)
: "r" (0x80000000)
- : "cc", "memory");
+ : "memory");
return !tmp;
}
@@ -102,7 +102,7 @@ static inline void _raw_read_unlock(raw_rwlock_t *rw)
" cbnz %w1, 1b\n"
: "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
:
- : "cc", "memory");
+ : "memory");
}
static inline void _raw_write_unlock(raw_rwlock_t *rw)
diff --git a/xen/include/asm-arm/arm64/system.h b/xen/include/asm-arm/arm64/system.h
index d7e912f..6efced3 100644
--- a/xen/include/asm-arm/arm64/system.h
+++ b/xen/include/asm-arm/arm64/system.h
@@ -2,176 +2,7 @@
#ifndef __ASM_ARM64_SYSTEM_H
#define __ASM_ARM64_SYSTEM_H
-#define sev() asm volatile("sev" : : : "memory")
-#define wfe() asm volatile("wfe" : : : "memory")
-#define wfi() asm volatile("wfi" : : : "memory")
-
-#define isb() asm volatile("isb" : : : "memory")
-#define dsb() asm volatile("dsb sy" : : : "memory")
-#define dmb() asm volatile("dmb sy" : : : "memory")
-
-#define mb() dsb()
-#define rmb() dsb()
-#define wmb() mb()
-
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-
-
-extern void __bad_xchg(volatile void *, int);
-
-static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
-{
- unsigned long ret, tmp;
-
- switch (size) {
- case 1:
- asm volatile("// __xchg1\n"
- "1: ldaxrb %w0, %2\n"
- " stlxrb %w1, %w3, %2\n"
- " cbnz %w1, 1b\n"
- : "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr)
- : "r" (x)
- : "cc", "memory");
- break;
- case 2:
- asm volatile("// __xchg2\n"
- "1: ldaxrh %w0, %2\n"
- " stlxrh %w1, %w3, %2\n"
- " cbnz %w1, 1b\n"
- : "=&r" (ret), "=&r" (tmp), "+Q" (*(u16 *)ptr)
- : "r" (x)
- : "cc", "memory");
- break;
- case 4:
- asm volatile("// __xchg4\n"
- "1: ldaxr %w0, %2\n"
- " stlxr %w1, %w3, %2\n"
- " cbnz %w1, 1b\n"
- : "=&r" (ret), "=&r" (tmp), "+Q" (*(u32 *)ptr)
- : "r" (x)
- : "cc", "memory");
- break;
- case 8:
- asm volatile("// __xchg8\n"
- "1: ldaxr %0, %2\n"
- " stlxr %w1, %3, %2\n"
- " cbnz %w1, 1b\n"
- : "=&r" (ret), "=&r" (tmp), "+Q" (*(u64 *)ptr)
- : "r" (x)
- : "cc", "memory");
- break;
- default:
- __bad_xchg(ptr, size), ret = 0;
- break;
- }
-
- return ret;
-}
-
-#define xchg(ptr,x) \
- ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-extern void __bad_cmpxchg(volatile void *ptr, int size);
-
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
- unsigned long new, int size)
-{
- unsigned long oldval = 0, res;
-
- switch (size) {
- case 1:
- do {
- asm volatile("// __cmpxchg1\n"
- " ldxrb %w1, %2\n"
- " mov %w0, #0\n"
- " cmp %w1, %w3\n"
- " b.ne 1f\n"
- " stxrb %w0, %w4, %2\n"
- "1:\n"
- : "=&r" (res), "=&r" (oldval), "+Q" (*(u8 *)ptr)
- : "Ir" (old), "r" (new)
- : "cc");
- } while (res);
- break;
-
- case 2:
- do {
- asm volatile("// __cmpxchg2\n"
- " ldxrh %w1, %2\n"
- " mov %w0, #0\n"
- " cmp %w1, %w3\n"
- " b.ne 1f\n"
- " stxrh %w0, %w4, %2\n"
- "1:\n"
- : "=&r" (res), "=&r" (oldval), "+Q" (*(u16 *)ptr)
- : "Ir" (old), "r" (new)
- : "cc");
- } while (res);
- break;
-
- case 4:
- do {
- asm volatile("// __cmpxchg4\n"
- " ldxr %w1, %2\n"
- " mov %w0, #0\n"
- " cmp %w1, %w3\n"
- " b.ne 1f\n"
- " stxr %w0, %w4, %2\n"
- "1:\n"
- : "=&r" (res), "=&r" (oldval), "+Q" (*(u32 *)ptr)
- : "Ir" (old), "r" (new)
- : "cc");
- } while (res);
- break;
-
- case 8:
- do {
- asm volatile("// __cmpxchg8\n"
- " ldxr %1, %2\n"
- " mov %w0, #0\n"
- " cmp %1, %3\n"
- " b.ne 1f\n"
- " stxr %w0, %4, %2\n"
- "1:\n"
- : "=&r" (res), "=&r" (oldval), "+Q" (*(u64 *)ptr)
- : "Ir" (old), "r" (new)
- : "cc");
- } while (res);
- break;
-
- default:
- __bad_cmpxchg(ptr, size);
- oldval = 0;
- }
-
- return oldval;
-}
-
-static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
- unsigned long new, int size)
-{
- unsigned long ret;
-
- smp_mb();
- ret = __cmpxchg(ptr, old, new, size);
- smp_mb();
-
- return ret;
-}
-
-#define cmpxchg(ptr,o,n) \
- ((__typeof__(*(ptr)))__cmpxchg_mb((ptr), \
- (unsigned long)(o), \
- (unsigned long)(n), \
- sizeof(*(ptr))))
-
-#define cmpxchg_local(ptr,o,n) \
- ((__typeof__(*(ptr)))__cmpxchg((ptr), \
- (unsigned long)(o), \
- (unsigned long)(n), \
- sizeof(*(ptr))))
+#include <asm/arm64/cmpxchg.h>
/* Uses uimm4 as a bitmask to select the clearing of one or more of
* the DAIF exception mask bits:
diff --git a/xen/include/asm-arm/atomic.h b/xen/include/asm-arm/atomic.h
index 69c8f3f..7d15fb0 100644
--- a/xen/include/asm-arm/atomic.h
+++ b/xen/include/asm-arm/atomic.h
@@ -2,6 +2,7 @@
#define __ARCH_ARM_ATOMIC__
#include <xen/config.h>
+#include <xen/prefetch.h>
#include <asm/system.h>
#define build_atomic_read(name, size, width, type, reg)\
@@ -83,11 +84,25 @@ typedef struct { int counter; } atomic_t;
* strex/ldrex monitor on some implementations. The reason we can use it for
* atomic_set() is the clrex or dummy strex done on every exception return.
*/
-#define _atomic_read(v) ((v).counter)
-#define atomic_read(v) (*(volatile int *)&(v)->counter)
+static inline int atomic_read(atomic_t *v)
+{
+ return *(volatile int *)&v->counter;
+}
+
+static inline int _atomic_read(atomic_t v)
+{
+ return v.counter;
+}
-#define _atomic_set(v,i) (((v).counter) = (i))
-#define atomic_set(v,i) (((v)->counter) = (i))
+static inline void atomic_set(atomic_t *v, int i)
+{
+ v->counter = i;
+}
+
+static inline void _atomic_set(atomic_t *v, int i)
+{
+ v->counter = i;
+}
#if defined(CONFIG_ARM_32)
# include <asm/arm32/atomic.h>
diff --git a/xen/include/asm-arm/bug.h b/xen/include/asm-arm/bug.h
index 458c818..ab9e811 100644
--- a/xen/include/asm-arm/bug.h
+++ b/xen/include/asm-arm/bug.h
@@ -1,10 +1,81 @@
#ifndef __ARM_BUG_H__
#define __ARM_BUG_H__
-#define BUG() __bug(__FILE__, __LINE__)
-#define WARN() __warn(__FILE__, __LINE__)
+#include <asm/processor.h>
-#endif /* __X86_BUG_H__ */
+#if defined(CONFIG_ARM_32)
+# include <asm/arm32/bug.h>
+#elif defined(CONFIG_ARM_64)
+# include <asm/arm64/bug.h>
+#else
+# error "unknown ARM variant"
+#endif
+
+#define BUG_DISP_WIDTH 24
+#define BUG_LINE_LO_WIDTH (31 - BUG_DISP_WIDTH)
+#define BUG_LINE_HI_WIDTH (31 - BUG_DISP_WIDTH)
+
+struct bug_frame {
+ signed int loc_disp; /* Relative address to the bug address */
+ signed int file_disp; /* Relative address to the filename */
+ signed int msg_disp; /* Relative address to the predicate (for ASSERT) */
+ uint16_t line; /* Line number */
+ uint32_t pad0:16; /* Padding for 8-bytes align */
+};
+
+#define bug_loc(b) ((const void *)(b) + (b)->loc_disp)
+#define bug_file(b) ((const void *)(b) + (b)->file_disp);
+#define bug_line(b) ((b)->line)
+#define bug_msg(b) ((const char *)(b) + (b)->msg_disp)
+
+#define BUGFRAME_warn 0
+#define BUGFRAME_bug 1
+#define BUGFRAME_assert 2
+
+/* Many versions of GCC doesn't support the asm %c parameter which would
+ * be preferable to this unpleasantness. We use mergeable string
+ * sections to avoid multiple copies of the string appearing in the
+ * Xen image.
+ */
+#define BUG_FRAME(type, line, file, has_msg, msg) do { \
+ BUILD_BUG_ON((line) >> 16); \
+ asm ("1:"BUG_INSTR"\n" \
+ ".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \
+ "2:\t.asciz " __stringify(file) "\n" \
+ "3:\n" \
+ ".if " #has_msg "\n" \
+ "\t.asciz " #msg "\n" \
+ ".endif\n" \
+ ".popsection\n" \
+ ".pushsection .bug_frames." __stringify(type) ", \"a\", %progbits\n"\
+ "4:\n" \
+ ".long (1b - 4b)\n" \
+ ".long (2b - 4b)\n" \
+ ".long (3b - 4b)\n" \
+ ".hword " __stringify(line) ", 0\n" \
+ ".popsection"); \
+} while (0)
+
+#define WARN() BUG_FRAME(BUGFRAME_warn, __LINE__, __FILE__, 0, "")
+
+#define BUG() do { \
+ BUG_FRAME(BUGFRAME_bug, __LINE__, __FILE__, 0, ""); \
+ unreachable(); \
+} while (0)
+
+#define assert_failed(msg) do { \
+ BUG_FRAME(BUGFRAME_assert, __LINE__, __FILE__, 1, msg); \
+ unreachable(); \
+} while (0)
+
+extern const struct bug_frame __start_bug_frames[],
+ __stop_bug_frames_0[],
+ __stop_bug_frames_1[],
+ __stop_bug_frames_2[];
+
+int do_bug_frame(struct cpu_user_regs *regs, vaddr_t pc);
+
+#endif /* __ARM_BUG_H__ */
/*
* Local variables:
* mode: C
diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
index 5b7b1a8..264e2c1 100644
--- a/xen/include/asm-arm/config.h
+++ b/xen/include/asm-arm/config.h
@@ -37,6 +37,8 @@
#define CONFIG_VIDEO 1
+#define CONFIG_IRQ_HAS_MULTIPLE_ACTION 1
+
#define OPT_CONSOLE_STR "dtuart"
#ifdef MAX_PHYS_CPUS
@@ -124,7 +126,12 @@
#define CONFIG_SEPARATE_XENHEAP 1
#define FRAMETABLE_VIRT_START _AT(vaddr_t,0x02000000)
-#define VMAP_VIRT_START _AT(vaddr_t,0x10000000)
+#define FRAMETABLE_SIZE MB(128-32)
+#define FRAMETABLE_NR (FRAMETABLE_SIZE / sizeof(*frame_table))
+#define FRAMETABLE_VIRT_END (FRAMETABLE_VIRT_START + FRAMETABLE_SIZE - 1)
+
+#define VMAP_VIRT_START _AT(vaddr_t,0x10000000)
+
#define XENHEAP_VIRT_START _AT(vaddr_t,0x40000000)
#define XENHEAP_VIRT_END _AT(vaddr_t,0x7fffffff)
#define DOMHEAP_VIRT_START _AT(vaddr_t,0x80000000)
@@ -147,13 +154,15 @@
#define VMAP_VIRT_END (VMAP_VIRT_START + GB(1) - 1)
#define FRAMETABLE_VIRT_START GB(32)
-#define FRAMETABLE_VIRT_END (FRAMETABLE_VIRT_START + GB(32) - 1)
+#define FRAMETABLE_SIZE GB(32)
+#define FRAMETABLE_NR (FRAMETABLE_SIZE / sizeof(*frame_table))
+#define FRAMETABLE_VIRT_END (FRAMETABLE_VIRT_START + FRAMETABLE_SIZE - 1)
#define DIRECTMAP_VIRT_START SLOT0(256)
#define DIRECTMAP_SIZE (SLOT0_ENTRY_SIZE * (265-256))
#define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + DIRECTMAP_SIZE - 1)
-#define XENHEAP_VIRT_START DIRECTMAP_VIRT_START
+#define XENHEAP_VIRT_START xenheap_virt_start
#define HYPERVISOR_VIRT_END DIRECTMAP_VIRT_END
@@ -192,17 +201,6 @@ extern unsigned long frametable_virt_end;
#define watchdog_disable() ((void)0)
#define watchdog_enable() ((void)0)
-#ifdef __ASSEMBLY__
-/* Board-specific: regs base address for the GIC
- * Theses constants are only intend to be used in assembly file
- * because the DT is not yet parsed.
- */
-#define GIC_DR_OFFSET 0x1000
-#define GIC_CR_OFFSET 0x2000
-#define GIC_HR_OFFSET 0x4000 /* Guess work http://lists.infradead.org/pipermail/linux-arm-kernel/2011-September/064219.html */
-#define GIC_VR_OFFSET 0x6000 /* Virtual Machine CPU interface) */
-#endif /* __ASSEMBLY__ */
-
#endif /* __ARM_CONFIG_H__ */
/*
* Local variables:
diff --git a/xen/include/asm-arm/cpufeature.h b/xen/include/asm-arm/cpufeature.h
index 1d2c9c7..7b519cd 100644
--- a/xen/include/asm-arm/cpufeature.h
+++ b/xen/include/asm-arm/cpufeature.h
@@ -15,18 +15,24 @@
#define cpu_has_el3_64 (boot_cpu_feature64(el3) >= 1)
#define cpu_has_fp (boot_cpu_feature64(fp) == 0)
#define cpu_has_simd (boot_cpu_feature64(simd) == 0)
+#define cpu_has_gicv3 (boot_cpu_feature64(gic) == 1)
#endif
#define cpu_feature32(c, feat) ((c)->pfr32.feat)
#define boot_cpu_feature32(feat) (boot_cpu_data.pfr32.feat)
-#define cpu_has_aarch32 (boot_cpu_feature32(arm) == 1)
+#define cpu_has_arm (boot_cpu_feature32(arm) == 1)
#define cpu_has_thumb (boot_cpu_feature32(thumb) >= 1)
#define cpu_has_thumb2 (boot_cpu_feature32(thumb) >= 3)
#define cpu_has_jazelle (boot_cpu_feature32(jazelle) >= 0)
#define cpu_has_thumbee (boot_cpu_feature32(thumbee) == 1)
+#define cpu_has_aarch32 (cpu_has_arm || cpu_has_thumb)
+#ifdef CONFIG_ARM_32
#define cpu_has_gentimer (boot_cpu_feature32(gentimer) == 1)
+#else
+#define cpu_has_gentimer (1)
+#endif
#define cpu_has_security (boot_cpu_feature32(security) > 0)
#endif
diff --git a/xen/include/asm-arm/debugger.h b/xen/include/asm-arm/debugger.h
index 916860b..ac776ef 100644
--- a/xen/include/asm-arm/debugger.h
+++ b/xen/include/asm-arm/debugger.h
@@ -1,7 +1,7 @@
#ifndef __ARM_DEBUGGER_H__
#define __ARM_DEBUGGER_H__
-#define debugger_trap_fatal(v, r) ((void) 0)
+#define debugger_trap_fatal(v, r) (0)
#define debugger_trap_immediate() ((void) 0)
#endif /* __ARM_DEBUGGER_H__ */
diff --git a/xen/include/asm-arm/device.h b/xen/include/asm-arm/device.h
index 9e47ca6..74a80c6 100644
--- a/xen/include/asm-arm/device.h
+++ b/xen/include/asm-arm/device.h
@@ -6,7 +6,11 @@
enum device_type
{
- DEVICE_SERIAL
+ DEVICE_SERIAL,
+ DEVICE_IOMMU,
+ DEVICE_GIC,
+ /* Use for error */
+ DEVICE_UNKNOWN,
};
struct device_desc {
@@ -31,6 +35,14 @@ struct device_desc {
int __init device_init(struct dt_device_node *dev, enum device_type type,
const void *data);
+/**
+ * device_get_type - Get the type of the device
+ * @dev: device to match
+ *
+ * Return the device type on success or DEVICE_ANY on failure
+ */
+enum device_type device_get_type(const struct dt_device_node *dev);
+
#define DT_DEVICE_START(_name, _namestr, _type) \
static const struct device_desc __dev_desc_##_name __used \
__attribute__((__section__(".dev.info"))) = { \
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 49f64b8..787e93c 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -7,87 +7,32 @@
#include <asm/page.h>
#include <asm/p2m.h>
#include <asm/vfp.h>
+#include <asm/mmio.h>
+#include <asm/gic.h>
#include <public/hvm/params.h>
#include <xen/serial.h>
-
-/* Represents state corresponding to a block of 32 interrupts */
-struct vgic_irq_rank {
- spinlock_t lock; /* Covers access to all other members of this struct */
- uint32_t ienable, iactive, ipend, pendsgi;
- uint32_t icfg[2];
- uint32_t ipriority[8];
- uint32_t itargets[8];
-};
-
-struct pending_irq
-{
- int irq;
- /*
- * The following two states track the lifecycle of the guest irq.
- * However because we are not sure and we don't want to track
- * whether an irq added to an LR register is PENDING or ACTIVE, the
- * following states are just an approximation.
- *
- * GIC_IRQ_GUEST_PENDING: the irq is asserted
- *
- * GIC_IRQ_GUEST_VISIBLE: the irq has been added to an LR register,
- * therefore the guest is aware of it. From the guest point of view
- * the irq can be pending (if the guest has not acked the irq yet)
- * or active (after acking the irq).
- *
- * In order for the state machine to be fully accurate, for level
- * interrupts, we should keep the GIC_IRQ_GUEST_PENDING state until
- * the guest deactivates the irq. However because we are not sure
- * when that happens, we simply remove the GIC_IRQ_GUEST_PENDING
- * state when we add the irq to an LR register. We add it back when
- * we receive another interrupt notification.
- * Therefore it is possible to set GIC_IRQ_GUEST_PENDING while the
- * irq is GIC_IRQ_GUEST_VISIBLE. We could also change the state of
- * the guest irq in the LR register from active to active and
- * pending, but for simplicity we simply inject a second irq after
- * the guest EOIs the first one.
- *
- *
- * An additional state is used to keep track of whether the guest
- * irq is enabled at the vgicd level:
- *
- * GIC_IRQ_GUEST_ENABLED: the guest IRQ is enabled at the VGICD
- * level (GICD_ICENABLER/GICD_ISENABLER).
- *
- */
-#define GIC_IRQ_GUEST_PENDING 0
-#define GIC_IRQ_GUEST_VISIBLE 1
-#define GIC_IRQ_GUEST_ENABLED 2
- unsigned long status;
- struct irq_desc *desc; /* only set it the irq corresponds to a physical irq */
- uint8_t priority;
- /* inflight is used to append instances of pending_irq to
- * vgic.inflight_irqs */
- struct list_head inflight;
- /* lr_queue is used to append instances of pending_irq to
- * gic.lr_pending */
- struct list_head lr_queue;
-};
+#include <xen/hvm/iommu.h>
struct hvm_domain
{
uint64_t params[HVM_NR_PARAMS];
+ struct hvm_iommu iommu;
} __cacheline_aligned;
#ifdef CONFIG_ARM_64
enum domain_type {
- DOMAIN_PV32,
- DOMAIN_PV64,
+ DOMAIN_32BIT,
+ DOMAIN_64BIT,
};
-#define is_pv32_domain(d) ((d)->arch.type == DOMAIN_PV32)
-#define is_pv64_domain(d) ((d)->arch.type == DOMAIN_PV64)
+#define is_32bit_domain(d) ((d)->arch.type == DOMAIN_32BIT)
+#define is_64bit_domain(d) ((d)->arch.type == DOMAIN_64BIT)
#else
-#define is_pv32_domain(d) (1)
-#define is_pv64_domain(d) (0)
+#define is_32bit_domain(d) (1)
+#define is_64bit_domain(d) (0)
#endif
extern int dom0_11_mapping;
-#define is_domain_direct_mapped(d) ((d) == dom0 && dom0_11_mapping)
+#define is_domain_direct_mapped(d) ((d) == hardware_domain && dom0_11_mapping)
struct vtimer {
struct vcpu *v;
@@ -110,6 +55,7 @@ struct arch_domain
struct hvm_domain hvm_domain;
xen_pfn_t *grant_table_gpfn;
+ struct io_handler io_handlers;
/* Continuable domain_relinquish_resources(). */
enum {
RELMEM_not_started,
@@ -130,6 +76,8 @@ struct arch_domain
} virt_timer_base;
struct {
+ /* GIC HW version specific vGIC driver handler */
+ const struct vgic_ops *handler;
/*
* Covers access to other members of this struct _except_ for
* shared_irqs where each member contains its own locking.
@@ -151,6 +99,14 @@ struct arch_domain
/* Base address for guest GIC */
paddr_t dbase; /* Distributor base address */
paddr_t cbase; /* CPU base address */
+#ifdef CONFIG_ARM_64
+ /* GIC V3 addressing */
+ paddr_t dbase_size; /* Distributor base size */
+ paddr_t rbase[MAX_RDIST_COUNT]; /* Re-Distributor base address */
+ paddr_t rbase_size[MAX_RDIST_COUNT]; /* Re-Distributor size */
+ uint32_t rdist_stride; /* Re-Distributor stride */
+ int rdist_count; /* No. of Re-Distributors */
+#endif
} vgic;
struct vuart {
@@ -252,9 +208,8 @@ struct arch_vcpu
uint32_t csselr;
register_t vmpidr;
- uint32_t gic_hcr, gic_vmcr, gic_apr;
- uint32_t gic_lr[64];
- uint64_t event_mask;
+ /* Holds gic context data */
+ union gic_state_data gic;
uint64_t lr_mask;
struct {
@@ -263,7 +218,7 @@ struct arch_vcpu
* struct arch_domain.
*/
struct pending_irq pending_irqs[32];
- struct vgic_irq_rank private_irqs;
+ struct vgic_irq_rank *private_irqs;
/* This list is ordered by IRQ priority and it is used to keep
* track of the IRQs that the VGIC injected into the guest.
@@ -288,6 +243,7 @@ struct arch_vcpu
struct vtimer phys_timer;
struct vtimer virt_timer;
+ bool_t vtimer_initialized;
} __cacheline_aligned;
void vcpu_show_execution_state(struct vcpu *);
diff --git a/xen/include/asm-arm/early_printk.h b/xen/include/asm-arm/early_printk.h
index 707bbf7..8c3d6a8 100644
--- a/xen/include/asm-arm/early_printk.h
+++ b/xen/include/asm-arm/early_printk.h
@@ -12,35 +12,12 @@
#include <xen/config.h>
-#ifdef EARLY_PRINTK
+#ifdef CONFIG_EARLY_PRINTK
/* need to add the uart address offset in page to the fixmap address */
#define EARLY_UART_VIRTUAL_ADDRESS \
(FIXMAP_ADDR(FIXMAP_CONSOLE) +(EARLY_UART_BASE_ADDRESS & ~PAGE_MASK))
-#endif
-
-#ifndef __ASSEMBLY__
-
-#ifdef EARLY_PRINTK
-
-void early_printk(const char *fmt, ...)
- __attribute__((format (printf, 1, 2)));
-void early_panic(const char *fmt, ...) __attribute__((noreturn))
- __attribute__((format (printf, 1, 2)));
-
-#else
-
-static inline __attribute__((format (printf, 1, 2))) void
-early_printk(const char *fmt, ...)
-{}
-
-static inline void __attribute__((noreturn))
-__attribute__((format (printf, 1, 2))) early_panic(const char *fmt, ...)
-{while(1);}
-
-#endif
-
-#endif /* __ASSEMBLY__ */
+#endif /* !CONFIG_EARLY_PRINTK */
#endif
diff --git a/xen/include/asm-arm/efibind.h b/xen/include/asm-arm/efibind.h
new file mode 100644
index 0000000..09dca7a
--- /dev/null
+++ b/xen/include/asm-arm/efibind.h
@@ -0,0 +1,2 @@
+#include <xen/types.h>
+#include <asm/arm64/efibind.h>
diff --git a/xen/include/asm-arm/event.h b/xen/include/asm-arm/event.h
index dd3ad13..5330dfe 100644
--- a/xen/include/asm-arm/event.h
+++ b/xen/include/asm-arm/event.h
@@ -6,6 +6,7 @@
void vcpu_kick(struct vcpu *v);
void vcpu_mark_events_pending(struct vcpu *v);
+void vcpu_block_unless_event_pending(struct vcpu *v);
static inline int vcpu_event_delivery_is_enabled(struct vcpu *v)
{
diff --git a/xen/include/asm-arm/flushtlb.h b/xen/include/asm-arm/flushtlb.h
index 329fbb4..c986b3f 100644
--- a/xen/include/asm-arm/flushtlb.h
+++ b/xen/include/asm-arm/flushtlb.h
@@ -25,6 +25,9 @@ do { \
/* Flush specified CPUs' TLBs */
void flush_tlb_mask(const cpumask_t *mask);
+/* Flush CPU's TLBs for the specified domain */
+void flush_tlb_domain(struct domain *d);
+
#endif /* __ASM_ARM_FLUSHTLB_H__ */
/*
* Local variables:
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 87f4298..187dc46 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -18,69 +18,76 @@
#ifndef __ASM_ARM_GIC_H__
#define __ASM_ARM_GIC_H__
-#define GICD_CTLR (0x000/4)
-#define GICD_TYPER (0x004/4)
-#define GICD_IIDR (0x008/4)
-#define GICD_IGROUPR (0x080/4)
-#define GICD_IGROUPRN (0x0FC/4)
-#define GICD_ISENABLER (0x100/4)
-#define GICD_ISENABLERN (0x17C/4)
-#define GICD_ICENABLER (0x180/4)
-#define GICD_ICENABLERN (0x1fC/4)
-#define GICD_ISPENDR (0x200/4)
-#define GICD_ISPENDRN (0x27C/4)
-#define GICD_ICPENDR (0x280/4)
-#define GICD_ICPENDRN (0x2FC/4)
-#define GICD_ISACTIVER (0x300/4)
-#define GICD_ISACTIVERN (0x37C/4)
-#define GICD_ICACTIVER (0x380/4)
-#define GICD_ICACTIVERN (0x3FC/4)
-#define GICD_IPRIORITYR (0x400/4)
-#define GICD_IPRIORITYRN (0x7F8/4)
-#define GICD_ITARGETSR (0x800/4)
-#define GICD_ITARGETSRN (0xBF8/4)
-#define GICD_ICFGR (0xC00/4)
-#define GICD_ICFGRN (0xCFC/4)
-#define GICD_NSACR (0xE00/4)
-#define GICD_NSACRN (0xEFC/4)
-#define GICD_SGIR (0xF00/4)
-#define GICD_CPENDSGIR (0xF10/4)
-#define GICD_CPENDSGIRN (0xF1C/4)
-#define GICD_SPENDSGIR (0xF20/4)
-#define GICD_SPENDSGIRN (0xF2C/4)
-#define GICD_ICPIDR2 (0xFE8/4)
+#define NR_GIC_LOCAL_IRQS NR_LOCAL_IRQS
+#define NR_GIC_SGI 16
+#define MAX_RDIST_COUNT 4
+
+#define GICD_CTLR (0x000)
+#define GICD_TYPER (0x004)
+#define GICD_IIDR (0x008)
+#define GICD_IGROUPR (0x080)
+#define GICD_IGROUPRN (0x0FC)
+#define GICD_ISENABLER (0x100)
+#define GICD_ISENABLERN (0x17C)
+#define GICD_ICENABLER (0x180)
+#define GICD_ICENABLERN (0x1fC)
+#define GICD_ISPENDR (0x200)
+#define GICD_ISPENDRN (0x27C)
+#define GICD_ICPENDR (0x280)
+#define GICD_ICPENDRN (0x2FC)
+#define GICD_ISACTIVER (0x300)
+#define GICD_ISACTIVERN (0x37C)
+#define GICD_ICACTIVER (0x380)
+#define GICD_ICACTIVERN (0x3FC)
+#define GICD_IPRIORITYR (0x400)
+#define GICD_IPRIORITYRN (0x7F8)
+#define GICD_ITARGETSR (0x800)
+#define GICD_ITARGETSRN (0xBF8)
+#define GICD_ICFGR (0xC00)
+#define GICD_ICFGRN (0xCFC)
+#define GICD_NSACR (0xE00)
+#define GICD_NSACRN (0xEFC)
+#define GICD_SGIR (0xF00)
+#define GICD_CPENDSGIR (0xF10)
+#define GICD_CPENDSGIRN (0xF1C)
+#define GICD_SPENDSGIR (0xF20)
+#define GICD_SPENDSGIRN (0xF2C)
+#define GICD_ICPIDR2 (0xFE8)
#define GICD_SGI_TARGET_LIST_SHIFT (24)
#define GICD_SGI_TARGET_LIST_MASK (0x3UL << GICD_SGI_TARGET_LIST_SHIFT)
#define GICD_SGI_TARGET_LIST (0UL<<GICD_SGI_TARGET_LIST_SHIFT)
+#define GICD_SGI_TARGET_LIST_VAL (0)
#define GICD_SGI_TARGET_OTHERS (1UL<<GICD_SGI_TARGET_LIST_SHIFT)
+#define GICD_SGI_TARGET_OTHERS_VAL (1)
#define GICD_SGI_TARGET_SELF (2UL<<GICD_SGI_TARGET_LIST_SHIFT)
+#define GICD_SGI_TARGET_SELF_VAL (2)
#define GICD_SGI_TARGET_SHIFT (16)
#define GICD_SGI_TARGET_MASK (0xFFUL<<GICD_SGI_TARGET_SHIFT)
#define GICD_SGI_GROUP1 (1UL<<15)
#define GICD_SGI_INTID_MASK (0xFUL)
-#define GICC_CTLR (0x0000/4)
-#define GICC_PMR (0x0004/4)
-#define GICC_BPR (0x0008/4)
-#define GICC_IAR (0x000C/4)
-#define GICC_EOIR (0x0010/4)
-#define GICC_RPR (0x0014/4)
-#define GICC_HPPIR (0x0018/4)
-#define GICC_APR (0x00D0/4)
-#define GICC_NSAPR (0x00E0/4)
-#define GICC_DIR (0x1000/4)
-
-#define GICH_HCR (0x00/4)
-#define GICH_VTR (0x04/4)
-#define GICH_VMCR (0x08/4)
-#define GICH_MISR (0x10/4)
-#define GICH_EISR0 (0x20/4)
-#define GICH_EISR1 (0x24/4)
-#define GICH_ELSR0 (0x30/4)
-#define GICH_ELSR1 (0x34/4)
-#define GICH_APR (0xF0/4)
-#define GICH_LR (0x100/4)
+#define GICC_CTLR (0x0000)
+#define GICC_PMR (0x0004)
+#define GICC_BPR (0x0008)
+#define GICC_IAR (0x000C)
+#define GICC_EOIR (0x0010)
+#define GICC_RPR (0x0014)
+#define GICC_HPPIR (0x0018)
+#define GICC_APR (0x00D0)
+#define GICC_NSAPR (0x00E0)
+#define GICC_DIR (0x1000)
+
+#define GICH_HCR (0x00)
+#define GICH_VTR (0x04)
+#define GICH_VMCR (0x08)
+#define GICH_MISR (0x10)
+#define GICH_EISR0 (0x20)
+#define GICH_EISR1 (0x24)
+#define GICH_ELSR0 (0x30)
+#define GICH_ELSR1 (0x34)
+#define GICH_APR (0xF0)
+#define GICH_LR (0x100)
/* Register bits */
#define GICD_CTL_ENABLE 0x1
@@ -114,54 +121,116 @@
#define GICH_MISR_VGRP1E (1 << 6)
#define GICH_MISR_VGRP1D (1 << 7)
-#define GICH_LR_VIRTUAL_MASK 0x3ff
-#define GICH_LR_VIRTUAL_SHIFT 0
-#define GICH_LR_PHYSICAL_MASK 0x3ff
-#define GICH_LR_PHYSICAL_SHIFT 10
-#define GICH_LR_STATE_MASK 0x3
-#define GICH_LR_STATE_SHIFT 28
-#define GICH_LR_PRIORITY_SHIFT 23
-#define GICH_LR_MAINTENANCE_IRQ (1<<19)
-#define GICH_LR_PENDING (1<<28)
-#define GICH_LR_ACTIVE (1<<29)
-#define GICH_LR_GRP1 (1<<30)
-#define GICH_LR_HW (1<<31)
-#define GICH_LR_CPUID_SHIFT 9
-#define GICH_VTR_NRLRGS 0x3f
+/*
+ * The minimum GICC_BPR is required to be in the range 0-3. We set
+ * GICC_BPR to 0 but we must expect that it might be 3. This means we
+ * can rely on premption between the following ranges:
+ * 0xf0..0xff
+ * 0xe0..0xdf
+ * 0xc0..0xcf
+ * 0xb0..0xbf
+ * 0xa0..0xaf
+ * 0x90..0x9f
+ * 0x80..0x8f
+ *
+ * Priorities within a range will not preempt each other.
+ *
+ * A GIC must support a mimimum of 16 priority levels.
+ */
+#define GIC_PRI_LOWEST 0xf0
+#define GIC_PRI_IRQ 0xa0
+#define GIC_PRI_IPI 0x90 /* IPIs must preempt normal interrupts */
+#define GIC_PRI_HIGHEST 0x80 /* Higher priorities belong to Secure-World */
+#define GIC_PRI_TO_GUEST(pri) (pri >> 3) /* GICH_LR and GICH_VMCR only support
+ 5 bits for guest irq priority */
+
+#define GICH_LR_PENDING 1
+#define GICH_LR_ACTIVE 2
#ifndef __ASSEMBLY__
#include <xen/device_tree.h>
+#include <xen/irq.h>
+#include <asm-arm/vgic.h>
-#define DT_MATCH_GIC DT_MATCH_COMPATIBLE("arm,cortex-a15-gic"), \
- DT_MATCH_COMPATIBLE("arm,cortex-a7-gic")
+#define DT_COMPAT_GIC_400 "arm,gic-400"
+#define DT_COMPAT_GIC_CORTEX_A15 "arm,cortex-a15-gic"
+#define DT_COMPAT_GIC_CORTEX_A7 "arm,cortex-a7-gic"
-extern int domain_vgic_init(struct domain *d);
-extern void domain_vgic_free(struct domain *d);
+#define DT_MATCH_GIC_V2 DT_MATCH_COMPATIBLE(DT_COMPAT_GIC_CORTEX_A15), \
+ DT_MATCH_COMPATIBLE(DT_COMPAT_GIC_CORTEX_A7), \
+ DT_MATCH_COMPATIBLE(DT_COMPAT_GIC_400)
-extern int vcpu_vgic_init(struct vcpu *v);
+#define DT_COMPAT_GIC_V3 "arm,gic-v3"
-extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq,int virtual);
-extern void vgic_clear_pending_irqs(struct vcpu *v);
-extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq);
+#define DT_MATCH_GIC_V3 DT_MATCH_COMPATIBLE(DT_COMPAT_GIC_V3)
-/* Program the GIC to route an interrupt with a dt_irq */
-extern void gic_route_dt_irq(const struct dt_irq *irq,
- const cpumask_t *cpu_mask,
- unsigned int priority);
-extern void gic_route_ppis(void);
-extern void gic_route_spis(void);
+/*
+ * GICv3 registers that needs to be saved/restored
+ */
+struct gic_v3 {
+ uint32_t hcr, vmcr, sre_el1;
+ uint32_t apr0[4];
+ uint32_t apr1[4];
+ uint64_t lr[16];
+};
+
+/*
+ * GICv2 register that needs to be saved/restored
+ * on VCPU context switch
+ */
+struct gic_v2 {
+ uint32_t hcr;
+ uint32_t vmcr;
+ uint32_t apr;
+ uint32_t lr[64];
+};
+
+/*
+ * Union to hold underlying hw version context information
+ */
+union gic_state_data {
+ struct gic_v2 v2;
+ struct gic_v3 v3;
+};
+
+/*
+ * Decode LR register content.
+ * The LR register format is different for GIC HW version
+ */
+struct gic_lr {
+ /* Physical IRQ */
+ uint32_t pirq;
+ /* Virtual IRQ */
+ uint32_t virq;
+ uint8_t priority;
+ uint8_t state;
+ uint8_t hw_status;
+ uint8_t grp;
+};
+
+enum gic_version {
+ GIC_V2,
+ GIC_V3,
+};
+
+extern enum gic_version gic_hw_version(void);
+
+/* Program the GIC to route an interrupt */
+extern void gic_route_irq_to_xen(struct irq_desc *desc, const cpumask_t *cpu_mask,
+ unsigned int priority);
+extern void gic_route_irq_to_guest(struct domain *, struct irq_desc *desc,
+ const cpumask_t *cpu_mask,
+ unsigned int priority);
extern void gic_inject(void);
extern void gic_clear_pending_irqs(struct vcpu *v);
extern int gic_events_need_delivery(void);
extern void __cpuinit init_maintenance_interrupt(void);
-extern void gic_set_guest_irq(struct vcpu *v, unsigned int irq,
- unsigned int state, unsigned int priority);
+extern void gic_raise_guest_irq(struct vcpu *v, unsigned int irq,
+ unsigned int priority);
+extern void gic_raise_inflight_irq(struct vcpu *v, unsigned int virtual_irq);
extern void gic_remove_from_queues(struct vcpu *v, unsigned int virtual_irq);
-extern int gic_route_irq_to_guest(struct domain *d,
- const struct dt_irq *irq,
- const char * devname);
/* Accept an interrupt from the GIC and dispatch its handler */
extern void gic_interrupt(struct cpu_user_regs *regs, int is_fiq);
@@ -184,6 +253,14 @@ enum gic_sgi {
GIC_SGI_DUMP_STATE = 1,
GIC_SGI_CALL_FUNCTION = 2,
};
+
+/* SGI irq mode types */
+enum gic_sgi_mode {
+ SGI_TARGET_LIST,
+ SGI_TARGET_OTHERS,
+ SGI_TARGET_SELF,
+};
+
extern void send_SGI_mask(const cpumask_t *cpumask, enum gic_sgi sgi);
extern void send_SGI_one(unsigned int cpu, enum gic_sgi sgi);
extern void send_SGI_self(enum gic_sgi sgi);
@@ -198,6 +275,76 @@ extern unsigned int gic_number_lines(void);
/* IRQ translation function for the device tree */
int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
unsigned int *out_hwirq, unsigned int *out_type);
+void gic_clear_lrs(struct vcpu *v);
+
+struct gic_info {
+ /* GIC version */
+ enum gic_version hw_version;
+ /* Number of GIC lines supported */
+ unsigned int nr_lines;
+ /* Number of LR registers */
+ uint8_t nr_lrs;
+ /* Maintenance irq number */
+ unsigned int maintenance_irq;
+};
+
+struct gic_hw_operations {
+ /* Hold GIC HW information */
+ const struct gic_info *info;
+ /* Save GIC registers */
+ void (*save_state)(struct vcpu *);
+ /* Restore GIC registers */
+ void (*restore_state)(const struct vcpu *);
+ /* Dump GIC LR register information */
+ void (*dump_state)(const struct vcpu *);
+ /* Map MMIO region of GIC */
+ int (*gicv_setup)(struct domain *);
+
+ /* hw_irq_controller to enable/disable/eoi host irq */
+ hw_irq_controller *gic_host_irq_type;
+
+ /* hw_irq_controller to enable/disable/eoi guest irq */
+ hw_irq_controller *gic_guest_irq_type;
+
+ /* End of Interrupt */
+ void (*eoi_irq)(struct irq_desc *irqd);
+ /* Deactivate/reduce priority of irq */
+ void (*deactivate_irq)(struct irq_desc *irqd);
+ /* Read IRQ id and Ack */
+ unsigned int (*read_irq)(void);
+ /* Set IRQ property */
+ void (*set_irq_properties)(struct irq_desc *desc,
+ const cpumask_t *cpu_mask,
+ unsigned int priority);
+ /* Send SGI */
+ void (*send_SGI)(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
+ const cpumask_t *online_mask);
+ /* Disable CPU physical and virtual interfaces */
+ void (*disable_interface)(void);
+ /* Update LR register with state and priority */
+ void (*update_lr)(int lr, const struct pending_irq *pending_irq,
+ unsigned int state);
+ /* Update HCR status register */
+ void (*update_hcr_status)(uint32_t flag, bool_t set);
+ /* Clear LR register */
+ void (*clear_lr)(int lr);
+ /* Read LR register and populate gic_lr structure */
+ void (*read_lr)(int lr, struct gic_lr *);
+ /* Write LR register from gic_lr structure */
+ void (*write_lr)(int lr, const struct gic_lr *);
+ /* Read VMCR priority */
+ unsigned int (*read_vmcr_priority)(void);
+ /* Read APRn register */
+ unsigned int (*read_apr)(int apr_reg);
+ /* Secondary CPU init */
+ int (*secondary_init)(void);
+ int (*make_dt_node)(const struct domain *d,
+ const struct dt_device_node *node, void *fdt);
+};
+
+void register_gic_ops(const struct gic_hw_operations *ops);
+int gic_make_node(const struct domain *d,const struct dt_device_node *node,
+ void *fdt);
#endif /* __ASSEMBLY__ */
#endif
diff --git a/xen/include/asm-arm/gic_v3_defs.h b/xen/include/asm-arm/gic_v3_defs.h
new file mode 100644
index 0000000..13adb53
--- /dev/null
+++ b/xen/include/asm-arm/gic_v3_defs.h
@@ -0,0 +1,161 @@
+/*
+ * ARM Generic Interrupt Controller v3 definitions
+ *
+ * Vijaya Kumar K <vijaya.kumar at caviumnetworks.com>
+ * Copyright (c) 2014 Cavium Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARM_GIC_V3_DEFS_H__
+#define __ASM_ARM_GIC_V3_DEFS_H__
+
+/*
+ * Additional registers defined in GIC v3.
+ * Common GICD registers are defined in gic.h
+ */
+
+#define GICD_STATUSR (0x010)
+#define GICD_SETSPI_NSR (0x040)
+#define GICD_CLRSPI_NSR (0x048)
+#define GICD_SETSPI_SR (0x050)
+#define GICD_CLRSPI_SR (0x058)
+#define GICD_IROUTER (0x6000)
+#define GICD_IROUTER31 (0x60F8)
+#define GICD_IROUTER32 (0x6100)
+#define GICD_IROUTERN (0x7FF8)
+#define GICD_PIDR0 (0xFFE0)
+#define GICD_PIDR1 (0xFFE4)
+#define GICD_PIDR2 (0xFFE8)
+#define GICD_PIDR3 (0xFFEC)
+#define GICD_PIDR4 (0xFFD0)
+#define GICD_PIDR5 (0xFFD4)
+#define GICD_PIDR7 (0xFFDC)
+
+#define GICC_SRE_EL2_SRE (1UL << 0)
+#define GICC_SRE_EL2_DFB (1UL << 1)
+#define GICC_SRE_EL2_DIB (1UL << 2)
+#define GICC_SRE_EL2_ENEL1 (1UL << 3)
+
+#define GICD_CTLR_RWP (1UL << 31)
+#define GICD_CTLR_ARE_NS (1U << 4)
+#define GICD_CTLR_ENABLE_G1A (1U << 1)
+#define GICD_CTLR_ENABLE_G1 (1U << 0)
+#define GICD_IROUTER_SPI_MODE_ANY (1UL << 31)
+
+#define GICC_CTLR_EL1_EOImode_drop (1U << 1)
+
+#define GICR_WAKER_ProcessorSleep (1U << 1)
+#define GICR_WAKER_ChildrenAsleep (1U << 2)
+
+#define GICD_PIDR2_ARCH_REV_MASK (0xf0)
+#define GICD_PIDR2_ARCH_REV_SHIFT (0x4)
+#define GICD_PIDR2_ARCH_GICV3 (0x3)
+
+#define GICR_PIDR2_ARCH_REV_MASK GICD_PIDR2_ARCH_REV_MASK
+#define GICR_PIDR2_ARCH_REV_SHIFT GICD_PIDR2_ARCH_REV_SHIFT
+#define GICR_PIDR2_ARCH_GICV3 GICD_PIDR2_ARCH_GICV3
+
+#define GICR_SYNCR_NOT_BUSY 1
+/*
+ * Implementation defined value JEP106?
+ * use physical hw value for now
+ */
+#define GICV3_GICD_IIDR_VAL 0x34c
+#define GICV3_GICR_IIDR_VAL GICV3_GICD_IIDR_VAL
+
+#define GICR_CTLR (0x0000)
+#define GICR_IIDR (0x0004)
+#define GICR_TYPER (0x0008)
+#define GICR_STATUSR (0x0010)
+#define GICR_WAKER (0x0014)
+#define GICR_SETLPIR (0x0040)
+#define GICR_CLRLPIR (0x0048)
+#define GICR_PROPBASER (0x0070)
+#define GICR_PENDBASER (0x0078)
+#define GICR_INVLPIR (0x00A0)
+#define GICR_INVALLR (0x00B0)
+#define GICR_SYNCR (0x00C0)
+#define GICR_MOVLPIR (0x100)
+#define GICR_MOVALLR (0x0110)
+#define GICR_PIDR0 GICD_PIDR0
+#define GICR_PIDR1 GICD_PIDR1
+#define GICR_PIDR2 GICD_PIDR2
+#define GICR_PIDR3 GICD_PIDR3
+#define GICR_PIDR4 GICD_PIDR4
+#define GICR_PIDR5 GICD_PIDR5
+#define GICR_PIDR7 GICD_PIDR7
+
+/* GICR for SGI's & PPI's */
+
+#define GICR_IGROUPR0 (0x0080)
+#define GICR_IGRPMODR0 (0x0F80)
+#define GICR_ISENABLER0 (0x0100)
+#define GICR_ICENABLER0 (0x0180)
+#define GICR_ISPENDR0 (0x0200)
+#define GICR_ICPENDR0 (0x0280)
+#define GICR_ISACTIVER0 (0x0300)
+#define GICR_ICACTIVER0 (0x0380)
+#define GICR_IPRIORITYR0 (0x0400)
+#define GICR_IPRIORITYR7 (0x041C)
+#define GICR_ICFGR0 (0x0C00)
+#define GICR_ICFGR1 (0x0C04)
+#define GICR_NSACR (0x0E00)
+
+#define GICR_TYPER_PLPIS (1U << 0)
+#define GICR_TYPER_VLPIS (1U << 1)
+#define GICR_TYPER_LAST (1U << 4)
+
+#define DEFAULT_PMR_VALUE 0xff
+
+#define GICH_VMCR_EOI (1 << 9)
+#define GICH_VMCR_VENG1 (1 << 1)
+
+#define GICH_LR_VIRTUAL_MASK 0xffff
+#define GICH_LR_VIRTUAL_SHIFT 0
+#define GICH_LR_PHYSICAL_MASK 0x3ff
+#define GICH_LR_PHYSICAL_SHIFT 32
+#define GICH_LR_STATE_MASK 0x3
+#define GICH_LR_STATE_SHIFT 62
+#define GICH_LR_PRIORITY_MASK 0xff
+#define GICH_LR_PRIORITY_SHIFT 48
+#define GICH_LR_HW_MASK 0x1
+#define GICH_LR_HW_SHIFT 61
+#define GICH_LR_GRP_MASK 0x1
+#define GICH_LR_GRP_SHIFT 60
+#define GICH_LR_MAINTENANCE_IRQ (1UL<<41)
+#define GICH_LR_GRP1 (1UL<<60)
+#define GICH_LR_HW (1UL<<61)
+
+#define GICH_VTR_NRLRGS 0x3f
+#define GICH_VTR_PRIBITS_MASK 0x7
+#define GICH_VTR_PRIBITS_SHIFT 29
+
+#define GICH_VMCR_PRIORITY_MASK 0xff
+#define GICH_VMCR_PRIORITY_SHIFT 24
+
+#define ICH_SGI_IRQMODE_SHIFT 40
+#define ICH_SGI_IRQMODE_MASK 0x1
+#define ICH_SGI_TARGET_OTHERS 1
+#define ICH_SGI_TARGET_LIST 0
+#define ICH_SGI_IRQ_SHIFT 24
+#define ICH_SGI_IRQ_MASK 0xf
+#define ICH_SGI_TARGETLIST_MASK 0xffff
+#endif /* __ASM_ARM_GIC_V3_DEFS_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/grant_table.h b/xen/include/asm-arm/grant_table.h
index 6e0cc59..0edad67 100644
--- a/xen/include/asm-arm/grant_table.h
+++ b/xen/include/asm-arm/grant_table.h
@@ -31,7 +31,10 @@ static inline int replace_grant_supported(void)
#define gnttab_shared_gmfn(d, t, i) \
( ((i >= nr_grant_frames(d->grant_table)) && \
- (i < max_nr_grant_frames)) ? 0 : (d->arch.grant_table_gpfn[i]))
+ (i < max_grant_frames)) ? 0 : (d->arch.grant_table_gpfn[i]))
+
+#define gnttab_need_iommu_mapping(d) \
+ (is_domain_direct_mapped(d) && need_iommu(d))
#endif /* __ASM_GRANT_TABLE_H__ */
/*
diff --git a/xen/include/asm-arm/hvm/iommu.h b/xen/include/asm-arm/hvm/iommu.h
new file mode 100644
index 0000000..461c8cf
--- /dev/null
+++ b/xen/include/asm-arm/hvm/iommu.h
@@ -0,0 +1,10 @@
+#ifndef __ASM_ARM_HVM_IOMMU_H_
+#define __ASM_ARM_HVM_IOMMU_H_
+
+struct arch_hvm_iommu
+{
+ /* Private information for the IOMMU drivers */
+ void *priv;
+};
+
+#endif /* __ASM_ARM_HVM_IOMMU_H_ */
diff --git a/xen/include/asm-arm/iommu.h b/xen/include/asm-arm/iommu.h
new file mode 100644
index 0000000..9322f08
--- /dev/null
+++ b/xen/include/asm-arm/iommu.h
@@ -0,0 +1,36 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+*/
+#ifndef __ARCH_ARM_IOMMU_H__
+#define __ARCH_ARM_IOMMU_H__
+
+/* Always share P2M Table between the CPU and the IOMMU */
+#define iommu_use_hap_pt(d) (1)
+#define domain_hvm_iommu(d) (&d->arch.hvm_domain.iommu)
+
+const struct iommu_ops *iommu_get_ops(void);
+void __init iommu_set_ops(const struct iommu_ops *ops);
+
+int __init iommu_hardware_setup(void);
+
+#endif /* __ARCH_ARM_IOMMU_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
index 7c20703..e877334 100644
--- a/xen/include/asm-arm/irq.h
+++ b/xen/include/asm-arm/irq.h
@@ -14,9 +14,9 @@ struct arch_pirq
{
};
-struct irq_cfg {
-#define arch_irq_desc irq_cfg
+struct arch_irq_desc {
int eoi_cpu;
+ unsigned int type;
};
#define NR_LOCAL_IRQS 32
@@ -40,10 +40,16 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq);
void init_IRQ(void);
void init_secondary_IRQ(void);
-int __init request_dt_irq(const struct dt_irq *irq,
- void (*handler)(int, void *, struct cpu_user_regs *),
- const char *devname, void *dev_id);
-int __init setup_dt_irq(const struct dt_irq *irq, struct irqaction *new);
+int route_irq_to_guest(struct domain *d, unsigned int irq,
+ const char *devname);
+void arch_move_irqs(struct vcpu *v);
+
+/* Set IRQ type for an SPI */
+int irq_set_spi_type(unsigned int spi, unsigned int type);
+
+int platform_get_irq(const struct dt_device_node *device, int index);
+
+void irq_set_affinity(struct irq_desc *desc, const cpumask_t *cpu_mask);
#endif /* _ASM_HW_IRQ_H */
/*
diff --git a/xen/include/asm-arm/macros.h b/xen/include/asm-arm/macros.h
new file mode 100644
index 0000000..5d837cb
--- /dev/null
+++ b/xen/include/asm-arm/macros.h
@@ -0,0 +1,16 @@
+#ifndef __ASM_MACROS_H
+#define __ASM_MACROS_H
+
+#ifndef __ASSEMBLY__
+# error "This file should only be included in assembly file"
+#endif
+
+#if defined (CONFIG_ARM_32)
+# include <asm/arm32/macros.h>
+#elif defined(CONFIG_ARM_64)
+/* No specific ARM64 macros for now */
+#else
+# error "unknown ARM variant"
+#endif
+
+#endif /* __ASM_ARM_MACROS_H */
diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
index 8bf179d..d25e485 100644
--- a/xen/include/asm-arm/mm.h
+++ b/xen/include/asm-arm/mm.h
@@ -5,6 +5,8 @@
#include <xen/kernel.h>
#include <asm/page.h>
#include <public/xen.h>
+#include <xen/domain_page.h>
+#include <xen/pdx.h>
/* Align Xen to a 2 MiB boundary. */
#define XEN_PADDR_ALIGN (1 << 21)
@@ -108,7 +110,10 @@ struct page_info
#define PGC_count_mask ((1UL<<PGC_count_width)-1)
extern unsigned long xenheap_mfn_start, xenheap_mfn_end;
-extern unsigned long xenheap_virt_end;
+extern vaddr_t xenheap_virt_end;
+#ifdef CONFIG_ARM_64
+extern vaddr_t xenheap_virt_start;
+#endif
#ifdef CONFIG_ARM_32
#define is_xen_heap_page(page) is_xen_heap_mfn(page_to_mfn(page))
@@ -139,12 +144,14 @@ extern void share_xen_page_with_privileged_guests(
struct page_info *page, int readonly);
#define frame_table ((struct page_info *)FRAMETABLE_VIRT_START)
-/* MFN of the first page in the frame table. */
-extern unsigned long frametable_base_mfn;
+/* PDX of the first page in the frame table. */
+extern unsigned long frametable_base_pdx;
extern unsigned long max_page;
extern unsigned long total_pages;
+#define PDX_GROUP_SHIFT SECOND_SHIFT
+
/* Boot-time pagetable setup */
extern void setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr);
/* Remove early mappings */
@@ -154,8 +161,6 @@ extern void remove_early_mappings(void);
extern int __cpuinit init_secondary_pagetables(int cpu);
/* Switch secondary CPUS to its own pagetables and finalise MMU setup */
extern void __cpuinit mmu_init_secondary_cpu(void);
-/* Second stage paging setup, to be called on all CPUs */
-extern void __cpuinit setup_virt_paging(void);
/* Set up the xenheap: up to 1GB of contiguous, always-mapped memory.
* Base must be 32MB aligned and size a multiple of 32MB. */
extern void setup_xenheap_mappings(unsigned long base_mfn, unsigned long nr_mfns);
@@ -183,20 +188,15 @@ static inline void __iomem *ioremap_wc(paddr_t start, size_t len)
return ioremap_attr(start, len, PAGE_HYPERVISOR_WC);
}
+/* XXX -- account for base */
#define mfn_valid(mfn) ({ \
unsigned long __m_f_n = (mfn); \
- likely(__m_f_n >= frametable_base_mfn && __m_f_n < max_page); \
+ likely(pfn_to_pdx(__m_f_n) >= frametable_base_pdx && __mfn_valid(__m_f_n)); \
})
-#define max_pdx max_page
-#define pfn_to_pdx(pfn) (pfn)
-#define pdx_to_pfn(pdx) (pdx)
-#define virt_to_pdx(va) virt_to_mfn(va)
-#define pdx_to_virt(pdx) mfn_to_virt(pdx)
-
/* Convert between machine frame numbers and page-info structures. */
-#define mfn_to_page(mfn) (frame_table + (pfn_to_pdx(mfn) - frametable_base_mfn))
-#define page_to_mfn(pg) pdx_to_pfn((unsigned long)((pg) - frame_table) + frametable_base_mfn)
+#define mfn_to_page(mfn) (frame_table + (pfn_to_pdx(mfn) - frametable_base_pdx))
+#define page_to_mfn(pg) pdx_to_pfn((unsigned long)((pg) - frame_table) + frametable_base_pdx)
#define __page_to_mfn(pg) page_to_mfn(pg)
#define __mfn_to_page(mfn) mfn_to_page(mfn)
@@ -209,6 +209,8 @@ static inline void __iomem *ioremap_wc(paddr_t start, size_t len)
#define paddr_to_pfn(pa) ((unsigned long)((pa) >> PAGE_SHIFT))
#define paddr_to_pdx(pa) pfn_to_pdx(paddr_to_pfn(pa))
+/* Page-align address and convert to frame number format */
+#define paddr_to_pfn_aligned(paddr) paddr_to_pfn(PAGE_ALIGN(paddr))
static inline paddr_t __virt_to_maddr(vaddr_t va)
{
@@ -227,9 +229,11 @@ static inline void *maddr_to_virt(paddr_t ma)
#else
static inline void *maddr_to_virt(paddr_t ma)
{
- ASSERT((ma >> PAGE_SHIFT) < (DIRECTMAP_SIZE >> PAGE_SHIFT));
- ma -= pfn_to_paddr(xenheap_mfn_start);
- return (void *)(unsigned long) ma + DIRECTMAP_VIRT_START;
+ ASSERT(pfn_to_pdx(ma >> PAGE_SHIFT) < (DIRECTMAP_SIZE >> PAGE_SHIFT));
+ return (void *)(XENHEAP_VIRT_START -
+ pfn_to_paddr(xenheap_mfn_start) +
+ ((ma & ma_va_bottom_mask) |
+ ((ma & ma_top_mask) >> pfn_pdx_hole_shift)));
}
#endif
@@ -255,13 +259,14 @@ static inline int gvirt_to_maddr(vaddr_t va, paddr_t *pa, unsigned int flags)
static inline struct page_info *virt_to_page(const void *v)
{
unsigned long va = (unsigned long)v;
+ unsigned long pdx;
+
ASSERT(va >= XENHEAP_VIRT_START);
ASSERT(va < xenheap_virt_end);
- return frame_table
- + ((va - XENHEAP_VIRT_START) >> PAGE_SHIFT)
- + xenheap_mfn_start
- - frametable_base_mfn;
+ pdx = (va - XENHEAP_VIRT_START) >> PAGE_SHIFT;
+ pdx += pfn_to_pdx(xenheap_mfn_start);
+ return frame_table + pdx - frametable_base_pdx;
}
static inline void *page_to_virt(const struct page_info *pg)
@@ -298,7 +303,6 @@ struct page_info *get_page_from_gva(struct domain *d, vaddr_t va,
})
static inline void put_gfn(struct domain *d, unsigned long gfn) {}
-static inline void mem_event_cleanup(struct domain *d) {}
static inline int relinquish_shared_pages(struct domain *d)
{
return 0;
@@ -344,6 +348,8 @@ static inline void put_page_and_type(struct page_info *page)
put_page(page);
}
+void clear_and_clean_page(struct page_info *page);
+
#endif /* __ARCH_ARM_MM__ */
/*
* Local variables:
diff --git a/xen/include/asm-arm/mmio.h b/xen/include/asm-arm/mmio.h
new file mode 100644
index 0000000..0160f09
--- /dev/null
+++ b/xen/include/asm-arm/mmio.h
@@ -0,0 +1,71 @@
+/*
+ * xen/include/asm-arm/mmio.h
+ *
+ * ARM I/O handlers
+ *
+ * Copyright (c) 2011 Citrix Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARM_MMIO_H__
+#define __ASM_ARM_MMIO_H__
+
+#include <xen/lib.h>
+#include <asm/processor.h>
+#include <asm/regs.h>
+
+#define MAX_IO_HANDLER 16
+
+typedef struct
+{
+ struct hsr_dabt dabt;
+ vaddr_t gva;
+ paddr_t gpa;
+} mmio_info_t;
+
+typedef int (*mmio_read_t)(struct vcpu *v, mmio_info_t *info);
+typedef int (*mmio_write_t)(struct vcpu *v, mmio_info_t *info);
+typedef int (*mmio_check_t)(struct vcpu *v, paddr_t addr);
+
+struct mmio_handler_ops {
+ mmio_read_t read_handler;
+ mmio_write_t write_handler;
+};
+
+struct mmio_handler {
+ paddr_t addr;
+ paddr_t size;
+ const struct mmio_handler_ops *mmio_handler_ops;
+};
+
+struct io_handler {
+ int num_entries;
+ spinlock_t lock;
+ struct mmio_handler mmio_handlers[MAX_IO_HANDLER];
+};
+
+extern int handle_mmio(mmio_info_t *info);
+void register_mmio_handler(struct domain *d,
+ const struct mmio_handler_ops *handle,
+ paddr_t addr, paddr_t size);
+int domain_io_init(struct domain *d);
+
+#endif /* __ASM_ARM_MMIO_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/numa.h b/xen/include/asm-arm/numa.h
index cb8f2ba..06a9d5a 100644
--- a/xen/include/asm-arm/numa.h
+++ b/xen/include/asm-arm/numa.h
@@ -12,6 +12,7 @@ static inline __attribute__((pure)) int phys_to_nid(paddr_t addr)
/* XXX: implement NUMA support */
#define node_spanned_pages(nid) (total_pages)
+#define node_start_pfn(nid) (pdx_to_pfn(frametable_base_pdx))
#define __node_distance(a, b) (20)
#endif /* __ARCH_ARM_NUMA_H */
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index e1013c8..da36504 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -3,8 +3,14 @@
#include <xen/mm.h>
+#include <xen/p2m-common.h>
+
+#define paddr_bits PADDR_BITS
+
struct domain;
+extern void memory_type_changed(struct domain *);
+
/* Per-p2m-table state */
struct p2m_domain {
/* Lock that protects updates to the p2m */
@@ -13,8 +19,8 @@ struct p2m_domain {
/* Pages used to construct the p2m */
struct page_list_head pages;
- /* Root of p2m page tables, 2 contiguous pages */
- struct page_info *first_level;
+ /* The root of the p2m tree. May be concatenated */
+ struct page_info *root;
/* Current VMID in use */
uint8_t vmid;
@@ -29,6 +35,19 @@ struct p2m_domain {
* resume the search. Apart from during teardown this can only
* decrease. */
unsigned long lowest_mapped_gfn;
+
+ /* Gather some statistics for information purposes only */
+ struct {
+ /* Number of mappings at each p2m tree level */
+ unsigned long mappings[4];
+ /* Number of times we have shattered a mapping
+ * at each p2m tree level. */
+ unsigned long shattered[4];
+ } stats;
+
+ /* If true, and an access fault comes in and there is no mem_event listener,
+ * pause domain. Otherwise, remove access restrictions. */
+ bool_t access_required;
};
/* List of possible type for each page in the p2m entry.
@@ -45,15 +64,34 @@ typedef enum {
p2m_map_foreign, /* Ram pages from foreign domain */
p2m_grant_map_rw, /* Read/write grant mapping */
p2m_grant_map_ro, /* Read-only grant mapping */
+ /* The types below are only used to decide the page attribute in the P2M */
+ p2m_iommu_map_rw, /* Read/write iommu mapping */
+ p2m_iommu_map_ro, /* Read-only iommu mapping */
p2m_max_real_type, /* Types after this won't be store in the p2m */
} p2m_type_t;
+static inline
+void p2m_mem_event_emulate_check(struct vcpu *v,
+ const mem_event_response_t *rsp)
+{
+ /* Not supported on ARM. */
+};
+
+static inline
+void p2m_setup_introspection(struct domain *d)
+{
+ /* No special setup on ARM. */
+}
+
#define p2m_is_foreign(_t) ((_t) == p2m_map_foreign)
#define p2m_is_ram(_t) ((_t) == p2m_ram_rw || (_t) == p2m_ram_ro)
/* Initialise vmid allocator */
void p2m_vmid_allocator_init(void);
+/* Second stage paging setup, to be called on all CPUs */
+void __cpuinit setup_virt_paging(void);
+
/* Init the datastructures for later use by the p2m code */
int p2m_init(struct domain *d);
@@ -72,13 +110,13 @@ int relinquish_p2m_mapping(struct domain *d);
*/
int p2m_alloc_table(struct domain *d);
-/* */
-void p2m_load_VTTBR(struct domain *d);
-
/* Context switch */
void p2m_save_state(struct vcpu *p);
void p2m_restore_state(struct vcpu *n);
+/* Print debugging/statistial info about a domain's p2m */
+void p2m_dump_info(struct domain *d);
+
/* Look up the MFN corresponding to a domain's PFN. */
paddr_t p2m_lookup(struct domain *d, paddr_t gpfn, p2m_type_t *t);
@@ -87,11 +125,6 @@ int p2m_cache_flush(struct domain *d, xen_pfn_t start_mfn, xen_pfn_t end_mfn);
/* Setup p2m RAM mapping for domain d from start-end. */
int p2m_populate_ram(struct domain *d, paddr_t start, paddr_t end);
-/* Map MMIO regions in the p2m: start_gaddr and end_gaddr is the range
- * in the guest physical address space to map, starting from the machine
- * address maddr. */
-int map_mmio_regions(struct domain *d, paddr_t start_gaddr,
- paddr_t end_gaddr, paddr_t maddr);
int guest_physmap_add_entry(struct domain *d,
unsigned long gfn,
@@ -181,6 +214,9 @@ static inline int get_page_and_type(struct page_info *page,
return rc;
}
+/* get host p2m table */
+#define p2m_get_hostp2m(d) (&(d)->arch.p2m)
+
#endif /* _XEN_P2M_H */
/*
diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h
index c118309..53d4b63 100644
--- a/xen/include/asm-arm/page.h
+++ b/xen/include/asm-arm/page.h
@@ -6,7 +6,11 @@
#include <public/xen.h>
#include <asm/processor.h>
+#ifdef CONFIG_ARM_64
+#define PADDR_BITS 48
+#else
#define PADDR_BITS 40
+#endif
#define PADDR_MASK ((1ULL << PADDR_BITS)-1)
#define VADDR_BITS 32
@@ -98,7 +102,7 @@
* bits that's not in use in a given node type can be used as
* extra software-defined bits. */
-typedef struct {
+typedef struct __packed {
/* These are used in all kinds of entry. */
unsigned long valid:1; /* Valid mapping */
unsigned long table:1; /* == 1 in 4k map entries too */
@@ -114,8 +118,8 @@ typedef struct {
unsigned long ng:1; /* Not-Global */
/* The base address must be appropriately aligned for Block entries */
- unsigned long base:28; /* Base address of block or next table */
- unsigned long sbz:12; /* Must be zero */
+ unsigned long long base:36; /* Base address of block or next table */
+ unsigned long sbz:4; /* Must be zero */
/* These seven bits are only used in Block entries and are ignored
* in Table entries. */
@@ -130,11 +134,11 @@ typedef struct {
unsigned long xnt:1; /* eXecute-Never */
unsigned long apt:2; /* Access Permissions */
unsigned long nst:1; /* Not-Secure */
-} __attribute__((__packed__)) lpae_pt_t;
+} lpae_pt_t;
/* The p2m tables have almost the same layout, but some of the permission
* and cache-control bits are laid out differently (or missing) */
-typedef struct {
+typedef struct __packed {
/* These are used in all kinds of entry. */
unsigned long valid:1; /* Valid mapping */
unsigned long table:1; /* == 1 in 4k map entries too */
@@ -149,8 +153,8 @@ typedef struct {
unsigned long sbz4:1;
/* The base address must be appropriately aligned for Block entries */
- unsigned long base:28; /* Base address of block or next table */
- unsigned long sbz3:12;
+ unsigned long long base:36; /* Base address of block or next table */
+ unsigned long sbz3:4;
/* These seven bits are only used in Block entries and are ignored
* in Table entries. */
@@ -160,13 +164,13 @@ typedef struct {
unsigned long type:4; /* Ignore by hardware. Used to store p2m types */
unsigned long sbz1:5;
-} __attribute__((__packed__)) lpae_p2m_t;
+} lpae_p2m_t;
/*
* Walk is the common bits of p2m and pt entries which are needed to
* simply walk the table (e.g. for debug).
*/
-typedef struct {
+typedef struct __packed {
/* These are used in all kinds of entry. */
unsigned long valid:1; /* Valid mapping */
unsigned long table:1; /* == 1 in 4k map entries too */
@@ -174,10 +178,10 @@ typedef struct {
unsigned long pad2:10;
/* The base address must be appropriately aligned for Block entries */
- unsigned long base:28; /* Base address of block or next table */
+ unsigned long long base:36; /* Base address of block or next table */
- unsigned long pad1:24;
-} __attribute__((__packed__)) lpae_walk_t;
+ unsigned long pad1:16;
+} lpae_walk_t;
typedef union {
uint64_t bits;
@@ -189,7 +193,7 @@ typedef union {
/* Standard entry type that we'll use to build Xen's own pagetables.
* We put the same permissions at every level, because they're ignored
* by the walker in non-leaf entries. */
-static inline lpae_t mfn_to_xen_entry(unsigned long mfn)
+static inline lpae_t mfn_to_xen_entry(unsigned long mfn, unsigned attr)
{
paddr_t pa = ((paddr_t) mfn) << PAGE_SHIFT;
lpae_t e = (lpae_t) {
@@ -197,10 +201,9 @@ static inline lpae_t mfn_to_xen_entry(unsigned long mfn)
.xn = 1, /* No need to execute outside .text */
.ng = 1, /* Makes TLB flushes easier */
.af = 1, /* No need for access tracking */
- .sh = LPAE_SH_OUTER, /* Xen mappings are globally coherent */
.ns = 1, /* Hyp mode is in the non-secure world */
.user = 1, /* See below */
- .ai = WRITEALLOC,
+ .ai = attr,
.table = 0, /* Set to 1 for links and 4k maps */
.valid = 1, /* Mappings are present */
}};;
@@ -209,6 +212,38 @@ static inline lpae_t mfn_to_xen_entry(unsigned long mfn)
* pagetables un User mode it's OK. If this changes, remember
* to update the hard-coded values in head.S too */
+ switch ( attr )
+ {
+ case BUFFERABLE:
+ /*
+ * ARM ARM: Overlaying the shareability attribute (DDI
+ * 0406C.b B3-1376 to 1377)
+ *
+ * A memory region with a resultant memory type attribute of Normal,
+ * and a resultant cacheability attribute of Inner Non-cacheable,
+ * Outer Non-cacheable, must have a resultant shareability attribute
+ * of Outer Shareable, otherwise shareability is UNPREDICTABLE.
+ *
+ * On ARMv8 sharability is ignored and explicitly treated as Outer
+ * Shareable for Normal Inner Non_cacheable, Outer Non-cacheable.
+ */
+ e.pt.sh = LPAE_SH_OUTER;
+ break;
+ case UNCACHED:
+ case DEV_SHARED:
+ /* Shareability is ignored for non-Normal memory, Outer is as
+ * good as anything.
+ *
+ * On ARMv8 sharability is ignored and explicitly treated as Outer
+ * Shareable for any device memory type.
+ */
+ e.pt.sh = LPAE_SH_OUTER;
+ break;
+ default:
+ e.pt.sh = LPAE_SH_INNER; /* Xen mappings are SMP coherent */
+ break;
+ }
+
ASSERT(!(pa & ~PAGE_MASK));
ASSERT(!(pa & ~PADDR_MASK));
@@ -230,38 +265,146 @@ static inline lpae_t mfn_to_xen_entry(unsigned long mfn)
/* Actual cacheline size on the boot CPU. */
extern size_t cacheline_bytes;
-/* Function for flushing medium-sized areas.
+/* Functions for flushing medium-sized areas.
* if 'range' is large enough we might want to use model-specific
* full-cache flushes. */
-static inline void clean_xen_dcache_va_range(void *p, unsigned long size)
+
+static inline int invalidate_dcache_va_range(const void *p, unsigned long size)
+{
+ size_t off;
+ const void *end = p + size;
+
+ dsb(sy); /* So the CPU issues all writes to the range */
+
+ off = (unsigned long)p % cacheline_bytes;
+ if ( off )
+ {
+ p -= off;
+ asm volatile (__clean_and_invalidate_dcache_one(0) : : "r" (p));
+ p += cacheline_bytes;
+ size -= cacheline_bytes - off;
+ }
+ off = (unsigned long)end % cacheline_bytes;
+ if ( off )
+ {
+ end -= off;
+ size -= off;
+ asm volatile (__clean_and_invalidate_dcache_one(0) : : "r" (end));
+ }
+
+ for ( ; p < end; p += cacheline_bytes )
+ asm volatile (__invalidate_dcache_one(0) : : "r" (p));
+
+ dsb(sy); /* So we know the flushes happen before continuing */
+
+ return 0;
+}
+
+static inline int clean_dcache_va_range(const void *p, unsigned long size)
{
- void *end;
- dsb(); /* So the CPU issues all writes to the range */
+ const void *end;
+ dsb(sy); /* So the CPU issues all writes to the range */
for ( end = p + size; p < end; p += cacheline_bytes )
- asm volatile (__clean_xen_dcache_one(0) : : "r" (p));
- dsb(); /* So we know the flushes happen before continuing */
+ asm volatile (__clean_dcache_one(0) : : "r" (p));
+ dsb(sy); /* So we know the flushes happen before continuing */
+ /* ARM callers assume that dcache_* functions cannot fail. */
+ return 0;
}
-/* Macro for flushing a single small item. The predicate is always
+static inline int clean_and_invalidate_dcache_va_range
+ (const void *p, unsigned long size)
+{
+ const void *end;
+ dsb(sy); /* So the CPU issues all writes to the range */
+ for ( end = p + size; p < end; p += cacheline_bytes )
+ asm volatile (__clean_and_invalidate_dcache_one(0) : : "r" (p));
+ dsb(sy); /* So we know the flushes happen before continuing */
+ /* ARM callers assume that dcache_* functions cannot fail. */
+ return 0;
+}
+
+/* Macros for flushing a single small item. The predicate is always
* compile-time constant so this will compile down to 3 instructions in
* the common case. */
-#define clean_xen_dcache(x) do { \
+#define clean_dcache(x) do { \
+ typeof(x) *_p = &(x); \
+ if ( sizeof(x) > MIN_CACHELINE_BYTES || sizeof(x) > alignof(x) ) \
+ clean_dcache_va_range(_p, sizeof(x)); \
+ else \
+ asm volatile ( \
+ "dsb sy;" /* Finish all earlier writes */ \
+ __clean_dcache_one(0) \
+ "dsb sy;" /* Finish flush before continuing */ \
+ : : "r" (_p), "m" (*_p)); \
+} while (0)
+
+#define clean_and_invalidate_dcache(x) do { \
typeof(x) *_p = &(x); \
if ( sizeof(x) > MIN_CACHELINE_BYTES || sizeof(x) > alignof(x) ) \
- clean_xen_dcache_va_range(_p, sizeof(x)); \
+ clean_and_invalidate_dcache_va_range(_p, sizeof(x)); \
else \
asm volatile ( \
"dsb sy;" /* Finish all earlier writes */ \
- __clean_xen_dcache_one(0) \
+ __clean_and_invalidate_dcache_one(0) \
"dsb sy;" /* Finish flush before continuing */ \
: : "r" (_p), "m" (*_p)); \
} while (0)
+/*
+ * Flush a range of VA's hypervisor mappings from the data TLB of the
+ * local processor. This is not sufficient when changing code mappings
+ * or for self modifying code.
+ */
+static inline void flush_xen_data_tlb_range_va_local(unsigned long va,
+ unsigned long size)
+{
+ unsigned long end = va + size;
+ dsb(sy); /* Ensure preceding are visible */
+ while ( va < end )
+ {
+ __flush_xen_data_tlb_one_local(va);
+ va += PAGE_SIZE;
+ }
+ dsb(sy); /* Ensure completion of the TLB flush */
+ isb();
+}
+
+/*
+ * Flush a range of VA's hypervisor mappings from the data TLB of all
+ * processors in the inner-shareable domain. This is not sufficient
+ * when changing code mappings or for self modifying code.
+ */
+static inline void flush_xen_data_tlb_range_va(unsigned long va,
+ unsigned long size)
+{
+ unsigned long end = va + size;
+ dsb(sy); /* Ensure preceding are visible */
+ while ( va < end )
+ {
+ __flush_xen_data_tlb_one(va);
+ va += PAGE_SIZE;
+ }
+ dsb(sy); /* Ensure completion of the TLB flush */
+ isb();
+}
+
/* Flush the dcache for an entire page. */
void flush_page_to_ram(unsigned long mfn);
-/* Print a walk of an arbitrary page table */
-void dump_pt_walk(lpae_t *table, paddr_t addr);
+/*
+ * Print a walk of a page table or p2m
+ *
+ * ttbr is the base address register (TTBR0_EL2 or VTTBR_EL2)
+ * addr is the PA or IPA to translate
+ * root_level is the starting level of the page table
+ * (e.g. TCR_EL2.SL0 or VTCR_EL2.SL0 )
+ * nr_root_tables is the number of concatenated tables at the root.
+ * this can only be != 1 for P2M walks starting at the first or
+ * subsequent level.
+ */
+void dump_pt_walk(paddr_t ttbr, paddr_t addr,
+ unsigned int root_level,
+ unsigned int nr_root_tables);
/* Print a walk of the hypervisor's page tables for a virtual addr. */
extern void dump_hyp_walk(vaddr_t addr);
@@ -305,7 +448,7 @@ static inline int gva_to_ipa(vaddr_t va, paddr_t *paddr)
*/
#define LPAE_SHIFT 9
-#define LPAE_ENTRIES (1u << LPAE_SHIFT)
+#define LPAE_ENTRIES (_AC(1,U) << LPAE_SHIFT)
#define LPAE_ENTRY_MASK (LPAE_ENTRIES - 1)
#define THIRD_SHIFT (PAGE_SHIFT)
@@ -333,8 +476,6 @@ static inline int gva_to_ipa(vaddr_t va, paddr_t *paddr)
#define third_table_offset(va) TABLE_OFFSET(third_linear_offset(va))
#define zeroeth_table_offset(va) TABLE_OFFSET(zeroeth_linear_offset(va))
-#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
-
#define PAGE_ALIGN(x) (((x) + PAGE_SIZE - 1) & PAGE_MASK)
#endif /* __ARM_PAGE_H__ */
diff --git a/xen/include/asm-arm/platform.h b/xen/include/asm-arm/platform.h
index bcd2097..eefaca6 100644
--- a/xen/include/asm-arm/platform.h
+++ b/xen/include/asm-arm/platform.h
@@ -55,6 +55,11 @@ struct platform_desc {
*/
#define PLATFORM_QUIRK_GIC_64K_STRIDE (1 << 0)
+/*
+ * Quirk for platforms where GICH_LR_HW does not work as expected.
+ */
+#define PLATFORM_QUIRK_GUEST_PIRQ_NEED_EOI (1 << 1)
+
void __init platform_init(void);
int __init platform_init_time(void);
int __init platform_specific_mapping(struct domain *d);
diff --git a/xen/include/asm-arm/platforms/exynos5.h b/xen/include/asm-arm/platforms/exynos5.h
index af30608..aef5c67 100644
--- a/xen/include/asm-arm/platforms/exynos5.h
+++ b/xen/include/asm-arm/platforms/exynos5.h
@@ -1,19 +1,14 @@
#ifndef __ASM_ARM_PLATFORMS_EXYNOS5_H
-#define __ASM_ASM_PLATFORMS_EXYSNO5_H
+#define __ASM_ARM_PLATFORMS_EXYNOS5_H
-#define EXYNOS5_MCT_BASE 0x101c0000
#define EXYNOS5_MCT_G_TCON 0x240 /* Relative to MCT_BASE */
#define EXYNOS5_MCT_G_TCON_START (1 << 8)
#define EXYNOS5_PA_CHIPID 0x10000000
#define EXYNOS5_PA_TIMER 0x12dd0000
-/* Base address of system controller */
-#define EXYNOS5_PA_PMU 0x10040000
#define EXYNOS5_SWRESET 0x0400 /* Relative to PA_PMU */
-#define S5P_PA_SYSRAM 0x02020000
-
#endif /* __ASM_ARM_PLATFORMS_EXYNOS5_H */
/*
* Local variables:
diff --git a/xen/include/asm-arm/processor-ca15.h b/xen/include/asm-arm/processor-ca15.h
deleted file mode 100644
index f65f40a..0000000
--- a/xen/include/asm-arm/processor-ca15.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef __ASM_ARM_PROCESSOR_CA15_H
-#define __ASM_ARM_PROCESSOR_CA15_H
-
-/* ACTLR Auxiliary Control Register, Cortex A15 */
-#define ACTLR_CA15_SNOOP_DELAYED (1<<31)
-#define ACTLR_CA15_MAIN_CLOCK (1<<30)
-#define ACTLR_CA15_NEON_CLOCK (1<<29)
-#define ACTLR_CA15_NONCACHE (1<<24)
-#define ACTLR_CA15_INORDER_REQ (1<<23)
-#define ACTLR_CA15_INORDER_LOAD (1<<22)
-#define ACTLR_CA15_L2_TLB_PREFETCH (1<<21)
-#define ACTLR_CA15_L2_IPA_PA_CACHE (1<<20)
-#define ACTLR_CA15_L2_CACHE (1<<19)
-#define ACTLR_CA15_L2_PA_CACHE (1<<18)
-#define ACTLR_CA15_TLB (1<<17)
-#define ACTLR_CA15_STRONGY_ORDERED (1<<16)
-#define ACTLR_CA15_INORDER (1<<15)
-#define ACTLR_CA15_FORCE_LIM (1<<14)
-#define ACTLR_CA15_CP_FLUSH (1<<13)
-#define ACTLR_CA15_CP_PUSH (1<<12)
-#define ACTLR_CA15_LIM (1<<11)
-#define ACTLR_CA15_SER (1<<10)
-#define ACTLR_CA15_OPT (1<<9)
-#define ACTLR_CA15_WFI (1<<8)
-#define ACTLR_CA15_WFE (1<<7)
-#define ACTLR_CA15_SMP (1<<6)
-#define ACTLR_CA15_PLD (1<<5)
-#define ACTLR_CA15_IP (1<<4)
-#define ACTLR_CA15_MICRO_BTB (1<<3)
-#define ACTLR_CA15_LOOP_ONE (1<<2)
-#define ACTLR_CA15_LOOP_DISABLE (1<<1)
-#define ACTLR_CA15_BTB (1<<0)
-
-#endif /* __ASM_ARM_PROCESSOR_CA15_H */
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/include/asm-arm/processor-ca7.h b/xen/include/asm-arm/processor-ca7.h
deleted file mode 100644
index 5048a95..0000000
--- a/xen/include/asm-arm/processor-ca7.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __ASM_ARM_PROCESSOR_CA7_H
-#define __ASM_ARM_PROCESSOR_CA7_H
-
-/* ACTLR Auxiliary Control Register, Cortex A7 */
-#define ACTLR_CA7_DDI (1<<28)
-#define ACTLR_CA7_DDVM (1<<15)
-#define ACTLR_CA7_L1RADIS (1<<12)
-#define ACTLR_CA7_L2RADIS (1<<11)
-#define ACTLR_CA7_DODMBS (1<<10)
-#define ACTLR_CA7_SMP (1<<6)
-
-#endif /* __ASM_ARM_PROCESSOR_CA7_H */
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h
index 1f158ce..b7ef817 100644
--- a/xen/include/asm-arm/processor.h
+++ b/xen/include/asm-arm/processor.h
@@ -3,6 +3,7 @@
#include <asm/cpregs.h>
#include <asm/sysregs.h>
+#include <public/arch-arm.h>
/* MIDR Main ID Register */
#define MIDR_MASK 0xff0ffff0
@@ -16,6 +17,22 @@
#define MPIDR_AFF0_MASK (_AC(0xff,U) << MPIDR_AFF0_SHIFT)
#define MPIDR_HWID_MASK _AC(0xffffff,U)
#define MPIDR_INVALID (~MPIDR_HWID_MASK)
+#define MPIDR_LEVEL_BITS (8)
+#define AFFINITY_MASK(level) ~((_AC(0x1,U) << ((level) * MPIDR_LEVEL_BITS)) - 1)
+
+
+/*
+ * Macros to extract affinity level. picked from kernel
+ */
+
+#define MPIDR_LEVEL_BITS_SHIFT 3
+#define MPIDR_LEVEL_MASK ((1 << MPIDR_LEVEL_BITS) - 1)
+
+#define MPIDR_LEVEL_SHIFT(level) \
+ (((1 << level) >> 1) << MPIDR_LEVEL_BITS_SHIFT)
+
+#define MPIDR_AFFINITY_LEVEL(mpidr, level) \
+ ((mpidr >> MPIDR_LEVEL_SHIFT(level)) & MPIDR_LEVEL_MASK)
/* TTBCR Translation Table Base Control Register */
#define TTBCR_EAE _AC(0x80000000,U)
@@ -84,6 +101,73 @@
#define HCR_SWIO (_AC(1,UL)<<1) /* Set/Way Invalidation Override */
#define HCR_VM (_AC(1,UL)<<0) /* Virtual MMU Enable */
+/* TCR: Stage 1 Translation Control */
+
+#define TCR_T0SZ(x) ((x)<<0)
+
+#define TCR_IRGN0_NC (_AC(0x0,UL)<<8)
+#define TCR_IRGN0_WBWA (_AC(0x1,UL)<<8)
+#define TCR_IRGN0_WT (_AC(0x2,UL)<<8)
+#define TCR_IRGN0_WB (_AC(0x3,UL)<<8)
+
+#define TCR_ORGN0_NC (_AC(0x0,UL)<<10)
+#define TCR_ORGN0_WBWA (_AC(0x1,UL)<<10)
+#define TCR_ORGN0_WT (_AC(0x2,UL)<<10)
+#define TCR_ORGN0_WB (_AC(0x3,UL)<<10)
+
+#define TCR_SH0_NS (_AC(0x0,UL)<<12)
+#define TCR_SH0_OS (_AC(0x2,UL)<<12)
+#define TCR_SH0_IS (_AC(0x3,UL)<<12)
+
+#define TCR_TG0_4K (_AC(0x0,UL)<<14)
+#define TCR_TG0_64K (_AC(0x1,UL)<<14)
+#define TCR_TG0_16K (_AC(0x2,UL)<<14)
+
+#ifdef CONFIG_ARM_64
+
+#define TCR_PS(x) ((x)<<16)
+#define TCR_TBI (_AC(0x1,UL)<<20)
+
+#define TCR_RES1 (_AC(1,UL)<<31|_AC(1,UL)<<23)
+
+#else
+
+#define TCR_RES1 (_AC(1,UL)<<31)
+
+#endif
+
+/* VTCR: Stage 2 Translation Control */
+
+#define VTCR_T0SZ(x) ((x)<<0)
+
+#define VTCR_SL0(x) ((x)<<6)
+
+#define VTCR_IRGN0_NC (_AC(0x0,UL)<<8)
+#define VTCR_IRGN0_WBWA (_AC(0x1,UL)<<8)
+#define VTCR_IRGN0_WT (_AC(0x2,UL)<<8)
+#define VTCR_IRGN0_WB (_AC(0x3,UL)<<8)
+
+#define VTCR_ORGN0_NC (_AC(0x0,UL)<<10)
+#define VTCR_ORGN0_WBWA (_AC(0x1,UL)<<10)
+#define VTCR_ORGN0_WT (_AC(0x2,UL)<<10)
+#define VTCR_ORGN0_WB (_AC(0x3,UL)<<10)
+
+#define VTCR_SH0_NS (_AC(0x0,UL)<<12)
+#define VTCR_SH0_OS (_AC(0x2,UL)<<12)
+#define VTCR_SH0_IS (_AC(0x3,UL)<<12)
+
+#ifdef CONFIG_ARM_64
+
+#define VTCR_TG0_4K (_AC(0x0,UL)<<14)
+#define VTCR_TG0_64K (_AC(0x1,UL)<<14)
+#define VTCR_TG0_16K (_AC(0x2,UL)<<14)
+
+#define VTCR_PS(x) ((x)<<16)
+
+#endif
+
+#define VTCR_RES1 (_AC(1,UL)<<31)
+
/* HCPTR Hyp. Coprocessor Trap Register */
#define HCPTR_TTA ((_AC(1,U)<<20)) /* Trap trace registers */
#define HCPTR_CP(x) ((_AC(1,U)<<(x))) /* Trap Coprocessor x */
@@ -96,6 +180,7 @@
#define HDCR_TDRA (_AC(1,U)<<11) /* Trap Debug ROM access */
#define HDCR_TDOSA (_AC(1,U)<<10) /* Trap Debug-OS-related register access */
#define HDCR_TDA (_AC(1,U)<<9) /* Trap Debug Access */
+#define HDCR_TDE (_AC(1,U)<<8) /* Route Soft Debug exceptions from EL1/EL1 to EL2 */
#define HDCR_TPM (_AC(1,U)<<6) /* Trap Performance Monitors accesses */
#define HDCR_TPMCR (_AC(1,U)<<5) /* Trap PMCR accesses */
@@ -122,6 +207,9 @@
#define HSR_EC_INSTR_ABORT_CURR_EL 0x21
#define HSR_EC_DATA_ABORT_LOWER_EL 0x24
#define HSR_EC_DATA_ABORT_CURR_EL 0x25
+#ifdef CONFIG_ARM_64
+#define HSR_EC_BRK 0x3c
+#endif
/* FSR format, common */
#define FSR_LPAE (_AC(1,UL)<<9)
@@ -174,8 +262,8 @@ struct cpuinfo_arm {
unsigned long el3:4;
unsigned long fp:4; /* Floating Point */
unsigned long simd:4; /* Advanced SIMD */
- unsigned long __res0:8;
-
+ unsigned long gic:4; /* GIC support */
+ unsigned long __res0:4;
unsigned long __res1;
};
} pfr64;
@@ -188,8 +276,19 @@ struct cpuinfo_arm {
uint64_t bits[2];
} aux64;
- struct {
+ union {
uint64_t bits[2];
+ struct {
+ unsigned long pa_range:4;
+ unsigned long asid_bits:4;
+ unsigned long bigend:4;
+ unsigned long secure_ns:4;
+ unsigned long bigend_el0:4;
+ unsigned long tgranule_16K:4;
+ unsigned long tgranule_64K:4;
+ unsigned long tgranule_4K:4;
+ unsigned long __res0:32;
+ };
} mm64;
struct {
@@ -251,6 +350,14 @@ extern struct cpuinfo_arm cpu_data[];
extern u32 __cpu_logical_map[];
#define cpu_logical_map(cpu) __cpu_logical_map[cpu]
+/* HSR data abort size definition */
+enum dabt_size {
+ DABT_BYTE = 0,
+ DABT_HALF_WORD = 1,
+ DABT_WORD = 2,
+ DABT_DOUBLE_WORD = 3,
+};
+
union hsr {
uint32_t bits;
struct {
@@ -268,6 +375,15 @@ union hsr {
unsigned long ec:6; /* Exception Class */
} cond;
+ struct hsr_wfi_wfe {
+ unsigned long ti:1; /* Trapped instruction */
+ unsigned long sbzp:19;
+ unsigned long cc:4; /* Condition Code */
+ unsigned long ccvalid:1;/* CC Valid */
+ unsigned long len:1; /* Instruction length */
+ unsigned long ec:6; /* Exception Class */
+ } wfi_wfe;
+
/* reg, reg0, reg1 are 4 bits on AArch32, the fifth bit is sbzp. */
struct hsr_cp32 {
unsigned long read:1; /* Direction */
@@ -295,6 +411,17 @@ union hsr {
unsigned long ec:6; /* Exception Class */
} cp64; /* HSR_EC_CP15_64, HSR_EC_CP14_64 */
+ struct hsr_cp {
+ unsigned long coproc:4; /* Number of coproc accessed */
+ unsigned long sbz0p:1;
+ unsigned long tas:1; /* Trapped Advanced SIMD */
+ unsigned long res0:14;
+ unsigned long cc:4; /* Condition Code */
+ unsigned long ccvalid:1;/* CC Valid */
+ unsigned long len:1; /* Instruction length */
+ unsigned long ec:6; /* Exception Class */
+ } cp; /* HSR_EC_CP */
+
#ifdef CONFIG_ARM_64
struct hsr_sysreg {
unsigned long read:1; /* Direction */
@@ -330,6 +457,17 @@ union hsr {
unsigned long len:1; /* Instruction length */
unsigned long ec:6; /* Exception Class */
} dabt; /* HSR_EC_DATA_ABORT_* */
+
+#ifdef CONFIG_ARM_64
+ struct hsr_brk {
+ unsigned long comment:16; /* Comment */
+ unsigned long res0:9;
+ unsigned long len:1; /* Instruction length */
+ unsigned long ec:6; /* Exception Class */
+ } brk;
+#endif
+
+
};
#endif
@@ -461,7 +599,7 @@ void panic_PAR(uint64_t par);
void show_execution_state(struct cpu_user_regs *regs);
void show_registers(struct cpu_user_regs *regs);
//#define dump_execution_state() run_in_exception_handler(show_execution_state)
-#define dump_execution_state() asm volatile (".word 0xe7f000f0\n"); /* XXX */
+#define dump_execution_state() WARN()
#define cpu_relax() barrier() /* Could yield? */
@@ -469,16 +607,15 @@ void show_registers(struct cpu_user_regs *regs);
#define cpu_to_core(_cpu) (0)
#define cpu_to_socket(_cpu) (0)
-void do_unexpected_trap(const char *msg, struct cpu_user_regs *regs);
+void noreturn do_unexpected_trap(const char *msg, struct cpu_user_regs *regs);
void vcpu_regs_hyp_to_user(const struct vcpu *vcpu,
struct vcpu_guest_core_regs *regs);
void vcpu_regs_user_to_hyp(struct vcpu *vcpu,
const struct vcpu_guest_core_regs *regs);
-struct cpuinfo_x86 {
- uint32_t pfr32[2];
-};
+int call_smc(register_t function_id, register_t arg0, register_t arg1,
+ register_t arg2);
#endif /* __ASSEMBLY__ */
#endif /* __ASM_ARM_PROCESSOR_H */
diff --git a/xen/include/asm-arm/procinfo.h b/xen/include/asm-arm/procinfo.h
index 9d3feb7..26306b3 100644
--- a/xen/include/asm-arm/procinfo.h
+++ b/xen/include/asm-arm/procinfo.h
@@ -21,10 +21,23 @@
#ifndef __ASM_ARM_PROCINFO_H
#define __ASM_ARM_PROCINFO_H
+#include <xen/sched.h>
+
+struct processor {
+ /* Initialize specific processor register for the new VPCU*/
+ void (*vcpu_initialise)(struct vcpu *v);
+};
+
struct proc_info_list {
- unsigned int cpu_val;
- unsigned int cpu_mask;
+ unsigned int cpu_val;
+ unsigned int cpu_mask;
void (*cpu_init)(void);
+ struct processor *processor;
};
+const __init struct proc_info_list *lookup_processor_type(void);
+
+void __init processor_setup(void);
+void processor_vcpu_initialise(struct vcpu *v);
+
#endif
diff --git a/xen/include/asm-arm/psci.h b/xen/include/asm-arm/psci.h
index 189964b..5d17ee3 100644
--- a/xen/include/asm-arm/psci.h
+++ b/xen/include/asm-arm/psci.h
@@ -1,22 +1,91 @@
#ifndef __ASM_PSCI_H__
#define __ASM_PSCI_H__
-#define PSCI_SUCCESS 0
-#define PSCI_ENOSYS -1
-#define PSCI_EINVAL -2
-#define PSCI_DENIED -3
+/* PSCI return values (inclusive of all PSCI versions) */
+#define PSCI_SUCCESS 0
+#define PSCI_NOT_SUPPORTED -1
+#define PSCI_INVALID_PARAMETERS -2
+#define PSCI_DENIED -3
+#define PSCI_ALREADY_ON -4
+#define PSCI_ON_PENDING -5
+#define PSCI_INTERNAL_FAILURE -6
+#define PSCI_NOT_PRESENT -7
+#define PSCI_DISABLED -8
/* availability of PSCI on the host for SMP bringup */
-extern bool_t psci_available;
+extern uint32_t psci_ver;
int psci_init(void);
int call_psci_cpu_on(int cpu);
+void call_psci_system_off(void);
+void call_psci_system_reset(void);
/* functions to handle guest PSCI requests */
-int do_psci_cpu_on(uint32_t vcpuid, register_t entry_point);
-int do_psci_cpu_off(uint32_t power_state);
-int do_psci_cpu_suspend(uint32_t power_state, register_t entry_point);
-int do_psci_migrate(uint32_t vcpuid);
+int32_t do_psci_cpu_on(uint32_t vcpuid, register_t entry_point);
+int32_t do_psci_cpu_off(uint32_t power_state);
+int32_t do_psci_cpu_suspend(uint32_t power_state, register_t entry_point);
+int32_t do_psci_migrate(uint32_t vcpuid);
+
+/* PSCI 0.2 functions to handle guest PSCI requests */
+uint32_t do_psci_0_2_version(void);
+register_t do_psci_0_2_cpu_suspend(uint32_t power_state, register_t entry_point,
+ register_t context_id);
+int32_t do_psci_0_2_cpu_off(void);
+int32_t do_psci_0_2_cpu_on(register_t target_cpu, register_t entry_point,
+ register_t context_id);
+int32_t do_psci_0_2_affinity_info(register_t target_affinity,
+ uint32_t lowest_affinity_level);
+int32_t do_psci_0_2_migrate(uint32_t target_cpu);
+uint32_t do_psci_0_2_migrate_info_type(void);
+register_t do_psci_0_2_migrate_info_up_cpu(void);
+void do_psci_0_2_system_off(void);
+void do_psci_0_2_system_reset(void);
+
+/* PSCI version */
+#define XEN_PSCI_V_0_1 1
+#define XEN_PSCI_V_0_2 2
+
+/* PSCI v0.2 interface */
+#define PSCI_0_2_FN_BASE 0x84000000
+#define PSCI_0_2_FN(n) (PSCI_0_2_FN_BASE + (n))
+#define PSCI_0_2_64BIT 0x40000000
+#define PSCI_0_2_FN64_BASE \
+ (PSCI_0_2_FN_BASE + PSCI_0_2_64BIT)
+#define PSCI_0_2_FN64(n) (PSCI_0_2_FN64_BASE + (n))
+
+#define PSCI_0_2_FN_PSCI_VERSION PSCI_0_2_FN(0)
+#define PSCI_0_2_FN_CPU_SUSPEND PSCI_0_2_FN(1)
+#define PSCI_0_2_FN_CPU_OFF PSCI_0_2_FN(2)
+#define PSCI_0_2_FN_CPU_ON PSCI_0_2_FN(3)
+#define PSCI_0_2_FN_AFFINITY_INFO PSCI_0_2_FN(4)
+#define PSCI_0_2_FN_MIGRATE PSCI_0_2_FN(5)
+#define PSCI_0_2_FN_MIGRATE_INFO_TYPE PSCI_0_2_FN(6)
+#define PSCI_0_2_FN_MIGRATE_INFO_UP_CPU PSCI_0_2_FN(7)
+#define PSCI_0_2_FN_SYSTEM_OFF PSCI_0_2_FN(8)
+#define PSCI_0_2_FN_SYSTEM_RESET PSCI_0_2_FN(9)
+
+#define PSCI_0_2_FN64_CPU_SUSPEND PSCI_0_2_FN64(1)
+#define PSCI_0_2_FN64_CPU_ON PSCI_0_2_FN64(3)
+#define PSCI_0_2_FN64_AFFINITY_INFO PSCI_0_2_FN64(4)
+#define PSCI_0_2_FN64_MIGRATE PSCI_0_2_FN64(5)
+#define PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU PSCI_0_2_FN64(7)
+
+/* PSCI v0.2 affinity level state returned by AFFINITY_INFO */
+#define PSCI_0_2_AFFINITY_LEVEL_ON 0
+#define PSCI_0_2_AFFINITY_LEVEL_OFF 1
+#define PSCI_0_2_AFFINITY_LEVEL_ON_PENDING 2
+
+/* PSCI v0.2 multicore support in Trusted OS returned by MIGRATE_INFO_TYPE */
+#define PSCI_0_2_TOS_UP_MIGRATE_CAPABLE 0
+#define PSCI_0_2_TOS_UP_NOT_MIGRATE_CAPABLE 1
+#define PSCI_0_2_TOS_MP_OR_NOT_PRESENT 2
+
+/* PSCI v0.2 power state encoding for CPU_SUSPEND function */
+#define PSCI_0_2_POWER_STATE_ID_MASK 0xffff
+#define PSCI_0_2_POWER_STATE_ID_SHIFT 0
+#define PSCI_0_2_POWER_STATE_TYPE_SHIFT 16
+#define PSCI_0_2_POWER_STATE_TYPE_MASK \
+ (0x1 << PSCI_0_2_POWER_STATE_TYPE_SHIFT)
#endif /* __ASM_PSCI_H__ */
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index 44a3b4d..ba5a67d 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -3,9 +3,53 @@
#include <public/version.h>
+#define NR_MEM_BANKS 64
+
+#define MAX_MODULES 5 /* Current maximum useful modules */
+
+typedef enum {
+ BOOTMOD_XEN,
+ BOOTMOD_FDT,
+ BOOTMOD_KERNEL,
+ BOOTMOD_RAMDISK,
+ BOOTMOD_XSM,
+ BOOTMOD_UNKNOWN
+} bootmodule_kind;
+
+
+struct membank {
+ paddr_t start;
+ paddr_t size;
+};
+
+struct meminfo {
+ int nr_banks;
+ struct membank bank[NR_MEM_BANKS];
+};
+
+#define BOOTMOD_MAX_CMDLINE 1024
+struct bootmodule {
+ bootmodule_kind kind;
+ paddr_t start;
+ paddr_t size;
+ char cmdline[BOOTMOD_MAX_CMDLINE];
+};
+
+struct bootmodules {
+ int nr_mods;
+ struct bootmodule module[MAX_MODULES];
+};
+
+struct bootinfo {
+ struct meminfo mem;
+ struct bootmodules modules;
+};
+
+extern struct bootinfo bootinfo;
+
void arch_init_memory(void);
-void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len, int attrindx);
+void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len);
void arch_get_xen_caps(xen_capabilities_info_t *info);
@@ -13,6 +57,15 @@ int construct_dom0(struct domain *d);
void discard_initial_modules(void);
+size_t __init boot_fdt_info(const void *fdt, paddr_t paddr);
+const char __init *boot_fdt_cmdline(const void *fdt);
+
+struct bootmodule *add_boot_module(bootmodule_kind kind,
+ paddr_t start, paddr_t size,
+ const char *cmdline);
+struct bootmodule *boot_module_find_by_kind(bootmodule_kind kind);
+const char * __init boot_module_kind_as_string(bootmodule_kind kind);
+
#endif
/*
* Local variables:
diff --git a/xen/include/asm-arm/smp.h b/xen/include/asm-arm/smp.h
index a1de03c..91b1e52 100644
--- a/xen/include/asm-arm/smp.h
+++ b/xen/include/asm-arm/smp.h
@@ -15,7 +15,7 @@ DECLARE_PER_CPU(cpumask_var_t, cpu_core_mask);
#define raw_smp_processor_id() (get_processor_id())
-extern void stop_cpu(void);
+extern void noreturn stop_cpu(void);
extern int arch_smp_init(void);
extern int arch_cpu_init(int cpu, struct dt_device_node *dn);
diff --git a/xen/include/asm-arm/softirq.h b/xen/include/asm-arm/softirq.h
index 35e578a..976e0eb 100644
--- a/xen/include/asm-arm/softirq.h
+++ b/xen/include/asm-arm/softirq.h
@@ -3,6 +3,8 @@
#define NR_ARCH_SOFTIRQS 0
+#define arch_skip_send_event_check(cpu) 0
+
#endif /* __ASM_SOFTIRQ_H__ */
/*
* Local variables:
diff --git a/xen/include/asm-arm/string.h b/xen/include/asm-arm/string.h
index abfa9d2..e4b4469 100644
--- a/xen/include/asm-arm/string.h
+++ b/xen/include/asm-arm/string.h
@@ -3,10 +3,39 @@
#include <xen/config.h>
-#if defined(CONFIG_ARM_32)
+/*
+ * We don't do inline string functions, since the
+ * optimised inline asm versions are not small.
+ */
+
+#define __HAVE_ARCH_STRRCHR
+extern char * strrchr(const char * s, int c);
+
+#define __HAVE_ARCH_STRCHR
+extern char * strchr(const char * s, int c);
+
+#if defined(CONFIG_ARM_64)
+#define __HAVE_ARCH_STRCMP
+extern int strcmp(const char *, const char *);
+
+#define __HAVE_ARCH_STRNCMP
+extern int strncmp(const char *, const char *, __kernel_size_t);
+
+#define __HAVE_ARCH_STRLEN
+extern __kernel_size_t strlen(const char *);
+
+#define __HAVE_ARCH_STRNLEN
+extern __kernel_size_t strnlen(const char *, __kernel_size_t);
+#endif
+
#define __HAVE_ARCH_MEMCPY
extern void * memcpy(void *, const void *, __kernel_size_t);
+#if defined(CONFIG_ARM_64)
+#define __HAVE_ARCH_MEMCMP
+extern int memcmp(const void *, const void *, __kernel_size_t);
+#endif
+
/* Some versions of gcc don't have this builtin. It's non-critical anyway. */
#define __HAVE_ARCH_MEMMOVE
extern void *memmove(void *dest, const void *src, size_t n);
@@ -14,6 +43,11 @@ extern void *memmove(void *dest, const void *src, size_t n);
#define __HAVE_ARCH_MEMSET
extern void * memset(void *, int, __kernel_size_t);
+#define __HAVE_ARCH_MEMCHR
+extern void * memchr(const void *, int, __kernel_size_t);
+
+#if defined(CONFIG_ARM_32)
+
extern void __memzero(void *ptr, __kernel_size_t n);
#define memset(p,v,n) \
diff --git a/xen/include/asm-arm/sysregs.h b/xen/include/asm-arm/sysregs.h
index b00871c..169b7ac 100644
--- a/xen/include/asm-arm/sysregs.h
+++ b/xen/include/asm-arm/sysregs.h
@@ -78,6 +78,9 @@
#define HSR_SYSREG_PMINTENCLR_EL1 HSR_SYSREG(3,0,c9,c14,2)
#define HSR_SYSREG_MAIR_EL1 HSR_SYSREG(3,0,c10,c2,0)
#define HSR_SYSREG_AMAIR_EL1 HSR_SYSREG(3,0,c10,c3,0)
+#define HSR_SYSREG_ICC_SGI1R_EL1 HSR_SYSREG(3,0,c12,c11,5)
+#define HSR_SYSREG_ICC_ASGI1R_EL1 HSR_SYSREG(3,1,c12,c11,6)
+#define HSR_SYSREG_ICC_SGI0R_EL1 HSR_SYSREG(3,2,c12,c11,7)
#define HSR_SYSREG_CONTEXTIDR_EL1 HSR_SYSREG(3,0,c13,c0,1)
#define HSR_SYSREG_PMCR_EL0 HSR_SYSREG(3,3,c9,c12,0)
@@ -100,6 +103,59 @@
#define HSR_SYSREG_CNTP_CTL_EL0 HSR_SYSREG(3,3,c14,c2,1)
#define HSR_SYSREG_CNTP_TVAL_EL0 HSR_SYSREG(3,3,c14,c2,0)
+/*
+ * GIC System register assembly aliases picked from kernel
+ */
+#define ICC_PMR_EL1 S3_0_C4_C6_0
+#define ICC_DIR_EL1 S3_0_C12_C11_1
+#define ICC_SGI1R_EL1 S3_0_C12_C11_5
+#define ICC_EOIR1_EL1 S3_0_C12_C12_1
+#define ICC_IAR1_EL1 S3_0_C12_C12_0
+#define ICC_BPR1_EL1 S3_0_C12_C12_3
+#define ICC_CTLR_EL1 S3_0_C12_C12_4
+#define ICC_SRE_EL1 S3_0_C12_C12_5
+#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7
+
+#define ICH_VSEIR_EL2 S3_4_C12_C9_4
+#define ICC_SRE_EL2 S3_4_C12_C9_5
+#define ICH_HCR_EL2 S3_4_C12_C11_0
+#define ICH_VTR_EL2 S3_4_C12_C11_1
+#define ICH_MISR_EL2 S3_4_C12_C11_2
+#define ICH_EISR_EL2 S3_4_C12_C11_3
+#define ICH_ELSR_EL2 S3_4_C12_C11_5
+#define ICH_VMCR_EL2 S3_4_C12_C11_7
+
+#define __LR0_EL2(x) S3_4_C12_C12_ ## x
+#define __LR8_EL2(x) S3_4_C12_C13_ ## x
+
+#define ICH_LR0_EL2 __LR0_EL2(0)
+#define ICH_LR1_EL2 __LR0_EL2(1)
+#define ICH_LR2_EL2 __LR0_EL2(2)
+#define ICH_LR3_EL2 __LR0_EL2(3)
+#define ICH_LR4_EL2 __LR0_EL2(4)
+#define ICH_LR5_EL2 __LR0_EL2(5)
+#define ICH_LR6_EL2 __LR0_EL2(6)
+#define ICH_LR7_EL2 __LR0_EL2(7)
+#define ICH_LR8_EL2 __LR8_EL2(0)
+#define ICH_LR9_EL2 __LR8_EL2(1)
+#define ICH_LR10_EL2 __LR8_EL2(2)
+#define ICH_LR11_EL2 __LR8_EL2(3)
+#define ICH_LR12_EL2 __LR8_EL2(4)
+#define ICH_LR13_EL2 __LR8_EL2(5)
+#define ICH_LR14_EL2 __LR8_EL2(6)
+#define ICH_LR15_EL2 __LR8_EL2(7)
+
+#define __AP0Rx_EL2(x) S3_4_C12_C8_ ## x
+#define ICH_AP0R0_EL2 __AP0Rx_EL2(0)
+#define ICH_AP0R1_EL2 __AP0Rx_EL2(1)
+#define ICH_AP0R2_EL2 __AP0Rx_EL2(2)
+#define ICH_AP0R3_EL2 __AP0Rx_EL2(3)
+
+#define __AP1Rx_EL2(x) S3_4_C12_C9_ ## x
+#define ICH_AP1R0_EL2 __AP1Rx_EL2(0)
+#define ICH_AP1R1_EL2 __AP1Rx_EL2(1)
+#define ICH_AP1R2_EL2 __AP1Rx_EL2(2)
+#define ICH_AP1R3_EL2 __AP1Rx_EL2(3)
#endif
diff --git a/xen/include/asm-arm/system.h b/xen/include/asm-arm/system.h
index 290d38d..ce3d38a 100644
--- a/xen/include/asm-arm/system.h
+++ b/xen/include/asm-arm/system.h
@@ -8,8 +8,30 @@
#define nop() \
asm volatile ( "nop" )
-#define xchg(ptr,x) \
- ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+#define sev() asm volatile("sev" : : : "memory")
+#define wfe() asm volatile("wfe" : : : "memory")
+#define wfi() asm volatile("wfi" : : : "memory")
+
+#define isb() asm volatile("isb" : : : "memory")
+#define dsb(scope) asm volatile("dsb " #scope : : : "memory")
+#define dmb(scope) asm volatile("dmb " #scope : : : "memory")
+
+#define mb() dsb(sy)
+#ifdef CONFIG_ARM_64
+#define rmb() dsb(ld)
+#else
+#define rmb() dsb(sy) /* 32-bit has no ld variant. */
+#endif
+#define wmb() dsb(st)
+
+#define smp_mb() dmb(ish)
+#ifdef CONFIG_ARM_64
+#define smp_rmb() dmb(ishld)
+#else
+#define smp_rmb() dmb(ish) /* 32-bit has no ishld variant. */
+#endif
+
+#define smp_wmb() dmb(ishst)
/*
* This is used to ensure the compiler did actually allocate the register we
diff --git a/xen/include/asm-arm/time.h b/xen/include/asm-arm/time.h
index 9d302d3..d544b5b 100644
--- a/xen/include/asm-arm/time.h
+++ b/xen/include/asm-arm/time.h
@@ -12,9 +12,6 @@ static inline cycles_t get_cycles (void)
return 0;
}
-struct tm;
-struct tm wallclock_time(void);
-
/* List of timer's IRQ */
enum timer_ppi
{
@@ -25,11 +22,8 @@ enum timer_ppi
MAX_TIMER_PPI = 4,
};
-/* Get one of the timer IRQ description */
-const struct dt_irq* timer_dt_irq(enum timer_ppi ppi);
-
-/* Route timer's IRQ on this CPU */
-extern void __cpuinit route_timer_interrupt(void);
+/* Get one of the timer IRQ number */
+unsigned int timer_get_irq(enum timer_ppi ppi);
/* Set up the timer interrupt on this CPU */
extern void __cpuinit init_timer_interrupt(void);
diff --git a/xen/include/asm-arm/types.h b/xen/include/asm-arm/types.h
index 6875a62..09e5455 100644
--- a/xen/include/asm-arm/types.h
+++ b/xen/include/asm-arm/types.h
@@ -55,7 +55,12 @@ typedef u64 register_t;
#define PRIregister "lx"
#endif
+#if defined(__SIZE_TYPE__)
+typedef __SIZE_TYPE__ size_t;
+#else
typedef unsigned long size_t;
+#endif
+typedef signed long ssize_t;
typedef char bool_t;
#define test_and_set_bool(b) xchg(&(b), 1)
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
new file mode 100644
index 0000000..5160f17
--- /dev/null
+++ b/xen/include/asm-arm/vgic.h
@@ -0,0 +1,209 @@
+/*
+ * ARM Virtual Generic Interrupt Controller support
+ *
+ * Ian Campbell <ian.campbell at citrix.com>
+ * Copyright (c) 2011 Citrix Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARM_VGIC_H__
+#define __ASM_ARM_VGIC_H__
+
+#include <xen/bitops.h>
+
+struct pending_irq
+{
+ /*
+ * The following two states track the lifecycle of the guest irq.
+ * However because we are not sure and we don't want to track
+ * whether an irq added to an LR register is PENDING or ACTIVE, the
+ * following states are just an approximation.
+ *
+ * GIC_IRQ_GUEST_QUEUED: the irq is asserted and queued for
+ * injection into the guest's LRs.
+ *
+ * GIC_IRQ_GUEST_VISIBLE: the irq has been added to an LR register,
+ * therefore the guest is aware of it. From the guest point of view
+ * the irq can be pending (if the guest has not acked the irq yet)
+ * or active (after acking the irq).
+ *
+ * In order for the state machine to be fully accurate, for level
+ * interrupts, we should keep the interrupt's pending state until
+ * the guest deactivates the irq. However because we are not sure
+ * when that happens, we instead track whether there is an interrupt
+ * queued using GIC_IRQ_GUEST_QUEUED. We clear it when we add it to
+ * an LR register. We set it when we receive another interrupt
+ * notification. Therefore it is possible to set
+ * GIC_IRQ_GUEST_QUEUED while the irq is GIC_IRQ_GUEST_VISIBLE. We
+ * could also change the state of the guest irq in the LR register
+ * from active to active and pending, but for simplicity we simply
+ * inject a second irq after the guest EOIs the first one.
+ *
+ *
+ * An additional state is used to keep track of whether the guest
+ * irq is enabled at the vgicd level:
+ *
+ * GIC_IRQ_GUEST_ENABLED: the guest IRQ is enabled at the VGICD
+ * level (GICD_ICENABLER/GICD_ISENABLER).
+ *
+ * GIC_IRQ_GUEST_MIGRATING: the irq is being migrated to a different
+ * vcpu while it is still inflight and on an GICH_LR register on the
+ * old vcpu.
+ *
+ */
+#define GIC_IRQ_GUEST_QUEUED 0
+#define GIC_IRQ_GUEST_ACTIVE 1
+#define GIC_IRQ_GUEST_VISIBLE 2
+#define GIC_IRQ_GUEST_ENABLED 3
+#define GIC_IRQ_GUEST_MIGRATING 4
+ unsigned long status;
+ struct irq_desc *desc; /* only set it the irq corresponds to a physical irq */
+ int irq;
+#define GIC_INVALID_LR ~(uint8_t)0
+ uint8_t lr;
+ uint8_t priority;
+ /* inflight is used to append instances of pending_irq to
+ * vgic.inflight_irqs */
+ struct list_head inflight;
+ /* lr_queue is used to append instances of pending_irq to
+ * lr_pending. lr_pending is a per vcpu queue, therefore lr_queue
+ * accesses are protected with the vgic lock.
+ * TODO: when implementing irq migration, taking only the current
+ * vgic lock is not going to be enough. */
+ struct list_head lr_queue;
+};
+
+/* Represents state corresponding to a block of 32 interrupts */
+struct vgic_irq_rank {
+ spinlock_t lock; /* Covers access to all other members of this struct */
+ uint32_t ienable, iactive, ipend, pendsgi;
+ uint32_t icfg[2];
+ uint32_t ipriority[8];
+ union {
+ struct {
+ uint32_t itargets[8];
+ }v2;
+ struct {
+ uint64_t irouter[32];
+ }v3;
+ };
+};
+
+struct vgic_ops {
+ /* Initialize vGIC */
+ int (*vcpu_init)(struct vcpu *v);
+ /* Domain specific initialization of vGIC */
+ int (*domain_init)(struct domain *d);
+ /* Get priority for a given irq stored in vgic structure */
+ int (*get_irq_priority)(struct vcpu *v, unsigned int irq);
+ /* Get the target vcpu for a given virq. The rank lock is already taken
+ * when calling this. */
+ struct vcpu *(*get_target_vcpu)(struct vcpu *v, unsigned int irq);
+ /* vGIC sysreg emulation */
+ int (*emulate_sysreg)(struct cpu_user_regs *regs, union hsr hsr);
+};
+
+/* Number of ranks of interrupt registers for a domain */
+#define DOMAIN_NR_RANKS(d) (((d)->arch.vgic.nr_lines+31)/32)
+
+#define vgic_lock(v) spin_lock_irq(&(v)->domain->arch.vgic.lock)
+#define vgic_unlock(v) spin_unlock_irq(&(v)->domain->arch.vgic.lock)
+
+#define vgic_lock_rank(v, r, flags) spin_lock_irqsave(&(r)->lock, flags)
+#define vgic_unlock_rank(v, r, flags) spin_unlock_irqrestore(&(r)->lock, flags)
+
+/*
+ * Rank containing GICD_<FOO><n> for GICD_<FOO> with
+ * <b>-bits-per-interrupt
+ */
+static inline int REG_RANK_NR(int b, uint32_t n)
+{
+ switch ( b )
+ {
+ /*
+ * IRQ ranks are of size 32. So n cannot be shifted beyond 5 for 32
+ * and above. For 64-bit n is already shifted DBAT_DOUBLE_WORD
+ * by the caller
+ */
+ case 64:
+ case 32: return n >> 5;
+ case 16: return n >> 4;
+ case 8: return n >> 3;
+ case 4: return n >> 2;
+ case 2: return n >> 1;
+ case 1: return n;
+ default: BUG();
+ }
+}
+
+static inline uint32_t vgic_byte_read(uint32_t val, int sign, int offset)
+{
+ int byte = offset & 0x3;
+
+ val = val >> (8*byte);
+ if ( sign && (val & 0x80) )
+ val |= 0xffffff00;
+ else
+ val &= 0x000000ff;
+ return val;
+}
+
+static inline void vgic_byte_write(uint32_t *reg, uint32_t var, int offset)
+{
+ int byte = offset & 0x3;
+
+ var &= (0xff << (8*byte));
+
+ *reg &= ~(0xff << (8*byte));
+ *reg |= var;
+}
+
+enum gic_sgi_mode;
+
+/*
+ * Offset of GICD_<FOO><n> with its rank, for GICD_<FOO> size <s> with
+ * <b>-bits-per-interrupt.
+ */
+#define REG_RANK_INDEX(b, n, s) ((((n) >> s) & ((b)-1)) % 32)
+
+extern int domain_vgic_init(struct domain *d);
+extern void domain_vgic_free(struct domain *d);
+extern int vcpu_vgic_init(struct vcpu *v);
+extern struct vcpu *vgic_get_target_vcpu(struct vcpu *v, unsigned int irq);
+extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq);
+extern void vgic_vcpu_inject_spi(struct domain *d, unsigned int irq);
+extern void vgic_clear_pending_irqs(struct vcpu *v);
+extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq);
+extern struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n, int s);
+extern struct vgic_irq_rank *vgic_rank_irq(struct vcpu *v, unsigned int irq);
+extern int vgic_emulate(struct cpu_user_regs *regs, union hsr hsr);
+extern void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n);
+extern void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n);
+extern void register_vgic_ops(struct domain *d, const struct vgic_ops *ops);
+int vgic_v2_init(struct domain *d);
+int vgic_v3_init(struct domain *d);
+
+extern int vcpu_vgic_free(struct vcpu *v);
+extern int vgic_to_sgi(struct vcpu *v, register_t sgir,
+ enum gic_sgi_mode irqmode, int virq,
+ unsigned long vcpu_mask);
+extern void vgic_migrate_irq(struct vcpu *old, struct vcpu *new, unsigned int irq);
+#endif /* __ASM_ARM_VGIC_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-x86/acpi.h b/xen/include/asm-x86/acpi.h
index a7b11b8..5e85b38 100644
--- a/xen/include/asm-x86/acpi.h
+++ b/xen/include/asm-x86/acpi.h
@@ -80,7 +80,6 @@ int __acpi_release_global_lock(unsigned int *lock);
extern bool_t acpi_lapic, acpi_ioapic, acpi_noirq;
extern bool_t acpi_force, acpi_ht, acpi_disabled;
-extern bool_t acpi_skip_timer_override;
extern u32 acpi_smi_cmd;
extern u8 acpi_enable_value, acpi_disable_value;
void acpi_pic_sci_set_trigger(unsigned int, u16);
diff --git a/xen/include/asm-x86/alternative.h b/xen/include/asm-x86/alternative.h
new file mode 100644
index 0000000..c746047
--- /dev/null
+++ b/xen/include/asm-x86/alternative.h
@@ -0,0 +1,78 @@
+#ifndef __X86_ALTERNATIVE_H__
+#define __X86_ALTERNATIVE_H__
+
+#include <asm/nops.h>
+
+#ifdef __ASSEMBLY__
+.macro altinstruction_entry orig alt feature orig_len alt_len
+ .long \orig - .
+ .long \alt - .
+ .word \feature
+ .byte \orig_len
+ .byte \alt_len
+.endm
+#else
+#include <xen/types.h>
+
+struct alt_instr {
+ s32 instr_offset; /* original instruction */
+ s32 repl_offset; /* offset to replacement instruction */
+ u16 cpuid; /* cpuid bit set for replacement */
+ u8 instrlen; /* length of original instruction */
+ u8 replacementlen; /* length of new instruction, <= instrlen */
+};
+
+extern void alternative_instructions(void);
+
+#define OLDINSTR(oldinstr) "661:\n\t" oldinstr "\n662:\n"
+
+#define b_replacement(number) "663"#number
+#define e_replacement(number) "664"#number
+
+#define alt_slen "662b-661b"
+#define alt_rlen(number) e_replacement(number)"f-"b_replacement(number)"f"
+
+#define ALTINSTR_ENTRY(feature, number) \
+ " .long 661b - .\n" /* label */ \
+ " .long " b_replacement(number)"f - .\n" /* new instruction */ \
+ " .word " __stringify(feature) "\n" /* feature bit */ \
+ " .byte " alt_slen "\n" /* source len */ \
+ " .byte " alt_rlen(number) "\n" /* replacement len */
+
+#define DISCARD_ENTRY(number) /* rlen <= slen */ \
+ " .byte 0xff + (" alt_rlen(number) ") - (" alt_slen ")\n"
+
+#define ALTINSTR_REPLACEMENT(newinstr, feature, number) /* replacement */ \
+ b_replacement(number)":\n\t" newinstr "\n" e_replacement(number) ":\n\t"
+
+/* alternative assembly primitive: */
+#define ALTERNATIVE(oldinstr, newinstr, feature) \
+ OLDINSTR(oldinstr) \
+ ".pushsection .altinstructions,\"a\"\n" \
+ ALTINSTR_ENTRY(feature, 1) \
+ ".popsection\n" \
+ ".pushsection .discard,\"aw\", at progbits\n" \
+ DISCARD_ENTRY(1) \
+ ".popsection\n" \
+ ".pushsection .altinstr_replacement, \"ax\"\n" \
+ ALTINSTR_REPLACEMENT(newinstr, feature, 1) \
+ ".popsection"
+
+/*
+ * Alternative instructions for different CPU types or capabilities.
+ *
+ * This allows to use optimized instructions even on generic binary
+ * kernels.
+ *
+ * length of oldinstr must be longer or equal the length of newinstr
+ * It can be padded with nops as needed.
+ *
+ * For non barrier like inlines please define new variants
+ * without volatile and memory clobber.
+ */
+#define alternative(oldinstr, newinstr, feature) \
+ asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory")
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __X86_ALTERNATIVE_H__ */
diff --git a/xen/include/asm-x86/apic.h b/xen/include/asm-x86/apic.h
index 43b39ce..6697245 100644
--- a/xen/include/asm-x86/apic.h
+++ b/xen/include/asm-x86/apic.h
@@ -206,7 +206,7 @@ extern void release_lapic_nmi(void);
extern void self_nmi(void);
extern void disable_timer_nmi_watchdog(void);
extern void enable_timer_nmi_watchdog(void);
-extern void nmi_watchdog_tick (struct cpu_user_regs *regs);
+extern bool_t nmi_watchdog_tick (const struct cpu_user_regs *regs);
extern int APIC_init_uniprocessor (void);
extern void disable_APIC_timer(void);
extern void enable_APIC_timer(void);
diff --git a/xen/include/asm-x86/apicdef.h b/xen/include/asm-x86/apicdef.h
index 2bdb3df..6069fce 100644
--- a/xen/include/asm-x86/apicdef.h
+++ b/xen/include/asm-x86/apicdef.h
@@ -84,12 +84,6 @@
#define APIC_LVT0 0x350
#define APIC_CMCI 0x2F0
-#define APIC_LVT_TIMER_BASE_MASK (0x3<<18)
-#define GET_APIC_TIMER_BASE(x) (((x)>>18)&0x3)
-#define SET_APIC_TIMER_BASE(x) (((x)<<18))
-#define APIC_TIMER_BASE_CLKIN 0x0
-#define APIC_TIMER_BASE_TMBASE 0x1
-#define APIC_TIMER_BASE_DIV 0x2
#define APIC_TIMER_MODE_MASK (0x3<<17)
#define APIC_TIMER_MODE_ONESHOT (0x0<<17)
#define APIC_TIMER_MODE_PERIODIC (0x1<<17)
@@ -110,10 +104,6 @@
#define APIC_TMICT 0x380
#define APIC_TMCCT 0x390
#define APIC_TDCR 0x3E0
-
-/* Only available in x2APIC mode */
-#define APIC_SELF_IPI 0x3F0
-
#define APIC_TDR_DIV_TMBASE (1<<2)
#define APIC_TDR_DIV_1 0xB
#define APIC_TDR_DIV_2 0x0
@@ -124,6 +114,9 @@
#define APIC_TDR_DIV_64 0x9
#define APIC_TDR_DIV_128 0xA
+/* Only available in x2APIC mode */
+#define APIC_SELF_IPI 0x3F0
+
#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
/* It's only used in x2APIC mode of an x2APIC unit. */
@@ -142,7 +135,7 @@
#define lapic ((volatile struct local_apic *)APIC_BASE)
#ifndef __ASSEMBLY__
-struct local_apic {
+struct __packed local_apic {
/*000*/ struct { u32 __reserved[4]; } __reserved_01;
@@ -388,7 +381,7 @@ struct local_apic {
/*3F0*/ struct { u32 __reserved[4]; } __reserved_20;
-} __attribute__ ((packed));
+};
#endif /* !__ASSEMBLY__ */
#undef u32
diff --git a/xen/include/asm-x86/asm_defns.h b/xen/include/asm-x86/asm_defns.h
index a4601ba..1674c7c 100644
--- a/xen/include/asm-x86/asm_defns.h
+++ b/xen/include/asm-x86/asm_defns.h
@@ -7,12 +7,68 @@
#include <asm/asm-offsets.h>
#endif
#include <asm/processor.h>
+#include <asm/percpu.h>
+#include <xen/stringify.h>
+#include <asm/cpufeature.h>
+#include <asm/alternative.h>
#ifndef __ASSEMBLY__
void ret_from_intr(void);
#endif
-#include <asm/x86_64/asm_defns.h>
+#ifdef CONFIG_FRAME_POINTER
+/* Indicate special exception stack frame by inverting the frame pointer. */
+#define SETUP_EXCEPTION_FRAME_POINTER(offs) \
+ leaq offs(%rsp),%rbp; \
+ notq %rbp
+#else
+#define SETUP_EXCEPTION_FRAME_POINTER(offs)
+#endif
+
+#ifndef NDEBUG
+#define ASSERT_INTERRUPT_STATUS(x) \
+ pushf; \
+ testb $X86_EFLAGS_IF>>8,1(%rsp); \
+ j##x 1f; \
+ ud2a; \
+1: addq $8,%rsp;
+#else
+#define ASSERT_INTERRUPT_STATUS(x)
+#endif
+
+#define ASSERT_INTERRUPTS_ENABLED ASSERT_INTERRUPT_STATUS(nz)
+#define ASSERT_INTERRUPTS_DISABLED ASSERT_INTERRUPT_STATUS(z)
+
+/*
+ * This flag is set in an exception frame when registers R12-R15 did not get
+ * saved.
+ */
+#define _TRAP_regs_partial 16
+#define TRAP_regs_partial (1 << _TRAP_regs_partial)
+/*
+ * This flag gets set in an exception frame when registers R12-R15 possibly
+ * get modified from their originally saved values and hence need to be
+ * restored even if the normal call flow would restore register values.
+ *
+ * The flag being set implies _TRAP_regs_partial to be unset. Restoring
+ * R12-R15 thus is
+ * - required when this flag is set,
+ * - safe when _TRAP_regs_partial is unset.
+ */
+#define _TRAP_regs_dirty 17
+#define TRAP_regs_dirty (1 << _TRAP_regs_dirty)
+
+#define mark_regs_dirty(r) ({ \
+ struct cpu_user_regs *r__ = (r); \
+ ASSERT(!((r__)->entry_vector & TRAP_regs_partial)); \
+ r__->entry_vector |= TRAP_regs_dirty; \
+})
+
+#ifdef __ASSEMBLY__
+# define _ASM_EX(p) p-.
+#else
+# define _ASM_EX(p) #p "-."
+#endif
/* Exception table entry */
#ifdef __ASSEMBLY__
@@ -77,6 +133,9 @@ void ret_from_intr(void);
#define ASSERT_NOT_IN_ATOMIC
#endif
+#define CPUINFO_FEATURE_OFFSET(feature) \
+ ((((feature) >> 3) & ~3) + CPUINFO_features)
+
#else
#ifdef __clang__ /* clang's builtin assember can't do .subsection */
@@ -103,4 +162,202 @@ void ret_from_intr(void);
#endif
+/* "Raw" instruction opcodes */
+#define __ASM_CLAC .byte 0x0f,0x01,0xca
+#define __ASM_STAC .byte 0x0f,0x01,0xcb
+
+#ifdef __ASSEMBLY__
+#define ASM_AC(op) \
+ 661: ASM_NOP3; \
+ .pushsection .altinstr_replacement, "ax"; \
+ 662: __ASM_##op; \
+ .popsection; \
+ .pushsection .altinstructions, "a"; \
+ altinstruction_entry 661b, 662b, X86_FEATURE_SMAP, 3, 3; \
+ .popsection
+
+#define ASM_STAC ASM_AC(STAC)
+#define ASM_CLAC ASM_AC(CLAC)
+#else
+static always_inline void clac(void)
+{
+ /* Note: a barrier is implicit in alternative() */
+ alternative(ASM_NOP3, __stringify(__ASM_CLAC), X86_FEATURE_SMAP);
+}
+
+static always_inline void stac(void)
+{
+ /* Note: a barrier is implicit in alternative() */
+ alternative(ASM_NOP3, __stringify(__ASM_STAC), X86_FEATURE_SMAP);
+}
+#endif
+
+#ifdef __ASSEMBLY__
+.macro SAVE_ALL op
+.ifeqs "\op", "CLAC"
+ ASM_CLAC
+.else
+.ifeqs "\op", "STAC"
+ ASM_STAC
+.else
+.ifnb \op
+ .err
+.endif
+.endif
+.endif
+ addq $-(UREGS_error_code-UREGS_r15), %rsp
+ cld
+ movq %rdi,UREGS_rdi(%rsp)
+ movq %rsi,UREGS_rsi(%rsp)
+ movq %rdx,UREGS_rdx(%rsp)
+ movq %rcx,UREGS_rcx(%rsp)
+ movq %rax,UREGS_rax(%rsp)
+ movq %r8,UREGS_r8(%rsp)
+ movq %r9,UREGS_r9(%rsp)
+ movq %r10,UREGS_r10(%rsp)
+ movq %r11,UREGS_r11(%rsp)
+ movq %rbx,UREGS_rbx(%rsp)
+ movq %rbp,UREGS_rbp(%rsp)
+ SETUP_EXCEPTION_FRAME_POINTER(UREGS_rbp)
+ movq %r12,UREGS_r12(%rsp)
+ movq %r13,UREGS_r13(%rsp)
+ movq %r14,UREGS_r14(%rsp)
+ movq %r15,UREGS_r15(%rsp)
+.endm
+
+/*
+ * Save all registers not preserved by C code or used in entry/exit code. Mark
+ * the frame as partial.
+ *
+ * @type: exception type
+ * @compat: R8-R15 don't need saving, and the frame nevertheless is complete
+ */
+.macro SAVE_VOLATILE type compat=0
+.if \compat
+ movl $\type,UREGS_entry_vector-UREGS_error_code(%rsp)
+.else
+ movl $\type|TRAP_regs_partial,\
+ UREGS_entry_vector-UREGS_error_code(%rsp)
+.endif
+ addq $-(UREGS_error_code-UREGS_r15),%rsp
+ cld
+ movq %rdi,UREGS_rdi(%rsp)
+ movq %rsi,UREGS_rsi(%rsp)
+ movq %rdx,UREGS_rdx(%rsp)
+ movq %rcx,UREGS_rcx(%rsp)
+ movq %rax,UREGS_rax(%rsp)
+.if !\compat
+ movq %r8,UREGS_r8(%rsp)
+ movq %r9,UREGS_r9(%rsp)
+ movq %r10,UREGS_r10(%rsp)
+ movq %r11,UREGS_r11(%rsp)
+.endif
+ movq %rbx,UREGS_rbx(%rsp)
+ movq %rbp,UREGS_rbp(%rsp)
+ SETUP_EXCEPTION_FRAME_POINTER(UREGS_rbp)
+.endm
+
+/*
+ * Complete a frame potentially only partially saved.
+ */
+.macro SAVE_PRESERVED
+ btrl $_TRAP_regs_partial,UREGS_entry_vector(%rsp)
+ jnc 987f
+ movq %r12,UREGS_r12(%rsp)
+ movq %r13,UREGS_r13(%rsp)
+ movq %r14,UREGS_r14(%rsp)
+ movq %r15,UREGS_r15(%rsp)
+987:
+.endm
+
+/*
+ * Reload registers not preserved by C code from frame.
+ *
+ * @compat: R8-R11 don't need reloading
+ *
+ * For the way it is used in RESTORE_ALL, this macro must preserve EFLAGS.ZF.
+ */
+.macro LOAD_C_CLOBBERED compat=0
+.if !\compat
+ movq UREGS_r11(%rsp),%r11
+ movq UREGS_r10(%rsp),%r10
+ movq UREGS_r9(%rsp),%r9
+ movq UREGS_r8(%rsp),%r8
+.endif
+ movq UREGS_rax(%rsp),%rax
+ movq UREGS_rcx(%rsp),%rcx
+ movq UREGS_rdx(%rsp),%rdx
+ movq UREGS_rsi(%rsp),%rsi
+ movq UREGS_rdi(%rsp),%rdi
+.endm
+
+/*
+ * Restore all previously saved registers.
+ *
+ * @adj: extra stack pointer adjustment to be folded into the adjustment done
+ * anyway at the end of the macro
+ * @compat: R8-R15 don't need reloading
+ */
+.macro RESTORE_ALL adj=0 compat=0
+.if !\compat
+ testl $TRAP_regs_dirty,UREGS_entry_vector(%rsp)
+.endif
+ LOAD_C_CLOBBERED \compat
+.if !\compat
+ jz 987f
+ movq UREGS_r15(%rsp),%r15
+ movq UREGS_r14(%rsp),%r14
+ movq UREGS_r13(%rsp),%r13
+ movq UREGS_r12(%rsp),%r12
+#ifndef NDEBUG
+ .subsection 1
+987: testl $TRAP_regs_partial,UREGS_entry_vector(%rsp)
+ jnz 987f
+ cmpq UREGS_r15(%rsp),%r15
+ jne 789f
+ cmpq UREGS_r14(%rsp),%r14
+ jne 789f
+ cmpq UREGS_r13(%rsp),%r13
+ jne 789f
+ cmpq UREGS_r12(%rsp),%r12
+ je 987f
+789: ud2
+ .subsection 0
+#endif
+.endif
+987: movq UREGS_rbp(%rsp),%rbp
+ movq UREGS_rbx(%rsp),%rbx
+ subq $-(UREGS_error_code-UREGS_r15+\adj), %rsp
+.endm
+
+#endif
+
+#ifdef PERF_COUNTERS
+#define PERFC_INCR(_name,_idx,_cur) \
+ pushq _cur; \
+ movslq VCPU_processor(_cur),_cur; \
+ pushq %rdx; \
+ leaq __per_cpu_offset(%rip),%rdx; \
+ movq (%rdx,_cur,8),_cur; \
+ leaq per_cpu__perfcounters(%rip),%rdx; \
+ addq %rdx,_cur; \
+ popq %rdx; \
+ incl ASM_PERFC_##_name*4(_cur,_idx,4); \
+ popq _cur
+#else
+#define PERFC_INCR(_name,_idx,_cur)
+#endif
+
+/* Work around AMD erratum #88 */
+#define safe_swapgs \
+ "mfence; swapgs;"
+
+#ifdef __sun__
+#define REX64_PREFIX "rex64\\"
+#elif defined(__clang__)
+#define REX64_PREFIX ".byte 0x48; "
+#else
+#define REX64_PREFIX "rex64/"
+#endif
+
#endif /* __X86_ASM_DEFNS_H__ */
diff --git a/xen/include/asm-x86/atomic.h b/xen/include/asm-x86/atomic.h
index e476ab5..8972463 100644
--- a/xen/include/asm-x86/atomic.h
+++ b/xen/include/asm-x86/atomic.h
@@ -66,21 +66,50 @@ typedef struct { int counter; } atomic_t;
/**
* atomic_read - read atomic variable
* @v: pointer of type atomic_t
- *
+ *
* Atomically reads the value of @v.
*/
-#define _atomic_read(v) ((v).counter)
-#define atomic_read(v) read_atomic(&((v)->counter))
+static inline int atomic_read(atomic_t *v)
+{
+ return read_atomic(&v->counter);
+}
+
+/**
+ * _atomic_read - read atomic variable non-atomically
+ * @v atomic_t
+ *
+ * Non-atomically reads the value of @v
+ */
+static inline int _atomic_read(atomic_t v)
+{
+ return v.counter;
+}
+
/**
* atomic_set - set atomic variable
* @v: pointer of type atomic_t
* @i: required value
- *
+ *
* Atomically sets the value of @v to @i.
- */
-#define _atomic_set(v,i) (((v).counter) = (i))
-#define atomic_set(v,i) write_atomic(&((v)->counter), (i))
+ */
+static inline void atomic_set(atomic_t *v, int i)
+{
+ write_atomic(&v->counter, i);
+}
+
+/**
+ * _atomic_set - set atomic variable non-atomically
+ * @v: pointer of type atomic_t
+ * @i: required value
+ *
+ * Non-atomically sets the value of @v to @i.
+ */
+static inline void _atomic_set(atomic_t *v, int i)
+{
+ v->counter = i;
+}
+
/**
* atomic_add - add integer to atomic variable
diff --git a/xen/include/asm-x86/bitops.h b/xen/include/asm-x86/bitops.h
index ab21d92..82a08ee 100644
--- a/xen/include/asm-x86/bitops.h
+++ b/xen/include/asm-x86/bitops.h
@@ -335,23 +335,20 @@ static inline unsigned int __scanbit(unsigned long val, unsigned long max)
* @offset: The bitnumber to start searching at
* @size: The maximum size to search
*/
-#define find_next_bit(addr, size, off) ({ \
- unsigned int r__ = (size); \
- unsigned int o__ = (off); \
- switch ( -!__builtin_constant_p(size) | r__ ) \
- { \
- case 0: (void)(addr); break; \
- case 1 ... BITS_PER_LONG: \
- r__ = o__ + __scanbit(*(const unsigned long *)(addr) >> o__, r__); \
- break; \
- default: \
- if ( __builtin_constant_p(off) && !o__ ) \
- r__ = __find_first_bit(addr, r__); \
- else \
- r__ = __find_next_bit(addr, r__, o__); \
- break; \
- } \
- r__; \
+#define find_next_bit(addr, size, off) ({ \
+ unsigned int r__; \
+ const unsigned long *a__ = (addr); \
+ unsigned int s__ = (size); \
+ unsigned int o__ = (off); \
+ if ( __builtin_constant_p(size) && !s__ ) \
+ r__ = s__; \
+ else if ( __builtin_constant_p(size) && s__ <= BITS_PER_LONG ) \
+ r__ = o__ + __scanbit(*(const unsigned long *)(a__) >> o__, s__); \
+ else if ( __builtin_constant_p(off) && !o__ ) \
+ r__ = __find_first_bit(a__, s__); \
+ else \
+ r__ = __find_next_bit(a__, s__, o__); \
+ r__; \
})
/**
@@ -370,23 +367,20 @@ static inline unsigned int __scanbit(unsigned long val, unsigned long max)
* @offset: The bitnumber to start searching at
* @size: The maximum size to search
*/
-#define find_next_zero_bit(addr, size, off) ({ \
- unsigned int r__ = (size); \
- unsigned int o__ = (off); \
- switch ( -!__builtin_constant_p(size) | r__ ) \
- { \
- case 0: (void)(addr); break; \
- case 1 ... BITS_PER_LONG: \
- r__ = o__ + __scanbit(~*(const unsigned long *)(addr) >> o__, r__); \
- break; \
- default: \
- if ( __builtin_constant_p(off) && !o__ ) \
- r__ = __find_first_zero_bit(addr, r__); \
- else \
- r__ = __find_next_zero_bit(addr, r__, o__); \
- break; \
- } \
- r__; \
+#define find_next_zero_bit(addr, size, off) ({ \
+ unsigned int r__; \
+ const unsigned long *a__ = (addr); \
+ unsigned int s__ = (size); \
+ unsigned int o__ = (off); \
+ if ( __builtin_constant_p(size) && !s__ ) \
+ r__ = s__; \
+ else if ( __builtin_constant_p(size) && s__ <= BITS_PER_LONG ) \
+ r__ = o__ + __scanbit(~*(const unsigned long *)(a__) >> o__, s__); \
+ else if ( __builtin_constant_p(off) && !o__ ) \
+ r__ = __find_first_zero_bit(a__, s__); \
+ else \
+ r__ = __find_next_zero_bit(a__, s__, o__); \
+ r__; \
})
/**
diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h
index 99d0e2c..3802721 100644
--- a/xen/include/asm-x86/config.h
+++ b/xen/include/asm-x86/config.h
@@ -17,7 +17,6 @@
#define BITS_PER_XEN_ULONG BITS_PER_LONG
#define CONFIG_X86 1
-#define CONFIG_X86_HT 1
#define CONFIG_PAGING_ASSISTANCE 1
#define CONFIG_X86_LOCAL_APIC 1
#define CONFIG_X86_GOOD_APIC 1
@@ -52,6 +51,12 @@
#define CONFIG_KEXEC 1
#define CONFIG_WATCHDOG 1
+#define CONFIG_MULTIBOOT 1
+
+#ifdef XSM_ENABLE
+#define CONFIG_LATE_HWDOM 1
+#endif
+
#define HZ 100
#define OPT_CONSOLE_STR "vga"
@@ -101,6 +106,10 @@
/* Return value for zero-size _xmalloc(), distinguished from NULL. */
#define ZERO_BLOCK_PTR ((void *)0xBAD0BAD0BAD0BAD0UL)
+/* Override include/xen/list.h to make these non-canonical addresses. */
+#define LIST_POISON1 ((void *)0x0100100100100100UL)
+#define LIST_POISON2 ((void *)0x0200200200200200UL)
+
#ifndef __ASSEMBLY__
extern unsigned long trampoline_phys;
#define bootsym_phys(sym) \
diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h
index 526821f..d3bd14d 100644
--- a/xen/include/asm-x86/cpufeature.h
+++ b/xen/include/asm-x86/cpufeature.h
@@ -7,7 +7,9 @@
#ifndef __ASM_I386_CPUFEATURE_H
#define __ASM_I386_CPUFEATURE_H
+#ifndef __ASSEMBLY__
#include <xen/bitops.h>
+#endif
#define NCAPINTS 8 /* N 32-bit words worth of info */
@@ -57,10 +59,7 @@
#define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */
#define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */
-/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */
-#define X86_FEATURE_RECOVERY (2*32+ 0) /* CPU in recovery mode */
-#define X86_FEATURE_LONGRUN (2*32+ 1) /* Longrun power control */
-#define X86_FEATURE_LRTI (2*32+ 3) /* LongRun table interface */
+/* *** Available for re-use ***, word 2 */
/* Other features, Linux-defined mapping, word 3 */
/* This range is used for feature bits which conflict or are synthesized */
@@ -137,6 +136,7 @@
#define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */
#define X86_FEATURE_TBM (6*32+21) /* trailing bit manipulations */
#define X86_FEATURE_TOPOEXT (6*32+22) /* topology extensions CPUID leafs */
+#define X86_FEATURE_DBEXT (6*32+26) /* data breakpoint extension */
/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 7 */
#define X86_FEATURE_FSGSBASE (7*32+ 0) /* {RD,WR}{FS,GS}BASE instructions */
@@ -148,9 +148,14 @@
#define X86_FEATURE_ERMS (7*32+ 9) /* Enhanced REP MOVSB/STOSB */
#define X86_FEATURE_INVPCID (7*32+10) /* Invalidate Process Context ID */
#define X86_FEATURE_RTM (7*32+11) /* Restricted Transactional Memory */
+#define X86_FEATURE_CMT (7*32+12) /* Cache Monitoring Technology */
#define X86_FEATURE_NO_FPU_SEL (7*32+13) /* FPU CS/DS stored as zero */
+#define X86_FEATURE_MPX (7*32+14) /* Memory Protection Extensions */
+#define X86_FEATURE_RDSEED (7*32+18) /* RDSEED instruction */
+#define X86_FEATURE_ADX (7*32+19) /* ADCX, ADOX instructions */
#define X86_FEATURE_SMAP (7*32+20) /* Supervisor Mode Access Prevention */
+#ifndef __ASSEMBLY__
#define cpu_has(c, bit) test_bit(bit, (c)->x86_capability)
#define boot_cpu_has(bit) test_bit(bit, boot_cpu_data.x86_capability)
#define cpufeat_mask(idx) (1u << ((idx) & 31))
@@ -186,6 +191,7 @@
#define cpu_has_fsgsbase boot_cpu_has(X86_FEATURE_FSGSBASE)
#define cpu_has_smep boot_cpu_has(X86_FEATURE_SMEP)
+#define cpu_has_smap boot_cpu_has(X86_FEATURE_SMAP)
#define cpu_has_fpu_sel (!boot_cpu_has(X86_FEATURE_NO_FPU_SEL))
#define cpu_has_ffxsr ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) \
@@ -198,6 +204,7 @@
#define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE)
#define cpu_has_avx boot_cpu_has(X86_FEATURE_AVX)
#define cpu_has_lwp boot_cpu_has(X86_FEATURE_LWP)
+#define cpu_has_mpx boot_cpu_has(X86_FEATURE_MPX)
#define cpu_has_arch_perfmon boot_cpu_has(X86_FEATURE_ARCH_PERFMON)
@@ -209,6 +216,52 @@
#define cpu_has_cpuid_faulting boot_cpu_has(X86_FEATURE_CPUID_FAULTING)
+enum _cache_type {
+ CACHE_TYPE_NULL = 0,
+ CACHE_TYPE_DATA = 1,
+ CACHE_TYPE_INST = 2,
+ CACHE_TYPE_UNIFIED = 3
+};
+
+union _cpuid4_leaf_eax {
+ struct {
+ enum _cache_type type:5;
+ unsigned int level:3;
+ unsigned int is_self_initializing:1;
+ unsigned int is_fully_associative:1;
+ unsigned int reserved:4;
+ unsigned int num_threads_sharing:12;
+ unsigned int num_cores_on_die:6;
+ } split;
+ u32 full;
+};
+
+union _cpuid4_leaf_ebx {
+ struct {
+ unsigned int coherency_line_size:12;
+ unsigned int physical_line_partition:10;
+ unsigned int ways_of_associativity:10;
+ } split;
+ u32 full;
+};
+
+union _cpuid4_leaf_ecx {
+ struct {
+ unsigned int number_of_sets:32;
+ } split;
+ u32 full;
+};
+
+struct cpuid4_info {
+ union _cpuid4_leaf_eax eax;
+ union _cpuid4_leaf_ebx ebx;
+ union _cpuid4_leaf_ecx ecx;
+ unsigned long size;
+};
+
+int cpuid4_cache_lookup(int index, struct cpuid4_info *this_leaf);
+#endif
+
#endif /* __ASM_I386_CPUFEATURE_H */
/*
diff --git a/xen/include/asm-x86/current.h b/xen/include/asm-x86/current.h
index c2792ce..b95fd79 100644
--- a/xen/include/asm-x86/current.h
+++ b/xen/include/asm-x86/current.h
@@ -25,9 +25,9 @@ struct cpu_info {
static inline struct cpu_info *get_cpu_info(void)
{
- unsigned long tos;
- __asm__ ( "and %%rsp,%0" : "=r" (tos) : "0" (~(STACK_SIZE-1)) );
- return (struct cpu_info *)(tos + STACK_SIZE) - 1;
+ register unsigned long sp asm("rsp");
+
+ return (struct cpu_info *)((sp & ~(STACK_SIZE-1)) + STACK_SIZE) - 1;
}
#define get_current() (get_cpu_info()->current_vcpu)
@@ -59,12 +59,23 @@ static inline struct cpu_info *get_cpu_info(void)
((sp & (~(STACK_SIZE-1))) + \
(STACK_SIZE - sizeof(struct cpu_info) - sizeof(unsigned long)))
-#define reset_stack_and_jump(__fn) \
- __asm__ __volatile__ ( \
- "mov %0,%%"__OP"sp; jmp %c1" \
- : : "r" (guest_cpu_user_regs()), "i" (__fn) : "memory" )
+#define reset_stack_and_jump(__fn) \
+ ({ \
+ __asm__ __volatile__ ( \
+ "mov %0,%%"__OP"sp; jmp %c1" \
+ : : "r" (guest_cpu_user_regs()), "i" (__fn) : "memory" ); \
+ unreachable(); \
+ })
-#define schedule_tail(vcpu) (((vcpu)->arch.schedule_tail)(vcpu))
+/*
+ * Schedule tail *should* be a terminal function pointer, but leave a bugframe
+ * around just incase it returns, to save going back into the context
+ * switching code and leaving a far more subtle crash to diagnose.
+ */
+#define schedule_tail(vcpu) do { \
+ (((vcpu)->arch.schedule_tail)(vcpu)); \
+ BUG(); \
+ } while (0)
/*
* Which VCPU's state is currently running on each CPU?
diff --git a/xen/include/asm-x86/debugreg.h b/xen/include/asm-x86/debugreg.h
index 24021b8..a5b2838 100644
--- a/xen/include/asm-x86/debugreg.h
+++ b/xen/include/asm-x86/debugreg.h
@@ -20,6 +20,7 @@
#define DR_TRAP3 (0x8) /* db3 */
#define DR_STEP (0x4000) /* single-step */
#define DR_SWITCH (0x8000) /* task switch */
+#define DR_NOT_RTM (0x10000) /* clear: #BP inside RTM region */
/* Now define a bunch of things for manipulating the control register.
The top two bytes of the control register consist of 4 fields of 4
@@ -62,6 +63,19 @@
#define DR_CONTROL_RESERVED_ONE (0x00000400ul) /* Reserved, read as one */
#define DR_LOCAL_EXACT_ENABLE (0x00000100ul) /* Local exact enable */
#define DR_GLOBAL_EXACT_ENABLE (0x00000200ul) /* Global exact enable */
+#define DR_RTM_ENABLE (0x00000800ul) /* RTM debugging enable */
#define DR_GENERAL_DETECT (0x00002000ul) /* General detect enable */
+#define write_debugreg(reg, val) do { \
+ unsigned long __val = val; \
+ asm volatile ( "mov %0,%%db" #reg : : "r" (__val) ); \
+} while (0)
+#define read_debugreg(reg) ({ \
+ unsigned long __val; \
+ asm volatile ( "mov %%db" #reg ",%0" : "=r" (__val) ); \
+ __val; \
+})
+long set_debugreg(struct vcpu *, unsigned int reg, unsigned long value);
+void activate_debugregs(const struct vcpu *);
+
#endif /* _X86_DEBUGREG_H */
diff --git a/xen/include/asm-x86/desc.h b/xen/include/asm-x86/desc.h
index 354b889..225913a 100644
--- a/xen/include/asm-x86/desc.h
+++ b/xen/include/asm-x86/desc.h
@@ -98,6 +98,14 @@
#ifndef __ASSEMBLY__
+/* System Descriptor types for GDT and IDT entries. */
+#define SYS_DESC_ldt 2
+#define SYS_DESC_tss_avail 9
+#define SYS_DESC_tss_busy 11
+#define SYS_DESC_call_gate 12
+#define SYS_DESC_irq_gate 14
+#define SYS_DESC_trap_gate 15
+
struct desc_struct {
u32 a, b;
};
@@ -181,17 +189,16 @@ do { \
(((u32)(addr) & 0x00FF0000U) >> 16); \
} while (0)
-struct desc_ptr {
+struct __packed desc_ptr {
unsigned short limit;
unsigned long base;
-} __attribute__((__packed__)) ;
+};
extern struct desc_struct boot_cpu_gdt_table[];
DECLARE_PER_CPU(struct desc_struct *, gdt_table);
extern struct desc_struct boot_cpu_compat_gdt_table[];
DECLARE_PER_CPU(struct desc_struct *, compat_gdt_table);
-extern void set_intr_gate(unsigned int irq, void * addr);
extern void load_TR(void);
#endif /* !__ASSEMBLY__ */
diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
index 4ff89f0..6a77a93 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -19,6 +19,7 @@
#define is_hvm_pv_evtchn_domain(d) (has_hvm_container_domain(d) && \
d->arch.hvm_domain.irq.callback_via_type == HVMIRQ_callback_vector)
#define is_hvm_pv_evtchn_vcpu(v) (is_hvm_pv_evtchn_domain(v->domain))
+#define is_domain_direct_mapped(d) ((void)(d), 0)
#define VCPU_TRAP_NMI 1
#define VCPU_TRAP_MCE 2
@@ -186,6 +187,20 @@ struct paging_domain {
struct hap_domain hap;
/* log dirty support */
struct log_dirty_domain log_dirty;
+
+ /* preemption handling */
+ struct {
+ const struct domain *dom;
+ unsigned int op;
+ union {
+ struct {
+ unsigned long done:PADDR_BITS - PAGE_SHIFT;
+ unsigned long i4:PAGETABLE_ORDER;
+ unsigned long i3:PAGETABLE_ORDER;
+ } log_dirty;
+ };
+ } preempt;
+
/* alloc/free pages from the pool for paging-assistance structures
* (used by p2m and log-dirty code for their tries) */
struct page_info * (*alloc_page)(struct domain *d);
@@ -225,13 +240,6 @@ struct pv_domain
{
l1_pgentry_t **gdt_ldt_l1tab;
- /* Shared page for notifying that explicit PIRQ EOI is required. */
- unsigned long *pirq_eoi_map;
- unsigned long pirq_eoi_map_mfn;
- /* set auto_unmask to 1 if you want PHYSDEVOP_eoi to automatically
- * unmask the event channel */
- bool_t auto_unmask;
-
/* map_domain_page() mapping cache. */
struct mapcache_domain mapcache;
};
@@ -313,6 +321,15 @@ struct arch_domain
spinlock_t e820_lock;
struct e820entry *e820;
unsigned int nr_e820;
+
+ /* set auto_unmask to 1 if you want PHYSDEVOP_eoi to automatically
+ * unmask the event channel */
+ bool_t auto_unmask;
+ /* Shared page for notifying that explicit PIRQ EOI is required. */
+ unsigned long *pirq_eoi_map;
+ unsigned long pirq_eoi_map_mfn;
+
+ unsigned int psr_rmid; /* RMID assigned to the domain for CMT */
} __cacheline_aligned;
#define has_arch_pdevs(d) (!list_empty(&(d)->arch.pdev_list))
@@ -374,11 +391,20 @@ struct pv_vcpu
unsigned long shadow_ldt_mapcnt;
spinlock_t shadow_ldt_lock;
+ /* data breakpoint extension MSRs */
+ uint32_t dr_mask[4];
+
/* Deferred VA-based update state. */
bool_t need_update_runstate_area;
struct vcpu_time_info pending_system_time;
};
+typedef enum __packed {
+ SMAP_CHECK_HONOR_CPL_AC, /* honor the guest's CPL and AC */
+ SMAP_CHECK_ENABLED, /* enable the check */
+ SMAP_CHECK_DISABLED, /* disable the check */
+} smap_check_policy_t;
+
struct arch_vcpu
{
/*
@@ -435,6 +461,12 @@ struct arch_vcpu
* and thus should be saved/restored. */
bool_t nonlazy_xstate_used;
+ /*
+ * The SMAP check policy when updating runstate_guest(v) and the
+ * secondary system time.
+ */
+ smap_check_policy_t smap_check_policy;
+
struct vmce vmce;
struct paging_vcpu paging;
@@ -443,14 +475,28 @@ struct arch_vcpu
/* A secondary copy of the vcpu time info. */
XEN_GUEST_HANDLE(vcpu_time_info_t) time_info_guest;
+
+ /*
+ * Should we emulate the next matching instruction on VCPU resume
+ * after a mem_event?
+ */
+ struct {
+ uint32_t emulate_flags;
+ unsigned long gpa;
+ unsigned long eip;
+ } mem_event;
+
} __cacheline_aligned;
+smap_check_policy_t smap_policy_change(struct vcpu *v,
+ smap_check_policy_t new_policy);
+
/* Shorthands to improve code legibility. */
#define hvm_vmx hvm_vcpu.u.vmx
#define hvm_svm hvm_vcpu.u.svm
-bool_t update_runstate_area(const struct vcpu *);
-bool_t update_secondary_system_time(const struct vcpu *,
+bool_t update_runstate_area(struct vcpu *);
+bool_t update_secondary_system_time(struct vcpu *,
struct vcpu_time_info *);
void vcpu_show_execution_state(struct vcpu *);
@@ -464,12 +510,14 @@ unsigned long pv_guest_cr4_fixup(const struct vcpu *, unsigned long guest_cr4);
(((v)->arch.pv_vcpu.ctrlreg[4] \
| (mmu_cr4_features \
& (X86_CR4_PGE | X86_CR4_PSE | X86_CR4_SMEP | \
- X86_CR4_OSXSAVE | X86_CR4_FSGSBASE)) \
+ X86_CR4_SMAP | X86_CR4_OSXSAVE | \
+ X86_CR4_FSGSBASE)) \
| ((v)->domain->arch.vtsc ? X86_CR4_TSD : 0)) \
& ~X86_CR4_DE)
#define real_cr4_to_pv_guest_cr4(c) \
((c) & ~(X86_CR4_PGE | X86_CR4_PSE | X86_CR4_TSD | \
- X86_CR4_OSXSAVE | X86_CR4_SMEP | X86_CR4_FSGSBASE))
+ X86_CR4_OSXSAVE | X86_CR4_SMEP | \
+ X86_CR4_FSGSBASE | X86_CR4_SMAP))
void domain_cpuid(struct domain *d,
unsigned int input,
diff --git a/xen/include/asm-x86/e820.h b/xen/include/asm-x86/e820.h
index 0fd81f6..d9ff4eb 100644
--- a/xen/include/asm-x86/e820.h
+++ b/xen/include/asm-x86/e820.h
@@ -10,16 +10,16 @@
#define E820_NVS 4
#define E820_UNUSABLE 5
-struct e820entry {
+struct __packed e820entry {
uint64_t addr;
uint64_t size;
uint32_t type;
-} __attribute__((packed));
+};
#define E820MAX 128
struct e820map {
- int nr_map;
+ unsigned int nr_map;
struct e820entry map[E820MAX];
};
@@ -30,12 +30,12 @@ extern int e820_change_range_type(
uint32_t orig_type, uint32_t new_type);
extern int e820_add_range(
struct e820map *, uint64_t s, uint64_t e, uint32_t type);
-extern unsigned long init_e820(const char *, struct e820entry *, int *);
+extern unsigned long init_e820(const char *, struct e820entry *, unsigned int *);
extern struct e820map e820;
/* These symbols live in the boot trampoline. */
extern struct e820entry e820map[];
-extern int e820nr;
+extern unsigned int e820nr;
extern unsigned int lowmem_kb, highmem_kb;
#define e820_raw bootsym(e820map)
diff --git a/xen/include/asm-x86/edd.h b/xen/include/asm-x86/edd.h
index 5544ba5..afaa237 100644
--- a/xen/include/asm-x86/edd.h
+++ b/xen/include/asm-x86/edd.h
@@ -25,7 +25,7 @@
#ifndef __ASSEMBLY__
-struct edd_info {
+struct __packed edd_info {
/* Int13, Fn48: Check Extensions Present. */
u8 device; /* %dl: device */
u8 version; /* %ah: major version */
@@ -35,7 +35,7 @@ struct edd_info {
u8 legacy_max_head; /* %dh: maximum head number */
u8 legacy_sectors_per_track; /* %cl[5:0]: maximum sector number */
/* Int13, Fn41: Get Device Parameters (as filled into %ds:%esi). */
- struct edd_device_params {
+ struct __packed edd_device_params {
u16 length;
u16 info_flags;
u32 num_default_cylinders;
@@ -51,97 +51,97 @@ struct edd_info {
u8 host_bus_type[4];
u8 interface_type[8];
union {
- struct {
+ struct __packed {
u16 base_address;
u16 reserved1;
u32 reserved2;
- } __attribute__ ((packed)) isa;
- struct {
+ } isa;
+ struct __packed {
u8 bus;
u8 slot;
u8 function;
u8 channel;
u32 reserved;
- } __attribute__ ((packed)) pci;
+ } pci;
/* pcix is same as pci */
- struct {
+ struct __packed {
u64 reserved;
- } __attribute__ ((packed)) ibnd;
- struct {
+ } ibnd;
+ struct __packed {
u64 reserved;
- } __attribute__ ((packed)) xprs;
- struct {
+ } xprs;
+ struct __packed {
u64 reserved;
- } __attribute__ ((packed)) htpt;
- struct {
+ } htpt;
+ struct __packed {
u64 reserved;
- } __attribute__ ((packed)) unknown;
+ } unknown;
} interface_path;
union {
- struct {
+ struct __packed {
u8 device;
u8 reserved1;
u16 reserved2;
u32 reserved3;
u64 reserved4;
- } __attribute__ ((packed)) ata;
- struct {
+ } ata;
+ struct __packed {
u8 device;
u8 lun;
u8 reserved1;
u8 reserved2;
u32 reserved3;
u64 reserved4;
- } __attribute__ ((packed)) atapi;
- struct {
+ } atapi;
+ struct __packed {
u16 id;
u64 lun;
u16 reserved1;
u32 reserved2;
- } __attribute__ ((packed)) scsi;
- struct {
+ } scsi;
+ struct __packed {
u64 serial_number;
u64 reserved;
- } __attribute__ ((packed)) usb;
- struct {
+ } usb;
+ struct __packed {
u64 eui;
u64 reserved;
- } __attribute__ ((packed)) i1394;
- struct {
+ } i1394;
+ struct __packed {
u64 wwid;
u64 lun;
- } __attribute__ ((packed)) fibre;
- struct {
+ } fibre;
+ struct __packed {
u64 identity_tag;
u64 reserved;
- } __attribute__ ((packed)) i2o;
- struct {
+ } i2o;
+ struct __packed {
u32 array_number;
u32 reserved1;
u64 reserved2;
- } __attribute__ ((packed)) raid;
- struct {
+ } raid;
+ struct __packed {
u8 device;
u8 reserved1;
u16 reserved2;
u32 reserved3;
u64 reserved4;
- } __attribute__ ((packed)) sata;
- struct {
+ } sata;
+ struct __packed {
u64 reserved1;
u64 reserved2;
- } __attribute__ ((packed)) unknown;
+ } unknown;
} device_path;
u8 reserved4;
u8 checksum;
- } __attribute__ ((packed)) edd_device_params;
-} __attribute__ ((packed));
+ } edd_device_params;
+};
-struct mbr_signature {
+struct __packed mbr_signature {
u8 device;
u8 pad[3];
u32 signature;
-} __attribute__ ((packed));
+};
/* These all reside in the boot trampoline. Access via bootsym(). */
extern struct mbr_signature boot_mbr_signature[];
diff --git a/xen/include/asm-x86/fixmap.h b/xen/include/asm-x86/fixmap.h
index 48c5676..ebb3207 100644
--- a/xen/include/asm-x86/fixmap.h
+++ b/xen/include/asm-x86/fixmap.h
@@ -62,7 +62,6 @@ enum fixed_addresses {
FIX_TBOOT_MAP_ADDRESS,
FIX_APEI_RANGE_BASE,
FIX_APEI_RANGE_END = FIX_APEI_RANGE_BASE + FIX_APEI_RANGE_MAX -1,
- FIX_IGD_MMIO,
FIX_EFI_MPF,
__end_of_fixed_addresses
};
diff --git a/xen/include/asm-x86/flushtlb.h b/xen/include/asm-x86/flushtlb.h
index 7f46632..8dbe2d6 100644
--- a/xen/include/asm-x86/flushtlb.h
+++ b/xen/include/asm-x86/flushtlb.h
@@ -11,6 +11,7 @@
#define __FLUSHTLB_H__
#include <xen/config.h>
+#include <xen/mm.h>
#include <xen/percpu.h>
#include <xen/smp.h>
#include <xen/types.h>
@@ -115,4 +116,21 @@ void flush_area_mask(const cpumask_t *, const void *va, unsigned int flags);
#define flush_tlb_one_all(v) \
flush_tlb_one_mask(&cpu_online_map, v)
+static inline void flush_page_to_ram(unsigned long mfn) {}
+static inline int invalidate_dcache_va_range(const void *p,
+ unsigned long size)
+{ return -EOPNOTSUPP; }
+static inline int clean_and_invalidate_dcache_va_range(const void *p,
+ unsigned long size)
+{
+ unsigned int order = get_order_from_bytes(size);
+ /* sub-page granularity support needs to be added if necessary */
+ flush_area_local(p, FLUSH_CACHE|FLUSH_ORDER(order));
+ return 0;
+}
+static inline int clean_dcache_va_range(const void *p, unsigned long size)
+{
+ return clean_and_invalidate_dcache_va_range(p, size);
+}
+
#endif /* __FLUSHTLB_H__ */
diff --git a/xen/include/asm-x86/genapic.h b/xen/include/asm-x86/genapic.h
index ad2a4fb..5496ab0 100644
--- a/xen/include/asm-x86/genapic.h
+++ b/xen/include/asm-x86/genapic.h
@@ -37,7 +37,7 @@ struct genapic {
const cpumask_t *(*vector_allocation_cpumask)(int cpu);
unsigned int (*cpu_mask_to_apicid)(const cpumask_t *cpumask);
void (*send_IPI_mask)(const cpumask_t *mask, int vector);
- void (*send_IPI_self)(int vector);
+ void (*send_IPI_self)(uint8_t vector);
};
#define APICFUNC(x) .x = x
@@ -52,12 +52,12 @@ extern const struct genapic *genapic;
extern const struct genapic apic_default;
const cpumask_t *target_cpus_all(void);
+void send_IPI_self_legacy(uint8_t vector);
void init_apic_ldr_flat(void);
void clustered_apic_check_flat(void);
unsigned int cpu_mask_to_apicid_flat(const cpumask_t *cpumask);
void send_IPI_mask_flat(const cpumask_t *mask, int vector);
-void send_IPI_self_flat(int vector);
const cpumask_t *vector_allocation_cpumask_flat(int cpu);
#define GENAPIC_FLAT \
.int_delivery_mode = dest_LowestPrio, \
@@ -68,13 +68,12 @@ const cpumask_t *vector_allocation_cpumask_flat(int cpu);
.vector_allocation_cpumask = vector_allocation_cpumask_flat, \
.cpu_mask_to_apicid = cpu_mask_to_apicid_flat, \
.send_IPI_mask = send_IPI_mask_flat, \
- .send_IPI_self = send_IPI_self_flat
+ .send_IPI_self = send_IPI_self_legacy
void init_apic_ldr_phys(void);
void clustered_apic_check_phys(void);
unsigned int cpu_mask_to_apicid_phys(const cpumask_t *cpumask);
void send_IPI_mask_phys(const cpumask_t *mask, int vector);
-void send_IPI_self_phys(int vector);
const cpumask_t *vector_allocation_cpumask_phys(int cpu);
#define GENAPIC_PHYS \
.int_delivery_mode = dest_Fixed, \
@@ -85,8 +84,6 @@ const cpumask_t *vector_allocation_cpumask_phys(int cpu);
.vector_allocation_cpumask = vector_allocation_cpumask_phys, \
.cpu_mask_to_apicid = cpu_mask_to_apicid_phys, \
.send_IPI_mask = send_IPI_mask_phys, \
- .send_IPI_self = send_IPI_self_phys
-
-void send_IPI_self_x2apic(int vector);
+ .send_IPI_self = send_IPI_self_legacy
#endif
diff --git a/xen/include/asm-x86/grant_table.h b/xen/include/asm-x86/grant_table.h
index 3013869..8c9bbcf 100644
--- a/xen/include/asm-x86/grant_table.h
+++ b/xen/include/asm-x86/grant_table.h
@@ -65,6 +65,9 @@ static inline void gnttab_clear_flag(unsigned int nr, uint16_t *st)
/* Done implicitly when page tables are destroyed. */
#define gnttab_release_host_mappings(domain) ( paging_mode_external(domain) )
+#define gnttab_need_iommu_mapping(d) \
+ (!paging_mode_translate(d) && need_iommu(d))
+
static inline int replace_grant_supported(void)
{
return 1;
diff --git a/xen/include/asm-x86/hap.h b/xen/include/asm-x86/hap.h
index e03f983..7876527 100644
--- a/xen/include/asm-x86/hap.h
+++ b/xen/include/asm-x86/hap.h
@@ -56,13 +56,13 @@ int hap_enable(struct domain *d, u32 mode);
void hap_final_teardown(struct domain *d);
void hap_teardown(struct domain *d);
void hap_vcpu_init(struct vcpu *v);
-void hap_logdirty_init(struct domain *d);
int hap_track_dirty_vram(struct domain *d,
unsigned long begin_pfn,
unsigned long nr,
XEN_GUEST_HANDLE_64(uint8) dirty_bitmap);
extern const struct paging_mode *hap_paging_get_mode(struct vcpu *);
+void hap_set_alloc_for_pvh_dom0(struct domain *d, unsigned long num_pages);
#endif /* XEN_HAP_H */
diff --git a/xen/include/asm-x86/hvm/cacheattr.h b/xen/include/asm-x86/hvm/cacheattr.h
index 371ce95..ab1ccef 100644
--- a/xen/include/asm-x86/hvm/cacheattr.h
+++ b/xen/include/asm-x86/hvm/cacheattr.h
@@ -1,12 +1,6 @@
#ifndef __HVM_CACHEATTR_H__
#define __HVM_CACHEATTR_H__
-struct hvm_mem_pinned_cacheattr_range {
- struct list_head list;
- uint64_t start, end;
- uint32_t type;
-};
-
void hvm_init_cacheattr_region_list(
struct domain *d);
void hvm_destroy_cacheattr_region_list(
@@ -15,11 +9,13 @@ void hvm_destroy_cacheattr_region_list(
/*
* To see guest_fn is in the pinned range or not,
* if yes, return 1, and set type to value in this range
- * if no, return 0, and set type to 0
+ * if no, return 0, setting type to ~0
+ * if ambiguous, return -1, setting type to ~0 (possible only for order > 0)
*/
-int32_t hvm_get_mem_pinned_cacheattr(
+int hvm_get_mem_pinned_cacheattr(
struct domain *d,
uint64_t guest_fn,
+ unsigned int order,
uint32_t *type);
diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h
index b1e3187..2757c7f 100644
--- a/xen/include/asm-x86/hvm/domain.h
+++ b/xen/include/asm-x86/hvm/domain.h
@@ -34,16 +34,61 @@
#include <public/grant_table.h>
#include <public/hvm/params.h>
#include <public/hvm/save.h>
+#include <public/hvm/hvm_op.h>
struct hvm_ioreq_page {
- spinlock_t lock;
+ unsigned long gmfn;
struct page_info *page;
void *va;
};
-struct hvm_domain {
+struct hvm_ioreq_vcpu {
+ struct list_head list_entry;
+ struct vcpu *vcpu;
+ evtchn_port_t ioreq_evtchn;
+};
+
+#define NR_IO_RANGE_TYPES (HVMOP_IO_RANGE_PCI + 1)
+#define MAX_NR_IO_RANGES 256
+
+struct hvm_ioreq_server {
+ struct list_head list_entry;
+ struct domain *domain;
+
+ /* Lock to serialize toolstack modifications */
+ spinlock_t lock;
+
+ /* Domain id of emulating domain */
+ domid_t domid;
+ ioservid_t id;
struct hvm_ioreq_page ioreq;
- struct hvm_ioreq_page buf_ioreq;
+ struct list_head ioreq_vcpu_list;
+ struct hvm_ioreq_page bufioreq;
+
+ /* Lock to serialize access to buffered ioreq ring */
+ spinlock_t bufioreq_lock;
+ evtchn_port_t bufioreq_evtchn;
+ struct rangeset *range[NR_IO_RANGE_TYPES];
+ bool_t enabled;
+};
+
+struct hvm_domain {
+ /* Guest page range used for non-default ioreq servers */
+ struct {
+ unsigned long base;
+ unsigned long mask;
+ } ioreq_gmfn;
+
+ /* Lock protects all other values in the sub-struct and the default */
+ struct {
+ spinlock_t lock;
+ ioservid_t id;
+ struct list_head list;
+ } ioreq_server;
+ struct hvm_ioreq_server *default_ioreq_server;
+
+ /* Cached CF8 for guest PCI config cycles */
+ uint32_t pci_cf8;
struct pl_time pl_time;
@@ -67,7 +112,7 @@ struct hvm_domain {
/* Memory ranges with pinned cache attributes. */
struct list_head pinned_cacheattr_ranges;
- /* VRAM dirty support. */
+ /* VRAM dirty support. Protect with the domain paging lock. */
struct sh_dirty_vram *dirty_vram;
/* If one of vcpus of this domain is in no_fill_mode or
@@ -89,6 +134,13 @@ struct hvm_domain {
bool_t mem_sharing_enabled;
bool_t qemu_mapcache_invalidate;
bool_t is_s3_suspended;
+ bool_t introspection_enabled;
+
+ /*
+ * TSC value that VCPUs use to calculate their tsc_offset value.
+ * Used during initialization and save/restore.
+ */
+ uint64_t sync_tsc;
union {
struct vmx_domain vmx;
@@ -100,3 +152,12 @@ struct hvm_domain {
#endif /* __ASM_X86_HVM_DOMAIN_H__ */
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-x86/hvm/emulate.h b/xen/include/asm-x86/hvm/emulate.h
index 00a06cc..5411302 100644
--- a/xen/include/asm-x86/hvm/emulate.h
+++ b/xen/include/asm-x86/hvm/emulate.h
@@ -13,6 +13,7 @@
#define __ASM_X86_HVM_EMULATE_H__
#include <xen/config.h>
+#include <asm/hvm/hvm.h>
#include <asm/x86_emulate.h>
struct hvm_emulate_ctxt {
@@ -28,15 +29,18 @@ struct hvm_emulate_ctxt {
unsigned long seg_reg_dirty;
bool_t exn_pending;
- uint8_t exn_vector;
- uint8_t exn_insn_len;
- int32_t exn_error_code;
+ struct hvm_trap trap;
uint32_t intr_shadow;
};
int hvm_emulate_one(
struct hvm_emulate_ctxt *hvmemul_ctxt);
+int hvm_emulate_one_no_write(
+ struct hvm_emulate_ctxt *hvmemul_ctxt);
+void hvm_mem_event_emulate_one(bool_t nowrite,
+ unsigned int trapnr,
+ unsigned int errcode);
void hvm_emulate_prepare(
struct hvm_emulate_ctxt *hvmemul_ctxt,
struct cpu_user_regs *regs);
@@ -50,4 +54,7 @@ int hvmemul_do_pio(
unsigned long port, unsigned long *reps, int size,
paddr_t ram_gpa, int dir, int df, void *p_data);
+void hvm_dump_emulation_state(const char *prefix,
+ struct hvm_emulate_ctxt *hvmemul_ctxt);
+
#endif /* __ASM_X86_HVM_EMULATE_H__ */
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index 974bcc0..e3d2d9a 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -26,7 +26,8 @@
#include <asm/hvm/asid.h>
#include <public/domctl.h>
#include <public/hvm/save.h>
-#include <asm/mm.h>
+#include <public/hvm/ioreq.h>
+#include <xen/mm.h>
/* Interrupt acknowledgement sources. */
enum hvm_intsrc {
@@ -109,6 +110,10 @@ struct hvm_function_table {
void (*save_cpu_ctxt)(struct vcpu *v, struct hvm_hw_cpu *ctxt);
int (*load_cpu_ctxt)(struct vcpu *v, struct hvm_hw_cpu *ctxt);
+ unsigned int (*init_msr)(void);
+ void (*save_msr)(struct vcpu *, struct hvm_msr *);
+ int (*load_msr)(struct vcpu *, struct hvm_msr *);
+
/* Examine specifics of the guest state. */
unsigned int (*get_interrupt_shadow)(struct vcpu *v);
void (*set_interrupt_shadow)(struct vcpu *v, unsigned int intr_shadow);
@@ -133,7 +138,7 @@ struct hvm_function_table {
int (*get_guest_pat)(struct vcpu *v, u64 *);
int (*set_guest_pat)(struct vcpu *v, u64);
- void (*set_tsc_offset)(struct vcpu *v, u64 offset);
+ void (*set_tsc_offset)(struct vcpu *v, u64 offset, u64 at_tsc);
void (*inject_trap)(struct hvm_trap *trap);
@@ -196,6 +201,12 @@ struct hvm_function_table {
paddr_t *L1_gpa, unsigned int *page_order,
uint8_t *p2m_acc, bool_t access_r,
bool_t access_w, bool_t access_x);
+
+ void (*hypervisor_cpuid_leaf)(uint32_t sub_idx,
+ uint32_t *eax, uint32_t *ebx,
+ uint32_t *ecx, uint32_t *edx);
+
+ void (*enable_msr_exit_interception)(struct domain *d);
};
extern struct hvm_function_table hvm_funcs;
@@ -217,23 +228,21 @@ int hvm_vcpu_cacheattr_init(struct vcpu *v);
void hvm_vcpu_cacheattr_destroy(struct vcpu *v);
void hvm_vcpu_reset_state(struct vcpu *v, uint16_t cs, uint16_t ip);
-/* Prepare/destroy a ring for a dom0 helper. Helper with talk
- * with Xen on behalf of this hvm domain. */
-int prepare_ring_for_helper(struct domain *d, unsigned long gmfn,
- struct page_info **_page, void **_va);
-void destroy_ring_for_helper(void **_va, struct page_info *page);
-
-bool_t hvm_send_assist_req(struct vcpu *v);
+bool_t hvm_send_assist_req(ioreq_t *p);
+void hvm_broadcast_assist_req(ioreq_t *p);
void hvm_get_guest_pat(struct vcpu *v, u64 *guest_pat);
int hvm_set_guest_pat(struct vcpu *v, u64 guest_pat);
-void hvm_set_guest_tsc(struct vcpu *v, u64 guest_tsc);
-u64 hvm_get_guest_tsc(struct vcpu *v);
+void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc);
+#define hvm_set_guest_tsc(v, t) hvm_set_guest_tsc_fixed(v, t, 0)
+u64 hvm_get_guest_tsc_fixed(struct vcpu *v, u64 at_tsc);
+#define hvm_get_guest_tsc(v) hvm_get_guest_tsc_fixed(v, 0)
void hvm_init_guest_time(struct domain *d);
void hvm_set_guest_time(struct vcpu *v, u64 guest_time);
-u64 hvm_get_guest_time(struct vcpu *v);
+u64 hvm_get_guest_time_fixed(struct vcpu *v, u64 at_tsc);
+#define hvm_get_guest_time(v) hvm_get_guest_time_fixed(v, 0)
int vmsi_deliver(
struct domain *d, int vector,
@@ -253,6 +262,8 @@ int hvm_girq_dest_2_vcpu_id(struct domain *d, uint8_t dest, uint8_t dest_mode);
(hvm_paging_enabled(v) && ((v)->arch.hvm_vcpu.guest_cr[4] & X86_CR4_PAE))
#define hvm_smep_enabled(v) \
(hvm_paging_enabled(v) && ((v)->arch.hvm_vcpu.guest_cr[4] & X86_CR4_SMEP))
+#define hvm_smap_enabled(v) \
+ (hvm_paging_enabled(v) && ((v)->arch.hvm_vcpu.guest_cr[4] & X86_CR4_SMAP))
#define hvm_nx_enabled(v) \
(!!((v)->arch.hvm_vcpu.guest_efer & EFER_NX))
@@ -329,12 +340,27 @@ static inline unsigned long hvm_get_shadow_gs_base(struct vcpu *v)
return hvm_funcs.get_shadow_gs_base(v);
}
-#define is_viridian_domain(_d) \
- (is_hvm_domain(_d) && ((_d)->arch.hvm_domain.params[HVM_PARAM_VIRIDIAN]))
+#define has_hvm_params(d) \
+ ((d)->arch.hvm_domain.params != NULL)
+
+#define viridian_feature_mask(d) \
+ (has_hvm_params(d) ? (d)->arch.hvm_domain.params[HVM_PARAM_VIRIDIAN] : 0)
+
+#define is_viridian_domain(d) \
+ (is_hvm_domain(d) && (viridian_feature_mask(d) & HVMPV_base_freq))
+
+#define has_viridian_time_ref_count(d) \
+ (is_viridian_domain(d) && (viridian_feature_mask(d) & HVMPV_time_ref_count))
+
+void hvm_hypervisor_cpuid_leaf(uint32_t sub_idx,
+ uint32_t *eax, uint32_t *ebx,
+ uint32_t *ecx, uint32_t *edx);
void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx);
void hvm_migrate_timers(struct vcpu *v);
+bool_t hvm_has_dm(struct domain *d);
+bool_t hvm_io_pending(struct vcpu *v);
void hvm_do_resume(struct vcpu *v);
void hvm_migrate_pirqs(struct vcpu *v);
@@ -347,51 +373,10 @@ static inline int hvm_event_pending(struct vcpu *v)
return hvm_funcs.event_pending(v);
}
-static inline bool_t hvm_vcpu_has_smep(void)
-{
- unsigned int eax, ebx;
-
- hvm_cpuid(0, &eax, NULL, NULL, NULL);
-
- if ( eax < 7 )
- return 0;
-
- hvm_cpuid(7, NULL, &ebx, NULL, NULL);
- return !!(ebx & cpufeat_mask(X86_FEATURE_SMEP));
-}
-
-/* These reserved bits in lower 32 remain 0 after any load of CR0 */
-#define HVM_CR0_GUEST_RESERVED_BITS \
- (~((unsigned long) \
- (X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | \
- X86_CR0_TS | X86_CR0_ET | X86_CR0_NE | \
- X86_CR0_WP | X86_CR0_AM | X86_CR0_NW | \
- X86_CR0_CD | X86_CR0_PG)))
-
/* These bits in CR4 are owned by the host. */
#define HVM_CR4_HOST_MASK (mmu_cr4_features & \
(X86_CR4_VMXE | X86_CR4_PAE | X86_CR4_MCE))
-/* These bits in CR4 cannot be set by the guest. */
-#define HVM_CR4_GUEST_RESERVED_BITS(v, restore) ({ \
- const struct vcpu *_v = (v); \
- bool_t _restore = !!(restore); \
- ASSERT((_restore) || _v == current); \
- (~((unsigned long) \
- (X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | \
- X86_CR4_DE | X86_CR4_PSE | X86_CR4_PAE | \
- X86_CR4_MCE | X86_CR4_PGE | X86_CR4_PCE | \
- X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT | \
- (((_restore) ? cpu_has_smep : \
- hvm_vcpu_has_smep()) ? \
- X86_CR4_SMEP : 0) | \
- (cpu_has_fsgsbase ? X86_CR4_FSGSBASE : 0) | \
- ((nestedhvm_enabled(_v->domain) && cpu_has_vmx) \
- ? X86_CR4_VMXE : 0) | \
- (cpu_has_pcid ? X86_CR4_PCIDE : 0) | \
- (cpu_has_xsave ? X86_CR4_OSXSAVE : 0)))); \
-})
-
/* These exceptions must always be intercepted. */
#define HVM_TRAP_MASK ((1U << TRAP_machine_check) | (1U << TRAP_invalid_op))
@@ -476,11 +461,8 @@ static inline void hvm_invalidate_regs_fields(struct cpu_user_regs *regs)
#endif
}
-int hvm_hap_nested_page_fault(paddr_t gpa,
- bool_t gla_valid, unsigned long gla,
- bool_t access_r,
- bool_t access_w,
- bool_t access_x);
+int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
+ struct npfec npfec);
#define hvm_msr_tsc_aux(v) ({ \
struct domain *__d = (v)->domain; \
@@ -536,4 +518,21 @@ bool_t nhvm_vmcx_hap_enabled(struct vcpu *v);
/* interrupt */
enum hvm_intblk nhvm_interrupt_blocked(struct vcpu *v);
+#ifndef NDEBUG
+/* Permit use of the Forced Emulation Prefix in HVM guests */
+extern bool_t opt_hvm_fep;
+#else
+#define opt_hvm_fep 0
+#endif
+
#endif /* __ASM_X86_HVM_HVM_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h
index 86db58d..886a9d6 100644
--- a/xen/include/asm-x86/hvm/io.h
+++ b/xen/include/asm-x86/hvm/io.h
@@ -91,6 +91,7 @@ static inline int hvm_buffered_io_intercept(ioreq_t *p)
return hvm_io_intercept(p, HVM_BUFFERED_IO);
}
+bool_t hvm_mmio_internal(paddr_t gpa);
int hvm_mmio_intercept(ioreq_t *p);
int hvm_buffered_io_send(ioreq_t *p);
@@ -118,12 +119,13 @@ static inline void register_buffered_io_handler(
void send_timeoffset_req(unsigned long timeoff);
void send_invalidate_req(void);
int handle_mmio(void);
-int handle_mmio_with_translation(unsigned long gva, unsigned long gpfn);
+int handle_mmio_with_translation(unsigned long gva, unsigned long gpfn,
+ struct npfec);
int handle_pio(uint16_t port, unsigned int size, int dir);
void hvm_interrupt_post(struct vcpu *v, int vector, int type);
void hvm_io_assist(ioreq_t *p);
void hvm_dpci_eoi(struct domain *d, unsigned int guest_irq,
- union vioapic_redir_entry *ent);
+ const union vioapic_redir_entry *ent);
void msix_write_completion(struct vcpu *);
struct hvm_hw_stdvga {
diff --git a/xen/include/asm-x86/hvm/iommu.h b/xen/include/asm-x86/hvm/iommu.h
index d488edf..46cb126 100644
--- a/xen/include/asm-x86/hvm/iommu.h
+++ b/xen/include/asm-x86/hvm/iommu.h
@@ -39,4 +39,26 @@ static inline int iommu_hardware_setup(void)
return 0;
}
+struct g2m_ioport {
+ struct list_head list;
+ unsigned int gport;
+ unsigned int mport;
+ unsigned int np;
+};
+
+struct arch_hvm_iommu
+{
+ u64 pgd_maddr; /* io page directory machine address */
+ spinlock_t mapping_lock; /* io page table lock */
+ int agaw; /* adjusted guest address width, 0 is level 2 30-bit */
+ struct list_head g2m_ioport_list; /* guest to machine ioport mapping */
+ u64 iommu_bitmap; /* bitmap of iommu(s) that the domain uses */
+ struct list_head mapped_rmrrs;
+
+ /* amd iommu support */
+ int paging_mode;
+ struct page_info *root_table;
+ struct guest_iommu *g_iommu;
+};
+
#endif /* __ASM_X86_HVM_IOMMU_H__ */
diff --git a/xen/include/asm-x86/hvm/support.h b/xen/include/asm-x86/hvm/support.h
index 3529499..05ef5c5 100644
--- a/xen/include/asm-x86/hvm/support.h
+++ b/xen/include/asm-x86/hvm/support.h
@@ -22,19 +22,10 @@
#define __ASM_X86_HVM_SUPPORT_H__
#include <xen/types.h>
-#include <public/hvm/ioreq.h>
#include <xen/sched.h>
#include <xen/hvm/save.h>
#include <asm/processor.h>
-static inline ioreq_t *get_ioreq(struct vcpu *v)
-{
- struct domain *d = v->domain;
- shared_iopage_t *p = d->arch.hvm_domain.ioreq.va;
- ASSERT((v == current) || spin_is_locked(&d->arch.hvm_domain.ioreq.lock));
- return p ? &p->vcpu_ioreq[v->vcpu_id] : NULL;
-}
-
#define HVM_DELIVER_NO_ERROR_CODE -1
#ifndef NDEBUG
@@ -142,3 +133,13 @@ int hvm_mov_to_cr(unsigned int cr, unsigned int gpr);
int hvm_mov_from_cr(unsigned int cr, unsigned int gpr);
#endif /* __ASM_X86_HVM_SUPPORT_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
index b5abc8f..cf43e29 100644
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
@@ -210,7 +210,7 @@ static inline int iommu_has_cap(struct amd_iommu *iommu, uint32_t bit)
return !!(iommu->cap.header & (1u << bit));
}
-static inline int iommu_has_feature(struct amd_iommu *iommu, uint32_t bit)
+static inline int amd_iommu_has_feature(struct amd_iommu *iommu, uint32_t bit)
{
if ( !iommu_has_cap(iommu, PCI_CAP_EFRSUP_SHIFT) )
return 0;
diff --git a/xen/include/asm-x86/hvm/svm/svm.h b/xen/include/asm-x86/hvm/svm/svm.h
index 1ffe6d6..cb2db3f 100644
--- a/xen/include/asm-x86/hvm/svm/svm.h
+++ b/xen/include/asm-x86/hvm/svm/svm.h
@@ -105,4 +105,10 @@ extern u32 svm_feature_flags;
extern void svm_host_osvw_reset(void);
extern void svm_host_osvw_init(void);
+/* EXITINFO1 fields on NPT faults */
+#define _NPT_PFEC_with_gla 32
+#define NPT_PFEC_with_gla (1UL<<_NPT_PFEC_with_gla)
+#define _NPT_PFEC_in_gpt 33
+#define NPT_PFEC_in_gpt (1UL<<_NPT_PFEC_in_gpt)
+
#endif /* __ASM_X86_HVM_SVM_H__ */
diff --git a/xen/include/asm-x86/hvm/svm/vmcb.h b/xen/include/asm-x86/hvm/svm/vmcb.h
index ade4bb2..fd0b0a4 100644
--- a/xen/include/asm-x86/hvm/svm/vmcb.h
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h
@@ -309,7 +309,7 @@ enum VMEXIT_EXITCODE
/* Definition of segment state is borrowed by the generic HVM code. */
typedef struct segment_register svm_segment_register_t;
-typedef union
+typedef union __packed
{
u64 bytes;
struct
@@ -321,9 +321,9 @@ typedef union
u64 v: 1;
u64 errorcode:32;
} fields;
-} __attribute__ ((packed)) eventinj_t;
+} eventinj_t;
-typedef union
+typedef union __packed
{
u64 bytes;
struct
@@ -339,9 +339,9 @@ typedef union
u64 vector: 8;
u64 rsvd3: 24;
} fields;
-} __attribute__ ((packed)) vintr_t;
+} vintr_t;
-typedef union
+typedef union __packed
{
u64 bytes;
struct
@@ -356,18 +356,18 @@ typedef union
u64 rsv1: 9;
u64 port: 16;
} fields;
-} __attribute__ ((packed)) ioio_info_t;
+} ioio_info_t;
-typedef union
+typedef union __packed
{
u64 bytes;
struct
{
u64 enable:1;
} fields;
-} __attribute__ ((packed)) lbrctrl_t;
+} lbrctrl_t;
-typedef union
+typedef union __packed
{
uint32_t bytes;
struct
@@ -397,12 +397,12 @@ typedef union
uint32_t lbr: 1;
uint32_t resv: 21;
} fields;
-} __attribute__ ((packed)) vmcbcleanbits_t;
+} vmcbcleanbits_t;
#define IOPM_SIZE (12 * 1024)
#define MSRPM_SIZE (8 * 1024)
-struct vmcb_struct {
+struct __packed vmcb_struct {
u32 _cr_intercepts; /* offset 0x00 - cleanbit 0 */
u32 _dr_intercepts; /* offset 0x04 - cleanbit 0 */
u32 _exception_intercepts; /* offset 0x08 - cleanbit 0 */
@@ -487,7 +487,7 @@ struct vmcb_struct {
u64 _lastintfromip; /* cleanbit 10 */
u64 _lastinttoip; /* cleanbit 10 */
u64 res16[301];
-} __attribute__ ((packed));
+};
struct svm_domain {
};
@@ -515,6 +515,9 @@ struct arch_svm_struct {
uint64_t guest_lwp_cfg; /* guest version */
uint64_t cpu_lwp_cfg; /* CPU version */
+ /* data breakpoint extension MSRs */
+ uint32_t dr_mask[4];
+
/* OSVW MSRs */
struct {
u64 length;
diff --git a/xen/include/asm-x86/hvm/trace.h b/xen/include/asm-x86/hvm/trace.h
index 9d7e00b..de802a6 100644
--- a/xen/include/asm-x86/hvm/trace.h
+++ b/xen/include/asm-x86/hvm/trace.h
@@ -58,6 +58,13 @@
#define TRC_PAR_LONG(par) ((par)&0xFFFFFFFF),((par)>>32)
+#define TRACE_2_LONG_2D(_e, d1, d2, ...) \
+ TRACE_4D(_e, d1, d2)
+#define TRACE_2_LONG_3D(_e, d1, d2, d3, ...) \
+ TRACE_5D(_e, d1, d2, d3)
+#define TRACE_2_LONG_4D(_e, d1, d2, d3, d4, ...) \
+ TRACE_6D(_e, d1, d2, d3, d4)
+
#define HVMTRACE_ND(evt, modifier, cycles, count, d1, d2, d3, d4, d5, d6) \
do { \
if ( unlikely(tb_init_done) && DO_TRC_HVM_ ## evt ) \
diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h
index 122ab0d..01e0665 100644
--- a/xen/include/asm-x86/hvm/vcpu.h
+++ b/xen/include/asm-x86/hvm/vcpu.h
@@ -54,8 +54,9 @@ struct hvm_vcpu_io {
* HVM emulation:
* Virtual address @mmio_gva maps to MMIO physical frame @mmio_gpfn.
* The latter is known to be an MMIO frame (not RAM).
- * This translation is only valid if @mmio_gva is non-zero.
+ * This translation is only valid for accesses as per @mmio_access.
*/
+ struct npfec mmio_access;
unsigned long mmio_gva;
unsigned long mmio_gpfn;
@@ -138,9 +139,7 @@ struct hvm_vcpu {
spinlock_t tm_lock;
struct list_head tm_list;
- int xen_port;
-
- bool_t flag_dr_dirty;
+ u8 flag_dr_dirty;
bool_t debug_state_latch;
bool_t single_step;
@@ -186,3 +185,13 @@ struct hvm_vcpu {
};
#endif /* __ASM_X86_HVM_VCPU_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-x86/hvm/viridian.h b/xen/include/asm-x86/hvm/viridian.h
index 496da33..4cab2e8 100644
--- a/xen/include/asm-x86/hvm/viridian.h
+++ b/xen/include/asm-x86/hvm/viridian.h
@@ -48,10 +48,24 @@ union viridian_hypercall_gpa
} fields;
};
+struct viridian_time_ref_count
+{
+ unsigned long flags;
+
+#define _TRC_accessed 0
+#define TRC_accessed (1 << _TRC_accessed)
+#define _TRC_running 1
+#define TRC_running (1 << _TRC_running)
+
+ uint64_t val;
+ int64_t off;
+};
+
struct viridian_domain
{
union viridian_guest_os_id guest_os_id;
union viridian_hypercall_gpa hypercall_gpa;
+ struct viridian_time_ref_count time_ref_count;
};
int
@@ -75,4 +89,17 @@ rdmsr_viridian_regs(
int
viridian_hypercall(struct cpu_user_regs *regs);
+void viridian_time_ref_count_freeze(struct domain *d);
+void viridian_time_ref_count_thaw(struct domain *d);
+
#endif /* __ASM_X86_HVM_VIRIDIAN_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-x86/hvm/vlapic.h b/xen/include/asm-x86/hvm/vlapic.h
index 66f0aff..cfe9bdb 100644
--- a/xen/include/asm-x86/hvm/vlapic.h
+++ b/xen/include/asm-x86/hvm/vlapic.h
@@ -28,10 +28,13 @@
#define vcpu_vlapic(x) (&(x)->arch.hvm_vcpu.vlapic)
#define vlapic_vcpu(x) (container_of((x), struct vcpu, arch.hvm_vcpu.vlapic))
+#define const_vlapic_vcpu(x) (container_of((x), const struct vcpu, \
+ arch.hvm_vcpu.vlapic))
#define vlapic_domain(x) (vlapic_vcpu(x)->domain)
-#define VLAPIC_ID(vlapic) \
- (GET_xAPIC_ID(vlapic_get_reg((vlapic), APIC_ID)))
+#define _VLAPIC_ID(vlapic, id) (vlapic_x2apic_mode(vlapic) \
+ ? (id) : GET_xAPIC_ID(id))
+#define VLAPIC_ID(vlapic) _VLAPIC_ID(vlapic, vlapic_get_reg(vlapic, APIC_ID))
/*
* APIC can be disabled in two ways:
@@ -58,6 +61,8 @@
#define VEC_POS(v) ((v) % 32)
#define REG_POS(v) (((v) / 32) * 0x10)
+#define vlapic_test_vector(vec, bitmap) \
+ test_bit(VEC_POS(vec), (const uint32_t *)((bitmap) + REG_POS(vec)))
#define vlapic_test_and_set_vector(vec, bitmap) \
test_and_set_bit(VEC_POS(vec), (uint32_t *)((bitmap) + REG_POS(vec)))
#define vlapic_test_and_clear_vector(vec, bitmap) \
@@ -70,6 +75,11 @@
struct vlapic {
struct hvm_hw_lapic hw;
struct hvm_hw_lapic_regs *regs;
+ struct {
+ bool_t hw, regs;
+ uint32_t id, ldr;
+ } loaded;
+ spinlock_t esr_lock;
struct periodic_time pt;
s_time_t timer_last_update;
struct page_info *regs_page;
@@ -83,7 +93,8 @@ struct vlapic {
/* vlapic's frequence is 100 MHz */
#define APIC_BUS_CYCLE_NS 10
-static inline uint32_t vlapic_get_reg(struct vlapic *vlapic, uint32_t reg)
+static inline uint32_t vlapic_get_reg(const struct vlapic *vlapic,
+ uint32_t reg)
{
return *((uint32_t *)(&vlapic->regs->data[reg]));
}
@@ -106,7 +117,7 @@ void vlapic_destroy(struct vcpu *v);
void vlapic_reset(struct vlapic *vlapic);
-void vlapic_msr_set(struct vlapic *vlapic, uint64_t value);
+bool_t vlapic_msr_set(struct vlapic *vlapic, uint64_t value);
void vlapic_tdt_msr_set(struct vlapic *vlapic, uint64_t value);
uint64_t vlapic_tdt_msr_get(struct vlapic *vlapic);
@@ -123,11 +134,11 @@ void vlapic_ipi(struct vlapic *vlapic, uint32_t icr_low, uint32_t icr_high);
int vlapic_apicv_write(struct vcpu *v, unsigned int offset);
struct vlapic *vlapic_lowest_prio(
- struct domain *d, struct vlapic *source,
- int short_hand, uint8_t dest, uint8_t dest_mode);
+ struct domain *d, const struct vlapic *source,
+ int short_hand, uint32_t dest, bool_t dest_mode);
bool_t vlapic_match_dest(
- struct vlapic *target, struct vlapic *source,
- int short_hand, uint8_t dest, uint8_t dest_mode);
+ const struct vlapic *target, const struct vlapic *source,
+ int short_hand, uint32_t dest, bool_t dest_mode);
#endif /* __ASM_X86_HVM_VLAPIC_H__ */
diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h
index f0c5fa5..6a99dca 100644
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
@@ -124,6 +124,9 @@ struct arch_vmx_struct {
unsigned long host_cr0;
+ /* Do we need to tolerate a spurious EPT_MISCONFIG VM exit? */
+ bool_t ept_spurious_misconfig;
+
/* Is the guest in real mode? */
uint8_t vmx_realmode;
/* Are we emulating rather than VMENTERing? */
@@ -186,6 +189,7 @@ extern u32 vmx_pin_based_exec_control;
#define VM_EXIT_SAVE_GUEST_EFER 0x00100000
#define VM_EXIT_LOAD_HOST_EFER 0x00200000
#define VM_EXIT_SAVE_PREEMPT_TIMER 0x00400000
+#define VM_EXIT_CLEAR_BNDCFGS 0x00800000
extern u32 vmx_vmexit_control;
#define VM_ENTRY_IA32E_MODE 0x00000200
@@ -194,6 +198,7 @@ extern u32 vmx_vmexit_control;
#define VM_ENTRY_LOAD_PERF_GLOBAL_CTRL 0x00002000
#define VM_ENTRY_LOAD_GUEST_PAT 0x00004000
#define VM_ENTRY_LOAD_GUEST_EFER 0x00008000
+#define VM_ENTRY_LOAD_BNDCFGS 0x00010000
extern u32 vmx_vmentry_control;
#define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
@@ -365,6 +370,8 @@ enum vmcs_field {
GUEST_PDPTR2_HIGH = 0x0000280f,
GUEST_PDPTR3 = 0x00002810,
GUEST_PDPTR3_HIGH = 0x00002811,
+ GUEST_BNDCFGS = 0x00002812,
+ GUEST_BNDCFGS_HIGH = 0x00002813,
HOST_PAT = 0x00002c00,
HOST_PAT_HIGH = 0x00002c01,
HOST_EFER = 0x00002c02,
@@ -464,6 +471,13 @@ enum vmcs_field {
HOST_RIP = 0x00006c16,
};
+/*
+ * A set of MSR-s that need to be enabled for memory introspection
+ * to work.
+ */
+extern const u32 vmx_introspection_force_enabled_msrs[];
+extern const unsigned int vmx_introspection_force_enabled_msrs_size;
+
#define VMCS_VPID_WIDTH 16
#define MSR_TYPE_R 1
diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h
index 6f6b672..c8bb548 100644
--- a/xen/include/asm-x86/hvm/vmx/vmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h
@@ -38,14 +38,14 @@ typedef union {
ipat : 1, /* bit 6 - Ignore PAT memory type */
sp : 1, /* bit 7 - Is this a superpage? */
rsvd1 : 2, /* bits 9:8 - Reserved for future use */
- avail1 : 1, /* bit 10 - Software available 1 */
- rsvd2_snp : 1, /* bit 11 - Used for VT-d snoop control
- in shared EPT/VT-d usage */
+ recalc : 1, /* bit 10 - Software available 1 */
+ snp : 1, /* bit 11 - VT-d snoop control in shared
+ EPT/VT-d usage */
mfn : 40, /* bits 51:12 - Machine physical frame number */
sa_p2mt : 6, /* bits 57:52 - Software available 2 */
access : 4, /* bits 61:58 - p2m_access_t */
- rsvd3_tm : 1, /* bit 62 - Used for VT-d transient-mapping
- hint in shared EPT/VT-d usage */
+ tm : 1, /* bit 62 - VT-d transient-mapping hint in
+ shared EPT/VT-d usage */
avail3 : 1; /* bit 63 - Software available 3 */
};
u64 epte;
@@ -91,7 +91,7 @@ typedef enum {
void vmx_asm_vmexit_handler(struct cpu_user_regs);
void vmx_asm_do_vmentry(void);
void vmx_intr_assist(void);
-void vmx_do_resume(struct vcpu *);
+void noreturn vmx_do_resume(struct vcpu *);
void vmx_vlapic_msr_changed(struct vcpu *v);
void vmx_realmode(struct cpu_user_regs *regs);
void vmx_update_debug_state(struct vcpu *v);
@@ -421,11 +421,11 @@ static inline void __invept(unsigned long type, u64 eptp, u64 gpa)
static inline void __invvpid(unsigned long type, u16 vpid, u64 gva)
{
- struct {
+ struct __packed {
u64 vpid:16;
u64 rsvd:48;
u64 gva;
- } __attribute__ ((packed)) operand = {vpid, 0, gva};
+ } operand = {vpid, 0, gva};
/* Fix up #UD exceptions which occur when TLBs are flushed before VMXON. */
asm volatile ( "1: "
@@ -520,6 +520,7 @@ int ept_p2m_init(struct p2m_domain *p2m);
void ept_p2m_uninit(struct p2m_domain *p2m);
void ept_walk_table(struct domain *d, unsigned long gfn);
+bool_t ept_handle_misconfig(uint64_t gpa);
void setup_ept_dump(void);
void update_guest_eip(void);
diff --git a/xen/include/asm-x86/hvm/vpmu.h b/xen/include/asm-x86/hvm/vpmu.h
index 40f63fb..1f28bd8 100644
--- a/xen/include/asm-x86/hvm/vpmu.h
+++ b/xen/include/asm-x86/hvm/vpmu.h
@@ -45,7 +45,8 @@
/* Arch specific operations shared by all vpmus */
struct arch_vpmu_ops {
- int (*do_wrmsr)(unsigned int msr, uint64_t msr_content);
+ int (*do_wrmsr)(unsigned int msr, uint64_t msr_content,
+ uint64_t supported);
int (*do_rdmsr)(unsigned int msr, uint64_t *msr_content);
int (*do_interrupt)(struct cpu_user_regs *regs);
void (*do_cpuid)(unsigned int input,
@@ -86,9 +87,9 @@ struct vpmu_struct {
#define vpmu_is_set(_vpmu, _x) ((_vpmu)->flags & (_x))
#define vpmu_clear(_vpmu) ((_vpmu)->flags = 0)
-int vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content);
+int vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content, uint64_t supported);
int vpmu_do_rdmsr(unsigned int msr, uint64_t *msr_content);
-int vpmu_do_interrupt(struct cpu_user_regs *regs);
+void vpmu_do_interrupt(struct cpu_user_regs *regs);
void vpmu_do_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx);
void vpmu_initialise(struct vcpu *v);
diff --git a/xen/include/asm-x86/hvm/vpt.h b/xen/include/asm-x86/hvm/vpt.h
index 41159d8..8b8b65a 100644
--- a/xen/include/asm-x86/hvm/vpt.h
+++ b/xen/include/asm-x86/hvm/vpt.h
@@ -96,7 +96,7 @@ typedef struct HPETState {
uint64_t hpet_to_ns_limit; /* max hpet ticks convertable to ns */
uint64_t mc_offset;
struct periodic_time pt[HPET_TIMER_NUM];
- spinlock_t lock;
+ rwlock_t lock;
} HPETState;
typedef struct RTCState {
@@ -190,7 +190,7 @@ void pmtimer_deinit(struct domain *d);
void pmtimer_reset(struct domain *d);
int pmtimer_change_ioport(struct domain *d, unsigned int version);
-void hpet_init(struct vcpu *v);
+void hpet_init(struct domain *d);
void hpet_deinit(struct domain *d);
void hpet_reset(struct domain *d);
diff --git a/xen/include/asm-x86/i387.h b/xen/include/asm-x86/i387.h
index fd268a9..150a09e 100644
--- a/xen/include/asm-x86/i387.h
+++ b/xen/include/asm-x86/i387.h
@@ -28,11 +28,11 @@ struct ix87_state {
uint32_t fdp;
uint16_t fds, _res6;
} env;
- struct ix87_reg {
+ struct __packed ix87_reg {
uint64_t mantissa;
uint16_t exponent:15;
uint16_t sign:1;
- } __attribute__((__packed__)) r[8];
+ } r[8];
};
void vcpu_restore_fpu_eager(struct vcpu *v);
diff --git a/xen/include/asm-x86/io_apic.h b/xen/include/asm-x86/io_apic.h
index 6d90628..b318a36 100644
--- a/xen/include/asm-x86/io_apic.h
+++ b/xen/include/asm-x86/io_apic.h
@@ -36,41 +36,41 @@
*/
union IO_APIC_reg_00 {
u32 raw;
- struct {
+ struct __packed {
u32 __reserved_2 : 14,
LTS : 1,
delivery_type : 1,
__reserved_1 : 8,
ID : 8;
- } __attribute__ ((packed)) bits;
+ } bits;
};
union IO_APIC_reg_01 {
u32 raw;
- struct {
+ struct __packed {
u32 version : 8,
__reserved_2 : 7,
PRQ : 1,
entries : 8,
__reserved_1 : 8;
- } __attribute__ ((packed)) bits;
+ } bits;
};
union IO_APIC_reg_02 {
u32 raw;
- struct {
+ struct __packed {
u32 __reserved_2 : 24,
arbitration : 4,
__reserved_1 : 4;
- } __attribute__ ((packed)) bits;
+ } bits;
};
union IO_APIC_reg_03 {
u32 raw;
- struct {
+ struct __packed {
u32 boot_DT : 1,
__reserved_1 : 31;
- } __attribute__ ((packed)) bits;
+ } bits;
};
/*
@@ -90,7 +90,7 @@ enum ioapic_irq_destination_types {
dest_ExtINT = 7
};
-struct IO_APIC_route_entry {
+struct __packed IO_APIC_route_entry {
__u32 vector : 8,
delivery_mode : 3, /* 000: FIXED
* 001: lowest prio
@@ -119,7 +119,7 @@ struct IO_APIC_route_entry {
__u32 dest32;
} dest;
-} __attribute__ ((packed));
+};
/*
* MP-BIOS irq configuration table structures:
diff --git a/xen/include/asm-x86/iommu.h b/xen/include/asm-x86/iommu.h
new file mode 100644
index 0000000..e7a65da
--- /dev/null
+++ b/xen/include/asm-x86/iommu.h
@@ -0,0 +1,43 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+*/
+#ifndef __ARCH_X86_IOMMU_H__
+#define __ARCH_X86_IOMMU_H__
+
+#define MAX_IOMMUS 32
+
+/* Does this domain have a P2M table we can use as its IOMMU pagetable? */
+#define iommu_use_hap_pt(d) (hap_enabled(d) && iommu_hap_pt_share)
+#define domain_hvm_iommu(d) (&d->arch.hvm_domain.hvm_iommu)
+
+void iommu_update_ire_from_apic(unsigned int apic, unsigned int reg, unsigned int value);
+unsigned int iommu_read_apic_from_ire(unsigned int apic, unsigned int reg);
+int iommu_setup_hpet_msi(struct msi_desc *);
+
+/* While VT-d specific, this must get declared in a generic header. */
+int adjust_vtd_irq_affinities(void);
+void iommu_pte_flush(struct domain *d, u64 gfn, u64 *pte, int order, int present);
+int iommu_supports_eim(void);
+int iommu_enable_x2apic_IR(void);
+void iommu_disable_x2apic_IR(void);
+
+#endif /* !__ARCH_X86_IOMMU_H__ */
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-x86/irq.h b/xen/include/asm-x86/irq.h
index 9066d38..d3c55f3 100644
--- a/xen/include/asm-x86/irq.h
+++ b/xen/include/asm-x86/irq.h
@@ -197,4 +197,6 @@ void cleanup_domain_irq_mapping(struct domain *);
bool_t cpu_has_pending_apic_eoi(void);
+static inline void arch_move_irqs(struct vcpu *v) { }
+
#endif /* _ASM_HW_IRQ_H */
diff --git a/xen/include/asm-x86/ldt.h b/xen/include/asm-x86/ldt.h
index b6f7beb..aa77368 100644
--- a/xen/include/asm-x86/ldt.h
+++ b/xen/include/asm-x86/ldt.h
@@ -18,7 +18,7 @@ static inline void load_LDT(struct vcpu *v)
desc = (!is_pv_32on64_vcpu(v)
? this_cpu(gdt_table) : this_cpu(compat_gdt_table))
+ LDT_ENTRY - FIRST_RESERVED_GDT_ENTRY;
- _set_tssldt_desc(desc, LDT_VIRT_START(v), ents*8-1, 2);
+ _set_tssldt_desc(desc, LDT_VIRT_START(v), ents*8-1, SYS_DESC_ldt);
__asm__ __volatile__ ( "lldt %%ax" : : "a" (LDT_ENTRY << 3) );
}
}
diff --git a/xen/include/asm-x86/mem_access.h b/xen/include/asm-x86/mem_access.h
deleted file mode 100644
index 88ae3fc..0000000
--- a/xen/include/asm-x86/mem_access.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/******************************************************************************
- * include/asm-x86/mem_paging.h
- *
- * Memory access support.
- *
- * Copyright (c) 2011 Virtuata, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-int mem_access_memop(struct domain *d, xen_mem_event_op_t *meo);
-int mem_access_send_req(struct domain *d, mem_event_request_t *req);
-
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/include/asm-x86/mem_event.h b/xen/include/asm-x86/mem_event.h
deleted file mode 100644
index ed4481a..0000000
--- a/xen/include/asm-x86/mem_event.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/******************************************************************************
- * include/asm-x86/mem_event.h
- *
- * Common interface for memory event support.
- *
- * Copyright (c) 2009 Citrix Systems, Inc. (Patrick Colp)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#ifndef __MEM_EVENT_H__
-#define __MEM_EVENT_H__
-
-/* Returns whether a ring has been set up */
-bool_t mem_event_check_ring(struct mem_event_domain *med);
-
-/* Returns 0 on success, -ENOSYS if there is no ring, -EBUSY if there is no
- * available space and the caller is a foreign domain. If the guest itself
- * is the caller, -EBUSY is avoided by sleeping on a wait queue to ensure
- * that the ring does not lose future events.
- *
- * However, the allow_sleep flag can be set to false in cases in which it is ok
- * to lose future events, and thus -EBUSY can be returned to guest vcpus
- * (handle with care!).
- *
- * In general, you must follow a claim_slot() call with either put_request() or
- * cancel_slot(), both of which are guaranteed to
- * succeed.
- */
-int __mem_event_claim_slot(struct domain *d, struct mem_event_domain *med,
- bool_t allow_sleep);
-static inline int mem_event_claim_slot(struct domain *d,
- struct mem_event_domain *med)
-{
- return __mem_event_claim_slot(d, med, 1);
-}
-
-static inline int mem_event_claim_slot_nosleep(struct domain *d,
- struct mem_event_domain *med)
-{
- return __mem_event_claim_slot(d, med, 0);
-}
-
-void mem_event_cancel_slot(struct domain *d, struct mem_event_domain *med);
-
-void mem_event_put_request(struct domain *d, struct mem_event_domain *med,
- mem_event_request_t *req);
-
-int mem_event_get_response(struct domain *d, struct mem_event_domain *med,
- mem_event_response_t *rsp);
-
-int do_mem_event_op(int op, uint32_t domain, void *arg);
-int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
- XEN_GUEST_HANDLE_PARAM(void) u_domctl);
-
-void mem_event_vcpu_pause(struct vcpu *v);
-void mem_event_vcpu_unpause(struct vcpu *v);
-
-#endif /* __MEM_EVENT_H__ */
-
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
index c835f76..dca298f 100644
--- a/xen/include/asm-x86/mm.h
+++ b/xen/include/asm-x86/mm.h
@@ -125,7 +125,7 @@ struct page_info
* PGT_partial gets set, and it must be dropped when the flag gets
* cleared. This is so that a get() leaving a page in partially
* validated state (where the caller would drop the reference acquired
- * due to the getting of the type [apparently] failing [-EAGAIN])
+ * due to the getting of the type [apparently] failing [-ERESTART])
* would not accidentally result in a page left with zero general
* reference count, but non-zero type reference count (possible when
* the partial get() is followed immediately by domain destruction).
@@ -280,9 +280,7 @@ extern unsigned long max_page;
extern unsigned long total_pages;
void init_frametable(void);
-#define PDX_GROUP_COUNT ((1 << L2_PAGETABLE_SHIFT) / \
- (sizeof(*frame_table) & -sizeof(*frame_table)))
-extern unsigned long pdx_group_valid[];
+#define PDX_GROUP_SHIFT L2_PAGETABLE_SHIFT
/* Convert between Xen-heap virtual addresses and page-info structures. */
static inline struct page_info *__virt_to_page(const void *v)
@@ -561,9 +559,9 @@ void *do_page_walk(struct vcpu *v, unsigned long addr);
int __sync_local_execstate(void);
/* Arch-specific portion of memory_op hypercall. */
-long arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg);
-long subarch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg);
-int compat_arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void));
+long arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg);
+long subarch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg);
+int compat_arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void));
int compat_subarch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void));
int steal_page(
@@ -590,8 +588,6 @@ unsigned int domain_clamp_alloc_bitsize(struct domain *d, unsigned int bits);
unsigned long domain_get_maximum_gpfn(struct domain *d);
-void mem_event_cleanup(struct domain *d);
-
extern struct domain *dom_xen, *dom_io, *dom_cow; /* for vmcoreinfo */
/* Definition of an mm lock: spinlock with extra fields for debugging */
diff --git a/xen/include/asm-x86/msi.h b/xen/include/asm-x86/msi.h
index 89a9266..4c62a3a 100644
--- a/xen/include/asm-x86/msi.h
+++ b/xen/include/asm-x86/msi.h
@@ -49,7 +49,7 @@
#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT)
#define MSI_ADDR_DEST_ID_SHIFT 12
-#define MSI_ADDR_DEST_ID_MASK 0x00ffff0
+#define MSI_ADDR_DEST_ID_MASK 0x00ff000
#define MSI_ADDR_DEST_ID(dest) (((dest) << MSI_ADDR_DEST_ID_SHIFT) & MSI_ADDR_DEST_ID_MASK)
/* MAX fixed pages reserved for mapping MSIX tables. */
@@ -168,7 +168,7 @@ int msi_free_irq(struct msi_desc *entry);
* MSI Defined Data Structures
*/
-struct msg_data {
+struct __packed msg_data {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u32 vector : 8;
__u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */
@@ -186,9 +186,9 @@ struct msg_data {
#else
#error "Bitfield endianness not defined! Check your byteorder.h"
#endif
-} __attribute__ ((packed));
+};
-struct msg_address {
+struct __packed msg_address {
union {
struct {
#if defined(__LITTLE_ENDIAN_BITFIELD)
@@ -212,7 +212,7 @@ struct msg_address {
__u32 value;
}lo_address;
__u32 hi_address;
-} __attribute__ ((packed));
+};
#define MAX_MSIX_TABLE_ENTRIES (PCI_MSIX_FLAGS_QSIZE + 1)
#define MAX_MSIX_TABLE_PAGES PFN_UP(MAX_MSIX_TABLE_ENTRIES * \
diff --git a/xen/include/asm-x86/msr-index.h b/xen/include/asm-x86/msr-index.h
index fc9fbc6..83f2f70 100644
--- a/xen/include/asm-x86/msr-index.h
+++ b/xen/include/asm-x86/msr-index.h
@@ -56,6 +56,8 @@
#define MSR_IA32_DS_AREA 0x00000600
#define MSR_IA32_PERF_CAPABILITIES 0x00000345
+#define MSR_IA32_BNDCFGS 0x00000D90
+
#define MSR_MTRRfix64K_00000 0x00000250
#define MSR_MTRRfix16K_80000 0x00000258
#define MSR_MTRRfix16K_A0000 0x00000259
@@ -77,6 +79,7 @@
#define IA32_DEBUGCTLMSR_BTINT (1<<8) /* Branch Trace Interrupt */
#define IA32_DEBUGCTLMSR_BTS_OFF_OS (1<<9) /* BTS off if CPL 0 */
#define IA32_DEBUGCTLMSR_BTS_OFF_USR (1<<10) /* BTS off if CPL > 0 */
+#define IA32_DEBUGCTLMSR_RTM (1<<15) /* RTM debugging enable */
#define MSR_IA32_LASTBRANCHFROMIP 0x000001db
#define MSR_IA32_LASTBRANCHTOIP 0x000001dc
@@ -85,22 +88,8 @@
#define MSR_IA32_POWER_CTL 0x000001fc
-#define MSR_IA32_MTRR_PHYSBASE0 0x00000200
-#define MSR_IA32_MTRR_PHYSMASK0 0x00000201
-#define MSR_IA32_MTRR_PHYSBASE1 0x00000202
-#define MSR_IA32_MTRR_PHYSMASK1 0x00000203
-#define MSR_IA32_MTRR_PHYSBASE2 0x00000204
-#define MSR_IA32_MTRR_PHYSMASK2 0x00000205
-#define MSR_IA32_MTRR_PHYSBASE3 0x00000206
-#define MSR_IA32_MTRR_PHYSMASK3 0x00000207
-#define MSR_IA32_MTRR_PHYSBASE4 0x00000208
-#define MSR_IA32_MTRR_PHYSMASK4 0x00000209
-#define MSR_IA32_MTRR_PHYSBASE5 0x0000020a
-#define MSR_IA32_MTRR_PHYSMASK5 0x0000020b
-#define MSR_IA32_MTRR_PHYSBASE6 0x0000020c
-#define MSR_IA32_MTRR_PHYSMASK6 0x0000020d
-#define MSR_IA32_MTRR_PHYSBASE7 0x0000020e
-#define MSR_IA32_MTRR_PHYSMASK7 0x0000020f
+#define MSR_IA32_MTRR_PHYSBASE(n) (0x00000200 + 2 * (n))
+#define MSR_IA32_MTRR_PHYSMASK(n) (0x00000201 + 2 * (n))
#define MSR_IA32_CR_PAT 0x00000277
#define MSR_IA32_CR_PAT_RESET 0x0007040600070406ULL
@@ -123,11 +112,6 @@
#define MSR_AMD64_MCx_MASK(x) (MSR_AMD64_MC0_MASK + (x))
-#define MSR_P6_PERFCTR0 0x000000c1
-#define MSR_P6_PERFCTR1 0x000000c2
-#define MSR_P6_EVNTSEL0 0x00000186
-#define MSR_P6_EVNTSEL1 0x00000187
-
/* MSRs & bits used for VMX enabling */
#define MSR_IA32_VMX_BASIC 0x480
#define MSR_IA32_VMX_PINBASED_CTLS 0x481
@@ -204,6 +188,8 @@
#define MSR_AMD_FAM15H_EVNTSEL5 0xc001020a
#define MSR_AMD_FAM15H_PERFCTR5 0xc001020b
+#define MSR_AMD_L7S0_FEATURE_MASK 0xc0011002
+#define MSR_AMD_THRM_FEATURE_MASK 0xc0011003
#define MSR_K8_FEATURE_MASK 0xc0011004
#define MSR_K8_EXT_FEATURE_MASK 0xc0011005
@@ -218,6 +204,11 @@
#define MSR_AMD64_DC_CFG 0xc0011022
#define AMD64_NB_CFG_CF8_EXT_ENABLE_BIT 46
+#define MSR_AMD64_DR0_ADDRESS_MASK 0xc0011027
+#define MSR_AMD64_DR1_ADDRESS_MASK 0xc0011019
+#define MSR_AMD64_DR2_ADDRESS_MASK 0xc001101a
+#define MSR_AMD64_DR3_ADDRESS_MASK 0xc001101b
+
/* AMD Family10h machine check MSRs */
#define MSR_F10_MC4_MISC1 0xc0000408
#define MSR_F10_MC4_MISC2 0xc0000409
@@ -332,9 +323,14 @@
#define MSR_IA32_TSC_DEADLINE 0x000006E0
#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0
+/* Platform Shared Resource MSRs */
+#define MSR_IA32_CMT_EVTSEL 0x00000c8d
+#define MSR_IA32_CMT_CTR 0x00000c8e
+#define MSR_IA32_PSR_ASSOC 0x00000c8f
+
/* Intel Model 6 */
-#define MSR_P6_EVNTSEL0 0x00000186
-#define MSR_P6_EVNTSEL1 0x00000187
+#define MSR_P6_PERFCTR(n) (0x000000c1 + (n))
+#define MSR_P6_EVNTSEL(n) (0x00000186 + (n))
/* P4/Xeon+ specific */
#define MSR_IA32_MCG_EAX 0x00000180
@@ -474,19 +470,25 @@
#define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x00000390
/* Intel cpuid spoofing MSRs */
-#define MSR_INTEL_CPUID_FEATURE_MASK 0x00000478
-#define MSR_INTEL_CPUID1_FEATURE_MASK 0x00000130
-#define MSR_INTEL_CPUID80000001_FEATURE_MASK 0x00000131
+#define MSR_INTEL_MASK_V1_CPUID1 0x00000478
+
+#define MSR_INTEL_MASK_V2_CPUID1 0x00000130
+#define MSR_INTEL_MASK_V2_CPUID80000001 0x00000131
-#define MSR_INTEL_CPUID1_FEATURE_MASK_V2 0x00000132
-#define MSR_INTEL_CPUID80000001_FEATURE_MASK_V2 0x00000133
-#define MSR_INTEL_CPUIDD_01_FEATURE_MASK 0x00000134
+#define MSR_INTEL_MASK_V3_CPUID1 0x00000132
+#define MSR_INTEL_MASK_V3_CPUID80000001 0x00000133
+#define MSR_INTEL_MASK_V3_CPUIDD_01 0x00000134
/* Intel cpuid faulting MSRs */
#define MSR_INTEL_PLATFORM_INFO 0x000000ce
+#define _MSR_PLATFORM_INFO_CPUID_FAULTING 31
+#define MSR_PLATFORM_INFO_CPUID_FAULTING (1ULL << _MSR_PLATFORM_INFO_CPUID_FAULTING)
+
#define MSR_INTEL_MISC_FEATURES_ENABLES 0x00000140
+#define _MSR_MISC_FEATURES_CPUID_FAULTING 0
+#define MSR_MISC_FEATURES_CPUID_FAULTING (1ULL << _MSR_MISC_FEATURES_CPUID_FAULTING)
-/* Geode defined MSRs */
-#define MSR_GEODE_BUSCONT_CONF0 0x00001900
+#define MSR_CC6_DEMOTION_POLICY_CONFIG 0x00000668
+#define MSR_MC6_DEMOTION_POLICY_CONFIG 0x00000669
#endif /* __ASM_MSR_INDEX_H */
diff --git a/xen/include/asm-x86/msr.h b/xen/include/asm-x86/msr.h
index 61f579a..52cae4b 100644
--- a/xen/include/asm-x86/msr.h
+++ b/xen/include/asm-x86/msr.h
@@ -78,9 +78,9 @@ static inline int wrmsr_safe(unsigned int msr, uint64_t val)
__asm__ __volatile__("rdtsc" : "=a" (low) : : "edx")
#define rdtscll(val) do { \
- unsigned int a,d; \
- asm volatile("rdtsc" : "=a" (a), "=d" (d)); \
- (val) = ((unsigned long)a) | (((unsigned long)d)<<32); \
+ unsigned int _eax, _edx; \
+ asm volatile("rdtsc" : "=a" (_eax), "=d" (_edx)); \
+ (val) = ((unsigned long)_eax) | (((unsigned long)_edx)<<32); \
} while(0)
#define __write_tsc(val) wrmsrl(MSR_IA32_TSC, val)
diff --git a/xen/include/asm-x86/mtrr.h b/xen/include/asm-x86/mtrr.h
index 6b4d632..328ba04 100644
--- a/xen/include/asm-x86/mtrr.h
+++ b/xen/include/asm-x86/mtrr.h
@@ -20,7 +20,6 @@
enum {
PAT_TYPE_UNCACHABLE=0,
PAT_TYPE_WRCOMB=1,
- PAT_TYPE_RESERVED=2,
PAT_TYPE_WRTHROUGH=4,
PAT_TYPE_WRPROT=5,
PAT_TYPE_WRBACK=6,
@@ -34,6 +33,14 @@ enum {
an 8 bit field: */
typedef u8 mtrr_type;
+#define MTRR_PHYSMASK_VALID_BIT 11
+#define MTRR_PHYSMASK_VALID (1 << MTRR_PHYSMASK_VALID_BIT)
+#define MTRR_PHYSMASK_SHIFT 12
+#define MTRR_PHYSBASE_TYPE_MASK 0xff
+#define MTRR_PHYSBASE_SHIFT 12
+/* Number of variable range MSR pairs we emulate for HVM guests: */
+#define MTRR_VCNT 8
+
struct mtrr_var_range {
uint64_t base;
uint64_t mask;
@@ -65,8 +72,9 @@ extern int mtrr_del_page(int reg, unsigned long base, unsigned long size);
extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
extern u32 get_pat_flags(struct vcpu *v, u32 gl1e_flags, paddr_t gpaddr,
paddr_t spaddr, uint8_t gmtrr_mtype);
-extern uint8_t epte_get_entry_emt(struct domain *d, unsigned long gfn,
- mfn_t mfn, uint8_t *ipat, bool_t direct_mmio);
+extern int epte_get_entry_emt(struct domain *, unsigned long gfn, mfn_t mfn,
+ unsigned int order, uint8_t *ipat,
+ bool_t direct_mmio);
extern void ept_change_entry_emt_with_range(
struct domain *d, unsigned long start_gfn, unsigned long end_gfn);
extern unsigned char pat_type_2_pte_flags(unsigned char pat_type);
@@ -75,12 +83,13 @@ extern void mtrr_aps_sync_begin(void);
extern void mtrr_aps_sync_end(void);
extern void mtrr_bp_restore(void);
-extern bool_t mtrr_var_range_msr_set(
- struct domain *d, struct mtrr_state *m,
- uint32_t msr, uint64_t msr_content);
-extern bool_t mtrr_fix_range_msr_set(struct mtrr_state *v,
- uint32_t row, uint64_t msr_content);
-extern bool_t mtrr_def_type_msr_set(struct mtrr_state *v, uint64_t msr_content);
+extern bool_t mtrr_var_range_msr_set(struct domain *, struct mtrr_state *,
+ uint32_t msr, uint64_t msr_content);
+extern bool_t mtrr_fix_range_msr_set(struct domain *, struct mtrr_state *,
+ uint32_t row, uint64_t msr_content);
+extern bool_t mtrr_def_type_msr_set(struct domain *, struct mtrr_state *,
+ uint64_t msr_content);
+extern void memory_type_changed(struct domain *);
extern bool_t pat_msr_set(uint64_t *pat, uint64_t msr);
bool_t is_var_mtrr_overlapped(struct mtrr_state *m);
diff --git a/xen/include/asm-x86/nmi.h b/xen/include/asm-x86/nmi.h
index 98b5e04..2c92db9 100644
--- a/xen/include/asm-x86/nmi.h
+++ b/xen/include/asm-x86/nmi.h
@@ -8,16 +8,19 @@ struct cpu_user_regs;
/* Watchdog boolean from the command line */
extern bool_t opt_watchdog;
+
+/* Watchdog force parameter from the command line */
+extern bool_t watchdog_force;
-typedef int (*nmi_callback_t)(struct cpu_user_regs *regs, int cpu);
+typedef int (*nmi_callback_t)(const struct cpu_user_regs *regs, int cpu);
/**
* set_nmi_callback
*
* Set a handler for an NMI. Only one handler may be
- * set. Return 1 if the NMI was handled.
+ * set. Return the old nmi callback handler.
*/
-void set_nmi_callback(nmi_callback_t callback);
+nmi_callback_t set_nmi_callback(nmi_callback_t callback);
/**
* unset_nmi_callback
diff --git a/xen/include/asm-x86/nops.h b/xen/include/asm-x86/nops.h
new file mode 100644
index 0000000..05f9162
--- /dev/null
+++ b/xen/include/asm-x86/nops.h
@@ -0,0 +1,66 @@
+#ifndef __X86_ASM_NOPS_H__
+#define __X86_ASM_NOPS_H__
+
+#include <xen/config.h>
+
+/*
+ * Define nops for use with alternative().
+ */
+
+/*
+ * Opteron 64bit nops
+ * 1: nop
+ * 2: osp nop
+ * 3: osp osp nop
+ * 4: osp osp osp nop
+ */
+#define K8_NOP1 0x90
+#define K8_NOP2 0x66,K8_NOP1
+#define K8_NOP3 0x66,K8_NOP2
+#define K8_NOP4 0x66,K8_NOP3
+#define K8_NOP5 K8_NOP3,K8_NOP2
+#define K8_NOP6 K8_NOP3,K8_NOP3
+#define K8_NOP7 K8_NOP4,K8_NOP3
+#define K8_NOP8 K8_NOP4,K8_NOP4
+
+/*
+ * P6 nops
+ * uses eax dependencies (Intel-recommended choice)
+ * 1: nop
+ * 2: osp nop
+ * 3: nopl (%eax)
+ * 4: nopl 0x00(%eax)
+ * 5: nopl 0x00(%eax,%eax,1)
+ * 6: osp nopl 0x00(%eax,%eax,1)
+ * 7: nopl 0x00000000(%eax)
+ * 8: nopl 0x00000000(%eax,%eax,1)
+ * Note: All the above are assumed to be a single instruction.
+ * There is kernel code that depends on this.
+ */
+#define P6_NOP1 0x90
+#define P6_NOP2 0x66,0x90
+#define P6_NOP3 0x0f,0x1f,0x00
+#define P6_NOP4 0x0f,0x1f,0x40,0
+#define P6_NOP5 0x0f,0x1f,0x44,0x00,0
+#define P6_NOP6 0x66,0x0f,0x1f,0x44,0x00,0
+#define P6_NOP7 0x0f,0x1f,0x80,0,0,0,0
+#define P6_NOP8 0x0f,0x1f,0x84,0x00,0,0,0,0
+
+#ifdef __ASSEMBLY__
+#define _ASM_MK_NOP(x) .byte x
+#else
+#define _ASM_MK_NOP(x) ".byte " __stringify(x) "\n"
+#endif
+
+#define ASM_NOP1 _ASM_MK_NOP(K8_NOP1)
+#define ASM_NOP2 _ASM_MK_NOP(K8_NOP2)
+#define ASM_NOP3 _ASM_MK_NOP(K8_NOP3)
+#define ASM_NOP4 _ASM_MK_NOP(K8_NOP4)
+#define ASM_NOP5 _ASM_MK_NOP(K8_NOP5)
+#define ASM_NOP6 _ASM_MK_NOP(K8_NOP6)
+#define ASM_NOP7 _ASM_MK_NOP(K8_NOP7)
+#define ASM_NOP8 _ASM_MK_NOP(K8_NOP8)
+
+#define ASM_NOP_MAX 8
+
+#endif /* __X86_ASM_NOPS_H__ */
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index a2cb1b7..5f7fe71 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -29,6 +29,7 @@
#include <xen/config.h>
#include <xen/paging.h>
+#include <xen/p2m-common.h>
#include <asm/mem_sharing.h>
#include <asm/page.h> /* for pagetable_t */
@@ -70,36 +71,9 @@ typedef enum {
p2m_ram_paging_in = 11, /* Memory that is being paged in */
p2m_ram_shared = 12, /* Shared or sharable memory */
p2m_ram_broken = 13, /* Broken page, access cause domain crash */
+ p2m_map_foreign = 14, /* ram pages from foreign domain */
} p2m_type_t;
-/*
- * Additional access types, which are used to further restrict
- * the permissions given my the p2m_type_t memory type. Violations
- * caused by p2m_access_t restrictions are sent to the mem_event
- * interface.
- *
- * The access permissions are soft state: when any ambigious change of page
- * type or use occurs, or when pages are flushed, swapped, or at any other
- * convenient type, the access permissions can get reset to the p2m_domain
- * default.
- */
-typedef enum {
- p2m_access_n = 0, /* No access permissions allowed */
- p2m_access_r = 1,
- p2m_access_w = 2,
- p2m_access_rw = 3,
- p2m_access_x = 4,
- p2m_access_rx = 5,
- p2m_access_wx = 6,
- p2m_access_rwx = 7,
- p2m_access_rx2rw = 8, /* Special: page goes from RX to RW on write */
- p2m_access_n2rwx = 9, /* Special: page goes from N to RWX on access, *
- * generates an event but does not pause the
- * vcpu */
-
- /* NOTE: Assumed to be only 4 bits right now */
-} p2m_access_t;
-
/* Modifiers to the query */
typedef unsigned int p2m_query_t;
#define P2M_ALLOC (1u<<0) /* Populate PoD and paged-out entries */
@@ -139,6 +113,10 @@ typedef unsigned int p2m_query_t;
| p2m_to_mask(p2m_grant_map_ro) \
| p2m_to_mask(p2m_ram_shared) )
+/* Types that can be subject to bulk transitions. */
+#define P2M_CHANGEABLE_TYPES (p2m_to_mask(p2m_ram_rw) \
+ | p2m_to_mask(p2m_ram_logdirty) )
+
#define P2M_POD_TYPES (p2m_to_mask(p2m_populate_on_demand))
/* Pageable types */
@@ -167,6 +145,7 @@ typedef unsigned int p2m_query_t;
#define p2m_is_hole(_t) (p2m_to_mask(_t) & P2M_HOLE_TYPES)
#define p2m_is_mmio(_t) (p2m_to_mask(_t) & P2M_MMIO_TYPES)
#define p2m_is_readonly(_t) (p2m_to_mask(_t) & P2M_RO_TYPES)
+#define p2m_is_changeable(_t) (p2m_to_mask(_t) & P2M_CHANGEABLE_TYPES)
#define p2m_is_pod(_t) (p2m_to_mask(_t) & P2M_POD_TYPES)
#define p2m_is_grant(_t) (p2m_to_mask(_t) & P2M_GRANT_TYPES)
/* Grant types are *not* considered valid, because they can be
@@ -180,6 +159,11 @@ typedef unsigned int p2m_query_t;
#define p2m_is_sharable(_t) (p2m_to_mask(_t) & P2M_SHARABLE_TYPES)
#define p2m_is_shared(_t) (p2m_to_mask(_t) & P2M_SHARED_TYPES)
#define p2m_is_broken(_t) (p2m_to_mask(_t) & P2M_BROKEN_TYPES)
+#define p2m_is_foreign(_t) (p2m_to_mask(_t) & p2m_to_mask(p2m_map_foreign))
+
+#define p2m_is_any_ram(_t) (p2m_to_mask(_t) & \
+ (P2M_RAM_TYPES | P2M_GRANT_TYPES | \
+ p2m_to_mask(p2m_map_foreign)))
/* Per-p2m-table state */
struct p2m_domain {
@@ -209,6 +193,11 @@ struct p2m_domain {
* threaded on in LRU order. */
struct list_head np2m_list;
+ /* Host p2m: Log-dirty ranges registered for the domain. */
+ struct rangeset *logdirty_ranges;
+
+ /* Host p2m: Global log-dirty mode enabled for the domain. */
+ bool_t global_logdirty;
/* Host p2m: when this flag is set, don't flush all the nested-p2m
* tables on every host-p2m change. The setter of this flag
@@ -233,15 +222,19 @@ struct p2m_domain {
void (*change_entry_type_global)(struct p2m_domain *p2m,
p2m_type_t ot,
p2m_type_t nt);
+ int (*change_entry_type_range)(struct p2m_domain *p2m,
+ p2m_type_t ot, p2m_type_t nt,
+ unsigned long first_gfn,
+ unsigned long last_gfn);
+ void (*memory_type_changed)(struct p2m_domain *p2m);
void (*write_p2m_entry)(struct p2m_domain *p2m,
unsigned long gfn, l1_pgentry_t *p,
- mfn_t table_mfn, l1_pgentry_t new,
- unsigned int level);
+ l1_pgentry_t new, unsigned int level);
long (*audit_p2m)(struct p2m_domain *p2m);
/* Default P2M access type for each page in the the domain: new pages,
- * swapped in pages, cleared pages, and pages that are ambiquously
+ * swapped in pages, cleared pages, and pages that are ambiguously
* retyped get this access type. See definition of p2m_access_t. */
p2m_access_t default_access;
@@ -503,13 +496,22 @@ void p2m_change_type_range(struct domain *d,
p2m_type_t ot, p2m_type_t nt);
/* Compare-exchange the type of a single p2m entry */
-p2m_type_t p2m_change_type(struct domain *d, unsigned long gfn,
- p2m_type_t ot, p2m_type_t nt);
+int p2m_change_type_one(struct domain *d, unsigned long gfn,
+ p2m_type_t ot, p2m_type_t nt);
+
+/* Report a change affecting memory types. */
+void p2m_memory_type_changed(struct domain *d);
+
+int p2m_is_logdirty_range(struct p2m_domain *, unsigned long start,
+ unsigned long end);
/* Set mmio addresses in the p2m table (for pass-through) */
int set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn);
-int clear_mmio_p2m_entry(struct domain *d, unsigned long gfn);
+int clear_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn);
+/* Add foreign mapping to the guest's p2m table. */
+int p2m_add_foreign(struct domain *tdom, unsigned long fgfn,
+ unsigned long gpfn, domid_t foreign_domid);
/*
* Populate-on-demand
@@ -568,21 +570,39 @@ void p2m_mem_paging_resume(struct domain *d);
* been promoted with no underlying vcpu pause. If the req_ptr has been populated,
* then the caller must put the event in the ring (once having released get_gfn*
* locks -- caller must also xfree the request. */
-bool_t p2m_mem_access_check(paddr_t gpa, bool_t gla_valid, unsigned long gla,
- bool_t access_r, bool_t access_w, bool_t access_x,
- mem_event_request_t **req_ptr);
-/* Resumes the running of the VCPU, restarting the last instruction */
-void p2m_mem_access_resume(struct domain *d);
+bool_t p2m_mem_access_check(paddr_t gpa, unsigned long gla,
+ struct npfec npfec,
+ mem_event_request_t **req_ptr);
/* Set access type for a region of pfns.
* If start_pfn == -1ul, sets the default access type */
-long p2m_set_mem_access(struct domain *d, unsigned long start_pfn,
- uint32_t nr, hvmmem_access_t access);
+long p2m_set_mem_access(struct domain *d, unsigned long start_pfn, uint32_t nr,
+ uint32_t start, uint32_t mask, xenmem_access_t access);
/* Get access type for a pfn
* If pfn == -1ul, gets the default access type */
-int p2m_get_mem_access(struct domain *d, unsigned long pfn,
- hvmmem_access_t *access);
+int p2m_get_mem_access(struct domain *d, unsigned long pfn,
+ xenmem_access_t *access);
+
+/* Check for emulation and mark vcpu for skipping one instruction
+ * upon rescheduling if required. */
+void p2m_mem_event_emulate_check(struct vcpu *v,
+ const mem_event_response_t *rsp);
+
+/* Enable arch specific introspection options (such as MSR interception). */
+void p2m_setup_introspection(struct domain *d);
+
+/* Sanity check for mem_event hardware support */
+static inline bool_t p2m_mem_event_sanity_check(struct domain *d)
+{
+ return hap_enabled(d) && cpu_has_vmx;
+}
+
+/* Sanity check for mem_access hardware support */
+static inline bool_t p2m_mem_access_sanity_check(struct domain *d)
+{
+ return is_hvm_domain(d);
+}
/*
* Internal functions, only called by other p2m code
@@ -593,7 +613,7 @@ void p2m_free_ptp(struct p2m_domain *p2m, struct page_info *pg);
/* Directly set a p2m entry: only for use by p2m code. Does not need
* a call to put_gfn afterwards/ */
-int set_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
+int p2m_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
unsigned int page_order, p2m_type_t p2mt, p2m_access_t p2ma);
/* Set up function pointers for PT implementation: only for use by p2m code */
@@ -648,6 +668,8 @@ static inline p2m_type_t p2m_flags_to_type(unsigned long flags)
return (flags >> 12) & 0x7f;
}
+int p2m_pt_handle_deferred_changes(uint64_t gpa);
+
/*
* Nested p2m: shadow p2m tables used for nested HVM virtualization
*/
@@ -658,7 +680,34 @@ void p2m_flush(struct vcpu *v, struct p2m_domain *p2m);
void p2m_flush_nestedp2m(struct domain *d);
void nestedp2m_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
- l1_pgentry_t *p, mfn_t table_mfn, l1_pgentry_t new, unsigned int level);
+ l1_pgentry_t *p, l1_pgentry_t new, unsigned int level);
+
+/*
+ * p2m type to IOMMU flags
+ */
+static inline unsigned int p2m_get_iommu_flags(p2m_type_t p2mt)
+{
+ unsigned int flags;
+
+ switch( p2mt )
+ {
+ case p2m_ram_rw:
+ case p2m_grant_map_rw:
+ case p2m_ram_logdirty:
+ case p2m_map_foreign:
+ flags = IOMMUF_readable | IOMMUF_writable;
+ break;
+ case p2m_ram_ro:
+ case p2m_grant_map_ro:
+ flags = IOMMUF_readable;
+ break;
+ default:
+ flags = 0;
+ break;
+ }
+
+ return flags;
+}
#endif /* _XEN_P2M_H */
diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h
index ccc268d..a8bc999 100644
--- a/xen/include/asm-x86/page.h
+++ b/xen/include/asm-x86/page.h
@@ -334,8 +334,6 @@ void *alloc_xen_pagetable(void);
void free_xen_pagetable(void *v);
l1_pgentry_t *virt_to_xen_l1e(unsigned long v);
-extern void set_pdx_range(unsigned long smfn, unsigned long emfn);
-
/* Convert between PAT/PCD/PWT embedded in PTE flags and 3-bit cacheattr. */
static inline uint32_t pte_flags_to_cacheattr(uint32_t flags)
{
@@ -346,9 +344,6 @@ static inline uint32_t cacheattr_to_pte_flags(uint32_t cacheattr)
return ((cacheattr & 4) << 5) | ((cacheattr & 3) << 3);
}
-/* No cache maintenance required on x86 architecture. */
-static inline void flush_page_to_ram(unsigned long mfn) {}
-
/* return true if permission increased */
static inline bool_t
perms_strictly_increased(uint32_t old_flags, uint32_t new_flags)
diff --git a/xen/include/asm-x86/paging.h b/xen/include/asm-x86/paging.h
index 8dd2a61..5f810f6 100644
--- a/xen/include/asm-x86/paging.h
+++ b/xen/include/asm-x86/paging.h
@@ -111,9 +111,8 @@ struct paging_mode {
unsigned int *page_order);
void (*update_cr3 )(struct vcpu *v, int do_locking);
void (*update_paging_modes )(struct vcpu *v);
- void (*write_p2m_entry )(struct vcpu *v, unsigned long gfn,
- l1_pgentry_t *p, mfn_t table_mfn,
- l1_pgentry_t new,
+ void (*write_p2m_entry )(struct domain *d, unsigned long gfn,
+ l1_pgentry_t *p, l1_pgentry_t new,
unsigned int level);
int (*write_guest_entry )(struct vcpu *v, intpte_t *p,
intpte_t new, mfn_t gmfn);
@@ -133,9 +132,6 @@ struct paging_mode {
/*****************************************************************************
* Log dirty code */
-/* free log dirty bitmap resource */
-void paging_free_log_dirty_bitmap(struct domain *d);
-
/* get the dirty bitmap for a specific range of pfns */
void paging_log_dirty_range(struct domain *d,
unsigned long begin_pfn,
@@ -145,9 +141,6 @@ void paging_log_dirty_range(struct domain *d,
/* enable log dirty */
int paging_log_dirty_enable(struct domain *d, bool_t log_global);
-/* disable log dirty */
-int paging_log_dirty_disable(struct domain *d);
-
/* log dirty initialization */
void paging_log_dirty_init(struct domain *d,
int (*enable_log_dirty)(struct domain *d,
@@ -204,10 +197,13 @@ int paging_domain_init(struct domain *d, unsigned int domcr_flags);
* and disable ephemeral shadow modes (test mode and log-dirty mode) and
* manipulate the log-dirty bitmap. */
int paging_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
- XEN_GUEST_HANDLE_PARAM(void) u_domctl);
+ XEN_GUEST_HANDLE_PARAM(void) u_domctl, bool_t resuming);
+
+/* Helper hypercall for dealing with continuations. */
+long paging_domctl_continuation(XEN_GUEST_HANDLE_PARAM(xen_domctl_t));
/* Call when destroying a domain */
-void paging_teardown(struct domain *d);
+int paging_teardown(struct domain *d);
/* Call once all of the references to the domain have gone away */
void paging_final_teardown(struct domain *d);
@@ -335,9 +331,9 @@ static inline void safe_write_pte(l1_pgentry_t *p, l1_pgentry_t new)
* we are writing. */
struct p2m_domain;
-void paging_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
- l1_pgentry_t *p, mfn_t table_mfn,
- l1_pgentry_t new, unsigned int level);
+void paging_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
+ l1_pgentry_t *p, l1_pgentry_t new,
+ unsigned int level);
/* Called from the guest to indicate that the a process is being
* torn down and its pagetables will soon be discarded */
diff --git a/xen/include/asm-x86/perfc_defn.h b/xen/include/asm-x86/perfc_defn.h
index 7d802cc..170da00 100644
--- a/xen/include/asm-x86/perfc_defn.h
+++ b/xen/include/asm-x86/perfc_defn.h
@@ -120,6 +120,7 @@ PERFCOUNTER(mshv_rdmsr_hc_page, "MS Hv rdmsr hypercall page")
PERFCOUNTER(mshv_rdmsr_vp_index, "MS Hv rdmsr vp index")
PERFCOUNTER(mshv_rdmsr_tsc_frequency, "MS Hv rdmsr TSC frequency")
PERFCOUNTER(mshv_rdmsr_apic_frequency, "MS Hv rdmsr APIC frequency")
+PERFCOUNTER(mshv_rdmsr_time_ref_count, "MS Hv rdmsr time ref count")
PERFCOUNTER(mshv_rdmsr_icr, "MS Hv rdmsr icr")
PERFCOUNTER(mshv_rdmsr_tpr, "MS Hv rdmsr tpr")
PERFCOUNTER(mshv_rdmsr_apic_assist, "MS Hv rdmsr APIC assist")
diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
index c120460..f98eaf5 100644
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -113,6 +113,7 @@
#define TRAP_alignment_check 17
#define TRAP_machine_check 18
#define TRAP_simd_error 19
+#define TRAP_virtualisation 20
#define TRAP_last_reserved 31
/* Set for entry via SYSCALL. Informs return code to use SYSRETQ not IRETQ. */
@@ -141,6 +142,12 @@
#define PFEC_page_paged (1U<<5)
#define PFEC_page_shared (1U<<6)
+#define XEN_MINIMAL_CR4 (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE)
+
+#define XEN_SYSCALL_MASK (X86_EFLAGS_AC|X86_EFLAGS_VM|X86_EFLAGS_RF| \
+ X86_EFLAGS_NT|X86_EFLAGS_DF|X86_EFLAGS_IF| \
+ X86_EFLAGS_TF)
+
#ifndef __ASSEMBLY__
struct domain;
@@ -162,6 +169,7 @@ struct cpuinfo_x86 {
__u8 x86_model;
__u8 x86_mask;
int cpuid_level; /* Maximum supported CPUID level, -1=no CPUID */
+ __u32 extended_cpuid_level; /* Maximum supported CPUID extended level */
unsigned int x86_capability[NCAPINTS];
char x86_vendor_id[16];
char x86_model_id[64];
@@ -191,6 +199,7 @@ extern void set_cpuid_faulting(bool_t enable);
extern u64 host_pat;
extern bool_t opt_cpu_info;
+extern u32 cpuid_ext_features;
/* Maximum width of physical addresses supported by the hardware */
extern unsigned int paddr_bits;
@@ -203,15 +212,13 @@ extern void dodgy_tsc(void);
extern void detect_extended_topology(struct cpuinfo_x86 *c);
-#ifdef CONFIG_X86_HT
extern void detect_ht(struct cpuinfo_x86 *c);
-#else
-static always_inline void detect_ht(struct cpuinfo_x86 *c) {}
-#endif
#define cpu_to_core(_cpu) (cpu_data[_cpu].cpu_core_id)
#define cpu_to_socket(_cpu) (cpu_data[_cpu].phys_proc_id)
+unsigned int apicid_to_socket(unsigned int);
+
/*
* Generic CPUID function
* clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
@@ -411,7 +418,7 @@ static always_inline void __mwait(unsigned long eax, unsigned long ecx)
#define IOBMP_BYTES 8192
#define IOBMP_INVALID_OFFSET 0x8000
-struct tss_struct {
+struct __packed __cacheline_aligned tss_struct {
unsigned short back_link,__blh;
union { u64 rsp0, esp0; };
union { u64 rsp1, esp1; };
@@ -425,7 +432,7 @@ struct tss_struct {
u16 bitmap;
/* Pads the TSS to be cacheline-aligned (total size is 0x80). */
u8 __cacheline_filler[24];
-} __cacheline_aligned __attribute__((packed));
+};
#define IST_NONE 0UL
#define IST_DF 1UL
@@ -461,17 +468,6 @@ long set_gdt(struct vcpu *d,
unsigned long *frames,
unsigned int entries);
-#define write_debugreg(reg, val) do { \
- unsigned long __val = val; \
- asm volatile ( "mov %0,%%db" #reg : : "r" (__val) ); \
-} while (0)
-#define read_debugreg(reg) ({ \
- unsigned long __val; \
- asm volatile ( "mov %%db" #reg ",%0" : "=r" (__val) ); \
- __val; \
-})
-long set_debugreg(struct vcpu *p, int reg, unsigned long value);
-
/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
static always_inline void rep_nop(void)
{
@@ -480,76 +476,56 @@ static always_inline void rep_nop(void)
#define cpu_relax() rep_nop()
-/* Prefetch instructions for Pentium III and AMD Athlon */
-#ifdef CONFIG_MPENTIUMIII
-
-#define ARCH_HAS_PREFETCH
-extern always_inline void prefetch(const void *x)
-{
- asm volatile ( "prefetchnta (%0)" : : "r"(x) );
-}
-
-#elif CONFIG_X86_USE_3DNOW
-
-#define ARCH_HAS_PREFETCH
-#define ARCH_HAS_PREFETCHW
-#define ARCH_HAS_SPINLOCK_PREFETCH
-
-extern always_inline void prefetch(const void *x)
-{
- asm volatile ( "prefetch (%0)" : : "r"(x) );
-}
-
-extern always_inline void prefetchw(const void *x)
-{
- asm volatile ( "prefetchw (%0)" : : "r"(x) );
-}
-#define spin_lock_prefetch(x) prefetchw(x)
-
-#endif
-
-void show_stack(struct cpu_user_regs *regs);
+void show_stack(const struct cpu_user_regs *regs);
void show_stack_overflow(unsigned int cpu, const struct cpu_user_regs *regs);
-void show_registers(struct cpu_user_regs *regs);
-void show_execution_state(struct cpu_user_regs *regs);
+void show_registers(const struct cpu_user_regs *regs);
+void show_execution_state(const struct cpu_user_regs *regs);
#define dump_execution_state() run_in_exception_handler(show_execution_state)
void show_page_walk(unsigned long addr);
-void fatal_trap(int trapnr, struct cpu_user_regs *regs);
+void noreturn fatal_trap(const struct cpu_user_regs *regs);
-void compat_show_guest_stack(struct vcpu *, struct cpu_user_regs *, int lines);
+void compat_show_guest_stack(struct vcpu *v,
+ const struct cpu_user_regs *regs, int lines);
extern void mtrr_ap_init(void);
extern void mtrr_bp_init(void);
void mcheck_init(struct cpuinfo_x86 *c, bool_t bsp);
-#define DECLARE_TRAP_HANDLER(_name) \
-void _name(void); \
-void do_ ## _name(struct cpu_user_regs *regs)
+#define DECLARE_TRAP_HANDLER(_name) \
+ void _name(void); \
+ void do_ ## _name(struct cpu_user_regs *regs)
+#define DECLARE_TRAP_HANDLER_CONST(_name) \
+ void _name(void); \
+ void do_ ## _name(const struct cpu_user_regs *regs)
+
DECLARE_TRAP_HANDLER(divide_error);
DECLARE_TRAP_HANDLER(debug);
-DECLARE_TRAP_HANDLER(nmi);
-DECLARE_TRAP_HANDLER(nmi_crash);
+DECLARE_TRAP_HANDLER_CONST(nmi);
DECLARE_TRAP_HANDLER(int3);
DECLARE_TRAP_HANDLER(overflow);
DECLARE_TRAP_HANDLER(bounds);
DECLARE_TRAP_HANDLER(invalid_op);
DECLARE_TRAP_HANDLER(device_not_available);
-DECLARE_TRAP_HANDLER(coprocessor_segment_overrun);
+DECLARE_TRAP_HANDLER(double_fault);
DECLARE_TRAP_HANDLER(invalid_TSS);
DECLARE_TRAP_HANDLER(segment_not_present);
DECLARE_TRAP_HANDLER(stack_segment);
DECLARE_TRAP_HANDLER(general_protection);
DECLARE_TRAP_HANDLER(page_fault);
+DECLARE_TRAP_HANDLER(early_page_fault);
DECLARE_TRAP_HANDLER(coprocessor_error);
DECLARE_TRAP_HANDLER(simd_coprocessor_error);
-DECLARE_TRAP_HANDLER(machine_check);
+DECLARE_TRAP_HANDLER_CONST(machine_check);
DECLARE_TRAP_HANDLER(alignment_check);
-DECLARE_TRAP_HANDLER(spurious_interrupt_bug);
+
+#undef DECLARE_TRAP_HANDLER_CONST
#undef DECLARE_TRAP_HANDLER
void trap_nop(void);
void enable_nmis(void);
+void noreturn do_nmi_crash(struct cpu_user_regs *regs);
+void do_reserved_trap(struct cpu_user_regs *regs);
void syscall_enter(void);
void sysenter_entry(void);
diff --git a/xen/include/asm-x86/psr.h b/xen/include/asm-x86/psr.h
new file mode 100644
index 0000000..c6076e9
--- /dev/null
+++ b/xen/include/asm-x86/psr.h
@@ -0,0 +1,61 @@
+/*
+ * psr.h: Platform Shared Resource related service for guest.
+ *
+ * Copyright (c) 2014, Intel Corporation
+ * Author: Dongxiao Xu <dongxiao.xu at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+#ifndef __ASM_PSR_H__
+#define __ASM_PSR_H__
+
+#include <xen/types.h>
+
+/* Resource Type Enumeration */
+#define PSR_RESOURCE_TYPE_L3 0x2
+
+/* L3 Monitoring Features */
+#define PSR_CMT_L3_OCCUPANCY 0x1
+
+struct psr_cmt_l3 {
+ unsigned int features;
+ unsigned int upscaling_factor;
+ unsigned int rmid_max;
+};
+
+struct psr_cmt {
+ unsigned int rmid_max;
+ unsigned int features;
+ domid_t *rmid_to_dom;
+ struct psr_cmt_l3 l3;
+};
+
+extern struct psr_cmt *psr_cmt;
+
+static inline bool_t psr_cmt_enabled(void)
+{
+ return !!psr_cmt;
+}
+
+int psr_alloc_rmid(struct domain *d);
+void psr_free_rmid(struct domain *d);
+void psr_assoc_rmid(unsigned int rmid);
+
+#endif /* __ASM_PSR_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-x86/setup.h b/xen/include/asm-x86/setup.h
index 3039e1b..8f8c6f3 100644
--- a/xen/include/asm-x86/setup.h
+++ b/xen/include/asm-x86/setup.h
@@ -7,7 +7,6 @@ extern unsigned long xenheap_initial_phys_start;
void early_cpu_init(void);
void early_time_init(void);
-void early_page_fault(void);
int intel_cpu_init(void);
int amd_init_cpu(void);
diff --git a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h
index 348915e..f40cab4 100644
--- a/xen/include/asm-x86/shadow.h
+++ b/xen/include/asm-x86/shadow.h
@@ -44,10 +44,6 @@
#define shadow_mode_external(_d) (paging_mode_shadow(_d) && \
paging_mode_external(_d))
-/* Xen traps & emulates all reads of all page table pages:
- * not yet supported */
-#define shadow_mode_trap_reads(_d) ({ (void)(_d); 0; })
-
/*****************************************************************************
* Entry points into the shadow code */
diff --git a/xen/include/asm-x86/softirq.h b/xen/include/asm-x86/softirq.h
index 9d8e2e1..ec787d6 100644
--- a/xen/include/asm-x86/softirq.h
+++ b/xen/include/asm-x86/softirq.h
@@ -7,6 +7,9 @@
#define MACHINE_CHECK_SOFTIRQ (NR_COMMON_SOFTIRQS + 3)
#define PCI_SERR_SOFTIRQ (NR_COMMON_SOFTIRQS + 4)
-#define NR_ARCH_SOFTIRQS 5
+#define HVM_DPCI_SOFTIRQ (NR_COMMON_SOFTIRQS + 5)
+#define NR_ARCH_SOFTIRQS 6
+
+bool_t arch_skip_send_event_check(unsigned int cpu);
#endif /* __ASM_SOFTIRQ_H__ */
diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h
index e9602aa..7111329 100644
--- a/xen/include/asm-x86/system.h
+++ b/xen/include/asm-x86/system.h
@@ -179,6 +179,8 @@ static inline int local_irq_is_enabled(void)
#define BROKEN_INIT_AFTER_S1 0x0002
void trap_init(void);
+void init_idt_traps(void);
+void load_system_tables(void);
void percpu_traps_init(void);
void subarch_percpu_traps_init(void);
diff --git a/xen/include/asm-x86/tboot.h b/xen/include/asm-x86/tboot.h
index e77d1c0..d242862 100644
--- a/xen/include/asm-x86/tboot.h
+++ b/xen/include/asm-x86/tboot.h
@@ -39,10 +39,6 @@
#include <xen/acpi.h>
-#ifndef __packed
-#define __packed __attribute__ ((packed))
-#endif
-
typedef struct __packed {
uint32_t data1;
uint16_t data2;
diff --git a/xen/include/asm-x86/time.h b/xen/include/asm-x86/time.h
index 147b39e..c4d82f6 100644
--- a/xen/include/asm-x86/time.h
+++ b/xen/include/asm-x86/time.h
@@ -44,13 +44,10 @@ int time_resume(void);
void init_percpu_time(void);
struct ioreq;
-int dom0_pit_access(struct ioreq *ioreq);
+int hwdom_pit_access(struct ioreq *ioreq);
int cpu_frequency_change(u64 freq);
-struct tm;
-struct tm wallclock_time(void);
-
void pit_broadcast_enter(void);
void pit_broadcast_exit(void);
int pit_broadcast_is_available(void);
@@ -74,9 +71,13 @@ void tsc_get_info(struct domain *d, uint32_t *tsc_mode, uint64_t *elapsed_nsec,
void force_update_vcpu_system_time(struct vcpu *v);
int host_tsc_is_safe(void);
-void cpuid_time_leaf(uint32_t sub_idx, unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx);
+void cpuid_time_leaf(uint32_t sub_idx, uint32_t *eax, uint32_t *ebx,
+ uint32_t *ecx, uint32_t *edx);
u64 stime2tsc(s_time_t stime);
+struct time_scale;
+void set_time_scale(struct time_scale *ts, u64 ticks_per_sec);
+u64 scale_delta(u64 delta, struct time_scale *scale);
+
#endif /* __X86_TIME_H__ */
diff --git a/xen/include/asm-x86/traps.h b/xen/include/asm-x86/traps.h
index 556b133..ebb6378 100644
--- a/xen/include/asm-x86/traps.h
+++ b/xen/include/asm-x86/traps.h
@@ -28,8 +28,6 @@ struct softirq_trap {
struct cpu_user_regs;
-extern void machine_check_vector(struct cpu_user_regs *regs, long error_code);
-
void async_exception_cleanup(struct vcpu *);
/**
diff --git a/xen/include/asm-x86/types.h b/xen/include/asm-x86/types.h
index 9da3053..b82fa58 100644
--- a/xen/include/asm-x86/types.h
+++ b/xen/include/asm-x86/types.h
@@ -39,6 +39,7 @@ typedef __SIZE_TYPE__ size_t;
#else
typedef unsigned long size_t;
#endif
+typedef signed long ssize_t;
typedef char bool_t;
#define test_and_set_bool(b) xchg(&(b), 1)
diff --git a/xen/include/asm-x86/uaccess.h b/xen/include/asm-x86/uaccess.h
index 88b4ba2..947470d 100644
--- a/xen/include/asm-x86/uaccess.h
+++ b/xen/include/asm-x86/uaccess.h
@@ -146,6 +146,7 @@ struct __large_struct { unsigned long buf[100]; };
* aliasing issues.
*/
#define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \
+ stac(); \
__asm__ __volatile__( \
"1: mov"itype" %"rtype"1,%2\n" \
"2:\n" \
@@ -155,9 +156,11 @@ struct __large_struct { unsigned long buf[100]; };
".previous\n" \
_ASM_EXTABLE(1b, 3b) \
: "=r"(err) \
- : ltype (x), "m"(__m(addr)), "i"(errret), "0"(err))
+ : ltype (x), "m"(__m(addr)), "i"(errret), "0"(err)); \
+ clac()
#define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \
+ stac(); \
__asm__ __volatile__( \
"1: mov"itype" %2,%"rtype"1\n" \
"2:\n" \
@@ -168,7 +171,8 @@ struct __large_struct { unsigned long buf[100]; };
".previous\n" \
_ASM_EXTABLE(1b, 3b) \
: "=r"(err), ltype (x) \
- : "m"(__m(addr)), "i"(errret), "0"(err))
+ : "m"(__m(addr)), "i"(errret), "0"(err)); \
+ clac()
/**
* __copy_to_user: - Copy a block of data into user space, with less checking
diff --git a/xen/include/asm-x86/x86_64/asm_defns.h b/xen/include/asm-x86/x86_64/asm_defns.h
deleted file mode 100644
index bf63ac1..0000000
--- a/xen/include/asm-x86/x86_64/asm_defns.h
+++ /dev/null
@@ -1,231 +0,0 @@
-#ifndef __X86_64_ASM_DEFNS_H__
-#define __X86_64_ASM_DEFNS_H__
-
-#include <asm/percpu.h>
-
-#ifdef CONFIG_FRAME_POINTER
-/* Indicate special exception stack frame by inverting the frame pointer. */
-#define SETUP_EXCEPTION_FRAME_POINTER(offs) \
- leaq offs(%rsp),%rbp; \
- notq %rbp
-#else
-#define SETUP_EXCEPTION_FRAME_POINTER(offs)
-#endif
-
-#ifndef NDEBUG
-#define ASSERT_INTERRUPT_STATUS(x) \
- pushf; \
- testb $X86_EFLAGS_IF>>8,1(%rsp); \
- j##x 1f; \
- ud2a; \
-1: addq $8,%rsp;
-#else
-#define ASSERT_INTERRUPT_STATUS(x)
-#endif
-
-#define ASSERT_INTERRUPTS_ENABLED ASSERT_INTERRUPT_STATUS(nz)
-#define ASSERT_INTERRUPTS_DISABLED ASSERT_INTERRUPT_STATUS(z)
-
-/*
- * This flag is set in an exception frame when registers R12-R15 did not get
- * saved.
- */
-#define _TRAP_regs_partial 16
-#define TRAP_regs_partial (1 << _TRAP_regs_partial)
-/*
- * This flag gets set in an exception frame when registers R12-R15 possibly
- * get modified from their originally saved values and hence need to be
- * restored even if the normal call flow would restore register values.
- *
- * The flag being set implies _TRAP_regs_partial to be unset. Restoring
- * R12-R15 thus is
- * - required when this flag is set,
- * - safe when _TRAP_regs_partial is unset.
- */
-#define _TRAP_regs_dirty 17
-#define TRAP_regs_dirty (1 << _TRAP_regs_dirty)
-
-#define mark_regs_dirty(r) ({ \
- struct cpu_user_regs *r__ = (r); \
- ASSERT(!((r__)->entry_vector & TRAP_regs_partial)); \
- r__->entry_vector |= TRAP_regs_dirty; \
-})
-
-#define SAVE_ALL \
- addq $-(UREGS_error_code-UREGS_r15), %rsp; \
- cld; \
- movq %rdi,UREGS_rdi(%rsp); \
- movq %rsi,UREGS_rsi(%rsp); \
- movq %rdx,UREGS_rdx(%rsp); \
- movq %rcx,UREGS_rcx(%rsp); \
- movq %rax,UREGS_rax(%rsp); \
- movq %r8,UREGS_r8(%rsp); \
- movq %r9,UREGS_r9(%rsp); \
- movq %r10,UREGS_r10(%rsp); \
- movq %r11,UREGS_r11(%rsp); \
- movq %rbx,UREGS_rbx(%rsp); \
- movq %rbp,UREGS_rbp(%rsp); \
- SETUP_EXCEPTION_FRAME_POINTER(UREGS_rbp); \
- movq %r12,UREGS_r12(%rsp); \
- movq %r13,UREGS_r13(%rsp); \
- movq %r14,UREGS_r14(%rsp); \
- movq %r15,UREGS_r15(%rsp); \
-
-#ifdef __ASSEMBLY__
-
-/*
- * Save all registers not preserved by C code or used in entry/exit code. Mark
- * the frame as partial.
- *
- * @type: exception type
- * @compat: R8-R15 don't need saving, and the frame nevertheless is complete
- */
-.macro SAVE_VOLATILE type compat=0
-.if \compat
- movl $\type,UREGS_entry_vector-UREGS_error_code(%rsp)
-.else
- movl $\type|TRAP_regs_partial,\
- UREGS_entry_vector-UREGS_error_code(%rsp)
-.endif
- addq $-(UREGS_error_code-UREGS_r15),%rsp
- cld
- movq %rdi,UREGS_rdi(%rsp)
- movq %rsi,UREGS_rsi(%rsp)
- movq %rdx,UREGS_rdx(%rsp)
- movq %rcx,UREGS_rcx(%rsp)
- movq %rax,UREGS_rax(%rsp)
-.if !\compat
- movq %r8,UREGS_r8(%rsp)
- movq %r9,UREGS_r9(%rsp)
- movq %r10,UREGS_r10(%rsp)
- movq %r11,UREGS_r11(%rsp)
-.endif
- movq %rbx,UREGS_rbx(%rsp)
- movq %rbp,UREGS_rbp(%rsp)
- SETUP_EXCEPTION_FRAME_POINTER(UREGS_rbp)
-.endm
-
-/*
- * Complete a frame potentially only partially saved.
- */
-.macro SAVE_PRESERVED
- btrl $_TRAP_regs_partial,UREGS_entry_vector(%rsp)
- jnc 987f
- movq %r12,UREGS_r12(%rsp)
- movq %r13,UREGS_r13(%rsp)
- movq %r14,UREGS_r14(%rsp)
- movq %r15,UREGS_r15(%rsp)
-987:
-.endm
-
-/*
- * Reload registers not preserved by C code from frame.
- *
- * @compat: R8-R11 don't need reloading
- *
- * For the way it is used in RESTORE_ALL, this macro must preserve EFLAGS.ZF.
- */
-.macro LOAD_C_CLOBBERED compat=0
-.if !\compat
- movq UREGS_r11(%rsp),%r11
- movq UREGS_r10(%rsp),%r10
- movq UREGS_r9(%rsp),%r9
- movq UREGS_r8(%rsp),%r8
-.endif
- movq UREGS_rax(%rsp),%rax
- movq UREGS_rcx(%rsp),%rcx
- movq UREGS_rdx(%rsp),%rdx
- movq UREGS_rsi(%rsp),%rsi
- movq UREGS_rdi(%rsp),%rdi
-.endm
-
-/*
- * Restore all previously saved registers.
- *
- * @adj: extra stack pointer adjustment to be folded into the adjustment done
- * anyway at the end of the macro
- * @compat: R8-R15 don't need reloading
- */
-.macro RESTORE_ALL adj=0 compat=0
-.if !\compat
- testl $TRAP_regs_dirty,UREGS_entry_vector(%rsp)
-.endif
- LOAD_C_CLOBBERED \compat
-.if !\compat
- jz 987f
- movq UREGS_r15(%rsp),%r15
- movq UREGS_r14(%rsp),%r14
- movq UREGS_r13(%rsp),%r13
- movq UREGS_r12(%rsp),%r12
-#ifndef NDEBUG
- .subsection 1
-987: testl $TRAP_regs_partial,UREGS_entry_vector(%rsp)
- jnz 987f
- cmpq UREGS_r15(%rsp),%r15
- jne 789f
- cmpq UREGS_r14(%rsp),%r14
- jne 789f
- cmpq UREGS_r13(%rsp),%r13
- jne 789f
- cmpq UREGS_r12(%rsp),%r12
- je 987f
-789: ud2
- .subsection 0
-#endif
-.endif
-987: movq UREGS_rbp(%rsp),%rbp
- movq UREGS_rbx(%rsp),%rbx
- subq $-(UREGS_error_code-UREGS_r15+\adj), %rsp
-.endm
-
-#endif
-
-#ifdef PERF_COUNTERS
-#define PERFC_INCR(_name,_idx,_cur) \
- pushq _cur; \
- movslq VCPU_processor(_cur),_cur; \
- pushq %rdx; \
- leaq __per_cpu_offset(%rip),%rdx; \
- movq (%rdx,_cur,8),_cur; \
- leaq per_cpu__perfcounters(%rip),%rdx; \
- addq %rdx,_cur; \
- popq %rdx; \
- incl ASM_PERFC_##_name*4(_cur,_idx,4); \
- popq _cur
-#else
-#define PERFC_INCR(_name,_idx,_cur)
-#endif
-
-/* Work around AMD erratum #88 */
-#define safe_swapgs \
- "mfence; swapgs;"
-
-#ifdef __sun__
-#define REX64_PREFIX "rex64\\"
-#elif defined(__clang__)
-#define REX64_PREFIX ".byte 0x48; "
-#else
-#define REX64_PREFIX "rex64/"
-#endif
-
-#define BUILD_COMMON_IRQ() \
-__asm__( \
- "\n" __ALIGN_STR"\n" \
- "common_interrupt:\n\t" \
- STR(SAVE_ALL) "\n\t" \
- "movq %rsp,%rdi\n\t" \
- "callq " STR(do_IRQ) "\n\t" \
- "jmp ret_from_intr\n");
-
-#define BUILD_IRQ(nr) \
- "pushq $0\n\t" \
- "movl $"#nr",4(%rsp)\n\t" \
- "jmp common_interrupt"
-
-#ifdef __ASSEMBLY__
-# define _ASM_EX(p) p-.
-#else
-# define _ASM_EX(p) #p "-."
-#endif
-
-#endif /* __X86_64_ASM_DEFNS_H__ */
diff --git a/xen/include/asm-x86/x86_64/page.h b/xen/include/asm-x86/x86_64/page.h
index c193c88..1d54587 100644
--- a/xen/include/asm-x86/x86_64/page.h
+++ b/xen/include/asm-x86/x86_64/page.h
@@ -35,17 +35,10 @@
#include <xen/config.h>
#include <asm/types.h>
-extern unsigned long xen_virt_end;
+#include <xen/pdx.h>
-extern unsigned long max_pdx;
-extern unsigned long pfn_pdx_bottom_mask, ma_va_bottom_mask;
-extern unsigned int pfn_pdx_hole_shift;
-extern unsigned long pfn_hole_mask;
-extern unsigned long pfn_top_mask, ma_top_mask;
-extern void pfn_pdx_hole_setup(unsigned long);
+extern unsigned long xen_virt_end;
-#define page_to_pdx(pg) ((pg) - frame_table)
-#define pdx_to_page(pdx) (frame_table + (pdx))
#define spage_to_pdx(spg) (((spg) - spage_table)<<(SUPERPAGE_SHIFT-PAGE_SHIFT))
#define pdx_to_spage(pdx) (spage_table + ((pdx)>>(SUPERPAGE_SHIFT-PAGE_SHIFT)))
/*
@@ -57,20 +50,6 @@ extern void pfn_pdx_hole_setup(unsigned long);
#define pdx_to_virt(pdx) ((void *)(DIRECTMAP_VIRT_START + \
((unsigned long)(pdx) << PAGE_SHIFT)))
-extern int __mfn_valid(unsigned long mfn);
-
-static inline unsigned long pfn_to_pdx(unsigned long pfn)
-{
- return (pfn & pfn_pdx_bottom_mask) |
- ((pfn & pfn_top_mask) >> pfn_pdx_hole_shift);
-}
-
-static inline unsigned long pdx_to_pfn(unsigned long pdx)
-{
- return (pdx & pfn_pdx_bottom_mask) |
- ((pdx << pfn_pdx_hole_shift) & pfn_top_mask);
-}
-
static inline unsigned long pfn_to_sdx(unsigned long pfn)
{
return pfn_to_pdx(pfn) >> (SUPERPAGE_SHIFT-PAGE_SHIFT);
@@ -161,20 +140,15 @@ typedef l4_pgentry_t root_pgentry_t;
/* Bit 22 of a 24-bit flag mask. This corresponds to bit 62 of a pte.*/
#define _PAGE_GNTTAB (1U<<22)
-#define PAGE_HYPERVISOR (__PAGE_HYPERVISOR | _PAGE_GLOBAL)
-#define PAGE_HYPERVISOR_NOCACHE (__PAGE_HYPERVISOR_NOCACHE | _PAGE_GLOBAL)
-
-#define USER_MAPPINGS_ARE_GLOBAL
-#ifdef USER_MAPPINGS_ARE_GLOBAL
/*
* Bit 12 of a 24-bit flag mask. This corresponds to bit 52 of a pte.
* This is needed to distinguish between user and kernel PTEs since _PAGE_USER
* is asserted for both.
*/
#define _PAGE_GUEST_KERNEL (1U<<12)
-#else
-#define _PAGE_GUEST_KERNEL 0
-#endif
+
+#define PAGE_HYPERVISOR (__PAGE_HYPERVISOR | _PAGE_GLOBAL)
+#define PAGE_HYPERVISOR_NOCACHE (__PAGE_HYPERVISOR_NOCACHE | _PAGE_GLOBAL)
#endif /* __X86_64_PAGE_H__ */
diff --git a/xen/include/asm-x86/x86_64/system.h b/xen/include/asm-x86/x86_64/system.h
index 20f038b..662813a 100644
--- a/xen/include/asm-x86/x86_64/system.h
+++ b/xen/include/asm-x86/x86_64/system.h
@@ -12,6 +12,7 @@
* is the same as the initial value of _o then _n is written to location _p.
*/
#define __cmpxchg_user(_p,_o,_n,_isuff,_oppre,_regtype) \
+ stac(); \
asm volatile ( \
"1: lock; cmpxchg"_isuff" %"_oppre"2,%3\n" \
"2:\n" \
@@ -22,7 +23,8 @@
_ASM_EXTABLE(1b, 3b) \
: "=a" (_o), "=r" (_rc) \
: _regtype (_n), "m" (*__xg((volatile void *)_p)), "0" (_o), "1" (0) \
- : "memory");
+ : "memory"); \
+ clac()
#define cmpxchg_user(_p,_o,_n) \
({ \
diff --git a/xen/include/asm-x86/xstate.h b/xen/include/asm-x86/xstate.h
index 5617963..8d21349 100644
--- a/xen/include/asm-x86/xstate.h
+++ b/xen/include/asm-x86/xstate.h
@@ -20,24 +20,29 @@
#define XCR_XFEATURE_ENABLED_MASK 0x00000000 /* index of XCR0 */
#define XSTATE_YMM_SIZE 256
-#define XSTATE_YMM_OFFSET XSAVE_AREA_MIN_SIZE
#define XSTATE_AREA_MIN_SIZE (512 + 64) /* FP/SSE + XSAVE.HEADER */
#define XSTATE_FP (1ULL << 0)
#define XSTATE_SSE (1ULL << 1)
#define XSTATE_YMM (1ULL << 2)
+#define XSTATE_BNDREGS (1ULL << 3)
+#define XSTATE_BNDCSR (1ULL << 4)
+#define XSTATE_OPMASK (1ULL << 5)
+#define XSTATE_ZMM (1ULL << 6)
+#define XSTATE_HI_ZMM (1ULL << 7)
#define XSTATE_LWP (1ULL << 62) /* AMD lightweight profiling */
#define XSTATE_FP_SSE (XSTATE_FP | XSTATE_SSE)
-#define XCNTXT_MASK (XSTATE_FP | XSTATE_SSE | XSTATE_YMM | XSTATE_LWP)
+#define XCNTXT_MASK (XSTATE_FP | XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | \
+ XSTATE_ZMM | XSTATE_HI_ZMM | XSTATE_NONLAZY)
-#define XSTATE_ALL (~0)
-#define XSTATE_NONLAZY (XSTATE_LWP)
+#define XSTATE_ALL (~(1ULL << 63))
+#define XSTATE_NONLAZY (XSTATE_LWP | XSTATE_BNDREGS | XSTATE_BNDCSR)
#define XSTATE_LAZY (XSTATE_ALL & ~XSTATE_NONLAZY)
extern u64 xfeature_mask;
/* extended state save area */
-struct xsave_struct
+struct __packed __attribute__((aligned (64))) xsave_struct
{
union { /* FPU/MMX, SSE */
char x[512];
@@ -68,7 +73,7 @@ struct xsave_struct
struct { char x[XSTATE_YMM_SIZE]; } ymm; /* YMM */
char data[]; /* Future new states */
-} __attribute__ ((packed, aligned (64)));
+};
/* extended state operations */
bool_t __must_check set_xcr0(u64 xfeatures);
@@ -76,8 +81,7 @@ uint64_t get_xcr0(void);
void xsave(struct vcpu *v, uint64_t mask);
void xrstor(struct vcpu *v, uint64_t mask);
bool_t xsave_enabled(const struct vcpu *v);
-int __must_check validate_xstate(u64 xcr0, u64 xcr0_accum, u64 xstate_bv,
- u64 xfeat_mask);
+int __must_check validate_xstate(u64 xcr0, u64 xcr0_accum, u64 xstate_bv);
int __must_check handle_xsetbv(u32 index, u64 new_bv);
/* extended state init and cleanup functions */
diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
index dd53c94..e711606 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -364,16 +364,50 @@ typedef uint64_t xen_callback_t;
*/
/* Physical Address Space */
-#define GUEST_GICD_BASE 0x2c001000ULL
-#define GUEST_GICD_SIZE 0x1000ULL
-#define GUEST_GICC_BASE 0x2c002000ULL
-#define GUEST_GICC_SIZE 0x100ULL
-#define GUEST_RAM_BASE 0x80000000ULL /* 768M @ 2GB */
-#define GUEST_RAM_SIZE 0x30000000ULL
+/* vGIC mappings: Only one set of mapping is used by the guest.
+ * Therefore they can overlap.
+ */
+
+/* vGIC v2 mappings */
+#define GUEST_GICD_BASE 0x03001000ULL
+#define GUEST_GICD_SIZE 0x00001000ULL
+#define GUEST_GICC_BASE 0x03002000ULL
+#define GUEST_GICC_SIZE 0x00000100ULL
+
+/* vGIC v3 mappings */
+#define GUEST_GICV3_GICD_BASE 0x03001000ULL
+#define GUEST_GICV3_GICD_SIZE 0x00010000ULL
+
+#define GUEST_GICV3_RDIST_STRIDE 0x20000ULL
+#define GUEST_GICV3_RDIST_REGIONS 1
+
+#define GUEST_GICV3_GICR0_BASE 0x03020000ULL /* vCPU0 - vCPU7 */
+#define GUEST_GICV3_GICR0_SIZE 0x00100000ULL
+
+/* 16MB == 4096 pages reserved for guest to use as a region to map its
+ * grant table in.
+ */
+#define GUEST_GNTTAB_BASE 0x38000000ULL
+#define GUEST_GNTTAB_SIZE 0x01000000ULL
+
+#define GUEST_MAGIC_BASE 0x39000000ULL
+#define GUEST_MAGIC_SIZE 0x01000000ULL
+
+#define GUEST_RAM_BANKS 2
+
+#define GUEST_RAM0_BASE 0x40000000ULL /* 3GB of low RAM @ 1GB */
+#define GUEST_RAM0_SIZE 0xc0000000ULL
+
+#define GUEST_RAM1_BASE 0x0200000000ULL /* 1016GB of RAM @ 8GB */
+#define GUEST_RAM1_SIZE 0xfe00000000ULL
-#define GUEST_GNTTAB_BASE 0xb0000000ULL
-#define GUEST_GNTTAB_SIZE 0x00020000ULL
+#define GUEST_RAM_BASE GUEST_RAM0_BASE /* Lowest RAM address */
+/* Largest amount of actual RAM, not including holes */
+#define GUEST_RAM_MAX (GUEST_RAM0_SIZE + GUEST_RAM1_SIZE)
+/* Suitable for e.g. const uint64_t ramfoo[] = GUEST_RAM_BANK_FOOS; */
+#define GUEST_RAM_BANK_BASES { GUEST_RAM0_BASE, GUEST_RAM1_BASE }
+#define GUEST_RAM_BANK_SIZES { GUEST_RAM0_SIZE, GUEST_RAM1_SIZE }
/* Interrupts */
#define GUEST_TIMER_VIRT_PPI 27
diff --git a/xen/include/public/arch-x86/cpuid.h b/xen/include/public/arch-x86/cpuid.h
index d9bd627..6005dfe 100644
--- a/xen/include/public/arch-x86/cpuid.h
+++ b/xen/include/public/arch-x86/cpuid.h
@@ -30,12 +30,20 @@
#ifndef __XEN_PUBLIC_ARCH_X86_CPUID_H__
#define __XEN_PUBLIC_ARCH_X86_CPUID_H__
-/* Xen identification leaves start at 0x40000000. */
+/*
+ * For compatibility with other hypervisor interfaces, the Xen cpuid leaves
+ * can be found at the first otherwise unused 0x100 aligned boundary starting
+ * from 0x40000000.
+ *
+ * e.g If viridian extensions are enabled for an HVM domain, the Xen cpuid
+ * leaves will start at 0x40000100
+ */
+
#define XEN_CPUID_FIRST_LEAF 0x40000000
#define XEN_CPUID_LEAF(i) (XEN_CPUID_FIRST_LEAF + (i))
/*
- * Leaf 1 (0x40000000)
+ * Leaf 1 (0x40000x00)
* EAX: Largest Xen-information leaf. All leaves up to an including @EAX
* are supported by the Xen host.
* EBX-EDX: "XenVMMXenVMM" signature, allowing positive identification
@@ -46,14 +54,14 @@
#define XEN_CPUID_SIGNATURE_EDX 0x4d4d566e /* "nVMM" */
/*
- * Leaf 2 (0x40000001)
+ * Leaf 2 (0x40000x01)
* EAX[31:16]: Xen major version.
* EAX[15: 0]: Xen minor version.
* EBX-EDX: Reserved (currently all zeroes).
*/
/*
- * Leaf 3 (0x40000002)
+ * Leaf 3 (0x40000x02)
* EAX: Number of hypercall transfer pages. This register is always guaranteed
* to specify one hypercall page.
* EBX: Base address of Xen-specific MSRs.
@@ -65,4 +73,17 @@
#define _XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD 0
#define XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD (1u<<0)
+/*
+ * Leaf 5 (0x40000x04)
+ * HVM-specific features
+ */
+
+/* EAX Features */
+#define XEN_HVM_CPUID_APIC_ACCESS_VIRT (1u << 0) /* Virtualized APIC registers */
+#define XEN_HVM_CPUID_X2APIC_VIRT (1u << 1) /* Virtualized x2APIC accesses */
+/* Memory mapped from other domains has valid IOMMU entries */
+#define XEN_HVM_CPUID_IOMMU_MAPPINGS (1u << 2)
+
+#define XEN_CPUID_MAX_NUM_LEAVES 4
+
#endif /* __XEN_PUBLIC_ARCH_X86_CPUID_H__ */
diff --git a/xen/include/public/arch-x86/hvm/save.h b/xen/include/public/arch-x86/hvm/save.h
index 3664aaf..88aab7e 100644
--- a/xen/include/public/arch-x86/hvm/save.h
+++ b/xen/include/public/arch-x86/hvm/save.h
@@ -544,7 +544,7 @@ DECLARE_HVM_SAVE_TYPE(MTRR, 14, struct hvm_hw_mtrr);
*/
struct hvm_hw_cpu_xsave {
- uint64_t xfeature_mask;
+ uint64_t xfeature_mask; /* Ignored */
uint64_t xcr0; /* Updated by XSETBV */
uint64_t xcr0_accum; /* Updated by XSETBV */
struct {
@@ -568,6 +568,7 @@ struct hvm_hw_cpu_xsave {
struct hvm_viridian_domain_context {
uint64_t hypercall_gpa;
uint64_t guest_os_id;
+ uint64_t time_ref_count;
};
DECLARE_HVM_SAVE_TYPE(VIRIDIAN_DOMAIN, 15, struct hvm_viridian_domain_context);
@@ -592,9 +593,27 @@ struct hvm_tsc_adjust {
DECLARE_HVM_SAVE_TYPE(TSC_ADJUST, 19, struct hvm_tsc_adjust);
+
+struct hvm_msr {
+ uint32_t count;
+ struct hvm_one_msr {
+ uint32_t index;
+ uint32_t _rsvd;
+ uint64_t val;
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+ } msr[];
+#elif defined(__GNUC__)
+ } msr[0];
+#else
+ } msr[1 /* variable size */];
+#endif
+};
+
+#define CPU_MSR_CODE 20
+
/*
* Largest type-code in use
*/
-#define HVM_SAVE_CODE_MAX 19
+#define HVM_SAVE_CODE_MAX 20
#endif /* __XEN_PUBLIC_HVM_SAVE_X86_H__ */
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index f22fe2e..57e2ed7 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -35,8 +35,9 @@
#include "xen.h"
#include "grant_table.h"
#include "hvm/save.h"
+#include "memory.h"
-#define XEN_DOMCTL_INTERFACE_VERSION 0x00000009
+#define XEN_DOMCTL_INTERFACE_VERSION 0x0000000a
/*
* NB. xen_domctl.domain is an IN/OUT parameter for this operation.
@@ -67,6 +68,19 @@ struct xen_domctl_createdomain {
typedef struct xen_domctl_createdomain xen_domctl_createdomain_t;
DEFINE_XEN_GUEST_HANDLE(xen_domctl_createdomain_t);
+#if defined(__arm__) || defined(__aarch64__)
+#define XEN_DOMCTL_CONFIG_GIC_DEFAULT 0
+#define XEN_DOMCTL_CONFIG_GIC_V2 1
+#define XEN_DOMCTL_CONFIG_GIC_V3 2
+/* XEN_DOMCTL_configure_domain */
+struct xen_domctl_arm_configuredomain {
+ /* IN/OUT parameters */
+ uint8_t gic_version;
+};
+typedef struct xen_domctl_arm_configuredomain xen_domctl_arm_configuredomain_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_arm_configuredomain_t);
+#endif
+
/* XEN_DOMCTL_getdomaininfo */
struct xen_domctl_getdomaininfo {
/* OUT variables. */
@@ -107,6 +121,7 @@ struct xen_domctl_getdomaininfo {
uint64_aligned_t shared_info_frame; /* GMFN of shared_info struct */
uint64_aligned_t cpu_time;
uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
+#define XEN_INVALID_MAX_VCPU_ID (~0U) /* Domain has no vcpus? */
uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
uint32_t ssidref;
xen_domain_handle_t handle;
@@ -300,8 +315,33 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_nodeaffinity_t);
/* XEN_DOMCTL_setvcpuaffinity */
/* XEN_DOMCTL_getvcpuaffinity */
struct xen_domctl_vcpuaffinity {
- uint32_t vcpu; /* IN */
- struct xenctl_bitmap cpumap; /* IN/OUT */
+ /* IN variables. */
+ uint32_t vcpu;
+ /* Set/get the hard affinity for vcpu */
+#define _XEN_VCPUAFFINITY_HARD 0
+#define XEN_VCPUAFFINITY_HARD (1U<<_XEN_VCPUAFFINITY_HARD)
+ /* Set/get the soft affinity for vcpu */
+#define _XEN_VCPUAFFINITY_SOFT 1
+#define XEN_VCPUAFFINITY_SOFT (1U<<_XEN_VCPUAFFINITY_SOFT)
+ uint32_t flags;
+ /*
+ * IN/OUT variables.
+ *
+ * Both are IN/OUT for XEN_DOMCTL_setvcpuaffinity, in which case they
+ * contain effective hard or/and soft affinity. That is, upon successful
+ * return, cpumap_soft, contains the intersection of the soft affinity,
+ * hard affinity and the cpupool's online CPUs for the domain (if
+ * XEN_VCPUAFFINITY_SOFT was set in flags). cpumap_hard contains the
+ * intersection between hard affinity and the cpupool's online CPUs (if
+ * XEN_VCPUAFFINITY_HARD was set in flags).
+ *
+ * Both are OUT-only for XEN_DOMCTL_getvcpuaffinity, in which case they
+ * contain the plain hard and/or soft affinity masks that were set during
+ * previous successful calls to XEN_DOMCTL_setvcpuaffinity (or the
+ * default values), without intersecting or altering them in any way.
+ */
+ struct xenctl_bitmap cpumap_hard;
+ struct xenctl_bitmap cpumap_soft;
};
typedef struct xen_domctl_vcpuaffinity xen_domctl_vcpuaffinity_t;
DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpuaffinity_t);
@@ -321,6 +361,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_vcpus_t);
#define XEN_SCHEDULER_CREDIT 5
#define XEN_SCHEDULER_CREDIT2 6
#define XEN_SCHEDULER_ARINC653 7
+#define XEN_SCHEDULER_RTDS 8
+
/* Set or get info? */
#define XEN_DOMCTL_SCHEDOP_putinfo 0
#define XEN_DOMCTL_SCHEDOP_getinfo 1
@@ -342,6 +384,10 @@ struct xen_domctl_scheduler_op {
struct xen_domctl_sched_credit2 {
uint16_t weight;
} credit2;
+ struct xen_domctl_sched_rtds {
+ uint32_t period;
+ uint32_t budget;
+ } rtds;
} u;
};
typedef struct xen_domctl_scheduler_op xen_domctl_scheduler_op_t;
@@ -401,19 +447,6 @@ typedef struct xen_domctl_hypercall_init xen_domctl_hypercall_init_t;
DEFINE_XEN_GUEST_HANDLE(xen_domctl_hypercall_init_t);
-/* XEN_DOMCTL_arch_setup */
-#define _XEN_DOMAINSETUP_hvm_guest 0
-#define XEN_DOMAINSETUP_hvm_guest (1UL<<_XEN_DOMAINSETUP_hvm_guest)
-#define _XEN_DOMAINSETUP_query 1 /* Get parameters (for save) */
-#define XEN_DOMAINSETUP_query (1UL<<_XEN_DOMAINSETUP_query)
-#define _XEN_DOMAINSETUP_sioemu_guest 2
-#define XEN_DOMAINSETUP_sioemu_guest (1UL<<_XEN_DOMAINSETUP_sioemu_guest)
-typedef struct xen_domctl_arch_setup {
- uint64_aligned_t flags; /* XEN_DOMAINSETUP_* */
-} xen_domctl_arch_setup_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_arch_setup_t);
-
-
/* XEN_DOMCTL_settimeoffset */
struct xen_domctl_settimeoffset {
int32_t time_offset_seconds; /* applied to domain wallclock time */
@@ -440,14 +473,6 @@ typedef struct xen_domctl_address_size {
DEFINE_XEN_GUEST_HANDLE(xen_domctl_address_size_t);
-/* XEN_DOMCTL_real_mode_area */
-struct xen_domctl_real_mode_area {
- uint32_t log; /* log2 of Real Mode Area size */
-};
-typedef struct xen_domctl_real_mode_area xen_domctl_real_mode_area_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_real_mode_area_t);
-
-
/* XEN_DOMCTL_sendtrigger */
#define XEN_DOMCTL_SENDTRIGGER_NMI 0
#define XEN_DOMCTL_SENDTRIGGER_RESET 1
@@ -555,6 +580,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_mapping_t);
#define XEN_DOMCTL_MEM_CACHEATTR_WP 5
#define XEN_DOMCTL_MEM_CACHEATTR_WB 6
#define XEN_DOMCTL_MEM_CACHEATTR_UCM 7
+#define XEN_DOMCTL_DELETE_MEM_CACHEATTR (~(uint32_t)0)
struct xen_domctl_pin_mem_cacheattr {
uint64_aligned_t start, end;
uint32_t type; /* XEN_DOMCTL_MEM_CACHEATTR_* */
@@ -767,10 +793,11 @@ struct xen_domctl_gdbsx_domstatus {
* ENODEV - host lacks HAP support (EPT/NPT) or HAP is disabled in guest
* EBUSY - guest has or had access enabled, ring buffer still active
*/
-#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS 2
+#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS 2
-#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE 0
-#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_DISABLE 1
+#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE 0
+#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_DISABLE 1
+#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE_INTROSPECTION 2
/*
* Sharing ENOMEM helper.
@@ -840,7 +867,7 @@ struct xen_domctl_vcpuextstate {
/* IN: VCPU that this call applies to. */
uint32_t vcpu;
/*
- * SET: xfeature support mask of struct (IN)
+ * SET: Ignored.
* GET: xfeature support mask of struct (IN/OUT)
* xfeature mask is served as identifications of the saving format
* so that compatible CPUs can have a check on format to decide
@@ -896,6 +923,78 @@ struct xen_domctl_cacheflush {
typedef struct xen_domctl_cacheflush xen_domctl_cacheflush_t;
DEFINE_XEN_GUEST_HANDLE(xen_domctl_cacheflush_t);
+#if defined(__i386__) || defined(__x86_64__)
+struct xen_domctl_vcpu_msr {
+ uint32_t index;
+ uint32_t reserved;
+ uint64_aligned_t value;
+};
+typedef struct xen_domctl_vcpu_msr xen_domctl_vcpu_msr_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpu_msr_t);
+
+/*
+ * XEN_DOMCTL_set_vcpu_msrs / XEN_DOMCTL_get_vcpu_msrs.
+ *
+ * Input:
+ * - A NULL 'msrs' guest handle is a request for the maximum 'msr_count'.
+ * - Otherwise, 'msr_count' is the number of entries in 'msrs'.
+ *
+ * Output for get:
+ * - If 'msr_count' is less than the number Xen needs to write, -ENOBUFS shall
+ * be returned and 'msr_count' updated to reflect the intended number.
+ * - On success, 'msr_count' shall indicate the number of MSRs written, which
+ * may be less than the maximum if some are not currently used by the vcpu.
+ *
+ * Output for set:
+ * - If Xen encounters an error with a specific MSR, -EINVAL shall be returned
+ * and 'msr_count' shall be set to the offending index, to aid debugging.
+ */
+struct xen_domctl_vcpu_msrs {
+ uint32_t vcpu; /* IN */
+ uint32_t msr_count; /* IN/OUT */
+ XEN_GUEST_HANDLE_64(xen_domctl_vcpu_msr_t) msrs; /* IN/OUT */
+};
+typedef struct xen_domctl_vcpu_msrs xen_domctl_vcpu_msrs_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpu_msrs_t);
+#endif
+
+/*
+ * Use in XEN_DOMCTL_setvnumainfo to set
+ * vNUMA domain topology.
+ */
+struct xen_domctl_vnuma {
+ uint32_t nr_vnodes;
+ uint32_t nr_vmemranges;
+ uint32_t nr_vcpus;
+ uint32_t pad;
+ XEN_GUEST_HANDLE_64(uint) vdistance;
+ XEN_GUEST_HANDLE_64(uint) vcpu_to_vnode;
+
+ /*
+ * vnodes to physical NUMA nodes mask.
+ * This kept on per-domain basis for
+ * interested consumers, such as numa aware ballooning.
+ */
+ XEN_GUEST_HANDLE_64(uint) vnode_to_pnode;
+
+ /*
+ * memory rages for each vNUMA node
+ */
+ XEN_GUEST_HANDLE_64(xen_vmemrange_t) vmemrange;
+};
+typedef struct xen_domctl_vnuma xen_domctl_vnuma_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_vnuma_t);
+
+struct xen_domctl_psr_cmt_op {
+#define XEN_DOMCTL_PSR_CMT_OP_DETACH 0
+#define XEN_DOMCTL_PSR_CMT_OP_ATTACH 1
+#define XEN_DOMCTL_PSR_CMT_OP_QUERY_RMID 2
+ uint32_t cmd;
+ uint32_t data;
+};
+typedef struct xen_domctl_psr_cmt_op xen_domctl_psr_cmt_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_psr_cmt_op_t);
+
struct xen_domctl {
uint32_t cmd;
#define XEN_DOMCTL_createdomain 1
@@ -920,10 +1019,10 @@ struct xen_domctl {
#define XEN_DOMCTL_iomem_permission 20
#define XEN_DOMCTL_ioport_permission 21
#define XEN_DOMCTL_hypercall_init 22
-#define XEN_DOMCTL_arch_setup 23
+#define XEN_DOMCTL_arch_setup 23 /* Obsolete IA64 only */
#define XEN_DOMCTL_settimeoffset 24
#define XEN_DOMCTL_getvcpuaffinity 25
-#define XEN_DOMCTL_real_mode_area 26
+#define XEN_DOMCTL_real_mode_area 26 /* Obsolete PPC only */
#define XEN_DOMCTL_resumedomain 27
#define XEN_DOMCTL_sendtrigger 28
#define XEN_DOMCTL_subscribe 29
@@ -966,6 +1065,11 @@ struct xen_domctl {
#define XEN_DOMCTL_getnodeaffinity 69
#define XEN_DOMCTL_set_max_evtchn 70
#define XEN_DOMCTL_cacheflush 71
+#define XEN_DOMCTL_get_vcpu_msrs 72
+#define XEN_DOMCTL_set_vcpu_msrs 73
+#define XEN_DOMCTL_setvnumainfo 74
+#define XEN_DOMCTL_psr_cmt_op 75
+#define XEN_DOMCTL_arm_configure_domain 76
#define XEN_DOMCTL_gdbsx_guestmemio 1000
#define XEN_DOMCTL_gdbsx_pausevcpu 1001
#define XEN_DOMCTL_gdbsx_unpausevcpu 1002
@@ -974,6 +1078,9 @@ struct xen_domctl {
domid_t domain;
union {
struct xen_domctl_createdomain createdomain;
+#if defined(__arm__) || defined(__aarch64__)
+ struct xen_domctl_arm_configuredomain configuredomain;
+#endif
struct xen_domctl_getdomaininfo getdomaininfo;
struct xen_domctl_getmemlist getmemlist;
struct xen_domctl_getpageframeinfo getpageframeinfo;
@@ -993,11 +1100,9 @@ struct xen_domctl {
struct xen_domctl_iomem_permission iomem_permission;
struct xen_domctl_ioport_permission ioport_permission;
struct xen_domctl_hypercall_init hypercall_init;
- struct xen_domctl_arch_setup arch_setup;
struct xen_domctl_settimeoffset settimeoffset;
struct xen_domctl_disable_migrate disable_migrate;
struct xen_domctl_tsc_info tsc_info;
- struct xen_domctl_real_mode_area real_mode_area;
struct xen_domctl_hvmcontext hvmcontext;
struct xen_domctl_hvmcontext_partial hvmcontext_partial;
struct xen_domctl_address_size address_size;
@@ -1017,6 +1122,7 @@ struct xen_domctl {
#if defined(__i386__) || defined(__x86_64__)
struct xen_domctl_cpuid cpuid;
struct xen_domctl_vcpuextstate vcpuextstate;
+ struct xen_domctl_vcpu_msrs vcpu_msrs;
#endif
struct xen_domctl_set_access_required access_required;
struct xen_domctl_audit_p2m audit_p2m;
@@ -1027,6 +1133,8 @@ struct xen_domctl {
struct xen_domctl_cacheflush cacheflush;
struct xen_domctl_gdbsx_pauseunp_vcpu gdbsx_pauseunp_vcpu;
struct xen_domctl_gdbsx_domstatus gdbsx_domstatus;
+ struct xen_domctl_vnuma vnuma;
+ struct xen_domctl_psr_cmt_op psr_cmt_op;
uint8_t pad[128];
} u;
};
diff --git a/xen/include/public/event_channel.h b/xen/include/public/event_channel.h
index 49ac8cc..05e531d 100644
--- a/xen/include/public/event_channel.h
+++ b/xen/include/public/event_channel.h
@@ -264,6 +264,10 @@ typedef struct evtchn_unmask evtchn_unmask_t;
* NOTES:
* 1. <dom> may be specified as DOMID_SELF.
* 2. Only a sufficiently-privileged domain may specify other than DOMID_SELF.
+ * 3. Destroys all control blocks and event array, resets event channel
+ * operations to 2-level ABI if called with <dom> == DOMID_SELF and FIFO
+ * ABI was used. Guests should not bind events during EVTCHNOP_reset call
+ * as these events are likely to be lost.
*/
struct evtchn_reset {
/* IN parameters. */
diff --git a/xen/include/public/features.h b/xen/include/public/features.h
index a149aa6..16d92aa 100644
--- a/xen/include/public/features.h
+++ b/xen/include/public/features.h
@@ -94,6 +94,11 @@
/* operation as Dom0 is supported */
#define XENFEAT_dom0 11
+/* Xen also maps grant references at pfn = mfn.
+ * This feature flag is deprecated and should not be used.
+#define XENFEAT_grant_map_identity 12
+ */
+
#define XENFEAT_NR_SUBMAPS 1
#endif /* __XEN_PUBLIC_FEATURES_H__ */
diff --git a/xen/include/public/grant_table.h b/xen/include/public/grant_table.h
index b8a3d6c..20d4e77 100644
--- a/xen/include/public/grant_table.h
+++ b/xen/include/public/grant_table.h
@@ -309,6 +309,7 @@ typedef uint16_t grant_status_t;
#define GNTTABOP_get_status_frames 9
#define GNTTABOP_get_version 10
#define GNTTABOP_swap_grant_ref 11
+#define GNTTABOP_cache_flush 12
#endif /* __XEN_INTERFACE_VERSION__ */
/* ` } */
@@ -574,6 +575,25 @@ struct gnttab_swap_grant_ref {
typedef struct gnttab_swap_grant_ref gnttab_swap_grant_ref_t;
DEFINE_XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t);
+/*
+ * Issue one or more cache maintenance operations on a portion of a
+ * page granted to the calling domain by a foreign domain.
+ */
+struct gnttab_cache_flush {
+ union {
+ uint64_t dev_bus_addr;
+ grant_ref_t ref;
+ } a;
+ uint16_t offset; /* offset from start of grant */
+ uint16_t length; /* size within the grant */
+#define GNTTAB_CACHE_CLEAN (1<<0)
+#define GNTTAB_CACHE_INVAL (1<<1)
+#define GNTTAB_CACHE_SOURCE_GREF (1<<31)
+ uint32_t op;
+};
+typedef struct gnttab_cache_flush gnttab_cache_flush_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_cache_flush_t);
+
#endif /* __XEN_INTERFACE_VERSION__ */
/*
diff --git a/xen/include/public/hvm/hvm_op.h b/xen/include/public/hvm/hvm_op.h
index a9aab4b..eeb0a60 100644
--- a/xen/include/public/hvm/hvm_op.h
+++ b/xen/include/public/hvm/hvm_op.h
@@ -23,6 +23,7 @@
#include "../xen.h"
#include "../trace.h"
+#include "../event_channel.h"
/* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
#define HVMOP_set_param 0
@@ -90,10 +91,10 @@ typedef enum {
struct xen_hvm_track_dirty_vram {
/* Domain to be tracked. */
domid_t domid;
+ /* Number of pages to track. */
+ uint32_t nr;
/* First pfn to track. */
uint64_aligned_t first_pfn;
- /* Number of pages to track. */
- uint64_aligned_t nr;
/* OUT variable. */
/* Dirty bitmap buffer. */
XEN_GUEST_HANDLE_64(uint8) dirty_bitmap;
@@ -106,10 +107,10 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_track_dirty_vram_t);
struct xen_hvm_modified_memory {
/* Domain to be updated. */
domid_t domid;
+ /* Number of pages. */
+ uint32_t nr;
/* First pfn. */
uint64_aligned_t first_pfn;
- /* Number of pages. */
- uint64_aligned_t nr;
};
typedef struct xen_hvm_modified_memory xen_hvm_modified_memory_t;
DEFINE_XEN_GUEST_HANDLE(xen_hvm_modified_memory_t);
@@ -162,49 +163,11 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_xentrace_t);
/* Following tools-only interfaces may change in future. */
#if defined(__XEN__) || defined(__XEN_TOOLS__)
+/* Deprecated by XENMEM_access_op_set_access */
#define HVMOP_set_mem_access 12
-typedef enum {
- HVMMEM_access_n,
- HVMMEM_access_r,
- HVMMEM_access_w,
- HVMMEM_access_rw,
- HVMMEM_access_x,
- HVMMEM_access_rx,
- HVMMEM_access_wx,
- HVMMEM_access_rwx,
- HVMMEM_access_rx2rw, /* Page starts off as r-x, but automatically
- * change to r-w on a write */
- HVMMEM_access_n2rwx, /* Log access: starts off as n, automatically
- * goes to rwx, generating an event without
- * pausing the vcpu */
- HVMMEM_access_default /* Take the domain default */
-} hvmmem_access_t;
-/* Notify that a region of memory is to have specific access types */
-struct xen_hvm_set_mem_access {
- /* Domain to be updated. */
- domid_t domid;
- /* Memory type */
- uint16_t hvmmem_access; /* hvm_access_t */
- /* Number of pages, ignored on setting default access */
- uint32_t nr;
- /* First pfn, or ~0ull to set the default access for new pages */
- uint64_aligned_t first_pfn;
-};
-typedef struct xen_hvm_set_mem_access xen_hvm_set_mem_access_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_mem_access_t);
+/* Deprecated by XENMEM_access_op_get_access */
#define HVMOP_get_mem_access 13
-/* Get the specific access type for that region of memory */
-struct xen_hvm_get_mem_access {
- /* Domain to be queried. */
- domid_t domid;
- /* Memory type: OUT */
- uint16_t hvmmem_access; /* hvm_access_t */
- /* pfn, or ~0ull for default access for new pages. IN */
- uint64_aligned_t pfn;
-};
-typedef struct xen_hvm_get_mem_access xen_hvm_get_mem_access_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_mem_access_t);
#define HVMOP_inject_trap 14
/* Inject a trap into a VCPU, which will get taken up on the next
@@ -270,6 +233,150 @@ struct xen_hvm_inject_msi {
typedef struct xen_hvm_inject_msi xen_hvm_inject_msi_t;
DEFINE_XEN_GUEST_HANDLE(xen_hvm_inject_msi_t);
+/*
+ * IOREQ Servers
+ *
+ * The interface between an I/O emulator an Xen is called an IOREQ Server.
+ * A domain supports a single 'legacy' IOREQ Server which is instantiated if
+ * parameter...
+ *
+ * HVM_PARAM_IOREQ_PFN is read (to get the gmfn containing the synchronous
+ * ioreq structures), or...
+ * HVM_PARAM_BUFIOREQ_PFN is read (to get the gmfn containing the buffered
+ * ioreq ring), or...
+ * HVM_PARAM_BUFIOREQ_EVTCHN is read (to get the event channel that Xen uses
+ * to request buffered I/O emulation).
+ *
+ * The following hypercalls facilitate the creation of IOREQ Servers for
+ * 'secondary' emulators which are invoked to implement port I/O, memory, or
+ * PCI config space ranges which they explicitly register.
+ */
+
+typedef uint16_t ioservid_t;
+
+/*
+ * HVMOP_create_ioreq_server: Instantiate a new IOREQ Server for a secondary
+ * emulator servicing domain <domid>.
+ *
+ * The <id> handed back is unique for <domid>. If <handle_bufioreq> is zero
+ * the buffered ioreq ring will not be allocated and hence all emulation
+ * requestes to this server will be synchronous.
+ */
+#define HVMOP_create_ioreq_server 17
+struct xen_hvm_create_ioreq_server {
+ domid_t domid; /* IN - domain to be serviced */
+ uint8_t handle_bufioreq; /* IN - should server handle buffered ioreqs */
+ ioservid_t id; /* OUT - server id */
+};
+typedef struct xen_hvm_create_ioreq_server xen_hvm_create_ioreq_server_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_create_ioreq_server_t);
+
+/*
+ * HVMOP_get_ioreq_server_info: Get all the information necessary to access
+ * IOREQ Server <id>.
+ *
+ * The emulator needs to map the synchronous ioreq structures and buffered
+ * ioreq ring (if it exists) that Xen uses to request emulation. These are
+ * hosted in domain <domid>'s gmfns <ioreq_pfn> and <bufioreq_pfn>
+ * respectively. In addition, if the IOREQ Server is handling buffered
+ * emulation requests, the emulator needs to bind to event channel
+ * <bufioreq_port> to listen for them. (The event channels used for
+ * synchronous emulation requests are specified in the per-CPU ioreq
+ * structures in <ioreq_pfn>).
+ * If the IOREQ Server is not handling buffered emulation requests then the
+ * values handed back in <bufioreq_pfn> and <bufioreq_port> will both be 0.
+ */
+#define HVMOP_get_ioreq_server_info 18
+struct xen_hvm_get_ioreq_server_info {
+ domid_t domid; /* IN - domain to be serviced */
+ ioservid_t id; /* IN - server id */
+ evtchn_port_t bufioreq_port; /* OUT - buffered ioreq port */
+ uint64_aligned_t ioreq_pfn; /* OUT - sync ioreq pfn */
+ uint64_aligned_t bufioreq_pfn; /* OUT - buffered ioreq pfn */
+};
+typedef struct xen_hvm_get_ioreq_server_info xen_hvm_get_ioreq_server_info_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_ioreq_server_info_t);
+
+/*
+ * HVM_map_io_range_to_ioreq_server: Register an I/O range of domain <domid>
+ * for emulation by the client of IOREQ
+ * Server <id>
+ * HVM_unmap_io_range_from_ioreq_server: Deregister an I/O range of <domid>
+ * for emulation by the client of IOREQ
+ * Server <id>
+ *
+ * There are three types of I/O that can be emulated: port I/O, memory accesses
+ * and PCI config space accesses. The <type> field denotes which type of range
+ * the <start> and <end> (inclusive) fields are specifying.
+ * PCI config space ranges are specified by segment/bus/device/function values
+ * which should be encoded using the HVMOP_PCI_SBDF helper macro below.
+ *
+ * NOTE: unless an emulation request falls entirely within a range mapped
+ * by a secondary emulator, it will not be passed to that emulator.
+ */
+#define HVMOP_map_io_range_to_ioreq_server 19
+#define HVMOP_unmap_io_range_from_ioreq_server 20
+struct xen_hvm_io_range {
+ domid_t domid; /* IN - domain to be serviced */
+ ioservid_t id; /* IN - server id */
+ uint32_t type; /* IN - type of range */
+# define HVMOP_IO_RANGE_PORT 0 /* I/O port range */
+# define HVMOP_IO_RANGE_MEMORY 1 /* MMIO range */
+# define HVMOP_IO_RANGE_PCI 2 /* PCI segment/bus/dev/func range */
+ uint64_aligned_t start, end; /* IN - inclusive start and end of range */
+};
+typedef struct xen_hvm_io_range xen_hvm_io_range_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_io_range_t);
+
+#define HVMOP_PCI_SBDF(s,b,d,f) \
+ ((((s) & 0xffff) << 16) | \
+ (((b) & 0xff) << 8) | \
+ (((d) & 0x1f) << 3) | \
+ ((f) & 0x07))
+
+/*
+ * HVMOP_destroy_ioreq_server: Destroy the IOREQ Server <id> servicing domain
+ * <domid>.
+ *
+ * Any registered I/O ranges will be automatically deregistered.
+ */
+#define HVMOP_destroy_ioreq_server 21
+struct xen_hvm_destroy_ioreq_server {
+ domid_t domid; /* IN - domain to be serviced */
+ ioservid_t id; /* IN - server id */
+};
+typedef struct xen_hvm_destroy_ioreq_server xen_hvm_destroy_ioreq_server_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_destroy_ioreq_server_t);
+
+/*
+ * HVMOP_set_ioreq_server_state: Enable or disable the IOREQ Server <id> servicing
+ * domain <domid>.
+ *
+ * The IOREQ Server will not be passed any emulation requests until it is in the
+ * enabled state.
+ * Note that the contents of the ioreq_pfn and bufioreq_fn (see
+ * HVMOP_get_ioreq_server_info) are not meaningful until the IOREQ Server is in
+ * the enabled state.
+ */
+#define HVMOP_set_ioreq_server_state 22
+struct xen_hvm_set_ioreq_server_state {
+ domid_t domid; /* IN - domain to be serviced */
+ ioservid_t id; /* IN - server id */
+ uint8_t enabled; /* IN - enabled? */
+};
+typedef struct xen_hvm_set_ioreq_server_state xen_hvm_set_ioreq_server_state_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_ioreq_server_state_t);
+
#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/public/hvm/ioreq.h b/xen/include/public/hvm/ioreq.h
index f05d130..5b5fedf 100644
--- a/xen/include/public/hvm/ioreq.h
+++ b/xen/include/public/hvm/ioreq.h
@@ -34,13 +34,20 @@
#define IOREQ_TYPE_PIO 0 /* pio */
#define IOREQ_TYPE_COPY 1 /* mmio ops */
+#define IOREQ_TYPE_PCI_CONFIG 2
#define IOREQ_TYPE_TIMEOFFSET 7
#define IOREQ_TYPE_INVALIDATE 8 /* mapcache */
/*
* VMExit dispatcher should cooperate with instruction decoder to
* prepare this structure and notify service OS and DM by sending
- * virq
+ * virq.
+ *
+ * For I/O type IOREQ_TYPE_PCI_CONFIG, the physical address is formatted
+ * as follows:
+ *
+ * 63....48|47..40|39..35|34..32|31........0
+ * SEGMENT |BUS |DEV |FN |OFFSET
*/
struct ioreq {
uint64_t addr; /* physical address */
diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
index 517a184..3c51072 100644
--- a/xen/include/public/hvm/params.h
+++ b/xen/include/public/hvm/params.h
@@ -56,9 +56,47 @@
#if defined(__i386__) || defined(__x86_64__)
-/* Expose Viridian interfaces to this HVM guest? */
+/*
+ * Viridian enlightenments
+ *
+ * (See http://download.microsoft.com/download/A/B/4/AB43A34E-BDD0-4FA6-BDEF-79EEF16E880B/Hypervisor%20Top%20Level%20Functional%20Specification%20v4.0.docx)
+ *
+ * To expose viridian enlightenments to the guest set this parameter
+ * to the desired feature mask. The base feature set must be present
+ * in any valid feature mask.
+ */
#define HVM_PARAM_VIRIDIAN 9
+/* Base+Freq viridian feature sets:
+ *
+ * - Hypercall MSRs (HV_X64_MSR_GUEST_OS_ID and HV_X64_MSR_HYPERCALL)
+ * - APIC access MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR)
+ * - Virtual Processor index MSR (HV_X64_MSR_VP_INDEX)
+ * - Timer frequency MSRs (HV_X64_MSR_TSC_FREQUENCY and
+ * HV_X64_MSR_APIC_FREQUENCY)
+ */
+#define _HVMPV_base_freq 0
+#define HVMPV_base_freq (1 << _HVMPV_base_freq)
+
+/* Feature set modifications */
+
+/* Disable timer frequency MSRs (HV_X64_MSR_TSC_FREQUENCY and
+ * HV_X64_MSR_APIC_FREQUENCY).
+ * This modification restores the viridian feature set to the
+ * original 'base' set exposed in releases prior to Xen 4.4.
+ */
+#define _HVMPV_no_freq 1
+#define HVMPV_no_freq (1 << _HVMPV_no_freq)
+
+/* Enable Partition Time Reference Counter (HV_X64_MSR_TIME_REF_COUNT) */
+#define _HVMPV_time_ref_count 2
+#define HVMPV_time_ref_count (1 << _HVMPV_time_ref_count)
+
+#define HVMPV_feature_mask \
+ (HVMPV_base_freq | \
+ HVMPV_no_freq | \
+ HVMPV_time_ref_count)
+
#endif
/*
@@ -145,6 +183,12 @@
/* SHUTDOWN_* action in case of a triple fault */
#define HVM_PARAM_TRIPLE_FAULT_REASON 31
-#define HVM_NR_PARAMS 32
+#define HVM_PARAM_IOREQ_SERVER_PFN 32
+#define HVM_PARAM_NR_IOREQ_SERVER_PAGES 33
+
+/* Location of the VM Generation ID in guest physical address space. */
+#define HVM_PARAM_VM_GENERATION_ID_ADDR 34
+
+#define HVM_NR_PARAMS 35
#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
diff --git a/xen/include/public/io/blkif.h b/xen/include/public/io/blkif.h
index c3e169c..6baf7fb 100644
--- a/xen/include/public/io/blkif.h
+++ b/xen/include/public/io/blkif.h
@@ -97,6 +97,28 @@
*
* The type of the backing device/object.
*
+ *
+ * direct-io-safe
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ *
+ * The underlying storage is not affected by the direct IO memory
+ * lifetime bug. See:
+ * http://lists.xen.org/archives/html/xen-devel/2012-12/msg01154.html
+ *
+ * Therefore this option gives the backend permission to use
+ * O_DIRECT, notwithstanding that bug.
+ *
+ * That is, if this option is enabled, use of O_DIRECT is safe,
+ * in circumstances where we would normally have avoided it as a
+ * workaround for that bug. This option is not relevant for all
+ * backends, and even not necessarily supported for those for
+ * which it is relevant. A backend which knows that it is not
+ * affected by the bug can ignore this option.
+ *
+ * This option doesn't require a backend to use O_DIRECT, so it
+ * should not be used to try to control the caching behaviour.
+ *
*--------------------------------- Features ---------------------------------
*
* feature-barrier
@@ -175,6 +197,16 @@
*
*------------------------- Backend Device Properties -------------------------
*
+ * discard-enable
+ * Values: 0/1 (boolean)
+ * Default Value: 1
+ *
+ * This optional property, set by the toolstack, instructs the backend
+ * to offer discard to the frontend. If the property is missing the
+ * backend should offer discard if the backing storage actually supports
+ * it. This optional property, set by the toolstack, requests that the
+ * backend offer, or not offer, discard to the frontend.
+ *
* discard-alignment
* Values: <uint32_t>
* Default Value: 0
diff --git a/xen/include/public/io/netif.h b/xen/include/public/io/netif.h
index d7fb771..61e9aea 100644
--- a/xen/include/public/io/netif.h
+++ b/xen/include/public/io/netif.h
@@ -69,6 +69,59 @@
*/
/*
+ * Multiple transmit and receive queues:
+ * If supported, the backend will write the key "multi-queue-max-queues" to
+ * the directory for that vif, and set its value to the maximum supported
+ * number of queues.
+ * Frontends that are aware of this feature and wish to use it can write the
+ * key "multi-queue-num-queues", set to the number they wish to use, which
+ * must be greater than zero, and no more than the value reported by the backend
+ * in "multi-queue-max-queues".
+ *
+ * Queues replicate the shared rings and event channels.
+ * "feature-split-event-channels" may optionally be used when using
+ * multiple queues, but is not mandatory.
+ *
+ * Each queue consists of one shared ring pair, i.e. there must be the same
+ * number of tx and rx rings.
+ *
+ * For frontends requesting just one queue, the usual event-channel and
+ * ring-ref keys are written as before, simplifying the backend processing
+ * to avoid distinguishing between a frontend that doesn't understand the
+ * multi-queue feature, and one that does, but requested only one queue.
+ *
+ * Frontends requesting two or more queues must not write the toplevel
+ * event-channel (or event-channel-{tx,rx}) and {tx,rx}-ring-ref keys,
+ * instead writing those keys under sub-keys having the name "queue-N" where
+ * N is the integer ID of the queue for which those keys belong. Queues
+ * are indexed from zero. For example, a frontend with two queues and split
+ * event channels must write the following set of queue-related keys:
+ *
+ * /local/domain/1/device/vif/0/multi-queue-num-queues = "2"
+ * /local/domain/1/device/vif/0/queue-0 = ""
+ * /local/domain/1/device/vif/0/queue-0/tx-ring-ref = "<ring-ref-tx0>"
+ * /local/domain/1/device/vif/0/queue-0/rx-ring-ref = "<ring-ref-rx0>"
+ * /local/domain/1/device/vif/0/queue-0/event-channel-tx = "<evtchn-tx0>"
+ * /local/domain/1/device/vif/0/queue-0/event-channel-rx = "<evtchn-rx0>"
+ * /local/domain/1/device/vif/0/queue-1 = ""
+ * /local/domain/1/device/vif/0/queue-1/tx-ring-ref = "<ring-ref-tx1>"
+ * /local/domain/1/device/vif/0/queue-1/rx-ring-ref = "<ring-ref-rx1"
+ * /local/domain/1/device/vif/0/queue-1/event-channel-tx = "<evtchn-tx1>"
+ * /local/domain/1/device/vif/0/queue-1/event-channel-rx = "<evtchn-rx1>"
+ *
+ * If there is any inconsistency in the XenStore data, the backend may
+ * choose not to connect any queues, instead treating the request as an
+ * error. This includes scenarios where more (or fewer) queues were
+ * requested than the frontend provided details for.
+ *
+ * Mapping of packets to queues is considered to be a function of the
+ * transmitting system (backend or frontend) and is not negotiated
+ * between the two. Guests are free to transmit packets on any queue
+ * they choose, provided it has been set up correctly. Guests must be
+ * prepared to receive packets on any queue they have requested be set up.
+ */
+
+/*
* "feature-no-csum-offload" should be used to turn IPv4 TCP/UDP checksum
* offload off or on. If it is missing then the feature is assumed to be on.
* "feature-ipv6-csum-offload" should be used to turn IPv6 TCP/UDP checksum
diff --git a/xen/include/public/io/vscsiif.h b/xen/include/public/io/vscsiif.h
index a50f980..7a1db05 100644
--- a/xen/include/public/io/vscsiif.h
+++ b/xen/include/public/io/vscsiif.h
@@ -1,8 +1,8 @@
/******************************************************************************
* vscsiif.h
- *
+ *
* Based on the blkif.h code.
- *
+ *
* 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
@@ -30,11 +30,131 @@
#include "ring.h"
#include "../grant_table.h"
-/* commands between backend and frontend */
-#define VSCSIIF_ACT_SCSI_CDB 1 /* SCSI CDB command */
-#define VSCSIIF_ACT_SCSI_ABORT 2 /* SCSI Device(Lun) Abort*/
-#define VSCSIIF_ACT_SCSI_RESET 3 /* SCSI Device(Lun) Reset*/
-#define VSCSIIF_ACT_SCSI_SG_PRESET 4 /* Preset SG elements */
+/*
+ * Feature and Parameter Negotiation
+ * =================================
+ * The two halves of a Xen pvSCSI driver utilize nodes within the XenStore to
+ * communicate capabilities and to negotiate operating parameters. This
+ * section enumerates these nodes which reside in the respective front and
+ * backend portions of the XenStore, following the XenBus convention.
+ *
+ * Any specified default value is in effect if the corresponding XenBus node
+ * is not present in the XenStore.
+ *
+ * XenStore nodes in sections marked "PRIVATE" are solely for use by the
+ * driver side whose XenBus tree contains them.
+ *
+ *****************************************************************************
+ * Backend XenBus Nodes
+ *****************************************************************************
+ *
+ *------------------ Backend Device Identification (PRIVATE) ------------------
+ *
+ * p-devname
+ * Values: string
+ *
+ * A free string used to identify the physical device (e.g. a disk name).
+ *
+ * p-dev
+ * Values: string
+ *
+ * A string specifying the backend device: either a 4-tuple "h:c:t:l"
+ * (host, controller, target, lun, all integers), or a WWN (e.g.
+ * "naa.60014054ac780582").
+ *
+ * v-dev
+ * Values: string
+ *
+ * A string specifying the frontend device in form of a 4-tuple "h:c:t:l"
+ * (host, controller, target, lun, all integers).
+ *
+ *--------------------------------- Features ---------------------------------
+ *
+ * feature-sg-grant
+ * Values: unsigned [VSCSIIF_SG_TABLESIZE...65535]
+ * Default Value: 0
+ *
+ * Specifies the maximum number of scatter/gather elements in grant pages
+ * supported. If not set, the backend supports up to VSCSIIF_SG_TABLESIZE
+ * SG elements specified directly in the request.
+ *
+ *****************************************************************************
+ * Frontend XenBus Nodes
+ *****************************************************************************
+ *
+ *----------------------- Request Transport Parameters -----------------------
+ *
+ * event-channel
+ * Values: unsigned
+ *
+ * The identifier of the Xen event channel used to signal activity
+ * in the ring buffer.
+ *
+ * ring-ref
+ * Values: unsigned
+ *
+ * The Xen grant reference granting permission for the backend to map
+ * the sole page in a single page sized ring buffer.
+ *
+ * protocol
+ * Values: string (XEN_IO_PROTO_ABI_*)
+ * Default Value: XEN_IO_PROTO_ABI_NATIVE
+ *
+ * The machine ABI rules governing the format of all ring request and
+ * response structures.
+ */
+
+/* Requests from the frontend to the backend */
+
+/*
+ * Request a SCSI operation specified via a CDB in vscsiif_request.cmnd.
+ * The target is specified via channel, id and lun.
+ *
+ * The operation to be performed is specified via a CDB in cmnd[], the length
+ * of the CDB is in cmd_len. sc_data_direction specifies the direction of data
+ * (to the device, from the device, or none at all).
+ *
+ * If data is to be transferred to or from the device the buffer(s) in the
+ * guest memory is/are specified via one or multiple scsiif_request_segment
+ * descriptors each specifying a memory page via a grant_ref_t, a offset into
+ * the page and the length of the area in that page. All scsiif_request_segment
+ * areas concatenated form the resulting data buffer used by the operation.
+ * If the number of scsiif_request_segment areas is not too large (less than
+ * or equal VSCSIIF_SG_TABLESIZE) the areas can be specified directly in the
+ * seg[] array and the number of valid scsiif_request_segment elements is to be
+ * set in nr_segments.
+ *
+ * If "feature-sg-grant" in the Xenstore is set it is possible to specify more
+ * than VSCSIIF_SG_TABLESIZE scsiif_request_segment elements via indirection.
+ * The maximum number of allowed scsiif_request_segment elements is the value
+ * of the "feature-sg-grant" entry from Xenstore. When using indirection the
+ * seg[] array doesn't contain specifications of the data buffers, but
+ * references to scsiif_request_segment arrays, which in turn reference the
+ * data buffers. While nr_segments holds the number of populated seg[] entries
+ * (plus the set VSCSIIF_SG_GRANT bit), the number of scsiif_request_segment
+ * elements referencing the target data buffers is calculated from the lengths
+ * of the seg[] elements (the sum of all valid seg[].length divided by the
+ * size of one scsiif_request_segment structure). The frontend may use a mix of
+ * direct and indirect requests.
+ */
+#define VSCSIIF_ACT_SCSI_CDB 1
+
+/*
+ * Request abort of a running operation for the specified target given by
+ * channel, id, lun and the operation's rqid in ref_rqid.
+ */
+#define VSCSIIF_ACT_SCSI_ABORT 2
+
+/*
+ * Request a device reset of the specified target (channel and id).
+ */
+#define VSCSIIF_ACT_SCSI_RESET 3
+
+/*
+ * Preset scatter/gather elements for a following request. Deprecated.
+ * Keeping the define only to avoid usage of the value "4" for other actions.
+ */
+#define VSCSIIF_ACT_SCSI_SG_PRESET 4
/*
* Maximum scatter/gather segments per request.
@@ -42,11 +162,20 @@
* Considering balance between allocating at least 16 "vscsiif_request"
* structures on one page (4096 bytes) and the number of scatter/gather
* elements needed, we decided to use 26 as a magic number.
+ *
+ * If "feature-sg-grant" is set, more scatter/gather elements can be specified
+ * by placing them in one or more (up to VSCSIIF_SG_TABLESIZE) granted pages.
+ * In this case the vscsiif_request seg elements don't contain references to
+ * the user data, but to the SG elements referencing the user data.
*/
#define VSCSIIF_SG_TABLESIZE 26
/*
- * based on Linux kernel 2.6.18
+ * based on Linux kernel 2.6.18, still valid
+ *
+ * Changing these values requires support of multiple protocols via the rings
+ * as "old clients" will blindly use these values and the resulting structure
+ * sizes.
*/
#define VSCSIIF_MAX_COMMAND_SIZE 16
#define VSCSIIF_SENSE_BUFFERSIZE 96
@@ -58,26 +187,38 @@ struct scsiif_request_segment {
};
typedef struct scsiif_request_segment vscsiif_segment_t;
+#define VSCSIIF_SG_PER_PAGE (PAGE_SIZE / sizeof(struct scsiif_request_segment))
+
+/* Size of one request is 252 bytes */
struct vscsiif_request {
uint16_t rqid; /* private guest value, echoed in resp */
uint8_t act; /* command between backend and frontend */
- uint8_t cmd_len;
-
- uint8_t cmnd[VSCSIIF_MAX_COMMAND_SIZE];
- uint16_t timeout_per_command; /* The command is issued by twice
- the value in Backend. */
- uint16_t channel, id, lun;
- uint16_t padding;
- uint8_t sc_data_direction; /* for DMA_TO_DEVICE(1)
- DMA_FROM_DEVICE(2)
- DMA_NONE(3) requests */
- uint8_t nr_segments; /* Number of pieces of scatter-gather */
+ uint8_t cmd_len; /* valid CDB bytes */
+
+ uint8_t cmnd[VSCSIIF_MAX_COMMAND_SIZE]; /* the CDB */
+ uint16_t timeout_per_command; /* deprecated: timeout in secs, 0=default */
+ uint16_t channel, id, lun; /* (virtual) device specification */
+ uint16_t ref_rqid; /* command abort reference */
+ uint8_t sc_data_direction; /* for DMA_TO_DEVICE(1)
+ DMA_FROM_DEVICE(2)
+ DMA_NONE(3) requests */
+ uint8_t nr_segments; /* Number of pieces of scatter-gather */
+/*
+ * flag in nr_segments: SG elements via grant page
+ *
+ * If VSCSIIF_SG_GRANT is set, the low 7 bits of nr_segments specify the number
+ * of grant pages containing SG elements. Usable if "feature-sg-grant" set.
+ */
+#define VSCSIIF_SG_GRANT 0x80
vscsiif_segment_t seg[VSCSIIF_SG_TABLESIZE];
uint32_t reserved[3];
};
typedef struct vscsiif_request vscsiif_request_t;
+/*
+ * The following interface is deprecated!
+ */
#define VSCSIIF_SG_LIST_SIZE ((sizeof(vscsiif_request_t) - 4) \
/ sizeof(vscsiif_segment_t))
@@ -89,10 +230,12 @@ struct vscsiif_sg_list {
vscsiif_segment_t seg[VSCSIIF_SG_LIST_SIZE];
};
typedef struct vscsiif_sg_list vscsiif_sg_list_t;
+/* End of deprecated interface */
+/* Size of one response is 252 bytes */
struct vscsiif_response {
- uint16_t rqid;
- uint8_t act; /* valid only when backend supports SG_PRESET */
+ uint16_t rqid; /* identifies request */
+ uint8_t act; /* deprecated: valid only if SG_PRESET supported */
uint8_t sense_len;
uint8_t sense_buffer[VSCSIIF_SENSE_BUFFERSIZE];
int32_t rslt;
diff --git a/xen/include/public/io/xs_wire.h b/xen/include/public/io/xs_wire.h
index 585f0c8..0a0cdbc 100644
--- a/xen/include/public/io/xs_wire.h
+++ b/xen/include/public/io/xs_wire.h
@@ -49,7 +49,9 @@ enum xsd_sockmsg_type
XS_RESUME,
XS_SET_TARGET,
XS_RESTRICT,
- XS_RESET_WATCHES
+ XS_RESET_WATCHES,
+
+ XS_INVALID = 0xffff /* Guaranteed to remain an invalid type */
};
#define XS_WRITE_NONE "NONE"
@@ -116,6 +118,8 @@ struct xenstore_domain_interface {
char rsp[XENSTORE_RING_SIZE]; /* Replies and async watch events. */
XENSTORE_RING_IDX req_cons, req_prod;
XENSTORE_RING_IDX rsp_cons, rsp_prod;
+ uint32_t server_features; /* Bitmap of features supported by the server */
+ uint32_t connection;
};
/* Violating this is very bad. See docs/misc/xenstore.txt. */
@@ -125,6 +129,13 @@ struct xenstore_domain_interface {
#define XENSTORE_ABS_PATH_MAX 3072
#define XENSTORE_REL_PATH_MAX 2048
+/* The ability to reconnect a ring */
+#define XENSTORE_SERVER_FEATURE_RECONNECTION 1
+
+/* Valid values for the connection field */
+#define XENSTORE_CONNECTED 0 /* the steady-state */
+#define XENSTORE_RECONNECT 1 /* guest has initiated a reconnect */
+
#endif /* _XS_WIRE_H */
/*
diff --git a/xen/include/public/mem_event.h b/xen/include/public/mem_event.h
index c9ed546..599f9e8 100644
--- a/xen/include/public/mem_event.h
+++ b/xen/include/public/mem_event.h
@@ -31,23 +31,72 @@
#include "io/ring.h"
/* Memory event flags */
-#define MEM_EVENT_FLAG_VCPU_PAUSED (1 << 0)
-#define MEM_EVENT_FLAG_DROP_PAGE (1 << 1)
-#define MEM_EVENT_FLAG_EVICT_FAIL (1 << 2)
-#define MEM_EVENT_FLAG_FOREIGN (1 << 3)
-#define MEM_EVENT_FLAG_DUMMY (1 << 4)
+#define MEM_EVENT_FLAG_VCPU_PAUSED (1 << 0)
+#define MEM_EVENT_FLAG_DROP_PAGE (1 << 1)
+#define MEM_EVENT_FLAG_EVICT_FAIL (1 << 2)
+#define MEM_EVENT_FLAG_FOREIGN (1 << 3)
+#define MEM_EVENT_FLAG_DUMMY (1 << 4)
+/*
+ * Emulate the fault-causing instruction (if set in the event response flags).
+ * This will allow the guest to continue execution without lifting the page
+ * access restrictions.
+ */
+#define MEM_EVENT_FLAG_EMULATE (1 << 5)
+/*
+ * Same as MEM_EVENT_FLAG_EMULATE, but with write operations or operations
+ * potentially having side effects (like memory mapped or port I/O) disabled.
+ */
+#define MEM_EVENT_FLAG_EMULATE_NOWRITE (1 << 6)
/* Reasons for the memory event request */
#define MEM_EVENT_REASON_UNKNOWN 0 /* typical reason */
#define MEM_EVENT_REASON_VIOLATION 1 /* access violation, GFN is address */
-#define MEM_EVENT_REASON_CR0 2 /* CR0 was hit: gfn is CR0 value */
-#define MEM_EVENT_REASON_CR3 3 /* CR3 was hit: gfn is CR3 value */
-#define MEM_EVENT_REASON_CR4 4 /* CR4 was hit: gfn is CR4 value */
+#define MEM_EVENT_REASON_CR0 2 /* CR0 was hit: gfn is new CR0 value, gla is previous */
+#define MEM_EVENT_REASON_CR3 3 /* CR3 was hit: gfn is new CR3 value, gla is previous */
+#define MEM_EVENT_REASON_CR4 4 /* CR4 was hit: gfn is new CR4 value, gla is previous */
#define MEM_EVENT_REASON_INT3 5 /* int3 was hit: gla/gfn are RIP */
#define MEM_EVENT_REASON_SINGLESTEP 6 /* single step was invoked: gla/gfn are RIP */
#define MEM_EVENT_REASON_MSR 7 /* MSR was hit: gfn is MSR value, gla is MSR address;
does NOT honour HVMPME_onchangeonly */
+/* Using a custom struct (not hvm_hw_cpu) so as to not fill
+ * the mem_event ring buffer too quickly. */
+struct mem_event_regs_x86 {
+ uint64_t rax;
+ uint64_t rcx;
+ uint64_t rdx;
+ uint64_t rbx;
+ uint64_t rsp;
+ uint64_t rbp;
+ uint64_t rsi;
+ uint64_t rdi;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ uint64_t rflags;
+ uint64_t dr7;
+ uint64_t rip;
+ uint64_t cr0;
+ uint64_t cr2;
+ uint64_t cr3;
+ uint64_t cr4;
+ uint64_t sysenter_cs;
+ uint64_t sysenter_esp;
+ uint64_t sysenter_eip;
+ uint64_t msr_efer;
+ uint64_t msr_star;
+ uint64_t msr_lstar;
+ uint64_t fs_base;
+ uint64_t gs_base;
+ uint32_t cs_arbytes;
+ uint32_t _pad;
+};
+
typedef struct mem_event_st {
uint32_t flags;
uint32_t vcpu_id;
@@ -62,9 +111,12 @@ typedef struct mem_event_st {
uint16_t access_w:1;
uint16_t access_x:1;
uint16_t gla_valid:1;
- uint16_t available:12;
+ uint16_t fault_with_gla:1;
+ uint16_t fault_in_gpt:1;
+ uint16_t available:10;
uint16_t reason;
+ struct mem_event_regs_x86 x86_regs;
} mem_event_request_t, mem_event_response_t;
DEFINE_RING_TYPES(mem_event, mem_event_request_t, mem_event_response_t);
diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h
index f19ac14..595f953 100644
--- a/xen/include/public/memory.h
+++ b/xen/include/public/memory.h
@@ -187,6 +187,15 @@ typedef struct xen_machphys_mfn_list xen_machphys_mfn_list_t;
DEFINE_XEN_GUEST_HANDLE(xen_machphys_mfn_list_t);
/*
+ * For a compat caller, this is identical to XENMEM_machphys_mfn_list.
+ *
+ * For a non compat caller, this functions similarly to
+ * XENMEM_machphys_mfn_list, but returns the mfns making up the compatibility
+ * m2p table.
+ */
+#define XENMEM_machphys_compat_mfn_list 25
+
+/*
* Returns the location in virtual address space of the machine_to_phys
* mapping table. Architectures which do not have a m2p table, or which do not
* map it by default into guest address space, do not implement this command.
@@ -363,9 +372,6 @@ typedef struct xen_pod_target xen_pod_target_t;
#define XENMEM_paging_op_evict 1
#define XENMEM_paging_op_prep 2
-#define XENMEM_access_op 21
-#define XENMEM_access_op_resume 0
-
struct xen_mem_event_op {
uint8_t op; /* XENMEM_*_op_* */
domid_t domain;
@@ -379,6 +385,56 @@ struct xen_mem_event_op {
typedef struct xen_mem_event_op xen_mem_event_op_t;
DEFINE_XEN_GUEST_HANDLE(xen_mem_event_op_t);
+#define XENMEM_access_op 21
+#define XENMEM_access_op_resume 0
+#define XENMEM_access_op_set_access 1
+#define XENMEM_access_op_get_access 2
+
+typedef enum {
+ XENMEM_access_n,
+ XENMEM_access_r,
+ XENMEM_access_w,
+ XENMEM_access_rw,
+ XENMEM_access_x,
+ XENMEM_access_rx,
+ XENMEM_access_wx,
+ XENMEM_access_rwx,
+ /*
+ * Page starts off as r-x, but automatically
+ * change to r-w on a write
+ */
+ XENMEM_access_rx2rw,
+ /*
+ * Log access: starts off as n, automatically
+ * goes to rwx, generating an event without
+ * pausing the vcpu
+ */
+ XENMEM_access_n2rwx,
+ /* Take the domain default */
+ XENMEM_access_default
+} xenmem_access_t;
+
+struct xen_mem_access_op {
+ /* XENMEM_access_op_* */
+ uint8_t op;
+ /* xenmem_access_t */
+ uint8_t access;
+ domid_t domid;
+ /*
+ * Number of pages for set op
+ * Ignored on setting default access and other ops
+ */
+ uint32_t nr;
+ /*
+ * First pfn for set op
+ * pfn for get op
+ * ~0ull is used to set and get the default access for pages
+ */
+ uint64_aligned_t pfn;
+};
+typedef struct xen_mem_access_op xen_mem_access_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mem_access_op_t);
+
#define XENMEM_sharing_op 22
#define XENMEM_sharing_op_nominate_gfn 0
#define XENMEM_sharing_op_nominate_gref 1
@@ -467,6 +523,57 @@ DEFINE_XEN_GUEST_HANDLE(xen_mem_sharing_op_t);
#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
+/*
+ * XENMEM_get_vnumainfo used by guest to get
+ * vNUMA topology from hypervisor.
+ */
+#define XENMEM_get_vnumainfo 26
+
+/* vNUMA node memory ranges */
+struct xen_vmemrange {
+ uint64_t start, end;
+ unsigned int flags;
+ unsigned int nid;
+};
+typedef struct xen_vmemrange xen_vmemrange_t;
+DEFINE_XEN_GUEST_HANDLE(xen_vmemrange_t);
+
+/*
+ * vNUMA topology specifies vNUMA node number, distance table,
+ * memory ranges and vcpu mapping provided for guests.
+ * XENMEM_get_vnumainfo hypercall expects to see from guest
+ * nr_vnodes, nr_vmemranges and nr_vcpus to indicate available memory.
+ * After filling guests structures, nr_vnodes, nr_vmemranges and nr_vcpus
+ * copied back to guest. Domain returns expected values of nr_vnodes,
+ * nr_vmemranges and nr_vcpus to guest if the values where incorrect.
+ */
+struct xen_vnuma_topology_info {
+ /* IN */
+ domid_t domid;
+ uint16_t pad;
+ /* IN/OUT */
+ unsigned int nr_vnodes;
+ unsigned int nr_vcpus;
+ unsigned int nr_vmemranges;
+ /* OUT */
+ union {
+ XEN_GUEST_HANDLE(uint) h;
+ uint64_t pad;
+ } vdistance;
+ union {
+ XEN_GUEST_HANDLE(uint) h;
+ uint64_t pad;
+ } vcpu_to_vnode;
+ union {
+ XEN_GUEST_HANDLE(xen_vmemrange_t) h;
+ uint64_t pad;
+ } vmemrange;
+};
+typedef struct xen_vnuma_topology_info xen_vnuma_topology_info_t;
+DEFINE_XEN_GUEST_HANDLE(xen_vnuma_topology_info_t);
+
+/* Next available subop number is 27 */
+
#endif /* __XEN_PUBLIC_MEMORY_H__ */
/*
diff --git a/xen/include/public/platform.h b/xen/include/public/platform.h
index 4341f54..5c57615 100644
--- a/xen/include/public/platform.h
+++ b/xen/include/public/platform.h
@@ -134,7 +134,7 @@ struct xenpf_efi_runtime_call {
* where it holds the single returned value.
*/
uint32_t misc;
- unsigned long status;
+ xen_ulong_t status;
union {
#define XEN_EFI_GET_TIME_SET_CLEARS_NS 0x00000001
struct {
@@ -168,7 +168,7 @@ struct xenpf_efi_runtime_call {
#define XEN_EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
struct {
XEN_GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */
- unsigned long size;
+ xen_ulong_t size;
XEN_GUEST_HANDLE(void) data;
struct xenpf_efi_guid {
uint32_t data1;
@@ -179,7 +179,7 @@ struct xenpf_efi_runtime_call {
} get_variable, set_variable;
struct {
- unsigned long size;
+ xen_ulong_t size;
XEN_GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */
struct xenpf_efi_guid vendor_guid;
} get_next_variable_name;
@@ -194,14 +194,14 @@ struct xenpf_efi_runtime_call {
struct {
XEN_GUEST_HANDLE(void) capsule_header_array;
- unsigned long capsule_count;
+ xen_ulong_t capsule_count;
uint64_t max_capsule_size;
- unsigned int reset_type;
+ uint32_t reset_type;
} query_capsule_capabilities;
struct {
XEN_GUEST_HANDLE(void) capsule_header_array;
- unsigned long capsule_count;
+ xen_ulong_t capsule_count;
uint64_t sg_list; /* machine address */
} update_capsule;
} u;
@@ -528,6 +528,39 @@ typedef struct xenpf_core_parking xenpf_core_parking_t;
DEFINE_XEN_GUEST_HANDLE(xenpf_core_parking_t);
/*
+ * Access generic platform resources(e.g., accessing MSR, port I/O, etc)
+ * in unified way. Batch resource operations in one call are supported and
+ * they are always non-preemptible and executed in their original order.
+ * The batch itself returns a negative integer for general errors, or a
+ * non-negative integer for the number of successful operations. For the latter
+ * case, the @ret in the failed entry (if any) indicates the exact error.
+ */
+#define XENPF_resource_op 61
+
+#define XEN_RESOURCE_OP_MSR_READ 0
+#define XEN_RESOURCE_OP_MSR_WRITE 1
+
+struct xenpf_resource_entry {
+ union {
+ uint32_t cmd; /* IN: XEN_RESOURCE_OP_* */
+ int32_t ret; /* OUT: return value for failed entry */
+ } u;
+ uint32_t rsvd; /* IN: padding and must be zero */
+ uint64_t idx; /* IN: resource address to access */
+ uint64_t val; /* IN/OUT: resource value to set/get */
+};
+typedef struct xenpf_resource_entry xenpf_resource_entry_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_resource_entry_t);
+
+struct xenpf_resource_op {
+ uint32_t nr_entries; /* number of resource entry */
+ uint32_t cpu; /* which cpu to run */
+ XEN_GUEST_HANDLE(xenpf_resource_entry_t) entries;
+};
+typedef struct xenpf_resource_op xenpf_resource_op_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_resource_op_t);
+
+/*
* ` enum neg_errnoval
* ` HYPERVISOR_platform_op(const struct xen_platform_op*);
*/
@@ -553,6 +586,7 @@ struct xen_platform_op {
struct xenpf_cpu_hotadd cpu_add;
struct xenpf_mem_hotadd mem_add;
struct xenpf_core_parking core_parking;
+ struct xenpf_resource_op resource_op;
uint8_t pad[128];
} u;
};
diff --git a/xen/include/public/sched.h b/xen/include/public/sched.h
index a30b11d..4000ac9 100644
--- a/xen/include/public/sched.h
+++ b/xen/include/public/sched.h
@@ -76,9 +76,10 @@
* Halt execution of this domain (all VCPUs) and notify the system controller.
* @arg == pointer to sched_shutdown_t structure.
*
- * If the sched_shutdown_t reason is SHUTDOWN_suspend then this
- * hypercall takes an additional extra argument which should be the
- * MFN of the guest's start_info_t.
+ * If the sched_shutdown_t reason is SHUTDOWN_suspend then
+ * x86 PV guests must also set RDX (EDX for 32-bit guests) to the MFN
+ * of the guest's start info page. RDX/EDX is the third hypercall
+ * argument.
*
* In addition, which reason is SHUTDOWN_suspend this hypercall
* returns 1 if suspend was cancelled or the domain was merely
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index 8437d31..b3713b3 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -34,7 +34,7 @@
#include "xen.h"
#include "domctl.h"
-#define XEN_SYSCTL_INTERFACE_VERSION 0x0000000A
+#define XEN_SYSCTL_INTERFACE_VERSION 0x0000000B
/*
* Read console content from Xen buffer ring.
@@ -226,13 +226,17 @@ struct pm_cx_stat {
uint64_aligned_t idle_time; /* idle time from boot */
XEN_GUEST_HANDLE_64(uint64) triggers; /* Cx trigger counts */
XEN_GUEST_HANDLE_64(uint64) residencies; /* Cx residencies */
- uint64_aligned_t pc2;
- uint64_aligned_t pc3;
- uint64_aligned_t pc6;
- uint64_aligned_t pc7;
- uint64_aligned_t cc3;
- uint64_aligned_t cc6;
- uint64_aligned_t cc7;
+ uint32_t nr_pc; /* entry nr in pc[] */
+ uint32_t nr_cc; /* entry nr in cc[] */
+ /*
+ * These two arrays may (and generally will) have unused slots; slots not
+ * having a corresponding hardware register will not be written by the
+ * hypervisor. It is therefore up to the caller to put a suitable sentinel
+ * into all slots before invoking the function.
+ * Indexing is 1-biased (PC1/CC1 being at index 0).
+ */
+ XEN_GUEST_HANDLE_64(uint64) pc;
+ XEN_GUEST_HANDLE_64(uint64) cc;
};
struct xen_sysctl_get_pmstat {
@@ -632,6 +636,24 @@ struct xen_sysctl_coverage_op {
typedef struct xen_sysctl_coverage_op xen_sysctl_coverage_op_t;
DEFINE_XEN_GUEST_HANDLE(xen_sysctl_coverage_op_t);
+#define XEN_SYSCTL_PSR_CMT_get_total_rmid 0
+#define XEN_SYSCTL_PSR_CMT_get_l3_upscaling_factor 1
+/* The L3 cache size is returned in KB unit */
+#define XEN_SYSCTL_PSR_CMT_get_l3_cache_size 2
+#define XEN_SYSCTL_PSR_CMT_enabled 3
+struct xen_sysctl_psr_cmt_op {
+ uint32_t cmd; /* IN: XEN_SYSCTL_PSR_CMT_* */
+ uint32_t flags; /* padding variable, may be extended for future use */
+ union {
+ uint64_t data; /* OUT */
+ struct {
+ uint32_t cpu; /* IN */
+ uint32_t rsvd;
+ } l3_cache;
+ } u;
+};
+typedef struct xen_sysctl_psr_cmt_op xen_sysctl_psr_cmt_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_psr_cmt_op_t);
struct xen_sysctl {
uint32_t cmd;
@@ -654,6 +676,7 @@ struct xen_sysctl {
#define XEN_SYSCTL_cpupool_op 18
#define XEN_SYSCTL_scheduler_op 19
#define XEN_SYSCTL_coverage_op 20
+#define XEN_SYSCTL_psr_cmt_op 21
uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
union {
struct xen_sysctl_readconsole readconsole;
@@ -675,6 +698,7 @@ struct xen_sysctl {
struct xen_sysctl_cpupool_op cpupool_op;
struct xen_sysctl_scheduler_op scheduler_op;
struct xen_sysctl_coverage_op coverage_op;
+ struct xen_sysctl_psr_cmt_op psr_cmt_op;
uint8_t pad[128];
} u;
};
diff --git a/xen/include/public/trace.h b/xen/include/public/trace.h
index e2f60a6..5211ae7 100644
--- a/xen/include/public/trace.h
+++ b/xen/include/public/trace.h
@@ -50,8 +50,9 @@
#define TRC_SUBCLS_SHIFT 12
/* trace subclasses for SVM */
-#define TRC_HVM_ENTRYEXIT 0x00081000 /* VMENTRY and #VMEXIT */
-#define TRC_HVM_HANDLER 0x00082000 /* various HVM handlers */
+#define TRC_HVM_ENTRYEXIT 0x00081000 /* VMENTRY and #VMEXIT */
+#define TRC_HVM_HANDLER 0x00082000 /* various HVM handlers */
+#define TRC_HVM_EMUL 0x00084000 /* emulated devices */
#define TRC_SCHED_MIN 0x00021000 /* Just runstate changes */
#define TRC_SCHED_CLASS 0x00022000 /* Scheduler-specific */
@@ -76,6 +77,7 @@
#define TRC_SCHED_CSCHED2 1
#define TRC_SCHED_SEDF 2
#define TRC_SCHED_ARINC653 3
+#define TRC_SCHED_RTDS 4
/* Per-scheduler tracing */
#define TRC_SCHED_CLASS_EVT(_c, _e) \
@@ -229,6 +231,25 @@
#define TRC_HVM_IOPORT_WRITE (TRC_HVM_HANDLER + 0x216)
#define TRC_HVM_IOMEM_WRITE (TRC_HVM_HANDLER + 0x217)
+/* Trace events for emulated devices */
+#define TRC_HVM_EMUL_HPET_START_TIMER (TRC_HVM_EMUL + 0x1)
+#define TRC_HVM_EMUL_PIT_START_TIMER (TRC_HVM_EMUL + 0x2)
+#define TRC_HVM_EMUL_RTC_START_TIMER (TRC_HVM_EMUL + 0x3)
+#define TRC_HVM_EMUL_LAPIC_START_TIMER (TRC_HVM_EMUL + 0x4)
+#define TRC_HVM_EMUL_HPET_STOP_TIMER (TRC_HVM_EMUL + 0x5)
+#define TRC_HVM_EMUL_PIT_STOP_TIMER (TRC_HVM_EMUL + 0x6)
+#define TRC_HVM_EMUL_RTC_STOP_TIMER (TRC_HVM_EMUL + 0x7)
+#define TRC_HVM_EMUL_LAPIC_STOP_TIMER (TRC_HVM_EMUL + 0x8)
+#define TRC_HVM_EMUL_PIT_TIMER_CB (TRC_HVM_EMUL + 0x9)
+#define TRC_HVM_EMUL_LAPIC_TIMER_CB (TRC_HVM_EMUL + 0xA)
+#define TRC_HVM_EMUL_PIC_INT_OUTPUT (TRC_HVM_EMUL + 0xB)
+#define TRC_HVM_EMUL_PIC_KICK (TRC_HVM_EMUL + 0xC)
+#define TRC_HVM_EMUL_PIC_INTACK (TRC_HVM_EMUL + 0xD)
+#define TRC_HVM_EMUL_PIC_POSEDGE (TRC_HVM_EMUL + 0xE)
+#define TRC_HVM_EMUL_PIC_NEGEDGE (TRC_HVM_EMUL + 0xF)
+#define TRC_HVM_EMUL_PIC_PEND_IRQ_CALL (TRC_HVM_EMUL + 0x10)
+#define TRC_HVM_EMUL_LAPIC_PIC_INTR (TRC_HVM_EMUL + 0x11)
+
/* trace events for per class */
#define TRC_PM_FREQ_CHANGE (TRC_HW_PM + 0x01)
#define TRC_PM_IDLE_ENTRY (TRC_HW_PM + 0x02)
diff --git a/xen/include/xen/bitmap.h b/xen/include/xen/bitmap.h
index b5ec455..e2a3686 100644
--- a/xen/include/xen/bitmap.h
+++ b/xen/include/xen/bitmap.h
@@ -110,13 +110,14 @@ extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order);
#define bitmap_bytes(nbits) (BITS_TO_LONGS(nbits) * sizeof(unsigned long))
-#define bitmap_switch(nbits, zero_ret, small, large) \
- switch (-!__builtin_constant_p(nbits) | (nbits)) { \
- case 0: return zero_ret; \
- case 1 ... BITS_PER_LONG: \
- small; break; \
- default: \
- large; break; \
+#define bitmap_switch(nbits, zero, small, large) \
+ unsigned int n__ = (nbits); \
+ if (__builtin_constant_p(nbits) && !n__) { \
+ zero; \
+ } else if (__builtin_constant_p(nbits) && n__ <= BITS_PER_LONG) { \
+ small; \
+ } else { \
+ large; \
}
static inline void bitmap_zero(unsigned long *dst, int nbits)
@@ -191,7 +192,8 @@ static inline void bitmap_complement(unsigned long *dst, const unsigned long *sr
static inline int bitmap_equal(const unsigned long *src1,
const unsigned long *src2, int nbits)
{
- bitmap_switch(nbits, -1,
+ bitmap_switch(nbits,
+ return -1,
return !((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits)),
return __bitmap_equal(src1, src2, nbits));
}
@@ -199,7 +201,8 @@ static inline int bitmap_equal(const unsigned long *src1,
static inline int bitmap_intersects(const unsigned long *src1,
const unsigned long *src2, int nbits)
{
- bitmap_switch(nbits, -1,
+ bitmap_switch(nbits,
+ return -1,
return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0,
return __bitmap_intersects(src1, src2, nbits));
}
@@ -207,21 +210,24 @@ static inline int bitmap_intersects(const unsigned long *src1,
static inline int bitmap_subset(const unsigned long *src1,
const unsigned long *src2, int nbits)
{
- bitmap_switch(nbits, -1,
+ bitmap_switch(nbits,
+ return -1,
return !((*src1 & ~*src2) & BITMAP_LAST_WORD_MASK(nbits)),
return __bitmap_subset(src1, src2, nbits));
}
static inline int bitmap_empty(const unsigned long *src, int nbits)
{
- bitmap_switch(nbits, -1,
+ bitmap_switch(nbits,
+ return -1,
return !(*src & BITMAP_LAST_WORD_MASK(nbits)),
return __bitmap_empty(src, nbits));
}
static inline int bitmap_full(const unsigned long *src, int nbits)
{
- bitmap_switch(nbits, -1,
+ bitmap_switch(nbits,
+ return -1,
return !(~*src & BITMAP_LAST_WORD_MASK(nbits)),
return __bitmap_full(src, nbits));
}
diff --git a/xen/include/xen/compat.h b/xen/include/xen/compat.h
index ca60699..e5c23e2 100644
--- a/xen/include/xen/compat.h
+++ b/xen/include/xen/compat.h
@@ -14,7 +14,7 @@
#define __DEFINE_COMPAT_HANDLE(name, type) \
typedef struct { \
compat_ptr_t c; \
- type *_[0] __attribute__((__packed__)); \
+ type *_[0] __packed; \
} __compat_handle_ ## name
#define DEFINE_COMPAT_HANDLE(name) \
@@ -195,6 +195,8 @@ static inline int name(k xen_ ## n *x, k compat_ ## n *c) \
* This option is useful for extracting the "op" argument or similar from the
* hypercall to enable further xlat processing.
*
+ * nr: Total number of arguments the hypercall has.
+ *
* mask: Specifies which of the hypercall arguments require compat translation.
* bit 0 indicates that the 0'th argument requires translation, bit 1 indicates
* that the first argument requires translation and so on. Native and compat
@@ -214,7 +216,8 @@ static inline int name(k xen_ ## n *x, k compat_ ## n *c) \
*
* Return: Number of arguments which were actually translated.
*/
-int hypercall_xlat_continuation(unsigned int *id, unsigned int mask, ...);
+int hypercall_xlat_continuation(unsigned int *id, unsigned int nr,
+ unsigned int mask, ...);
/* In-place translation functons: */
struct start_info;
diff --git a/xen/include/xen/compiler.h b/xen/include/xen/compiler.h
index 7d6805c..4b3472d 100644
--- a/xen/include/xen/compiler.h
+++ b/xen/include/xen/compiler.h
@@ -7,13 +7,17 @@
#define barrier() __asm__ __volatile__("": : :"memory")
-#define likely(x) __builtin_expect((x),1)
-#define unlikely(x) __builtin_expect((x),0)
+#define likely(x) __builtin_expect(!!(x),1)
+#define unlikely(x) __builtin_expect(!!(x),0)
#define inline __inline__
#define always_inline __inline__ __attribute__ ((always_inline))
#define noinline __attribute__((noinline))
+#define noreturn __attribute__((noreturn))
+
+#define __packed __attribute__((packed))
+
#if (!defined(__clang__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 5))
#define unreachable() do {} while (1)
#else
diff --git a/xen/include/xen/config.h b/xen/include/xen/config.h
index 657c6e5..7bef8a6 100644
--- a/xen/include/xen/config.h
+++ b/xen/include/xen/config.h
@@ -74,12 +74,11 @@
#ifndef __ASSEMBLY__
-int current_domain_id(void);
#define dprintk(_l, _f, _a...) \
printk(_l "%s:%d: " _f, __FILE__ , __LINE__ , ## _a )
#define gdprintk(_l, _f, _a...) \
- printk(XENLOG_GUEST _l "%s:%d:d%d " _f, __FILE__, \
- __LINE__, current_domain_id() , ## _a )
+ printk(XENLOG_GUEST _l "%s:%d:%pv " _f, __FILE__, \
+ __LINE__, current, ## _a )
#endif /* !__ASSEMBLY__ */
@@ -99,4 +98,14 @@ int current_domain_id(void);
#define __cpuinitdata
#define __cpuinit
+#ifdef FLASK_ENABLE
+#define XSM_MAGIC 0xf97cff8c
+/* Enable permissive mode (xl setenforce or flask_enforcing parameter) */
+#define FLASK_DEVELOP 1
+/* Allow runtime disabling of FLASK via the flask_enable parameter */
+#define FLASK_BOOTPARAM 1
+/* Maintain statistics on the access vector cache */
+#define FLASK_AVC_STATS 1
+#endif
+
#endif /* __XEN_CONFIG_H__ */
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index 9a8c3de..08db8bc 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -15,46 +15,11 @@
#include <xen/init.h>
#include <xen/string.h>
#include <xen/types.h>
+#include <xen/stdbool.h>
+#include <xen/list.h>
#define DEVICE_TREE_MAX_DEPTH 16
-#define NR_MEM_BANKS 8
-
-#define MOD_XEN 0
-#define MOD_FDT 1
-#define MOD_KERNEL 2
-#define MOD_INITRD 3
-#define NR_MODULES 4
-
-#define MOD_DISCARD_FIRST MOD_FDT
-
-struct membank {
- paddr_t start;
- paddr_t size;
-};
-
-struct dt_mem_info {
- int nr_banks;
- struct membank bank[NR_MEM_BANKS];
-};
-
-struct dt_mb_module {
- paddr_t start;
- paddr_t size;
- char cmdline[1024];
-};
-
-struct dt_module_info {
- int nr_mods;
- /* Module 0 is Xen itself, followed by the provided modules-proper */
- struct dt_mb_module module[NR_MODULES];
-};
-
-struct dt_early_info {
- struct dt_mem_info mem;
- struct dt_module_info modules;
-};
-
/*
* Struct used for matching a device
*/
@@ -62,11 +27,13 @@ struct dt_device_match {
const char *path;
const char *type;
const char *compatible;
+ const bool_t not_available;
};
#define DT_MATCH_PATH(p) { .path = p }
#define DT_MATCH_TYPE(typ) { .type = typ }
#define DT_MATCH_COMPATIBLE(compat) { .compatible = compat }
+#define DT_MATCH_NOT_AVAILABLE() { .not_available = 1 }
typedef u32 dt_phandle;
@@ -109,6 +76,16 @@ struct dt_device_node {
struct dt_device_node *next; /* TODO: Remove it. Only use to know the last children */
struct dt_device_node *allnext;
+ /* IOMMU specific fields */
+ bool is_protected;
+ struct list_head domain_list;
+};
+
+#define MAX_PHANDLE_ARGS 16
+struct dt_phandle_args {
+ struct dt_device_node *np;
+ int args_count;
+ uint32_t args[MAX_PHANDLE_ARGS];
};
/**
@@ -122,6 +99,7 @@ struct dt_device_node {
* DT_IRQ_TYPE_LEVEL_LOW - low level triggered
* DT_IRQ_TYPE_LEVEL_MASK - Mask to filter out the level bits
* DT_IRQ_TYPE_SENSE_MASK - Mask for all the above bits
+ * DT_IRQ_TYPE_INVALID - Use to initialize the type
*/
#define DT_IRQ_TYPE_NONE 0x00000000
#define DT_IRQ_TYPE_EDGE_RISING 0x00000001
@@ -134,6 +112,8 @@ struct dt_device_node {
(DT_IRQ_TYPE_LEVEL_LOW | DT_IRQ_TYPE_LEVEL_HIGH)
#define DT_IRQ_TYPE_SENSE_MASK 0x0000000f
+#define DT_IRQ_TYPE_INVALID 0x00000010
+
/**
* dt_irq - describe an IRQ in the device tree
* @irq: IRQ number
@@ -177,14 +157,8 @@ typedef int (*device_tree_node_func)(const void *fdt,
u32 address_cells, u32 size_cells,
void *data);
-extern struct dt_early_info early_info;
extern const void *device_tree_flattened;
-size_t __init device_tree_early_init(const void *fdt, paddr_t paddr);
-
-const char __init *device_tree_bootargs(const void *fdt);
-void __init device_tree_dump(const void *fdt);
-
/**
* dt_unflatten_host_device_tree - Unflatten the host device tree
*
@@ -317,6 +291,16 @@ static inline domid_t dt_device_used_by(const struct dt_device_node *device)
return device->used_by;
}
+static inline void dt_device_set_protected(struct dt_device_node *device)
+{
+ device->is_protected = true;
+}
+
+static inline bool dt_device_is_protected(const struct dt_device_node *device)
+{
+ return device->is_protected;
+}
+
static inline bool_t dt_property_name_is_equal(const struct dt_property *pp,
const char *name)
{
@@ -347,6 +331,10 @@ struct dt_device_node *dt_find_compatible_node(struct dt_device_node *from,
const void *dt_get_property(const struct dt_device_node *np,
const char *name, u32 *lenp);
+const struct dt_property *dt_find_property(const struct dt_device_node *np,
+ const char *name, u32 *lenp);
+
+
/**
* dt_property_read_u32 - Helper to read a u32 property.
* @np: node to get the value
@@ -369,6 +357,22 @@ bool_t dt_property_read_u64(const struct dt_device_node *np,
const char *name, u64 *out_value);
/**
+ * dt_property_read_bool - Check if a property exists
+ * @np: node to get the value
+ * @name: name of the property
+ *
+ * Search for a property in a device node.
+ * Return true if the property exists false otherwise.
+ */
+static inline bool_t dt_property_read_bool(const struct dt_device_node *np,
+ const char *name)
+{
+ const struct dt_property *prop = dt_find_property(np, name, NULL);
+
+ return prop ? true : false;
+}
+
+/**
* dt_property_read_string - Find and read a string from a property
* @np: Device node from which the property value is to be read
* @propname: Name of the property to be searched
@@ -600,6 +604,53 @@ void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
void dt_get_range(const __be32 **cellp, const struct dt_device_node *np,
u64 *address, u64 *size);
+/**
+ * dt_parse_phandle - Resolve a phandle property to a device_node pointer
+ * @np: Pointer to device node holding phandle property
+ * @phandle_name: Name of property holding a phandle value
+ * @index: For properties holding a table of phandles, this is the index into
+ * the table
+ *
+ * Returns the device_node pointer.
+ */
+struct dt_device_node *dt_parse_phandle(const struct dt_device_node *np,
+ const char *phandle_name,
+ int index);
+
+/**
+ * dt_parse_phandle_with_args() - Find a node pointed by phandle in a list
+ * @np: pointer to a device tree node containing a list
+ * @list_name: property name that contains a list
+ * @cells_name: property name that specifies phandles' arguments count
+ * @index: index of a phandle to parse out
+ * @out_args: optional pointer to output arguments structure (will be filled)
+ *
+ * This function is useful to parse lists of phandles and their arguments.
+ * Returns 0 on success and fills out_args, on error returns appropriate
+ * errno value.
+ *
+ * Example:
+ *
+ * phandle1: node1 {
+ * #list-cells = <2>;
+ * }
+ *
+ * phandle2: node2 {
+ * #list-cells = <1>;
+ * }
+ *
+ * node3 {
+ * list = <&phandle1 1 2 &phandle2 3>;
+ * }
+ *
+ * To get a device_node of the `node2' node you may call this:
+ * dt_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
+ */
+int dt_parse_phandle_with_args(const struct dt_device_node *np,
+ const char *list_name,
+ const char *cells_name, int index,
+ struct dt_phandle_args *out_args);
+
#endif /* __XEN_DEVICE_TREE_H */
/*
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index a057069..72667da 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -12,7 +12,7 @@ typedef union {
struct vcpu *alloc_vcpu(
struct domain *d, unsigned int vcpu_id, unsigned int cpu_id);
-struct vcpu *alloc_dom0_vcpu0(void);
+struct vcpu *alloc_dom0_vcpu0(struct domain *dom0);
int vcpu_reset(struct vcpu *);
struct xen_domctl_getdomaininfo;
@@ -59,6 +59,10 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags);
void arch_domain_destroy(struct domain *d);
+void arch_domain_shutdown(struct domain *d);
+void arch_domain_pause(struct domain *d);
+void arch_domain_unpause(struct domain *d);
+
int arch_set_info_guest(struct vcpu *, vcpu_guest_context_u);
void arch_get_info_guest(struct vcpu *, vcpu_guest_context_u);
@@ -89,4 +93,16 @@ extern unsigned int xen_processor_pmbits;
extern bool_t opt_dom0_vcpus_pin;
+/* vnuma topology per domain. */
+struct vnuma_info {
+ unsigned int nr_vnodes;
+ unsigned int nr_vmemranges;
+ unsigned int *vdistance;
+ unsigned int *vcpu_to_vnode;
+ unsigned int *vnode_to_pnode;
+ struct xen_vmemrange *vmemrange;
+};
+
+void vnuma_destroy(struct vnuma_info *vnuma);
+
#endif /* __XEN_DOMAIN_H__ */
diff --git a/xen/include/xen/early_printk.h b/xen/include/xen/early_printk.h
new file mode 100644
index 0000000..2c3e1b3
--- /dev/null
+++ b/xen/include/xen/early_printk.h
@@ -0,0 +1,21 @@
+/*
+ * printk() for use before the console is initialized
+ */
+#ifndef __XEN_EARLY_PRINTK_H__
+#define __XEN_EARLY_PRINTK_H__
+
+#ifdef CONFIG_EARLY_PRINTK
+void early_puts(const char *s);
+#else
+#define early_puts NULL
+#endif
+
+#endif
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/xen/efi.h b/xen/include/xen/efi.h
index 8a2b788..5e02724 100644
--- a/xen/include/xen/efi.h
+++ b/xen/include/xen/efi.h
@@ -28,6 +28,7 @@ struct xenpf_efi_runtime_call;
struct compat_pf_efi_runtime_call;
void efi_init_memory(void);
+paddr_t efi_rs_page_table(void);
unsigned long efi_get_time(void);
void efi_halt_system(void);
void efi_reset_system(bool_t warm);
diff --git a/xen/include/xen/event.h b/xen/include/xen/event.h
index 06c0654..88526f8 100644
--- a/xen/include/xen/event.h
+++ b/xen/include/xen/event.h
@@ -69,6 +69,9 @@ int guest_enabled_event(struct vcpu *v, uint32_t virq);
/* Notify remote end of a Xen-attached event channel.*/
void notify_via_xen_event_channel(struct domain *ld, int lport);
+/* Inject an event channel notification into the guest */
+void arch_evtchn_inject(struct vcpu *v);
+
/*
* Internal event channel object storage.
*
diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h
index 5941191..32f5786 100644
--- a/xen/include/xen/grant_table.h
+++ b/xen/include/xen/grant_table.h
@@ -49,10 +49,8 @@
/* Default maximum size of a grant table. [POLICY] */
#define DEFAULT_MAX_NR_GRANT_FRAMES 32
#endif
-#ifndef max_nr_grant_frames /* to allow arch to override */
/* The maximum size of a grant table. */
-extern unsigned int max_nr_grant_frames;
-#endif
+extern unsigned int max_grant_frames;
/*
* Tracks a mapping of another domain's grant reference. Each domain has a
diff --git a/xen/include/xen/hvm/iommu.h b/xen/include/xen/hvm/iommu.h
index 8c98274..693346c 100644
--- a/xen/include/xen/hvm/iommu.h
+++ b/xen/include/xen/hvm/iommu.h
@@ -21,30 +21,25 @@
#define __XEN_HVM_IOMMU_H__
#include <xen/iommu.h>
-
-struct g2m_ioport {
- struct list_head list;
- unsigned int gport;
- unsigned int mport;
- unsigned int np;
-};
+#include <xen/list.h>
+#include <asm/hvm/iommu.h>
struct hvm_iommu {
- u64 pgd_maddr; /* io page directory machine address */
- spinlock_t mapping_lock; /* io page table lock */
- int agaw; /* adjusted guest address width, 0 is level 2 30-bit */
- struct list_head g2m_ioport_list; /* guest to machine ioport mapping */
- u64 iommu_bitmap; /* bitmap of iommu(s) that the domain uses */
- struct list_head mapped_rmrrs;
-
- /* amd iommu support */
- int domain_id;
- int paging_mode;
- struct page_info *root_table;
- struct guest_iommu *g_iommu;
+ struct arch_hvm_iommu arch;
/* iommu_ops */
const struct iommu_ops *platform_ops;
+
+#ifdef HAS_DEVICE_TREE
+ /* List of DT devices assigned to this domain */
+ struct list_head dt_devices;
+#endif
+
+ /* Features supported by the IOMMU */
+ DECLARE_BITMAP(features, IOMMU_FEAT_count);
};
+#define iommu_set_feature(d, f) set_bit((f), domain_hvm_iommu(d)->features)
+#define iommu_clear_feature(d, f) clear_bit((f), domain_hvm_iommu(d)->features)
+
#endif /* __XEN_HVM_IOMMU_H__ */
diff --git a/xen/include/xen/hvm/irq.h b/xen/include/xen/hvm/irq.h
index 973368c..3996f1f 100644
--- a/xen/include/xen/hvm/irq.h
+++ b/xen/include/xen/hvm/irq.h
@@ -30,10 +30,9 @@
struct dev_intx_gsi_link {
struct list_head list;
+ uint8_t bus;
uint8_t device;
uint8_t intx;
- uint8_t gsi;
- uint8_t link;
};
#define _HVM_IRQ_DPCI_MACH_PCI_SHIFT 0
@@ -69,6 +68,7 @@ struct hvm_gmsi_info {
struct hvm_girq_dpci_mapping {
struct list_head list;
+ uint8_t bus;
uint8_t device;
uint8_t intx;
uint8_t machine_gsi;
@@ -88,18 +88,19 @@ struct hvm_irq_dpci {
DECLARE_BITMAP(isairq_map, NR_ISAIRQS);
/* Record of mapped Links */
uint8_t link_cnt[NR_LINK];
- struct tasklet dirq_tasklet;
};
/* Machine IRQ to guest device/intx mapping. */
struct hvm_pirq_dpci {
uint32_t flags;
+ unsigned int state;
bool_t masked;
uint16_t pending;
struct list_head digl_list;
struct domain *dom;
struct hvm_gmsi_info gmsi;
struct timer timer;
+ struct list_head softirq_list;
};
void pt_pirq_init(struct domain *, struct hvm_pirq_dpci *);
@@ -109,6 +110,7 @@ int pt_pirq_iterate(struct domain *d,
struct hvm_pirq_dpci *, void *arg),
void *arg);
+bool_t pt_pirq_softirq_active(struct hvm_pirq_dpci *);
/* Modify state of a PCI INTx wire. */
void hvm_pci_intx_assert(
struct domain *d, unsigned int device, unsigned int intx);
@@ -123,7 +125,7 @@ void hvm_isa_irq_deassert(
void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq);
-void hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data);
+int hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data);
void hvm_maybe_deassert_evtchn_irq(void);
void hvm_assert_evtchn_irq(struct vcpu *v);
diff --git a/xen/include/xen/init.h b/xen/include/xen/init.h
index 9d481b3..b3bced3 100644
--- a/xen/include/xen/init.h
+++ b/xen/include/xen/init.h
@@ -129,4 +129,12 @@ extern struct kernel_param __setup_start, __setup_end;
#define __devexitdata __exitdata
#endif
+#ifdef CONFIG_LATE_HWDOM
+#define __hwdom_init
+#define __hwdom_initdata __read_mostly
+#else
+#define __hwdom_init __init
+#define __hwdom_initdata __initdata
+#endif
+
#endif /* _LINUX_INIT_H */
diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h
index 8bb0a1d..8eb764a 100644
--- a/xen/include/xen/iommu.h
+++ b/xen/include/xen/iommu.h
@@ -25,6 +25,7 @@
#include <xen/pci.h>
#include <public/hvm/ioreq.h>
#include <public/domctl.h>
+#include <asm/iommu.h>
extern bool_t iommu_enable, iommu_enabled;
extern bool_t force_iommu, iommu_verbose;
@@ -34,31 +35,38 @@ extern bool_t iommu_hap_pt_share;
extern bool_t iommu_debug;
extern bool_t amd_iommu_perdev_intremap;
-/* Does this domain have a P2M table we can use as its IOMMU pagetable? */
-#define iommu_use_hap_pt(d) (hap_enabled(d) && iommu_hap_pt_share)
-
-#define domain_hvm_iommu(d) (&d->arch.hvm_domain.hvm_iommu)
-
-#define MAX_IOMMUS 32
+#define IOMMU_PAGE_SIZE(sz) (1UL << PAGE_SHIFT_##sz)
+#define IOMMU_PAGE_MASK(sz) (~(u64)0 << PAGE_SHIFT_##sz)
+#define IOMMU_PAGE_ALIGN(sz, addr) (((addr) + ~PAGE_MASK_##sz) & PAGE_MASK_##sz)
#define PAGE_SHIFT_4K (12)
-#define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K)
-#define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K)
-#define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
+#define PAGE_SIZE_4K IOMMU_PAGE_SIZE(4K)
+#define PAGE_MASK_4K IOMMU_PAGE_MASK(4K)
+#define PAGE_ALIGN_4K(addr) IOMMU_PAGE_ALIGN(4K, addr)
+
+#define PAGE_SHIFT_64K (16)
+#define PAGE_SIZE_64K IOMMU_PAGE_SIZE(64K)
+#define PAGE_MASK_64K IOMMU_PAGE_MASK(64K)
+#define PAGE_ALIGN_64K(addr) IOMMU_PAGE_ALIGN(64K, addr)
int iommu_setup(void);
-int iommu_supports_eim(void);
-int iommu_enable_x2apic_IR(void);
-void iommu_disable_x2apic_IR(void);
int iommu_add_device(struct pci_dev *pdev);
int iommu_enable_device(struct pci_dev *pdev);
int iommu_remove_device(struct pci_dev *pdev);
int iommu_domain_init(struct domain *d);
-void iommu_dom0_init(struct domain *d);
+void iommu_hwdom_init(struct domain *d);
void iommu_domain_destroy(struct domain *d);
int deassign_device(struct domain *d, u16 seg, u8 bus, u8 devfn);
+void arch_iommu_domain_destroy(struct domain *d);
+int arch_iommu_domain_init(struct domain *d);
+int arch_iommu_populate_page_table(struct domain *d);
+void arch_iommu_check_autotranslated_hwdom(struct domain *d);
+
+/* Function used internally, use iommu_domain_destroy */
+void iommu_teardown(struct domain *d);
+
/* iommu_map_page() takes flags to direct the mapping operation. */
#define _IOMMUF_readable 0
#define IOMMUF_readable (1u<<_IOMMUF_readable)
@@ -67,10 +75,17 @@ int deassign_device(struct domain *d, u16 seg, u8 bus, u8 devfn);
int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn,
unsigned int flags);
int iommu_unmap_page(struct domain *d, unsigned long gfn);
-void iommu_pte_flush(struct domain *d, u64 gfn, u64 *pte, int order, int present);
-void iommu_set_pgd(struct domain *d);
-void iommu_domain_teardown(struct domain *d);
+enum iommu_feature
+{
+ IOMMU_FEAT_COHERENT_WALK,
+ IOMMU_FEAT_count
+};
+
+bool_t iommu_has_feature(struct domain *d, enum iommu_feature feature);
+
+
+#ifdef HAS_PCI
void pt_pci_init(void);
struct pirq;
@@ -84,32 +99,57 @@ struct hvm_irq_dpci *domain_get_irq_dpci(const struct domain *);
void free_hvm_irq_dpci(struct hvm_irq_dpci *dpci);
bool_t pt_irq_need_timer(uint32_t flags);
-#define PT_IRQ_TIME_OUT MILLISECS(8)
-
struct msi_desc;
struct msi_msg;
+
+int iommu_update_ire_from_msi(struct msi_desc *msi_desc, struct msi_msg *msg);
+void iommu_read_msi_from_ire(struct msi_desc *msi_desc, struct msi_msg *msg);
+
+#define PT_IRQ_TIME_OUT MILLISECS(8)
+#endif /* HAS_PCI */
+
+#ifdef HAS_DEVICE_TREE
+#include <xen/device_tree.h>
+
+int iommu_assign_dt_device(struct domain *d, struct dt_device_node *dev);
+int iommu_deassign_dt_device(struct domain *d, struct dt_device_node *dev);
+int iommu_dt_domain_init(struct domain *d);
+void iommu_dt_domain_destroy(struct domain *d);
+
+#endif /* HAS_DEVICE_TREE */
+
struct page_info;
struct iommu_ops {
int (*init)(struct domain *d);
- void (*dom0_init)(struct domain *d);
+ void (*hwdom_init)(struct domain *d);
+#ifdef HAS_PCI
int (*add_device)(u8 devfn, struct pci_dev *);
int (*enable_device)(struct pci_dev *pdev);
int (*remove_device)(u8 devfn, struct pci_dev *);
int (*assign_device)(struct domain *, u8 devfn, struct pci_dev *);
+ int (*reassign_device)(struct domain *s, struct domain *t,
+ u8 devfn, struct pci_dev *);
+ int (*get_device_group_id)(u16 seg, u8 bus, u8 devfn);
+ int (*update_ire_from_msi)(struct msi_desc *msi_desc, struct msi_msg *msg);
+ void (*read_msi_from_ire)(struct msi_desc *msi_desc, struct msi_msg *msg);
+#endif /* HAS_PCI */
+#ifdef HAS_DEVICE_TREE
+ int (*assign_dt_device)(struct domain *d, const struct dt_device_node *dev);
+ int (*reassign_dt_device)(struct domain *s, struct domain *t,
+ const struct dt_device_node *dev);
+#endif
+
void (*teardown)(struct domain *d);
int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn,
unsigned int flags);
int (*unmap_page)(struct domain *d, unsigned long gfn);
void (*free_page_table)(struct page_info *);
- int (*reassign_device)(struct domain *s, struct domain *t,
- u8 devfn, struct pci_dev *);
- int (*get_device_group_id)(u16 seg, u8 bus, u8 devfn);
+#ifdef CONFIG_X86
void (*update_ire_from_apic)(unsigned int apic, unsigned int reg, unsigned int value);
- int (*update_ire_from_msi)(struct msi_desc *msi_desc, struct msi_msg *msg);
- void (*read_msi_from_ire)(struct msi_desc *msi_desc, struct msi_msg *msg);
unsigned int (*read_apic_from_ire)(unsigned int apic, unsigned int reg);
int (*setup_hpet_msi)(struct msi_desc *);
+#endif /* CONFIG_X86 */
void (*suspend)(void);
void (*resume)(void);
void (*share_p2m)(struct domain *d);
@@ -119,28 +159,23 @@ struct iommu_ops {
void (*dump_p2m_table)(struct domain *d);
};
-void iommu_update_ire_from_apic(unsigned int apic, unsigned int reg, unsigned int value);
-int iommu_update_ire_from_msi(struct msi_desc *msi_desc, struct msi_msg *msg);
-void iommu_read_msi_from_ire(struct msi_desc *msi_desc, struct msi_msg *msg);
-unsigned int iommu_read_apic_from_ire(unsigned int apic, unsigned int reg);
-int iommu_setup_hpet_msi(struct msi_desc *);
-
void iommu_suspend(void);
void iommu_resume(void);
void iommu_crash_shutdown(void);
-void iommu_set_dom0_mapping(struct domain *d);
void iommu_share_p2m_table(struct domain *d);
+#ifdef HAS_PCI
+int iommu_do_pci_domctl(struct xen_domctl *, struct domain *d,
+ XEN_GUEST_HANDLE_PARAM(xen_domctl_t));
+#endif
+
int iommu_do_domctl(struct xen_domctl *, struct domain *d,
XEN_GUEST_HANDLE_PARAM(xen_domctl_t));
void iommu_iotlb_flush(struct domain *d, unsigned long gfn, unsigned int page_count);
void iommu_iotlb_flush_all(struct domain *d);
-/* While VT-d specific, this must get declared in a generic header. */
-int adjust_vtd_irq_affinities(void);
-
/*
* The purpose of the iommu_dont_flush_iotlb optional cpu flag is to
* avoid unecessary iotlb_flush in the low level IOMMU code.
diff --git a/xen/include/xen/irq.h b/xen/include/xen/irq.h
index f2e6215..ffb5932 100644
--- a/xen/include/xen/irq.h
+++ b/xen/include/xen/irq.h
@@ -14,19 +14,32 @@ struct irqaction {
const char *name;
void *dev_id;
bool_t free_on_release;
+#ifdef CONFIG_IRQ_HAS_MULTIPLE_ACTION
+ struct irqaction *next;
+#endif
};
/*
* IRQ line status.
*/
-#define IRQ_INPROGRESS (1u<<0) /* IRQ handler active - do not enter! */
-#define IRQ_DISABLED (1u<<1) /* IRQ disabled - do not enter! */
-#define IRQ_PENDING (1u<<2) /* IRQ pending - replay on enable */
-#define IRQ_REPLAY (1u<<3) /* IRQ has been replayed but not acked yet */
-#define IRQ_GUEST (1u<<4) /* IRQ is handled by guest OS(es) */
-#define IRQ_MOVE_PENDING (1u<<5) /* IRQ is migrating to another CPUs */
-#define IRQ_PER_CPU (1u<<6) /* IRQ is per CPU */
-#define IRQ_GUEST_EOI_PENDING (1u<<7) /* IRQ was disabled, pending a guest EOI */
+#define _IRQ_INPROGRESS 0 /* IRQ handler active - do not enter! */
+#define _IRQ_DISABLED 1 /* IRQ disabled - do not enter! */
+#define _IRQ_PENDING 2 /* IRQ pending - replay on enable */
+#define _IRQ_REPLAY 3 /* IRQ has been replayed but not acked yet */
+#define _IRQ_GUEST 4 /* IRQ is handled by guest OS(es) */
+#define _IRQ_MOVE_PENDING 5 /* IRQ is migrating to another CPUs */
+#define _IRQ_PER_CPU 6 /* IRQ is per CPU */
+#define _IRQ_GUEST_EOI_PENDING 7 /* IRQ was disabled, pending a guest EOI */
+#define _IRQF_SHARED 8 /* IRQ is shared */
+#define IRQ_INPROGRESS (1u<<_IRQ_INPROGRESS)
+#define IRQ_DISABLED (1u<<_IRQ_DISABLED)
+#define IRQ_PENDING (1u<<_IRQ_PENDING)
+#define IRQ_REPLAY (1u<<_IRQ_REPLAY)
+#define IRQ_GUEST (1u<<_IRQ_GUEST)
+#define IRQ_MOVE_PENDING (1u<<_IRQ_MOVE_PENDING)
+#define IRQ_PER_CPU (1u<<_IRQ_PER_CPU)
+#define IRQ_GUEST_EOI_PENDING (1u<<_IRQ_GUEST_EOI_PENDING)
+#define IRQF_SHARED (1u<<_IRQF_SHARED)
/* Special IRQ numbers. */
#define AUTO_ASSIGN_IRQ (-1)
@@ -63,6 +76,11 @@ struct msi_desc;
* This is the "IRQ descriptor", which contains various information
* about the irq, including what kind of hardware handling it has,
* whether it is disabled etc etc.
+ *
+ * Note: on ARMv8 we can use normal bit manipulation functions to access
+ * the status field because struct irq_desc contains pointers, therefore
+ * the alignment of the struct is at least 8 bytes and status is the
+ * first field.
*/
typedef struct irq_desc {
unsigned int status; /* IRQ status */
@@ -89,9 +107,10 @@ int arch_init_one_irq_desc(struct irq_desc *);
#define irq_desc_initialized(desc) ((desc)->handler != NULL)
-extern int setup_irq(unsigned int irq, struct irqaction *);
-extern void release_irq(unsigned int irq);
-extern int request_irq(unsigned int irq,
+extern int setup_irq(unsigned int irq, unsigned int irqflags,
+ struct irqaction *);
+extern void release_irq(unsigned int irq, const void *dev_id);
+extern int request_irq(unsigned int irq, unsigned int irqflags,
void (*handler)(int, void *, struct cpu_user_regs *),
const char * devname, void *dev_id);
diff --git a/xen/include/xen/kernel.h b/xen/include/xen/kernel.h
index 54e88dd..548b64d 100644
--- a/xen/include/xen/kernel.h
+++ b/xen/include/xen/kernel.h
@@ -65,7 +65,7 @@
1; \
})
-extern char _start[], _end[];
+extern char _start[], _end[], start[];
#define is_kernel(p) ({ \
char *__p = (char *)(unsigned long)(p); \
(__p >= _start) && (__p < _end); \
@@ -92,6 +92,7 @@ extern char _sinittext[], _einittext[];
extern enum system_state {
SYS_STATE_early_boot,
SYS_STATE_boot,
+ SYS_STATE_smp_boot,
SYS_STATE_active,
SYS_STATE_suspend,
SYS_STATE_resume
diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h
index 5b258fd..f11b49e 100644
--- a/xen/include/xen/lib.h
+++ b/xen/include/xen/lib.h
@@ -8,7 +8,7 @@
#include <xen/string.h>
#include <asm/bug.h>
-void __bug(char *file, int line) __attribute__((noreturn));
+void noreturn __bug(char *file, int line);
void __warn(char *file, int line);
#define BUG_ON(p) do { if (unlikely(p)) BUG(); } while (0)
@@ -75,7 +75,8 @@ int parse_bool(const char *s);
/*#define DEBUG_TRACE_DUMP*/
#ifdef DEBUG_TRACE_DUMP
extern void debugtrace_dump(void);
-extern void debugtrace_printk(const char *fmt, ...);
+extern void debugtrace_printk(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
#else
#define debugtrace_dump() ((void)0)
#define debugtrace_printk(_f, ...) ((void)0)
@@ -87,7 +88,7 @@ extern void printk(const char *format, ...)
__attribute__ ((format (printf, 1, 2)));
extern void guest_printk(const struct domain *d, const char *format, ...)
__attribute__ ((format (printf, 2, 3)));
-extern void panic(const char *format, ...)
+extern void noreturn panic(const char *format, ...)
__attribute__ ((format (printf, 1, 2)));
extern long vm_assist(struct domain *, unsigned int, unsigned int);
extern int __printk_ratelimit(int ratelimit_ms, int ratelimit_burst);
@@ -104,6 +105,10 @@ extern int scnprintf(char * buf, size_t size, const char * fmt, ...)
__attribute__ ((format (printf, 3, 4)));
extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
__attribute__ ((format (printf, 3, 0)));
+extern int asprintf(char ** bufp, const char * fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int vasprintf(char ** bufp, const char * fmt, va_list args)
+ __attribute__ ((format (printf, 2, 0)));
long simple_strtol(
const char *cp,const char **endp, unsigned int base);
diff --git a/xen/include/xen/libfdt/fdt.h b/xen/include/xen/libfdt/fdt.h
index 48ccfd9..526aedb 100644
--- a/xen/include/xen/libfdt/fdt.h
+++ b/xen/include/xen/libfdt/fdt.h
@@ -1,48 +1,99 @@
#ifndef _FDT_H
#define _FDT_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright 2012 Kim Phillips, Freescale Semiconductor.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
#ifndef __ASSEMBLY__
struct fdt_header {
- uint32_t magic; /* magic word FDT_MAGIC */
- uint32_t totalsize; /* total size of DT block */
- uint32_t off_dt_struct; /* offset to structure */
- uint32_t off_dt_strings; /* offset to strings */
- uint32_t off_mem_rsvmap; /* offset to memory reserve map */
- uint32_t version; /* format version */
- uint32_t last_comp_version; /* last compatible version */
+ fdt32_t magic; /* magic word FDT_MAGIC */
+ fdt32_t totalsize; /* total size of DT block */
+ fdt32_t off_dt_struct; /* offset to structure */
+ fdt32_t off_dt_strings; /* offset to strings */
+ fdt32_t off_mem_rsvmap; /* offset to memory reserve map */
+ fdt32_t version; /* format version */
+ fdt32_t last_comp_version; /* last compatible version */
/* version 2 fields below */
- uint32_t boot_cpuid_phys; /* Which physical CPU id we're
+ fdt32_t boot_cpuid_phys; /* Which physical CPU id we're
booting on */
/* version 3 fields below */
- uint32_t size_dt_strings; /* size of the strings block */
+ fdt32_t size_dt_strings; /* size of the strings block */
/* version 17 fields below */
- uint32_t size_dt_struct; /* size of the structure block */
+ fdt32_t size_dt_struct; /* size of the structure block */
};
struct fdt_reserve_entry {
- uint64_t address;
- uint64_t size;
+ fdt64_t address;
+ fdt64_t size;
};
struct fdt_node_header {
- uint32_t tag;
+ fdt32_t tag;
char name[0];
};
struct fdt_property {
- uint32_t tag;
- uint32_t len;
- uint32_t nameoff;
+ fdt32_t tag;
+ fdt32_t len;
+ fdt32_t nameoff;
char data[0];
};
#endif /* !__ASSEMBLY */
#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
-#define FDT_TAGSIZE sizeof(uint32_t)
+#define FDT_TAGSIZE sizeof(fdt32_t)
#define FDT_BEGIN_NODE 0x1 /* Start node: full name */
#define FDT_END_NODE 0x2 /* End node */
@@ -51,10 +102,10 @@ struct fdt_property {
#define FDT_NOP 0x4 /* nop */
#define FDT_END 0x9
-#define FDT_V1_SIZE (7*sizeof(uint32_t))
-#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(uint32_t))
-#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(uint32_t))
+#define FDT_V1_SIZE (7*sizeof(fdt32_t))
+#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t))
+#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t))
#define FDT_V16_SIZE FDT_V3_SIZE
-#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(uint32_t))
+#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t))
#endif /* _FDT_H */
diff --git a/xen/include/xen/libfdt/libfdt.h b/xen/include/xen/libfdt/libfdt.h
index 6086047..37349f1 100644
--- a/xen/include/xen/libfdt/libfdt.h
+++ b/xen/include/xen/libfdt/libfdt.h
@@ -136,6 +136,28 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
int fdt_next_node(const void *fdt, int offset, int *depth);
+/**
+ * fdt_first_subnode() - get offset of first direct subnode
+ *
+ * @fdt: FDT blob
+ * @offset: Offset of node to check
+ * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
+ */
+int fdt_first_subnode(const void *fdt, int offset);
+
+/**
+ * fdt_next_subnode() - get offset of next direct subnode
+ *
+ * After first calling fdt_first_subnode(), call this function repeatedly to
+ * get direct subnodes of a parent node.
+ *
+ * @fdt: FDT blob
+ * @offset: Offset of previous subnode
+ * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
+ * subnodes
+ */
+int fdt_next_subnode(const void *fdt, int offset);
+
/**********************************************************************/
/* General functions */
/**********************************************************************/
@@ -582,7 +604,7 @@ const char *fdt_get_alias_namelen(const void *fdt,
* value of the property named 'name' in the node /aliases.
*
* returns:
- * a pointer to the expansion of the alias named 'name', of it exists
+ * a pointer to the expansion of the alias named 'name', if it exists
* NULL, if the given alias or the /aliases node does not exist
*/
const char *fdt_get_alias(const void *fdt, const char *name);
@@ -816,6 +838,20 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
const char *compatible);
+/**
+ * fdt_stringlist_contains - check a string list property for a string
+ * @strlist: Property containing a list of strings to check
+ * @listlen: Length of property
+ * @str: String to search for
+ *
+ * This is a utility function provided for convenience. The list contains
+ * one or more strings, each terminated by \0, as is found in a device tree
+ * "compatible" property.
+ *
+ * @return: 1 if the string is found in the list, 0 not found, or invalid list
+ */
+int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
+
/**********************************************************************/
/* Write-in-place functions */
/**********************************************************************/
@@ -852,17 +888,17 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
const void *val, int len);
/**
- * fdt_setprop_inplace_cell - change the value of a single-cell property
+ * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
- * @val: cell (32-bit integer) value to replace the property with
+ * @val: 32-bit integer value to replace the property with
*
- * fdt_setprop_inplace_cell() replaces the value of a given property
- * with the 32-bit integer cell value in val, converting val to
- * big-endian if necessary. This function cannot change the size of a
- * property, and so will only work if the property already exists and
- * has length 4.
+ * fdt_setprop_inplace_u32() replaces the value of a given property
+ * with the 32-bit integer value in val, converting val to big-endian
+ * if necessary. This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 4.
*
* This function will alter only the bytes in the blob which contain
* the given property value, and will not alter or move any other part
@@ -871,7 +907,42 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, if the property's length is not equal to 4
- * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
+ const char *name, uint32_t val)
+{
+ fdt32_t tmp = cpu_to_fdt32(val);
+ return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+/**
+ * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to replace the property with
+ *
+ * fdt_setprop_inplace_u64() replaces the value of a given property
+ * with the 64-bit integer value in val, converting val to big-endian
+ * if necessary. This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 8.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, if the property's length is not equal to 8
+ * -FDT_ERR_NOTFOUND, node does not have the named property
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
@@ -879,11 +950,22 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_TRUNCATED, standard meanings
*/
+static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
+ const char *name, uint64_t val)
+{
+ fdt64_t tmp = cpu_to_fdt64(val);
+ return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+/**
+ * fdt_setprop_inplace_cell - change the value of a single-cell property
+ *
+ * This is an alternative name for fdt_setprop_inplace_u32()
+ */
static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
const char *name, uint32_t val)
{
- val = cpu_to_fdt32(val);
- return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+ return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val);
}
/**
@@ -945,10 +1027,19 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
int fdt_finish_reservemap(void *fdt);
int fdt_begin_node(void *fdt, const char *name);
int fdt_property(void *fdt, const char *name, const void *val, int len);
+static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
+{
+ fdt32_t tmp = cpu_to_fdt32(val);
+ return fdt_property(fdt, name, &tmp, sizeof(tmp));
+}
+static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val)
+{
+ fdt64_t tmp = cpu_to_fdt64(val);
+ return fdt_property(fdt, name, &tmp, sizeof(tmp));
+}
static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
{
- val = cpu_to_fdt32(val);
- return fdt_property(fdt, name, &val, sizeof(val));
+ return fdt_property_u32(fdt, name, val);
}
#define fdt_property_string(fdt, name, str) \
fdt_property(fdt, name, str, strlen(str)+1)
@@ -959,6 +1050,7 @@ int fdt_finish(void *fdt);
/* Read-write functions */
/**********************************************************************/
+int fdt_create_empty_tree(void *buf, int bufsize);
int fdt_open_into(const void *fdt, void *buf, int bufsize);
int fdt_pack(void *fdt);
@@ -1068,14 +1160,14 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
const void *val, int len);
/**
- * fdt_setprop_cell - set a property to a single cell value
+ * fdt_setprop_u32 - set a property to a 32-bit integer
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
* @val: 32-bit integer value for the property (native endian)
*
- * fdt_setprop_cell() sets the value of the named property in the
- * given node to the given cell value (converting to big-endian if
+ * fdt_setprop_u32() sets the value of the named property in the given
+ * node to the given 32-bit integer value (converting to big-endian if
* necessary), or creates a new property with that value if it does
* not already exist.
*
@@ -1095,11 +1187,57 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_TRUNCATED, standard meanings
*/
+static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name,
+ uint32_t val)
+{
+ fdt32_t tmp = cpu_to_fdt32(val);
+ return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+/**
+ * fdt_setprop_u64 - set a property to a 64-bit integer
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value for the property (native endian)
+ *
+ * fdt_setprop_u64() sets the value of the named property in the given
+ * node to the given 64-bit integer value (converting to big-endian if
+ * necessary), or creates a new property with that value if it does
+ * not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
+ uint64_t val)
+{
+ fdt64_t tmp = cpu_to_fdt64(val);
+ return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+/**
+ * fdt_setprop_cell - set a property to a single cell value
+ *
+ * This is an alternative name for fdt_setprop_u32()
+ */
static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
uint32_t val)
{
- val = cpu_to_fdt32(val);
- return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+ return fdt_setprop_u32(fdt, nodeoffset, name, val);
}
/**
@@ -1134,6 +1272,147 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
/**
+ * fdt_appendprop - append to or create a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to append to
+ * @val: pointer to data to append to the property value
+ * @len: length of the data to append to the property value
+ *
+ * fdt_appendprop() appends the value to the named property in the
+ * given node, creating the property if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len);
+
+/**
+ * fdt_appendprop_u32 - append a 32-bit integer value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_u32() appends the given 32-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_appendprop_u32(void *fdt, int nodeoffset,
+ const char *name, uint32_t val)
+{
+ fdt32_t tmp = cpu_to_fdt32(val);
+ return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+/**
+ * fdt_appendprop_u64 - append a 64-bit integer value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_u64() appends the given 64-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
+ const char *name, uint64_t val)
+{
+ fdt64_t tmp = cpu_to_fdt64(val);
+ return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+/**
+ * fdt_appendprop_cell - append a single cell value to a property
+ *
+ * This is an alternative name for fdt_appendprop_u32()
+ */
+static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
+ const char *name, uint32_t val)
+{
+ return fdt_appendprop_u32(fdt, nodeoffset, name, val);
+}
+
+/**
+ * fdt_appendprop_string - append a string to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @str: string value to append to the property
+ *
+ * fdt_appendprop_string() appends the given string to the value of
+ * the named property in the given node, or creates a new property
+ * with that value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+#define fdt_appendprop_string(fdt, nodeoffset, name, str) \
+ fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
* fdt_delprop - delete a property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to nop
diff --git a/xen/include/xen/libfdt/libfdt_env.h b/xen/include/xen/libfdt/libfdt_env.h
index 2f1b03c..89a794b 100644
--- a/xen/include/xen/libfdt/libfdt_env.h
+++ b/xen/include/xen/libfdt/libfdt_env.h
@@ -6,6 +6,10 @@
#include <xen/string.h>
#include <asm/byteorder.h>
+typedef uint16_t fdt16_t;
+typedef uint32_t fdt32_t;
+typedef uint64_t fdt64_t;
+
#define fdt16_to_cpu(x) be16_to_cpu(x)
#define cpu_to_fdt16(x) cpu_to_be16(x)
#define fdt32_to_cpu(x) be32_to_cpu(x)
diff --git a/xen/include/xen/list.h b/xen/include/xen/list.h
index 792eda3..59cf571 100644
--- a/xen/include/xen/list.h
+++ b/xen/include/xen/list.h
@@ -10,12 +10,15 @@
#include <xen/lib.h>
#include <asm/system.h>
-/* These are non-NULL pointers that will result in page faults
- * under normal circumstances, used to verify that nobody uses
- * non-initialized list entries.
+/*
+ * These are non-NULL pointers that will result in faults under normal
+ * circumstances, used to verify that nobody uses non-initialized list
+ * entries. Architectures can override these.
*/
+#ifndef LIST_POISON1
#define LIST_POISON1 ((void *) 0x00100100)
#define LIST_POISON2 ((void *) 0x00200200)
+#endif
/*
* Simple doubly linked list implementation.
@@ -304,6 +307,15 @@ static inline int list_empty(const struct list_head *head)
}
/**
+ * list_is_singular - tests whether a list has exactly one entry
+ * @head: the list to test.
+ */
+static inline int list_is_singular(const struct list_head *head)
+{
+ return !list_empty(head) && (head->next == head->prev);
+}
+
+/**
* list_empty_careful - tests whether a list is empty and not being modified
* @head: the list to test
*
diff --git a/xen/include/xen/lzo.h b/xen/include/xen/lzo.h
index cbf135f..e920027 100644
--- a/xen/include/xen/lzo.h
+++ b/xen/include/xen/lzo.h
@@ -4,22 +4,22 @@
* LZO Public Kernel Interface
* A mini subset of the LZO real-time data compression library
*
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus at oberhumer.com>
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus at oberhumer.com>
*
* The full LZO package can be found at:
* http://www.oberhumer.com/opensource/lzo/
*
- * Changed for kernel use by:
+ * Changed for Linux kernel use by:
* Nitin Gupta <nitingupta910 at gmail.com>
* Richard Purdie <rpurdie at openedhand.com>
*/
-#define LZO1X_MEM_COMPRESS (16384 * sizeof(unsigned char *))
-#define LZO1X_1_MEM_COMPRESS LZO1X_MEM_COMPRESS
+#define LZO1X_1_MEM_COMPRESS (8192 * sizeof(unsigned short))
+#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
#define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3)
-/* This requires 'workmem' of size LZO1X_1_MEM_COMPRESS */
+/* This requires 'wrkmem' of size LZO1X_1_MEM_COMPRESS */
int lzo1x_1_compress(const unsigned char *src, size_t src_len,
unsigned char *dst, size_t *dst_len, void *wrkmem);
@@ -40,5 +40,6 @@ int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
#define LZO_E_EOF_NOT_FOUND (-7)
#define LZO_E_INPUT_NOT_CONSUMED (-8)
#define LZO_E_NOT_YET_IMPLEMENTED (-9)
+#define LZO_E_INVALID_ARGUMENT (-10)
#endif
diff --git a/xen/include/xen/mem_access.h b/xen/include/xen/mem_access.h
new file mode 100644
index 0000000..6ceb2a4
--- /dev/null
+++ b/xen/include/xen/mem_access.h
@@ -0,0 +1,65 @@
+/******************************************************************************
+ * mem_access.h
+ *
+ * Memory access support.
+ *
+ * Copyright (c) 2011 Virtuata, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _XEN_ASM_MEM_ACCESS_H
+#define _XEN_ASM_MEM_ACCESS_H
+
+#include <public/memory.h>
+
+#ifdef HAS_MEM_ACCESS
+
+int mem_access_memop(unsigned long cmd,
+ XEN_GUEST_HANDLE_PARAM(xen_mem_access_op_t) arg);
+int mem_access_send_req(struct domain *d, mem_event_request_t *req);
+
+/* Resumes the running of the VCPU, restarting the last instruction */
+void mem_access_resume(struct domain *d);
+
+#else
+
+static inline
+int mem_access_memop(unsigned long cmd,
+ XEN_GUEST_HANDLE_PARAM(xen_mem_access_op_t) arg)
+{
+ return -ENOSYS;
+}
+
+static inline
+int mem_access_send_req(struct domain *d, mem_event_request_t *req)
+{
+ return -ENOSYS;
+}
+
+static inline void mem_access_resume(struct domain *d) {}
+
+#endif /* HAS_MEM_ACCESS */
+
+#endif /* _XEN_ASM_MEM_ACCESS_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/xen/mem_event.h b/xen/include/xen/mem_event.h
new file mode 100644
index 0000000..4f3ad8e
--- /dev/null
+++ b/xen/include/xen/mem_event.h
@@ -0,0 +1,143 @@
+/******************************************************************************
+ * mem_event.h
+ *
+ * Common interface for memory event support.
+ *
+ * Copyright (c) 2009 Citrix Systems, Inc. (Patrick Colp)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef __MEM_EVENT_H__
+#define __MEM_EVENT_H__
+
+#include <xen/sched.h>
+
+#ifdef HAS_MEM_ACCESS
+
+/* Clean up on domain destruction */
+void mem_event_cleanup(struct domain *d);
+
+/* Returns whether a ring has been set up */
+bool_t mem_event_check_ring(struct mem_event_domain *med);
+
+/* Returns 0 on success, -ENOSYS if there is no ring, -EBUSY if there is no
+ * available space and the caller is a foreign domain. If the guest itself
+ * is the caller, -EBUSY is avoided by sleeping on a wait queue to ensure
+ * that the ring does not lose future events.
+ *
+ * However, the allow_sleep flag can be set to false in cases in which it is ok
+ * to lose future events, and thus -EBUSY can be returned to guest vcpus
+ * (handle with care!).
+ *
+ * In general, you must follow a claim_slot() call with either put_request() or
+ * cancel_slot(), both of which are guaranteed to
+ * succeed.
+ */
+int __mem_event_claim_slot(struct domain *d, struct mem_event_domain *med,
+ bool_t allow_sleep);
+static inline int mem_event_claim_slot(struct domain *d,
+ struct mem_event_domain *med)
+{
+ return __mem_event_claim_slot(d, med, 1);
+}
+
+static inline int mem_event_claim_slot_nosleep(struct domain *d,
+ struct mem_event_domain *med)
+{
+ return __mem_event_claim_slot(d, med, 0);
+}
+
+void mem_event_cancel_slot(struct domain *d, struct mem_event_domain *med);
+
+void mem_event_put_request(struct domain *d, struct mem_event_domain *med,
+ mem_event_request_t *req);
+
+int mem_event_get_response(struct domain *d, struct mem_event_domain *med,
+ mem_event_response_t *rsp);
+
+int do_mem_event_op(int op, uint32_t domain, void *arg);
+int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
+ XEN_GUEST_HANDLE_PARAM(void) u_domctl);
+
+void mem_event_vcpu_pause(struct vcpu *v);
+void mem_event_vcpu_unpause(struct vcpu *v);
+
+#else
+
+static inline void mem_event_cleanup(struct domain *d) {}
+
+static inline bool_t mem_event_check_ring(struct mem_event_domain *med)
+{
+ return 0;
+}
+
+static inline int mem_event_claim_slot(struct domain *d,
+ struct mem_event_domain *med)
+{
+ return -ENOSYS;
+}
+
+static inline int mem_event_claim_slot_nosleep(struct domain *d,
+ struct mem_event_domain *med)
+{
+ return -ENOSYS;
+}
+
+static inline
+void mem_event_cancel_slot(struct domain *d, struct mem_event_domain *med)
+{}
+
+static inline
+void mem_event_put_request(struct domain *d, struct mem_event_domain *med,
+ mem_event_request_t *req)
+{}
+
+static inline
+int mem_event_get_response(struct domain *d, struct mem_event_domain *med,
+ mem_event_response_t *rsp)
+{
+ return -ENOSYS;
+}
+
+static inline int do_mem_event_op(int op, uint32_t domain, void *arg)
+{
+ return -ENOSYS;
+}
+
+static inline
+int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
+ XEN_GUEST_HANDLE_PARAM(void) u_domctl)
+{
+ return -ENOSYS;
+}
+
+static inline void mem_event_vcpu_pause(struct vcpu *v) {}
+static inline void mem_event_vcpu_unpause(struct vcpu *v) {}
+
+#endif /* HAS_MEM_ACCESS */
+
+#endif /* __MEM_EVENT_H__ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/xen/mm.h b/xen/include/xen/mm.h
index b183189..74a65a6 100644
--- a/xen/include/xen/mm.h
+++ b/xen/include/xen/mm.h
@@ -88,6 +88,27 @@ int assign_pages(
/* Dump info to serial console */
void arch_dump_shared_mem_info(void);
+/*
+ * Extra fault info types which are used to further describe
+ * the source of an access violation.
+ */
+typedef enum {
+ npfec_kind_unknown, /* must be first */
+ npfec_kind_in_gpt, /* violation in guest page table */
+ npfec_kind_with_gla /* violation with guest linear address */
+} npfec_kind_t;
+
+/*
+ * Nested page fault exception codes.
+ */
+struct npfec {
+ unsigned int read_access:1;
+ unsigned int write_access:1;
+ unsigned int insn_fetch:1;
+ unsigned int gla_valid:1;
+ unsigned int kind:2; /* npfec_kind_t */
+};
+
/* memflags: */
#define _MEMF_no_refcount 0
#define MEMF_no_refcount (1U<<_MEMF_no_refcount)
@@ -371,4 +392,10 @@ int guest_remove_page(struct domain *d, unsigned long gmfn);
/* TRUE if the whole page at @mfn is of the requested RAM type(s) above. */
int page_is_ram_type(unsigned long mfn, unsigned long mem_type);
+/* Prepare/destroy a ring for a dom0 helper. Helper with talk
+ * with Xen on behalf of this domain. */
+int prepare_ring_for_helper(struct domain *d, unsigned long gmfn,
+ struct page_info **_page, void **_va);
+void destroy_ring_for_helper(void **_va, struct page_info *page);
+
#endif /* __XEN_MM_H__ */
diff --git a/xen/include/xen/p2m-common.h b/xen/include/xen/p2m-common.h
new file mode 100644
index 0000000..29f3628
--- /dev/null
+++ b/xen/include/xen/p2m-common.h
@@ -0,0 +1,47 @@
+#ifndef _XEN_P2M_COMMON_H
+#define _XEN_P2M_COMMON_H
+
+#include <public/mem_event.h>
+
+/*
+ * Additional access types, which are used to further restrict
+ * the permissions given my the p2m_type_t memory type. Violations
+ * caused by p2m_access_t restrictions are sent to the mem_event
+ * interface.
+ *
+ * The access permissions are soft state: when any ambiguous change of page
+ * type or use occurs, or when pages are flushed, swapped, or at any other
+ * convenient type, the access permissions can get reset to the p2m_domain
+ * default.
+ */
+typedef enum {
+ p2m_access_rwx = 0, /* The default access type when not used. */
+ p2m_access_wx = 1,
+ p2m_access_rx = 2,
+ p2m_access_x = 3,
+ p2m_access_rw = 4,
+ p2m_access_w = 5,
+ p2m_access_r = 6,
+ p2m_access_n = 7, /* No access allowed. */
+
+ p2m_access_rx2rw = 8, /* Special: page goes from RX to RW on write */
+ p2m_access_n2rwx = 9, /* Special: page goes from N to RWX on access, *
+ * generates an event but does not pause the
+ * vcpu */
+
+ /* NOTE: Assumed to be only 4 bits right now on x86. */
+} p2m_access_t;
+
+/* Map MMIO regions in the p2m: start_gfn and nr describe the range in
+ * * the guest physical address space to map, starting from the machine
+ * * frame number mfn. */
+int map_mmio_regions(struct domain *d,
+ unsigned long start_gfn,
+ unsigned long nr,
+ unsigned long mfn);
+int unmap_mmio_regions(struct domain *d,
+ unsigned long start_gfn,
+ unsigned long nr,
+ unsigned long mfn);
+
+#endif /* _XEN_P2M_COMMON_H */
diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h
index f3f080f..5f295f3 100644
--- a/xen/include/xen/pci.h
+++ b/xen/include/xen/pci.h
@@ -97,9 +97,9 @@ struct pci_dev *pci_lock_pdev(int seg, int bus, int devfn);
struct pci_dev *pci_lock_domain_pdev(
struct domain *, int seg, int bus, int devfn);
-void setup_dom0_pci_devices(struct domain *,
+void setup_hwdom_pci_devices(struct domain *,
int (*)(u8 devfn, struct pci_dev *));
-void pci_release_devices(struct domain *d);
+int pci_release_devices(struct domain *d);
int pci_add_segment(u16 seg);
const unsigned long *pci_get_ro_map(u16 seg);
int pci_add_device(u16 seg, u8 bus, u8 devfn, const struct pci_dev_info *);
diff --git a/xen/include/xen/pdx.h b/xen/include/xen/pdx.h
new file mode 100644
index 0000000..18fe8e5
--- /dev/null
+++ b/xen/include/xen/pdx.h
@@ -0,0 +1,50 @@
+#ifndef __XEN_PDX_H__
+#define __XEN_PDX_H__
+
+#ifdef HAS_PDX
+
+extern unsigned long max_pdx;
+extern unsigned long pfn_pdx_bottom_mask, ma_va_bottom_mask;
+extern unsigned int pfn_pdx_hole_shift;
+extern unsigned long pfn_hole_mask;
+extern unsigned long pfn_top_mask, ma_top_mask;
+
+#define PDX_GROUP_COUNT ((1 << PDX_GROUP_SHIFT) / \
+ (sizeof(*frame_table) & -sizeof(*frame_table)))
+extern unsigned long pdx_group_valid[];
+
+extern u64 pdx_init_mask(u64 base_addr);
+extern u64 pdx_region_mask(u64 base, u64 len);
+
+extern void set_pdx_range(unsigned long smfn, unsigned long emfn);
+
+#define page_to_pdx(pg) ((pg) - frame_table)
+#define pdx_to_page(pdx) (frame_table + (pdx))
+
+extern int __mfn_valid(unsigned long mfn);
+
+static inline unsigned long pfn_to_pdx(unsigned long pfn)
+{
+ return (pfn & pfn_pdx_bottom_mask) |
+ ((pfn & pfn_top_mask) >> pfn_pdx_hole_shift);
+}
+
+static inline unsigned long pdx_to_pfn(unsigned long pdx)
+{
+ return (pdx & pfn_pdx_bottom_mask) |
+ ((pdx << pfn_pdx_hole_shift) & pfn_top_mask);
+}
+
+extern void pfn_pdx_hole_setup(unsigned long);
+
+#endif /* HAS_PDX */
+#endif /* __XEN_PDX_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/xen/prefetch.h b/xen/include/xen/prefetch.h
index ba73998..85831f9 100644
--- a/xen/include/xen/prefetch.h
+++ b/xen/include/xen/prefetch.h
@@ -42,7 +42,6 @@
#endif
#ifndef ARCH_HAS_SPINLOCK_PREFETCH
-#define ARCH_HAS_SPINLOCK_PREFETCH
#define spin_lock_prefetch(x) prefetchw(x)
#endif
diff --git a/xen/include/xen/rangeset.h b/xen/include/xen/rangeset.h
index 1e16a6b..5ed6817 100644
--- a/xen/include/xen/rangeset.h
+++ b/xen/include/xen/rangeset.h
@@ -38,6 +38,13 @@ struct rangeset *rangeset_new(
void rangeset_destroy(
struct rangeset *r);
+/*
+ * Set a limit on the number of ranges that may exist in set @r.
+ * NOTE: This must be called while @r is empty.
+ */
+void rangeset_limit(
+ struct rangeset *r, unsigned int limit);
+
/* Flags for passing to rangeset_new(). */
/* Pretty-print range limits in hexadecimal. */
#define _RANGESETF_prettyprint_hex 0
@@ -67,6 +74,9 @@ int __must_check rangeset_remove_singleton(
int __must_check rangeset_contains_singleton(
struct rangeset *r, unsigned long s);
+/* swap contents */
+void rangeset_swap(struct rangeset *a, struct rangeset *b);
+
/* Rangeset pretty printing. */
void rangeset_printk(
struct rangeset *r);
@@ -74,3 +84,13 @@ void rangeset_domain_printk(
struct domain *d);
#endif /* __XEN_RANGESET_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/xen/sched-if.h b/xen/include/xen/sched-if.h
index d95e254..7cc25c6 100644
--- a/xen/include/xen/sched-if.h
+++ b/xen/include/xen/sched-if.h
@@ -158,8 +158,6 @@ struct scheduler {
struct xen_domctl_scheduler_op *);
int (*adjust_global) (const struct scheduler *,
struct xen_sysctl_scheduler_op *);
- void (*set_node_affinity) (const struct scheduler *,
- struct domain *, nodemask_t *);
void (*dump_settings) (const struct scheduler *);
void (*dump_cpu_state) (const struct scheduler *, int);
@@ -171,6 +169,7 @@ extern const struct scheduler sched_sedf_def;
extern const struct scheduler sched_credit_def;
extern const struct scheduler sched_credit2_def;
extern const struct scheduler sched_arinc653_def;
+extern const struct scheduler sched_rtds_def;
struct cpupool
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 4418883..46fc6e3 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -43,8 +43,14 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_runstate_info_compat_t);
#define SCHED_STAT_CRANK(_X) (perfc_incr(_X))
-/* A global pointer to the initial domain (DOM0). */
-extern struct domain *dom0;
+/* A global pointer to the hardware domain (usually DOM0). */
+extern struct domain *hardware_domain;
+
+#ifdef CONFIG_LATE_HWDOM
+extern domid_t hardware_domid;
+#else
+#define hardware_domid 0
+#endif
#ifndef CONFIG_COMPAT
#define BITS_PER_EVTCHN_WORD(d) BITS_PER_XEN_ULONG
@@ -68,6 +74,9 @@ extern struct domain *dom0;
#define EVTCHNS_PER_GROUP (BUCKETS_PER_GROUP * EVTCHNS_PER_BUCKET)
#define NR_EVTCHN_GROUPS DIV_ROUND_UP(MAX_NR_EVTCHNS, EVTCHNS_PER_GROUP)
+#define XEN_CONSUMER_BITS 3
+#define NR_XEN_CONSUMERS ((1 << XEN_CONSUMER_BITS) - 1)
+
struct evtchn
{
#define ECS_FREE 0 /* Channel is available for use. */
@@ -78,7 +87,8 @@ struct evtchn
#define ECS_VIRQ 5 /* Channel is bound to a virtual IRQ line. */
#define ECS_IPI 6 /* Channel is bound to a virtual IPI line. */
u8 state; /* ECS_* */
- u8 xen_consumer; /* Consumer in Xen, if any? (0 = send to guest) */
+ u8 xen_consumer:XEN_CONSUMER_BITS; /* Consumer in Xen if nonzero */
+ u8 pending:1;
u16 notify_vcpu_id; /* VCPU for local delivery notification */
u32 port;
union {
@@ -97,11 +107,26 @@ struct evtchn
u16 virq; /* state == ECS_VIRQ */
} u;
u8 priority;
- u8 pending:1;
- u16 last_vcpu_id;
u8 last_priority;
+ u16 last_vcpu_id;
+#ifdef XSM_ENABLE
+ union {
+#ifdef XSM_NEED_GENERIC_EVTCHN_SSID
+ /*
+ * If an XSM module needs more space for its event channel context,
+ * this pointer stores the necessary data for the security server.
+ */
+ void *generic;
+#endif
#ifdef FLASK_ENABLE
- void *ssid;
+ /*
+ * Inlining the contents of the structure for FLASK avoids unneeded
+ * allocations, and on 64-bit platforms with only FLASK enabled,
+ * reduces the size of struct evtchn.
+ */
+ u32 flask_sid;
+#endif
+ } ssid;
#endif
};
@@ -191,17 +216,22 @@ struct vcpu
/* VCPU paused for mem_event replies. */
atomic_t mem_event_pause_count;
+ /* VCPU paused by system controller. */
+ int controller_pause_count;
/* IRQ-safe virq_lock protects against delivering VIRQ to stale evtchn. */
evtchn_port_t virq_to_evtchn[NR_VIRQS];
spinlock_t virq_lock;
/* Bitmask of CPUs on which this VCPU may run. */
- cpumask_var_t cpu_affinity;
+ cpumask_var_t cpu_hard_affinity;
/* Used to change affinity temporarily. */
- cpumask_var_t cpu_affinity_tmp;
+ cpumask_var_t cpu_hard_affinity_tmp;
/* Used to restore affinity across S3. */
- cpumask_var_t cpu_affinity_saved;
+ cpumask_var_t cpu_hard_affinity_saved;
+
+ /* Bitmask of CPUs on which this VCPU prefers to run. */
+ cpumask_var_t cpu_soft_affinity;
/* Bitmask of CPUs which are holding onto this VCPU's state. */
cpumask_var_t vcpu_dirty_cpumask;
@@ -422,6 +452,10 @@ struct domain
nodemask_t node_affinity;
unsigned int last_alloc_node;
spinlock_t node_affinity_lock;
+
+ /* vNUMA topology accesses are protected by rwlock. */
+ rwlock_t vnuma_rwlock;
+ struct vnuma_info *vnuma;
};
struct domain_setup_info
@@ -471,7 +505,7 @@ static always_inline int get_domain(struct domain *d)
old = seen;
if ( unlikely(_atomic_read(old) & DOMAIN_DESTROYED) )
return 0;
- _atomic_set(new, _atomic_read(old) + 1);
+ _atomic_set(&new, _atomic_read(old) + 1);
seen = atomic_compareandswap(old, new, &d->refcnt);
}
while ( unlikely(_atomic_read(seen) != _atomic_read(old)) );
@@ -583,7 +617,7 @@ void __domain_crash(struct domain *d);
* Mark current domain as crashed and synchronously deschedule from the local
* processor. This function never returns.
*/
-void __domain_crash_synchronous(void) __attribute__((noreturn));
+void noreturn __domain_crash_synchronous(void);
#define domain_crash_synchronous() do { \
printk("domain_crash_sync called from %s:%d\n", __FILE__, __LINE__); \
__domain_crash_synchronous(); \
@@ -594,7 +628,7 @@ void __domain_crash_synchronous(void) __attribute__((noreturn));
* the crash occured. If addr is 0, look up address from last extable
* redirection.
*/
-void asm_domain_crash_synchronous(unsigned long addr) __attribute__((noreturn));
+void noreturn asm_domain_crash_synchronous(unsigned long addr);
#define set_current_state(_s) do { current->state = (_s); } while (0)
void scheduler_init(void);
@@ -605,11 +639,11 @@ void sched_destroy_domain(struct domain *d);
int sched_move_domain(struct domain *d, struct cpupool *c);
long sched_adjust(struct domain *, struct xen_domctl_scheduler_op *);
long sched_adjust_global(struct xen_sysctl_scheduler_op *);
-void sched_set_node_affinity(struct domain *, nodemask_t *);
int sched_id(void);
void sched_tick_suspend(void);
void sched_tick_resume(void);
void vcpu_wake(struct vcpu *v);
+long vcpu_yield(void);
void vcpu_sleep_nosync(struct vcpu *v);
void vcpu_sleep_sync(struct vcpu *v);
@@ -741,9 +775,12 @@ void vcpu_block(void);
void vcpu_unblock(struct vcpu *v);
void vcpu_pause(struct vcpu *v);
void vcpu_pause_nosync(struct vcpu *v);
+void vcpu_unpause(struct vcpu *v);
+int vcpu_pause_by_systemcontroller(struct vcpu *v);
+int vcpu_unpause_by_systemcontroller(struct vcpu *v);
+
void domain_pause(struct domain *d);
void domain_pause_nosync(struct domain *d);
-void vcpu_unpause(struct vcpu *v);
void domain_unpause(struct domain *d);
int domain_unpause_by_systemcontroller(struct domain *d);
int __domain_pause_by_systemcontroller(struct domain *d,
@@ -766,7 +803,8 @@ void scheduler_free(struct scheduler *sched);
int schedule_cpu_switch(unsigned int cpu, struct cpupool *c);
void vcpu_force_reschedule(struct vcpu *v);
int cpu_disable_scheduler(unsigned int cpu);
-int vcpu_set_affinity(struct vcpu *v, const cpumask_t *affinity);
+int vcpu_set_hard_affinity(struct vcpu *v, const cpumask_t *affinity);
+int vcpu_set_soft_affinity(struct vcpu *v, const cpumask_t *affinity);
void restore_vcpu_affinity(struct domain *d);
void vcpu_runstate_get(struct vcpu *v, struct vcpu_runstate_info *runstate);
@@ -787,10 +825,10 @@ void watchdog_domain_destroy(struct domain *d);
/*
* Use this check when the following are both true:
* - Using this feature or interface requires full access to the hardware
- * (that is, this is would not be suitable for a driver domain)
- * - There is never a reason to deny dom0 access to this
+ * (that is, this would not be suitable for a driver domain)
+ * - There is never a reason to deny the hardware domain access to this
*/
-#define is_hardware_domain(_d) ((_d)->is_privileged)
+#define is_hardware_domain(_d) ((_d) == hardware_domain)
/* This check is for functionality specific to a control domain */
#define is_control_domain(_d) ((_d)->is_privileged)
@@ -806,13 +844,18 @@ void watchdog_domain_destroy(struct domain *d);
#define has_hvm_container_domain(d) ((d)->guest_type != guest_type_pv)
#define has_hvm_container_vcpu(v) (has_hvm_container_domain((v)->domain))
#define is_pinned_vcpu(v) ((v)->domain->is_pinned || \
- cpumask_weight((v)->cpu_affinity) == 1)
+ cpumask_weight((v)->cpu_hard_affinity) == 1)
#ifdef HAS_PASSTHROUGH
#define need_iommu(d) ((d)->need_iommu)
#else
#define need_iommu(d) (0)
#endif
+static inline bool_t is_vcpu_online(const struct vcpu *v)
+{
+ return !test_bit(_VPF_down, &v->pause_flags);
+}
+
void set_vcpu_migration_delay(unsigned int delay);
unsigned int get_vcpu_migration_delay(void);
@@ -828,6 +871,7 @@ struct cpupool *cpupool_get_by_id(int poolid);
void cpupool_put(struct cpupool *pool);
int cpupool_add_domain(struct domain *d, int poolid);
void cpupool_rm_domain(struct domain *d);
+int cpupool_move_domain(struct domain *d, struct cpupool *c);
int cpupool_do_sysctl(struct xen_sysctl_cpupool_op *op);
void schedule_dump(struct cpupool *c);
extern void dump_runq(unsigned char key);
diff --git a/xen/include/xen/serial.h b/xen/include/xen/serial.h
index f38c9b7..9f4451b 100644
--- a/xen/include/xen/serial.h
+++ b/xen/include/xen/serial.h
@@ -81,8 +81,6 @@ struct uart_driver {
int (*getc)(struct serial_port *, char *);
/* Get IRQ number for this port's serial line: returns -1 if none. */
int (*irq)(struct serial_port *);
- /* Get IRQ device node for this port's serial line: returns NULL if none. */
- const struct dt_irq *(*dt_irq_get)(struct serial_port *);
/* Get serial information */
const struct vuart_info *(*vuart_info)(struct serial_port *);
};
@@ -135,9 +133,6 @@ void serial_end_log_everything(int handle);
/* Return irq number for specified serial port (identified by index). */
int serial_irq(int idx);
-/* Return irq device node for specified serial port (identified by index). */
-const struct dt_irq *serial_dt_irq(int idx);
-
/* Retrieve basic UART information to emulate it (base address, size...) */
const struct vuart_info* serial_vuart_info(int idx);
diff --git a/xen/include/xen/shutdown.h b/xen/include/xen/shutdown.h
index 2bee748..b3f7e30 100644
--- a/xen/include/xen/shutdown.h
+++ b/xen/include/xen/shutdown.h
@@ -1,13 +1,14 @@
#ifndef __XEN_SHUTDOWN_H__
#define __XEN_SHUTDOWN_H__
+#include <xen/compiler.h>
+
/* opt_noreboot: If true, machine will need manual reset on error. */
extern bool_t opt_noreboot;
-void dom0_shutdown(u8 reason);
+void noreturn hwdom_shutdown(u8 reason);
-void machine_restart(unsigned int delay_millisecs);
-void machine_halt(void);
-void machine_power_off(void);
+void noreturn machine_restart(unsigned int delay_millisecs);
+void noreturn machine_halt(void);
#endif /* __XEN_SHUTDOWN_H__ */
diff --git a/xen/include/xen/sizes.h b/xen/include/xen/sizes.h
new file mode 100644
index 0000000..f7b728d
--- /dev/null
+++ b/xen/include/xen/sizes.h
@@ -0,0 +1,48 @@
+#ifndef __XEN_SIZES_H__
+#define __XEN_SIZES_H__
+
+/*
+ * Taken from kernel code include/linux/size.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define SZ_1 0x00000001
+#define SZ_2 0x00000002
+#define SZ_4 0x00000004
+#define SZ_8 0x00000008
+#define SZ_16 0x00000010
+#define SZ_32 0x00000020
+#define SZ_64 0x00000040
+#define SZ_128 0x00000080
+#define SZ_256 0x00000100
+#define SZ_512 0x00000200
+
+#define SZ_1K 0x00000400
+#define SZ_2K 0x00000800
+#define SZ_4K 0x00001000
+#define SZ_8K 0x00002000
+#define SZ_16K 0x00004000
+#define SZ_32K 0x00008000
+#define SZ_64K 0x00010000
+#define SZ_128K 0x00020000
+#define SZ_256K 0x00040000
+#define SZ_512K 0x00080000
+
+#define SZ_1M 0x00100000
+#define SZ_2M 0x00200000
+#define SZ_4M 0x00400000
+#define SZ_8M 0x00800000
+#define SZ_16M 0x01000000
+#define SZ_32M 0x02000000
+#define SZ_64M 0x04000000
+#define SZ_128M 0x08000000
+#define SZ_256M 0x10000000
+#define SZ_512M 0x20000000
+
+#define SZ_1G 0x40000000
+#define SZ_2G 0x80000000
+
+#endif /* __XEN_SIZES_H__ */
diff --git a/xen/include/xen/softirq.h b/xen/include/xen/softirq.h
index 0c0d481..0895a16 100644
--- a/xen/include/xen/softirq.h
+++ b/xen/include/xen/softirq.h
@@ -30,6 +30,9 @@ void cpumask_raise_softirq(const cpumask_t *, unsigned int nr);
void cpu_raise_softirq(unsigned int cpu, unsigned int nr);
void raise_softirq(unsigned int nr);
+void cpu_raise_softirq_batch_begin(void);
+void cpu_raise_softirq_batch_finish(void);
+
/*
* Process pending softirqs on this CPU. This should be called periodically
* when performing work that prevents softirqs from running in a timely manner.
diff --git a/xen/include/xen/stdarg.h b/xen/include/xen/stdarg.h
index 216fe6d..29249a1 100644
--- a/xen/include/xen/stdarg.h
+++ b/xen/include/xen/stdarg.h
@@ -2,6 +2,7 @@
#define __XEN_STDARG_H__
typedef __builtin_va_list va_list;
+#define va_copy(dest, src) __builtin_va_copy((dest), (src))
#define va_start(ap, last) __builtin_va_start((ap), (last))
#define va_end(ap) __builtin_va_end(ap)
#define va_arg __builtin_va_arg
diff --git a/xen/include/xen/time.h b/xen/include/xen/time.h
index 95b4b91..709501f 100644
--- a/xen/include/xen/time.h
+++ b/xen/include/xen/time.h
@@ -32,6 +32,7 @@ struct vcpu;
typedef s64 s_time_t;
#define PRI_stime PRId64
+s_time_t get_s_time_fixed(u64 at_tick);
s_time_t get_s_time(void);
unsigned long get_localtime(struct domain *d);
uint64_t get_localtime_us(struct domain *d);
@@ -48,6 +49,7 @@ struct tm {
int tm_isdst; /* daylight saving time */
};
struct tm gmtime(unsigned long t);
+struct tm wallclock_time(uint64_t *ns);
#define SYSTEM_TIME_HZ 1000000000ULL
#define NOW() ((s_time_t)get_s_time())
diff --git a/xen/include/xlat.lst b/xen/include/xlat.lst
index 8caede6..41b3e35 100644
--- a/xen/include/xlat.lst
+++ b/xen/include/xlat.lst
@@ -37,6 +37,7 @@
? evtchn_send event_channel.h
? evtchn_status event_channel.h
? evtchn_unmask event_channel.h
+? gnttab_cache_flush grant_table.h
! gnttab_copy grant_table.h
? gnttab_dump_table grant_table.h
? gnttab_map_grant_ref grant_table.h
@@ -60,6 +61,7 @@
! memory_exchange memory.h
! memory_map memory.h
! memory_reservation memory.h
+? mem_access_op memory.h
! pod_target memory.h
! remove_from_physmap memory.h
? physdev_eoi physdev.h
@@ -87,6 +89,7 @@
? xenpf_enter_acpi_sleep platform.h
? xenpf_pcpuinfo platform.h
? xenpf_pcpu_version platform.h
+? xenpf_resource_entry platform.h
! sched_poll sched.h
? sched_remote_shutdown sched.h
? sched_shutdown sched.h
@@ -99,3 +102,16 @@
! vcpu_set_singleshot_timer vcpu.h
? xenoprof_init xenoprof.h
? xenoprof_passive xenoprof.h
+? flask_access xsm/flask_op.h
+! flask_boolean xsm/flask_op.h
+? flask_cache_stats xsm/flask_op.h
+? flask_hash_stats xsm/flask_op.h
+! flask_load xsm/flask_op.h
+? flask_ocontext xsm/flask_op.h
+? flask_peersid xsm/flask_op.h
+? flask_relabel xsm/flask_op.h
+? flask_setavc_threshold xsm/flask_op.h
+? flask_setenforce xsm/flask_op.h
+! flask_sid_context xsm/flask_op.h
+? flask_transition xsm/flask_op.h
+! flask_userlist xsm/flask_op.h
diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index eb9e1a1..f20e89c 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -59,20 +59,14 @@ static always_inline int xsm_default_action(
switch ( action ) {
case XSM_HOOK:
return 0;
- case XSM_DM_PRIV:
- if ( src->is_privileged )
- return 0;
- if ( target && src->target == target )
- return 0;
- return -EPERM;
case XSM_TARGET:
if ( src == target )
return 0;
- if ( src->is_privileged )
- return 0;
+ /* fall through */
+ case XSM_DM_PRIV:
if ( target && src->target == target )
return 0;
- return -EPERM;
+ /* fall through */
case XSM_PRIV:
if ( src->is_privileged )
return 0;
@@ -146,12 +140,6 @@ static XSM_INLINE int xsm_readconsole(XSM_DEFAULT_ARG uint32_t clear)
return xsm_default_action(action, current->domain, NULL);
}
-static XSM_INLINE int xsm_do_mca(XSM_DEFAULT_VOID)
-{
- XSM_ASSERT_ACTION(XSM_PRIV);
- return xsm_default_action(action, current->domain, NULL);
-}
-
static XSM_INLINE int xsm_alloc_security_domain(struct domain *d)
{
return 0;
@@ -311,6 +299,12 @@ static XSM_INLINE char *xsm_show_security_evtchn(struct domain *d, const struct
return NULL;
}
+static XSM_INLINE int xsm_init_hardware_domain(XSM_DEFAULT_ARG struct domain *d)
+{
+ XSM_ASSERT_ACTION(XSM_HOOK);
+ return xsm_default_action(action, current->domain, d);
+}
+
static XSM_INLINE int xsm_get_pod_target(XSM_DEFAULT_ARG struct domain *d)
{
XSM_ASSERT_ACTION(XSM_PRIV);
@@ -323,6 +317,13 @@ static XSM_INLINE int xsm_set_pod_target(XSM_DEFAULT_ARG struct domain *d)
return xsm_default_action(action, current->domain, d);
}
+static XSM_INLINE int xsm_get_vnumainfo(XSM_DEFAULT_ARG struct domain *d)
+{
+ XSM_ASSERT_ACTION(XSM_TARGET);
+ return xsm_default_action(action, current->domain, d);
+}
+
+#if defined(HAS_PASSTHROUGH) && defined(HAS_PCI)
static XSM_INLINE int xsm_get_device_group(XSM_DEFAULT_ARG uint32_t machine_bdf)
{
XSM_ASSERT_ACTION(XSM_HOOK);
@@ -347,6 +348,8 @@ static XSM_INLINE int xsm_deassign_device(XSM_DEFAULT_ARG struct domain *d, uint
return xsm_default_action(action, current->domain, d);
}
+#endif /* HAS_PASSTHROUGH && HAS_PCI */
+
static XSM_INLINE int xsm_resource_plug_core(XSM_DEFAULT_VOID)
{
XSM_ASSERT_ACTION(XSM_HOOK);
@@ -412,6 +415,13 @@ static XSM_INLINE long xsm_do_xsm_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
return -ENOSYS;
}
+#ifdef CONFIG_COMPAT
+static XSM_INLINE int xsm_do_compat_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
+{
+ return -ENOSYS;
+}
+#endif
+
static XSM_INLINE char *xsm_show_irq_sid(int irq)
{
return NULL;
@@ -479,19 +489,51 @@ static XSM_INLINE int xsm_remove_from_physmap(XSM_DEFAULT_ARG struct domain *d1,
return xsm_default_action(action, d1, d2);
}
+static XSM_INLINE int xsm_map_gmfn_foreign(XSM_DEFAULT_ARG struct domain *d, struct domain *t)
+{
+ XSM_ASSERT_ACTION(XSM_TARGET);
+ return xsm_default_action(action, d, t);
+}
+
static XSM_INLINE int xsm_hvm_param(XSM_DEFAULT_ARG struct domain *d, unsigned long op)
{
XSM_ASSERT_ACTION(XSM_TARGET);
return xsm_default_action(action, current->domain, d);
}
+static XSM_INLINE int xsm_hvm_control(XSM_DEFAULT_ARG struct domain *d, unsigned long op)
+{
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
+ return xsm_default_action(action, current->domain, d);
+}
+
static XSM_INLINE int xsm_hvm_param_nested(XSM_DEFAULT_ARG struct domain *d)
{
XSM_ASSERT_ACTION(XSM_PRIV);
return xsm_default_action(action, current->domain, d);
}
+#ifdef HAS_MEM_ACCESS
+static XSM_INLINE int xsm_mem_event_control(XSM_DEFAULT_ARG struct domain *d, int mode, int op)
+{
+ XSM_ASSERT_ACTION(XSM_PRIV);
+ return xsm_default_action(action, current->domain, d);
+}
+
+static XSM_INLINE int xsm_mem_event_op(XSM_DEFAULT_ARG struct domain *d, int op)
+{
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
+ return xsm_default_action(action, current->domain, d);
+}
+#endif
+
#ifdef CONFIG_X86
+static XSM_INLINE int xsm_do_mca(XSM_DEFAULT_VOID)
+{
+ XSM_ASSERT_ACTION(XSM_PRIV);
+ return xsm_default_action(action, current->domain, NULL);
+}
+
static XSM_INLINE int xsm_shadow_control(XSM_DEFAULT_ARG struct domain *d, uint32_t op)
{
XSM_ASSERT_ACTION(XSM_HOOK);
@@ -522,21 +564,15 @@ static XSM_INLINE int xsm_hvm_inject_msi(XSM_DEFAULT_ARG struct domain *d)
return xsm_default_action(action, current->domain, d);
}
-static XSM_INLINE int xsm_mem_event_control(XSM_DEFAULT_ARG struct domain *d, int mode, int op)
-{
- XSM_ASSERT_ACTION(XSM_PRIV);
- return xsm_default_action(action, current->domain, d);
-}
-
-static XSM_INLINE int xsm_mem_event_op(XSM_DEFAULT_ARG struct domain *d, int op)
+static XSM_INLINE int xsm_hvm_ioreq_server(XSM_DEFAULT_ARG struct domain *d, int op)
{
- XSM_ASSERT_ACTION(XSM_TARGET);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
}
static XSM_INLINE int xsm_mem_sharing_op(XSM_DEFAULT_ARG struct domain *d, struct domain *cd, int op)
{
- XSM_ASSERT_ACTION(XSM_TARGET);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, cd);
}
@@ -620,11 +656,3 @@ static XSM_INLINE int xsm_ioport_mapping(XSM_DEFAULT_ARG struct domain *d, uint3
}
#endif /* CONFIG_X86 */
-
-#ifdef CONFIG_ARM
-static XSM_INLINE int xsm_map_gmfn_foreign(XSM_DEFAULT_ARG struct domain *d, struct domain *t)
-{
- XSM_ASSERT_ACTION(XSM_TARGET);
- return xsm_default_action(action, d, t);
-}
-#endif
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index 1939453..4ce089f 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -61,7 +61,6 @@ struct xsm_operations {
int (*domctl) (struct domain *d, int cmd);
int (*sysctl) (int cmd);
int (*readconsole) (uint32_t clear);
- int (*do_mca) (void);
int (*evtchn_unbound) (struct domain *d, struct evtchn *chn, domid_t id2);
int (*evtchn_interdomain) (struct domain *d1, struct evtchn *chn1,
@@ -83,6 +82,7 @@ struct xsm_operations {
int (*alloc_security_evtchn) (struct evtchn *chn);
void (*free_security_evtchn) (struct evtchn *chn);
char *(*show_security_evtchn) (struct domain *d, const struct evtchn *chn);
+ int (*init_hardware_domain) (struct domain *d);
int (*get_pod_target) (struct domain *d);
int (*set_pod_target) (struct domain *d);
@@ -92,6 +92,7 @@ struct xsm_operations {
int (*memory_pin_page) (struct domain *d1, struct domain *d2, struct page_info *page);
int (*add_to_physmap) (struct domain *d1, struct domain *d2);
int (*remove_from_physmap) (struct domain *d1, struct domain *d2);
+ int (*map_gmfn_foreign) (struct domain *d, struct domain *t);
int (*claim_pages) (struct domain *d);
int (*console_io) (struct domain *d, int cmd);
@@ -111,10 +112,12 @@ struct xsm_operations {
int (*iomem_mapping) (struct domain *d, uint64_t s, uint64_t e, uint8_t allow);
int (*pci_config_permission) (struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access);
+#if defined(HAS_PASSTHROUGH) && defined(HAS_PCI)
int (*get_device_group) (uint32_t machine_bdf);
int (*test_assign_device) (uint32_t machine_bdf);
int (*assign_device) (struct domain *d, uint32_t machine_bdf);
int (*deassign_device) (struct domain *d, uint32_t machine_bdf);
+#endif
int (*resource_plug_core) (void);
int (*resource_unplug_core) (void);
@@ -129,18 +132,28 @@ struct xsm_operations {
int (*tmem_control)(void);
long (*do_xsm_op) (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op);
+#ifdef CONFIG_COMPAT
+ int (*do_compat_op) (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op);
+#endif
int (*hvm_param) (struct domain *d, unsigned long op);
+ int (*hvm_control) (struct domain *d, unsigned long op);
int (*hvm_param_nested) (struct domain *d);
+ int (*get_vnumainfo) (struct domain *d);
+
+#ifdef HAS_MEM_ACCESS
+ int (*mem_event_control) (struct domain *d, int mode, int op);
+ int (*mem_event_op) (struct domain *d, int op);
+#endif
#ifdef CONFIG_X86
+ int (*do_mca) (void);
int (*shadow_control) (struct domain *d, uint32_t op);
int (*hvm_set_pci_intx_level) (struct domain *d);
int (*hvm_set_isa_irq_level) (struct domain *d);
int (*hvm_set_pci_link_route) (struct domain *d);
int (*hvm_inject_msi) (struct domain *d);
- int (*mem_event_control) (struct domain *d, int mode, int op);
- int (*mem_event_op) (struct domain *d, int op);
+ int (*hvm_ioreq_server) (struct domain *d, int op);
int (*mem_sharing_op) (struct domain *d, struct domain *cd, int op);
int (*apic) (struct domain *d, int cmd);
int (*memtype) (uint32_t access);
@@ -161,9 +174,6 @@ struct xsm_operations {
int (*ioport_permission) (struct domain *d, uint32_t s, uint32_t e, uint8_t allow);
int (*ioport_mapping) (struct domain *d, uint32_t s, uint32_t e, uint8_t allow);
#endif
-#ifdef CONFIG_ARM
- int (*map_gmfn_foreign) (struct domain *d, struct domain *t);
-#endif
};
#ifdef XSM_ENABLE
@@ -218,11 +228,6 @@ static inline int xsm_readconsole (xsm_default_t def, uint32_t clear)
return xsm_ops->readconsole(clear);
}
-static inline int xsm_do_mca(xsm_default_t def)
-{
- return xsm_ops->do_mca();
-}
-
static inline int xsm_evtchn_unbound (xsm_default_t def, struct domain *d1, struct evtchn *chn,
domid_t id2)
{
@@ -311,6 +316,11 @@ static inline char *xsm_show_security_evtchn (struct domain *d, const struct evt
return xsm_ops->show_security_evtchn(d, chn);
}
+static inline int xsm_init_hardware_domain (xsm_default_t def, struct domain *d)
+{
+ return xsm_ops->init_hardware_domain(d);
+}
+
static inline int xsm_get_pod_target (xsm_default_t def, struct domain *d)
{
return xsm_ops->get_pod_target(d);
@@ -354,6 +364,11 @@ static inline int xsm_remove_from_physmap(xsm_default_t def, struct domain *d1,
return xsm_ops->remove_from_physmap(d1, d2);
}
+static inline int xsm_map_gmfn_foreign (xsm_default_t def, struct domain *d, struct domain *t)
+{
+ return xsm_ops->map_gmfn_foreign(d, t);
+}
+
static inline int xsm_claim_pages(xsm_default_t def, struct domain *d)
{
return xsm_ops->claim_pages(d);
@@ -424,6 +439,7 @@ static inline int xsm_pci_config_permission (xsm_default_t def, struct domain *d
return xsm_ops->pci_config_permission(d, machine_bdf, start, end, access);
}
+#if defined(HAS_PASSTHROUGH) && defined(HAS_PCI)
static inline int xsm_get_device_group(xsm_default_t def, uint32_t machine_bdf)
{
return xsm_ops->get_device_group(machine_bdf);
@@ -443,6 +459,7 @@ static inline int xsm_deassign_device(xsm_default_t def, struct domain *d, uint3
{
return xsm_ops->deassign_device(d, machine_bdf);
}
+#endif /* HAS_PASSTHROUGH && HAS_PCI) */
static inline int xsm_resource_plug_pci (xsm_default_t def, uint32_t machine_bdf)
{
@@ -499,17 +516,51 @@ static inline long xsm_do_xsm_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
return xsm_ops->do_xsm_op(op);
}
+#ifdef CONFIG_COMPAT
+static inline int xsm_do_compat_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
+{
+ return xsm_ops->do_compat_op(op);
+}
+#endif
+
static inline int xsm_hvm_param (xsm_default_t def, struct domain *d, unsigned long op)
{
return xsm_ops->hvm_param(d, op);
}
+static inline int xsm_hvm_control(xsm_default_t def, struct domain *d, unsigned long op)
+{
+ return xsm_ops->hvm_control(d, op);
+}
+
static inline int xsm_hvm_param_nested (xsm_default_t def, struct domain *d)
{
return xsm_ops->hvm_param_nested(d);
}
+static inline int xsm_get_vnumainfo (xsm_default_t def, struct domain *d)
+{
+ return xsm_ops->get_vnumainfo(d);
+}
+
+#ifdef HAS_MEM_ACCESS
+static inline int xsm_mem_event_control (xsm_default_t def, struct domain *d, int mode, int op)
+{
+ return xsm_ops->mem_event_control(d, mode, op);
+}
+
+static inline int xsm_mem_event_op (xsm_default_t def, struct domain *d, int op)
+{
+ return xsm_ops->mem_event_op(d, op);
+}
+#endif
+
#ifdef CONFIG_X86
+static inline int xsm_do_mca(xsm_default_t def)
+{
+ return xsm_ops->do_mca();
+}
+
static inline int xsm_shadow_control (xsm_default_t def, struct domain *d, uint32_t op)
{
return xsm_ops->shadow_control(d, op);
@@ -535,14 +586,9 @@ static inline int xsm_hvm_inject_msi (xsm_default_t def, struct domain *d)
return xsm_ops->hvm_inject_msi(d);
}
-static inline int xsm_mem_event_control (xsm_default_t def, struct domain *d, int mode, int op)
+static inline int xsm_hvm_ioreq_server (xsm_default_t def, struct domain *d, int op)
{
- return xsm_ops->mem_event_control(d, mode, op);
-}
-
-static inline int xsm_mem_event_op (xsm_default_t def, struct domain *d, int op)
-{
- return xsm_ops->mem_event_op(d, op);
+ return xsm_ops->hvm_ioreq_server(d, op);
}
static inline int xsm_mem_sharing_op (xsm_default_t def, struct domain *d, struct domain *cd, int op)
@@ -618,22 +664,25 @@ static inline int xsm_ioport_mapping (xsm_default_t def, struct domain *d, uint3
{
return xsm_ops->ioport_mapping(d, s, e, allow);
}
-#endif /* CONFIG_X86 */
-#ifdef CONFIG_ARM
-static inline int xsm_map_gmfn_foreign (struct domain *d, struct domain *t)
-{
- return xsm_ops->map_gmfn_foreign(d, t);
-}
-#endif /* CONFIG_ARM */
+#endif /* CONFIG_X86 */
#endif /* XSM_NO_WRAPPERS */
-extern int xsm_init(unsigned long *module_map, const multiboot_info_t *mbi,
- void *(*bootstrap_map)(const module_t *));
-extern int xsm_policy_init(unsigned long *module_map,
- const multiboot_info_t *mbi,
- void *(*bootstrap_map)(const module_t *));
+#ifdef CONFIG_MULTIBOOT
+extern int xsm_multiboot_init(unsigned long *module_map,
+ const multiboot_info_t *mbi,
+ void *(*bootstrap_map)(const module_t *));
+extern int xsm_multiboot_policy_init(unsigned long *module_map,
+ const multiboot_info_t *mbi,
+ void *(*bootstrap_map)(const module_t *));
+#endif
+
+#ifdef HAS_DEVICE_TREE
+extern int xsm_dt_init(void);
+extern int xsm_dt_policy_init(void);
+#endif
+
extern int register_xsm(struct xsm_operations *ops);
extern int unregister_xsm(struct xsm_operations *ops);
@@ -644,12 +693,22 @@ extern void xsm_fixup_ops(struct xsm_operations *ops);
#include <xsm/dummy.h>
-static inline int xsm_init (unsigned long *module_map,
- const multiboot_info_t *mbi,
- void *(*bootstrap_map)(const module_t *))
+#ifdef CONFIG_MULTIBOOT
+static inline int xsm_multiboot_init (unsigned long *module_map,
+ const multiboot_info_t *mbi,
+ void *(*bootstrap_map)(const module_t *))
{
return 0;
}
+#endif
+
+#ifdef HAS_DEVICE_TREE
+static inline int xsm_dt_init(void)
+{
+ return 0;
+}
+#endif
+
#endif /* XSM_ENABLE */
#endif /* __XSM_H */
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
index 31e4f73..8eb3050 100644
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -38,7 +38,6 @@ void xsm_fixup_ops (struct xsm_operations *ops)
set_to_dummy_if_null(ops, domctl);
set_to_dummy_if_null(ops, sysctl);
set_to_dummy_if_null(ops, readconsole);
- set_to_dummy_if_null(ops, do_mca);
set_to_dummy_if_null(ops, evtchn_unbound);
set_to_dummy_if_null(ops, evtchn_interdomain);
@@ -59,6 +58,8 @@ void xsm_fixup_ops (struct xsm_operations *ops)
set_to_dummy_if_null(ops, alloc_security_evtchn);
set_to_dummy_if_null(ops, free_security_evtchn);
set_to_dummy_if_null(ops, show_security_evtchn);
+ set_to_dummy_if_null(ops, init_hardware_domain);
+
set_to_dummy_if_null(ops, get_pod_target);
set_to_dummy_if_null(ops, set_pod_target);
@@ -84,11 +85,14 @@ void xsm_fixup_ops (struct xsm_operations *ops)
set_to_dummy_if_null(ops, iomem_permission);
set_to_dummy_if_null(ops, iomem_mapping);
set_to_dummy_if_null(ops, pci_config_permission);
+ set_to_dummy_if_null(ops, get_vnumainfo);
+#if defined(HAS_PASSTHROUGH) && defined(HAS_PCI)
set_to_dummy_if_null(ops, get_device_group);
set_to_dummy_if_null(ops, test_assign_device);
set_to_dummy_if_null(ops, assign_device);
set_to_dummy_if_null(ops, deassign_device);
+#endif
set_to_dummy_if_null(ops, resource_plug_core);
set_to_dummy_if_null(ops, resource_unplug_core);
@@ -102,21 +106,31 @@ void xsm_fixup_ops (struct xsm_operations *ops)
set_to_dummy_if_null(ops, tmem_op);
set_to_dummy_if_null(ops, tmem_control);
set_to_dummy_if_null(ops, hvm_param);
+ set_to_dummy_if_null(ops, hvm_control);
set_to_dummy_if_null(ops, hvm_param_nested);
set_to_dummy_if_null(ops, do_xsm_op);
+#ifdef CONFIG_COMPAT
+ set_to_dummy_if_null(ops, do_compat_op);
+#endif
set_to_dummy_if_null(ops, add_to_physmap);
set_to_dummy_if_null(ops, remove_from_physmap);
+ set_to_dummy_if_null(ops, map_gmfn_foreign);
+
+#ifdef HAS_MEM_ACCESS
+ set_to_dummy_if_null(ops, mem_event_control);
+ set_to_dummy_if_null(ops, mem_event_op);
+#endif
#ifdef CONFIG_X86
+ set_to_dummy_if_null(ops, do_mca);
set_to_dummy_if_null(ops, shadow_control);
set_to_dummy_if_null(ops, hvm_set_pci_intx_level);
set_to_dummy_if_null(ops, hvm_set_isa_irq_level);
set_to_dummy_if_null(ops, hvm_set_pci_link_route);
set_to_dummy_if_null(ops, hvm_inject_msi);
- set_to_dummy_if_null(ops, mem_event_control);
- set_to_dummy_if_null(ops, mem_event_op);
+ set_to_dummy_if_null(ops, hvm_ioreq_server);
set_to_dummy_if_null(ops, mem_sharing_op);
set_to_dummy_if_null(ops, apic);
set_to_dummy_if_null(ops, platform_op);
@@ -131,7 +145,4 @@ void xsm_fixup_ops (struct xsm_operations *ops)
set_to_dummy_if_null(ops, ioport_permission);
set_to_dummy_if_null(ops, ioport_mapping);
#endif
-#ifdef CONFIG_ARM
- set_to_dummy_if_null(ops, map_gmfn_foreign);
-#endif
}
diff --git a/xen/xsm/flask/avc.c b/xen/xsm/flask/avc.c
index 7fede00..fc6580e 100644
--- a/xen/xsm/flask/avc.c
+++ b/xen/xsm/flask/avc.c
@@ -197,7 +197,7 @@ static void avc_dump_av(struct avc_dump_buf *buf, u16 tclass, u32 av)
}
if ( av )
- avc_printk(buf, " 0x%x", av);
+ avc_printk(buf, " %#x", av);
avc_printk(buf, " }");
}
@@ -360,11 +360,10 @@ static struct avc_node *avc_alloc_node(void)
{
struct avc_node *node;
- node = xmalloc(struct avc_node);
+ node = xzalloc(struct avc_node);
if (!node)
goto out;
- memset(node, 0, sizeof(*node));
INIT_RCU_HEAD(&node->rhead);
INIT_HLIST_NODE(&node->list);
avc_cache_stats_incr(allocations);
@@ -592,16 +591,16 @@ void avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested,
avc_printk(&buf, "domid=%d ", cdom->domain_id);
switch ( a ? a->type : 0 ) {
case AVC_AUDIT_DATA_DEV:
- avc_printk(&buf, "device=0x%lx ", a->device);
+ avc_printk(&buf, "device=%#lx ", a->device);
break;
case AVC_AUDIT_DATA_IRQ:
avc_printk(&buf, "irq=%d ", a->irq);
break;
case AVC_AUDIT_DATA_RANGE:
- avc_printk(&buf, "range=0x%lx-0x%lx ", a->range.start, a->range.end);
+ avc_printk(&buf, "range=%#lx-%#lx ", a->range.start, a->range.end);
break;
case AVC_AUDIT_DATA_MEMORY:
- avc_printk(&buf, "pte=0x%lx mfn=0x%lx ", a->memory.pte, a->memory.mfn);
+ avc_printk(&buf, "pte=%#lx mfn=%#lx ", a->memory.pte, a->memory.mfn);
break;
}
@@ -655,11 +654,6 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, u16 tclass,
return rc;
}
-static inline int avc_sidcmp(u32 x, u32 y)
-{
- return (x == y || x == SECSID_WILD || y == SECSID_WILD);
-}
-
/**
* avc_update_node Update an AVC entry
* @event : Updating event
diff --git a/xen/xsm/flask/flask_op.c b/xen/xsm/flask/flask_op.c
index dddef29..7743aac 100644
--- a/xen/xsm/flask/flask_op.c
+++ b/xen/xsm/flask/flask_op.c
@@ -7,7 +7,7 @@
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*/
-
+#ifndef COMPAT
#include <xen/errno.h>
#include <xen/event.h>
#include <xsm/xsm.h>
@@ -20,6 +20,10 @@
#include <objsec.h>
#include <conditional.h>
+#define ret_t long
+#define _copy_to_guest copy_to_guest
+#define _copy_from_guest copy_from_guest
+
#ifdef FLASK_DEVELOP
int flask_enforcing = 0;
integer_param("flask_enforcing", flask_enforcing);
@@ -72,7 +76,7 @@ static int domain_has_security(struct domain *d, u32 perms)
perms, NULL);
}
-static int flask_copyin_string(XEN_GUEST_HANDLE_PARAM(char) u_buf, char **buf,
+static int flask_copyin_string(XEN_GUEST_HANDLE(char) u_buf, char **buf,
size_t size, size_t max_size)
{
char *tmp;
@@ -95,6 +99,8 @@ static int flask_copyin_string(XEN_GUEST_HANDLE_PARAM(char) u_buf, char **buf,
return 0;
}
+#endif /* COMPAT */
+
static int flask_security_user(struct xen_flask_userlist *arg)
{
char *user;
@@ -119,7 +125,7 @@ static int flask_security_user(struct xen_flask_userlist *arg)
arg->size = nsids;
- if ( copy_to_guest(arg->u.sids, sids, nsids) )
+ if ( _copy_to_guest(arg->u.sids, sids, nsids) )
rv = -EFAULT;
xfree(sids);
@@ -128,6 +134,8 @@ static int flask_security_user(struct xen_flask_userlist *arg)
return rv;
}
+#ifndef COMPAT
+
static int flask_security_relabel(struct xen_flask_transition *arg)
{
int rv;
@@ -208,6 +216,8 @@ static int flask_security_setenforce(struct xen_flask_setenforce *arg)
return 0;
}
+#endif /* COMPAT */
+
static int flask_security_context(struct xen_flask_sid_context *arg)
{
int rv;
@@ -252,7 +262,7 @@ static int flask_security_sid(struct xen_flask_sid_context *arg)
arg->size = len;
- if ( !rv && copy_to_guest(arg->context, context, len) )
+ if ( !rv && _copy_to_guest(arg->context, context, len) )
rv = -EFAULT;
xfree(context);
@@ -260,7 +270,9 @@ static int flask_security_sid(struct xen_flask_sid_context *arg)
return rv;
}
-int flask_disable(void)
+#ifndef COMPAT
+
+static int flask_disable(void)
{
static int flask_disabled = 0;
@@ -302,6 +314,8 @@ static int flask_security_setavc_threshold(struct xen_flask_setavc_threshold *ar
return rv;
}
+#endif /* COMPAT */
+
static int flask_security_resolve_bool(struct xen_flask_boolean *arg)
{
char *name;
@@ -382,24 +396,6 @@ static int flask_security_set_bool(struct xen_flask_boolean *arg)
return rv;
}
-static int flask_security_commit_bools(void)
-{
- int rv;
-
- spin_lock(&sel_sem);
-
- rv = domain_has_security(current->domain, SECURITY__SETBOOL);
- if ( rv )
- goto out;
-
- if ( bool_pending_values )
- rv = security_set_bools(bool_num, bool_pending_values);
-
- out:
- spin_unlock(&sel_sem);
- return rv;
-}
-
static int flask_security_get_bool(struct xen_flask_boolean *arg)
{
int rv;
@@ -431,7 +427,7 @@ static int flask_security_get_bool(struct xen_flask_boolean *arg)
rv = -ERANGE;
arg->size = nameout_len;
- if ( !rv && copy_to_guest(arg->name, nameout, nameout_len) )
+ if ( !rv && _copy_to_guest(arg->name, nameout, nameout_len) )
rv = -EFAULT;
xfree(nameout);
}
@@ -441,6 +437,26 @@ static int flask_security_get_bool(struct xen_flask_boolean *arg)
return rv;
}
+#ifndef COMPAT
+
+static int flask_security_commit_bools(void)
+{
+ int rv;
+
+ spin_lock(&sel_sem);
+
+ rv = domain_has_security(current->domain, SECURITY__SETBOOL);
+ if ( rv )
+ goto out;
+
+ if ( bool_pending_values )
+ rv = security_set_bools(bool_num, bool_pending_values);
+
+ out:
+ spin_unlock(&sel_sem);
+ return rv;
+}
+
static int flask_security_make_bools(void)
{
int ret = 0;
@@ -484,6 +500,7 @@ static int flask_security_avc_cachestats(struct xen_flask_cache_stats *arg)
}
#endif
+#endif /* COMPAT */
static int flask_security_load(struct xen_flask_load *load)
{
@@ -501,7 +518,7 @@ static int flask_security_load(struct xen_flask_load *load)
if ( !buf )
return -ENOMEM;
- if ( copy_from_guest(buf, load->buffer, load->size) )
+ if ( _copy_from_guest(buf, load->buffer, load->size) )
{
ret = -EFAULT;
goto out_free;
@@ -524,6 +541,8 @@ static int flask_security_load(struct xen_flask_load *load)
return ret;
}
+#ifndef COMPAT
+
static int flask_ocontext_del(struct xen_flask_ocontext *arg)
{
int rv;
@@ -636,7 +655,9 @@ static int flask_relabel_domain(struct xen_flask_relabel *arg)
return rc;
}
-long do_flask_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) u_flask_op)
+#endif /* !COMPAT */
+
+ret_t do_flask_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) u_flask_op)
{
xen_flask_op_t op;
int rv;
@@ -763,3 +784,52 @@ long do_flask_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) u_flask_op)
out:
return rv;
}
+
+#if defined(CONFIG_COMPAT) && !defined(COMPAT)
+#undef _copy_to_guest
+#define _copy_to_guest copy_to_compat
+#undef _copy_from_guest
+#define _copy_from_guest copy_from_compat
+
+#include <compat/event_channel.h>
+#include <compat/xsm/flask_op.h>
+
+CHECK_flask_access;
+CHECK_flask_cache_stats;
+CHECK_flask_hash_stats;
+CHECK_flask_ocontext;
+CHECK_flask_peersid;
+CHECK_flask_relabel;
+CHECK_flask_setavc_threshold;
+CHECK_flask_setenforce;
+CHECK_flask_transition;
+
+#define COMPAT
+#define flask_copyin_string(ch, pb, sz, mx) ({ \
+ XEN_GUEST_HANDLE_PARAM(char) gh; \
+ guest_from_compat_handle(gh, ch); \
+ flask_copyin_string(gh, pb, sz, mx); \
+})
+
+#define xen_flask_load compat_flask_load
+#define flask_security_load compat_security_load
+
+#define xen_flask_userlist compat_flask_userlist
+#define flask_security_user compat_security_user
+
+#define xen_flask_sid_context compat_flask_sid_context
+#define flask_security_context compat_security_context
+#define flask_security_sid compat_security_sid
+
+#define xen_flask_boolean compat_flask_boolean
+#define flask_security_resolve_bool compat_security_resolve_bool
+#define flask_security_get_bool compat_security_get_bool
+#define flask_security_set_bool compat_security_set_bool
+
+#define xen_flask_op_t compat_flask_op_t
+#undef ret_t
+#define ret_t int
+#define do_flask_op compat_flask_op
+
+#include "flask_op.c"
+#endif
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index d94ab77..d48463f 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -9,6 +9,7 @@
*/
#include <xen/init.h>
+#include <xen/irq.h>
#include <xen/lib.h>
#include <xen/sched.h>
#include <xen/paging.h>
@@ -19,7 +20,9 @@
#include <xen/errno.h>
#include <xen/guest_access.h>
#include <xen/xenoprof.h>
+#ifdef HAS_PCI
#include <asm/msi.h>
+#endif
#include <public/xen.h>
#include <public/physdev.h>
#include <public/platform.h>
@@ -52,8 +55,7 @@ static u32 domain_target_sid(struct domain *src, struct domain *dst)
static u32 evtchn_sid(const struct evtchn *chn)
{
- struct evtchn_security_struct *esec = chn->ssid;
- return esec->sid;
+ return chn->ssid.flask_sid;
}
static int domain_has_perm(struct domain *dom1, struct domain *dom2,
@@ -100,7 +102,6 @@ static int domain_has_xen(struct domain *d, u32 perms)
static int get_irq_sid(int irq, u32 *sid, struct avc_audit_data *ad)
{
- struct irq_desc *desc = irq_to_desc(irq);
if ( irq >= nr_irqs || irq < 0 )
return -EINVAL;
if ( irq < nr_static_irqs ) {
@@ -110,15 +111,21 @@ static int get_irq_sid(int irq, u32 *sid, struct avc_audit_data *ad)
}
return security_irq_sid(irq, sid);
}
- if ( desc->msi_desc && desc->msi_desc->dev ) {
- struct pci_dev *dev = desc->msi_desc->dev;
- u32 sbdf = (dev->seg << 16) | (dev->bus << 8) | dev->devfn;
- if (ad) {
- AVC_AUDIT_DATA_INIT(ad, DEV);
- ad->device = sbdf;
+#ifdef HAS_PCI
+ {
+ struct irq_desc *desc = irq_to_desc(irq);
+ if ( desc->msi_desc && desc->msi_desc->dev ) {
+ struct pci_dev *dev = desc->msi_desc->dev;
+ u32 sbdf = (dev->seg << 16) | (dev->bus << 8) | dev->devfn;
+ if (ad) {
+ AVC_AUDIT_DATA_INIT(ad, DEV);
+ ad->device = sbdf;
+ }
+ return security_device_sid(sbdf, sid);
}
- return security_device_sid(sbdf, sid);
}
+#endif
+
if (ad) {
AVC_AUDIT_DATA_INIT(ad, IRQ);
ad->irq = irq;
@@ -132,13 +139,10 @@ static int flask_domain_alloc_security(struct domain *d)
{
struct domain_security_struct *dsec;
- dsec = xmalloc(struct domain_security_struct);
-
+ dsec = xzalloc(struct domain_security_struct);
if ( !dsec )
return -ENOMEM;
- memset(dsec, 0, sizeof(struct domain_security_struct));
-
switch ( d->domain_id )
{
case DOMID_IDLE:
@@ -177,7 +181,6 @@ static int flask_evtchn_unbound(struct domain *d1, struct evtchn *chn,
u32 sid1, sid2, newsid;
int rc;
struct domain *d2;
- struct evtchn_security_struct *esec;
d2 = rcu_lock_domain_by_any_id(id2);
if ( d2 == NULL )
@@ -185,7 +188,6 @@ static int flask_evtchn_unbound(struct domain *d1, struct evtchn *chn,
sid1 = domain_sid(d1);
sid2 = domain_target_sid(d1, d2);
- esec = chn->ssid;
rc = security_transition_sid(sid1, sid2, SECCLASS_EVENT, &newsid);
if ( rc )
@@ -199,7 +201,7 @@ static int flask_evtchn_unbound(struct domain *d1, struct evtchn *chn,
if ( rc )
goto out;
- esec->sid = newsid;
+ chn->ssid.flask_sid = newsid;
out:
rcu_unlock_domain(d2);
@@ -211,7 +213,6 @@ static int flask_evtchn_interdomain(struct domain *d1, struct evtchn *chn1,
{
u32 sid1, sid2, newsid, reverse_sid;
int rc;
- struct evtchn_security_struct *esec1;
struct avc_audit_data ad;
AVC_AUDIT_DATA_INIT(&ad, NONE);
ad.sdom = d1;
@@ -220,8 +221,6 @@ static int flask_evtchn_interdomain(struct domain *d1, struct evtchn *chn1,
sid1 = domain_sid(d1);
sid2 = domain_target_sid(d1, d2);
- esec1 = chn1->ssid;
-
rc = security_transition_sid(sid1, sid2, SECCLASS_EVENT, &newsid);
if ( rc )
{
@@ -247,17 +246,14 @@ static int flask_evtchn_interdomain(struct domain *d1, struct evtchn *chn1,
if ( rc )
return rc;
- esec1->sid = newsid;
+ chn1->ssid.flask_sid = newsid;
return rc;
}
static void flask_evtchn_close_post(struct evtchn *chn)
{
- struct evtchn_security_struct *esec;
- esec = chn->ssid;
-
- esec->sid = SECINITSID_UNLABELED;
+ chn->ssid.flask_sid = SECINITSID_UNLABELED;
}
static int flask_evtchn_send(struct domain *d, struct evtchn *chn)
@@ -292,36 +288,17 @@ static int flask_evtchn_reset(struct domain *d1, struct domain *d2)
static int flask_alloc_security_evtchn(struct evtchn *chn)
{
- struct evtchn_security_struct *esec;
-
- esec = xmalloc(struct evtchn_security_struct);
-
- if ( !esec )
- return -ENOMEM;
-
- memset(esec, 0, sizeof(struct evtchn_security_struct));
-
- esec->sid = SECINITSID_UNLABELED;
-
- chn->ssid = esec;
+ chn->ssid.flask_sid = SECINITSID_UNLABELED;
return 0;
}
static void flask_free_security_evtchn(struct evtchn *chn)
{
- struct evtchn_security_struct *esec;
-
if ( !chn )
return;
- esec = chn->ssid;
-
- if ( !esec )
- return;
-
- chn->ssid = NULL;
- xfree(esec);
+ chn->ssid.flask_sid = SECINITSID_UNLABELED;
}
static char *flask_show_security_evtchn(struct domain *d, const struct evtchn *chn)
@@ -350,6 +327,11 @@ static char *flask_show_security_evtchn(struct domain *d, const struct evtchn *c
return ctx;
}
+static int flask_init_hardware_domain(struct domain *d)
+{
+ return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__CREATE_HARDWARE_DOMAIN);
+}
+
static int flask_grant_mapref(struct domain *d1, struct domain *d2,
uint32_t flags)
{
@@ -422,6 +404,11 @@ static int flask_claim_pages(struct domain *d)
return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__SETCLAIM);
}
+static int flask_get_vnumainfo(struct domain *d)
+{
+ return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__GET_VNUMAINFO);
+}
+
static int flask_console_io(struct domain *d, int cmd)
{
u32 perm;
@@ -588,16 +575,18 @@ static int flask_domctl(struct domain *d, int cmd)
case XEN_DOMCTL_scheduler_op:
case XEN_DOMCTL_irq_permission:
case XEN_DOMCTL_iomem_permission:
+ case XEN_DOMCTL_memory_mapping:
case XEN_DOMCTL_set_target:
+#ifdef HAS_MEM_ACCESS
+ case XEN_DOMCTL_mem_event_op:
+#endif
#ifdef CONFIG_X86
/* These have individual XSM hooks (arch/x86/domctl.c) */
case XEN_DOMCTL_shadow_op:
case XEN_DOMCTL_ioport_permission:
case XEN_DOMCTL_bind_pt_irq:
case XEN_DOMCTL_unbind_pt_irq:
- case XEN_DOMCTL_memory_mapping:
case XEN_DOMCTL_ioport_mapping:
- case XEN_DOMCTL_mem_event_op:
/* These have individual XSM hooks (drivers/passthrough/iommu.c) */
case XEN_DOMCTL_get_device_group:
case XEN_DOMCTL_test_assign_device:
@@ -683,9 +672,11 @@ static int flask_domctl(struct domain *d, int cmd)
return current_has_perm(d, SECCLASS_HVM, HVM__CACHEATTR);
case XEN_DOMCTL_set_ext_vcpucontext:
+ case XEN_DOMCTL_set_vcpu_msrs:
return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SETEXTVCPUCONTEXT);
case XEN_DOMCTL_get_ext_vcpucontext:
+ case XEN_DOMCTL_get_vcpu_msrs:
return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__GETEXTVCPUCONTEXT);
case XEN_DOMCTL_setvcpuextstate:
@@ -733,6 +724,14 @@ static int flask_domctl(struct domain *d, int cmd)
case XEN_DOMCTL_cacheflush:
return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__CACHEFLUSH);
+ case XEN_DOMCTL_setvnumainfo:
+ return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN2__SET_VNUMAINFO);
+ case XEN_DOMCTL_psr_cmt_op:
+ return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__PSR_CMT_OP);
+
+ case XEN_DOMCTL_arm_configure_domain:
+ return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__CONFIGURE_DOMAIN);
+
default:
printk("flask_domctl: Unknown op %d\n", cmd);
return -EPERM;
@@ -788,6 +787,10 @@ static int flask_sysctl(int cmd)
case XEN_SYSCTL_numainfo:
return domain_has_xen(current->domain, XEN__PHYSINFO);
+ case XEN_SYSCTL_psr_cmt_op:
+ return avc_current_has_perm(SECINITSID_XEN, SECCLASS_XEN2,
+ XEN2__PSR_CMT_OP, NULL);
+
default:
printk("flask_sysctl: Unknown op %d\n", cmd);
return -EPERM;
@@ -804,11 +807,6 @@ static int flask_readconsole(uint32_t clear)
return domain_has_xen(current->domain, perms);
}
-static int flask_do_mca(void)
-{
- return domain_has_xen(current->domain, XEN__MCA_OP);
-}
-
static inline u32 resource_to_perm(uint8_t access)
{
if ( access )
@@ -836,21 +834,34 @@ static int flask_map_domain_pirq (struct domain *d)
return current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
}
+static int flask_map_domain_msi (struct domain *d, int irq, void *data,
+ u32 *sid, struct avc_audit_data *ad)
+{
+#ifdef HAS_PCI
+ struct msi_info *msi = data;
+
+ u32 machine_bdf = (msi->seg << 16) | (msi->bus << 8) | msi->devfn;
+ AVC_AUDIT_DATA_INIT(ad, DEV);
+ ad->device = machine_bdf;
+
+ return security_device_sid(machine_bdf, sid);
+#else
+ return -EINVAL;
+#endif
+}
+
static int flask_map_domain_irq (struct domain *d, int irq, void *data)
{
u32 sid, dsid;
int rc = -EPERM;
- struct msi_info *msi = data;
struct avc_audit_data ad;
- if ( irq >= nr_static_irqs && msi ) {
- u32 machine_bdf = (msi->seg << 16) | (msi->bus << 8) | msi->devfn;
- AVC_AUDIT_DATA_INIT(&ad, DEV);
- ad.device = machine_bdf;
- rc = security_device_sid(machine_bdf, &sid);
+ if ( irq >= nr_static_irqs && data ) {
+ rc = flask_map_domain_msi(d, irq, data, &sid, &ad);
} else {
rc = get_irq_sid(irq, &sid, &ad);
}
+
if ( rc )
return rc;
@@ -869,18 +880,30 @@ static int flask_unmap_domain_pirq (struct domain *d)
return current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__REMOVE);
}
+static int flask_unmap_domain_msi (struct domain *d, int irq, void *data,
+ u32 *sid, struct avc_audit_data *ad)
+{
+#ifdef HAS_PCI
+ struct msi_info *msi = data;
+ u32 machine_bdf = (msi->seg << 16) | (msi->bus << 8) | msi->devfn;
+
+ AVC_AUDIT_DATA_INIT(ad, DEV);
+ ad->device = machine_bdf;
+
+ return security_device_sid(machine_bdf, sid);
+#else
+ return -EINVAL;
+#endif
+}
+
static int flask_unmap_domain_irq (struct domain *d, int irq, void *data)
{
u32 sid;
int rc = -EPERM;
- struct msi_info *msi = data;
struct avc_audit_data ad;
- if ( irq >= nr_static_irqs && msi ) {
- u32 machine_bdf = (msi->seg << 16) | (msi->bus << 8) | msi->devfn;
- AVC_AUDIT_DATA_INIT(&ad, DEV);
- ad.device = machine_bdf;
- rc = security_device_sid(machine_bdf, &sid);
+ if ( irq >= nr_static_irqs && data ) {
+ rc = flask_unmap_domain_msi(d, irq, data, &sid, &ad);
} else {
rc = get_irq_sid(irq, &sid, &ad);
}
@@ -1081,6 +1104,11 @@ static int flask_remove_from_physmap(struct domain *d1, struct domain *d2)
return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__PHYSMAP);
}
+static int flask_map_gmfn_foreign(struct domain *d, struct domain *t)
+{
+ return domain_has_perm(d, t, SECCLASS_MMU, MMU__MAP_READ | MMU__MAP_WRITE);
+}
+
static int flask_hvm_param(struct domain *d, unsigned long op)
{
u32 perm;
@@ -1108,7 +1136,90 @@ static int flask_hvm_param_nested(struct domain *d)
return current_has_perm(d, SECCLASS_HVM, HVM__NESTED);
}
+#if defined(HAS_PASSTHROUGH) && defined(HAS_PCI)
+static int flask_get_device_group(uint32_t machine_bdf)
+{
+ u32 rsid;
+ int rc = -EPERM;
+
+ rc = security_device_sid(machine_bdf, &rsid);
+ if ( rc )
+ return rc;
+
+ return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE, NULL);
+}
+
+static int flask_test_assign_device(uint32_t machine_bdf)
+{
+ u32 rsid;
+ int rc = -EPERM;
+
+ rc = security_device_sid(machine_bdf, &rsid);
+ if ( rc )
+ return rc;
+
+ return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE, NULL);
+}
+
+static int flask_assign_device(struct domain *d, uint32_t machine_bdf)
+{
+ u32 dsid, rsid;
+ int rc = -EPERM;
+ struct avc_audit_data ad;
+
+ rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
+ if ( rc )
+ return rc;
+
+ rc = security_device_sid(machine_bdf, &rsid);
+ if ( rc )
+ return rc;
+
+ AVC_AUDIT_DATA_INIT(&ad, DEV);
+ ad.device = (unsigned long) machine_bdf;
+ rc = avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__ADD_DEVICE, &ad);
+ if ( rc )
+ return rc;
+
+ dsid = domain_sid(d);
+ return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad);
+}
+
+static int flask_deassign_device(struct domain *d, uint32_t machine_bdf)
+{
+ u32 rsid;
+ int rc = -EPERM;
+
+ rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__REMOVE);
+ if ( rc )
+ return rc;
+
+ rc = security_device_sid(machine_bdf, &rsid);
+ if ( rc )
+ return rc;
+
+ return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__REMOVE_DEVICE, NULL);
+}
+#endif /* HAS_PASSTHROUGH && HAS_PCI */
+
+#ifdef HAS_MEM_ACCESS
+static int flask_mem_event_control(struct domain *d, int mode, int op)
+{
+ return current_has_perm(d, SECCLASS_HVM, HVM__MEM_EVENT);
+}
+
+static int flask_mem_event_op(struct domain *d, int op)
+{
+ return current_has_perm(d, SECCLASS_HVM, HVM__MEM_EVENT);
+}
+#endif /* HAS_MEM_ACCESS */
+
#ifdef CONFIG_X86
+static int flask_do_mca(void)
+{
+ return domain_has_xen(current->domain, XEN__MCA_OP);
+}
+
static int flask_shadow_control(struct domain *d, uint32_t op)
{
u32 perm;
@@ -1208,14 +1319,9 @@ static int flask_hvm_inject_msi(struct domain *d)
return current_has_perm(d, SECCLASS_HVM, HVM__SEND_IRQ);
}
-static int flask_mem_event_control(struct domain *d, int mode, int op)
+static int flask_hvm_ioreq_server(struct domain *d, int op)
{
- return current_has_perm(d, SECCLASS_HVM, HVM__MEM_EVENT);
-}
-
-static int flask_mem_event_op(struct domain *d, int op)
-{
- return current_has_perm(d, SECCLASS_HVM, HVM__MEM_EVENT);
+ return current_has_perm(d, SECCLASS_HVM, HVM__HVMCTL);
}
static int flask_mem_sharing_op(struct domain *d, struct domain *cd, int op)
@@ -1300,6 +1406,10 @@ static int flask_platform_op(uint32_t op)
case XENPF_get_cpuinfo:
return domain_has_xen(current->domain, XEN__GETCPUINFO);
+ case XENPF_resource_op:
+ return avc_current_has_perm(SECINITSID_XEN, SECCLASS_XEN2,
+ XEN2__RESOURCE_OP, NULL);
+
default:
printk("flask_platform_op: Unknown op %d\n", op);
return -EPERM;
@@ -1361,70 +1471,6 @@ static int flask_priv_mapping(struct domain *d, struct domain *t)
return domain_has_perm(d, t, SECCLASS_MMU, MMU__TARGET_HACK);
}
-static int flask_get_device_group(uint32_t machine_bdf)
-{
- u32 rsid;
- int rc = -EPERM;
-
- rc = security_device_sid(machine_bdf, &rsid);
- if ( rc )
- return rc;
-
- return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE, NULL);
-}
-
-static int flask_test_assign_device(uint32_t machine_bdf)
-{
- u32 rsid;
- int rc = -EPERM;
-
- rc = security_device_sid(machine_bdf, &rsid);
- if ( rc )
- return rc;
-
- return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE, NULL);
-}
-
-static int flask_assign_device(struct domain *d, uint32_t machine_bdf)
-{
- u32 dsid, rsid;
- int rc = -EPERM;
- struct avc_audit_data ad;
-
- rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
- if ( rc )
- return rc;
-
- rc = security_device_sid(machine_bdf, &rsid);
- if ( rc )
- return rc;
-
- AVC_AUDIT_DATA_INIT(&ad, DEV);
- ad.device = (unsigned long) machine_bdf;
- rc = avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__ADD_DEVICE, &ad);
- if ( rc )
- return rc;
-
- dsid = domain_sid(d);
- return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad);
-}
-
-static int flask_deassign_device(struct domain *d, uint32_t machine_bdf)
-{
- u32 rsid;
- int rc = -EPERM;
-
- rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__REMOVE);
- if ( rc )
- return rc;
-
- rc = security_device_sid(machine_bdf, &rsid);
- if ( rc )
- return rc;
-
- return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__REMOVE_DEVICE, NULL);
-}
-
static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *bind)
{
u32 dsid, rsid;
@@ -1456,14 +1502,8 @@ static int flask_unbind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq
}
#endif /* CONFIG_X86 */
-#ifdef CONFIG_ARM
-static int flask_map_gmfn_foreign(struct domain *d, struct domain *t)
-{
- return domain_has_perm(d, t, SECCLASS_MMU, MMU__MAP_READ | MMU__MAP_WRITE);
-}
-#endif
-
long do_flask_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) u_flask_op);
+int compat_flask_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) u_flask_op);
static struct xsm_operations flask_ops = {
.security_domaininfo = flask_security_domaininfo,
@@ -1475,7 +1515,6 @@ static struct xsm_operations flask_ops = {
.domctl = flask_domctl,
.sysctl = flask_sysctl,
.readconsole = flask_readconsole,
- .do_mca = flask_do_mca,
.evtchn_unbound = flask_evtchn_unbound,
.evtchn_interdomain = flask_evtchn_interdomain,
@@ -1496,6 +1535,7 @@ static struct xsm_operations flask_ops = {
.alloc_security_evtchn = flask_alloc_security_evtchn,
.free_security_evtchn = flask_free_security_evtchn,
.show_security_evtchn = flask_show_security_evtchn,
+ .init_hardware_domain = flask_init_hardware_domain,
.get_pod_target = flask_get_pod_target,
.set_pod_target = flask_set_pod_target,
@@ -1535,21 +1575,40 @@ static struct xsm_operations flask_ops = {
.tmem_op = flask_tmem_op,
.tmem_control = flask_tmem_control,
.hvm_param = flask_hvm_param,
+ .hvm_control = flask_hvm_param,
.hvm_param_nested = flask_hvm_param_nested,
.do_xsm_op = do_flask_op,
+ .get_vnumainfo = flask_get_vnumainfo,
+
+#ifdef CONFIG_COMPAT
+ .do_compat_op = compat_flask_op,
+#endif
.add_to_physmap = flask_add_to_physmap,
.remove_from_physmap = flask_remove_from_physmap,
+ .map_gmfn_foreign = flask_map_gmfn_foreign,
+
+#if defined(HAS_PASSTHROUGH) && defined(HAS_PCI)
+ .get_device_group = flask_get_device_group,
+ .test_assign_device = flask_test_assign_device,
+ .assign_device = flask_assign_device,
+ .deassign_device = flask_deassign_device,
+#endif
+
+#ifdef HAS_MEM_ACCESS
+ .mem_event_control = flask_mem_event_control,
+ .mem_event_op = flask_mem_event_op,
+#endif
#ifdef CONFIG_X86
+ .do_mca = flask_do_mca,
.shadow_control = flask_shadow_control,
.hvm_set_pci_intx_level = flask_hvm_set_pci_intx_level,
.hvm_set_isa_irq_level = flask_hvm_set_isa_irq_level,
.hvm_set_pci_link_route = flask_hvm_set_pci_link_route,
.hvm_inject_msi = flask_hvm_inject_msi,
- .mem_event_control = flask_mem_event_control,
- .mem_event_op = flask_mem_event_op,
+ .hvm_ioreq_server = flask_hvm_ioreq_server,
.mem_sharing_op = flask_mem_sharing_op,
.apic = flask_apic,
.platform_op = flask_platform_op,
@@ -1559,18 +1618,11 @@ static struct xsm_operations flask_ops = {
.mmuext_op = flask_mmuext_op,
.update_va_mapping = flask_update_va_mapping,
.priv_mapping = flask_priv_mapping,
- .get_device_group = flask_get_device_group,
- .test_assign_device = flask_test_assign_device,
- .assign_device = flask_assign_device,
- .deassign_device = flask_deassign_device,
.bind_pt_irq = flask_bind_pt_irq,
.unbind_pt_irq = flask_unbind_pt_irq,
.ioport_permission = flask_ioport_permission,
.ioport_mapping = flask_ioport_mapping,
#endif
-#ifdef CONFIG_ARM
- .map_gmfn_foreign = flask_map_gmfn_foreign,
-#endif
};
static __init int flask_init(void)
diff --git a/xen/xsm/flask/include/conditional.h b/xen/xsm/flask/include/conditional.h
index 043cfd8..9055340 100644
--- a/xen/xsm/flask/include/conditional.h
+++ b/xen/xsm/flask/include/conditional.h
@@ -21,7 +21,7 @@ int security_set_bools(int len, int *values);
int security_find_bool(const char *name);
-char *security_get_bool_name(unsigned int bool);
-int security_get_bool_value(unsigned int bool);
+char *security_get_bool_name(unsigned int b);
+int security_get_bool_value(unsigned int b);
#endif
diff --git a/xen/xsm/flask/include/objsec.h b/xen/xsm/flask/include/objsec.h
index 6595dc3..b576a5d 100644
--- a/xen/xsm/flask/include/objsec.h
+++ b/xen/xsm/flask/include/objsec.h
@@ -23,10 +23,4 @@ struct domain_security_struct {
u32 target_sid; /* SID for device model target domain */
};
-struct evtchn_security_struct {
- u32 sid; /* current SID */
-};
-
-extern unsigned int selinux_checkreqprot;
-
#endif /* _FLASK_OBJSEC_H_ */
diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors
index a0ed13d..1da9f63 100644
--- a/xen/xsm/flask/policy/access_vectors
+++ b/xen/xsm/flask/policy/access_vectors
@@ -3,9 +3,9 @@
#
# class class_name { permission_name ... }
-# Class xen consists of dom0-only operations dealing with the hypervisor itself.
-# Unless otherwise specified, the source is the domain executing the hypercall,
-# and the target is the xen initial sid (type xen_t).
+# Class xen and xen2 consists of dom0-only operations dealing with the
+# hypervisor itself. Unless otherwise specified, the source is the domain
+# executing the hypercall, and the target is the xen initial sid (type xen_t).
class xen
{
# XENPF_settime
@@ -75,6 +75,16 @@ class xen
setscheduler
}
+# This is a continuation of class xen, since only 32 permissions can be
+# defined per class
+class xen2
+{
+# XENPF_resource_op
+ resource_op
+# XEN_SYSCTL_psr_cmt_op
+ psr_cmt_op
+}
+
# Classes domain and domain2 consist of operations that a domain performs on
# another domain or on itself. Unless otherwise specified, the source is the
# domain executing the hypercall, and the target is the domain being operated on
@@ -92,7 +102,7 @@ class domain
unpause
# XEN_DOMCTL_resumedomain
resume
-# XEN_DOMCTL_createdomain
+# XEN_DOMCTL_arm_createdomain
create
# checked in FLASK_RELABEL_DOMAIN for any relabel operation:
# source = the old label of the domain
@@ -141,8 +151,10 @@ class domain
# XEN_DOMCTL_sendtrigger
trigger
# XEN_DOMCTL_get_ext_vcpucontext
+# XEN_DOMCTL_set_vcpu_msrs
getextvcpucontext
# XEN_DOMCTL_set_ext_vcpucontext
+# XEN_DOMCTL_get_vcpu_msrs
setextvcpucontext
# XEN_DOMCTL_getvcpuextstate
getvcpuextstate
@@ -198,6 +210,16 @@ class domain2
set_max_evtchn
# XEN_DOMCTL_cacheflush
cacheflush
+# Creation of the hardware domain when it is not dom0
+ create_hardware_domain
+# XEN_DOMCTL_setvnumainfo
+ set_vnumainfo
+# XENMEM_getvnumainfo
+ get_vnumainfo
+# XEN_DOMCTL_psr_cmt_op
+ psr_cmt_op
+# XEN_DOMCTL_configure_domain
+ configure_domain
}
# Similar to class domain, but primarily contains domctls related to HVM domains
diff --git a/xen/xsm/flask/policy/security_classes b/xen/xsm/flask/policy/security_classes
index ef134a7..ca191db 100644
--- a/xen/xsm/flask/policy/security_classes
+++ b/xen/xsm/flask/policy/security_classes
@@ -8,6 +8,7 @@
# for userspace object managers
class xen
+class xen2
class domain
class domain2
class hvm
diff --git a/xen/xsm/flask/ss/avtab.c b/xen/xsm/flask/ss/avtab.c
index 47912e9..bfc91c8 100644
--- a/xen/xsm/flask/ss/avtab.c
+++ b/xen/xsm/flask/ss/avtab.c
@@ -38,11 +38,10 @@ static struct avtab_node* avtab_insert_node(struct avtab *h, int hvalue,
struct avtab_node * prev, struct avtab_node * cur, struct avtab_key *key,
struct avtab_datum *datum)
{
- struct avtab_node * newnode;
- newnode = xmalloc(struct avtab_node);
+ struct avtab_node *newnode = xzalloc(struct avtab_node);
+
if ( newnode == NULL )
return NULL;
- memset(newnode, 0, sizeof(struct avtab_node));
newnode->key = *key;
newnode->datum = *datum;
if ( prev )
diff --git a/xen/xsm/flask/ss/conditional.c b/xen/xsm/flask/ss/conditional.c
index 123d839..098ddc0 100644
--- a/xen/xsm/flask/ss/conditional.c
+++ b/xen/xsm/flask/ss/conditional.c
@@ -228,10 +228,9 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
u32 len;
int rc;
- booldatum = xmalloc(struct cond_bool_datum);
+ booldatum = xzalloc(struct cond_bool_datum);
if ( !booldatum )
return -1;
- memset(booldatum, 0, sizeof(struct cond_bool_datum));
rc = next_entry(buf, fp, sizeof buf);
if ( rc < 0 )
@@ -343,10 +342,9 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k,
goto err;
}
- list = xmalloc(struct cond_av_list);
+ list = xzalloc(struct cond_av_list);
if ( !list )
goto err;
- memset(list, 0, sizeof(*list));
list->node = node_ptr;
if ( !data->head )
@@ -441,12 +439,9 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
if ( rc < 0 )
goto err;
- expr = xmalloc(struct cond_expr);
+ expr = xzalloc(struct cond_expr);
if ( !expr )
- {
goto err;
- }
- memset(expr, 0, sizeof(struct cond_expr));
expr->expr_type = le32_to_cpu(buf[0]);
expr->bool = le32_to_cpu(buf[1]);
@@ -494,10 +489,9 @@ int cond_read_list(struct policydb *p, void *fp)
for ( i = 0; i < len; i++ )
{
- node = xmalloc(struct cond_node);
+ node = xzalloc(struct cond_node);
if ( !node )
goto err;
- memset(node, 0, sizeof(struct cond_node));
if ( cond_read_node(p, node, fp) != 0 )
goto err;
diff --git a/xen/xsm/flask/ss/ebitmap.c b/xen/xsm/flask/ss/ebitmap.c
index 61f38d8..bb3ec8e 100644
--- a/xen/xsm/flask/ss/ebitmap.c
+++ b/xen/xsm/flask/ss/ebitmap.c
@@ -50,13 +50,12 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
prev = NULL;
while ( n )
{
- new = xmalloc(struct ebitmap_node);
+ new = xzalloc(struct ebitmap_node);
if ( !new )
{
ebitmap_destroy(dst);
return -ENOMEM;
}
- memset(new, 0, sizeof(*new));
new->startbit = n->startbit;
memcpy(new->maps, n->maps, EBITMAP_SIZE / 8);
new->next = NULL;
@@ -176,10 +175,9 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
if ( !value )
return 0;
- new = xmalloc(struct ebitmap_node);
+ new = xzalloc(struct ebitmap_node);
if ( !new )
return -ENOMEM;
- memset(new, 0, sizeof(*new));
new->startbit = bit - (bit % EBITMAP_SIZE);
ebitmap_node_set_bit(new, bit);
@@ -284,8 +282,8 @@ int ebitmap_read(struct ebitmap *e, void *fp)
if ( !n || startbit >= n->startbit + EBITMAP_SIZE )
{
- struct ebitmap_node *tmp;
- tmp = xmalloc(struct ebitmap_node);
+ struct ebitmap_node *tmp = xzalloc(struct ebitmap_node);
+
if ( !tmp )
{
printk(KERN_ERR
@@ -293,7 +291,6 @@ int ebitmap_read(struct ebitmap *e, void *fp)
rc = -ENOMEM;
goto bad;
}
- memset(tmp, 0, sizeof(*tmp));
/* round down */
tmp->startbit = startbit - (startbit % EBITMAP_SIZE);
if ( n )
diff --git a/xen/xsm/flask/ss/hashtab.c b/xen/xsm/flask/ss/hashtab.c
index 5be7a88..f35c0dc 100644
--- a/xen/xsm/flask/ss/hashtab.c
+++ b/xen/xsm/flask/ss/hashtab.c
@@ -16,28 +16,21 @@ struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h,
int (*keycmp)(struct hashtab *h, const void *key1,
const void *key2), u32 size)
{
- struct hashtab *p;
- u32 i;
+ struct hashtab *p = xzalloc(struct hashtab);
- p = xmalloc(struct hashtab);
if ( p == NULL )
return p;
- memset(p, 0, sizeof(*p));
p->size = size;
- p->nel = 0;
p->hash_value = hash_value;
p->keycmp = keycmp;
- p->htable = xmalloc_array(struct hashtab_node *, size);
+ p->htable = xzalloc_array(struct hashtab_node *, size);
if ( p->htable == NULL )
{
xfree(p);
return NULL;
}
- for ( i = 0; i < size; i++ )
- p->htable[i] = NULL;
-
return p;
}
@@ -61,10 +54,9 @@ int hashtab_insert(struct hashtab *h, void *key, void *datum)
if ( cur && (h->keycmp(h, key, cur->key) == 0) )
return -EEXIST;
- newnode = xmalloc(struct hashtab_node);
+ newnode = xzalloc(struct hashtab_node);
if ( newnode == NULL )
return -ENOMEM;
- memset(newnode, 0, sizeof(*newnode));
newnode->key = key;
newnode->datum = datum;
if ( prev )
diff --git a/xen/xsm/flask/ss/policydb.c b/xen/xsm/flask/ss/policydb.c
index bdec4ac..50b2c78 100644
--- a/xen/xsm/flask/ss/policydb.c
+++ b/xen/xsm/flask/ss/policydb.c
@@ -166,13 +166,12 @@ static int roles_init(struct policydb *p)
int rc;
struct role_datum *role;
- role = xmalloc(struct role_datum);
+ role = xzalloc(struct role_datum);
if ( !role )
{
rc = -ENOMEM;
goto out;
}
- memset(role, 0, sizeof(*role));
role->value = ++p->p_roles.nprim;
if ( role->value != OBJECT_R_VAL )
{
@@ -950,13 +949,12 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
__le32 buf[2];
u32 len;
- perdatum = xmalloc(struct perm_datum);
+ perdatum = xzalloc(struct perm_datum);
if ( !perdatum )
{
rc = -ENOMEM;
goto out;
}
- memset(perdatum, 0, sizeof(*perdatum));
rc = next_entry(buf, fp, sizeof buf);
if ( rc < 0 )
@@ -994,13 +992,12 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp)
u32 len, nel;
int i, rc;
- comdatum = xmalloc(struct common_datum);
+ comdatum = xzalloc(struct common_datum);
if ( !comdatum )
{
rc = -ENOMEM;
goto out;
}
- memset(comdatum, 0, sizeof(*comdatum));
rc = next_entry(buf, fp, sizeof buf);
if ( rc < 0 )
@@ -1055,10 +1052,9 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons,
lc = NULL;
for ( i = 0; i < ncons; i++ )
{
- c = xmalloc(struct constraint_node);
+ c = xzalloc(struct constraint_node);
if ( !c )
return -ENOMEM;
- memset(c, 0, sizeof(*c));
if ( lc )
{
@@ -1078,10 +1074,9 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons,
depth = -1;
for ( j = 0; j < nexpr; j++ )
{
- e = xmalloc(struct constraint_expr);
+ e = xzalloc(struct constraint_expr);
if ( !e )
return -ENOMEM;
- memset(e, 0, sizeof(*e));
if ( le )
le->next = e;
@@ -1142,13 +1137,12 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
u32 len, len2, ncons, nel;
int i, rc;
- cladatum = xmalloc(struct class_datum);
+ cladatum = xzalloc(struct class_datum);
if ( !cladatum )
{
rc = -ENOMEM;
goto out;
}
- memset(cladatum, 0, sizeof(*cladatum));
rc = next_entry(buf, fp, sizeof(u32)*6);
if ( rc < 0 )
@@ -1226,13 +1220,12 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
__le32 buf[3];
u32 len;
- role = xmalloc(struct role_datum);
+ role = xzalloc(struct role_datum);
if ( !role )
{
rc = -ENOMEM;
goto out;
}
- memset(role, 0, sizeof(*role));
if ( p->policyvers >= POLICYDB_VERSION_BOUNDARY )
rc = next_entry(buf, fp, sizeof(buf[0]) * 3);
@@ -1297,13 +1290,12 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
__le32 buf[4];
u32 len;
- typdatum = xmalloc(struct type_datum);
+ typdatum = xzalloc(struct type_datum);
if ( !typdatum )
{
rc = -ENOMEM;
return rc;
}
- memset(typdatum, 0, sizeof(*typdatum));
if ( p->policyvers >= POLICYDB_VERSION_BOUNDARY )
rc = next_entry(buf, fp, sizeof(buf[0]) * 4);
@@ -1391,13 +1383,12 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
__le32 buf[3];
u32 len;
- usrdatum = xmalloc(struct user_datum);
+ usrdatum = xzalloc(struct user_datum);
if ( !usrdatum )
{
rc = -ENOMEM;
goto out;
}
- memset(usrdatum, 0, sizeof(*usrdatum));
if ( p->policyvers >= POLICYDB_VERSION_BOUNDARY )
rc = next_entry(buf, fp, sizeof(buf[0]) * 3);
@@ -1455,13 +1446,12 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
__le32 buf[2];
u32 len;
- levdatum = xmalloc(struct level_datum);
+ levdatum = xzalloc(struct level_datum);
if ( !levdatum )
{
rc = -ENOMEM;
goto out;
}
- memset(levdatum, 0, sizeof(*levdatum));
rc = next_entry(buf, fp, sizeof buf);
if ( rc < 0 )
@@ -1511,13 +1501,12 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
__le32 buf[3];
u32 len;
- catdatum = xmalloc(struct cat_datum);
+ catdatum = xzalloc(struct cat_datum);
if ( !catdatum )
{
rc = -ENOMEM;
goto out;
}
- memset(catdatum, 0, sizeof(*catdatum));
rc = next_entry(buf, fp, sizeof buf);
if ( rc < 0 )
@@ -1727,8 +1716,8 @@ int policydb_read(struct policydb *p, void *fp)
if ( le32_to_cpu(buf[0]) != POLICYDB_MAGIC )
{
- printk(KERN_ERR "Flask: policydb magic number 0x%x does "
- "not match expected magic number 0x%x\n",
+ printk(KERN_ERR "Flask: policydb magic number %#x does "
+ "not match expected magic number %#x\n",
le32_to_cpu(buf[0]), POLICYDB_MAGIC);
goto bad;
}
@@ -1875,13 +1864,12 @@ int policydb_read(struct policydb *p, void *fp)
ltr = NULL;
for ( i = 0; i < nel; i++ )
{
- tr = xmalloc(struct role_trans);
+ tr = xzalloc(struct role_trans);
if ( !tr )
{
rc = -ENOMEM;
goto bad;
}
- memset(tr, 0, sizeof(*tr));
if ( ltr )
ltr->next = tr;
else
@@ -1909,13 +1897,12 @@ int policydb_read(struct policydb *p, void *fp)
lra = NULL;
for ( i = 0; i < nel; i++ )
{
- ra = xmalloc(struct role_allow);
+ ra = xzalloc(struct role_allow);
if ( !ra )
{
rc = -ENOMEM;
goto bad;
}
- memset(ra, 0, sizeof(*ra));
if ( lra )
lra->next = ra;
else
@@ -1951,13 +1938,12 @@ int policydb_read(struct policydb *p, void *fp)
l = NULL;
for ( j = 0; j < nel; j++ )
{
- c = xmalloc(struct ocontext);
+ c = xzalloc(struct ocontext);
if ( !c )
{
rc = -ENOMEM;
goto bad;
}
- memset(c, 0, sizeof(*c));
if ( l )
l->next = c;
else
@@ -2067,13 +2053,12 @@ int policydb_read(struct policydb *p, void *fp)
lrt = NULL;
for ( i = 0; i < nel; i++ )
{
- rt = xmalloc(struct range_trans);
+ rt = xzalloc(struct range_trans);
if ( !rt )
{
rc = -ENOMEM;
goto bad;
}
- memset(rt, 0, sizeof(*rt));
if ( lrt )
lrt->next = rt;
else
diff --git a/xen/xsm/flask/ss/services.c b/xen/xsm/flask/ss/services.c
index 6067317..f0e459a 100644
--- a/xen/xsm/flask/ss/services.c
+++ b/xen/xsm/flask/ss/services.c
@@ -1771,13 +1771,12 @@ int security_get_user_sids(u32 fromsid, char *username, u32 **sids, u32 *nel)
}
usercon.user = user->value;
- mysids = xmalloc_array(u32, maxnel);
+ mysids = xzalloc_array(u32, maxnel);
if ( !mysids )
{
rc = -ENOMEM;
goto out_unlock;
}
- memset(mysids, 0, maxnel*sizeof(*mysids));
ebitmap_for_each_positive_bit(&user->roles, rnode, i)
{
@@ -1808,14 +1807,13 @@ int security_get_user_sids(u32 fromsid, char *username, u32 **sids, u32 *nel)
else
{
maxnel += SIDS_NEL;
- mysids2 = xmalloc_array(u32, maxnel);
+ mysids2 = xzalloc_array(u32, maxnel);
if ( !mysids2 )
{
rc = -ENOMEM;
xfree(mysids);
goto out_unlock;
}
- memset(mysids2, 0, maxnel*sizeof(*mysids2));
memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
xfree(mysids);
mysids = mysids2;
@@ -1868,14 +1866,14 @@ int security_get_bools(int *len, char ***names, int **values, size_t *maxstr)
goto out;
}
- if ( names ) {
- *names = (char**)xmalloc_array(char*, *len);
+ if ( names )
+ {
+ *names = xzalloc_array(char *, *len);
if ( !*names )
goto err;
- memset(*names, 0, sizeof(char*) * *len);
}
- *values = (int*)xmalloc_array(int, *len);
+ *values = xmalloc_array(int, *len);
if ( !*values )
goto err;
@@ -1960,7 +1958,7 @@ out:
return rc;
}
-int security_get_bool_value(unsigned int bool)
+int security_get_bool_value(unsigned int b)
{
int rc = 0;
unsigned int len;
@@ -1968,19 +1966,19 @@ int security_get_bool_value(unsigned int bool)
POLICY_RDLOCK;
len = policydb.p_bools.nprim;
- if ( bool >= len )
+ if ( b >= len )
{
rc = -ENOENT;
goto out;
}
- rc = policydb.bool_val_to_struct[bool]->state;
+ rc = policydb.bool_val_to_struct[b]->state;
out:
POLICY_RDUNLOCK;
return rc;
}
-char *security_get_bool_name(unsigned int bool)
+char *security_get_bool_name(unsigned int b)
{
unsigned int len;
char *rv = NULL;
@@ -1988,16 +1986,16 @@ char *security_get_bool_name(unsigned int bool)
POLICY_RDLOCK;
len = policydb.p_bools.nprim;
- if ( bool >= len )
+ if ( b >= len )
{
goto out;
}
- len = strlen(policydb.p_bool_val_to_name[bool]) + 1;
+ len = strlen(policydb.p_bool_val_to_name[b]) + 1;
rv = xmalloc_array(char, len);
if ( !rv )
goto out;
- memcpy(rv, policydb.p_bool_val_to_name[bool], len);
+ memcpy(rv, policydb.p_bool_val_to_name[b], len);
out:
POLICY_RDUNLOCK;
return rv;
@@ -2037,20 +2035,6 @@ out:
return rc;
}
-int determine_ocontext( char *ocontext )
-{
- if ( strcmp(ocontext, "pirq") == 0 )
- return OCON_PIRQ;
- else if ( strcmp(ocontext, "ioport") == 0 )
- return OCON_IOPORT;
- else if ( strcmp(ocontext, "iomem") == 0 )
- return OCON_IOMEM;
- else if ( strcmp(ocontext, "pcidevice") == 0 )
- return OCON_DEVICE;
- else
- return -1;
-}
-
int security_ocontext_add( u32 ocon, unsigned long low, unsigned long high
,u32 sid )
{
@@ -2059,9 +2043,8 @@ int security_ocontext_add( u32 ocon, unsigned long low, unsigned long high
struct ocontext *prev;
struct ocontext *add;
- if ( (add = xmalloc(struct ocontext)) == NULL )
+ if ( (add = xzalloc(struct ocontext)) == NULL )
return -ENOMEM;
- memset(add, 0, sizeof(struct ocontext));
add->sid[0] = sid;
POLICY_WRLOCK;
@@ -2114,7 +2097,7 @@ int security_ocontext_add( u32 ocon, unsigned long low, unsigned long high
c->u.ioport.high_ioport == high && c->sid[0] == sid)
break;
- printk("%s: IO Port overlap with entry 0x%x - 0x%x\n",
+ printk("%s: IO Port overlap with entry %#x - %#x\n",
__FUNCTION__, c->u.ioport.low_ioport,
c->u.ioport.high_ioport);
ret = -EEXIST;
@@ -2148,7 +2131,7 @@ int security_ocontext_add( u32 ocon, unsigned long low, unsigned long high
c->u.iomem.high_iomem == high && c->sid[0] == sid)
break;
- printk("%s: IO Memory overlap with entry 0x%x - 0x%x\n",
+ printk("%s: IO Memory overlap with entry %#x - %#x\n",
__FUNCTION__, c->u.iomem.low_iomem,
c->u.iomem.high_iomem);
ret = -EEXIST;
@@ -2180,7 +2163,7 @@ int security_ocontext_add( u32 ocon, unsigned long low, unsigned long high
if ( c->sid[0] == sid )
break;
- printk("%s: Duplicate PCI Device 0x%x\n", __FUNCTION__,
+ printk("%s: Duplicate PCI Device %#x\n", __FUNCTION__,
add->u.device);
ret = -EEXIST;
break;
@@ -2260,7 +2243,7 @@ int security_ocontext_del( u32 ocon, unsigned int low, unsigned int high )
}
}
- printk("%s: ocontext not found: ioport 0x%x - 0x%x\n", __FUNCTION__,
+ printk("%s: ocontext not found: ioport %#x - %#x\n", __FUNCTION__,
low, high);
ret = -ENOENT;
break;
@@ -2287,7 +2270,7 @@ int security_ocontext_del( u32 ocon, unsigned int low, unsigned int high )
}
}
- printk("%s: ocontext not found: iomem 0x%x - 0x%x\n", __FUNCTION__,
+ printk("%s: ocontext not found: iomem %#x - %#x\n", __FUNCTION__,
low, high);
ret = -ENOENT;
break;
@@ -2313,7 +2296,7 @@ int security_ocontext_del( u32 ocon, unsigned int low, unsigned int high )
}
}
- printk("%s: ocontext not found: pcidevice 0x%x\n", __FUNCTION__, low);
+ printk("%s: ocontext not found: pcidevice %#x\n", __FUNCTION__, low);
ret = -ENOENT;
break;
diff --git a/xen/xsm/xsm_core.c b/xen/xsm/xsm_core.c
index ca28f91..0ac6d03 100644
--- a/xen/xsm/xsm_core.c
+++ b/xen/xsm/xsm_core.c
@@ -43,8 +43,25 @@ static void __init do_xsm_initcalls(void)
}
}
-int __init xsm_init(unsigned long *module_map, const multiboot_info_t *mbi,
- void *(*bootstrap_map)(const module_t *))
+static int __init xsm_core_init(void)
+{
+ if ( verify(&dummy_xsm_ops) )
+ {
+ printk("%s could not verify "
+ "dummy_xsm_ops structure.\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ xsm_ops = &dummy_xsm_ops;
+ do_xsm_initcalls();
+
+ return 0;
+}
+
+#ifdef CONFIG_MULTIBOOT
+int __init xsm_multiboot_init(unsigned long *module_map,
+ const multiboot_info_t *mbi,
+ void *(*bootstrap_map)(const module_t *))
{
int ret = 0;
@@ -52,7 +69,7 @@ int __init xsm_init(unsigned long *module_map, const multiboot_info_t *mbi,
if ( XSM_MAGIC )
{
- ret = xsm_policy_init(module_map, mbi, bootstrap_map);
+ ret = xsm_multiboot_policy_init(module_map, mbi, bootstrap_map);
if ( ret )
{
bootstrap_map(NULL);
@@ -61,20 +78,38 @@ int __init xsm_init(unsigned long *module_map, const multiboot_info_t *mbi,
}
}
- if ( verify(&dummy_xsm_ops) )
+ ret = xsm_core_init();
+ bootstrap_map(NULL);
+
+ return 0;
+}
+#endif
+
+#ifdef HAS_DEVICE_TREE
+int __init xsm_dt_init(void)
+{
+ int ret = 0;
+
+ printk("XSM Framework v" XSM_FRAMEWORK_VERSION " initialized\n");
+
+ if ( XSM_MAGIC )
{
- bootstrap_map(NULL);
- printk("%s could not verify "
- "dummy_xsm_ops structure.\n", __FUNCTION__);
- return -EIO;
+ ret = xsm_dt_policy_init();
+ if ( ret )
+ {
+ printk("%s: Error initializing policy (rc = %d).\n",
+ __FUNCTION__, ret);
+ return -EINVAL;
+ }
}
- xsm_ops = &dummy_xsm_ops;
- do_xsm_initcalls();
- bootstrap_map(NULL);
+ ret = xsm_core_init();
- return 0;
+ xfree(policy_buffer);
+
+ return ret;
}
+#endif
int register_xsm(struct xsm_operations *ops)
{
@@ -116,4 +151,9 @@ long do_xsm_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
return xsm_do_xsm_op(op);
}
-
+#ifdef CONFIG_COMPAT
+int compat_xsm_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
+{
+ return xsm_do_compat_op(op);
+}
+#endif
diff --git a/xen/xsm/xsm_policy.c b/xen/xsm/xsm_policy.c
index cad7964..6e0bb78 100644
--- a/xen/xsm/xsm_policy.c
+++ b/xen/xsm/xsm_policy.c
@@ -19,15 +19,22 @@
*/
#include <xsm/xsm.h>
+#ifdef CONFIG_MULTIBOOT
#include <xen/multiboot.h>
+#endif
#include <xen/bitops.h>
+#ifdef HAS_DEVICE_TREE
+# include <asm/setup.h>
+# include <xen/device_tree.h>
+#endif
char *__initdata policy_buffer = NULL;
u32 __initdata policy_size = 0;
-int __init xsm_policy_init(unsigned long *module_map,
- const multiboot_info_t *mbi,
- void *(*bootstrap_map)(const module_t *))
+#ifdef CONFIG_MULTIBOOT
+int __init xsm_multiboot_policy_init(unsigned long *module_map,
+ const multiboot_info_t *mbi,
+ void *(*bootstrap_map)(const module_t *))
{
int i;
module_t *mod = (module_t *)__va(mbi->mods_addr);
@@ -52,7 +59,7 @@ int __init xsm_policy_init(unsigned long *module_map,
policy_buffer = (char *)_policy_start;
policy_size = _policy_len;
- printk("Policy len 0x%lx, start at %p.\n",
+ printk("Policy len %#lx, start at %p.\n",
_policy_len,_policy_start);
__clear_bit(i, module_map);
@@ -65,3 +72,50 @@ int __init xsm_policy_init(unsigned long *module_map,
return rc;
}
+#endif
+
+#ifdef HAS_DEVICE_TREE
+int __init xsm_dt_policy_init(void)
+{
+ struct bootmodule *mod = boot_module_find_by_kind(BOOTMOD_XSM);
+ paddr_t paddr, len;
+ xsm_magic_t magic;
+
+ if ( !mod || !mod->size )
+ return 0;
+
+ paddr = mod->start;
+ len = mod->size;
+
+ copy_from_paddr(&magic, paddr, sizeof(magic));
+
+ if ( magic != XSM_MAGIC )
+ {
+ printk(XENLOG_ERR "xsm: Invalid magic for XSM blob got 0x%x "
+ "expected 0x%x\n", magic, XSM_MAGIC);
+ return -EINVAL;
+ }
+
+ printk("xsm: Policy len = 0x%"PRIpaddr" start at 0x%"PRIpaddr"\n",
+ len, paddr);
+
+ policy_buffer = xmalloc_bytes(len);
+ if ( !policy_buffer )
+ return -ENOMEM;
+
+ copy_from_paddr(policy_buffer, paddr, len);
+ policy_size = len;
+
+ return 0;
+}
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-xen/xen.git
More information about the Pkg-xen-changes
mailing list