[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 Hollis Blanchard <hollisb@xxxxxxxxxx> # Node ID 87cefa5f7c5e431eedfde8a500932abfe1f7a952 # Parent 61204c1d740ef3da8913c1f15bee79cc4a7ac134 # Parent ec8dd0528fc69fc643268493d5a3d722a5650cd7 merge with xen-unstable.hg --- tools/ioemu/CVS/Entries | 109 tools/ioemu/CVS/Repository | 1 tools/ioemu/CVS/Root | 1 tools/ioemu/CVS/Tag | 1 tools/ioemu/audio/CVS/Entries | 19 tools/ioemu/audio/CVS/Repository | 1 tools/ioemu/audio/CVS/Root | 1 tools/ioemu/audio/CVS/Tag | 1 tools/ioemu/fpu/CVS/Entries | 7 tools/ioemu/fpu/CVS/Repository | 1 tools/ioemu/fpu/CVS/Root | 1 tools/ioemu/fpu/CVS/Tag | 1 tools/ioemu/hw/CVS/Entries | 72 tools/ioemu/hw/CVS/Repository | 1 tools/ioemu/hw/CVS/Root | 1 tools/ioemu/hw/CVS/Tag | 1 tools/ioemu/keymaps/CVS/Entries | 36 tools/ioemu/keymaps/CVS/Repository | 1 tools/ioemu/keymaps/CVS/Root | 1 tools/ioemu/keymaps/CVS/Tag | 1 tools/ioemu/pc-bios/CVS/Entries | 15 tools/ioemu/pc-bios/CVS/Repository | 1 tools/ioemu/pc-bios/CVS/Root | 1 tools/ioemu/pc-bios/CVS/Tag | 1 tools/ioemu/pc-bios/proll.patch | 3836 ---------- tools/ioemu/target-i386/CVS/Entries | 13 tools/ioemu/target-i386/CVS/Repository | 1 tools/ioemu/target-i386/CVS/Root | 1 tools/ioemu/target-i386/CVS/Tag | 1 tools/ioemu/tests/CVS/Entries | 18 tools/ioemu/tests/CVS/Repository | 1 tools/ioemu/tests/CVS/Root | 1 tools/ioemu/tests/CVS/Tag | 1 xen/include/xen/reboot.h | 8 .hgignore | 1 buildconfigs/linux-defconfig_xen0_ia64 | 14 buildconfigs/linux-defconfig_xenU_ia64 | 16 buildconfigs/linux-defconfig_xen_ia64 | 14 docs/figs/acm_ezpolicy.eps | 650 + docs/figs/acm_overview.eps | 1459 +++ docs/src/user.tex | 984 ++ extras/mini-os/console/xencons_ring.c | 2 extras/mini-os/events.c | 72 extras/mini-os/gnttab.c | 12 extras/mini-os/include/events.h | 24 extras/mini-os/include/gnttab.h | 1 extras/mini-os/time.c | 2 extras/mini-os/xenbus/xenbus.c | 3 linux-2.6-xen-sparse/arch/i386/kernel/ldt-xen.c | 1 linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c | 2 linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c | 3 linux-2.6-xen-sparse/arch/ia64/Kconfig | 15 linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c | 3 linux-2.6-xen-sparse/drivers/xen/Kconfig | 9 linux-2.6-xen-sparse/drivers/xen/netback/common.h | 18 linux-2.6-xen-sparse/drivers/xen/netback/interface.c | 84 linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 545 - linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c | 27 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 582 + linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c | 4 linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c | 3 linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c | 15 linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c | 10 linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c | 1 linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c | 39 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c | 114 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c | 4 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h | 16 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/mmu.h | 3 linux-2.6-xen-sparse/include/asm-i386/spinlock.h | 4 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/mmu.h | 1 linux-2.6-xen-sparse/include/xen/pcifront.h | 42 tools/blktap/drivers/Makefile | 19 tools/blktap/drivers/blktapctrl.c | 21 tools/blktap/lib/Makefile | 14 tools/examples/block | 18 tools/examples/xmexample.hvm | 10 tools/firmware/Makefile | 2 tools/firmware/acpi/acpi_dsdt.asl | 235 tools/firmware/acpi/acpi_dsdt.c | 531 - tools/firmware/hvmloader/Makefile | 9 tools/firmware/hvmloader/acpi_madt.c | 4 tools/firmware/hvmloader/hvmloader.c | 125 tools/firmware/hvmloader/hypercall.h | 180 tools/firmware/hvmloader/mp_tables.c | 3 tools/firmware/hvmloader/util.c | 96 tools/firmware/hvmloader/util.h | 19 tools/firmware/vmxassist/vm86.c | 31 tools/ioemu/.CVS/Entries | 109 tools/ioemu/.CVS/Entries.Log | 7 tools/ioemu/.CVS/Repository | 1 tools/ioemu/.CVS/Root | 1 tools/ioemu/.CVS/Tag | 1 tools/ioemu/.cvsignore | 13 tools/ioemu/Changelog | 19 tools/ioemu/Makefile | 31 tools/ioemu/Makefile.target | 55 tools/ioemu/TODO | 2 tools/ioemu/VERSION | 2 tools/ioemu/audio/.CVS/Entries | 20 tools/ioemu/audio/.CVS/Repository | 1 tools/ioemu/audio/.CVS/Root | 1 tools/ioemu/audio/.CVS/Tag | 1 tools/ioemu/audio/alsaaudio.c | 23 tools/ioemu/audio/audio.c | 452 + tools/ioemu/audio/audio.h | 46 tools/ioemu/audio/audio_int.h | 42 tools/ioemu/audio/audio_template.h | 33 tools/ioemu/audio/coreaudio.c | 16 tools/ioemu/audio/dsound_template.h | 20 tools/ioemu/audio/dsoundaudio.c | 8 tools/ioemu/audio/fmodaudio.c | 10 tools/ioemu/audio/noaudio.c | 40 tools/ioemu/audio/ossaudio.c | 44 tools/ioemu/audio/rate_template.h | 2 tools/ioemu/audio/sdlaudio.c | 10 tools/ioemu/audio/wavaudio.c | 4 tools/ioemu/audio/wavcapture.c | 164 tools/ioemu/block-bochs.c | 2 tools/ioemu/block-cloop.c | 2 tools/ioemu/block-cow.c | 9 tools/ioemu/block-qcow.c | 9 tools/ioemu/block-vmdk.c | 9 tools/ioemu/block-vpc.c | 2 tools/ioemu/block-vvfat.c | 1 tools/ioemu/block.c | 64 tools/ioemu/block_int.h | 1 tools/ioemu/cocoa.m | 60 tools/ioemu/configure | 55 tools/ioemu/console.c | 170 tools/ioemu/cpu-all.h | 102 tools/ioemu/cpu-defs.h | 2 tools/ioemu/cpu-exec.c | 49 tools/ioemu/disas.c | 4 tools/ioemu/dyngen-exec.h | 27 tools/ioemu/dyngen.c | 92 tools/ioemu/dyngen.h | 8 tools/ioemu/elf.h | 2 tools/ioemu/exec-all.h | 2 tools/ioemu/exec.c | 33 tools/ioemu/fpu/.CVS/Entries | 7 tools/ioemu/fpu/.CVS/Repository | 1 tools/ioemu/fpu/.CVS/Root | 1 tools/ioemu/fpu/.CVS/Tag | 1 tools/ioemu/fpu/softfloat-native.c | 13 tools/ioemu/gdbstub.c | 131 tools/ioemu/hw/.CVS/Entries | 89 tools/ioemu/hw/.CVS/Repository | 1 tools/ioemu/hw/.CVS/Root | 1 tools/ioemu/hw/.CVS/Tag | 1 tools/ioemu/hw/acpi-dsdt.dsl | 559 + tools/ioemu/hw/acpi-dsdt.hex | 278 tools/ioemu/hw/acpi.c | 615 + tools/ioemu/hw/adlib.c | 4 tools/ioemu/hw/apb_pci.c | 232 tools/ioemu/hw/apic.c | 4 tools/ioemu/hw/cdrom.c | 156 tools/ioemu/hw/cuda.c | 2 tools/ioemu/hw/es1370.c | 10 tools/ioemu/hw/esp.c | 538 - tools/ioemu/hw/grackle_pci.c | 156 tools/ioemu/hw/i8259.c | 2 tools/ioemu/hw/ide.c | 135 tools/ioemu/hw/lsi53c895a.c | 1571 ++++ tools/ioemu/hw/m48t59.c | 10 tools/ioemu/hw/mips_r4k.c | 6 tools/ioemu/hw/ne2000.c | 2 tools/ioemu/hw/pc.c | 61 tools/ioemu/hw/pci.c | 1489 --- tools/ioemu/hw/pci_host.h | 93 tools/ioemu/hw/pcnet.c | 1789 ++++ tools/ioemu/hw/pcspk.c | 4 tools/ioemu/hw/pflash_cfi02.c | 624 + tools/ioemu/hw/piix4acpi.c | 153 tools/ioemu/hw/piix_pci.c | 435 + tools/ioemu/hw/pl050.c | 2 tools/ioemu/hw/ppc_chrp.c | 20 tools/ioemu/hw/ppc_prep.c | 4 tools/ioemu/hw/prep_pci.c | 167 tools/ioemu/hw/rtl8139.c | 1494 ++- tools/ioemu/hw/sb16.c | 94 tools/ioemu/hw/scsi-disk.c | 478 + tools/ioemu/hw/sh7750.c | 2 tools/ioemu/hw/slavio_intctl.c | 2 tools/ioemu/hw/slavio_timer.c | 2 tools/ioemu/hw/sun4m.c | 14 tools/ioemu/hw/sun4u.c | 18 tools/ioemu/hw/unin_pci.c | 261 tools/ioemu/hw/usb-hid.c | 14 tools/ioemu/hw/usb-hub.c | 26 tools/ioemu/hw/usb-msd.c | 402 + tools/ioemu/hw/usb-ohci.c | 1190 +++ tools/ioemu/hw/usb-uhci.c | 22 tools/ioemu/hw/usb.h | 18 tools/ioemu/hw/versatile_pci.c | 119 tools/ioemu/hw/versatilepb.c | 216 tools/ioemu/hw/vga.c | 137 tools/ioemu/hw/vga_int.h | 9 tools/ioemu/hw/vga_template.h | 234 tools/ioemu/keymaps/.CVS/Entries | 36 tools/ioemu/keymaps/.CVS/Repository | 1 tools/ioemu/keymaps/.CVS/Root | 1 tools/ioemu/keymaps/.CVS/Tag | 1 tools/ioemu/kqemu.c | 11 tools/ioemu/loader.c | 2 tools/ioemu/monitor.c | 169 tools/ioemu/osdep.c | 22 tools/ioemu/osdep.h | 2 tools/ioemu/patches/acpi-poweroff-support | 8 tools/ioemu/patches/acpi-support | 158 tools/ioemu/patches/acpi-timer-support | 226 tools/ioemu/patches/domain-destroy | 21 tools/ioemu/patches/domain-reset | 12 tools/ioemu/patches/domain-timeoffset | 40 tools/ioemu/patches/hypervisor-pit | 18 tools/ioemu/patches/ide-hd-multithread | 24 tools/ioemu/patches/ioemu-ia64 | 43 tools/ioemu/patches/qemu-64bit | 28 tools/ioemu/patches/qemu-allow-disable-sdl | 27 tools/ioemu/patches/qemu-bugfixes | 25 tools/ioemu/patches/qemu-cleanup | 22 tools/ioemu/patches/qemu-dm | 126 tools/ioemu/patches/qemu-fix-memset-args | 15 tools/ioemu/patches/qemu-fix-write-to-disk-synchronous | 66 tools/ioemu/patches/qemu-hvm-banner | 4 tools/ioemu/patches/qemu-init-vgabios | 6 tools/ioemu/patches/qemu-logging | 28 tools/ioemu/patches/qemu-no-apic | 16 tools/ioemu/patches/qemu-nobios | 19 tools/ioemu/patches/qemu-smp | 20 tools/ioemu/patches/qemu-target-i386-dm | 48 tools/ioemu/patches/qemu-timer | 14 tools/ioemu/patches/serial-non-block | 4 tools/ioemu/patches/series | 6 tools/ioemu/patches/shadow-vram | 12 tools/ioemu/patches/shared-vram | 26 tools/ioemu/patches/support-xm-console | 6 tools/ioemu/patches/vnc-access-monitor-vt | 16 tools/ioemu/patches/vnc-cleanup | 19 tools/ioemu/patches/vnc-fixes | 101 tools/ioemu/patches/vnc-start-vncviewer | 48 tools/ioemu/patches/vnc-title-domain-name | 6 tools/ioemu/patches/xen-build | 57 tools/ioemu/patches/xen-domain-name | 30 tools/ioemu/patches/xen-domid | 18 tools/ioemu/patches/xen-mm | 27 tools/ioemu/patches/xen-network | 12 tools/ioemu/patches/xenstore-block-device-config | 221 tools/ioemu/patches/xenstore-write-vnc-port | 27 tools/ioemu/pc-bios/.CVS/Entries | 14 tools/ioemu/pc-bios/.CVS/Repository | 1 tools/ioemu/pc-bios/.CVS/Root | 1 tools/ioemu/pc-bios/.CVS/Tag | 1 tools/ioemu/pc-bios/README | 8 tools/ioemu/pc-bios/bios.diff | 87 tools/ioemu/pc-bios/vgabios.diff | 825 -- tools/ioemu/qemu-doc.texi | 250 tools/ioemu/qemu-img.c | 33 tools/ioemu/sdl.c | 27 tools/ioemu/tap-win32.c | 8 tools/ioemu/target-i386/.CVS/Entries | 13 tools/ioemu/target-i386/.CVS/Repository | 1 tools/ioemu/target-i386/.CVS/Root | 1 tools/ioemu/target-i386/.CVS/Tag | 1 tools/ioemu/target-i386/exec.h | 3 tools/ioemu/target-i386/helper.c | 39 tools/ioemu/target-i386/helper2.c | 33 tools/ioemu/target-i386/op.c | 15 tools/ioemu/target-i386/translate.c | 93 tools/ioemu/tests/.CVS/Entries | 18 tools/ioemu/tests/.CVS/Repository | 1 tools/ioemu/tests/.CVS/Root | 1 tools/ioemu/tests/.CVS/Tag | 1 tools/ioemu/tests/Makefile | 3 tools/ioemu/tests/test-i386.c | 22 tools/ioemu/usb-linux.c | 44 tools/ioemu/vl.c | 1370 ++- tools/ioemu/vl.h | 148 tools/ioemu/vnc.c | 258 tools/ioemu/vnchextile.h | 48 tools/ioemu/xenstore.c | 215 tools/libxc/Makefile | 3 tools/libxc/ia64/Makefile | 8 tools/libxc/xc_hvm_build.c | 32 tools/libxc/xc_misc.c | 13 tools/libxc/xenctrl.h | 9 tools/misc/lomount/lomount.c | 6 tools/misc/xend | 2 tools/misc/xenperf.c | 60 tools/python/xen/sv/CreateDomain.py | 1 tools/python/xen/util/auxbin.py | 4 tools/python/xen/xend/XendDomainInfo.py | 2 tools/python/xen/xend/image.py | 30 tools/python/xen/xend/server/DevController.py | 2 tools/python/xen/xend/server/blkif.py | 26 tools/python/xen/xm/create.py | 14 tools/python/xen/xm/main.py | 11 tools/python/xen/xm/shutdown.py | 15 tools/security/Makefile | 2 tools/security/xensec_ezpolicy | 1628 ++++ tools/xenstore/Makefile | 4 tools/xenstore/xenstore_client.c | 106 tools/xenstore/xenstored_core.c | 9 tools/xenstore/xenstored_core.h | 1 tools/xenstore/xenstored_transaction.c | 8 tools/xenstore/xsls.c | 103 xen/Makefile | 22 xen/Rules.mk | 7 xen/arch/ia64/linux-xen/setup.c | 2 xen/arch/ia64/vmx/vmx_support.c | 3 xen/arch/ia64/xen/dom_fw.c | 14 xen/arch/ia64/xen/domain.c | 5 xen/arch/ia64/xen/xensetup.c | 10 xen/arch/powerpc/boot_of.c | 8 xen/arch/powerpc/domain.c | 2 xen/arch/powerpc/domain_build.c | 4 xen/arch/powerpc/mpic_init.c | 1 xen/arch/powerpc/ofd_fixup.c | 4 xen/arch/powerpc/powerpc64/traps.c | 4 xen/arch/x86/cpu/mcheck/mce.c | 4 xen/arch/x86/dom0_ops.c | 2 xen/arch/x86/domain.c | 2 xen/arch/x86/domain_build.c | 7 xen/arch/x86/genapic/es7000plat.c | 1 xen/arch/x86/hvm/hvm.c | 364 xen/arch/x86/hvm/i8259.c | 4 xen/arch/x86/hvm/io.c | 5 xen/arch/x86/hvm/platform.c | 29 xen/arch/x86/hvm/svm/intr.c | 18 xen/arch/x86/hvm/svm/svm.c | 106 xen/arch/x86/hvm/vioapic.c | 37 xen/arch/x86/hvm/vlapic.c | 562 - xen/arch/x86/hvm/vmx/io.c | 17 xen/arch/x86/hvm/vmx/vmx.c | 118 xen/arch/x86/mm.c | 23 xen/arch/x86/setup.c | 22 xen/arch/x86/shadow32.c | 6 xen/arch/x86/shadow_public.c | 6 xen/arch/x86/shutdown.c | 17 xen/arch/x86/traps.c | 124 xen/arch/x86/x86_32/entry.S | 2 xen/arch/x86/x86_32/traps.c | 16 xen/arch/x86/x86_64/entry.S | 2 xen/arch/x86/x86_64/traps.c | 18 xen/common/Makefile | 4 xen/common/domain.c | 27 xen/common/event_channel.c | 108 xen/common/kernel.c | 23 xen/common/keyhandler.c | 2 xen/common/perfc.c | 53 xen/common/sched_credit.c | 17 xen/common/shutdown.c | 66 xen/common/version.c | 56 xen/drivers/char/Makefile | 3 xen/drivers/char/console.c | 31 xen/drivers/char/serial.c | 1 xen/include/asm-ia64/perfc.h | 16 xen/include/asm-ia64/vmx_platform.h | 11 xen/include/asm-powerpc/perfc.h | 16 xen/include/asm-x86/domain.h | 2 xen/include/asm-x86/guest_access.h | 25 xen/include/asm-x86/hvm/domain.h | 8 xen/include/asm-x86/hvm/guest_access.h | 10 xen/include/asm-x86/hvm/hvm.h | 5 xen/include/asm-x86/hvm/support.h | 4 xen/include/asm-x86/hvm/svm/vmmcall.h | 8 xen/include/asm-x86/hvm/vlapic.h | 113 xen/include/asm-x86/hvm/vmx/vmcs.h | 1 xen/include/asm-x86/hvm/vmx/vmx.h | 2 xen/include/asm-x86/perfc.h | 23 xen/include/asm-x86/processor.h | 4 xen/include/asm-x86/shadow.h | 7 xen/include/public/dom0_ops.h | 7 xen/include/public/hvm/ioreq.h | 1 xen/include/public/hvm/params.h | 24 xen/include/public/io/netif.h | 15 xen/include/public/version.h | 3 xen/include/public/xen.h | 1 xen/include/xen/event.h | 37 xen/include/xen/hypercall.h | 5 xen/include/xen/sched.h | 8 xen/include/xen/shutdown.h | 13 xen/include/xen/version.h | 16 ioemu/pc-bios/video.x | 0 384 files changed, 25173 insertions(+), 11053 deletions(-) diff -r 61204c1d740e -r 87cefa5f7c5e .hgignore --- a/.hgignore Thu Jul 27 20:07:02 2006 -0400 +++ b/.hgignore Mon Aug 07 18:00:22 2006 -0500 @@ -156,6 +156,7 @@ ^tools/xenstat/xentop/xentop$ ^tools/xenstore/testsuite/tmp/.*$ ^tools/xenstore/xen$ +^tools/xenstore/xenstore-chmod$ ^tools/xenstore/xenstore-exists$ ^tools/xenstore/xenstore-list$ ^tools/xenstore/xenstore-read$ diff -r 61204c1d740e -r 87cefa5f7c5e buildconfigs/linux-defconfig_xen0_ia64 --- a/buildconfigs/linux-defconfig_xen0_ia64 Thu Jul 27 20:07:02 2006 -0400 +++ b/buildconfigs/linux-defconfig_xen0_ia64 Mon Aug 07 18:00:22 2006 -0500 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.16.13-xen0 -# Fri Jun 30 12:59:19 2006 +# Fri Jul 28 16:33:47 2006 # # @@ -92,6 +92,7 @@ CONFIG_GENERIC_IOMAP=y CONFIG_GENERIC_IOMAP=y CONFIG_XEN=y CONFIG_XEN_IA64_DOM0_VP=y +CONFIG_XEN_IA64_VDSO_PARAVIRT=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_DMA_IS_DMA32=y # CONFIG_IA64_GENERIC is not set @@ -180,6 +181,8 @@ CONFIG_ACPI_CONTAINER=y # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y +CONFIG_XEN_PCIDEV_FRONTEND=y +# CONFIG_XEN_PCIDEV_FE_DEBUG is not set CONFIG_PCI_LEGACY_PROC=y # CONFIG_PCI_DEBUG is not set @@ -1513,7 +1516,7 @@ CONFIG_XEN_NETDEV_BACKEND=y CONFIG_XEN_NETDEV_BACKEND=y CONFIG_XEN_NETDEV_FRONTEND=y # CONFIG_XEN_DEVMEM is not set -# CONFIG_XEN_REBOOT is not set +CONFIG_XEN_REBOOT=y # CONFIG_XEN_SMPBOOT is not set CONFIG_XEN_INTERFACE_VERSION=0x00030202 @@ -1523,13 +1526,16 @@ CONFIG_XEN_PRIVILEGED_GUEST=y CONFIG_XEN_PRIVILEGED_GUEST=y # CONFIG_XEN_UNPRIVILEGED_GUEST is not set CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_XENBUS_DEV=y CONFIG_XEN_BACKEND=y -# CONFIG_XEN_PCIDEV_BACKEND is not set CONFIG_XEN_BLKDEV_BACKEND=y -CONFIG_XEN_XENBUS_DEV=y # CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set CONFIG_XEN_NETDEV_LOOPBACK=y +CONFIG_XEN_PCIDEV_BACKEND=y +CONFIG_XEN_PCIDEV_BACKEND_VPCI=y +# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set +# CONFIG_XEN_PCIDEV_BE_DEBUG is not set # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y # CONFIG_XEN_SCRUB_PAGES is not set diff -r 61204c1d740e -r 87cefa5f7c5e buildconfigs/linux-defconfig_xenU_ia64 --- a/buildconfigs/linux-defconfig_xenU_ia64 Thu Jul 27 20:07:02 2006 -0400 +++ b/buildconfigs/linux-defconfig_xenU_ia64 Mon Aug 07 18:00:22 2006 -0500 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.16.13-xenU -# Mon May 22 15:05:32 2006 +# Fri Jul 28 16:32:18 2006 # # @@ -89,6 +89,7 @@ CONFIG_GENERIC_IOMAP=y CONFIG_GENERIC_IOMAP=y CONFIG_XEN=y CONFIG_XEN_IA64_DOM0_VP=y +CONFIG_XEN_IA64_VDSO_PARAVIRT=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_DMA_IS_DMA32=y # CONFIG_IA64_GENERIC is not set @@ -177,6 +178,8 @@ CONFIG_ACPI_SYSTEM=y # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y +CONFIG_XEN_PCIDEV_FRONTEND=y +# CONFIG_XEN_PCIDEV_FE_DEBUG is not set CONFIG_PCI_LEGACY_PROC=y # CONFIG_PCI_DEBUG is not set @@ -1380,8 +1383,15 @@ CONFIG_CRYPTO_DES=y # # Hardware crypto devices # +# CONFIG_XEN_UTIL is not set CONFIG_HAVE_ARCH_ALLOC_SKB=y CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_SKBUFF=y +CONFIG_XEN_NETDEV_FRONTEND=y +# CONFIG_XEN_DEVMEM is not set +CONFIG_XEN_REBOOT=y +# CONFIG_XEN_SMPBOOT is not set CONFIG_XEN_INTERFACE_VERSION=0x00030202 # @@ -1389,13 +1399,15 @@ CONFIG_XEN_INTERFACE_VERSION=0x00030202 # # CONFIG_XEN_PRIVILEGED_GUEST is not set CONFIG_XEN_UNPRIVILEGED_GUEST=y +CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_XENBUS_DEV=y # CONFIG_XEN_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y -CONFIG_XEN_NETDEV_FRONTEND=y # CONFIG_XEN_SCRUB_PAGES is not set # CONFIG_XEN_DISABLE_SERIAL is not set CONFIG_XEN_SYSFS=y CONFIG_XEN_COMPAT_030002_AND_LATER=y # CONFIG_XEN_COMPAT_LATEST_ONLY is not set CONFIG_XEN_COMPAT_030002=y +CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y diff -r 61204c1d740e -r 87cefa5f7c5e buildconfigs/linux-defconfig_xen_ia64 --- a/buildconfigs/linux-defconfig_xen_ia64 Thu Jul 27 20:07:02 2006 -0400 +++ b/buildconfigs/linux-defconfig_xen_ia64 Mon Aug 07 18:00:22 2006 -0500 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.16.13-xen -# Thu Jun 29 16:23:48 2006 +# Fri Jul 28 16:33:08 2006 # # @@ -92,6 +92,7 @@ CONFIG_GENERIC_IOMAP=y CONFIG_GENERIC_IOMAP=y CONFIG_XEN=y CONFIG_XEN_IA64_DOM0_VP=y +CONFIG_XEN_IA64_VDSO_PARAVIRT=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_DMA_IS_DMA32=y # CONFIG_IA64_GENERIC is not set @@ -180,6 +181,8 @@ CONFIG_ACPI_CONTAINER=y # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y +CONFIG_XEN_PCIDEV_FRONTEND=y +# CONFIG_XEN_PCIDEV_FE_DEBUG is not set CONFIG_PCI_LEGACY_PROC=y # CONFIG_PCI_DEBUG is not set @@ -1519,7 +1522,7 @@ CONFIG_XEN_NETDEV_BACKEND=y CONFIG_XEN_NETDEV_BACKEND=y CONFIG_XEN_NETDEV_FRONTEND=y # CONFIG_XEN_DEVMEM is not set -# CONFIG_XEN_REBOOT is not set +CONFIG_XEN_REBOOT=y # CONFIG_XEN_SMPBOOT is not set CONFIG_XEN_INTERFACE_VERSION=0x00030202 @@ -1529,13 +1532,16 @@ CONFIG_XEN_PRIVILEGED_GUEST=y CONFIG_XEN_PRIVILEGED_GUEST=y # CONFIG_XEN_UNPRIVILEGED_GUEST is not set CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_XENBUS_DEV=y CONFIG_XEN_BACKEND=y -# CONFIG_XEN_PCIDEV_BACKEND is not set CONFIG_XEN_BLKDEV_BACKEND=y -CONFIG_XEN_XENBUS_DEV=y # CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set CONFIG_XEN_NETDEV_LOOPBACK=y +CONFIG_XEN_PCIDEV_BACKEND=y +CONFIG_XEN_PCIDEV_BACKEND_VPCI=y +# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set +# CONFIG_XEN_PCIDEV_BE_DEBUG is not set # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y # CONFIG_XEN_SCRUB_PAGES is not set diff -r 61204c1d740e -r 87cefa5f7c5e docs/src/user.tex --- a/docs/src/user.tex Thu Jul 27 20:07:02 2006 -0400 +++ b/docs/src/user.tex Mon Aug 07 18:00:22 2006 -0500 @@ -2059,6 +2059,988 @@ iptables: # this command disables all access to the Xen relocation port iptables -A INPUT -p tcp -{}-destination-port 8002 -j REJECT \end{verbatim} + +%% Chapter Xen Mandatory Access Control Framework +\chapter{sHype/Xen Access Control} + +The Xen mandatory access control framework is an implementation of the +sHype Hypervisor Security Architecture +(www.research.ibm.com/ssd\_shype). It permits or denies communication +and resource access of domains based on a security policy. The +mandatory access controls are enforced in addition to the Xen core +controls, such as memory protection. They are designed to remain +transparent during normal operation of domains (policy-conform +behavior) but to intervene when domains move outside their intended +sharing behavior. This chapter will describe how the sHype access +controls in Xen can be configured to prevent viruses from spilling +over from one into another workload type and secrets from leaking from +one workload type to another. sHype/Xen depends on the correct +behavior of Domain0 (cf previous chapter). + +Benefits of configuring sHype/ACM in Xen include: +\begin{itemize} +\item robust workload and resource protection effective against rogue + user domains +\item simple, platform- and operating system-independent security + policies (ideal for heterogeneous distributed environments) +\item safety net with minimal performance overhead in case operating + system security is missing, does not scale, or fails +\end{itemize} + +These benefits are very valuable because today's operating systems +become increasingly complex and often have no or insufficient +mandatory access controls. (Discretionary access controls, supported +by of most operating systems, are not effective against viruses or +misbehaving programs.) Where mandatory access control exists (e.g., +SELinux), they usually deploy complex and difficult to understand +security policies. Additionally, multi-tier applications in business +environments usually require different types of operating systems +(e.g., AIX, Windows, Linux) which cannot be configured with compatible +security policies. Related distributed transactions and workloads +cannot be easily protected on the OS level. The Xen access control +framework steps in to offer a coarse-grained but very robust security +layer and safety net in case operating system security fails or is +missing. + +To control sharing between domains, Xen mediates all inter-domain +communication (shared memory, events) as well as the access of domains +to resources such as disks. Thus, Xen can confine distributed +workloads (domain payloads) by permitting sharing among domains +running the same type of workload and denying sharing between pairs of +domains that run different workload types. We assume that--from a Xen +perspective--only one workload type is running per user domain. To +enable Xen to associate domains and resources with workload types, +security labels including the workload types are attached to domains +and resources. These labels and the hypervisor sHype controls cannot +be manipulated or bypassed and are effective even against rogue +domains. + +\section{Overview} +This section gives an overview of how workloads can be protected using +the sHype mandatory access control framework in Xen. +Figure~\ref{fig:acmoverview} shows the necessary steps in activating +the Xen workload protection. These steps are described in detail in +Section~\ref{section:acmexample}. + +\begin{figure} +\centering +\includegraphics[width=13cm]{figs/acm_overview.eps} +\caption{Overview of activating sHype workload protection in Xen. + Section numbers point to representative examples.} +\label{fig:acmoverview} +\end{figure} + +First, the sHype/ACM access control must be enabled in the Xen +distribution and the distribution must be built and installed (cf +Subsection~\ref{subsection:acmexampleconfigure}). Before we can +enforce security, a Xen security policy must be created (cf +Subsection~\ref{subsection:acmexamplecreate}) and deployed (cf +Subsection~\ref{subsection:acmexampleinstall}). This policy defines +the workload types differentiated during access control. It also +defines the rules that compare workload types of domains and resources +to provide access decisions. Workload types are represented by +security labels that can be attached to domains and resources (cf +Subsections~\ref{subsection:acmexamplelabeldomains} +and~\ref{subsection:acmexamplelabelresources}). The functioning of +the active sHype/Xen workload protection is demonstrated using simple +resource assignment, and domain creation tests in +Subsection~\ref{subsection:acmexampletest}. +Section~\ref{section:acmpolicy} describes the syntax and semantics of +the sHype/Xen security policy in detail and introduces briefly the +tools that are available to help create valid security policies. + +The next section describes all the necessary steps to create, deploy, +and test a simple workload protection policy. It is meant to enable +anybody to quickly try out the sHype/Xen workload protection. Those +readers who are interested in learning more about how the sHype access +control in Xen works and how it is configured using the XML security +policy should read Section~\ref{section:acmpolicy} as well. +Section~\ref{section:acmlimitations} concludes this chapter with +current limitations of the sHype implementation for Xen. + +\section{Xen Workload Protection Step-by-Step} +\label{section:acmexample} + +What you are about to do consists of the following sequence: +\begin{itemize} +\item configure and install sHype/Xen +\item create a simple workload protection security policy +\item deploy the sHype/Xen security policy +\item associate domains and resources with workload labels, +\item test the workload protection +\end{itemize} +The essential commands to create and deploy a sHype/Xen security +policy are numbered throughout the following sections. If you want a +quick-guide or return at a later time to go quickly through this +demonstration, simply look for the numbered commands and apply them in +order. + +\subsection{Configuring/Building sHype Support into Xen} +\label{subsection:acmexampleconfigure} +First, we need to configure the access control module in Xen and +install the ACM-enabled Xen hypervisor. This step installs security +tools and compiles sHype/ACM controls into the Xen hypervisor. + +To enable sHype/ACM in Xen, please edit the Config.mk file in the top +Xen directory. + +\begin{verbatim} + (1) In Config.mk + Change: ACM_SECURITY ?= n + To: ACM_SECURITY ?= y +\end{verbatim} + +Then install the security-enabled Xen environment as follows: + +\begin{verbatim} + (2) # make world + # make install +\end{verbatim} + +\subsection{Creating A WLP Policy in 3 Simple Steps with ezPolicy} +\label{subsection:acmexamplecreate} + +We will use the ezPolicy tool to quickly create a policy that protects +workloads. You will need both the Python and wxPython packages to run +this tool. To run the tool in Domain0, you can download the wxPython +package from www.wxpython.org or use the command +\verb|yum install wxPython| in Redhat/Fedora. To run the tool on MS +Windows, you also need to download the Python package from +www.python.org. After these packages are installed, start the ezPolicy +tool with the following command: + +\begin{verbatim} + (3) # xensec_ezpolicy +\end{verbatim} + +Figure~\ref{fig:acmezpolicy} shows a screen-shot of the tool. The +following steps show you how to create the policy shown in +Figure~\ref{fig:acmezpolicy}. You can use \verb|<CTRL>-h| to pop up a +help window at any time. The indicators (a), (b), and (c) in +Figure~\ref{fig:acmezpolicy} show the buttons that are used during the +3 steps of creating a policy: +\begin{enumerate} +\item defining workloads +\item defining run-time conflicts +\item translating the workload definition into a sHype/Xen access + control policy +\end{enumerate} + +\paragraph{Defining workloads.} Workloads are defined for each +organization and department that you enter in the left panel. Please +use the ``New Org'' button (a) to create the organizations ``Avis'', +``Hertz'', ``CocaCola'', and ``PepsiCo''. + +You can refine an organization to differentiate between multiple +department workloads by right-clicking the organization and selecting +\verb|Add Department| (or selecting an organization and pressing +\verb|<CRTL>-a|). Create department workloads ``Intranet'', +``Extranet'', ``HumanResources'', and ``Payroll'' for the ``CocaCola'' +organization and department workloads ``Intranet'' and ``Extranet'' +for the ``PepsiCo'' organization. The resulting layout of the tool +should be similar to the left panel shown in +Figure~\ref{fig:acmezpolicy}. + +\paragraph{Defining run-time conflicts.} Workloads that shall be +prohibited from running concurrently on the same hypervisor platform +are grouped into ``Run-time Exclusion rules'' on the right panel of +the window. + +To prevent PepsiCo and CocaCola workloads (including their +departmental workloads) from running simultaneously on the same +hypervisor system, select the organization ``PepsiCo'' and, while +pressing the \verb|<CTRL>|-key, select the organization ``CocaCola''. +Now press the button (b) named ``Create run-time exclusion rule from +selection''. A popup window will ask for the name for this run-time +exclusion rule (enter a name or just hit \verb|<ENTER>|). A rule will +appear on the right panel. The name is used as reference only and does +not affect the hypervisor policy. + +Repeat the process to create a run-time exclusion rule just for the +department workloads CocaCola.Extranet and CocaCola.Payroll. + +\begin{figure}[htb] +\centering +\includegraphics[width=13cm]{figs/acm_ezpolicy.eps} +\caption{Final layout including workload definition and Run-time Exclusion rules.} +\label{fig:acmezpolicy} +\end{figure} + +The resulting layout of your window should be similar to +Figure~\ref{fig:acmezpolicy}. Save this workload definition by +selecting ``Save Workload Definition as ...'' in the ``File'' menu +(c). This workload definition can be later refined if required. + +\paragraph{Translating the workload definition into a sHype/Xen access + control policy.} To translate the workload definition into a access +control policy understood by Xen, please select the ``Save as Xen ACM +Security Policy'' in the ``File'' menu (c). Enter the following policy +name in the popup window: \verb|example.chwall_ste.test-wld|. If you +are running ezPolicy in Domain0, the resulting policy file +test-wld\_security-policy.xml will automatically be placed into the +right directory (/etc/xen/acm-security/ policies/example/chwall\_ste). +If you run the tool on another system, then you need to copy the +resulting policy file into Domain0 before continuing. See +Section~\ref{subsection:acmnaming} for naming conventions of security +policies. + +\subsection{Deploying a WLP Policy} +\label{subsection:acmexampleinstall} +To deploy the workload protection policy we created in +Section~\ref{subsection:acmexamplecreate}, we create a policy +representation (test-wld.bin) that can be loaded into the Xen +hypervisor and we configure Xen to actually load this policy at +startup time. + +The following command translates the source policy representation +into a format that can be loaded into Xen with sHype/ACM support. +Refer to the \verb|xm| man page for further details: + +\begin{verbatim} + (4) # xm makepolicy example.chwall_ste.test-wld +\end{verbatim} + +The easiest way to install a security policy for Xen is to include the +policy in the boot sequence. The following command does just this: + +\begin{verbatim} + (5) # xm cfgbootpolicy example.chwall_ste.test-wld +\end{verbatim} + +\textit{Alternatively, if this command fails} (e.g., because it cannot +identify the Xen boot entry), you can manually install the policy in 2 +steps. First, manually copy the policy binary file into the boot +directory: + +\begin{scriptsize} +\begin{verbatim} + # cp /etc/xen/acm-security/policies/example/chwall_ste/test-wld.bin \ + /boot/example.chwall_ste.test-wld.bin +\end{verbatim} +\end{scriptsize} + +Second, manually add a module line to your Xen boot entry so that grub +loads this policy file during startup: + +\begin{scriptsize} +\begin{verbatim} + title Xen (2.6.16.13) + root (hd0,0) + kernel /xen.gz dom0_mem=2000000 console=vga + module /vmlinuz-2.6.16.13-xen ro root=/dev/hda3 + module /initrd-2.6.16.13-xen.img + module /example.chwall_ste.test-wld.bin +\end{verbatim} +\end{scriptsize} + +Now reboot into this Xen boot entry to activate the policy and the +security-enabled Xen hypervisor. + +\begin{verbatim} + (6) # reboot +\end{verbatim} + +After reboot, check if security is enabled: + +\begin{scriptsize} +\begin{verbatim} + # xm list --label + Name ID Mem(MiB) VCPUs State Time(s) Label + Domain-0 0 1949 4 r----- 163.9 SystemManagement +\end{verbatim} +\end{scriptsize} + +If the security label at the end of the line says ``INACTIV'' then the +security is not enabled. Verify the previous steps. Note: Domain0 is +assigned a default label (see \verb|bootstrap| policy attribute +explained in Section~\ref{section:acmpolicy}). All other domains must +be labeled in order to start on this sHype/ACM-enabled Xen hypervisor +(see following sections for labeling domains and resources). + +\subsection{Labeling Domains} +\label{subsection:acmexamplelabeldomains} +You should have a Xen domain configuration file that looks like the +following (Note: www.jailtime.org or www.xen-get.org might be good +places to look for example domU images). The following configuration +file defines \verb|domain1|: + +\begin{scriptsize} +\begin{verbatim} + # cat domain1.xm + kernel = "/boot/vmlinuz-2.6.16.13-xen" + memory = 128 + name = "domain1" + vif = [ '' ] + dhcp = "dhcp" + disk = ['file:/home/xen/dom_fc5/fedora.fc5.img,sda1,w', \ + 'file:/home/xen/dom_fc5/fedora.swap,sda2,w'] + root = "/dev/sda1 ro" +\end{verbatim} +\end{scriptsize} + +If you try to start domain1, you will get the following error: + +\begin{scriptsize} +\begin{verbatim} + # xm create domain1.xm + Using config file "domain1.xm". + domain1: DENIED + --> Domain not labeled + Checking resources: (skipped) + Security configuration prevents domain from starting +\end{verbatim} +\end{scriptsize} + +Every domain must be associated with a security label before it can +start on sHype/Xen. Otherwise, sHype/Xen would not be able to enforce +the policy consistently. The following command prints all domain +labels available in the active policy: + +\begin{scriptsize} +\begin{verbatim} + # xm labels type=dom + Avis + CocaCola + CocaCola.Extranet + CocaCola.HumanResources + CocaCola.Intranet + CocaCola.Payroll + Hertz + PepsiCo + PepsiCo.Extranet + PepsiCo.Intranet + SystemManagement +\end{verbatim} +\end{scriptsize} + +Now label domain1 with the CocaCola label and another domain2 with the +PepsiCo.Extranet label. Please refer to the xm man page for further +information. + +\begin{verbatim} + (7) # xm addlabel CocaCola dom domain1.xm + # xm addlabel PepsiCo.Extranet dom domain2.xm +\end{verbatim} + +Let us try to start the domain again: + +\begin{scriptsize} +\begin{verbatim} + # xm create domain1.xm + Using config file "domain1.xm". + file:/home/xen/dom_fc5/fedora.fc5.img: DENIED + --> res:__NULL_LABEL__ (NULL) + --> dom:CocaCola (example.chwall_ste.test-wld) + file:/home/xen/dom_fc5/fedora.swap: DENIED + --> res:__NULL_LABEL__ (NULL) + --> dom:CocaCola (example.chwall_ste.test-wld) + Security configuration prevents domain from starting +\end{verbatim} +\end{scriptsize} + +This error indicates that domain1, if started, would not be able to +access its image and swap files because they are not labeled. This +makes sense because to confine workloads, access of domains to +resources must be controlled. Otherwise, domains that are not allowed +to communicate or run simultaneously could share data through storage +resources. + +\subsection{Labeling Resources} +\label{subsection:acmexamplelabelresources} +You can use the \verb|xm labels type=res| command to list available +resource labels. Let us assign the CocaCola resource label to the domain1 +image file representing \verb|/dev/sda1| and to its swap file: + +\begin{verbatim} + (8) # xm addlabel CocaCola res \ + file:/home/xen/dom_fc5/fedora.fc5.img + Resource file not found, creating new file at: + /etc/xen/acm-security/policies/resource_labels + # xm addlabel CocaCola res \ + file:/home/xen/dom_fc5/fedora.swap +\end{verbatim} + +Starting \verb|domain1| now will succeed: + +\begin{scriptsize} +\begin{verbatim} + # xm create domain1.xm + # xm list --label + Name ID Mem(MiB) VCPUs State Time(s) Label + domain1 1 128 1 r----- 2.8 CocaCola + Domain-0 0 1949 4 r----- 387.7 SystemManagement +\end{verbatim} +\end{scriptsize} + +The following command lists all labeled resources on the +system, e.g., to lookup or verify the labeling: + +\begin{scriptsize} +\begin{verbatim} + # xm resources + file:/home/xen/dom_fc5/fedora.swap + policy: example.chwall_ste.test-wld + label: CocaCola + file:/home/xen/dom_fc5/fedora.fc5.img + policy: example.chwall_ste.test-wld + label: CocaCola +\end{verbatim} +\end{scriptsize} + +Currently, if a labeled resource is moved to another location, the +label must first be manually removed, and after the move re-attached +using the xm commands \verb|xm rmlabel| and \verb|xm addlabel| +respectively. Please see Section~\ref{section:acmlimitations} for +further details. + +\begin{verbatim} + (9) Label the resources of domain2 as PepsiCo.Extranet + Do not try to start this domain yet +\end{verbatim} + +\subsection{Testing The Xen Workload Protection} +\label{subsection:acmexampletest} +We are about to demonstrate how the workload protection works by +verifying: +\begin{itemize} +\item that domains with conflicting workloads cannot run + simultaneously +\item that domains cannot access resources of other workloads +\item that domains cannot exchange network packets if they are not + associated with the same workload type +\end{itemize} + +\paragraph{Test 1: Run-time exclusion rules.} We assume that domain1 +with the CocaCola label is still running. While domain1 is running, +the run-time exclusion set of our policy says that domain2 cannot +start because the label of domain1 includes the CHWALL type CocaCola +and the label of domain2 includes the CHWALL type PepsiCo. The +run-time exclusion rule of our policy enforces that PepsiCo and +CocaCola cannot run at the same time on the same hypervisor platform. +Once domain1 is stopped or saved, domain2 can start but domain1 can no +longer start or be resumed. The ezPolicy tool, when creating the +Chinese Wall types for the workload labels, ensures that department +workloads inherit the organization type (and with it any organization +exclusions). + +\begin{scriptsize} +\begin{verbatim} +# xm list --label +Name ID Mem(MiB) VCPUs State Time(s) Label +domain1 2 128 1 -b---- 6.9 CocaCola +Domain-0 0 1949 4 r----- 273.1 SystemManagement + +# xm create domain2.xm +Using config file "domain2.xm". +Error: (1, 'Operation not permitted') + +# xm destroy domain1 +# xm create domain2.xm +Using config file "domain2.xm". +Started domain domain2 + +# xm list --label +Name ID Mem(MiB) VCPUs State Time(s) Label +domain2 4 164 1 r----- 4.3 PepsiCo.Extranet +Domain-0 0 1949 4 r----- 298.4 SystemManagement + +# xm create domain1.xm +Using config file "domain1.xm". +Error: (1, 'Operation not permitted') + +# xm destroy domain2 +# xm list +Name ID Mem(MiB) VCPUs State Time(s) +Domain-0 0 1949 4 r----- 391.2 +\end{verbatim} +\end{scriptsize} + +You can verify that domains with Avis label can run together with +domains labeled CocaCola, PepsiCo, or Hertz. + +\paragraph{Test2: Resource access.} In this test, we will re-label the +swap file for domain1 with the Avis resource label. We expect that +Domain1 will no longer start because it cannot access this resource. +This test checks the sharing abilities of domains, which are defined +by the Simple Type Enforcement Policy component. + +\begin{scriptsize} +\begin{verbatim} +# xm rmlabel res file:/home/xen/dom_fc5/fedora.swap +# xm addlabel Avis res file:/home/xen/dom_fc5/fedora.swap +# xm resources +file:/home/xen/dom_fc5/fedora.swap + policy: example.chwall_ste.test-wld + label: Avis +file:/home/xen/dom_fc5/fedora.fc5.img + policy: example.chwall_ste.test-wld + label: CocaCola + +# xm create domain1.xm +Using config file "domain1.xm". + file:/home/xen/dom_fc4/fedora.swap: DENIED + --> res:Avis (example.chwall_ste.test-wld) + --> dom:CocaCola (example.chwall_ste.test-wld) +Security configuration prevents domain from starting +\end{verbatim} +\end{scriptsize} + +\paragraph{Test 3: Communication.} In this test we would verify that +two domains with labels Hertz and Avis cannot exchange network packets +by using the 'ping' connectivity test. It is also related to the STE +policy.{\bf Note:} sHype/Xen does control direct communication between +domains. However, domains associated with different workloads can +currently still communicate through the Domain0 virtual network. We +are working on the sHype/ACM controls for local and remote network +traffic through Domain0. Please monitor the xen-devel mailing list +for updated information. + +\section{Xen Access Control Policy} +\label{section:acmpolicy} + +This section describes the sHype/Xen access control policy in detail. +It gives enough information to enable the reader to write custom +access control policies and to use the available Xen policy tools. The +policy language is expressive enough to specify most symmetric access +relationships between domains and resources efficiently. + +The Xen access control policy consists of two policy components. The +first component, called Chinese Wall (CHWALL) policy, controls which +domains can run simultaneously on the same virtualized platform. The +second component, called Simple Type Enforcement (STE) policy, +controls the sharing between running domains, i.e., communication or +access to shared resources. The CHWALL and STE policy components can +be configured to run alone, however in our examples we will assume +that both policy components are configured together since they +complement each other. The XML policy file includes all information +needed by Xen to enforce the policies. + +Figures~\ref{fig:acmxmlfilea} and \ref{fig:acmxmlfileb} show a fully +functional but very simple example policy for Xen. The policy can +distinguish two workload types \verb|CocaCola| and \verb|PepsiCo| and +defines the labels necessary to associate domains and resources with +one of these workload types. The XML Policy consists of four parts: +\begin{enumerate} +\item policy header including the policy name +\item Simple Type Enforcement block +\item Chinese Wall Policy block +\item label definition block +\end{enumerate} + +\begin{figure} +\begin{scriptsize} +\begin{verbatim} +01 <?xml version="1.0" encoding="UTF-8"?> +02 <!-- Auto-generated by ezPolicy --> +03 <SecurityPolicyDefinition + xmlns="http://www.ibm.com" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation= + "http://www.ibm.com ../../security_policy.xsd "> +04 <PolicyHeader> +05 <PolicyName>example.chwall_ste.test</PolicyName> +06 <Date>Wed Jul 12 17:32:59 2006</Date> +07 </PolicyHeader> +08 +09 <SimpleTypeEnforcement> +10 <SimpleTypeEnforcementTypes> +11 <Type>SystemManagement</Type> +12 <Type>PepsiCo</Type> +13 <Type>CocaCola</Type> +14 </SimpleTypeEnforcementTypes> +15 </SimpleTypeEnforcement> +16 +17 <ChineseWall priority="PrimaryPolicyComponent"> +18 <ChineseWallTypes> +19 <Type>SystemManagement</Type> +20 <Type>PepsiCo</Type> +21 <Type>CocaCola</Type> +22 </ChineseWallTypes> +23 +24 <ConflictSets> +25 <Conflict name="RER1"> +26 <Type>CocaCola</Type> +27 <Type>PepsiCo</Type> +28 </Conflict> +29 </ConflictSets> +30 </ChineseWall> +31 +\end{verbatim} +\end{scriptsize} +\caption{Example XML security policy file -- Part I: Types and Rules Definition.} +\label{fig:acmxmlfilea} +\end{figure} + +\subsection{Policy Header and Policy Name} +\label{subsection:acmnaming} +Lines 1-2 (cf Figure~\ref{fig:acmxmlfilea}) include the usual XML +header. The security policy definition starts in Line 3 and refers to +the policy schema. The XML-Schema definition for the Xen policy can be +found in the file +\textit{/etc/xen/acm-security/policies/security-policy.xsd}. Examples +for security policies can be found in the example subdirectory. The +acm-security directory is only installed if ACM security is configured +during installation (cf Section~\ref{subsection:acmexampleconfigure}). + +The \verb|Policy Header| spans lines 4-7. It includes a date field and +defines the policy name \verb|example.chwall_ste.test|. It can also +include optional fields that are not shown and are for future use (see +schema definition). + +The policy name serves two purposes: First, it provides a unique name +for the security policy. This name is also exported by the Xen +hypervisor to the Xen management tools in order to ensure that both +enforce the same policy. We plan to extend the policy name with a +digital fingerprint of the policy contents to better protect this +correlation. Second, it implicitly points the xm tools to the +location where the XML policy file is stored on the Xen system. +Replacing the colons in the policy name by slashes yields the local +path to the policy file starting from the global policy directory +\verb|/etc/xen/acm-security/policies|. The last part of the policy +name is the prefix for the XML policy file name, completed by +\verb|-security_policy.xml|. Consequently, the policy with the name +\verb|example.chwall_ste.test| can be found in the XML policy file +named \verb|test-security_policy.xml| that is stored in the local +directory \verb|example/chwall_ste| under the global policy directory. + +\subsection{Simple Type Enforcement Policy Component} + +The Simple Type Enforcement (STE) policy controls which domains can +communicate or share resources. This way, Xen can enforce confinement +of workload types by confining the domains running those workload +types. The mandatory access control framework enforces its policy when +domains access intended ways of communication or cooperation (shared +memory, events, shared resources such as block devices). It builds on +top of the core hypervisor isolation, which restricts the ways of +inter-communication to those intended means. STE does not protect or +intend to protect from covert channels in the hypervisor or hardware; +this is an orthogonal problem that can be mitigated by using the +Run-time Exclusion rules described above or by fixing the problem in +the core hypervisor. + +Xen controls sharing between domains on the resource and domain level +because this is the abstraction the hypervisor and its management +understand naturally. While this is coarse-grained, it is also very +reliable and robust and it requires minimal changes to implement +mandatory access controls in the hypervisor. It enables platform- and +operation system-independent policies as part of a layered security +approach. + +Lines 9-15 (cf Figure~\ref{fig:acmxmlfilea}) define the Simple Type +Enforcement policy component. Essentially, they define the workload +type names \verb|SystemManagement|, \verb|PepsiCo|, and +\verb|CocaCola| that are available in the STE policy component. The +policy rules are implicit: Xen permits a domain to communicate with +another domain if and only if the labels of the domains share an +common STE type. Xen permits a domain to access a resource if and +only if the labels of the domain and the resource share a common STE +workload type. + +\subsection{Chinese Wall Policy Component} + +The Chinese Wall security policy interpretation of sHype enables users +to prevent certain workloads from running simultaneously on the same +hypervisor platform. Run-time Exclusion rules (RER), also called +Conflict Sets, define a set of workload types that are not permitted +to run simultaneously. Of all the workloads specified in a Run-time +Exclusion rule, at most one type can run on the same hypervisor +platform at a time. Run-time Exclusion Rules implement a less +rigorous variant of the original Chinese Wall security component. They +do not implement the *-property of the policy, which would require to +restrict also types that are not part of an exclusion rule once they +are running together with a type in an exclusion rule (please refer to +http://www.gammassl.co.uk/topics/chinesewall.html for more information +on the original Chinese Wall policy). + +Xen considers the \verb|ChineseWallTypes| part of the label for the +enforcement of the Run-time Exclusion rules. It is illegal to define +labels including conflicting Chinese Wall types. + +Lines 17-30 (cf Figure~\ref{fig:acmxmlfilea}) define the Chinese Wall +policy component. Lines 17-22 define the known Chinese Wall types, +which coincide here with the STE types defined above. This usually +holds if the criteria for sharing among domains and sharing of the +hardware platform are the same. Lines 24-29 define one Run-time +Exclusion rule: + +\begin{scriptsize} +\begin{verbatim} + <Conflict name="RER1"> + <Type>CocaCola</Type> + <Type>PepsiCo</Type> + </Conflict> +\end{verbatim} +\end{scriptsize} + +Based on this rule, Xen enforces that only one of the types +\verb|CocaCola| or \verb|PepsiCo| will run on a single hypervisor +platform at a time. For example, once a domain assigned a +\verb|CocaCola| workload type is started, domains with the +\verb|PepsiCo| type will be denied to start. When the former domain +stops and no other domains with the \verb|CocaCola| type are running, +then domains with the \verb|PepsiCo| type can start. + +Xen maintains reference counts on each running workload type to keep +track of which workload types are running. Every time a domain starts +or resumes, the reference count on those Chinese Wall types that are +referenced in the domain's label are incremented. Every time a domain +is destroyed or saved, the reference counts of its Chinese Wall types +are decremented. sHype in Xen covers migration and live-migration, +which is treated the same way as saving a domain on the source +platform and resuming it on the destination platform. + +Reasons why users would want to restrict which workloads or domains +can share the system hardware include: + +\begin{itemize} +\item Imperfect resource management or control might enable a rogue + domain to starve another domain and the workload running in it. +\item Redundant domains might run the same workload to increase + availability; such domains should not run on the same hardware to + avoid single points of failure. +\item Imperfect Xen core domain isolation might enable two rogue + domains running different workload types to use unintended and + unknown ways (covert channels) to exchange some data. This way, they + bypass the policed Xen access control mechanisms. Such + imperfections cannot be completely eliminated and are a result of + trade-offs between security and other design requirements. For a + simple example of a covert channel see + http://www.multicians.org/timing-chn.html. Such covert channels + exist also between workloads running on different platforms if they + are connected through networks. The Xen Chinese Wall policy provides + an approximation of this imperfect ``air-gap'' between selected + workload types. +\end{itemize} + +\subsection{Security Labels} + +To enable Xen to associate domains with workload types running in +them, each domain is assigned a security label that includes the +workload types of the domain. + +\begin{figure} +\begin{scriptsize} +\begin{verbatim} +32 <SecurityLabelTemplate> +33 <SubjectLabels bootstrap="SystemManagement"> +34 <VirtualMachineLabel> +35 <Name>SystemManagement</Name> +36 <SimpleTypeEnforcementTypes> +37 <Type>SystemManagement</Type> +38 <Type>PepsiCo</Type> +39 <Type>CocaCola</Type> +40 </SimpleTypeEnforcementTypes> +41 <ChineseWallTypes> +42 <Type>SystemManagement</Type> +43 </ChineseWallTypes> +44 </VirtualMachineLabel> +45 +46 <VirtualMachineLabel> +47 <Name>PepsiCo</Name> +48 <SimpleTypeEnforcementTypes> +49 <Type>PepsiCo</Type> +50 </SimpleTypeEnforcementTypes> +51 <ChineseWallTypes> +52 <Type>PepsiCo</Type> +53 </ChineseWallTypes> +54 </VirtualMachineLabel> +55 +56 <VirtualMachineLabel> +57 <Name>CocaCola</Name> +58 <SimpleTypeEnforcementTypes> +59 <Type>CocaCola</Type> +60 </SimpleTypeEnforcementTypes> +61 <ChineseWallTypes> +62 <Type>CocaCola</Type> +63 </ChineseWallTypes> +64 </VirtualMachineLabel> +65 </SubjectLabels> +66 +67 <ObjectLabels> +68 <ResourceLabel> +69 <Name>SystemManagement</Name> +70 <SimpleTypeEnforcementTypes> +71 <Type>SystemManagement</Type> +72 </SimpleTypeEnforcementTypes> +73 </ResourceLabel> +74 +75 <ResourceLabel> +76 <Name>PepsiCo</Name> +77 <SimpleTypeEnforcementTypes> +78 <Type>PepsiCo</Type> +79 </SimpleTypeEnforcementTypes> +80 </ResourceLabel> +81 +82 <ResourceLabel> +83 <Name>CocaCola</Name> +84 <SimpleTypeEnforcementTypes> +85 <Type>CocaCola</Type> +86 </SimpleTypeEnforcementTypes> +87 </ResourceLabel> +88 </ObjectLabels> +89 </SecurityLabelTemplate> +90 </SecurityPolicyDefinition> +\end{verbatim} +\end{scriptsize} +\caption{Example XML security policy file -- Part II: Label Definition.} +\label{fig:acmxmlfileb} +\end{figure} + +Lines 32-89 (cf Figure~\ref{fig:acmxmlfileb}) define the +\verb|SecurityLabelTemplate|, which includes the labels that can be +attached to domains and resources when this policy is active. The +domain labels include Chinese Wall types while resource labels do not +include Chinese Wall types. Lines 33-65 define the +\verb|SubjectLabels| that can be assigned to domains. For example, the +virtual machine label \verb|CocaCola| (cf lines 56-64 in +Figure~\ref{fig:acmxmlfileb}) associates the domain that carries it +with the workload type \verb|CocaCola|. + +The \verb|bootstrap| attribute names the label +\verb|SystemManagement|. Xen will assign this label to Domain0 at +boot time. All other domains are assigned labels according to their +domain configuration file (see +Section~\ref{subsection:acmexamplelabeldomains} for examples of how to +label domains). Lines 67-88 define the \verb|ObjectLabels|. Those +labels can be assigned to resources when this policy is active. + +In general, user domains should be assigned labels that have only a +single SimpleTypeEnforcement workload type. This way, workloads remain +confined even if user domains become rogue. Any domain that is +assigned a label with multiple STE types must be trusted to keep +information belonging to the different STE types separate (confined). +For example, Domain0 is assigned the bootstrap label +\verb|SystemsManagement|, which includes all existing STE types. +Therefore, Domain0 must take care not to enable unauthorized +information flow (eg. through block devices or virtual networking) +between domains or resources that are assigned different STE types. + +Security administrators simply use the name of a label (specified in +the \verb|<Name>| field) to associate a label with a domain (cf. +Section~\ref{subsection:acmexamplelabeldomains}). The types inside the +label are used by the Xen access control enforcement. While the name +can be arbitrarily chosen (as long as it is unique), it is advisable +to choose the label name in accordance to the security types included. +While the XML representation in the above label seems unnecessary +flexible, labels in general can consist of multiple types as we will +see in the following example. + +Assume that \verb|PepsiCo| and \verb|CocaCola| workloads use virtual +disks that are provided by a virtual I/O domain hosting a physical +storage device and carrying the following label: + +\begin{scriptsize} +\begin{verbatim} + <VirtualMachineLabel> + <Name>VIO</Name> + <SimpleTypeEnforcementTypes> + <Type>CocaCola</Type> + <Type>PepsiCo</Type> + </SimpleTypeEnforcementTypes> + <ChineseWallTypes> + <Type>VIOServer</Type> + </ChineseWallTypes> + </VirtualMachineLabel> +\end{verbatim} +\end{scriptsize} + +This Virtual I/O domain (VIO) exports its virtualized disks by +communicating both to domains labeled with the \verb|PepsiCo| label +and domains labeled with the \verb|CocaCola| label. This requires the +VIO domain to carry both the STE types \verb|CocaCola| and +\verb|PepsiCo|. In this example, the confinement of \verb|CocaCola| +and \verb|PepsiCo| workload depends on a VIO domain that must keep the +data of those different workloads separate. The virtual disks are +labeled as well (see Section~\ref{subsection:acmexamplelabelresources} +for labeling resources) and enforcement functions inside the VIO +domain must ensure that the labels of the domain mounting a virtual +disk and the virtual disk label share a common STE type. The VIO label +carrying its own VIOServer CHWALL type introduces the flexibility to +permit the trusted VIO server to run together with CocaCola or PepsiCo +workloads. + +Alternatively, a system that has two hard-drives does not need a VIO +domain but can directly assign one hardware storage device to each of +the workloads (if the platform offers an IO-MMU, cf +Section~\ref{s:ddsecurity}. Sharing hardware through virtualization +is a trade-off between the amount of trusted code (size of the trusted +computing base) and the amount of acceptable over-provisioning. This +holds both for peripherals and for system platforms. + +\subsection{Tools For Creating sHype/Xen Security Policies} +To create a security policy for Xen, you can use one of the following +tools: +\begin{itemize} +\item \verb|ezPolicy| GUI tool -- start writing policies +\item \verb|xensec_gen| tool -- refine policies created with \verb|ezPolicy| +\item text or XML editor +\end{itemize} + +We use the \verb|ezPolicy| tool in +Section~\ref{subsection:acmexamplecreate} to quickly create a workload +protection policy. If desired, the resulting XML policy file can be +loaded into the \verb|xensec_gen| tool to refine it. It can also be +directly edited using an XML editor. Any XML policy file is verified +against the security policy schema when it is translated (see +Subsection~\ref{subsection:acmexampleinstall}). + +\section{Current Limitations} +\label{section:acmlimitations} + +The sHype/ACM configuration for Xen is work in progress. There is +ongoing work for protecting virtualized resources and planned and +ongoing work for protecting access to remote resources and domains. +The following sections describe limitations of some of the areas into +which access control is being extended. + +\subsection{Network Traffic} +Local and remote network traffic is currently not controlled. +Solutions to add sHype/ACM policy enforcement to the virtual network +exist but need to be discussed before they can become part of Xen. +Subjecting external network traffic to the ACM security policy is work +in progress. Manually setting up filters in domain 0 is required for +now but does not scale well. + +\subsection{Resource Access and Usage Control} + +Enforcing the security policy across multiple hypervisor systems and +on access to remote shared resources is work in progress. Extending +access control to new types of resources is ongoing work (e.g. network +storage). + +On a single Xen system, information about the association of resources +and security labels is stored in +\verb|/etc/xen/acm-security/policy/resource_labels|. This file relates +a full resource path with a security label. This association is weak +and will break if resources are moved or renamed without adapting the +label file. Improving the protection of label-resource relationships +is ongoing work. + +Controlling resource usage and enforcing resource limits in general is +ongoing work in the Xen community. + +\subsection{Domain Migration} + +Labels on domains are enforced during domain migration and the +destination hypervisor will ensure that the domain label is valid and +the domain is permitted to run (considering the Chinese Wall policy +rules) before it accepts the migration. However, the network between +the source and destination hypervisor as well as both hypervisors must +be trusted. Architectures and prototypes exist that both protect the +network connection and ensure that the hypervisors enforce access +control consistently but patches are not yet available for the main +stream. + +\subsection{Covert Channels} + +The sHype access control aims at system independent security policies. +It builds on top of the core hypervisor isolation. Any covert channels +that exist in the core hypervisor or in the hardware (e.g., shared +processor cache) will be inherited. If those covert channels are not +the result of trade-offs between security and other system properties, +then they are most effectively minimized or eliminated where they are +caused. sHype offers however some means to mitigate their impact +(cf. run-time exclusion rules). \part{Reference} @@ -2188,7 +3170,7 @@ editing \path{grub.conf}. \item [ tbuf\_size=xxx ] Set the size of the per-cpu trace buffers, in pages (default 0). \item [ sched=xxx ] Select the CPU scheduler Xen should use. The - current possibilities are `sedf' (default), `credit', and `bvt'. + current possibilities are `credit' (default), `sedf', and `bvt'. \item [ apic\_verbosity=debug,verbose ] Print more detailed information about local APIC and IOAPIC configuration. \item [ lapic ] Force use of local APIC even when left disabled by diff -r 61204c1d740e -r 87cefa5f7c5e extras/mini-os/console/xencons_ring.c --- a/extras/mini-os/console/xencons_ring.c Thu Jul 27 20:07:02 2006 -0400 +++ b/extras/mini-os/console/xencons_ring.c Mon Aug 07 18:00:22 2006 -0500 @@ -53,7 +53,7 @@ int xencons_ring_send(const char *data, -static void handle_input(int port, struct pt_regs *regs, void *ign) +static void handle_input(evtchn_port_t port, struct pt_regs *regs, void *ign) { struct xencons_interface *intf = xencons_interface(); XENCONS_RING_IDX cons, prod; diff -r 61204c1d740e -r 87cefa5f7c5e extras/mini-os/events.c --- a/extras/mini-os/events.c Thu Jul 27 20:07:02 2006 -0400 +++ b/extras/mini-os/events.c Mon Aug 07 18:00:22 2006 -0500 @@ -26,20 +26,20 @@ /* this represents a event handler. Chaining or sharing is not allowed */ typedef struct _ev_action_t { - void (*handler)(int, struct pt_regs *, void *); + evtchn_handler_t handler; void *data; u32 count; } ev_action_t; static ev_action_t ev_actions[NR_EVS]; -void default_handler(int port, struct pt_regs *regs, void *data); +void default_handler(evtchn_port_t port, struct pt_regs *regs, void *data); /* * Demux events to different handlers. */ -int do_event(u32 port, struct pt_regs *regs) +int do_event(evtchn_port_t port, struct pt_regs *regs) { ev_action_t *action; if (port >= NR_EVS) { @@ -60,8 +60,8 @@ int do_event(u32 port, struct pt_regs *r } -int bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *, void *), - void *data ) +evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler, + void *data) { if(ev_actions[port].handler != default_handler) printk("WARN: Handler for port %d already registered, replacing\n", @@ -77,7 +77,7 @@ int bind_evtchn( u32 port, void (*handle return port; } -void unbind_evtchn( u32 port ) +void unbind_evtchn(evtchn_port_t port ) { if (ev_actions[port].handler == default_handler) printk("WARN: No handler for port %d when unbinding\n", port); @@ -86,8 +86,7 @@ void unbind_evtchn( u32 port ) ev_actions[port].data = NULL; } -int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *, void *data), - void *data) +int bind_virq(uint32_t virq, evtchn_handler_t handler, void *data) { evtchn_op_t op; @@ -103,11 +102,6 @@ int bind_virq( u32 virq, void (*handler) } bind_evtchn(op.u.bind_virq.port, handler, data); return 0; -} - -void unbind_virq( u32 port ) -{ - unbind_evtchn(port); } #if defined(__x86_64__) @@ -142,32 +136,48 @@ void init_events(void) } } -void default_handler(int port, struct pt_regs *regs, void *ignore) +void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore) { printk("[Port %d] - event received\n", port); } +/* Create a port available to the pal for exchanging notifications. + Returns the result of the hypervisor call. */ + /* Unfortunate confusion of terminology: the port is unbound as far as Xen is concerned, but we automatically bind a handler to it from inside mini-os. */ -int evtchn_alloc_unbound(void (*handler)(int, struct pt_regs *regs, - void *data), - void *data) + +int evtchn_alloc_unbound(domid_t pal, evtchn_handler_t handler, + void *data, evtchn_port_t *port) { - u32 port; - evtchn_op_t op; - int err; + evtchn_op_t op; + op.cmd = EVTCHNOP_alloc_unbound; + op.u.alloc_unbound.dom = DOMID_SELF; + op.u.alloc_unbound.remote_dom = pal; + int err = HYPERVISOR_event_channel_op(&op); + if (err) + return err; + *port = bind_evtchn(op.u.alloc_unbound.port, handler, data); + return err; +} - op.cmd = EVTCHNOP_alloc_unbound; - op.u.alloc_unbound.dom = DOMID_SELF; - op.u.alloc_unbound.remote_dom = 0; +/* Connect to a port so as to allow the exchange of notifications with + the pal. Returns the result of the hypervisor call. */ - err = HYPERVISOR_event_channel_op(&op); - if (err) { - printk("Failed to alloc unbound evtchn: %d.\n", err); - return -1; - } - port = op.u.alloc_unbound.port; - bind_evtchn(port, handler, data); - return port; +int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port, + evtchn_handler_t handler, void *data, + evtchn_port_t *local_port) +{ + evtchn_op_t op; + op.cmd = EVTCHNOP_bind_interdomain; + op.u.bind_interdomain.remote_dom = pal; + op.u.bind_interdomain.remote_port = remote_port; + int err = HYPERVISOR_event_channel_op(&op); + if (err) + return err; + evtchn_port_t port = op.u.bind_interdomain.local_port; + clear_evtchn(port); /* Without, handler gets invoked now! */ + *local_port = bind_evtchn(port, handler, data); + return err; } diff -r 61204c1d740e -r 87cefa5f7c5e extras/mini-os/gnttab.c --- a/extras/mini-os/gnttab.c Thu Jul 27 20:07:02 2006 -0400 +++ b/extras/mini-os/gnttab.c Mon Aug 07 18:00:22 2006 -0500 @@ -137,6 +137,18 @@ gnttab_alloc_and_grant(void **map) return gref; } +static const char *gnttabop_error_msgs[] = GNTTABOP_error_msgs; + +const char * +gnttabop_error(int16_t status) +{ + status = -status; + if (status < 0 || status >= ARRAY_SIZE(gnttabop_error_msgs)) + return "bad status"; + else + return gnttabop_error_msgs[status]; +} + void init_gnttab(void) { diff -r 61204c1d740e -r 87cefa5f7c5e extras/mini-os/include/events.h --- a/extras/mini-os/include/events.h Thu Jul 27 20:07:02 2006 -0400 +++ b/extras/mini-os/include/events.h Mon Aug 07 18:00:22 2006 -0500 @@ -22,20 +22,22 @@ #include<traps.h> #include <xen/event_channel.h> +typedef void (*evtchn_handler_t)(evtchn_port_t, struct pt_regs *, void *); + /* prototypes */ -int do_event(u32 port, struct pt_regs *regs); -int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *, void *data), - void *data); -int bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *, void *data), - void *data ); -void unbind_evtchn( u32 port ); +int do_event(evtchn_port_t port, struct pt_regs *regs); +int bind_virq(uint32_t virq, evtchn_handler_t handler, void *data); +evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler, + void *data); +void unbind_evtchn(evtchn_port_t port); void init_events(void); -void unbind_virq( u32 port ); -int evtchn_alloc_unbound(void (*handler)(int, struct pt_regs *regs, - void *data), - void *data); +int evtchn_alloc_unbound(domid_t pal, evtchn_handler_t handler, + void *data, evtchn_port_t *port); +int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port, + evtchn_handler_t handler, void *data, + evtchn_port_t *local_port); -static inline int notify_remote_via_evtchn(int port) +static inline int notify_remote_via_evtchn(evtchn_port_t port) { evtchn_op_t op; op.cmd = EVTCHNOP_send; diff -r 61204c1d740e -r 87cefa5f7c5e extras/mini-os/include/gnttab.h --- a/extras/mini-os/include/gnttab.h Thu Jul 27 20:07:02 2006 -0400 +++ b/extras/mini-os/include/gnttab.h Mon Aug 07 18:00:22 2006 -0500 @@ -10,5 +10,6 @@ grant_ref_t gnttab_grant_transfer(domid_ grant_ref_t gnttab_grant_transfer(domid_t domid, unsigned long pfn); unsigned long gnttab_end_transfer(grant_ref_t gref); int gnttab_end_access(grant_ref_t ref); +const char *gnttabop_error(int16_t status); #endif /* !__GNTTAB_H__ */ diff -r 61204c1d740e -r 87cefa5f7c5e extras/mini-os/time.c --- a/extras/mini-os/time.c Thu Jul 27 20:07:02 2006 -0400 +++ b/extras/mini-os/time.c Mon Aug 07 18:00:22 2006 -0500 @@ -215,7 +215,7 @@ void block_domain(u32 millisecs) /* * Just a dummy */ -static void timer_handler(int ev, struct pt_regs *regs, void *ign) +static void timer_handler(evtchn_port_t ev, struct pt_regs *regs, void *ign) { static int i; diff -r 61204c1d740e -r 87cefa5f7c5e extras/mini-os/xenbus/xenbus.c --- a/extras/mini-os/xenbus/xenbus.c Thu Jul 27 20:07:02 2006 -0400 +++ b/extras/mini-os/xenbus/xenbus.c Mon Aug 07 18:00:22 2006 -0500 @@ -112,7 +112,8 @@ static void xenbus_thread_func(void *ign } } -static void xenbus_evtchn_handler(int port, struct pt_regs *regs, void *ign) +static void xenbus_evtchn_handler(evtchn_port_t port, struct pt_regs *regs, + void *ign) { wake_up(&xb_waitq); } diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/arch/i386/kernel/ldt-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/ldt-xen.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/ldt-xen.c Mon Aug 07 18:00:22 2006 -0500 @@ -109,6 +109,7 @@ int init_new_context(struct task_struct init_MUTEX(&mm->context.sem); mm->context.size = 0; + mm->context.has_foreign_mappings = 0; old_mm = current->mm; if (old_mm && old_mm->context.size > 0) { down(&old_mm->context.sem); diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c --- a/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c Mon Aug 07 18:00:22 2006 -0500 @@ -126,6 +126,8 @@ int direct_remap_pfn_range(struct vm_are if (domid == DOMID_SELF) return -EINVAL; + vma->vm_mm->context.has_foreign_mappings = 1; + return __direct_remap_pfn_range( vma->vm_mm, address, mfn, size, prot, domid); } diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c --- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c Mon Aug 07 18:00:22 2006 -0500 @@ -694,6 +694,7 @@ void _arch_exit_mmap(struct mm_struct *m task_unlock(tsk); if (test_bit(PG_pinned, &virt_to_page(mm->pgd)->flags) && - (atomic_read(&mm->mm_count) == 1)) + (atomic_read(&mm->mm_count) == 1) && + !mm->context.has_foreign_mappings) mm_unpin(mm); } diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/arch/ia64/Kconfig --- a/linux-2.6-xen-sparse/arch/ia64/Kconfig Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig Mon Aug 07 18:00:22 2006 -0500 @@ -438,6 +438,21 @@ config PCI_DOMAINS bool default PCI +config XEN_PCIDEV_FRONTEND + bool "Xen PCI Frontend" + depends on PCI && XEN + default y + help + The PCI device frontend driver allows the kernel to import arbitrary + PCI devices from a PCI backend to support PCI driver domains. + +config XEN_PCIDEV_FE_DEBUG + bool "Xen PCI Frontend Debugging" + depends on XEN_PCIDEV_FRONTEND + default n + help + Enables some debug statements within the PCI Frontend. + source "drivers/pci/Kconfig" source "drivers/pci/hotplug/Kconfig" diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c Mon Aug 07 18:00:22 2006 -0500 @@ -159,7 +159,8 @@ void _arch_exit_mmap(struct mm_struct *m task_unlock(tsk); - if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) ) + if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) && + !mm->context.has_foreign_mappings ) mm_unpin(mm); } diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/drivers/xen/Kconfig --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig Mon Aug 07 18:00:22 2006 -0500 @@ -143,15 +143,6 @@ config XEN_TPMDEV_BACKEND help The TPM-device backend driver -config XEN_TPMDEV_CLOSE_IF_VTPM_FAILS - bool "TPM backend closes upon vTPM failure" - depends on XEN_TPMDEV_BACKEND - default n - help - The TPM backend closes the channel if the vTPM in userspace indicates - a failure. The corresponding domain's channel will be closed. - Say Y if you want this feature. - config XEN_BLKDEV_FRONTEND tristate "Block-device frontend driver" depends on XEN diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/drivers/xen/netback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Mon Aug 07 18:00:22 2006 -0500 @@ -76,6 +76,10 @@ typedef struct netif_st { struct vm_struct *tx_comms_area; struct vm_struct *rx_comms_area; + /* Set of features that can be turned on in dev->features. */ + int features; + int can_queue; + /* Allow netif_be_start_xmit() to peek ahead in the rx request ring. */ RING_IDX rx_req_cons_peek; @@ -86,8 +90,6 @@ typedef struct netif_st { struct timer_list credit_timeout; /* Miscellaneous private stuff. */ - enum { DISCONNECTED, DISCONNECTING, CONNECTED } status; - int active; struct list_head list; /* scheduling list */ atomic_t refcnt; struct net_device *dev; @@ -121,4 +123,16 @@ struct net_device_stats *netif_be_get_st struct net_device_stats *netif_be_get_stats(struct net_device *dev); irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs); +static inline int netbk_can_queue(struct net_device *dev) +{ + netif_t *netif = netdev_priv(dev); + return netif->can_queue; +} + +static inline int netbk_can_sg(struct net_device *dev) +{ + netif_t *netif = netdev_priv(dev); + return netif->features & NETIF_F_SG; +} + #endif /* __NETIF__BACKEND__COMMON_H__ */ diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/drivers/xen/netback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Mon Aug 07 18:00:22 2006 -0500 @@ -36,46 +36,74 @@ static void __netif_up(netif_t *netif) { - struct net_device *dev = netif->dev; - netif_tx_lock_bh(dev); - netif->active = 1; - netif_tx_unlock_bh(dev); enable_irq(netif->irq); netif_schedule_work(netif); } static void __netif_down(netif_t *netif) { - struct net_device *dev = netif->dev; disable_irq(netif->irq); - netif_tx_lock_bh(dev); - netif->active = 0; - netif_tx_unlock_bh(dev); netif_deschedule_work(netif); } static int net_open(struct net_device *dev) { netif_t *netif = netdev_priv(dev); - if (netif->status == CONNECTED) + if (netif_carrier_ok(dev)) __netif_up(netif); - netif_start_queue(dev); return 0; } static int net_close(struct net_device *dev) { netif_t *netif = netdev_priv(dev); - netif_stop_queue(dev); - if (netif->status == CONNECTED) + if (netif_carrier_ok(dev)) __netif_down(netif); return 0; +} + +static int netbk_change_mtu(struct net_device *dev, int mtu) +{ + int max = netbk_can_sg(dev) ? 65535 - ETH_HLEN : ETH_DATA_LEN; + + if (mtu > max) + return -EINVAL; + dev->mtu = mtu; + return 0; +} + +static int netbk_set_sg(struct net_device *dev, u32 data) +{ + if (data) { + netif_t *netif = netdev_priv(dev); + + if (!(netif->features & NETIF_F_SG)) + return -ENOSYS; + } + + return ethtool_op_set_sg(dev, data); +} + +static int netbk_set_tso(struct net_device *dev, u32 data) +{ + if (data) { + netif_t *netif = netdev_priv(dev); + + if (!(netif->features & NETIF_F_TSO)) + return -ENOSYS; + } + + return ethtool_op_set_tso(dev, data); } static struct ethtool_ops network_ethtool_ops = { .get_tx_csum = ethtool_op_get_tx_csum, .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = netbk_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = netbk_set_tso, .get_link = ethtool_op_get_link, }; @@ -93,11 +121,12 @@ netif_t *netif_alloc(domid_t domid, unsi return ERR_PTR(-ENOMEM); } + netif_carrier_off(dev); + netif = netdev_priv(dev); memset(netif, 0, sizeof(*netif)); netif->domid = domid; netif->handle = handle; - netif->status = DISCONNECTED; atomic_set(&netif->refcnt, 1); init_waitqueue_head(&netif->waiting_to_free); netif->dev = dev; @@ -110,12 +139,16 @@ netif_t *netif_alloc(domid_t domid, unsi dev->get_stats = netif_be_get_stats; dev->open = net_open; dev->stop = net_close; + dev->change_mtu = netbk_change_mtu; dev->features = NETIF_F_IP_CSUM; SET_ETHTOOL_OPS(dev, &network_ethtool_ops); - /* Disable queuing. */ - dev->tx_queue_len = 0; + /* + * Reduce default TX queuelen so that each guest interface only + * allows it to eat around 6.4MB of host memory. + */ + dev->tx_queue_len = 100; for (i = 0; i < ETH_ALEN; i++) if (be_mac[i] != 0) @@ -256,11 +289,9 @@ int netif_map(netif_t *netif, unsigned l netif->rx_req_cons_peek = 0; netif_get(netif); - wmb(); /* Other CPUs see new state before interface is started. */ rtnl_lock(); - netif->status = CONNECTED; - wmb(); + netif_carrier_on(netif->dev); if (netif_running(netif->dev)) __netif_up(netif); rtnl_unlock(); @@ -296,20 +327,13 @@ static void netif_free(netif_t *netif) void netif_disconnect(netif_t *netif) { - switch (netif->status) { - case CONNECTED: + if (netif_carrier_ok(netif->dev)) { rtnl_lock(); - netif->status = DISCONNECTING; - wmb(); + netif_carrier_off(netif->dev); if (netif_running(netif->dev)) __netif_down(netif); rtnl_unlock(); netif_put(netif); - /* fall through */ - case DISCONNECTED: - netif_free(netif); - break; - default: - BUG(); - } -} + } + netif_free(netif); +} diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Mon Aug 07 18:00:22 2006 -0500 @@ -40,17 +40,22 @@ /*#define NETBE_DEBUG_INTERRUPT*/ +struct netbk_rx_meta { + skb_frag_t frag; + int id; +}; + static void netif_idx_release(u16 pending_idx); static void netif_page_release(struct page *page); static void make_tx_response(netif_t *netif, netif_tx_request_t *txp, s8 st); -static int make_rx_response(netif_t *netif, - u16 id, - s8 st, - u16 offset, - u16 size, - u16 flags); +static netif_rx_response_t *make_rx_response(netif_t *netif, + u16 id, + s8 st, + u16 offset, + u16 size, + u16 flags); static void net_tx_action(unsigned long unused); static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0); @@ -100,21 +105,27 @@ static unsigned long mfn_list[MAX_MFN_AL static unsigned long mfn_list[MAX_MFN_ALLOC]; static unsigned int alloc_index = 0; -static unsigned long alloc_mfn(void) -{ - unsigned long mfn = 0; +static inline unsigned long alloc_mfn(void) +{ + return mfn_list[--alloc_index]; +} + +static int check_mfn(int nr) +{ struct xen_memory_reservation reservation = { - .nr_extents = MAX_MFN_ALLOC, .extent_order = 0, .domid = DOMID_SELF }; - set_xen_guest_handle(reservation.extent_start, mfn_list); - if ( unlikely(alloc_index == 0) ) - alloc_index = HYPERVISOR_memory_op( - XENMEM_increase_reservation, &reservation); - if ( alloc_index != 0 ) - mfn = mfn_list[--alloc_index]; - return mfn; + + if (likely(alloc_index >= nr)) + return 0; + + set_xen_guest_handle(reservation.extent_start, mfn_list + alloc_index); + reservation.nr_extents = MAX_MFN_ALLOC - alloc_index; + alloc_index += HYPERVISOR_memory_op(XENMEM_increase_reservation, + &reservation); + + return alloc_index >= nr ? 0 : -ENOMEM; } static inline void maybe_schedule_tx_action(void) @@ -136,6 +147,96 @@ static inline int is_xen_skb(struct sk_b return (cp == skbuff_cachep); } +static struct sk_buff *netbk_copy_skb(struct sk_buff *skb) +{ + struct skb_shared_info *ninfo; + struct sk_buff *nskb; + unsigned long offset; + int ret; + int len; + int headlen; + + nskb = alloc_skb(SKB_MAX_HEAD(0), GFP_ATOMIC); + if (unlikely(!nskb)) + goto err; + + skb_reserve(nskb, 16); + headlen = nskb->end - nskb->data; + if (headlen > skb_headlen(skb)) + headlen = skb_headlen(skb); + ret = skb_copy_bits(skb, 0, __skb_put(nskb, headlen), headlen); + BUG_ON(ret); + + ninfo = skb_shinfo(nskb); + ninfo->gso_size = skb_shinfo(skb)->gso_size; + ninfo->gso_type = skb_shinfo(skb)->gso_type; + + offset = headlen; + len = skb->len - headlen; + + nskb->len = skb->len; + nskb->data_len = len; + nskb->truesize += len; + + while (len) { + struct page *page; + int copy; + int zero; + + if (unlikely(ninfo->nr_frags >= MAX_SKB_FRAGS)) { + dump_stack(); + goto err_free; + } + + copy = len >= PAGE_SIZE ? PAGE_SIZE : len; + zero = len >= PAGE_SIZE ? 0 : __GFP_ZERO; + + page = alloc_page(GFP_ATOMIC | zero); + if (unlikely(!page)) + goto err_free; + + ret = skb_copy_bits(skb, offset, page_address(page), copy); + BUG_ON(ret); + + ninfo->frags[ninfo->nr_frags].page = page; + ninfo->frags[ninfo->nr_frags].page_offset = 0; + ninfo->frags[ninfo->nr_frags].size = copy; + ninfo->nr_frags++; + + offset += copy; + len -= copy; + } + + offset = nskb->data - skb->data; + + nskb->h.raw = skb->h.raw + offset; + nskb->nh.raw = skb->nh.raw + offset; + nskb->mac.raw = skb->mac.raw + offset; + + return nskb; + + err_free: + kfree_skb(nskb); + err: + return NULL; +} + +static inline int netbk_max_required_rx_slots(netif_t *netif) +{ + if (netif->features & (NETIF_F_SG|NETIF_F_TSO)) + return MAX_SKB_FRAGS + 2; /* header + extra_info + frags */ + return 1; /* all in one */ +} + +static inline int netbk_queue_full(netif_t *netif) +{ + RING_IDX peek = netif->rx_req_cons_peek; + RING_IDX needed = netbk_max_required_rx_slots(netif); + + return ((netif->rx.sring->req_prod - peek) < needed) || + ((netif->rx.rsp_prod_pvt + NET_RX_RING_SIZE - peek) < needed); +} + int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev) { netif_t *netif = netdev_priv(dev); @@ -143,30 +244,26 @@ int netif_be_start_xmit(struct sk_buff * BUG_ON(skb->dev != dev); /* Drop the packet if the target domain has no receive buffers. */ - if (!netif->active || - (netif->rx_req_cons_peek == netif->rx.sring->req_prod) || - ((netif->rx_req_cons_peek - netif->rx.rsp_prod_pvt) == - NET_RX_RING_SIZE)) + if (unlikely(!netif_running(dev) || !netif_carrier_ok(dev))) goto drop; + + if (unlikely(netbk_queue_full(netif))) { + /* Not a BUG_ON() -- misbehaving netfront can trigger this. */ + if (netbk_can_queue(dev)) + DPRINTK("Queue full but not stopped!\n"); + goto drop; + } /* * We do not copy the packet unless: * 1. The data is shared; or * 2. The data is not allocated from our special cache. - * NB. We also couldn't cope with fragmented packets, but we won't get - * any because we not advertise the NETIF_F_SG feature. + * 3. The data is fragmented. */ - if (skb_shared(skb) || skb_cloned(skb) || !is_xen_skb(skb)) { - int hlen = skb->data - skb->head; - int ret; - struct sk_buff *nskb = dev_alloc_skb(hlen + skb->len); + if (skb_cloned(skb) || skb_is_nonlinear(skb) || !is_xen_skb(skb)) { + struct sk_buff *nskb = netbk_copy_skb(skb); if ( unlikely(nskb == NULL) ) goto drop; - skb_reserve(nskb, hlen); - __skb_put(nskb, skb->len); - ret = skb_copy_bits(skb, -hlen, nskb->data - hlen, - skb->len + hlen); - BUG_ON(ret); /* Copy only the header fields we use in this driver. */ nskb->dev = skb->dev; nskb->ip_summed = skb->ip_summed; @@ -175,8 +272,17 @@ int netif_be_start_xmit(struct sk_buff * skb = nskb; } - netif->rx_req_cons_peek++; + netif->rx_req_cons_peek += skb_shinfo(skb)->nr_frags + 1 + + !!skb_shinfo(skb)->gso_size; netif_get(netif); + + if (netbk_can_queue(dev) && netbk_queue_full(netif)) { + netif->rx.sring->req_event = netif->rx_req_cons_peek + + netbk_max_required_rx_slots(netif); + mb(); /* request notification /then/ check & stop the queue */ + if (netbk_queue_full(netif)) + netif_stop_queue(dev); + } skb_queue_tail(&rx_queue, skb); tasklet_schedule(&net_rx_tasklet); @@ -208,116 +314,85 @@ int xen_network_done(void) } #endif -static void net_rx_action(unsigned long unused) -{ - netif_t *netif = NULL; - s8 status; - u16 size, id, irq, flags; - multicall_entry_t *mcl; - mmu_update_t *mmu; - gnttab_transfer_t *gop; - unsigned long vdata, old_mfn, new_mfn; - struct sk_buff_head rxq; - struct sk_buff *skb; - int notify_nr = 0; - int ret; +static u16 netbk_gop_frag(netif_t *netif, struct page *page, int count, int i) +{ + multicall_entry_t *mcl = rx_mcl + count; + mmu_update_t *mmu = rx_mmu + count; + gnttab_transfer_t *gop = grant_rx_op + count; + netif_rx_request_t *req; + unsigned long old_mfn, new_mfn; + + old_mfn = virt_to_mfn(page_address(page)); + + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + new_mfn = alloc_mfn(); + + /* + * Set the new P2M table entry before reassigning + * the old data page. Heed the comment in + * pgtable-2level.h:pte_page(). :-) + */ + set_phys_to_machine(page_to_pfn(page), new_mfn); + + MULTI_update_va_mapping(mcl, (unsigned long)page_address(page), + pfn_pte_ma(new_mfn, PAGE_KERNEL), 0); + + mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) | + MMU_MACHPHYS_UPDATE; + mmu->val = page_to_pfn(page); + } + + req = RING_GET_REQUEST(&netif->rx, netif->rx.req_cons + i); + gop->mfn = old_mfn; + gop->domid = netif->domid; + gop->ref = req->gref; + return req->id; +} + +static void netbk_gop_skb(struct sk_buff *skb, struct netbk_rx_meta *meta, + int count) +{ + netif_t *netif = netdev_priv(skb->dev); + int nr_frags = skb_shinfo(skb)->nr_frags; + int i; + int extra; + + meta[count].frag.page_offset = skb_shinfo(skb)->gso_type; + meta[count].frag.size = skb_shinfo(skb)->gso_size; + extra = !!meta[count].frag.size + 1; + + for (i = 0; i < nr_frags; i++) { + meta[++count].frag = skb_shinfo(skb)->frags[i]; + meta[count].id = netbk_gop_frag(netif, meta[count].frag.page, + count, i + extra); + } + /* - * Putting hundreds of bytes on the stack is considered rude. - * Static works because a tasklet can only be on one CPU at any time. + * This must occur at the end to ensure that we don't trash + * skb_shinfo until we're done. */ - static u16 notify_list[NET_RX_RING_SIZE]; - - skb_queue_head_init(&rxq); - - mcl = rx_mcl; - mmu = rx_mmu; - gop = grant_rx_op; - - while ((skb = skb_dequeue(&rx_queue)) != NULL) { - netif = netdev_priv(skb->dev); - vdata = (unsigned long)skb->data; - old_mfn = virt_to_mfn(vdata); - - if (!xen_feature(XENFEAT_auto_translated_physmap)) { - /* Memory squeeze? Back off for an arbitrary while. */ - if ((new_mfn = alloc_mfn()) == 0) { - if ( net_ratelimit() ) - WPRINTK("Memory squeeze in netback " - "driver.\n"); - mod_timer(&net_timer, jiffies + HZ); - skb_queue_head(&rx_queue, skb); - break; - } - /* - * Set the new P2M table entry before reassigning - * the old data page. Heed the comment in - * pgtable-2level.h:pte_page(). :-) - */ - set_phys_to_machine( - __pa(skb->data) >> PAGE_SHIFT, - new_mfn); - - MULTI_update_va_mapping(mcl, vdata, - pfn_pte_ma(new_mfn, - PAGE_KERNEL), 0); - mcl++; - - mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) | - MMU_MACHPHYS_UPDATE; - mmu->val = __pa(vdata) >> PAGE_SHIFT; - mmu++; - } - - gop->mfn = old_mfn; - gop->domid = netif->domid; - gop->ref = RING_GET_REQUEST( - &netif->rx, netif->rx.req_cons)->gref; - netif->rx.req_cons++; - gop++; - - __skb_queue_tail(&rxq, skb); - - /* Filled the batch queue? */ - if ((gop - grant_rx_op) == ARRAY_SIZE(grant_rx_op)) - break; - } - - if (!xen_feature(XENFEAT_auto_translated_physmap)) { - if (mcl == rx_mcl) - return; - - mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; - - if (mmu - rx_mmu) { - mcl->op = __HYPERVISOR_mmu_update; - mcl->args[0] = (unsigned long)rx_mmu; - mcl->args[1] = mmu - rx_mmu; - mcl->args[2] = 0; - mcl->args[3] = DOMID_SELF; - mcl++; - } - - ret = HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl); - BUG_ON(ret != 0); - } - - ret = HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op, - gop - grant_rx_op); - BUG_ON(ret != 0); - - mcl = rx_mcl; - gop = grant_rx_op; - while ((skb = __skb_dequeue(&rxq)) != NULL) { - netif = netdev_priv(skb->dev); - size = skb->tail - skb->data; - - atomic_set(&(skb_shinfo(skb)->dataref), 1); - skb_shinfo(skb)->nr_frags = 0; - skb_shinfo(skb)->frag_list = NULL; - - netif->stats.tx_bytes += size; - netif->stats.tx_packets++; - + meta[count - nr_frags].id = netbk_gop_frag(netif, + virt_to_page(skb->data), + count - nr_frags, 0); + netif->rx.req_cons += nr_frags + extra; +} + +static inline void netbk_free_pages(int nr_frags, struct netbk_rx_meta *meta) +{ + int i; + + for (i = 0; i < nr_frags; i++) + put_page(meta[i].frag.page); +} + +static int netbk_check_gop(int nr_frags, domid_t domid, int count) +{ + multicall_entry_t *mcl = rx_mcl + count; + gnttab_transfer_t *gop = grant_rx_op + count; + int status = NETIF_RSP_OKAY; + int i; + + for (i = 0; i <= nr_frags; i++) { if (!xen_feature(XENFEAT_auto_translated_physmap)) { /* The update_va_mapping() must not fail. */ BUG_ON(mcl->result != 0); @@ -325,10 +400,9 @@ static void net_rx_action(unsigned long } /* Check the reassignment error code. */ - status = NETIF_RSP_OKAY; if (gop->status != 0) { DPRINTK("Bad status %d from grant transfer to DOM%u\n", - gop->status, netif->domid); + gop->status, domid); /* * Page no longer belongs to us unless GNTST_bad_page, * but that should be a fatal error anyway. @@ -336,24 +410,166 @@ static void net_rx_action(unsigned long BUG_ON(gop->status == GNTST_bad_page); status = NETIF_RSP_ERROR; } - irq = netif->irq; - id = RING_GET_REQUEST(&netif->rx, netif->rx.rsp_prod_pvt)->id; - flags = 0; + gop++; + } + + return status; +} + +static void netbk_add_frag_responses(netif_t *netif, int status, + struct netbk_rx_meta *meta, int nr_frags) +{ + int i; + + for (i = 0; i < nr_frags; i++) { + int id = meta[i].id; + int flags = (i == nr_frags - 1) ? 0 : NETRXF_more_data; + + make_rx_response(netif, id, status, meta[i].frag.page_offset, + meta[i].frag.size, flags); + } +} + +static void net_rx_action(unsigned long unused) +{ + netif_t *netif = NULL; + s8 status; + u16 id, irq, flags; + netif_rx_response_t *resp; + struct netif_extra_info *extra; + multicall_entry_t *mcl; + struct sk_buff_head rxq; + struct sk_buff *skb; + int notify_nr = 0; + int ret; + int nr_frags; + int count; + + /* + * Putting hundreds of bytes on the stack is considered rude. + * Static works because a tasklet can only be on one CPU at any time. + */ + static u16 notify_list[NET_RX_RING_SIZE]; + static struct netbk_rx_meta meta[NET_RX_RING_SIZE]; + + skb_queue_head_init(&rxq); + + count = 0; + + while ((skb = skb_dequeue(&rx_queue)) != NULL) { + nr_frags = skb_shinfo(skb)->nr_frags; + *(int *)skb->cb = nr_frags; + + if (!xen_feature(XENFEAT_auto_translated_physmap) && + check_mfn(nr_frags + 1)) { + /* Memory squeeze? Back off for an arbitrary while. */ + if ( net_ratelimit() ) + WPRINTK("Memory squeeze in netback " + "driver.\n"); + mod_timer(&net_timer, jiffies + HZ); + skb_queue_head(&rx_queue, skb); + break; + } + + netbk_gop_skb(skb, meta, count); + + count += nr_frags + 1; + + __skb_queue_tail(&rxq, skb); + + /* Filled the batch queue? */ + if (count + MAX_SKB_FRAGS >= NET_RX_RING_SIZE) + break; + } + + if (!count) + return; + + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + mcl = rx_mcl + count; + + mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; + + mcl->op = __HYPERVISOR_mmu_update; + mcl->args[0] = (unsigned long)rx_mmu; + mcl->args[1] = count; + mcl->args[2] = 0; + mcl->args[3] = DOMID_SELF; + + ret = HYPERVISOR_multicall(rx_mcl, count + 1); + BUG_ON(ret != 0); + } + + ret = HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op, count); + BUG_ON(ret != 0); + + count = 0; + while ((skb = __skb_dequeue(&rxq)) != NULL) { + nr_frags = *(int *)skb->cb; + + atomic_set(&(skb_shinfo(skb)->dataref), 1); + skb_shinfo(skb)->nr_frags = 0; + skb_shinfo(skb)->frag_list = NULL; + + netif = netdev_priv(skb->dev); + netif->stats.tx_bytes += skb->len; + netif->stats.tx_packets++; + + netbk_free_pages(nr_frags, meta + count + 1); + status = netbk_check_gop(nr_frags, netif->domid, count); + + id = meta[count].id; + flags = nr_frags ? NETRXF_more_data : 0; + if (skb->ip_summed == CHECKSUM_HW) /* local packet? */ flags |= NETRXF_csum_blank | NETRXF_data_validated; else if (skb->proto_data_valid) /* remote but checksummed? */ flags |= NETRXF_data_validated; - if (make_rx_response(netif, id, status, - (unsigned long)skb->data & ~PAGE_MASK, - size, flags) && - (rx_notify[irq] == 0)) { + + resp = make_rx_response(netif, id, status, + offset_in_page(skb->data), + skb_headlen(skb), flags); + + extra = NULL; + + if (meta[count].frag.size) { + struct netif_extra_info *gso = + (struct netif_extra_info *) + RING_GET_RESPONSE(&netif->rx, + netif->rx.rsp_prod_pvt++); + + if (extra) + extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE; + else + resp->flags |= NETRXF_extra_info; + + gso->u.gso.size = meta[count].frag.size; + gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4; + gso->u.gso.pad = 0; + gso->u.gso.features = 0; + + gso->type = XEN_NETIF_EXTRA_TYPE_GSO; + gso->flags = 0; + extra = gso; + } + + netbk_add_frag_responses(netif, status, meta + count + 1, + nr_frags); + + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->rx, ret); + irq = netif->irq; + if (ret && !rx_notify[irq]) { rx_notify[irq] = 1; notify_list[notify_nr++] = irq; } + if (netif_queue_stopped(netif->dev) && + !netbk_queue_full(netif)) + netif_wake_queue(netif->dev); + netif_put(netif); dev_kfree_skb(skb); - gop++; + count += nr_frags + 1; } while (notify_nr != 0) { @@ -404,7 +620,9 @@ static void add_to_net_schedule_list_tai return; spin_lock_irq(&net_schedule_list_lock); - if (!__on_net_schedule_list(netif) && netif->active) { + if (!__on_net_schedule_list(netif) && + likely(netif_running(netif->dev) && + netif_carrier_ok(netif->dev))) { list_add_tail(&netif->list, &net_schedule_list); netif_get(netif); } @@ -972,8 +1190,13 @@ irqreturn_t netif_be_int(int irq, void * irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs) { netif_t *netif = dev_id; + add_to_net_schedule_list_tail(netif); maybe_schedule_tx_action(); + + if (netif_queue_stopped(netif->dev) && !netbk_queue_full(netif)) + netif_wake_queue(netif->dev); + return IRQ_HANDLED; } @@ -1007,16 +1230,15 @@ static void make_tx_response(netif_t *ne #endif } -static int make_rx_response(netif_t *netif, - u16 id, - s8 st, - u16 offset, - u16 size, - u16 flags) +static netif_rx_response_t *make_rx_response(netif_t *netif, + u16 id, + s8 st, + u16 offset, + u16 size, + u16 flags) { RING_IDX i = netif->rx.rsp_prod_pvt; netif_rx_response_t *resp; - int notify; resp = RING_GET_RESPONSE(&netif->rx, i); resp->offset = offset; @@ -1027,9 +1249,8 @@ static int make_rx_response(netif_t *net resp->status = (s16)st; netif->rx.rsp_prod_pvt = ++i; - RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->rx, notify); - - return notify; + + return resp; } #ifdef NETBE_DEBUG_INTERRUPT diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Mon Aug 07 18:00:22 2006 -0500 @@ -101,14 +101,12 @@ static int netback_probe(struct xenbus_d goto abort_transaction; } -#if 0 /* KAF: After the protocol is finalised. */ err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4", "%d", 1); if (err) { message = "writing feature-gso-tcpv4"; goto abort_transaction; } -#endif err = xenbus_transaction_end(xbt, 0); } while (err == -EAGAIN); @@ -353,6 +351,7 @@ static int connect_rings(struct backend_ unsigned long tx_ring_ref, rx_ring_ref; unsigned int evtchn; int err; + int val; DPRINTK(""); @@ -365,6 +364,30 @@ static int connect_rings(struct backend_ "reading %s/ring-ref and event-channel", dev->otherend); return err; + } + + if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-rx-notify", "%d", + &val) < 0) + val = 0; + if (val) + be->netif->can_queue = 1; + else + /* Must be non-zero for pfifo_fast to work. */ + be->netif->dev->tx_queue_len = 1; + + if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg", "%d", &val) < 0) + val = 0; + if (val) { + be->netif->features |= NETIF_F_SG; + be->netif->dev->features |= NETIF_F_SG; + } + + if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4", "%d", + &val) < 0) + val = 0; + if (val) { + be->netif->features |= NETIF_F_TSO; + be->netif->dev->features |= NETIF_F_TSO; } /* Map the shared frame, irq etc. */ diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Mon Aug 07 18:00:22 2006 -0500 @@ -46,11 +46,11 @@ #include <linux/ethtool.h> #include <linux/in.h> #include <linux/if_ether.h> +#include <linux/io.h> #include <net/sock.h> #include <net/pkt_sched.h> #include <net/arp.h> #include <net/route.h> -#include <asm/io.h> #include <asm/uaccess.h> #include <xen/evtchn.h> #include <xen/xenbus.h> @@ -62,17 +62,12 @@ #include <xen/interface/grant_table.h> #include <xen/gnttab.h> +#define RX_COPY_THRESHOLD 256 + #define GRANT_INVALID_REF 0 #define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE) #define NET_RX_RING_SIZE __RING_SIZE((struct netif_rx_sring *)0, PAGE_SIZE) - -static inline void init_skb_shinfo(struct sk_buff *skb) -{ - atomic_set(&(skb_shinfo(skb)->dataref), 1); - skb_shinfo(skb)->nr_frags = 0; - skb_shinfo(skb)->frag_list = NULL; -} struct netfront_info { struct list_head list; @@ -99,17 +94,17 @@ struct netfront_info { struct timer_list rx_refill_timer; /* - * {tx,rx}_skbs store outstanding skbuffs. The first entry in each - * array is an index into a chain of free entries. + * {tx,rx}_skbs store outstanding skbuffs. The first entry in tx_skbs + * is an index into a chain of free entries. */ struct sk_buff *tx_skbs[NET_TX_RING_SIZE+1]; - struct sk_buff *rx_skbs[NET_RX_RING_SIZE+1]; + struct sk_buff *rx_skbs[NET_RX_RING_SIZE]; #define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256) grant_ref_t gref_tx_head; grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1]; grant_ref_t gref_rx_head; - grant_ref_t grant_rx_ref[NET_TX_RING_SIZE + 1]; + grant_ref_t grant_rx_ref[NET_TX_RING_SIZE]; struct xenbus_device *xbdev; int tx_ring_ref; @@ -121,8 +116,13 @@ struct netfront_info { struct mmu_update rx_mmu[NET_RX_RING_SIZE]; }; +struct netfront_rx_info { + struct netif_rx_response rx; + struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1]; +}; + /* - * Access macros for acquiring freeing slots in {tx,rx}_skbs[]. + * Access macros for acquiring freeing slots in tx_skbs[]. */ static inline void add_id_to_freelist(struct sk_buff **list, unsigned short id) @@ -136,6 +136,29 @@ static inline unsigned short get_id_from unsigned int id = (unsigned int)(unsigned long)list[0]; list[0] = list[id]; return id; +} + +static inline int xennet_rxidx(RING_IDX idx) +{ + return idx & (NET_RX_RING_SIZE - 1); +} + +static inline struct sk_buff *xennet_get_rx_skb(struct netfront_info *np, + RING_IDX ri) +{ + int i = xennet_rxidx(ri); + struct sk_buff *skb = np->rx_skbs[i]; + np->rx_skbs[i] = NULL; + return skb; +} + +static inline grant_ref_t xennet_get_rx_ref(struct netfront_info *np, + RING_IDX ri) +{ + int i = xennet_rxidx(ri); + grant_ref_t ref = np->grant_rx_ref[i]; + np->grant_rx_ref[i] = GRANT_INVALID_REF; + return ref; } #define DPRINTK(fmt, args...) \ @@ -303,6 +326,24 @@ again: goto abort_transaction; } + err = xenbus_printf(xbt, dev->nodename, "feature-rx-notify", "%d", 1); + if (err) { + message = "writing feature-rx-notify"; + goto abort_transaction; + } + + err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", 1); + if (err) { + message = "writing feature-sg"; + goto abort_transaction; + } + + err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4", "%d", 1); + if (err) { + message = "writing feature-gso-tcpv4"; + goto abort_transaction; + } + err = xenbus_transaction_end(xbt, 0); if (err) { if (err == -EAGAIN) @@ -455,6 +496,9 @@ static int network_open(struct net_devic network_alloc_rx_buffers(dev); np->rx.sring->rsp_event = np->rx.rsp_cons + 1; + + if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) + netif_rx_schedule(dev); netif_start_queue(dev); @@ -546,10 +590,13 @@ static void network_alloc_rx_buffers(str unsigned short id; struct netfront_info *np = netdev_priv(dev); struct sk_buff *skb; - int i, batch_target; + struct page *page; + int i, batch_target, notify; RING_IDX req_prod = np->rx.req_prod_pvt; struct xen_memory_reservation reservation; grant_ref_t ref; + unsigned long pfn; + void *vaddr; if (unlikely(!netif_carrier_ok(dev))) return; @@ -562,29 +609,36 @@ static void network_alloc_rx_buffers(str */ batch_target = np->rx_target - (req_prod - np->rx.rsp_cons); for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) { - /* - * Subtract dev_alloc_skb headroom (16 bytes) and shared info - * tailroom then round down to SKB_DATA_ALIGN boundary. - */ - skb = __dev_alloc_skb( - ((PAGE_SIZE - sizeof(struct skb_shared_info)) & - (-SKB_DATA_ALIGN(1))) - 16, - GFP_ATOMIC|__GFP_NOWARN); - if (skb == NULL) { + /* Allocate an skb and a page. */ + skb = __dev_alloc_skb(RX_COPY_THRESHOLD, + GFP_ATOMIC | __GFP_NOWARN); + if (unlikely(!skb)) + goto no_skb; + + page = alloc_page(GFP_ATOMIC | __GFP_NOWARN); + if (!page) { + kfree_skb(skb); +no_skb: /* Any skbuffs queued for refill? Force them out. */ if (i != 0) goto refill; /* Could not allocate any skbuffs. Try again later. */ mod_timer(&np->rx_refill_timer, jiffies + (HZ/10)); - return; + break; } + + skb_shinfo(skb)->frags[0].page = page; + skb_shinfo(skb)->nr_frags = 1; __skb_queue_tail(&np->rx_batch, skb); } /* Is the batch large enough to be worthwhile? */ - if (i < (np->rx_target/2)) + if (i < (np->rx_target/2)) { + if (req_prod > np->rx.sring->req_prod) + goto push; return; + } /* Adjust our fill target if we risked running out of buffers. */ if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) && @@ -598,26 +652,29 @@ static void network_alloc_rx_buffers(str skb->dev = dev; - id = get_id_from_freelist(np->rx_skbs); - + id = xennet_rxidx(req_prod + i); + + BUG_ON(np->rx_skbs[id]); np->rx_skbs[id] = skb; RING_GET_REQUEST(&np->rx, req_prod + i)->id = id; ref = gnttab_claim_grant_reference(&np->gref_rx_head); BUG_ON((signed short)ref < 0); np->grant_rx_ref[id] = ref; + + pfn = page_to_pfn(skb_shinfo(skb)->frags[0].page); + vaddr = page_address(skb_shinfo(skb)->frags[0].page); + gnttab_grant_foreign_transfer_ref(ref, - np->xbdev->otherend_id, - __pa(skb->head)>>PAGE_SHIFT); + np->xbdev->otherend_id, pfn); RING_GET_REQUEST(&np->rx, req_prod + i)->gref = ref; - np->rx_pfn_array[i] = virt_to_mfn(skb->head); + np->rx_pfn_array[i] = pfn_to_mfn(pfn); if (!xen_feature(XENFEAT_auto_translated_physmap)) { /* Remove this page before passing back to Xen. */ - set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT, - INVALID_P2M_ENTRY); + set_phys_to_machine(pfn, INVALID_P2M_ENTRY); MULTI_update_va_mapping(np->rx_mcl+i, - (unsigned long)skb->head, + (unsigned long)vaddr, __pte(0), 0); } } @@ -654,7 +711,10 @@ static void network_alloc_rx_buffers(str /* Above is a suitable barrier to ensure backend will see requests. */ np->rx.req_prod_pvt = req_prod + i; - RING_PUSH_REQUESTS(&np->rx); + push: + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify); + if (notify) + notify_remote_via_irq(np->irq); } static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, @@ -840,49 +900,99 @@ static irqreturn_t netif_int(int irq, vo return IRQ_HANDLED; } - -static int netif_poll(struct net_device *dev, int *pbudget) -{ - struct netfront_info *np = netdev_priv(dev); - struct sk_buff *skb, *nskb; - struct netif_rx_response *rx; - RING_IDX i, rp; - struct mmu_update *mmu = np->rx_mmu; - struct multicall_entry *mcl = np->rx_mcl; - int work_done, budget, more_to_do = 1; - struct sk_buff_head rxq; - unsigned long flags; - unsigned long mfn; - grant_ref_t ref; - - spin_lock(&np->rx_lock); - - if (unlikely(!netif_carrier_ok(dev))) { - spin_unlock(&np->rx_lock); - return 0; - } - - skb_queue_head_init(&rxq); - - if ((budget = *pbudget) > dev->quota) - budget = dev->quota; - rp = np->rx.sring->rsp_prod; - rmb(); /* Ensure we see queued responses up to 'rp'. */ - - for (i = np->rx.rsp_cons, work_done = 0; - (i != rp) && (work_done < budget); - i++, work_done++) { - rx = RING_GET_RESPONSE(&np->rx, i); +static void xennet_move_rx_slot(struct netfront_info *np, struct sk_buff *skb, + grant_ref_t ref) +{ + int new = xennet_rxidx(np->rx.req_prod_pvt); + + BUG_ON(np->rx_skbs[new]); + np->rx_skbs[new] = skb; + np->grant_rx_ref[new] = ref; + RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->id = new; + RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->gref = ref; + np->rx.req_prod_pvt++; +} + +int xennet_get_extras(struct netfront_info *np, + struct netif_extra_info *extras, RING_IDX rp) + +{ + struct netif_extra_info *extra; + RING_IDX cons = np->rx.rsp_cons; + int err = 0; + + do { + struct sk_buff *skb; + grant_ref_t ref; + + if (unlikely(cons + 1 == rp)) { + if (net_ratelimit()) + WPRINTK("Missing extra info\n"); + err = -EBADR; + break; + } + + extra = (struct netif_extra_info *) + RING_GET_RESPONSE(&np->rx, ++cons); + + if (unlikely(!extra->type || + extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) { + if (net_ratelimit()) + WPRINTK("Invalid extra type: %d\n", + extra->type); + err = -EINVAL; + } else + memcpy(&extras[extra->type - 1], extra, sizeof(*extra)); + + skb = xennet_get_rx_skb(np, cons); + ref = xennet_get_rx_ref(np, cons); + xennet_move_rx_slot(np, skb, ref); + } while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE); + + np->rx.rsp_cons = cons; + return err; +} + +static int xennet_get_responses(struct netfront_info *np, + struct netfront_rx_info *rinfo, RING_IDX rp, + struct sk_buff_head *list, int count) +{ + struct mmu_update *mmu = np->rx_mmu + count; + struct multicall_entry *mcl = np->rx_mcl + count; + struct netif_rx_response *rx = &rinfo->rx; + struct netif_extra_info *extras = rinfo->extras; + RING_IDX cons = np->rx.rsp_cons; + struct sk_buff *skb = xennet_get_rx_skb(np, cons); + grant_ref_t ref = xennet_get_rx_ref(np, cons); + int max = MAX_SKB_FRAGS + (rx->status <= RX_COPY_THRESHOLD); + int frags = 1; + int err = 0; + + if (rx->flags & NETRXF_extra_info) { + err = xennet_get_extras(np, extras, rp); + cons = np->rx.rsp_cons; + } + + for (;;) { + unsigned long mfn; + + if (unlikely(rx->status < 0 || + rx->offset + rx->status > PAGE_SIZE)) { + if (net_ratelimit()) + WPRINTK("rx->offset: %x, size: %u\n", + rx->offset, rx->status); + err = -EINVAL; + } /* * This definitely indicates a bug, either in this driver or in * the backend driver. In future this should flag the bad * situation to the system controller to reboot the backed. */ - if ((ref = np->grant_rx_ref[rx->id]) == GRANT_INVALID_REF) { + if (ref == GRANT_INVALID_REF) { WPRINTK("Bad rx response id %d.\n", rx->id); - work_done--; - continue; + err = -EINVAL; + goto next; } /* Memory pressure, insufficient buffer headroom, ... */ @@ -890,26 +1000,201 @@ static int netif_poll(struct net_device if (net_ratelimit()) WPRINTK("Unfulfilled rx req (id=%d, st=%d).\n", rx->id, rx->status); - RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->id = - rx->id; - RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->gref = - ref; - np->rx.req_prod_pvt++; - RING_PUSH_REQUESTS(&np->rx); + xennet_move_rx_slot(np, skb, ref); + err = -ENOMEM; + goto next; + } + + gnttab_release_grant_reference(&np->gref_rx_head, ref); + + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + /* Remap the page. */ + struct page *page = skb_shinfo(skb)->frags[0].page; + unsigned long pfn = page_to_pfn(page); + void *vaddr = page_address(page); + + MULTI_update_va_mapping(mcl, (unsigned long)vaddr, + pfn_pte_ma(mfn, PAGE_KERNEL), + 0); + mcl++; + mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT) + | MMU_MACHPHYS_UPDATE; + mmu->val = pfn; + mmu++; + + set_phys_to_machine(pfn, mfn); + } + + __skb_queue_tail(list, skb); + +next: + if (!(rx->flags & NETRXF_more_data)) + break; + + if (cons + frags == rp) { + if (net_ratelimit()) + WPRINTK("Need more frags\n"); + err = -ENOENT; + break; + } + + rx = RING_GET_RESPONSE(&np->rx, cons + frags); + skb = xennet_get_rx_skb(np, cons + frags); + ref = xennet_get_rx_ref(np, cons + frags); + frags++; + } + + if (unlikely(frags > max)) { + if (net_ratelimit()) + WPRINTK("Too many frags\n"); + err = -E2BIG; + } + + return err; +} + +static RING_IDX xennet_fill_frags(struct netfront_info *np, + struct sk_buff *skb, + struct sk_buff_head *list) +{ + struct skb_shared_info *shinfo = skb_shinfo(skb); + int nr_frags = shinfo->nr_frags; + RING_IDX cons = np->rx.rsp_cons; + skb_frag_t *frag = shinfo->frags + nr_frags; + struct sk_buff *nskb; + + while ((nskb = __skb_dequeue(list))) { + struct netif_rx_response *rx = + RING_GET_RESPONSE(&np->rx, ++cons); + + frag->page = skb_shinfo(nskb)->frags[0].page; + frag->page_offset = rx->offset; + frag->size = rx->status; + + skb->data_len += rx->status; + + skb_shinfo(nskb)->nr_frags = 0; + kfree_skb(nskb); + + frag++; + nr_frags++; + } + + shinfo->nr_frags = nr_frags; + return cons; +} + +static int xennet_set_skb_gso(struct sk_buff *skb, struct netif_extra_info *gso) +{ + if (!gso->u.gso.size) { + if (net_ratelimit()) + WPRINTK("GSO size must not be zero.\n"); + return -EINVAL; + } + + /* Currently only TCPv4 S.O. is supported. */ + if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { + if (net_ratelimit()) + WPRINTK("Bad GSO type %d.\n", gso->u.gso.type); + return -EINVAL; + } + + skb_shinfo(skb)->gso_size = gso->u.gso.size; + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; + + /* Header must be checked, and gso_segs computed. */ + skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; + skb_shinfo(skb)->gso_segs = 0; + + return 0; +} + +static int netif_poll(struct net_device *dev, int *pbudget) +{ + struct netfront_info *np = netdev_priv(dev); + struct sk_buff *skb; + struct netfront_rx_info rinfo; + struct netif_rx_response *rx = &rinfo.rx; + struct netif_extra_info *extras = rinfo.extras; + RING_IDX i, rp; + struct multicall_entry *mcl; + int work_done, budget, more_to_do = 1; + struct sk_buff_head rxq; + struct sk_buff_head errq; + struct sk_buff_head tmpq; + unsigned long flags; + unsigned int len; + int pages_done; + int err; + + spin_lock(&np->rx_lock); + + if (unlikely(!netif_carrier_ok(dev))) { + spin_unlock(&np->rx_lock); + return 0; + } + + skb_queue_head_init(&rxq); + skb_queue_head_init(&errq); + skb_queue_head_init(&tmpq); + + if ((budget = *pbudget) > dev->quota) + budget = dev->quota; + rp = np->rx.sring->rsp_prod; + rmb(); /* Ensure we see queued responses up to 'rp'. */ + + for (i = np->rx.rsp_cons, work_done = 0, pages_done = 0; + (i != rp) && (work_done < budget); + np->rx.rsp_cons = ++i, work_done++) { + memcpy(rx, RING_GET_RESPONSE(&np->rx, i), sizeof(*rx)); + memset(extras, 0, sizeof(extras)); + + err = xennet_get_responses(np, &rinfo, rp, &tmpq, pages_done); + pages_done += skb_queue_len(&tmpq); + + if (unlikely(err)) { +err: + i = np->rx.rsp_cons + skb_queue_len(&tmpq) - 1; work_done--; + while ((skb = __skb_dequeue(&tmpq))) + __skb_queue_tail(&errq, skb); + np->stats.rx_errors++; continue; } - gnttab_release_grant_reference(&np->gref_rx_head, ref); - np->grant_rx_ref[rx->id] = GRANT_INVALID_REF; - - skb = np->rx_skbs[rx->id]; - add_id_to_freelist(np->rx_skbs, rx->id); - - /* NB. We handle skb overflow later. */ - skb->data = skb->head + rx->offset; - skb->len = rx->status; - skb->tail = skb->data + skb->len; + skb = __skb_dequeue(&tmpq); + + if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) { + struct netif_extra_info *gso; + gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; + + if (unlikely(xennet_set_skb_gso(skb, gso))) { + __skb_queue_head(&tmpq, skb); + goto err; + } + } + + skb->nh.raw = (void *)skb_shinfo(skb)->frags[0].page; + skb->h.raw = skb->nh.raw + rx->offset; + + len = rx->status; + if (len > RX_COPY_THRESHOLD) + len = RX_COPY_THRESHOLD; + skb_put(skb, len); + + if (rx->status > len) { + skb_shinfo(skb)->frags[0].page_offset = + rx->offset + len; + skb_shinfo(skb)->frags[0].size = rx->status - len; + skb->data_len = rx->status - len; + } else { + skb_shinfo(skb)->frags[0].page = NULL; + skb_shinfo(skb)->nr_frags = 0; + } + + i = xennet_fill_frags(np, skb, &tmpq); + skb->truesize += skb->data_len; + skb->len += skb->data_len; /* * Old backends do not assert data_validated but we @@ -925,96 +1210,38 @@ static int netif_poll(struct net_device skb->proto_csum_blank = !!(rx->flags & NETRXF_csum_blank); np->stats.rx_packets++; - np->stats.rx_bytes += rx->status; - - if (!xen_feature(XENFEAT_auto_translated_physmap)) { - /* Remap the page. */ - MULTI_update_va_mapping(mcl, (unsigned long)skb->head, - pfn_pte_ma(mfn, PAGE_KERNEL), - 0); - mcl++; - mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT) - | MMU_MACHPHYS_UPDATE; - mmu->val = __pa(skb->head) >> PAGE_SHIFT; - mmu++; - - set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT, - mfn); - } + np->stats.rx_bytes += skb->len; __skb_queue_tail(&rxq, skb); } /* Some pages are no longer absent... */ - balloon_update_driver_allowance(-work_done); + balloon_update_driver_allowance(-pages_done); /* Do all the remapping work, and M2P updates, in one big hypercall. */ - if (likely((mcl - np->rx_mcl) != 0)) { + if (likely(pages_done)) { + mcl = np->rx_mcl + pages_done; mcl->op = __HYPERVISOR_mmu_update; mcl->args[0] = (unsigned long)np->rx_mmu; - mcl->args[1] = mmu - np->rx_mmu; + mcl->args[1] = pages_done; mcl->args[2] = 0; mcl->args[3] = DOMID_SELF; - mcl++; - (void)HYPERVISOR_multicall(np->rx_mcl, mcl - np->rx_mcl); - } + (void)HYPERVISOR_multicall(np->rx_mcl, pages_done + 1); + } + + while ((skb = __skb_dequeue(&errq))) + kfree_skb(skb); while ((skb = __skb_dequeue(&rxq)) != NULL) { - if (skb->len > (dev->mtu + ETH_HLEN + 4)) { - if (net_ratelimit()) - printk(KERN_INFO "Received packet too big for " - "MTU (%d > %d)\n", - skb->len - ETH_HLEN - 4, dev->mtu); - skb->len = 0; - skb->tail = skb->data; - init_skb_shinfo(skb); - dev_kfree_skb(skb); - continue; - } - - /* - * Enough room in skbuff for the data we were passed? Also, - * Linux expects at least 16 bytes headroom in each rx buffer. - */ - if (unlikely(skb->tail > skb->end) || - unlikely((skb->data - skb->head) < 16)) { - if (net_ratelimit()) { - if (skb->tail > skb->end) - printk(KERN_INFO "Received packet " - "is %zd bytes beyond tail.\n", - skb->tail - skb->end); - else - printk(KERN_INFO "Received packet " - "is %zd bytes before head.\n", - 16 - (skb->data - skb->head)); - } - - nskb = __dev_alloc_skb(skb->len + 2, - GFP_ATOMIC|__GFP_NOWARN); - if (nskb != NULL) { - skb_reserve(nskb, 2); - skb_put(nskb, skb->len); - memcpy(nskb->data, skb->data, skb->len); - /* Copy any other fields we already set up. */ - nskb->dev = skb->dev; - nskb->ip_summed = skb->ip_summed; - nskb->proto_data_valid = skb->proto_data_valid; - nskb->proto_csum_blank = skb->proto_csum_blank; - } - - /* Reinitialise and then destroy the old skbuff. */ - skb->len = 0; - skb->tail = skb->data; - init_skb_shinfo(skb); - dev_kfree_skb(skb); - - /* Switch old for new, if we copied the buffer. */ - if ((skb = nskb) == NULL) - continue; - } - - /* Set the shinfo area, which is hidden behind the data. */ - init_skb_shinfo(skb); + struct page *page = (struct page *)skb->nh.raw; + void *vaddr = page_address(page); + + memcpy(skb->data, vaddr + (skb->h.raw - skb->nh.raw), + skb_headlen(skb)); + + if (page != skb_shinfo(skb)->frags[0].page) + __free_page(page); + /* Ethernet work: Delayed to here as it peeks the header. */ skb->protocol = eth_type_trans(skb, dev); @@ -1022,8 +1249,6 @@ static int netif_poll(struct net_device netif_receive_skb(skb); dev->last_rx = jiffies; } - - np->rx.rsp_cons = i; /* If we get a callback with very few responses, reduce fill target. */ /* NB. Note exponential increase, linear decrease. */ @@ -1103,9 +1328,7 @@ static int xennet_set_tso(struct net_dev if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-gso-tcpv4", "%d", &val) < 0) val = 0; -#if 0 /* KAF: After the protocol is finalised. */ if (!val) -#endif return -ENOSYS; } @@ -1128,6 +1351,7 @@ static void network_connect(struct net_d struct netfront_info *np = netdev_priv(dev); int i, requeue_idx; struct sk_buff *skb; + grant_ref_t ref; xennet_set_features(dev); @@ -1158,20 +1382,24 @@ static void network_connect(struct net_d } /* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */ - for (requeue_idx = 0, i = 1; i <= NET_RX_RING_SIZE; i++) { - if ((unsigned long)np->rx_skbs[i] < PAGE_OFFSET) + for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) { + if (!np->rx_skbs[i]) continue; + + skb = np->rx_skbs[requeue_idx] = xennet_get_rx_skb(np, i); + ref = np->grant_rx_ref[requeue_idx] = xennet_get_rx_ref(np, i); + gnttab_grant_foreign_transfer_ref( - np->grant_rx_ref[i], np->xbdev->otherend_id, - __pa(np->rx_skbs[i]->data) >> PAGE_SHIFT); - RING_GET_REQUEST(&np->rx, requeue_idx)->gref = - np->grant_rx_ref[i]; - RING_GET_REQUEST(&np->rx, requeue_idx)->id = i; + ref, np->xbdev->otherend_id, + page_to_pfn(skb_shinfo(skb)->frags->page)); + + RING_GET_REQUEST(&np->rx, requeue_idx)->gref = ref; + RING_GET_REQUEST(&np->rx, requeue_idx)->id = requeue_idx; + requeue_idx++; } np->rx.req_prod_pvt = requeue_idx; - RING_PUSH_REQUESTS(&np->rx); /* * Step 3: All public and private state should now be sane. Get @@ -1392,8 +1620,8 @@ static struct net_device * __devinit cre np->grant_tx_ref[i] = GRANT_INVALID_REF; } - for (i = 0; i <= NET_RX_RING_SIZE; i++) { - np->rx_skbs[i] = (void *)((unsigned long) i+1); + for (i = 0; i < NET_RX_RING_SIZE; i++) { + np->rx_skbs[i] = NULL; np->grant_rx_ref[i] = GRANT_INVALID_REF; } diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c --- a/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c Mon Aug 07 18:00:22 2006 -0500 @@ -232,6 +232,10 @@ static int __devinit pcistub_match_one(s && dev->bus->number == pdev_id->bus && dev->devfn == pdev_id->devfn) return 1; + + /* Sometimes topmost bridge links to itself. */ + if (dev == dev->bus->self) + break; } return 0; diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c Mon Aug 07 18:00:22 2006 -0500 @@ -445,6 +445,9 @@ static struct xenbus_driver xenbus_pciba int __init pciback_xenbus_register(void) { + if (!is_running_on_xen()) + return -ENODEV; + return xenbus_register_backend(&xenbus_pciback_driver); } diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c --- a/linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c Mon Aug 07 18:00:22 2006 -0500 @@ -105,7 +105,7 @@ static int pcifront_bus_read(struct pci_ .size = size, }; struct pcifront_sd *sd = bus->sysdata; - struct pcifront_device *pdev = sd->pdev; + struct pcifront_device *pdev = pcifront_get_pdev(sd); if (verbose_request) dev_info(&pdev->xdev->dev, @@ -144,7 +144,7 @@ static int pcifront_bus_write(struct pci .value = val, }; struct pcifront_sd *sd = bus->sysdata; - struct pcifront_device *pdev = sd->pdev; + struct pcifront_device *pdev = pcifront_get_pdev(sd); if (verbose_request) dev_info(&pdev->xdev->dev, @@ -207,12 +207,13 @@ int pcifront_scan_root(struct pcifront_d err = -ENOMEM; goto err_out; } - sd->domain = domain; - sd->pdev = pdev; - - b = pci_scan_bus_parented(&pdev->xdev->dev, bus, &pcifront_bus_ops, sd); + pcifront_init_sd(sd, domain, pdev); + + b = pci_scan_bus_parented(&pdev->xdev->dev, bus, + &pcifront_bus_ops, sd); if (!b) { - dev_err(&pdev->xdev->dev, "Error creating PCI Frontend Bus!\n"); + dev_err(&pdev->xdev->dev, + "Error creating PCI Frontend Bus!\n"); err = -ENOMEM; goto err_out; } diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c Mon Aug 07 18:00:22 2006 -0500 @@ -7,6 +7,7 @@ #include <linux/init.h> #include <linux/mm.h> #include <xen/xenbus.h> +#include <xen/gnttab.h> #include "pcifront.h" #define INVALID_GRANT_REF (0) @@ -283,11 +284,10 @@ static struct xenbus_driver xenbus_pcifr static int __init pcifront_init(void) { - int err = 0; - - err = xenbus_register_frontend(&xenbus_pcifront_driver); - - return err; + if (!is_running_on_xen()) + return -ENODEV; + + return xenbus_register_frontend(&xenbus_pcifront_driver); } /* Initialize after the Xen PCI Frontend Stub is initialized */ diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Mon Aug 07 18:00:22 2006 -0500 @@ -270,6 +270,7 @@ static int __init privcmd_init(void) set_bit(__HYPERVISOR_sched_op_compat, hypercall_permission_map); set_bit(__HYPERVISOR_event_channel_op_compat, hypercall_permission_map); + set_bit(__HYPERVISOR_hvm_op, hypercall_permission_map); privcmd_intf = create_xen_proc_entry("privcmd", 0400); if (privcmd_intf != NULL) diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Mon Aug 07 18:00:22 2006 -0500 @@ -55,7 +55,6 @@ struct packet { enum { PACKET_FLAG_DISCARD_RESPONSE = 1, - PACKET_FLAG_CHECK_RESPONSESTATUS = 2, }; /* local variables */ @@ -201,21 +200,6 @@ static void packet_free(struct packet *p kfree(pak); } -static int packet_set(struct packet *pak, - const unsigned char *buffer, u32 size) -{ - int rc = 0; - unsigned char *buf = kmalloc(size, GFP_KERNEL); - - if (buf) { - pak->data_buffer = buf; - memcpy(buf, buffer, size); - pak->data_len = size; - } else { - rc = -ENOMEM; - } - return rc; -} /* * Write data to the shared memory and send it to the FE. @@ -224,29 +208,6 @@ static int packet_write(struct packet *p const char *data, size_t size, int isuserbuffer) { int rc = 0; - - if ((pak->flags & PACKET_FLAG_CHECK_RESPONSESTATUS)) { -#ifdef CONFIG_XEN_TPMDEV_CLOSE_IF_VTPM_FAILS - u32 res; - - if (copy_from_buffer(&res, - &data[2 + 4], sizeof (res), - isuserbuffer)) { - return -EFAULT; - } - - if (res != 0) { - /* - * Close down this device. Should have the - * FE notified about closure. - */ - if (!pak->tpmif) { - return -EFAULT; - } - pak->tpmif->status = DISCONNECTING; - } -#endif - } if (0 != (pak->flags & PACKET_FLAG_DISCARD_RESPONSE)) { /* Don't send a respone to this packet. Just acknowledge it. */ diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Mon Aug 07 18:00:22 2006 -0500 @@ -58,6 +58,9 @@ struct xenbus_dev_data { /* In-progress transaction. */ struct list_head transactions; + /* Active watches. */ + struct list_head watches; + /* Partial request. */ unsigned int len; union { @@ -70,6 +73,8 @@ struct xenbus_dev_data { char read_buffer[PAGE_SIZE]; unsigned int read_cons, read_prod; wait_queue_head_t read_waitq; + + struct mutex reply_mutex; }; static struct proc_dir_entry *xenbus_dev_intf; @@ -100,13 +105,59 @@ static void queue_reply(struct xenbus_de { int i; + mutex_lock(&u->reply_mutex); + for (i = 0; i < len; i++, u->read_prod++) u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i]; BUG_ON((u->read_prod - u->read_cons) > sizeof(u->read_buffer)); + mutex_unlock(&u->reply_mutex); + wake_up(&u->read_waitq); } + +struct watch_adapter +{ + struct list_head list; + struct xenbus_watch watch; + struct xenbus_dev_data *dev_data; + char *token; +}; + +static void free_watch_adapter (struct watch_adapter *watch) +{ + kfree(watch->watch.node); + kfree(watch->token); + kfree(watch); +} + +static void watch_fired(struct xenbus_watch *watch, + const char **vec, + unsigned int len) +{ + struct watch_adapter *adap = + container_of(watch, struct watch_adapter, watch); + struct xsd_sockmsg hdr; + const char *path, *token; + int path_len, tok_len, body_len; + + path = vec[XS_WATCH_PATH]; + token = adap->token; + + path_len = strlen(path) + 1; + tok_len = strlen(token) + 1; + body_len = path_len + tok_len; + + hdr.type = XS_WATCH_EVENT; + hdr.len = body_len; + + queue_reply(adap->dev_data, (char *)&hdr, sizeof(hdr)); + queue_reply(adap->dev_data, (char *)path, path_len); + queue_reply(adap->dev_data, (char *)token, tok_len); +} + +static LIST_HEAD(watch_list); static ssize_t xenbus_dev_write(struct file *filp, const char __user *ubuf, @@ -116,6 +167,9 @@ static ssize_t xenbus_dev_write(struct f struct xenbus_dev_transaction *trans = NULL; uint32_t msg_type; void *reply; + char *path, *token; + struct watch_adapter *watch, *tmp_watch; + int err; if ((len + u->len) > sizeof(u->u.buffer)) return -EINVAL; @@ -169,6 +223,56 @@ static ssize_t xenbus_dev_write(struct f kfree(reply); break; + case XS_WATCH: + case XS_UNWATCH: + path = u->u.buffer + sizeof(u->u.msg); + token = memchr(path, 0, u->u.msg.len); + if (token == NULL) + return -EILSEQ; + token++; + + if (msg_type == XS_WATCH) { + static const char * XS_WATCH_RESP = "OK"; + struct xsd_sockmsg hdr; + + watch = kmalloc(sizeof(*watch), GFP_KERNEL); + watch->watch.node = kmalloc(strlen(path)+1, + GFP_KERNEL); + strcpy((char *)watch->watch.node, path); + watch->watch.callback = watch_fired; + watch->token = kmalloc(strlen(token)+1, GFP_KERNEL); + strcpy(watch->token, token); + watch->dev_data = u; + + err = register_xenbus_watch(&watch->watch); + if (err) { + free_watch_adapter(watch); + return err; + } + + list_add(&watch->list, &u->watches); + + hdr.type = XS_WATCH; + hdr.len = strlen(XS_WATCH_RESP) + 1; + queue_reply(u, (char *)&hdr, sizeof(hdr)); + queue_reply(u, (char *)XS_WATCH_RESP, hdr.len); + } else { + list_for_each_entry_safe(watch, tmp_watch, + &u->watches, list) { + if (!strcmp(watch->token, token) && + !strcmp(watch->watch.node, path)) + break; + { + unregister_xenbus_watch(&watch->watch); + list_del(&watch->list); + free_watch_adapter(watch); + break; + } + } + } + + break; + default: return -EINVAL; } @@ -191,7 +295,10 @@ static int xenbus_dev_open(struct inode return -ENOMEM; INIT_LIST_HEAD(&u->transactions); + INIT_LIST_HEAD(&u->watches); init_waitqueue_head(&u->read_waitq); + + mutex_init(&u->reply_mutex); filp->private_data = u; @@ -202,11 +309,18 @@ static int xenbus_dev_release(struct ino { struct xenbus_dev_data *u = filp->private_data; struct xenbus_dev_transaction *trans, *tmp; + struct watch_adapter *watch, *tmp_watch; list_for_each_entry_safe(trans, tmp, &u->transactions, list) { xenbus_transaction_end(trans->handle, 1); list_del(&trans->list); kfree(trans); + } + + list_for_each_entry_safe(watch, tmp_watch, &u->watches, list) { + unregister_xenbus_watch(&watch->watch); + list_del(&watch->list); + free_watch_adapter(watch); } kfree(u); diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Mon Aug 07 18:00:22 2006 -0500 @@ -141,7 +141,9 @@ static int read_otherend_details(struct } if (strlen(xendev->otherend) == 0 || !xenbus_exists(XBT_NIL, xendev->otherend, "")) { - xenbus_dev_fatal(xendev, -ENOENT, "missing other end from %s", + xenbus_dev_fatal(xendev, -ENOENT, + "unable to read other end from %s. " + "missing or inaccessible.", xendev->nodename); free_otherend_details(xendev); return -ENOENT; diff -r 61204c1d740e -r 87cefa5f7c5e 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 Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h Mon Aug 07 18:00:22 2006 -0500 @@ -187,16 +187,14 @@ MULTI_update_va_mapping( mcl->args[0] = va; #if defined(CONFIG_X86_64) mcl->args[1] = new_val.pte; - mcl->args[2] = flags; #elif defined(CONFIG_X86_PAE) mcl->args[1] = new_val.pte_low; mcl->args[2] = new_val.pte_high; - mcl->args[3] = flags; #else mcl->args[1] = new_val.pte_low; mcl->args[2] = 0; - mcl->args[3] = flags; -#endif +#endif + mcl->args[MULTI_UVMFLAGS_INDEX] = flags; } static inline void @@ -208,19 +206,15 @@ MULTI_update_va_mapping_otherdomain( mcl->args[0] = va; #if defined(CONFIG_X86_64) mcl->args[1] = new_val.pte; - mcl->args[2] = flags; - mcl->args[3] = domid; #elif defined(CONFIG_X86_PAE) mcl->args[1] = new_val.pte_low; mcl->args[2] = new_val.pte_high; - mcl->args[3] = flags; - mcl->args[4] = domid; #else mcl->args[1] = new_val.pte_low; mcl->args[2] = 0; - mcl->args[3] = flags; - mcl->args[4] = domid; -#endif +#endif + mcl->args[MULTI_UVMFLAGS_INDEX] = flags; + mcl->args[MULTI_UVMDOMID_INDEX] = domid; } #endif /* __HYPERVISOR_H__ */ diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/mmu.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/mmu.h Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/mmu.h Mon Aug 07 18:00:22 2006 -0500 @@ -12,6 +12,9 @@ typedef struct { int size; struct semaphore sem; void *ldt; +#ifdef CONFIG_XEN + int has_foreign_mappings; +#endif } mm_context_t; /* mm/memory.c:exit_mmap hook */ diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/include/asm-i386/spinlock.h --- a/linux-2.6-xen-sparse/include/asm-i386/spinlock.h Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/include/asm-i386/spinlock.h Mon Aug 07 18:00:22 2006 -0500 @@ -23,7 +23,7 @@ (*(volatile signed char *)(&(x)->slock) <= 0) #define __raw_spin_lock_string \ - "\n1:\n" \ + "\n1:\t" \ LOCK \ "decb %0\n\t" \ "jns 3f\n" \ @@ -35,7 +35,7 @@ "3:\n\t" #define __raw_spin_lock_string_flags \ - "\n1:\n" \ + "\n1:\t" \ LOCK \ "decb %0\n\t" \ "jns 4f\n\t" \ diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/mmu.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/mmu.h Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/mmu.h Mon Aug 07 18:00:22 2006 -0500 @@ -17,6 +17,7 @@ typedef struct { struct semaphore sem; #ifdef CONFIG_XEN unsigned pinned:1; + unsigned has_foreign_mappings:1; struct list_head unpinned; #endif } mm_context_t; diff -r 61204c1d740e -r 87cefa5f7c5e linux-2.6-xen-sparse/include/xen/pcifront.h --- a/linux-2.6-xen-sparse/include/xen/pcifront.h Thu Jul 27 20:07:02 2006 -0400 +++ b/linux-2.6-xen-sparse/include/xen/pcifront.h Mon Aug 07 18:00:22 2006 -0500 @@ -11,16 +11,30 @@ #ifdef __KERNEL__ +#ifndef __ia64__ + struct pcifront_device; +struct pci_bus; struct pcifront_sd { int domain; struct pcifront_device *pdev; }; -struct pci_bus; +static inline struct pcifront_device * +pcifront_get_pdev(struct pcifront_sd *sd) +{ + return sd->pdev; +} -#ifdef CONFIG_PCI_DOMAINS +static inline void pcifront_init_sd(struct pcifront_sd *sd, int domain, + struct pcifront_device *pdev) +{ + sd->domain = domain; + sd->pdev = pdev; +} + +#if defined(CONFIG_PCI_DOMAINS) static inline int pci_domain_nr(struct pci_bus *bus) { struct pcifront_sd *sd = bus->sysdata; @@ -32,6 +46,30 @@ static inline int pci_proc_domain(struct } #endif /* CONFIG_PCI_DOMAINS */ +#else /* __ia64__ */ + +#include <asm/pci.h> +#define pcifront_sd pci_controller + +static inline struct pcifront_device * +pcifront_get_pdev(struct pcifront_sd *sd) +{ + return (struct pcifront_device *)sd->platform_data; +} + +static inline void pcifront_init_sd(struct pcifront_sd *sd, int domain, + struct pcifront_device *pdev) +{ + sd->segment = domain; + sd->acpi_handle = NULL; + sd->iommu = NULL; + sd->windows = 0; + sd->window = NULL; + sd->platform_data = pdev; +} + +#endif /* __ia64__ */ + extern spinlock_t pci_bus_lock; #endif /* __KERNEL__ */ diff -r 61204c1d740e -r 87cefa5f7c5e tools/blktap/drivers/Makefile --- a/tools/blktap/drivers/Makefile Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/blktap/drivers/Makefile Mon Aug 07 18:00:22 2006 -0500 @@ -33,9 +33,7 @@ LIBS += -lz LIBS += -lz LIBS += -L$(XEN_XENSTORE) -lxenstore -AIOLIBS := -L $(LIBAIO_DIR) -AIOLIBS += -laio -AIOLIBS += -static +AIOLIBS := $(LIBAIO_DIR)/libaio.a BLK-OBJS := block-aio.o BLK-OBJS += block-sync.o @@ -49,21 +47,18 @@ LINUX_ROOT := $(wildcard $(XEN_ROOT)/lin LINUX_ROOT := $(wildcard $(XEN_ROOT)/linux-2.6.*-xen-sparse) -blktapctrl: +blktapctrl: blktapctrl.c $(CC) $(CFLAGS) -o blktapctrl $(LIBS) blktapctrl.c -tapdisk: $(BLK-OBJS) +tapdisk: $(BLK-OBJS) tapdisk.c $(CC) $(CFLAGS) -o tapdisk $(BLK-OBJS) tapdisk.c \ $(AIOLIBS) $(LIBS) +.PHONY: qcow-util +qcow-util: img2qcow qcow2raw qcow-create -qcow-util: $(BLK-OBJS) - $(CC) $(CFLAGS) -o img2qcow $(BLK-OBJS) img2qcow.c \ - $(AIOLIBS) $(LIBS) - $(CC) $(CFLAGS) -o qcow2raw $(BLK-OBJS) qcow2raw.c \ - $(AIOLIBS) $(LIBS) - $(CC) $(CFLAGS) -o qcow-create $(BLK-OBJS) qcow-create.c \ - $(AIOLIBS) $(LIBS) +img2qcow qcow2raw qcow-create: %: $(BLK-OBJS) + $(CC) $(CFLAGS) -o $* $(BLK-OBJS) $*.c $(AIOLIBS) $(LIBS) install: all $(INSTALL_PROG) $(IBIN) $(QCOW_UTIL) $(DESTDIR)$(INSTALL_DIR) diff -r 61204c1d740e -r 87cefa5f7c5e tools/blktap/drivers/blktapctrl.c --- a/tools/blktap/drivers/blktapctrl.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/blktap/drivers/blktapctrl.c Mon Aug 07 18:00:22 2006 -0500 @@ -61,6 +61,7 @@ #define MSG_SIZE 4096 #define MAX_TIMEOUT 10 #define MAX_RAND_VAL 0xFFFF +#define MAX_ATTEMPTS 10 int run = 1; int max_timeout = MAX_TIMEOUT; @@ -626,13 +627,14 @@ int main(int argc, char *argv[]) { char *devname; tapdev_info_t *ctlinfo; - int tap_pfd, store_pfd, xs_fd, ret, timeout, pfd_count; + int tap_pfd, store_pfd, xs_fd, ret, timeout, pfd_count, count=0; struct xs_handle *h; struct pollfd pfd[NUM_POLL_FDS]; pid_t process; __init_blkif(); openlog("BLKTAPCTRL", LOG_CONS|LOG_ODELAY, LOG_DAEMON); + daemon(0,0); print_drivers(); init_driver_list(); @@ -651,18 +653,28 @@ int main(int argc, char *argv[]) goto open_failed; } + retry: /* Set up store connection and watch. */ h = xs_daemon_open(); if (h == NULL) { DPRINTF("xs_daemon_open failed -- " "is xenstore running?\n"); - goto open_failed; + if (count < MAX_ATTEMPTS) { + count++; + sleep(2); + goto retry; + } else goto open_failed; } ret = add_blockdevice_probe_watch(h, "Domain-0"); if (ret != 0) { - DPRINTF("adding device probewatch\n"); - goto open_failed; + DPRINTF("Failed adding device probewatch\n"); + if (count < MAX_ATTEMPTS) { + count++; + sleep(2); + xs_daemon_close(h); + goto retry; + } else goto open_failed; } ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE ); @@ -691,6 +703,7 @@ int main(int argc, char *argv[]) } } + xs_daemon_close(h); ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_PASSTHROUGH ); close(ctlfd); closelog(); diff -r 61204c1d740e -r 87cefa5f7c5e tools/blktap/lib/Makefile --- a/tools/blktap/lib/Makefile Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/blktap/lib/Makefile Mon Aug 07 18:00:22 2006 -0500 @@ -35,10 +35,14 @@ IBINS := LIB = libblktap.a libblktap.so.$(MAJOR).$(MINOR) +.PHONY: all all: build -build: - $(MAKE) libblktap +.PHONY: build +build: libblktap.a + +.PHONY: libblktap +libblktap: libblktap.a install: all $(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR) @@ -51,13 +55,13 @@ clean: clean: rm -rf *.a *.so* *.o *.rpm $(LIB) *~ $(DEPS) xen TAGS -libblktap: $(OBJS) +libblktap.a: $(OBJS) $(CC) $(CFLAGS) -Wl,-soname -Wl,$(SONAME) -shared \ -L$(XEN_XENSTORE) -l xenstore \ -o libblktap.so.$(MAJOR).$(MINOR) $^ $(LIBS) ln -sf libblktap.so.$(MAJOR).$(MINOR) libblktap.so.$(MAJOR) - ln -sf libblktap.so.$(MAJOR) $@.so - ar rc libblktap.a $@.so + ln -sf libblktap.so.$(MAJOR) libblktap.so + ar rc $@ libblktap.so .PHONY: TAGS all build clean install libblktap diff -r 61204c1d740e -r 87cefa5f7c5e tools/examples/block --- a/tools/examples/block Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/examples/block Mon Aug 07 18:00:22 2006 -0500 @@ -239,8 +239,11 @@ case "$command" in exit 0 fi - p=$(xenstore_read "$XENBUS_PATH/params") - mode=$(xenstore_read "$XENBUS_PATH/mode") + if [ -n "$t" ] + then + p=$(xenstore_read "$XENBUS_PATH/params") + mode=$(xenstore_read "$XENBUS_PATH/mode") + fi case $t in phy) @@ -370,6 +373,13 @@ mount it read-write in a guest domain." release_lock "block" exit 0 ;; + + "") + claim_lock "block" + success + echo happy gun \"$t\" >>/tmp/block.$$ + release_lock "block" + ;; esac ;; @@ -384,6 +394,10 @@ mount it read-write in a guest domain." losetup -d "$node" exit 0 ;; + + "") + exit 0 + ;; esac ;; diff -r 61204c1d740e -r 87cefa5f7c5e tools/examples/xmexample.hvm --- a/tools/examples/xmexample.hvm Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/examples/xmexample.hvm Mon Aug 07 18:00:22 2006 -0500 @@ -66,7 +66,7 @@ vif = [ 'type=ioemu, bridge=xenbr0' ] # and MODE is r for read-only, w for read-write. #disk = [ 'phy:hda1,hda1,r' ] -disk = [ 'file:/var/images/min-el3-i386.img,ioemu:hda,w' ] +disk = [ 'file:/var/images/min-el3-i386.img,hda,w', ',hdc:cdrom,r' ] #---------------------------------------------------------------------------- # Configure the behaviour when a domain exits. There are three 'reasons' @@ -111,10 +111,6 @@ device_model = '/usr/' + arch_libdir + ' device_model = '/usr/' + arch_libdir + '/xen/bin/qemu-dm' #----------------------------------------------------------------------------- -# Disk image for -#cdrom= - -#----------------------------------------------------------------------------- # boot on floppy (a), hard disk (c) or CD-ROM (d) #boot=[a|c|d] #----------------------------------------------------------------------------- @@ -153,8 +149,8 @@ serial='pty' #----------------------------------------------------------------------------- -# enable audio support -#audio=1 +# enable sound card support, [sb16|es1370|all|..,..], default none +#soundhw='sb16' #----------------------------------------------------------------------------- diff -r 61204c1d740e -r 87cefa5f7c5e tools/firmware/Makefile --- a/tools/firmware/Makefile Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/firmware/Makefile Mon Aug 07 18:00:22 2006 -0500 @@ -30,7 +30,7 @@ all: .PHONY: install install: all [ -d $(INSTALL_DIR) ] || install -d -m0755 $(INSTALL_DIR) - [ ! -e $(TARGET) ] || install -m0644 $(TARGET) $(INSTALL_DIR) + install -m0644 $(TARGET) $(INSTALL_DIR) .PHONY: clean clean: diff -r 61204c1d740e -r 87cefa5f7c5e tools/firmware/acpi/acpi_dsdt.asl --- a/tools/firmware/acpi/acpi_dsdt.asl Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/firmware/acpi/acpi_dsdt.asl Mon Aug 07 18:00:22 2006 -0500 @@ -16,7 +16,7 @@ //* Place - Suite 330, Boston, MA 02111-1307 USA. //** -//** DSDT for Xen with Qemu device model +//** DSDT for Xen with Qemu device model //** //** @@ -50,21 +50,36 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, }) - Name(PICD, 0) - - Method(_PIC, 1) { + Name(PICD, 0) + + Method(_PIC, 1) { - Store(Arg0, PICD) - } + Store(Arg0, PICD) + } Scope (\_SB) { - Device (PCI0) + /* Fix HCT test for 0x400 pci memory - need to report low 640 MB mem as motherboard resource */ + + Device(MEM0) { + Name(_HID, EISAID("PNP0C02")) + Name(_CRS, ResourceTemplate() { + QWordMemory (ResourceConsumer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, + 0x00000000, + 0x00000000, + 0x0009ffff, + 0x00000000, + 0x000a0000) + } + ) + } + + Device (PCI0) { - Name (_HID, EisaId ("PNP0A03")) - Name (_UID, 0x00) - Name (_ADR, 0x00) - Name (_BBN, 0x00) - OperationRegion (PIRP, PCI_Config, 0x3c, 0x10) + Name (_HID, EisaId ("PNP0A03")) + Name (_UID, 0x00) + Name (_ADR, 0x00) + Name (_BBN, 0x00) + OperationRegion (PIRP, PCI_Config, 0x3c, 0x10) Field(PIRP, ByteAcc, NoLock, Preserve){ IRQ3,3, IRQ5,5, @@ -79,7 +94,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, Name (PRT0, ResourceTemplate () { - /* bus number is from 0 - 255*/ + /* bus number is from 0 - 255*/ WordBusNumber (ResourceConsumer, MinFixed, MaxFixed, SubDecode, 0x0000, 0x0000, @@ -122,7 +137,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, 0x00000000, 0x00030000) - /* reserve what device model consumed for PCI VGA device */ + /* reserve what device model consumed for PCI VGA device */ DWordMemory (ResourceConsumer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, 0x00000000, @@ -146,9 +161,9 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, }) Return (PRT0) } - Name(BUFA, ResourceTemplate() { + Name(BUFA, ResourceTemplate() { IRQ(Level, ActiveLow, Shared) { - 3,4,5,6,7,10,11,12,14,15} + 3,4,5,6,7,10,11,12,14,15} }) Name(BUFB, Buffer(){ @@ -156,7 +171,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, 0x79, 0}) CreateWordField(BUFB, 0x01, IRQV) - + Name(BUFC, Buffer(){ 5, 7, 10, 11 }) @@ -165,17 +180,17 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, CreateByteField(BUFC, 0x01, PIQB) CreateByteField(BUFC, 0x01, PIQC) CreateByteField(BUFC, 0x01, PIQD) - - Device(LNKA) { - Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link + + Device(LNKA) { + Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link Name(_UID, 1) Method(_STA, 0) { And(PIRA, 0x80, Local0) If(LEqual(Local0, 0x80)) { - Return(0x09) + Return(0x09) } Else { - Return(0x0B) + Return(0x0B) } } @@ -189,34 +204,34 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, } Method(_CRS) { - And(PIRB, 0x0f, Local0) - ShiftLeft(0x1, Local0, IRQV) - Return(BUFB) + And(PIRB, 0x0f, Local0) + ShiftLeft(0x1, Local0, IRQV) + Return(BUFB) } Method(_SRS, 1) { - CreateWordField(ARG0, 0x01, IRQ1) - FindSetRightBit(IRQ1, Local0) - Decrement(Local0) - Store(Local0, PIRA) + CreateWordField(ARG0, 0x01, IRQ1) + FindSetRightBit(IRQ1, Local0) + Decrement(Local0) + Store(Local0, PIRA) } // Method(_SRS) } - Device(LNKB) { - Name(_HID, EISAID("PNP0C0F")) + Device(LNKB){ + Name(_HID, EISAID("PNP0C0F")) Name(_UID, 2) Method(_STA, 0) { And(PIRB, 0x80, Local0) If(LEqual(Local0, 0x80)) { - Return(0x09) + Return(0x09) } Else { - Return(0x0B) + Return(0x0B) } } Method(_PRS) { - Return(BUFA) + Return(BUFA) } // Method(_PRS) Method(_DIS) { @@ -225,35 +240,35 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, } Method(_CRS) { - And(PIRB, 0x0f, Local0) - ShiftLeft(0x1, Local0, IRQV) - Return(BUFB) + And(PIRB, 0x0f, Local0) + ShiftLeft(0x1, Local0, IRQV) + Return(BUFB) } // Method(_CRS) Method(_SRS, 1) { - CreateWordField(ARG0, 0x01, IRQ1) - FindSetRightBit(IRQ1, Local0) - Decrement(Local0) - Store(Local0, PIRB) + CreateWordField(ARG0, 0x01, IRQ1) + FindSetRightBit(IRQ1, Local0) + Decrement(Local0) + Store(Local0, PIRB) } // Method(_SRS) } - Device(LNKC) { - Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link + Device(LNKC){ + Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link Name(_UID, 3) Method(_STA, 0) { - And(PIRC, 0x80, Local0) + And(PIRC, 0x80, Local0) If(LEqual(Local0, 0x80)) { - Return(0x09) + Return(0x09) } Else { - Return(0x0B) - } - } - - Method(_PRS) { - Return(BUFA) - } // Method(_PRS) + Return(0x0B) + } + } + + Method(_PRS) { + Return(BUFA) + } // Method(_PRS) Method(_DIS) { @@ -261,91 +276,89 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, } Method(_CRS) { - And(PIRC, 0x0f, Local0) - ShiftLeft(0x1, Local0, IRQV) - Return(BUFB) + And(PIRC, 0x0f, Local0) + ShiftLeft(0x1, Local0, IRQV) + Return(BUFB) } // Method(_CRS) Method(_SRS, 1) { - CreateWordField(ARG0, 0x01, IRQ1) - FindSetRightBit(IRQ1, Local0) - Decrement(Local0) - Store(Local0, PIRC) + CreateWordField(ARG0, 0x01, IRQ1) + FindSetRightBit(IRQ1, Local0) + Decrement(Local0) + Store(Local0, PIRC) } // Method(_SRS) } - Device(LNKD) { - Name(_HID, EISAID("PNP0C0F")) + Device(LNKD) { + Name(_HID, EISAID("PNP0C0F")) Name(_UID, 4) Method(_STA, 0) { And(PIRD, 0x80, Local0) If(LEqual(Local0, 0x80)) { - Return(0x09) + Return(0x09) } Else { - Return(0x0B) - } - } - - Method(_PRS) { - Return(BUFA) - } // Method(_PRS) + Return(0x0B) + } + } + + Method(_PRS) { + Return(BUFA) + } // Method(_PRS) Method(_DIS) { Or(PIRD, 0x80, PIRD) } Method(_CRS) { - And(PIRD, 0x0f, Local0) - ShiftLeft(0x1, Local0, IRQV) - Return(BUFB) + And(PIRD, 0x0f, Local0) + ShiftLeft(0x1, Local0, IRQV) + Return(BUFB) } // Method(_CRS) Method(_SRS, 1) { - CreateWordField(ARG0, 0x01, IRQ1) - FindSetRightBit(IRQ1, Local0) - Decrement(Local0) - Store(Local0, PIRD) + CreateWordField(ARG0, 0x01, IRQ1) + FindSetRightBit(IRQ1, Local0) + Decrement(Local0) + Store(Local0, PIRD) } // Method(_SRS) } Method(_PRT,0) { - If(PICD) {Return(PRTA)} - Return (PRTP) - } // end _PRT - - + If(PICD) {Return(PRTA)} + Return (PRTP) + } // end _PRT + Name(PRTP, Package(){ - Package(){0x0000ffff, 0, \_SB.PCI0.LNKA, 0}, // Slot 1, INTA - Package(){0x0000ffff, 1, \_SB.PCI0.LNKB, 0}, // Slot 1, INTB - Package(){0x0000ffff, 2, \_SB.PCI0.LNKC, 0}, // Slot 1, INTC - Package(){0x0000ffff, 3, \_SB.PCI0.LNKD, 0}, // Slot 1, INTD - - Package(){0x0001ffff, 0, \_SB.PCI0.LNKB, 0}, // Slot 2, INTB - Package(){0x0001ffff, 1, \_SB.PCI0.LNKC, 0}, // Slot 2, INTC - Package(){0x0001ffff, 2, \_SB.PCI0.LNKD, 0}, // Slot 2, INTD - Package(){0x0001ffff, 3, \_SB.PCI0.LNKA, 0}, // Slot 2, INTA + Package(){0x0000ffff, 0, \_SB.PCI0.LNKA, 0}, // Slot 1, INTA + Package(){0x0000ffff, 1, \_SB.PCI0.LNKB, 0}, // Slot 1, INTB + Package(){0x0000ffff, 2, \_SB.PCI0.LNKC, 0}, // Slot 1, INTC + Package(){0x0000ffff, 3, \_SB.PCI0.LNKD, 0}, // Slot 1, INTD + + Package(){0x0001ffff, 0, \_SB.PCI0.LNKB, 0}, // Slot 2, INTB + Package(){0x0001ffff, 1, \_SB.PCI0.LNKC, 0}, // Slot 2, INTC + Package(){0x0001ffff, 2, \_SB.PCI0.LNKD, 0}, // Slot 2, INTD + Package(){0x0001ffff, 3, \_SB.PCI0.LNKA, 0}, // Slot 2, INTA - Package(){0x0002ffff, 0, \_SB.PCI0.LNKC, 0}, // Slot 3, INTC - Package(){0x0002ffff, 1, \_SB.PCI0.LNKD, 0}, // Slot 3, INTD - Package(){0x0002ffff, 2, \_SB.PCI0.LNKA, 0}, // Slot 3, INTA - Package(){0x0002ffff, 3, \_SB.PCI0.LNKB, 0}, // Slot 3, INTB + Package(){0x0002ffff, 0, \_SB.PCI0.LNKC, 0}, // Slot 3, INTC + Package(){0x0002ffff, 1, \_SB.PCI0.LNKD, 0}, // Slot 3, INTD + Package(){0x0002ffff, 2, \_SB.PCI0.LNKA, 0}, // Slot 3, INTA + Package(){0x0002ffff, 3, \_SB.PCI0.LNKB, 0}, // Slot 3, INTB - Package(){0x0003ffff, 0, \_SB.PCI0.LNKD, 0}, // Slot 2, INTD - Package(){0x0003ffff, 1, \_SB.PCI0.LNKA, 0}, // Slot 2, INTA - Package(){0x0003ffff, 2, \_SB.PCI0.LNKB, 0}, // Slot 2, INTB - Package(){0x0003ffff, 3, \_SB.PCI0.LNKC, 0}, // Slot 2, INTC + Package(){0x0003ffff, 0, \_SB.PCI0.LNKD, 0}, // Slot 2, INTD + Package(){0x0003ffff, 1, \_SB.PCI0.LNKA, 0}, // Slot 2, INTA + Package(){0x0003ffff, 2, \_SB.PCI0.LNKB, 0}, // Slot 2, INTB + Package(){0x0003ffff, 3, \_SB.PCI0.LNKC, 0}, // Slot 2, INTC } ) - Name(PRTA, Package(){ - Package(){0x0001ffff, 0, 0, 5}, // Device 1, INTA - - Package(){0x0002ffff, 0, 0, 7}, // Device 2, INTA + Name(PRTA, Package(){ + Package(){0x0001ffff, 0, 0, 5}, // Device 1, INTA + + Package(){0x0002ffff, 0, 0, 7}, // Device 2, INTA - Package(){0x0003ffff, 0, 0, 10}, // Device 3, INTA - - Package(){0x0003ffff, 0, 0, 11}, // Device 4, INTA - + Package(){0x0003ffff, 0, 0, 10}, // Device 3, INTA + + Package(){0x0004ffff, 0, 0, 11}, // Device 4, INTA } ) @@ -354,22 +367,22 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, { Name (_ADR, 0x00000000) /* device id, PCI bus num, ... */ - OperationRegion(PIRQ, PCI_Config, 0x60, 0x4) + OperationRegion(PIRQ, PCI_Config, 0x60, 0x4) Scope(\) { - Field (\_SB.PCI0.ISA.PIRQ, ByteAcc, NoLock, Preserve) { + Field (\_SB.PCI0.ISA.PIRQ, ByteAcc, NoLock, Preserve) { PIRA, 8, PIRB, 8, PIRC, 8, PIRD, 8 } - } + } Device (SYSR) { Name (_HID, EisaId ("PNP0C02")) Name (_UID, 0x01) Name (CRS, ResourceTemplate () { - /* TODO: list hidden resources */ + /* TODO: list hidden resources */ IO (Decode16, 0x0010, 0x0010, 0x00, 0x10) IO (Decode16, 0x0022, 0x0022, 0x00, 0x0C) IO (Decode16, 0x0030, 0x0030, 0x00, 0x10) @@ -417,7 +430,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, IO (Decode16, 0x0089, 0x0089, 0x00, 0x03) IO (Decode16, 0x008F, 0x008F, 0x00, 0x01) IO (Decode16, 0x00C0, 0x00C0, 0x00, 0x20) - IO (Decode16, 0x0480, 0x0480, 0x00, 0x10) + IO (Decode16, 0x0480, 0x0480, 0x00, 0x10) }) } diff -r 61204c1d740e -r 87cefa5f7c5e tools/firmware/acpi/acpi_dsdt.c --- a/tools/firmware/acpi/acpi_dsdt.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/firmware/acpi/acpi_dsdt.c Mon Aug 07 18:00:22 2006 -0500 @@ -5,15 +5,15 @@ * Copyright (C) 2000 - 2005 Intel Corporation * Supports ACPI Specification Revision 3.0 * - * Compilation of "acpi_dsdt.asl" - Mon Jun 12 22:33:41 2006 + * Compilation of "acpi_dsdt.asl" - Thu Aug 3 11:05:15 2006 * * C source code output * */ unsigned char AmlCode[] = { - 0x44,0x53,0x44,0x54,0xC3,0x08,0x00,0x00, /* 00000000 "DSDT...." */ - 0x01,0x0C,0x49,0x4E,0x54,0x45,0x4C,0x00, /* 00000008 "..INTEL." */ + 0x44,0x53,0x44,0x54,0x0E,0x09,0x00,0x00, /* 00000000 "DSDT...." */ + 0x01,0x03,0x49,0x4E,0x54,0x45,0x4C,0x00, /* 00000008 "..INTEL." */ 0x69,0x6E,0x74,0x2D,0x78,0x65,0x6E,0x00, /* 00000010 "int-xen." */ 0xD6,0x07,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ 0x13,0x05,0x05,0x20,0x08,0x50,0x4D,0x42, /* 00000020 "... .PMB" */ @@ -34,264 +34,273 @@ unsigned char AmlCode[] = 0x12,0x08,0x04,0x0A,0x07,0x0A,0x07,0x00, /* 00000098 "........" */ 0x00,0x08,0x50,0x49,0x43,0x44,0x00,0x14, /* 000000A0 "..PICD.." */ 0x0C,0x5F,0x50,0x49,0x43,0x01,0x70,0x68, /* 000000A8 "._PIC.ph" */ - 0x50,0x49,0x43,0x44,0x10,0x4E,0x80,0x5F, /* 000000B0 "PICD.N._" */ - 0x53,0x42,0x5F,0x5B,0x82,0x46,0x80,0x50, /* 000000B8 "SB_[.F.P" */ - 0x43,0x49,0x30,0x08,0x5F,0x48,0x49,0x44, /* 000000C0 "CI0._HID" */ - 0x0C,0x41,0xD0,0x0A,0x03,0x08,0x5F,0x55, /* 000000C8 ".A...._U" */ - 0x49,0x44,0x00,0x08,0x5F,0x41,0x44,0x52, /* 000000D0 "ID.._ADR" */ - 0x00,0x08,0x5F,0x42,0x42,0x4E,0x00,0x5B, /* 000000D8 ".._BBN.[" */ - 0x80,0x50,0x49,0x52,0x50,0x02,0x0A,0x3C, /* 000000E0 ".PIRP..<" */ - 0x0A,0x10,0x5B,0x81,0x24,0x50,0x49,0x52, /* 000000E8 "..[.$PIR" */ - 0x50,0x01,0x49,0x52,0x51,0x33,0x03,0x49, /* 000000F0 "P.IRQ3.I" */ - 0x52,0x51,0x35,0x05,0x49,0x52,0x51,0x37, /* 000000F8 "RQ5.IRQ7" */ - 0x07,0x49,0x52,0x51,0x39,0x09,0x49,0x52, /* 00000100 ".IRQ9.IR" */ - 0x51,0x41,0x0A,0x49,0x52,0x51,0x42,0x0B, /* 00000108 "QA.IRQB." */ - 0x14,0x48,0x0D,0x5F,0x43,0x52,0x53,0x00, /* 00000110 ".H._CRS." */ - 0x08,0x50,0x52,0x54,0x30,0x11,0x46,0x0C, /* 00000118 ".PRT0.F." */ - 0x0A,0xC2,0x88,0x0D,0x00,0x02,0x0F,0x00, /* 00000120 "........" */ - 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00, /* 00000128 "........" */ - 0x00,0x01,0x47,0x01,0xF8,0x0C,0xF8,0x0C, /* 00000130 "..G....." */ - 0x01,0x08,0x88,0x0D,0x00,0x01,0x0C,0x03, /* 00000138 "........" */ - 0x00,0x00,0x00,0x00,0xF7,0x0C,0x00,0x00, /* 00000140 "........" */ - 0xF8,0x0C,0x88,0x0D,0x00,0x01,0x0C,0x03, /* 00000148 "........" */ - 0x00,0x00,0x00,0x0D,0xFF,0x0F,0x00,0x00, /* 00000150 "........" */ - 0x00,0x03,0x88,0x0D,0x00,0x01,0x0D,0x03, /* 00000158 "........" */ - 0x00,0x00,0x00,0xC0,0x1F,0xC0,0x00,0x00, /* 00000160 "........" */ - 0x20,0x00,0x88,0x0D,0x00,0x01,0x0D,0x03, /* 00000168 " ......." */ - 0x00,0x00,0x20,0xC0,0x3F,0xC0,0x00,0x00, /* 00000170 ".. .?..." */ - 0x10,0x00,0x87,0x17,0x00,0x00,0x0C,0x02, /* 00000178 "........" */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00, /* 00000180 "........" */ - 0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00, /* 00000188 "........" */ - 0x00,0x00,0x03,0x00,0x87,0x17,0x00,0x00, /* 00000190 "........" */ - 0x0D,0x03,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000198 "........" */ - 0x00,0xF0,0xFF,0xFF,0xFF,0xF1,0x00,0x00, /* 000001A0 "........" */ - 0x00,0x00,0x00,0x00,0x00,0x02,0x87,0x17, /* 000001A8 "........" */ - 0x00,0x00,0x0D,0x03,0x00,0x00,0x00,0x00, /* 000001B0 "........" */ - 0x00,0x00,0x00,0xF2,0xFF,0x0F,0x00,0xF2, /* 000001B8 "........" */ - 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00, /* 000001C0 "........" */ - 0x87,0x17,0x00,0x00,0x0D,0x03,0x00,0x00, /* 000001C8 "........" */ - 0x00,0x00,0x00,0x10,0x00,0xF2,0x1F,0x10, /* 000001D0 "........" */ - 0x00,0xF2,0x00,0x00,0x00,0x00,0x20,0x00, /* 000001D8 "...... ." */ - 0x00,0x00,0x79,0x00,0xA4,0x50,0x52,0x54, /* 000001E0 "..y..PRT" */ - 0x30,0x08,0x42,0x55,0x46,0x41,0x11,0x09, /* 000001E8 "0.BUFA.." */ - 0x0A,0x06,0x23,0xF8,0xDC,0x18,0x79,0x00, /* 000001F0 "..#...y." */ - 0x08,0x42,0x55,0x46,0x42,0x11,0x09,0x0A, /* 000001F8 ".BUFB..." */ - 0x06,0x23,0x00,0x00,0x18,0x79,0x00,0x8B, /* 00000200 ".#...y.." */ - 0x42,0x55,0x46,0x42,0x01,0x49,0x52,0x51, /* 00000208 "BUFB.IRQ" */ - 0x56,0x08,0x42,0x55,0x46,0x43,0x11,0x07, /* 00000210 "V.BUFC.." */ - 0x0A,0x04,0x05,0x07,0x0A,0x0B,0x8C,0x42, /* 00000218 ".......B" */ - 0x55,0x46,0x43,0x01,0x50,0x49,0x51,0x41, /* 00000220 "UFC.PIQA" */ - 0x8C,0x42,0x55,0x46,0x43,0x01,0x50,0x49, /* 00000228 ".BUFC.PI" */ - 0x51,0x42,0x8C,0x42,0x55,0x46,0x43,0x01, /* 00000230 "QB.BUFC." */ - 0x50,0x49,0x51,0x43,0x8C,0x42,0x55,0x46, /* 00000238 "PIQC.BUF" */ - 0x43,0x01,0x50,0x49,0x51,0x44,0x5B,0x82, /* 00000240 "C.PIQD[." */ - 0x48,0x08,0x4C,0x4E,0x4B,0x41,0x08,0x5F, /* 00000248 "H.LNKA._" */ - 0x48,0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F, /* 00000250 "HID.A..." */ - 0x08,0x5F,0x55,0x49,0x44,0x01,0x14,0x1C, /* 00000258 "._UID..." */ - 0x5F,0x53,0x54,0x41,0x00,0x7B,0x50,0x49, /* 00000260 "_STA.{PI" */ - 0x52,0x41,0x0A,0x80,0x60,0xA0,0x08,0x93, /* 00000268 "RA..`..." */ - 0x60,0x0A,0x80,0xA4,0x0A,0x09,0xA1,0x04, /* 00000270 "`......." */ - 0xA4,0x0A,0x0B,0x14,0x0B,0x5F,0x50,0x52, /* 00000278 "....._PR" */ - 0x53,0x00,0xA4,0x42,0x55,0x46,0x41,0x14, /* 00000280 "S..BUFA." */ - 0x11,0x5F,0x44,0x49,0x53,0x00,0x7D,0x50, /* 00000288 "._DIS.}P" */ - 0x49,0x52,0x41,0x0A,0x80,0x50,0x49,0x52, /* 00000290 "IRA..PIR" */ - 0x41,0x14,0x1A,0x5F,0x43,0x52,0x53,0x00, /* 00000298 "A.._CRS." */ - 0x7B,0x50,0x49,0x52,0x42,0x0A,0x0F,0x60, /* 000002A0 "{PIRB..`" */ - 0x79,0x01,0x60,0x49,0x52,0x51,0x56,0xA4, /* 000002A8 "y.`IRQV." */ - 0x42,0x55,0x46,0x42,0x14,0x1B,0x5F,0x53, /* 000002B0 "BUFB.._S" */ - 0x52,0x53,0x01,0x8B,0x68,0x01,0x49,0x52, /* 000002B8 "RS..h.IR" */ - 0x51,0x31,0x82,0x49,0x52,0x51,0x31,0x60, /* 000002C0 "Q1.IRQ1`" */ - 0x76,0x60,0x70,0x60,0x50,0x49,0x52,0x41, /* 000002C8 "v`p`PIRA" */ - 0x5B,0x82,0x49,0x08,0x4C,0x4E,0x4B,0x42, /* 000002D0 "[.I.LNKB" */ - 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 000002D8 "._HID.A." */ - 0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44,0x0A, /* 000002E0 "..._UID." */ - 0x02,0x14,0x1C,0x5F,0x53,0x54,0x41,0x00, /* 000002E8 "..._STA." */ - 0x7B,0x50,0x49,0x52,0x42,0x0A,0x80,0x60, /* 000002F0 "{PIRB..`" */ - 0xA0,0x08,0x93,0x60,0x0A,0x80,0xA4,0x0A, /* 000002F8 "...`...." */ - 0x09,0xA1,0x04,0xA4,0x0A,0x0B,0x14,0x0B, /* 00000300 "........" */ - 0x5F,0x50,0x52,0x53,0x00,0xA4,0x42,0x55, /* 00000308 "_PRS..BU" */ - 0x46,0x41,0x14,0x11,0x5F,0x44,0x49,0x53, /* 00000310 "FA.._DIS" */ - 0x00,0x7D,0x50,0x49,0x52,0x42,0x0A,0x80, /* 00000318 ".}PIRB.." */ - 0x50,0x49,0x52,0x42,0x14,0x1A,0x5F,0x43, /* 00000320 "PIRB.._C" */ - 0x52,0x53,0x00,0x7B,0x50,0x49,0x52,0x42, /* 00000328 "RS.{PIRB" */ - 0x0A,0x0F,0x60,0x79,0x01,0x60,0x49,0x52, /* 00000330 "..`y.`IR" */ - 0x51,0x56,0xA4,0x42,0x55,0x46,0x42,0x14, /* 00000338 "QV.BUFB." */ - 0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B,0x68, /* 00000340 "._SRS..h" */ - 0x01,0x49,0x52,0x51,0x31,0x82,0x49,0x52, /* 00000348 ".IRQ1.IR" */ - 0x51,0x31,0x60,0x76,0x60,0x70,0x60,0x50, /* 00000350 "Q1`v`p`P" */ - 0x49,0x52,0x42,0x5B,0x82,0x49,0x08,0x4C, /* 00000358 "IRB[.I.L" */ - 0x4E,0x4B,0x43,0x08,0x5F,0x48,0x49,0x44, /* 00000360 "NKC._HID" */ - 0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55, /* 00000368 ".A...._U" */ - 0x49,0x44,0x0A,0x03,0x14,0x1C,0x5F,0x53, /* 00000370 "ID...._S" */ - 0x54,0x41,0x00,0x7B,0x50,0x49,0x52,0x43, /* 00000378 "TA.{PIRC" */ - 0x0A,0x80,0x60,0xA0,0x08,0x93,0x60,0x0A, /* 00000380 "..`...`." */ - 0x80,0xA4,0x0A,0x09,0xA1,0x04,0xA4,0x0A, /* 00000388 "........" */ - 0x0B,0x14,0x0B,0x5F,0x50,0x52,0x53,0x00, /* 00000390 "..._PRS." */ - 0xA4,0x42,0x55,0x46,0x41,0x14,0x11,0x5F, /* 00000398 ".BUFA.._" */ - 0x44,0x49,0x53,0x00,0x7D,0x50,0x49,0x52, /* 000003A0 "DIS.}PIR" */ - 0x43,0x0A,0x80,0x50,0x49,0x52,0x43,0x14, /* 000003A8 "C..PIRC." */ - 0x1A,0x5F,0x43,0x52,0x53,0x00,0x7B,0x50, /* 000003B0 "._CRS.{P" */ - 0x49,0x52,0x43,0x0A,0x0F,0x60,0x79,0x01, /* 000003B8 "IRC..`y." */ - 0x60,0x49,0x52,0x51,0x56,0xA4,0x42,0x55, /* 000003C0 "`IRQV.BU" */ - 0x46,0x42,0x14,0x1B,0x5F,0x53,0x52,0x53, /* 000003C8 "FB.._SRS" */ - 0x01,0x8B,0x68,0x01,0x49,0x52,0x51,0x31, /* 000003D0 "..h.IRQ1" */ - 0x82,0x49,0x52,0x51,0x31,0x60,0x76,0x60, /* 000003D8 ".IRQ1`v`" */ - 0x70,0x60,0x50,0x49,0x52,0x43,0x5B,0x82, /* 000003E0 "p`PIRC[." */ - 0x49,0x08,0x4C,0x4E,0x4B,0x44,0x08,0x5F, /* 000003E8 "I.LNKD._" */ - 0x48,0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F, /* 000003F0 "HID.A..." */ - 0x08,0x5F,0x55,0x49,0x44,0x0A,0x04,0x14, /* 000003F8 "._UID..." */ - 0x1C,0x5F,0x53,0x54,0x41,0x00,0x7B,0x50, /* 00000400 "._STA.{P" */ - 0x49,0x52,0x44,0x0A,0x80,0x60,0xA0,0x08, /* 00000408 "IRD..`.." */ - 0x93,0x60,0x0A,0x80,0xA4,0x0A,0x09,0xA1, /* 00000410 ".`......" */ - 0x04,0xA4,0x0A,0x0B,0x14,0x0B,0x5F,0x50, /* 00000418 "......_P" */ - 0x52,0x53,0x00,0xA4,0x42,0x55,0x46,0x41, /* 00000420 "RS..BUFA" */ - 0x14,0x11,0x5F,0x44,0x49,0x53,0x00,0x7D, /* 00000428 ".._DIS.}" */ - 0x50,0x49,0x52,0x44,0x0A,0x80,0x50,0x49, /* 00000430 "PIRD..PI" */ - 0x52,0x44,0x14,0x1A,0x5F,0x43,0x52,0x53, /* 00000438 "RD.._CRS" */ - 0x00,0x7B,0x50,0x49,0x52,0x44,0x0A,0x0F, /* 00000440 ".{PIRD.." */ - 0x60,0x79,0x01,0x60,0x49,0x52,0x51,0x56, /* 00000448 "`y.`IRQV" */ - 0xA4,0x42,0x55,0x46,0x42,0x14,0x1B,0x5F, /* 00000450 ".BUFB.._" */ - 0x53,0x52,0x53,0x01,0x8B,0x68,0x01,0x49, /* 00000458 "SRS..h.I" */ - 0x52,0x51,0x31,0x82,0x49,0x52,0x51,0x31, /* 00000460 "RQ1.IRQ1" */ - 0x60,0x76,0x60,0x70,0x60,0x50,0x49,0x52, /* 00000468 "`v`p`PIR" */ - 0x44,0x14,0x16,0x5F,0x50,0x52,0x54,0x00, /* 00000470 "D.._PRT." */ - 0xA0,0x0A,0x50,0x49,0x43,0x44,0xA4,0x50, /* 00000478 "..PICD.P" */ - 0x52,0x54,0x41,0xA4,0x50,0x52,0x54,0x50, /* 00000480 "RTA.PRTP" */ - 0x08,0x50,0x52,0x54,0x50,0x12,0x43,0x0E, /* 00000488 ".PRTP.C." */ - 0x10,0x12,0x0B,0x04,0x0B,0xFF,0xFF,0x00, /* 00000490 "........" */ - 0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0B,0x04, /* 00000498 "LNKA...." */ - 0x0B,0xFF,0xFF,0x01,0x4C,0x4E,0x4B,0x42, /* 000004A0 "....LNKB" */ - 0x00,0x12,0x0C,0x04,0x0B,0xFF,0xFF,0x0A, /* 000004A8 "........" */ - 0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0C, /* 000004B0 ".LNKC..." */ - 0x04,0x0B,0xFF,0xFF,0x0A,0x03,0x4C,0x4E, /* 000004B8 "......LN" */ - 0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 000004C0 "KD......" */ - 0xFF,0x01,0x00,0x00,0x4C,0x4E,0x4B,0x42, /* 000004C8 "....LNKB" */ - 0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x01, /* 000004D0 "........" */ - 0x00,0x01,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 000004D8 "..LNKC.." */ - 0x0E,0x04,0x0C,0xFF,0xFF,0x01,0x00,0x0A, /* 000004E0 "........" */ - 0x02,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0E, /* 000004E8 ".LNKD..." */ - 0x04,0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x03, /* 000004F0 "........" */ - 0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04, /* 000004F8 "LNKA...." */ - 0x0C,0xFF,0xFF,0x02,0x00,0x00,0x4C,0x4E, /* 00000500 "......LN" */ - 0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 00000508 "KC......" */ - 0xFF,0x02,0x00,0x01,0x4C,0x4E,0x4B,0x44, /* 00000510 "....LNKD" */ - 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x02, /* 00000518 "........" */ - 0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x41,0x00, /* 00000520 "...LNKA." */ - 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x02,0x00, /* 00000528 "........" */ - 0x0A,0x03,0x4C,0x4E,0x4B,0x42,0x00,0x12, /* 00000530 "..LNKB.." */ - 0x0D,0x04,0x0C,0xFF,0xFF,0x03,0x00,0x00, /* 00000538 "........" */ - 0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04, /* 00000540 "LNKD...." */ - 0x0C,0xFF,0xFF,0x03,0x00,0x01,0x4C,0x4E, /* 00000548 "......LN" */ - 0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000550 "KA......" */ - 0xFF,0x03,0x00,0x0A,0x02,0x4C,0x4E,0x4B, /* 00000558 ".....LNK" */ - 0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000560 "B......." */ - 0x03,0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x43, /* 00000568 "....LNKC" */ - 0x00,0x08,0x50,0x52,0x54,0x41,0x12,0x32, /* 00000570 "..PRTA.2" */ - 0x04,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x01, /* 00000578 "........" */ - 0x00,0x00,0x00,0x0A,0x05,0x12,0x0B,0x04, /* 00000580 "........" */ - 0x0C,0xFF,0xFF,0x02,0x00,0x00,0x00,0x0A, /* 00000588 "........" */ - 0x07,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x03, /* 00000590 "........" */ - 0x00,0x00,0x00,0x0A,0x0A,0x12,0x0B,0x04, /* 00000598 "........" */ - 0x0C,0xFF,0xFF,0x03,0x00,0x00,0x00,0x0A, /* 000005A0 "........" */ - 0x0B,0x5B,0x82,0x48,0x31,0x49,0x53,0x41, /* 000005A8 ".[.H1ISA" */ - 0x5F,0x08,0x5F,0x41,0x44,0x52,0x00,0x5B, /* 000005B0 "_._ADR.[" */ - 0x80,0x50,0x49,0x52,0x51,0x02,0x0A,0x60, /* 000005B8 ".PIRQ..`" */ - 0x0A,0x04,0x10,0x2E,0x5C,0x00,0x5B,0x81, /* 000005C0 "....\.[." */ - 0x29,0x5C,0x2F,0x04,0x5F,0x53,0x42,0x5F, /* 000005C8 ")\/._SB_" */ - 0x50,0x43,0x49,0x30,0x49,0x53,0x41,0x5F, /* 000005D0 "PCI0ISA_" */ - 0x50,0x49,0x52,0x51,0x01,0x50,0x49,0x52, /* 000005D8 "PIRQ.PIR" */ - 0x41,0x08,0x50,0x49,0x52,0x42,0x08,0x50, /* 000005E0 "A.PIRB.P" */ - 0x49,0x52,0x43,0x08,0x50,0x49,0x52,0x44, /* 000005E8 "IRC.PIRD" */ - 0x08,0x5B,0x82,0x46,0x0B,0x53,0x59,0x53, /* 000005F0 ".[.F.SYS" */ - 0x52,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 000005F8 "R._HID.A" */ - 0xD0,0x0C,0x02,0x08,0x5F,0x55,0x49,0x44, /* 00000600 "...._UID" */ - 0x01,0x08,0x43,0x52,0x53,0x5F,0x11,0x4E, /* 00000608 "..CRS_.N" */ - 0x08,0x0A,0x8A,0x47,0x01,0x10,0x00,0x10, /* 00000610 "...G...." */ - 0x00,0x00,0x10,0x47,0x01,0x22,0x00,0x22, /* 00000618 "...G."."" */ - 0x00,0x00,0x0C,0x47,0x01,0x30,0x00,0x30, /* 00000620 "...G.0.0" */ - 0x00,0x00,0x10,0x47,0x01,0x44,0x00,0x44, /* 00000628 "...G.D.D" */ - 0x00,0x00,0x1C,0x47,0x01,0x62,0x00,0x62, /* 00000630 "...G.b.b" */ - 0x00,0x00,0x02,0x47,0x01,0x65,0x00,0x65, /* 00000638 "...G.e.e" */ - 0x00,0x00,0x0B,0x47,0x01,0x72,0x00,0x72, /* 00000640 "...G.r.r" */ - 0x00,0x00,0x0E,0x47,0x01,0x80,0x00,0x80, /* 00000648 "...G...." */ - 0x00,0x00,0x01,0x47,0x01,0x84,0x00,0x84, /* 00000650 "...G...." */ - 0x00,0x00,0x03,0x47,0x01,0x88,0x00,0x88, /* 00000658 "...G...." */ - 0x00,0x00,0x01,0x47,0x01,0x8C,0x00,0x8C, /* 00000660 "...G...." */ - 0x00,0x00,0x03,0x47,0x01,0x90,0x00,0x90, /* 00000668 "...G...." */ - 0x00,0x00,0x10,0x47,0x01,0xA2,0x00,0xA2, /* 00000670 "...G...." */ - 0x00,0x00,0x1C,0x47,0x01,0xE0,0x00,0xE0, /* 00000678 "...G...." */ - 0x00,0x00,0x10,0x47,0x01,0xA0,0x08,0xA0, /* 00000680 "...G...." */ - 0x08,0x00,0x04,0x47,0x01,0xC0,0x0C,0xC0, /* 00000688 "...G...." */ - 0x0C,0x00,0x10,0x47,0x01,0xD0,0x04,0xD0, /* 00000690 "...G...." */ - 0x04,0x00,0x02,0x79,0x00,0x14,0x0B,0x5F, /* 00000698 "...y..._" */ - 0x43,0x52,0x53,0x00,0xA4,0x43,0x52,0x53, /* 000006A0 "CRS..CRS" */ - 0x5F,0x5B,0x82,0x2B,0x50,0x49,0x43,0x5F, /* 000006A8 "_[.+PIC_" */ - 0x08,0x5F,0x48,0x49,0x44,0x0B,0x41,0xD0, /* 000006B0 "._HID.A." */ - 0x08,0x5F,0x43,0x52,0x53,0x11,0x18,0x0A, /* 000006B8 "._CRS..." */ - 0x15,0x47,0x01,0x20,0x00,0x20,0x00,0x01, /* 000006C0 ".G. . .." */ - 0x02,0x47,0x01,0xA0,0x00,0xA0,0x00,0x01, /* 000006C8 ".G......" */ - 0x02,0x22,0x04,0x00,0x79,0x00,0x5B,0x82, /* 000006D0 "."..y.[." */ - 0x47,0x05,0x44,0x4D,0x41,0x30,0x08,0x5F, /* 000006D8 "G.DMA0._" */ - 0x48,0x49,0x44,0x0C,0x41,0xD0,0x02,0x00, /* 000006E0 "HID.A..." */ - 0x08,0x5F,0x43,0x52,0x53,0x11,0x41,0x04, /* 000006E8 "._CRS.A." */ - 0x0A,0x3D,0x2A,0x10,0x04,0x47,0x01,0x00, /* 000006F0 ".=*..G.." */ - 0x00,0x00,0x00,0x00,0x10,0x47,0x01,0x81, /* 000006F8 ".....G.." */ - 0x00,0x81,0x00,0x00,0x03,0x47,0x01,0x87, /* 00000700 ".....G.." */ - 0x00,0x87,0x00,0x00,0x01,0x47,0x01,0x89, /* 00000708 ".....G.." */ - 0x00,0x89,0x00,0x00,0x03,0x47,0x01,0x8F, /* 00000710 ".....G.." */ - 0x00,0x8F,0x00,0x00,0x01,0x47,0x01,0xC0, /* 00000718 ".....G.." */ - 0x00,0xC0,0x00,0x00,0x20,0x47,0x01,0x80, /* 00000720 ".... G.." */ - 0x04,0x80,0x04,0x00,0x10,0x79,0x00,0x5B, /* 00000728 ".....y.[" */ - 0x82,0x25,0x54,0x4D,0x52,0x5F,0x08,0x5F, /* 00000730 ".%TMR_._" */ - 0x48,0x49,0x44,0x0C,0x41,0xD0,0x01,0x00, /* 00000738 "HID.A..." */ - 0x08,0x5F,0x43,0x52,0x53,0x11,0x10,0x0A, /* 00000740 "._CRS..." */ - 0x0D,0x47,0x01,0x40,0x00,0x40,0x00,0x00, /* 00000748 ".G.@.@.." */ - 0x04,0x22,0x01,0x00,0x79,0x00,0x5B,0x82, /* 00000750 "."..y.[." */ - 0x25,0x52,0x54,0x43,0x5F,0x08,0x5F,0x48, /* 00000758 "%RTC_._H" */ - 0x49,0x44,0x0C,0x41,0xD0,0x0B,0x00,0x08, /* 00000760 "ID.A...." */ - 0x5F,0x43,0x52,0x53,0x11,0x10,0x0A,0x0D, /* 00000768 "_CRS...." */ - 0x47,0x01,0x70,0x00,0x70,0x00,0x00,0x02, /* 00000770 "G.p.p..." */ - 0x22,0x00,0x01,0x79,0x00,0x5B,0x82,0x22, /* 00000778 ""..y.[."" */ - 0x53,0x50,0x4B,0x52,0x08,0x5F,0x48,0x49, /* 00000780 "SPKR._HI" */ - 0x44,0x0C,0x41,0xD0,0x08,0x00,0x08,0x5F, /* 00000788 "D.A...._" */ - 0x43,0x52,0x53,0x11,0x0D,0x0A,0x0A,0x47, /* 00000790 "CRS....G" */ - 0x01,0x61,0x00,0x61,0x00,0x00,0x01,0x79, /* 00000798 ".a.a...y" */ - 0x00,0x5B,0x82,0x31,0x50,0x53,0x32,0x4D, /* 000007A0 ".[.1PS2M" */ + 0x50,0x49,0x43,0x44,0x10,0x49,0x85,0x5F, /* 000000B0 "PICD.I._" */ + 0x53,0x42,0x5F,0x5B,0x82,0x49,0x04,0x4D, /* 000000B8 "SB_[.I.M" */ + 0x45,0x4D,0x30,0x08,0x5F,0x48,0x49,0x44, /* 000000C0 "EM0._HID" */ + 0x0C,0x41,0xD0,0x0C,0x02,0x08,0x5F,0x43, /* 000000C8 ".A...._C" */ + 0x52,0x53,0x11,0x33,0x0A,0x30,0x8A,0x2B, /* 000000D0 "RS.3.0.+" */ + 0x00,0x00,0x0D,0x03,0x00,0x00,0x00,0x00, /* 000000D8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E0 "........" */ + 0x00,0x00,0x00,0x00,0xFF,0xFF,0x09,0x00, /* 000000E8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000F0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x00, /* 000000F8 "........" */ + 0x00,0x00,0x00,0x00,0x79,0x00,0x5B,0x82, /* 00000100 "....y.[." */ + 0x46,0x80,0x50,0x43,0x49,0x30,0x08,0x5F, /* 00000108 "F.PCI0._" */ + 0x48,0x49,0x44,0x0C,0x41,0xD0,0x0A,0x03, /* 00000110 "HID.A..." */ + 0x08,0x5F,0x55,0x49,0x44,0x00,0x08,0x5F, /* 00000118 "._UID.._" */ + 0x41,0x44,0x52,0x00,0x08,0x5F,0x42,0x42, /* 00000120 "ADR.._BB" */ + 0x4E,0x00,0x5B,0x80,0x50,0x49,0x52,0x50, /* 00000128 "N.[.PIRP" */ + 0x02,0x0A,0x3C,0x0A,0x10,0x5B,0x81,0x24, /* 00000130 "..<..[.$" */ + 0x50,0x49,0x52,0x50,0x01,0x49,0x52,0x51, /* 00000138 "PIRP.IRQ" */ + 0x33,0x03,0x49,0x52,0x51,0x35,0x05,0x49, /* 00000140 "3.IRQ5.I" */ + 0x52,0x51,0x37,0x07,0x49,0x52,0x51,0x39, /* 00000148 "RQ7.IRQ9" */ + 0x09,0x49,0x52,0x51,0x41,0x0A,0x49,0x52, /* 00000150 ".IRQA.IR" */ + 0x51,0x42,0x0B,0x14,0x48,0x0D,0x5F,0x43, /* 00000158 "QB..H._C" */ + 0x52,0x53,0x00,0x08,0x50,0x52,0x54,0x30, /* 00000160 "RS..PRT0" */ + 0x11,0x46,0x0C,0x0A,0xC2,0x88,0x0D,0x00, /* 00000168 ".F......" */ + 0x02,0x0F,0x00,0x00,0x00,0x00,0x00,0xFF, /* 00000170 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x47,0x01,0xF8, /* 00000178 ".....G.." */ + 0x0C,0xF8,0x0C,0x01,0x08,0x88,0x0D,0x00, /* 00000180 "........" */ + 0x01,0x0C,0x03,0x00,0x00,0x00,0x00,0xF7, /* 00000188 "........" */ + 0x0C,0x00,0x00,0xF8,0x0C,0x88,0x0D,0x00, /* 00000190 "........" */ + 0x01,0x0C,0x03,0x00,0x00,0x00,0x0D,0xFF, /* 00000198 "........" */ + 0x0F,0x00,0x00,0x00,0x03,0x88,0x0D,0x00, /* 000001A0 "........" */ + 0x01,0x0D,0x03,0x00,0x00,0x00,0xC0,0x1F, /* 000001A8 "........" */ + 0xC0,0x00,0x00,0x20,0x00,0x88,0x0D,0x00, /* 000001B0 "... ...." */ + 0x01,0x0D,0x03,0x00,0x00,0x20,0xC0,0x3F, /* 000001B8 "..... .?" */ + 0xC0,0x00,0x00,0x10,0x00,0x87,0x17,0x00, /* 000001C0 "........" */ + 0x00,0x0C,0x02,0x00,0x00,0x00,0x00,0x00, /* 000001C8 "........" */ + 0x00,0x0C,0x00,0xFF,0xFF,0x0F,0x00,0x00, /* 000001D0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x87, /* 000001D8 "........" */ + 0x17,0x00,0x00,0x0D,0x03,0x00,0x00,0x00, /* 000001E0 "........" */ + 0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF, /* 000001E8 "........" */ + 0xF1,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000001F0 "........" */ + 0x02,0x87,0x17,0x00,0x00,0x0D,0x03,0x00, /* 000001F8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0xF2,0xFF, /* 00000200 "........" */ + 0x0F,0x00,0xF2,0x00,0x00,0x00,0x00,0x00, /* 00000208 "........" */ + 0x10,0x00,0x00,0x87,0x17,0x00,0x00,0x0D, /* 00000210 "........" */ + 0x03,0x00,0x00,0x00,0x00,0x00,0x10,0x00, /* 00000218 "........" */ + 0xF2,0x1F,0x10,0x00,0xF2,0x00,0x00,0x00, /* 00000220 "........" */ + 0x00,0x20,0x00,0x00,0x00,0x79,0x00,0xA4, /* 00000228 ". ...y.." */ + 0x50,0x52,0x54,0x30,0x08,0x42,0x55,0x46, /* 00000230 "PRT0.BUF" */ + 0x41,0x11,0x09,0x0A,0x06,0x23,0xF8,0xDC, /* 00000238 "A....#.." */ + 0x18,0x79,0x00,0x08,0x42,0x55,0x46,0x42, /* 00000240 ".y..BUFB" */ + 0x11,0x09,0x0A,0x06,0x23,0x00,0x00,0x18, /* 00000248 "....#..." */ + 0x79,0x00,0x8B,0x42,0x55,0x46,0x42,0x01, /* 00000250 "y..BUFB." */ + 0x49,0x52,0x51,0x56,0x08,0x42,0x55,0x46, /* 00000258 "IRQV.BUF" */ + 0x43,0x11,0x07,0x0A,0x04,0x05,0x07,0x0A, /* 00000260 "C......." */ + 0x0B,0x8C,0x42,0x55,0x46,0x43,0x01,0x50, /* 00000268 "..BUFC.P" */ + 0x49,0x51,0x41,0x8C,0x42,0x55,0x46,0x43, /* 00000270 "IQA.BUFC" */ + 0x01,0x50,0x49,0x51,0x42,0x8C,0x42,0x55, /* 00000278 ".PIQB.BU" */ + 0x46,0x43,0x01,0x50,0x49,0x51,0x43,0x8C, /* 00000280 "FC.PIQC." */ + 0x42,0x55,0x46,0x43,0x01,0x50,0x49,0x51, /* 00000288 "BUFC.PIQ" */ + 0x44,0x5B,0x82,0x48,0x08,0x4C,0x4E,0x4B, /* 00000290 "D[.H.LNK" */ + 0x41,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000298 "A._HID.A" */ + 0xD0,0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44, /* 000002A0 "...._UID" */ + 0x01,0x14,0x1C,0x5F,0x53,0x54,0x41,0x00, /* 000002A8 "..._STA." */ + 0x7B,0x50,0x49,0x52,0x41,0x0A,0x80,0x60, /* 000002B0 "{PIRA..`" */ + 0xA0,0x08,0x93,0x60,0x0A,0x80,0xA4,0x0A, /* 000002B8 "...`...." */ + 0x09,0xA1,0x04,0xA4,0x0A,0x0B,0x14,0x0B, /* 000002C0 "........" */ + 0x5F,0x50,0x52,0x53,0x00,0xA4,0x42,0x55, /* 000002C8 "_PRS..BU" */ + 0x46,0x41,0x14,0x11,0x5F,0x44,0x49,0x53, /* 000002D0 "FA.._DIS" */ + 0x00,0x7D,0x50,0x49,0x52,0x41,0x0A,0x80, /* 000002D8 ".}PIRA.." */ + 0x50,0x49,0x52,0x41,0x14,0x1A,0x5F,0x43, /* 000002E0 "PIRA.._C" */ + 0x52,0x53,0x00,0x7B,0x50,0x49,0x52,0x42, /* 000002E8 "RS.{PIRB" */ + 0x0A,0x0F,0x60,0x79,0x01,0x60,0x49,0x52, /* 000002F0 "..`y.`IR" */ + 0x51,0x56,0xA4,0x42,0x55,0x46,0x42,0x14, /* 000002F8 "QV.BUFB." */ + 0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B,0x68, /* 00000300 "._SRS..h" */ + 0x01,0x49,0x52,0x51,0x31,0x82,0x49,0x52, /* 00000308 ".IRQ1.IR" */ + 0x51,0x31,0x60,0x76,0x60,0x70,0x60,0x50, /* 00000310 "Q1`v`p`P" */ + 0x49,0x52,0x41,0x5B,0x82,0x49,0x08,0x4C, /* 00000318 "IRA[.I.L" */ + 0x4E,0x4B,0x42,0x08,0x5F,0x48,0x49,0x44, /* 00000320 "NKB._HID" */ + 0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55, /* 00000328 ".A...._U" */ + 0x49,0x44,0x0A,0x02,0x14,0x1C,0x5F,0x53, /* 00000330 "ID...._S" */ + 0x54,0x41,0x00,0x7B,0x50,0x49,0x52,0x42, /* 00000338 "TA.{PIRB" */ + 0x0A,0x80,0x60,0xA0,0x08,0x93,0x60,0x0A, /* 00000340 "..`...`." */ + 0x80,0xA4,0x0A,0x09,0xA1,0x04,0xA4,0x0A, /* 00000348 "........" */ + 0x0B,0x14,0x0B,0x5F,0x50,0x52,0x53,0x00, /* 00000350 "..._PRS." */ + 0xA4,0x42,0x55,0x46,0x41,0x14,0x11,0x5F, /* 00000358 ".BUFA.._" */ + 0x44,0x49,0x53,0x00,0x7D,0x50,0x49,0x52, /* 00000360 "DIS.}PIR" */ + 0x42,0x0A,0x80,0x50,0x49,0x52,0x42,0x14, /* 00000368 "B..PIRB." */ + 0x1A,0x5F,0x43,0x52,0x53,0x00,0x7B,0x50, /* 00000370 "._CRS.{P" */ + 0x49,0x52,0x42,0x0A,0x0F,0x60,0x79,0x01, /* 00000378 "IRB..`y." */ + 0x60,0x49,0x52,0x51,0x56,0xA4,0x42,0x55, /* 00000380 "`IRQV.BU" */ + 0x46,0x42,0x14,0x1B,0x5F,0x53,0x52,0x53, /* 00000388 "FB.._SRS" */ + 0x01,0x8B,0x68,0x01,0x49,0x52,0x51,0x31, /* 00000390 "..h.IRQ1" */ + 0x82,0x49,0x52,0x51,0x31,0x60,0x76,0x60, /* 00000398 ".IRQ1`v`" */ + 0x70,0x60,0x50,0x49,0x52,0x42,0x5B,0x82, /* 000003A0 "p`PIRB[." */ + 0x49,0x08,0x4C,0x4E,0x4B,0x43,0x08,0x5F, /* 000003A8 "I.LNKC._" */ + 0x48,0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F, /* 000003B0 "HID.A..." */ + 0x08,0x5F,0x55,0x49,0x44,0x0A,0x03,0x14, /* 000003B8 "._UID..." */ + 0x1C,0x5F,0x53,0x54,0x41,0x00,0x7B,0x50, /* 000003C0 "._STA.{P" */ + 0x49,0x52,0x43,0x0A,0x80,0x60,0xA0,0x08, /* 000003C8 "IRC..`.." */ + 0x93,0x60,0x0A,0x80,0xA4,0x0A,0x09,0xA1, /* 000003D0 ".`......" */ + 0x04,0xA4,0x0A,0x0B,0x14,0x0B,0x5F,0x50, /* 000003D8 "......_P" */ + 0x52,0x53,0x00,0xA4,0x42,0x55,0x46,0x41, /* 000003E0 "RS..BUFA" */ + 0x14,0x11,0x5F,0x44,0x49,0x53,0x00,0x7D, /* 000003E8 ".._DIS.}" */ + 0x50,0x49,0x52,0x43,0x0A,0x80,0x50,0x49, /* 000003F0 "PIRC..PI" */ + 0x52,0x43,0x14,0x1A,0x5F,0x43,0x52,0x53, /* 000003F8 "RC.._CRS" */ + 0x00,0x7B,0x50,0x49,0x52,0x43,0x0A,0x0F, /* 00000400 ".{PIRC.." */ + 0x60,0x79,0x01,0x60,0x49,0x52,0x51,0x56, /* 00000408 "`y.`IRQV" */ + 0xA4,0x42,0x55,0x46,0x42,0x14,0x1B,0x5F, /* 00000410 ".BUFB.._" */ + 0x53,0x52,0x53,0x01,0x8B,0x68,0x01,0x49, /* 00000418 "SRS..h.I" */ + 0x52,0x51,0x31,0x82,0x49,0x52,0x51,0x31, /* 00000420 "RQ1.IRQ1" */ + 0x60,0x76,0x60,0x70,0x60,0x50,0x49,0x52, /* 00000428 "`v`p`PIR" */ + 0x43,0x5B,0x82,0x49,0x08,0x4C,0x4E,0x4B, /* 00000430 "C[.I.LNK" */ + 0x44,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000438 "D._HID.A" */ + 0xD0,0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44, /* 00000440 "...._UID" */ + 0x0A,0x04,0x14,0x1C,0x5F,0x53,0x54,0x41, /* 00000448 "...._STA" */ + 0x00,0x7B,0x50,0x49,0x52,0x44,0x0A,0x80, /* 00000450 ".{PIRD.." */ + 0x60,0xA0,0x08,0x93,0x60,0x0A,0x80,0xA4, /* 00000458 "`...`..." */ + 0x0A,0x09,0xA1,0x04,0xA4,0x0A,0x0B,0x14, /* 00000460 "........" */ + 0x0B,0x5F,0x50,0x52,0x53,0x00,0xA4,0x42, /* 00000468 "._PRS..B" */ + 0x55,0x46,0x41,0x14,0x11,0x5F,0x44,0x49, /* 00000470 "UFA.._DI" */ + 0x53,0x00,0x7D,0x50,0x49,0x52,0x44,0x0A, /* 00000478 "S.}PIRD." */ + 0x80,0x50,0x49,0x52,0x44,0x14,0x1A,0x5F, /* 00000480 ".PIRD.._" */ + 0x43,0x52,0x53,0x00,0x7B,0x50,0x49,0x52, /* 00000488 "CRS.{PIR" */ + 0x44,0x0A,0x0F,0x60,0x79,0x01,0x60,0x49, /* 00000490 "D..`y.`I" */ + 0x52,0x51,0x56,0xA4,0x42,0x55,0x46,0x42, /* 00000498 "RQV.BUFB" */ + 0x14,0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B, /* 000004A0 ".._SRS.." */ + 0x68,0x01,0x49,0x52,0x51,0x31,0x82,0x49, /* 000004A8 "h.IRQ1.I" */ + 0x52,0x51,0x31,0x60,0x76,0x60,0x70,0x60, /* 000004B0 "RQ1`v`p`" */ + 0x50,0x49,0x52,0x44,0x14,0x16,0x5F,0x50, /* 000004B8 "PIRD.._P" */ + 0x52,0x54,0x00,0xA0,0x0A,0x50,0x49,0x43, /* 000004C0 "RT...PIC" */ + 0x44,0xA4,0x50,0x52,0x54,0x41,0xA4,0x50, /* 000004C8 "D.PRTA.P" */ + 0x52,0x54,0x50,0x08,0x50,0x52,0x54,0x50, /* 000004D0 "RTP.PRTP" */ + 0x12,0x43,0x0E,0x10,0x12,0x0B,0x04,0x0B, /* 000004D8 ".C......" */ + 0xFF,0xFF,0x00,0x4C,0x4E,0x4B,0x41,0x00, /* 000004E0 "...LNKA." */ + 0x12,0x0B,0x04,0x0B,0xFF,0xFF,0x01,0x4C, /* 000004E8 ".......L" */ + 0x4E,0x4B,0x42,0x00,0x12,0x0C,0x04,0x0B, /* 000004F0 "NKB....." */ + 0xFF,0xFF,0x0A,0x02,0x4C,0x4E,0x4B,0x43, /* 000004F8 "....LNKC" */ + 0x00,0x12,0x0C,0x04,0x0B,0xFF,0xFF,0x0A, /* 00000500 "........" */ + 0x03,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D, /* 00000508 ".LNKD..." */ + 0x04,0x0C,0xFF,0xFF,0x01,0x00,0x00,0x4C, /* 00000510 ".......L" */ + 0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04,0x0C, /* 00000518 "NKB....." */ + 0xFF,0xFF,0x01,0x00,0x01,0x4C,0x4E,0x4B, /* 00000520 ".....LNK" */ + 0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000528 "C......." */ + 0x01,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x44, /* 00000530 "....LNKD" */ + 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x01, /* 00000538 "........" */ + 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x41,0x00, /* 00000540 "...LNKA." */ + 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x02,0x00, /* 00000548 "........" */ + 0x00,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0D, /* 00000550 ".LNKC..." */ + 0x04,0x0C,0xFF,0xFF,0x02,0x00,0x01,0x4C, /* 00000558 ".......L" */ + 0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 00000560 "NKD....." */ + 0xFF,0xFF,0x02,0x00,0x0A,0x02,0x4C,0x4E, /* 00000568 "......LN" */ + 0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000570 "KA......" */ + 0xFF,0x02,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000578 ".....LNK" */ + 0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000580 "B......." */ + 0x03,0x00,0x00,0x4C,0x4E,0x4B,0x44,0x00, /* 00000588 "...LNKD." */ + 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x03,0x00, /* 00000590 "........" */ + 0x01,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 00000598 ".LNKA..." */ + 0x04,0x0C,0xFF,0xFF,0x03,0x00,0x0A,0x02, /* 000005A0 "........" */ + 0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04, /* 000005A8 "LNKB...." */ + 0x0C,0xFF,0xFF,0x03,0x00,0x0A,0x03,0x4C, /* 000005B0 ".......L" */ + 0x4E,0x4B,0x43,0x00,0x08,0x50,0x52,0x54, /* 000005B8 "NKC..PRT" */ + 0x41,0x12,0x32,0x04,0x12,0x0B,0x04,0x0C, /* 000005C0 "A.2....." */ + 0xFF,0xFF,0x01,0x00,0x00,0x00,0x0A,0x05, /* 000005C8 "........" */ + 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x02,0x00, /* 000005D0 "........" */ + 0x00,0x00,0x0A,0x07,0x12,0x0B,0x04,0x0C, /* 000005D8 "........" */ + 0xFF,0xFF,0x03,0x00,0x00,0x00,0x0A,0x0A, /* 000005E0 "........" */ + 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x04,0x00, /* 000005E8 "........" */ + 0x00,0x00,0x0A,0x0B,0x5B,0x82,0x48,0x31, /* 000005F0 "....[.H1" */ + 0x49,0x53,0x41,0x5F,0x08,0x5F,0x41,0x44, /* 000005F8 "ISA_._AD" */ + 0x52,0x00,0x5B,0x80,0x50,0x49,0x52,0x51, /* 00000600 "R.[.PIRQ" */ + 0x02,0x0A,0x60,0x0A,0x04,0x10,0x2E,0x5C, /* 00000608 "..`....\" */ + 0x00,0x5B,0x81,0x29,0x5C,0x2F,0x04,0x5F, /* 00000610 ".[.)\/._" */ + 0x53,0x42,0x5F,0x50,0x43,0x49,0x30,0x49, /* 00000618 "SB_PCI0I" */ + 0x53,0x41,0x5F,0x50,0x49,0x52,0x51,0x01, /* 00000620 "SA_PIRQ." */ + 0x50,0x49,0x52,0x41,0x08,0x50,0x49,0x52, /* 00000628 "PIRA.PIR" */ + 0x42,0x08,0x50,0x49,0x52,0x43,0x08,0x50, /* 00000630 "B.PIRC.P" */ + 0x49,0x52,0x44,0x08,0x5B,0x82,0x46,0x0B, /* 00000638 "IRD.[.F." */ + 0x53,0x59,0x53,0x52,0x08,0x5F,0x48,0x49, /* 00000640 "SYSR._HI" */ + 0x44,0x0C,0x41,0xD0,0x0C,0x02,0x08,0x5F, /* 00000648 "D.A...._" */ + 0x55,0x49,0x44,0x01,0x08,0x43,0x52,0x53, /* 00000650 "UID..CRS" */ + 0x5F,0x11,0x4E,0x08,0x0A,0x8A,0x47,0x01, /* 00000658 "_.N...G." */ + 0x10,0x00,0x10,0x00,0x00,0x10,0x47,0x01, /* 00000660 "......G." */ + 0x22,0x00,0x22,0x00,0x00,0x0C,0x47,0x01, /* 00000668 ""."...G." */ + 0x30,0x00,0x30,0x00,0x00,0x10,0x47,0x01, /* 00000670 "0.0...G." */ + 0x44,0x00,0x44,0x00,0x00,0x1C,0x47,0x01, /* 00000678 "D.D...G." */ + 0x62,0x00,0x62,0x00,0x00,0x02,0x47,0x01, /* 00000680 "b.b...G." */ + 0x65,0x00,0x65,0x00,0x00,0x0B,0x47,0x01, /* 00000688 "e.e...G." */ + 0x72,0x00,0x72,0x00,0x00,0x0E,0x47,0x01, /* 00000690 "r.r...G." */ + 0x80,0x00,0x80,0x00,0x00,0x01,0x47,0x01, /* 00000698 "......G." */ + 0x84,0x00,0x84,0x00,0x00,0x03,0x47,0x01, /* 000006A0 "......G." */ + 0x88,0x00,0x88,0x00,0x00,0x01,0x47,0x01, /* 000006A8 "......G." */ + 0x8C,0x00,0x8C,0x00,0x00,0x03,0x47,0x01, /* 000006B0 "......G." */ + 0x90,0x00,0x90,0x00,0x00,0x10,0x47,0x01, /* 000006B8 "......G." */ + 0xA2,0x00,0xA2,0x00,0x00,0x1C,0x47,0x01, /* 000006C0 "......G." */ + 0xE0,0x00,0xE0,0x00,0x00,0x10,0x47,0x01, /* 000006C8 "......G." */ + 0xA0,0x08,0xA0,0x08,0x00,0x04,0x47,0x01, /* 000006D0 "......G." */ + 0xC0,0x0C,0xC0,0x0C,0x00,0x10,0x47,0x01, /* 000006D8 "......G." */ + 0xD0,0x04,0xD0,0x04,0x00,0x02,0x79,0x00, /* 000006E0 "......y." */ + 0x14,0x0B,0x5F,0x43,0x52,0x53,0x00,0xA4, /* 000006E8 ".._CRS.." */ + 0x43,0x52,0x53,0x5F,0x5B,0x82,0x2B,0x50, /* 000006F0 "CRS_[.+P" */ + 0x49,0x43,0x5F,0x08,0x5F,0x48,0x49,0x44, /* 000006F8 "IC_._HID" */ + 0x0B,0x41,0xD0,0x08,0x5F,0x43,0x52,0x53, /* 00000700 ".A.._CRS" */ + 0x11,0x18,0x0A,0x15,0x47,0x01,0x20,0x00, /* 00000708 "....G. ." */ + 0x20,0x00,0x01,0x02,0x47,0x01,0xA0,0x00, /* 00000710 " ...G..." */ + 0xA0,0x00,0x01,0x02,0x22,0x04,0x00,0x79, /* 00000718 "...."..y" */ + 0x00,0x5B,0x82,0x47,0x05,0x44,0x4D,0x41, /* 00000720 ".[.G.DMA" */ + 0x30,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000728 "0._HID.A" */ + 0xD0,0x02,0x00,0x08,0x5F,0x43,0x52,0x53, /* 00000730 "...._CRS" */ + 0x11,0x41,0x04,0x0A,0x3D,0x2A,0x10,0x04, /* 00000738 ".A..=*.." */ + 0x47,0x01,0x00,0x00,0x00,0x00,0x00,0x10, /* 00000740 "G......." */ + 0x47,0x01,0x81,0x00,0x81,0x00,0x00,0x03, /* 00000748 "G......." */ + 0x47,0x01,0x87,0x00,0x87,0x00,0x00,0x01, /* 00000750 "G......." */ + 0x47,0x01,0x89,0x00,0x89,0x00,0x00,0x03, /* 00000758 "G......." */ + 0x47,0x01,0x8F,0x00,0x8F,0x00,0x00,0x01, /* 00000760 "G......." */ + 0x47,0x01,0xC0,0x00,0xC0,0x00,0x00,0x20, /* 00000768 "G...... " */ + 0x47,0x01,0x80,0x04,0x80,0x04,0x00,0x10, /* 00000770 "G......." */ + 0x79,0x00,0x5B,0x82,0x25,0x54,0x4D,0x52, /* 00000778 "y.[.%TMR" */ + 0x5F,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000780 "_._HID.A" */ + 0xD0,0x01,0x00,0x08,0x5F,0x43,0x52,0x53, /* 00000788 "...._CRS" */ + 0x11,0x10,0x0A,0x0D,0x47,0x01,0x40,0x00, /* 00000790 "....G.@." */ + 0x40,0x00,0x00,0x04,0x22,0x01,0x00,0x79, /* 00000798 "@..."..y" */ + 0x00,0x5B,0x82,0x25,0x52,0x54,0x43,0x5F, /* 000007A0 ".[.%RTC_" */ 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 000007A8 "._HID.A." */ - 0x0F,0x13,0x08,0x5F,0x43,0x49,0x44,0x0C, /* 000007B0 "..._CID." */ - 0x41,0xD0,0x0F,0x13,0x14,0x09,0x5F,0x53, /* 000007B8 "A....._S" */ - 0x54,0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F, /* 000007C0 "TA....._" */ - 0x43,0x52,0x53,0x11,0x08,0x0A,0x05,0x22, /* 000007C8 "CRS...."" */ - 0x00,0x10,0x79,0x00,0x5B,0x82,0x42,0x04, /* 000007D0 "..y.[.B." */ - 0x50,0x53,0x32,0x4B,0x08,0x5F,0x48,0x49, /* 000007D8 "PS2K._HI" */ - 0x44,0x0C,0x41,0xD0,0x03,0x03,0x08,0x5F, /* 000007E0 "D.A...._" */ - 0x43,0x49,0x44,0x0C,0x41,0xD0,0x03,0x0B, /* 000007E8 "CID.A..." */ - 0x14,0x09,0x5F,0x53,0x54,0x41,0x00,0xA4, /* 000007F0 ".._STA.." */ - 0x0A,0x0F,0x08,0x5F,0x43,0x52,0x53,0x11, /* 000007F8 "..._CRS." */ - 0x18,0x0A,0x15,0x47,0x01,0x60,0x00,0x60, /* 00000800 "...G.`.`" */ - 0x00,0x00,0x01,0x47,0x01,0x64,0x00,0x64, /* 00000808 "...G.d.d" */ - 0x00,0x00,0x01,0x22,0x02,0x00,0x79,0x00, /* 00000810 "..."..y." */ - 0x5B,0x82,0x3A,0x46,0x44,0x43,0x30,0x08, /* 00000818 "[.:FDC0." */ - 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x07, /* 00000820 "_HID.A.." */ - 0x00,0x14,0x09,0x5F,0x53,0x54,0x41,0x00, /* 00000828 "..._STA." */ - 0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52,0x53, /* 00000830 "...._CRS" */ - 0x11,0x1B,0x0A,0x18,0x47,0x01,0xF0,0x03, /* 00000838 "....G..." */ - 0xF0,0x03,0x01,0x06,0x47,0x01,0xF7,0x03, /* 00000840 "....G..." */ - 0xF7,0x03,0x01,0x01,0x22,0x40,0x00,0x2A, /* 00000848 "...."@.*" */ - 0x04,0x00,0x79,0x00,0x5B,0x82,0x35,0x55, /* 00000850 "..y.[.5U" */ - 0x41,0x52,0x31,0x08,0x5F,0x48,0x49,0x44, /* 00000858 "AR1._HID" */ - 0x0C,0x41,0xD0,0x05,0x01,0x08,0x5F,0x55, /* 00000860 ".A...._U" */ - 0x49,0x44,0x01,0x14,0x09,0x5F,0x53,0x54, /* 00000868 "ID..._ST" */ - 0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43, /* 00000870 "A....._C" */ - 0x52,0x53,0x11,0x10,0x0A,0x0D,0x47,0x01, /* 00000878 "RS....G." */ - 0xF8,0x03,0xF8,0x03,0x01,0x08,0x22,0x10, /* 00000880 "......"." */ - 0x00,0x79,0x00,0x5B,0x82,0x36,0x55,0x41, /* 00000888 ".y.[.6UA" */ - 0x52,0x32,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 00000890 "R2._HID." */ - 0x41,0xD0,0x05,0x01,0x08,0x5F,0x55,0x49, /* 00000898 "A...._UI" */ - 0x44,0x0A,0x02,0x14,0x09,0x5F,0x53,0x54, /* 000008A0 "D...._ST" */ - 0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43, /* 000008A8 "A....._C" */ - 0x52,0x53,0x11,0x10,0x0A,0x0D,0x47,0x01, /* 000008B0 "RS....G." */ - 0xF8,0x02,0xF8,0x02,0x01,0x08,0x22,0x08, /* 000008B8 "......"." */ - 0x00,0x79,0x00, + 0x0B,0x00,0x08,0x5F,0x43,0x52,0x53,0x11, /* 000007B0 "..._CRS." */ + 0x10,0x0A,0x0D,0x47,0x01,0x70,0x00,0x70, /* 000007B8 "...G.p.p" */ + 0x00,0x00,0x02,0x22,0x00,0x01,0x79,0x00, /* 000007C0 "..."..y." */ + 0x5B,0x82,0x22,0x53,0x50,0x4B,0x52,0x08, /* 000007C8 "[."SPKR." */ + 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x08, /* 000007D0 "_HID.A.." */ + 0x00,0x08,0x5F,0x43,0x52,0x53,0x11,0x0D, /* 000007D8 ".._CRS.." */ + 0x0A,0x0A,0x47,0x01,0x61,0x00,0x61,0x00, /* 000007E0 "..G.a.a." */ + 0x00,0x01,0x79,0x00,0x5B,0x82,0x31,0x50, /* 000007E8 "..y.[.1P" */ + 0x53,0x32,0x4D,0x08,0x5F,0x48,0x49,0x44, /* 000007F0 "S2M._HID" */ + 0x0C,0x41,0xD0,0x0F,0x13,0x08,0x5F,0x43, /* 000007F8 ".A...._C" */ + 0x49,0x44,0x0C,0x41,0xD0,0x0F,0x13,0x14, /* 00000800 "ID.A...." */ + 0x09,0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A, /* 00000808 "._STA..." */ + 0x0F,0x08,0x5F,0x43,0x52,0x53,0x11,0x08, /* 00000810 ".._CRS.." */ + 0x0A,0x05,0x22,0x00,0x10,0x79,0x00,0x5B, /* 00000818 ".."..y.[" */ + 0x82,0x42,0x04,0x50,0x53,0x32,0x4B,0x08, /* 00000820 ".B.PS2K." */ + 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x03, /* 00000828 "_HID.A.." */ + 0x03,0x08,0x5F,0x43,0x49,0x44,0x0C,0x41, /* 00000830 ".._CID.A" */ + 0xD0,0x03,0x0B,0x14,0x09,0x5F,0x53,0x54, /* 00000838 "....._ST" */ + 0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43, /* 00000840 "A....._C" */ + 0x52,0x53,0x11,0x18,0x0A,0x15,0x47,0x01, /* 00000848 "RS....G." */ + 0x60,0x00,0x60,0x00,0x00,0x01,0x47,0x01, /* 00000850 "`.`...G." */ + 0x64,0x00,0x64,0x00,0x00,0x01,0x22,0x02, /* 00000858 "d.d..."." */ + 0x00,0x79,0x00,0x5B,0x82,0x3A,0x46,0x44, /* 00000860 ".y.[.:FD" */ + 0x43,0x30,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 00000868 "C0._HID." */ + 0x41,0xD0,0x07,0x00,0x14,0x09,0x5F,0x53, /* 00000870 "A....._S" */ + 0x54,0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F, /* 00000878 "TA....._" */ + 0x43,0x52,0x53,0x11,0x1B,0x0A,0x18,0x47, /* 00000880 "CRS....G" */ + 0x01,0xF0,0x03,0xF0,0x03,0x01,0x06,0x47, /* 00000888 ".......G" */ + 0x01,0xF7,0x03,0xF7,0x03,0x01,0x01,0x22, /* 00000890 "......."" */ + 0x40,0x00,0x2A,0x04,0x00,0x79,0x00,0x5B, /* 00000898 "@.*..y.[" */ + 0x82,0x35,0x55,0x41,0x52,0x31,0x08,0x5F, /* 000008A0 ".5UAR1._" */ + 0x48,0x49,0x44,0x0C,0x41,0xD0,0x05,0x01, /* 000008A8 "HID.A..." */ + 0x08,0x5F,0x55,0x49,0x44,0x01,0x14,0x09, /* 000008B0 "._UID..." */ + 0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F, /* 000008B8 "_STA...." */ + 0x08,0x5F,0x43,0x52,0x53,0x11,0x10,0x0A, /* 000008C0 "._CRS..." */ + 0x0D,0x47,0x01,0xF8,0x03,0xF8,0x03,0x01, /* 000008C8 ".G......" */ + 0x08,0x22,0x10,0x00,0x79,0x00,0x5B,0x82, /* 000008D0 "."..y.[." */ + 0x36,0x55,0x41,0x52,0x32,0x08,0x5F,0x48, /* 000008D8 "6UAR2._H" */ + 0x49,0x44,0x0C,0x41,0xD0,0x05,0x01,0x08, /* 000008E0 "ID.A...." */ + 0x5F,0x55,0x49,0x44,0x0A,0x02,0x14,0x09, /* 000008E8 "_UID...." */ + 0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F, /* 000008F0 "_STA...." */ + 0x08,0x5F,0x43,0x52,0x53,0x11,0x10,0x0A, /* 000008F8 "._CRS..." */ + 0x0D,0x47,0x01,0xF8,0x02,0xF8,0x02,0x01, /* 00000900 ".G......" */ + 0x08,0x22,0x08,0x00,0x79,0x00, }; int DsdtLen=sizeof(AmlCode); diff -r 61204c1d740e -r 87cefa5f7c5e tools/firmware/hvmloader/Makefile --- a/tools/firmware/hvmloader/Makefile Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/firmware/hvmloader/Makefile Mon Aug 07 18:00:22 2006 -0500 @@ -42,12 +42,15 @@ CFLAGS += $(DEFINES) -I. $(XENINC) -fno CFLAGS += $(DEFINES) -I. $(XENINC) -fno-builtin -O2 -msoft-float LDFLAGS = -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR) +SRCS = hvmloader.c acpi_madt.c mp_tables.c util.c +OBJS = $(patsubst %.c,%.o,$(SRCS)) + .PHONY: all all: hvmloader -hvmloader: roms.h hvmloader.c acpi_madt.c mp_tables.c - $(CC) $(CFLAGS) -c hvmloader.c acpi_madt.c mp_tables.c - $(CC) $(LDFLAGS) -o hvmloader.tmp hvmloader.o acpi_madt.o mp_tables.o +hvmloader: roms.h $(SRCS) + $(CC) $(CFLAGS) -c $(SRCS) + $(CC) $(LDFLAGS) -o hvmloader.tmp $(OBJS) $(OBJCOPY) hvmloader.tmp hvmloader rm -f hvmloader.tmp diff -r 61204c1d740e -r 87cefa5f7c5e tools/firmware/hvmloader/acpi_madt.c --- a/tools/firmware/hvmloader/acpi_madt.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/firmware/hvmloader/acpi_madt.c Mon Aug 07 18:00:22 2006 -0500 @@ -20,12 +20,10 @@ #include "../acpi/acpi2_0.h" #include "../acpi/acpi_madt.h" - +#include "util.h" #include <xen/hvm/hvm_info_table.h> #define NULL ((void*)0) - -extern int puts(const char *s); static struct hvm_info_table *table = NULL; diff -r 61204c1d740e -r 87cefa5f7c5e tools/firmware/hvmloader/hvmloader.c --- a/tools/firmware/hvmloader/hvmloader.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/firmware/hvmloader/hvmloader.c Mon Aug 07 18:00:22 2006 -0500 @@ -23,15 +23,19 @@ */ #include "roms.h" #include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */ +#include "hypercall.h" +#include "util.h" +#include <xen/version.h> #include <xen/hvm/hvm_info_table.h> /* memory map */ +#define HYPERCALL_PHYSICAL_ADDRESS 0x00080000 #define VGABIOS_PHYSICAL_ADDRESS 0x000C0000 #define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000 #define ROMBIOS_PHYSICAL_ADDRESS 0x000F0000 /* invoke SVM's paged realmode support */ -#define SVM_VMMCALL_RESET_TO_REALMODE 0x00000001 +#define SVM_VMMCALL_RESET_TO_REALMODE 0x80000001 /* * C runtime start off @@ -75,79 +79,28 @@ extern void create_mp_tables(void); extern void create_mp_tables(void); struct hvm_info_table *get_hvm_info_table(void); -static inline void -outw(unsigned short addr, unsigned short val) -{ - __asm__ __volatile__ ("outw %%ax, %%dx" :: "d"(addr), "a"(val)); -} - -static inline void -outb(unsigned short addr, unsigned char val) -{ - __asm__ __volatile__ ("outb %%al, %%dx" :: "d"(addr), "a"(val)); -} - -static inline unsigned char -inb(unsigned short addr) -{ - unsigned char val; - - __asm__ __volatile__ ("inb %w1,%0" : "=a" (val) : "Nd" (addr)); - return val; -} - -void * -memcpy(void *dest, const void *src, unsigned n) -{ - int t0, t1, t2; - - __asm__ __volatile__( - "cld\n" - "rep; movsl\n" - "testb $2,%b4\n" - "je 1f\n" - "movsw\n" - "1: testb $1,%b4\n" - "je 2f\n" - "movsb\n" - "2:" - : "=&c" (t0), "=&D" (t1), "=&S" (t2) - : "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src) - : "memory" - ); - return dest; -} - -int -puts(const char *s) -{ - while (*s) - outb(0xE9, *s++); - return 0; -} - -int +static int cirrus_check(void) { outw(0x3C4, 0x9206); return inb(0x3C5) == 0x12; } -int -vmmcall(int edi, int esi, int edx, int ecx, int ebx) +static int +vmmcall(int function, int edi, int esi, int edx, int ecx, int ebx) { int eax; __asm__ __volatile__( ".byte 0x0F,0x01,0xD9" : "=a" (eax) - : "a"(0x58454E00), /* XEN\0 key */ + : "a"(function), "b"(ebx), "c"(ecx), "d"(edx), "D"(edi), "S"(esi) ); return eax; } -int +static int check_amd(void) { char id[12]; @@ -162,12 +115,68 @@ check_amd(void) return __builtin_memcmp(id, "AuthenticAMD", 12) == 0; } +static void +cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) +{ + __asm__ __volatile__( + "cpuid" + : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) + : "0" (idx) ); +} + +static void +wrmsr(uint32_t idx, uint64_t v) +{ + __asm__ __volatile__( + "wrmsr" + : : "c" (idx), "a" ((uint32_t)v), "d" ((uint32_t)(v>>32)) ); +} + +static void +init_hypercalls(void) +{ + uint32_t eax, ebx, ecx, edx; + unsigned long i; + char signature[13], number[13]; + xen_extraversion_t extraversion; + + cpuid(0x40000000, &eax, &ebx, &ecx, &edx); + + *(uint32_t *)(signature + 0) = ebx; + *(uint32_t *)(signature + 4) = ecx; + *(uint32_t *)(signature + 8) = edx; + signature[12] = '\0'; + + if (strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002)) { + puts("FATAL: Xen hypervisor not detected\n"); + __asm__ __volatile__( "ud2" ); + } + + cpuid(0x40000001, &eax, &ebx, &ecx, &edx); + + puts("Detected Xen v"); + puts(itoa(number, eax >> 16)); + puts("."); + puts(itoa(number, eax & 0xffff)); + + cpuid(0x40000002, &eax, &ebx, &ecx, &edx); + + for (i = 0; i < eax; i++) + wrmsr(ebx, HYPERCALL_PHYSICAL_ADDRESS + (i << 12) + i); + + hypercall_xen_version(XENVER_extraversion, extraversion); + puts(extraversion); + puts("\n"); +} + int main(void) { struct hvm_info_table *t = get_hvm_info_table(); puts("HVM Loader\n"); + + init_hypercalls(); puts("Loading ROMBIOS ...\n"); memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios)); @@ -200,7 +209,7 @@ main(void) if (check_amd()) { /* AMD implies this is SVM */ puts("SVM go ...\n"); - vmmcall(SVM_VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0); + vmmcall(SVM_VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0, 0); } else { puts("Loading VMXAssist ...\n"); memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS, diff -r 61204c1d740e -r 87cefa5f7c5e tools/firmware/hvmloader/mp_tables.c --- a/tools/firmware/hvmloader/mp_tables.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/firmware/hvmloader/mp_tables.c Mon Aug 07 18:00:22 2006 -0500 @@ -93,7 +93,8 @@ typedef signed long int64_t; #define INTR_MAX_NR 16 -extern int puts(const char *); /* for printing */ +#include "util.h" + extern int get_vcpu_nr(void); /* for the guest's VCPU count */ /* diff -r 61204c1d740e -r 87cefa5f7c5e tools/firmware/vmxassist/vm86.c --- a/tools/firmware/vmxassist/vm86.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/firmware/vmxassist/vm86.c Mon Aug 07 18:00:22 2006 -0500 @@ -52,6 +52,31 @@ static char *rnames[] = { "ax", "cx", "d static char *rnames[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" }; #endif /* DEBUG */ +#define PT_ENTRY_PRESENT 0x1 + +static unsigned +guest_linear_to_real(unsigned long base, unsigned off) +{ + unsigned int gcr3 = oldctx.cr3; + unsigned int l1_mfn; + unsigned int l0_mfn; + + if (!(oldctx.cr0 & CR0_PG)) + return base + off; + + l1_mfn = ((unsigned int *)gcr3)[(base >> 22) & 0x3ff ]; + if (!(l1_mfn & PT_ENTRY_PRESENT)) + panic("l2 entry not present\n"); + l1_mfn = l1_mfn & 0xfffff000 ; + + l0_mfn = ((unsigned int *)l1_mfn)[(base >> 12) & 0x3ff]; + if (!(l0_mfn & PT_ENTRY_PRESENT)) + panic("l1 entry not present\n"); + l0_mfn = l0_mfn & 0xfffff000; + + return l0_mfn + off + (base & 0xfff); +} + static unsigned address(struct regs *regs, unsigned seg, unsigned off) { @@ -70,7 +95,7 @@ address(struct regs *regs, unsigned seg, (mode == VM86_REAL_TO_PROTECTED && regs->cs == seg)) return ((seg & 0xFFFF) << 4) + off; - entry = ((unsigned long long *) oldctx.gdtr_base)[seg >> 3]; + entry = ((unsigned long long *) guest_linear_to_real(oldctx.gdtr_base, 0))[seg >> 3]; entry_high = entry >> 32; entry_low = entry & 0xFFFFFFFF; @@ -94,7 +119,7 @@ trace(struct regs *regs, int adjust, cha trace(struct regs *regs, int adjust, char *fmt, ...) { unsigned off = regs->eip - adjust; - va_list ap; + va_list ap; if ((traceset & (1 << mode)) && (mode == VM86_REAL_TO_PROTECTED || mode == VM86_REAL)) { @@ -755,7 +780,7 @@ load_seg(unsigned long sel, uint32_t *ba return 1; } - entry = ((unsigned long long *) oldctx.gdtr_base)[sel >> 3]; + entry = ((unsigned long long *) guest_linear_to_real(oldctx.gdtr_base, 0))[sel >> 3]; /* Check the P bit first */ if (!((entry >> (15+32)) & 0x1) && sel != 0) diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/.cvsignore --- a/tools/ioemu/.cvsignore Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/.cvsignore Mon Aug 07 18:00:22 2006 -0500 @@ -11,6 +11,8 @@ ppc-user ppc-user qemu-doc.html qemu-tech.html +qemu-doc.info +qemu-tech.info qemu.1 qemu.pod qemu-img.1 @@ -25,5 +27,16 @@ mipsel-softmmu mipsel-softmmu mips-user mipsel-user +.gdbinit sh4-user sh4-softmmu +*.aux +*.cp +*.dvi +*.fn +*.ky +*.log +*.pg +*.toc +*.tp +*.vr diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/Changelog --- a/tools/ioemu/Changelog Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/Changelog Mon Aug 07 18:00:22 2006 -0500 @@ -1,3 +1,22 @@ version 0.8.1: +version 0.8.2: + + - ACPI support + - PC VGA BIOS fixes + - switch to OpenBios for SPARC targets (Blue Swirl) + - VNC server fixes + - MIPS FPU support (Marius Groeger) + - Solaris/SPARC host support (Ben Taylor) + - PPC breakpoints and single stepping (Jason Wessel) + - USB updates (Paul Brook) + - UDP/TCP/telnet character devices (Jason Wessel) + - Windows sparse file support (Frediano Ziglio) + - RTL8139 NIC TCP segmentation offloading (Igor Kovalenko) + - PCNET NIC support (Antony T Curtis) + - Support for variable frequency host CPUs + - Workaround for win32 SMP hosts + - Support for AMD Flash memories (Jocelyn Mayer) + - Audio capture to WAV files support (malc) + version 0.8.1: - USB tablet support (Brad Campbell, Anthony Liguori) diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/Makefile --- a/tools/ioemu/Makefile Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/Makefile Mon Aug 07 18:00:22 2006 -0500 @@ -1,11 +1,19 @@ XEN_ROOT=../.. +# Makefile for QEMU. + XEN_ROOT=../.. include $(XEN_ROOT)/tools/Rules.mk -include config-host.mak +.PHONY: all clean distclean dvi info install install-doc tar tarbin \ + speed test test2 html dvi info + CFLAGS+=-Wall -O2 -g -fno-strict-aliasing -I. ifdef CONFIG_DARWIN CFLAGS+= -mdynamic-no-pic +endif +ifeq ($(ARCH),sparc) +CFLAGS+=-mcpu=ultrasparc endif LDFLAGS=-g LIBS= @@ -20,11 +28,15 @@ DOCS= DOCS= endif -all: $(DOCS) - for d in $(TARGET_DIRS); do \ - $(MAKE) -C $$d $@ || exit 1 ; \ - done +TOOLS= +all: $(TOOLS) $(DOCS) recurse-all + +subdir-%: + $(MAKE) -C $(subst subdir-,,$@) all + +recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS)) + qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c $(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS) @@ -42,6 +54,7 @@ clean: distclean: clean rm -f config-host.mak config-host.h $(DOCS) + rm -f qemu-{doc,tech}.{info,aux,cp,dvi,fn,info,ky,log,pg,toc,tp,vr} for d in $(TARGET_DIRS); do \ rm -rf $$d || exit 1 ; \ done @@ -63,7 +76,7 @@ install: all $(if $(BUILD_DOCS),install- # $(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)" # mkdir -p "$(DESTDIR)$(datadir)" # for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \ -# video.x proll.elf linux_boot.bin; do \ +# video.x openbios-sparc32 linux_boot.bin; do \ # $(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \ # done ifndef CONFIG_WIN32 @@ -106,6 +119,12 @@ qemu-img.1: qemu-img.texi perl -w $(SRC_PATH)/texi2pod.pl $< qemu-img.pod pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@ +info: qemu-doc.info qemu-tech.info + +dvi: qemu-doc.dvi qemu-tech.dvi + +html: qemu-doc.html qemu-tech.html + FILE=qemu-$(shell cat VERSION) # tar release (use 'make -k tar' on a checkouted tree) @@ -138,7 +157,7 @@ tarbin: $(datadir)/vgabios-cirrus.bin \ $(datadir)/ppc_rom.bin \ $(datadir)/video.x \ - $(datadir)/proll.elf \ + $(datadir)/openbios-sparc32 \ $(datadir)/linux_boot.bin \ $(docdir)/qemu-doc.html \ $(docdir)/qemu-tech.html \ diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/Makefile.target --- a/tools/ioemu/Makefile.target Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/Makefile.target Mon Aug 07 18:00:22 2006 -0500 @@ -40,6 +40,11 @@ ifeq ($(TARGET_ARCH),arm) TARGET_ARCH2=armeb endif endif +ifeq ($(TARGET_ARCH),sh4) + ifeq ($(TARGET_WORDS_BIGENDIAN),yes) + TARGET_ARCH2=sh4eb + endif +endif ifeq ($(TARGET_ARCH),mips) ifneq ($(TARGET_WORDS_BIGENDIAN),yes) TARGET_ARCH2=mipsel @@ -114,17 +119,24 @@ endif endif ifeq ($(ARCH),sparc) -CFLAGS+=-m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6 +ifeq ($(CONFIG_SOLARIS),yes) +CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3 +LDFLAGS+=-m32 +OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0 +else +CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6 LDFLAGS+=-m32 OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0 HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat # -static is used to avoid g1/g3 usage by the dynamic linker LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc.ld -static endif +endif ifeq ($(ARCH),sparc64) -CFLAGS+=-m64 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6 +CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7 LDFLAGS+=-m64 +LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0 endif @@ -186,7 +198,12 @@ main.o: CFLAGS+=-p main.o: CFLAGS+=-p endif -OBJS= elfload.o main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o +OBJS= main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o \ + elfload.o linuxload.o +ifdef TARGET_HAS_BFLT +OBJS+= flatload.o +endif + ifeq ($(TARGET_ARCH), i386) OBJS+= vm86.o endif @@ -323,25 +340,32 @@ ifdef CONFIG_ADLIB ifdef CONFIG_ADLIB SOUND_HW += fmopl.o adlib.o endif +AUDIODRV+= wavcapture.o + +# SCSI layer +VL_OBJS+= scsi-disk.o cdrom.o lsi53c895a.o # USB layer -VL_OBJS+= usb.o usb-hub.o usb-uhci.o usb-linux.o usb-hid.o +VL_OBJS+= usb.o usb-hub.o usb-linux.o usb-hid.o usb-ohci.o usb-msd.o # PCI network cards -VL_OBJS+= ne2000.o rtl8139.o +VL_OBJS+= ne2000.o rtl8139.o pcnet.o ifeq ($(TARGET_BASE_ARCH), i386) # Hardware support VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) VL_OBJS+= fdc.o mc146818rtc.o serial.o pc.o -VL_OBJS+= cirrus_vga.o mixeng.o parallel.o +VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o piix_pci.o +VL_OBJS+= usb-uhci.o VL_OBJS+= piix4acpi.o +VL_OBJS+= xenstore.o DEFINES += -DHAS_AUDIO endif ifeq ($(TARGET_BASE_ARCH), ppc) VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o +VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o DEFINES += -DHAS_AUDIO endif ifeq ($(TARGET_ARCH), mips) @@ -350,7 +374,7 @@ endif endif ifeq ($(TARGET_BASE_ARCH), sparc) ifeq ($(TARGET_ARCH), sparc64) -VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o +VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o VL_OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o VL_OBJS+= cirrus_vga.o parallel.o else @@ -361,6 +385,7 @@ ifeq ($(TARGET_BASE_ARCH), arm) ifeq ($(TARGET_BASE_ARCH), arm) VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o VL_OBJS+= arm_boot.o pl011.o pl050.o pl080.o pl110.o pl190.o +VL_OBJS+= versatile_pci.o endif ifeq ($(TARGET_BASE_ARCH), sh4) VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o @@ -398,7 +423,7 @@ ifndef CONFIG_DARWIN ifndef CONFIG_DARWIN ifndef CONFIG_WIN32 ifndef CONFIG_SOLARIS -VL_LIBS=-lutil +VL_LIBS=-lutil -lrt endif endif endif @@ -409,6 +434,11 @@ endif ifeq ($(ARCH),ia64) VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld +endif + +ifeq ($(ARCH),sparc64) +VL_LDFLAGS+=-m64 +VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld endif ifdef CONFIG_WIN32 @@ -489,6 +519,13 @@ endif endif loader.o: loader.c elf_ops.h + +acpi.o: acpi.c acpi-dsdt.hex + +ifdef BUILD_ACPI_TABLES +$(SRC_PATH)/hw/acpi-dsdt.hex: acpi-dsdt.dsl + iasl -tc -p $@ $< +endif ifeq ($(TARGET_ARCH), sh4) op.o: op.c op_mem.c cpu.h @@ -500,6 +537,8 @@ tc58128.o: tc58128.c tc58128.o: tc58128.c endif +$(OBJS) $(LIBOBJS) $(VL_OBJS): config.h ../config-host.h + %.o: %.c $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/TODO --- a/tools/ioemu/TODO Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/TODO Mon Aug 07 18:00:22 2006 -0500 @@ -1,24 +1,20 @@ short term: short term: ---------- +- cycle counter for all archs +- cpu_interrupt() win32/SMP fix - support variable tsc freq -- cpu_interrupt() win32/SMP fix - USB host async - IDE async - debug option in 'configure' script + disable -fomit-frame-pointer - Precise VGA timings for old games/demos (malc patch) - merge PIC spurious interrupt patch -- merge Solaris patch - warning for OS/2: must not use 128 MB memory (merge bochs cmos patch ?) - config file (at least for windows/Mac OS X) -- commit message if execution of code in IO memory - update doc: PCI infos. -- VNC patch + Synaptic patch. - basic VGA optimizations -- physical memory cache (reduce qemu-fast address space size to about 32 MB) - better code fetch (different exception handling + CS.limit support) - do not resize vga if invalid size. - avoid looping if only exceptions -- cycle counter for all archs - TLB code protection support for PPC - see openMosix Doc - disable SMC handling for ARM/SPARC/PPC (not finished) @@ -31,12 +27,10 @@ short term: - fix CCOP optimisation - fix all remaining thread lock issues (must put TBs in a specific invalid state, find a solution for tb_flush()). -- fix arm fpu rounding (at least for float->integer conversions) ppc specific: ------------ - TLB invalidate not needed if msr_pr changes -- SPR_ENCODE() not useful - enable shift optimizations ? linux-user specific: diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/VERSION --- a/tools/ioemu/VERSION Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/VERSION Mon Aug 07 18:00:22 2006 -0500 @@ -1,1 +1,1 @@ 0.8.1 -0.8.1 \ No newline at end of file +0.8.2 \ No newline at end of file diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/audio/alsaaudio.c --- a/tools/ioemu/audio/alsaaudio.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/audio/alsaaudio.c Mon Aug 07 18:00:22 2006 -0500 @@ -61,8 +61,8 @@ static struct { .size_in_usec_in = 1, .size_in_usec_out = 1, #endif - .pcm_name_out = "hw:0,0", - .pcm_name_in = "hw:0,0", + .pcm_name_out = "default", + .pcm_name_in = "default", #ifdef HIGH_LATENCY .buffer_size_in = 400000, .period_size_in = 400000 / 4, @@ -606,7 +606,6 @@ static int alsa_run_out (HWVoiceOut *hw) } } - mixeng_clear (src, written); rpos = (rpos + written) % hw->samples; samples -= written; len -= written; @@ -663,12 +662,9 @@ static int alsa_init_out (HWVoiceOut *hw obt_as.freq = obt.freq; obt_as.nchannels = obt.nchannels; obt_as.fmt = effective_fmt; - - audio_pcm_init_info ( - &hw->info, - &obt_as, - audio_need_to_swap_endian (endianness) - ); + obt_as.endianness = endianness; + + audio_pcm_init_info (&hw->info, &obt_as); hw->samples = obt.samples; alsa->pcm_buf = audio_calloc (AUDIO_FUNC, obt.samples, 1 << hw->info.shift); @@ -752,12 +748,9 @@ static int alsa_init_in (HWVoiceIn *hw, obt_as.freq = obt.freq; obt_as.nchannels = obt.nchannels; obt_as.fmt = effective_fmt; - - audio_pcm_init_info ( - &hw->info, - &obt_as, - audio_need_to_swap_endian (endianness) - ); + obt_as.endianness = endianness; + + audio_pcm_init_info (&hw->info, &obt_as); hw->samples = obt.samples; alsa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/audio/audio.c --- a/tools/ioemu/audio/audio.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/audio/audio.c Mon Aug 07 18:00:22 2006 -0500 @@ -29,6 +29,7 @@ /* #define DEBUG_PLIVE */ /* #define DEBUG_LIVE */ /* #define DEBUG_OUT */ +/* #define DEBUG_CAPTURE */ #define SW_NAME(sw) (sw)->name ? (sw)->name : "unknown" @@ -137,7 +138,7 @@ int audio_bug (const char *funcname, int if (cond) { static int shown; - AUD_log (NULL, "Error a bug that was just triggered in %s\n", funcname); + AUD_log (NULL, "A bug was just triggered in %s\n", funcname); if (!shown) { shown = 1; AUD_log (NULL, "Save all your work and restart without audio\n"); @@ -509,14 +510,28 @@ static void audio_print_settings (audset AUD_log (NULL, "invalid(%d)", as->fmt); break; } + + AUD_log (NULL, " endianness="); + switch (as->endianness) { + case 0: + AUD_log (NULL, "little"); + break; + case 1: + AUD_log (NULL, "big"); + break; + default: + AUD_log (NULL, "invalid"); + break; + } AUD_log (NULL, "\n"); } -static int audio_validate_settigs (audsettings_t *as) +static int audio_validate_settings (audsettings_t *as) { int invalid; invalid = as->nchannels != 1 && as->nchannels != 2; + invalid |= as->endianness != 0 && as->endianness != 1; switch (as->fmt) { case AUD_FMT_S8: @@ -530,11 +545,7 @@ static int audio_validate_settigs (audse } invalid |= as->freq <= 0; - - if (invalid) { - return -1; - } - return 0; + return invalid ? -1 : 0; } static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as) @@ -556,14 +567,11 @@ static int audio_pcm_info_eq (struct aud return info->freq == as->freq && info->nchannels == as->nchannels && info->sign == sign - && info->bits == bits; -} - -void audio_pcm_init_info ( - struct audio_pcm_info *info, - audsettings_t *as, - int swap_endian - ) + && info->bits == bits + && info->swap_endianness == (as->endianness != AUDIO_HOST_ENDIANNESS); +} + +void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as) { int bits = 8, sign = 0; @@ -587,7 +595,7 @@ void audio_pcm_init_info ( info->shift = (as->nchannels == 2) + (bits == 16); info->align = (1 << info->shift) - 1; info->bytes_per_second = info->freq << info->shift; - info->swap_endian = swap_endian; + info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS); } void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len) @@ -597,11 +605,11 @@ void audio_pcm_info_clear_buf (struct au } if (info->sign) { - memset (buf, len << info->shift, 0x00); + memset (buf, 0x00, len << info->shift); } else { if (info->bits == 8) { - memset (buf, len << info->shift, 0x80); + memset (buf, 0x80, len << info->shift); } else { int i; @@ -609,7 +617,7 @@ void audio_pcm_info_clear_buf (struct au int shift = info->nchannels - 1; short s = INT16_MAX; - if (info->swap_endian) { + if (info->swap_endianness) { s = bswap16 (s); } @@ -618,6 +626,143 @@ void audio_pcm_info_clear_buf (struct au } } } +} + +/* + * Capture + */ +static void noop_conv (st_sample_t *dst, const void *src, + int samples, volume_t *vol) +{ + (void) src; + (void) dst; + (void) samples; + (void) vol; +} + +static CaptureVoiceOut *audio_pcm_capture_find_specific ( + AudioState *s, + audsettings_t *as + ) +{ + CaptureVoiceOut *cap; + + for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) { + if (audio_pcm_info_eq (&cap->hw.info, as)) { + return cap; + } + } + return NULL; +} + +static void audio_notify_capture (CaptureVoiceOut *cap, audcnotification_e cmd) +{ + struct capture_callback *cb; + +#ifdef DEBUG_CAPTURE + dolog ("notification %d sent\n", cmd); +#endif + for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) { + cb->ops.notify (cb->opaque, cmd); + } +} + +static void audio_capture_maybe_changed (CaptureVoiceOut *cap, int enabled) +{ + if (cap->hw.enabled != enabled) { + audcnotification_e cmd; + cap->hw.enabled = enabled; + cmd = enabled ? AUD_CNOTIFY_ENABLE : AUD_CNOTIFY_DISABLE; + audio_notify_capture (cap, cmd); + } +} + +static void audio_recalc_and_notify_capture (CaptureVoiceOut *cap) +{ + HWVoiceOut *hw = &cap->hw; + SWVoiceOut *sw; + int enabled = 0; + + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { + if (sw->active) { + enabled = 1; + break; + } + } + audio_capture_maybe_changed (cap, enabled); +} + +static void audio_detach_capture (HWVoiceOut *hw) +{ + SWVoiceCap *sc = hw->cap_head.lh_first; + + while (sc) { + SWVoiceCap *sc1 = sc->entries.le_next; + SWVoiceOut *sw = &sc->sw; + CaptureVoiceOut *cap = sc->cap; + int was_active = sw->active; + + if (sw->rate) { + st_rate_stop (sw->rate); + sw->rate = NULL; + } + + LIST_REMOVE (sw, entries); + LIST_REMOVE (sc, entries); + qemu_free (sc); + if (was_active) { + /* We have removed soft voice from the capture: + this might have changed the overall status of the capture + since this might have been the only active voice */ + audio_recalc_and_notify_capture (cap); + } + sc = sc1; + } +} + +static int audio_attach_capture (AudioState *s, HWVoiceOut *hw) +{ + CaptureVoiceOut *cap; + + audio_detach_capture (hw); + for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) { + SWVoiceCap *sc; + SWVoiceOut *sw; + HWVoiceOut *hw_cap = &cap->hw; + + sc = audio_calloc (AUDIO_FUNC, 1, sizeof (*sc)); + if (!sc) { + dolog ("Could not allocate soft capture voice (%zu bytes)\n", + sizeof (*sc)); + return -1; + } + + sc->cap = cap; + sw = &sc->sw; + sw->hw = hw_cap; + sw->info = hw->info; + sw->empty = 1; + sw->active = hw->enabled; + sw->conv = noop_conv; + sw->ratio = ((int64_t) hw_cap->info.freq << 32) / sw->info.freq; + sw->rate = st_rate_start (sw->info.freq, hw_cap->info.freq); + if (!sw->rate) { + dolog ("Could not start rate conversion for `%s'\n", SW_NAME (sw)); + qemu_free (sw); + return -1; + } + LIST_INSERT_HEAD (&hw_cap->sw_head, sw, entries); + LIST_INSERT_HEAD (&hw->cap_head, sc, entries); +#ifdef DEBUG_CAPTURE + asprintf (&sw->name, "for %p %d,%d,%d", + hw, sw->info.freq, sw->info.bits, sw->info.nchannels); + dolog ("Added %s active = %d\n", sw->name, sw->active); +#endif + if (sw->active) { + audio_capture_maybe_changed (cap, 1); + } + } + return 0; } /* @@ -796,6 +941,9 @@ int audio_pcm_sw_write (SWVoiceOut *sw, } if (live == hwsamples) { +#ifdef DEBUG_OUT + dolog ("%s is full %d\n", sw->name, live); +#endif return 0; } @@ -914,19 +1062,14 @@ void AUD_set_active_out (SWVoiceOut *sw, hw = sw->hw; if (sw->active != on) { SWVoiceOut *temp_sw; + SWVoiceCap *sc; if (on) { - int total; - hw->pending_disable = 0; if (!hw->enabled) { hw->enabled = 1; hw->pcm_ops->ctl_out (hw, VOICE_ENABLE); } - - if (sw->empty) { - total = 0; - } } else { if (hw->enabled) { @@ -940,6 +1083,13 @@ void AUD_set_active_out (SWVoiceOut *sw, hw->pending_disable = nb_active == 1; } } + + for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) { + sc->sw.active = hw->enabled; + if (hw->enabled) { + audio_capture_maybe_changed (sc->cap, 1); + } + } sw->active = on; } } @@ -997,7 +1147,7 @@ static int audio_get_avail (SWVoiceIn *s } ldebug ( - "%s: get_avail live %d ret %lld\n", + "%s: get_avail live %d ret %" PRId64 "\n", SW_NAME (sw), live, (((int64_t) live << 32) / sw->ratio) << sw->info.shift ); @@ -1023,7 +1173,7 @@ static int audio_get_free (SWVoiceOut *s dead = sw->hw->samples - live; #ifdef DEBUG_OUT - dolog ("%s: get_free live %d dead %d ret %lld\n", + dolog ("%s: get_free live %d dead %d ret %" PRId64 "\n", SW_NAME (sw), live, dead, (((int64_t) dead << 32) / sw->ratio) << sw->info.shift); #endif @@ -1031,6 +1181,43 @@ static int audio_get_free (SWVoiceOut *s return (((int64_t) dead << 32) / sw->ratio) << sw->info.shift; } +static void audio_capture_mix_and_clear (HWVoiceOut *hw, int rpos, int samples) +{ + int n; + + if (hw->enabled) { + SWVoiceCap *sc; + + for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) { + SWVoiceOut *sw = &sc->sw; + int rpos2 = rpos; + + n = samples; + while (n) { + int till_end_of_hw = hw->samples - rpos2; + int to_write = audio_MIN (till_end_of_hw, n); + int bytes = to_write << hw->info.shift; + int written; + + sw->buf = hw->mix_buf + rpos2; + written = audio_pcm_sw_write (sw, NULL, bytes); + if (written - bytes) { + dolog ("Could not mix %d bytes into a capture " + "buffer, mixed %d\n", + bytes, written); + break; + } + n -= to_write; + rpos2 = (rpos2 + to_write) % hw->samples; + } + } + } + + n = audio_MIN (samples, hw->samples - rpos); + mixeng_clear (hw->mix_buf + rpos, n); + mixeng_clear (hw->mix_buf, samples - n); +} + static void audio_run_out (AudioState *s) { HWVoiceOut *hw = NULL; @@ -1038,7 +1225,7 @@ static void audio_run_out (AudioState *s while ((hw = audio_pcm_hw_find_any_enabled_out (s, hw))) { int played; - int live, free, nb_live, cleanup_required; + int live, free, nb_live, cleanup_required, prev_rpos; live = audio_pcm_hw_get_live_out2 (hw, &nb_live); if (!nb_live) { @@ -1051,12 +1238,17 @@ static void audio_run_out (AudioState *s } if (hw->pending_disable && !nb_live) { + SWVoiceCap *sc; #ifdef DEBUG_OUT dolog ("Disabling voice\n"); #endif hw->enabled = 0; hw->pending_disable = 0; hw->pcm_ops->ctl_out (hw, VOICE_DISABLE); + for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) { + sc->sw.active = 0; + audio_recalc_and_notify_capture (sc->cap); + } continue; } @@ -1072,6 +1264,7 @@ static void audio_run_out (AudioState *s continue; } + prev_rpos = hw->rpos; played = hw->pcm_ops->run_out (hw); if (audio_bug (AUDIO_FUNC, hw->rpos >= hw->samples)) { dolog ("hw->rpos=%d hw->samples=%d played=%d\n", @@ -1085,6 +1278,7 @@ static void audio_run_out (AudioState *s if (played) { hw->ts_helper += played; + audio_capture_mix_and_clear (hw, prev_rpos, played); } cleanup_required = 0; @@ -1115,15 +1309,18 @@ static void audio_run_out (AudioState *s } if (cleanup_required) { - restart: - for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { + SWVoiceOut *sw1; + + sw = hw->sw_head.lh_first; + while (sw) { + sw1 = sw->entries.le_next; if (!sw->active && !sw->callback.fn) { #ifdef DEBUG_PLIVE dolog ("Finishing with old voice\n"); #endif audio_close_out (s, sw); - goto restart; /* play it safe */ } + sw = sw1; } } } @@ -1158,12 +1355,60 @@ static void audio_run_in (AudioState *s) } } +static void audio_run_capture (AudioState *s) +{ + CaptureVoiceOut *cap; + + for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) { + int live, rpos, captured; + HWVoiceOut *hw = &cap->hw; + SWVoiceOut *sw; + + captured = live = audio_pcm_hw_get_live_out (hw); + rpos = hw->rpos; + while (live) { + int left = hw->samples - rpos; + int to_capture = audio_MIN (live, left); + st_sample_t *src; + struct capture_callback *cb; + + src = hw->mix_buf + rpos; + hw->clip (cap->buf, src, to_capture); + mixeng_clear (src, to_capture); + + for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) { + cb->ops.capture (cb->opaque, cap->buf, + to_capture << hw->info.shift); + } + rpos = (rpos + to_capture) % hw->samples; + live -= to_capture; + } + hw->rpos = rpos; + + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { + if (!sw->active && sw->empty) { + continue; + } + + if (audio_bug (AUDIO_FUNC, captured > sw->total_hw_samples_mixed)) { + dolog ("captured=%d sw->total_hw_samples_mixed=%d\n", + captured, sw->total_hw_samples_mixed); + captured = sw->total_hw_samples_mixed; + } + + sw->total_hw_samples_mixed -= captured; + sw->empty = sw->total_hw_samples_mixed == 0; + } + } +} + static void audio_timer (void *opaque) { AudioState *s = opaque; audio_run_out (s); audio_run_in (s); + audio_run_capture (s); qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks); } @@ -1327,8 +1572,19 @@ static void audio_atexit (void) HWVoiceIn *hwi = NULL; while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) { + SWVoiceCap *sc; + hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE); hwo->pcm_ops->fini_out (hwo); + + for (sc = hwo->cap_head.lh_first; sc; sc = sc->entries.le_next) { + CaptureVoiceOut *cap = sc->cap; + struct capture_callback *cb; + + for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) { + cb->ops.destroy (cb->opaque); + } + } } while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) { @@ -1383,6 +1639,7 @@ AudioState *AUD_init (void) LIST_INIT (&s->hw_head_out); LIST_INIT (&s->hw_head_in); + LIST_INIT (&s->cap_head); atexit (audio_atexit); s->ts = qemu_new_timer (vm_clock, audio_timer, s); @@ -1479,3 +1736,136 @@ AudioState *AUD_init (void) qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks); return s; } + +CaptureVoiceOut *AUD_add_capture ( + AudioState *s, + audsettings_t *as, + struct audio_capture_ops *ops, + void *cb_opaque + ) +{ + CaptureVoiceOut *cap; + struct capture_callback *cb; + + if (!s) { + /* XXX suppress */ + s = &glob_audio_state; + } + + if (audio_validate_settings (as)) { + dolog ("Invalid settings were passed when trying to add capture\n"); + audio_print_settings (as); + goto err0; + } + + cb = audio_calloc (AUDIO_FUNC, 1, sizeof (*cb)); + if (!cb) { + dolog ("Could not allocate capture callback information, size %zu\n", + sizeof (*cb)); + goto err0; + } + cb->ops = *ops; + cb->opaque = cb_opaque; + + cap = audio_pcm_capture_find_specific (s, as); + if (cap) { + LIST_INSERT_HEAD (&cap->cb_head, cb, entries); + return cap; + } + else { + HWVoiceOut *hw; + CaptureVoiceOut *cap; + + cap = audio_calloc (AUDIO_FUNC, 1, sizeof (*cap)); + if (!cap) { + dolog ("Could not allocate capture voice, size %zu\n", + sizeof (*cap)); + goto err1; + } + + hw = &cap->hw; + LIST_INIT (&hw->sw_head); + LIST_INIT (&cap->cb_head); + + /* XXX find a more elegant way */ + hw->samples = 4096 * 4; + hw->mix_buf = audio_calloc (AUDIO_FUNC, hw->samples, + sizeof (st_sample_t)); + if (!hw->mix_buf) { + dolog ("Could not allocate capture mix buffer (%d samples)\n", + hw->samples); + goto err2; + } + + audio_pcm_init_info (&hw->info, as); + + cap->buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); + if (!cap->buf) { + dolog ("Could not allocate capture buffer " + "(%d samples, each %d bytes)\n", + hw->samples, 1 << hw->info.shift); + goto err3; + } + + hw->clip = mixeng_clip + [hw->info.nchannels == 2] + [hw->info.sign] + [hw->info.swap_endianness] + [hw->info.bits == 16]; + + LIST_INSERT_HEAD (&s->cap_head, cap, entries); + LIST_INSERT_HEAD (&cap->cb_head, cb, entries); + + hw = NULL; + while ((hw = audio_pcm_hw_find_any_out (s, hw))) { + audio_attach_capture (s, hw); + } + return cap; + + err3: + qemu_free (cap->hw.mix_buf); + err2: + qemu_free (cap); + err1: + qemu_free (cb); + err0: + return NULL; + } +} + +void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque) +{ + struct capture_callback *cb; + + for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) { + if (cb->opaque == cb_opaque) { + cb->ops.destroy (cb_opaque); + LIST_REMOVE (cb, entries); + qemu_free (cb); + + if (!cap->cb_head.lh_first) { + SWVoiceOut *sw = cap->hw.sw_head.lh_first, *sw1; + + while (sw) { + SWVoiceCap *sc = (SWVoiceCap *) sw; +#ifdef DEBUG_CAPTURE + dolog ("freeing %s\n", sw->name); +#endif + + sw1 = sw->entries.le_next; + if (sw->rate) { + st_rate_stop (sw->rate); + sw->rate = NULL; + } + LIST_REMOVE (sw, entries); + LIST_REMOVE (sc, entries); + qemu_free (sc); + sw = sw1; + } + LIST_REMOVE (cap, entries); + qemu_free (cap); + } + return; + } + } +} diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/audio/audio.h --- a/tools/ioemu/audio/audio.h Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/audio/audio.h Mon Aug 07 18:00:22 2006 -0500 @@ -24,6 +24,7 @@ #ifndef QEMU_AUDIO_H #define QEMU_AUDIO_H +#include "config.h" #include "sys-queue.h" typedef void (*audio_callback_fn_t) (void *opaque, int avail); @@ -35,14 +36,44 @@ typedef enum { AUD_FMT_S16 } audfmt_e; +#ifdef WORDS_BIGENDIAN +#define AUDIO_HOST_ENDIANNESS 1 +#else +#define AUDIO_HOST_ENDIANNESS 0 +#endif + typedef struct { int freq; int nchannels; audfmt_e fmt; + int endianness; } audsettings_t; + +typedef enum { + AUD_CNOTIFY_ENABLE, + AUD_CNOTIFY_DISABLE +} audcnotification_e; + +struct audio_capture_ops { + void (*notify) (void *opaque, audcnotification_e cmd); + void (*capture) (void *opaque, void *buf, int size); + void (*destroy) (void *opaque); +}; + +struct capture_ops { + void (*info) (void *opaque); + void (*destroy) (void *opaque); +}; + +typedef struct CaptureState { + void *opaque; + struct capture_ops ops; + LIST_ENTRY (CaptureState) entries; +} CaptureState; typedef struct AudioState AudioState; typedef struct SWVoiceOut SWVoiceOut; +typedef struct CaptureVoiceOut CaptureVoiceOut; typedef struct SWVoiceIn SWVoiceIn; typedef struct QEMUSoundCard { @@ -66,6 +97,13 @@ void AUD_help (void); void AUD_help (void); void AUD_register_card (AudioState *s, const char *name, QEMUSoundCard *card); void AUD_remove_card (QEMUSoundCard *card); +CaptureVoiceOut *AUD_add_capture ( + AudioState *s, + audsettings_t *as, + struct audio_capture_ops *ops, + void *opaque + ); +void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque); SWVoiceOut *AUD_open_out ( QEMUSoundCard *card, @@ -73,8 +111,7 @@ SWVoiceOut *AUD_open_out ( const char *name, void *callback_opaque, audio_callback_fn_t callback_fn, - audsettings_t *settings, - int sw_endian + audsettings_t *settings ); void AUD_close_out (QEMUSoundCard *card, SWVoiceOut *sw); @@ -92,8 +129,7 @@ SWVoiceIn *AUD_open_in ( const char *name, void *callback_opaque, audio_callback_fn_t callback_fn, - audsettings_t *settings, - int sw_endian + audsettings_t *settings ); void AUD_close_in (QEMUSoundCard *card, SWVoiceIn *sw); @@ -111,7 +147,7 @@ static inline void *advance (void *p, in } uint32_t popcount (uint32_t u); -inline uint32_t lsbindex (uint32_t u); +uint32_t lsbindex (uint32_t u); #ifdef __GNUC__ #define audio_MIN(a, b) ( __extension__ ({ \ diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/audio/audio_int.h --- a/tools/ioemu/audio/audio_int.h Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/audio/audio_int.h Mon Aug 07 18:00:22 2006 -0500 @@ -61,13 +61,14 @@ struct audio_pcm_info { int align; int shift; int bytes_per_second; - int swap_endian; -}; + int swap_endianness; +}; + +typedef struct SWVoiceCap SWVoiceCap; typedef struct HWVoiceOut { int enabled; int pending_disable; - int valid; struct audio_pcm_info info; f_sample *clip; @@ -79,6 +80,7 @@ typedef struct HWVoiceOut { int samples; LIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head; + LIST_HEAD (sw_cap_listhead, SWVoiceCap) cap_head; struct audio_pcm_ops *pcm_ops; LIST_ENTRY (HWVoiceOut) entries; } HWVoiceOut; @@ -160,14 +162,34 @@ struct audio_pcm_ops { int (*ctl_in) (HWVoiceIn *hw, int cmd, ...); }; +struct capture_callback { + struct audio_capture_ops ops; + void *opaque; + LIST_ENTRY (capture_callback) entries; +}; + +struct CaptureVoiceOut { + HWVoiceOut hw; + void *buf; + LIST_HEAD (cb_listhead, capture_callback) cb_head; + LIST_ENTRY (CaptureVoiceOut) entries; +}; + +struct SWVoiceCap { + SWVoiceOut sw; + CaptureVoiceOut *cap; + LIST_ENTRY (SWVoiceCap) entries; +}; + struct AudioState { struct audio_driver *drv; void *drv_opaque; QEMUTimer *ts; - LIST_HEAD (card_head, QEMUSoundCard) card_head; + LIST_HEAD (card_listhead, QEMUSoundCard) card_head; LIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in; LIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out; + LIST_HEAD (cap_listhead, CaptureVoiceOut) cap_head; int nb_hw_voices_out; int nb_hw_voices_in; }; @@ -182,8 +204,7 @@ extern struct audio_driver dsound_audio_ extern struct audio_driver dsound_audio_driver; extern volume_t nominal_volume; -void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as, - int swap_endian); +void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as); void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len); int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int len); @@ -202,15 +223,6 @@ static inline int audio_ring_dist (int d static inline int audio_ring_dist (int dst, int src, int len) { return (dst >= src) ? (dst - src) : (len - src + dst); -} - -static inline int audio_need_to_swap_endian (int endianness) -{ -#ifdef WORDS_BIGENDIAN - return endianness != 1; -#else - return endianness != 0; -#endif } #if defined __GNUC__ diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/audio/audio_template.h --- a/tools/ioemu/audio/audio_template.h Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/audio/audio_template.h Mon Aug 07 18:00:22 2006 -0500 @@ -140,13 +140,12 @@ static int glue (audio_pcm_sw_init_, TYP SW *sw, HW *hw, const char *name, - audsettings_t *as, - int endian + audsettings_t *as ) { int err; - audio_pcm_init_info (&sw->info, as, audio_need_to_swap_endian (endian)); + audio_pcm_init_info (&sw->info, as); sw->hw = hw; sw->active = 0; #ifdef DAC @@ -164,7 +163,7 @@ static int glue (audio_pcm_sw_init_, TYP #endif [sw->info.nchannels == 2] [sw->info.sign] - [sw->info.swap_endian] + [sw->info.swap_endianness] [sw->info.bits == 16]; sw->name = qemu_strdup (name); @@ -200,6 +199,9 @@ static void glue (audio_pcm_hw_gc_, TYPE HW *hw = *hwp; if (!hw->sw_head.lh_first) { +#ifdef DAC + audio_detach_capture (hw); +#endif LIST_REMOVE (hw, entries); glue (s->nb_hw_voices_, TYPE) += 1; glue (audio_pcm_hw_free_resources_ ,TYPE) (hw); @@ -266,7 +268,9 @@ static HW *glue (audio_pcm_hw_add_new_, hw->pcm_ops = drv->pcm_ops; LIST_INIT (&hw->sw_head); - +#ifdef DAC + LIST_INIT (&hw->cap_head); +#endif if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) { goto err0; } @@ -283,7 +287,7 @@ static HW *glue (audio_pcm_hw_add_new_, #endif [hw->info.nchannels == 2] [hw->info.sign] - [hw->info.swap_endian] + [hw->info.swap_endianness] [hw->info.bits == 16]; if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) { @@ -292,6 +296,9 @@ static HW *glue (audio_pcm_hw_add_new_, LIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries); glue (s->nb_hw_voices_, TYPE) -= 1; +#ifdef DAC + audio_attach_capture (s, hw); +#endif return hw; err1: @@ -328,8 +335,7 @@ static SW *glue (audio_pcm_create_voice_ static SW *glue (audio_pcm_create_voice_pair_, TYPE) ( AudioState *s, const char *sw_name, - audsettings_t *as, - int sw_endian + audsettings_t *as ) { SW *sw; @@ -357,7 +363,7 @@ static SW *glue (audio_pcm_create_voice_ glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw); - if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as, sw_endian)) { + if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) { goto err3; } @@ -399,8 +405,7 @@ SW *glue (AUD_open_, TYPE) ( const char *name, void *callback_opaque , audio_callback_fn_t callback_fn, - audsettings_t *as, - int sw_endian + audsettings_t *as ) { AudioState *s; @@ -421,7 +426,7 @@ SW *glue (AUD_open_, TYPE) ( s = card->audio; - if (audio_bug (AUDIO_FUNC, audio_validate_settigs (as))) { + if (audio_bug (AUDIO_FUNC, audio_validate_settings (as))) { audio_print_settings (as); goto fail; } @@ -473,12 +478,12 @@ SW *glue (AUD_open_, TYPE) ( } glue (audio_pcm_sw_fini_, TYPE) (sw); - if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as, sw_endian)) { + if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as)) { goto fail; } } else { - sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as, sw_endian); + sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as); if (!sw) { dolog ("Failed to create voice `%s'\n", name); return NULL; diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/audio/coreaudio.c --- a/tools/ioemu/audio/coreaudio.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/audio/coreaudio.c Mon Aug 07 18:00:22 2006 -0500 @@ -275,8 +275,6 @@ static OSStatus audioDeviceIOProc( #endif } - /* cleanup */ - mixeng_clear (src, frameCount); rpos = (rpos + frameCount) % hw->samples; core->decr += frameCount; core->rpos = rpos; @@ -297,7 +295,6 @@ static int coreaudio_init_out (HWVoiceOu UInt32 propertySize; int err; int bits = 8; - int endianess = 0; const char *typ = "playback"; AudioValueRange frameRange; @@ -310,16 +307,9 @@ static int coreaudio_init_out (HWVoiceOu if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) { bits = 16; - endianess = 1; - } - - audio_pcm_init_info ( - &hw->info, - as, - /* Following is irrelevant actually since we do not use - mixengs clipping routines */ - audio_need_to_swap_endian (endianess) - ); + } + + audio_pcm_init_info (&hw->info, as); /* open default output device */ propertySize = sizeof(core->outputDeviceID); diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/audio/dsound_template.h --- a/tools/ioemu/audio/dsound_template.h Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/audio/dsound_template.h Mon Aug 07 18:00:22 2006 -0500 @@ -70,7 +70,13 @@ static int glue (dsound_lock_, TYPE) ( int i; LPVOID p1 = NULL, p2 = NULL; DWORD blen1 = 0, blen2 = 0; - + DWORD flag; + +#ifdef DSBTYPE_IN + flag = entire ? DSCBLOCK_ENTIREBUFFER : 0; +#else + flag = entire ? DSBLOCK_ENTIREBUFFER : 0; +#endif for (i = 0; i < conf.lock_retries; ++i) { hr = glue (IFACE, _Lock) ( buf, @@ -80,13 +86,7 @@ static int glue (dsound_lock_, TYPE) ( &blen1, &p2, &blen2, - (entire -#ifdef DSBTYPE_IN - ? DSCBLOCK_ENTIREBUFFER -#else - ? DSBLOCK_ENTIREBUFFER -#endif - : 0) + flag ); if (FAILED (hr)) { @@ -250,8 +250,8 @@ static int dsound_init_out (HWVoiceOut * } ds->first_time = 1; - - audio_pcm_init_info (&hw->info, &obt_as, audio_need_to_swap_endian (0)); + obt_as.endianness = 0; + audio_pcm_init_info (&hw->info, &obt_as); if (bc.dwBufferBytes & hw->info.align) { dolog ( diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/audio/dsoundaudio.c --- a/tools/ioemu/audio/dsoundaudio.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/audio/dsoundaudio.c Mon Aug 07 18:00:22 2006 -0500 @@ -453,13 +453,11 @@ static void dsound_write_sample (HWVoice if (src_len1) { hw->clip (dst, src1, src_len1); - mixeng_clear (src1, src_len1); } if (src_len2) { dst = advance (dst, src_len1 << hw->info.shift); hw->clip (dst, src2, src_len2); - mixeng_clear (src2, src_len2); } hw->rpos = pos % hw->samples; @@ -987,6 +985,12 @@ static void *dsound_audio_init (void) hr = IDirectSound_Initialize (s->dsound, NULL); if (FAILED (hr)) { dsound_logerr (hr, "Could not initialize DirectSound\n"); + + hr = IDirectSound_Release (s->dsound); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not release DirectSound\n"); + } + s->dsound = NULL; return NULL; } diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/audio/fmodaudio.c --- a/tools/ioemu/audio/fmodaudio.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/audio/fmodaudio.c Mon Aug 07 18:00:22 2006 -0500 @@ -153,13 +153,11 @@ static void fmod_write_sample (HWVoiceOu if (src_len1) { hw->clip (dst, src1, src_len1); - mixeng_clear (src1, src_len1); } if (src_len2) { dst = advance (dst, src_len1 << hw->info.shift); hw->clip (dst, src2, src_len2); - mixeng_clear (src2, src_len2); } hw->rpos = pos % hw->samples; @@ -360,6 +358,7 @@ static int fmod_init_out (HWVoiceOut *hw { int bits16, mode, channel; FMODVoiceOut *fmd = (FMODVoiceOut *) hw; + audsettings_t obt_as = *as; mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0); fmd->fmod_sample = FSOUND_Sample_Alloc ( @@ -386,7 +385,8 @@ static int fmod_init_out (HWVoiceOut *hw fmd->channel = channel; /* FMOD always operates on little endian frames? */ - audio_pcm_init_info (&hw->info, as, audio_need_to_swap_endian (0)); + obt_as.endianness = 0; + audio_pcm_init_info (&hw->info, &obt_as); bits16 = (mode & FSOUND_16BITS) != 0; hw->samples = conf.nb_samples; return 0; @@ -420,6 +420,7 @@ static int fmod_init_in (HWVoiceIn *hw, { int bits16, mode; FMODVoiceIn *fmd = (FMODVoiceIn *) hw; + audsettings_t obt_as = *as; if (conf.broken_adc) { return -1; @@ -442,7 +443,8 @@ static int fmod_init_in (HWVoiceIn *hw, } /* FMOD always operates on little endian frames? */ - audio_pcm_init_info (&hw->info, as, audio_need_to_swap_endian (0)); + obt_as.endianness = 0; + audio_pcm_init_info (&hw->info, &obt_as); bits16 = (mode & FSOUND_16BITS) != 0; hw->samples = conf.nb_samples; return 0; diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/audio/noaudio.c --- a/tools/ioemu/audio/noaudio.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/audio/noaudio.c Mon Aug 07 18:00:22 2006 -0500 @@ -40,21 +40,20 @@ static int no_run_out (HWVoiceOut *hw) { NoVoiceOut *no = (NoVoiceOut *) hw; int live, decr, samples; - int64_t now = qemu_get_clock (vm_clock); - int64_t ticks = now - no->old_ticks; - int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec; - - if (bytes > INT_MAX) { - samples = INT_MAX >> hw->info.shift; - } - else { - samples = bytes >> hw->info.shift; - } + int64_t now; + int64_t ticks; + int64_t bytes; live = audio_pcm_hw_get_live_out (&no->hw); if (!live) { return 0; } + + now = qemu_get_clock (vm_clock); + ticks = now - no->old_ticks; + bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec; + bytes = audio_MIN (bytes, INT_MAX); + samples = bytes >> hw->info.shift; no->old_ticks = now; decr = audio_MIN (live, samples); @@ -69,7 +68,7 @@ static int no_write (SWVoiceOut *sw, voi static int no_init_out (HWVoiceOut *hw, audsettings_t *as) { - audio_pcm_init_info (&hw->info, as, 0); + audio_pcm_init_info (&hw->info, as); hw->samples = 1024; return 0; } @@ -88,7 +87,7 @@ static int no_ctl_out (HWVoiceOut *hw, i static int no_init_in (HWVoiceIn *hw, audsettings_t *as) { - audio_pcm_init_info (&hw->info, as, 0); + audio_pcm_init_info (&hw->info, as); hw->samples = 1024; return 0; } @@ -101,17 +100,20 @@ static int no_run_in (HWVoiceIn *hw) static int no_run_in (HWVoiceIn *hw) { NoVoiceIn *no = (NoVoiceIn *) hw; - int64_t now = qemu_get_clock (vm_clock); - int64_t ticks = now - no->old_ticks; - int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec; int live = audio_pcm_hw_get_live_in (hw); int dead = hw->samples - live; - int samples; + int samples = 0; - bytes = audio_MIN (bytes, INT_MAX); - samples = bytes >> hw->info.shift; - samples = audio_MIN (samples, dead); + if (dead) { + int64_t now = qemu_get_clock (vm_clock); + int64_t ticks = now - no->old_ticks; + int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec; + no->old_ticks = now; + bytes = audio_MIN (bytes, INT_MAX); + samples = bytes >> hw->info.shift; + samples = audio_MIN (samples, dead); + } return samples; } diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/audio/ossaudio.c --- a/tools/ioemu/audio/ossaudio.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/audio/ossaudio.c Mon Aug 07 18:00:22 2006 -0500 @@ -55,12 +55,14 @@ static struct { int fragsize; const char *devpath_out; const char *devpath_in; + int debug; } conf = { .try_mmap = 0, .nfrags = 4, .fragsize = 4096, .devpath_out = "/dev/dsp", - .devpath_in = "/dev/dsp" + .devpath_in = "/dev/dsp", + .debug = 0 }; struct oss_params { @@ -324,9 +326,20 @@ static int oss_run_out (HWVoiceOut *hw) return 0; } - if (abinfo.bytes < 0 || abinfo.bytes > bufsize) { - ldebug ("warning: Invalid available size, size=%d bufsize=%d\n", - abinfo.bytes, bufsize); + if (abinfo.bytes > bufsize) { + if (conf.debug) { + dolog ("warning: Invalid available size, size=%d bufsize=%d\n" + "please report your OS/audio hw to malc@xxxxxxxxxxxxx\n", + abinfo.bytes, bufsize); + } + abinfo.bytes = bufsize; + } + + if (abinfo.bytes < 0) { + if (conf.debug) { + dolog ("warning: Invalid available size, size=%d bufsize=%d\n", + abinfo.bytes, bufsize); + } return 0; } @@ -369,14 +382,11 @@ static int oss_run_out (HWVoiceOut *hw) "alignment %d\n", wbytes, written, hw->info.align + 1); } - mixeng_clear (src, wsamples); decr -= wsamples; rpos = (rpos + wsamples) % hw->samples; break; } } - - mixeng_clear (src, convert_samples); rpos = (rpos + convert_samples) % hw->samples; samples -= convert_samples; @@ -443,12 +453,9 @@ static int oss_init_out (HWVoiceOut *hw, obt_as.freq = obt.freq; obt_as.nchannels = obt.nchannels; obt_as.fmt = effective_fmt; - - audio_pcm_init_info ( - &hw->info, - &obt_as, - audio_need_to_swap_endian (endianness) - ); + obt_as.endianness = endianness; + + audio_pcm_init_info (&hw->info, &obt_as); oss->nfrags = obt.nfrags; oss->fragsize = obt.fragsize; @@ -587,12 +594,9 @@ static int oss_init_in (HWVoiceIn *hw, a obt_as.freq = obt.freq; obt_as.nchannels = obt.nchannels; obt_as.fmt = effective_fmt; - - audio_pcm_init_info ( - &hw->info, - &obt_as, - audio_need_to_swap_endian (endianness) - ); + obt_as.endianness = endianness; + + audio_pcm_init_info (&hw->info, &obt_as); oss->nfrags = obt.nfrags; oss->fragsize = obt.fragsize; @@ -730,6 +734,8 @@ static struct audio_option oss_options[] "Path to DAC device", NULL, 0}, {"ADC_DEV", AUD_OPT_STR, &conf.devpath_in, "Path to ADC device", NULL, 0}, + {"DEBUG", AUD_OPT_BOOL, &conf.debug, + "Turn on some debugging messages", NULL, 0}, {NULL, 0, NULL, NULL, NULL, 0} }; diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/audio/rate_template.h --- a/tools/ioemu/audio/rate_template.h Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/audio/rate_template.h Mon Aug 07 18:00:22 2006 -0500 @@ -51,7 +51,7 @@ void NAME (void *opaque, st_sample_t *ib if (rate->opos_inc == (1ULL + UINT_MAX)) { int i, n = *isamp > *osamp ? *osamp : *isamp; for (i = 0; i < n; i++) { - OP (obuf[i].l, ibuf[i].r); + OP (obuf[i].l, ibuf[i].l); OP (obuf[i].r, ibuf[i].r); } *isamp = n; diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/audio/sdlaudio.c --- a/tools/ioemu/audio/sdlaudio.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/audio/sdlaudio.c Mon Aug 07 18:00:22 2006 -0500 @@ -240,7 +240,6 @@ static void sdl_callback (void *opaque, /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */ hw->clip (buf, src, chunk); - mixeng_clear (src, chunk); sdl->rpos = (sdl->rpos + chunk) % hw->samples; to_mix -= chunk; buf += chunk << hw->info.shift; @@ -336,12 +335,9 @@ static int sdl_init_out (HWVoiceOut *hw, obt_as.freq = obt.freq; obt_as.nchannels = obt.channels; obt_as.fmt = effective_fmt; - - audio_pcm_init_info ( - &hw->info, - &obt_as, - audio_need_to_swap_endian (endianess) - ); + obt_as.endianness = endianess; + + audio_pcm_init_info (&hw->info, &obt_as); hw->samples = obt.samples; s->initialized = 1; diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/audio/wavaudio.c --- a/tools/ioemu/audio/wavaudio.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/audio/wavaudio.c Mon Aug 07 18:00:22 2006 -0500 @@ -81,7 +81,6 @@ static int wav_run_out (HWVoiceOut *hw) hw->clip (dst, src, convert_samples); qemu_put_buffer (wav->f, dst, convert_samples << hw->info.shift); - mixeng_clear (src, convert_samples); rpos = (rpos + convert_samples) % hw->samples; samples -= convert_samples; @@ -136,7 +135,8 @@ static int wav_init_out (HWVoiceOut *hw, hdr[34] = bits16 ? 0x10 : 0x08; - audio_pcm_init_info (&hw->info, &wav_as, audio_need_to_swap_endian (0)); + wav_as.endianness = 0; + audio_pcm_init_info (&hw->info, &wav_as); hw->samples = 1024; wav->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/block-bochs.c --- a/tools/ioemu/block-bochs.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/block-bochs.c Mon Aug 07 18:00:22 2006 -0500 @@ -91,7 +91,7 @@ static int bochs_open(BlockDriverState * int fd, i; struct bochs_header bochs; - fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE); + fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE | O_SYNC); if (fd < 0) { fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); if (fd < 0) diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/block-cloop.c --- a/tools/ioemu/block-cloop.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/block-cloop.c Mon Aug 07 18:00:22 2006 -0500 @@ -55,7 +55,7 @@ static int cloop_open(BlockDriverState * BDRVCloopState *s = bs->opaque; uint32_t offsets_size,max_compressed_block_size=1,i; - s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); + s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE | O_SYNC); if (s->fd < 0) return -1; bs->read_only = 1; diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/block-cow.c --- a/tools/ioemu/block-cow.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/block-cow.c Mon Aug 07 18:00:22 2006 -0500 @@ -69,7 +69,7 @@ static int cow_open(BlockDriverState *bs struct cow_header_v2 cow_header; int64_t size; - fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE); + fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE | O_SYNC); if (fd < 0) { fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); if (fd < 0) @@ -250,6 +250,12 @@ static int cow_create(const char *filena return 0; } +static void cow_flush(BlockDriverState *bs) +{ + BDRVCowState *s = bs->opaque; + fsync(s->fd); +} + BlockDriver bdrv_cow = { "cow", sizeof(BDRVCowState), @@ -259,6 +265,7 @@ BlockDriver bdrv_cow = { cow_write, cow_close, cow_create, + cow_flush, cow_is_allocated, }; #endif diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/block-qcow.c --- a/tools/ioemu/block-qcow.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/block-qcow.c Mon Aug 07 18:00:22 2006 -0500 @@ -95,7 +95,7 @@ static int qcow_open(BlockDriverState *b int fd, len, i, shift; QCowHeader header; - fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE); + fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE | O_SYNC); if (fd < 0) { fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); if (fd < 0) @@ -693,6 +693,12 @@ int qcow_compress_cluster(BlockDriverSta return 0; } +static void qcow_flush(BlockDriverState *bs) +{ + BDRVQcowState *s = bs->opaque; + fsync(s->fd); +} + BlockDriver bdrv_qcow = { "qcow", sizeof(BDRVQcowState), @@ -702,6 +708,7 @@ BlockDriver bdrv_qcow = { qcow_write, qcow_close, qcow_create, + qcow_flush, qcow_is_allocated, qcow_set_key, qcow_make_empty diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/block-vmdk.c --- a/tools/ioemu/block-vmdk.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/block-vmdk.c Mon Aug 07 18:00:22 2006 -0500 @@ -96,7 +96,7 @@ static int vmdk_open(BlockDriverState *b uint32_t magic; int l1_size; - fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE); + fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE | O_SYNC); if (fd < 0) { fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); if (fd < 0) @@ -426,6 +426,12 @@ static void vmdk_close(BlockDriverState close(s->fd); } +static void vmdk_flush(BlockDriverState *bs) +{ + BDRVVmdkState *s = bs->opaque; + fsync(s->fd); +} + BlockDriver bdrv_vmdk = { "vmdk", sizeof(BDRVVmdkState), @@ -435,5 +441,6 @@ BlockDriver bdrv_vmdk = { vmdk_write, vmdk_close, vmdk_create, + vmdk_flush, vmdk_is_allocated, }; diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/block-vpc.c --- a/tools/ioemu/block-vpc.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/block-vpc.c Mon Aug 07 18:00:22 2006 -0500 @@ -163,7 +163,7 @@ static inline int seek_to_sector(BlockDr bitmap_offset = 512 * s->pagetable[pagetable_index]; block_offset = bitmap_offset + 512 + (512 * pageentry_index); -// printf("sector: %llx, index: %x, offset: %x, bioff: %llx, bloff: %llx\n", +// printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n", // sector_num, pagetable_index, pageentry_index, // bitmap_offset, block_offset); diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/block-vvfat.c --- a/tools/ioemu/block-vvfat.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/block-vvfat.c Mon Aug 07 18:00:22 2006 -0500 @@ -2772,6 +2772,7 @@ BlockDriver bdrv_vvfat = { vvfat_read, vvfat_write, vvfat_close, + NULL, /* ??? Not sure if we can do any meaningful flushing. */ NULL, vvfat_is_allocated }; diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/block.c --- a/tools/ioemu/block.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/block.c Mon Aug 07 18:00:22 2006 -0500 @@ -615,6 +615,14 @@ const char *bdrv_get_device_name(BlockDr return bs->device_name; } +void bdrv_flush(BlockDriverState *bs) +{ + if (bs->drv->bdrv_flush) + bs->drv->bdrv_flush(bs); + if (bs->backing_hd) + bdrv_flush(bs->backing_hd); +} + void bdrv_info(void) { BlockDriverState *bs; @@ -677,7 +685,7 @@ static int raw_open(BlockDriverState *bs int rv; #endif - fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE); + fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE | O_SYNC); if (fd < 0) { fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); if (fd < 0) @@ -750,8 +758,54 @@ static void raw_close(BlockDriverState * static void raw_close(BlockDriverState *bs) { BDRVRawState *s = bs->opaque; + bs->total_sectors = 0; close(s->fd); } + +#ifdef _WIN32 +#include <windows.h> +#include <winioctl.h> + +int qemu_ftruncate64(int fd, int64_t length) +{ + LARGE_INTEGER li; + LONG high; + HANDLE h; + BOOL res; + + if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0) + return -1; + + h = (HANDLE)_get_osfhandle(fd); + + /* get current position, ftruncate do not change position */ + li.HighPart = 0; + li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT); + if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR) + return -1; + + high = length >> 32; + if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN)) + return -1; + res = SetEndOfFile(h); + + /* back to old position */ + SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN); + return res ? 0 : -1; +} + +static int set_sparse(int fd) +{ + DWORD returned; + return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE, + NULL, 0, NULL, 0, &returned, NULL); +} +#else +static inline int set_sparse(int fd) +{ + return 1; +} +#endif static int raw_create(const char *filename, int64_t total_size, const char *backing_file, int flags) @@ -765,9 +819,16 @@ static int raw_create(const char *filena 0644); if (fd < 0) return -EIO; + set_sparse(fd); ftruncate(fd, total_size * 512); close(fd); return 0; +} + +static void raw_flush(BlockDriverState *bs) +{ + BDRVRawState *s = bs->opaque; + fsync(s->fd); } BlockDriver bdrv_raw = { @@ -779,6 +840,7 @@ BlockDriver bdrv_raw = { raw_write, raw_close, raw_create, + raw_flush, }; void bdrv_init(void) diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/block_int.h --- a/tools/ioemu/block_int.h Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/block_int.h Mon Aug 07 18:00:22 2006 -0500 @@ -36,6 +36,7 @@ struct BlockDriver { void (*bdrv_close)(BlockDriverState *bs); int (*bdrv_create)(const char *filename, int64_t total_sectors, const char *backing_file, int flags); + void (*bdrv_flush)(BlockDriverState *bs); int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum); int (*bdrv_set_key)(BlockDriverState *bs, const char *key); diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/cocoa.m --- a/tools/ioemu/cocoa.m Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/cocoa.m Mon Aug 07 18:00:22 2006 -0500 @@ -439,23 +439,40 @@ static void cocoa_refresh(DisplayState * kbd_put_keycode(keycode & 0x7f); //remove e0 bit in front /* handle monitor key events */ } else { + int keysym = 0; + switch([event keyCode]) { - case 123: - kbd_put_keysym(QEMU_KEY_LEFT); - break; - case 124: - kbd_put_keysym(QEMU_KEY_RIGHT); - break; - case 125: - kbd_put_keysym(QEMU_KEY_DOWN); - break; - case 126: - kbd_put_keysym(QEMU_KEY_UP); - break; - default: - kbd_put_keysym([[event characters] characterAtIndex:0]); - break; + case 115: + keysym = QEMU_KEY_HOME; + break; + case 117: + keysym = QEMU_KEY_DELETE; + break; + case 119: + keysym = QEMU_KEY_END; + break; + case 123: + keysym = QEMU_KEY_LEFT; + break; + case 124: + keysym = QEMU_KEY_RIGHT; + break; + case 125: + keysym = QEMU_KEY_DOWN; + break; + case 126: + keysym = QEMU_KEY_UP; + break; + default: + { + NSString *ks = [event characters]; + + if ([ks length] > 0) + keysym = [ks characterAtIndex:0]; + } } + if (keysym) + kbd_put_keysym(keysym); } } } @@ -867,10 +884,9 @@ static void setupWindowMenu(void) /* Finally give up our references to the objects */ [windowMenu release]; [windowMenuItem release]; - -} - -static void CustomApplicationMain (argc, argv) +} + +static void CustomApplicationMain(void) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; QemuCocoaGUIController *gui_controller; @@ -904,8 +920,8 @@ int main(int argc, char **argv) { gArgc = argc; gArgv = argv; - - CustomApplicationMain (argc, argv); - + + CustomApplicationMain(); + return 0; } diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/configure --- a/tools/ioemu/configure Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/configure Mon Aug 07 18:00:22 2006 -0500 @@ -96,6 +96,8 @@ softmmu="yes" softmmu="yes" user="no" build_docs="no" +build_acpi_tables="no" +uname_release="" # OS specific targetos=`uname -s` @@ -212,7 +214,7 @@ for opt do ;; --fmod-inc=*) fmod_inc="$optarg" ;; - --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" + --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; user="no" ;; --disable-slirp) slirp="no" ;; @@ -226,8 +228,6 @@ for opt do ;; --enable-cocoa) cocoa="yes" ; coreaudio="yes" ; sdl="no" ;; - --disable-gfx-check) check_gfx="no" - ;; --disable-gcc-check) check_gcc="no" ;; --disable-system) softmmu="no" @@ -237,6 +237,10 @@ for opt do --disable-user) user="no" ;; --enable-user) user="yes" + ;; + --enable-uname-release=*) uname_release="$optarg" + ;; + --enable-iasl) build_acpi_tables="yes" ;; esac done @@ -285,6 +289,8 @@ echo " --disable-user disable echo " --disable-user disable all linux usermode emulation targets" echo " --fmod-lib path to FMOD library" echo " --fmod-inc path to FMOD includes" +echo " --enable-uname-release=R Return R for uname -r in usermode emulation" +echo " --enable-iasl compilation of ACPI tables with the IASL compiler" echo "" echo "NOTE: The object files are build at the place where configure is launched" exit 1 @@ -294,15 +300,21 @@ ar="${cross_prefix}${ar}" ar="${cross_prefix}${ar}" strip="${cross_prefix}${strip}" -if [ ! -x "`which $cc`" ] ; then - echo "Compiler $cc could not be found" - exit +# check that the C compiler works. +cat > $TMPC <<EOF +int main(void) {} +EOF + +if $cc -c -o $TMPO $TMPC 2>/dev/null ; then + : C compiler works ok +else + echo "ERROR: \"$cc\" either does not exist or does not work" + exit 1 fi if test "$mingw32" = "yes" ; then linux="no" EXESUF=".exe" - gdbstub="no" oss="no" if [ "$cpu" = "i386" ] ; then kqemu="yes" @@ -553,6 +565,8 @@ echo "FMOD support $fmod $fmod_supp echo "FMOD support $fmod $fmod_support" echo "kqemu support $kqemu" echo "Documentation $build_docs" +[ ! -z "$uname_release" ] && \ +echo "uname -r $uname_release" if test $sdl_too_old = "yes"; then echo "-> Your SDL version is too old - please upgrade to have SDL support" @@ -705,6 +719,9 @@ if [ "$build_docs" = "yes" ] ; then if [ "$build_docs" = "yes" ] ; then echo "BUILD_DOCS=yes" >> $config_mak fi +if [ "$build_acpi_tables" = "yes" ] ; then + echo "BUILD_ACPI_TABLES=yes" >> $config_mak +fi # XXX: suppress that if [ "$bsd" = "yes" ] ; then @@ -712,6 +729,8 @@ if [ "$bsd" = "yes" ] ; then echo "#define MAP_ANONYMOUS MAP_ANON" >> $config_h echo "#define _BSD 1" >> $config_h fi + +echo "#define CONFIG_UNAME_RELEASE \"$uname_release\"" >> $config_h for target in $target_list; do target_dir="$target" @@ -725,6 +744,7 @@ target_bigendian="no" [ "$target_cpu" = "ppc" ] && target_bigendian=yes [ "$target_cpu" = "ppc64" ] && target_bigendian=yes [ "$target_cpu" = "mips" ] && target_bigendian=yes +[ "$target_cpu" = "sh4eb" ] && target_bigendian=yes target_softmmu="no" if expr $target : '.*-softmmu' > /dev/null ; then target_softmmu="yes" @@ -736,14 +756,6 @@ if expr $target : '.*-user' > /dev/null target_user_only="yes" fi -if test "$target_user_only" = "no" -a "$check_gfx" = "yes" \ - -a "$sdl" = "no" -a "$cocoa" = "no" ; then - echo "ERROR: QEMU requires SDL or Cocoa for graphical output" - echo "To build QEMU without graphical output configure with --disable-gfx-check" - echo "Note that this will disable all output from the virtual graphics card." - exit 1; -fi - #echo "Creating $config_mak, $config_h and $target_dir/Makefile" mkdir -p $target_dir @@ -769,6 +781,7 @@ echo "include ../config-host.mak" >> $co echo "include ../config-host.mak" >> $config_mak echo "#include \"../config-host.h\"" >> $config_h +bflt="no" interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"` echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h @@ -789,6 +802,7 @@ elif test "$target_cpu" = "arm" -o "$tar echo "TARGET_ARCH=arm" >> $config_mak echo "#define TARGET_ARCH \"arm\"" >> $config_h echo "#define TARGET_ARM 1" >> $config_h + bflt="yes" elif test "$target_cpu" = "sparc" ; then echo "TARGET_ARCH=sparc" >> $config_mak echo "#define TARGET_ARCH \"sparc\"" >> $config_h @@ -819,10 +833,13 @@ elif test "$target_cpu" = "mips" -o "$ta echo "TARGET_ARCH=mips" >> $config_mak echo "#define TARGET_ARCH \"mips\"" >> $config_h echo "#define TARGET_MIPS 1" >> $config_h -elif test "$target_cpu" = "sh4" ; then + echo "CONFIG_SOFTFLOAT=yes" >> $config_mak + echo "#define CONFIG_SOFTFLOAT 1" >> $config_h +elif test "$target_cpu" = "sh4" -o "$target_cpu" = "sh4eb" ; then echo "TARGET_ARCH=sh4" >> $config_mak echo "#define TARGET_ARCH \"sh4\"" >> $config_h echo "#define TARGET_SH4 1" >> $config_h + bflt="yes" else echo "Unsupported target CPU" exit 1 @@ -844,9 +861,13 @@ if expr $target : '.*-dm' > /dev/null ; echo "#define CONFIG_DM 1" >> $config_h fi -if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" ; then +if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64"; then echo "CONFIG_SOFTFLOAT=yes" >> $config_mak echo "#define CONFIG_SOFTFLOAT 1" >> $config_h +fi +if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then + echo "TARGET_HAS_BFLT=yes" >> $config_mak + echo "#define TARGET_HAS_BFLT 1" >> $config_h fi # sdl defines diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/console.c --- a/tools/ioemu/console.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/console.c Mon Aug 07 18:00:22 2006 -0500 @@ -27,8 +27,8 @@ #define DEFAULT_BACKSCROLL 512 #define MAX_CONSOLES 12 -#define RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) -#define RGB(r, g, b) RGBA(r, g, b, 0xff) +#define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) +#define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff) typedef struct TextAttributes { uint8_t fgcol:4; @@ -52,6 +52,57 @@ enum TTYState { TTY_STATE_ESC, TTY_STATE_CSI, }; + +typedef struct QEMUFIFO { + uint8_t *buf; + int buf_size; + int count, wptr, rptr; +} QEMUFIFO; + +int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1) +{ + int l, len; + + l = f->buf_size - f->count; + if (len1 > l) + len1 = l; + len = len1; + while (len > 0) { + l = f->buf_size - f->wptr; + if (l > len) + l = len; + memcpy(f->buf + f->wptr, buf, l); + f->wptr += l; + if (f->wptr >= f->buf_size) + f->wptr = 0; + buf += l; + len -= l; + } + f->count += len1; + return len1; +} + +int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1) +{ + int l, len; + + if (len1 > f->count) + len1 = f->count; + len = len1; + while (len > 0) { + l = f->buf_size - f->rptr; + if (l > len) + l = len; + memcpy(buf, f->buf + f->rptr, l); + f->rptr += l; + if (f->rptr >= f->buf_size) + f->rptr = 0; + buf += l; + len -= l; + } + f->count -= len1; + return len1; +} /* ??? This is mis-named. It is used for both text and graphical consoles. */ @@ -81,8 +132,13 @@ struct TextConsole { int nb_esc_params; /* kbd read handler */ + IOCanRWHandler *fd_can_read; IOReadHandler *fd_read; void *fd_opaque; + /* fifo for key pressed */ + QEMUFIFO out_fifo; + uint8_t out_fifo_buf[16]; + QEMUTimer *kbd_timer; }; static TextConsole *active_console; @@ -274,24 +330,24 @@ enum color_names { static const uint32_t color_table_rgb[2][8] = { { /* dark */ - RGB(0x00, 0x00, 0x00), /* black */ - RGB(0xaa, 0x00, 0x00), /* red */ - RGB(0x00, 0xaa, 0x00), /* green */ - RGB(0xaa, 0xaa, 0x00), /* yellow */ - RGB(0x00, 0x00, 0xaa), /* blue */ - RGB(0xaa, 0x00, 0xaa), /* magenta */ - RGB(0x00, 0xaa, 0xaa), /* cyan */ - RGB(0xaa, 0xaa, 0xaa), /* white */ + QEMU_RGB(0x00, 0x00, 0x00), /* black */ + QEMU_RGB(0xaa, 0x00, 0x00), /* red */ + QEMU_RGB(0x00, 0xaa, 0x00), /* green */ + QEMU_RGB(0xaa, 0xaa, 0x00), /* yellow */ + QEMU_RGB(0x00, 0x00, 0xaa), /* blue */ + QEMU_RGB(0xaa, 0x00, 0xaa), /* magenta */ + QEMU_RGB(0x00, 0xaa, 0xaa), /* cyan */ + QEMU_RGB(0xaa, 0xaa, 0xaa), /* white */ }, { /* bright */ - RGB(0x00, 0x00, 0x00), /* black */ - RGB(0xff, 0x00, 0x00), /* red */ - RGB(0x00, 0xff, 0x00), /* green */ - RGB(0xff, 0xff, 0x00), /* yellow */ - RGB(0x00, 0x00, 0xff), /* blue */ - RGB(0xff, 0x00, 0xff), /* magenta */ - RGB(0x00, 0xff, 0xff), /* cyan */ - RGB(0xff, 0xff, 0xff), /* white */ + QEMU_RGB(0x00, 0x00, 0x00), /* black */ + QEMU_RGB(0xff, 0x00, 0x00), /* red */ + QEMU_RGB(0x00, 0xff, 0x00), /* green */ + QEMU_RGB(0xff, 0xff, 0x00), /* yellow */ + QEMU_RGB(0x00, 0x00, 0xff), /* blue */ + QEMU_RGB(0xff, 0x00, 0xff), /* magenta */ + QEMU_RGB(0x00, 0xff, 0xff), /* cyan */ + QEMU_RGB(0xff, 0xff, 0xff), /* white */ } }; @@ -563,7 +619,6 @@ static void console_put_lf(TextConsole * TextCell *c; int x, y1; - s->x = 0; s->y++; if (s->y >= s->height) { s->y = s->height - 1; @@ -712,15 +767,12 @@ static void console_putchar(TextConsole console_put_lf(s); break; case '\b': /* backspace */ - if(s->x > 0) s->x--; - y1 = (s->y_base + s->y) % s->total_height; - c = &s->cells[y1 * s->width + s->x]; - c->ch = ' '; - c->t_attrib = s->t_attrib; - update_xy(s, s->x, s->y); + if (s->x > 0) + s->x--; break; case '\t': /* tabspace */ if (s->x + (8 - (s->x % 8)) > s->width) { + s->x = 0; console_put_lf(s); } else { s->x = s->x + (8 - (s->x % 8)); @@ -739,8 +791,10 @@ static void console_putchar(TextConsole c->t_attrib = s->t_attrib; update_xy(s, s->x, s->y); s->x++; - if (s->x >= s->width) + if (s->x >= s->width) { + s->x = 0; console_put_lf(s); + } break; } break; @@ -835,6 +889,7 @@ static void console_chr_add_read_handler IOReadHandler *fd_read, void *opaque) { TextConsole *s = chr->opaque; + s->fd_can_read = fd_can_read; s->fd_read = fd_read; s->fd_opaque = opaque; } @@ -854,6 +909,28 @@ static void console_send_event(CharDrive } } +static void kbd_send_chars(void *opaque) +{ + TextConsole *s = opaque; + int len; + uint8_t buf[16]; + + len = s->fd_can_read(s->fd_opaque); + if (len > s->out_fifo.count) + len = s->out_fifo.count; + if (len > 0) { + if (len > sizeof(buf)) + len = sizeof(buf); + qemu_fifo_read(&s->out_fifo, buf, len); + s->fd_read(s->fd_opaque, buf, len); + } + /* characters are pending: we send them a bit later (XXX: + horrible, should change char device API) */ + if (s->out_fifo.count > 0) { + qemu_mod_timer(s->kbd_timer, qemu_get_clock(rt_clock) + 1); + } +} + /* called when an ascii key is pressed */ void kbd_put_keysym(int keysym) { @@ -879,25 +956,26 @@ void kbd_put_keysym(int keysym) console_scroll(10); break; default: + /* convert the QEMU keysym to VT100 key string */ + q = buf; + if (keysym >= 0xe100 && keysym <= 0xe11f) { + *q++ = '\033'; + *q++ = '['; + c = keysym - 0xe100; + if (c >= 10) + *q++ = '0' + (c / 10); + *q++ = '0' + (c % 10); + *q++ = '~'; + } else if (keysym >= 0xe120 && keysym <= 0xe17f) { + *q++ = '\033'; + *q++ = '['; + *q++ = keysym & 0xff; + } else { + *q++ = keysym; + } if (s->fd_read) { - /* convert the QEMU keysym to VT100 key string */ - q = buf; - if (keysym >= 0xe100 && keysym <= 0xe11f) { - *q++ = '\033'; - *q++ = '['; - c = keysym - 0xe100; - if (c >= 10) - *q++ = '0' + (c / 10); - *q++ = '0' + (c % 10); - *q++ = '~'; - } else if (keysym >= 0xe120 && keysym <= 0xe17f) { - *q++ = '\033'; - *q++ = '['; - *q++ = keysym & 0xff; - } else { - *q++ = keysym; - } - s->fd_read(s->fd_opaque, buf, q - buf); + qemu_fifo_write(&s->out_fifo, buf, q - buf); + kbd_send_chars(s); } break; } @@ -984,6 +1062,10 @@ CharDriverState *text_console_init(Displ chr->chr_add_read_handler = console_chr_add_read_handler; chr->chr_send_event = console_send_event; + s->out_fifo.buf = s->out_fifo_buf; + s->out_fifo.buf_size = sizeof(s->out_fifo_buf); + s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s); + if (!color_inited) { color_inited = 1; set_color_table(ds); diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/cpu-all.h --- a/tools/ioemu/cpu-all.h Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/cpu-all.h Mon Aug 07 18:00:22 2006 -0500 @@ -878,6 +878,10 @@ extern uint8_t *phys_ram_dirty; #define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */ #define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT) #define IO_MEM_NOTDIRTY (4 << IO_MEM_SHIFT) /* used internally, never use directly */ +/* acts like a ROM when read and like a device when written. As an + exception, the write memory callback gets the ram offset instead of + the physical address */ +#define IO_MEM_ROMD (1) typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value); typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr); @@ -946,13 +950,105 @@ void dump_exec_info(FILE *f, void dump_exec_info(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); +/*******************************************/ +/* host CPU ticks (if available) */ + +#if defined(__powerpc__) + +static inline uint32_t get_tbl(void) +{ + uint32_t tbl; + asm volatile("mftb %0" : "=r" (tbl)); + return tbl; +} + +static inline uint32_t get_tbu(void) +{ + uint32_t tbl; + asm volatile("mftbu %0" : "=r" (tbl)); + return tbl; +} + +static inline int64_t cpu_get_real_ticks(void) +{ + uint32_t l, h, h1; + /* NOTE: we test if wrapping has occurred */ + do { + h = get_tbu(); + l = get_tbl(); + h1 = get_tbu(); + } while (h != h1); + return ((int64_t)h << 32) | l; +} + +#elif defined(__i386__) + +static inline int64_t cpu_get_real_ticks(void) +{ + int64_t val; + asm volatile ("rdtsc" : "=A" (val)); + return val; +} + +#elif defined(__x86_64__) + +static inline int64_t cpu_get_real_ticks(void) +{ + uint32_t low,high; + int64_t val; + asm volatile("rdtsc" : "=a" (low), "=d" (high)); + val = high; + val <<= 32; + val |= low; + return val; +} + +#elif defined(__ia64) + +static inline int64_t cpu_get_real_ticks(void) +{ + int64_t val; + asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory"); + return val; +} + +#elif defined(__s390__) + +static inline int64_t cpu_get_real_ticks(void) +{ + int64_t val; + asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc"); + return val; +} + +#elif defined(__sparc_v9__) + +static inline int64_t cpu_get_real_ticks (void) +{ +#if defined(_LP64) + uint64_t rval; + asm volatile("rd %%tick,%0" : "=r"(rval)); + return rval; +#else + union { + uint64_t i64; + struct { + uint32_t high; + uint32_t low; + } i32; + } rval; + asm volatile("rd %%tick,%1; srlx %1,32,%0" + : "=r"(rval.i32.high), "=r"(rval.i32.low)); + return rval.i64; +#endif +} +#endif + /* profiling */ #ifdef CONFIG_PROFILER static inline int64_t profile_getclock(void) { - int64_t val; - asm volatile ("rdtsc" : "=A" (val)); - return val; + return cpu_get_real_ticks(); } extern int64_t kqemu_time, kqemu_time_start; diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/cpu-defs.h --- a/tools/ioemu/cpu-defs.h Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/cpu-defs.h Mon Aug 07 18:00:22 2006 -0500 @@ -47,7 +47,7 @@ typedef uint32_t target_ulong; #elif TARGET_LONG_SIZE == 8 typedef int64_t target_long; typedef uint64_t target_ulong; -#define TARGET_FMT_lx "%016llx" +#define TARGET_FMT_lx "%016" PRIx64 #else #error TARGET_LONG_SIZE undefined #endif diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/cpu-exec.c --- a/tools/ioemu/cpu-exec.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/cpu-exec.c Mon Aug 07 18:00:22 2006 -0500 @@ -47,7 +47,7 @@ void cpu_loop_exit(void) longjmp(env->jmp_env, 1); } #endif -#ifndef TARGET_SPARC +#if !(defined(TARGET_SPARC) || defined(TARGET_SH4)) #define reg_T2 #endif @@ -175,9 +175,13 @@ static inline TranslationBlock *tb_find_ pc = env->regs[15]; #elif defined(TARGET_SPARC) #ifdef TARGET_SPARC64 - flags = (env->pstate << 2) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2); -#else - flags = env->psrs | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1); + // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled + flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2)) + | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2); +#else + // FPU enable . MMU enabled . MMU no-fault . Supervisor + flags = (env->psref << 3) | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1) + | env->psrs; #endif cs_base = env->npc; pc = env->pc; @@ -253,7 +257,7 @@ int cpu_exec(CPUState *env1) uint32_t *saved_regwptr; #endif #endif -#ifdef __sparc__ +#if defined(__sparc__) && !defined(HOST_SOLARIS) int saved_i7, tmp_T0; #endif int ret, interrupt_request; @@ -323,7 +327,7 @@ int cpu_exec(CPUState *env1) #if defined(reg_T2) saved_T2 = T2; #endif -#ifdef __sparc__ +#if defined(__sparc__) && !defined(HOST_SOLARIS) /* we also save i7 because longjmp may not restore it */ asm volatile ("mov %%i7, %0" : "=r" (saved_i7)); #endif @@ -447,7 +451,7 @@ int cpu_exec(CPUState *env1) T0 = 0; /* force lookup of first TB */ for(;;) { -#ifdef __sparc__ +#if defined(__sparc__) && !defined(HOST_SOLARIS) /* g1 can be modified by some libc? functions */ tmp_T0 = T0; #endif @@ -467,7 +471,7 @@ int cpu_exec(CPUState *env1) do_interrupt(intno, 0, 0, 0, 1); /* ensure that no TB jump will be modified as the program flow was changed */ -#ifdef __sparc__ +#if defined(__sparc__) && !defined(HOST_SOLARIS) tmp_T0 = 0; #else T0 = 0; @@ -486,7 +490,7 @@ int cpu_exec(CPUState *env1) env->error_code = 0; do_interrupt(env); env->interrupt_request &= ~CPU_INTERRUPT_HARD; -#ifdef __sparc__ +#if defined(__sparc__) && !defined(HOST_SOLARIS) tmp_T0 = 0; #else T0 = 0; @@ -497,7 +501,7 @@ int cpu_exec(CPUState *env1) env->error_code = 0; do_interrupt(env); env->interrupt_request &= ~CPU_INTERRUPT_TIMER; -#ifdef __sparc__ +#if defined(__sparc__) && !defined(HOST_SOLARIS) tmp_T0 = 0; #else T0 = 0; @@ -516,7 +520,7 @@ int cpu_exec(CPUState *env1) env->error_code = 0; do_interrupt(env); env->interrupt_request &= ~CPU_INTERRUPT_HARD; -#ifdef __sparc__ +#if defined(__sparc__) && !defined(HOST_SOLARIS) tmp_T0 = 0; #else T0 = 0; @@ -534,7 +538,7 @@ int cpu_exec(CPUState *env1) env->interrupt_request &= ~CPU_INTERRUPT_HARD; do_interrupt(env->interrupt_index); env->interrupt_index = 0; -#ifdef __sparc__ +#if defined(__sparc__) && !defined(HOST_SOLARIS) tmp_T0 = 0; #else T0 = 0; @@ -561,11 +565,13 @@ int cpu_exec(CPUState *env1) #elif defined(TARGET_SH4) /* XXXXX */ #endif + /* Don't use the cached interupt_request value, + do_interrupt may have updated the EXITTB flag. */ if (env->interrupt_request & CPU_INTERRUPT_EXITTB) { env->interrupt_request &= ~CPU_INTERRUPT_EXITTB; /* ensure that no TB jump will be modified as the program flow was changed */ -#ifdef __sparc__ +#if defined(__sparc__) && !defined(HOST_SOLARIS) tmp_T0 = 0; #else T0 = 0; @@ -633,7 +639,7 @@ int cpu_exec(CPUState *env1) lookup_symbol(tb->pc)); } #endif -#ifdef __sparc__ +#if defined(__sparc__) && !defined(HOST_SOLARIS) T0 = tmp_T0; #endif /* see if we can patch the calling TB. When the TB @@ -669,7 +675,9 @@ int cpu_exec(CPUState *env1) "mov %%o7,%%i0" : /* no outputs */ : "r" (gen_func) - : "i0", "i1", "i2", "i3", "i4", "i5"); + : "i0", "i1", "i2", "i3", "i4", "i5", + "l0", "l1", "l2", "l3", "l4", "l5", + "l6", "l7"); #elif defined(__arm__) asm volatile ("mov pc, %0\n\t" ".global exec_loop\n\t" @@ -834,7 +842,7 @@ int cpu_exec(CPUState *env1) #else #error unsupported target CPU #endif -#ifdef __sparc__ +#if defined(__sparc__) && !defined(HOST_SOLARIS) asm volatile ("mov %0, %%i7" : : "r" (saved_i7)); #endif T0 = saved_T0; @@ -1168,19 +1176,14 @@ static inline int handle_cpu_signal(unsi a virtual CPU fault */ cpu_restore_state(tb, env, pc, puc); } - if (ret == 1) { #if 0 printf("PF exception: NIP=0x%08x error=0x%x %p\n", env->nip, env->error_code, tb); #endif /* we restore the process signal mask as the sigreturn should do it (XXX: use sigsetjmp) */ - sigprocmask(SIG_SETMASK, old_set, NULL); - // do_raise_exception_err(env->exception_index, env->error_code); - } else { - /* activate soft MMU for this block */ - cpu_resume_from_signal(env, puc); - } + sigprocmask(SIG_SETMASK, old_set, NULL); + cpu_loop_exit(); /* never comes here */ return 1; } diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/disas.c --- a/tools/ioemu/disas.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/disas.c Mon Aug 07 18:00:22 2006 -0500 @@ -58,7 +58,7 @@ perror_memory (status, memaddr, info) /* Actually, address between memaddr and memaddr + len was out of bounds. */ (*info->fprintf_func) (info->stream, - "Address 0x%llx is out of bounds.\n", memaddr); + "Address 0x%" PRIx64 " is out of bounds.\n", memaddr); } /* This could be in a separate file, to save miniscule amounts of space @@ -73,7 +73,7 @@ generic_print_address (addr, info) bfd_vma addr; struct disassemble_info *info; { - (*info->fprintf_func) (info->stream, "0x%llx", addr); + (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr); } /* Just return the given address. */ diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/dyngen-exec.h --- a/tools/ioemu/dyngen-exec.h Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/dyngen-exec.h Mon Aug 07 18:00:22 2006 -0500 @@ -35,11 +35,14 @@ typedef unsigned char uint8_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; +// Linux/Sparc64 defines uint64_t +#if !(defined (__sparc_v9__) && defined(__linux__)) /* XXX may be done for all 64 bits targets ? */ #if defined (__x86_64__) || defined(__ia64) typedef unsigned long uint64_t; #else typedef unsigned long long uint64_t; +#endif #endif /* if Solaris/__sun__, don't typedef int8_t, as it will be typedef'd @@ -50,10 +53,13 @@ typedef signed char int8_t; #endif typedef signed short int16_t; typedef signed int int32_t; +// Linux/Sparc64 defines int64_t +#if !(defined (__sparc_v9__) && defined(__linux__)) #if defined (__x86_64__) || defined(__ia64) typedef signed long int64_t; #else typedef signed long long int64_t; +#endif #endif #define INT8_MIN (-128) @@ -121,6 +127,19 @@ extern int printf(const char *, ...); #define AREG3 "s2" #endif #ifdef __sparc__ +#ifdef HOST_SOLARIS +#define AREG0 "g2" +#define AREG1 "g3" +#define AREG2 "g4" +#define AREG3 "g5" +#define AREG4 "g6" +#else +#ifdef __sparc_v9__ +#define AREG0 "g1" +#define AREG1 "g4" +#define AREG2 "g5" +#define AREG3 "g7" +#else #define AREG0 "g6" #define AREG1 "g1" #define AREG2 "g2" @@ -133,6 +152,8 @@ extern int printf(const char *, ...); #define AREG9 "l5" #define AREG10 "l6" #define AREG11 "l7" +#endif +#endif #define USE_FP_CONVERT #endif #ifdef __s390__ @@ -241,10 +262,8 @@ extern int __op_jmp0, __op_jmp1, __op_jm ASM_NAME(__op_gen_label) #n) #endif #ifdef __sparc__ -#define EXIT_TB() asm volatile ("jmpl %i0 + 8, %g0\n" \ - "nop") -#define GOTO_LABEL_PARAM(n) asm volatile ( \ - "set " ASM_NAME(__op_gen_label) #n ", %g1; jmp %g1; nop") +#define EXIT_TB() asm volatile ("jmpl %i0 + 8, %g0; nop") +#define GOTO_LABEL_PARAM(n) asm volatile ("ba " ASM_NAME(__op_gen_label) #n ";nop") #endif #ifdef __arm__ #define EXIT_TB() asm volatile ("b exec_loop") diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/dyngen.c --- a/tools/ioemu/dyngen.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/dyngen.c Mon Aug 07 18:00:22 2006 -0500 @@ -1196,7 +1196,7 @@ void get_reloc_expr(char *name, int name } else { #ifdef HOST_SPARC if (sym_name[0] == '.') - snprintf(name, sizeof(name), + snprintf(name, name_size, "(long)(&__dot_%s)", sym_name + 1); else @@ -1440,6 +1440,15 @@ void gen_code(const char *name, host_ulo } #elif defined(HOST_SPARC) { +#define INSN_SAVE 0x9de3a000 +#define INSN_RET 0x81c7e008 +#define INSN_RETL 0x81c3e008 +#define INSN_RESTORE 0x81e80000 +#define INSN_RETURN 0x81cfe008 +#define INSN_NOP 0x01000000 +#define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp +#define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp + uint32_t start_insn, end_insn1, end_insn2; uint8_t *p; p = (void *)(p_end - 8); @@ -1448,13 +1457,21 @@ void gen_code(const char *name, host_ulo start_insn = get32((uint32_t *)(p_start + 0x0)); end_insn1 = get32((uint32_t *)(p + 0x0)); end_insn2 = get32((uint32_t *)(p + 0x4)); - if ((start_insn & ~0x1fff) == 0x9de3a000) { + if (((start_insn & ~0x1fff) == INSN_SAVE) || + (start_insn & ~0x1fff) == INSN_ADD_SP) { p_start += 0x4; start_offset += 0x4; - if ((int)(start_insn | ~0x1fff) < -128) - error("Found bogus save at the start of %s", name); - if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000) + if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE) + /* SPARC v7: ret; restore; */ ; + else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP) + /* SPARC v9: return; nop; */ ; + else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP) + /* SPARC v7: retl; sub %sp, nn, %sp; */ ; + else + error("ret; restore; not found at end of %s", name); + } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) { + ; } else { error("No save at the beginning of %s", name); } @@ -1462,7 +1479,7 @@ void gen_code(const char *name, host_ulo /* Skip a preceeding nop, if present. */ if (p > p_start) { skip_insn = get32((uint32_t *)(p - 0x4)); - if (skip_insn == 0x01000000) + if (skip_insn == INSN_NOP) p -= 4; } #endif @@ -1470,21 +1487,41 @@ void gen_code(const char *name, host_ulo } #elif defined(HOST_SPARC64) { +#define INSN_SAVE 0x9de3a000 +#define INSN_RET 0x81c7e008 +#define INSN_RETL 0x81c3e008 +#define INSN_RESTORE 0x81e80000 +#define INSN_RETURN 0x81cfe008 +#define INSN_NOP 0x01000000 +#define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp +#define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp + uint32_t start_insn, end_insn1, end_insn2, skip_insn; uint8_t *p; p = (void *)(p_end - 8); +#if 0 + /* XXX: check why it occurs */ if (p <= p_start) error("empty code for %s", name); +#endif start_insn = get32((uint32_t *)(p_start + 0x0)); end_insn1 = get32((uint32_t *)(p + 0x0)); end_insn2 = get32((uint32_t *)(p + 0x4)); - if ((start_insn & ~0x1fff) == 0x9de3a000) { + if (((start_insn & ~0x1fff) == INSN_SAVE) || + (start_insn & ~0x1fff) == INSN_ADD_SP) { p_start += 0x4; start_offset += 0x4; - if ((int)(start_insn | ~0x1fff) < -256) - error("Found bogus save at the start of %s", name); - if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000) + if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE) + /* SPARC v7: ret; restore; */ ; + else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP) + /* SPARC v9: return; nop; */ ; + else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP) + /* SPARC v7: retl; sub %sp, nn, %sp; */ ; + else + error("ret; restore; not found at end of %s", name); + } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) { + ; } else { error("No save at the beginning of %s", name); } @@ -2151,6 +2188,18 @@ void gen_code(const char *name, host_ulo reloc_offset, reloc_offset, name, addend, reloc_offset); break; + case R_SPARC_WDISP22: + fprintf(outfile, + " *(uint32_t *)(gen_code_ptr + %d) = " + "((*(uint32_t *)(gen_code_ptr + %d)) " + " & ~0x3fffff) " + " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) " + " & 0x3fffff);\n", + rel->r_offset - start_offset, + rel->r_offset - start_offset, + name, addend, + rel->r_offset - start_offset); + break; default: error("unsupported sparc relocation (%d)", type); } @@ -2168,7 +2217,7 @@ void gen_code(const char *name, host_ulo rel->r_offset < start_offset + copy_size) { sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; get_reloc_expr(name, sizeof(name), sym_name); - type = ELF64_R_TYPE(rel->r_info); + type = ELF32_R_TYPE(rel->r_info); addend = rel->r_addend; reloc_offset = rel->r_offset - start_offset; switch(type) { @@ -2192,6 +2241,15 @@ void gen_code(const char *name, host_ulo " | ((%s + %d) & 0x3ff);\n", reloc_offset, reloc_offset, name, addend); break; + case R_SPARC_OLO10: + addend += ELF64_R_TYPE_DATA (rel->r_info); + fprintf(outfile, + " *(uint32_t *)(gen_code_ptr + %d) = " + "((*(uint32_t *)(gen_code_ptr + %d)) " + " & ~0x3ff) " + " | ((%s + %d) & 0x3ff);\n", + reloc_offset, reloc_offset, name, addend); + break; case R_SPARC_WDISP30: fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = " @@ -2202,8 +2260,18 @@ void gen_code(const char *name, host_ulo reloc_offset, reloc_offset, name, addend, reloc_offset); break; + case R_SPARC_WDISP22: + fprintf(outfile, + " *(uint32_t *)(gen_code_ptr + %d) = " + "((*(uint32_t *)(gen_code_ptr + %d)) " + " & ~0x3fffff) " + " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) " + " & 0x3fffff);\n", + reloc_offset, reloc_offset, name, addend, + reloc_offset); + break; default: - error("unsupported sparc64 relocation (%d)", type); + error("unsupported sparc64 relocation (%d) for symbol %s", type, name); } } } diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/dyngen.h --- a/tools/ioemu/dyngen.h Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/dyngen.h Mon Aug 07 18:00:22 2006 -0500 @@ -19,7 +19,13 @@ */ int __op_param1, __op_param2, __op_param3; -int __op_gen_label1, __op_gen_label2, __op_gen_label3; +#ifdef __sparc__ + void __op_gen_label1(){} + void __op_gen_label2(){} + void __op_gen_label3(){} +#else + int __op_gen_label1, __op_gen_label2, __op_gen_label3; +#endif int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; #ifdef __i386__ diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/elf.h --- a/tools/ioemu/elf.h Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/elf.h Mon Aug 07 18:00:22 2006 -0500 @@ -227,6 +227,7 @@ typedef struct { #define ELF64_R_SYM(i) ((i) >> 32) #define ELF64_R_TYPE(i) ((i) & 0xffffffff) +#define ELF64_R_TYPE_DATA(i) (((ELF64_R_TYPE(i) >> 8) ^ 0x00800000) - 0x00800000) #define R_386_NONE 0 #define R_386_32 1 @@ -326,6 +327,7 @@ typedef struct { #define R_SPARC_10 30 #define R_SPARC_11 31 #define R_SPARC_64 32 +#define R_SPARC_OLO10 33 #define R_SPARC_WDISP16 40 #define R_SPARC_WDISP19 41 #define R_SPARC_7 43 diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/exec-all.h --- a/tools/ioemu/exec-all.h Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/exec-all.h Mon Aug 07 18:00:22 2006 -0500 @@ -571,7 +571,7 @@ static inline target_ulong get_phys_addr ldub_code(addr); } pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK; - if (pd > IO_MEM_ROM) { + if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x%08lx\n", addr); } return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base; diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/exec.c --- a/tools/ioemu/exec.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/exec.c Mon Aug 07 18:00:22 2006 -0500 @@ -1488,7 +1488,7 @@ int tlb_set_page_exec(CPUState *env, tar if (is_softmmu) #endif { - if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) { + if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { /* IO memory case */ address = vaddr | pd; addend = paddr; @@ -1513,9 +1513,11 @@ int tlb_set_page_exec(CPUState *env, tar te->addr_code = -1; } if (prot & PAGE_WRITE) { - if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM) { - /* ROM: access is ignored (same as unassigned) */ - te->addr_write = vaddr | IO_MEM_ROM; + if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM || + (pd & IO_MEM_ROMD)) { + /* write access calls the I/O callback */ + te->addr_write = vaddr | + (pd & ~(TARGET_PAGE_MASK | IO_MEM_ROMD)); } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && !cpu_physical_memory_is_dirty(pd)) { te->addr_write = vaddr | IO_MEM_NOTDIRTY; @@ -1779,14 +1781,23 @@ void cpu_register_physical_memory(target { target_phys_addr_t addr, end_addr; PhysPageDesc *p; + CPUState *env; size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK; end_addr = start_addr + size; for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) { p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1); p->phys_offset = phys_offset; - if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) + if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM || + (phys_offset & IO_MEM_ROMD)) phys_offset += TARGET_PAGE_SIZE; + } + + /* since each CPU stores ram addresses in its TLB cache, we must + reset the modified entries */ + /* XXX: slow ! */ + for(env = first_cpu; env != NULL; env = env->next_cpu) { + tlb_flush(env, 1); } } @@ -2048,7 +2059,8 @@ void cpu_physical_memory_rw(target_phys_ } } } else { - if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) { + if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && + !(pd & IO_MEM_ROMD)) { /* I/O case */ io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); if (l >= 4 && ((addr & 3) == 0)) { @@ -2103,7 +2115,8 @@ void cpu_physical_memory_write_rom(targe } if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM && - (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM) { + (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM && + !(pd & IO_MEM_ROMD)) { /* do nothing */ } else { unsigned long addr1; @@ -2135,7 +2148,8 @@ uint32_t ldl_phys(target_phys_addr_t add pd = p->phys_offset; } - if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) { + if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && + !(pd & IO_MEM_ROMD)) { /* I/O case */ io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr); @@ -2164,7 +2178,8 @@ uint64_t ldq_phys(target_phys_addr_t add pd = p->phys_offset; } - if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) { + if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && + !(pd & IO_MEM_ROMD)) { /* I/O case */ io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); #ifdef TARGET_WORDS_BIGENDIAN diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/fpu/softfloat-native.c --- a/tools/ioemu/fpu/softfloat-native.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/fpu/softfloat-native.c Mon Aug 07 18:00:22 2006 -0500 @@ -6,7 +6,7 @@ void set_float_rounding_mode(int val STA void set_float_rounding_mode(int val STATUS_PARAM) { STATUS(float_rounding_mode) = val; -#if defined(_BSD) && !defined(__APPLE__) +#if defined(_BSD) && !defined(__APPLE__) || (defined(HOST_SOLARIS) && HOST_SOLARIS < 10) fpsetround(val); #elif defined(__arm__) /* nothing to do */ @@ -22,9 +22,14 @@ void set_floatx80_rounding_precision(int } #endif -#if defined(_BSD) -#define lrint(d) ((long)rint(d)) -#define llrint(d) ((long long)rint(d)) +#if defined(_BSD) || (defined(HOST_SOLARIS) && HOST_SOLARIS < 10) +#define lrint(d) ((int32_t)rint(d)) +#define llrint(d) ((int64_t)rint(d)) +#define lrintf(f) ((int32_t)rint(f)) +#define llrintf(f) ((int64_t)rint(f)) +#define sqrtf(f) ((float)sqrt(f)) +#define remainderf(fa, fb) ((float)remainder(fa, fb)) +#define rintf(f) ((float)rint(f)) #endif #if defined(__powerpc__) diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/gdbstub.c --- a/tools/ioemu/gdbstub.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/gdbstub.c Mon Aug 07 18:00:22 2006 -0500 @@ -17,6 +17,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "config.h" #ifdef CONFIG_USER_ONLY #include <stdlib.h> #include <stdio.h> @@ -24,16 +25,25 @@ #include <string.h> #include <errno.h> #include <unistd.h> +#include <fcntl.h> #include "qemu.h" #else #include "vl.h" #endif -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/tcp.h> +#include "qemu_socket.h" +#ifdef _WIN32 +/* XXX: these constants may be independent of the host ones even for Unix */ +#ifndef SIGTRAP +#define SIGTRAP 5 +#endif +#ifndef SIGINT +#define SIGINT 2 +#endif +#else #include <signal.h> +#endif //#define DEBUG_GDB @@ -69,7 +79,7 @@ static int get_char(GDBState *s) int ret; for(;;) { - ret = read(s->fd, &ch, 1); + ret = recv(s->fd, &ch, 1, 0); if (ret < 0) { if (errno != EINTR && errno != EAGAIN) return -1; @@ -87,7 +97,7 @@ static void put_buffer(GDBState *s, cons int ret; while (len > 0) { - ret = write(s->fd, buf, len); + ret = send(s->fd, buf, len, 0); if (ret < 0) { if (errno != EINTR && errno != EAGAIN) return; @@ -305,11 +315,11 @@ static int cpu_gdb_read_registers(CPUSta for(i = 0; i < 24; i++) { registers[i + 8] = tswapl(env->regwptr[i]); } +#ifndef TARGET_SPARC64 /* fill in fprs */ for (i = 0; i < 32; i++) { registers[i + 32] = tswapl(*((uint32_t *)&env->fpr[i])); } -#ifndef TARGET_SPARC64 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ registers[64] = tswapl(env->y); { @@ -327,16 +337,21 @@ static int cpu_gdb_read_registers(CPUSta registers[72] = 0; return 73 * sizeof(target_ulong); #else - for (i = 0; i < 32; i += 2) { - registers[i/2 + 64] = tswapl(*((uint64_t *)&env->fpr[i])); - } - registers[81] = tswapl(env->pc); - registers[82] = tswapl(env->npc); - registers[83] = tswapl(env->tstate[env->tl]); - registers[84] = tswapl(env->fsr); - registers[85] = tswapl(env->fprs); - registers[86] = tswapl(env->y); - return 87 * sizeof(target_ulong); + /* fill in fprs */ + for (i = 0; i < 64; i += 2) { + uint64_t tmp; + + tmp = (uint64_t)tswap32(*((uint32_t *)&env->fpr[i])) << 32; + tmp |= tswap32(*((uint32_t *)&env->fpr[i + 1])); + registers[i/2 + 32] = tmp; + } + registers[64] = tswapl(env->pc); + registers[65] = tswapl(env->npc); + registers[66] = tswapl(env->tstate[env->tl]); + registers[67] = tswapl(env->fsr); + registers[68] = tswapl(env->fprs); + registers[69] = tswapl(env->y); + return 70 * sizeof(target_ulong); #endif } @@ -353,11 +368,11 @@ static void cpu_gdb_write_registers(CPUS for(i = 0; i < 24; i++) { env->regwptr[i] = tswapl(registers[i + 8]); } +#ifndef TARGET_SPARC64 /* fill in fprs */ for (i = 0; i < 32; i++) { *((uint32_t *)&env->fpr[i]) = tswapl(registers[i + 32]); } -#ifndef TARGET_SPARC64 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ env->y = tswapl(registers[64]); PUT_PSR(env, tswapl(registers[65])); @@ -367,18 +382,16 @@ static void cpu_gdb_write_registers(CPUS env->npc = tswapl(registers[69]); env->fsr = tswapl(registers[70]); #else - for (i = 0; i < 32; i += 2) { - uint64_t tmp; - tmp = tswapl(registers[i/2 + 64]) << 32; - tmp |= tswapl(registers[i/2 + 64 + 1]); - *((uint64_t *)&env->fpr[i]) = tmp; - } - env->pc = tswapl(registers[81]); - env->npc = tswapl(registers[82]); - env->tstate[env->tl] = tswapl(registers[83]); - env->fsr = tswapl(registers[84]); - env->fprs = tswapl(registers[85]); - env->y = tswapl(registers[86]); + for (i = 0; i < 64; i += 2) { + *((uint32_t *)&env->fpr[i]) = tswap32(registers[i/2 + 32] >> 32); + *((uint32_t *)&env->fpr[i + 1]) = tswap32(registers[i/2 + 32] & 0xffffffff); + } + env->pc = tswapl(registers[64]); + env->npc = tswapl(registers[65]); + env->tstate[env->tl] = tswapl(registers[66]); + env->fsr = tswapl(registers[67]); + env->fprs = tswapl(registers[68]); + env->y = tswapl(registers[69]); #endif } #elif defined (TARGET_ARM) @@ -494,7 +507,12 @@ static int cpu_gdb_read_registers(CPUSta int i; #define SAVE(x) *ptr++=tswapl(x) - for (i = 0; i < 16; i++) SAVE(env->gregs[i]); + if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) { + for (i = 0; i < 8; i++) SAVE(env->gregs[i + 16]); + } else { + for (i = 0; i < 8; i++) SAVE(env->gregs[i]); + } + for (i = 8; i < 16; i++) SAVE(env->gregs[i]); SAVE (env->pc); SAVE (env->pr); SAVE (env->gbr); @@ -517,7 +535,12 @@ static void cpu_gdb_write_registers(CPUS int i; #define LOAD(x) (x)=*ptr++; - for (i = 0; i < 16; i++) LOAD(env->gregs[i]); + if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) { + for (i = 0; i < 8; i++) LOAD(env->gregs[i + 16]); + } else { + for (i = 0; i < 8; i++) LOAD(env->gregs[i]); + } + for (i = 8; i < 16; i++) LOAD(env->gregs[i]); LOAD (env->pc); LOAD (env->pr); LOAD (env->gbr); @@ -545,7 +568,7 @@ static int gdb_handle_packet(GDBState *s char buf[4096]; uint8_t mem_buf[2000]; uint32_t *registers; - uint32_t addr, len; + target_ulong addr, len; #ifdef DEBUG_GDB printf("command='%s'\n", line_buf); @@ -560,7 +583,7 @@ static int gdb_handle_packet(GDBState *s break; case 'c': if (*p != '\0') { - addr = strtoul(p, (char **)&p, 16); + addr = strtoull(p, (char **)&p, 16); #if defined(TARGET_I386) env->eip = addr; #elif defined (TARGET_PPC) @@ -616,10 +639,10 @@ static int gdb_handle_packet(GDBState *s put_packet(s, "OK"); break; case 'm': - addr = strtoul(p, (char **)&p, 16); + addr = strtoull(p, (char **)&p, 16); if (*p == ',') p++; - len = strtoul(p, NULL, 16); + len = strtoull(p, NULL, 16); if (cpu_memory_rw_debug(env, addr, mem_buf, len, 0) != 0) { put_packet (s, "E14"); } else { @@ -628,10 +651,10 @@ static int gdb_handle_packet(GDBState *s } break; case 'M': - addr = strtoul(p, (char **)&p, 16); + addr = strtoull(p, (char **)&p, 16); if (*p == ',') p++; - len = strtoul(p, (char **)&p, 16); + len = strtoull(p, (char **)&p, 16); if (*p == ':') p++; hextomem(mem_buf, p, len); @@ -644,10 +667,10 @@ static int gdb_handle_packet(GDBState *s type = strtoul(p, (char **)&p, 16); if (*p == ',') p++; - addr = strtoul(p, (char **)&p, 16); + addr = strtoull(p, (char **)&p, 16); if (*p == ',') p++; - len = strtoul(p, (char **)&p, 16); + len = strtoull(p, (char **)&p, 16); if (type == 0 || type == 1) { if (cpu_breakpoint_insert(env, addr) < 0) goto breakpoint_error; @@ -661,10 +684,10 @@ static int gdb_handle_packet(GDBState *s type = strtoul(p, (char **)&p, 16); if (*p == ',') p++; - addr = strtoul(p, (char **)&p, 16); + addr = strtoull(p, (char **)&p, 16); if (*p == ',') p++; - len = strtoul(p, (char **)&p, 16); + len = strtoull(p, (char **)&p, 16); if (type == 0 || type == 1) { cpu_breakpoint_remove(env, addr); put_packet(s, "OK"); @@ -672,6 +695,18 @@ static int gdb_handle_packet(GDBState *s goto breakpoint_error; } break; +#ifdef CONFIG_USER_ONLY + case 'q': + if (strncmp(p, "Offsets", 7) == 0) { + TaskState *ts = env->opaque; + + sprintf(buf, "Text=%x;Data=%x;Bss=%x", ts->info->code_offset, + ts->info->data_offset, ts->info->data_offset); + put_packet(s, buf); + break; + } + /* Fall through. */ +#endif default: // unknown_command: /* put empty packet */ @@ -829,7 +864,7 @@ static void gdb_read(void *opaque) int i, size; uint8_t buf[4096]; - size = read(s->fd, buf, sizeof(buf)); + size = recv(s->fd, buf, sizeof(buf), 0); if (size < 0) return; if (size == 0) { @@ -866,7 +901,7 @@ static void gdb_accept(void *opaque) /* set short latency */ val = 1; - setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); #ifdef CONFIG_USER_ONLY s = &gdbserver_state; @@ -881,9 +916,11 @@ static void gdb_accept(void *opaque) s->env = first_cpu; /* XXX: allow to change CPU */ s->fd = fd; +#ifdef CONFIG_USER_ONLY fcntl(fd, F_SETFL, O_NONBLOCK); - -#ifndef CONFIG_USER_ONLY +#else + socket_set_nonblock(fd); + /* stop the VM */ vm_stop(EXCP_INTERRUPT); @@ -907,7 +944,7 @@ static int gdbserver_open(int port) /* allow fast reuse */ val = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); sockaddr.sin_family = AF_INET; sockaddr.sin_port = htons(port); @@ -923,7 +960,7 @@ static int gdbserver_open(int port) return -1; } #ifndef CONFIG_USER_ONLY - fcntl(fd, F_SETFL, O_NONBLOCK); + socket_set_nonblock(fd); #endif return fd; } diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/hw/adlib.c --- a/tools/ioemu/hw/adlib.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/hw/adlib.c Mon Aug 07 18:00:22 2006 -0500 @@ -301,6 +301,7 @@ int Adlib_init (AudioState *audio) as.freq = conf.freq; as.nchannels = SHIFT; as.fmt = AUD_FMT_S16; + as.endianness = AUDIO_HOST_ENDIANNESS; AUD_register_card (audio, "adlib", &s->card); @@ -310,8 +311,7 @@ int Adlib_init (AudioState *audio) "adlib", s, adlib_callback, - &as, - 0 /* XXX: little endian? */ + &as ); if (!s->voice) { Adlib_fini (s); diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/hw/apic.c --- a/tools/ioemu/hw/apic.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/hw/apic.c Mon Aug 07 18:00:22 2006 -0500 @@ -239,7 +239,7 @@ void cpu_set_apic_base(CPUState *env, ui { APICState *s = env->apic_state; #ifdef DEBUG_APIC - printf("cpu_set_apic_base: %016llx\n", val); + printf("cpu_set_apic_base: %016" PRIx64 "\n", val); #endif s->apicbase = (val & 0xfffff000) | (s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE)); @@ -255,7 +255,7 @@ uint64_t cpu_get_apic_base(CPUState *env { APICState *s = env->apic_state; #ifdef DEBUG_APIC - printf("cpu_get_apic_base: %016llx\n", (uint64_t)s->apicbase); + printf("cpu_get_apic_base: %016" PRIx64 "\n", (uint64_t)s->apicbase); #endif return s->apicbase; } diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/hw/cuda.c --- a/tools/ioemu/hw/cuda.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/hw/cuda.c Mon Aug 07 18:00:22 2006 -0500 @@ -209,7 +209,7 @@ static int64_t get_next_irq_time(CUDATim } #if 0 #ifdef DEBUG_CUDA - printf("latch=%d counter=%lld delta_next=%lld\n", + printf("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n", s->latch, d, next_time - d); #endif #endif diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/hw/es1370.c --- a/tools/ioemu/hw/es1370.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/hw/es1370.c Mon Aug 07 18:00:22 2006 -0500 @@ -423,6 +423,7 @@ static void es1370_update_voices (ES1370 as.freq = new_freq; as.nchannels = 1 << (new_fmt & 1); as.fmt = (new_fmt & 2) ? AUD_FMT_S16 : AUD_FMT_U8; + as.endianness = 0; if (i == ADC_CHANNEL) { s->adc_voice = @@ -432,8 +433,7 @@ static void es1370_update_voices (ES1370 "es1370.adc", s, es1370_adc_callback, - &as, - 0 /* little endian */ + &as ); } else { @@ -444,8 +444,7 @@ static void es1370_update_voices (ES1370 i ? "es1370.dac2" : "es1370.dac1", s, i ? es1370_dac2_callback : es1370_dac1_callback, - &as, - 0 /* litle endian */ + &as ); } } @@ -479,8 +478,9 @@ IO_WRITE_PROTO (es1370_writeb) IO_WRITE_PROTO (es1370_writeb) { ES1370State *s = opaque; + uint32_t shift, mask; + addr = es1370_fixup (s, addr); - uint32_t shift, mask; switch (addr) { case ES1370_REG_CONTROL: diff -r 61204c1d740e -r 87cefa5f7c5e tools/ioemu/hw/esp.c --- a/tools/ioemu/hw/esp.c Thu Jul 27 20:07:02 2006 -0400 +++ b/tools/ioemu/hw/esp.c Mon Aug 07 18:00:22 2006 -0500 @@ -38,16 +38,13 @@ do { printf("ESP: set_irq(%d): %d\n", (i #define ESPDMA_REGS 4 #define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1) #define ESP_MAXREG 0x3f -#define TI_BUFSZ 1024*1024 // XXX +#define TI_BUFSZ 32 #define DMA_VER 0xa0000000 #define DMA_INTR 1 #define DMA_INTREN 0x10 +#define DMA_WRITE_MEM 0x100 #define DMA_LOADED 0x04000000 typedef struct ESPState ESPState; - -typedef int ESPDMAFunc(ESPState *s, - target_phys_addr_t phys_addr, - int transfer_size1); struct ESPState { BlockDriverState **bd; @@ -57,12 +54,14 @@ struct ESPState { uint32_t espdmaregs[ESPDMA_REGS]; uint32_t ti_size; uint32_t ti_rptr, ti_wptr; - int ti_dir; uint8_t ti_buf[TI_BUFSZ]; + int sense; int dma; - ESPDMAFunc *dma_cb; - int64_t offset, len; - int target; + SCSIDevice *scsi_dev[MAX_DISKS]; + SCSIDevice *current_dev; + uint8_t cmdbuf[TI_BUFSZ]; + int cmdlen; + int do_cmd; }; #define STAT_DO 0x00 @@ -83,394 +82,200 @@ struct ESPState { #define SEQ_0 0x0 #define SEQ_CD 0x4 -/* XXX: stolen from ide.c, move to common ATAPI/SCSI library */ -static void lba_to_msf(uint8_t *buf, int lba) -{ - lba += 150; - buf[0] = (lba / 75) / 60; - buf[1] = (lba / 75) % 60; - buf[2] = lba % 75; -} - -static inline void cpu_to_ube16(uint8_t *buf, int val) -{ - buf[0] = val >> 8; - buf[1] = val; -} - -static inline void cpu_to_ube32(uint8_t *buf, unsigned int val) -{ - buf[0] = val >> 24; - buf[1] = val >> 16; - buf[2] = val >> 8; - buf[3] = val; -} - -/* same toc as bochs. Return -1 if error or the toc length */ -/* XXX: check this */ -static int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track) -{ - uint8_t *q; - int len; - - if (start_track > 1 && start_track != 0xaa) - return -1; - q = buf + 2; - *q++ = 1; /* first session */ - *q++ = 1; /* last session */ - if (start_track <= 1) { - *q++ = 0; /* reserved */ - *q++ = 0x14; /* ADR, control */ - *q++ = 1; /* track number */ - *q++ = 0; /* reserved */ - if (msf) { - *q++ = 0; /* reserved */ - lba_to_msf(q, 0); - q += 3; - } else { - /* sector 0 */ - cpu_to_ube32(q, 0); - q += 4; - } - } - /* lead out track */ - *q++ = 0; /* reserved */ - *q++ = 0x16; /* ADR, control */ - *q++ = 0xaa; /* track number */ - *q++ = 0; /* reserved */ - if (msf) { - *q++ = 0; /* reserved */ - lba_to_msf(q, nb_sectors); - q += 3; - } else { - cpu_to_ube32(q, nb_sectors); - q += 4; - } - len = q - buf; - cpu_to_ube16(buf, len - 2); - return len; -} - -/* mostly same info as PearPc */ -static int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, - int session_num) -{ - uint8_t *q; - int len; - - q = buf + 2; - *q++ = 1; /* first session */ - *q++ = 1; /* last session */ - - *q++ = 1; /* session number */ - *q++ = 0x14; /* data track */ - *q++ = 0; /* track number */ - *q++ = 0xa0; /* lead-in */ - *q++ = 0; /* min */ - *q++ = 0; /* sec */ - *q++ = 0; /* frame */ - *q++ = 0; - *q++ = 1; /* first track */ - *q++ = 0x00; /* disk type */ - *q++ = 0x00; - - *q++ = 1; /* session number */ - *q++ = 0x14; /* data track */ - *q++ = 0; /* track number */ - *q++ = 0xa1; - *q++ = 0; /* min */ - *q++ = 0; /* sec */ - *q++ = 0; /* frame */ - *q++ = 0; - *q++ = 1; /* last track */ - *q++ = 0x00; - *q++ = 0x00; - - *q++ = 1; /* session number */ - *q++ = 0x14; /* data track */ - *q++ = 0; /* track number */ - *q++ = 0xa2; /* lead-out */ - *q++ = 0; /* min */ - *q++ = 0; /* sec */ - *q++ = 0; /* frame */ - if (msf) { - *q++ = 0; /* reserved */ - lba_to_msf(q, nb_sectors); - q += 3; - } else { - cpu_to_ube32(q, nb_sectors); - q += 4; - } - - *q++ = 1; /* session number */ - *q++ = 0x14; /* ADR, control */ - *q++ = 0; /* track number */ - *q++ = 1; /* point */ - *q++ = 0; /* min */ - *q++ = 0; /* sec */ - *q++ = 0; /* frame */ - if (msf) { - *q++ = 0; - lba_to_msf(q, 0); - q += 3; - } else { - *q++ = 0; - *q++ = 0; - *q++ = 0; - *q++ = 0; - } - - len = q - buf; - cpu_to_ube16(buf, len - 2); - return len; -} - -static int esp_write_dma_cb(ESPState *s, - target_phys_addr_t phys_addr, - int transfer_size1) -{ - DPRINTF("Write callback (offset %lld len %lld size %d trans_size %d)\n", - s->offset, s->len, s->ti_size, transfer_size1); - bdrv_write(s->bd[s->target], s->offset, s->ti_buf, s->len); - s->offset = 0; - s->len = 0; - s->target = 0; - return 0; -} - -static void handle_satn(ESPState *s) -{ - uint8_t buf[32]; +static int get_cmd(ESPState *s, uint8_t *buf) +{ uint32_t dmaptr, dmalen; - unsigned int i; - int64_t nb_sectors; int target; dmalen = s->wregs[0] | (s->wregs[1] << 8); target = s->wregs[4] & 7; - DPRINTF("Select with ATN len %d target %d\n", dmalen, target); + DPRINTF("get_cmd: len %d target %d\n", dmalen, target); if (s->dma) { dmaptr = iommu_translate(s->espdmaregs[1]); - DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr); + DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", + s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', dmaptr); cpu_physical_memory_read(dmaptr, buf, dmalen); } else { buf[0] = 0; memcpy(&buf[1], s->ti_buf, dmalen); dmalen++; } - for (i = 0; i < dmalen; i++) { - DPRINTF("Command %2.2x\n", buf[i]); - } - s->ti_dir = 0; + s->ti_size = 0; s->ti_rptr = 0; s->ti_wptr = 0; - if (target >= 4 || !s->bd[target]) { // No such drive + if (target >= 4 || !s->scsi_dev[target]) { + // No such drive s->rregs[4] = STAT_IN; s->rregs[5] = INTR_DC; s->rregs[6] = SEQ_0; s->espdmaregs[0] |= DMA_INTR; pic_set_irq(s->irq, 1); - return; - } - switch (buf[1]) { - case 0x0: - DPRINTF("Test Unit Ready (len %d)\n", buf[5]); - break; - case 0x12: - DPRINTF("Inquiry (len %d)\n", buf[5]); - memset(s->ti_buf, 0, 36); - if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) { - s->ti_buf[0] = 5; - memcpy(&s->ti_buf[16], "QEMU CDROM ", 16); - } else { - s->ti_buf[0] = 0; - memcpy(&s->ti_buf[16], "QEMU HARDDISK ", 16); - } - memcpy(&s->ti_buf[8], "QEMU ", 8); - s->ti_buf[2] = 1; - s->ti_buf[3] = 2; - s->ti_buf[4] = 32; - s->ti_dir = 1; - s->ti_size = 36; - break; - case 0x1a: - DPRINTF("Mode Sense(6) (page %d, len %d)\n", buf[3], buf[5]); - break; - case 0x25: - DPRINTF("Read Capacity (len %d)\n", buf[5]); - memset(s->ti_buf, 0, 8); - bdrv_get_geometry(s->bd[target], &nb_sectors); - s->ti_buf[0] = (nb_sectors >> 24) & 0xff; - s->ti_buf[1] = (nb_sectors >> 16) & 0xff; - s->ti_buf[2] = (nb_sectors >> 8) & 0xff; - s->ti_buf[3] = nb_sectors & 0xff; - s->ti_buf[4] = 0; - s->ti_buf[5] = 0; - if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) - s->ti_buf[6] = 8; // sector size 2048 - else - s->ti_buf[6] = 2; // sector size 512 - s->ti_buf[7] = 0; - s->ti_dir = 1; - s->ti_size = 8; - break; - case 0x28: - { - int64_t offset, len; - - if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) { - offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4; - len = ((buf[8] << 8) | buf[9]) * 4; - s->ti_size = len * 2048; - } else { - offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]; - len = (buf[8] << 8) | buf[9]; - s->ti_size = len * 512; - } - DPRINTF("Read (10) (offset %lld len %lld)\n", offset, len); - if (s->ti_size > TI_BUFSZ) { - DPRINTF("size too large %d\n", s->ti_size); - } - bdrv_read(s->bd[target], offset, s->ti_buf, len); - // XXX error handling - s->ti_dir = 1; - break; - } - case 0x2a: - { - int64_t offset, len; - - if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) { - offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4; - len = ((buf[8] << 8) | buf[9]) * 4; - s->ti_size = len * 2048; - } else { - offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]; - len = (buf[8] << 8) | buf[9]; - s->ti_size = len * 512; - } - DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len); - if (s->ti_size > TI_BUFSZ) { - DPRINTF("size too large %d\n", s->ti_size); - } - s->dma_cb = esp_write_dma_cb; - s->offset = offset; - s->len = len; - s->target = target; - // XXX error handling - s->ti_dir = 0; - break; - } - case 0x43: - { - int start_track, format, msf, len; - - msf = buf[2] & 2; - format = buf[3] & 0xf; - start_track = buf[7]; - bdrv_get_geometry(s->bd[target], &nb_sectors); - DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1); - switch(format) { - case 0: - len = cdrom_read_toc(nb_sectors, buf, msf, start_track); - if (len < 0) - goto error_cmd; - s->ti_size = len; - break; - case 1: - /* multi session : only a single session defined */ - memset(buf, 0, 12); - buf[1] = 0x0a; - buf[2] = 0x01; - buf[3] = 0x01; - s->ti_size = 12; - break; - case 2: - len = cdrom_read_toc_raw(nb_sectors, buf, msf, start_track); - if (len < 0) - goto error_cmd; - s->ti_size = len; - break; - default: - error_cmd: - DPRINTF("Read TOC error\n"); - // XXX error handling - break; - } - s->ti_dir = 1; - break; - } - default: - DPRINTF("Unknown SCSI command (%2.2x)\n", buf[1]); - break; - } - s->rregs[4] = STAT_IN | STAT_TC | STAT_DI; + return 0; + } + s->current_dev = s->scsi_dev[target]; + return dmalen; +} + +static void do_cmd(ESPState *s, uint8_t *buf) +{ + int32_t datalen; + int lun; + + DPRINTF("do_cmd: busid 0x%x\n", buf[0]); + lun = buf[0] & 7; + datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun); + if (datalen == 0) { + s->ti_size = 0; + } else { + s->rregs[4] = STAT_IN | STAT_TC; + if (datalen > 0) { + s->rregs[4] |= STAT_DI; + s->ti_size = datalen; + } else { + s->rregs[4] |= STAT_DO; + s->ti_size = -datalen; + } + } s->rregs[5] = INTR_BS | INTR_FC; s->rregs[6] = SEQ_CD; s->espdmaregs[0] |= DMA_INTR; pic_set_irq(s->irq, 1); } -static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len) -{ - uint32_t dmaptr, dmalen; - - dmalen = s->wregs[0] | (s->wregs[1] << 8); - DPRINTF("Transfer status len %d\n", dmalen); +static void handle_satn(ESPState *s) +{ + uint8_t buf[32]; + int len; + + len = get_cmd(s, buf); + if (len) + do_cmd(s, buf); +} + +static void handle_satn_stop(ESPState *s) +{ + s->cmdlen = get_cmd(s, s->cmdbuf); + if (s->cmdlen) { + DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen); + s->do_cmd = 1; + s->espdmaregs[1] += s->cmdlen; + s->rregs[4] = STAT_IN | STAT_TC | STAT_CD; + s->rregs[5] = INTR_BS | INTR_FC; + s->rregs[6] = SEQ_CD; + s->espdmaregs[0] |= DMA_INTR; + pic_set_irq(s->irq, 1); + } +} + +static void write_response(ESPState *s) +{ + uint32_t dmaptr; + + DPRINTF("Transfer status (sense=%d)\n", s->sense); + s->ti_buf[0] = s->sense; + s->ti_buf[1] = 0; if (s->dma) { dmaptr = iommu_translate(s->espdmaregs[1]); - DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r'); - cpu_physical_memory_write(dmaptr, buf, len); + DPRINTF("DMA Direction: %c\n", + s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r'); + cpu_physical_memory_write(dmaptr, s->ti_buf, 2); s->rregs[4] = STAT_IN | STAT_TC | STAT_ST; s->rregs[5] = INTR_BS | INTR_FC; s->rregs[6] = SEQ_CD; } else { - memcpy(s->ti_buf, buf, len); - s->ti_size = dmalen; + s->ti_size = 2; s->ti_rptr = 0; s->ti_wptr = 0; - s->rregs[7] = dmalen; + s->rregs[7] = 2; } s->espdmaregs[0] |= DMA_INTR; pic_set_irq(s->irq, 1); } -static const uint8_t okbuf[] = {0, 0}; +static void esp_command_complete(void *opaque, uint32_t tag, int sense) +{ + ESPState *s = (ESPState *)opaque; + + DPRINTF("SCSI Command complete\n"); + if (s->ti_size != 0) + DPRINTF("SCSI command completed unexpectedly\n"); + s->ti_size = 0; + if (sense) + DPRINTF("Command failed\n"); + s->sense = sense; + s->rregs[4] = STAT_IN | STAT_TC | STAT_ST; +} static void handle_ti(ESPState *s) { - uint32_t dmaptr, dmalen; + uint32_t dmaptr, dmalen, minlen, len, from, to; unsigned int i; + int to_device; + uint8_t buf[TARGET_PAGE_SIZE]; dmalen = s->wregs[0] | (s->wregs[1] << 8); - DPRINTF("Transfer Information len %d\n", dmalen); + if (dmalen==0) { + dmalen=0x10000; + } + + if (s->do_cmd) + minlen = (dmalen < 32) ? dmalen : 32; + else + minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size; + DPRINTF("Transfer Information len %d\n", minlen); if (s->dma) { dmaptr = iommu_translate(s->espdmaregs[1]); - DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr); - for (i = 0; i < s->ti_size; i++) { + /* Check if the transfer writes to to reads from the device. */ + to_device = (s->espdmaregs[0] & DMA_WRITE_MEM) == 0; + DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x\n", + to_device ? 'r': 'w', dmaptr, s->ti_size); + from = s->espdmaregs[1]; + to = from + minlen; + for (i = 0; i < minlen; i += len, from += len) { dmaptr = iommu_translate(s->espdmaregs[1] + i); - if (s->ti_dir) - cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1); - else - cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1); - } - if (s->dma_cb) { - s->dma_cb(s, s->espdmaregs[1], dmalen); - s->dma_cb = NULL; - } - s->rregs[4] = STAT_IN | STAT_TC | STAT_ST; - s->rregs[5] = INTR_BS; + if ((from & TARGET_PAGE_MASK) != (to & TARGET_PAGE_MASK)) { + len = TARGET_PAGE_SIZE - (from & ~TARGET_PAGE_MASK); + } else { + len = to - from; + } + DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to); + s->ti_size -= len; + if (s->do_cmd) { + DPRINTF("command len %d + %d\n", s->cmdlen, len); + cpu_physical_memory_read(dmaptr, &s->cmdbuf[s->cmdlen], len); + s->ti_size = 0; + s->cmdlen = 0; + s->do_cmd = 0; + do_cmd(s, s->cmdbuf); + return; + } else { + if (to_device) { + cpu_physical_memory_read(dmaptr, buf, len); + scsi_write_data(s->current_dev, buf, len); + } else { + scsi_read_data(s->current_dev, buf, len); + cpu_physical_memory_write(dmaptr, buf, len); + } + } + } + if (s->ti_size) { + s->rregs[4] = STAT_IN | STAT_TC | (to_device ? STAT_DO : STAT_DI); + } + s->rregs[5] = INTR_BS; s->rregs[6] = 0; + s->rregs[7] = 0; s->espdmaregs[0] |= DMA_INTR; - } else { - s->ti_size = dmalen; - s->ti_rptr = 0; - s->ti_wptr = 0; - s->rregs[7] = dmalen; - } + } else if (s->do_cmd) { + DPRINTF("command len %d\n", s->cmdlen); + s->ti_size = 0; + s->cmdlen = 0; + s->do_cmd = 0; + do_cmd(s, s->cmdbuf); + return; + } pic_set_irq(s->irq, 1); } @@ -484,9 +289,8 @@ static void esp_reset(void *opaque) s->ti_size = 0; s->ti_rptr = 0; s->ti_wptr = 0; - s->ti_dir = 0; s->dma = 0; - s->dma_cb = NULL; + s->do_cmd = 0; } static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr) @@ -501,7 +305,12 @@ static uint32_t esp_mem_readb(void *opaq // FIFO if (s->ti_size > 0) { s->ti_size--; - s->rregs[saddr] = s->ti_buf[s->ti_rptr++]; + if ((s->rregs[4] & 6) == 0) { + /* Data in/out. */ + scsi_read_data(s->current_dev, &s->rregs[2], 0); + } else { + s->rregs[2] = s->ti_buf[s->ti_rptr++]; + } pic_set_irq(s->irq, 1); } if (s->ti_size == 0) { @@ -536,8 +345,17 @@ static void esp_mem_writeb(void *opaque, break; case 2: // FIFO - s->ti_size++; - s->ti_buf[s->ti_wptr++] = val & 0xff; + if (s->do_cmd) { + s->cmdbuf[s->cmdlen++] = val & 0xff; + } else if ((s->rregs[4] & 6) == 0) { + uint8_t buf; + buf = val & 0xff; + s->ti_size--; + scsi_write_data(s->current_dev, &buf, 0); + } else { + s->ti_size++; + s->ti_buf[s->ti_wptr++] = val & 0xff; + } break; case 3: s->rregs[saddr] = val; @@ -574,11 +392,11 @@ static void esp_mem_writeb(void *opaque, break; case 0x11: DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val); - dma_write(s, okbuf, 2); + write_response(s); break; case 0x12: DPRINTF("Message Accepted (%2.2x)\n", val); - dma_write(s, okbuf, 2); + write_response(s); s->rregs[5] = INTR_DC; s->rregs[6] = 0; break; @@ -586,11 +404,12 @@ static void esp_mem_writeb(void *opaque, DPRINTF("Set ATN (%2.2x)\n", val); break; case 0x42: + DPRINTF("Set ATN (%2.2x)\n", val); handle_satn(s); break; case 0x43: DPRINTF("Set ATN & stop (%2.2x)\n", val); - handle_satn(s); + handle_satn_stop(s); break; default: DPRINTF("Unhandled ESP command (%2.2x)\n", val); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |