[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
# HG changeset patch # User awilliam@xxxxxxxxxxx # Node ID ebed727182630279e605f32f35a5364924cbd433 # Parent 11b718eb22c996868bed5b18dcc08081ad27d0be # Parent d19deb173503962cc42c235cdeda84d3b4a6a52c merge with xen-unstable.hg --- tools/firmware/acpi/Makefile | 68 tools/firmware/acpi/README | 22 tools/firmware/acpi/acpi2_0.h | 331 tools/firmware/acpi/acpi_build.c | 232 tools/firmware/acpi/acpi_dsdt.asl | 521 tools/firmware/acpi/acpi_dsdt.c | 300 tools/firmware/acpi/acpi_facs.c | 72 tools/firmware/acpi/acpi_facs.h | 32 tools/firmware/acpi/acpi_fadt.c | 193 tools/firmware/acpi/acpi_fadt.h | 166 tools/firmware/acpi/acpi_gen.c | 53 tools/firmware/acpi/acpi_madt.c | 68 tools/firmware/acpi/acpi_madt.h | 44 tools/firmware/acpi/acpi_rsdt.c | 68 tools/pygrub/src/fsys/__init__.py | 64 tools/pygrub/src/fsys/ext2/__init__.py | 38 tools/pygrub/src/fsys/ext2/ext2module.c | 387 tools/pygrub/src/fsys/ext2/test.py | 15 tools/pygrub/src/fsys/reiser/__init__.py | 40 tools/pygrub/src/fsys/reiser/reisermodule.c | 345 .hgignore | 3 buildconfigs/linux-defconfig_xen0_ia64 | 2 buildconfigs/linux-defconfig_xen_ia64 | 2 config/SunOS.mk | 2 docs/src/user.tex | 26 docs/xen-api/Makefile | 23 docs/xen-api/coversheet.tex | 50 docs/xen-api/fdl.tex | 488 docs/xen-api/presentation.tex | 149 docs/xen-api/todo.tex | 140 docs/xen-api/vm-lifecycle.tex | 24 docs/xen-api/vm_lifecycle.dot | 15 docs/xen-api/wire-protocol.tex | 287 docs/xen-api/xen.eps | 49 docs/xen-api/xenapi-coversheet.tex | 40 docs/xen-api/xenapi-datamodel-graph.dot | 17 docs/xen-api/xenapi-datamodel.tex | 9648 ++++++++++ docs/xen-api/xenapi.tex | 56 linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c | 2 linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c | 4 linux-2.6-xen-sparse/arch/i386/mm/init-xen.c | 4 linux-2.6-xen-sparse/arch/ia64/xen/xencomm.c | 5 linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c | 4 linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c | 1 linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c | 42 linux-2.6-xen-sparse/drivers/xen/blkback/common.h | 5 linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c | 3 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c | 21 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c | 30 linux-2.6-xen-sparse/drivers/xen/blkfront/block.h | 2 linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c | 75 linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c | 215 linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c | 6 linux-2.6-xen-sparse/drivers/xen/core/Makefile | 2 linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c | 185 linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 212 linux-2.6-xen-sparse/drivers/xen/netback/interface.c | 3 linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 9 linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c | 14 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 48 linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c | 18 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c | 7 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/fixmap.h | 1 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h | 10 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h | 8 linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h | 15 linux-2.6-xen-sparse/include/asm-ia64/hypercall.h | 3 linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h | 16 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/fixmap.h | 1 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h | 10 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h | 17 linux-2.6-xen-sparse/include/xen/gnttab.h | 5 patches/linux-2.6.16.29/series | 1 patches/linux-2.6.16.29/xenoprof-generic.patch | 53 tools/Makefile | 1 tools/blktap/drivers/blktapctrl.c | 4 tools/blktap/drivers/tapdisk.c | 5 tools/blktap/drivers/tapdisk.h | 1 tools/blktap/lib/blktaplib.h | 7 tools/console/Makefile | 2 tools/examples/blktap | 18 tools/examples/block | 30 tools/examples/external-device-migrate | 56 tools/examples/vif-bridge | 2 tools/examples/vif-nat | 4 tools/examples/vif-route | 2 tools/examples/xend-config.sxp | 2 tools/examples/xmexample.hvm | 3 tools/firmware/Makefile | 1 tools/firmware/hvmloader/Makefile | 11 tools/firmware/hvmloader/acpi/Makefile | 63 tools/firmware/hvmloader/acpi/README | 24 tools/firmware/hvmloader/acpi/acpi2_0.h | 324 tools/firmware/hvmloader/acpi/build.c | 241 tools/firmware/hvmloader/acpi/dsdt.asl | 521 tools/firmware/hvmloader/acpi/dsdt.c | 300 tools/firmware/hvmloader/acpi/gen.c | 53 tools/firmware/hvmloader/acpi/static_tables.c | 184 tools/firmware/hvmloader/acpi_madt.c | 176 tools/firmware/hvmloader/acpi_ssdt_tpm.asl | 29 tools/firmware/hvmloader/acpi_ssdt_tpm.h | 25 tools/firmware/hvmloader/acpi_utils.c | 207 tools/firmware/hvmloader/acpi_utils.h | 36 tools/firmware/hvmloader/hvmloader.c | 16 tools/firmware/hvmloader/util.c | 5 tools/firmware/vmxassist/setup.c | 3 tools/firmware/vmxassist/vm86.c | 87 tools/ioemu/Makefile.target | 1 tools/ioemu/hw/ne2000.c | 35 tools/ioemu/hw/pc.c | 3 tools/ioemu/hw/serial.c | 44 tools/ioemu/hw/tpm_tis.c | 1114 + tools/ioemu/keymaps/ja | 3 tools/ioemu/target-i386-dm/cpu.h | 2 tools/ioemu/target-i386-dm/exec-dm.c | 50 tools/ioemu/target-i386-dm/helper2.c | 131 tools/ioemu/target-i386-dm/i8259-dm.c | 42 tools/ioemu/target-i386-dm/qemu-dm.debug | 7 tools/ioemu/vl.c | 25 tools/ioemu/vl.h | 23 tools/ioemu/vnc_keysym.h | 10 tools/ioemu/xenstore.c | 137 tools/libfsimage/Makefile | 13 tools/libfsimage/Rules.mk | 32 tools/libfsimage/check-libext2fs | 21 tools/libfsimage/common/Makefile | 46 tools/libfsimage/common/fsimage.c | 142 tools/libfsimage/common/fsimage.h | 52 tools/libfsimage/common/fsimage_grub.c | 276 tools/libfsimage/common/fsimage_grub.h | 92 tools/libfsimage/common/fsimage_plugin.c | 214 tools/libfsimage/common/fsimage_plugin.h | 65 tools/libfsimage/common/fsimage_priv.h | 62 tools/libfsimage/common/mapfile-GNU | 37 tools/libfsimage/common/mapfile-SunOS | 35 tools/libfsimage/ext2fs-lib/Makefile | 15 tools/libfsimage/ext2fs-lib/ext2fs-lib.c | 172 tools/libfsimage/ext2fs/Makefile | 13 tools/libfsimage/ext2fs/fsys_ext2fs.c | 804 tools/libfsimage/reiserfs/Makefile | 13 tools/libfsimage/reiserfs/fsys_reiserfs.c | 1254 + tools/libfsimage/ufs/Makefile | 13 tools/libfsimage/ufs/fsys_ufs.c | 276 tools/libfsimage/ufs/ufs.h | 228 tools/libxc/ia64/xc_ia64_hvm_build.c | 2 tools/libxc/xc_core.c | 2 tools/libxc/xc_domain.c | 28 tools/libxc/xc_hvm_build.c | 297 tools/libxc/xc_linux_build.c | 195 tools/libxc/xc_linux_save.c | 24 tools/libxc/xc_misc.c | 28 tools/libxc/xc_private.c | 22 tools/libxc/xc_private.h | 5 tools/libxc/xc_ptrace.c | 29 tools/libxc/xc_ptrace_core.c | 24 tools/libxc/xenctrl.h | 31 tools/libxc/xenguest.h | 34 tools/libxc/xg_private.c | 66 tools/libxc/xg_private.h | 2 tools/libxen/COPYING | 510 tools/libxen/Makefile | 37 tools/libxen/README | 54 tools/libxen/include/xen_boot_type.h | 87 tools/libxen/include/xen_boot_type_internal.h | 37 tools/libxen/include/xen_common.h | 145 tools/libxen/include/xen_cpu_feature.h | 387 tools/libxen/include/xen_cpu_feature_internal.h | 37 tools/libxen/include/xen_driver_type.h | 77 tools/libxen/include/xen_driver_type_internal.h | 37 tools/libxen/include/xen_host.h | 292 tools/libxen/include/xen_host_cpu.h | 239 tools/libxen/include/xen_host_cpu_decl.h | 30 tools/libxen/include/xen_host_decl.h | 30 tools/libxen/include/xen_int_float_map.h | 53 tools/libxen/include/xen_internal.h | 193 tools/libxen/include/xen_network.h | 273 tools/libxen/include/xen_network_decl.h | 30 tools/libxen/include/xen_on_crash_behaviour.h | 97 tools/libxen/include/xen_on_crash_behaviour_internal.h | 38 tools/libxen/include/xen_on_normal_exit.h | 77 tools/libxen/include/xen_on_normal_exit_internal.h | 37 tools/libxen/include/xen_pif.h | 290 tools/libxen/include/xen_pif_decl.h | 30 tools/libxen/include/xen_sr.h | 282 tools/libxen/include/xen_sr_decl.h | 30 tools/libxen/include/xen_string_string_map.h | 53 tools/libxen/include/xen_user.h | 204 tools/libxen/include/xen_user_decl.h | 30 tools/libxen/include/xen_vbd.h | 285 tools/libxen/include/xen_vbd_decl.h | 30 tools/libxen/include/xen_vbd_mode.h | 77 tools/libxen/include/xen_vbd_mode_internal.h | 37 tools/libxen/include/xen_vdi.h | 344 tools/libxen/include/xen_vdi_decl.h | 30 tools/libxen/include/xen_vdi_type.h | 82 tools/libxen/include/xen_vdi_type_internal.h | 37 tools/libxen/include/xen_vif.h | 305 tools/libxen/include/xen_vif_decl.h | 30 tools/libxen/include/xen_vm.h | 819 tools/libxen/include/xen_vm_decl.h | 30 tools/libxen/include/xen_vm_power_state.h | 97 tools/libxen/include/xen_vm_power_state_internal.h | 37 tools/libxen/include/xen_vtpm.h | 216 tools/libxen/include/xen_vtpm_decl.h | 31 tools/libxen/src/xen_boot_type.c | 83 tools/libxen/src/xen_common.c | 1363 + tools/libxen/src/xen_cpu_feature.c | 143 tools/libxen/src/xen_driver_type.c | 81 tools/libxen/src/xen_host.c | 390 tools/libxen/src/xen_host_cpu.c | 287 tools/libxen/src/xen_int_float_map.c | 37 tools/libxen/src/xen_network.c | 364 tools/libxen/src/xen_on_crash_behaviour.c | 85 tools/libxen/src/xen_on_normal_exit.c | 81 tools/libxen/src/xen_pif.c | 403 tools/libxen/src/xen_sr.c | 388 tools/libxen/src/xen_string_string_map.c | 49 tools/libxen/src/xen_user.c | 201 tools/libxen/src/xen_vbd.c | 387 tools/libxen/src/xen_vbd_mode.c | 81 tools/libxen/src/xen_vdi.c | 533 tools/libxen/src/xen_vdi_type.c | 82 tools/libxen/src/xen_vif.c | 440 tools/libxen/src/xen_vm.c | 1596 + tools/libxen/src/xen_vm_power_state.c | 85 tools/libxen/src/xen_vtpm.c | 227 tools/libxen/test/test_bindings.c | 424 tools/pygrub/setup.py | 43 tools/pygrub/src/fsimage/fsimage.c | 299 tools/pygrub/src/pygrub | 35 tools/python/README.XendConfig | 159 tools/python/README.sxpcfg | 116 tools/python/scripts/README | 49 tools/python/scripts/README.lifecycle | 136 tools/python/scripts/xapi.domcfg.py | 37 tools/python/scripts/xapi.py | 537 tools/python/scripts/xapi.vbdcfg.py | 12 tools/python/scripts/xapi.vdicfg.py | 7 tools/python/scripts/xapi.vifcfg.py | 10 tools/python/scripts/xapi.vtpmcfg.py | 3 tools/python/setup.py | 3 tools/python/xen/lowlevel/xc/xc.c | 90 tools/python/xen/util/blkif.py | 14 tools/python/xen/util/xmlrpclib2.py | 36 tools/python/xen/xend/Args.py | 2 tools/python/xen/xend/PrettyPrint.py | 2 tools/python/xen/xend/XendAPI.py | 1531 + tools/python/xen/xend/XendAPIConstants.py | 75 tools/python/xen/xend/XendAuthSessions.py | 137 tools/python/xen/xend/XendBootloader.py | 6 tools/python/xen/xend/XendCheckpoint.py | 29 tools/python/xen/xend/XendConfig.py | 872 tools/python/xen/xend/XendConstants.py | 96 tools/python/xen/xend/XendDevices.py | 68 tools/python/xen/xend/XendDomain.py | 1313 + tools/python/xen/xend/XendDomainInfo.py | 2490 +- tools/python/xen/xend/XendError.py | 16 tools/python/xen/xend/XendNode.py | 131 tools/python/xen/xend/XendProtocol.py | 2 tools/python/xen/xend/XendRoot.py | 28 tools/python/xen/xend/XendStorageRepository.py | 381 tools/python/xen/xend/XendVDI.py | 155 tools/python/xen/xend/image.py | 84 tools/python/xen/xend/server/DevController.py | 79 tools/python/xen/xend/server/SrvDaemon.py | 10 tools/python/xen/xend/server/SrvDomainDir.py | 2 tools/python/xen/xend/server/SrvServer.py | 30 tools/python/xen/xend/server/XMLRPCServer.py | 103 tools/python/xen/xend/server/blkif.py | 56 tools/python/xen/xend/server/iopif.py | 4 tools/python/xen/xend/server/irqif.py | 2 tools/python/xen/xend/server/netif.py | 38 tools/python/xen/xend/server/pciif.py | 61 tools/python/xen/xend/server/tpmif.py | 32 tools/python/xen/xend/sxp.py | 24 tools/python/xen/xend/uuid.py | 10 tools/python/xen/xm/create.py | 84 tools/python/xen/xm/main.py | 108 tools/python/xen/xm/new.py | 68 tools/xenmon/Makefile | 2 tools/xenmon/xenmon.py | 4 tools/xenstat/libxenstat/src/xenstat.c | 20 tools/xenstore/Makefile | 2 tools/xenstore/xsls.c | 19 tools/xentrace/formats | 2 tools/xm-test/configure.ac | 9 tools/xm-test/lib/XmTestLib/arch.py | 1 tools/xm-test/lib/XmTestReport/arch.py | 4 tools/xm-test/ramdisk/Makefile.am | 6 tools/xm-test/ramdisk/README-XenSource-initrd-1.0-img | 3 tools/xm-test/ramdisk/README-XenSource-initrd-1.1-img | 45 tools/xm-test/ramdisk/make-release.sh | 47 tools/xm-test/ramdisk/patches/buildroot/add_xvd_devices.patch | 5 tools/xm-test/runtest.sh | 27 tools/xm-test/tests/block-create/01_block_attach_device_pos.py | 10 tools/xm-test/tests/block-create/02_block_attach_file_device_pos.py | 8 tools/xm-test/tests/block-create/04_block_attach_device_repeatedly_pos.py | 16 tools/xm-test/tests/block-create/05_block_attach_and_dettach_device_repeatedly_pos.py | 18 tools/xm-test/tests/block-create/06_block_attach_baddomain_neg.py | 8 tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py | 14 tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py | 16 tools/xm-test/tests/block-create/09_block_attach_and_dettach_device_check_data_pos.py | 44 tools/xm-test/tests/block-create/10_block_attach_dettach_multiple_devices.py | 30 tools/xm-test/tests/block-create/11_block_attach_shared_dom0.py | 2 tools/xm-test/tests/block-create/12_block_attach_shared_domU.py | 2 tools/xm-test/tests/block-destroy/01_block-destroy_btblock_pos.py | 8 tools/xm-test/tests/block-destroy/02_block-destroy_rtblock_pos.py | 8 tools/xm-test/tests/block-destroy/04_block-destroy_nonattached_neg.py | 2 tools/xm-test/tests/block-destroy/05_block-destroy_byname_pos.py | 8 tools/xm-test/tests/block-destroy/06_block-destroy_check_list_pos.py | 10 tools/xm-test/tests/block-integrity/01_block_device_read_verify.py | 4 tools/xm-test/tests/block-integrity/02_block_device_write_verify.py | 4 tools/xm-test/tests/block-list/01_block-list_pos.py | 6 tools/xm-test/tests/block-list/02_block-list_attachbd_pos.py | 6 tools/xm-test/tests/block-list/03_block-list_anotherbd_pos.py | 10 tools/xm-test/tests/block-list/06_block-list_checkremove_pos.py | 24 tools/xm-test/tests/create/07_create_mem64_pos.py | 2 tools/xm-test/tests/create/08_create_mem128_pos.py | 2 tools/xm-test/tests/create/09_create_mem256_pos.py | 2 tools/xm-test/tests/create/14_create_blockroot_pos.py | 11 tools/xm-test/tests/network-attach/04_network_attach_baddomain_neg.py | 6 unmodified_drivers/linux-2.6/Makefile | 1 unmodified_drivers/linux-2.6/compat-include/asm-generic/pgtable-nopud.h | 1 unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h | 15 unmodified_drivers/linux-2.6/mkbuildtree | 3 unmodified_drivers/linux-2.6/platform-pci/evtchn.c | 8 unmodified_drivers/linux-2.6/util/Kbuild | 3 unmodified_drivers/linux-2.6/util/Makefile | 3 xen/COPYING | 20 xen/arch/ia64/vmx/mmio.c | 16 xen/arch/ia64/vmx/vlsapic.c | 61 xen/arch/ia64/vmx/vmx_hypercall.c | 2 xen/arch/ia64/vmx/vmx_init.c | 11 xen/arch/ia64/vmx/vmx_process.c | 4 xen/arch/ia64/vmx/vmx_support.c | 25 xen/arch/ia64/xen/dom0_ops.c | 3 xen/arch/ia64/xen/domain.c | 110 xen/arch/ia64/xen/irq.c | 14 xen/arch/ia64/xen/mm.c | 77 xen/arch/ia64/xen/tlb_track.c | 5 xen/arch/ia64/xen/vcpu.c | 7 xen/arch/ia64/xen/xencomm.c | 7 xen/arch/ia64/xen/xensetup.c | 6 xen/arch/powerpc/domain.c | 23 xen/arch/powerpc/domain_build.c | 2 xen/arch/powerpc/mm.c | 8 xen/arch/powerpc/papr/xlate.c | 2 xen/arch/powerpc/setup.c | 9 xen/arch/powerpc/shadow.c | 4 xen/arch/powerpc/usercopy.c | 7 xen/arch/x86/domain.c | 129 xen/arch/x86/domain_build.c | 100 xen/arch/x86/domctl.c | 57 xen/arch/x86/e820.c | 2 xen/arch/x86/extable.c | 2 xen/arch/x86/hvm/hvm.c | 508 xen/arch/x86/hvm/i8254.c | 16 xen/arch/x86/hvm/i8259.c | 295 xen/arch/x86/hvm/instrlen.c | 5 xen/arch/x86/hvm/intercept.c | 93 xen/arch/x86/hvm/io.c | 139 xen/arch/x86/hvm/platform.c | 85 xen/arch/x86/hvm/pmtimer.c | 6 xen/arch/x86/hvm/rtc.c | 30 xen/arch/x86/hvm/svm/intr.c | 80 xen/arch/x86/hvm/svm/svm.c | 245 xen/arch/x86/hvm/svm/vmcb.c | 412 xen/arch/x86/hvm/svm/x86_32/exits.S | 7 xen/arch/x86/hvm/svm/x86_64/exits.S | 11 xen/arch/x86/hvm/vioapic.c | 988 - xen/arch/x86/hvm/vlapic.c | 737 xen/arch/x86/hvm/vmx/io.c | 48 xen/arch/x86/hvm/vmx/vmcs.c | 479 xen/arch/x86/hvm/vmx/vmx.c | 829 xen/arch/x86/hvm/vmx/x86_32/exits.S | 3 xen/arch/x86/hvm/vmx/x86_64/exits.S | 3 xen/arch/x86/io_apic.c | 3 xen/arch/x86/irq.c | 13 xen/arch/x86/mm.c | 33 xen/arch/x86/mm/shadow/common.c | 152 xen/arch/x86/mm/shadow/multi.c | 717 xen/arch/x86/mm/shadow/private.h | 117 xen/arch/x86/mm/shadow/types.h | 96 xen/arch/x86/oprofile/xenoprof.c | 2 xen/arch/x86/platform_hypercall.c | 2 xen/arch/x86/setup.c | 11 xen/arch/x86/traps.c | 114 xen/arch/x86/x86_32/asm-offsets.c | 1 xen/arch/x86/x86_32/domain_page.c | 2 xen/arch/x86/x86_32/seg_fixup.c | 50 xen/arch/x86/x86_32/traps.c | 16 xen/arch/x86/x86_64/asm-offsets.c | 1 xen/arch/x86/x86_64/traps.c | 24 xen/arch/x86/x86_emulate.c | 12 xen/common/domain.c | 99 xen/common/domctl.c | 44 xen/common/event_channel.c | 3 xen/common/grant_table.c | 93 xen/common/keyhandler.c | 4 xen/common/lib.c | 17 xen/common/memory.c | 303 xen/common/multicall.c | 2 xen/common/page_alloc.c | 7 xen/common/perfc.c | 13 xen/common/sched_credit.c | 520 xen/common/sched_sedf.c | 44 xen/common/schedule.c | 27 xen/common/trace.c | 2 xen/common/xmalloc.c | 90 xen/drivers/char/console.c | 260 xen/include/asm-ia64/config.h | 7 xen/include/asm-ia64/debugger.h | 1 xen/include/asm-ia64/mm.h | 2 xen/include/asm-ia64/vlsapic.h | 1 xen/include/asm-ia64/vmx.h | 2 xen/include/asm-ia64/vmx_platform.h | 6 xen/include/asm-ia64/vmx_vpd.h | 1 xen/include/asm-powerpc/powerpc64/config.h | 6 xen/include/asm-x86/bitops.h | 58 xen/include/asm-x86/config.h | 7 xen/include/asm-x86/grant_table.h | 4 xen/include/asm-x86/hvm/domain.h | 12 xen/include/asm-x86/hvm/hvm.h | 31 xen/include/asm-x86/hvm/io.h | 18 xen/include/asm-x86/hvm/support.h | 17 xen/include/asm-x86/hvm/svm/vmcb.h | 24 xen/include/asm-x86/hvm/vcpu.h | 5 xen/include/asm-x86/hvm/vioapic.h | 113 xen/include/asm-x86/hvm/vlapic.h | 116 xen/include/asm-x86/hvm/vmx/vmcs.h | 6 xen/include/asm-x86/hvm/vmx/vmx.h | 178 xen/include/asm-x86/hvm/vpic.h | 39 xen/include/asm-x86/hvm/vpt.h | 1 xen/include/asm-x86/mm.h | 9 xen/include/asm-x86/page.h | 12 xen/include/asm-x86/perfc_defn.h | 3 xen/include/asm-x86/processor.h | 2 xen/include/asm-x86/regs.h | 2 xen/include/asm-x86/shadow.h | 70 xen/include/asm-x86/x86_32/page-2level.h | 3 xen/include/asm-x86/x86_32/page-3level.h | 11 xen/include/asm-x86/x86_64/page.h | 3 xen/include/public/COPYING | 16 xen/include/public/acm.h | 18 xen/include/public/acm_ops.h | 18 xen/include/public/arch-ia64.h | 19 xen/include/public/arch-x86_32.h | 21 xen/include/public/arch-x86_64.h | 27 xen/include/public/callback.h | 18 xen/include/public/dom0_ops.h | 18 xen/include/public/domctl.h | 63 xen/include/public/elfnote.h | 18 xen/include/public/event_channel.h | 18 xen/include/public/features.h | 18 xen/include/public/grant_table.h | 18 xen/include/public/hvm/e820.h | 27 xen/include/public/hvm/hvm_info_table.h | 18 xen/include/public/hvm/hvm_op.h | 25 xen/include/public/hvm/ioreq.h | 48 xen/include/public/hvm/params.h | 42 xen/include/public/hvm/vmx_assist.h | 18 xen/include/public/io/blkif.h | 47 xen/include/public/io/console.h | 18 xen/include/public/io/netif.h | 18 xen/include/public/io/pciif.h | 18 xen/include/public/io/ring.h | 18 xen/include/public/io/tpmif.h | 18 xen/include/public/io/xenbus.h | 18 xen/include/public/io/xs_wire.h | 19 xen/include/public/memory.h | 18 xen/include/public/nmi.h | 18 xen/include/public/physdev.h | 20 xen/include/public/platform.h | 18 xen/include/public/sched.h | 18 xen/include/public/sysctl.h | 18 xen/include/public/trace.h | 18 xen/include/public/vcpu.h | 18 xen/include/public/version.h | 18 xen/include/public/xen-compat.h | 18 xen/include/public/xen.h | 18 xen/include/public/xenoprof.h | 18 xen/include/xen/config.h | 74 xen/include/xen/console.h | 3 xen/include/xen/domain.h | 14 xen/include/xen/lib.h | 4 xen/include/xen/sched-if.h | 6 xen/include/xen/sched.h | 61 xen/include/xen/softirq.h | 5 488 files changed, 47189 insertions(+), 11341 deletions(-), 3 modifications(!) diff -r 11b718eb22c9 -r ebed72718263 .hgignore --- a/.hgignore Thu Nov 02 12:43:04 2006 -0700 +++ b/.hgignore Fri Nov 10 11:11:04 2006 -0700 @@ -98,7 +98,7 @@ ^tools/firmware/.*\.bin$ ^tools/firmware/.*\.sym$ ^tools/firmware/.*bios/.*bios.*\.txt$ -^tools/firmware/acpi/acpigen$ +^tools/firmware/hvmloader/acpi/acpigen$ ^tools/firmware/hvmloader/hvmloader$ ^tools/firmware/hvmloader/roms\.h$ ^tools/firmware/rombios/BIOS-bochs-[^/]*$ @@ -123,6 +123,7 @@ ^tools/ioemu/qemu\.1$ ^tools/ioemu/qemu\.pod$ ^tools/libxc/xen/.*$ +^tools/libxen/test/test_bindings$ ^tools/libaio/src/.*\.ol$ ^tools/libaio/src/.*\.os$ ^tools/misc/cpuperf/cpuperf-perfcntr$ diff -r 11b718eb22c9 -r ebed72718263 buildconfigs/linux-defconfig_xen0_ia64 --- a/buildconfigs/linux-defconfig_xen0_ia64 Thu Nov 02 12:43:04 2006 -0700 +++ b/buildconfigs/linux-defconfig_xen0_ia64 Fri Nov 10 11:11:04 2006 -0700 @@ -1529,7 +1529,7 @@ CONFIG_XEN_XENBUS_DEV=y CONFIG_XEN_XENBUS_DEV=y CONFIG_XEN_BACKEND=y CONFIG_XEN_BLKDEV_BACKEND=y -# CONFIG_XEN_BLKDEV_TAP is not set +CONFIG_XEN_BLKDEV_TAP=y CONFIG_XEN_NETDEV_BACKEND=y # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set CONFIG_XEN_NETDEV_LOOPBACK=y diff -r 11b718eb22c9 -r ebed72718263 buildconfigs/linux-defconfig_xen_ia64 --- a/buildconfigs/linux-defconfig_xen_ia64 Thu Nov 02 12:43:04 2006 -0700 +++ b/buildconfigs/linux-defconfig_xen_ia64 Fri Nov 10 11:11:04 2006 -0700 @@ -1535,7 +1535,7 @@ CONFIG_XEN_XENBUS_DEV=y CONFIG_XEN_XENBUS_DEV=y CONFIG_XEN_BACKEND=y CONFIG_XEN_BLKDEV_BACKEND=y -# CONFIG_XEN_BLKDEV_TAP is not set +CONFIG_XEN_BLKDEV_TAP=y CONFIG_XEN_NETDEV_BACKEND=y # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set CONFIG_XEN_NETDEV_LOOPBACK=y diff -r 11b718eb22c9 -r ebed72718263 config/SunOS.mk --- a/config/SunOS.mk Thu Nov 02 12:43:04 2006 -0700 +++ b/config/SunOS.mk Fri Nov 10 11:11:04 2006 -0700 @@ -21,7 +21,7 @@ SOCKET_LIBS = -lsocket SOCKET_LIBS = -lsocket CURSES_LIBS = -lcurses SONAME_LDFLAG = -h -SHLIB_CFLAGS = -static-libgcc -shared +SHLIB_CFLAGS = -R /usr/sfw/$(LIBDIR) -shared ifneq ($(debug),y) # Optimisation flags are overridable diff -r 11b718eb22c9 -r ebed72718263 docs/src/user.tex --- a/docs/src/user.tex Thu Nov 02 12:43:04 2006 -0700 +++ b/docs/src/user.tex Fri Nov 10 11:11:04 2006 -0700 @@ -3192,6 +3192,15 @@ editing \path{grub.conf}. input to DOM0 when it boots --- if it is `x' then auto-switching is disabled. Any other value, or omitting the character, enables auto-switching. [NB. Default switch-char is `a'.] +\item [ loglvl=$<$level$>/<$level$>$ ] + Specify logging level. Messages of the specified severity level (and + higher) will be printed to the Xen console. Valid levels are `none', + `error', `warning', `info', `debug', and `all'. The second level + specifier is optional: it is used to specify message severities + which are to be rate limited. Default is `loglvl=warning'. +\item [ guest\_loglvl=$<$level$>/<$level$>$ ] As for loglvl, but + applies to messages relating to guests. Default is + `guest\_loglvl=none/warning'. \item [ nmi=xxx ] Specify what to do with an NMI parity or I/O error. \\ `nmi=fatal': Xen prints a diagnostic and then hangs. \\ @@ -3202,12 +3211,21 @@ editing \path{grub.conf}. ignored. This parameter may be specified with a B, K, M or G suffix, representing bytes, kilobytes, megabytes and gigabytes respectively. The default unit, if no suffix is specified, is kilobytes. -\item [ dom0\_mem=xxx ] Set the amount of memory to be allocated to - domain0. In Xen 3.x the parameter may be specified with a B, K, M or +\item [ dom0\_mem=$<$specifier list$>$ ] Set the amount of memory to + be allocated to domain 0. This is a comma-separated list containing + the following optional components: + \begin{description} + \item[ min:$<$min\_amt$>$ ] Minimum amount to allocate to domain 0 + \item[ max:$<$min\_amt$>$ ] Maximum amount to allocate to domain 0 + \item[ $<$amt$>$ ] Precise amount to allocate to domain 0 + \end{description} + Each numeric parameter may be specified with a B, K, M or G suffix, representing bytes, kilobytes, megabytes and gigabytes respectively; if no suffix is specified, the parameter defaults to - kilobytes. In previous versions of Xen, suffixes were not supported - and the value is always interpreted as kilobytes. + kilobytes. Negative values are subtracted from total available + memory. If $<$amt$>$ is not specified, it defaults to all available + memory less a small amount (clamped to 128MB) for uses such as DMA + buffers. \item [ dom0\_vcpus\_pin ] Pins domain 0 VCPUs on their respective physical CPUS (default=false). \item [ tbuf\_size=xxx ] Set the size of the per-cpu trace buffers, in diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c Fri Nov 10 11:11:04 2006 -0700 @@ -60,7 +60,7 @@ int __init sysenter_setup(void) #ifdef CONFIG_XEN if (boot_cpu_has(X86_FEATURE_SEP)) { - struct callback_register sysenter = { + static struct callback_register __initdata sysenter = { .type = CALLBACKTYPE_sysenter, .address = { __KERNEL_CS, (unsigned long)sysenter_entry }, }; diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c --- a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c Fri Nov 10 11:11:04 2006 -0700 @@ -325,6 +325,7 @@ int xen_create_contiguous_region( success = (exchange.nr_exchanged == (1UL << order)); BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0))); BUG_ON(success && (rc != 0)); +#ifdef CONFIG_XEN_COMPAT_030002 if (unlikely(rc == -ENOSYS)) { /* Compatibility when XENMEM_exchange is unsupported. */ if (HYPERVISOR_memory_op(XENMEM_decrease_reservation, @@ -341,6 +342,7 @@ int xen_create_contiguous_region( BUG(); } } +#endif /* 3. Map the new extent in place of old pages. */ for (i = 0; i < (1UL<<order); i++) { @@ -419,6 +421,7 @@ void xen_destroy_contiguous_region(unsig success = (exchange.nr_exchanged == 1); BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0))); BUG_ON(success && (rc != 0)); +#ifdef CONFIG_XEN_COMPAT_030002 if (unlikely(rc == -ENOSYS)) { /* Compatibility when XENMEM_exchange is unsupported. */ if (HYPERVISOR_memory_op(XENMEM_decrease_reservation, @@ -429,6 +432,7 @@ void xen_destroy_contiguous_region(unsig BUG(); success = 1; } +#endif /* 4. Map new pages in place of old pages. */ for (i = 0; i < (1UL<<order); i++) { diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/arch/i386/mm/init-xen.c --- a/linux-2.6-xen-sparse/arch/i386/mm/init-xen.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/mm/init-xen.c Fri Nov 10 11:11:04 2006 -0700 @@ -663,8 +663,8 @@ void __init mem_init(void) totalram_pages += free_all_bootmem(); /* XEN: init and count low-mem pages outside initial allocation. */ for (pfn = xen_start_info->nr_pages; pfn < max_low_pfn; pfn++) { - ClearPageReserved(&mem_map[pfn]); - set_page_count(&mem_map[pfn], 1); + ClearPageReserved(pfn_to_page(pfn)); + set_page_count(pfn_to_page(pfn), 1); totalram_pages++; } diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/arch/ia64/xen/xencomm.c --- a/linux-2.6-xen-sparse/arch/ia64/xen/xencomm.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xencomm.c Fri Nov 10 11:11:04 2006 -0700 @@ -20,6 +20,11 @@ #include <linux/mm.h> #include <xen/interface/xen.h> #include <asm/page.h> + +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif + #include <asm/xen/xencomm.h> static int xencomm_debug = 0; diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c Fri Nov 10 11:11:04 2006 -0700 @@ -913,8 +913,8 @@ void __init mem_init(void) #endif /* XEN: init and count pages outside initial allocation. */ for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) { - ClearPageReserved(&mem_map[pfn]); - set_page_count(&mem_map[pfn], 1); + ClearPageReserved(pfn_to_page(pfn)); + set_page_count(pfn_to_page(pfn), 1); totalram_pages++; } reservedpages = end_pfn - totalram_pages - e820_hole_size(0, end_pfn); diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c Fri Nov 10 11:11:04 2006 -0700 @@ -41,6 +41,7 @@ #include <xen/evtchn.h> #include <xen/interface/grant_table.h> #include <xen/interface/io/tpmif.h> +#include <xen/gnttab.h> #include <xen/xenbus.h> #include "tpm.h" #include "tpm_vtpm.h" diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Fri Nov 10 11:11:04 2006 -0700 @@ -189,9 +189,9 @@ static void fast_flush_area(pending_req_ static void print_stats(blkif_t *blkif) { - printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d\n", + printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d | br %4d\n", current->comm, blkif->st_oo_req, - blkif->st_rd_req, blkif->st_wr_req); + blkif->st_rd_req, blkif->st_wr_req, blkif->st_br_req); blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000); blkif->st_rd_req = 0; blkif->st_wr_req = 0; @@ -241,11 +241,17 @@ int blkif_schedule(void *arg) * COMPLETION CALLBACK -- Called as bh->b_end_io() */ -static void __end_block_io_op(pending_req_t *pending_req, int uptodate) +static void __end_block_io_op(pending_req_t *pending_req, int error) { /* An error fails the entire request. */ - if (!uptodate) { - DPRINTK("Buffer not up-to-date at end of operation\n"); + if ((pending_req->operation == BLKIF_OP_WRITE_BARRIER) && + (error == -EOPNOTSUPP)) { + DPRINTK("blkback: write barrier op failed, not supported\n"); + blkback_barrier(XBT_NIL, pending_req->blkif->be, 0); + pending_req->status = BLKIF_RSP_EOPNOTSUPP; + } else if (error) { + DPRINTK("Buffer not up-to-date at end of operation, " + "error=%d\n", error); pending_req->status = BLKIF_RSP_ERROR; } @@ -262,7 +268,7 @@ static int end_block_io_op(struct bio *b { if (bio->bi_size != 0) return 1; - __end_block_io_op(bio->bi_private, !error); + __end_block_io_op(bio->bi_private, error); bio_put(bio); return error; } @@ -319,6 +325,9 @@ static int do_block_io_op(blkif_t *blkif blkif->st_rd_req++; dispatch_rw_block_io(blkif, &req, pending_req); break; + case BLKIF_OP_WRITE_BARRIER: + blkif->st_br_req++; + /* fall through */ case BLKIF_OP_WRITE: blkif->st_wr_req++; dispatch_rw_block_io(blkif, &req, pending_req); @@ -340,7 +349,6 @@ static void dispatch_rw_block_io(blkif_t pending_req_t *pending_req) { extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]); - int operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ; struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST]; struct phys_req preq; struct { @@ -349,6 +357,22 @@ static void dispatch_rw_block_io(blkif_t unsigned int nseg; struct bio *bio = NULL, *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST]; int ret, i, nbio = 0; + int operation; + + switch (req->operation) { + case BLKIF_OP_READ: + operation = READ; + break; + case BLKIF_OP_WRITE: + operation = WRITE; + break; + case BLKIF_OP_WRITE_BARRIER: + operation = WRITE_BARRIER; + break; + default: + operation = 0; /* make gcc happy */ + BUG(); + } /* Check that number of segments is sane. */ nseg = req->nr_segments; @@ -364,7 +388,7 @@ static void dispatch_rw_block_io(blkif_t pending_req->blkif = blkif; pending_req->id = req->id; - pending_req->operation = operation; + pending_req->operation = req->operation; pending_req->status = BLKIF_RSP_OKAY; pending_req->nr_pages = nseg; @@ -380,7 +404,7 @@ static void dispatch_rw_block_io(blkif_t preq.nr_sects += seg[i].nsec; flags = GNTMAP_host_map; - if ( operation == WRITE ) + if (operation != READ) flags |= GNTMAP_readonly; gnttab_set_map_op(&map[i], vaddr(pending_req, i), flags, req->seg[i].gref, blkif->domid); diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/blkback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Fri Nov 10 11:11:04 2006 -0700 @@ -44,6 +44,7 @@ #include <xen/interface/io/ring.h> #include <xen/gnttab.h> #include <xen/driver_util.h> +#include <xen/xenbus.h> #define DPRINTK(_f, _a...) \ pr_debug("(file=%s, line=%d) " _f, \ @@ -87,6 +88,7 @@ typedef struct blkif_st { int st_rd_req; int st_wr_req; int st_oo_req; + int st_br_req; wait_queue_head_t waiting_to_free; @@ -131,4 +133,7 @@ irqreturn_t blkif_be_int(int irq, void * irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs); int blkif_schedule(void *arg); +int blkback_barrier(struct xenbus_transaction xbt, + struct backend_info *be, int state); + #endif /* __BLKIF__BACKEND__COMMON_H__ */ diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c Fri Nov 10 11:11:04 2006 -0700 @@ -31,7 +31,6 @@ */ #include "common.h" -#include <xen/xenbus.h> #define vbd_sz(_v) ((_v)->bdev->bd_part ? \ (_v)->bdev->bd_part->nr_sects : (_v)->bdev->bd_disk->capacity) @@ -104,7 +103,7 @@ int vbd_translate(struct phys_req *req, struct vbd *vbd = &blkif->vbd; int rc = -EACCES; - if ((operation == WRITE) && vbd->readonly) + if ((operation != READ) && vbd->readonly) goto out; if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd))) diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Fri Nov 10 11:11:04 2006 -0700 @@ -20,7 +20,6 @@ #include <stdarg.h> #include <linux/module.h> #include <linux/kthread.h> -#include <xen/xenbus.h> #include "common.h" #undef DPRINTK @@ -91,11 +90,13 @@ VBD_SHOW(oo_req, "%d\n", be->blkif->st_o VBD_SHOW(oo_req, "%d\n", be->blkif->st_oo_req); VBD_SHOW(rd_req, "%d\n", be->blkif->st_rd_req); VBD_SHOW(wr_req, "%d\n", be->blkif->st_wr_req); +VBD_SHOW(br_req, "%d\n", be->blkif->st_br_req); static struct attribute *vbdstat_attrs[] = { &dev_attr_oo_req.attr, &dev_attr_rd_req.attr, &dev_attr_wr_req.attr, + &dev_attr_br_req.attr, NULL }; @@ -165,6 +166,19 @@ static int blkback_remove(struct xenbus_ return 0; } +int blkback_barrier(struct xenbus_transaction xbt, + struct backend_info *be, int state) +{ + struct xenbus_device *dev = be->dev; + int err; + + err = xenbus_printf(xbt, dev->nodename, "feature-barrier", + "%d", state); + if (err) + xenbus_dev_fatal(dev, err, "writing feature-barrier"); + + return err; +} /** * Entry point to this code when a new device is created. Allocate the basic @@ -366,11 +380,14 @@ static void connect(struct backend_info /* Supply the information about the device the frontend needs */ again: err = xenbus_transaction_start(&xbt); - if (err) { xenbus_dev_fatal(dev, err, "starting transaction"); return; } + + err = blkback_barrier(xbt, be, 1); + if (err) + goto abort; err = xenbus_printf(xbt, dev->nodename, "sectors", "%lu", vbd_size(&be->blkif->vbd)); diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Fri Nov 10 11:11:04 2006 -0700 @@ -320,6 +320,12 @@ static void connect(struct blkfront_info return; } + err = xenbus_gather(XBT_NIL, info->xbdev->otherend, + "feature-barrier", "%lu", &info->feature_barrier, + NULL); + if (err) + info->feature_barrier = 0; + err = xlvbd_add(sectors, info->vdevice, binfo, sector_size, info); if (err) { xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s", @@ -569,10 +575,13 @@ static int blkif_queue_request(struct re info->shadow[id].request = (unsigned long)req; ring_req->id = id; + ring_req->sector_number = (blkif_sector_t)req->sector; + ring_req->handle = info->handle; + ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE : BLKIF_OP_READ; - ring_req->sector_number = (blkif_sector_t)req->sector; - ring_req->handle = info->handle; + if (blk_barrier_rq(req)) + ring_req->operation = BLKIF_OP_WRITE_BARRIER; ring_req->nr_segments = 0; rq_for_each_bio (bio, req) { @@ -670,6 +679,7 @@ static irqreturn_t blkif_int(int irq, vo RING_IDX i, rp; unsigned long flags; struct blkfront_info *info = (struct blkfront_info *)dev_id; + int uptodate; spin_lock_irqsave(&blkif_io_lock, flags); @@ -694,19 +704,27 @@ static irqreturn_t blkif_int(int irq, vo ADD_ID_TO_FREELIST(info, id); + uptodate = (bret->status == BLKIF_RSP_OKAY); switch (bret->operation) { + case BLKIF_OP_WRITE_BARRIER: + if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { + printk("blkfront: %s: write barrier op failed\n", + info->gd->disk_name); + uptodate = -EOPNOTSUPP; + info->feature_barrier = 0; + xlvbd_barrier(info); + } + /* fall through */ case BLKIF_OP_READ: case BLKIF_OP_WRITE: if (unlikely(bret->status != BLKIF_RSP_OKAY)) DPRINTK("Bad return from blkdev data " "request: %x\n", bret->status); - ret = end_that_request_first( - req, (bret->status == BLKIF_RSP_OKAY), + ret = end_that_request_first(req, uptodate, req->hard_nr_sectors); BUG_ON(ret); - end_that_request_last( - req, (bret->status == BLKIF_RSP_OKAY)); + end_that_request_last(req, uptodate); break; default: BUG(); diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/blkfront/block.h --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Fri Nov 10 11:11:04 2006 -0700 @@ -126,6 +126,7 @@ struct blkfront_info struct gnttab_free_callback callback; struct blk_shadow shadow[BLK_RING_SIZE]; unsigned long shadow_free; + int feature_barrier; /** * The number of people holding this device open. We won't allow a @@ -152,5 +153,6 @@ int xlvbd_add(blkif_sector_t capacity, i int xlvbd_add(blkif_sector_t capacity, int device, u16 vdisk_info, u16 sector_size, struct blkfront_info *info); void xlvbd_del(struct blkfront_info *info); +int xlvbd_barrier(struct blkfront_info *info); #endif /* __XEN_DRIVERS_BLOCK_H__ */ diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Fri Nov 10 11:11:04 2006 -0700 @@ -50,7 +50,7 @@ */ #define NUM_IDE_MAJORS 10 -#define NUM_SCSI_MAJORS 9 +#define NUM_SCSI_MAJORS 17 #define NUM_VBD_MAJORS 1 static struct xlbd_type_info xlbd_ide_type = { @@ -165,8 +165,11 @@ xlbd_get_major_info(int vdevice) case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR: index = 11 + major - SCSI_DISK1_MAJOR; break; - case SCSI_CDROM_MAJOR: index = 18; break; - default: index = 19; break; + case SCSI_DISK8_MAJOR ... SCSI_DISK15_MAJOR: + index = 18 + major - SCSI_DISK8_MAJOR; + break; + case SCSI_CDROM_MAJOR: index = 26; break; + default: index = 27; break; } mi = ((major_info[index] != NULL) ? major_info[index] : @@ -227,6 +230,7 @@ xlvbd_alloc_gendisk(int minor, blkif_sec struct xlbd_major_info *mi; int nr_minors = 1; int err = -ENODEV; + unsigned int offset; BUG_ON(info->gd != NULL); BUG_ON(info->mi != NULL); @@ -244,15 +248,33 @@ xlvbd_alloc_gendisk(int minor, blkif_sec if (gd == NULL) goto out; - if (nr_minors > 1) - sprintf(gd->disk_name, "%s%c", mi->type->diskname, - 'a' + mi->index * mi->type->disks_per_major + - (minor >> mi->type->partn_shift)); - else - sprintf(gd->disk_name, "%s%c%d", mi->type->diskname, - 'a' + mi->index * mi->type->disks_per_major + - (minor >> mi->type->partn_shift), - minor & ((1 << mi->type->partn_shift) - 1)); + offset = mi->index * mi->type->disks_per_major + + (minor >> mi->type->partn_shift); + if (nr_minors > 1) { + if (offset < 26) { + sprintf(gd->disk_name, "%s%c", + mi->type->diskname, 'a' + offset ); + } + else { + sprintf(gd->disk_name, "%s%c%c", + mi->type->diskname, + 'a' + ((offset/26)-1), 'a' + (offset%26) ); + } + } + else { + if (offset < 26) { + sprintf(gd->disk_name, "%s%c%d", + mi->type->diskname, + 'a' + offset, + minor & ((1 << mi->type->partn_shift) - 1)); + } + else { + sprintf(gd->disk_name, "%s%c%c%d", + mi->type->diskname, + 'a' + ((offset/26)-1), 'a' + (offset%26), + minor & ((1 << mi->type->partn_shift) - 1)); + } + } gd->major = mi->major; gd->first_minor = minor; @@ -267,6 +289,10 @@ xlvbd_alloc_gendisk(int minor, blkif_sec } info->rq = gd->queue; + info->gd = gd; + + if (info->feature_barrier) + xlvbd_barrier(info); if (vdisk_info & VDISK_READONLY) set_disk_ro(gd, 1); @@ -276,8 +302,6 @@ xlvbd_alloc_gendisk(int minor, blkif_sec if (vdisk_info & VDISK_CDROM) gd->flags |= GENHD_FL_CD; - - info->gd = gd; return 0; @@ -326,3 +350,26 @@ xlvbd_del(struct blkfront_info *info) blk_cleanup_queue(info->rq); info->rq = NULL; } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) +int +xlvbd_barrier(struct blkfront_info *info) +{ + int err; + + err = blk_queue_ordered(info->rq, + info->feature_barrier ? QUEUE_ORDERED_DRAIN : QUEUE_ORDERED_NONE, NULL); + if (err) + return err; + printk("blkfront: %s: barriers %s\n", + info->gd->disk_name, info->feature_barrier ? "enabled" : "disabled"); + return 0; +} +#else +int +xlvbd_barrier(struct blkfront_info *info) +{ + printk("blkfront: %s: barriers disabled\n", info->gd->disk_name); + return -ENOSYS; +} +#endif diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c --- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c Fri Nov 10 11:11:04 2006 -0700 @@ -93,8 +93,9 @@ int setup_xen_class(void) * mmap_alloc is initialised to 2 and should be adjustable on the fly via * sysfs. */ -#define MAX_DYNAMIC_MEM 64 -#define MAX_PENDING_REQS 64 +#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE) +#define MAX_DYNAMIC_MEM BLK_RING_SIZE +#define MAX_PENDING_REQS BLK_RING_SIZE #define MMAP_PAGES (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST) #define MMAP_VADDR(_start, _req,_seg) \ (_start + \ @@ -215,6 +216,7 @@ struct grant_handle_pair grant_handle_t kernel; grant_handle_t user; }; +#define INVALID_GRANT_HANDLE 0xFFFF static struct grant_handle_pair pending_grant_handles[MAX_DYNAMIC_MEM][MMAP_PAGES]; @@ -293,10 +295,11 @@ static inline int GET_NEXT_REQ(unsigned #define BLKTAP_INVALID_HANDLE(_g) \ - (((_g->kernel) == 0xFFFF) && ((_g->user) == 0xFFFF)) + (((_g->kernel) == INVALID_GRANT_HANDLE) && \ + ((_g->user) == INVALID_GRANT_HANDLE)) #define BLKTAP_INVALIDATE_HANDLE(_g) do { \ - (_g)->kernel = 0xFFFF; (_g)->user = 0xFFFF; \ + (_g)->kernel = INVALID_GRANT_HANDLE; (_g)->user = INVALID_GRANT_HANDLE; \ } while(0) @@ -535,8 +538,10 @@ static int blktap_release(struct inode * } if ( (info->status != CLEANSHUTDOWN) && (info->blkif != NULL) ) { - kthread_stop(info->blkif->xenblkd); - info->blkif->xenblkd = NULL; + if (info->blkif->xenblkd != NULL) { + kthread_stop(info->blkif->xenblkd); + info->blkif->xenblkd = NULL; + } info->status = CLEANSHUTDOWN; } return 0; @@ -588,8 +593,6 @@ static int blktap_mmap(struct file *filp info->user_vstart = info->rings_vstart + (RING_PAGES << PAGE_SHIFT); /* Map the ring pages to the start of the region and reserve it. */ - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - if (remap_pfn_range(vma, vma->vm_start, __pa(info->ufe_ring.sring) >> PAGE_SHIFT, PAGE_SIZE, vma->vm_page_prot)) { @@ -884,6 +887,15 @@ static void fast_flush_area(pending_req_ return; } + if (info->vma != NULL && + xen_feature(XENFEAT_auto_translated_physmap)) { + down_write(&info->vma->vm_mm->mmap_sem); + zap_page_range(info->vma, + MMAP_VADDR(info->user_vstart, u_idx, 0), + req->nr_pages << PAGE_SHIFT, NULL); + up_write(&info->vma->vm_mm->mmap_sem); + } + mmap_idx = req->mem_idx; for (i = 0; i < req->nr_pages; i++) { @@ -892,14 +904,15 @@ static void fast_flush_area(pending_req_ khandle = &pending_handle(mmap_idx, k_idx, i); - if (khandle->kernel != 0xFFFF) { + if (khandle->kernel != INVALID_GRANT_HANDLE) { gnttab_set_unmap_op(&unmap[invcount], idx_to_kaddr(mmap_idx, k_idx, i), GNTMAP_host_map, khandle->kernel); invcount++; } - if (khandle->user != 0xFFFF) { + if (khandle->user != INVALID_GRANT_HANDLE) { + BUG_ON(xen_feature(XENFEAT_auto_translated_physmap)); if (create_lookup_pte_addr( info->vma->vm_mm, MMAP_VADDR(info->user_vstart, u_idx, i), @@ -908,8 +921,10 @@ static void fast_flush_area(pending_req_ return; } - gnttab_set_unmap_op(&unmap[invcount], - ptep, GNTMAP_host_map, + gnttab_set_unmap_op(&unmap[invcount], ptep, + GNTMAP_host_map + | GNTMAP_application_map + | GNTMAP_contains_pte, khandle->user); invcount++; } @@ -920,7 +935,7 @@ static void fast_flush_area(pending_req_ GNTTABOP_unmap_grant_ref, unmap, invcount); BUG_ON(ret); - if (info->vma != NULL) + if (info->vma != NULL && !xen_feature(XENFEAT_auto_translated_physmap)) zap_page_range(info->vma, MMAP_VADDR(info->user_vstart, u_idx, 0), req->nr_pages << PAGE_SHIFT, NULL); @@ -1004,11 +1019,14 @@ static int blktap_read_ufe_ring(tap_blki rmb(); for (i = info->ufe_ring.rsp_cons; i != rp; i++) { + blkif_response_t res; resp = RING_GET_RESPONSE(&info->ufe_ring, i); + memcpy(&res, resp, sizeof(res)); + mb(); /* rsp_cons read by RING_FULL() in do_block_io_op(). */ ++info->ufe_ring.rsp_cons; /*retrieve [usr_idx] to [mmap_idx,pending_idx] mapping*/ - usr_idx = (int)resp->id; + usr_idx = (int)res.id; pending_idx = MASK_PEND_IDX(ID_TO_IDX(info->idx_map[usr_idx])); mmap_idx = ID_TO_MIDX(info->idx_map[usr_idx]); @@ -1041,8 +1059,8 @@ static int blktap_read_ufe_ring(tap_blki map[offset] = NULL; } fast_flush_area(pending_req, pending_idx, usr_idx, info->minor); - make_response(blkif, pending_req->id, resp->operation, - resp->status); + make_response(blkif, pending_req->id, res.operation, + res.status); info->idx_map[usr_idx] = INVALID_REQ; blkif_put(pending_req->blkif); free_req(pending_req); @@ -1184,8 +1202,10 @@ static void dispatch_rw_block_io(blkif_t /* Check we have space on user ring - should never fail. */ usr_idx = GET_NEXT_REQ(info->idx_map); - if (usr_idx == INVALID_REQ) + if (usr_idx == INVALID_REQ) { + BUG(); goto fail_response; + } /* Check that number of segments is sane. */ nseg = req->nr_segments; @@ -1219,14 +1239,12 @@ static void dispatch_rw_block_io(blkif_t unsigned long uvaddr; unsigned long kvaddr; uint64_t ptep; - struct page *page; uint32_t flags; uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i); kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i); - page = virt_to_page(kvaddr); - - sector = req->sector_number + (8*i); + + sector = req->sector_number + ((PAGE_SIZE / 512) * i); if( (blkif->sectors > 0) && (sector >= blkif->sectors) ) { WPRINTK("BLKTAP: Sector request greater" "than size\n"); @@ -1236,7 +1254,7 @@ static void dispatch_rw_block_io(blkif_t BLKIF_OP_WRITE ? "WRITE" : "READ"), (long long unsigned) sector, (long long unsigned) sector>>9, - blkif->sectors); + (long long unsigned) blkif->sectors); } flags = GNTMAP_host_map; @@ -1246,68 +1264,103 @@ static void dispatch_rw_block_io(blkif_t req->seg[i].gref, blkif->domid); op++; - /* Now map it to user. */ - ret = create_lookup_pte_addr(info->vma->vm_mm, - uvaddr, &ptep); - if (ret) { - WPRINTK("Couldn't get a pte addr!\n"); - goto fail_flush; - } - - flags = GNTMAP_host_map | GNTMAP_application_map - | GNTMAP_contains_pte; - if (operation == WRITE) - flags |= GNTMAP_readonly; - gnttab_set_map_op(&map[op], ptep, flags, - req->seg[i].gref, blkif->domid); - op++; + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + /* Now map it to user. */ + ret = create_lookup_pte_addr(info->vma->vm_mm, + uvaddr, &ptep); + if (ret) { + WPRINTK("Couldn't get a pte addr!\n"); + goto fail_flush; + } + + flags = GNTMAP_host_map | GNTMAP_application_map + | GNTMAP_contains_pte; + if (operation == WRITE) + flags |= GNTMAP_readonly; + gnttab_set_map_op(&map[op], ptep, flags, + req->seg[i].gref, blkif->domid); + op++; + } } ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, op); BUG_ON(ret); - for (i = 0; i < (nseg*2); i+=2) { - unsigned long uvaddr; - unsigned long kvaddr; - unsigned long offset; - struct page *pg; - - uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i/2); - kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i/2); - - if (unlikely(map[i].status != 0)) { - WPRINTK("invalid kernel buffer -- " - "could not remap it\n"); - ret |= 1; - map[i].handle = 0xFFFF; - } - - if (unlikely(map[i+1].status != 0)) { - WPRINTK("invalid user buffer -- " - "could not remap it\n"); - ret |= 1; - map[i+1].handle = 0xFFFF; - } - - pending_handle(mmap_idx, pending_idx, i/2).kernel - = map[i].handle; - pending_handle(mmap_idx, pending_idx, i/2).user - = map[i+1].handle; - - if (ret) - continue; - - set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT, - FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT)); - offset = (uvaddr - info->vma->vm_start) >> PAGE_SHIFT; - pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); - ((struct page **)info->vma->vm_private_data)[offset] = - pg; + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + for (i = 0; i < (nseg*2); i+=2) { + unsigned long uvaddr; + unsigned long kvaddr; + unsigned long offset; + struct page *pg; + + uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i/2); + kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i/2); + + if (unlikely(map[i].status != 0)) { + WPRINTK("invalid kernel buffer -- " + "could not remap it\n"); + ret |= 1; + map[i].handle = INVALID_GRANT_HANDLE; + } + + if (unlikely(map[i+1].status != 0)) { + WPRINTK("invalid user buffer -- " + "could not remap it\n"); + ret |= 1; + map[i+1].handle = INVALID_GRANT_HANDLE; + } + + pending_handle(mmap_idx, pending_idx, i/2).kernel + = map[i].handle; + pending_handle(mmap_idx, pending_idx, i/2).user + = map[i+1].handle; + + if (ret) + continue; + + set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT, + FOREIGN_FRAME(map[i].dev_bus_addr + >> PAGE_SHIFT)); + offset = (uvaddr - info->vma->vm_start) >> PAGE_SHIFT; + pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); + ((struct page **)info->vma->vm_private_data)[offset] = + pg; + } + } else { + for (i = 0; i < nseg; i++) { + unsigned long uvaddr; + unsigned long kvaddr; + unsigned long offset; + struct page *pg; + + uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i); + kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i); + + if (unlikely(map[i].status != 0)) { + WPRINTK("invalid kernel buffer -- " + "could not remap it\n"); + ret |= 1; + map[i].handle = INVALID_GRANT_HANDLE; + } + + pending_handle(mmap_idx, pending_idx, i).kernel + = map[i].handle; + + if (ret) + continue; + + offset = (uvaddr - info->vma->vm_start) >> PAGE_SHIFT; + pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); + ((struct page **)info->vma->vm_private_data)[offset] = + pg; + } } if (ret) goto fail_flush; + if (xen_feature(XENFEAT_auto_translated_physmap)) + down_write(&info->vma->vm_mm->mmap_sem); /* Mark mapped pages as reserved: */ for (i = 0; i < req->nr_segments; i++) { unsigned long kvaddr; @@ -1316,7 +1369,18 @@ static void dispatch_rw_block_io(blkif_t kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i); pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); SetPageReserved(pg); - } + if (xen_feature(XENFEAT_auto_translated_physmap)) { + ret = vm_insert_page(info->vma, + MMAP_VADDR(info->user_vstart, + usr_idx, i), pg); + if (ret) { + up_write(&info->vma->vm_mm->mmap_sem); + goto fail_flush; + } + } + } + if (xen_feature(XENFEAT_auto_translated_physmap)) + up_write(&info->vma->vm_mm->mmap_sem); /*record [mmap_idx,pending_idx] to [usr_idx] mapping*/ info->idx_map[usr_idx] = MAKE_ID(mmap_idx, pending_idx); @@ -1327,6 +1391,7 @@ static void dispatch_rw_block_io(blkif_t info->ufe_ring.req_prod_pvt); memcpy(target, req, sizeof(*req)); target->id = usr_idx; + wmb(); /* blktap_poll() reads req_prod_pvt asynchronously */ info->ufe_ring.req_prod_pvt++; return; diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c Fri Nov 10 11:11:04 2006 -0700 @@ -189,7 +189,7 @@ static int blktap_probe(struct xenbus_de return 0; fail: - DPRINTK("blktap probe failed"); + DPRINTK("blktap probe failed\n"); blktap_remove(dev); return err; } @@ -243,7 +243,7 @@ static void tap_frontend_changed(struct struct backend_info *be = dev->dev.driver_data; int err; - DPRINTK(""); + DPRINTK("\n"); switch (frontend_state) { case XenbusStateInitialising: @@ -318,7 +318,7 @@ static int connect_ring(struct backend_i unsigned int evtchn; int err; - DPRINTK("%s", dev->otherend); + DPRINTK("%s\n", dev->otherend); err = xenbus_gather(XBT_NIL, dev->otherend, "ring-ref", "%lu", &ring_ref, "event-channel", "%u", &evtchn, NULL); diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/core/Makefile --- a/linux-2.6-xen-sparse/drivers/xen/core/Makefile Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/core/Makefile Fri Nov 10 11:11:04 2006 -0700 @@ -9,5 +9,5 @@ obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o obj-$(CONFIG_XEN_SKBUFF) += skbuff.o -obj-$(CONFIG_XEN_REBOOT) += reboot.o +obj-$(CONFIG_XEN_REBOOT) += reboot.o machine_reboot.o obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/core/reboot.c --- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Fri Nov 10 11:11:04 2006 -0700 @@ -1,25 +1,15 @@ #define __KERNEL_SYSCALLS__ #include <linux/version.h> #include <linux/kernel.h> -#include <linux/mm.h> #include <linux/unistd.h> #include <linux/module.h> #include <linux/reboot.h> #include <linux/sysrq.h> -#include <linux/stringify.h> -#include <asm/irq.h> -#include <asm/mmu_context.h> -#include <xen/evtchn.h> #include <asm/hypervisor.h> -#include <xen/interface/dom0_ops.h> #include <xen/xenbus.h> -#include <linux/cpu.h> #include <linux/kthread.h> -#include <xen/gnttab.h> -#include <xen/xencons.h> -#include <xen/cpu_hotplug.h> - -extern void ctrl_alt_del(void); + +MODULE_LICENSE("Dual BSD/GPL"); #define SHUTDOWN_INVALID -1 #define SHUTDOWN_POWEROFF 0 @@ -31,185 +21,17 @@ extern void ctrl_alt_del(void); */ #define SHUTDOWN_HALT 4 -#if defined(__i386__) || defined(__x86_64__) - -/* - * Power off function, if any - */ -void (*pm_power_off)(void); -EXPORT_SYMBOL(pm_power_off); - -void machine_emergency_restart(void) -{ - /* We really want to get pending console data out before we die. */ - xencons_force_flush(); - HYPERVISOR_shutdown(SHUTDOWN_reboot); -} - -void machine_restart(char * __unused) -{ - machine_emergency_restart(); -} - -void machine_halt(void) -{ - machine_power_off(); -} - -void machine_power_off(void) -{ - /* We really want to get pending console data out before we die. */ - xencons_force_flush(); - if (pm_power_off) - pm_power_off(); - HYPERVISOR_shutdown(SHUTDOWN_poweroff); -} - -int reboot_thru_bios = 0; /* for dmi_scan.c */ -EXPORT_SYMBOL(machine_restart); -EXPORT_SYMBOL(machine_halt); -EXPORT_SYMBOL(machine_power_off); - -#endif /* defined(__i386__) || defined(__x86_64__) */ - -/****************************************************************************** - * Stop/pickle callback handling. - */ - /* Ignore multiple shutdown requests. */ static int shutting_down = SHUTDOWN_INVALID; + static void __shutdown_handler(void *unused); static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL); -#if defined(__i386__) || defined(__x86_64__) - -/* Ensure we run on the idle task page tables so that we will - switch page tables before running user space. This is needed - on architectures with separate kernel and user page tables - because the user page table pointer is not saved/restored. */ -static void switch_idle_mm(void) -{ - struct mm_struct *mm = current->active_mm; - - if (mm == &init_mm) - return; - - atomic_inc(&init_mm.mm_count); - switch_mm(mm, &init_mm, current); - current->active_mm = &init_mm; - mmdrop(mm); -} - -static void pre_suspend(void) -{ - HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page; - clear_fixmap(FIX_SHARED_INFO); - - xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn); - xen_start_info->console.domU.mfn = - mfn_to_pfn(xen_start_info->console.domU.mfn); -} - -static void post_suspend(void) -{ - int i, j, k, fpp; - extern unsigned long max_pfn; - extern unsigned long *pfn_to_mfn_frame_list_list; - extern unsigned long *pfn_to_mfn_frame_list[]; - - set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info); - - HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); - - memset(empty_zero_page, 0, PAGE_SIZE); - - HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = - virt_to_mfn(pfn_to_mfn_frame_list_list); - - fpp = PAGE_SIZE/sizeof(unsigned long); - for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) { - if ((j % fpp) == 0) { - k++; - pfn_to_mfn_frame_list_list[k] = - virt_to_mfn(pfn_to_mfn_frame_list[k]); - j = 0; - } - pfn_to_mfn_frame_list[k][j] = - virt_to_mfn(&phys_to_machine_mapping[i]); - } - HYPERVISOR_shared_info->arch.max_pfn = max_pfn; -} - -#else /* !(defined(__i386__) || defined(__x86_64__)) */ - -#define switch_idle_mm() ((void)0) -#define mm_pin_all() ((void)0) -#define pre_suspend() ((void)0) -#define post_suspend() ((void)0) - +#ifdef CONFIG_XEN +int __xen_suspend(void); +#else +#define __xen_suspend() (void)0 #endif - -static int __do_suspend(void *ignore) -{ - int err; - - extern void time_resume(void); - - BUG_ON(smp_processor_id() != 0); - BUG_ON(in_interrupt()); - -#if defined(__i386__) || defined(__x86_64__) - if (xen_feature(XENFEAT_auto_translated_physmap)) { - printk(KERN_WARNING "Cannot suspend in " - "auto_translated_physmap mode.\n"); - return -EOPNOTSUPP; - } -#endif - - err = smp_suspend(); - if (err) - return err; - - xenbus_suspend(); - - preempt_disable(); - - mm_pin_all(); - local_irq_disable(); - preempt_enable(); - - gnttab_suspend(); - - pre_suspend(); - - /* - * We'll stop somewhere inside this hypercall. When it returns, - * we'll start resuming after the restore. - */ - HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); - - shutting_down = SHUTDOWN_INVALID; - - post_suspend(); - - gnttab_resume(); - - irq_resume(); - - time_resume(); - - switch_idle_mm(); - - local_irq_enable(); - - xencons_resume(); - - xenbus_resume(); - - smp_resume(); - - return err; -} static int shutdown_process(void *__unused) { @@ -222,16 +44,25 @@ static int shutdown_process(void *__unus if ((shutting_down == SHUTDOWN_POWEROFF) || (shutting_down == SHUTDOWN_HALT)) { - if (execve("/sbin/poweroff", poweroff_argv, envp) < 0) { + if (call_usermodehelper("/sbin/poweroff", poweroff_argv, envp, 0) < 0) { +#ifdef CONFIG_XEN sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, NULL); +#endif /* CONFIG_XEN */ } } shutting_down = SHUTDOWN_INVALID; /* could try again */ + return 0; +} + +static int xen_suspend(void *__unused) +{ + __xen_suspend(); + shutting_down = SHUTDOWN_INVALID; return 0; } @@ -257,7 +88,7 @@ static void __shutdown_handler(void *unu err = kernel_thread(shutdown_process, NULL, CLONE_FS | CLONE_FILES); else - err = kthread_create_on_cpu(__do_suspend, NULL, "suspend", 0); + err = kthread_create_on_cpu(xen_suspend, NULL, "suspend", 0); if (err < 0) { printk(KERN_WARNING "Error creating shutdown process (%d): " @@ -298,7 +129,7 @@ static void shutdown_handler(struct xenb if (strcmp(str, "poweroff") == 0) shutting_down = SHUTDOWN_POWEROFF; else if (strcmp(str, "reboot") == 0) - ctrl_alt_del(); + kill_proc(1, SIGINT, 1); /* interrupt init */ else if (strcmp(str, "suspend") == 0) shutting_down = SHUTDOWN_SUSPEND; else if (strcmp(str, "halt") == 0) @@ -364,10 +195,14 @@ static int setup_shutdown_watcher(struct err = register_xenbus_watch(&shutdown_watch); if (err) printk(KERN_ERR "Failed to set shutdown watcher\n"); + else + xenbus_write(XBT_NIL, "control", "feature-reboot", "1"); err = register_xenbus_watch(&sysrq_watch); if (err) printk(KERN_ERR "Failed to set sysrq watcher\n"); + else + xenbus_write(XBT_NIL, "control", "feature-sysrq", "1"); return NOTIFY_DONE; } @@ -378,6 +213,7 @@ static int __init setup_shutdown_event(v .notifier_call = setup_shutdown_watcher }; register_xenstore_notifier(&xenstore_notifier); + return 0; } diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/netback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Fri Nov 10 11:11:04 2006 -0700 @@ -166,9 +166,6 @@ netif_t *netif_alloc(domid_t domid, unsi SET_ETHTOOL_OPS(dev, &network_ethtool_ops); dev->tx_queue_len = netbk_queue_length; - if (dev->tx_queue_len != 0) - printk(KERN_WARNING "netbk: WARNING: device '%s' has non-zero " - "queue length (%lu)!\n", dev->name, dev->tx_queue_len); /* * Initialise a dummy MAC address. We choose the numerically diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Fri Nov 10 11:11:04 2006 -0700 @@ -814,7 +814,7 @@ void netif_deschedule_work(netif_t *neti static void tx_add_credit(netif_t *netif) { - unsigned long max_burst; + unsigned long max_burst, max_credit; /* * Allow a burst big enough to transmit a jumbo packet of up to 128kB. @@ -824,9 +824,10 @@ static void tx_add_credit(netif_t *netif max_burst = min(max_burst, 131072UL); max_burst = max(max_burst, netif->credit_bytes); - netif->remaining_credit = min(netif->remaining_credit + - netif->credit_bytes, - max_burst); + /* Take care that adding a new chunk of credit doesn't wrap to zero. */ + max_credit = max(netif->remaining_credit + netif->credit_bytes, ~0UL); + + netif->remaining_credit = min(max_credit, max_burst); } static void tx_credit_callback(unsigned long data) diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Nov 10 11:11:04 2006 -0700 @@ -93,10 +93,22 @@ static int netback_probe(struct xenbus_d goto abort_transaction; } + /* We support rx-copy path. */ err = xenbus_printf(xbt, dev->nodename, "feature-rx-copy", "%d", 1); if (err) { - message = "writing feature-copying"; + message = "writing feature-rx-copy"; + goto abort_transaction; + } + + /* + * We don't support rx-flip path (except old guests who don't + * grok this feature flag). + */ + err = xenbus_printf(xbt, dev->nodename, + "feature-rx-flip", "%d", 0); + if (err) { + message = "writing feature-rx-flip"; goto abort_transaction; } diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Fri Nov 10 11:11:04 2006 -0700 @@ -101,6 +101,14 @@ static inline void dev_disable_gso_featu } #elif defined(NETIF_F_TSO) #define HAVE_TSO 1 + +/* Some older kernels cannot cope with incorrect checksums, + * particularly in netfilter. I'm not sure there is 100% correlation + * with the presence of NETIF_F_TSO but it appears to be a good first + * approximiation. + */ +#define HAVE_NO_CSUM_OFFLOAD 1 + #define gso_size tso_size #define gso_segs tso_segs static inline void dev_disable_gso_features(struct net_device *dev) @@ -242,7 +250,6 @@ static void netif_disconnect_backend(str static void netif_disconnect_backend(struct netfront_info *); static int open_netdev(struct netfront_info *); static void close_netdev(struct netfront_info *); -static void netif_free(struct netfront_info *); static int network_connect(struct net_device *); static void network_tx_buf_gc(struct net_device *); @@ -395,6 +402,14 @@ again: goto abort_transaction; } +#ifdef HAVE_NO_CSUM_OFFLOAD + err = xenbus_printf(xbt, dev->nodename, "feature-no-csum-offload", "%d", 1); + if (err) { + message = "writing feature-no-csum-offload"; + goto abort_transaction; + } +#endif + err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", 1); if (err) { message = "writing feature-sg"; @@ -427,7 +442,6 @@ again: out: return err; } - static int setup_device(struct xenbus_device *dev, struct netfront_info *info) { @@ -488,10 +502,8 @@ static int setup_device(struct xenbus_de return 0; fail: - netif_free(info); return err; } - /** * Callback received when the backend's state changes. @@ -513,10 +525,8 @@ static void backend_changed(struct xenbu break; case XenbusStateInitWait: - if (network_connect(netdev) != 0) { - netif_free(np); + if (network_connect(netdev) != 0) break; - } xenbus_switch_state(dev, XenbusStateConnected); (void)send_fake_arp(netdev); break; @@ -526,7 +536,6 @@ static void backend_changed(struct xenbu break; } } - /** Send a packet on a net device to encourage switches to learn the * MAC. We send a fake ARP request. @@ -555,7 +564,6 @@ static int send_fake_arp(struct net_devi return dev_queue_xmit(skb); } - static int network_open(struct net_device *dev) { @@ -648,13 +656,11 @@ static void network_tx_buf_gc(struct net network_maybe_wake_tx(dev); } - static void rx_refill_timeout(unsigned long data) { struct net_device *dev = (struct net_device *)data; netif_rx_schedule(dev); } - static void network_alloc_rx_buffers(struct net_device *dev) { @@ -1617,8 +1623,16 @@ static void xennet_set_features(struct n if (!(dev->features & NETIF_F_IP_CSUM)) return; - if (!xennet_set_sg(dev, 1)) - xennet_set_tso(dev, 1); + if (xennet_set_sg(dev, 1)) + return; + + /* Before 2.6.9 TSO seems to be unreliable so do not enable it + * on older kernels. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) + xennet_set_tso(dev, 1); +#endif + } static int network_connect(struct net_device *dev) @@ -2063,14 +2077,6 @@ static void netif_disconnect_backend(str } -static void netif_free(struct netfront_info *info) -{ - close_netdev(info); - netif_disconnect_backend(info); - free_netdev(info->netdev); -} - - static void end_access(int ref, void *page) { if (ref != GRANT_INVALID_REF) diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Fri Nov 10 11:11:04 2006 -0700 @@ -53,6 +53,8 @@ static int privcmd_ioctl(struct inode *i return -EFAULT; #if defined(__i386__) + if (hypercall.op >= (PAGE_SIZE >> 5)) + break; __asm__ __volatile__ ( "pushl %%ebx; pushl %%ecx; pushl %%edx; " "pushl %%esi; pushl %%edi; " @@ -69,21 +71,21 @@ static int privcmd_ioctl(struct inode *i "popl %%ecx; popl %%ebx" : "=a" (ret) : "0" (&hypercall) : "memory" ); #elif defined (__x86_64__) - { + if (hypercall.op < (PAGE_SIZE >> 5)) { long ign1, ign2, ign3; __asm__ __volatile__ ( "movq %8,%%r10; movq %9,%%r8;" - "shlq $5,%%rax ;" + "shll $5,%%eax ;" "addq $hypercall_page,%%rax ;" "call *%%rax" : "=a" (ret), "=D" (ign1), "=S" (ign2), "=d" (ign3) - : "0" ((unsigned long)hypercall.op), - "1" ((unsigned long)hypercall.arg[0]), - "2" ((unsigned long)hypercall.arg[1]), - "3" ((unsigned long)hypercall.arg[2]), - "g" ((unsigned long)hypercall.arg[3]), - "g" ((unsigned long)hypercall.arg[4]) + : "0" ((unsigned int)hypercall.op), + "1" (hypercall.arg[0]), + "2" (hypercall.arg[1]), + "3" (hypercall.arg[2]), + "g" (hypercall.arg[3]), + "g" (hypercall.arg[4]) : "r8", "r10", "memory" ); } #elif defined (__ia64__) diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Fri Nov 10 11:11:04 2006 -0700 @@ -30,13 +30,16 @@ * IN THE SOFTWARE. */ -#include <asm/hypervisor.h> -#include <xen/evtchn.h> #include <linux/wait.h> #include <linux/interrupt.h> #include <linux/sched.h> #include <linux/err.h> +#include <linux/ptrace.h> +#include <xen/evtchn.h> #include <xen/xenbus.h> + +#include <asm/hypervisor.h> + #include "xenbus_comms.h" #ifdef HAVE_XEN_PLATFORM_COMPAT_H diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/fixmap.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/fixmap.h Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/fixmap.h Fri Nov 10 11:11:04 2006 -0700 @@ -27,7 +27,6 @@ extern unsigned long __FIXADDR_TOP; #include <asm/acpi.h> #include <asm/apicdef.h> #include <asm/page.h> -#include <xen/gnttab.h> #ifdef CONFIG_HIGHMEM #include <linux/threads.h> #include <asm/kmap_types.h> diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h Fri Nov 10 11:11:04 2006 -0700 @@ -260,6 +260,8 @@ HYPERVISOR_event_channel_op( int cmd, void *arg) { int rc = _hypercall2(int, event_channel_op, cmd, arg); + +#ifdef CONFIG_XEN_COMPAT_030002 if (unlikely(rc == -ENOSYS)) { struct evtchn_op op; op.cmd = cmd; @@ -267,6 +269,8 @@ HYPERVISOR_event_channel_op( rc = _hypercall1(int, event_channel_op_compat, &op); memcpy(arg, &op.u, sizeof(op.u)); } +#endif + return rc; } @@ -296,6 +300,8 @@ HYPERVISOR_physdev_op( int cmd, void *arg) { int rc = _hypercall2(int, physdev_op, cmd, arg); + +#ifdef CONFIG_XEN_COMPAT_030002 if (unlikely(rc == -ENOSYS)) { struct physdev_op op; op.cmd = cmd; @@ -303,6 +309,8 @@ HYPERVISOR_physdev_op( rc = _hypercall1(int, physdev_op_compat, &op); memcpy(arg, &op.u, sizeof(op.u)); } +#endif + return rc; } @@ -350,9 +358,11 @@ HYPERVISOR_suspend( int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown, &sched_shutdown, srec); +#ifdef CONFIG_XEN_COMPAT_030002 if (rc == -ENOSYS) rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown, SHUTDOWN_suspend, srec); +#endif return rc; } diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h Fri Nov 10 11:11:04 2006 -0700 @@ -131,8 +131,10 @@ HYPERVISOR_yield( { int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL); +#ifdef CONFIG_XEN_COMPAT_030002 if (rc == -ENOSYS) rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0); +#endif return rc; } @@ -143,8 +145,10 @@ HYPERVISOR_block( { int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL); +#ifdef CONFIG_XEN_COMPAT_030002 if (rc == -ENOSYS) rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0); +#endif return rc; } @@ -159,8 +163,10 @@ HYPERVISOR_shutdown( int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown); +#ifdef CONFIG_XEN_COMPAT_030002 if (rc == -ENOSYS) rc = HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason); +#endif return rc; } @@ -177,8 +183,10 @@ HYPERVISOR_poll( set_xen_guest_handle(sched_poll.ports, ports); rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll); +#ifdef CONFIG_XEN_COMPAT_030002 if (rc == -ENOSYS) rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0); +#endif return rc; } diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h Fri Nov 10 11:11:04 2006 -0700 @@ -56,15 +56,15 @@ static void __init machine_specific_arch struct xen_machphys_mapping mapping; unsigned long machine_to_phys_nr_ents; struct xen_platform_parameters pp; - struct callback_register event = { + static struct callback_register __initdata event = { .type = CALLBACKTYPE_event, .address = { __KERNEL_CS, (unsigned long)hypervisor_callback }, }; - struct callback_register failsafe = { + static struct callback_register __initdata failsafe = { .type = CALLBACKTYPE_failsafe, .address = { __KERNEL_CS, (unsigned long)failsafe_callback }, }; - struct callback_register nmi_cb = { + static struct callback_register __initdata nmi_cb = { .type = CALLBACKTYPE_nmi, .address = { __KERNEL_CS, (unsigned long)nmi }, }; @@ -72,19 +72,24 @@ static void __init machine_specific_arch ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event); if (ret == 0) ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe); +#ifdef CONFIG_XEN_COMPAT_030002 if (ret == -ENOSYS) ret = HYPERVISOR_set_callbacks( event.address.cs, event.address.eip, failsafe.address.cs, failsafe.address.eip); +#endif BUG_ON(ret); ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb); +#ifdef CONFIG_XEN_COMPAT_030002 if (ret == -ENOSYS) { - struct xennmi_callback cb; + static struct xennmi_callback __initdata cb = { + .handler_address = (unsigned long)nmi + }; - cb.handler_address = nmi_cb.address.eip; HYPERVISOR_nmi_op(XENNMI_register_callback, &cb); } +#endif if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0) diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/include/asm-ia64/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Fri Nov 10 11:11:04 2006 -0700 @@ -283,6 +283,9 @@ static inline void exit_idle(void) {} #ifdef CONFIG_XEN #include <asm/xen/privop.h> #endif /* CONFIG_XEN */ +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif static inline unsigned long __HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size) diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h --- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h Fri Nov 10 11:11:04 2006 -0700 @@ -191,6 +191,22 @@ MULTI_grant_table_op(multicall_entry_t * mcl->args[2] = count; } +/* + * for blktap.c + * int create_lookup_pte_addr(struct mm_struct *mm, + * unsigned long address, + * uint64_t *ptep); + */ +#define create_lookup_pte_addr(mm, address, ptep) \ + ({ \ + printk(KERN_EMERG \ + "%s:%d " \ + "create_lookup_pte_addr() isn't supported.\n", \ + __func__, __LINE__); \ + BUG(); \ + (-ENOSYS); \ + }) + // for debug asmlinkage int xprintk(const char *fmt, ...); #define xprintd(fmt, ...) xprintk("%s:%d " fmt, __func__, __LINE__, \ diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/fixmap.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/fixmap.h Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/fixmap.h Fri Nov 10 11:11:04 2006 -0700 @@ -14,7 +14,6 @@ #include <linux/config.h> #include <linux/kernel.h> #include <asm/apicdef.h> -#include <xen/gnttab.h> #include <asm/page.h> #include <asm/vsyscall.h> #include <asm/vsyscall32.h> diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h Fri Nov 10 11:11:04 2006 -0700 @@ -258,6 +258,8 @@ HYPERVISOR_event_channel_op( int cmd, void *arg) { int rc = _hypercall2(int, event_channel_op, cmd, arg); + +#ifdef CONFIG_XEN_COMPAT_030002 if (unlikely(rc == -ENOSYS)) { struct evtchn_op op; op.cmd = cmd; @@ -265,6 +267,8 @@ HYPERVISOR_event_channel_op( rc = _hypercall1(int, event_channel_op_compat, &op); memcpy(arg, &op.u, sizeof(op.u)); } +#endif + return rc; } @@ -294,6 +298,8 @@ HYPERVISOR_physdev_op( int cmd, void *arg) { int rc = _hypercall2(int, physdev_op, cmd, arg); + +#ifdef CONFIG_XEN_COMPAT_030002 if (unlikely(rc == -ENOSYS)) { struct physdev_op op; op.cmd = cmd; @@ -301,6 +307,8 @@ HYPERVISOR_physdev_op( rc = _hypercall1(int, physdev_op_compat, &op); memcpy(arg, &op.u, sizeof(op.u)); } +#endif + return rc; } @@ -351,9 +359,11 @@ HYPERVISOR_suspend( int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown, &sched_shutdown, srec); +#ifdef CONFIG_XEN_COMPAT_030002 if (rc == -ENOSYS) rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown, SHUTDOWN_suspend, srec); +#endif return rc; } diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h Fri Nov 10 11:11:04 2006 -0700 @@ -15,20 +15,20 @@ static void __init machine_specific_arch static void __init machine_specific_arch_setup(void) { int ret; - struct callback_register event = { + static struct callback_register __initdata event = { .type = CALLBACKTYPE_event, .address = (unsigned long) hypervisor_callback, }; - struct callback_register failsafe = { + static struct callback_register __initdata failsafe = { .type = CALLBACKTYPE_failsafe, .address = (unsigned long)failsafe_callback, }; - struct callback_register syscall = { + static struct callback_register __initdata syscall = { .type = CALLBACKTYPE_syscall, .address = (unsigned long)system_call, }; #ifdef CONFIG_X86_LOCAL_APIC - struct callback_register nmi_cb = { + static struct callback_register __initdata nmi_cb = { .type = CALLBACKTYPE_nmi, .address = (unsigned long)nmi, }; @@ -39,20 +39,25 @@ static void __init machine_specific_arch ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe); if (ret == 0) ret = HYPERVISOR_callback_op(CALLBACKOP_register, &syscall); +#ifdef CONFIG_XEN_COMPAT_030002 if (ret == -ENOSYS) ret = HYPERVISOR_set_callbacks( event.address, failsafe.address, syscall.address); +#endif BUG_ON(ret); #ifdef CONFIG_X86_LOCAL_APIC ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb); +#ifdef CONFIG_XEN_COMPAT_030002 if (ret == -ENOSYS) { - struct xennmi_callback cb; + static struct xennmi_callback __initdata cb = { + .handler_address = (unsigned long)nmi + }; - cb.handler_address = nmi_cb.address; HYPERVISOR_nmi_op(XENNMI_register_callback, &cb); } #endif +#endif } diff -r 11b718eb22c9 -r ebed72718263 linux-2.6-xen-sparse/include/xen/gnttab.h --- a/linux-2.6-xen-sparse/include/xen/gnttab.h Thu Nov 02 12:43:04 2006 -0700 +++ b/linux-2.6-xen-sparse/include/xen/gnttab.h Fri Nov 10 11:11:04 2006 -0700 @@ -39,6 +39,7 @@ #include <linux/config.h> #include <asm/hypervisor.h> +#include <asm/maddr.h> /* maddr_t */ #include <xen/interface/grant_table.h> #include <xen/features.h> @@ -118,7 +119,7 @@ int gnttab_resume(void); int gnttab_resume(void); static inline void -gnttab_set_map_op(struct gnttab_map_grant_ref *map, unsigned long addr, +gnttab_set_map_op(struct gnttab_map_grant_ref *map, maddr_t addr, uint32_t flags, grant_ref_t ref, domid_t domid) { if (flags & GNTMAP_contains_pte) @@ -134,7 +135,7 @@ gnttab_set_map_op(struct gnttab_map_gran } static inline void -gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, unsigned long addr, +gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, maddr_t addr, uint32_t flags, grant_handle_t handle) { if (flags & GNTMAP_contains_pte) diff -r 11b718eb22c9 -r ebed72718263 patches/linux-2.6.16.29/series --- a/patches/linux-2.6.16.29/series Thu Nov 02 12:43:04 2006 -0700 +++ b/patches/linux-2.6.16.29/series Fri Nov 10 11:11:04 2006 -0700 @@ -10,6 +10,7 @@ net-gso-2-checksum-fix.patch net-gso-2-checksum-fix.patch net-gso-3-fix-errorcheck.patch net-gso-4-kill-warnon.patch +net-gso-5-rcv-mss.patch pci-mmconfig-fix-from-2.6.17.patch pmd-shared.patch rcu_needs_cpu.patch diff -r 11b718eb22c9 -r ebed72718263 patches/linux-2.6.16.29/xenoprof-generic.patch --- a/patches/linux-2.6.16.29/xenoprof-generic.patch Thu Nov 02 12:43:04 2006 -0700 +++ b/patches/linux-2.6.16.29/xenoprof-generic.patch Fri Nov 10 11:11:04 2006 -0700 @@ -1,6 +1,6 @@ diff -pruN ../orig-linux-2.6.16.29/drive diff -pruN ../orig-linux-2.6.16.29/drivers/oprofile/buffer_sync.c ./drivers/oprofile/buffer_sync.c ---- ../orig-linux-2.6.16.29/drivers/oprofile/buffer_sync.c 2006-09-12 19:02:10.000000000 +0100 -+++ ./drivers/oprofile/buffer_sync.c 2006-09-19 14:06:05.000000000 +0100 +--- ../orig-linux-2.6.16.29/drivers/oprofile/buffer_sync.c 2006-11-06 14:46:52.000000000 -0800 ++++ ./drivers/oprofile/buffer_sync.c 2006-11-06 15:16:52.000000000 -0800 @@ -6,6 +6,10 @@ * * @author John Levon <levon@xxxxxxxxxxxxxxxxx> @@ -12,7 +12,27 @@ diff -pruN ../orig-linux-2.6.16.29/drive * This is the core of the buffer management. Each * CPU buffer is processed and entered into the * global event buffer. Such processing is necessary -@@ -275,15 +279,31 @@ static void add_cpu_switch(int i) +@@ -38,6 +42,7 @@ static cpumask_t marked_cpus = CPU_MASK_ + static DEFINE_SPINLOCK(task_mortuary); + static void process_task_mortuary(void); + ++static int cpu_current_domain[NR_CPUS]; + + /* Take ownership of the task struct and place it on the + * list for processing. Only after two full buffer syncs +@@ -146,6 +151,11 @@ static void end_sync(void) + int sync_start(void) + { + int err; ++ int i; ++ ++ for (i = 0; i < NR_CPUS; i++) { ++ cpu_current_domain[i] = COORDINATOR_DOMAIN; ++ } + + start_cpu_work(); + +@@ -275,15 +285,31 @@ static void add_cpu_switch(int i) last_cookie = INVALID_COOKIE; } @@ -50,7 +70,7 @@ diff -pruN ../orig-linux-2.6.16.29/drive static void add_user_ctx_switch(struct task_struct const * task, unsigned long cookie) { -@@ -348,9 +368,9 @@ static int add_us_sample(struct mm_struc +@@ -348,9 +374,9 @@ static int add_us_sample(struct mm_struc * for later lookup from userspace. */ static int @@ -62,7 +82,7 @@ diff -pruN ../orig-linux-2.6.16.29/drive add_sample_entry(s->eip, s->event); return 1; } else if (mm) { -@@ -496,10 +516,11 @@ void sync_buffer(int cpu) +@@ -496,15 +522,21 @@ void sync_buffer(int cpu) struct mm_struct *mm = NULL; struct task_struct * new; unsigned long cookie = 0; @@ -75,7 +95,17 @@ diff -pruN ../orig-linux-2.6.16.29/drive down(&buffer_sem); -@@ -512,16 +533,18 @@ void sync_buffer(int cpu) + add_cpu_switch(cpu); + ++ /* We need to assign the first samples in this CPU buffer to the ++ same domain that we were processing at the last sync_buffer */ ++ if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN) { ++ add_domain_switch(cpu_current_domain[cpu]); ++ } + /* Remember, only we can modify tail_pos */ + + available = get_slots(cpu_buf); +@@ -512,16 +544,18 @@ void sync_buffer(int cpu) for (i = 0; i < available; ++i) { struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos]; @@ -99,7 +129,7 @@ diff -pruN ../orig-linux-2.6.16.29/drive } else { struct mm_struct * oldmm = mm; -@@ -535,11 +558,16 @@ void sync_buffer(int cpu) +@@ -535,11 +569,21 @@ void sync_buffer(int cpu) add_user_ctx_switch(new, cookie); } } else { @@ -109,10 +139,15 @@ diff -pruN ../orig-linux-2.6.16.29/drive - state = sb_bt_ignore; - atomic_inc(&oprofile_stats.bt_lost_no_mapping); + if (domain_switch) { ++ cpu_current_domain[cpu] = s->eip; + add_domain_switch(s->eip); + domain_switch = 0; + } else { -+ if (state >= sb_bt_start && ++ if (cpu_current_domain[cpu] != ++ COORDINATOR_DOMAIN) { ++ add_sample_entry(s->eip, s->event); ++ } ++ else if (state >= sb_bt_start && + !add_sample(mm, s, cpu_mode)) { + if (state == sb_bt_start) { + state = sb_bt_ignore; @@ -121,9 +156,21 @@ diff -pruN ../orig-linux-2.6.16.29/drive } } } +@@ -548,6 +592,11 @@ void sync_buffer(int cpu) + } + release_mm(mm); + ++ /* We reset domain to COORDINATOR at each CPU switch */ ++ if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN) { ++ add_domain_switch(COORDINATOR_DOMAIN); ++ } ++ + mark_done(cpu); + + up(&buffer_sem); diff -pruN ../orig-linux-2.6.16.29/drivers/oprofile/cpu_buffer.c ./drivers/oprofile/cpu_buffer.c ---- ../orig-linux-2.6.16.29/drivers/oprofile/cpu_buffer.c 2006-09-12 19:02:10.000000000 +0100 -+++ ./drivers/oprofile/cpu_buffer.c 2006-09-19 14:06:05.000000000 +0100 +--- ../orig-linux-2.6.16.29/drivers/oprofile/cpu_buffer.c 2006-11-06 14:46:52.000000000 -0800 ++++ ./drivers/oprofile/cpu_buffer.c 2006-11-06 14:47:55.000000000 -0800 @@ -6,6 +6,10 @@ * * @author John Levon <levon@xxxxxxxxxxxxxxxxx> @@ -233,8 +280,8 @@ diff -pruN ../orig-linux-2.6.16.29/drive * This serves to avoid cpu buffer overflow, and makes sure * the task mortuary progresses diff -pruN ../orig-linux-2.6.16.29/drivers/oprofile/cpu_buffer.h ./drivers/oprofile/cpu_buffer.h ---- ../orig-linux-2.6.16.29/drivers/oprofile/cpu_buffer.h 2006-09-12 19:02:10.000000000 +0100 -+++ ./drivers/oprofile/cpu_buffer.h 2006-09-19 14:06:05.000000000 +0100 +--- ../orig-linux-2.6.16.29/drivers/oprofile/cpu_buffer.h 2006-11-06 14:46:52.000000000 -0800 ++++ ./drivers/oprofile/cpu_buffer.h 2006-11-06 14:47:55.000000000 -0800 @@ -36,7 +36,7 @@ struct oprofile_cpu_buffer { volatile unsigned long tail_pos; unsigned long buffer_size; @@ -258,8 +305,8 @@ diff -pruN ../orig-linux-2.6.16.29/drive #endif /* OPROFILE_CPU_BUFFER_H */ diff -pruN ../orig-linux-2.6.16.29/drivers/oprofile/event_buffer.h ./drivers/oprofile/event_buffer.h ---- ../orig-linux-2.6.16.29/drivers/oprofile/event_buffer.h 2006-09-12 19:02:10.000000000 +0100 -+++ ./drivers/oprofile/event_buffer.h 2006-09-19 14:06:05.000000000 +0100 +--- ../orig-linux-2.6.16.29/drivers/oprofile/event_buffer.h 2006-11-06 14:46:52.000000000 -0800 ++++ ./drivers/oprofile/event_buffer.h 2006-11-06 14:47:55.000000000 -0800 @@ -29,15 +29,20 @@ void wake_up_buffer_waiter(void); #define CPU_SWITCH_CODE 2 #define COOKIE_SWITCH_CODE 3 @@ -283,8 +330,8 @@ diff -pruN ../orig-linux-2.6.16.29/drive void add_event_entry(unsigned long data); diff -pruN ../orig-linux-2.6.16.29/drivers/oprofile/oprof.c ./drivers/oprofile/oprof.c ---- ../orig-linux-2.6.16.29/drivers/oprofile/oprof.c 2006-09-12 19:02:10.000000000 +0100 -+++ ./drivers/oprofile/oprof.c 2006-09-19 14:06:05.000000000 +0100 +--- ../orig-linux-2.6.16.29/drivers/oprofile/oprof.c 2006-11-06 14:46:52.000000000 -0800 ++++ ./drivers/oprofile/oprof.c 2006-11-06 14:47:55.000000000 -0800 @@ -5,6 +5,10 @@ * @remark Read the file COPYING * @@ -339,8 +386,8 @@ diff -pruN ../orig-linux-2.6.16.29/drive { int err; diff -pruN ../orig-linux-2.6.16.29/drivers/oprofile/oprof.h ./drivers/oprofile/oprof.h ---- ../orig-linux-2.6.16.29/drivers/oprofile/oprof.h 2006-09-12 19:02:10.000000000 +0100 -+++ ./drivers/oprofile/oprof.h 2006-09-19 14:06:05.000000000 +0100 +--- ../orig-linux-2.6.16.29/drivers/oprofile/oprof.h 2006-11-06 14:46:52.000000000 -0800 ++++ ./drivers/oprofile/oprof.h 2006-11-06 14:47:55.000000000 -0800 @@ -35,5 +35,8 @@ void oprofile_create_files(struct super_ void oprofile_timer_init(struct oprofile_operations * ops); @@ -351,8 +398,8 @@ diff -pruN ../orig-linux-2.6.16.29/drive #endif /* OPROF_H */ diff -pruN ../orig-linux-2.6.16.29/drivers/oprofile/oprofile_files.c ./drivers/oprofile/oprofile_files.c ---- ../orig-linux-2.6.16.29/drivers/oprofile/oprofile_files.c 2006-09-12 19:02:10.000000000 +0100 -+++ ./drivers/oprofile/oprofile_files.c 2006-09-19 14:06:05.000000000 +0100 +--- ../orig-linux-2.6.16.29/drivers/oprofile/oprofile_files.c 2006-11-06 14:46:52.000000000 -0800 ++++ ./drivers/oprofile/oprofile_files.c 2006-11-06 14:47:55.000000000 -0800 @@ -5,15 +5,21 @@ * @remark Read the file COPYING * @@ -581,8 +628,8 @@ diff -pruN ../orig-linux-2.6.16.29/drive oprofilefs_create_ulong(sb, root, "buffer_size", &fs_buffer_size); oprofilefs_create_ulong(sb, root, "buffer_watershed", &fs_buffer_watershed); diff -pruN ../orig-linux-2.6.16.29/include/linux/oprofile.h ./include/linux/oprofile.h ---- ../orig-linux-2.6.16.29/include/linux/oprofile.h 2006-09-12 19:02:10.000000000 +0100 -+++ ./include/linux/oprofile.h 2006-09-19 14:06:05.000000000 +0100 +--- ../orig-linux-2.6.16.29/include/linux/oprofile.h 2006-11-06 14:46:42.000000000 -0800 ++++ ./include/linux/oprofile.h 2006-11-06 14:47:55.000000000 -0800 @@ -16,6 +16,8 @@ #include <linux/types.h> #include <linux/spinlock.h> diff -r 11b718eb22c9 -r ebed72718263 tools/Makefile --- a/tools/Makefile Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/Makefile Fri Nov 10 11:11:04 2006 -0700 @@ -18,6 +18,7 @@ SUBDIRS-y += xenstat SUBDIRS-y += xenstat SUBDIRS-y += libaio SUBDIRS-y += blktap +SUBDIRS-y += libfsimage # These don't cross-compile ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH)) diff -r 11b718eb22c9 -r ebed72718263 tools/blktap/drivers/blktapctrl.c --- a/tools/blktap/drivers/blktapctrl.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/blktap/drivers/blktapctrl.c Fri Nov 10 11:11:04 2006 -0700 @@ -607,9 +607,11 @@ int main(int argc, char *argv[]) struct xs_handle *h; struct pollfd pfd[NUM_POLL_FDS]; pid_t process; + char buf[128]; __init_blkif(); - openlog("BLKTAPCTRL", LOG_CONS|LOG_ODELAY, LOG_DAEMON); + snprintf(buf, sizeof(buf), "BLKTAPCTRL[%d]", getpid()); + openlog(buf, LOG_CONS|LOG_ODELAY, LOG_DAEMON); daemon(0,0); print_drivers(); diff -r 11b718eb22c9 -r ebed72718263 tools/blktap/drivers/tapdisk.c --- a/tools/blktap/drivers/tapdisk.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/blktap/drivers/tapdisk.c Fri Nov 10 11:11:04 2006 -0700 @@ -381,7 +381,6 @@ static inline int write_rsp_to_ring(stru rsp_d = RING_GET_RESPONSE(&info->fe_ring, info->fe_ring.rsp_prod_pvt); memcpy(rsp_d, rsp, sizeof(blkif_response_t)); - wmb(); info->fe_ring.rsp_prod_pvt++; return 0; @@ -562,12 +561,14 @@ int main(int argc, char *argv[]) fd_list_entry_t *ptr; struct tap_disk *drv; struct td_state *s; + char openlogbuf[128]; if (argc != 3) usage(); daemonize(); - openlog("TAPDISK", LOG_CONS|LOG_ODELAY, LOG_DAEMON); + snprintf(openlogbuf, sizeof(openlogbuf), "TAPDISK[%d]", getpid()); + openlog(openlogbuf, LOG_CONS|LOG_ODELAY, LOG_DAEMON); /*Setup signal handlers*/ signal (SIGBUS, sig_handler); signal (SIGINT, sig_handler); diff -r 11b718eb22c9 -r ebed72718263 tools/blktap/drivers/tapdisk.h --- a/tools/blktap/drivers/tapdisk.h Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/blktap/drivers/tapdisk.h Fri Nov 10 11:11:04 2006 -0700 @@ -61,7 +61,6 @@ /* Things disks need to know about, these should probably be in a higher-level * header. */ -#define MAX_REQUESTS 64 #define MAX_SEGMENTS_PER_REQ 11 #define SECTOR_SHIFT 9 #define DEFAULT_SECTOR_SIZE 512 diff -r 11b718eb22c9 -r ebed72718263 tools/blktap/lib/blktaplib.h --- a/tools/blktap/lib/blktaplib.h Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/blktap/lib/blktaplib.h Fri Nov 10 11:11:04 2006 -0700 @@ -41,7 +41,7 @@ #include <sys/types.h> #include <unistd.h> -#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, getpagesize()) +#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, XC_PAGE_SIZE) /* size of the extra VMA area to map in attached pages. */ #define BLKTAP_VMA_PAGES BLK_RING_SIZE @@ -74,10 +74,10 @@ static inline int BLKTAP_MODE_VALID(unsi ( arg == BLKTAP_MODE_INTERPOSE ) ); } -#define MAX_REQUESTS 64 +#define MAX_REQUESTS BLK_RING_SIZE #define BLKTAP_IOCTL_KICK 1 -#define MAX_PENDING_REQS 64 +#define MAX_PENDING_REQS BLK_RING_SIZE #define BLKTAP_DEV_DIR "/dev/xen" #define BLKTAP_DEV_NAME "blktap" #define BLKTAP_DEV_MINOR 0 @@ -199,7 +199,6 @@ int xs_fire_next_watch(struct xs_handle /* Abitrary values, must match the underlying driver... */ -#define MAX_PENDING_REQS 64 #define MAX_TAP_DEV 100 /* Accessing attached data page mappings */ diff -r 11b718eb22c9 -r ebed72718263 tools/console/Makefile --- a/tools/console/Makefile Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/console/Makefile Fri Nov 10 11:11:04 2006 -0700 @@ -5,7 +5,7 @@ DAEMON_INSTALL_DIR = /usr/sbin DAEMON_INSTALL_DIR = /usr/sbin CLIENT_INSTALL_DIR = /usr/$(LIBDIR)/xen/bin -CFLAGS += -Werror -g +CFLAGS += -Werror CFLAGS += -I $(XEN_LIBXC) CFLAGS += -I $(XEN_XENSTORE) diff -r 11b718eb22c9 -r ebed72718263 tools/examples/blktap --- a/tools/examples/blktap Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/examples/blktap Fri Nov 10 11:11:04 2006 -0700 @@ -4,12 +4,26 @@ dir=$(dirname "$0") . "$dir/xen-hotplug-common.sh" +. "$dir/block-common.sh" findCommand "$@" -if [ "$command" == 'add' ] +t=$(xenstore_read_default "$XENBUS_PATH/type" 'MISSING') +if [ -n "$t" ] then - success + p=$(xenstore_read "$XENBUS_PATH/params") + # if we have a ':', chew from head including : + if echo $p | grep -q \: + then + p=${p#*:} + fi +fi +file=$(readlink -f "$p") || ebusy "$p does not exist." + +if [ "$command" = 'add' ] +then + [ -e "$file" ] || { ebusy $file does not exist; } + success fi exit 0 diff -r 11b718eb22c9 -r ebed72718263 tools/examples/block --- a/tools/examples/block Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/examples/block Fri Nov 10 11:11:04 2006 -0700 @@ -68,7 +68,7 @@ check_sharing() local devmm=$(device_major_minor "$dev") local file - if [ "$mode" == 'w' ] + if [ "$mode" = 'w' ] then toskip="^$" else @@ -81,7 +81,7 @@ check_sharing() then local d=$(device_major_minor "$file") - if [ "$d" == "$devmm" ] + if [ "$d" = "$devmm" ] then echo 'local' return @@ -96,9 +96,9 @@ check_sharing() do d=$(xenstore_read_default "$base_path/$dom/$dev/physical-device" "") - if [ "$d" == "$devmm" ] + if [ "$d" = "$devmm" ] then - if [ "$mode" == 'w' ] + if [ "$mode" = 'w' ] then if ! same_vm $dom then @@ -109,7 +109,7 @@ check_sharing() local m=$(xenstore_read "$base_path/$dom/$dev/mode") m=$(canonicalise_mode "$m") - if [ "$m" == 'w' ] + if [ "$m" = 'w' ] then if ! same_vm $dom then @@ -138,7 +138,7 @@ same_vm() local othervm=$(xenstore_read_default "/local/domain/$otherdom/vm" \ "$FRONTEND_UUID") - [ "$FRONTEND_UUID" == "$othervm" ] + [ "$FRONTEND_UUID" = "$othervm" ] } @@ -153,7 +153,7 @@ check_device_sharing() local mode=$(canonicalise_mode "$2") local result - if [ "$mode" == '!' ] + if [ "x$mode" = 'x!' ] then return 0 fi @@ -202,7 +202,7 @@ do_ebusy() local mode="$2" local result="$3" - if [ "$result" == 'guest' ] + if [ "$result" = 'guest' ] then dom='a guest ' when='now' @@ -211,7 +211,7 @@ do_ebusy() when='by a guest' fi - if [ "$mode" == 'w' ] + if [ "$mode" = 'w' ] then m1='' m2='' @@ -266,7 +266,7 @@ case "$command" in claim_lock "block" - if [ "$mode" == 'w' ] && ! stat "$file" -c %A | grep -q w + if [ "$mode" = 'w' ] && ! stat "$file" -c %A | grep -q w then release_lock "block" ebusy \ @@ -287,7 +287,7 @@ mount it read-write in a guest domain." if [ "$f" ] then # $dev is in use. Check sharing. - if [ "$mode" == '!' ] + if [ "x$mode" = 'x!' ] then continue fi @@ -307,7 +307,7 @@ mount it read-write in a guest domain." do d=$(xenstore_read_default \ "$XENBUS_BASE_PATH/$dom/$domdev/node" "") - if [ "$d" == "$dev" ] + if [ "$d" = "$dev" ] then f=$(xenstore_read "$XENBUS_BASE_PATH/$dom/$domdev/params") found=1 @@ -347,7 +347,7 @@ mount it read-write in a guest domain." f=$(readlink -f "$f" || echo $(dirname "$file")/$(basename "$f")) - if [ "$f" == "$file" ] + if [ "$f" = "$file" ] then check_file_sharing "$file" "$dev" "$mode" fi @@ -355,14 +355,14 @@ mount it read-write in a guest domain." # $dev is not in use, so we'll remember it for use later; we want # to finish the sharing check first. - if [ "$loopdev" == '' ] + if [ "$loopdev" = '' ] then loopdev="$dev" fi fi done - if [ "$loopdev" == '' ] + if [ "$loopdev" = '' ] then fatal 'Failed to find an unused loop device' fi diff -r 11b718eb22c9 -r ebed72718263 tools/examples/external-device-migrate --- a/tools/examples/external-device-migrate Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/examples/external-device-migrate Fri Nov 10 11:11:04 2006 -0700 @@ -55,41 +55,27 @@ function evaluate_params() { local step host domname typ recover filename func stype stype="" - while [ 1 ]; do - if [ "$1" == "-step" ]; then - shift - step=$1 - elif [ "$1" == "-host" ]; then - shift - host=$1 - elif [ "$1" == "-domname" ]; then - shift - domname=$1 - elif [ "$1" == "-type" ]; then - shift - typ=$1 - elif [ "$1" == "-subtype" ]; then - shift - stype="_$1" - elif [ "$1" == "-recover" ]; then - recover=1 - elif [ "$1" == "-help" ]; then - ext_dev_migrate_usage - exit - else - break - fi - shift + while [ $# -ge 1 ]; do + case "$1" in + -step) step=$2; shift 2;; + -host) host=$2; shift 2;; + -domname) domname=$2; shift 2;; + -type) type=$2; shift 2;; + -subtype) subtype=$2; shift 2;; + -recover) recover=1; shift;; + -help) ext_dev_migrate_usage; exit 0;; + *) break;; + esac done - if [ "$step" == "" -o \ - "$host" == "" -o \ - "$typ" == "" -o \ - "$domname" == "" ]; then - echo "Error: Parameter(s) missing (-step/-host/-type/-domname)" - echo "" - echo "$0 -help for usage." - exit + if [ "$step" = "" -o \ + "$host" = "" -o \ + "$typ" = "" -o \ + "$domname" = "" ]; then + echo "Error: Parameter(s) missing (-step/-host/-type/-domname)" 1>&2 + echo "" 1>&2 + echo "$0 -help for usage." 1>&2 + exit 1 fi filename="$dir/$typ$stype-migration.sh" @@ -99,7 +85,7 @@ function evaluate_params() fi . "$filename" - if [ "$recover" == "1" ]; then + if [ "$recover" = "1" ]; then func="$typ"_recover eval $func $host $domname $step $* else @@ -108,4 +94,4 @@ function evaluate_params() fi } -evaluate_params $* +evaluate_params "$@" diff -r 11b718eb22c9 -r ebed72718263 tools/examples/vif-bridge --- a/tools/examples/vif-bridge Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/examples/vif-bridge Fri Nov 10 11:11:04 2006 -0700 @@ -61,7 +61,7 @@ handle_iptable handle_iptable log debug "Successful vif-bridge $command for $vif, bridge $bridge." -if [ "$command" == "online" ] +if [ "$command" = "online" ] then success fi diff -r 11b718eb22c9 -r ebed72718263 tools/examples/vif-nat --- a/tools/examples/vif-nat Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/examples/vif-nat Fri Nov 10 11:11:04 2006 -0700 @@ -72,7 +72,7 @@ dotted_quad() } -if [ "$ip" == "" ] +if [ "$ip" = "" ] then ip=$(ip_from_dom) fi @@ -152,7 +152,7 @@ handle_iptable handle_iptable log debug "Successful vif-nat $command for $vif." -if [ "$command" == "online" ] +if [ "$command" = "online" ] then success fi diff -r 11b718eb22c9 -r ebed72718263 tools/examples/vif-route --- a/tools/examples/vif-route Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/examples/vif-route Fri Nov 10 11:11:04 2006 -0700 @@ -50,7 +50,7 @@ handle_iptable handle_iptable log debug "Successful vif-route $command for $vif." -if [ "$command" == "online" ] +if [ "$command" = "online" ] then success fi diff -r 11b718eb22c9 -r ebed72718263 tools/examples/xend-config.sxp --- a/tools/examples/xend-config.sxp Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/examples/xend-config.sxp Fri Nov 10 11:11:04 2006 -0700 @@ -51,7 +51,7 @@ # regular expressions will be accepted. # # For example: -# (xend-relocation-hosts-allow '^localhost$ ^.*\.example\.org$') +# (xend-relocation-hosts-allow '^localhost$ ^.*\\.example\\.org$') # #(xend-relocation-hosts-allow '') (xend-relocation-hosts-allow '^localhost$ ^localhost\\.localdomain$') diff -r 11b718eb22c9 -r ebed72718263 tools/examples/xmexample.hvm --- a/tools/examples/xmexample.hvm Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/examples/xmexample.hvm Fri Nov 10 11:11:04 2006 -0700 @@ -47,9 +47,6 @@ name = "ExampleHVMDomain" # enable/disable HVM guest ACPI, default=0 (disabled) #acpi=0 - -# enable/disable HVM guest APIC, default=0 (disabled) -#apic=0 # List of which CPUS this domain is allowed to use, default Xen picks #cpus = "" # leave to Xen to pick diff -r 11b718eb22c9 -r ebed72718263 tools/firmware/Makefile --- a/tools/firmware/Makefile Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/firmware/Makefile Fri Nov 10 11:11:04 2006 -0700 @@ -9,7 +9,6 @@ SUBDIRS := SUBDIRS := SUBDIRS += rombios SUBDIRS += vgabios -SUBDIRS += acpi SUBDIRS += vmxassist SUBDIRS += hvmloader diff -r 11b718eb22c9 -r ebed72718263 tools/firmware/hvmloader/Makefile --- a/tools/firmware/hvmloader/Makefile Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/firmware/hvmloader/Makefile Fri Nov 10 11:11:04 2006 -0700 @@ -40,11 +40,14 @@ CFLAGS += $(DEFINES) -I. $(XENINC) -fno CFLAGS += $(DEFINES) -I. $(XENINC) -fno-builtin -O2 -msoft-float LDFLAGS = -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR) -SRCS = hvmloader.c acpi_madt.c mp_tables.c util.c smbios.c +SRCS = hvmloader.c acpi_madt.c mp_tables.c util.c smbios.c acpi_utils.c OBJS = $(patsubst %.c,%.o,$(SRCS)) .PHONY: all all: hvmloader + +acpi/acpi.bin: + $(MAKE) -C acpi hvmloader: roms.h $(SRCS) $(CC) $(CFLAGS) -c $(SRCS) @@ -52,15 +55,15 @@ hvmloader: roms.h $(SRCS) $(OBJCOPY) hvmloader.tmp hvmloader rm -f hvmloader.tmp -roms.h: ../rombios/BIOS-bochs-latest ../vgabios/VGABIOS-lgpl-latest.bin ../vgabios/VGABIOS-lgpl-latest.cirrus.bin ../vmxassist/vmxassist.bin ../acpi/acpi.bin +roms.h: ../rombios/BIOS-bochs-latest ../vgabios/VGABIOS-lgpl-latest.bin ../vgabios/VGABIOS-lgpl-latest.cirrus.bin ../vmxassist/vmxassist.bin acpi/acpi.bin sh ./mkhex rombios ../rombios/BIOS-bochs-latest > roms.h sh ./mkhex vgabios_stdvga ../vgabios/VGABIOS-lgpl-latest.bin >> roms.h sh ./mkhex vgabios_cirrusvga ../vgabios/VGABIOS-lgpl-latest.cirrus.bin >> roms.h sh ./mkhex vmxassist ../vmxassist/vmxassist.bin >> roms.h - sh ./mkhex acpi ../acpi/acpi.bin >> roms.h + sh ./mkhex acpi acpi/acpi.bin >> roms.h .PHONY: clean clean: rm -f roms.h acpi.h rm -f hvmloader hvmloader.tmp hvmloader.o $(OBJS) - + $(MAKE) -C acpi clean diff -r 11b718eb22c9 -r ebed72718263 tools/firmware/hvmloader/acpi_madt.c --- a/tools/firmware/hvmloader/acpi_madt.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/firmware/hvmloader/acpi_madt.c Fri Nov 10 11:11:04 2006 -0700 @@ -18,9 +18,9 @@ * Place - Suite 330, Boston, MA 02111-1307 USA. */ -#include "../acpi/acpi2_0.h" -#include "../acpi/acpi_madt.h" +#include "acpi/acpi2_0.h" #include "util.h" +#include "acpi_utils.h" #include <xen/hvm/hvm_info_table.h> #define NULL ((void*)0) @@ -29,160 +29,134 @@ static struct hvm_info_table *table = NU static int validate_hvm_info(struct hvm_info_table *t) { - char signature[] = "HVM INFO"; - uint8_t *ptr = (uint8_t *)t; - uint8_t sum = 0; - int i; + char signature[] = "HVM INFO"; + uint8_t *ptr = (uint8_t *)t; + uint8_t sum = 0; + int i; - /* strncmp(t->signature, "HVM INFO", 8) */ - for (i = 0; i < 8; i++) { - if (signature[i] != t->signature[i]) { - puts("Bad hvm info signature\n"); - return 0; - } - } + /* strncmp(t->signature, "HVM INFO", 8) */ + for (i = 0; i < 8; i++) { + if (signature[i] != t->signature[i]) { + puts("Bad hvm info signature\n"); + return 0; + } + } - for (i = 0; i < t->length; i++) - sum += ptr[i]; + for (i = 0; i < t->length; i++) + sum += ptr[i]; - return (sum == 0); + return (sum == 0); } /* xc_vmx_builder wrote hvm info at 0x9F800. Return it. */ struct hvm_info_table * get_hvm_info_table(void) { - struct hvm_info_table *t; + struct hvm_info_table *t; - if (table != NULL) - return table; + if (table != NULL) + return table; - t = (struct hvm_info_table *)HVM_INFO_PADDR; + t = (struct hvm_info_table *)HVM_INFO_PADDR; - if (!validate_hvm_info(t)) { - puts("Bad hvm info table\n"); - return NULL; - } + if (!validate_hvm_info(t)) { + puts("Bad hvm info table\n"); + return NULL; + } - table = t; + table = t; - return table; + return table; } int get_vcpu_nr(void) { - struct hvm_info_table *t = get_hvm_info_table(); - return (t ? t->nr_vcpus : 1); /* default 1 vcpu */ + struct hvm_info_table *t = get_hvm_info_table(); + return (t ? t->nr_vcpus : 1); /* default 1 vcpu */ } int get_acpi_enabled(void) { - struct hvm_info_table *t = get_hvm_info_table(); - return (t ? t->acpi_enabled : 0); /* default no acpi */ + struct hvm_info_table *t = get_hvm_info_table(); + return (t ? t->acpi_enabled : 0); /* default no acpi */ } static void * acpi_madt_get_madt(unsigned char *acpi_start) { - ACPI_2_0_RSDP *rsdp=NULL; - ACPI_2_0_RSDT *rsdt=NULL; - ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE *madt; + struct acpi_20_rsdt *rsdt; + struct acpi_20_madt *madt; - rsdp = (ACPI_2_0_RSDP *)(acpi_start + sizeof(ACPI_2_0_FACS)); - if (rsdp->Signature != ACPI_2_0_RSDP_SIGNATURE) { - puts("Bad RSDP signature\n"); - return NULL; - } + rsdt = acpi_rsdt_get(acpi_start); + if (rsdt == NULL) + return NULL; - rsdt= (ACPI_2_0_RSDT *) - (acpi_start + rsdp->RsdtAddress - ACPI_PHYSICAL_ADDRESS); - if (rsdt->Header.Signature != ACPI_2_0_RSDT_SIGNATURE) { - puts("Bad RSDT signature\n"); - return NULL; - } + madt = (struct acpi_20_madt *)(acpi_start + rsdt->entry[1] - + ACPI_PHYSICAL_ADDRESS); + if (madt->header.header.signature != ACPI_2_0_MADT_SIGNATURE) { + puts("Bad MADT signature \n"); + return NULL; + } - madt = (ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE *) - ( acpi_start+ rsdt->Entry[1] - ACPI_PHYSICAL_ADDRESS); - if (madt->Header.Header.Signature != - ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE) { - puts("Bad MADT signature \n"); - return NULL; - } - - return madt; -} - -static void -set_checksum(void *start, int checksum_offset, int len) -{ - unsigned char sum = 0; - unsigned char *ptr; - - ptr = start; - ptr[checksum_offset] = 0; - while (len--) - sum += *ptr++; - - ptr = start; - ptr[checksum_offset] = -sum; + return madt; } static int acpi_madt_set_local_apics( - int nr_vcpu, - ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE *madt) + int nr_vcpu, + struct acpi_20_madt *madt) { - int i; + int i; - if ((nr_vcpu > MAX_VIRT_CPUS) || (nr_vcpu < 0) || !madt) - return -1; + if ((nr_vcpu > MAX_VIRT_CPUS) || (nr_vcpu < 0) || !madt) + return -1; - for (i = 0; i < nr_vcpu; i++) { - madt->LocalApic[i].Type = ACPI_PROCESSOR_LOCAL_APIC; - madt->LocalApic[i].Length = sizeof (ACPI_LOCAL_APIC_STRUCTURE); - madt->LocalApic[i].AcpiProcessorId = i; - madt->LocalApic[i].ApicId = i; - madt->LocalApic[i].Flags = 1; - } + for (i = 0; i < nr_vcpu; i++) { + madt->lapic[i].type = ACPI_PROCESSOR_LOCAL_APIC; + madt->lapic[i].length = sizeof(struct acpi_20_madt_lapic); + madt->lapic[i].acpi_processor_id = i; + madt->lapic[i].apic_id = i; + madt->lapic[i].flags = 1; + } - madt->Header.Header.Length = - sizeof(ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE) - - (MAX_VIRT_CPUS - nr_vcpu)* sizeof(ACPI_LOCAL_APIC_STRUCTURE); + madt->header.header.length = + sizeof(struct acpi_20_madt) - + (MAX_VIRT_CPUS - nr_vcpu) * sizeof(struct acpi_20_madt_lapic); - return 0; + return 0; } #define FIELD_OFFSET(TYPE,Field) ((unsigned int)(&(((TYPE *) 0)->Field))) int acpi_madt_update(unsigned char *acpi_start) { - int rc; - ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE *madt; + int rc; + struct acpi_20_madt *madt; - madt = acpi_madt_get_madt(acpi_start); - if (!madt) - return -1; + madt = acpi_madt_get_madt(acpi_start); + if (!madt) + return -1; - rc = acpi_madt_set_local_apics(get_vcpu_nr(), madt); - if (rc != 0) - return rc; + rc = acpi_madt_set_local_apics(get_vcpu_nr(), madt); + if (rc != 0) + return rc; - set_checksum( - madt, FIELD_OFFSET(ACPI_TABLE_HEADER, Checksum), - madt->Header.Header.Length); + set_checksum( + madt, FIELD_OFFSET(struct acpi_header, checksum), + madt->header.header.length); - return 0; + return 0; } /* * Local variables: - * c-file-style: "linux" - * indent-tabs-mode: t - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil * End: */ diff -r 11b718eb22c9 -r ebed72718263 tools/firmware/hvmloader/hvmloader.c --- a/tools/firmware/hvmloader/hvmloader.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/firmware/hvmloader/hvmloader.c Fri Nov 10 11:11:04 2006 -0700 @@ -22,9 +22,10 @@ * Place - Suite 330, Boston, MA 02111-1307 USA. */ #include "roms.h" -#include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */ +#include "acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */ #include "hypercall.h" #include "util.h" +#include "acpi_utils.h" #include "smbios.h" #include <xen/version.h> #include <xen/hvm/params.h> @@ -164,8 +165,6 @@ int int main(void) { - struct xen_hvm_param hvm_param; - puts("HVM Loader\n"); init_hypercalls(); @@ -176,10 +175,7 @@ main(void) puts("Loading ROMBIOS ...\n"); memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios)); - hvm_param.domid = DOMID_SELF; - hvm_param.index = HVM_PARAM_APIC_ENABLED; - if (!hypercall_hvm_op(HVMOP_get_param, &hvm_param) && hvm_param.value) - create_mp_tables(); + create_mp_tables(); if (cirrus_check()) { puts("Loading Cirrus VGABIOS ...\n"); @@ -195,12 +191,18 @@ main(void) puts("Loading ACPI ...\n"); acpi_madt_update((unsigned char *) acpi); if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000) { + unsigned char *freemem = (unsigned char *) + (ACPI_PHYSICAL_ADDRESS + sizeof(acpi)); /* * Make sure acpi table does not overlap rombios * currently acpi less than 8K will be OK. */ memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi, sizeof(acpi)); + acpi_update((unsigned char *)ACPI_PHYSICAL_ADDRESS, + sizeof(acpi), + (unsigned char *)0xF0000, + &freemem); } } diff -r 11b718eb22c9 -r ebed72718263 tools/firmware/hvmloader/util.c --- a/tools/firmware/hvmloader/util.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/firmware/hvmloader/util.c Fri Nov 10 11:11:04 2006 -0700 @@ -18,7 +18,7 @@ * Place - Suite 330, Boston, MA 02111-1307 USA. */ -#include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */ +#include "acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */ #include "util.h" #include <stdint.h> @@ -227,4 +227,5 @@ uuid_to_string(char *dest, uint8_t *uuid byte_to_hex(p, uuid[i]); p += 2; } -} + *p = 0; +} diff -r 11b718eb22c9 -r ebed72718263 tools/firmware/vmxassist/setup.c --- a/tools/firmware/vmxassist/setup.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/firmware/vmxassist/setup.c Fri Nov 10 11:11:04 2006 -0700 @@ -53,13 +53,10 @@ struct e820entry e820map[] = { struct e820entry e820map[] = { { 0x0000000000000000ULL, 0x000000000009F800ULL, E820_RAM }, { 0x000000000009F800ULL, 0x0000000000000800ULL, E820_RESERVED }, - { 0x00000000000A0000ULL, 0x0000000000020000ULL, E820_IO }, { 0x00000000000C0000ULL, 0x0000000000040000ULL, E820_RESERVED }, { 0x0000000000100000ULL, 0x0000000000000000ULL, E820_RAM }, - { 0x0000000000000000ULL, 0x0000000000001000ULL, E820_SHARED_PAGE }, { 0x0000000000000000ULL, 0x0000000000003000ULL, E820_NVS }, { 0x0000000000003000ULL, 0x000000000000A000ULL, E820_ACPI }, - { 0x00000000FEC00000ULL, 0x0000000001400000ULL, E820_IO }, }; #endif /* TEST */ diff -r 11b718eb22c9 -r ebed72718263 tools/firmware/vmxassist/vm86.c --- a/tools/firmware/vmxassist/vm86.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/firmware/vmxassist/vm86.c Fri Nov 10 11:11:04 2006 -0700 @@ -867,6 +867,18 @@ load_seg(unsigned long sel, uint32_t *ba } /* + * Emulate a protected mode segment load, falling back to clearing it if + * the descriptor was invalid. + */ +static void +load_or_clear_seg(unsigned long sel, uint32_t *base, uint32_t *limit, union vmcs_arbytes *arbytes) +{ + if (!load_seg(sel, base, limit, arbytes)) + load_seg(0, base, limit, arbytes); +} + + +/* * Transition to protected mode */ static void @@ -877,8 +889,6 @@ protected_mode(struct regs *regs) oldctx.eip = regs->eip; oldctx.esp = regs->uesp; oldctx.eflags = regs->eflags; - - memset(&saved_rm_regs, 0, sizeof(struct regs)); /* reload all segment registers */ if (!load_seg(regs->cs, &oldctx.cs_base, @@ -886,55 +896,16 @@ protected_mode(struct regs *regs) panic("Invalid %%cs=0x%x for protected mode\n", regs->cs); oldctx.cs_sel = regs->cs; - if (load_seg(regs->ves, &oldctx.es_base, - &oldctx.es_limit, &oldctx.es_arbytes)) - oldctx.es_sel = regs->ves; - else { - load_seg(0, &oldctx.es_base, - &oldctx.es_limit, &oldctx.es_arbytes); - oldctx.es_sel = 0; - saved_rm_regs.ves = regs->ves; - } - - if (load_seg(regs->uss, &oldctx.ss_base, - &oldctx.ss_limit, &oldctx.ss_arbytes)) - oldctx.ss_sel = regs->uss; - else { - load_seg(0, &oldctx.ss_base, - &oldctx.ss_limit, &oldctx.ss_arbytes); - oldctx.ss_sel = 0; - saved_rm_regs.uss = regs->uss; - } - - if (load_seg(regs->vds, &oldctx.ds_base, - &oldctx.ds_limit, &oldctx.ds_arbytes)) - oldctx.ds_sel = regs->vds; - else { - load_seg(0, &oldctx.ds_base, - &oldctx.ds_limit, &oldctx.ds_arbytes); - oldctx.ds_sel = 0; - saved_rm_regs.vds = regs->vds; - } - - if (load_seg(regs->vfs, &oldctx.fs_base, - &oldctx.fs_limit, &oldctx.fs_arbytes)) - oldctx.fs_sel = regs->vfs; - else { - load_seg(0, &oldctx.fs_base, - &oldctx.fs_limit, &oldctx.fs_arbytes); - oldctx.fs_sel = 0; - saved_rm_regs.vfs = regs->vfs; - } - - if (load_seg(regs->vgs, &oldctx.gs_base, - &oldctx.gs_limit, &oldctx.gs_arbytes)) - oldctx.gs_sel = regs->vgs; - else { - load_seg(0, &oldctx.gs_base, - &oldctx.gs_limit, &oldctx.gs_arbytes); - oldctx.gs_sel = 0; - saved_rm_regs.vgs = regs->vgs; - } + load_or_clear_seg(oldctx.es_sel, &oldctx.es_base, + &oldctx.es_limit, &oldctx.es_arbytes); + load_or_clear_seg(oldctx.ss_sel, &oldctx.ss_base, + &oldctx.ss_limit, &oldctx.ss_arbytes); + load_or_clear_seg(oldctx.ds_sel, &oldctx.ds_base, + &oldctx.ds_limit, &oldctx.ds_arbytes); + load_or_clear_seg(oldctx.fs_sel, &oldctx.fs_base, + &oldctx.fs_limit, &oldctx.fs_arbytes); + load_or_clear_seg(oldctx.gs_sel, &oldctx.gs_base, + &oldctx.gs_limit, &oldctx.gs_arbytes); /* initialize jump environment to warp back to protected mode */ regs->cs = CODE_SELECTOR; @@ -1022,6 +993,16 @@ set_mode(struct regs *regs, enum vm86_mo case VM86_REAL_TO_PROTECTED: if (mode == VM86_REAL) { regs->eflags |= EFLAGS_TF; + saved_rm_regs.vds = regs->vds; + saved_rm_regs.ves = regs->ves; + saved_rm_regs.vfs = regs->vfs; + saved_rm_regs.vgs = regs->vgs; + saved_rm_regs.uss = regs->uss; + oldctx.ds_sel = 0; + oldctx.es_sel = 0; + oldctx.fs_sel = 0; + oldctx.gs_sel = 0; + oldctx.ss_sel = 0; break; } else if (mode == VM86_REAL_TO_PROTECTED) { break; @@ -1282,6 +1263,10 @@ opcode(struct regs *regs) else regs->ves = pop16(regs); TRACE((regs, regs->eip - eip, "pop %%es")); + if (mode == VM86_REAL_TO_PROTECTED) { + saved_rm_regs.ves = 0; + oldctx.es_sel = regs->ves; + } return OPC_EMULATED; case 0x0F: /* two byte opcode */ diff -r 11b718eb22c9 -r ebed72718263 tools/ioemu/Makefile.target --- a/tools/ioemu/Makefile.target Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/ioemu/Makefile.target Fri Nov 10 11:11:04 2006 -0700 @@ -368,6 +368,7 @@ VL_OBJS+= piix4acpi.o VL_OBJS+= piix4acpi.o VL_OBJS+= xenstore.o VL_OBJS+= xen_platform.o +VL_OBJS+= tpm_tis.o DEFINES += -DHAS_AUDIO endif ifeq ($(TARGET_BASE_ARCH), ppc) diff -r 11b718eb22c9 -r ebed72718263 tools/ioemu/hw/ne2000.c --- a/tools/ioemu/hw/ne2000.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/ioemu/hw/ne2000.c Fri Nov 10 11:11:04 2006 -0700 @@ -137,6 +137,7 @@ typedef struct NE2000State { uint8_t curpag; uint8_t mult[8]; /* multicast mask array */ int irq; + int tainted; PCIDevice *pci_dev; VLANClientState *vc; uint8_t macaddr[6]; @@ -226,6 +227,27 @@ static int ne2000_can_receive(void *opaq #define MIN_BUF_SIZE 60 +static inline int ne2000_valid_ring_addr(NE2000State *s, unsigned int addr) +{ + addr <<= 8; + return addr < s->stop && addr >= s->start; +} + +static inline int ne2000_check_state(NE2000State *s) +{ + if (!s->tainted) + return 0; + + if (s->start >= s->stop || s->stop > NE2000_MEM_SIZE) + return -EINVAL; + + if (!ne2000_valid_ring_addr(s, s->curpag)) + return -EINVAL; + + s->tainted = 0; + return 0; +} + static void ne2000_receive(void *opaque, const uint8_t *buf, int size) { NE2000State *s = opaque; @@ -238,6 +260,12 @@ static void ne2000_receive(void *opaque, #if defined(DEBUG_NE2000) printf("NE2000: received len=%d\n", size); #endif + + if (ne2000_check_state(s)) + return; + + if (!ne2000_valid_ring_addr(s, s->boundary)) + return; if (s->cmd & E8390_STOP || ne2000_buffer_full(s)) return; @@ -359,9 +387,11 @@ static void ne2000_ioport_write(void *op switch(offset) { case EN0_STARTPG: s->start = val << 8; + s->tainted = 1; break; case EN0_STOPPG: s->stop = val << 8; + s->tainted = 1; break; case EN0_BOUNDARY: s->boundary = val; @@ -406,6 +436,7 @@ static void ne2000_ioport_write(void *op break; case EN1_CURPAG: s->curpag = val; + s->tainted = 1; break; case EN1_MULT ... EN1_MULT + 7: s->mult[offset - EN1_MULT] = val; @@ -509,7 +540,7 @@ static inline void ne2000_mem_writel(NE2 { addr &= ~1; /* XXX: check exact behaviour if not even */ if (addr < 32 || - (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE - 2)) { cpu_to_le32wu((uint32_t *)(s->mem + addr), val); } } @@ -539,7 +570,7 @@ static inline uint32_t ne2000_mem_readl( { addr &= ~1; /* XXX: check exact behaviour if not even */ if (addr < 32 || - (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE - 2)) { return le32_to_cpupu((uint32_t *)(s->mem + addr)); } else { return 0xffffffff; diff -r 11b718eb22c9 -r ebed72718263 tools/ioemu/hw/pc.c --- a/tools/ioemu/hw/pc.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/ioemu/hw/pc.c Fri Nov 10 11:11:04 2006 -0700 @@ -875,6 +875,9 @@ static void pc_init1(uint64_t ram_size, } } + if (has_tpm_device()) + tpm_tis_init(&pic_set_irq_new, isa_pic, 11); + kbd_init(); DMA_init(0); #ifdef HAS_AUDIO diff -r 11b718eb22c9 -r ebed72718263 tools/ioemu/hw/serial.c --- a/tools/ioemu/hw/serial.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/ioemu/hw/serial.c Fri Nov 10 11:11:04 2006 -0700 @@ -93,6 +93,15 @@ struct SerialState { int last_break_enable; target_ulong base; int it_shift; + + /* + * If a character transmitted via UART cannot be written to its + * destination immediately we remember it here and retry a few times via + * a polling timer. + */ + int write_retries; + char write_chr; + QEMUTimer *write_retry_timer; }; static void serial_update_irq(SerialState *s) @@ -204,10 +213,32 @@ static void serial_get_token(void) tokens_avail--; } +static void serial_chr_write(void *opaque) +{ + SerialState *s = opaque; + + qemu_del_timer(s->write_retry_timer); + + /* Retry every 100ms for 300ms total. */ + if (qemu_chr_write(s->chr, &s->write_chr, 1) == -1) { + if (s->write_retries++ >= 3) + printf("serial: write error\n"); + else + qemu_mod_timer(s->write_retry_timer, + qemu_get_clock(vm_clock) + ticks_per_sec / 10); + return; + } + + /* Success: Notify guest that THR is empty. */ + s->thr_ipending = 1; + s->lsr |= UART_LSR_THRE; + s->lsr |= UART_LSR_TEMT; + serial_update_irq(s); +} + static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) { SerialState *s = opaque; - unsigned char ch; addr &= 7; #ifdef DEBUG_SERIAL @@ -223,12 +254,9 @@ static void serial_ioport_write(void *op s->thr_ipending = 0; s->lsr &= ~UART_LSR_THRE; serial_update_irq(s); - ch = val; - qemu_chr_write(s->chr, &ch, 1); - s->thr_ipending = 1; - s->lsr |= UART_LSR_THRE; - s->lsr |= UART_LSR_TEMT; - serial_update_irq(s); + s->write_chr = val; + s->write_retries = 0; + serial_chr_write(s); } break; case 1: @@ -424,6 +452,7 @@ SerialState *serial_init(SetIRQFunc *set s->lsr = UART_LSR_TEMT | UART_LSR_THRE; s->iir = UART_IIR_NO_INT; s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS; + s->write_retry_timer = qemu_new_timer(vm_clock, serial_chr_write, s); register_savevm("serial", base, 1, serial_save, serial_load, s); @@ -511,6 +540,7 @@ SerialState *serial_mm_init (SetIRQFunc s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS; s->base = base; s->it_shift = it_shift; + s->write_retry_timer = qemu_new_timer(vm_clock, serial_chr_write, s); register_savevm("serial", base, 1, serial_save, serial_load, s); diff -r 11b718eb22c9 -r ebed72718263 tools/ioemu/keymaps/ja --- a/tools/ioemu/keymaps/ja Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/ioemu/keymaps/ja Fri Nov 10 11:11:04 2006 -0700 @@ -102,3 +102,6 @@ Henkan_Mode 0x79 Henkan_Mode 0x79 Katakana 0x70 Muhenkan 0x7b +Henkan_Mode_Real 0x79 +Henkan_Mode_Ultra 0x79 +backslash_ja 0x73 diff -r 11b718eb22c9 -r ebed72718263 tools/ioemu/target-i386-dm/cpu.h --- a/tools/ioemu/target-i386-dm/cpu.h Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/ioemu/target-i386-dm/cpu.h Fri Nov 10 11:11:04 2006 -0700 @@ -55,8 +55,6 @@ typedef struct CPUX86State { int interrupt_request; CPU_COMMON - - int send_event; } CPUX86State; CPUX86State *cpu_x86_init(void); diff -r 11b718eb22c9 -r ebed72718263 tools/ioemu/target-i386-dm/exec-dm.c --- a/tools/ioemu/target-i386-dm/exec-dm.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/ioemu/target-i386-dm/exec-dm.c Fri Nov 10 11:11:04 2006 -0700 @@ -32,6 +32,8 @@ #include <unistd.h> #include <inttypes.h> +#include <xen/hvm/e820.h> + #include "cpu.h" #include "exec-all.h" @@ -407,22 +409,36 @@ int iomem_index(target_phys_addr_t addr) return 0; } +static inline int paddr_is_ram(target_phys_addr_t addr) +{ + /* Is this guest physical address RAM-backed? */ +#if defined(CONFIG_DM) && (defined(__i386__) || defined(__x86_64__)) + if (ram_size <= HVM_BELOW_4G_RAM_END) + /* RAM is contiguous */ + return (addr < ram_size); + else + /* There is RAM below and above the MMIO hole */ + return ((addr < HVM_BELOW_4G_MMIO_START) || + ((addr >= HVM_BELOW_4G_MMIO_START + HVM_BELOW_4G_MMIO_LENGTH) + && (addr < ram_size + HVM_BELOW_4G_MMIO_LENGTH))); +#else + return (addr < ram_size); +#endif +} + void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, int len, int is_write) { int l, io_index; uint8_t *ptr; uint32_t val; - target_phys_addr_t page; - unsigned long pd; while (len > 0) { - page = addr & TARGET_PAGE_MASK; - l = (page + TARGET_PAGE_SIZE) - addr; + /* How much can we copy before the next page boundary? */ + l = TARGET_PAGE_SIZE - (addr & ~TARGET_PAGE_MASK); if (l > len) l = len; - pd = page; io_index = iomem_index(addr); if (is_write) { if (io_index) { @@ -442,15 +458,11 @@ void cpu_physical_memory_rw(target_phys_ io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val); l = 1; } - } else { - unsigned long addr1; - - addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); - /* RAM case */ - ptr = phys_ram_base + addr1; - memcpy(ptr, buf, l); + } else if (paddr_is_ram(addr)) { + /* Reading from RAM */ + memcpy(phys_ram_base + addr, buf, l); #ifdef __ia64__ - sync_icache((unsigned long)ptr, l); + sync_icache((unsigned long)(phys_ram_base + addr), l); #endif } } else { @@ -471,14 +483,12 @@ void cpu_physical_memory_rw(target_phys_ stb_raw(buf, val); l = 1; } - } else if (addr < ram_size) { - /* RAM case */ - ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + - (addr & ~TARGET_PAGE_MASK); - memcpy(buf, ptr, l); + } else if (paddr_is_ram(addr)) { + /* Reading from RAM */ + memcpy(buf, phys_ram_base + addr, l); } else { - /* unreported MMIO space */ - memset(buf, 0xff, len); + /* Neither RAM nor known MMIO space */ + memset(buf, 0xff, len); } } len -= l; diff -r 11b718eb22c9 -r ebed72718263 tools/ioemu/target-i386-dm/helper2.c --- a/tools/ioemu/target-i386-dm/helper2.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/ioemu/target-i386-dm/helper2.c Fri Nov 10 11:11:04 2006 -0700 @@ -193,10 +193,10 @@ void sp_info() for (i = 0; i < vcpus; i++) { req = &(shared_page->vcpu_iodata[i].vp_ioreq); term_printf("vcpu %d: event port %d\n", i, ioreq_local_port[i]); - term_printf(" req state: %x, pvalid: %x, addr: %"PRIx64", " + term_printf(" req state: %x, ptr: %x, addr: %"PRIx64", " "data: %"PRIx64", count: %"PRIx64", size: %"PRIx64"\n", - req->state, req->pdata_valid, req->addr, - req->u.data, req->count, req->size); + req->state, req->data_is_ptr, req->addr, + req->data, req->count, req->size); term_printf(" IO totally occurred on this vcpu: %"PRIx64"\n", req->io_count); } @@ -209,18 +209,19 @@ static ioreq_t *__cpu_get_ioreq(int vcpu req = &(shared_page->vcpu_iodata[vcpu].vp_ioreq); - if (req->state == STATE_IOREQ_READY) { - req->state = STATE_IOREQ_INPROCESS; - rmb(); - return req; - } - - fprintf(logfile, "False I/O request ... in-service already: " - "%x, pvalid: %x, port: %"PRIx64", " - "data: %"PRIx64", count: %"PRIx64", size: %"PRIx64"\n", - req->state, req->pdata_valid, req->addr, - req->u.data, req->count, req->size); - return NULL; + if (req->state != STATE_IOREQ_READY) { + fprintf(logfile, "I/O request not ready: " + "%x, ptr: %x, port: %"PRIx64", " + "data: %"PRIx64", count: %"PRIx64", size: %"PRIx64"\n", + req->state, req->data_is_ptr, req->addr, + req->data, req->count, req->size); + return NULL; + } + + rmb(); /* see IOREQ_READY /then/ read contents of ioreq */ + + req->state = STATE_IOREQ_INPROCESS; + return req; } //use poll to get the port notification @@ -305,26 +306,26 @@ void cpu_ioreq_pio(CPUState *env, ioreq_ sign = req->df ? -1 : 1; if (req->dir == IOREQ_READ) { - if (!req->pdata_valid) { - req->u.data = do_inp(env, req->addr, req->size); + if (!req->data_is_ptr) { + req->data = do_inp(env, req->addr, req->size); } else { unsigned long tmp; for (i = 0; i < req->count; i++) { tmp = do_inp(env, req->addr, req->size); - write_physical((target_phys_addr_t) req->u.pdata + write_physical((target_phys_addr_t) req->data + (sign * i * req->size), req->size, &tmp); } } } else if (req->dir == IOREQ_WRITE) { - if (!req->pdata_valid) { - do_outp(env, req->addr, req->size, req->u.data); + if (!req->data_is_ptr) { + do_outp(env, req->addr, req->size, req->data); } else { for (i = 0; i < req->count; i++) { unsigned long tmp; - read_physical((target_phys_addr_t) req->u.pdata + read_physical((target_phys_addr_t) req->data + (sign * i * req->size), req->size, &tmp); do_outp(env, req->addr, req->size, tmp); @@ -339,18 +340,18 @@ void cpu_ioreq_move(CPUState *env, ioreq sign = req->df ? -1 : 1; - if (!req->pdata_valid) { + if (!req->data_is_ptr) { if (req->dir == IOREQ_READ) { for (i = 0; i < req->count; i++) { read_physical(req->addr + (sign * i * req->size), - req->size, &req->u.data); + req->size, &req->data); } } else if (req->dir == IOREQ_WRITE) { for (i = 0; i < req->count; i++) { write_physical(req->addr + (sign * i * req->size), - req->size, &req->u.data); + req->size, &req->data); } } } else { @@ -361,13 +362,13 @@ void cpu_ioreq_move(CPUState *env, ioreq read_physical(req->addr + (sign * i * req->size), req->size, &tmp); - write_physical((target_phys_addr_t )req->u.pdata + write_physical((target_phys_addr_t )req->data + (sign * i * req->size), req->size, &tmp); } } else if (req->dir == IOREQ_WRITE) { for (i = 0; i < req->count; i++) { - read_physical((target_phys_addr_t) req->u.pdata + read_physical((target_phys_addr_t) req->data + (sign * i * req->size), req->size, &tmp); write_physical(req->addr @@ -382,51 +383,66 @@ void cpu_ioreq_and(CPUState *env, ioreq_ { unsigned long tmp1, tmp2; - if (req->pdata_valid != 0) + if (req->data_is_ptr != 0) hw_error("expected scalar value"); read_physical(req->addr, req->size, &tmp1); if (req->dir == IOREQ_WRITE) { - tmp2 = tmp1 & (unsigned long) req->u.data; + tmp2 = tmp1 & (unsigned long) req->data; write_physical(req->addr, req->size, &tmp2); } - req->u.data = tmp1; -} - -void cpu_ioreq_or(CPUState *env, ioreq_t *req) + req->data = tmp1; +} + +void cpu_ioreq_add(CPUState *env, ioreq_t *req) { unsigned long tmp1, tmp2; - if (req->pdata_valid != 0) + if (req->data_is_ptr != 0) hw_error("expected scalar value"); read_physical(req->addr, req->size, &tmp1); if (req->dir == IOREQ_WRITE) { - tmp2 = tmp1 | (unsigned long) req->u.data; + tmp2 = tmp1 + (unsigned long) req->data; write_physical(req->addr, req->size, &tmp2); } - req->u.data = tmp1; -} - -void cpu_ioreq_xor(CPUState *env, ioreq_t *req) + req->data = tmp1; +} + +void cpu_ioreq_or(CPUState *env, ioreq_t *req) { unsigned long tmp1, tmp2; - if (req->pdata_valid != 0) + if (req->data_is_ptr != 0) hw_error("expected scalar value"); read_physical(req->addr, req->size, &tmp1); if (req->dir == IOREQ_WRITE) { - tmp2 = tmp1 ^ (unsigned long) req->u.data; + tmp2 = tmp1 | (unsigned long) req->data; write_physical(req->addr, req->size, &tmp2); } - req->u.data = tmp1; + req->data = tmp1; +} + +void cpu_ioreq_xor(CPUState *env, ioreq_t *req) +{ + unsigned long tmp1, tmp2; + + if (req->data_is_ptr != 0) + hw_error("expected scalar value"); + + read_physical(req->addr, req->size, &tmp1); + if (req->dir == IOREQ_WRITE) { + tmp2 = tmp1 ^ (unsigned long) req->data; + write_physical(req->addr, req->size, &tmp2); + } + req->data = tmp1; } void __handle_ioreq(CPUState *env, ioreq_t *req) { - if (!req->pdata_valid && req->dir == IOREQ_WRITE && req->size != 4) - req->u.data &= (1UL << (8 * req->size)) - 1; + if (!req->data_is_ptr && req->dir == IOREQ_WRITE && req->size != 4) + req->data &= (1UL << (8 * req->size)) - 1; switch (req->type) { case IOREQ_TYPE_PIO: @@ -437,6 +453,9 @@ void __handle_ioreq(CPUState *env, ioreq break; case IOREQ_TYPE_AND: cpu_ioreq_and(env, req); + break; + case IOREQ_TYPE_ADD: + cpu_ioreq_add(env, req); break; case IOREQ_TYPE_OR: cpu_ioreq_or(env, req); @@ -486,12 +505,19 @@ void cpu_handle_ioreq(void *opaque) if (req) { __handle_ioreq(env, req); - /* No state change if state = STATE_IORESP_HOOK */ - if (req->state == STATE_IOREQ_INPROCESS) { - mb(); - req->state = STATE_IORESP_READY; - } - env->send_event = 1; + if (req->state != STATE_IOREQ_INPROCESS) { + fprintf(logfile, "Badness in I/O request ... not in service?!: " + "%x, ptr: %x, port: %"PRIx64", " + "data: %"PRIx64", count: %"PRIx64", size: %"PRIx64"\n", + req->state, req->data_is_ptr, req->addr, + req->data, req->count, req->size); + destroy_hvm_domain(); + return; + } + + wmb(); /* Update ioreq contents /then/ update state. */ + req->state = STATE_IORESP_READY; + xc_evtchn_notify(xce_handle, ioreq_local_port[send_vcpu]); } } @@ -507,8 +533,6 @@ int main_loop(void) qemu_mod_timer(buffered_io_timer, qemu_get_clock(rt_clock)); qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env); - - env->send_event = 0; while (1) { if (vm_running) { @@ -522,11 +546,6 @@ int main_loop(void) /* Wait up to 10 msec. */ main_loop_wait(10); - - if (env->send_event) { - env->send_event = 0; - xc_evtchn_notify(xce_handle, ioreq_local_port[send_vcpu]); - } } destroy_hvm_domain(); return 0; diff -r 11b718eb22c9 -r ebed72718263 tools/ioemu/target-i386-dm/i8259-dm.c --- a/tools/ioemu/target-i386-dm/i8259-dm.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/ioemu/target-i386-dm/i8259-dm.c Fri Nov 10 11:11:04 2006 -0700 @@ -22,58 +22,18 @@ * THE SOFTWARE. */ #include "vl.h" - -/* debug PIC */ -//#define DEBUG_PIC - -//#define DEBUG_IRQ_LATENCY -//#define DEBUG_IRQ_COUNT - #include "xenctrl.h" #include <xen/hvm/ioreq.h> #include <stdio.h> #include "cpu.h" #include "cpu-all.h" -extern shared_iopage_t *shared_page; - struct PicState2 { }; void pic_set_irq_new(void *opaque, int irq, int level) { - /* PicState2 *s = opaque; */ - global_iodata_t *gio; - int mask; - - gio = &shared_page->sp_global; - mask = 1 << irq; - if ( gio->pic_elcr & mask ) { - /* level */ - if ( level ) { - atomic_clear_bit(irq, &gio->pic_clear_irr); - atomic_set_bit(irq, &gio->pic_irr); - cpu_single_env->send_event = 1; - } - else { - atomic_clear_bit(irq, &gio->pic_irr); - atomic_set_bit(irq, &gio->pic_clear_irr); - cpu_single_env->send_event = 1; - } - } - else { - /* edge */ - if ( level ) { - if ( (mask & gio->pic_last_irr) == 0 ) { - atomic_set_bit(irq, &gio->pic_irr); - atomic_set_bit(irq, &gio->pic_last_irr); - cpu_single_env->send_event = 1; - } - } - else { - atomic_clear_bit(irq, &gio->pic_last_irr); - } - } + xc_hvm_set_irq_level(xc_handle, domid, irq, level); } /* obsolete function */ diff -r 11b718eb22c9 -r ebed72718263 tools/ioemu/target-i386-dm/qemu-dm.debug --- a/tools/ioemu/target-i386-dm/qemu-dm.debug Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/ioemu/target-i386-dm/qemu-dm.debug Fri Nov 10 11:11:04 2006 -0700 @@ -1,5 +1,10 @@ #!/bin/sh +if [ "`arch`" = "x86_64" ]; then + LIBDIR="lib64" +else + LIBDIR="lib" +fi echo $* > /tmp/args echo $DISPLAY >> /tmp/args -exec /usr/lib/xen/bin/qemu-dm $* +exec /usr/$LIBDIR/xen/bin/qemu-dm $* diff -r 11b718eb22c9 -r ebed72718263 tools/ioemu/vl.c --- a/tools/ioemu/vl.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/ioemu/vl.c Fri Nov 10 11:11:04 2006 -0700 @@ -1684,7 +1684,7 @@ static void tty_serial_init(int fd, int tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |INLCR|IGNCR|ICRNL|IXON); - tty.c_oflag |= OPOST; + tty.c_oflag &= ~OPOST; /* no output mangling of raw serial stream */ tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG); tty.c_cflag &= ~(CSIZE|PARENB|PARODD|CRTSCTS); switch(data_bits) { @@ -6390,17 +6390,17 @@ int main(int argc, char **argv) exit(1); } - /* init the memory */ - phys_ram_size = ram_size + vga_ram_size + bios_size; - -#ifdef CONFIG_DM - - xc_handle = xc_interface_open(); - #if defined (__ia64__) if (ram_size > MMIO_START) ram_size += 1 * MEM_G; /* skip 3G-4G MMIO, LEGACY_IO_SPACE etc. */ #endif + + /* init the memory */ + phys_ram_size = ram_size + vga_ram_size + bios_size; + +#ifdef CONFIG_DM + + xc_handle = xc_interface_open(); nr_pages = ram_size/PAGE_SIZE; tmp_nr_pages = nr_pages; @@ -6420,14 +6420,13 @@ int main(int argc, char **argv) } #if defined(__i386__) || defined(__x86_64__) - if (xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages) { + for ( i = 0; i < tmp_nr_pages; i++) + page_array[i] = i; + if (xc_domain_translate_gpfn_list(xc_handle, domid, tmp_nr_pages, + page_array, page_array)) { fprintf(logfile, "xc_get_pfn_list returned error %d\n", errno); exit(-1); } - - if (ram_size > HVM_BELOW_4G_RAM_END) - for (i = 0; i < nr_pages - (HVM_BELOW_4G_RAM_END >> PAGE_SHIFT); i++) - page_array[tmp_nr_pages - 1 - i] = page_array[nr_pages - 1 - i]; phys_ram_base = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE, page_array, diff -r 11b718eb22c9 -r ebed72718263 tools/ioemu/vl.h --- a/tools/ioemu/vl.h Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/ioemu/vl.h Fri Nov 10 11:11:04 2006 -0700 @@ -929,6 +929,10 @@ void piix4_pm_init(PCIBus *bus, int devf void piix4_pm_init(PCIBus *bus, int devfn); void acpi_bios_init(void); +/* tpm_tis.c */ +int has_tpm_device(void); +void tpm_tis_init(SetIRQFunc *set_irq, void *irq_opaque, int irq); + /* piix4acpi.c */ extern void pci_piix4_acpi_init(PCIBus *bus, int devfn); @@ -1213,6 +1217,25 @@ void xenstore_write_vncport(int vnc_disp void xenstore_write_vncport(int vnc_display); int xenstore_read_vncpasswd(int domid); +int xenstore_domain_has_devtype(struct xs_handle *handle, + const char *devtype); +char **xenstore_domain_get_devices(struct xs_handle *handle, + const char *devtype, unsigned int *num); +char *xenstore_read_hotplug_status(struct xs_handle *handle, + const char *devtype, const char *inst); +char *xenstore_backend_read_variable(struct xs_handle *, + const char *devtype, const char *inst, + const char *var); +int xenstore_subscribe_to_hotplug_status(struct xs_handle *handle, + const char *devtype, + const char *inst, + const char *token); +int xenstore_unsubscribe_from_hotplug_status(struct xs_handle *handle, + const char *devtype, + const char *inst, + const char *token); + + /* xen_platform.c */ void pci_xen_platform_init(PCIBus *bus); diff -r 11b718eb22c9 -r ebed72718263 tools/ioemu/vnc_keysym.h --- a/tools/ioemu/vnc_keysym.h Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/ioemu/vnc_keysym.h Fri Nov 10 11:11:04 2006 -0700 @@ -271,5 +271,15 @@ static name2keysym_t name2keysym[]={ {"Num_Lock", 0xff7f}, /* XK_Num_Lock */ {"Pause", 0xff13}, /* XK_Pause */ {"Escape", 0xff1b}, /* XK_Escape */ + + /* localized keys */ +{"BackApostrophe", 0xff21}, +{"Muhenkan", 0xff22}, +{"Katakana", 0xff25}, +{"Zenkaku_Hankaku", 0xff29}, +{"Henkan_Mode_Real", 0xff23}, +{"Henkan_Mode_Ultra", 0xff3e}, +{"backslash_ja", 0xffa5}, + {0,0}, }; diff -r 11b718eb22c9 -r ebed72718263 tools/ioemu/xenstore.c --- a/tools/ioemu/xenstore.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/ioemu/xenstore.c Fri Nov 10 11:11:04 2006 -0700 @@ -264,3 +264,140 @@ int xenstore_read_vncpasswd(int domid) return rc; } + + +/* + * get all device instances of a certain type + */ +char **xenstore_domain_get_devices(struct xs_handle *handle, + const char *devtype, unsigned int *num) +{ + char *path; + char *buf = NULL; + char **e = NULL; + + path = xs_get_domain_path(handle, domid); + if (path == NULL) + goto out; + + if (pasprintf(&buf, "%s/device/%s", path,devtype) == -1) + goto out; + + e = xs_directory(handle, XBT_NULL, buf, num); + + out: + free(path); + free(buf); + return e; +} + +/* + * Check whether a domain has devices of the given type + */ +int xenstore_domain_has_devtype(struct xs_handle *handle, const char *devtype) +{ + int rc = 0; + unsigned int num; + char **e = xenstore_domain_get_devices(handle, devtype, &num); + if (e) + rc = 1; + free(e); + return rc; +} + +/* + * Function that creates a path to a variable of an instance of a + * certain device + */ +static char *get_device_variable_path(const char *devtype, const char *inst, + const char *var) +{ + char *buf = NULL; + if (pasprintf(&buf, "/local/domain/0/backend/%s/%d/%s/%s", + devtype, + domid, + inst, + var) == -1) { + free(buf); + buf = NULL; + } + return buf; +} + +char *xenstore_backend_read_variable(struct xs_handle *handle, + const char *devtype, const char *inst, + const char *var) +{ + char *value = NULL; + char *buf = NULL; + unsigned int len; + + buf = get_device_variable_path(devtype, inst, var); + if (NULL == buf) + goto out; + + value = xs_read(handle, XBT_NULL, buf, &len); + + free(buf); + +out: + return value; +} + +/* + Read the hotplug status variable from the backend given the type + of device and its instance. +*/ +char *xenstore_read_hotplug_status(struct xs_handle *handle, + const char *devtype, const char *inst) +{ + return xenstore_backend_read_variable(handle, devtype, inst, + "hotplug-status"); +} + +/* + Subscribe to the hotplug status of a device given the type of device and + its instance. + In case an error occurrs, a negative number is returned. + */ +int xenstore_subscribe_to_hotplug_status(struct xs_handle *handle, + const char *devtype, + const char *inst, + const char *token) +{ + int rc = 0; + char *path = get_device_variable_path(devtype, inst, "hotplug-status"); + + if (path == NULL) + return -1; + + if (0 == xs_watch(handle, path, token)) + rc = -2; + + free(path); + + return rc; +} + +/* + * Unsubscribe from a subscription to the status of a hotplug variable of + * a device. + */ +int xenstore_unsubscribe_from_hotplug_status(struct xs_handle *handle, + const char *devtype, + const char *inst, + const char *token) +{ + int rc = 0; + char *path; + path = get_device_variable_path(devtype, inst, "hotplug-status"); + if (path == NULL) + return -1; + + if (0 == xs_unwatch(handle, path, token)) + rc = -2; + + free(path); + + return rc; +} diff -r 11b718eb22c9 -r ebed72718263 tools/libxc/ia64/xc_ia64_hvm_build.c --- a/tools/libxc/ia64/xc_ia64_hvm_build.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/libxc/ia64/xc_ia64_hvm_build.c Fri Nov 10 11:11:04 2006 -0700 @@ -618,7 +618,7 @@ int int xc_hvm_build(int xc_handle, uint32_t domid, int memsize, const char *image_name, unsigned int vcpus, unsigned int pae, - unsigned int acpi, unsigned int apic, unsigned int store_evtchn, + unsigned int acpi, unsigned int store_evtchn, unsigned long *store_mfn) { struct xen_domctl launch_domctl, domctl; diff -r 11b718eb22c9 -r ebed72718263 tools/libxc/xc_core.c --- a/tools/libxc/xc_core.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/libxc/xc_core.c Fri Nov 10 11:11:04 2006 -0700 @@ -62,7 +62,7 @@ xc_domain_dumpcore_via_callback(int xc_h nr_pages = info.nr_pages; - header.xch_magic = XC_CORE_MAGIC; + header.xch_magic = info.hvm ? XC_CORE_MAGIC_HVM : XC_CORE_MAGIC; header.xch_nr_vcpus = nr_vcpus; header.xch_nr_pages = nr_pages; header.xch_ctxt_offset = sizeof(struct xc_core_header); diff -r 11b718eb22c9 -r ebed72718263 tools/libxc/xc_domain.c --- a/tools/libxc/xc_domain.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/libxc/xc_domain.c Fri Nov 10 11:11:04 2006 -0700 @@ -12,6 +12,7 @@ int xc_domain_create(int xc_handle, int xc_domain_create(int xc_handle, uint32_t ssidref, xen_domain_handle_t handle, + uint32_t flags, uint32_t *pdomid) { int err; @@ -20,6 +21,7 @@ int xc_domain_create(int xc_handle, domctl.cmd = XEN_DOMCTL_createdomain; domctl.domain = (domid_t)*pdomid; domctl.u.createdomain.ssidref = ssidref; + domctl.u.createdomain.flags = flags; memcpy(domctl.u.createdomain.handle, handle, sizeof(xen_domain_handle_t)); if ( (err = do_domctl(xc_handle, &domctl)) != 0 ) return err; @@ -169,15 +171,16 @@ int xc_domain_getinfo(int xc_handle, break; info->domid = (uint16_t)domctl.domain; - info->dying = !!(domctl.u.getdomaininfo.flags & DOMFLAGS_DYING); - info->shutdown = !!(domctl.u.getdomaininfo.flags & DOMFLAGS_SHUTDOWN); - info->paused = !!(domctl.u.getdomaininfo.flags & DOMFLAGS_PAUSED); - info->blocked = !!(domctl.u.getdomaininfo.flags & DOMFLAGS_BLOCKED); - info->running = !!(domctl.u.getdomaininfo.flags & DOMFLAGS_RUNNING); + info->dying = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_dying); + info->shutdown = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_shutdown); + info->paused = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_paused); + info->blocked = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_blocked); + info->running = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_running); + info->hvm = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_hvm_guest); info->shutdown_reason = - (domctl.u.getdomaininfo.flags>>DOMFLAGS_SHUTDOWNSHIFT) & - DOMFLAGS_SHUTDOWNMASK; + (domctl.u.getdomaininfo.flags>>XEN_DOMINF_shutdownshift) & + XEN_DOMINF_shutdownmask; if ( info->shutdown && (info->shutdown_reason == SHUTDOWN_crash) ) { @@ -200,7 +203,8 @@ int xc_domain_getinfo(int xc_handle, info++; } - if( !nr_doms ) return rc; + if ( nr_doms == 0 ) + return rc; return nr_doms; } @@ -345,7 +349,7 @@ int xc_domain_memory_increase_reservatio if ( err == nr_extents ) return 0; - if ( err > 0 ) + if ( err >= 0 ) { DPRINTF("Failed allocation for dom %d: " "%ld pages order %d addr_bits %d\n", @@ -384,11 +388,11 @@ int xc_domain_memory_decrease_reservatio if ( err == nr_extents ) return 0; - if ( err > 0 ) + if ( err >= 0 ) { DPRINTF("Failed deallocation for dom %d: %ld pages order %d\n", domid, nr_extents, extent_order); - errno = EBUSY; + errno = EINVAL; err = -1; } @@ -415,7 +419,7 @@ int xc_domain_memory_populate_physmap(in if ( err == nr_extents ) return 0; - if ( err > 0 ) + if ( err >= 0 ) { DPRINTF("Failed allocation for dom %d: %ld pages order %d\n", domid, nr_extents, extent_order); diff -r 11b718eb22c9 -r ebed72718263 tools/libxc/xc_hvm_build.c --- a/tools/libxc/xc_hvm_build.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/libxc/xc_hvm_build.c Fri Nov 10 11:11:04 2006 -0700 @@ -12,7 +12,6 @@ #include <unistd.h> #include <zlib.h> #include <xen/hvm/hvm_info_table.h> -#include <xen/hvm/ioreq.h> #include <xen/hvm/params.h> #include <xen/hvm/e820.h> @@ -57,88 +56,67 @@ static void build_e820map(void *e820_pag unsigned char nr_map = 0; /* - * physical address space from HVM_BELOW_4G_RAM_END to 4G is reserved + * Physical address space from HVM_BELOW_4G_RAM_END to 4G is reserved * for PCI devices MMIO. So if HVM has more than HVM_BELOW_4G_RAM_END * RAM, memory beyond HVM_BELOW_4G_RAM_END will go to 4G above. */ - if ( mem_size > HVM_BELOW_4G_RAM_END ) { + if ( mem_size > HVM_BELOW_4G_RAM_END ) + { extra_mem_size = mem_size - HVM_BELOW_4G_RAM_END; mem_size = HVM_BELOW_4G_RAM_END; } + /* 0x0-0x9F000: Ordinary RAM. */ e820entry[nr_map].addr = 0x0; e820entry[nr_map].size = 0x9F000; e820entry[nr_map].type = E820_RAM; nr_map++; + /* + * 0x9F000-0x9F800: SMBIOS tables. + * 0x9FC00-0xA0000: Extended BIOS Data Area (EBDA). + * TODO: SMBIOS tables should be moved higher (>=0xE0000). + * They are unusually low in our memory map: could cause problems? + */ e820entry[nr_map].addr = 0x9F000; e820entry[nr_map].size = 0x1000; e820entry[nr_map].type = E820_RESERVED; nr_map++; - e820entry[nr_map].addr = 0xA0000; + /* + * Following regions are standard regions of the PC memory map. + * They are not covered by e820 regions. OSes will not use as RAM. + * 0xA0000-0xC0000: VGA memory-mapped I/O. Not covered by E820. + * 0xC0000-0xE0000: 16-bit devices, expansion ROMs (inc. vgabios). + * TODO: hvmloader should free pages which turn out to be unused. + */ + + /* + * 0xE0000-0x0F0000: PC-specific area. We place ACPI tables here. + * We *cannot* mark as E820_ACPI, for two reasons: + * 1. ACPI spec. says that E820_ACPI regions below + * 16MB must clip INT15h 0x88 and 0xe801 queries. + * Our rombios doesn't do this. + * 2. The OS is allowed to reclaim ACPI memory after + * parsing the tables. But our FACS is in this + * region and it must not be reclaimed (it contains + * the ACPI global lock!). + * 0xF0000-0x100000: System BIOS. + * TODO: hvmloader should free pages which turn out to be unused. + */ + e820entry[nr_map].addr = 0xE0000; e820entry[nr_map].size = 0x20000; - e820entry[nr_map].type = E820_IO; - nr_map++; - - e820entry[nr_map].addr = 0xEA000; - e820entry[nr_map].size = 0x01000; - e820entry[nr_map].type = E820_ACPI; - nr_map++; - - e820entry[nr_map].addr = 0xF0000; - e820entry[nr_map].size = 0x10000; e820entry[nr_map].type = E820_RESERVED; nr_map++; -/* buffered io page. */ -#define BUFFERED_IO_PAGES 1 -/* xenstore page. */ -#define XENSTORE_PAGES 1 -/* shared io page. */ -#define SHARED_IO_PAGES 1 -/* totally 16 static pages are reserved in E820 table */ - - /* Most of the ram goes here */ + /* Low RAM goes here. Remove 3 pages for ioreq, bufioreq, and xenstore. */ e820entry[nr_map].addr = 0x100000; - e820entry[nr_map].size = mem_size - 0x100000 - PAGE_SIZE * - (BUFFERED_IO_PAGES + - XENSTORE_PAGES + - SHARED_IO_PAGES); + e820entry[nr_map].size = mem_size - 0x100000 - PAGE_SIZE * 3; e820entry[nr_map].type = E820_RAM; nr_map++; - /* Statically allocated special pages */ - - /* For buffered IO requests */ - e820entry[nr_map].addr = mem_size - PAGE_SIZE * - (BUFFERED_IO_PAGES + - XENSTORE_PAGES + - SHARED_IO_PAGES); - e820entry[nr_map].size = PAGE_SIZE * BUFFERED_IO_PAGES; - e820entry[nr_map].type = E820_BUFFERED_IO; - nr_map++; - - /* For xenstore */ - e820entry[nr_map].addr = mem_size - PAGE_SIZE * - (XENSTORE_PAGES + - SHARED_IO_PAGES); - e820entry[nr_map].size = PAGE_SIZE * XENSTORE_PAGES; - e820entry[nr_map].type = E820_XENSTORE; - nr_map++; - - /* Shared ioreq_t page */ - e820entry[nr_map].addr = mem_size - PAGE_SIZE * SHARED_IO_PAGES; - e820entry[nr_map].size = PAGE_SIZE * SHARED_IO_PAGES; - e820entry[nr_map].type = E820_SHARED_PAGE; - nr_map++; - - e820entry[nr_map].addr = 0xFEC00000; - e820entry[nr_map].size = 0x1400000; - e820entry[nr_map].type = E820_IO; - nr_map++; - - if ( extra_mem_size ) { + if ( extra_mem_size ) + { e820entry[nr_map].addr = (1ULL << 32); e820entry[nr_map].size = extra_mem_size; e820entry[nr_map].type = E820_RAM; @@ -197,28 +175,22 @@ static int setup_guest(int xc_handle, static int setup_guest(int xc_handle, uint32_t dom, int memsize, char *image, unsigned long image_size, - unsigned long nr_pages, vcpu_guest_context_t *ctxt, unsigned long shared_info_frame, unsigned int vcpus, unsigned int pae, unsigned int acpi, - unsigned int apic, unsigned int store_evtchn, unsigned long *store_mfn) { xen_pfn_t *page_array = NULL; - unsigned long count, i; - unsigned long long ptr; - xc_mmu_t *mmu = NULL; - + unsigned long i, nr_pages = (unsigned long)memsize << (20 - PAGE_SHIFT); + unsigned long shared_page_nr; shared_info_t *shared_info; void *e820_page; - struct domain_setup_info dsi; uint64_t v_end; - - unsigned long shared_page_nr; + int rc; memset(&dsi, 0, sizeof(struct domain_setup_info)); @@ -231,7 +203,6 @@ static int setup_guest(int xc_handle, goto error_out; } - /* memsize is in megabytes */ v_end = (unsigned long long)memsize << 20; IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n" @@ -256,40 +227,33 @@ static int setup_guest(int xc_handle, goto error_out; } - if ( xc_get_pfn_list(xc_handle, dom, page_array, nr_pages) != nr_pages ) - { - PERROR("Could not get the page frame list.\n"); + for ( i = 0; i < nr_pages; i++ ) + page_array[i] = i; + for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < nr_pages; i++ ) + page_array[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT; + + /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */ + rc = xc_domain_memory_populate_physmap( + xc_handle, dom, (nr_pages > 0xa0) ? 0xa0 : nr_pages, + 0, 0, &page_array[0x00]); + if ( (rc == 0) && (nr_pages > 0xc0) ) + rc = xc_domain_memory_populate_physmap( + xc_handle, dom, nr_pages - 0xc0, 0, 0, &page_array[0xc0]); + if ( rc != 0 ) + { + PERROR("Could not allocate memory for HVM guest.\n"); + goto error_out; + } + + if ( xc_domain_translate_gpfn_list(xc_handle, dom, nr_pages, + page_array, page_array) ) + { + PERROR("Could not translate addresses of HVM guest.\n"); goto error_out; } loadelfimage(image, xc_handle, dom, page_array, &dsi); - if ( (mmu = xc_init_mmu_updates(xc_handle, dom)) == NULL ) - goto error_out; - - /* Write the machine->phys table entries. */ - for ( count = 0; count < nr_pages; count++ ) - { - unsigned long gpfn_count_skip; - - ptr = (unsigned long long)page_array[count] << PAGE_SHIFT; - - gpfn_count_skip = 0; - - /* - * physical address space from HVM_BELOW_4G_RAM_END to 4G is reserved - * for PCI devices MMIO. So if HVM has more than HVM_BELOW_4G_RAM_END - * RAM, memory beyond HVM_BELOW_4G_RAM_END will go to 4G above. - */ - if ( count >= (HVM_BELOW_4G_RAM_END >> PAGE_SHIFT) ) - gpfn_count_skip = HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT; - - if ( xc_add_mmu_update(xc_handle, mmu, - ptr | MMU_MACHPHYS_UPDATE, - count + gpfn_count_skip) ) - goto error_out; - } - if ( set_hvm_info(xc_handle, dom, page_array, vcpus, acpi) ) { ERROR("Couldn't set hvm info for HVM guest.\n"); @@ -297,7 +261,6 @@ static int setup_guest(int xc_handle, } xc_set_hvm_param(xc_handle, dom, HVM_PARAM_PAE_ENABLED, pae); - xc_set_hvm_param(xc_handle, dom, HVM_PARAM_APIC_ENABLED, apic); if ( (e820_page = xc_map_foreign_range( xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, @@ -316,6 +279,8 @@ static int setup_guest(int xc_handle, /* Mask all upcalls... */ for ( i = 0; i < MAX_VIRT_CPUS; i++ ) shared_info->vcpu_info[i].evtchn_upcall_mask = 1; + memset(&shared_info->evtchn_mask[0], 0xff, + sizeof(shared_info->evtchn_mask)); munmap(shared_info, PAGE_SIZE); if ( v_end > HVM_BELOW_4G_RAM_END ) @@ -323,39 +288,25 @@ static int setup_guest(int xc_handle, else shared_page_nr = (v_end >> PAGE_SHIFT) - 1; + /* Paranoia: clean pages. */ + if ( xc_clear_domain_page(xc_handle, dom, page_array[shared_page_nr]) || + xc_clear_domain_page(xc_handle, dom, page_array[shared_page_nr-1]) || + xc_clear_domain_page(xc_handle, dom, page_array[shared_page_nr-2]) ) + goto error_out; + *store_mfn = page_array[shared_page_nr - 1]; - - xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, shared_page_nr - 1); + xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, shared_page_nr-1); xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_EVTCHN, store_evtchn); - - /* Paranoia */ - /* clean the shared IO requests page */ - if ( xc_clear_domain_page(xc_handle, dom, page_array[shared_page_nr]) ) - goto error_out; - - /* clean the buffered IO requests page */ - if ( xc_clear_domain_page(xc_handle, dom, page_array[shared_page_nr - 2]) ) - goto error_out; - - if ( xc_clear_domain_page(xc_handle, dom, *store_mfn) ) - goto error_out; - - /* Send the page update requests down to the hypervisor. */ - if ( xc_finish_mmu_updates(xc_handle, mmu) ) - goto error_out; - - free(mmu); + xc_set_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN, shared_page_nr-2); + xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, shared_page_nr); + free(page_array); - /* - * Initial register values: - */ ctxt->user_regs.eip = dsi.v_kernentry; return 0; error_out: - free(mmu); free(page_array); return -1; } @@ -368,45 +319,17 @@ static int xc_hvm_build_internal(int xc_ unsigned int vcpus, unsigned int pae, unsigned int acpi, - unsigned int apic, unsigned int store_evtchn, unsigned long *store_mfn) { struct xen_domctl launch_domctl, domctl; - int rc, i; - vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt; - unsigned long nr_pages; - xen_capabilities_info_t xen_caps; + vcpu_guest_context_t ctxt; + int rc; if ( (image == NULL) || (image_size == 0) ) { ERROR("Image required"); goto error_out; - } - - if ( (rc = xc_version(xc_handle, XENVER_capabilities, &xen_caps)) != 0 ) - { - PERROR("Failed to get xen version info"); - goto error_out; - } - - if ( !strstr(xen_caps, "hvm") ) - { - PERROR("CPU doesn't support HVM extensions or " - "the extensions are not enabled"); - goto error_out; - } - - if ( (nr_pages = xc_get_tot_pages(xc_handle, domid)) < 0 ) - { - PERROR("Could not find total pages for domain"); - goto error_out; - } - - if ( lock_pages(&st_ctxt, sizeof(st_ctxt) ) ) - { - PERROR("%s: ctxt mlock failed", __func__); - return 1; } domctl.cmd = XEN_DOMCTL_getdomaininfo; @@ -418,68 +341,30 @@ static int xc_hvm_build_internal(int xc_ goto error_out; } - /* HVM domains must be put into shadow mode at the start of day */ - if ( xc_shadow_control(xc_handle, domid, XEN_DOMCTL_SHADOW_OP_ENABLE, - NULL, 0, NULL, - XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT | - XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE | - XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL, - NULL) ) - { - PERROR("Could not enable shadow paging for domain.\n"); - goto error_out; - } - - memset(ctxt, 0, sizeof(*ctxt)); - - ctxt->flags = VGCF_HVM_GUEST; - if ( setup_guest(xc_handle, domid, memsize, image, image_size, nr_pages, - ctxt, domctl.u.getdomaininfo.shared_info_frame, - vcpus, pae, acpi, apic, store_evtchn, store_mfn) < 0) + memset(&ctxt, 0, sizeof(ctxt)); + + if ( setup_guest(xc_handle, domid, memsize, image, image_size, + &ctxt, domctl.u.getdomaininfo.shared_info_frame, + vcpus, pae, acpi, store_evtchn, store_mfn) < 0) { ERROR("Error constructing guest OS"); goto error_out; } - /* FPU is set up to default initial state. */ - memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt)); - - /* Virtual IDT is empty at start-of-day. */ - for ( i = 0; i < 256; i++ ) - { - ctxt->trap_ctxt[i].vector = i; - ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS; - } - - /* No LDT. */ - ctxt->ldt_ents = 0; - - /* Use the default Xen-provided GDT. */ - ctxt->gdt_ents = 0; - - /* No debugging. */ - memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg)); - - /* No callback handlers. */ -#if defined(__i386__) - ctxt->event_callback_cs = FLAT_KERNEL_CS; - ctxt->event_callback_eip = 0; - ctxt->failsafe_callback_cs = FLAT_KERNEL_CS; - ctxt->failsafe_callback_eip = 0; -#elif defined(__x86_64__) - ctxt->event_callback_eip = 0; - ctxt->failsafe_callback_eip = 0; - ctxt->syscall_callback_eip = 0; -#endif + if ( lock_pages(&ctxt, sizeof(ctxt) ) ) + { + PERROR("%s: ctxt mlock failed", __func__); + goto error_out; + } memset(&launch_domctl, 0, sizeof(launch_domctl)); - launch_domctl.domain = (domid_t)domid; launch_domctl.u.vcpucontext.vcpu = 0; - set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, ctxt); - + set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, &ctxt); launch_domctl.cmd = XEN_DOMCTL_setvcpucontext; rc = xc_domctl(xc_handle, &launch_domctl); + + unlock_pages(&ctxt, sizeof(ctxt)); return rc; @@ -626,7 +511,6 @@ int xc_hvm_build(int xc_handle, unsigned int vcpus, unsigned int pae, unsigned int acpi, - unsigned int apic, unsigned int store_evtchn, unsigned long *store_mfn) { @@ -640,7 +524,7 @@ int xc_hvm_build(int xc_handle, sts = xc_hvm_build_internal(xc_handle, domid, memsize, image, image_size, - vcpus, pae, acpi, apic, + vcpus, pae, acpi, store_evtchn, store_mfn); free(image); @@ -662,7 +546,6 @@ int xc_hvm_build_mem(int xc_handle, unsigned int vcpus, unsigned int pae, unsigned int acpi, - unsigned int apic, unsigned int store_evtchn, unsigned long *store_mfn) { @@ -687,7 +570,7 @@ int xc_hvm_build_mem(int xc_handle, sts = xc_hvm_build_internal(xc_handle, domid, memsize, img, img_len, - vcpus, pae, acpi, apic, + vcpus, pae, acpi, store_evtchn, store_mfn); /* xc_inflate_buffer may return the original buffer pointer (for diff -r 11b718eb22c9 -r ebed72718263 tools/libxc/xc_linux_build.c --- a/tools/libxc/xc_linux_build.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/libxc/xc_linux_build.c Fri Nov 10 11:11:04 2006 -0700 @@ -25,17 +25,16 @@ #define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) #endif -#ifdef __ia64__ -#define get_tot_pages xc_get_max_pages -#else -#define get_tot_pages xc_get_tot_pages -#endif - #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) #define round_pgdown(_p) ((_p)&PAGE_MASK) struct initrd_info { enum { INITRD_none, INITRD_file, INITRD_mem } type; + /* + * .len must be filled in by the user for type==INITRD_mem. It is + * filled in by load_initrd() for INITRD_file and unused for + * INITRD_none. + */ unsigned long len; union { gzFile file_handle; @@ -134,30 +133,42 @@ static int load_initrd(int xc_handle, do xen_pfn_t *phys_to_mach) { char page[PAGE_SIZE]; - unsigned long pfn_start, pfn, nr_pages; + unsigned long pfn_start, pfn; if ( initrd->type == INITRD_none ) return 0; pfn_start = physbase >> PAGE_SHIFT; - nr_pages = (initrd->len + PAGE_SIZE - 1) >> PAGE_SHIFT; - - for ( pfn = pfn_start; pfn < (pfn_start + nr_pages); pfn++ ) - { - if ( initrd->type == INITRD_mem ) + + if ( initrd->type == INITRD_mem ) + { + unsigned long nr_pages = (initrd->len + PAGE_SIZE - 1) >> PAGE_SHIFT; + + for ( pfn = pfn_start; pfn < (pfn_start + nr_pages); pfn++ ) { xc_copy_to_domain_page( xc_handle, dom, phys_to_mach[pfn], &initrd->u.mem_addr[(pfn - pfn_start) << PAGE_SHIFT]); } - else - { - if ( gzread(initrd->u.file_handle, page, PAGE_SIZE) == -1 ) + } + else + { + int readlen; + + pfn = pfn_start; + initrd->len = 0; + + /* gzread returns 0 on EOF */ + while ( (readlen = gzread(initrd->u.file_handle, page, PAGE_SIZE)) ) + { + if ( readlen < 0 ) { PERROR("Error reading initrd image, could not"); return -EINVAL; } - xc_copy_to_domain_page(xc_handle, dom, phys_to_mach[pfn], page); + + initrd->len += readlen; + xc_copy_to_domain_page(xc_handle, dom, phys_to_mach[pfn++], page); } } @@ -485,10 +496,17 @@ static int setup_guest(int xc_handle, if ( rc != 0 ) goto error_out; - dsi.v_start = round_pgdown(dsi.v_start); - vinitrd_start = round_pgup(dsi.v_end); - vinitrd_end = vinitrd_start + initrd->len; - v_end = round_pgup(vinitrd_end); + dsi.v_start = round_pgdown(dsi.v_start); + (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array, + &dsi); + + vinitrd_start = round_pgup(dsi.v_end); + if ( load_initrd(xc_handle, dom, initrd, + vinitrd_start - dsi.v_start, page_array) ) + goto error_out; + + vinitrd_end = vinitrd_start + initrd->len; + v_end = round_pgup(vinitrd_end); start_info_mpa = (nr_pages - 3) << PAGE_SHIFT; /* Build firmware. */ @@ -524,13 +542,6 @@ static int setup_guest(int xc_handle, _p(vinitrd_start), _p(vinitrd_end), _p(dsi.v_start), _p(v_end)); IPRINTF(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry)); - - (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array, - &dsi); - - if ( load_initrd(xc_handle, dom, initrd, - vinitrd_start - dsi.v_start, page_array) ) - goto error_out; *pvke = dsi.v_kernentry; @@ -657,7 +668,6 @@ static int setup_guest(int xc_handle, int hypercall_page_defined; start_info_t *start_info; shared_info_t *shared_info; - xc_mmu_t *mmu = NULL; const char *p; DECLARE_DOMCTL; int rc; @@ -699,7 +709,7 @@ static int setup_guest(int xc_handle, goto error_out; } - if (!compat_check(xc_handle, &dsi)) + if ( !compat_check(xc_handle, &dsi) ) goto error_out; /* Parse and validate kernel features. */ @@ -727,6 +737,28 @@ static int setup_guest(int xc_handle, shadow_mode_enabled = test_feature_bit(XENFEAT_auto_translated_physmap, required_features); + + if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL ) + { + PERROR("Could not allocate memory"); + goto error_out; + } + + for ( i = 0; i < nr_pages; i++ ) + page_array[i] = i; + + if ( xc_domain_memory_populate_physmap(xc_handle, dom, nr_pages, + 0, 0, page_array) ) + { + PERROR("Could not allocate memory for PV guest.\n"); + goto error_out; + } + + rc = (load_funcs.loadimage)(image, image_size, + xc_handle, dom, page_array, + &dsi); + if ( rc != 0 ) + goto error_out; /* * Why do we need this? The number of page-table frames depends on the @@ -741,9 +773,14 @@ static int setup_guest(int xc_handle, ERROR("End of mapped kernel image too close to end of memory"); goto error_out; } + vinitrd_start = v_end; + if ( load_initrd(xc_handle, dom, initrd, + vinitrd_start - dsi.v_start, page_array) ) + goto error_out; if ( !increment_ulong(&v_end, round_pgup(initrd->len)) ) goto error_out; + vphysmap_start = v_end; if ( !increment_ulong(&v_end, round_pgup(nr_pages * sizeof(long))) ) goto error_out; @@ -845,31 +882,8 @@ static int setup_guest(int xc_handle, goto error_out; } - if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL ) - { - PERROR("Could not allocate memory"); - goto error_out; - } - - if ( xc_get_pfn_list(xc_handle, dom, page_array, nr_pages) != nr_pages ) - { - PERROR("Could not get the page frame list"); - goto error_out; - } - - rc = (load_funcs.loadimage)(image, image_size, - xc_handle, dom, page_array, - &dsi); - if ( rc != 0 ) - goto error_out; - - if ( load_initrd(xc_handle, dom, initrd, - vinitrd_start - dsi.v_start, page_array) ) - goto error_out; - - /* setup page tables */ #if defined(__i386__) - if (dsi.pae_kernel != PAEKERN_no) + if ( dsi.pae_kernel != PAEKERN_no ) rc = setup_pg_tables_pae(xc_handle, dom, ctxt, dsi.v_start, v_end, page_array, vpt_start, vpt_end, @@ -886,16 +900,16 @@ static int setup_guest(int xc_handle, page_array, vpt_start, vpt_end, shadow_mode_enabled); #endif - if (0 != rc) - goto error_out; - -#if defined(__i386__) + if ( rc != 0 ) + goto error_out; + /* * Pin down l2tab addr as page dir page - causes hypervisor to provide * correct protection for the page */ if ( !shadow_mode_enabled ) { +#if defined(__i386__) if ( dsi.pae_kernel != PAEKERN_no ) { if ( pin_table(xc_handle, MMUEXT_PIN_L3_TABLE, @@ -908,40 +922,24 @@ static int setup_guest(int xc_handle, xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) ) goto error_out; } - } +#elif defined(__x86_64__) + /* + * Pin down l4tab addr as page dir page - causes hypervisor to provide + * correct protection for the page + */ + if ( pin_table(xc_handle, MMUEXT_PIN_L4_TABLE, + xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) ) + goto error_out; #endif - -#if defined(__x86_64__) - /* - * Pin down l4tab addr as page dir page - causes hypervisor to provide - * correct protection for the page - */ - if ( pin_table(xc_handle, MMUEXT_PIN_L4_TABLE, - xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) ) - goto error_out; -#endif - - if ( (mmu = xc_init_mmu_updates(xc_handle, dom)) == NULL ) - goto error_out; - - /* Write the phys->machine and machine->phys table entries. */ + } + + /* Write the phys->machine table entries (machine->phys already done). */ physmap_pfn = (vphysmap_start - dsi.v_start) >> PAGE_SHIFT; physmap = physmap_e = xc_map_foreign_range( xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, page_array[physmap_pfn++]); - for ( count = 0; count < nr_pages; count++ ) { - if ( xc_add_mmu_update( - xc_handle, mmu, - ((uint64_t)page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, - count) ) - { - DPRINTF("m2p update failure p=%lx m=%"PRIx64"\n", - count, (uint64_t)page_array[count]); - munmap(physmap, PAGE_SIZE); - goto error_out; - } *physmap_e++ = page_array[count]; if ( ((unsigned long)physmap_e & (PAGE_SIZE-1)) == 0 ) { @@ -952,10 +950,6 @@ static int setup_guest(int xc_handle, } } munmap(physmap, PAGE_SIZE); - - /* Send the page update requests down to the hypervisor. */ - if ( xc_finish_mmu_updates(xc_handle, mmu) ) - goto error_out; if ( shadow_mode_enabled ) { @@ -1063,10 +1057,6 @@ static int setup_guest(int xc_handle, munmap(shared_info, PAGE_SIZE); - /* Send the page update requests down to the hypervisor. */ - if ( xc_finish_mmu_updates(xc_handle, mmu) ) - goto error_out; - hypercall_page = xen_elfnote_numeric(&dsi, XEN_ELFNOTE_HYPERCALL_PAGE, &hypercall_page_defined); if ( hypercall_page_defined ) @@ -1082,7 +1072,6 @@ static int setup_guest(int xc_handle, goto error_out; } - free(mmu); free(page_array); *pvsi = vstartinfo_start; @@ -1092,7 +1081,6 @@ static int setup_guest(int xc_handle, return 0; error_out: - free(mmu); free(page_array); return -1; } @@ -1100,6 +1088,7 @@ static int setup_guest(int xc_handle, static int xc_linux_build_internal(int xc_handle, uint32_t domid, + unsigned int mem_mb, char *image, unsigned long image_size, struct initrd_info *initrd, @@ -1114,8 +1103,7 @@ static int xc_linux_build_internal(int x struct xen_domctl launch_domctl; DECLARE_DOMCTL; int rc, i; - vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt; - unsigned long nr_pages; + struct vcpu_guest_context st_ctxt, *ctxt = &st_ctxt; unsigned long vstartinfo_start, vkern_entry, vstack_start; uint32_t features_bitmap[XENFEAT_NR_SUBMAPS] = { 0, }; @@ -1126,12 +1114,6 @@ static int xc_linux_build_internal(int x PERROR("Failed to parse configured features\n"); goto error_out; } - } - - if ( (nr_pages = get_tot_pages(xc_handle, domid)) < 0 ) - { - PERROR("Could not find total pages for domain"); - goto error_out; } #ifdef VALGRIND @@ -1157,7 +1139,7 @@ static int xc_linux_build_internal(int x if ( setup_guest(xc_handle, domid, image, image_size, initrd, - nr_pages, + mem_mb << (20 - PAGE_SHIFT), &vstartinfo_start, &vkern_entry, &vstack_start, ctxt, cmdline, domctl.u.getdomaininfo.shared_info_frame, @@ -1253,6 +1235,7 @@ static int xc_linux_build_internal(int x int xc_linux_build_mem(int xc_handle, uint32_t domid, + unsigned int mem_mb, const char *image_buffer, unsigned long image_size, const char *initrd, @@ -1301,7 +1284,7 @@ int xc_linux_build_mem(int xc_handle, } } - sts = xc_linux_build_internal(xc_handle, domid, img_buf, img_len, + sts = xc_linux_build_internal(xc_handle, domid, mem_mb, img_buf, img_len, &initrd_info, cmdline, features, flags, store_evtchn, store_mfn, console_evtchn, console_mfn); @@ -1321,6 +1304,7 @@ int xc_linux_build_mem(int xc_handle, int xc_linux_build(int xc_handle, uint32_t domid, + unsigned int mem_mb, const char *image_name, const char *initrd_name, const char *cmdline, @@ -1350,7 +1334,6 @@ int xc_linux_build(int xc_handle, goto error_out; } - initrd_info.len = xc_get_filesz(fd); if ( (initrd_info.u.file_handle = gzdopen(fd, "rb")) == NULL ) { PERROR("Could not allocate decompression state for initrd"); @@ -1358,7 +1341,7 @@ int xc_linux_build(int xc_handle, } } - sts = xc_linux_build_internal(xc_handle, domid, image, image_size, + sts = xc_linux_build_internal(xc_handle, domid, mem_mb, image, image_size, &initrd_info, cmdline, features, flags, store_evtchn, store_mfn, console_evtchn, console_mfn); diff -r 11b718eb22c9 -r ebed72718263 tools/libxc/xc_linux_save.c --- a/tools/libxc/xc_linux_save.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/libxc/xc_linux_save.c Fri Nov 10 11:11:04 2006 -0700 @@ -978,12 +978,14 @@ int xc_linux_save(int xc_handle, int io_ } if(!write_exact(io_fd, &batch, sizeof(unsigned int))) { - ERROR("Error when writing to state file (2)"); + ERROR("Error when writing to state file (2) (errno %d)", + errno); goto out; } if(!write_exact(io_fd, pfn_type, sizeof(unsigned long)*j)) { - ERROR("Error when writing to state file (3)"); + ERROR("Error when writing to state file (3) (errno %d)", + errno); goto out; } @@ -1013,7 +1015,8 @@ int xc_linux_save(int xc_handle, int io_ goto out; if (ratewrite(io_fd, page, PAGE_SIZE) != PAGE_SIZE) { - ERROR("Error when writing to state file (4)"); + ERROR("Error when writing to state file (4)" + " (errno %d)", errno); goto out; } @@ -1021,7 +1024,8 @@ int xc_linux_save(int xc_handle, int io_ /* We have a normal page: just write it directly. */ if (ratewrite(io_fd, spage, PAGE_SIZE) != PAGE_SIZE) { - ERROR("Error when writing to state file (5)"); + ERROR("Error when writing to state file (5)" + " (errno %d)", errno); goto out; } } @@ -1056,7 +1060,8 @@ int xc_linux_save(int xc_handle, int io_ /* send "-1" to put receiver into debug mode */ if(!write_exact(io_fd, &minusone, sizeof(int))) { - ERROR("Error when writing to state file (6)"); + ERROR("Error when writing to state file (6) (errno %d)", + errno); goto out; } @@ -1110,7 +1115,7 @@ int xc_linux_save(int xc_handle, int io_ /* Zero terminate */ i = 0; if (!write_exact(io_fd, &i, sizeof(int))) { - ERROR("Error when writing to state file (6)"); + ERROR("Error when writing to state file (6') (errno %d)", errno); goto out; } @@ -1125,7 +1130,7 @@ int xc_linux_save(int xc_handle, int io_ } if(!write_exact(io_fd, &j, sizeof(unsigned int))) { - ERROR("Error when writing to state file (6a)"); + ERROR("Error when writing to state file (6a) (errno %d)", errno); goto out; } @@ -1137,7 +1142,8 @@ int xc_linux_save(int xc_handle, int io_ i++; if (j == 1024 || i == max_pfn) { if(!write_exact(io_fd, &pfntab, sizeof(unsigned long)*j)) { - ERROR("Error when writing to state file (6b)"); + ERROR("Error when writing to state file (6b) (errno %d)", + errno); goto out; } j = 0; @@ -1170,7 +1176,7 @@ int xc_linux_save(int xc_handle, int io_ if (!write_exact(io_fd, &ctxt, sizeof(ctxt)) || !write_exact(io_fd, live_shinfo, PAGE_SIZE)) { - ERROR("Error when writing to state file (1)"); + ERROR("Error when writing to state file (1) (errno %d)", errno); goto out; } diff -r 11b718eb22c9 -r ebed72718263 tools/libxc/xc_misc.c --- a/tools/libxc/xc_misc.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/libxc/xc_misc.c Fri Nov 10 11:11:04 2006 -0700 @@ -5,6 +5,7 @@ */ #include "xc_private.h" +#include <xen/hvm/hvm_op.h> int xc_readconsolering(int xc_handle, char **pbuffer, @@ -89,6 +90,33 @@ int xc_perfc_control(int xc_handle, return rc; } +int xc_hvm_set_irq_level(int xc_handle, domid_t dom, int irq, int level) +{ + DECLARE_HYPERCALL; + struct xen_hvm_set_irq_level arg; + int rc; + + hypercall.op = __HYPERVISOR_hvm_op; + hypercall.arg[0] = HVMOP_set_irq_level; + hypercall.arg[1] = (unsigned long)&arg; + + arg.domid = dom; + arg.irq = irq; + arg.level = level; + + if ( mlock(&arg, sizeof(arg)) != 0 ) + { + PERROR("Could not lock memory"); + return -1; + } + + rc = do_xen_hypercall(xc_handle, &hypercall); + + safe_munlock(&arg, sizeof(arg)); + + return rc; +} + /* * Local variables: * mode: C diff -r 11b718eb22c9 -r ebed72718263 tools/libxc/xc_private.c --- a/tools/libxc/xc_private.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/libxc/xc_private.c Fri Nov 10 11:11:04 2006 -0700 @@ -344,28 +344,6 @@ int xc_clear_domain_page(int xc_handle, return 0; } -unsigned long xc_get_filesz(int fd) -{ - uint16_t sig; - uint32_t _sz = 0; - unsigned long sz; - - lseek(fd, 0, SEEK_SET); - if ( read(fd, &sig, sizeof(sig)) != sizeof(sig) ) - return 0; - sz = lseek(fd, 0, SEEK_END); - if ( sig == 0x8b1f ) /* GZIP signature? */ - { - lseek(fd, -4, SEEK_END); - if ( read(fd, &_sz, 4) != 4 ) - return 0; - sz = _sz; - } - lseek(fd, 0, SEEK_SET); - - return sz; -} - void xc_map_memcpy(unsigned long dst, const char *src, unsigned long size, int xch, uint32_t dom, xen_pfn_t *parray, unsigned long vstart) diff -r 11b718eb22c9 -r ebed72718263 tools/libxc/xc_private.h --- a/tools/libxc/xc_private.h Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/libxc/xc_private.h Fri Nov 10 11:11:04 2006 -0700 @@ -158,4 +158,9 @@ int xc_map_foreign_ranges(int xc_handle, int xc_map_foreign_ranges(int xc_handle, uint32_t dom, privcmd_mmap_entry_t *entries, int nr); +void *map_domain_va_core(unsigned long domfd, int cpu, void *guest_va, + vcpu_guest_context_t *ctxt); +int xc_waitdomain_core(int xc_handle, int domain, int *status, + int options, vcpu_guest_context_t *ctxt); + #endif /* __XC_PRIVATE_H__ */ diff -r 11b718eb22c9 -r ebed72718263 tools/libxc/xc_ptrace.c --- a/tools/libxc/xc_ptrace.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/libxc/xc_ptrace.c Fri Nov 10 11:11:04 2006 -0700 @@ -36,8 +36,9 @@ static char *ptrace_names[] = { }; #endif -static int current_domid = -1; -static int current_isfile; +static int current_domid = -1; +static int current_isfile; +static int current_is_hvm; static uint64_t online_cpumap; static uint64_t regs_valid; @@ -45,7 +46,6 @@ static vcpu_guest_context_t ctxt[MAX extern int ffsll(long long int); #define FOREACH_CPU(cpumap, i) for ( cpumap = online_cpumap; (i = ffsll(cpumap)); cpumap &= ~(1 << (index - 1)) ) - static int fetch_regs(int xc_handle, int cpu, int *online) @@ -172,7 +172,7 @@ to_ma(int cpu, { unsigned long maddr = in_addr; - if ( (ctxt[cpu].flags & VGCF_HVM_GUEST) && paging_enabled(&ctxt[cpu]) ) + if ( current_is_hvm && paging_enabled(&ctxt[cpu]) ) maddr = page_array[maddr >> PAGE_SHIFT] << PAGE_SHIFT; return maddr; } @@ -443,7 +443,7 @@ __xc_waitdomain( goto done; } - if ( !(domctl.u.getdomaininfo.flags & DOMFLAGS_PAUSED) ) + if ( !(domctl.u.getdomaininfo.flags & XEN_DOMINF_paused) ) { nanosleep(&ts,NULL); goto retry; @@ -482,11 +482,11 @@ xc_ptrace( case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: if (current_isfile) - guest_va = (unsigned long *)map_domain_va_core(current_domid, - cpu, addr, ctxt); + guest_va = (unsigned long *)map_domain_va_core( + current_domid, cpu, addr, ctxt); else - guest_va = (unsigned long *)map_domain_va(xc_handle, - cpu, addr, PROT_READ); + guest_va = (unsigned long *)map_domain_va( + xc_handle, cpu, addr, PROT_READ); if ( guest_va == NULL ) goto out_error; retval = *guest_va; @@ -496,11 +496,11 @@ xc_ptrace( case PTRACE_POKEDATA: /* XXX assume that all CPUs have the same address space */ if (current_isfile) - guest_va = (unsigned long *)map_domain_va_core(current_domid, - cpu, addr, ctxt); + guest_va = (unsigned long *)map_domain_va_core( + current_domid, cpu, addr, ctxt); else - guest_va = (unsigned long *)map_domain_va(xc_handle, - cpu, addr, PROT_READ|PROT_WRITE); + guest_va = (unsigned long *)map_domain_va( + xc_handle, cpu, addr, PROT_READ|PROT_WRITE); if ( guest_va == NULL ) goto out_error; *guest_va = (unsigned long)data; @@ -590,10 +590,11 @@ xc_ptrace( retval = do_domctl(xc_handle, &domctl); if ( retval || (domctl.domain != current_domid) ) goto out_error_domctl; - if ( domctl.u.getdomaininfo.flags & DOMFLAGS_PAUSED ) + if ( domctl.u.getdomaininfo.flags & XEN_DOMINF_paused ) IPRINTF("domain currently paused\n"); else if ((retval = xc_domain_pause(xc_handle, current_domid))) goto out_error_domctl; + current_is_hvm = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_hvm_guest); domctl.cmd = XEN_DOMCTL_setdebugging; domctl.domain = current_domid; domctl.u.setdebugging.enable = 1; diff -r 11b718eb22c9 -r ebed72718263 tools/libxc/xc_ptrace_core.c --- a/tools/libxc/xc_ptrace_core.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/libxc/xc_ptrace_core.c Fri Nov 10 11:11:04 2006 -0700 @@ -7,6 +7,7 @@ /* XXX application state */ +static int current_is_hvm = 0; static long nr_pages = 0; static unsigned long *p2m_array = NULL; static unsigned long *m2p_array = NULL; @@ -24,8 +25,8 @@ map_mtop_offset(unsigned long ma) void * -map_domain_va_core(unsigned long domfd, int cpu, void * guest_va, - vcpu_guest_context_t *ctxt) +map_domain_va_core(unsigned long domfd, int cpu, void *guest_va, + vcpu_guest_context_t *ctxt) { unsigned long pde, page; unsigned long va = (unsigned long)guest_va; @@ -55,7 +56,7 @@ map_domain_va_core(unsigned long domfd, } if ((pde = cr3_virt[cpu][l2_table_offset_i386(va)]) == 0) /* logical address */ return NULL; - if (ctxt[cpu].flags & VGCF_HVM_GUEST) + if (current_is_hvm) pde = p2m_array[pde >> PAGE_SHIFT] << PAGE_SHIFT; if (pde != pde_phys[cpu]) { @@ -71,7 +72,7 @@ map_domain_va_core(unsigned long domfd, } if ((page = pde_virt[cpu][l1_table_offset_i386(va)]) == 0) /* logical address */ return NULL; - if (ctxt[cpu].flags & VGCF_HVM_GUEST) + if (current_is_hvm) page = p2m_array[page >> PAGE_SHIFT] << PAGE_SHIFT; if (page != page_phys[cpu]) { @@ -104,17 +105,18 @@ xc_waitdomain_core( int i; xc_core_header_t header; - if (nr_pages == 0) + if ( nr_pages == 0 ) { - if (read(domfd, &header, sizeof(header)) != sizeof(header)) return -1; - if (header.xch_magic != XC_CORE_MAGIC) { - IPRINTF("Magic number missmatch: 0x%08x (file) != " - " 0x%08x (code)\n", header.xch_magic, - XC_CORE_MAGIC); - return -1; + current_is_hvm = (header.xch_magic == XC_CORE_MAGIC_HVM); + if ( !current_is_hvm && (header.xch_magic != XC_CORE_MAGIC) ) + { + IPRINTF("Magic number missmatch: 0x%08x (file) != " + " 0x%08x (code)\n", header.xch_magic, + XC_CORE_MAGIC); + return -1; } nr_pages = header.xch_nr_pages; diff -r 11b718eb22c9 -r ebed72718263 tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/libxc/xenctrl.h Fri Nov 10 11:11:04 2006 -0700 @@ -47,10 +47,9 @@ #define rmb() __asm__ __volatile__ ( "lfence" : : : "memory") #define wmb() __asm__ __volatile__ ( "" : : : "memory") #elif defined(__ia64__) -/* FIXME */ -#define mb() -#define rmb() -#define wmb() +#define mb() __asm__ __volatile__ ("mf" ::: "memory") +#define rmb() __asm__ __volatile__ ("mf" ::: "memory") +#define wmb() __asm__ __volatile__ ("mf" ::: "memory") #elif defined(__powerpc__) /* XXX loosen these up later */ #define mb() __asm__ __volatile__ ("sync" : : : "memory") @@ -113,25 +112,13 @@ typedef struct xc_core_header { unsigned int xch_pages_offset; } xc_core_header_t; -#define XC_CORE_MAGIC 0xF00FEBED +#define XC_CORE_MAGIC 0xF00FEBED +#define XC_CORE_MAGIC_HVM 0xF00FEBEE #ifdef __linux__ #include <sys/ptrace.h> #include <thread_db.h> - -void * map_domain_va_core( - unsigned long domfd, - int cpu, - void *guest_va, - vcpu_guest_context_t *ctxt); - -int xc_waitdomain_core( - int xc_handle, - int domain, - int *status, - int options, - vcpu_guest_context_t *ctxt); typedef void (*thr_ev_handler_t)(long); @@ -158,11 +145,12 @@ int xc_waitdomain( * DOMAIN MANAGEMENT FUNCTIONS */ -typedef struct { +typedef struct xc_dominfo { uint32_t domid; uint32_t ssidref; unsigned int dying:1, crashed:1, shutdown:1, - paused:1, blocked:1, running:1; + paused:1, blocked:1, running:1, + hvm:1; unsigned int shutdown_reason; /* only meaningful if shutdown==1 */ unsigned long nr_pages; unsigned long shared_info_frame; @@ -177,6 +165,7 @@ int xc_domain_create(int xc_handle, int xc_domain_create(int xc_handle, uint32_t ssidref, xen_domain_handle_t handle, + uint32_t flags, uint32_t *pdomid); @@ -677,4 +666,6 @@ evtchn_port_t xc_evtchn_pending(int xce_ */ int xc_evtchn_unmask(int xce_handle, evtchn_port_t port); +int xc_hvm_set_irq_level(int xce_handle, domid_t dom, int irq, int level); + #endif diff -r 11b718eb22c9 -r ebed72718263 tools/libxc/xenguest.h --- a/tools/libxc/xenguest.h Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/libxc/xenguest.h Fri Nov 10 11:11:04 2006 -0700 @@ -48,8 +48,9 @@ int xc_linux_restore(int xc_handle, int * * @parm xc_handle a handle to an open hypervisor interface * @parm domid the id of the domain - * @param image_name name of the kernel image file - * @param ramdisk_name name of the ramdisk image file + * @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 @@ -60,6 +61,7 @@ int xc_linux_restore(int xc_handle, int */ int xc_linux_build(int xc_handle, uint32_t domid, + unsigned int mem_mb, const char *image_name, const char *ramdisk_name, const char *cmdline, @@ -74,22 +76,24 @@ int xc_linux_build(int xc_handle, * This function will create a domain for a paravirtualized Linux * using buffers for kernel and initrd * - * @param xc_handle a handle to an open hypervisor interface - * @param domid the id of the domain - * @param image_buffer buffer containing kernel image - * @param image_size size of the kernel image buffer - * @param initrd_buffer name of the ramdisk image file - * @param initrd_size size of the ramdisk buffer - * @param cmdline command line string - * @param flags domain creation flags - * @param store_evtchn the store event channel for this domain to use - * @param store_mfn returned with the mfn of the store page - * @param console_evtchn the console event channel for this domain to use - * @param conole_mfn returned with the mfn of the console page + * @parm xc_handle 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(int xc_handle, uint32_t domid, + unsigned int mem_mb, const char *image_buffer, unsigned long image_size, const char *initrd_buffer, @@ -109,7 +113,6 @@ int xc_hvm_build(int xc_handle, unsigned int vcpus, unsigned int pae, unsigned int acpi, - unsigned int apic, unsigned int store_evtchn, unsigned long *store_mfn); @@ -121,7 +124,6 @@ int xc_hvm_build_mem(int xc_handle, unsigned int vcpus, unsigned int pae, unsigned int acpi, - unsigned int apic, unsigned int store_evtchn, unsigned long *store_mfn); diff -r 11b718eb22c9 -r ebed72718263 tools/libxc/xg_private.c --- a/tools/libxc/xg_private.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/libxc/xg_private.c Fri Nov 10 11:11:04 2006 -0700 @@ -31,7 +31,7 @@ char *xc_read_image(const char *filename { int kernel_fd = -1; gzFile kernel_gfd = NULL; - char *image = NULL; + char *image = NULL, *tmp; unsigned int bytes; if ( (filename == NULL) || (size == NULL) ) @@ -43,33 +43,58 @@ char *xc_read_image(const char *filename goto out; } - if ( (*size = xc_get_filesz(kernel_fd)) == 0 ) - { - PERROR("Could not read kernel image"); - goto out; - } - if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL ) { PERROR("Could not allocate decompression state for state file"); goto out; } - if ( (image = malloc(*size)) == NULL ) - { - PERROR("Could not allocate memory for kernel image"); - goto out; - } - - if ( (bytes = gzread(kernel_gfd, image, *size)) != *size ) - { - PERROR("Error reading kernel image, could not" - " read the whole image (%d != %ld).", bytes, *size); - free(image); - image = NULL; - } + *size = 0; + +#define CHUNK 1*1024*1024 + while(1) + { + if ( (tmp = realloc(image, *size + CHUNK)) == NULL ) + { + PERROR("Could not allocate memory for kernel image"); + free(image); + image = NULL; + goto out; + } + image = tmp; + + bytes = gzread(kernel_gfd, image + *size, CHUNK); + switch (bytes) + { + case -1: + PERROR("Error reading kernel image"); + free(image); + image = NULL; + goto out; + case 0: /* EOF */ + goto out; + default: + *size += bytes; + break; + } + } +#undef CHUNK out: + if ( *size == 0 ) + { + PERROR("Could not read kernel image"); + free(image); + image = NULL; + } + else if ( image ) + { + /* Shrink allocation to fit image. */ + tmp = realloc(image, *size); + if ( tmp ) + image = tmp; + } + if ( kernel_gfd != NULL ) gzclose(kernel_gfd); else if ( kernel_fd >= 0 ) @@ -171,7 +196,6 @@ __attribute__((weak)) int xc_hvm_build( unsigned int vcpus, unsigned int pae, unsigned int acpi, - unsigned int apic, unsigned int store_evtchn, unsigned long *store_mfn) { diff -r 11b718eb22c9 -r ebed72718263 tools/libxc/xg_private.h --- a/tools/libxc/xg_private.h Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/libxc/xg_private.h Fri Nov 10 11:11:04 2006 -0700 @@ -193,8 +193,6 @@ int xc_copy_to_domain_page(int xc_handle int xc_copy_to_domain_page(int xc_handle, uint32_t domid, unsigned long dst_pfn, const char *src_page); -unsigned long xc_get_filesz(int fd); - void xc_map_memcpy(unsigned long dst, const char *src, unsigned long size, int xch, uint32_t dom, xen_pfn_t *parray, unsigned long vstart); diff -r 11b718eb22c9 -r ebed72718263 tools/pygrub/setup.py --- a/tools/pygrub/setup.py Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/pygrub/setup.py Fri Nov 10 11:11:04 2006 -0700 @@ -3,48 +3,27 @@ import os import os import sys -extra_compile_args = [ "-fno-strict-aliasing", "-Wall", "-Werror" ] +extra_compile_args = [ "-fno-strict-aliasing", "-Werror" ] -fsys_mods = [] -fsys_pkgs = [] +XEN_ROOT = "../.." -if os.path.exists("/usr/include/ext2fs/ext2_fs.h"): - ext2defines = [] - cc = new_compiler() - cc.add_library("ext2fs") - if hasattr(cc, "has_function") and cc.has_function("ext2fs_open2"): - ext2defines.append( ("HAVE_EXT2FS_OPEN2", None) ) - else: - sys.stderr.write("WARNING: older version of e2fsprogs installed, not building full\n") - sys.stderr.write(" disk support for ext2.\n") - - ext2 = Extension("grub.fsys.ext2._pyext2", - extra_compile_args = extra_compile_args, - libraries = ["ext2fs"], - define_macros = ext2defines, - sources = ["src/fsys/ext2/ext2module.c"]) - fsys_mods.append(ext2) - fsys_pkgs.append("grub.fsys.ext2") +fsimage = Extension("fsimage", + extra_compile_args = extra_compile_args, + include_dirs = [ XEN_ROOT + "/tools/libfsimage/common/" ], + library_dirs = [ XEN_ROOT + "/tools/libfsimage/common/" ], + libraries = ["fsimage"], + sources = ["src/fsimage/fsimage.c"]) -if os.path.exists("/usr/include/reiserfs/reiserfs.h"): - reiser = Extension("grub.fsys.reiser._pyreiser", - extra_compile_args = extra_compile_args, - libraries = ["reiserfs"], - sources = ["src/fsys/reiser/reisermodule.c"]) - fsys_mods.append(reiser) - fsys_pkgs.append("grub.fsys.reiser") +pkgs = [ 'grub' ] -pkgs = ['grub', 'grub.fsys'] -pkgs.extend(fsys_pkgs) setup(name='pygrub', version='0.3', description='Boot loader that looks a lot like grub for Xen', author='Jeremy Katz', author_email='katzj@xxxxxxxxxx', license='GPL', - package_dir={'grub': 'src'}, + package_dir={'grub': 'src', 'fsimage': 'src'}, scripts = ["src/pygrub"], packages=pkgs, - ext_modules = fsys_mods + ext_modules = [ fsimage ] ) - diff -r 11b718eb22c9 -r ebed72718263 tools/pygrub/src/pygrub --- a/tools/pygrub/src/pygrub Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/pygrub/src/pygrub Fri Nov 10 11:11:04 2006 -0700 @@ -22,8 +22,8 @@ import getopt sys.path = [ '/usr/lib/python' ] + sys.path +import fsimage import grub.GrubConf -import grub.fsys PYGRUB_VER = 0.5 @@ -113,17 +113,21 @@ class GrubLineEditor(curses.textpad.Text elif ch == curses.ascii.SOH: # ^a self.pos = 0 elif ch in (curses.ascii.STX,curses.KEY_LEFT): - self.pos -= 1 + if self.pos > 0: + self.pos -= 1 elif ch in (curses.ascii.BS,curses.KEY_BACKSPACE): if self.pos > 0: self.pos -= 1 + if self.pos < len(self.line): + self.line.pop(self.pos) + elif ch == curses.ascii.EOT: # ^d + if self.pos < len(self.line): self.line.pop(self.pos) - elif ch == curses.ascii.EOT: # ^d - self.line.pop(self.pos) elif ch == curses.ascii.ENQ: # ^e self.pos = len(self.line) elif ch in (curses.ascii.ACK, curses.KEY_RIGHT): - self.pos +=1 + if self.pos < len(self.line): + self.pos +=1 elif ch == curses.ascii.VT: # ^k self.line = self.line[:self.pos] else: @@ -313,25 +317,21 @@ class Grub: raise RuntimeError, "Unable to find active partition on disk" # open the image and read the grub config - fs = None - for fstype in grub.fsys.fstypes.values(): - if fstype.sniff_magic(fn, offset): - fs = fstype.open_fs(fn, offset) - break + fs = fsimage.open(fn, offset) if fs is not None: grubfile = None for f in ("/boot/grub/menu.lst", "/boot/grub/grub.conf", "/grub/menu.lst", "/grub/grub.conf"): - if fs.file_exist(f): + if fs.file_exists(f): grubfile = f break if grubfile is None: raise RuntimeError, "we couldn't find grub config file in the image provided." f = fs.open_file(grubfile) buf = f.read() - f.close() - fs.close() + del f + del fs # then parse the grub config self.cf.parse(buf) else: @@ -511,14 +511,7 @@ if __name__ == "__main__": raise RuntimeError, "Unable to find active partition on disk" # read the kernel and initrd onto the hostfs - fs = None - for fstype in grub.fsys.fstypes.values(): - if fstype.sniff_magic(file, offset): - fs = fstype.open_fs(file, offset) - break - - if fs is None: - raise RuntimeError, "Unable to open filesystem" + fs = fsimage.open(file, offset) kernel = fs.open_file(img.kernel[1],).read() (tfd, fn) = tempfile.mkstemp(prefix="vmlinuz.", dir="/var/lib/xen") diff -r 11b718eb22c9 -r ebed72718263 tools/python/setup.py --- a/tools/python/setup.py Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/python/setup.py Fri Nov 10 11:11:04 2006 -0700 @@ -4,8 +4,7 @@ import os XEN_ROOT = "../.." -extra_compile_args = [ "-fno-strict-aliasing", "-Wall", "-Werror" ] - +extra_compile_args = [ "-fno-strict-aliasing", "-Werror" ] include_dirs = [ XEN_ROOT + "/tools/libxc", XEN_ROOT + "/tools/xenstore", diff -r 11b718eb22c9 -r ebed72718263 tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/python/xen/lowlevel/xc/xc.c Fri Nov 10 11:11:04 2006 -0700 @@ -65,18 +65,17 @@ static PyObject *pyxc_domain_create(XcOb PyObject *args, PyObject *kwds) { - uint32_t dom = 0; - int ret, i; - uint32_t ssidref = 0; + uint32_t dom = 0, ssidref = 0, flags = 0; + int ret, i, hvm = 0; PyObject *pyhandle = NULL; xen_domain_handle_t handle = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef }; - static char *kwd_list[] = { "dom", "ssidref", "handle", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiO", kwd_list, - &dom, &ssidref, &pyhandle)) + static char *kwd_list[] = { "domid", "ssidref", "handle", "hvm", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiOi", kwd_list, + &dom, &ssidref, &pyhandle, &hvm)) return NULL; if ( pyhandle != NULL ) @@ -94,7 +93,11 @@ static PyObject *pyxc_domain_create(XcOb } } - if ( (ret = xc_domain_create(self->xc_handle, ssidref, handle, &dom)) < 0 ) + if ( hvm ) + flags |= XEN_DOMCTL_CDF_hvm_guest; + + if ( (ret = xc_domain_create(self->xc_handle, ssidref, + handle, flags, &dom)) < 0 ) return PyErr_SetFromErrno(xc_error); return PyInt_FromLong(dom); @@ -144,7 +147,7 @@ static PyObject *pyxc_vcpu_setaffinity(X uint64_t cpumap = ~0ULL; PyObject *cpulist = NULL; - static char *kwd_list[] = { "dom", "vcpu", "cpumap", NULL }; + static char *kwd_list[] = { "domid", "vcpu", "cpumap", NULL }; if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|iO", kwd_list, &dom, &vcpu, &cpulist) ) @@ -171,7 +174,7 @@ static PyObject *pyxc_domain_setcpuweigh uint32_t dom; float cpuweight = 1; - static char *kwd_list[] = { "dom", "cpuweight", NULL }; + static char *kwd_list[] = { "domid", "cpuweight", NULL }; if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|f", kwd_list, &dom, &cpuweight) ) @@ -254,11 +257,12 @@ static PyObject *pyxc_domain_getinfo(XcO PyObject *pyhandle = PyList_New(sizeof(xen_domain_handle_t)); for ( j = 0; j < sizeof(xen_domain_handle_t); j++ ) PyList_SetItem(pyhandle, j, PyInt_FromLong(info[i].handle[j])); - info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i" + info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i" ",s:l,s:L,s:l,s:i,s:i}", - "dom", info[i].domid, + "domid", info[i].domid, "online_vcpus", info[i].nr_online_vcpus, "max_vcpu_id", info[i].max_vcpu_id, + "hvm", info[i].hvm, "dying", info[i].dying, "crashed", info[i].crashed, "shutdown", info[i].shutdown, @@ -291,7 +295,7 @@ static PyObject *pyxc_vcpu_getinfo(XcObj int rc, i; uint64_t cpumap; - static char *kwd_list[] = { "dom", "vcpu", NULL }; + static char *kwd_list[] = { "domid", "vcpu", NULL }; if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, &dom, &vcpu) ) @@ -331,24 +335,25 @@ static PyObject *pyxc_linux_build(XcObje char *image, *ramdisk = NULL, *cmdline = "", *features = NULL; int flags = 0; int store_evtchn, console_evtchn; + unsigned int mem_mb; unsigned long store_mfn = 0; unsigned long console_mfn = 0; - static char *kwd_list[] = { "dom", "store_evtchn", + static char *kwd_list[] = { "domid", "store_evtchn", "memsize", "console_evtchn", "image", /* optional */ "ramdisk", "cmdline", "flags", "features", NULL }; - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiis|ssis", kwd_list, - &dom, &store_evtchn, + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiis|ssis", kwd_list, + &dom, &store_evtchn, &mem_mb, &console_evtchn, &image, /* optional */ &ramdisk, &cmdline, &flags, &features) ) return NULL; - if ( xc_linux_build(self->xc_handle, dom, image, + if ( xc_linux_build(self->xc_handle, dom, mem_mb, image, ramdisk, cmdline, features, flags, store_evtchn, &store_mfn, console_evtchn, &console_mfn) != 0 ) { @@ -372,19 +377,18 @@ static PyObject *pyxc_hvm_build(XcObject int vcpus = 1; int pae = 0; int acpi = 0; - int apic = 0; unsigned long store_mfn = 0; - static char *kwd_list[] = { "dom", "store_evtchn", "memsize", "image", - "vcpus", "pae", "acpi", "apic", - NULL }; - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiisiiii", kwd_list, + static char *kwd_list[] = { "domid", "store_evtchn", + "memsize", "image", "vcpus", "pae", "acpi", + NULL }; + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiisiii", kwd_list, &dom, &store_evtchn, &memsize, - &image, &vcpus, &pae, &acpi, &apic) ) + &image, &vcpus, &pae, &acpi) ) return NULL; if ( xc_hvm_build(self->xc_handle, dom, memsize, image, - vcpus, pae, acpi, apic, store_evtchn, &store_mfn) != 0 ) + vcpus, pae, acpi, store_evtchn, &store_mfn) != 0 ) return PyErr_SetFromErrno(xc_error); return Py_BuildValue("{s:i}", "store_mfn", store_mfn); @@ -397,7 +401,7 @@ static PyObject *pyxc_evtchn_alloc_unbou uint32_t dom, remote_dom; int port; - static char *kwd_list[] = { "dom", "remote_dom", NULL }; + static char *kwd_list[] = { "domid", "remote_dom", NULL }; if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, &dom, &remote_dom) ) @@ -416,7 +420,7 @@ static PyObject *pyxc_physdev_pci_access uint32_t dom; int bus, dev, func, enable, ret; - static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL }; + static char *kwd_list[] = { "domid", "bus", "dev", "func", "enable", NULL }; if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list, &dom, &bus, &dev, &func, &enable) ) @@ -557,7 +561,7 @@ static PyObject *pyxc_sedf_domain_set(Xc uint32_t domid; uint64_t period, slice, latency; uint16_t extratime, weight; - static char *kwd_list[] = { "dom", "period", "slice", + static char *kwd_list[] = { "domid", "period", "slice", "latency", "extratime", "weight",NULL }; if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLhh", kwd_list, @@ -586,7 +590,7 @@ static PyObject *pyxc_sedf_domain_get(Xc return PyErr_SetFromErrno(xc_error); return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i,s:i}", - "domain", domid, + "domid", domid, "period", period, "slice", slice, "latency", latency, @@ -647,6 +651,15 @@ static PyObject *pyxc_shadow_mem_control return Py_BuildValue("i", mbarg); } +static PyObject *pyxc_sched_id_get(XcObject *self) { + + int sched_id; + if (xc_sched_id(self->xc_handle, &sched_id) != 0) + return PyErr_SetFromErrno(xc_error); + + return Py_BuildValue("i", sched_id); +} + static PyObject *pyxc_sched_credit_domain_set(XcObject *self, PyObject *args, PyObject *kwds) @@ -654,7 +667,7 @@ static PyObject *pyxc_sched_credit_domai uint32_t domid; uint16_t weight; uint16_t cap; - static char *kwd_list[] = { "dom", "weight", "cap", NULL }; + static char *kwd_list[] = { "domid", "weight", "cap", NULL }; static char kwd_type[] = "I|HH"; struct xen_domctl_sched_credit sdom; @@ -714,7 +727,7 @@ static PyObject *pyxc_domain_memory_incr unsigned int extent_order = 0 , address_bits = 0; unsigned long nr_extents; - static char *kwd_list[] = { "dom", "mem_kb", "extent_order", "address_bits", NULL }; + static char *kwd_list[] = { "domid", "mem_kb", "extent_order", "address_bits", NULL }; if ( !PyArg_ParseTupleAndKeywords(args, kwds, "il|ii", kwd_list, &dom, &mem_kb, &extent_order, &address_bits) ) @@ -739,7 +752,7 @@ static PyObject *pyxc_domain_ioport_perm uint32_t dom; int first_port, nr_ports, allow_access, ret; - static char *kwd_list[] = { "dom", "first_port", "nr_ports", "allow_access", NULL }; + static char *kwd_list[] = { "domid", "first_port", "nr_ports", "allow_access", NULL }; if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiii", kwd_list, &dom, &first_port, &nr_ports, &allow_access) ) @@ -762,7 +775,7 @@ static PyObject *pyxc_domain_irq_permiss uint32_t dom; int pirq, allow_access, ret; - static char *kwd_list[] = { "dom", "pirq", "allow_access", NULL }; + static char *kwd_list[] = { "domid", "pirq", "allow_access", NULL }; if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iii", kwd_list, &dom, &pirq, &allow_access) ) @@ -785,7 +798,7 @@ static PyObject *pyxc_domain_iomem_permi uint32_t dom; unsigned long first_pfn, nr_pfns, allow_access, ret; - static char *kwd_list[] = { "dom", "first_pfn", "nr_pfns", "allow_access", NULL }; + static char *kwd_list[] = { "domid", "first_pfn", "nr_pfns", "allow_access", NULL }; if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illi", kwd_list, &dom, &first_pfn, &nr_pfns, &allow_access) ) @@ -975,6 +988,12 @@ static PyMethodDef pyxc_methods[] = { " image [str]: Name of HVM loader image file.\n" " vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n" "Returns: [int] 0 on success; -1 on error.\n" }, + + { "sched_id_get", + (PyCFunction)pyxc_sched_id_get, + METH_NOARGS, "\n" + "Get the current scheduler type in use.\n" + "Returns: [int] sched_id.\n" }, { "sedf_domain_set", (PyCFunction)pyxc_sedf_domain_set, @@ -1242,6 +1261,11 @@ PyMODINIT_FUNC initxc(void) Py_INCREF(xc_error); PyModule_AddObject(m, "Error", xc_error); + + /* Expose some libxc constants to Python */ + PyModule_AddIntConstant(m, "XEN_SCHEDULER_SEDF", XEN_SCHEDULER_SEDF); + PyModule_AddIntConstant(m, "XEN_SCHEDULER_CREDIT", XEN_SCHEDULER_CREDIT); + } diff -r 11b718eb22c9 -r ebed72718263 tools/python/xen/util/blkif.py --- a/tools/python/xen/util/blkif.py Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/python/xen/util/blkif.py Fri Nov 10 11:11:04 2006 -0700 @@ -21,11 +21,17 @@ def blkdev_name_to_number(name): try: return os.stat(n).st_rdev except Exception, ex: - log.debug("exception looking up device number for %s: %s", name, ex) pass - if re.match( '/dev/sd[a-p]([1-9]|1[0-5])?', n): - return 8 * 256 + 16 * (ord(n[7:8]) - ord('a')) + int(n[8:] or 0) + 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) + return major * 256 + minor + if 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) + return major * 256 + minor if 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 ] @@ -53,7 +59,7 @@ def blkdev_segment(name): """ val = None n = blkdev_name_to_number(name) - if n: + if not n is None: val = { 'device' : n, 'start_sector' : long(0), 'nr_sectors' : long(1L<<63), diff -r 11b718eb22c9 -r ebed72718263 tools/python/xen/util/xmlrpclib2.py --- a/tools/python/xen/util/xmlrpclib2.py Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/python/xen/util/xmlrpclib2.py Fri Nov 10 11:11:04 2006 -0700 @@ -21,11 +21,11 @@ An enhanced XML-RPC client/server interf """ import string -import types import fcntl +from types import * + from httplib import HTTPConnection, HTTP -from xmlrpclib import Transport from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler import SocketServer import xmlrpclib, socket, os, stat @@ -39,6 +39,23 @@ except ImportError: # SSHTransport is disabled on Python <2.4, because it uses the subprocess # package. ssh_enabled = False + +# +# Convert all integers to strings as described in the Xen API +# + + +def stringify(value): + if isinstance(value, IntType) and not isinstance(value, BooleanType): + return str(value) + elif isinstance(value, DictType): + for k, v in value.items(): + value[k] = stringify(v) + return value + elif isinstance(value, (TupleType, ListType)): + return [stringify(v) for v in value] + else: + return value # A new ServerProxy that also supports httpu urls. An http URL comes in the @@ -81,18 +98,18 @@ class HTTPUnix(HTTP): class HTTPUnix(HTTP): _connection_class = HTTPUnixConnection -class UnixTransport(Transport): +class UnixTransport(xmlrpclib.Transport): def request(self, host, handler, request_body, verbose=0): self.__handler = handler - return Transport.request(self, host, '/RPC2', request_body, verbose) + return xmlrpclib.Transport.request(self, host, '/RPC2', + request_body, verbose) def make_connection(self, host): return HTTPUnix(self.__handler) # See _marshalled_dispatch below. def conv_string(x): - if (isinstance(x, types.StringType) or - isinstance(x, unicode)): + if isinstance(x, StringTypes): s = string.replace(x, "'", r"\047") exec "s = '" + s + "'" return s @@ -134,7 +151,7 @@ class TCPXMLRPCServer(SocketServer.Threa allow_reuse_address = True def __init__(self, addr, requestHandler=XMLRPCRequestHandler, - logRequests=1): + logRequests = 1): SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests) flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD) @@ -169,8 +186,7 @@ class TCPXMLRPCServer(SocketServer.Threa # to transmit the string using Python encoding. # Thanks to David Mertz <mertz@xxxxxxxxx> for the trick (buried # in xml_pickle.py). - if (isinstance(response, types.StringType) or - isinstance(response, unicode)): + if isinstance(response, StringTypes): response = repr(response)[1:-1] response = (response,) @@ -201,7 +217,7 @@ class UnixXMLRPCServer(TCPXMLRPCServer): class UnixXMLRPCServer(TCPXMLRPCServer): address_family = socket.AF_UNIX - def __init__(self, addr, logRequests): + def __init__(self, addr, logRequests = 1): parent = os.path.dirname(addr) if os.path.exists(parent): os.chown(parent, os.geteuid(), os.getegid()) diff -r 11b718eb22c9 -r ebed72718263 tools/python/xen/xend/Args.py --- a/tools/python/xen/xend/Args.py Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/python/xen/xend/Args.py Fri Nov 10 11:11:04 2006 -0700 @@ -18,7 +18,7 @@ import types import types import StringIO -import sxp +from xen.xend import sxp class ArgError(StandardError): pass diff -r 11b718eb22c9 -r ebed72718263 tools/python/xen/xend/PrettyPrint.py --- a/tools/python/xen/xend/PrettyPrint.py Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/python/xen/xend/PrettyPrint.py Fri Nov 10 11:11:04 2006 -0700 @@ -22,7 +22,7 @@ import sys import sys import types import StringIO -import sxp +from xen.xend import sxp class PrettyItem: diff -r 11b718eb22c9 -r ebed72718263 tools/python/xen/xend/XendBootloader.py --- a/tools/python/xen/xend/XendBootloader.py Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/python/xen/xend/XendBootloader.py Fri Nov 10 11:11:04 2006 -0700 @@ -14,8 +14,8 @@ import os, select, errno import random -import sxp import shlex +from xen.xend import sxp from XendLogging import log from XendError import VmError @@ -38,7 +38,7 @@ def bootloader(blexec, disk, quiet = 0, raise VmError(msg) while True: - fifo = "/var/lib/xen/xenbl.%s" %(random.randint(0, 32000),) + fifo = "/var/lib/xen/xenbl.%s" % random.randint(0, 32000) if not os.path.exists(fifo): break os.mkfifo(fifo, 0600) @@ -48,7 +48,7 @@ def bootloader(blexec, disk, quiet = 0, args = [ blexec ] if quiet: args.append("-q") - args.append("--output=%s" %(fifo,)) + args.append("--output=%s" % fifo) if blargs is not None: args.extend(shlex.split(blargs)) args.append(disk) diff -r 11b718eb22c9 -r ebed72718263 tools/python/xen/xend/XendCheckpoint.py --- a/tools/python/xen/xend/XendCheckpoint.py Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/python/xen/xend/XendCheckpoint.py Fri Nov 10 11:11:04 2006 -0700 @@ -8,21 +8,18 @@ import os import os import re import string -import sxp import threading from struct import pack, unpack, calcsize from xen.util.xpopen import xPopen3 - import xen.util.auxbin - import xen.lowlevel.xc -import balloon -from XendError import XendError -from XendLogging import log -from XendDomainInfo import DEV_MIGRATE_STEP1, DEV_MIGRATE_STEP2 -from XendDomainInfo import DEV_MIGRATE_STEP3 +from xen.xend import balloon, sxp +from xen.xend.XendError import XendError +from xen.xend.XendLogging import log +from xen.xend.XendConstants import * +from xen.xend.XendConfig import XendConfig SIGNATURE = "LinuxGuestRecord" XC_SAVE = "xc_save" @@ -43,13 +40,13 @@ def read_exact(fd, size, errmsg): def read_exact(fd, size, errmsg): buf = '' while size != 0: - str = os.read(fd, size) - if not len(str): + 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(str) - buf = buf + str + size = size - len(readstr) + buf = buf + readstr return buf @@ -111,7 +108,7 @@ def save(fd, dominfo, network, live, dst raise Exception, exn -def restore(xd, fd): +def restore(xd, fd, dominfo = None): signature = read_exact(fd, len(SIGNATURE), "not a valid guest state file: signature read") if signature != SIGNATURE: @@ -131,7 +128,11 @@ def restore(xd, fd): vmconfig = p.get_val() - dominfo = xd.restore_(vmconfig) + if dominfo: + dominfo.update(XendConfig(sxp = vmconfig), refresh = False) + dominfo.resume() + else: + dominfo = xd.restore_(vmconfig) store_port = dominfo.getStorePort() console_port = dominfo.getConsolePort() diff -r 11b718eb22c9 -r ebed72718263 tools/python/xen/xend/XendDomain.py --- a/tools/python/xen/xend/XendDomain.py Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/python/xen/xend/XendDomain.py Fri Nov 10 11:11:04 2006 -0700 @@ -22,45 +22,60 @@ Needs to be persistent for one uptime. """ -import logging import os +import shutil import socket -import sys import threading import xen.lowlevel.xc -import XendDomainInfo - -from xen.xend import XendRoot -from xen.xend import XendCheckpoint + +from xen.xend import XendRoot, XendCheckpoint, XendDomainInfo +from xen.xend.PrettyPrint import prettyprint +from xen.xend.XendConfig import XendConfig from xen.xend.XendError import XendError, XendInvalidDomain from xen.xend.XendLogging import log +from xen.xend.XendConstants import XS_VMROOT +from xen.xend.XendConstants import DOM_STATE_HALTED, DOM_STATE_RUNNING + from xen.xend.xenstore.xstransact import xstransact from xen.xend.xenstore.xswatch import xswatch from xen.util import security - +from xen.xend import uuid xc = xen.lowlevel.xc.xc() -xroot = XendRoot.instance() - +xroot = XendRoot.instance() __all__ = [ "XendDomain" ] -PRIV_DOMAIN = 0 -VMROOT = '/vm/' - +CACHED_CONFIG_FILE = 'config.sxp' +CHECK_POINT_FILE = 'checkpoint.chk' +DOM0_UUID = "00000000-0000-0000-0000-000000000000" +DOM0_NAME = "Domain-0" +DOM0_ID = 0 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 + """ - ## public: - def __init__(self): self.domains = {} + self.managed_domains = {} self.domains_lock = threading.RLock() + # 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 @@ -68,85 +83,277 @@ class XendDomain: # instance() must be able to return a valid instance of this class even # during this initialisation. def init(self): - xstransact.Mkdir(VMROOT) - xstransact.SetPermissions(VMROOT, { 'dom' : PRIV_DOMAIN }) - - self.domains_lock.acquire() - try: - self._add_domain( - XendDomainInfo.recreate(self.xen_domains()[PRIV_DOMAIN], - True)) - self.dom0_setup() + """Singleton initialisation function.""" + + dom_path = self._managed_path() + try: + os.stat(dom_path) + except OSError: + log.info("Making %s", dom_path) + os.makedirs(dom_path, 0755) + + 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) + self._add_domain(dom0) + 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.onChangeDomain) - xswatch("@releaseDomain", self.onChangeDomain) + 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) + self._add_domain(new_dom) + except Exception: + log.exception("Failed to create reference to running " + "domain id: %d" % dom['domid']) + + # 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', '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) + 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 = xroot.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 _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) + + # make sure the domain dir exists + if not os.path.exists(domains_dir): + os.makedirs(domains_dir, 0755) + elif not os.path.isdir(domains_dir): + log.error("xend_domain_dir is not a directory.") + raise XendError("Unable to save managed configuration " + "because %s is not a directory." % + domains_dir) - self.refresh(True) - finally: - self.domains_lock.release() - - - def list(self): - """Get list of domain objects. - - @return: domain objects - """ - self.domains_lock.acquire() - try: - self.refresh() - return self.domains.values() - finally: - self.domains_lock.release() - - - def list_sorted(self): - """Get list of domain objects, sorted by name. - - @return: domain objects - """ - doms = self.list() - doms.sort(lambda x, y: cmp(x.getName(), y.getName())) + if not os.path.exists(domain_config_dir): + try: + os.makedirs(domain_config_dir, 0755) + except IOError: + log.exception("Failed to create directory: %s" % + domain_config_dir) + raise XendError("Failed to create directory: %s" % + domain_config_dir) + + try: + sxp_cache_file = open(self._managed_config_path(dom_uuid),'w') + prettyprint(dominfo.sxpr(), sxp_cache_file, width = 78) + sxp_cache_file.close() + except IOError: + log.error("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(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 list_names(self): - """Get list of domain names. - - @return: domain names - """ - doms = self.list_sorted() - return map(lambda x: x.getName(), doms) - - - ## private: - - def onChangeDomain(self, _): - self.domains_lock.acquire() - try: - self.refresh() - finally: - self.domains_lock.release() - return 1 - - - def xen_domains(self): - """Get table of domains indexed by id from xc. Expects to be - protected by the domains_lock. - """ - domlist = xc.domain_getinfo() - doms = {} - for d in domlist: - domid = d['dom'] - doms[domid] = d - return doms - - - def dom0_setup(self): - """Expects to be protected by the domains_lock.""" - dom0 = self.domains[PRIV_DOMAIN] + 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()] + 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{XendRoot}. + + @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(xroot.get_dom0_vcpus()) @@ -157,74 +364,441 @@ class XendDomain: dom0.setVCpuCount(target) + def _refresh(self): + """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 + """ + + # update information for all running domains + # - like cpu_time, status, dying, etc. + running = self._running_domains() + for dom in running: + domid = dom['domid'] + if domid in self.domains and dom['dying'] != 1: + self.domains[domid].update(dom) + + # 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_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 the given domain entry to this instance's internal cache. - Expects to be protected by the domains_lock. - """ + """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 - - def _delete_domain(self, domid): - """Remove the given domain from this instance's internal cache. - Expects to be protected by the domains_lock. - """ - info = self.domains.get(domid) + 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: - del self.domains[domid] - info.cleanupDomain() - - - def refresh(self, initialising = False): - """Refresh domain list from Xen. Expects to be protected by the - domains_lock. - - @param initialising True if this is the first refresh after starting - Xend. This does not change this method's behaviour, except for - logging. - """ - doms = self.xen_domains() - for d in self.domains.values(): - info = doms.get(d.getDomid()) - if info: - d.update(info) - else: - self._delete_domain(d.getDomid()) - for d in doms: - if d not in self.domains: - if doms[d]['dying']: - log.log(initialising and logging.ERROR or logging.DEBUG, - 'Cannot recreate information for dying domain %d.' - ' Xend will ignore this domain from now on.', - doms[d]['dom']) - elif d == PRIV_DOMAIN: - log.fatal( - "No record of privileged domain %d! Terminating.", d) - sys.exit(1) - else: - try: - self._add_domain( - XendDomainInfo.recreate(doms[d], False)) - except: - log.exception( - "Failed to recreate information for domain " - "%d. Destroying it in the hope of " - "recovery.", d) - try: - xc.domain_destroy(d) - except: - log.exception('Destruction of %d failed.', d) - - - ## public: + if domid == None: + domid = info.getDomid() + + if info.state != DOM_STATE_HALTED: + info.cleanupDomain() + + if domid in self.domains: + del self.domains[domid] + 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: + security.refresh_ssidref(config) + dominfo = XendDomainInfo.restore(config) + self._add_domain(dominfo) + 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 XendError: If domain is not found. + """ + self.domains_lock.acquire() + try: + self._refresh() + dom = self.domain_lookup_nr(domid) + if not dom: + raise XendError("No domain named '%s'." % 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 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 + + if dom.state == 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': + chkfile = self._managed_check_point_path(dom.getName()) + self.domain_save(dom.domid, chkfile) + 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()] + result += self.managed_domains.keys() + 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): + self.domains_lock.acquire() + try: + dom = self.get_vm_with_dev_uuid(klass, dev_uuid) + if not dom: + return None + + value = dom.get_device_property(klass, dev_uuid, field) + return value + except ValueError, e: + pass + + return None + + 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): + self.domains_lock.acquire() + try: + for domid, dom in self.domains.items(): + if dom.get_uuid == vm_uuid: + return fn(domid, *args) + + if vm_uuid in self.managed_domains: + domid = self.managed_domains[vm_uuid].getDomid() + if domid == None: + domid = self.managed_domains[vm_uuid].getName() + return fn(domid, *args) + + raise XendInvalidDomain("Domain does not exist") + finally: + self.domains_lock.release() + + + def create_domain(self, xenapi_vm): + self.domains_lock.acquire() + try: + try: + xeninfo = XendConfig(xenapi_vm = 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): + """Get list of domain objects. + + @return: domains + @rtype: list of XendDomainInfo + """ + self.domains_lock.acquire() + try: + self._refresh() + + # 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) + + return active_domains + inactive_domains + finally: + self.domains_lock.release() + + + def list_sorted(self): + """Get list of domain objects, sorted by name. + + @return: domain objects + @rtype: list of XendDomainInfo + """ + doms = self.list() + doms.sort(lambda x, y: cmp(x.getName(), y.getName())) + return doms + + def list_names(self): + """Get list of domain names. + + @return: domain names + @rtype: list of strings. + """ + return [d.getName() for d in self.list_sorted()] + + 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 save privileged domain %s" % domname) + + if dominfo.state != DOM_STATE_RUNNING: + raise XendError("Cannot suspend domain that is not running.") + + if not os.path.exists(self._managed_config_path(domname)): + raise XendError("Domain is not managed by Xend lifecycle " + + "support.") + + path = self._managed_check_point_path(domname) + fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) + 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): + """Resumes a domain that is persistently managed by Xend. + + @param domname: Domain Name + @type domname: string + @rtype: None + @raise XendError: If failed to restore. + """ + try: + dominfo = self.domain_lookup_nr(domname) + + if not dominfo: + raise XendInvalidDomain(domname) + + if dominfo.getDomid() == DOM0_ID: + raise XendError("Cannot save privileged domain %s" % domname) + + if dominfo.state != DOM_STATE_HALTED: + raise XendError("Cannot suspend domain that is not running.") + + chkpath = self._managed_check_point_path(domname) + 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.state) + XendCheckpoint.restore(self, + os.open(chkpath, os.O_RDONLY), + dominfo) + 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)) + def domain_create(self, config): """Create a domain from a configuration. @param config: configuration - @return: domain - """ - self.domains_lock.acquire() - try: + @type config: SXP Object (list of lists) + @rtype: XendDomainInfo + """ + self.domains_lock.acquire() + try: + self._refresh() + dominfo = XendDomainInfo.create(config) self._add_domain(dominfo) self.domain_sched_credit_set(dominfo.getDomid(), @@ -235,10 +809,91 @@ class XendDomain: 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: + xeninfo = XendConfig(sxp = config) + dominfo = XendDomainInfo.createDormant(xeninfo) + 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 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.state != DOM_STATE_HALTED: + raise XendError("Domain is already running") + + dominfo.start(is_managed = True) + self._add_domain(dominfo) + finally: + self.domains_lock.release() + + + 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.state != DOM_STATE_HALTED: + raise XendError("Domain is still running") + + self._managed_domain_unregister(dominfo) + self._remove_domain(dominfo) + + except Exception, ex: + raise XendError(str(ex)) + finally: + self.domains_lock.release() + + 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") @@ -246,9 +901,12 @@ class XendDomain: def domain_restore(self, src): """Restore a domain from file. - @param src: source 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: fd = os.open(src, os.O_RDONLY) try: @@ -260,7 +918,13 @@ class XendDomain: (src, ex[1])) def domain_restore_fd(self, fd): - """Restore a domain from the given file descriptor.""" + """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: return XendCheckpoint.restore(self, fd) @@ -270,151 +934,85 @@ class XendDomain: # poor, so we need to log this for debugging. log.exception("Restore failed") raise XendError("Restore failed") - - - def restore_(self, config): - """Create a domain as part of the restore process. This is called - only from {@link XendCheckpoint}. - - A restore request comes into XendDomain through {@link - #domain_restore} or {@link #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 {@link 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. - """ - self.domains_lock.acquire() - try: - security.refresh_ssidref(config) - dominfo = XendDomainInfo.restore(config) - self._add_domain(dominfo) - return dominfo - finally: - self.domains_lock.release() - - - def domain_lookup(self, domid): - self.domains_lock.acquire() - try: - self.refresh() - return self.domains.get(domid) - finally: - self.domains_lock.release() - - - def domain_lookup_nr(self, domid): - self.domains_lock.acquire() - try: - return self.domains.get(domid) - finally: - self.domains_lock.release() - - - def domain_lookup_by_name_or_id(self, name): - self.domains_lock.acquire() - try: - self.refresh() - return self.domain_lookup_by_name_or_id_nr(name) - finally: - self.domains_lock.release() - - - def domain_lookup_by_name_or_id_nr(self, name): - self.domains_lock.acquire() - try: - dominfo = self.domain_lookup_by_name_nr(name) - - if dominfo: - return dominfo - else: - try: - return self.domains.get(int(name)) - except ValueError: - return None - finally: - self.domains_lock.release() - - - def domain_lookup_by_name_nr(self, name): - self.domains_lock.acquire() - try: - matching = filter(lambda d: d.getName() == name, - self.domains.values()) - n = len(matching) - if n == 1: - return matching[0] - return None - finally: - self.domains_lock.release() - - - def privilegedDomain(self): - self.domains_lock.acquire() - try: - return self.domains[PRIV_DOMAIN] - finally: - self.domains_lock.release() - def domain_unpause(self, domid): - """Unpause domain execution.""" - - dominfo = self.domain_lookup_by_name_or_id_nr(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)) + + 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): + """Pause domain execution. + + @param domid: Domain ID or Name + @type domid: int or string. + @rtype: None + @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)) + log.info("Domain %s (%d) paused.", dominfo.getName(), + int(dominfo.getDomid())) + dominfo.pause() + except XendInvalidDomain: + log.exception("domain_pause") + raise + except Exception, ex: + log.exception("domain_pause") + raise XendError(str(ex)) + + def domain_dump(self, domid, filename, live, crash): + """Dump domain core.""" + + dominfo = self.domain_lookup_nr(domid) if not dominfo: raise XendInvalidDomain(str(domid)) - if dominfo.getDomid() == PRIV_DOMAIN: - raise XendError("Cannot unpause privileged domain %s" % domid) - - try: - log.info("Domain %s (%d) unpaused.", dominfo.getName(), - dominfo.getDomid()) - return dominfo.unpause() - except Exception, ex: - raise XendError(str(ex)) - - - def domain_pause(self, domid): - """Pause domain execution.""" - - dominfo = self.domain_lookup_by_name_or_id_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - - if dominfo.getDomid() == PRIV_DOMAIN: - raise XendError("Cannot pause privileged domain %s" % domid) - - try: - log.info("Domain %s (%d) paused.", dominfo.getName(), - dominfo.getDomid()) - return dominfo.pause() - except Exception, ex: - raise XendError(str(ex)) - - def domain_dump(self, domid, filename, live, crash): - """Dump domain core.""" - - dominfo = self.domain_lookup_by_name_or_id_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - - if dominfo.getDomid() == PRIV_DOMAIN: + if dominfo.getDomid() == DOM0_ID: raise XendError("Cannot dump core for privileged domain %s" % domid) try: - log.info("Domain core dump requested for domain %s (%d) live=%d crash=%d.", + log.info("Domain core dump requested for domain %s (%d) " + "live=%d crash=%d.", dominfo.getName(), dominfo.getDomid(), live, crash) return dominfo.dumpCore(filename) except Exception, ex: raise XendError(str(ex)) def domain_destroy(self, domid): - """Terminate domain immediately.""" - - dominfo = self.domain_lookup_by_name_or_id_nr(domid) - if dominfo and dominfo.getDomid() == PRIV_DOMAIN: + """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: @@ -422,19 +1020,36 @@ class XendDomain: else: try: val = xc.domain_destroy(int(domid)) - except Exception, ex: - raise XendInvalidDomain(str(domid)) + except ValueError: + raise XendInvalidDomain(domid) + except Exception, e: + raise XendError(str(e)) + return val def domain_migrate(self, domid, dst, live=False, resource=0, port=0): - """Start domain migration.""" - - dominfo = self.domain_lookup_by_name_or_id_nr(domid) + """Start domain migration. + + @param domid: Domain ID or Name + @type domid: int or string. + @param dst: Destination IP address + @type dst: string + @keyword port: relocation port on destination + @type port: int + @keyword live: Live migration + @type live: bool + @keyword resource: not used?? + @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() == PRIV_DOMAIN: - raise XendError("Cannot migrate privileged domain %s" % domid) + if dominfo.getDomid() == DOM0_ID: + raise XendError("Cannot migrate privileged domain %i" % domid) """ The following call may raise a XendError exception """ dominfo.testMigrateDevices(True, dst) @@ -460,21 +1075,26 @@ class XendDomain: def domain_save(self, domid, dst): """Start saving a domain to file. - @param dst: destination file - """ - - try: - dominfo = self.domain_lookup_by_name_or_id_nr(domid) + @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() == PRIV_DOMAIN: - raise XendError("Cannot save privileged domain %s" % domid) + if dominfo.getDomid() == DOM0_ID: + raise XendError("Cannot save privileged domain %i" % domid) fd = os.open(dst, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) try: # For now we don't support 'live checkpoint' - return XendCheckpoint.save(fd, dominfo, False, False, dst) + XendCheckpoint.save(fd, dominfo, False, False, dst) finally: os.close(fd) except OSError, ex: @@ -484,9 +1104,15 @@ class XendDomain: def domain_pincpu(self, domid, vcpu, cpumap): """Set which cpus vcpu can use - @param cpumap: string repr of list of usable cpus - """ - dominfo = self.domain_lookup_by_name_or_id_nr(domid) + @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)) @@ -507,8 +1133,12 @@ class XendDomain: def domain_cpu_sedf_set(self, domid, period, slice_, latency, extratime, weight): """Set Simple EDF scheduler parameters for a domain. - """ - dominfo = self.domain_lookup_by_name_or_id_nr(domid) + + @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: @@ -519,15 +1149,20 @@ class XendDomain: def domain_cpu_sedf_get(self, domid): """Get Simple EDF scheduler parameters for a domain. - """ - dominfo = self.domain_lookup_by_name_or_id_nr(domid) + + @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', - ['domain', sedf_info['domain']], + ['domid', sedf_info['domid']], ['period', sedf_info['period']], ['slice', sedf_info['slice']], ['latency', sedf_info['latency']], @@ -538,7 +1173,14 @@ class XendDomain: raise XendError(str(ex)) def domain_shadow_control(self, domid, op): - """Shadow page control.""" + """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) @@ -546,7 +1188,13 @@ class XendDomain: raise XendError(str(ex)) def domain_shadow_mem_get(self, domid): - """Get shadow pagetable memory allocation.""" + """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()) @@ -554,7 +1202,15 @@ class XendDomain: raise XendError(str(ex)) def domain_shadow_mem_set(self, domid, mb): - """Set shadow pagetable memory allocation.""" + """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) @@ -563,8 +1219,13 @@ class XendDomain: def domain_sched_credit_get(self, domid): """Get credit scheduler parameters for a domain. - """ - dominfo = self.domain_lookup_by_name_or_id_nr(domid) + + @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)) try: @@ -574,8 +1235,14 @@ class XendDomain: def domain_sched_credit_set(self, domid, weight = None, cap = None): """Set credit scheduler parameters for a domain. - """ - dominfo = self.domain_lookup_by_name_or_id_nr(domid) + + @param domid: Domain ID or Name + @type domid: int or string. + @type weight: int + @type cap: int + @rtype: 0 + """ + dominfo = self.domain_lookup_nr(domid) if not dominfo: raise XendInvalidDomain(str(domid)) try: @@ -589,17 +1256,25 @@ class XendDomain: elif cap < 0 or cap > dominfo.getVCpuCount() * 100: raise XendError("cap is out of range") + assert type(weight) == int + assert type(cap) == int + return xc.sched_credit_domain_set(dominfo.getDomid(), weight, cap) 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) - @return: 0 on success, -1 on error - """ - dominfo = self.domain_lookup_by_name_or_id_nr(domid) + @type mem: int + @raise XendError: fail to set memory + @rtype: 0 + """ + dominfo = self.domain_lookup_nr(domid) if not dominfo: raise XendInvalidDomain(str(domid)) maxmem = int(mem) * 1024 @@ -613,9 +1288,10 @@ class XendDomain: @param first: first IO port @param last: last IO port - @return: 0 on success, -1 on error - """ - dominfo = self.domain_lookup_by_name_or_id_nr(domid) + @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 @@ -632,9 +1308,10 @@ class XendDomain: @param first: first IO port @param last: last IO port - @return: 0 on success, -1 on error - """ - dominfo = self.domain_lookup_by_name_or_id_nr(domid) + @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 diff -r 11b718eb22c9 -r ebed72718263 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Thu Nov 02 12:43:04 2006 -0700 +++ b/tools/python/xen/xend/XendDomainInfo.py Fri Nov 10 11:11:04 2006 -0700 @@ -24,90 +24,39 @@ Author: Mike Wray <mike.wray@xxxxxx> """ -import errno import logging -import string import time import threading +import re +import copy import os +from types import StringTypes import xen.lowlevel.xc from xen.util import asserts from xen.util.blkif import blkdev_uname_to_file from xen.util import security -import balloon -import image -import sxp -import uuid -import XendDomain -import XendRoot + +from xen.xend import balloon, sxp, uuid, image, arch +from xen.xend import XendRoot, XendNode from xen.xend.XendBootloader import bootloader +from xen.xend.XendConfig import XendConfig from xen.xend.XendError import XendError, VmError - +from xen.xend.XendDevices import XendDevices from xen.xend.xenstore.xstransact import xstransact, complete from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain from xen.xend.xenstore.xswatch import xswatch - -from xen.xend import arch - -"""Shutdown code for poweroff.""" -DOMAIN_POWEROFF = 0 - -"""Shutdown code for reboot.""" -DOMAIN_REBOOT = 1 - -"""Shutdown code for suspend.""" -DOMAIN_SUSPEND = 2 - -"""Shutdown code for crash.""" -DOMAIN_CRASH = 3 - -"""Shutdown code for halt.""" -DOMAIN_HALT = 4 - -"""Map shutdown codes to strings.""" -shutdown_reasons = { - DOMAIN_POWEROFF: "poweroff", - DOMAIN_REBOOT : "reboot", - DOMAIN_SUSPEND : "suspend", - DOMAIN_CRASH : "crash", - DOMAIN_HALT : "halt" - } - -restart_modes = [ - "restart", - "destroy", - "preserve", - "rename-restart" - ] - -STATE_DOM_OK = 1 -STATE_DOM_SHUTDOWN = 2 - -SHUTDOWN_TIMEOUT = 30.0 +from xen.xend.XendConstants import * +from xen.xend.XendAPIConstants import * + MIGRATE_TIMEOUT = 30.0 - -ZOMBIE_PREFIX = 'Zombie-' - -"""Constants for the different stages of ext. device migration """ -DEV_MIGRATE_TEST = 0 -DEV_MIGRATE_STEP1 = 1 -DEV_MIGRATE_STEP2 = 2 -DEV_MIGRATE_STEP3 = 3 - -"""Minimum time between domain restarts in seconds.""" -MINIMUM_RESTART_TIME = 20 - -RESTART_IN_PROGRESS = 'xend/restart_in_progress' - xc = xen.lowlevel.xc.xc() xroot = XendRoot.instance() log = logging.getLogger("xend.XendDomainInfo") #log.setLevel(logging.TRACE) - ## # All parameters of VMs that may be configured on-the-fly, or at start-up. @@ -157,6 +106,8 @@ VM_STORE_ENTRIES = [ ('shadow_memory', int), ('maxmem', int), ('start_time', float), + ('on_xend_start', str), + ('on_xend_stop', str), ] VM_STORE_ENTRIES += VM_CONFIG_PARAMS @@ -182,77 +133,102 @@ VM_STORE_ENTRIES += VM_CONFIG_PARAMS def create(config): - """Create a VM from a configuration. - - @param config configuration - @raise: VmError for invalid configuration + """Creates and start a VM using the supplied configuration. + (called from XMLRPCServer directly) + + @param config: A configuration object involving lists of tuples. + @type config: list of lists, eg ['vm', ['image', 'xen.gz']] + + @rtype: XendDomainInfo + @return: A up and running XendDomainInfo instance + @raise VmError: Invalid configuration or failure to start. """ log.debug("XendDomainInfo.create(%s)", config) - - vm = XendDomainInfo(parseConfig(config)) + vm = XendDomainInfo(XendConfig(sxp = config)) try: - vm.construct() - vm.initDomain() - vm.storeVmDetails() - vm.storeDomDetails() - vm.registerWatches() - vm.refreshShutdown() - return vm + vm.start() except: log.exception('Domain construction failed') vm.destroy() raise - -def recreate(xeninfo, priv): + 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.""" - - log.debug("XendDomainInfo.recreate(%s)", xeninfo) - - assert not xeninfo['dying'] - - domid = xeninfo['dom'] + and asking us to recreate them causes problems. + + @param xeninfo: Parsed configuration + @type xeninfo: Dictionary + @param priv: TODO, unknown, something to do with memory + @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)", info) + + assert not info['dying'] + + xeninfo = XendConfig(cfg = info) + domid = xeninfo['domid'] uuid1 = xeninfo['handle'] xeninfo['uuid'] = uuid.toString(uuid1) + 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.", domid, xeninfo['uuid']) + 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: - raise XendError( - 'No vm path in store for existing domain %d' % domid) + 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: - raise XendError( - 'No vm/uuid path in store for existing domain %d' % domid) - + 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: - raise XendError( - 'Uuid in store does not match uuid for existing domain %d: ' - '%s != %s' % (domid, uuid2_str, xeninfo['uuid'])) - - vm = XendDomainInfo(xeninfo, domid, dompath, True, priv) - - except Exception, exn: - if priv: - log.warn(str(exn)) - - vm = XendDomainInfo(xeninfo, domid, dompath, True, priv) - vm.recreateDom() - vm.removeVm() - vm.storeVmDetails() - vm.storeDomDetails() - - vm.registerWatches() + 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) + + if needs_reinitialising: + vm._recreateDom() + vm._removeVm() + vm._storeVmDetails() + vm._storeDomDetails() + + vm._registerWatches() vm.refreshShutdown(xeninfo) return vm @@ -260,146 +236,52 @@ def restore(config): def restore(config): """Create a domain and a VM object to do a restore. - @param config: domain configuration + @param config: Domain configuration object + @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)", config) - - vm = XendDomainInfo(parseConfig(config), None, None, False, False, True) + vm = XendDomainInfo(XendConfig(sxp = config), resume = True) try: - vm.construct() - vm.storeVmDetails() - vm.createDevices() - vm.createChannels() - vm.storeDomDetails() - vm.endRestore() + vm.resume() return vm except: vm.destroy() raise - -def parseConfig(config): - def get_cfg(name, conv = None): - val = sxp.child_value(config, name) - - if conv and not val is None: - try: - return conv(val) - except TypeError, exn: - raise VmError( - 'Invalid setting %s = %s in configuration: %s' % - (name, val, str(exn))) - else: - return val - - - log.debug("parseConfig: config is %s", config) - - result = {} - - for e in ROUNDTRIPPING_CONFIG_ENTRIES: - result[e[0]] = get_cfg(e[0], e[1]) - - result['cpu'] = get_cfg('cpu', int) - result['cpus'] = get_cfg('cpus', str) - result['image'] = get_cfg('image') - tmp_security = get_cfg('security') - if tmp_security: - result['security'] = tmp_security - - try: - if result['image']: - v = sxp.child_value(result['image'], 'vcpus') - if result['vcpus'] is None and v is not None: - result['vcpus'] = int(v) - elif v is not None and int(v) != result['vcpus']: - log.warn(('Image VCPUs setting overrides vcpus=%d elsewhere.' - ' Using %s VCPUs for VM %s.') % - (result['vcpus'], v, result['uuid'])) - result['vcpus'] = int(v) - except TypeError, exn: - raise VmError( - 'Invalid configuration setting: vcpus = %s: %s' % - (sxp.child_value(result['image'], 'vcpus', 1), str(exn))) - - try: - # support legacy config files with 'cpu' parameter - # NB: prepending to list to support previous behavior - # where 'cpu' parameter pinned VCPU0. - if result['cpu']: - if result['cpus']: - result['cpus'] = "%s,%s" % (str(result['cpu']), result['cpus']) - else: - result['cpus'] = str(result['cpu']) - - # convert 'cpus' string to list of ints - # 'cpus' 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] - if result['cpus']: - cpus = [] - for c in result['cpus'].split(','): - 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)) - - result['cpus'] = cpus - - except ValueError, exn: - raise VmError( - 'Invalid configuration setting: cpus = %s: %s' % - (result['cpus'], exn)) - - result['backend'] = [] - for c in sxp.children(config, 'backend'): - result['backend'].append(sxp.name(sxp.child0(c))) - - result['device'] = [] - for d in sxp.children(config, 'device'): - c = sxp.child0(d) - result['device'].append((sxp.name(c), c)) - - # Configuration option "restart" is deprecated. Parse it, but - # let on_xyz override it if they are present. - restart = get_cfg('restart') - if restart: - def handle_restart(event, val): - if result[event] is None: - result[event] = val - - if restart == "onreboot": - handle_restart('on_poweroff', 'destroy') - handle_restart('on_reboot', 'restart') - handle_restart('on_crash', 'destroy') - elif restart == "always": - handle_restart('on_poweroff', 'restart') - handle_restart('on_reboot', 'restart') - handle_restart('on_crash', 'restart') - elif restart == "never": - handle_restart('on_poweroff', 'destroy') - handle_restart('on_reboot', 'destroy') - handle_restart('on_crash', 'destroy') - else: - log.warn("Ignoring malformed and deprecated config option " - "restart = %s", restart) - - result['start_time'] = get_cfg('start_time', float) - - log.debug("parseConfig: result is %s", result) - return result - +def createDormant(xeninfo): + """Create a dormant/inactive XenDomainInfo without creating VM. + This is for creating instances of persistent domains that are not + yet start. + + @param xeninfo: Parsed configuration + @type xeninfo: dictionary + + @rtype: XendDomainInfo + @return: A up and running XendDomainInfo instance + @raise XendError: Errors with configuration. + """ + + log.debug("XendDomainInfo.createDormant(%s)", xeninfo) + + # domid does not make sense for non-running domains. + xeninfo.pop('domid', None) + vm = XendDomainInfo(XendConfig(cfg = xeninfo)) + 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) @@ -411,17 +293,19 @@ def shutdown_reason(code): @return: shutdown reason @rtype: string """ - return shutdown_reasons.get(code, "?") + 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]['dom']: + if domlist and dom == domlist[0]['domid']: return domlist[0] except Exception, err: # ignore missing domain @@ -430,32 +314,87 @@ def dom_get(dom): 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 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 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 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): + """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 privledged domain (Dom 0) (TODO: really?) + @type priv: bool + @keyword resume: Is this domain being resumed? + @type resume: bool + """ self.info = info - - if not self.infoIsSet('uuid'): - self.info['uuid'] = uuid.toString(uuid.create()) - - if domid is not None: + if domid == None: + self.domid = self.info.get('domid') + else: self.domid = domid - elif 'dom' in info: - self.domid = int(info['dom']) - else: - self.domid = None - - self.vmpath = XendDomain.VMROOT + self.info['uuid'] + + #REMOVE: uuid is now generated in XendConfig + #if not self._infoIsSet('uuid'): + # self.info['uuid'] = uuid.toString(uuid.create()) + + #REMOVE: domid logic can be shortened + #if domid is not None: + # self.domid = domid + #elif info.has_key('dom'): + # self.domid = int(info['dom']) + #else: + # self.domid = None + + self.vmpath = XS_VMROOT + self.info['uuid'] self.dompath = dompath - if augment: - self.augmentInfo(priv) - - self.validateInfo() - self.image = None - self.security = None self.store_port = None self.store_mfn = None self.console_port = None @@ -463,67 +402,215 @@ class XendDomainInfo: self.vmWatch = None self.shutdownWatch = None - self.shutdownStartTime = None - self.state = STATE_DOM_OK + self.state = DOM_STATE_HALTED self.state_updated = threading.Condition() self.refresh_shutdown_lock = threading.Condition() + self._deviceControllers = {} + + for state in DOM_STATES_OLD: + self.info[state] = 0 + + if augment: + self._augmentInfo(priv) + + self._checkName(self.info['name']) self.setResume(resume) - - ## private: - - def readVMDetails(self, params): - """Read the specified parameters from the store. + + + # + # 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.state == DOM_STATE_HALTED: + try: + self._constructDomain() + self._initDomain() + self._storeVmDetails() + self._storeDomDetails() + self._registerWatches() + self.refreshShutdown() + self.unpause() + + # save running configuration if XendDomains believe domain is + # persistent + # + if is_managed: + xendomains = XendDomain.instance() + 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.""" + if self.state in (DOM_STATE_HALTED, DOM_STATE_SUSPENDED): + try: + self._constructDomain() + self._storeVmDetails() + self._createDevices() + self._createChannels() + self._storeDomDetails() + self._endRestore() + except: + log.exception('VM resume failed') + raise + else: + raise XendError('VM already running') + + def shutdown(self, reason): + """Shutdown a domain by signalling this via xenstored.""" + log.debug('XendDomainInfo.shutdown') + if self.state in (DOM_STATE_SHUTDOWN, DOM_STATE_HALTED,): + raise XendError('Domain cannot be shutdown') + + if not reason in DOMAIN_SHUTDOWN_REASONS.values(): + raise XendError('Invalid reason: %s' % reason) + self._storeDom("control/shutdown", reason) + + def pause(self): + """Pause domain + + @raise XendError: Failed pausing a domain """ try: - return self.gatherVm(*params) + xc.domain_pause(self.domid) + self._stateSet(DOM_STATE_PAUSED) + except Exception, ex: + raise XendError("Domain unable to be paused: %s" % str(ex)) + + def unpause(self): + """Unpause domain + + @raise XendError: Failed unpausing a domain + """ + try: + xc.domain_unpause(self.domid) + self._stateSet(DOM_STATE_RUNNING) + except Exception, ex: + raise XendError("Domain unable to be unpaused: %s" % str(ex)) + + def send_sysrq(self, key): + """ Send a Sysrq equivalent key via xenstored.""" + asserts.isCharConvertible(key) + self._storeDom("control/sysrq", '%c' % key) + + def device_create(self, dev_config): + """Create a new device. + + @param dev_config: device configuration + @type dev_config: dictionary (parsed config) + """ + log.debug("XendDomainInfo.device_create: %s" % dev_config) + dev_type = sxp.name(dev_config) + devid = self._createDevice(dev_type, dev_config) + self.info.device_add(dev_type, cfg_sxp = dev_config) + self._waitForDevice(dev_type, devid) + return self.getDeviceController(dev_type).sxpr(devid) + + def device_configure(self, dev_config, devid): + """Configure an existing device. + + @param dev_config: device configuration + @type dev_config: dictionary (parsed config) + @param devid: device id + @type devid: int + """ + deviceClass = sxp.name(dev_config) + self._reconfigureDevice(deviceClass, devid, dev_config) + + 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 destroyDevice(self, deviceClass, devid): + try: + devid = int(devid) 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 storeChanged(self, _): - log.trace("XendDomainInfo.storeChanged"); - - changed = False - - def f(x, y): - if y is not None and self.info[x[0]] != y: - self.info[x[0]] = y - changed = True - - map(f, VM_CONFIG_PARAMS, self.readVMDetails(VM_CONFIG_PARAMS)) - - im = self.readVm('image') - current_im = self.info['image'] - if (im is not None and - (current_im is None or sxp.to_string(current_im) != im)): - self.info['image'] = sxp.from_string(im) - changed = True - - if changed: - # Update the domain section of the store, as this contains some - # parameters derived from the VM configuration. - self.storeDomDetails() - - return 1 - - - def augmentInfo(self, priv): - """Augment self.info, as given to us through {@link #recreate}, with - values taken from the store. This recovers those values known to xend - but not to the hypervisor. + # devid is not a number, let's search for it in xenstore. + devicePath = '%s/device/%s' % (self.dompath, deviceClass) + for entry in xstransact.List(devicePath): + backend = xstransact.Read('%s/%s' % (devicePath, entry), + "backend") + devName = xstransact.Read(backend, "dev") + if devName == devid: + # We found the integer matching our devid, use it instead + devid = entry + break + + return self.getDeviceController(deviceClass).destroyDevice(devid) + + + def getDeviceSxprs(self, deviceClass): + return self.getDeviceController(deviceClass).sxprs() + + + def setMemoryTarget(self, target): + """Set the memory target of this domain. + @param target: In MiB. + """ + log.debug("Setting memory target of domain %s (%d) to %d MiB.", + self.info['name'], self.domid, target) + + if target <= 0: + raise XendError('Invalid memory size') + + self.info['memory'] = target + self.storeVm("memory", target) + self._storeDom("memory/target", target << 10) + + def getVCPUInfo(self): + try: + # We include the domain name and ID, to help xm. + sxpr = ['domain', + ['domid', self.domid], + ['name', self.info['name']], + ['vcpu_count', self.info['online_vcpus']]] + + for i in range(0, self.info['max_vcpu_id']+1): + 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']]]) + + return sxpr + + except RuntimeError, exn: + raise XendError(str(exn)) + + # + # 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. """ def useIfNeeded(name, val): - if not self.infoIsSet(name) and val is not None: + if not self._infoIsSet(name) and val is not None: self.info[name] = val if priv: @@ -536,199 +623,64 @@ class XendDomainInfo: entries.append(('security', str)) map(lambda x, y: useIfNeeded(x[0], y), entries, - self.readVMDetails(entries)) - - device = [] - for c in controllerClasses: - devconfig = self.getDeviceConfigurations(c) + self._readVMDetails(entries)) + + devices = [] + + for devclass in XendDevices.valid_devices(): + devconfig = self.getDeviceController(devclass).configurations() if devconfig: - device.extend(map(lambda x: (c, x), devconfig)) - useIfNeeded('device', device) - - - def validateInfo(self): - """Validate and normalise the info block. This has either been parsed - by parseConfig, or received from xc through recreate and augmented by - the current store contents. - """ - def defaultInfo(name, val): - if not self.infoIsSet(name): - self.info[name] = val() - - try: - defaultInfo('name', lambda: "Domain-%d" % self.domid) - defaultInfo('on_poweroff', lambda: "destroy") - defaultInfo('on_reboot', lambda: "restart") - defaultInfo('on_crash', lambda: "restart") - defaultInfo('features', lambda: "") - defaultInfo('cpu', lambda: None) - defaultInfo('cpus', lambda: []) - defaultInfo('cpu_cap', lambda: 0) - defaultInfo('cpu_weight', lambda: 256) - - # some domains don't have a config file (e.g. dom0 ) - # to set number of vcpus so we derive available cpus - # from max_vcpu_id which is present for running domains. - if not self.infoIsSet('vcpus') and self.infoIsSet('max_vcpu_id'): - avail = int(self.info['max_vcpu_id'])+1 - else: - avail = int(1) - - defaultInfo('vcpus', lambda: avail) - defaultInfo('online_vcpus', lambda: self.info['vcpus']) - defaultInfo('max_vcpu_id', lambda: self.info['vcpus']-1) - defaultInfo('vcpu_avail', lambda: (1 << self.info['vcpus']) - 1) - - defaultInfo('memory', lambda: 0) - defaultInfo('shadow_memory', lambda: 0) - defaultInfo('maxmem', lambda: 0) - defaultInfo('bootloader', lambda: None) - defaultInfo('bootloader_args', lambda: None) - defaultInfo('backend', lambda: []) - defaultInfo('device', lambda: []) - defaultInfo('image', lambda: None) - defaultInfo('security', lambda: None) - - self.check_name(self.info['name']) - - if isinstance(self.info['image'], str): - self.info['image'] = sxp.from_string(self.info['image']) - - if isinstance(self.info['security'], str): - self.info['security'] = sxp.from_string(self.info['security']) - - if self.info['memory'] == 0: - if self.infoIsSet('mem_kb'): - self.info['memory'] = (self.info['mem_kb'] + 1023) / 1024 - if self.info['memory'] <= 0: - raise VmError('Invalid memory size') - - if self.info['maxmem'] < self.info['memory']: - self.info['maxmem'] = self.info['memory'] - - for (n, c) in self.info['device']: - if not n or not c or n not in controllerClasses: - raise VmError('invalid device (%s, %s)' % - (str(n), str(c))) - - for event in ['on_poweroff', 'on_reboot', 'on_crash']: - if self.info[event] not in restart_modes: - raise VmError('invalid restart event: %s = %s' % - (event, str(self.info[event]))) - - except KeyError, exn: - log.exception(exn) - raise VmError('Unspecified domain detail: %s' % exn) - - - def readVm(self, *args): + devices.extend(map(lambda conf: (devclass, conf), devconfig)) + + if not self.info['device'] and devices is not None: + for device in devices: + self.info.device_add(device[0], cfg_sxp = device) + + # + # Function to update xenstore /vm/* + # + + def _readVm(self, *args): return xstransact.Read(self.vmpath, *args) - def writeVm(self, *args): + def _writeVm(self, *args): return xstransact.Write(self.vmpath, *args) - def removeVm(self, *args): + def _removeVm(self, *args): return xstransact.Remove(self.vmpath, *args) - def gatherVm(self, *args): + def _gatherVm(self, *args): return xstransact.Gather(self.vmpath, *args) - - - ## public: def storeVm(self, *args): return xstransact.Store(self.vmpath, *args) - - ## private: - - def readDom(self, *args): + # + # Function to update xenstore /dom/* + # + + def _readDom(self, *args): return xstransact.Read(self.dompath, *args) - def writeDom(self, *args): + def _writeDom(self, *args): return xstransact.Write(self.dompath, *args) - - ## public: - - def removeDom(self, *args): + def _removeDom(self, *args): return xstransact.Remove(self.dompath, *args) - def recreateDom(self): - complete(self.dompath, lambda t: self._recreateDom(t)) - - def _recreateDom(self, t): + def _storeDom(self, *args): + return xstransact.Store(self.dompath, *args) + + 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 }) - - - ## private: - - def storeDom(self, *args): - return xstransact.Store(self.dompath, *args) - - - ## public: - - def completeRestore(self, store_mfn, console_mfn): - - log.debug("XendDomainInfo.completeRestore") - - self.store_mfn = store_mfn - self.console_mfn = console_mfn - - self.introduceDomain() - self.storeDomDetails() - self.registerWatches() - self.refreshShutdown() - - log.debug("XendDomainInfo.completeRestore done") - - - def storeVmDetails(self): - to_store = {} - - for k in VM_STORE_ENTRIES: - if self.infoIsSet(k[0]): - to_store[k[0]] = str(self.info[k[0]]) - - if self.infoIsSet('image'): - to_store['image'] = sxp.to_string(self.info['image']) - - if self.infoIsSet('security'): - security = self.info['security'] - to_store['security'] = sxp.to_string(security) - for idx in range(0, len(security)): - if security[idx][0] == 'access_control': - to_store['security/access_control'] = sxp.to_string([ security[idx][1] , security[idx][2] ]) - for aidx in range(1, len(security[idx])): - if security[idx][aidx][0] == 'label': - to_store['security/access_control/label'] = security[idx][aidx][1] - if security[idx][aidx][0] == 'policy': - to_store['security/access_control/policy'] = security[idx][aidx][1] - if security[idx][0] == 'ssidref': - to_store['security/ssidref'] = str(security[idx][1]) - - if not self.readVm('xend/restart_count'): - to_store['xend/restart_count'] = str(0) - - log.debug("Storing VM details: %s", 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 }) - - - def storeDomDetails(self): + t.write('vm', self.vmpath) + + def _storeDomDetails(self): to_store = { 'domid': str(self.domid), 'vm': self.vmpath, @@ -746,16 +698,13 @@ class XendDomainInfo: f('store/port', self.store_port) f('store/ring-ref', self.store_mfn) - to_store.update(self.vcpuDomDetails()) + to_store.update(self._vcpuDomDetails()) log.debug("Storing domain details: %s", to_store) - self.writeDom(to_store) - - - ## private: - - def vcpuDomDetails(self): + self._writeDom(to_store) + + def _vcpuDomDetails(self): def availability(n): if self.info['vcpu_avail'] & (1 << n): return 'online' @@ -767,25 +716,80 @@ class XendDomainInfo: result["cpu/%d/availability" % v] = availability(v) return result - - ## public: - - def registerWatches(self): + # + # 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.vmWatch = xswatch(self.vmpath, self._storeChanged) self.shutdownWatch = xswatch(self.dompath + '/control/shutdown', - self.handleShutdownWatch) + self._handleShutdownWatch) + + def _storeChanged(self, _): + log.trace("XendDomainInfo.storeChanged"); + + changed = False + + def f(x, y): + if y is not None and self.info[x[0]] != y: + self.info[x[0]] = y + changed = True + + map(f, VM_CONFIG_PARAMS, self._readVMDetails(VM_CONFIG_PARAMS)) + + im = self._readVm('image') + current_im = self.info['image'] + if (im is not None and + (current_im is None or sxp.to_string(current_im) != im)): + self.info['image'] = sxp.from_string(im) + changed = True + + if changed: + # Update the domain section of the store, as this contains some + # parameters derived from the VM configuration. + self._storeDomDetails() + + 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 setName(self, name): - self.check_name(name) + self._checkName(name) self.info['name'] = name self.storeVm("name", name) @@ -795,12 +799,13 @@ class XendDomainInfo: 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 @@ -812,11 +817,10 @@ class XendDomainInfo: def getVCpuCount(self): return self.info['vcpus'] - def setVCpuCount(self, vcpus): self.info['vcpu_avail'] = (1 << vcpus) - 1 self.storeVm('vcpu_avail', self.info['vcpu_avail']) - self.writeDom(self.vcpuDomDetails()) + self._writeDom(self._vcpuDomDetails()) def getLabel(self): return security.get_security_info(self.info, 'label') @@ -834,21 +838,23 @@ class XendDomainInfo: def getWeight(self): return self.info['cpu_weight'] - def endRestore(self): - self.setResume(False) - def setResume(self, state): self.info['resume'] = state def getRestartCount(self): - return self.readVm('xend/restart_count') + 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: @@ -862,6 +868,7 @@ class XendDomainInfo: # VM may have migrated to a different domain on this # machine. self.cleanupDomain() + self._stateSet(DOM_STATE_HALTED) return if xeninfo['dying']: @@ -873,10 +880,11 @@ class XendDomainInfo: # 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'): + if self._readDom('xend/shutdown_completed'): # We've seen this shutdown already, but we are preserving # the domain for debugging. Leave it alone. return @@ -888,9 +896,11 @@ class XendDomainInfo: self.dumpCore() restart_reason = 'crash' + self._stateSet(DOM_STATE_HALTED) elif xeninfo['shutdown']: - if self.readDom('xend/shutdown_completed'): + 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 @@ -901,15 +911,15 @@ class XendDomainInfo: log.info('Domain has shutdown: name=%s id=%d reason=%s.', self.info['name'], self.domid, reason) - self.clearRestart() + self._clearRestart() if reason == 'suspend': - self.state_set(STATE_DOM_SHUTDOWN) + 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() + self._unwatchVm() elif reason in ['poweroff', 'reboot']: restart_reason = reason else: @@ -923,7 +933,11 @@ class XendDomainInfo: else: # Domain is alive. If we are shutting it down, then check # the timeout on that, and destroy it if necessary. - + if xeninfo['paused']: + self._stateSet(DOM_STATE_PAUSED) + else: + self._stateSet(DOM_STATE_RUNNING) + if self.shutdownStartTime: timeout = (SHUTDOWN_TIMEOUT - time.time() + self.shutdownStartTime) @@ -936,61 +950,133 @@ class XendDomainInfo: self.refresh_shutdown_lock.release() if restart_reason: - self.maybeRestart(restart_reason) - - - 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 - - - def shutdown(self, reason): - if not reason in shutdown_reasons.values(): - raise XendError('Invalid reason: %s' % reason) - if self.domid == 0: - raise XendError("Can't specify Domain-0") - self.storeDom("control/shutdown", reason) - - - ## private: - - def clearRestart(self): - self.removeDom("xend/shutdown_start_time") - - - def maybeRestart(self, reason): + self._maybeRestart(restart_reason) + + + # + # Restart functions - handling whether we come back up on shutdown. + # + + def _clearRestart(self): + self._removeDom("xend/shutdown_start_time") + + + def _maybeRestart(self, reason): # Dispatch to the correct method based upon the configured on_{reason} # behaviour. {"destroy" : self.destroy, - "restart" : self.restart, - "preserve" : self.preserve, - "rename-restart" : self.renameRestart}[self.info['on_' + reason]]() - - - def renameRestart(self): - self.restart(True) - - - def dumpCore(self,corefile=None): + "restart" : self._restart, + "preserve" : self._preserve, + "rename-restart" : self._renameRestart}[self.info['on_' + reason]]() + + + 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 + + self._configureBootloader() + config = self.sxpr() + + if self._infoIsSet('cpus') and len(self.info['cpus']) != 0: + config.append(['cpus', reduce(lambda x, y: str(x) + "," + str(y), + self.info['cpus'])]) + + 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') + + now = time.time() + rst = self._readVm('xend/previous_restart_time') + if rst: + rst = float(rst) + timeout = now - rst + if timeout < MINIMUM_RESTART_TIME: + log.error( + 'VM %s restarting too fast (%f seconds since the last ' + 'restart). Refusing to restart to avoid loops.', + self.info['name'], timeout) + self.destroy() + return + + self._writeVm('xend/previous_restart_time', str(now)) + + try: + if rename: + self._preserveForRestart() + else: + self._unwatchVm() + self.destroyDomain() + + # 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(config) + new_dom.unpause() + rst_cnt = self._readVm('xend/restart_count') + rst_cnt = int(rst_cnt) + 1 + self._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'], self.domid, self.info['uuid'], + new_name, new_uuid) + self._unwatchVm() + self._releaseDevices() + self.info['name'] = new_name + self.info['uuid'] = new_uuid + self.vmpath = XS_VMROOT + new_uuid + self._storeVmDetails() + self._preserve() + + + def _preserve(self): + log.info("Preserving dead domain %s (%d).", self.info['name'], + 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. Nothrow guarantee.""" try: @@ -1011,260 +1097,132 @@ class XendDomainInfo: self.domid, self.info['name']) raise XendError("Failed to dump core: %s" % str(ex)) - ## public: - - def setMemoryTarget(self, target): - """Set the memory target of this domain. - @param target In MiB. - """ - if target <= 0: - raise XendError('Invalid memory size') - - log.debug("Setting memory target of domain %s (%d) to %d MiB.", - self.info['name'], self.domid, target) - - self.info['memory'] = target - self.storeVm("memory", target) - self.storeDom("memory/target", target << 10) - - - def update(self, info = None): - """Update with info from xc.domain_getinfo(). - """ - - log.trace("XendDomainInfo.update(%s) on domain %d", info, self.domid) - if not info: - info = dom_get(self.domid) - if not info: - return - - #manually update ssidref / security fields - if security.on() and info.has_key('ssidref'): - if (info['ssidref'] != 0) and self.info.has_key('security'): - security_field = self.info['security'] - if not security_field: - #create new security element - self.info.update({'security': [['ssidref', str(info['ssidref'])]]}) - #ssidref field not used any longer - info.pop('ssidref') - - self.info.update(info) - self.validateInfo() - self.refreshShutdown(info) - - log.trace("XendDomainInfo.update done on domain %d: %s", self.domid, - self.info) - - - ## private: - - def state_set(self, state): - self.state_updated.acquire() - try: - if self.state != state: - self.state = state - self.state_updated.notifyAll() - finally: - self.state_updated.release() - - - ## public: - - def waitForShutdown(self): - self.state_updated.acquire() - try: - while self.state == STATE_DOM_OK: - self.state_updated.wait() - finally: - self.state_updated.release() - - - def __str__(self): - s = "<domain" - s += " id=" + str(self.domid) - s += " name=" + self.info['name'] - s += " memory=" + str(self.info['memory']) - s += ">" - return s - - __repr__ = __str__ - - - ## private: - - def createDevice(self, deviceClass, devconfig): - return self.getDeviceController(deviceClass).createDevice(devconfig) - - - def waitForDevices_(self, deviceClass): - return self.getDeviceController(deviceClass).waitForDevices() - - - def waitForDevice(self, deviceClass, devid): + # + # 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 reconfigureDevice(self, deviceClass, devid, devconfig): + def _reconfigureDevice(self, deviceClass, devid, devconfig): return self.getDeviceController(deviceClass).reconfigureDevice( devid, devconfig) - - ## public: - - def destroyDevice(self, deviceClass, devid): - if type(devid) is str: - devicePath = '%s/device/%s' % (self.dompath, deviceClass) - for entry in xstransact.List(devicePath): - backend = xstransact.Read('%s/%s' % (devicePath, entry), - "backend") - devName = xstransact.Read(backend, "dev") - if devName == devid: - # We found the integer matching our devid, use it instead - devid = entry - break - return self.getDeviceController(deviceClass).destroyDevice(devid) - - - def getDeviceSxprs(self, deviceClass): - return self.getDeviceController(deviceClass).sxprs() + def _createDevices(self): + """Create the devices for a vm. + + @raise: VmError for invalid devices + """ + for (devclass, config) in self.info.all_devices_sxpr(): + log.info("createDevice: %s : %s" % (devclass, config)) + self._createDevice(devclass, config) + + if self.image: + self.image.createDeviceModel() + + def _releaseDevices(self): + """Release all domain's devices. Nothrow guarantee.""" + + while True: + t = xstransact("%s/device" % self.dompath) + for devclass in XendDevices.valid_devices(): + for dev in t.list(devclass): + try: + t.remove(dev) + 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'], devclass, dev) + if t.commit(): + break + + 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) + 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) ## private: - def getDeviceConfigurations(self, deviceClass): - return self.getDeviceController(deviceClass).configurations() - - - def getDeviceController(self, name): - if name not in controllerClasses: - raise XendError("unknown device type: " + str(name)) - - return controllerClasses[name](self) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |